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"
26 #include "ifd_phoenix.h"
27 #include "io_serial.h"
32 struct s_sc8in1_display
36 uint16_t char_change_time
;
39 struct s_sc8in1_display
*next
;
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
;
58 static int32_t Sc8in1_DebugSignals(struct s_reader
*reader
, uint16_t slot
, const char *extra
)
61 if(ioctl(reader
->handle
, TIOCMGET
, &msr
) < 0)
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);
68 #define Sc8in1_DebugSignals(a, b, c) {}
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");
82 rdr_log_dbg(reader
, D_TRACE
, "Sc8in1_NeedBaudrateChange 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 */
93 call(tcgetattr(reader
->handle
, &tio
) != 0);
100 baudrate
= reader
->current_baudrate
;
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
));
115 reader
->current_baudrate
= baudrate
;
120 static int32_t sc8in1_tcdrain(struct s_reader
*reader
)
124 int32_t tcdrain_ret
= tcdrain(reader
->handle
);
125 if(tcdrain_ret
== -1)
129 //try again in case of Interrupted system call
133 { rdr_log(reader
, "ERROR: %s: (errno=%d %s)", __func__
, errno
, strerror(errno
)); }
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;
151 rdr_log(reader
, "ERROR: SC8in1 Command no valid handle");
155 Sc8in1_DebugSignals(reader
, reader
->slot
, "CMD10");
157 // switch SC8in1 to command mode
158 IO_Serial_DTR_Set(reader
);
159 tcflush(reader
->handle
, TCIOFLUSH
);
162 tcgetattr(reader
->handle
, &termio
);
163 memcpy(&termiobackup
, &termio
, sizeof(termio
));
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
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");
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");
215 tcflush(reader
->handle
, TCIOFLUSH
);
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
);
225 rdr_log(reader
, "SC8in1 Command write error");
228 if(written
== lenwrite
)
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");
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");
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");
263 if(buff_echo_hack
[0] != 'A')
265 rdr_log(reader
, "SC8in1 Echo command read wrong character");
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");
284 if(tcsetattr(reader
->handle
, TCSANOW
, &termiobackup
) < 0)
286 rdr_log(reader
, "ERROR: SC8in1 Command error in set RS232 attributes");
293 // restore baudrate only if changed
296 if(Sc8in1_SetBaudrate(reader
, currentBaudrate
, &termiobackup
, 1))
298 rdr_log(reader
, "ERROR: SC8in1 selectslot restore Bitrate attributes");
305 if(tcsetattr(reader
->handle
, TCSANOW
, &termiobackup
) < 0)
307 rdr_log(reader
, "ERROR: SC8in1 Command error in restore RS232 attributes");
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");
329 static int32_t mcrReadStatus(struct s_reader
*reader
, unsigned char *status
)
331 unsigned char buff
[2] = "";
333 if(sc8in1_command(reader
, buff
, 1, 2, 0, 1, 0) < 0)
340 static int32_t sc8in1ReadStatus(struct s_reader
*reader
, unsigned char *status
)
342 unsigned char buff
[9]; // read 1 echo byte + 8 status bytes
344 if(sc8in1_command(reader
, buff
, 1, 9, 0, 1, 0) < 0)
346 memcpy(&status
[0], &buff
[1], 8);
351 static int32_t mcrReadType(struct s_reader
*reader
, unsigned char *type
)
353 unsigned char buff
[1];
355 if(sc8in1_command(reader
, buff
, 1, 1, 0, 0, 0) < 0)
361 static int32_t mcrReadVersion(struct s_reader
*reader
, unsigned char *version
)
363 unsigned char buff
[1];
365 if(sc8in1_command(reader
, buff
, 1, 1, 0, 0, 0) < 0)
367 version
[0] = buff
[0];
371 static int32_t mcrReadSerial(struct s_reader
*reader
, unsigned char *serial
)
373 unsigned char buff
[2];
375 if(sc8in1_command(reader
, buff
, 1, 2, 0, 0, 0) < 0)
382 /*static int32_t mcrWriteDisplayRaw(struct s_reader *reader, unsigned char data[7]) {
383 unsigned char buff[8];
385 memcpy(&buff[1], &data[0], 7);
386 if (sc8in1_command(reader, buff, 8, 0, 0, 0, 0) < 0)
391 static int32_t mcrWriteDisplayAscii(struct s_reader
*reader
, unsigned char data
, unsigned char timeout
)
393 unsigned char buff
[3];
397 if(sc8in1_command(reader
, buff
, 3, 0, 0, 0, 0) < 0)
402 static int32_t mcrWriteClock(struct s_reader
*reader
, unsigned char saveClock
, unsigned char clock_val
[2])
404 unsigned char buff
[3];
406 buff
[1] = clock_val
[0];
407 buff
[2] = clock_val
[1];
408 if(sc8in1_command(reader
, buff
, 3, 0, 0, 0, 0) < 0)
413 if(sc8in1_command(reader
, buff
, 1, 0, 1, 0, 0) < 0)
419 static int32_t mcrReadClock(struct s_reader
*reader
, unsigned char *clock_val
)
421 unsigned char buff
[2];
423 if(sc8in1_command(reader
, buff
, 1, 2, 0, 0, 0) < 0)
425 clock_val
[0] = buff
[0];
426 clock_val
[1] = buff
[1];
430 static int32_t mcrWriteTimeout(struct s_reader
*reader
, unsigned char timeout
[2])
432 unsigned char buff
[3];
434 buff
[1] = timeout
[0];
435 buff
[2] = timeout
[1];
436 if(sc8in1_command(reader
, buff
, 3, 0, 1, 0, 0) < 0)
441 static int32_t mcrReadTimeout(struct s_reader
*reader
, unsigned char *timeout
)
443 unsigned char buff
[2];
445 if(sc8in1_command(reader
, buff
, 1, 2, 0, 0, 0) < 0)
447 timeout
[0] = buff
[1];
448 timeout
[1] = buff
[0];
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];
459 if(sc8in1_command(reader
, buff
, 2, 0, 0, 0, slot
) < 0)
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];
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)
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.");
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
;
504 struct s_sc8in1_display
*d
= crdr_data
->display
;
518 cs_writeunlock(__func__
, &crdr_data
->sc8in1_display_lock
);
522 rdr_log(reader
, "MCR_DisplayText: Out of memory.");
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
539 uint16_t numClients
= 0;
540 for(cl
= first_client
; cl
; cl
= cl
->next
)
548 int msgLen
= snprintf(&msg
[0], 8, "CN%i", numClients
);
549 if(msgLen
> 0 && MCR_DisplayText(reader
, msg
, msgLen
, 300, 0))
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");
570 set_thread_name(__func__
);
572 while(crdr_data
->display_running
)
574 uint16_t display_sleep
= DEFAULT_SLEEP_TIME
;
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
)
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
);
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
);
632 cs_writeunlock(__func__
, &crdr_data
->sc8in1_display_lock
);
634 cs_sleepms(display_sleep
);
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]))
663 tcflush(reader
->handle
, TCIOFLUSH
);
668 unsigned char buff
[8];
669 if(sc8in1ReadStatus(reader
, &buff
[0]))
677 tcflush(reader
->handle
, TCIOFLUSH
);
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
)
689 rdr_log_dbg(reader
, D_TRACE
, "SC8in1: select slot %i", slot
);
692 struct timeb tv_start
, tv_end
;
696 int32_t status
= ERROR
;
697 if(crdr_data
->mcr_type
)
699 status
= mcrSelectSlot(reader
, slot
);
703 status
= sc8in1SelectSlot(reader
, slot
);
708 crdr_data
->current_reader
= reader
;
709 crdr_data
->current_slot
= slot
;
713 rdr_log_dbg(reader
, D_DEVICE
, "SC8in1 Selectslot in %"PRId64
" ms", comp_timeb(&tv_end
, &tv_start
));
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)
725 if(reader
->handle
== 0)
727 ioctl(reader
->handle
, TIOCMGET
, &lineData
);
728 result
= (lineData
& TIOCM_CTS
) / TIOCM_CTS
;
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
741 rdr_log(reader
, "Sc8in1_GetStatus 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));
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
,
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];
780 // at least fritzbox7170 needs to issue this twice
781 mcrReadType(reader
, &mcrType
[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];
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];
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];
809 retval
= mcrReadTimeout(reader
, &timeout
[0]);
812 rdr_log(reader
, "SC8in1: Error reading timeout.");
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");
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
);
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
888 rdr_log(reader
, "ERROR: Sc8in1 cannot set clockspeed to %d", rdr
->mhz
);
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]);
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");
919 unsigned char buff
[1];
920 while(! IO_Serial_Read(reader
, 0, 500000, 1, &buff
[0]))
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
946 if(crdr_data
->mcr_type
)
948 mcrHelloOscam(reader
);
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))
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
);
984 if(Sc8in1_GetActiveHandle(reader
, 1))
986 rdr_log_dbg(reader
, D_IFD
, "Just deactivating SC8in1 device %s", reader
->device
);
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
)
1000 status
= Sc8in1_Selectslot(rdr
, rdr
->slot
);
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
))
1028 // close serial port
1029 if(reader
->handle
!= 0)
1031 status
= IO_Serial_Close(reader
);
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;
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
);
1060 int32_t pos
= cs_strlen(reader
->device
) - 2;
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
);
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
);
1093 rdr
->device
[pos
] = save
; //restore character
1095 if(reader_config_exists
)
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);
1119 reader
->device
[pos
] = savePos
;
1120 rdr_log(reader
, "sc8in1: Out of memory.");
1125 reader
->device
[pos
] = savePos
;
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
)
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
);
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);
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
));
1189 cs_writeunlock(__func__
, &crdr_data
->sc8in1_lock
);
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
);
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
);
1207 int32_t ret
= Sc8in1_Init(reader
);
1208 cs_writeunlock(__func__
, &crdr_data
->sc8in1_lock
);
1211 rdr_log(reader
, "ERROR: Sc8in1_Init returns error");
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
);
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
);
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
);
1247 rdr_log_dbg(reader
, D_TRACE
, "ERROR: Phoenix_Reset returns error");
1253 static int32_t sc8in1_set_baudrate(struct s_reader
*reader
, uint32_t baudrate
)
1255 call(Sc8in1_SetBaudrate(reader
, baudrate
, NULL
, 0));
1259 const struct s_cardreader cardreader_sc8in1
=
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
,