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

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

add test for USE_PTHREAD in the smartreader code as we use both libusb and pthread

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