source: trunk/csctapi/ifd_sc8in1.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 8.9 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2/*
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#include <stdio.h>
21//#include <time.h>
22//#include <string.h>
23//#include "ioctls.h"
24#include "../globals.h"
25#include "atr.h"
26#include <termios.h>
27#include "ifd_sc8in1.h"
28#include "io_serial.h"
29#include "icc_async.h"
30
31static struct termios stored_termio[8];//FIXME no globals please
32static int current_slot; //FIXME should not be a global, but one per SC8in1
33static unsigned char cardstatus; //FIXME not global but one per SC8in1 //if not static, the threads dont share same cardstatus!
34
35#define MAX_TRANSMIT 255
36
37static int sc8in1_command(struct s_reader * reader, unsigned char * buff, unsigned short lenwrite, unsigned short lenread)
38{
39 int init_phase = (buff[0] == 0x63); //FIXME UGLY
40 struct termios termio, termiobackup;
41
42 // backup data
43 tcgetattr(reader->handle,&termio);
44 memcpy(&termiobackup,&termio,sizeof(termio));
45
46 // switch SC8in1 to command mode
47 IO_Serial_DTR_Set(reader);
48
49 // set communication parameters
50 termio.c_oflag = 0;
51 termio.c_lflag = 0;
52 termio.c_cc[VTIME] = 1; // working
53 termio.c_cflag = B9600|CS8|CREAD|CLOCAL;
54 if (tcsetattr(reader->handle,TCSANOW,&termio) < 0) {
55 cs_log("ERROR: SC8in1 Command error in set RS232 attributes\n");
56 return ERROR;
57 }
58 cs_ddump_mask (D_DEVICE, buff, lenwrite, "IO: Sending: ");
59 if (!write(reader->handle, buff, lenwrite)) { //dont use IO_Serial_Write since mcr commands dont echo back
60 cs_log("SC8in1 Command write error");
61 return ERROR;
62 }
63 tcdrain(reader->handle);
64 // give some time back to the system .. we're in a thread after all
65 sched_yield();
66
67 if (IO_Serial_Read (reader, 1000, lenread, buff) == ERROR) {
68 cs_log("SC8in1 Command read error");
69 return ERROR;
70 }
71 // give some time back to the system .. we're in a thread after all
72 sched_yield();
73 // restore data
74 memcpy(&termio,&termiobackup,sizeof(termio));
75 if (tcsetattr(reader->handle,TCSANOW,&termio) < 0) {
76 cs_log("ERROR: SC8in1 Command error in restore RS232 attributes\n");
77 return ERROR;
78 }
79 if(!init_phase)
80 // switch SC8in1 to normal mode
81 IO_Serial_DTR_Clr(reader);
82 // give some time back to the system .. we're in a thread after all
83 sched_yield();
84 return OK;
85}
86
87static int readsc8in1(struct s_reader * reader)
88{
89 // Reads the card status
90 //
91 // the bits in the return bytes:
92 // bit0=1 means Slot1=Smartcard inside
93 // bit1=1 means Slot2=Smartcard inside
94 // bit2=1 means Slot3=Smartcard inside
95 // bit3=1 means Slot4=Smartcard inside
96 // bit4=1 means Slot5=Smartcard inside
97 // bit5=1 means Slot6=Smartcard inside
98 // bit6=1 means Slot7=Smartcard inside
99 // bit7=1 means Slot8=Smartcard inside
100 unsigned char buf[10];
101 buf[0]=0x47;
102 IO_Serial_Flush(reader);
103 if (sc8in1_command(reader, buf, 1, 8) < 0) return (-1);
104 if (buf[1]!=0x90) return(-1);
105
106 // return result byte
107 return(buf[2]);
108}
109
110int Sc8in1_Selectslot(struct s_reader * reader, int slot) {
111 // selects the Smartcard Socket "slot"
112 //
113 if (slot == current_slot)
114 return OK;
115 cs_log("SC8in1: select slot %i", slot);
116 int res;
117 unsigned char tmp[128];
118 struct termios termio;
119 //cs_sleepms(10); //FIXME do I need this?
120 // backup rs232 data
121 tcgetattr(reader->handle,&termio);
122 if (current_slot != 0)
123 memcpy(&stored_termio[current_slot-1],&termio,sizeof(termio));
124 //
125 // switch SC8in1 to command mode
126 IO_Serial_DTR_Set(reader);
127 // give some time back to the system .. we're in a thread after all
128 sched_yield();
129
130 // set communication parameters
131 termio.c_cc[VTIME] = 1; // working
132 termio.c_cflag = B9600|CS8|CREAD|CLOCAL;
133 if (tcsetattr(reader->handle,TCSANOW,&termio) < 0) {
134 cs_log("ERROR: SC8in1 selectslot set RS232 attributes\n");
135 return ERROR;
136 }
137 tcflush(reader->handle, TCIOFLUSH);
138 // selecd select slot command to SC8in1
139 //tmp[0]=0x73; //MCR command
140 tmp[0]=0x53;
141 tmp[1]=slot&0x0F;
142 IO_Serial_Write (reader, 0, 2, tmp);
143 // give some time back to the system .. we're in a thread after all
144 sched_yield();
145 tcdrain(reader->handle);
146 //tcflush(reader->handle, TCIOFLUSH);
147 res=IO_Serial_Read (reader, 1000, 4, tmp); // ignore reader response of 4 bytes
148 current_slot = slot;
149 // give some time back to the system .. we're in a thread after all
150 sched_yield();
151 tcdrain(reader->handle);
152 // restore rs232 data
153 memcpy(&termio, &stored_termio[reader->slot-1], sizeof(termio));
154 if (tcsetattr(reader->handle,TCSANOW,&termio) < 0) {
155 cs_log("ERROR: SC8in1 selectslot restore RS232 attributes\n");
156 return ERROR;
157 }
158 // switch SC8in1 to normal mode
159 IO_Serial_DTR_Clr(reader);
160 //cs_sleepms(10); //FIXME do I need this?
161 // give some time back to the system .. we're in a thread after all
162 sched_yield();
163 return OK;
164}
165
166int Sc8in1_Init(struct s_reader * reader)
167{
168 //additional init, Phoenix_Init is also called for Sc8in1 !
169 struct termios termio;
170 int i,pos, speed,fd = reader->handle;
171 unsigned int is_mcr, sc8in1_clock = 0;
172
173 tcgetattr(reader->handle,&termio);
174 for (i=0; i<8; i++) {
175 //init all stored termios to default comm settings after device init, before ATR
176 memcpy(&stored_termio[i],&termio,sizeof(termio));
177 }
178
179 // check for a MCR device and how many slots it has.
180 unsigned char buff[] = { 0x74 };
181 sc8in1_command(reader, buff, 1, 1);
182 if (buff[0] == 4 || buff[0] == 8) {
183 is_mcr = (unsigned short) buff[0];
184 cs_log("SC8in1: device MCR%i detected", is_mcr);
185 }
186 else
187 is_mcr = 0;
188
189 tcflush(reader->handle, TCIOFLUSH); // a non MCR reader might give longer answer
190
191 for (i=0; i<CS_MAXREADER; i++) //copy handle to other slots, FIXME change this if multiple sc8in1 readers
192 if (reader[i].typ == R_SC8in1) {
193 if (reader[i].slot == 0) {//not initialized yet
194 pos = strlen(reader[i].device)-2; //this is where : should be located; is also valid length of physical device name
195 if (reader[i].device[pos] != 0x3a) //0x3a = ":"
196 cs_log("ERROR: '%c' detected instead of slot separator `:` at second to last position of device %s", reader[i].device[pos], reader[i].device);
197 reader[i].slot=(int)reader[i].device[pos+1] - 0x30;//FIXME test boundaries
198 reader[i].device[pos]= 0; //slot 1 reader now gets correct physicalname
199 }
200 reader[i].handle = fd;
201 }
202
203 if (is_mcr) {
204 //if MCR set clock
205 switch (reader->mhz) {
206 case 357:
207 case 358:
208 speed=0;
209 break;
210 case 368:
211 case 369:
212 speed = 1;
213 break;
214 case 600:
215 speed = 2;
216 break;
217 case 800:
218 speed = 3;
219 break;
220 default:
221 speed = 0;
222 cs_log("ERROR Sc8in1, cannot set clockspeed to %i", reader->mhz);
223 break;
224 }
225 sc8in1_clock |= (speed << (reader[i].slot - 1) * 2);
226 buff[0] = 0x63; //MCR set clock
227 buff[1] = (sc8in1_clock >> 8) & 0xFF;
228 buff[2] = sc8in1_clock & 0xFF;
229 sc8in1_command(reader, buff, 3, 0);
230 }
231
232 //IO_Serial_Flush(reader); //FIXME somehow ATR is generated and must be flushed
233 i = -1; //Flag for GetStatus init
234 Sc8in1_GetStatus(reader, &i); //Initialize cardstatus
235
236 return OK;
237}
238
239int Sc8in1_Card_Changed(struct s_reader * reader) {
240 // returns the SC8in1 Status
241 // 0= no card was changed (inserted or removed)
242 // -1= one ore more cards were changed (inserted or removed)
243 int result;
244 int lineData;
245 ioctl(reader->handle, TIOCMGET, &lineData);
246 result= (lineData & TIOCM_CTS) / TIOCM_CTS;
247 // give some time back to the system .. we're in a thread after all
248 sched_yield();
249 return(result-1);
250}
251
252int Sc8in1_GetStatus (struct s_reader * reader, int * in)
253{
254 if (Sc8in1_Card_Changed(reader)|| *in == -1) { //FIXME what happens if slot 1 has no reader defined
255 cs_debug("SC8in1: locking for Getstatus for slot %i",reader->slot);
256 pthread_mutex_lock(&sc8in1);
257 cs_debug("SC8in1: locked for Getstatus for slot %i",reader->slot);
258 int i=readsc8in1(reader); //read cardstatus
259 pthread_mutex_unlock(&sc8in1);
260 cs_debug("SC8in1: unlocked for Getstatus for slot %i",reader->slot);
261 if (i < 0) {
262 // give some time back to the system .. we're in a thread after all
263 sched_yield();
264 return ERROR;
265 }
266 cardstatus = i;
267 }
268 *in = (cardstatus & 1<<(reader->slot-1));
269 // give some time back to the system .. we're in a thread after all
270 sched_yield();
271 return OK;
272}
Note: See TracBrowser for help on using the repository browser.