source: trunk/csctapi/io_serial.c@ 70

Last change on this file since 70 was 70, checked in by rorothetroll, 12 years ago

csctapi/io_serial.c : fix the serial port read/write wait routine to use select instead of poll

This make them compatible with Mac OS X and now oscamd works on OS X. The same code off course
still works on linux and other unix platforms. I let that code ran for 24h before commiting this code.
If you have any issue let me know and I'llr evert to poll for non compatible machines.

all the others : fix all the warning due to sign difference (mostly uchar versus char). This make the code compile

with -Werror on the more strict version of gcc (which is the case on OS X). I also noticed that in a lot of places
the code use a buffer defined as an uchar * ... and use strings functions (strnXXXX) where some memcpy/memcmp .. function
would have been preferable as we're suposedly manipulation a binary buffer. Anyway I fixed all of them and it now compile
without any warning or error on linux and OS X (and also probably on all the other unices but we will have to try before
adding -Werror on the other platform).

File size: 22.7 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 <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29#include <errno.h>
30#ifdef OS_HPUX
31#include <sys/modem.h>
32#endif
33#include <termios.h>
34#include <unistd.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#ifdef HAVE_POLL
38#include <sys/poll.h>
39#else
40#include <sys/signal.h>
41#include <sys/types.h>
42#include <sys/time.h>
43#endif
44#include <sys/ioctl.h>
45#include <time.h>
46#include "io_serial.h"
47#include "mc_global.h"
48
49#ifdef OS_LINUX
50#include <linux/serial.h>
51#endif
52
53#define IO_SERIAL_FILENAME_LENGTH 32
54
55/*
56 * Internal functions declaration
57 */
58
59static int IO_Serial_Bitrate(int bitrate);
60
61static bool IO_Serial_WaitToRead (int hnd, unsigned delay_ms, unsigned timeout_ms);
62
63static bool IO_Serial_WaitToWrite (IO_Serial *io, unsigned delay_ms, unsigned timeout_ms);
64
65static void IO_Serial_DeviceName (unsigned com, bool usbserial, char * filename, unsigned length);
66
67static bool IO_Serial_InitPnP (IO_Serial * io);
68
69static void IO_Serial_Clear (IO_Serial * io);
70
71static bool IO_Serial_GetPropertiesCache(IO_Serial * io, IO_Serial_Properties * props);
72
73static void IO_Serial_SetPropertiesCache(IO_Serial * io, IO_Serial_Properties * props);
74
75static void IO_Serial_ClearPropertiesCache (IO_Serial * io);
76
77static int _in_echo_read = 0;
78int io_serial_need_dummy_char = 0;
79
80int fdmc=(-1);
81
82#if defined(TUXBOX) && defined(PPC)
83void IO_Serial_Ioctl_Lock(IO_Serial * io, int flag)
84{
85 extern int *oscam_sem;
86 if ((io->com!=RTYP_DB2COM1) && (io->com!=RTYP_DB2COM2)) return;
87 if (!flag)
88 *oscam_sem=0;
89 else while (*oscam_sem!=io->com)
90 {
91 while (*oscam_sem)
92 usleep((io->com)*2000);
93 *oscam_sem=io->com;
94 usleep(1000);
95 }
96}
97
98static bool IO_Serial_DTR_RTS_dbox2(int mcport, int dtr, int set)
99{
100 int rc;
101 unsigned short msr;
102 unsigned int mbit;
103 unsigned short rts_bits[2]={ 0x10, 0x800};
104 unsigned short dtr_bits[2]={0x100, 0};
105
106#ifdef DEBUG_IO
107printf("IO: multicam.o %s %s\n", dtr ? "dtr" : "rts", set ? "set" : "clear"); fflush(stdout);
108#endif
109 if ((rc=ioctl(fdmc, GET_PCDAT, &msr))>=0)
110 {
111 if (dtr) // DTR
112 {
113 if (dtr_bits[mcport])
114 {
115 if (set)
116 msr&=(unsigned short)(~dtr_bits[mcport]);
117 else
118 msr|=dtr_bits[mcport];
119 rc=ioctl(fdmc, SET_PCDAT, &msr);
120 }
121 else
122 rc=0; // Dummy, can't handle using multicam.o
123 }
124 else // RTS
125 {
126 if (set)
127 msr&=(unsigned short)(~rts_bits[mcport]);
128 else
129 msr|=rts_bits[mcport];
130 rc=ioctl(fdmc, SET_PCDAT, &msr);
131 }
132 }
133 return((rc<0) ? FALSE : TRUE);
134}
135#endif
136
137bool IO_Serial_DTR_RTS(IO_Serial * io, int dtr, int set)
138{
139 unsigned int msr;
140 unsigned int mbit;
141
142#if defined(TUXBOX) && defined(PPC)
143 if ((io->com==RTYP_DB2COM1) || (io->com==RTYP_DB2COM2))
144 return(IO_Serial_DTR_RTS_dbox2(io->com==RTYP_DB2COM2, dtr, set));
145#endif
146
147 mbit=(dtr) ? TIOCM_DTR : TIOCM_RTS;
148#if defined(TIOCMBIS) && defined(TIOBMBIC)
149 if (ioctl (io->fd, set ? TIOCMBIS : TIOCMBIC, &mbit) < 0)
150 return FALSE;
151#else
152 if (ioctl(io->fd, TIOCMGET, &msr) < 0)
153 return FALSE;
154 if (set)
155 msr|=mbit;
156 else
157 msr&=~mbit;
158 return((ioctl(io->fd, TIOCMSET, &msr)<0) ? FALSE : TRUE);
159#endif
160}
161
162/*
163 * Public functions definition
164 */
165
166IO_Serial * IO_Serial_New (void)
167{
168 IO_Serial *io;
169
170 io = (IO_Serial *) malloc (sizeof (IO_Serial));
171
172 if (io != NULL)
173 IO_Serial_Clear (io);
174
175 return io;
176}
177
178bool IO_Serial_Init (IO_Serial * io, unsigned com, bool usbserial, bool pnp)
179{
180 char filename[IO_SERIAL_FILENAME_LENGTH];
181
182 IO_Serial_DeviceName (com, usbserial, filename, IO_SERIAL_FILENAME_LENGTH);
183
184#ifdef DEBUG_IO
185 printf ("IO: Opening serial port %s\n", filename);
186#endif
187
188 if (com < 1)
189 return FALSE;
190
191 io->com = com;
192
193#ifdef SCI_DEV
194 if (com==RTYP_SCI)
195 io->fd = open (filename, O_RDWR);
196 else
197#endif
198
199#ifdef OS_MACOSX
200 io->fd = open (filename, O_RDWR | O_NOCTTY | O_NDELAY );
201#else
202 io->fd = open (filename, O_RDWR | O_NOCTTY | O_SYNC);
203#endif
204
205 if (io->fd < 0)
206 return FALSE;
207
208#if defined(TUXBOX) && defined(PPC)
209 if ((com==RTYP_DB2COM1) || (com==RTYP_DB2COM2))
210 if ((fdmc = open(DEV_MULTICAM, O_RDWR)) < 0)
211 {
212 close(io->fd);
213 return FALSE;
214 }
215#endif
216
217 if (com!=RTYP_SCI)
218 IO_Serial_InitPnP (io);
219
220 io->usbserial=usbserial;
221
222 if(io->com!=RTYP_SCI)
223 IO_Serial_Flush(io);
224
225 return TRUE;
226}
227
228bool IO_Serial_GetProperties (IO_Serial * io, IO_Serial_Properties * props)
229{
230 struct termios currtio;
231 speed_t i_speed, o_speed;
232 unsigned int mctl;
233
234#ifdef SCI_DEV
235 if(io->com==RTYP_SCI)
236 return FALSE;
237#endif
238
239 if (IO_Serial_GetPropertiesCache(io, props))
240 return TRUE;
241
242 if (tcgetattr (io->fd, &currtio) != 0)
243 return FALSE;
244
245 o_speed = cfgetospeed (&currtio);
246
247 switch (o_speed)
248 {
249#ifdef B0
250 case B0:
251 props->output_bitrate = 0;
252 break;
253#endif
254#ifdef B50
255 case B50:
256 props->output_bitrate = 50;
257 break;
258#endif
259#ifdef B75
260 case B75:
261 props->output_bitrate = 75;
262 break;
263#endif
264#ifdef B110
265 case B110:
266 props->output_bitrate = 110;
267 break;
268#endif
269#ifdef B134
270 case B134:
271 props->output_bitrate = 134;
272 break;
273#endif
274#ifdef B150
275 case B150:
276 props->output_bitrate = 150;
277 break;
278#endif
279#ifdef B200
280 case B200:
281 props->output_bitrate = 200;
282 break;
283#endif
284#ifdef B300
285 case B300:
286 props->output_bitrate = 300;
287 break;
288#endif
289#ifdef B600
290 case B600:
291 props->output_bitrate = 600;
292 break;
293#endif
294#ifdef B1200
295 case B1200:
296 props->output_bitrate = 1200;
297 break;
298#endif
299#ifdef B1800
300 case B1800:
301 props->output_bitrate = 1800;
302 break;
303#endif
304#ifdef B2400
305 case B2400:
306 props->output_bitrate = 2400;
307 break;
308#endif
309#ifdef B4800
310 case B4800:
311 props->output_bitrate = 4800;
312 break;
313#endif
314#ifdef B9600
315 case B9600:
316 props->output_bitrate = 9600;
317 break;
318#endif
319#ifdef B19200
320 case B19200:
321 props->output_bitrate = 19200;
322 break;
323#endif
324#ifdef B38400
325 case B38400:
326 props->output_bitrate = 38400;
327 break;
328#endif
329#ifdef B57600
330 case B57600:
331 props->output_bitrate = 57600;
332 break;
333#endif
334#ifdef B115200
335 case B115200:
336 props->output_bitrate = 115200;
337 break;
338#endif
339#ifdef B230400
340 case B230400:
341 props->output_bitrate = 230400;
342 break;
343#endif
344 default:
345 props->output_bitrate = 1200;
346 break;
347 }
348
349 i_speed = cfgetispeed (&currtio);
350
351 switch (i_speed)
352 {
353#ifdef B0
354 case B0:
355 props->input_bitrate = 0;
356 break;
357#endif
358#ifdef B50
359 case B50:
360 props->input_bitrate = 50;
361 break;
362#endif
363#ifdef B75
364 case B75:
365 props->input_bitrate = 75;
366 break;
367#endif
368#ifdef B110
369 case B110:
370 props->input_bitrate = 110;
371 break;
372#endif
373#ifdef B134
374 case B134:
375 props->input_bitrate = 134;
376 break;
377#endif
378#ifdef B150
379 case B150:
380 props->input_bitrate = 150;
381 break;
382#endif
383#ifdef B200
384 case B200:
385 props->input_bitrate = 200;
386 break;
387#endif
388#ifdef B300
389 case B300:
390 props->input_bitrate = 300;
391 break;
392#endif
393#ifdef B600
394 case B600:
395 props->input_bitrate = 600;
396 break;
397#endif
398#ifdef B1200
399 case B1200:
400 props->input_bitrate = 1200;
401 break;
402#endif
403#ifdef B1800
404 case B1800:
405 props->input_bitrate = 1800;
406 break;
407#endif
408#ifdef B2400
409 case B2400:
410 props->input_bitrate = 2400;
411 break;
412#endif
413#ifdef B4800
414 case B4800:
415 props->input_bitrate = 4800;
416 break;
417#endif
418#ifdef B9600
419 case B9600:
420 props->input_bitrate = 9600;
421 break;
422#endif
423#ifdef B19200
424 case B19200:
425 props->input_bitrate = 19200;
426 break;
427#endif
428#ifdef B38400
429 case B38400:
430 props->input_bitrate = 38400;
431 break;
432#endif
433#ifdef B57600
434 case B57600:
435 props->input_bitrate = 57600;
436 break;
437#endif
438#ifdef B115200
439 case B115200:
440 props->input_bitrate = 115200;
441 break;
442#endif
443#ifdef B230400
444 case B230400:
445 props->input_bitrate = 230400;
446 break;
447#endif
448 default:
449 props->input_bitrate = 1200;
450 break;
451 }
452
453 switch (currtio.c_cflag & CSIZE)
454 {
455 case CS5:
456 props->bits = 5;
457 break;
458 case CS6:
459 props->bits = 6;
460 break;
461 case CS7:
462 props->bits = 7;
463 break;
464 case CS8:
465 props->bits = 8;
466 break;
467 }
468
469 if (((currtio.c_cflag) & PARENB) == PARENB)
470 {
471 if (((currtio.c_cflag) & PARODD) == PARODD)
472 props->parity = IO_SERIAL_PARITY_ODD;
473 else
474 props->parity = IO_SERIAL_PARITY_EVEN;
475 }
476 else
477 {
478 props->parity = IO_SERIAL_PARITY_NONE;
479 }
480
481 if (((currtio.c_cflag) & CSTOPB) == CSTOPB)
482 props->stopbits = 2;
483 else
484 props->stopbits = 1;
485
486 if (ioctl (io->fd, TIOCMGET, &mctl) < 0)
487 return FALSE;
488
489 props->dtr = ((mctl & TIOCM_DTR) ? IO_SERIAL_HIGH : IO_SERIAL_LOW);
490 props->rts = ((mctl & TIOCM_RTS) ? IO_SERIAL_HIGH : IO_SERIAL_LOW);
491
492 IO_Serial_SetPropertiesCache (io, props);
493
494#ifdef DEBUG_IO
495 printf("IO: Getting properties: %ld bps; %d bits/byte; %s parity; %d stopbits; dtr=%d; rts=%d\n", props->input_bitrate, props->bits, props->parity == IO_SERIAL_PARITY_EVEN ? "Even" : props->parity == IO_SERIAL_PARITY_ODD ? "Odd" : "None", props->stopbits, props->dtr, props->rts);
496#endif
497
498 return TRUE;
499}
500
501bool IO_Serial_SetProperties (IO_Serial * io, IO_Serial_Properties * props)
502{
503 struct termios newtio;
504 unsigned int modembits;
505
506#ifdef SCI_DEV
507 if(io->com==RTYP_SCI)
508 return FALSE;
509#endif
510
511 // printf("IO: Setting properties: com%d, %ld bps; %d bits/byte; %s parity; %d stopbits; dtr=%d; rts=%d\n", io->com, props->input_bitrate, props->bits, props->parity == IO_SERIAL_PARITY_EVEN ? "Even" : props->parity == IO_SERIAL_PARITY_ODD ? "Odd" : "None", props->stopbits, props->dtr, props->rts);
512 memset (&newtio, 0, sizeof (newtio));
513 /* Set the bitrate */
514
515 extern int mhz;
516 extern int reader_irdeto_mode;
517 if (mhz == 600)
518 {
519 /* for 6MHz */
520 if (reader_irdeto_mode)
521 {
522 cfsetospeed(&newtio, IO_Serial_Bitrate(props->output_bitrate));
523 cfsetispeed(&newtio, IO_Serial_Bitrate(props->input_bitrate));
524 }
525 else
526 {
527#ifdef OS_LINUX
528 /* these structures are only available on linux as fas as we know so limit this code to OS_LINUX */
529 struct serial_struct nuts;
530 ioctl(io->fd, TIOCGSERIAL, &nuts);
531 nuts.custom_divisor = nuts.baud_base / 9600 * 3.57 / 6;
532 nuts.flags &= ~ASYNC_SPD_MASK;
533 nuts.flags |= ASYNC_SPD_CUST;
534 ioctl(io->fd, TIOCSSERIAL, &nuts);
535 cfsetospeed(&newtio, IO_Serial_Bitrate(38400));
536 cfsetispeed(&newtio, IO_Serial_Bitrate(38400));
537#else
538 cfsetospeed(&newtio, IO_Serial_Bitrate(props->output_bitrate));
539 cfsetispeed(&newtio, IO_Serial_Bitrate(props->input_bitrate));
540#endif
541 }
542 }
543 else if (mhz == 357 || mhz == 358)
544 {
545 /* for 3.57 MHz */
546 if (reader_irdeto_mode)
547 {
548#ifdef OS_LINUX
549 /* these structures are only available on linux as fas as we know so limit this code to OS_LINUX */
550 struct serial_struct nuts;
551 ioctl(io->fd, TIOCGSERIAL, &nuts);
552 nuts.custom_divisor = nuts.baud_base / 5713;
553 nuts.flags &= ~ASYNC_SPD_MASK;
554 nuts.flags |= ASYNC_SPD_CUST;
555 ioctl(io->fd, TIOCSSERIAL, &nuts);
556 cfsetospeed(&newtio, IO_Serial_Bitrate(38400));
557 cfsetispeed(&newtio, IO_Serial_Bitrate(38400));
558#else
559 cfsetospeed(&newtio, IO_Serial_Bitrate(props->output_bitrate));
560 cfsetispeed(&newtio, IO_Serial_Bitrate(props->input_bitrate));
561#endif
562 }
563 else
564 {
565 cfsetospeed(&newtio, IO_Serial_Bitrate(props->output_bitrate));
566 cfsetispeed(&newtio, IO_Serial_Bitrate(props->input_bitrate));
567 }
568 }
569 else
570 {
571 /* invalid */
572 return FALSE;
573 }
574
575 /* Set the character size */
576 switch (props->bits)
577 {
578 case 5:
579 newtio.c_cflag |= CS5;
580 break;
581
582 case 6:
583 newtio.c_cflag |= CS6;
584 break;
585
586 case 7:
587 newtio.c_cflag |= CS7;
588 break;
589
590 case 8:
591 newtio.c_cflag |= CS8;
592 break;
593 }
594
595 /* Set the parity */
596 switch (props->parity)
597 {
598 case IO_SERIAL_PARITY_ODD:
599 newtio.c_cflag |= PARENB;
600 newtio.c_cflag |= PARODD;
601 break;
602
603 case IO_SERIAL_PARITY_EVEN:
604 newtio.c_cflag |= PARENB;
605 newtio.c_cflag &= ~PARODD;
606 break;
607
608 case IO_SERIAL_PARITY_NONE:
609 newtio.c_cflag &= ~PARENB;
610 break;
611 }
612
613 /* Set the number of stop bits */
614 switch (props->stopbits)
615 {
616 case 1:
617 newtio.c_cflag &= (~CSTOPB);
618 break;
619 case 2:
620 newtio.c_cflag |= CSTOPB;
621 break;
622 }
623
624 /* Selects raw (non-canonical) input and output */
625 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
626 newtio.c_oflag &= ~OPOST;
627#if 1
628 newtio.c_iflag |= IGNPAR;
629 /* Ignore parity errors!!! Windows driver does so why shouldn't I? */
630#endif
631 /* Enable receiber, hang on close, ignore control line */
632 newtio.c_cflag |= CREAD | HUPCL | CLOCAL;
633
634 /* Read 1 byte minimun, no timeout specified */
635 newtio.c_cc[VMIN] = 1;
636 newtio.c_cc[VTIME] = 0;
637
638// tcdrain(io->fd);
639 if (tcsetattr (io->fd, TCSANOW, &newtio) < 0)
640 return FALSE;
641// tcflush(io->fd, TCIOFLUSH);
642// if (tcsetattr (io->fd, TCSAFLUSH, &newtio) < 0)
643// return FALSE;
644
645 IO_Serial_Ioctl_Lock(io, 1);
646 IO_Serial_DTR_RTS(io, 0, props->rts == IO_SERIAL_HIGH);
647 IO_Serial_DTR_RTS(io, 1, props->dtr == IO_SERIAL_HIGH);
648 IO_Serial_Ioctl_Lock(io, 0);
649
650 IO_Serial_SetPropertiesCache (io, props);
651
652#ifdef DEBUG_IO
653 printf("IO: Setting properties: com%d, %ld bps; %d bits/byte; %s parity; %d stopbits; dtr=%d; rts=%d\n", io->com, props->input_bitrate, props->bits, props->parity == IO_SERIAL_PARITY_EVEN ? "Even" : props->parity == IO_SERIAL_PARITY_ODD ? "Odd" : "None", props->stopbits, props->dtr, props->rts);
654#endif
655 return TRUE;
656}
657
658void IO_Serial_Flush (IO_Serial * io)
659{
660 BYTE b;
661 while(IO_Serial_Read(io, 1000, 1, &b));
662}
663
664
665void IO_Serial_GetPnPId (IO_Serial * io, BYTE * pnp_id, unsigned *length)
666{
667 (*length) = io->PnP_id_size;
668 memcpy (pnp_id, io->PnP_id, io->PnP_id_size);
669}
670
671unsigned IO_Serial_GetCom (IO_Serial * io)
672{
673 return io->com;
674}
675
676
677bool IO_Serial_Read (IO_Serial * io, unsigned timeout, unsigned size, BYTE * data)
678{
679 BYTE c;
680 int count = 0;
681
682
683 if((io->com!=RTYP_SCI) && (io->wr>0))
684 {
685 BYTE buf[256];
686 int n = io->wr;
687 io->wr = 0;
688
689 if(!IO_Serial_Read (io, timeout, n, buf))
690 {
691 return FALSE;
692 }
693 }
694
695#ifdef DEBUG_IO
696 printf ("IO: Receiving: ");
697 fflush (stdout);
698#endif
699 for (count = 0; count < size * (_in_echo_read ? (1+io_serial_need_dummy_char) : 1); count++)
700 {
701 if (IO_Serial_WaitToRead (io->fd, 0, timeout))
702 {
703 if (read (io->fd, &c, 1) != 1)
704 {
705#ifdef DEBUG_IO
706 printf ("ERROR\n");
707 fflush (stdout);
708#endif
709 return FALSE;
710 }
711 data[_in_echo_read ? count/(1+io_serial_need_dummy_char) : count] = c;
712
713#ifdef DEBUG_IO
714 printf ("%X ", c);
715 fflush (stdout);
716#endif
717 }
718 else
719 {
720#ifdef DEBUG_IO
721 printf ("TIMEOUT\n");
722 fflush (stdout);
723#endif
724 tcflush (io->fd, TCIFLUSH);
725 return FALSE;
726 }
727 }
728
729 _in_echo_read = 0;
730
731#ifdef DEBUG_IO
732 printf ("\n");
733 fflush (stdout);
734#endif
735
736 return TRUE;
737}
738
739
740
741
742bool IO_Serial_Write (IO_Serial * io, unsigned delay, unsigned size, BYTE * data)
743{
744 unsigned count, to_send;
745 BYTE data_w[512];
746 int i_w;
747#ifdef DEBUG_IO
748 unsigned i;
749
750 printf ("IO: Sending: ");
751 fflush (stdout);
752#endif
753 /* Discard input data from previous commands */
754// tcflush (io->fd, TCIFLUSH);
755
756 for (count = 0; count < size; count += to_send)
757 {
758// if(io->com==RTYP_SCI)
759// to_send = 1;
760// else
761 to_send = (delay? 1: size);
762
763 if (IO_Serial_WaitToWrite (io, delay, 1000))
764 {
765 for (i_w=0; i_w < to_send; i_w++) {
766 data_w [(1+io_serial_need_dummy_char)*i_w] = data [count + i_w];
767 if (io_serial_need_dummy_char) {
768 data_w [2*i_w+1] = 0x00;
769 }
770 }
771 unsigned int u = write (io->fd, data_w, (1+io_serial_need_dummy_char)*to_send);
772 _in_echo_read = 1;
773 if (u != (1+io_serial_need_dummy_char)*to_send)
774 {
775#ifdef DEBUG_IO
776 printf ("ERROR\n");
777 fflush (stdout);
778#endif
779 if(io->com!=RTYP_SCI)
780 io->wr += u;
781 return FALSE;
782 }
783
784 if(io->com!=RTYP_SCI)
785 io->wr += to_send;
786
787#ifdef DEBUG_IO
788 for (i=0; i<(1+io_serial_need_dummy_char)*to_send; i++)
789 printf ("%X ", data_w[count + i]);
790 fflush (stdout);
791#endif
792 }
793 else
794 {
795#ifdef DEBUG_IO
796 printf ("TIMEOUT\n");
797 fflush (stdout);
798#endif
799// tcflush (io->fd, TCIFLUSH);
800 return FALSE;
801 }
802 }
803
804#ifdef DEBUG_IO
805 printf ("\n");
806 fflush (stdout);
807#endif
808
809 return TRUE;
810}
811
812bool IO_Serial_Close (IO_Serial * io)
813{
814 char filename[IO_SERIAL_FILENAME_LENGTH];
815
816 IO_Serial_DeviceName (io->com, io->usbserial, filename, IO_SERIAL_FILENAME_LENGTH);
817
818#ifdef DEBUG_IO
819 printf ("IO: Clossing serial port %s\n", filename);
820#endif
821
822#if defined(TUXBOX) && defined(PPC)
823 close(fdmc);
824#endif
825 if (close (io->fd) != 0)
826 return FALSE;
827
828 IO_Serial_ClearPropertiesCache (io);
829 IO_Serial_Clear (io);
830
831 return TRUE;
832}
833
834void IO_Serial_Delete (IO_Serial * io)
835{
836 if (io->props != NULL)
837 free (io->props);
838
839 free (io);
840}
841
842/*
843 * Internal functions definition
844 */
845
846static int IO_Serial_Bitrate(int bitrate)
847{
848#ifdef B230400
849 if ((bitrate)>=230400) return B230400;
850#endif
851#ifdef B115200
852 if ((bitrate)>=115200) return B115200;
853#endif
854#ifdef B57600
855 if ((bitrate)>=57600) return B57600;
856#endif
857#ifdef B38400
858 if ((bitrate)>=38400) return B38400;
859#endif
860#ifdef B19200
861 if ((bitrate)>=19200) return B19200;
862#endif
863#ifdef B9600
864 if ((bitrate)>=9600) return B9600;
865#endif
866#ifdef B4800
867 if ((bitrate)>=4800) return B4800;
868#endif
869#ifdef B2400
870 if ((bitrate)>=2400) return B2400;
871#endif
872#ifdef B1800
873 if ((bitrate)>=1800) return B1800;
874#endif
875#ifdef B1200
876 if ((bitrate)>=1200) return B1200;
877#endif
878#ifdef B600
879 if ((bitrate)>=600) return B600;
880#endif
881#ifdef B300
882 if ((bitrate)>=300) return B300;
883#endif
884#ifdef B200
885 if ((bitrate)>=200) return B200;
886#endif
887#ifdef B150
888 if ((bitrate)>=150) return B150;
889#endif
890#ifdef B134
891 if ((bitrate)>=134) return B134;
892#endif
893#ifdef B110
894 if ((bitrate)>=110) return B110;
895#endif
896#ifdef B75
897 if ((bitrate)>=75) return B75;
898#endif
899#ifdef B50
900 if ((bitrate)>=50) return B50;
901#endif
902#ifdef B0
903 if ((bitrate)>=0) return B0;
904#endif
905 return 0; /* Should never get here */
906}
907
908static bool IO_Serial_WaitToRead (int hnd, unsigned delay_ms, unsigned timeout_ms)
909{
910 fd_set rfds;
911 fd_set erfds;
912 struct timeval tv;
913 int select_ret;
914 int in_fd;
915
916 if (delay_ms > 0)
917 {
918#ifdef HAVE_NANOSLEEP
919 struct timespec req_ts;
920
921 req_ts.tv_sec = delay_ms / 1000;
922 req_ts.tv_nsec = (delay_ms % 1000) * 1000000L;
923 nanosleep (&req_ts, NULL);
924#else
925 usleep (delay_ms * 1000L);
926#endif
927 }
928
929 in_fd=hnd;
930
931 FD_ZERO(&rfds);
932 FD_SET(in_fd, &rfds);
933
934 FD_ZERO(&erfds);
935 FD_SET(in_fd, &erfds);
936
937 tv.tv_sec = timeout_ms/1000;
938 tv.tv_usec = (timeout_ms % 1000) * 1000L;
939 select_ret = select(in_fd+1, &rfds, NULL, &erfds, &tv);
940 if(select_ret==-1)
941 {
942 printf("select_ret=%i\n" , select_ret);
943 printf("errno =%d\n", errno);
944 fflush(stdout);
945 return (FALSE);
946 }
947
948 if (FD_ISSET(in_fd, &erfds))
949 {
950 printf("fd is in error fds\n");
951 printf("errno =%d\n", errno);
952 fflush(stdout);
953 return (FALSE);
954 }
955
956 return(FD_ISSET(in_fd,&rfds));
957}
958
959static bool IO_Serial_WaitToWrite (IO_Serial *io, unsigned delay_ms, unsigned timeout_ms)
960{
961 fd_set wfds;
962 fd_set ewfds;
963 struct timeval tv;
964 int select_ret;
965 int out_fd;
966
967#ifdef SCI_DEV
968 if(io->com==RTYP_SCI)
969 return TRUE;
970#endif
971
972 if (delay_ms > 0)
973 {
974#ifdef HAVE_NANOSLEEP
975 struct timespec req_ts;
976
977 req_ts.tv_sec = delay_ms / 1000;
978 req_ts.tv_nsec = (delay_ms % 1000) * 1000000L;
979 nanosleep (&req_ts, NULL);
980#else
981 usleep (delay_ms * 1000L);
982#endif
983 }
984
985 out_fd=io->fd;
986
987 FD_ZERO(&wfds);
988 FD_SET(out_fd, &wfds);
989
990 FD_ZERO(&ewfds);
991 FD_SET(out_fd, &ewfds);
992
993 tv.tv_sec = timeout_ms/1000L;
994 tv.tv_usec = (timeout_ms % 1000) * 1000L;
995
996 select_ret = select(out_fd+1, NULL, &wfds, &ewfds, &tv);
997
998 if(select_ret==-1)
999 {
1000 printf("select_ret=%d\n" , select_ret);
1001 printf("errno =%d\n", errno);
1002 fflush(stdout);
1003 return (FALSE);
1004 }
1005
1006 if (FD_ISSET(out_fd, &ewfds))
1007 {
1008 printf("fd is in ewfds\n");
1009 printf("errno =%d\n", errno);
1010 fflush(stdout);
1011 return (FALSE);
1012 }
1013
1014 return(FD_ISSET(out_fd,&wfds));
1015
1016}
1017
1018static void IO_Serial_Clear (IO_Serial * io)
1019{
1020 io->fd = -1;
1021 io->props = NULL;
1022 io->com = 0;
1023 memset (io->PnP_id, 0, IO_SERIAL_PNPID_SIZE);
1024 io->PnP_id_size = 0;
1025 io->usbserial = FALSE;
1026 io->wr = 0;
1027}
1028
1029static void IO_Serial_SetPropertiesCache(IO_Serial * io, IO_Serial_Properties * props)
1030{
1031#ifdef SCI_DEV
1032 if(io->com==RTYP_SCI)
1033 return;
1034#endif
1035
1036 if (io->props == NULL)
1037 io->props = (IO_Serial_Properties *) malloc (sizeof (IO_Serial_Properties));
1038#ifdef DEBUG_IO
1039 printf ("IO: Catching properties\n");
1040#endif
1041
1042 memcpy (io->props, props, sizeof (IO_Serial_Properties));
1043}
1044
1045static bool IO_Serial_GetPropertiesCache(IO_Serial * io, IO_Serial_Properties * props)
1046{
1047 if (io->props != NULL)
1048 {
1049 memcpy (props, io->props, sizeof (IO_Serial_Properties));
1050#if 0
1051#ifdef DEBUG_IO
1052 printf("IO: Getting properties (catched): %ld bps; %d bits/byte; %s parity; %d stopbits; dtr=%d; rts=%d\n", props->input_bitrate, props->bits, props->parity == IO_SERIAL_PARITY_EVEN ? "Even" : props->parity == IO_SERIAL_PARITY_ODD ? "Odd" : "None", props->stopbits, props->dtr, props->rts);
1053#endif
1054#endif
1055 return TRUE;
1056 }
1057
1058 return FALSE;
1059}
1060
1061static void IO_Serial_ClearPropertiesCache (IO_Serial * io)
1062{
1063#ifdef DEBUG_IO
1064 printf ("IO: Clearing properties cache\n");
1065#endif
1066 if (io->props != NULL)
1067 {
1068 free (io->props);
1069 io->props = NULL;
1070 }
1071}
1072
1073static void IO_Serial_DeviceName (unsigned com, bool usbserial, char * filename, unsigned length)
1074{
1075 extern char oscam_device[];
1076 snprintf (filename, length, "%s", oscam_device);
1077// if(com==1)
1078// snprintf (filename, length, "/dev/tts/%d", com - 1);
1079// else
1080// snprintf (filename, length, "/dev/sci%d", com - 2);
1081}
1082
1083static bool IO_Serial_InitPnP (IO_Serial * io)
1084{
1085 IO_Serial_Properties props;
1086 int i = 0;
1087 props.input_bitrate = 1200;
1088 props.output_bitrate = 1200;
1089 props.parity = IO_SERIAL_PARITY_NONE;
1090 props.bits = 7;
1091 props.stopbits = 1;
1092 props.dtr = IO_SERIAL_HIGH;
1093// props.rts = IO_SERIAL_HIGH;
1094 props.rts = IO_SERIAL_LOW;
1095
1096 if (!IO_Serial_SetProperties (io, &props))
1097 return FALSE;
1098
1099 while ((i < IO_SERIAL_PNPID_SIZE) && IO_Serial_Read (io, 200, 1, &(io->PnP_id[i])))
1100 i++;
1101
1102 io->PnP_id_size = i;
1103 return TRUE;
1104}
Note: See TracBrowser for help on using the repository browser.