source: trunk/module-serial.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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