- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / csctapi / ifd_sc8in1.c
blobcc5a1f91f9cf8edea1291097c2585675cf709624
1 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "../globals.h"
21 #ifdef CARDREADER_SC8IN1
22 #include "../oscam-lock.h"
23 #include "../oscam-string.h"
24 #include "../oscam-time.h"
25 #include "atr.h"
26 #include "ifd_phoenix.h"
27 #include "io_serial.h"
29 #define OK 0
30 #define ERROR 1
32 struct s_sc8in1_display
34 char *text;
35 uint16_t text_length;
36 uint16_t char_change_time;
37 uint16_t last_char;
38 uint8_t blocking;
39 struct s_sc8in1_display *next;
42 struct sc8in1_data
44 struct termios stored_termio[8];
45 uint16_t current_slot;
46 uint32_t current_baudrate;
47 struct s_reader *current_reader;
48 unsigned char cardstatus;
49 unsigned char mcr_type;
50 CS_MUTEX_LOCK sc8in1_lock;
51 struct s_sc8in1_display *display;
52 CS_MUTEX_LOCK sc8in1_display_lock;
53 unsigned char display_running;
54 pthread_t display_thread;
57 #ifdef WITH_DEBUG
58 static int32_t Sc8in1_DebugSignals(struct s_reader *reader, uint16_t slot, const char *extra)
60 uint32_t msr;
61 if(ioctl(reader->handle, TIOCMGET, &msr) < 0)
62 { return ERROR; }
63 rdr_log_dbg(reader, D_DEVICE, "SC8in1: Signals(%s): Slot: %i, DTR: %u, RTS: %u",
64 extra, slot, msr & TIOCM_DTR ? 1 : 0, msr & TIOCM_RTS ? 1 : 0);
65 return OK;
67 #else
68 #define Sc8in1_DebugSignals(a, b, c) {}
69 #endif
71 static int32_t Sc8in1_NeedBaudrateChange(struct s_reader *reader, uint32_t desiredBaudrate, struct termios *current, struct termios *new, uint8_t cmdMode)
73 struct sc8in1_data *crdr_data = reader->crdr_data;
74 // Returns 1 if we need to change the baudrate
75 if((desiredBaudrate != crdr_data->current_baudrate) ||
76 (reader->mhz != reader->cardmhz) ||
77 (cmdMode == 0 && memcmp(current, new, sizeof(struct termios))))
79 rdr_log_dbg(reader, D_TRACE, "Sc8in1_NeedBaudrateChange 1");
80 return 1;
82 rdr_log_dbg(reader, D_TRACE, "Sc8in1_NeedBaudrateChange 0");
83 return 0;
86 static int32_t Sc8in1_SetBaudrate(struct s_reader *reader, uint32_t baudrate, struct termios *termio, uint8_t cmdMode)
88 struct sc8in1_data *crdr_data = reader->crdr_data;
89 /* Get current settings */
90 struct termios tio;
91 if(termio == NULL)
93 call(tcgetattr(reader->handle, &tio) != 0);
95 else
97 tio = *termio;
98 if(baudrate == 0)
100 baudrate = reader->current_baudrate;
101 if(baudrate == 0)
103 baudrate = 9600;
107 rdr_log_dbg(reader, D_IFD, "Sc8in1 Setting baudrate to %u", baudrate);
108 rdr_log_dbg(reader, D_TRACE, "Sc8in1 Setting baudrate to %u, reader br=%u, currentBaudrate=%u, cmdMode=%u",
109 baudrate, reader->current_baudrate, crdr_data->current_baudrate, cmdMode);
110 call(IO_Serial_SetBitrate(reader, baudrate, &tio));
111 crdr_data->current_baudrate = baudrate;
112 call(IO_Serial_SetProperties(reader, tio));
113 if(cmdMode == 0)
115 reader->current_baudrate = baudrate;
117 return OK;
120 static int32_t sc8in1_tcdrain(struct s_reader *reader)
122 while(1)
124 int32_t tcdrain_ret = tcdrain(reader->handle);
125 if(tcdrain_ret == -1)
127 if(errno == EINTR)
129 //try again in case of Interrupted system call
130 continue;
132 else
133 { rdr_log(reader, "ERROR: %s: (errno=%d %s)", __func__, errno, strerror(errno)); }
134 return ERROR;
136 break;
138 return OK;
141 static int32_t sc8in1_command(struct s_reader *reader, unsigned char *buff,
142 uint16_t lenwrite, uint16_t lenread, uint8_t enableEepromWrite, unsigned char UNUSED(getStatusMode),
143 uint8_t selectSlotMode)
145 struct sc8in1_data *crdr_data = reader->crdr_data;
146 struct termios termio, termiobackup;
147 uint32_t currentBaudrate = 0;
149 if(! reader->handle)
151 rdr_log(reader, "ERROR: SC8in1 Command no valid handle");
152 return ERROR;
155 Sc8in1_DebugSignals(reader, reader->slot, "CMD10");
157 // switch SC8in1 to command mode
158 IO_Serial_DTR_Set(reader);
159 tcflush(reader->handle, TCIOFLUSH);
161 // backup data
162 tcgetattr(reader->handle, &termio);
163 memcpy(&termiobackup, &termio, sizeof(termio));
165 if(selectSlotMode)
167 if(crdr_data->current_slot != 0)
169 memcpy(&crdr_data->stored_termio[crdr_data->current_slot - 1],
170 &termiobackup, sizeof(termiobackup)); //not if current_slot is undefined
174 // set communication parameters
175 termio.c_oflag = 0;
176 termio.c_lflag = 0;
177 termio.c_cc[VTIME] = 1; // working
178 termio.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
180 // Do we need to set the baudrate?
181 if(Sc8in1_NeedBaudrateChange(reader, 9600, &termiobackup, &termio, 1))
183 rdr_log_dbg(reader, D_TRACE, "Sc8in1_NeedBaudrateChange for SC8in1 command");
184 // save current baudrate for later restore
185 currentBaudrate = crdr_data->current_baudrate;
186 crdr_data->current_baudrate = 9600;
187 cfsetospeed(&termio, B9600);
188 cfsetispeed(&termio, B9600);
189 rdr_log_dbg(reader, D_DEVICE, "standard baudrate: cardmhz=%d mhz=%d -> effective baudrate %u", reader->cardmhz, reader->mhz, 9600);
191 if(tcsetattr(reader->handle, TCSANOW, &termio) < 0)
193 rdr_log(reader, "ERROR: SC8in1 Command error in set RS232 attributes");
194 return ERROR;
196 if(reader->sc8in1_dtrrts_patch == 1)
198 IO_Serial_DTR_Set(reader);
200 Sc8in1_DebugSignals(reader, reader->slot, "CMD11");
202 // enable EEPROM write
203 if(enableEepromWrite)
205 unsigned char eepromBuff[3];
206 eepromBuff[0] = 0x70;
207 eepromBuff[1] = 0xab;
208 eepromBuff[2] = 0xba;
209 rdr_log_dump_dbg(reader, D_DEVICE, eepromBuff, 3, "Sending:");
210 if(!write(reader->handle, eepromBuff, 3))
212 rdr_log(reader, "SC8in1 Command write EEPROM error");
213 return ERROR;
215 tcflush(reader->handle, TCIOFLUSH);
217 // write cmd
218 rdr_log_dump_dbg(reader, D_DEVICE, buff, lenwrite, "Sending:");
219 int32_t dataWritten = 0, dataToWrite = lenwrite;
220 while(dataWritten < lenwrite)
222 int32_t written = write(reader->handle, buff, dataToWrite);
223 if(written == -1)
225 rdr_log(reader, "SC8in1 Command write error");
226 return ERROR;
228 if(written == lenwrite)
230 break;
232 else
234 dataWritten += written;
235 dataToWrite -= written;
239 sc8in1_tcdrain(reader);
241 if(IO_Serial_Read(reader, 0, 1000000, lenread, buff) == ERROR)
243 rdr_log(reader, "SC8in1 Command read error");
244 return ERROR;
247 // Workaround for systems where tcdrain doesnt work properly
248 if(lenread <= 0 && crdr_data->mcr_type)
250 unsigned char buff_echo_hack[2] = { 0x65, 'A' };
251 rdr_log_dump_dbg(reader, D_DEVICE, &buff_echo_hack[0], 2, "Sending:");
252 if(write(reader->handle, &buff_echo_hack[0], 2) != 2)
254 rdr_log(reader, "SC8in1 Echo command write error");
255 return ERROR;
257 sc8in1_tcdrain(reader);
258 if(IO_Serial_Read(reader, 0, 1000000, 1, &buff_echo_hack[0]) == ERROR)
260 rdr_log(reader, "SC8in1 Echo command read error");
261 return ERROR;
263 if(buff_echo_hack[0] != 'A')
265 rdr_log(reader, "SC8in1 Echo command read wrong character");
269 if(selectSlotMode)
271 memcpy(&termiobackup, &crdr_data->stored_termio[selectSlotMode - 1],
272 sizeof(termiobackup));
273 if(Sc8in1_NeedBaudrateChange(reader, reader->current_baudrate, &termio, &termiobackup, 1))
275 rdr_log_dbg(reader, D_TRACE, "Sc8in1_SetTermioForSlot for select slot");
276 if(Sc8in1_SetBaudrate(reader, reader->current_baudrate, &termiobackup, 0))
278 rdr_log(reader, "ERROR: SC8in1 Command Sc8in1_SetBaudrate");
279 return ERROR;
282 else
284 if(tcsetattr(reader->handle, TCSANOW, &termiobackup) < 0)
286 rdr_log(reader, "ERROR: SC8in1 Command error in set RS232 attributes");
287 return ERROR;
291 else
293 // restore baudrate only if changed
294 if(currentBaudrate)
296 if(Sc8in1_SetBaudrate(reader, currentBaudrate, &termiobackup, 1))
298 rdr_log(reader, "ERROR: SC8in1 selectslot restore Bitrate attributes");
299 return ERROR;
302 else
304 // restore data
305 if(tcsetattr(reader->handle, TCSANOW, &termiobackup) < 0)
307 rdr_log(reader, "ERROR: SC8in1 Command error in restore RS232 attributes");
308 return ERROR;
313 Sc8in1_DebugSignals(reader, reader->slot, "CMD12");
314 if(reader->sc8in1_dtrrts_patch == 1)
316 IO_Serial_DTR_Set(reader);
319 tcflush(reader->handle, TCIOFLUSH);
321 // switch SC8in1 to normal mode
322 IO_Serial_DTR_Clr(reader);
324 Sc8in1_DebugSignals(reader, reader->slot, "CMD13");
326 return OK;
329 static int32_t mcrReadStatus(struct s_reader *reader, unsigned char *status)
331 unsigned char buff[2] = "";
332 buff[0] = 0x3f;
333 if(sc8in1_command(reader, buff, 1, 2, 0, 1, 0) < 0)
334 { return ERROR; }
335 status[0] = buff[0];
336 status[1] = buff[1];
337 return OK;
340 static int32_t sc8in1ReadStatus(struct s_reader *reader, unsigned char *status)
342 unsigned char buff[9]; // read 1 echo byte + 8 status bytes
343 buff[0] = 0x47;
344 if(sc8in1_command(reader, buff, 1, 9, 0, 1, 0) < 0)
345 { return ERROR; }
346 memcpy(&status[0], &buff[1], 8);
347 return OK;
351 static int32_t mcrReadType(struct s_reader *reader, unsigned char *type)
353 unsigned char buff[1];
354 buff[0] = 0x74;
355 if(sc8in1_command(reader, buff, 1, 1, 0, 0, 0) < 0)
356 { return ERROR; }
357 type[0] = buff[0];
358 return OK;
361 static int32_t mcrReadVersion(struct s_reader *reader, unsigned char *version)
363 unsigned char buff[1];
364 buff[0] = 0x76;
365 if(sc8in1_command(reader, buff, 1, 1, 0, 0, 0) < 0)
366 { return ERROR; }
367 version[0] = buff[0];
368 return OK;
371 static int32_t mcrReadSerial(struct s_reader *reader, unsigned char *serial)
373 unsigned char buff[2];
374 buff[0] = 0x6e;
375 if(sc8in1_command(reader, buff, 1, 2, 0, 0, 0) < 0)
376 { return ERROR; }
377 serial[0] = buff[1];
378 serial[1] = buff[0];
379 return OK;
382 /*static int32_t mcrWriteDisplayRaw(struct s_reader *reader, unsigned char data[7]) {
383 unsigned char buff[8];
384 buff[0] = 0x64;
385 memcpy(&buff[1], &data[0], 7);
386 if (sc8in1_command(reader, buff, 8, 0, 0, 0, 0) < 0)
387 return ERROR;
388 return OK;
391 static int32_t mcrWriteDisplayAscii(struct s_reader *reader, unsigned char data, unsigned char timeout)
393 unsigned char buff[3];
394 buff[0] = 0x61;
395 buff[1] = data;
396 buff[2] = timeout;
397 if(sc8in1_command(reader, buff, 3, 0, 0, 0, 0) < 0)
398 { return ERROR; }
399 return OK;
402 static int32_t mcrWriteClock(struct s_reader *reader, unsigned char saveClock, unsigned char clock_val[2])
404 unsigned char buff[3];
405 buff[0] = 0x63;
406 buff[1] = clock_val[0];
407 buff[2] = clock_val[1];
408 if(sc8in1_command(reader, buff, 3, 0, 0, 0, 0) < 0)
409 { return ERROR; }
410 if(saveClock)
412 buff[0] = 0x6d;
413 if(sc8in1_command(reader, buff, 1, 0, 1, 0, 0) < 0)
414 { return ERROR; }
416 return OK;
419 static int32_t mcrReadClock(struct s_reader *reader, unsigned char *clock_val)
421 unsigned char buff[2];
422 buff[0] = 0x67;
423 if(sc8in1_command(reader, buff, 1, 2, 0, 0, 0) < 0)
424 { return ERROR; }
425 clock_val[0] = buff[0];
426 clock_val[1] = buff[1];
427 return OK;
430 static int32_t mcrWriteTimeout(struct s_reader *reader, unsigned char timeout[2])
432 unsigned char buff[3];
433 buff[0] = 0x6f;
434 buff[1] = timeout[0];
435 buff[2] = timeout[1];
436 if(sc8in1_command(reader, buff, 3, 0, 1, 0, 0) < 0)
437 { return ERROR; }
438 return OK;
441 static int32_t mcrReadTimeout(struct s_reader *reader, unsigned char *timeout)
443 unsigned char buff[2];
444 buff[0] = 0x72;
445 if(sc8in1_command(reader, buff, 1, 2, 0, 0, 0) < 0)
446 { return ERROR; }
447 timeout[0] = buff[1];
448 timeout[1] = buff[0];
449 return OK;
452 static int32_t mcrSelectSlot(struct s_reader *reader, unsigned char slot)
454 // Select slot for MCR device.
455 // Parameter slot is from 1-8
456 unsigned char buff[2];
457 buff[0] = 0x73;
458 buff[1] = slot - 1;
459 if(sc8in1_command(reader, buff, 2, 0, 0, 0, slot) < 0)
460 { return ERROR; }
461 return OK;
464 static int32_t sc8in1SelectSlot(struct s_reader *reader, unsigned char slot)
466 // Select slot for SC8in1 device.
467 // Parameter slot is from 1-8
468 unsigned char buff[6];
469 buff[0] = 0x53;
470 buff[1] = slot & 0x0F;
471 // Read 6 Bytes: 2 Bytes write cmd and 4 unknown Bytes.
472 if(sc8in1_command(reader, buff, 2, 6, 0, 0, slot) < 0)
473 { return ERROR; }
474 return OK;
477 static int32_t MCR_DisplayText(struct s_reader *reader, char *text, uint16_t text_len, uint16_t ch_time, uint8_t blocking)
479 struct sc8in1_data *crdr_data = reader->crdr_data;
480 struct s_sc8in1_display *display;
481 if(cs_malloc(&display, sizeof(struct s_sc8in1_display)))
483 if(!cs_malloc(&display->text, text_len))
485 rdr_log(reader, "MCR_DisplayText: Out of memory.");
486 NULLFREE(display);
487 return ERROR;
489 if (display) {
490 memcpy(display->text, text, text_len);
491 display->text_length = text_len;
492 display->char_change_time = ch_time;
493 display->last_char = 0;
494 display->blocking = blocking;
495 display->next = NULL;
497 cs_writelock(__func__, &crdr_data->sc8in1_display_lock);
498 if(crdr_data->display == NULL)
500 crdr_data->display = display;
502 else
504 struct s_sc8in1_display *d = crdr_data->display;
505 while(d != NULL)
507 if(d->next == NULL)
509 d->next = display;
510 break;
512 else
514 d = d->next;
518 cs_writeunlock(__func__, &crdr_data->sc8in1_display_lock);
520 else
522 rdr_log(reader, "MCR_DisplayText: Out of memory.");
523 return ERROR;
525 return OK;
528 static int32_t mcrHelloOscam(struct s_reader *reader)
530 // Display "OSCam" on MCR display
531 char helloOscam[5] = {'O', 'S', 'C', 'a', 'm'};
532 return MCR_DisplayText(reader, &helloOscam[0], 5, 100, 1);
535 static int32_t mcr_generateStatisticsForDisplay(struct s_reader *reader)
537 // show number of clients
538 struct s_client *cl;
539 uint16_t numClients = 0;
540 for(cl = first_client; cl ; cl = cl->next)
542 if(cl->typ == 'c')
544 numClients++;
547 char msg[8] = { 0 };
548 int msgLen = snprintf(&msg[0], 8, "CN%i", numClients);
549 if(msgLen > 0 && MCR_DisplayText(reader, msg, msgLen, 300, 0))
551 return ERROR;
553 return OK;
556 static void *mcr_update_display_thread(void *param)
558 const uint16_t DEFAULT_SLEEP_TIME = 100;
559 const int32_t STATISTICS_UPDATE_SECONDS = 60;
560 struct s_reader *reader = (struct s_reader *)param;
561 struct sc8in1_data *crdr_data = reader->crdr_data;
562 time_t lastStatisticUpdateTime = time((time_t *)0);
564 if(reader->typ != R_SC8in1 || ! crdr_data->mcr_type)
566 rdr_log(reader, "Error: mcr_update_display_thread reader no MCR8in1 reader");
567 pthread_exit(NULL);
570 set_thread_name(__func__);
572 while(crdr_data->display_running)
574 uint16_t display_sleep = DEFAULT_SLEEP_TIME;
576 // Update statistics
577 time_t currentTime = time((time_t *)0);
578 if(currentTime - lastStatisticUpdateTime >= STATISTICS_UPDATE_SECONDS)
580 if(mcr_generateStatisticsForDisplay(reader))
582 rdr_log(reader, "ERROR: mcr_generateStatisticsForDisplay");
584 lastStatisticUpdateTime = currentTime;
587 cs_writelock(__func__, &crdr_data->sc8in1_display_lock);
588 if(crdr_data->display != NULL) // is there something to display?
590 cs_writeunlock(__func__, &crdr_data->sc8in1_display_lock);
592 display_sleep = crdr_data->display->char_change_time;
594 // display the next character
595 cs_writelock(__func__, &crdr_data->sc8in1_lock);
596 if(crdr_data->display->blocking)
598 uint16_t i = 0;
599 for(i = 0; i < crdr_data->display->text_length; i++)
601 if(mcrWriteDisplayAscii(crdr_data->current_reader,
602 crdr_data->display->text[++crdr_data->display->last_char - 1], 0xFF))
604 rdr_log(reader, "SC8in1: Error in mcr_update_display_thread write");
606 cs_sleepms(display_sleep);
609 else
611 if(mcrWriteDisplayAscii(crdr_data->current_reader,
612 crdr_data->display->text[++crdr_data->display->last_char - 1], 0xFF))
614 rdr_log(reader, "SC8in1: Error in mcr_update_display_thread write");
617 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
619 // remove the display struct if the text has been shown completely
620 if(crdr_data->display->last_char == crdr_data->display->text_length)
622 cs_writelock(__func__, &crdr_data->sc8in1_display_lock);
623 struct s_sc8in1_display *next = crdr_data->display->next;
624 NULLFREE(crdr_data->display->text);
625 NULLFREE(crdr_data->display);
626 crdr_data->display = next;
627 cs_writeunlock(__func__, &crdr_data->sc8in1_display_lock);
630 else
632 cs_writeunlock(__func__, &crdr_data->sc8in1_display_lock);
634 cs_sleepms(display_sleep);
636 pthread_exit(NULL);
637 return NULL;
641 static int32_t readSc8in1Status(struct s_reader *reader)
643 struct sc8in1_data *crdr_data = reader->crdr_data;
644 // Reads the card status
646 // the bits in the return bytes:
647 // bit0=1 means Slot1=Smartcard inside
648 // bit1=1 means Slot2=Smartcard inside
649 // bit2=1 means Slot3=Smartcard inside
650 // bit3=1 means Slot4=Smartcard inside
651 // bit4=1 means Slot5=Smartcard inside
652 // bit5=1 means Slot6=Smartcard inside
653 // bit6=1 means Slot7=Smartcard inside
654 // bit7=1 means Slot8=Smartcard inside
655 tcflush(reader->handle, TCIOFLUSH);
656 if(crdr_data->mcr_type)
658 unsigned char buff[2];
659 if(mcrReadStatus(reader, &buff[0]))
661 return (-1);
663 tcflush(reader->handle, TCIOFLUSH);
664 return buff[0];
666 else
668 unsigned char buff[8];
669 if(sc8in1ReadStatus(reader, &buff[0]))
671 return (-1);
673 if(buff[0] != 0x90)
675 return (-1);
677 tcflush(reader->handle, TCIOFLUSH);
678 return buff[1];
682 static int32_t Sc8in1_Selectslot(struct s_reader *reader, uint16_t slot)
684 // selects the Smartcard Socket "slot"
686 struct sc8in1_data *crdr_data = reader->crdr_data;
687 if(slot == crdr_data->current_slot)
688 { return OK; }
689 rdr_log_dbg(reader, D_TRACE, "SC8in1: select slot %i", slot);
691 #ifdef WITH_DEBUG
692 struct timeb tv_start, tv_end;
693 cs_ftime(&tv_start);
694 #endif
696 int32_t status = ERROR;
697 if(crdr_data->mcr_type)
699 status = mcrSelectSlot(reader, slot);
701 else
703 status = sc8in1SelectSlot(reader, slot);
706 if(status == OK)
708 crdr_data->current_reader = reader;
709 crdr_data->current_slot = slot;
711 #ifdef WITH_DEBUG
712 cs_ftime(&tv_end);
713 rdr_log_dbg(reader, D_DEVICE, "SC8in1 Selectslot in %"PRId64" ms", comp_timeb(&tv_end, &tv_start));
714 #endif
715 return status;
718 static int32_t Sc8in1_Card_Changed(struct s_reader *reader)
720 // returns the SC8in1 Status
721 // 0= no card was changed (inserted or removed)
722 // -1= one ore more cards were changed (inserted or removed)
723 int32_t result;
724 int32_t lineData;
725 if(reader->handle == 0)
726 { return 0; }
727 ioctl(reader->handle, TIOCMGET, &lineData);
728 result = (lineData & TIOCM_CTS) / TIOCM_CTS;
729 return result - 1;
732 static int32_t Sc8in1_GetStatus(struct s_reader *reader, int32_t *in)
734 // Only same thread my access serial port
735 struct sc8in1_data *crdr_data = reader->crdr_data;
736 if((crdr_data->current_slot == reader->slot && Sc8in1_Card_Changed(reader)) || *in == -1)
738 int32_t i = readSc8in1Status(reader); //read cardstatus
739 if(i < 0)
741 rdr_log(reader, "Sc8in1_GetStatus Error");
742 return ERROR;
744 crdr_data->cardstatus = i;
745 rdr_log_dbg(reader, D_TRACE, "SC8in1: Card status changed; cardstatus=0x%X", crdr_data->cardstatus);
747 *in = (crdr_data->cardstatus & 1 << (reader->slot - 1));
748 return OK;
751 static int32_t Sc8in1_Init(struct s_reader *reader)
753 struct sc8in1_data *crdr_data = reader->crdr_data;
754 //additional init, Phoenix_Init is also called for Sc8in1 !
755 struct termios termio;
756 int32_t i, speed, retval;
757 uint16_t sc8in1_clock = 0;
758 //unsigned char buff[3];
760 Sc8in1_DebugSignals(reader, reader->slot, "I-1");
762 // Clr DTR, which is set by phoenix_init
763 IO_Serial_DTR_Clr(reader);
765 tcgetattr(reader->handle, &termio);
766 for(i = 0; i < 8; i++)
768 //init all stored termios to default comm settings after device init, before ATR
769 memcpy(&crdr_data->stored_termio[i], &termio,
770 sizeof(termio));
773 // Init sc8in1 config
774 crdr_data->mcr_type = 0;
775 crdr_data->current_reader = reader;
777 // check for a MCR device and how many slots it has.
778 unsigned char mcrType[1];
779 mcrType[0] = 0;
780 // at least fritzbox7170 needs to issue this twice
781 mcrReadType(reader, &mcrType[0]);
782 mcrType[0] = 0;
783 if(! mcrReadType(reader, &mcrType[0]))
785 if(mcrType[0] == 4 || mcrType[0] == 8)
787 crdr_data->mcr_type = mcrType[0];
788 rdr_log(reader, "SC8in1: MCR%u detected for device %s", crdr_data->mcr_type, reader->device);
790 unsigned char version[1];
791 version[0] = 0;
792 if(! mcrReadVersion(reader, &version[0]))
794 rdr_log(reader, "SC8in1: Version %u for device %s", (unsigned char)version[0], reader->device);
797 unsigned char serial[2];
798 serial[0] = 0;
799 serial[1] = 0;
800 if(! mcrReadSerial(reader, &serial[0]))
802 rdr_log(reader, "SC8in1: Serial %u for device %s", (uint16_t)serial[0], reader->device);
805 //now work-around the problem that timeout of MCR has to be 0 in case of USB
806 unsigned char timeout[2];
807 timeout[0] = 0;
808 timeout[1] = 0;
809 retval = mcrReadTimeout(reader, &timeout[0]);
810 if(retval)
812 rdr_log(reader, "SC8in1: Error reading timeout.");
814 else
816 rdr_log(reader, "SC8in1: Timeout %u for device %s", (uint16_t)timeout[0], reader->device);
818 if((strstr(reader->device, "USB"))
819 && (retval == ERROR || timeout[0] != 0 || timeout[1] != 0)) //assuming we are connected thru USB and timeout is undetected or not zero
821 rdr_log(reader, "SC8in1: Detected Sc8in1 device connected with USB, setting timeout to 0 and writing to EEPROM");
822 timeout[0] = 0;
823 timeout[1] = 0;
824 if(mcrWriteTimeout(reader, timeout))
826 rdr_log(reader, "SC8in1: Error writing timeout.");
830 // Start display thread
831 crdr_data->display_running = 1;
833 start_thread("mcr_update_display", mcr_update_display_thread, (void *)(reader), &crdr_data->display_thread, 0, 1);
837 if(! crdr_data->mcr_type)
839 tcflush(reader->handle, TCIOFLUSH); // a non MCR reader might give longer answer
842 Sc8in1_DebugSignals(reader, reader->slot, "I0");
844 struct s_reader *rdr;
845 LL_ITER itr = ll_iter_create(configured_readers);
846 while((rdr = ll_iter_next(&itr))) //also do this for disabled readers, so we configure the clocks right for all readers
847 if(rdr->crdr_data == crdr_data) //corresponding slot
849 //check slot boundaries
850 int32_t upper_slot = (crdr_data->mcr_type) ? crdr_data->mcr_type : 8; //set upper limit to 8 for non MCR readers
851 if(rdr->slot <= 0 || rdr->slot > upper_slot)
853 rdr_log(reader, "ERROR: device %s has invalid slot number %i", rdr->device, rdr->slot);
854 return ERROR;
857 // set initial current_baudrate which is needed by sc8in1_command
858 rdr->current_baudrate = reader->current_baudrate;
860 if(crdr_data->mcr_type)
862 //set RTS for every slot to 1 to prevent jitter/glitch detection problems
863 Sc8in1_DebugSignals(reader, rdr->slot, "I1");
864 mcrSelectSlot(reader, rdr->slot);
865 Sc8in1_DebugSignals(reader, rdr->slot, "I2");
866 IO_Serial_RTS_Set(reader);
867 Sc8in1_DebugSignals(reader, rdr->slot, "I3");
869 //calculate clock-bits
870 switch(rdr->mhz)
872 case 357:
873 case 358:
874 speed = 0;
875 break;
876 case 368:
877 case 369:
878 speed = 1;
879 break;
880 case 600:
881 speed = 2;
882 break;
883 case 800:
884 speed = 3;
885 break;
886 default:
887 speed = 0;
888 rdr_log(reader, "ERROR: Sc8in1 cannot set clockspeed to %d", rdr->mhz);
889 break;
891 sc8in1_clock |= (speed << ((rdr->slot - 1) * 2));
895 if(crdr_data->mcr_type)
897 sc8in1_clock = ((sc8in1_clock & 0xFF) << 8) | ((sc8in1_clock & 0xFF00) >> 8);
899 //set clockspeeds for all slots
900 unsigned char clockspeed[2];
901 memcpy(&clockspeed, &sc8in1_clock, 2);
902 if(mcrWriteClock(reader, 0, clockspeed))
904 rdr_log(reader, "ERROR: Sc8in1 cannot set clockspeed to %d", (uint16_t)clockspeed[0]);
907 // Clear RTS again
908 itr = ll_iter_create(configured_readers);
909 while((rdr = ll_iter_next(&itr)))
911 if(rdr->crdr_data == crdr_data)
913 Sc8in1_DebugSignals(reader, rdr->slot, "I4");
914 mcrSelectSlot(reader, rdr->slot);
915 Sc8in1_DebugSignals(reader, rdr->slot, "I5");
916 IO_Serial_RTS_Clr(reader);
917 Sc8in1_DebugSignals(reader, rdr->slot, "I6");
918 // Discard ATR
919 unsigned char buff[1];
920 while(! IO_Serial_Read(reader, 0, 500000, 1, &buff[0]))
922 cs_sleepms(1);
924 tcflush(reader->handle, TCIOFLUSH);
928 //DEBUG get clockspeeds
929 if(mcrReadClock(reader, &clockspeed[0]))
931 rdr_log(reader, "ERROR: Sc8in1 cannot read clockspeed");
933 static char *clock_mhz[] = { "3,57", "3,68", "6,00", "8,00" };
934 uint16_t result = clockspeed[0] << 8 | clockspeed[1];
935 for(i = 0; i < 8; i++)
937 rdr_log(reader, "Slot %i is clocked with %s mhz", i + 1, clock_mhz[(result >> (i * 2)) & 0X0003]);
941 Sc8in1_Selectslot(reader, reader->slot);
943 i = -1; //Flag for GetStatus init
944 Sc8in1_GetStatus(reader, &i); //Initialize cardstatus
945 // Gimmick
946 if(crdr_data->mcr_type)
948 mcrHelloOscam(reader);
951 return OK;
954 static int32_t Sc8in1_GetActiveHandle(struct s_reader *reader, uint8_t onlyEnabledReaders)
956 // Returns a handle to the serial port, if it exists in some other
957 // slot of the same physical reader.
958 // Or returns 0 otherwise.
959 struct sc8in1_data *crdr_data = reader->crdr_data;
960 struct s_reader *rdr;
961 LL_ITER itr = ll_iter_create(configured_readers);
962 while((rdr = ll_iter_next(&itr)))
964 if(rdr->typ == R_SC8in1)
966 if((reader != rdr) && (crdr_data == rdr->crdr_data)
967 && rdr->handle != 0 && (onlyEnabledReaders ? rdr->enable != 0 : 1))
969 return rdr->handle;
973 return OK;
976 static int32_t Sc8in1_Close(struct s_reader *reader)
978 // Check if we are the last active slot for the reader,
979 // then close the serial port. Otherwise select next acive slot.
980 struct sc8in1_data *crdr_data = reader->crdr_data;
981 rdr_log_dbg(reader, D_IFD, "Closing SC8in1 device %s", reader->device);
982 bool status = ERROR;
984 if(Sc8in1_GetActiveHandle(reader, 1))
986 rdr_log_dbg(reader, D_IFD, "Just deactivating SC8in1 device %s", reader->device);
987 reader->written = 0;
988 status = OK;
989 // select next active reader slot, so getstatus still works
990 if(crdr_data->current_slot == reader->slot)
992 struct s_reader *rdr;
993 for(rdr = first_active_reader; rdr; rdr = rdr->next)
995 if(rdr->typ == R_SC8in1)
997 if((reader != rdr) && (crdr_data == rdr->crdr_data)
998 && rdr->handle != 0)
1000 status = Sc8in1_Selectslot(rdr, rdr->slot);
1001 break;
1007 else
1009 if(crdr_data->mcr_type)
1011 // disable reader threads
1012 crdr_data->display_running = 0;
1013 SAFE_THREAD_JOIN(crdr_data->display_thread, NULL);
1015 // disable other slots
1016 struct s_reader *rdr;
1017 LL_ITER itr = ll_iter_create(configured_readers);
1018 while((rdr = ll_iter_next(&itr)))
1020 if(rdr->typ == R_SC8in1)
1022 if((reader != rdr) && (crdr_data == rdr->crdr_data))
1024 rdr->handle = 0;
1028 // close serial port
1029 if(reader->handle != 0)
1031 status = IO_Serial_Close(reader);
1032 reader->handle = 0;
1036 return status;
1039 static int32_t Sc8in1_SetSlotForReader(struct s_reader *reader)
1041 // Sets the slot for the reader if it is not set already
1042 int32_t pos = cs_strlen(reader->device) - 2; //this is where : should be located; is also valid length of physical device name
1043 if(reader->device[pos] != 0x3a) //0x3a = ":"
1044 { rdr_log(reader, "ERROR: '%c' detected instead of slot separator `:` at second to last position of device %s", reader->device[pos], reader->device); }
1045 reader->slot = (uint16_t)reader->device[pos + 1] - 0x30;
1046 return OK;
1049 static int32_t Sc8in1_InitLocks(struct s_reader *reader)
1051 // Create SC8in1_Configs and init locks.
1052 // Method is called once for every reader.
1053 // If there is already a Sc8in1 reader configured with the
1054 // same device (means same reader, different slot) then use
1055 // its sc8in1_config, otherwise create a new sc8in1_config and return.
1057 Sc8in1_SetSlotForReader(reader);
1059 // Get device name
1060 int32_t pos = cs_strlen(reader->device) - 2;
1061 if(pos <= 0)
1063 return ERROR;
1065 if(reader->device[pos] != 0x3a) //0x3a = ":"
1066 { rdr_log(reader, "ERROR: Sc8in1_InitLocks: '%c' detected instead of slot separator `:` at second to last position of device %s", reader->device[pos], reader->device); }
1067 unsigned char savePos = reader->device[pos];
1068 reader->device[pos] = 0;
1071 uint8_t reader_config_exists = 0;
1072 struct s_reader *rdr;
1073 LL_ITER itr = ll_iter_create(configured_readers);
1074 while((rdr = ll_iter_next(&itr)))
1076 if(rdr->typ == R_SC8in1 && rdr != reader)
1078 unsigned char save = rdr->device[pos];
1079 rdr->device[pos] = 0; //set to 0 so we can compare device names
1080 if(!strcmp(reader->device, rdr->device)) //we have a match to another slot with same device name
1082 rdr->device[pos] = save; //restore character
1083 Sc8in1_SetSlotForReader(rdr);
1084 if(rdr->crdr_data)
1086 reader->crdr_data = rdr->crdr_data;
1087 reader_config_exists = 1;
1088 rdr_log_dbg(reader, D_DEVICE, "Sc8in1_InitLocks: Found config for %s", reader->device);
1091 else
1093 rdr->device[pos] = save; //restore character
1095 if(reader_config_exists)
1097 break;
1102 if(!reader_config_exists)
1104 rdr_log_dbg(reader, D_DEVICE, "Sc8in1_InitLocks: Creating new config for %s", reader->device);
1105 // Create SC8in1_Config for reader
1106 if(cs_malloc(&reader->crdr_data, sizeof(struct sc8in1_data)))
1108 struct sc8in1_data *crdr_data = reader->crdr_data;
1109 char *buff = NULL, *buff2 = NULL;
1110 if(cs_malloc(&buff, 128))
1111 { snprintf(buff, 128, "sc8in1_lock_%.64s", reader->device); }
1112 if(cs_malloc(&buff2, 128))
1113 { snprintf(buff2, 128, "display_sc8in1_lock_%.64s", reader->device); }
1114 cs_lock_create(__func__, &crdr_data->sc8in1_lock, ESTR(buff), 40000);
1115 cs_lock_create(__func__, &crdr_data->sc8in1_display_lock, ESTR(buff2), 10000);
1117 else
1119 reader->device[pos] = savePos;
1120 rdr_log(reader, "sc8in1: Out of memory.");
1121 return ERROR;
1125 reader->device[pos] = savePos;
1127 return OK;
1130 static void sc8in1_lock(struct s_reader *reader)
1132 struct sc8in1_data *crdr_data = reader->crdr_data;
1133 cs_writelock(__func__, &crdr_data->sc8in1_lock);
1134 rdr_log_dbg(reader, D_ATR, "Locked for access of slot %i", reader->slot);
1135 Sc8in1_Selectslot(reader, reader->slot);
1138 static void sc8in1_unlock(struct s_reader *reader)
1140 struct sc8in1_data *crdr_data = reader->crdr_data;
1141 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1142 rdr_log_dbg(reader, D_ATR, "Unlocked for access of slot %i", reader->slot);
1145 static void sc8in1_display(struct s_reader *reader, char *message)
1147 struct sc8in1_data *crdr_data = reader->crdr_data;
1148 if(!crdr_data->mcr_type)
1149 { return; }
1150 char msg[4] = " ";
1151 if(cs_strlen(message) >= 3)
1153 msg[0] = message[0];
1154 msg[1] = message[1];
1155 msg[2] = message[2];
1157 char text[5] = { 'S', (char)reader->slot + 0x30, msg[0], msg[1], msg[2] };
1158 MCR_DisplayText(reader, text, sizeof(text), 400, 0);
1161 static int32_t sc8in1_init(struct s_reader *reader)
1163 struct sc8in1_data *crdr_data = reader->crdr_data;
1164 cs_writelock(__func__, &crdr_data->sc8in1_lock);
1165 if(reader->handle != 0) //this reader is already initialized
1167 rdr_log_dbg(reader, D_DEVICE, "%s Sc8in1 already open", __func__);
1168 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1169 return OK;
1171 //get physical device name
1172 int32_t pos = cs_strlen(reader->device) - 2; //this is where : should be located; is also valid length of physical device name
1173 if(pos <= 0 || reader->device[pos] != 0x3a) //0x3a = ":"
1174 { rdr_log(reader, "ERROR: '%c' detected instead of slot separator `:` at second to last position of device %s", reader->device[pos], reader->device); }
1175 // Check if serial port is open already
1176 reader->handle = Sc8in1_GetActiveHandle(reader, 0);
1177 if(!reader->handle)
1179 rdr_log_dbg(reader, D_DEVICE, "%s opening SC8in1", __func__);
1180 //open physical device
1181 char deviceName[128];
1182 cs_strncpy(deviceName, reader->device, 128);
1183 deviceName[pos] = 0;
1184 reader->handle = open(deviceName, O_RDWR | O_NOCTTY | O_NONBLOCK);
1185 if(reader->handle < 0)
1187 rdr_log(reader, "ERROR: Opening device %s with real device %s (errno=%d %s)", reader->device, deviceName, errno, strerror(errno));
1188 reader->handle = 0;
1189 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1190 return ERROR;
1193 else
1195 // serial port already initialized
1196 rdr_log_dbg(reader, D_DEVICE, "%s another Sc8in1 already open", __func__);
1197 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1198 return OK;
1200 if(Phoenix_Init(reader))
1202 rdr_log(reader, "ERROR: Phoenix_Init returns error");
1203 Phoenix_Close(reader);
1204 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1205 return ERROR;
1207 int32_t ret = Sc8in1_Init(reader);
1208 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1209 if(ret)
1211 rdr_log(reader, "ERROR: Sc8in1_Init returns error");
1212 return ERROR;
1214 return OK;
1217 static int32_t sc8in1_close(struct s_reader *reader)
1219 struct sc8in1_data *crdr_data = reader->crdr_data;
1220 cs_writelock(__func__, &crdr_data->sc8in1_lock);
1221 int32_t retval = Sc8in1_Close(reader);
1222 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1223 if(retval == ERROR)
1224 { return ERROR; }
1225 return OK;
1228 static int32_t sc8in1_get_status(struct s_reader *reader, int32_t *in)
1230 struct sc8in1_data *crdr_data = reader->crdr_data;
1231 cs_writelock(__func__, &crdr_data->sc8in1_lock);
1232 int32_t ret = Sc8in1_GetStatus(reader, in);
1233 cs_writeunlock(__func__, &crdr_data->sc8in1_lock);
1234 return ret;
1237 static int32_t sc8in1_activate(struct s_reader *reader, struct s_ATR *atr)
1239 const struct s_cardreader *crdr_ops = reader->crdr;
1240 if (!crdr_ops) return ERROR;
1242 crdr_ops->lock(reader);
1243 int32_t retval = Phoenix_Reset(reader, atr);
1244 crdr_ops->unlock(reader);
1245 if(retval == ERROR)
1247 rdr_log_dbg(reader, D_TRACE, "ERROR: Phoenix_Reset returns error");
1248 return ERROR;
1250 return OK;
1253 static int32_t sc8in1_set_baudrate(struct s_reader *reader, uint32_t baudrate)
1255 call(Sc8in1_SetBaudrate(reader, baudrate, NULL, 0));
1256 return OK;
1259 const struct s_cardreader cardreader_sc8in1 =
1261 .desc = "sc8in1",
1262 .typ = R_SC8in1,
1263 .flush = 1,
1264 .read_written = 1,
1265 .need_inverse = 1,
1266 .skip_t1_command_retries = 1,
1267 .lock_init = Sc8in1_InitLocks,
1268 .lock = sc8in1_lock,
1269 .unlock = sc8in1_unlock,
1270 .display_msg = sc8in1_display,
1271 .reader_init = sc8in1_init,
1272 .close = sc8in1_close,
1273 .get_status = sc8in1_get_status,
1274 .activate = sc8in1_activate,
1275 .transmit = IO_Serial_Transmit,
1276 .receive = IO_Serial_Receive,
1277 .set_parity = IO_Serial_SetParity,
1278 .set_baudrate = sc8in1_set_baudrate,
1281 #endif