source: trunk/module-serial.c@ 4149

Last change on this file since 4149 was 4141, checked in by dingo35, 13 years ago

all: simplify debug system, add D_DVBAPI = -d128, eliminate cs_ptyp which complicates stuff unnecc

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