source: branches/smartreader/csctapi/ifd_smartreader.c@ 1294

Last change on this file since 1294 was 1294, checked in by rorothetroll, 11 years ago

added the base for the new code for the smartreader. The code isn't called yet

File size: 9.4 KB
Line 
1#ifdef HAVE_LIBUSB
2/*
3 ifd_smartreader.c
4 This module provides IFD handling functions for for Argolis smartreader+.
5*/
6
7#include <stdio.h>
8#include <time.h>
9#include <string.h>
10#include"ifd_smartreader.h"
11
12#define OK 1
13#define ERROR 0
14
15int SR_Init (int device_index)
16{
17
18 int ret;
19
20 if(!find_smartreader(device_index, &ftdic))
21 return ERROR;
22
23 //The smartreader has different endpoint addresses
24 //compared to a real FT232 device, so change them here,
25 //also a good way to compare a real FT232 with a smartreader
26 //if you enumarate usb devices
27 ftdic.in_ep = 0x1;
28 ftdic.out_ep = 0x82;
29
30 //open the first smartreader if found by find_smartreader
31 if ((ret = ftdi_usb_open(&ftdic, 0x0403, 0x6001)) < 0) {
32 cs_log("unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
33 return ERROR;
34 }
35
36 //Set the FTDI latency timer to 1ms
37 ret = ftdi_set_latency_timer(&ftdic, 1);
38
39 //Set databits to 8o2
40 ret = ftdi_set_line_property(&ftdic, BITS_8, STOP_BIT_2, ODD);
41
42 //Set the DTR HIGH and RTS LOW
43 ftdi_setdtr_rts(&ftdic, 1, 1);
44
45 //Disable flow control
46 ftdi_setflowctrl(&ftdic, 0);
47
48 ret = pthread_create(&rt, NULL, ReaderThread, (void *)&ftdic);
49 if (ret) {
50 cs_log("ERROR; return code from pthread_create() is %d\n", ret);
51 return ERROR;
52 }
53
54
55 return OK;
56}
57
58
59int SR_GetStatus (int * in)
60{
61 int state;
62
63 //state = 0 no card, 1 = not ready, 2 = ready
64 if (state)
65 *in = 1; //CARD, even if not ready report card is in, or it will never get activated
66 else
67 *in = 0; //NOCARD
68 return OK;
69}
70
71int SR_Reset (ATR ** atr)
72{
73 unsigned char data[ATR_MAX_SIZE] = {0};
74 int ret;
75
76 //Reset smartreader to defaults
77 ResetSmartReader(&ftdic);
78
79 //Reset smartcard
80 pthread_mutex_lock(&g_usb_mutex);
81 ftdi_setdtr_rts(&ftdic, 1, 1);
82 usleep(200000);
83 ftdi_setdtr_rts(&ftdic, 1, 0);
84 pthread_mutex_unlock(&g_usb_mutex);
85 //Read the ATR
86 ret = smart_read(&ftdic, data, 32,1);
87 if(data[0]==0x03) {
88 sr_config.inv=1;
89 EnableSmartReader(&ftdic, 3571200, 372, 1, 0, sr_config.inv);
90 }
91 // parse atr
92 (*atr) = ATR_New ();
93 if(ATR_InitFromArray ((*atr), data, ret) == ATR_OK)
94 {
95 struct timespec req_ts;
96 req_ts.tv_sec = 0;
97 req_ts.tv_nsec = 50000000;
98 nanosleep (&req_ts, NULL);
99 return OK;
100 }
101 else
102 {
103 ATR_Delete (*atr);
104 (*atr) = NULL;
105 return ERROR;
106 }
107
108}
109
110int SR_Transmit (BYTE * sent, unsigned size)
111{
112 int ret;
113 ret = smart_write(&ftdic, sent, size, 0);
114 if (ret!=size)
115 return ERROR;
116
117 return OK;
118}
119
120int SR_Receive (BYTE * data, unsigned size)
121{
122 int ret;
123 ret = smart_read(&ftdic, data, size,1);
124 if (ret!=size)
125 return ERROR;
126
127 return OK;
128}
129
130int SR_SetBaudrate (int mhz)
131{
132
133 sr_config.fs=mhz*1000; //freq in KHz
134 EnableSmartReader(&ftdic, sr_config.fs, sr_config.F, sr_config.D, sr_config.N, sr_config.inv);
135
136 return OK;
137}
138
139
140bool find_smartreader(int index, struct ftdi_context* ftdic)
141{
142 int ret, i;
143 bool dev_found;
144 struct ftdi_device_list *devlist, *curdev;
145 char manufacturer[128], description[128];
146
147 if (ftdi_init(ftdic) < 0) {
148 fprintf(stderr, "ftdi_init failed\n");
149 return ERROR;
150 }
151
152 if ((ret = ftdi_usb_find_all(ftdic, &devlist, 0x0403, 0x6001)) < 0)
153 {
154 fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
155 return ERROR;
156 }
157
158 printf("Number of FTDI devices found: %d\n", ret);
159
160 i = 0;
161 dev_found=FALSE;
162 for (curdev = devlist; curdev != NULL; i++)
163 {
164 printf("Checking device: %d\n", i);
165 if ((ret = ftdi_usb_get_strings(ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0)
166 {
167 fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(ftdic));
168 return ERROR;
169 }
170 printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description);
171 if (i==index)
172 {
173 printf("Found device index %d\n",i);
174 dev_found=TRUE;
175 break;
176 }
177 curdev = curdev->next;
178 }
179
180 ftdi_list_free(&devlist);
181
182 if(!dev_found)
183 {
184 printf("Device not found\n");
185
186 ftdi_deinit(ftdic);
187 return FALSE;
188 }
189
190 return TRUE;
191}
192
193void smart_flush(struct ftdi_context* ftdic)
194{
195
196 pthread_mutex_lock(&g_usb_mutex);
197 ftdi_usb_purge_buffers(ftdic);
198 pthread_mutex_unlock(&g_usb_mutex);
199
200 pthread_mutex_lock(&g_read_mutex);
201 g_read_buffer_size = 0;
202 pthread_mutex_unlock(&g_read_mutex);
203}
204
205int smart_read(struct ftdi_context* ftdic, unsigned char* buff, size_t size, int timeout_sec)
206{
207
208 int ret = 0;
209 int total_read = 0;
210 struct timeval start, now, dif = {0};
211 gettimeofday(&start,NULL);
212
213
214 while(total_read < size && dif.tv_sec < timeout_sec) {
215
216 pthread_mutex_lock(&g_read_mutex);
217 if(g_read_buffer_size > 0) {
218
219 ret = g_read_buffer_size>size-total_read ? size-total_read : g_read_buffer_size;
220 memcpy(buff+total_read,g_read_buffer,ret);
221 g_read_buffer_size -= ret;
222 total_read+=ret;
223 }
224 pthread_mutex_unlock(&g_read_mutex);
225
226 gettimeofday(&now,NULL);
227 timersub(&now, &start, &dif);
228 }
229
230
231 return total_read;
232}
233
234int smart_write(struct ftdi_context* ftdic, unsigned char* buff, size_t size, int udelay)
235{
236
237 int ret = 0;
238 int idx;
239 printf("write: ");
240 hexdump(buff, size, 0);
241
242 struct timeval start, stop, taken;
243 gettimeofday(&start, NULL);
244
245 if (udelay == 0) {
246 pthread_mutex_lock(&g_usb_mutex);
247 ret = ftdi_write_data(ftdic, buff, size);
248 pthread_mutex_unlock(&g_usb_mutex);
249 }
250 else {
251 for (idx = 0; idx < size; idx++) {
252 pthread_mutex_lock(&g_usb_mutex);
253 if ((ret = ftdi_write_data(ftdic, &buff[idx], 1)) < 0){
254 pthread_mutex_unlock(&g_usb_mutex);
255 break;
256 }
257 pthread_mutex_unlock(&g_usb_mutex);
258 usleep(udelay);
259 }
260 }
261
262 gettimeofday(&stop, NULL);
263 timersub(&stop, &start, &taken);
264 printf(" took %u.000%u seconds\n", (unsigned int) taken.tv_sec, (unsigned int) taken.tv_usec);
265 return ret;
266}
267
268void EnableSmartReader(struct ftdi_context* ftdic, int clock, unsigned short Fi, unsigned char Di, unsigned char Ni, unsigned char inv) {
269
270 int ret = 0;
271 unsigned char buff[4];
272 int delay=50000;
273
274 pthread_mutex_lock(&g_usb_mutex);
275 ret = ftdi_set_baudrate(ftdic, 9600);
276 ret = ftdi_set_line_property(ftdic, (enum ftdi_bits_type) 5, STOP_BIT_2, NONE);
277 pthread_mutex_unlock(&g_usb_mutex);
278
279 unsigned char FiDi[] = {0x01, HIBYTE(Fi), LOBYTE(Fi), Di};
280 ret = smart_write(ftdic, FiDi, sizeof (FiDi),-1);
281 usleep(delay);
282
283 unsigned short freqk = (unsigned short) (clock / 1000);
284 unsigned char Freq[] = {0x02, HIBYTE(freqk), LOBYTE(freqk)};
285 ret = smart_write(ftdic, Freq, sizeof (Freq),-1);
286 usleep(delay);
287
288 unsigned char N[] = {0x03, Ni};
289 ret = smart_write(ftdic, N, sizeof (N),-1);
290 usleep(delay);
291
292 unsigned char Prot[] = {0x04, 0x00};
293 ret = smart_write(ftdic, Prot, sizeof (Prot),-1);
294 usleep(delay);
295
296 unsigned char Invert[] = {0x05, inv};
297 ret = smart_write(ftdic, Invert, sizeof (Invert),-1);
298 usleep(delay);
299
300 pthread_mutex_lock(&g_usb_mutex);
301 ret = ftdi_set_line_property2(ftdic, BITS_8, STOP_BIT_2, ODD, BREAK_ON);
302 pthread_mutex_unlock(&g_usb_mutex);
303
304 usleep(50000);
305
306 pthread_mutex_lock(&g_usb_mutex);
307 ret = ftdi_set_line_property2(ftdic, BITS_8, STOP_BIT_2, ODD, BREAK_OFF);
308 pthread_mutex_unlock(&g_usb_mutex);
309
310 smart_flush(ftdic);
311}
312
313void ResetSmartReader(struct ftdi_context* ftdic)
314{
315
316 smart_flush(ftdic);
317 EnableSmartReader(ftdic, 3571200, 372, 1, 0, 0);
318 // set smartreader+ default values
319 sr_config.F=372;
320 sr_config.D=1.0;
321 sr_config.fs=3571200;
322 sr_config.N=0;
323 sr_config.T=0;
324 sr_config.inv=0;
325
326}
327
328void* ReaderThread(void *p)
329{
330
331 struct ftdi_context* ftdic = (struct ftdi_context*)p;
332 bool running = TRUE;
333 int ret;
334 unsigned char local_buffer[64]; //64 is max transfer size of FTDI bulk pipe
335
336 while(running){
337
338 if(g_read_buffer_size == sizeof(g_read_buffer)){
339 //if out read buffer is full then delay
340 //slightly and go around again
341 struct timespec req = {0,200000000}; //20ms
342 nanosleep(&req,NULL);
343 continue;
344 }
345
346 pthread_mutex_lock(&g_usb_mutex);
347 ret = usb_bulk_read(ftdic->usb_dev,ftdic->out_ep,(char*)local_buffer,64,1000);
348 pthread_mutex_unlock(&g_usb_mutex);
349 pthread_yield_np();
350
351 if(ret>2){ //FTDI always sends modem status bytes as first 2 chars with the 232BM
352 pthread_mutex_lock(&g_read_mutex);
353
354 int copy_size = sizeof(g_read_buffer) - g_read_buffer_size > ret-2 ?ret-2: sizeof(g_read_buffer) - g_read_buffer_size;
355 memcpy(g_read_buffer+g_read_buffer_size,local_buffer+2,copy_size);
356 g_read_buffer_size += copy_size;
357 //printf("Transferred %u bytes to read buffer - current buffer = ",copy_size); hexdump(g_read_buffer,g_read_buffer_size); printf("\n");
358 pthread_mutex_unlock(&g_read_mutex);
359 }else{
360 //sleep for 50ms since there was nothing to read last time
361 usleep(50000);
362 }
363 }
364
365 pthread_exit(NULL);
366}
367
368
369#endif
Note: See TracBrowser for help on using the repository browser.