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.