Timeout patch
[oscam.git] / module-serial.c
blob7cc557fb2fae6363266d1b912347402e6d0e98a7
1 #include "globals.h"
2 #include <termios.h>
4 #define HSIC_CRC 0xA5
5 #define SSSP_MAX_PID 8
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
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
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
33 static char *proto_txt[]={"unknown", "hsic", "sssp", "bomba", "dsr9500", "gs",
34 "alpha", "dsr9500old", "gbox"};
35 static char *dsrproto_txt[]={"unknown", "samsung", "openbox", "pioneer",
36 "extended", "unknown"};
37 static char *incomplete="incomplete request (%d bytes)";
38 static int connected=0;
39 static struct timeb tps, tpe;
40 static char oscam_ser_usr[32]={0};
41 static char oscam_ser_device[64]={0};
42 static speed_t oscam_ser_baud=0;
43 static int oscam_ser_delay=0;
44 static int oscam_ser_timeout=50;
45 static int oscam_ser_proto=0;
46 int serial_errors=0;
47 static int dsr9500type=P_DSR_AUTO;
48 static int samsung_0a=0; // number of 0A in ALL dcw sent into samsung
49 static int samsung_dcw=0; // number of dcw sent into samsung before echo or ecm is received
51 typedef struct s_gbox
53 int cat_len;
54 int pmt_len;
55 int ecm_len;
56 } GBOX_LENS;
58 typedef struct s_sssp
60 ushort caid;
61 ushort pid;
62 ulong prid;
63 } SSSP_TAB;
66 GBOX_LENS gbox_lens;
67 SSSP_TAB sssp_tab[SSSP_MAX_PID];
68 ushort sssp_srvid;
69 int sssp_num=0, sssp_fix=0;
71 static int oscam_ser_alpha_convert(uchar *buf, int l)
73 int i;
74 if (buf[0]==0x7E) // normalize
76 l-=2;
77 memmove(buf, buf+1, l); // remove BOT/EOT
78 for (i=0; i<l; i++)
79 if (buf[i]==0x20)
81 memmove(buf+i, buf+i+1, --l);
82 buf[i]^=0x20;
85 else // to alphastar
87 memmove(buf+1, buf, l++); // insert BOT
88 buf[0]=0x7E;
89 for (i=1; i<l; i++)
90 if ((buf[i]==0x20) || (buf[i]==0x7E) || (buf[i]==0x7F))
92 buf[i]^=0x20;
93 memmove(buf+i+1, buf+i, l++);
94 buf[i++]=0x20;
96 buf[l++]=0x7F; // insert EOT
98 return(l);
101 static void oscam_ser_disconnect(void);
103 static int oscam_ser_parse_url(char *url)
105 char *service, *usr, *dev, *baud=NULL, *dummy, *para;
107 oscam_ser_proto=P_AUTO;
108 if( (dummy=strstr(url, "://")) )
110 int i;
111 service=url;
112 url=dummy+3;
113 *dummy=0;
114 for (i=1; i<=P_MAX; i++)
115 if (!strcmp(service, proto_txt[i]))
116 oscam_ser_proto=i;
118 if ((!is_server) && (oscam_ser_proto==P_AUTO)) return(0);
119 switch(oscam_ser_proto) // set the defaults
121 case P_GS:
122 oscam_ser_timeout=500;
123 oscam_ser_baud=B19200;
124 break;
125 default:
126 oscam_ser_timeout=50;
127 #ifdef B115200
128 oscam_ser_baud=B115200;
129 #else
130 oscam_ser_baud=B9600;
131 #endif
134 switch( oscam_ser_proto )
136 case P_DSR95:
137 dsr9500type=(is_server)?P_DSR_AUTO:P_DSR_WITHSID;
138 break;
139 case P_DSR95_OLD:
140 dsr9500type=P_DSR_AUTO;
141 oscam_ser_proto=P_DSR95;
144 usr=url;
145 if( (dev=strchr(usr, '@')) )
147 *dev++='\0';
148 if( (dummy=strchr(usr, ':')) ) // fake pwd
149 *dummy++='\0';
150 if ((is_server) && (!usr[0])) return(0);
152 else
154 if (is_server) return(0); // user needed in server-mode
155 dev=usr;
157 if( (baud=strchr(dev, ':')) )// port = baud
158 *baud++='\0';
159 dummy=baud ? baud : dev;
160 if( (para=strchr(dummy, '?')) )
162 char *ptr1, *ptr2;
163 *para++='\0';
164 for (ptr1=strtok(para, "&"); ptr1; ptr1=strtok(NULL, "&"))
166 if (!(ptr2=strchr(ptr1, '='))) continue;
167 *ptr2++='\0';
168 strtolower(ptr1);
169 if (!strcmp("delay" , ptr1)) oscam_ser_delay =atoi(ptr2);
170 if (!strcmp("timeout", ptr1)) oscam_ser_timeout=atoi(ptr2);
173 if (baud)
175 trim(baud);
176 #ifdef B115200
177 if (!strcmp(baud, "115200"))
178 oscam_ser_baud=B115200;
179 else
180 #endif
181 #ifdef B57600
182 if (!strcmp(baud, "57600"))
183 oscam_ser_baud=B57600;
184 else
185 #endif
186 if (!strcmp(baud, "38400"))
187 oscam_ser_baud=B38400;
188 else if (!strcmp(baud, "19200"))
189 oscam_ser_baud=B19200;
190 else if (!strcmp(baud, "9600"))
191 oscam_ser_baud=B9600;
193 strncpy(oscam_ser_usr, usr, sizeof(oscam_ser_usr)-1);
194 strncpy(oscam_ser_device, dev, sizeof(oscam_ser_device)-1);
195 return(oscam_ser_baud);
198 static void oscam_ser_set_baud(struct termios *tio, speed_t baud)
200 cfsetospeed(tio, baud);
201 cfsetispeed(tio, baud);
204 static int oscam_ser_set_serial_device(int fd)
206 struct termios tio;
208 memset(&tio, 0, sizeof(tio));
209 // tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
210 tio.c_cflag = (CS8 | CREAD | CLOCAL);
211 tio.c_iflag = IGNPAR;
212 tio.c_cc[VMIN] = 1;
213 tio.c_cc[VTIME] = 0;
214 //#if !defined(OS_CYGWIN32)
215 oscam_ser_set_baud(&tio, B1200);
216 tcsetattr(fd, TCSANOW, &tio);
217 cs_sleepms(500);
218 //#endif
219 oscam_ser_set_baud(&tio, oscam_ser_baud);
220 return(tcsetattr(fd, TCSANOW, &tio));
223 static int oscam_ser_poll(int event)
225 int msec;
226 struct pollfd pfds;
227 struct timeb tpc;
228 cs_ftime(&tpc);
229 msec=1000*(tpe.time-tpc.time)+tpe.millitm-tpc.millitm;
230 if (msec<0)
231 return(0);
232 pfds.fd=pfd;
233 pfds.events=event;
234 pfds.revents=0;
235 if (poll(&pfds, 1, msec)!=1)
236 return(0);
237 else
238 return(((pfds.revents)&event)==event);
241 static int oscam_ser_write(uchar *buf, int n)
243 int i;
244 for (i=0; (i<n) && (oscam_ser_poll(POLLOUT)); i++)
246 if (oscam_ser_delay)
247 cs_sleepms(oscam_ser_delay);
248 if (write(pfd, buf+i, 1)<1)
249 break;
251 return(i);
254 static int oscam_ser_send(uchar *buf, int l)
256 int n;
257 if (!pfd) return(0);
258 cs_ftime(&tps);
259 tpe=tps;
260 tpe.millitm+=oscam_ser_timeout+(l*(oscam_ser_delay+1));
261 tpe.time+=(tpe.millitm/1000);
262 tpe.millitm%=1000;
263 n=oscam_ser_write(buf, l);
264 cs_ftime(&tpe);
265 cs_ddump(buf, l, "send %d of %d bytes to %s in %d msec", n, l, remote_txt(),
266 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm);
267 if (n!=l)
268 cs_log("transmit error. send %d of %d bytes only !", n, l);
269 return(n);
272 static int oscam_ser_selrec(uchar *buf, int n, int l, int *c)
274 int i;
275 if (*c+n>l)
276 n=l-*c;
277 if (n<=0) return(0);
278 for (i=0; (i<n) && (oscam_ser_poll(POLLIN)); i++)
279 if (read(pfd, buf+*c, 1)<1 )
280 return(0);
281 else
282 (*c)++;
283 return(i==n);
286 static int oscam_ser_recv(uchar *xbuf, int l)
288 int s, p, n, r;
289 uchar job=IS_BAD;
290 static uchar lb;
291 static int have_lb=0;
292 uchar *buf=xbuf+1;
294 if (!pfd) return(-1);
295 cs_ftime(&tps);
296 tpe=tps;
297 tpe.millitm+=oscam_ser_timeout;
298 tpe.time+=(tpe.millitm/1000);
299 tpe.millitm%=1000;
300 buf[0]=lb;
301 for (s=p=r=0, n=have_lb; (s<4) && (p>=0); s++)
303 switch(s)
305 case 0: // STAGE 0: skip known garbage from DSR9500
306 if (oscam_ser_selrec(buf, 2-n, l, &n))
308 if ((buf[0]==0x0A) && (buf[1]==0x0D))
309 p=(-4);
310 if ((buf[0]==0x0D) && (buf[1]==0x0A))
311 p=(-4);
313 else
314 p=(-3);
315 have_lb=0;
316 break;
317 case 1: // STAGE 1: identify protocol
318 p=(-3);
319 if (oscam_ser_selrec(buf, 1, l, &n)) // now we have 3 bytes in buf
321 p=(-2);
322 if (is_server) // HERE IS SERVER
324 job=IS_ECM; // assume ECM
325 switch(buf[0])
327 case 0x00: if( (buf[1]==0x01)&&(buf[2]==0x00) )
328 { p=P_GS; job=IS_LGO; tpe.time++; } break;
329 case 0x01: if( (buf[1]&0xf0)==0xb0 ) p=P_GBOX;
330 else {p=P_SSSP; job=IS_PMT;}
331 break; // pmt-request
332 case 0x02: p=P_HSIC; break;
333 case 0x03: switch(oscam_ser_proto)
335 case P_SSSP :
336 case P_GS :
337 case P_DSR95 : p=oscam_ser_proto; break;
338 case P_AUTO : p=(buf[1]<0x30) ? P_SSSP : P_DSR95;
339 break; // auto for GS is useless !!
340 } break;
341 case 0x04: p=P_DSR95; job=IS_ECHO; dsr9500type=P_DSR_GNUSMAS; break;
342 case 0x7E: p=P_ALPHA; if (buf[1]!=0x80) job=IS_BAD; break;
343 case 0x80:
344 case 0x81: p=P_BOMBA; break;
347 else // HERE IS CLIENT
349 job=IS_DCW; // assume DCW
350 switch(oscam_ser_proto)
352 case P_HSIC : if ((buf[0]==4) && (buf[1]==4)) p=P_HSIC; break;
353 case P_BOMBA: p=P_BOMBA; break;
354 case P_DSR95: if (buf[0]==4) p=P_DSR95; break;
355 case P_ALPHA: if (buf[0]==0x88) p=P_ALPHA; break;
358 if ((oscam_ser_proto!=p) && (oscam_ser_proto!=P_AUTO))
359 p=(-2);
361 break;
362 case 2: // STAGE 2: examine length
363 if (is_server) switch(p)
365 case P_SSSP : r=(buf[1]<<8)|buf[2]; break;
366 case P_BOMBA : r=buf[2]; break;
367 case P_HSIC : if (oscam_ser_selrec(buf, 12, l, &n)) r=buf[14];
368 else p=(-1);
369 break;
370 case P_DSR95 : if( job==IS_ECHO )
372 r=17*samsung_dcw-3+samsung_0a;
373 samsung_dcw=samsung_0a=0;
375 else
377 if (oscam_ser_selrec(buf, 16, l, &n))
379 uchar b;
380 if (cs_atob(&b, buf+17, 1)<0)
381 p=(-2);
382 else {
383 r=(b<<1);
384 r+=(dsr9500type==P_DSR_WITHSID)?4:0;
387 else p=(-1);
389 break;
390 case P_GS : if (job==IS_LGO)
391 r=5;
392 else
394 if (oscam_ser_selrec(buf, 1, l, &n))
395 r=(buf[3]<<8)|buf[2];
396 else p=(-1);
398 break;
399 case P_ALPHA : r=-0x7F; // char specifying EOT
400 break;
401 case P_GBOX : r=((buf[1]&0xf)<<8) | buf[2];
402 gbox_lens.cat_len = r;
403 break;
404 default : dsr9500type=P_DSR_AUTO;
406 else switch(p)
408 case P_HSIC : r=(buf[2]==0x3A) ? 20 : 0; break; // 3A=DCW / FC=ECM was wrong
409 case P_BOMBA : r=13; break;
410 case P_DSR95 : r=14; break;
411 case P_ALPHA : r=(buf[1]<<8)|buf[2]; break; // should be 16 always
413 break;
414 case 3: // STAGE 3: get the rest ...
415 if (r>0) // read r additional bytes
417 int all = n+r;
418 if( !oscam_ser_selrec(buf, r, l, &n) )
420 cs_debug("not all data received, waiting another 50 ms");
421 tpe.millitm+=50;
422 if( !oscam_ser_selrec(buf, all-n, l, &n) )
423 p=(-1);
425 // auto detect DSR9500 protocol
426 if( is_server && p==P_DSR95 && dsr9500type==P_DSR_AUTO )
428 tpe.millitm+=20;
429 if( oscam_ser_selrec(buf, 2, l, &n) )
431 if( cs_atoi(buf+n-2, 1, 1)==0xFFFFFFFF )
433 switch( (buf[n-2]<<8)|buf[n-1] )
435 case 0x0A0D : dsr9500type=P_DSR_OPEN; break;
436 case 0x0D0A : dsr9500type=P_DSR_PIONEER; break;
437 default : dsr9500type=P_DSR_UNKNOWN; break;
439 }else{
440 if( oscam_ser_selrec(buf, 2, l, &n) )
441 if( cs_atoi(buf+n-2, 1, 1)==0xFFFFFFFF )
442 dsr9500type=P_DSR_UNKNOWN;
443 else
444 dsr9500type=P_DSR_WITHSID;
445 else {
446 dsr9500type=P_DSR_UNKNOWN;
447 p=(-1);
451 else
452 dsr9500type=P_DSR_GNUSMAS;
453 if( p )
454 cs_log("detected dsr9500-%s type receiver",
455 dsrproto_txt[dsr9500type]);
457 // gbox
458 if( is_server && p==P_GBOX )
460 int j;
461 for( j=0; (j<3) && (p>0); j++)
462 switch( j )
464 case 0: // PMT head
465 if( !oscam_ser_selrec(buf, 3, l, &n) )
466 p=(-1);
467 else if( !(buf[n-3]==0x02 && (buf[n-2]&0xf0)==0xb0) )
468 p=(-2);
469 break;
470 case 1: // PMT + ECM header
471 gbox_lens.pmt_len=((buf[n-2]&0xf)<<8)|buf[n-1];
472 if( !oscam_ser_selrec(buf, gbox_lens.pmt_len+3, l, &n) )
473 p=(-1);
474 break;
475 case 2: // ECM + ECM PID
476 gbox_lens.ecm_len=((buf[n-2]&0xf)<<8)|buf[n-1];
477 if( !oscam_ser_selrec(buf, gbox_lens.ecm_len+4, l, &n) )
478 p=(-1);
480 } // gbox
482 else if (r<0) // read until specified char (-r)
484 while((buf[n-1]!=(-r)) && (p>0))
485 if (!oscam_ser_selrec(buf, 1, l, &n))
486 p=(-1);
488 break;
491 if (p==(-2) || p==(-1)) {
492 oscam_ser_selrec(buf, l-n, l, &n); // flush buffer
493 serial_errors++;
495 cs_ftime(&tpe);
496 cs_ddump(buf, n, "received %d bytes from %s in %d msec", n, remote_txt(),
497 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm);
498 client[cs_idx].last=tpe.time;
499 switch(p)
501 case (-1): if (is_server&&(n>2)&&(buf[0]==2)&&(buf[1]==2)&&(buf[2]==2))
503 oscam_ser_disconnect();
504 cs_log("humax powered on"); // this is nice ;)
506 else
507 cs_log(incomplete, n);
508 break;
509 case (-2): cs_debug("unknown request or garbage");
510 break;
512 xbuf[0]=(uchar) ((job<<4) | p);
513 return((p<0)?0:n+1);
517 * server functions
520 static void oscam_ser_disconnect_client()
522 switch(connected ? connected : oscam_ser_proto)
524 case P_GS:
525 mbuf[0] = 0x01;
526 mbuf[1] = 0x00;
527 mbuf[2] = 0x00;
528 mbuf[3] = 0x00;
529 oscam_ser_send(mbuf, 4);
530 break;
532 dsr9500type=P_DSR_AUTO;
533 serial_errors=0;
536 static void oscam_ser_init_client()
538 switch(oscam_ser_proto) // sure, does not work in auto-mode
540 case P_GS:
541 oscam_ser_disconnect_client(); // send disconnect first
542 cs_sleepms(300); // wait a little bit
543 mbuf[0] = 0x00;
544 mbuf[1] = 0x00;
545 mbuf[2] = 0x00;
546 mbuf[3] = 0x00;
547 oscam_ser_send(mbuf, 4); // send connect
548 break;
552 static void oscam_ser_disconnect()
554 oscam_ser_disconnect_client();
555 if (connected)
556 cs_log("%s disconnected (%s)", username(cs_idx), proto_txt[connected]);
557 connected=0;
560 static void oscam_ser_auth_client(int proto)
562 int ok;
563 // After reload base account ptrs may be placed in other address,
564 // and we may can't find it in this process.
565 // Simply save valid account.
566 static struct s_auth *account=0;
568 if (connected==proto)
569 return;
570 if (connected)
571 oscam_ser_disconnect();
572 connected=proto;
573 if( !account )
575 client[cs_idx].usr[0]=0;
576 for (ok=0, account=cfg->account; (account) && (!ok); account=account->next)
577 if( (ok=!strcmp(oscam_ser_usr, account->usr)) )
578 break;
580 cs_auth_client(ok ? account : (struct s_auth *)(-1), proto_txt[connected]);
583 static void oscam_ser_send_dcw(ECM_REQUEST *er)
585 int i;
586 uchar crc;
587 if (er->rc<4) // found
588 switch(connected)
590 case P_HSIC:
591 for (i=0, crc=HSIC_CRC; i<16; i++)
592 crc^=er->cw[i];
593 memset(mbuf , 0x04 , 2);
594 memset(mbuf+2 , 0x3a , 2);
595 memcpy(mbuf+4 , er->cw, 16);
596 memcpy(mbuf+20, &crc , 1);
597 memset(mbuf+21, 0x1b , 2);
598 oscam_ser_send(mbuf, 23);
599 break;
600 case P_SSSP:
601 mbuf[0]=0xF2;
602 mbuf[1]=0;
603 mbuf[2]=16;
604 memcpy(mbuf+3, er->cw, 16);
605 oscam_ser_send(mbuf, 19);
606 if (!sssp_fix)
608 mbuf[0]=0xF1;
609 mbuf[1]=0;
610 mbuf[2]=2;
611 memcpy(mbuf+3, i2b(2, er->pid), 2);
612 oscam_ser_send(mbuf, 5);
613 sssp_fix=1;
615 break;
616 case P_GBOX:
617 case P_BOMBA:
618 oscam_ser_send(er->cw, 16);
619 break;
620 case P_DSR95:
621 mbuf[0]=4;
622 memcpy(mbuf+1, er->cw, 16);
623 oscam_ser_send(mbuf, 17);
624 if( dsr9500type==P_DSR_GNUSMAS )
626 int i;
627 samsung_0a=0;
628 for( i=1; i<17; i++ )
629 if( mbuf[i]==0x0A )
630 samsung_0a++;
631 samsung_dcw++;
633 break;
634 case P_GS:
635 mbuf[0]=0x03;
636 mbuf[1]=0x08;
637 mbuf[2]=0x10;
638 mbuf[3]=0x00;
639 memcpy(mbuf+4, er->cw, 16);
640 oscam_ser_send(mbuf, 20);
641 break;
642 case P_ALPHA:
643 mbuf[0]=0x88;
644 mbuf[1]=0x00;
645 mbuf[2]=0x10;
646 memcpy(mbuf+3, er->cw, 16);
647 oscam_ser_send(mbuf, 19);
648 break;
650 else // not found
651 switch(connected)
653 case P_GS:
654 mbuf[0]=0x03;
655 mbuf[1]=0x09;
656 mbuf[2]=0x00;
657 mbuf[3]=0x00;
658 oscam_ser_send(mbuf, 4);
659 break;
661 serial_errors=0; // clear error counter
664 static void oscam_ser_process_pmt(uchar *buf, int l)
666 int i;
667 uchar sbuf[32];
669 switch(connected)
671 case P_SSSP:
672 sssp_fix=0;
673 memset(sssp_tab, 0, sizeof(sssp_tab));
674 sssp_srvid=b2i(2, buf+3);
675 for (i=9, sssp_num=0; (i<l) && (sssp_num<SSSP_MAX_PID); i+=7, sssp_num++)
677 memcpy(sbuf+3+(sssp_num<<1), buf+i+2, 2);
678 sssp_tab[sssp_num].caid=b2i(2, buf+i );
679 sssp_tab[sssp_num].pid =b2i(2, buf+i+2);
680 sssp_tab[sssp_num].prid=b2i(3, buf+i+4);
682 sbuf[0]=0xF1;
683 sbuf[1]=0;
684 sbuf[2]=(sssp_num<<1);
685 oscam_ser_send(sbuf, sbuf[2]+3);
686 break;
690 static void oscam_ser_client_logon(uchar *buf, int l)
692 uchar gs_logon[]={0, 1, 0, 0, 2, 1, 0, 0};
693 switch(connected)
695 case P_GS:
696 if ((l>=8) && (!memcmp(buf, gs_logon, 8)))
698 buf[0] = 0x02;
699 buf[1] = 0x04;
700 buf[2] = 0x00;
701 buf[3] = 0x00;
702 oscam_ser_send(buf, 4);
704 break;
708 static int oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int l)
710 int i;
712 if (l<16)
714 cs_log(incomplete, l);
715 return(1);
718 switch(connected)
720 case P_HSIC:
721 er->l = l-12;
722 er->caid = b2i(2, buf+1 );
723 er->prid = b2i(3, buf+3 );
724 er->pid = b2i(2, buf+6 );
725 er->srvid= b2i(2, buf+10);
726 memcpy(er->ecm, buf+12, er->l);
727 break;
728 case P_SSSP:
729 er->pid=b2i(2, buf+3);
730 for (i=0; (i<8) && (sssp_tab[i].pid!=er->pid); i++);
731 if (i>=sssp_num)
733 cs_debug("illegal request, unknown pid=%04X", er->pid);
734 return(2);
736 er->l = l-5;
737 er->srvid= sssp_srvid;
738 er->caid = sssp_tab[i].caid;
739 er->prid = sssp_tab[i].prid;
740 memcpy(er->ecm, buf+5, er->l);
741 break;
742 case P_BOMBA:
743 er->l=l;
744 memcpy(er->ecm, buf, er->l);
745 break;
746 case P_DSR95:
747 buf[l]='\0'; // prepare for trim
748 trim(buf+13); // strip spc, nl, cr ...
749 er->l=strlen(buf+13)>>1;
750 er->prid=cs_atoi(buf+3, 3, 0); // ignore errors
751 er->caid=cs_atoi(buf+9, 2, 0); // ignore errors
752 if (cs_atob(er->ecm, buf+13, er->l)<0)
754 cs_log("illegal characters in ecm-request");
755 return(1);
757 if( dsr9500type==P_DSR_WITHSID )
759 er->l-=2;
760 er->srvid=cs_atoi(buf+13+(er->l<<1), 2, 0);
762 break;
763 case P_GS:
764 er->l = ((buf[3]<<8)|buf[2]) - 6;
765 er->srvid = (buf[5]<<8)|buf[4]; // sid
766 er->caid = (buf[7]<<8)|buf[6];
767 er->prid = 0;
768 if (er->l>256) er->l=256;
769 memcpy(er->ecm, buf+10, er->l);
770 break;
771 case P_ALPHA:
772 l=oscam_ser_alpha_convert(buf, l);
773 er->l = b2i(2, buf+1 )-2;
774 er->caid = b2i(2, buf+3 );
775 if ((er->l!=l-5) || (er->l>257))
777 cs_log(incomplete, l);
778 return(1);
780 memcpy(er->ecm, buf+5, er->l);
781 break;
782 case P_GBOX:
783 er->srvid = b2i(2, buf+gbox_lens.cat_len+3+3);
784 er->l = gbox_lens.ecm_len+3;
785 memcpy(er->ecm, buf+gbox_lens.cat_len+3+gbox_lens.pmt_len+3, er->l);
786 break;
788 return(0);
791 static void oscam_ser_process_ecm(uchar *buf, int l)
793 ECM_REQUEST *er;
795 if (!(er=get_ecmtask()))
796 return;
798 switch(oscam_ser_check_ecm(er, buf, l))
800 case 2: er->rc=9; return; // error without log
801 case 1: er->rc=9; // error with log
803 get_cw(er);
807 static void oscam_ser_server()
809 int n;
811 connected=0;
812 oscam_ser_init_client();
814 while ((n=process_input(mbuf, sizeof(mbuf), cfg->cmaxidle))>=0)
816 if (serial_errors > 3)
818 cs_log("too many errors, reiniting...");
819 break;
821 if (n>0)
823 oscam_ser_auth_client(mbuf[0] & 0xF);
824 switch (mbuf[0]>>4)
826 case IS_ECM:
827 oscam_ser_process_ecm(mbuf+1, n-1);
828 break;
829 case IS_PMT:
830 oscam_ser_process_pmt(mbuf+1, n-1);
831 break;
832 case IS_LGO:
833 oscam_ser_client_logon(mbuf+1, n-1);
834 break;
838 oscam_ser_disconnect();
841 static int init_oscam_ser_device(char *device)
843 int fd;
845 fd=open(device, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
846 if (fd>0)
848 fcntl(fd, F_SETFL, 0);
849 if (oscam_ser_set_serial_device(fd)<0) cs_log("ERROR ioctl");
850 if (tcflush(fd, TCIOFLUSH)<0) cs_log("ERROR flush");
852 else
854 fd=0;
855 cs_log("ERROR opening %s", device);
857 return(fd);
860 static void oscam_ser_fork(int idx, char *url)
862 static char logtxt[32];
864 is_server=1;
865 if ((!url) || (!url[0])) return;
866 if (!oscam_ser_parse_url(url)) return;
867 snprintf(logtxt, sizeof(logtxt)-1, ", %s@%s",
868 oscam_ser_proto>P_MAX ? "auto" : proto_txt[oscam_ser_proto], oscam_ser_device);
869 ph[idx].logtxt=logtxt;
870 switch(cs_fork(0, idx))
872 case 0: // master
873 case -1:
874 return;
875 default:
876 wait4master();
878 while(1)
880 client[cs_idx].au=(-1);
881 client[cs_idx].usr[0]='\0';
882 client[cs_idx].login=time((time_t *)0);
883 if (pfd=init_oscam_ser_device(oscam_ser_device))
884 oscam_ser_server();
885 else
886 sleep(60); // retry in 1 min. (USB-Device ?)
887 if (pfd) close(pfd);
891 void init_oscam_ser(int idx)
893 char *p;
894 while( (p=strrchr(cfg->ser_device, 1)) )
896 *p=0;
897 oscam_ser_fork(idx, p+1);
899 oscam_ser_fork(idx, cfg->ser_device);
903 * client functions
906 static int oscam_ser_client_init()
908 if ((!reader[ridx].device[0])) cs_exit(1);
909 if (!oscam_ser_parse_url(reader[ridx].device)) cs_exit(1);
910 pfd=init_oscam_ser_device(oscam_ser_device);
911 return((pfd>0) ? 0 : 1);
914 static int oscam_ser_send_ecm(ECM_REQUEST *er, uchar *buf)
916 switch(oscam_ser_proto)
918 case P_HSIC:
919 memset(buf, 0, 12);
920 buf[0]=2;
921 memcpy(buf+ 1, i2b(2, er->caid ), 2);
922 memcpy(buf+ 3, i2b(3, er->prid ), 3);
923 memcpy(buf+ 6, i2b(2, er->pid ), 2);
924 memcpy(buf+10, i2b(2, er->srvid), 2);
925 memcpy(buf+12, er->ecm, er->l);
926 oscam_ser_send(buf, 12+er->l);
927 break;
928 case P_BOMBA:
929 oscam_ser_send(er->ecm, er->l);
930 break;
931 case P_DSR95:
932 if( dsr9500type==P_DSR_WITHSID )
934 sprintf(buf, "%c%08X%04X%s%04X\n\r",
935 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->l), er->srvid);
936 oscam_ser_send(buf, (er->l<<1)+19); // 1 + 8 + 4 + l*2 + 4 + 2
938 else
940 sprintf(buf, "%c%08X%04X%s\n\r",
941 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->l));
942 oscam_ser_send(buf, (er->l<<1)+15); // 1 + 8 + 4 + l*2 + 2
944 break;
945 case P_ALPHA:
946 buf[0]=0x80;
947 memcpy(buf+1, i2b(2, 2+er->l), 2);
948 memcpy(buf+3, i2b(2, er->caid), 2);
949 memcpy(buf+5, er->ecm, er->l);
950 oscam_ser_send(buf, oscam_ser_alpha_convert(buf, 5+er->l));
951 break;
953 return(0);
956 static void oscam_ser_process_dcw(uchar *dcw, int *rc, uchar *buf, int l)
958 switch(oscam_ser_proto)
960 case P_HSIC:
961 if ((l>=23) && (buf[2]==0x3A) && (buf[3]==0x3A))
963 int i;
964 uchar crc;
965 for (i=4, crc=HSIC_CRC; i<20; i++)
966 crc^=buf[i];
967 if (crc==buf[20])
969 memcpy(dcw, buf+4, 16);
970 *rc=1;
973 break;
974 case P_BOMBA:
975 if (l>=16)
977 memcpy(dcw, buf, 16);
978 *rc=1;
980 break;
981 case P_DSR95:
982 if ((l>=17) && (buf[0]==4))
984 memcpy(dcw, buf+1, 16);
985 *rc=1;
987 break;
988 case P_ALPHA:
989 if ((l>=19) && (buf[0]==0x88))
991 memcpy(dcw, buf+3, 16);
992 *rc=1;
994 break;
998 static int oscam_ser_recv_chk(uchar *dcw, int *rc, uchar *buf, int n)
1000 *rc=(-1);
1001 switch (buf[0]>>4)
1003 case IS_DCW:
1004 oscam_ser_process_dcw(dcw, rc, buf+1, n-1);
1005 break;
1007 return((*rc<0) ? (-1) : 0); // idx not supported in serial module
1011 * protocol structure
1014 void module_oscam_ser(struct s_module *ph)
1016 strcpy(ph->desc, "serial");
1017 ph->type=MOD_CONN_SERIAL;
1018 ph->multi=1;
1019 ph->watchdog=0;
1020 ph->s_handler=init_oscam_ser;
1021 ph->recv=oscam_ser_recv;
1022 ph->send_dcw=oscam_ser_send_dcw;
1023 ph->c_multi=0;
1024 ph->c_init=oscam_ser_client_init;
1025 ph->c_recv_chk=oscam_ser_recv_chk;
1026 ph->c_send_ecm=oscam_ser_send_ecm;