source: trunk/csctapi/io_serial.c@ 1253

Last change on this file since 1253 was 1253, checked in by dingo35, 11 years ago

Move Reset to ifd_phoenix.c and cleanup lot of overhead

File size: 15.5 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
25#include "defines.h"
26#include "../globals.h"
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <errno.h>
31#ifdef OS_HPUX
32#include <sys/modem.h>
33#endif
34#include <termios.h>
35#include <unistd.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#ifdef HAVE_POLL
39#include <sys/poll.h>
40#else
41#include <sys/signal.h>
42#include <sys/types.h>
43#endif
44#include <sys/time.h>
45#include <sys/ioctl.h>
46#include <time.h>
47#include "io_serial.h"
48#include "mc_global.h"
49
50#ifdef OS_LINUX
51#include <linux/serial.h>
52#endif
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 usleep((reader[ridx].typ)*2000); //FIXME is this right ?!?!
82 *oscam_sem=reader[ridx].typ;
83 usleep(1000);
84 }
85}
86
87static bool IO_Serial_DTR_RTS_dbox2(int mcport, int dtr, int set)
88{
89 int rc;
90 unsigned short msr;
91 unsigned int mbit;
92 unsigned short rts_bits[2]={ 0x10, 0x800};
93 unsigned short dtr_bits[2]={0x100, 0};
94
95#ifdef DEBUG_IO
96printf("IO: multicam.o %s %s\n", dtr ? "dtr" : "rts", set ? "set" : "clear"); fflush(stdout);
97#endif
98 if ((rc=ioctl(fdmc, GET_PCDAT, &msr))>=0)
99 {
100 if (dtr) // DTR
101 {
102 if (dtr_bits[mcport])
103 {
104 if (set)
105 msr&=(unsigned short)(~dtr_bits[mcport]);
106 else
107 msr|=dtr_bits[mcport];
108 rc=ioctl(fdmc, SET_PCDAT, &msr);
109 }
110 else
111 rc=0; // Dummy, can't handle using multicam.o
112 }
113 else // RTS
114 {
115 if (set)
116 msr&=(unsigned short)(~rts_bits[mcport]);
117 else
118 msr|=rts_bits[mcport];
119 rc=ioctl(fdmc, SET_PCDAT, &msr);
120 }
121 }
122 return((rc<0) ? FALSE : TRUE);
123}
124#endif
125
126bool IO_Serial_DTR_RTS(int dtr, int set)
127{
128 unsigned int msr;
129 unsigned int mbit;
130
131#if defined(TUXBOX) && defined(PPC)
132 if ((reader[ridx].typ == R_DB2COM1) || (reader[ridx].typ == R_DB2COM2))
133 return(IO_Serial_DTR_RTS_dbox2(reader[ridx].typ == R_DB2COM2, dtr, set));
134#endif
135
136 mbit=(dtr) ? TIOCM_DTR : TIOCM_RTS;
137#if defined(TIOCMBIS) && defined(TIOBMBIC)
138 if (ioctl (reader[ridx].handle, set ? TIOCMBIS : TIOCMBIC, &mbit) < 0)
139 return FALSE;
140#else
141 if (ioctl(reader[ridx].handle, TIOCMGET, &msr) < 0)
142 return FALSE;
143 if (set)
144 msr|=mbit;
145 else
146 msr&=~mbit;
147 return((ioctl(reader[ridx].handle, TIOCMSET, &msr)<0) ? FALSE : TRUE);
148#endif
149}
150
151/*
152 * Public functions definition
153 */
154
155bool IO_Serial_SetBitrate (unsigned long bitrate, struct termios * tio)
156{
157 /* Set the bitrate */
158#ifdef OS_LINUX
159 if (reader[ridx].mhz == reader[ridx].cardmhz)
160#endif
161 { //no overcloking
162 cfsetospeed(tio, IO_Serial_Bitrate(bitrate));
163 cfsetispeed(tio, IO_Serial_Bitrate(bitrate));
164 cs_debug("standard baudrate: cardmhz=%d mhz=%d -> effective baudrate %lu", reader[ridx].cardmhz, reader[ridx].mhz, bitrate);
165 }
166#ifdef OS_LINUX
167 else { //over or underclocking
168 /* these structures are only available on linux as fas as we know so limit this code to OS_LINUX */
169 struct serial_struct nuts;
170 ioctl(reader[ridx].handle, TIOCGSERIAL, &nuts);
171 int custom_baud = bitrate * reader[ridx].mhz / reader[ridx].cardmhz;
172 nuts.custom_divisor = (nuts.baud_base + (custom_baud/2))/ custom_baud;
173 cs_debug("custom baudrate: cardmhz=%d mhz=%d custom_baud=%d baud_base=%d divisor=%d -> effective baudrate %d",
174 reader[ridx].cardmhz, reader[ridx].mhz, custom_baud, nuts.baud_base, nuts.custom_divisor, nuts.baud_base/nuts.custom_divisor);
175 nuts.flags &= ~ASYNC_SPD_MASK;
176 nuts.flags |= ASYNC_SPD_CUST;
177 ioctl(reader[ridx].handle, TIOCSSERIAL, &nuts);
178 cfsetospeed(tio, IO_Serial_Bitrate(38400));
179 cfsetispeed(tio, IO_Serial_Bitrate(38400));
180 }
181#endif
182 return TRUE;
183}
184
185bool IO_Serial_SetParams (unsigned long bitrate, unsigned bits, int parity, unsigned stopbits, int dtr, int rts)
186{
187 struct termios newtio;
188
189 if(reader[ridx].typ == R_INTERNAL)
190 return FALSE;
191
192 memset (&newtio, 0, sizeof (newtio));
193
194 if (!IO_Serial_SetBitrate (bitrate, & newtio))
195 return FALSE;
196
197 /* Set the character size */
198 switch (bits)
199 {
200 case 5:
201 newtio.c_cflag |= CS5;
202 break;
203
204 case 6:
205 newtio.c_cflag |= CS6;
206 break;
207
208 case 7:
209 newtio.c_cflag |= CS7;
210 break;
211
212 case 8:
213 newtio.c_cflag |= CS8;
214 break;
215 }
216
217 /* Set the parity */
218 switch (parity)
219 {
220 case PARITY_ODD:
221 newtio.c_cflag |= PARENB;
222 newtio.c_cflag |= PARODD;
223 break;
224
225 case PARITY_EVEN:
226 newtio.c_cflag |= PARENB;
227 newtio.c_cflag &= ~PARODD;
228 break;
229
230 case PARITY_NONE:
231 newtio.c_cflag &= ~PARENB;
232 break;
233 }
234
235 /* Set the number of stop bits */
236 switch (stopbits)
237 {
238 case 1:
239 newtio.c_cflag &= (~CSTOPB);
240 break;
241 case 2:
242 newtio.c_cflag |= CSTOPB;
243 break;
244 }
245
246 /* Selects raw (non-canonical) input and output */
247 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
248 newtio.c_oflag &= ~OPOST;
249#if 1
250 newtio.c_iflag |= IGNPAR;
251 /* Ignore parity errors!!! Windows driver does so why shouldn't I? */
252#endif
253 /* Enable receiber, hang on close, ignore control line */
254 newtio.c_cflag |= CREAD | HUPCL | CLOCAL;
255
256 /* Read 1 byte minimun, no timeout specified */
257 newtio.c_cc[VMIN] = 1;
258 newtio.c_cc[VTIME] = 0;
259
260 if (!IO_Serial_SetProperties(newtio))
261 return FALSE;
262
263 reader[ridx].baudrate = bitrate;
264
265 IO_Serial_Ioctl_Lock(1);
266 IO_Serial_DTR_RTS(0, rts == IO_SERIAL_HIGH);
267 IO_Serial_DTR_RTS(1, dtr == IO_SERIAL_HIGH);
268 IO_Serial_Ioctl_Lock(0);
269
270 return TRUE;
271}
272
273bool IO_Serial_SetProperties (struct termios newtio)
274{
275 if(reader[ridx].typ == R_INTERNAL)
276 return FALSE;
277
278 if (tcsetattr (reader[ridx].handle, TCSANOW, &newtio) < 0)
279 return FALSE;
280// tcflush(reader[ridx].handle, TCIOFLUSH);
281// if (tcsetattr (reader[ridx].handle, TCSAFLUSH, &newtio) < 0)
282// return FALSE;
283
284 unsigned int mctl;
285 if (ioctl (reader[ridx].handle, TIOCMGET, &mctl) < 0)
286 return FALSE;
287
288#ifdef DEBUG_IO
289 printf("IO: Setting properties\n");
290#endif
291
292 return TRUE;
293}
294
295int IO_Serial_SetParity (BYTE parity)
296{
297 if(reader[ridx].typ == R_INTERNAL)
298 return TRUE;
299
300 if ((parity != PARITY_EVEN) && (parity != PARITY_ODD) && (parity != PARITY_NONE))
301 return FALSE;
302
303 struct termios tio;
304 int current_parity;
305 // Get current parity
306 if (tcgetattr (reader[ridx].handle, &tio) != 0)
307 return FALSE;
308
309 if (((tio.c_cflag) & PARENB) == PARENB)
310 {
311 if (((tio.c_cflag) & PARODD) == PARODD)
312 current_parity = PARITY_ODD;
313 else
314 current_parity = PARITY_EVEN;
315 }
316 else
317 {
318 current_parity = PARITY_NONE;
319 }
320
321#ifdef DEBUG_IFD
322 printf ("IFD: Setting parity from %s to %s\n",
323 current_parity == PARITY_ODD ? "Odd" :
324 current_parity == PARITY_NONE ? "None" :
325 current_parity == PARITY_EVEN ? "Even" : "Invalid",
326 parity == PARITY_ODD ? "Odd" :
327 parity == PARITY_NONE ? "None" :
328 parity == PARITY_EVEN ? "Even" : "Invalid");
329#endif
330
331 if (current_parity != parity)
332 {
333
334 // Set the parity
335 switch (parity)
336 {
337 case PARITY_ODD:
338 tio.c_cflag |= PARENB;
339 tio.c_cflag |= PARODD;
340 break;
341
342 case PARITY_EVEN:
343 tio.c_cflag |= PARENB;
344 tio.c_cflag &= ~PARODD;
345 break;
346
347 case PARITY_NONE:
348 tio.c_cflag &= ~PARENB;
349 break;
350 }
351 if (!IO_Serial_SetProperties (tio))
352 return FALSE;
353 }
354
355 return TRUE;
356}
357
358void IO_Serial_Flush ()
359{
360 BYTE b;
361 while(IO_Serial_Read(1000, 1, &b));
362}
363
364
365bool IO_Serial_Read (unsigned timeout, unsigned size, BYTE * data)
366{
367 BYTE c;
368 uint count = 0;
369#ifdef SH4
370 bool readed;
371 struct timeval tv, tv_spent;
372#endif
373
374 if((reader[ridx].typ != R_INTERNAL) && (wr>0))
375 {
376 BYTE buf[256];
377 int n = wr;
378 wr = 0;
379
380 if(!IO_Serial_Read (timeout, n, buf))
381 {
382 return FALSE;
383 }
384 }
385
386#ifdef DEBUG_IO
387 printf ("IO: Receiving: ");
388 fflush (stdout);
389#endif
390 for (count = 0; count < size * (_in_echo_read ? (1+io_serial_need_dummy_char) : 1); count++)
391 {
392#ifdef SH4
393 gettimeofday(&tv,0);
394 memcpy(&tv_spent,&tv,sizeof(struct timeval));
395 readed=FALSE;
396 while( (((tv_spent.tv_sec-tv.tv_sec)*1000) + ((tv_spent.tv_usec-tv.tv_usec)/1000L))<timeout )
397 {
398 if (read (reader[ridx].handle, &c, 1) == 1)
399 {
400 readed=TRUE;
401 break;
402 }
403 gettimeofday(&tv_spent,0);
404 }
405 if(!readed) return FALSE;
406
407 data[_in_echo_read ? count/(1+io_serial_need_dummy_char) : count] = c;
408#ifdef DEBUG_IO
409 printf ("%X ", c);
410 fflush (stdout);
411#endif
412#else
413 if (IO_Serial_WaitToRead (0, timeout))
414 {
415 if (read (reader[ridx].handle, &c, 1) != 1)
416 {
417#ifdef DEBUG_IO
418 printf ("ERROR\n");
419 fflush (stdout);
420#endif
421 return FALSE;
422 }
423 data[_in_echo_read ? count/(1+io_serial_need_dummy_char) : count] = c;
424
425#ifdef DEBUG_IO
426 printf ("%X ", c);
427 fflush (stdout);
428#endif
429 }
430 else
431 {
432#ifdef DEBUG_IO
433 printf ("TIMEOUT\n");
434 fflush (stdout);
435#endif
436 tcflush (reader[ridx].handle, TCIFLUSH);
437 return FALSE;
438 }
439#endif
440 }
441
442 _in_echo_read = 0;
443
444#ifdef DEBUG_IO
445 printf ("\n");
446 fflush (stdout);
447#endif
448
449 return TRUE;
450}
451
452
453
454
455bool IO_Serial_Write (unsigned delay, unsigned size, BYTE * data)
456{
457 unsigned count, to_send, i_w;
458 BYTE data_w[512];
459#ifdef DEBUG_IO
460 unsigned i;
461
462 printf ("IO: Sending: ");
463 fflush (stdout);
464#endif
465 /* Discard input data from previous commands */
466// tcflush (reader[ridx].handle, TCIFLUSH);
467
468 for (count = 0; count < size; count += to_send)
469 {
470// if(reader[ridx].typ == R_INTERNAL)
471// to_send = 1;
472// else
473 to_send = (delay? 1: size);
474
475 if (IO_Serial_WaitToWrite (delay, 1000))
476 {
477 for (i_w=0; i_w < to_send; i_w++) {
478 data_w [(1+io_serial_need_dummy_char)*i_w] = data [count + i_w];
479 if (io_serial_need_dummy_char) {
480 data_w [2*i_w+1] = 0x00;
481 }
482 }
483 unsigned int u = write (reader[ridx].handle, data_w, (1+io_serial_need_dummy_char)*to_send);
484 _in_echo_read = 1;
485 if (u != (1+io_serial_need_dummy_char)*to_send)
486 {
487#ifdef DEBUG_IO
488 printf ("ERROR\n");
489 fflush (stdout);
490#endif
491 if(reader[ridx].typ != R_INTERNAL)
492 wr += u;
493 return FALSE;
494 }
495
496 if(reader[ridx].typ != R_INTERNAL)
497 wr += to_send;
498
499#ifdef DEBUG_IO
500 for (i=0; i<(1+io_serial_need_dummy_char)*to_send; i++)
501 printf ("%X ", data_w[count + i]);
502 fflush (stdout);
503#endif
504 }
505 else
506 {
507#ifdef DEBUG_IO
508 printf ("TIMEOUT\n");
509 fflush (stdout);
510#endif
511// tcflush (reader[ridx].handle, TCIFLUSH);
512 return FALSE;
513 }
514 }
515
516#ifdef DEBUG_IO
517 printf ("\n");
518 fflush (stdout);
519#endif
520
521 return TRUE;
522}
523
524bool IO_Serial_Close ()
525{
526
527#ifdef DEBUG_IO
528 printf ("IO: Clossing serial port %s\n", reader[ridx].device);
529#endif
530
531#if defined(TUXBOX) && defined(PPC)
532 close(fdmc);
533#endif
534 if (close (reader[ridx].handle) != 0)
535 return FALSE;
536
537 wr = 0;
538
539 return TRUE;
540}
541
542/*
543 * Internal functions definition
544 */
545
546static int IO_Serial_Bitrate(int bitrate)
547{
548#ifdef B230400
549 if ((bitrate)>=230400) return B230400;
550#endif
551#ifdef B115200
552 if ((bitrate)>=115200) return B115200;
553#endif
554#ifdef B57600
555 if ((bitrate)>=57600) return B57600;
556#endif
557#ifdef B38400
558 if ((bitrate)>=38400) return B38400;
559#endif
560#ifdef B19200
561 if ((bitrate)>=19200) return B19200;
562#endif
563#ifdef B9600
564 if ((bitrate)>=9600) return B9600;
565#endif
566#ifdef B4800
567 if ((bitrate)>=4800) return B4800;
568#endif
569#ifdef B2400
570 if ((bitrate)>=2400) return B2400;
571#endif
572#ifdef B1800
573 if ((bitrate)>=1800) return B1800;
574#endif
575#ifdef B1200
576 if ((bitrate)>=1200) return B1200;
577#endif
578#ifdef B600
579 if ((bitrate)>=600) return B600;
580#endif
581#ifdef B300
582 if ((bitrate)>=300) return B300;
583#endif
584#ifdef B200
585 if ((bitrate)>=200) return B200;
586#endif
587#ifdef B150
588 if ((bitrate)>=150) return B150;
589#endif
590#ifdef B134
591 if ((bitrate)>=134) return B134;
592#endif
593#ifdef B110
594 if ((bitrate)>=110) return B110;
595#endif
596#ifdef B75
597 if ((bitrate)>=75) return B75;
598#endif
599#ifdef B50
600 if ((bitrate)>=50) return B50;
601#endif
602#ifdef B0
603 if ((bitrate)>=0) return B0;
604#endif
605 return 0; /* Should never get here */
606}
607
608static bool IO_Serial_WaitToRead (unsigned delay_ms, unsigned timeout_ms)
609{
610 fd_set rfds;
611 fd_set erfds;
612 struct timeval tv;
613 int select_ret;
614 int in_fd;
615
616 if (delay_ms > 0)
617 {
618#ifdef HAVE_NANOSLEEP
619 struct timespec req_ts;
620
621 req_ts.tv_sec = delay_ms / 1000;
622 req_ts.tv_nsec = (delay_ms % 1000) * 1000000L;
623 nanosleep (&req_ts, NULL);
624#else
625 usleep (delay_ms * 1000L);
626#endif
627 }
628
629 in_fd=reader[ridx].handle;
630
631 FD_ZERO(&rfds);
632 FD_SET(in_fd, &rfds);
633
634 FD_ZERO(&erfds);
635 FD_SET(in_fd, &erfds);
636
637 tv.tv_sec = timeout_ms/1000;
638 tv.tv_usec = (timeout_ms % 1000) * 1000L;
639 select_ret = select(in_fd+1, &rfds, NULL, &erfds, &tv);
640 if(select_ret==-1)
641 {
642 printf("select_ret=%i\n" , select_ret);
643 printf("errno =%d\n", errno);
644 fflush(stdout);
645 return (FALSE);
646 }
647
648 if (FD_ISSET(in_fd, &erfds))
649 {
650 printf("fd is in error fds\n");
651 printf("errno =%d\n", errno);
652 fflush(stdout);
653 return (FALSE);
654 }
655
656 return(FD_ISSET(in_fd,&rfds));
657}
658
659static bool IO_Serial_WaitToWrite (unsigned delay_ms, unsigned timeout_ms)
660{
661 fd_set wfds;
662 fd_set ewfds;
663 struct timeval tv;
664 int select_ret;
665 int out_fd;
666
667#ifdef SCI_DEV
668 if(reader[ridx].typ == R_INTERNAL)
669 return TRUE;
670#endif
671
672 if (delay_ms > 0)
673 {
674#ifdef HAVE_NANOSLEEP
675 struct timespec req_ts;
676
677 req_ts.tv_sec = delay_ms / 1000;
678 req_ts.tv_nsec = (delay_ms % 1000) * 1000000L;
679 nanosleep (&req_ts, NULL);
680#else
681 usleep (delay_ms * 1000L);
682#endif
683 }
684
685 out_fd=reader[ridx].handle;
686
687 FD_ZERO(&wfds);
688 FD_SET(out_fd, &wfds);
689
690 FD_ZERO(&ewfds);
691 FD_SET(out_fd, &ewfds);
692
693 tv.tv_sec = timeout_ms/1000L;
694 tv.tv_usec = (timeout_ms % 1000) * 1000L;
695
696 select_ret = select(out_fd+1, NULL, &wfds, &ewfds, &tv);
697
698 if(select_ret==-1)
699 {
700 printf("select_ret=%d\n" , select_ret);
701 printf("errno =%d\n", errno);
702 fflush(stdout);
703 return (FALSE);
704 }
705
706 if (FD_ISSET(out_fd, &ewfds))
707 {
708 printf("fd is in ewfds\n");
709 printf("errno =%d\n", errno);
710 fflush(stdout);
711 return (FALSE);
712 }
713
714 return(FD_ISSET(out_fd,&wfds));
715
716}
717
718bool IO_Serial_InitPnP ()
719{
720 unsigned int PnP_id_size = 0;
721 BYTE PnP_id[IO_SERIAL_PNPID_SIZE]; /* PnP Id of the serial device */
722
723 if (!IO_Serial_SetParams (1200, 7, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_LOW))
724 return FALSE;
725
726 while ((PnP_id_size < IO_SERIAL_PNPID_SIZE) && IO_Serial_Read (200, 1, &(PnP_id[PnP_id_size])))
727 PnP_id_size++;
728
729 return TRUE;
730}
731
Note: See TracBrowser for help on using the repository browser.