source: trunk/csctapi/io_serial.c@ 1808

Last change on this file since 1808 was 1808, checked in by merek, 10 years ago

Remove smargopatch as native smartreader mode is now stable

File size: 15.6 KB
Line 
1 /*
2 io_serial.c
3 Serial port input/output functions
4
5 This file is part of the Unix driver for Towitoko smartcard readers
6 Copyright (C) 2000 2001 Carlos Prados <cprados@yahoo.com>
7
8 This version is modified by doz21 to work in a special manner ;)
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <errno.h>
28#ifdef OS_HPUX
29#include <sys/modem.h>
30#endif
31#include <unistd.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#ifdef HAVE_POLL
35#include <sys/poll.h>
36#else
37#include <sys/signal.h>
38#include <sys/types.h>
39#endif
40#include <sys/time.h>
41#include <sys/ioctl.h>
42#include <time.h>
43
44#ifdef OS_LINUX
45#include <linux/serial.h>
46#endif
47
48#include "../globals.h"
49#include "defines.h"
50#include "io_serial.h"
51#include "mc_global.h"
52#include "icc_async.h"
53
54#define IO_SERIAL_FILENAME_LENGTH 32
55
56/*
57 * Internal functions declaration
58 */
59
60static int IO_Serial_Bitrate(int bitrate);
61
62static bool IO_Serial_WaitToRead (unsigned delay_ms, unsigned timeout_ms);
63
64static bool IO_Serial_WaitToWrite (unsigned delay_ms, unsigned timeout_ms);
65
66static int _in_echo_read = 0;
67int io_serial_need_dummy_char = 0;
68
69extern int fdmc;
70
71#if defined(TUXBOX) && defined(PPC)
72void IO_Serial_Ioctl_Lock(int flag)
73{
74 extern int *oscam_sem;
75 if ((reader[ridx].typ != R_DB2COM1) && (reader[ridx].typ != R_DB2COM2)) return;
76 if (!flag)
77 *oscam_sem=0;
78 else while (*oscam_sem!=reader[ridx].typ)
79 {
80 while (*oscam_sem)
81 if (reader[ridx].typ == R_DB2COM1)
82 cs_sleepms(6);
83 else
84 cs_sleepms(8);
85 *oscam_sem=reader[ridx].typ;
86 cs_sleepms(1);
87 }
88}
89
90static bool IO_Serial_DTR_RTS_dbox2(int mcport, int dtr, int set)
91{
92 int rc;
93 unsigned short msr;
94 unsigned int mbit;
95 unsigned short rts_bits[2]={ 0x10, 0x800};
96 unsigned short dtr_bits[2]={0x100, 0};
97
98 cs_debug("IO: multicam.o %s %s\n", dtr ? "dtr" : "rts", set ? "set" : "clear"); fflush(stdout);
99 if ((rc=ioctl(fdmc, GET_PCDAT, &msr))>=0)
100 {
101 if (dtr) // DTR
102 {
103 if (dtr_bits[mcport])
104 {
105 if (set)
106 msr&=(unsigned short)(~dtr_bits[mcport]);
107 else
108 msr|=dtr_bits[mcport];
109 rc=ioctl(fdmc, SET_PCDAT, &msr);
110 }
111 else
112 rc=0; // Dummy, can't handle using multicam.o
113 }
114 else // RTS
115 {
116 if (set)
117 msr&=(unsigned short)(~rts_bits[mcport]);
118 else
119 msr|=rts_bits[mcport];
120 rc=ioctl(fdmc, SET_PCDAT, &msr);
121 }
122 }
123 if (rc<0)
124 return ERROR;
125 return OK;
126}
127#endif
128
129bool IO_Serial_DTR_RTS(int dtr, int set)
130{
131 unsigned int msr;
132 unsigned int mbit;
133
134#if defined(TUXBOX) && defined(PPC)
135 if ((reader[ridx].typ == R_DB2COM1) || (reader[ridx].typ == R_DB2COM2))
136 return(IO_Serial_DTR_RTS_dbox2(reader[ridx].typ == R_DB2COM2, dtr, set));
137#endif
138
139 mbit=(dtr) ? TIOCM_DTR : TIOCM_RTS;
140#if defined(TIOCMBIS) && defined(TIOBMBIC)
141 if (ioctl (reader[ridx].handle, set ? TIOCMBIS : TIOCMBIC, &mbit) < 0)
142 return ERROR;
143#else
144 if (ioctl(reader[ridx].handle, TIOCMGET, &msr) < 0)
145 return ERROR;
146 if (set)
147 msr|=mbit;
148 else
149 msr&=~mbit;
150 if (ioctl(reader[ridx].handle, TIOCMSET, &msr)<0)
151 return ERROR;
152 return OK;
153#endif
154}
155
156/*
157 * Public functions definition
158 */
159
160bool IO_Serial_SetBitrate (unsigned long bitrate, struct termios * tio)
161{
162 /* Set the bitrate */
163#ifdef OS_LINUX
164 //FIXME workaround for Smargo until native mode works
165 if ((reader[ridx].mhz == reader[ridx].cardmhz))
166#endif
167 { //no overcloking
168 cfsetospeed(tio, IO_Serial_Bitrate(bitrate));
169 cfsetispeed(tio, IO_Serial_Bitrate(bitrate));
170 cs_debug("standard baudrate: cardmhz=%d mhz=%d -> effective baudrate %lu", reader[ridx].cardmhz, reader[ridx].mhz, bitrate);
171 }
172#ifdef OS_LINUX
173 else { //over or underclocking
174 /* these structures are only available on linux as fas as we know so limit this code to OS_LINUX */
175 struct serial_struct nuts;
176 ioctl(reader[ridx].handle, TIOCGSERIAL, &nuts);
177 int custom_baud_asked = bitrate * reader[ridx].mhz / reader[ridx].cardmhz;
178 nuts.custom_divisor = (nuts.baud_base + (custom_baud_asked/2))/ custom_baud_asked;
179 int custom_baud_delivered = nuts.baud_base / nuts.custom_divisor;
180 cs_debug("custom baudrate: cardmhz=%d mhz=%d custom_baud=%d baud_base=%d divisor=%d -> effective baudrate %d",
181 reader[ridx].cardmhz, reader[ridx].mhz, custom_baud_asked, nuts.baud_base, nuts.custom_divisor, custom_baud_delivered);
182 int baud_diff = custom_baud_delivered - custom_baud_asked;
183 if (baud_diff < 0)
184 baud_diff = (-baud_diff);
185 if (baud_diff > 0.05 * custom_baud_asked) {
186 cs_log("WARNING: your card is asking for custom_baudrate = %i, but your configuration can only deliver custom_baudrate = %i",custom_baud_asked, custom_baud_delivered);
187 cs_log("You are over- or underclocking, try OSCam when running your reader at normal clockspeed as required by your card, and setting mhz and cardmhz parameters accordingly.");
188 if (nuts.baud_base <= 115200)
189 cs_log("You are probably connecting your reader via a serial port, OSCam has more flexibility switching to custom_baudrates when using an USB->serial converter, preferably based on FTDI chip.");
190 }
191 nuts.flags &= ~ASYNC_SPD_MASK;
192 nuts.flags |= ASYNC_SPD_CUST;
193 ioctl(reader[ridx].handle, TIOCSSERIAL, &nuts);
194 cfsetospeed(tio, IO_Serial_Bitrate(38400));
195 cfsetispeed(tio, IO_Serial_Bitrate(38400));
196 }
197#endif
198 return OK;
199}
200
201bool IO_Serial_SetParams (unsigned long bitrate, unsigned bits, int parity, unsigned stopbits, int dtr, int rts)
202{
203 struct termios newtio;
204
205 if(reader[ridx].typ == R_INTERNAL)
206 return ERROR;
207
208 memset (&newtio, 0, sizeof (newtio));
209
210 if (IO_Serial_SetBitrate (bitrate, & newtio))
211 return ERROR;
212
213 /* Set the character size */
214 switch (bits)
215 {
216 case 5:
217 newtio.c_cflag |= CS5;
218 break;
219
220 case 6:
221 newtio.c_cflag |= CS6;
222 break;
223
224 case 7:
225 newtio.c_cflag |= CS7;
226 break;
227
228 case 8:
229 newtio.c_cflag |= CS8;
230 break;
231 }
232
233 /* Set the parity */
234 switch (parity)
235 {
236 case PARITY_ODD:
237 newtio.c_cflag |= PARENB;
238 newtio.c_cflag |= PARODD;
239 break;
240
241 case PARITY_EVEN:
242 newtio.c_cflag |= PARENB;
243 newtio.c_cflag &= ~PARODD;
244 break;
245
246 case PARITY_NONE:
247 newtio.c_cflag &= ~PARENB;
248 break;
249 }
250
251 /* Set the number of stop bits */
252 switch (stopbits)
253 {
254 case 1:
255 newtio.c_cflag &= (~CSTOPB);
256 break;
257 case 2:
258 newtio.c_cflag |= CSTOPB;
259 break;
260 }
261
262 /* Selects raw (non-canonical) input and output */
263 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
264 newtio.c_oflag &= ~OPOST;
265#if 1
266 newtio.c_iflag |= IGNPAR;
267 /* Ignore parity errors!!! Windows driver does so why shouldn't I? */
268#endif
269 /* Enable receiber, hang on close, ignore control line */
270 newtio.c_cflag |= CREAD | HUPCL | CLOCAL;
271
272 /* Read 1 byte minimun, no timeout specified */
273 newtio.c_cc[VMIN] = 1;
274 newtio.c_cc[VTIME] = 0;
275
276 if (IO_Serial_SetProperties(newtio))
277 return ERROR;
278
279 current_baudrate = bitrate;
280
281 IO_Serial_Ioctl_Lock(1);
282 IO_Serial_DTR_RTS(0, rts == IO_SERIAL_HIGH);
283 IO_Serial_DTR_RTS(1, dtr == IO_SERIAL_HIGH);
284 IO_Serial_Ioctl_Lock(0);
285
286 return OK;
287}
288
289bool IO_Serial_SetProperties (struct termios newtio)
290{
291 if(reader[ridx].typ == R_INTERNAL)
292 return ERROR;
293
294 if (tcsetattr (reader[ridx].handle, TCSANOW, &newtio) < 0)
295 return ERROR;
296// tcflush(reader[ridx].handle, TCIOFLUSH);
297// if (tcsetattr (reader[ridx].handle, TCSAFLUSH, &newtio) < 0)
298// return ERROR;
299
300 int mctl;
301 if (ioctl (reader->handle, TIOCMGET, &mctl) >= 0) {
302 mctl &= ~TIOCM_RTS; //should be mctl |= TIOCM_RTS; for readers with reversed polarity reset
303 ioctl (reader->handle, TIOCMSET, &mctl);
304 }
305 else
306 cs_log("WARNING: Failed to reset reader %s", reader[ridx].label);
307
308 cs_debug("IO: Setting properties\n");
309 return OK;
310}
311
312int IO_Serial_SetParity (BYTE parity)
313{
314 if(reader[ridx].typ == R_INTERNAL)
315 return OK;
316
317 if ((parity != PARITY_EVEN) && (parity != PARITY_ODD) && (parity != PARITY_NONE))
318 return ERROR;
319
320 struct termios tio;
321 int current_parity;
322 // Get current parity
323 if (tcgetattr (reader[ridx].handle, &tio) != 0)
324 return ERROR;
325
326 if (((tio.c_cflag) & PARENB) == PARENB)
327 {
328 if (((tio.c_cflag) & PARODD) == PARODD)
329 current_parity = PARITY_ODD;
330 else
331 current_parity = PARITY_EVEN;
332 }
333 else
334 {
335 current_parity = PARITY_NONE;
336 }
337
338 cs_debug ("IFD: Setting parity from %s to %s\n",
339 current_parity == PARITY_ODD ? "Odd" :
340 current_parity == PARITY_NONE ? "None" :
341 current_parity == PARITY_EVEN ? "Even" : "Invalid",
342 parity == PARITY_ODD ? "Odd" :
343 parity == PARITY_NONE ? "None" :
344 parity == PARITY_EVEN ? "Even" : "Invalid");
345
346 if (current_parity != parity)
347 {
348
349 // Set the parity
350 switch (parity)
351 {
352 case PARITY_ODD:
353 tio.c_cflag |= PARENB;
354 tio.c_cflag |= PARODD;
355 break;
356
357 case PARITY_EVEN:
358 tio.c_cflag |= PARENB;
359 tio.c_cflag &= ~PARODD;
360 break;
361
362 case PARITY_NONE:
363 tio.c_cflag &= ~PARENB;
364 break;
365 }
366 if (IO_Serial_SetProperties (tio))
367 return ERROR;
368 }
369
370 return OK;
371}
372
373void IO_Serial_Flush ()
374{
375 BYTE b;
376 while(!IO_Serial_Read(1000, 1, &b));
377}
378
379
380bool IO_Serial_Read (unsigned timeout, unsigned size, BYTE * data)
381{
382 BYTE c;
383 uint count = 0;
384#ifdef SH4
385 bool readed;
386 struct timeval tv, tv_spent;
387#endif
388
389 if((reader[ridx].typ != R_INTERNAL) && (wr>0))
390 {
391 BYTE buf[256];
392 int n = wr;
393 wr = 0;
394
395 if(IO_Serial_Read (timeout, n, buf))
396 return ERROR;
397 }
398
399 cs_debug ("IO: Receiving: ");
400 for (count = 0; count < size * (_in_echo_read ? (1+io_serial_need_dummy_char) : 1); count++)
401 {
402#ifdef SH4
403 gettimeofday(&tv,0);
404 memcpy(&tv_spent,&tv,sizeof(struct timeval));
405 readed=FALSE;
406 while( (((tv_spent.tv_sec-tv.tv_sec)*1000) + ((tv_spent.tv_usec-tv.tv_usec)/1000L))<timeout )
407 {
408 if (read (reader[ridx].handle, &c, 1) == 1)
409 {
410 readed=TRUE;
411 break;
412 }
413 gettimeofday(&tv_spent,0);
414 }
415 if(!readed) return ERROR;
416
417 data[_in_echo_read ? count/(1+io_serial_need_dummy_char) : count] = c;
418 cs_debug_nolf ("%02X ", c);
419#else
420 if (!IO_Serial_WaitToRead (0, timeout))
421 {
422 if (read (reader[ridx].handle, &c, 1) != 1)
423 {
424 cs_debug_nolf ("ERROR\n");
425 return ERROR;
426 }
427 data[_in_echo_read ? count/(1+io_serial_need_dummy_char) : count] = c;
428 cs_debug_nolf ("%02X ", c);
429 }
430 else
431 {
432 cs_debug_nolf ("TIMEOUT\n");
433 tcflush (reader[ridx].handle, TCIFLUSH);
434 return ERROR;
435 }
436#endif
437 }
438 cs_debug_nolf("\n"); //UGLY this is essential, resets global var, do not delete
439 _in_echo_read = 0;
440 return OK;
441}
442
443bool IO_Serial_Write (unsigned delay, unsigned size, BYTE * data)
444{
445 unsigned count, to_send, i_w;
446 BYTE data_w[512];
447
448 /* Discard input data from previous commands */
449// tcflush (reader[ridx].handle, TCIFLUSH);
450
451 for (count = 0; count < size; count += to_send)
452 {
453// if(reader[ridx].typ == R_INTERNAL)
454// to_send = 1;
455// else
456 to_send = (delay? 1: size);
457
458 if (!IO_Serial_WaitToWrite (delay, 1000))
459 {
460 for (i_w=0; i_w < to_send; i_w++) {
461 data_w [(1+io_serial_need_dummy_char)*i_w] = data [count + i_w];
462 if (io_serial_need_dummy_char) {
463 data_w [2*i_w+1] = 0x00;
464 }
465 }
466 unsigned int u = write (reader[ridx].handle, data_w, (1+io_serial_need_dummy_char)*to_send);
467 _in_echo_read = 1;
468 if (u != (1+io_serial_need_dummy_char)*to_send)
469 {
470 cs_debug ("ERROR\n");
471 if(reader[ridx].typ != R_INTERNAL)
472 wr += u;
473 return ERROR;
474 }
475
476 if(reader[ridx].typ != R_INTERNAL)
477 wr += to_send;
478
479 cs_ddump (data_w+count, (1+io_serial_need_dummy_char)*to_send, "IO: Sending: ");
480 }
481 else
482 {
483 cs_debug ("TIMEOUT\n");
484// tcflush (reader[ridx].handle, TCIFLUSH);
485 return ERROR;
486 }
487 }
488 return OK;
489}
490
491bool IO_Serial_Close ()
492{
493
494 cs_debug ("IO: Clossing serial port %s\n", reader[ridx].device);
495
496#if defined(TUXBOX) && defined(PPC)
497 close(fdmc);
498#endif
499 if (close (reader[ridx].handle) != 0)
500 return ERROR;
501
502 wr = 0;
503
504 return OK;
505}
506
507/*
508 * Internal functions definition
509 */
510
511static int IO_Serial_Bitrate(int bitrate)
512{
513#ifdef B230400
514 if ((bitrate)>=230400) return B230400;
515#endif
516#ifdef B115200
517 if ((bitrate)>=115200) return B115200;
518#endif
519#ifdef B57600
520 if ((bitrate)>=57600) return B57600;
521#endif
522#ifdef B38400
523 if ((bitrate)>=38400) return B38400;
524#endif
525#ifdef B19200
526 if ((bitrate)>=19200) return B19200;
527#endif
528#ifdef B9600
529 if ((bitrate)>=9600) return B9600;
530#endif
531#ifdef B4800
532 if ((bitrate)>=4800) return B4800;
533#endif
534#ifdef B2400
535 if ((bitrate)>=2400) return B2400;
536#endif
537#ifdef B1800
538 if ((bitrate)>=1800) return B1800;
539#endif
540#ifdef B1200
541 if ((bitrate)>=1200) return B1200;
542#endif
543#ifdef B600
544 if ((bitrate)>=600) return B600;
545#endif
546#ifdef B300
547 if ((bitrate)>=300) return B300;
548#endif
549#ifdef B200
550 if ((bitrate)>=200) return B200;
551#endif
552#ifdef B150
553 if ((bitrate)>=150) return B150;
554#endif
555#ifdef B134
556 if ((bitrate)>=134) return B134;
557#endif
558#ifdef B110
559 if ((bitrate)>=110) return B110;
560#endif
561#ifdef B75
562 if ((bitrate)>=75) return B75;
563#endif
564#ifdef B50
565 if ((bitrate)>=50) return B50;
566#endif
567#ifdef B0
568 if ((bitrate)>=0) return B0;
569#endif
570 return 0; /* Should never get here */
571}
572
573static bool IO_Serial_WaitToRead (unsigned delay_ms, unsigned timeout_ms)
574{
575 fd_set rfds;
576 fd_set erfds;
577 struct timeval tv;
578 int select_ret;
579 int in_fd;
580
581 if (delay_ms > 0)
582 cs_sleepms (delay_ms);
583
584 in_fd=reader[ridx].handle;
585
586 FD_ZERO(&rfds);
587 FD_SET(in_fd, &rfds);
588
589 FD_ZERO(&erfds);
590 FD_SET(in_fd, &erfds);
591
592 tv.tv_sec = timeout_ms/1000;
593 tv.tv_usec = (timeout_ms % 1000) * 1000L;
594 select_ret = select(in_fd+1, &rfds, NULL, &erfds, &tv);
595 if(select_ret==-1)
596 {
597 printf("select_ret=%i\n" , select_ret);
598 printf("errno =%d\n", errno);
599 fflush(stdout);
600 return ERROR;
601 }
602
603 if (FD_ISSET(in_fd, &erfds))
604 {
605 printf("fd is in error fds\n");
606 printf("errno =%d\n", errno);
607 fflush(stdout);
608 return ERROR;
609 }
610 if (FD_ISSET(in_fd,&rfds))
611 return OK;
612 else
613 return ERROR;
614}
615
616static bool IO_Serial_WaitToWrite (unsigned delay_ms, unsigned timeout_ms)
617{
618 fd_set wfds;
619 fd_set ewfds;
620 struct timeval tv;
621 int select_ret;
622 int out_fd;
623
624#ifdef SCI_DEV
625 if(reader[ridx].typ == R_INTERNAL)
626 return OK;
627#endif
628
629 if (delay_ms > 0)
630 cs_sleepms(delay_ms);
631
632 out_fd=reader[ridx].handle;
633
634 FD_ZERO(&wfds);
635 FD_SET(out_fd, &wfds);
636
637 FD_ZERO(&ewfds);
638 FD_SET(out_fd, &ewfds);
639
640 tv.tv_sec = timeout_ms/1000L;
641 tv.tv_usec = (timeout_ms % 1000) * 1000L;
642
643 select_ret = select(out_fd+1, NULL, &wfds, &ewfds, &tv);
644
645 if(select_ret==-1)
646 {
647 printf("select_ret=%d\n" , select_ret);
648 printf("errno =%d\n", errno);
649 fflush(stdout);
650 return ERROR;
651 }
652
653 if (FD_ISSET(out_fd, &ewfds))
654 {
655 printf("fd is in ewfds\n");
656 printf("errno =%d\n", errno);
657 fflush(stdout);
658 return ERROR;
659 }
660
661 if (FD_ISSET(out_fd,&wfds))
662 return OK;
663 else
664 return ERROR;
665}
666
667bool IO_Serial_InitPnP ()
668{
669 unsigned int PnP_id_size = 0;
670 BYTE PnP_id[IO_SERIAL_PNPID_SIZE]; /* PnP Id of the serial device */
671
672 if (IO_Serial_SetParams (1200, 7, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_LOW))
673 return ERROR;
674
675 while ((PnP_id_size < IO_SERIAL_PNPID_SIZE) && !IO_Serial_Read (200, 1, &(PnP_id[PnP_id_size])))
676 PnP_id_size++;
677
678 return OK;
679}
680
Note: See TracBrowser for help on using the repository browser.