source: trunk/module-serial.c @ 5375

Last change on this file since 5375 was 5310, checked in by Admin, 8 years ago

Replace i2b with i2b_buf. cl->dump is now only used in cs_hexdump function...

File size: 32.6 KB
Line 
1#include "globals.h"
2#include <termios.h>
3
4#define HSIC_CRC 0xA5
5#define SSSP_MAX_PID 8
6
7#define P_HSIC      1   // Humax Sharing Interface Client
8#define P_SSSP      2   // Simple Serial Sharing Protocol
9#define P_BOMBA     3   // This is not really a Protocol
10#define P_DSR95     4   // DSR9500 with SID
11#define P_GS        5   // GS7001
12#define P_ALPHA     6   // AlphaStar Receivers
13#define P_DSR95_OLD 7   // DSR9500 without SID
14#define P_GBOX      8   // Arion with gbox
15#define P_MAX       P_GBOX
16#define P_AUTO      0xFF
17
18#define P_DSR_AUTO    0
19#define P_DSR_GNUSMAS 1
20#define P_DSR_OPEN    2
21#define P_DSR_PIONEER 3
22#define P_DSR_WITHSID 4
23#define P_DSR_UNKNOWN 5
24
25#define IS_ECM  0   // incoming data is ECM
26#define IS_DCW  1   // incoming data is DCW
27#define IS_PMT  2   // incoming data is PMT
28#define IS_LGO  3   // incoming data is client logon
29#define IS_ECHO 4   // incoming data is DCW echo from Samsung
30#define IS_CAT  5   // incoming data is CAT
31#define IS_BAD  0xFF    // incoming data is unknown
32
33static const char * const proto_txt[]={"unknown", "hsic", "sssp", "bomba", "dsr9500", "gs",
34                          "alpha", "dsr9500old", "gbox"};
35static const char * const dsrproto_txt[]={"unknown", "samsung", "openbox", "pioneer",
36                             "extended", "unknown"};
37static const char * const incomplete="incomplete request (%d bytes)";
38
39typedef struct s_gbox
40{
41  int32_t cat_len;
42  int32_t pmt_len;
43  int32_t ecm_len;
44} GBOX_LENS;
45
46typedef struct s_sssp
47{
48  uint16_t caid;
49  uint16_t pid;
50  uint32_t  prid;
51} SSSP_TAB;
52
53//added to support multiple instances with thread
54struct s_serial_client
55{
56    int32_t connected;
57    struct timeb tps;
58    struct timeb tpe;
59    char oscam_ser_usr[32];
60    char oscam_ser_device[64];
61    speed_t oscam_ser_baud;
62    int32_t oscam_ser_delay;
63    int32_t oscam_ser_timeout;
64    int32_t oscam_ser_proto;
65    int32_t serial_errors;
66    int32_t dsr9500type;
67    int32_t samsung_0a;   // number of 0A in ALL dcw sent into samsung
68    int32_t samsung_dcw;  // number of dcw sent into samsung before echo or ecm is received
69
70    GBOX_LENS gbox_lens;
71    SSSP_TAB sssp_tab[SSSP_MAX_PID];
72    uint16_t sssp_srvid;
73    int32_t sssp_num;
74    int32_t sssp_fix;
75};
76
77pthread_mutex_t mutex;
78pthread_cond_t cond;
79int32_t bcopy_end = -1;
80
81struct s_thread_param
82{
83    int32_t ctyp;
84    struct s_serial_client serialdata;
85};
86
87static void oscam_ser_disconnect(void);
88
89static void oscam_wait_ser_fork(void)
90{
91    cs_lock(&mutex);
92    do {
93            if (bcopy_end) {
94              bcopy_end = 0;
95                break;
96            }
97            else
98                pthread_cond_wait(&cond, &mutex);
99    } while (1);
100    cs_unlock(&mutex);
101}
102
103static int32_t oscam_ser_alpha_convert(uchar *buf, int32_t l)
104{
105  int32_t i;
106  if (buf[0]==0x7E)     // normalize
107  {
108    l-=2;
109    memmove(buf, buf+1, l); // remove BOT/EOT
110    for (i=0; i<l; i++)
111      if (buf[i]==0x20)
112      {
113        memmove(buf+i, buf+i+1, --l);
114        buf[i]^=0x20;
115      }
116  }
117  else              // to alphastar
118  {
119    memmove(buf+1, buf, l++);   // insert BOT
120    buf[0]=0x7E;
121    for (i=1; i<l; i++)
122      if ((buf[i]==0x20) || (buf[i]==0x7E) || (buf[i]==0x7F))
123      {
124        buf[i]^=0x20;
125        memmove(buf+i+1, buf+i, l++);
126        buf[i++]=0x20;
127      }
128    buf[l++]=0x7F;      // insert EOT
129  }
130  return(l);
131}
132
133static void oscam_ser_disconnect(void);
134
135static int32_t oscam_ser_parse_url(char *url, struct s_serial_client *serialdata, char *pcltype)
136{
137  char *service, *usr, *dev, *baud=NULL, *dummy, *para;
138  char cltype;
139 
140    cltype = pcltype?(*pcltype):cur_client()->typ;
141
142  serialdata->oscam_ser_proto=P_AUTO;
143  if( (dummy=strstr(url, "://")) )
144  {
145    int32_t i;
146    service=url;
147    url=dummy+3;
148    *dummy=0;
149    for (i=1; i<=P_MAX; i++)
150      if (!strcmp(service, proto_txt[i]))
151        serialdata->oscam_ser_proto=i;
152  }
153  if (!(cltype == 'c') && (serialdata->oscam_ser_proto==P_AUTO)) return(0);
154  switch(serialdata->oscam_ser_proto)   // set the defaults
155  {
156    case P_GS:
157      serialdata->oscam_ser_timeout=500;
158      serialdata->oscam_ser_baud=B19200;
159      break;
160    default:
161      serialdata->oscam_ser_timeout=50;
162#ifdef B115200
163      serialdata->oscam_ser_baud=B115200;
164#else
165      serialdata->oscam_ser_baud=B9600;
166#endif
167  }
168
169  switch( serialdata->oscam_ser_proto )
170  {
171    case P_DSR95:
172      serialdata->dsr9500type=(cltype == 'c')?P_DSR_AUTO:P_DSR_WITHSID;
173      break;
174    case P_DSR95_OLD:
175      serialdata->dsr9500type=P_DSR_AUTO;
176      serialdata->oscam_ser_proto=P_DSR95;
177  }
178
179  usr=url;
180  if( (dev=strchr(usr, '@')) )
181  {
182    *dev++='\0';
183    if( (dummy=strchr(usr, ':')) )  // fake pwd
184      *dummy++='\0';
185    if ((cltype == 'c') && (!usr[0])) return(0);
186  }
187  else
188  {
189    if (cltype == 'c') return(0);   // user needed in server-mode
190    dev=usr;
191  }
192  if( (baud=strchr(dev, ':'))   )// port = baud
193    *baud++='\0';
194  dummy=baud ? baud : dev;
195  if( (para=strchr(dummy, '?')) )
196  {
197    char *ptr1, *ptr2, *saveptr1 = NULL;
198    *para++='\0';
199    for (ptr1=strtok_r(para, "&", &saveptr1); ptr1; ptr1=strtok_r(NULL, "&", &saveptr1))
200    {
201      if (!(ptr2=strchr(ptr1, '='))) continue;
202      *ptr2++='\0';
203      strtolower(ptr1);
204      if (!strcmp("delay"  , ptr1)) serialdata->oscam_ser_delay  =atoi(ptr2);
205      if (!strcmp("timeout", ptr1)) serialdata->oscam_ser_timeout=atoi(ptr2);
206    }
207  }
208  if (baud)
209  {
210    trim(baud);
211#ifdef B115200
212    if (!strcmp(baud, "115200"))
213      serialdata->oscam_ser_baud=B115200;
214    else
215#endif
216#ifdef B57600
217    if (!strcmp(baud, "57600"))
218      serialdata->oscam_ser_baud=B57600;
219    else
220#endif
221    if (!strcmp(baud, "38400"))
222      serialdata->oscam_ser_baud=B38400;
223    else if (!strcmp(baud, "19200"))
224      serialdata->oscam_ser_baud=B19200;
225    else if (!strcmp(baud, "9600"))
226      serialdata->oscam_ser_baud=B9600;
227  }
228  cs_strncpy(serialdata->oscam_ser_usr, usr, sizeof(serialdata->oscam_ser_usr));
229  cs_strncpy(serialdata->oscam_ser_device, dev, sizeof(serialdata->oscam_ser_device));
230  return(serialdata->oscam_ser_baud);
231}
232
233static void oscam_ser_set_baud(struct termios *tio, speed_t baud)
234{
235  cfsetospeed(tio, baud);
236  cfsetispeed(tio, baud);
237}
238
239static int32_t oscam_ser_set_serial_device(int32_t fd, speed_t baud)
240{
241  struct termios tio;
242
243  memset(&tio, 0, sizeof(tio));
244  //  tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
245  tio.c_cflag = (CS8 | CREAD | CLOCAL);
246  tio.c_iflag = IGNPAR;
247  tio.c_cc[VMIN] = 1;
248  tio.c_cc[VTIME] = 0;
249//#if !defined(OS_CYGWIN32)
250  oscam_ser_set_baud(&tio, B1200);
251  tcsetattr(fd, TCSANOW, &tio);
252  cs_sleepms(500);
253//#endif
254  oscam_ser_set_baud(&tio, baud);
255  return(tcsetattr(fd, TCSANOW, &tio));
256}
257
258static int32_t oscam_ser_poll(int32_t event, struct s_client *client)
259{
260  int32_t msec;
261  struct pollfd pfds;
262  struct timeb tpc;
263  cs_ftime(&tpc);
264  msec=1000*(client->serialdata->tpe.time-tpc.time)+client->serialdata->tpe.millitm-tpc.millitm;
265  if (msec<0)
266    return(0);
267  pfds.fd=cur_client()->pfd;
268  pfds.events=event;
269  pfds.revents=0;
270  if (poll(&pfds, 1, msec)!=1)
271    return(0);
272  else
273    return(((pfds.revents)&event)==event);
274}
275
276static int32_t oscam_ser_write(struct s_client *client, const uchar * const buf, int32_t n)
277{
278  int32_t i;
279  for (i=0; (i<n) && (oscam_ser_poll(POLLOUT, client)); i++)
280  {
281    if (client->serialdata->oscam_ser_delay)
282      cs_sleepms(client->serialdata->oscam_ser_delay);
283    if (write(client->pfd, buf+i, 1)<1)
284      break;
285  }
286  return(i);
287}
288
289static int32_t oscam_ser_send(struct s_client *client, const uchar * const buf, int32_t l)
290{
291  int32_t n;
292  struct s_serial_client *serialdata=client->serialdata ;
293  if (!client->pfd) return(0);
294  cs_ftime(&serialdata->tps);
295  serialdata->tpe=client->serialdata->tps;
296  serialdata->tpe.millitm+=serialdata->oscam_ser_timeout+(l*(serialdata->oscam_ser_delay+1));
297  serialdata->tpe.time+=(serialdata->tpe.millitm/1000);
298  serialdata->tpe.millitm%=1000;
299  n=oscam_ser_write(client, buf, l);
300  cs_ftime(&serialdata->tpe);
301  cs_ddump_mask(D_CLIENT, buf, l, "send %d of %d bytes to %s in %d msec", n, l, remote_txt(),
302                    1000*(serialdata->tpe.time-serialdata->tps.time)+serialdata->tpe.millitm-serialdata->tps.millitm);
303  if (n!=l)
304    cs_log("transmit error. send %d of %d bytes only !", n, l);
305  return(n);
306}
307
308static int32_t oscam_ser_selrec(uchar *buf, int32_t n, int32_t l, int32_t *c)
309{
310  int32_t i;
311  if (*c+n>l)
312    n=l-*c;
313  if (n<=0) return(0);
314  for (i=0; (i<n) && (oscam_ser_poll(POLLIN, cur_client())); i++)
315    if (read(cur_client()->pfd, buf+*c, 1)<1 )
316      return(0);
317    else
318      (*c)++;
319  return(i==n);
320}
321
322static int32_t oscam_ser_recv(struct s_client *client, uchar *xbuf, int32_t l)
323{
324  int32_t s, p, n, r;
325  uchar job=IS_BAD;
326  static uchar lb;
327  static int32_t have_lb=0;
328  uchar *buf=xbuf+1;
329  struct s_serial_client *serialdata=client->serialdata;
330
331  if (!client->pfd) return(-1);
332  cs_ftime(&serialdata->tps);
333  serialdata->tpe=serialdata->tps;
334  serialdata->tpe.millitm+=serialdata->oscam_ser_timeout;
335  serialdata->tpe.time+=(serialdata->tpe.millitm/1000);
336  serialdata->tpe.millitm%=1000;
337  buf[0]=lb;
338  for (s=p=r=0, n=have_lb; (s<4) && (p>=0); s++)
339  {
340    switch(s)
341    {
342      case 0:       // STAGE 0: skip known garbage from DSR9500
343        if (oscam_ser_selrec(buf, 2-n, l, &n))
344        {
345          if ((buf[0]==0x0A) && (buf[1]==0x0D))
346            p=(-4);
347          if ((buf[0]==0x0D) && (buf[1]==0x0A))
348            p=(-4);
349        }
350        else
351          p=(-3);
352        have_lb=0;
353        break;
354      case 1:       // STAGE 1: identify protocol
355        p=(-3);
356        if (oscam_ser_selrec(buf, 1, l, &n)) // now we have 3 bytes in buf
357        {
358          p=(-2);
359          if (client->typ == 'c')        // HERE IS SERVER
360          {
361            job=IS_ECM;     // assume ECM
362            switch(buf[0])
363            {
364              case 0x00: if( (buf[1]==0x01)&&(buf[2]==0x00) )
365                           { p=P_GS; job=IS_LGO; serialdata->tpe.time++; } break;
366              case 0x01: if( (buf[1]&0xf0)==0xb0 ) p=P_GBOX;
367                         else  {p=P_SSSP; job=IS_PMT;}
368                         break; // pmt-request
369              case 0x02: p=P_HSIC; break;
370              case 0x03: switch(serialdata->oscam_ser_proto)
371                         {
372                           case P_SSSP  :
373                           case P_GS    :
374                           case P_DSR95 : p=serialdata->oscam_ser_proto; break;
375                           case P_AUTO  : p=(buf[1]<0x30) ? P_SSSP : P_DSR95;
376                                          break;    // auto for GS is useless !!
377                         } break;
378              case 0x04: p=P_DSR95; job=IS_ECHO; serialdata->dsr9500type=P_DSR_GNUSMAS; break;
379              case 0x7E: p=P_ALPHA; if (buf[1]!=0x80) job=IS_BAD; break;
380              case 0x80:
381              case 0x81: p=P_BOMBA; break;
382            }
383          }
384          else              // HERE IS CLIENT
385          {
386            job=IS_DCW;     // assume DCW
387            switch(serialdata->oscam_ser_proto)
388            {
389              case P_HSIC : if ((buf[0]==4) && (buf[1]==4)) p=P_HSIC; break;
390              case P_BOMBA: p=P_BOMBA; break;
391              case P_DSR95: if (buf[0]==4) p=P_DSR95; break;
392              case P_ALPHA: if (buf[0]==0x88) p=P_ALPHA; break;
393            }
394          }
395          if ((serialdata->oscam_ser_proto!=p) && (serialdata->oscam_ser_proto!=P_AUTO))
396            p=(-2);
397        }
398        break;
399      case 2:       // STAGE 2: examine length
400        if (client->typ == 'c') switch(p)
401        {
402          case P_SSSP  : r=(buf[1]<<8)|buf[2]; break;
403          case P_BOMBA : r=buf[2]; break;
404          case P_HSIC  : if (oscam_ser_selrec(buf, 12, l, &n)) r=buf[14];
405                         else p=(-1);
406                         break;
407          case P_DSR95 : if( job==IS_ECHO )
408                         {
409                           r=17*serialdata->samsung_dcw-3+serialdata->samsung_0a;
410                           serialdata->samsung_dcw=serialdata->samsung_0a=0;
411                         }
412                         else
413                         {
414                           if (oscam_ser_selrec(buf, 16, l, &n))
415                           {
416                             uchar b;
417                             if (cs_atob(&b, (char *)buf+17, 1)<0)
418                               p=(-2);
419                             else {
420                               r=(b<<1);
421                               r+=(serialdata->dsr9500type==P_DSR_WITHSID)?4:0;
422                             }
423                           }
424                           else p=(-1);
425                         }
426                         break;
427          case P_GS    : if (job==IS_LGO)
428                           r=5;
429                         else
430                         {
431                           if (oscam_ser_selrec(buf, 1, l, &n))
432                             r=(buf[3]<<8)|buf[2];
433                           else p=(-1);
434                         }
435                         break;
436          case P_ALPHA : r=-0x7F;   // char specifying EOT
437                         break;
438          case P_GBOX  : r=((buf[1]&0xf)<<8) | buf[2];
439                         serialdata->gbox_lens.cat_len = r;
440                         break;
441          default      : serialdata->dsr9500type=P_DSR_AUTO;
442        }
443        else switch(p)
444        {
445          case P_HSIC   : r=(buf[2]==0x3A) ? 20 : 0; break; // 3A=DCW / FC=ECM was wrong
446          case P_BOMBA  : r=13; break;
447          case P_DSR95  : r=14; break;
448          case P_ALPHA  : r=(buf[1]<<8)|buf[2]; break;  // should be 16 always
449        }
450        break;
451      case 3:       // STAGE 3: get the rest ...
452        if (r>0)    // read r additional bytes
453        {
454          int32_t all = n+r;
455          if( !oscam_ser_selrec(buf, r, l, &n) )
456          {
457            cs_debug_mask(D_CLIENT, "not all data received, waiting another 50 ms");
458            serialdata->tpe.millitm+=50;
459            if( !oscam_ser_selrec(buf, all-n, l, &n) )
460              p=(-1);
461          }
462          // auto detect DSR9500 protocol
463          if( client->typ == 'c' && p==P_DSR95 && serialdata->dsr9500type==P_DSR_AUTO )
464          {
465            serialdata->tpe.millitm+=20;
466            if( oscam_ser_selrec(buf, 2, l, &n) ) 
467            {
468              if( cs_atoi((char *)buf+n-2, 1, 1)==0xFFFFFFFF )
469              {
470                switch( (buf[n-2]<<8)|buf[n-1] )
471                {
472                  case 0x0A0D : serialdata->dsr9500type=P_DSR_OPEN; break;
473                  case 0x0D0A : serialdata->dsr9500type=P_DSR_PIONEER; break;
474                  default     : serialdata->dsr9500type=P_DSR_UNKNOWN; break;
475                }
476              }else{
477                if( oscam_ser_selrec(buf, 2, l, &n) )
478                  if( cs_atoi((char *)buf+n-2, 1, 1)==0xFFFFFFFF )
479                    serialdata->dsr9500type=P_DSR_UNKNOWN;
480                  else
481                    serialdata->dsr9500type=P_DSR_WITHSID;
482                else {
483                  serialdata->dsr9500type=P_DSR_UNKNOWN;
484                  p=(-1);
485                }
486              }
487            }
488            else 
489              serialdata->dsr9500type=P_DSR_GNUSMAS;
490            if( p )
491              cs_log("detected dsr9500-%s type receiver", 
492                      dsrproto_txt[serialdata->dsr9500type]);
493          } 
494          // gbox
495          if( client->typ == 'c' && p==P_GBOX )
496          {
497            int32_t j;
498            for( j=0; (j<3) && (p>0); j++)
499              switch( j )
500              {
501                case 0: // PMT head
502                  if( !oscam_ser_selrec(buf, 3, l, &n) )
503                    p=(-1);
504                  else if( !(buf[n-3]==0x02 && (buf[n-2]&0xf0)==0xb0) )
505                    p=(-2);
506                  break;
507                case 1: // PMT + ECM header
508                  serialdata->gbox_lens.pmt_len=((buf[n-2]&0xf)<<8)|buf[n-1];
509                  if( !oscam_ser_selrec(buf, serialdata->gbox_lens.pmt_len+3, l, &n) ) 
510                    p=(-1);
511                  break;
512                case 2: // ECM + ECM PID
513                  serialdata->gbox_lens.ecm_len=((buf[n-2]&0xf)<<8)|buf[n-1];
514                  if( !oscam_ser_selrec(buf, serialdata->gbox_lens.ecm_len+4, l, &n) ) 
515                    p=(-1);
516              }
517          } // gbox
518        }
519        else if (r<0)   // read until specified char (-r)
520        {
521          while((buf[n-1]!=(-r)) && (p>0))
522            if (!oscam_ser_selrec(buf, 1, l, &n))
523              p=(-1);
524        }
525        break;
526    }
527  }
528  if (p==(-2) || p==(-1)) {
529    oscam_ser_selrec(buf, l-n, l, &n);  // flush buffer
530    serialdata->serial_errors++;
531  }
532  cs_ftime(&serialdata->tpe);
533  cs_ddump_mask(D_CLIENT, buf, n, "received %d bytes from %s in %d msec", n, remote_txt(),
534                    1000*(serialdata->tpe.time-serialdata->tps.time)+serialdata->tpe.millitm-serialdata->tps.millitm);
535  client->last=serialdata->tpe.time;
536  switch(p)
537  {
538    case (-1): if (client->typ == 'c'&&(n>2)&&(buf[0]==2)&&(buf[1]==2)&&(buf[2]==2))
539               {
540                 oscam_ser_disconnect();
541                 cs_log("humax powered on");    // this is nice ;)
542               }
543               else
544                 cs_log(incomplete, n);
545               break;
546    case (-2): cs_debug_mask(D_CLIENT, "unknown request or garbage");
547               break;
548  }
549  xbuf[0]=(uchar) ((job<<4) | p);
550  return((p<0)?0:n+1);
551}
552
553/*
554 *  server functions
555 */
556
557static void oscam_ser_disconnect_client()
558{
559  uchar mbuf[1024];
560  struct s_serial_client *serialdata=cur_client()->serialdata;
561  switch(serialdata->connected ? serialdata->connected : serialdata->oscam_ser_proto)
562  {
563    case P_GS:
564      mbuf[0] = 0x01;
565      mbuf[1] = 0x00;
566      mbuf[2] = 0x00;
567      mbuf[3] = 0x00;
568      oscam_ser_send(cur_client(), mbuf, 4);
569      break;
570  }
571  serialdata->dsr9500type=P_DSR_AUTO;
572  serialdata->serial_errors=0;
573}
574
575static void oscam_ser_init_client()
576{
577  uchar mbuf[4];
578  switch(cur_client()->serialdata->oscam_ser_proto)     // sure, does not work in auto-mode
579  {
580    case P_GS:
581      oscam_ser_disconnect_client(); // send disconnect first
582      cs_sleepms(300);              // wait a little bit
583      mbuf[0] = 0x00;
584      mbuf[1] = 0x00;
585      mbuf[2] = 0x00;
586      mbuf[3] = 0x00;
587      oscam_ser_send(cur_client(), mbuf, 4);    // send connect
588      break;
589  }
590}
591
592static void oscam_ser_disconnect()
593{
594  oscam_ser_disconnect_client();
595  if (cur_client()->serialdata->connected)
596    cs_log("%s disconnected (%s)", username(cur_client()), proto_txt[cur_client()->serialdata->connected]);
597  cur_client()->serialdata->connected=0;
598}
599
600static void oscam_ser_auth_client(int32_t proto)
601{
602  int32_t ok = 0;
603  struct s_serial_client *serialdata=cur_client()->serialdata;
604  // After reload base account ptrs may be placed in other address,
605  // and we may can't find it in this process.
606  // Simply save valid account.
607  struct s_auth *account=0;
608
609  if (serialdata->connected==proto)
610    return;
611  if (serialdata->connected)
612    oscam_ser_disconnect();
613  serialdata->connected=proto;
614
615  for (ok=0, account=cfg.account; (account) && (!ok); account=account->next)
616    if( (ok=!strcmp(serialdata->oscam_ser_usr, account->usr)) )
617      break;
618  cs_auth_client(cur_client(), ok ? account : (struct s_auth *)(-1), proto_txt[serialdata->connected]);
619}
620
621static void oscam_ser_send_dcw(struct s_client *client, ECM_REQUEST *er)
622{
623  uchar mbuf[23];
624  int32_t i;
625  uchar crc;
626  struct s_serial_client *serialdata=cur_client()->serialdata;
627  if (er->rc<E_NOTFOUND)        // found
628    switch(serialdata->connected)
629    {
630      case P_HSIC:
631        for (i=0, crc=HSIC_CRC; i<16; i++)
632          crc^=er->cw[i];
633        memset(mbuf   , 0x04  ,  2);
634        memset(mbuf+2 , 0x3a  ,  2);
635        memcpy(mbuf+4 , er->cw, 16);
636        memcpy(mbuf+20, &crc  ,  1);
637        memset(mbuf+21, 0x1b  ,  2);
638        oscam_ser_send(client, mbuf, 23);
639        break;
640      case P_SSSP:
641        mbuf[0]=0xF2;
642        mbuf[1]=0;
643        mbuf[2]=16;
644        memcpy(mbuf+3, er->cw, 16);
645        oscam_ser_send(client, mbuf, 19);
646        if (!serialdata->sssp_fix)
647        {
648          mbuf[0]=0xF1;
649          mbuf[1]=0;
650          mbuf[2]=2;
651          i2b_buf(2, er->pid, mbuf + 3);
652          oscam_ser_send(client, mbuf, 5);
653          serialdata->sssp_fix=1;
654        }
655        break;
656      case P_GBOX:
657      case P_BOMBA:
658        oscam_ser_send(client, er->cw, 16);
659        break;
660      case P_DSR95:
661        mbuf[0]=4;
662        memcpy(mbuf+1, er->cw, 16);
663        oscam_ser_send(client, mbuf, 17);
664        if( serialdata->dsr9500type==P_DSR_GNUSMAS )
665        {
666          int32_t i;
667          serialdata->samsung_0a=0;
668          for( i=1; i<17; i++ )
669            if( mbuf[i]==0x0A )
670              serialdata->samsung_0a++;
671          serialdata->samsung_dcw++;
672        }
673        break;
674      case P_GS:
675        mbuf[0]=0x03;
676        mbuf[1]=0x08;
677        mbuf[2]=0x10;
678        mbuf[3]=0x00;
679        memcpy(mbuf+4, er->cw, 16);
680        oscam_ser_send(client, mbuf, 20);
681        break;
682      case P_ALPHA:
683        mbuf[0]=0x88;
684        mbuf[1]=0x00;
685        mbuf[2]=0x10;
686        memcpy(mbuf+3, er->cw, 16);
687        oscam_ser_send(client, mbuf, 19);
688        break;
689    }
690  else          // not found
691    switch(serialdata->connected)
692    {
693      case P_GS:
694        mbuf[0]=0x03;
695        mbuf[1]=0x09;
696        mbuf[2]=0x00;
697        mbuf[3]=0x00;
698        oscam_ser_send(client, mbuf, 4);
699        break;
700    }
701  serialdata->serial_errors=0; // clear error counter
702}
703
704static void oscam_ser_process_pmt(uchar *buf, int32_t l)
705{
706  int32_t i;
707  uchar sbuf[32];
708  struct s_serial_client *serialdata=cur_client()->serialdata;
709  switch(serialdata->connected)
710  {
711    case P_SSSP:
712      serialdata->sssp_fix=0;
713      memset(serialdata->sssp_tab, 0, sizeof(serialdata->sssp_tab));
714      serialdata->sssp_srvid=b2i(2, buf+3);
715      for (i=9, serialdata->sssp_num=0; (i<l) && (serialdata->sssp_num<SSSP_MAX_PID); i+=7, serialdata->sssp_num++)
716      {
717        memcpy(sbuf+3+(serialdata->sssp_num<<1), buf+i+2, 2);
718        serialdata->sssp_tab[serialdata->sssp_num].caid=b2i(2, buf+);
719        serialdata->sssp_tab[serialdata->sssp_num].pid =b2i(2, buf+i+2);
720        serialdata->sssp_tab[serialdata->sssp_num].prid=b2i(3, buf+i+4);
721      }
722      sbuf[0]=0xF1;
723      sbuf[1]=0;
724      sbuf[2]=(serialdata->sssp_num<<1);
725      oscam_ser_send(cur_client(), sbuf, sbuf[2]+3);
726      break;
727  }
728}
729
730static void oscam_ser_client_logon(uchar *buf, int32_t l)
731{
732  uchar gs_logon[]={0, 1, 0, 0, 2, 1, 0, 0};
733  switch(cur_client()->serialdata->connected)
734  {
735    case P_GS:
736      if ((l>=8) && (!memcmp(buf, gs_logon, 8)))
737      {
738        buf[0] = 0x02;
739        buf[1] = 0x04;
740        buf[2] = 0x00;
741        buf[3] = 0x00;
742        oscam_ser_send(cur_client(), buf, 4);
743      }
744      break;
745  }
746}
747
748static int32_t oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int32_t l)
749{
750  int32_t i;
751  struct s_serial_client *serialdata = cur_client()->serialdata;
752
753  if (l<16)
754  {
755    cs_log(incomplete, l);
756    return(1);
757  }
758
759  switch(serialdata->connected)
760  {
761    case P_HSIC:
762      er->l    = l-12;
763      er->caid = b2i(2, buf+1 );
764      er->prid = b2i(3, buf+3 );
765      er->pid  = b2i(2, buf+6 );
766      er->srvid= b2i(2, buf+10);
767      memcpy(er->ecm, buf+12, er->l);
768      break;
769    case P_SSSP:
770      er->pid=b2i(2, buf+3);
771      for (i=0; (i<8) && (serialdata->sssp_tab[i].pid!=er->pid); i++);
772      if (i>=serialdata->sssp_num)
773      {
774        cs_debug_mask(D_CLIENT, "illegal request, unknown pid=%04X", er->pid);
775        return(2);
776      }
777      er->l    = l-5;
778      er->srvid= serialdata->sssp_srvid;
779      er->caid = serialdata->sssp_tab[i].caid;
780      er->prid = serialdata->sssp_tab[i].prid;
781      memcpy(er->ecm, buf+5, er->l);
782      break;
783    case P_BOMBA:
784      er->l=l;
785      memcpy(er->ecm, buf, er->l);
786      break;
787    case P_DSR95:
788      buf[l]='\0';  // prepare for trim
789      trim((char *)buf+13); // strip spc, nl, cr ...
790      er->l=strlen((char *)buf+13)>>1;
791      er->prid=cs_atoi((char *)buf+3, 3, 0);    // ignore errors
792      er->caid=cs_atoi((char *)buf+9, 2, 0);    // ignore errors
793      if (cs_atob(er->ecm, (char *)buf+13, er->l)<0)
794      {
795        cs_log("illegal characters in ecm-request");
796        return(1);
797      }
798      if( serialdata->dsr9500type==P_DSR_WITHSID )
799      {
800        er->l-=2;
801        er->srvid=cs_atoi((char *)buf+13+(er->l<<1), 2, 0);
802      }
803      break;
804    case P_GS:
805      er->l     = ((buf[3]<<8)|buf[2]) - 6;
806      er->srvid =  (buf[5]<<8)|buf[4]; // sid
807      er->caid  =  (buf[7]<<8)|buf[6];
808      er->prid  = 0;
809      if (er->l>256) er->l=256;
810      memcpy(er->ecm, buf+10, er->l);
811      break;
812    case P_ALPHA:
813      l=oscam_ser_alpha_convert(buf, l);
814      er->l     = b2i(2, buf+1 )-2;
815      er->caid  = b2i(2, buf+3 );
816      if ((er->l!=l-5) || (er->l>257))
817      {
818        cs_log(incomplete, l);
819        return(1);
820      }
821      memcpy(er->ecm, buf+5, er->l);
822      break;
823    case P_GBOX:
824      er->srvid = b2i(2, buf+serialdata->gbox_lens.cat_len+3+3);
825      er->l = serialdata->gbox_lens.ecm_len+3;
826      memcpy(er->ecm, buf+serialdata->gbox_lens.cat_len+3+serialdata->gbox_lens.pmt_len+3, er->l);
827      break;
828  }
829  return(0);
830}
831
832static void oscam_ser_process_ecm(uchar *buf, int32_t l)
833{
834  ECM_REQUEST *er;
835
836  if (!(er=get_ecmtask()))
837    return;
838
839  switch(oscam_ser_check_ecm(er, buf, l))
840  {
841    case 2: er->rc=E_CORRUPT; return;   // error without log
842    case 1: er->rc=E_CORRUPT;             // error with log
843  }
844  get_cw(cur_client(), er);
845}
846
847
848static void oscam_ser_server()
849{
850  int32_t n;
851  uchar mbuf[1024];
852 
853  int32_t * pserial_errors = &cur_client()->serialdata->serial_errors;
854
855  cur_client()->serialdata->connected=0;
856  oscam_ser_init_client();
857
858  while ((n=process_input(mbuf, sizeof(mbuf), cfg.cmaxidle))>=0)
859  {
860    if ((*pserial_errors) > 3)
861    {
862      cs_log("too many errors, reiniting...");
863      break;
864    }
865    if (n>0)
866    {
867      oscam_ser_auth_client(mbuf[0] & 0xF);
868      switch (mbuf[0]>>4)
869      {
870        case IS_ECM:
871          oscam_ser_process_ecm(mbuf+1, n-1);
872          break;
873        case IS_PMT:
874          oscam_ser_process_pmt(mbuf+1, n-1);
875          break;
876        case IS_LGO:
877          oscam_ser_client_logon(mbuf+1, n-1);
878          break;
879      }
880    }
881  }
882  oscam_ser_disconnect();
883}
884
885static int32_t init_oscam_ser_device(char *device, speed_t baud)
886{
887  int32_t fd;
888
889  fd=open(device, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
890  if (fd>0)
891  {
892    fcntl(fd, F_SETFL, 0);
893    if (oscam_ser_set_serial_device(fd, baud)<0) cs_log("ERROR ioctl");
894    if (tcflush(fd, TCIOFLUSH)<0) cs_log("ERROR flush");
895  }
896  else
897  {
898    fd=0;
899    cs_log("ERROR opening %s", device);
900  }
901  return(fd);
902}
903
904static void oscam_copy_serialdata(struct s_serial_client *dest, struct s_serial_client *src)
905{
906  if( dest &&  src )
907  {
908    dest->connected = src->connected;
909    memcpy(&dest->tps, &src->tps, sizeof(dest->tps));
910    memcpy(&dest->tpe, &src->tpe, sizeof(dest->tpe));
911    memcpy(&dest->oscam_ser_usr, &src->oscam_ser_usr, sizeof(dest->oscam_ser_usr));
912    memcpy(&dest->oscam_ser_device, &src->oscam_ser_device, sizeof(dest->oscam_ser_device));
913    dest->oscam_ser_baud = src->oscam_ser_baud;
914    dest->oscam_ser_delay = src->oscam_ser_delay;
915    dest->oscam_ser_timeout = src->oscam_ser_timeout;
916    dest->oscam_ser_proto = src->oscam_ser_proto;
917    dest->serial_errors = src->serial_errors;
918    dest->dsr9500type = src->dsr9500type;
919    dest->samsung_0a = src->samsung_0a;   // number of 0A in ALL dcw sent into samsung
920    dest->samsung_dcw = src->samsung_dcw;  // number of dcw sent into samsung before echo or ecm is received
921
922    dest->gbox_lens = src->gbox_lens;
923    memcpy(&dest->sssp_tab, &src->sssp_tab, sizeof(dest->sssp_tab));
924    dest->sssp_srvid = src->sssp_srvid;
925    dest->sssp_num = src->sssp_num;
926    dest->sssp_fix = src->sssp_fix;
927  }
928}
929
930static void oscam_init_serialdata(struct s_serial_client *dest)
931{
932  if(dest)
933  {
934    memset(dest, 0, sizeof(struct s_serial_client));
935    dest->oscam_ser_timeout = 50;
936    dest->dsr9500type=P_DSR_AUTO;
937  }
938}
939
940static void * oscam_ser_fork(void *pthreadparam)
941{
942  struct s_thread_param *pparam = (struct s_thread_param *) pthreadparam;
943  struct s_client *cl=create_client(0);
944  pthread_setspecific(getclient, cl);
945  cl->thread=pthread_self();
946  cl->typ='c'; 
947  cl->ctyp = pparam->ctyp;
948  cl->account=first_client->account;
949
950  if(!cl->serialdata){
951    if(!cs_malloc(&cl->serialdata,sizeof(struct s_serial_client), -1)) return NULL;
952  }
953  oscam_init_serialdata(cl->serialdata); 
954  oscam_copy_serialdata(cl->serialdata, &pparam->serialdata);
955  cs_log("serial: initialized (%s@%s)", cl->serialdata->oscam_ser_proto>P_MAX ? 
956         "auto" : proto_txt[cl->serialdata->oscam_ser_proto], cl->serialdata->oscam_ser_device);
957
958  cs_lock(&mutex);
959  bcopy_end = 1;
960  cs_unlock(&mutex);
961  pthread_cond_signal(&cond);
962
963  while(1)
964  {
965    cl->login=time((time_t *)0);
966    cl->pfd=init_oscam_ser_device(cl->serialdata->oscam_ser_device, cl->serialdata->oscam_ser_baud);
967    if (cl->pfd)
968      oscam_ser_server();
969    else
970      cs_sleepms(60000);    // retry in 1 min. (USB-Device ?)
971    if (cl->pfd) close(cl->pfd);
972  }
973  NULLFREE(cl->serialdata);
974  return NULL;
975}
976
977void * init_oscam_ser(int32_t ctyp)
978{
979    char sdevice[512];
980    struct s_thread_param param;
981    oscam_init_serialdata(&param.serialdata);
982    cs_strncpy(sdevice, cfg.ser_device, sizeof(sdevice));
983    param.ctyp=ctyp;
984    char *p;
985    pthread_t temp;
986    char cltype = 'c'; //now auto should work
987    if(bcopy_end == -1){ //mutex should be initialized only once
988        pthread_mutex_init(&mutex,NULL);
989        pthread_cond_init(&cond,NULL);
990        bcopy_end = 0;
991    }
992    while( (p=strrchr(sdevice, ';')) )
993    {
994        *p = 0;
995        if (!(p + 1) || (!(p + 1)[0])) return NULL;
996        if (!oscam_ser_parse_url(p + 1, &param.serialdata, &cltype)) return NULL;
997        pthread_create(&temp, NULL, oscam_ser_fork, (void *) &param);
998            oscam_wait_ser_fork();
999        pthread_detach(temp);
1000    }
1001
1002    if (!sdevice[0]) return NULL;
1003    if (!oscam_ser_parse_url(sdevice, &param.serialdata, &cltype)) return NULL;
1004    pthread_create(&temp, NULL, oscam_ser_fork, (void *) &param);
1005    oscam_wait_ser_fork();
1006    pthread_detach(temp); 
1007    return NULL;
1008}
1009
1010/*
1011 *  client functions
1012 */
1013
1014static int32_t oscam_ser_client_init(struct s_client *client)
1015{
1016  if(!client->serialdata){
1017    if(!cs_malloc(&client->serialdata,sizeof(struct s_serial_client), -1)) return 1;
1018  }
1019  oscam_init_serialdata(client->serialdata);
1020 
1021  if ((!client->reader->device[0])) cs_exit(1);
1022  if (!oscam_ser_parse_url(client->reader->device, client->serialdata, NULL)) cs_exit(1);
1023  client->pfd=init_oscam_ser_device(client->serialdata->oscam_ser_device, client->serialdata->oscam_ser_baud);
1024  return((client->pfd>0) ? 0 : 1);
1025}
1026
1027static int32_t oscam_ser_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
1028{
1029  switch(client->serialdata->oscam_ser_proto)
1030  {
1031    case P_HSIC:
1032      memset(buf, 0, 12);
1033      buf[0]=2;
1034      i2b_buf(2, er->caid, buf + 1);
1035      i2b_buf(3, er->prid, buf + 3);
1036      i2b_buf(2, er->pid, buf + 6);
1037      i2b_buf(2, er->srvid, buf + 10);
1038      memcpy(buf+12, er->ecm, er->l);
1039      oscam_ser_send(client, buf, 12+er->l);
1040      break;
1041    case P_BOMBA:
1042      oscam_ser_send(client, er->ecm, er->l);
1043      break;
1044    case P_DSR95:
1045      if( client->serialdata->dsr9500type==P_DSR_WITHSID )
1046      {
1047        snprintf((char *)buf, 512, "%c%08X%04X%s%04X\n\r",
1048          3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->l), er->srvid);
1049        oscam_ser_send(client, buf, (er->l<<1)+19); // 1 + 8 + 4 + l*2 + 4 + 2
1050      }
1051      else
1052      {
1053        snprintf((char *)buf, 512, "%c%08X%04X%s\n\r",
1054          3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->l));
1055        oscam_ser_send(client, buf, (er->l<<1)+15); // 1 + 8 + 4 + l*2 + 2
1056      }
1057      break;
1058    case P_ALPHA:
1059      buf[0]=0x80;
1060      i2b_buf(2, 2+er->l, buf + 1);
1061      i2b_buf(2, er->caid, buf + 3);
1062      memcpy(buf+5, er->ecm, er->l);
1063      oscam_ser_send(client, buf, oscam_ser_alpha_convert(buf, 5+er->l));
1064      break;
1065  }
1066  return(0);
1067}
1068
1069static void oscam_ser_process_dcw(uchar *dcw, int32_t *rc, uchar *buf, int32_t l, struct s_client *client)
1070{
1071  switch(client->serialdata->oscam_ser_proto)
1072  {
1073    case P_HSIC:
1074      if ((l>=23) && (buf[2]==0x3A) && (buf[3]==0x3A))
1075      {
1076        int32_t i;
1077        uchar crc;
1078        for (i=4, crc=HSIC_CRC; i<20; i++)
1079          crc^=buf[i];
1080        if (crc==buf[20])
1081        {
1082          memcpy(dcw, buf+4, 16);
1083          *rc=1;
1084        }
1085      }
1086      break;
1087    case P_BOMBA:
1088      if (l>=16)
1089      {
1090        memcpy(dcw, buf, 16);
1091        *rc=1;
1092      }
1093      break;
1094    case P_DSR95:
1095      if ((l>=17) && (buf[0]==4))
1096      {
1097        memcpy(dcw, buf+1, 16);
1098        *rc=1;
1099      }
1100      break;
1101    case P_ALPHA:
1102      if ((l>=19) && (buf[0]==0x88))
1103      {
1104        memcpy(dcw, buf+3, 16);
1105        *rc=1;
1106      }
1107      break;
1108  }
1109}
1110
1111static int32_t oscam_ser_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n)
1112{
1113  *rc=(-1);
1114  switch (buf[0]>>4)
1115  {
1116    case IS_DCW:
1117      oscam_ser_process_dcw(dcw, rc, buf+1, n-1, client);
1118      break;
1119  }
1120  return((*rc<0) ? (-1) : 0);   // idx not supported in serial module
1121}
1122
1123/*
1124 *  protocol structure
1125 */
1126
1127void module_oscam_ser(struct s_module *ph)
1128{
1129  cs_strncpy(ph->desc, "serial", sizeof(ph->desc));
1130  ph->type=MOD_CONN_SERIAL;
1131  ph->multi=1;
1132  ph->watchdog=0;
1133  ph->s_handler=init_oscam_ser;
1134  ph->recv=oscam_ser_recv;
1135  ph->send_dcw=oscam_ser_send_dcw;
1136  ph->c_multi=0;
1137  ph->c_init=oscam_ser_client_init;
1138  ph->c_recv_chk=oscam_ser_recv_chk;
1139  ph->c_send_ecm=oscam_ser_send_ecm;
1140  ph->num=R_SERIAL;
1141}
Note: See TracBrowser for help on using the repository browser.