revert breaks some stupid old compilers
[oscam.git] / module-serial.c
blob48da1cb5d4a396e9c55e1c4967daee6c6409afd4
1 #define MODULE_LOG_PREFIX "serial"
3 #include "globals.h"
4 #ifdef MODULE_SERIAL
5 #include "oscam-config.h"
6 #include "oscam-client.h"
7 #include "oscam-ecm.h"
8 #include "oscam-net.h"
9 #include "oscam-string.h"
10 #include "oscam-time.h"
11 #include "oscam-reader.h"
13 extern int32_t exit_oscam;
15 #define HSIC_CRC 0xA5
16 #define SSSP_MAX_PID 8
18 #define P_HSIC 1 // Humax Sharing Interface Client
19 #define P_SSSP 2 // Simple Serial Sharing Protocol
20 #define P_BOMBA 3 // This is not really a Protocol
21 #define P_DSR95 4 // DSR9500 with SID
22 #define P_GS 5 // GS7001
23 #define P_ALPHA 6 // AlphaStar Receivers
24 #define P_DSR95_OLD 7 // DSR9500 without SID
25 #define P_GBOX 8 // Arion with gbox
26 #define P_TWIN 9 // Twin Protocol
27 #define P_MAX P_TWIN
28 #define P_AUTO 0xFF
30 #define P_DSR_AUTO 0
31 #define P_DSR_GNUSMAS 1
32 #define P_DSR_OPEN 2
33 #define P_DSR_PIONEER 3
34 #define P_DSR_WITHSID 4
35 #define P_DSR_UNKNOWN 5
37 #define IS_ECM 0 // incoming data is ECM
38 #define IS_DCW 1 // incoming data is DCW
39 #define IS_PMT 2 // incoming data is PMT
40 #define IS_LGO 3 // incoming data is client logon
41 #define IS_ECHO 4 // incoming data is DCW echo from Samsung
42 #define IS_CAT 5 // incoming data is CAT
43 #define IS_BAD 0xFF // incoming data is unknown
45 static const char *const proto_txt[] = {"unknown", "hsic", "sssp", "bomba", "dsr9500", "gs",
46 "alpha", "dsr9500old", "gbox", "twin"
48 static const char *const dsrproto_txt[] = {"unknown", "samsung", "openbox", "pioneer",
49 "extended", "unknown"
52 typedef struct s_gbox
54 int32_t cat_len;
55 int32_t pmt_len;
56 int32_t ecm_len;
57 } GBOX_LENS;
59 typedef struct s_sssp
61 uint16_t caid;
62 uint16_t pid;
63 uint32_t prid;
64 } SSSP_TAB;
66 //added to support multiple instances with thread
67 struct s_serial_client
69 int32_t connected;
70 struct timeb tps;
71 struct timeb tpe;
72 char oscam_ser_usr[32];
73 char oscam_ser_device[64];
74 int32_t oscam_ser_port;
75 speed_t oscam_ser_baud;
76 int32_t oscam_ser_delay;
77 int32_t oscam_ser_timeout;
78 int32_t oscam_ser_proto;
79 int32_t serial_errors;
80 int32_t dsr9500type;
81 int32_t samsung_0a; // number of 0A in ALL dcw sent into samsung
82 int32_t samsung_dcw; // number of dcw sent into samsung before echo or ecm is received
84 GBOX_LENS gbox_lens;
85 SSSP_TAB sssp_tab[SSSP_MAX_PID];
86 uint16_t sssp_srvid;
87 int32_t sssp_num;
88 int32_t sssp_fix;
91 static pthread_mutex_t mutex;
92 static pthread_cond_t cond;
93 static int32_t bcopy_end = -1;
94 static struct s_module *serial_ph = NULL;
96 struct s_thread_param
98 uint8_t module_idx;
99 struct s_serial_client serialdata;
102 static int32_t chk_ser_srvid_match(uint16_t caid, uint16_t sid, uint32_t provid, SIDTAB *sidtab)
104 int32_t i, rc = 0;
106 if(!sidtab->num_caid)
107 { rc |= 1; }
108 else
109 for(i = 0; (i < sidtab->num_caid) && (!(rc & 1)); i++)
110 if(caid == sidtab->caid[i]) { rc |= 1; }
112 if(!sidtab->num_provid)
113 { rc |= 2; }
114 else
115 for(i = 0; (i < sidtab->num_provid) && (!(rc & 2)); i++)
116 if(provid == sidtab->provid[i]) { rc |= 2; }
118 if(!sidtab->num_srvid)
119 { rc |= 4; }
120 else
121 for(i = 0; (i < sidtab->num_srvid) && (!(rc & 4)); i++)
122 if(sid == sidtab->srvid[i]) { rc |= 4; }
124 return (rc == 7);
127 static int32_t chk_ser_srvid(struct s_client *cl, uint16_t caid, uint16_t sid, uint32_t provid)
129 int32_t nr, rc = 0;
130 SIDTAB *sidtab;
132 if(!cl->sidtabs.ok)
134 if(!cl->sidtabs.no) { return (1); }
135 rc = 1;
137 for(nr = 0, sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next, nr++)
138 if(sidtab->num_caid | sidtab->num_provid | sidtab->num_srvid)
140 if((cl->sidtabs.no & ((SIDTABBITS)1 << nr)) &&
141 (chk_ser_srvid_match(caid, sid, provid, sidtab)))
142 { return (0); }
143 if((cl->sidtabs.ok & ((SIDTABBITS)1 << nr)) &&
144 (chk_ser_srvid_match(caid, sid, provid, sidtab)))
145 { rc = 1; }
147 return (rc);
150 static void oscam_wait_ser_fork(void)
152 SAFE_MUTEX_LOCK(&mutex);
155 if(bcopy_end)
157 bcopy_end = 0;
158 break;
160 else
161 { SAFE_COND_WAIT(&cond, &mutex); }
163 while(1);
164 SAFE_MUTEX_UNLOCK(&mutex);
167 static int32_t oscam_ser_alpha_convert(uchar *buf, int32_t l)
169 int32_t i;
170 if(buf[0] == 0x7E) // normalize
172 l -= 2;
173 memmove(buf, buf + 1, l); // remove BOT/EOT
174 for(i = 0; i < l; i++)
175 if(buf[i] == 0x20)
177 memmove(buf + i, buf + i + 1, --l);
178 buf[i] ^= 0x20;
181 else // to alphastar
183 memmove(buf + 1, buf, l++); // insert BOT
184 buf[0] = 0x7E;
185 for(i = 1; i < l; i++)
186 if((buf[i] == 0x20) || (buf[i] == 0x7E) || (buf[i] == 0x7F))
188 buf[i] ^= 0x20;
189 memmove(buf + i + 1, buf + i, l++);
190 buf[i++] = 0x20;
192 buf[l++] = 0x7F; // insert EOT
194 return (l);
197 static void oscam_ser_disconnect(void);
199 static int32_t oscam_ser_parse_url(char *url, struct s_serial_client *serialdata, char *pcltype)
201 char *service, *usr, *dev, *baud = NULL, *dummy, *para;
202 char cltype;
204 cltype = pcltype ? (*pcltype) : cur_client()->typ;
206 serialdata->oscam_ser_proto = P_AUTO;
207 if((dummy = strstr(url, "://")))
209 int32_t i;
210 service = url;
211 url = dummy + 3;
212 *dummy = 0;
213 for(i = 1; i <= P_MAX; i++)
214 if(!strcmp(service, proto_txt[i]))
215 { serialdata->oscam_ser_proto = i; }
217 if(!(cltype == 'c') && (serialdata->oscam_ser_proto == P_AUTO)) { return (0); }
218 switch(serialdata->oscam_ser_proto) // set the defaults
220 case P_GS:
221 serialdata->oscam_ser_timeout = 500;
222 serialdata->oscam_ser_baud = B19200;
223 break;
224 default:
225 serialdata->oscam_ser_timeout = 50;
226 #ifdef B115200
227 serialdata->oscam_ser_baud = B115200;
228 #else
229 serialdata->oscam_ser_baud = B9600;
230 #endif
233 switch(serialdata->oscam_ser_proto)
235 case P_DSR95:
236 serialdata->dsr9500type = (cltype == 'c') ? P_DSR_AUTO : P_DSR_WITHSID;
237 break;
238 case P_DSR95_OLD:
239 serialdata->dsr9500type = P_DSR_AUTO;
240 serialdata->oscam_ser_proto = P_DSR95;
243 usr = url;
244 if((dev = strchr(usr, '@')))
246 *dev++ = '\0';
247 if((dummy = strchr(usr, ':'))) // fake pwd
248 { *dummy++ = '\0'; }
249 if((cltype == 'c') && (!usr[0])) { return (0); }
251 else
253 if(cltype == 'c') { return (0); } // user needed in server-mode
254 dev = usr;
256 if((baud = strchr(dev, ':'))) // port = baud
257 { *baud++ = '\0'; }
258 dummy = baud ? baud : dev;
259 if((para = strchr(dummy, '?')))
261 char *ptr1, *ptr2, *saveptr1 = NULL;
262 *para++ = '\0';
263 for(ptr1 = strtok_r(para, "&", &saveptr1); ptr1; ptr1 = strtok_r(NULL, "&", &saveptr1))
265 if(!(ptr2 = strchr(ptr1, '='))) { continue; }
266 *ptr2++ = '\0';
267 strtolower(ptr1);
268 if(!strcmp("delay" , ptr1)) { serialdata->oscam_ser_delay = atoi(ptr2); }
269 if(!strcmp("timeout", ptr1)) { serialdata->oscam_ser_timeout = atoi(ptr2); }
272 if(baud)
274 trim(baud);
275 #ifdef B115200
276 if(!strcmp(baud, "115200"))
277 { serialdata->oscam_ser_baud = B115200; }
278 else
279 #endif
280 #ifdef B57600
281 if(!strcmp(baud, "57600"))
282 { serialdata->oscam_ser_baud = B57600; }
283 else
284 #endif
285 if(!strcmp(baud, "38400"))
286 { serialdata->oscam_ser_baud = B38400; }
287 else if(!strcmp(baud, "19200"))
288 { serialdata->oscam_ser_baud = B19200; }
289 else if(!strcmp(baud, "9600"))
290 { serialdata->oscam_ser_baud = B9600; }
292 if((para = strchr(dev, ','))) // device = ip/hostname and port
294 *para++ = '\0';
295 serialdata->oscam_ser_port = atoi(para);
297 else
298 { serialdata->oscam_ser_port = 0; }
299 cs_strncpy(serialdata->oscam_ser_usr, usr, sizeof(serialdata->oscam_ser_usr));
300 cs_strncpy(serialdata->oscam_ser_device, dev, sizeof(serialdata->oscam_ser_device));
301 return (serialdata->oscam_ser_baud);
304 static void oscam_ser_set_baud(struct termios *tio, speed_t baud)
306 cfsetospeed(tio, baud);
307 cfsetispeed(tio, baud);
310 static int32_t oscam_ser_set_serial_device(int32_t fd, speed_t baud)
312 struct termios tio;
314 memset(&tio, 0, sizeof(tio));
315 // tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
316 tio.c_cflag = (CS8 | CREAD | CLOCAL);
317 tio.c_iflag = IGNPAR;
318 tio.c_cc[VMIN] = 1;
319 tio.c_cc[VTIME] = 0;
320 //#if !defined(__CYGWIN__)
321 oscam_ser_set_baud(&tio, B1200);
322 tcsetattr(fd, TCSANOW, &tio);
323 cs_sleepms(500);
324 //#endif
325 oscam_ser_set_baud(&tio, baud);
326 return (tcsetattr(fd, TCSANOW, &tio));
329 static int32_t oscam_ser_poll(int32_t event, struct s_client *client)
331 int64_t msec;
332 struct pollfd pfds;
333 struct timeb tpc;
334 cs_ftime(&tpc);
335 msec = comp_timeb(&client->serialdata->tpe, &tpc);
336 if(msec < 0)
337 { return (0); }
338 pfds.fd = cur_client()->pfd;
339 pfds.events = event;
340 pfds.revents = 0;
341 if(poll(&pfds, 1, msec) != 1)
342 { return (0); }
343 else
344 { return (((pfds.revents)&event) == event); }
347 static int32_t oscam_ser_write(struct s_client *client, const uchar *const buf, int32_t n)
349 int32_t i;
350 for(i = 0; (i < n) && (oscam_ser_poll(POLLOUT, client)); i++)
352 if(client->serialdata->oscam_ser_delay)
353 { cs_sleepms(client->serialdata->oscam_ser_delay); }
354 if(write(client->pfd, buf + i, 1) < 1)
355 { break; }
357 return (i);
360 static int32_t oscam_ser_send(struct s_client *client, const uchar *const buf, int32_t l)
362 int32_t n;
363 struct s_serial_client *serialdata = client->serialdata ;
364 if(!client->pfd) { return (0); }
365 cs_ftime(&serialdata->tps);
366 serialdata->tpe = client->serialdata->tps;
367 add_ms_to_timeb(&serialdata->tpe, serialdata->oscam_ser_timeout);
368 add_ms_to_timeb(&serialdata->tpe, (l * (serialdata->oscam_ser_delay + 1)));
369 n = oscam_ser_write(client, buf, l);
370 cs_ftime(&serialdata->tpe);
371 cs_log_dump_dbg(D_CLIENT, buf, l, "send %d of %d bytes to %s in %"PRId64" ms", n, l, remote_txt(),
372 comp_timeb(&serialdata->tpe, &serialdata->tps));
373 if(n != l)
374 { cs_log("transmit error. send %d of %d bytes only !", n, l); }
375 return (n);
378 static int32_t oscam_ser_selrec(uchar *buf, int32_t n, int32_t l, int32_t *c)
380 int32_t i;
381 if(*c + n > l)
382 { n = l - *c; }
383 if(n <= 0) { return (0); }
384 for(i = 0; (i < n) && (oscam_ser_poll(POLLIN, cur_client())); i++)
385 if(read(cur_client()->pfd, buf + *c, 1) < 1)
386 { return (0); }
387 else
388 { (*c)++; }
389 return (i == n);
392 static int32_t oscam_ser_recv(struct s_client *client, uchar *xbuf, int32_t l)
394 int32_t s, p, n, r;
395 uchar job = IS_BAD;
396 static uchar lb;
397 static int32_t have_lb = 0;
398 uchar *buf = xbuf + 1;
399 struct s_serial_client *serialdata = client->serialdata;
401 if(!client->pfd) { return (-1); }
402 cs_ftime(&serialdata->tps);
403 serialdata->tpe = serialdata->tps;
404 add_ms_to_timeb(&serialdata->tpe, serialdata->oscam_ser_timeout);
405 buf[0] = lb;
406 for(s = p = r = 0, n = have_lb; (s < 4) && (p >= 0); s++)
408 switch(s)
410 case 0: // STAGE 0: skip known garbage from DSR9500
411 if(oscam_ser_selrec(buf, 2 - n, l, &n))
413 if((buf[0] == 0x0A) && (buf[1] == 0x0D))
414 { p = (-4); }
415 if((buf[0] == 0x0D) && (buf[1] == 0x0A))
416 { p = (-4); }
418 else
419 { p = (-3); }
420 have_lb = 0;
421 break;
422 case 1: // STAGE 1: identify protocol
423 p = (-3);
424 if(oscam_ser_selrec(buf, 1, l, &n)) // now we have 3 bytes in buf
426 if((buf[0] == 0x04) && (buf[1] == 0x00) && (buf[2] == 0x02)) //skip unsupported Advanced Serial Sharing Protocol HF 8900
428 oscam_ser_selrec(buf, 2, l, &n); // get rest 2 bytes to buffor
429 p = (-4);
430 have_lb = 0;
431 break;
433 else
436 p = (-2);
437 if(client->typ == 'c') // HERE IS SERVER
439 job = IS_ECM; // assume ECM
440 switch(buf[0])
442 case 0x00:
443 if((buf[1] == 0x01) && (buf[2] == 0x00))
445 p = P_GS;
446 job = IS_LGO;
447 serialdata->tpe.time++;
449 break;
450 case 0x01:
451 if((buf[1] & 0xf0) == 0xb0) { p = P_GBOX; }
452 else
454 p = P_SSSP;
455 job = IS_PMT;
457 break; // pmt-request
458 case 0x02:
459 p = P_HSIC;
460 break;
461 case 0x03:
462 switch(serialdata->oscam_ser_proto)
464 case P_SSSP :
465 case P_GS :
466 case P_DSR95 :
467 p = serialdata->oscam_ser_proto;
468 break;
469 case P_AUTO :
470 p = (buf[1] < 0x30) ? P_SSSP : P_DSR95;
471 break; // auto for GS is useless !!
473 break;
474 case 0x04:
475 p = P_DSR95;
476 job = IS_ECHO;
477 serialdata->dsr9500type = P_DSR_GNUSMAS;
478 break;
479 case 0x7E:
480 p = P_ALPHA;
481 if(buf[1] != 0x80) { job = IS_BAD; }
482 break;
483 case 0x80:
484 case 0x81:
485 p = P_BOMBA;
486 break;
490 else // HERE IS CLIENT
492 job = IS_DCW; // assume DCW
493 switch(serialdata->oscam_ser_proto)
495 case P_HSIC :
496 if((buf[0] == 4) && (buf[1] == 4)) { p = P_HSIC; }
497 break;
498 case P_BOMBA:
499 p = P_BOMBA;
500 break;
501 case P_DSR95:
502 if(buf[0] == 4) { p = P_DSR95; }
503 break;
504 case P_ALPHA:
505 if(buf[0] == 0x88) { p = P_ALPHA; }
506 break;
507 case P_TWIN:
508 if((buf[0] == 0xF7) && (buf[1] == 0x00) && (buf[2] == 0x16)) { p = P_TWIN; }
509 break;
512 if((serialdata->oscam_ser_proto != p) && (serialdata->oscam_ser_proto != P_AUTO))
513 { p = (-2); }
516 break;
517 case 2: // STAGE 2: examine length
518 if(client->typ == 'c') switch(p)
520 case P_SSSP :
521 r = (buf[1] << 8) | buf[2];
522 break;
523 case P_BOMBA :
524 r = buf[2];
525 break;
526 case P_HSIC :
527 if(oscam_ser_selrec(buf, 12, l, &n)) { r = buf[14]; }
528 else { p = (-1); }
529 break;
530 case P_DSR95 :
531 if(job == IS_ECHO)
533 r = 17 * serialdata->samsung_dcw - 3 + serialdata->samsung_0a;
534 serialdata->samsung_dcw = serialdata->samsung_0a = 0;
536 else
538 if(oscam_ser_selrec(buf, 16, l, &n))
540 uchar b;
541 if(cs_atob(&b, (char *)buf + 17, 1) < 0)
542 { p = (-2); }
543 else
545 r = (b << 1);
546 r += (serialdata->dsr9500type == P_DSR_WITHSID) ? 4 : 0;
549 else { p = (-1); }
551 break;
552 case P_GS :
553 if(job == IS_LGO)
554 { r = 5; }
555 else
557 if(oscam_ser_selrec(buf, 1, l, &n))
558 { r = (buf[3] << 8) | buf[2]; }
559 else { p = (-1); }
561 break;
562 case P_ALPHA :
563 r = -0x7F; // char specifying EOT
564 break;
565 case P_GBOX :
566 r = ((buf[1] & 0xf) << 8) | buf[2];
567 serialdata->gbox_lens.cat_len = r;
568 break;
569 default :
570 serialdata->dsr9500type = P_DSR_AUTO;
572 else switch(p)
574 case P_HSIC :
575 r = (buf[2] == 0x3A) ? 20 : 0;
576 break; // 3A=DCW / FC=ECM was wrong
577 case P_BOMBA :
578 r = 13;
579 break;
580 case P_DSR95 :
581 r = 14;
582 break;
583 case P_ALPHA :
584 r = (buf[1] << 8) | buf[2];
585 break; // should be 16 always
586 case P_TWIN :
587 r = 16;
588 break;
590 break;
591 case 3: // STAGE 3: get the rest ...
592 if(r > 0) // read r additional bytes
594 int32_t all = n + r;
595 if(!oscam_ser_selrec(buf, r, l, &n))
597 cs_log_dbg(D_CLIENT, "not all data received, waiting another 50 ms");
598 add_ms_to_timeb(&serialdata->tpe, 50);
599 if(!oscam_ser_selrec(buf, all - n, l, &n))
600 { p = (-1); }
602 // auto detect DSR9500 protocol
603 if(client->typ == 'c' && p == P_DSR95 && serialdata->dsr9500type == P_DSR_AUTO)
605 add_ms_to_timeb(&serialdata->tpe, 20);
606 if(oscam_ser_selrec(buf, 2, l, &n))
608 if(cs_atoi((char *)buf + n - 2, 1, 1) == 0xFFFFFFFF)
610 switch((buf[n - 2] << 8) | buf[n - 1])
612 case 0x0A0D :
613 serialdata->dsr9500type = P_DSR_OPEN;
614 break;
615 case 0x0D0A :
616 serialdata->dsr9500type = P_DSR_PIONEER;
617 break;
618 default :
619 serialdata->dsr9500type = P_DSR_UNKNOWN;
620 break;
623 else
625 if(oscam_ser_selrec(buf, 2, l, &n))
626 if(cs_atoi((char *)buf + n - 2, 1, 1) == 0xFFFFFFFF)
627 { serialdata->dsr9500type = P_DSR_UNKNOWN; }
628 else
629 { serialdata->dsr9500type = P_DSR_WITHSID; }
630 else
632 serialdata->dsr9500type = P_DSR_UNKNOWN;
633 p = (-1);
637 else
638 { serialdata->dsr9500type = P_DSR_GNUSMAS; }
639 if(p)
640 cs_log("detected dsr9500-%s type receiver",
641 dsrproto_txt[serialdata->dsr9500type]);
643 // gbox
644 if(client->typ == 'c' && p == P_GBOX)
646 int32_t j;
647 for(j = 0; (j < 3) && (p > 0); j++)
648 switch(j)
650 case 0: // PMT head
651 if(!oscam_ser_selrec(buf, 3, l, &n))
652 { p = (-1); }
653 else if(!(buf[n - 3] == 0x02 && (buf[n - 2] & 0xf0) == 0xb0))
654 { p = (-2); }
655 break;
656 case 1: // PMT + ECM header
657 serialdata->gbox_lens.pmt_len = ((buf[n - 2] & 0xf) << 8) | buf[n - 1];
658 if(!oscam_ser_selrec(buf, serialdata->gbox_lens.pmt_len + 3, l, &n))
659 { p = (-1); }
660 break;
661 case 2: // ECM + ECM PID
662 serialdata->gbox_lens.ecm_len = ((buf[n - 2] & 0xf) << 8) | buf[n - 1];
663 if(!oscam_ser_selrec(buf, serialdata->gbox_lens.ecm_len + 4, l, &n))
664 { p = (-1); }
666 } // gbox
668 else if(r < 0) // read until specified char (-r)
670 while((buf[n - 1] != (-r)) && (p > 0))
671 if(!oscam_ser_selrec(buf, 1, l, &n))
672 { p = (-1); }
674 break;
677 if(p == (-2) || p == (-1))
679 oscam_ser_selrec(buf, l - n, l, &n); // flush buffer
680 serialdata->serial_errors++;
682 cs_ftime(&serialdata->tpe);
683 cs_log_dump_dbg(D_CLIENT, buf, n, "received %d bytes from %s in %"PRId64" ms", n, remote_txt(), comp_timeb(&serialdata->tpe, &serialdata->tps));
684 client->last = serialdata->tpe.time;
685 switch(p)
687 case(-1):
688 if(client->typ == 'c' && (n > 2) && (buf[0] == 2) && (buf[1] == 2) && (buf[2] == 2))
690 oscam_ser_disconnect();
691 cs_log("humax powered on"); // this is nice ;)
693 else
695 if(client->typ == 'c' && buf[0] == 0x1 && buf[1] == 0x08 && buf[2] == 0x20 && buf[3] == 0x08)
697 oscam_ser_disconnect();
698 cs_log("ferguson powered on"); // this is nice to ;)
700 else
701 cs_log("incomplete request (%d bytes)", n);
703 break;
704 case(-2):
705 cs_log_dbg(D_CLIENT, "unknown request or garbage");
706 break;
708 xbuf[0] = (uchar)((job << 4) | p);
709 return ((p < 0) ? 0 : n + 1);
713 * server functions
716 static void oscam_ser_disconnect_client(void)
718 uchar mbuf[1024];
719 struct s_serial_client *serialdata = cur_client()->serialdata;
720 switch(serialdata->connected ? serialdata->connected : serialdata->oscam_ser_proto)
722 case P_GS:
723 mbuf[0] = 0x01;
724 mbuf[1] = 0x00;
725 mbuf[2] = 0x00;
726 mbuf[3] = 0x00;
727 oscam_ser_send(cur_client(), mbuf, 4);
728 break;
730 serialdata->dsr9500type = P_DSR_AUTO;
731 serialdata->serial_errors = 0;
734 static void oscam_ser_init_client(void)
736 uchar mbuf[4];
737 switch(cur_client()->serialdata->oscam_ser_proto) // sure, does not work in auto-mode
739 case P_GS:
740 oscam_ser_disconnect_client(); // send disconnect first
741 cs_sleepms(300); // wait a little bit
742 mbuf[0] = 0x00;
743 mbuf[1] = 0x00;
744 mbuf[2] = 0x00;
745 mbuf[3] = 0x00;
746 oscam_ser_send(cur_client(), mbuf, 4); // send connect
747 break;
751 static void oscam_ser_disconnect(void)
753 oscam_ser_disconnect_client();
754 if(cur_client()->serialdata->connected)
755 { cs_log("%s disconnected (%s)", username(cur_client()), proto_txt[cur_client()->serialdata->connected]); }
756 cur_client()->serialdata->connected = 0;
759 static void oscam_ser_auth_client(int32_t proto)
761 int32_t ok = 0;
762 struct s_serial_client *serialdata = cur_client()->serialdata;
763 // After reload base account ptrs may be placed in other address,
764 // and we may can't find it in this process.
765 // Simply save valid account.
766 struct s_auth *account = 0;
768 if(serialdata->connected == proto)
769 { return; }
770 if(serialdata->connected)
771 { oscam_ser_disconnect(); }
772 serialdata->connected = proto;
774 for(ok = 0, account = cfg.account; (account) && (!ok); account = account->next)
775 if((ok = !strcmp(serialdata->oscam_ser_usr, account->usr)))
776 { break; }
777 cs_auth_client(cur_client(), ok ? account : (struct s_auth *)(-1), proto_txt[serialdata->connected]);
780 static void oscam_ser_send_dcw(struct s_client *client, ECM_REQUEST *er)
782 uchar mbuf[23];
783 int32_t i;
784 uchar crc;
785 struct s_serial_client *serialdata = cur_client()->serialdata;
786 if(er->rc < E_NOTFOUND) // found
787 switch(serialdata->connected)
789 case P_HSIC:
790 for(i = 0, crc = HSIC_CRC; i < 16; i++)
791 { crc ^= er->cw[i]; }
792 memset(mbuf , 0x04 , 2);
793 memset(mbuf + 2 , 0x3a , 2);
794 memcpy(mbuf + 4 , er->cw, 16);
795 memcpy(mbuf + 20, &crc , 1);
796 memset(mbuf + 21, 0x1b , 2);
797 oscam_ser_send(client, mbuf, 23);
798 break;
799 case P_SSSP:
800 mbuf[0] = 0xF2;
801 mbuf[1] = 0;
802 mbuf[2] = 16;
803 memcpy(mbuf + 3, er->cw, 16);
804 oscam_ser_send(client, mbuf, 19);
805 if(!serialdata->sssp_fix)
807 mbuf[0] = 0xF1;
808 mbuf[1] = 0;
809 mbuf[2] = 2;
810 i2b_buf(2, er->pid, mbuf + 3);
811 oscam_ser_send(client, mbuf, 5);
812 serialdata->sssp_fix = 1;
814 break;
815 case P_GBOX:
816 case P_BOMBA:
817 oscam_ser_send(client, er->cw, 16);
818 break;
819 case P_DSR95:
820 mbuf[0] = 4;
821 memcpy(mbuf + 1, er->cw, 16);
822 oscam_ser_send(client, mbuf, 17);
823 if(serialdata->dsr9500type == P_DSR_GNUSMAS)
825 serialdata->samsung_0a = 0;
826 for(i = 1; i < 17; i++)
827 if(mbuf[i] == 0x0A)
828 { serialdata->samsung_0a++; }
829 serialdata->samsung_dcw++;
831 break;
832 case P_GS:
833 mbuf[0] = 0x03;
834 mbuf[1] = 0x08;
835 mbuf[2] = 0x10;
836 mbuf[3] = 0x00;
837 memcpy(mbuf + 4, er->cw, 16);
838 oscam_ser_send(client, mbuf, 20);
839 break;
840 case P_ALPHA:
841 mbuf[0] = 0x88;
842 mbuf[1] = 0x00;
843 mbuf[2] = 0x10;
844 memcpy(mbuf + 3, er->cw, 16);
845 oscam_ser_send(client, mbuf, 19);
846 break;
848 else // not found
849 switch(serialdata->connected)
851 case P_GS:
852 mbuf[0] = 0x03;
853 mbuf[1] = 0x09;
854 mbuf[2] = 0x00;
855 mbuf[3] = 0x00;
856 oscam_ser_send(client, mbuf, 4);
857 break;
859 serialdata->serial_errors = 0; // clear error counter
862 static void oscam_ser_process_pmt(uchar *buf, int32_t l)
864 int32_t i;
865 uchar sbuf[32];
866 struct s_serial_client *serialdata = cur_client()->serialdata;
867 switch(serialdata->connected)
869 case P_SSSP:
870 serialdata->sssp_fix = 0;
871 memset(serialdata->sssp_tab, 0, sizeof(serialdata->sssp_tab));
872 serialdata->sssp_srvid = b2i(2, buf + 3);
873 serialdata->sssp_num = 0;
876 for(i = 9; (i < l) && (serialdata->sssp_num < SSSP_MAX_PID); i += 7)
878 if(chk_ser_srvid(cur_client(), b2i(2, buf + i), b2i(2, buf + 3), b2i(3, buf + i + 4))) // check support for pid (caid, sid and provid in oscam.services)
880 memcpy(sbuf + 3 + (serialdata->sssp_num << 1), buf + i + 2, 2);
881 serialdata->sssp_tab[serialdata->sssp_num].caid = b2i(2, buf + i);
882 serialdata->sssp_tab[serialdata->sssp_num].pid = b2i(2, buf + i + 2);
883 serialdata->sssp_tab[serialdata->sssp_num].prid = b2i(3, buf + i + 4);
884 serialdata->sssp_num++;
887 sbuf[0] = 0xF1;
888 sbuf[1] = 0;
889 sbuf[2] = (serialdata->sssp_num << 1);
890 oscam_ser_send(cur_client(), sbuf, sbuf[2] + 3);
891 break;
895 static void oscam_ser_client_logon(uchar *buf, int32_t l)
897 uchar gs_logon[] = {0, 1, 0, 0, 2, 1, 0, 0};
898 switch(cur_client()->serialdata->connected)
900 case P_GS:
901 if((l >= 8) && (!memcmp(buf, gs_logon, 8)))
903 buf[0] = 0x02;
904 buf[1] = 0x04;
905 buf[2] = 0x00;
906 buf[3] = 0x00;
907 oscam_ser_send(cur_client(), buf, 4);
909 break;
913 static int32_t oscam_ser_check_ecm(ECM_REQUEST *er, uchar *buf, int32_t l)
915 int32_t i;
916 struct s_serial_client *serialdata = cur_client()->serialdata;
918 if(l < 16)
920 cs_log("incomplete request (%d bytes)", l);
921 return (1);
924 switch(serialdata->connected)
926 case P_HSIC:
927 er->ecmlen = l - 12;
928 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE)
929 { return (3); }
930 er->caid = b2i(2, buf + 1);
931 er->prid = b2i(3, buf + 3);
932 er->pid = b2i(2, buf + 6);
933 er->srvid = b2i(2, buf + 10);
934 memcpy(er->ecm, buf + 12, er->ecmlen);
935 break;
936 case P_SSSP:
937 er->pid = b2i(2, buf + 3);
938 for(i = 0; (i < 8) && (serialdata->sssp_tab[i].pid != er->pid); i++) { ; }
939 if(i >= serialdata->sssp_num)
941 cs_log_dbg(D_CLIENT, "illegal request, unknown pid=%04X", er->pid);
942 return (2);
944 er->ecmlen = l - 5;
945 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE)
946 { return (3); }
947 er->srvid = serialdata->sssp_srvid;
948 er->caid = serialdata->sssp_tab[i].caid;
949 er->prid = serialdata->sssp_tab[i].prid;
950 memcpy(er->ecm, buf + 5, er->ecmlen);
951 break;
952 case P_BOMBA:
953 er->ecmlen = l;
954 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE)
955 { return (3); }
956 memcpy(er->ecm, buf, er->ecmlen);
957 break;
958 case P_DSR95:
959 buf[l] = '\0'; // prepare for trim
960 trim((char *)buf + 13); // strip spc, nl, cr ...
961 er->ecmlen = strlen((char *)buf + 13) >> 1;
962 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE)
963 { return (3); }
964 er->prid = cs_atoi((char *)buf + 3, 3, 0); // ignore errors
965 er->caid = cs_atoi((char *)buf + 9, 2, 0); // ignore errors
966 if(cs_atob(er->ecm, (char *)buf + 13, er->ecmlen) < 0)
968 cs_log("illegal characters in ecm-request");
969 return (1);
971 if(serialdata->dsr9500type == P_DSR_WITHSID)
973 er->ecmlen -= 2;
974 if(er->ecmlen < 0)
975 { return (3); }
976 er->srvid = cs_atoi((char *)buf + 13 + (er->ecmlen << 1), 2, 0);
978 break;
979 case P_GS:
980 er->ecmlen = ((buf[3] << 8) | buf[2]) - 6;
981 er->srvid = (buf[5] << 8) | buf[4]; // sid
982 er->caid = (buf[7] << 8) | buf[6];
983 er->prid = 0;
985 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE || (10 + er->ecmlen > l))
986 { return (3); }
988 memcpy(er->ecm, buf + 10, er->ecmlen);
989 break;
990 case P_ALPHA:
991 l = oscam_ser_alpha_convert(buf, l);
992 er->ecmlen = b2i(2, buf + 1) - 2;
993 er->caid = b2i(2, buf + 3);
994 if((er->ecmlen != l - 5) || (er->ecmlen > MAX_ECM_SIZE) || (er->ecmlen < 0))
996 cs_log("incomplete request (%d bytes)", l);
997 return (1);
999 memcpy(er->ecm, buf + 5, er->ecmlen);
1000 break;
1001 case P_GBOX:
1002 if(((serialdata->gbox_lens.cat_len + 3 + 3 + 1) > l)
1003 || ((serialdata->gbox_lens.ecm_len + 3) > l))
1005 return (3);
1007 er->srvid = b2i(2, buf + serialdata->gbox_lens.cat_len + 3 + 3);
1008 er->ecmlen = serialdata->gbox_lens.ecm_len + 3;
1010 if(er->ecmlen < 0 || er->ecmlen > MAX_ECM_SIZE)
1011 { return (3); }
1012 if(serialdata->gbox_lens.cat_len + 3 + serialdata->gbox_lens.pmt_len + 3 + er->ecmlen > l)
1013 { return (3); }
1015 memcpy(er->ecm, buf + serialdata->gbox_lens.cat_len + 3 + serialdata->gbox_lens.pmt_len + 3, er->ecmlen);
1016 break;
1018 return (0);
1021 static void oscam_ser_process_ecm(uchar *buf, int32_t l)
1023 ECM_REQUEST *er;
1025 if(!(er = get_ecmtask()))
1026 { return; }
1028 switch(oscam_ser_check_ecm(er, buf, l))
1030 default:
1031 case 3:
1032 case 2:
1033 //er->rc = E_CORRUPT;
1034 NULLFREE(er);
1035 return; // error without log
1036 case 1:
1037 er->rc = E_CORRUPT; // error with log
1038 break;
1040 get_cw(cur_client(), er);
1044 static void oscam_ser_server(void)
1046 int32_t n;
1047 uchar mbuf[1024];
1049 int32_t *pserial_errors = &cur_client()->serialdata->serial_errors;
1051 cur_client()->serialdata->connected = 0;
1052 oscam_ser_init_client();
1054 while((n = process_input(mbuf, sizeof(mbuf), INT_MAX)) > 0)
1056 if((*pserial_errors) > 3)
1058 cs_log("too many errors, reiniting...");
1059 break;
1061 oscam_ser_auth_client(mbuf[0] & 0xF);
1062 switch(mbuf[0] >> 4)
1064 case IS_ECM:
1065 oscam_ser_process_ecm(mbuf + 1, n - 1);
1066 break;
1067 case IS_PMT:
1068 oscam_ser_process_pmt(mbuf + 1, n - 1);
1069 break;
1070 case IS_LGO:
1071 oscam_ser_client_logon(mbuf + 1, n - 1);
1072 break;
1075 if(cur_client()->serialdata->oscam_ser_port > 0)
1076 { network_tcp_connection_close(cur_client()->reader, "error reading from socket"); }
1077 oscam_ser_disconnect();
1080 static int32_t init_oscam_ser_device(struct s_client *cl)
1082 char *device = cl->serialdata->oscam_ser_device;
1083 speed_t baud = cl->serialdata->oscam_ser_baud;
1084 int32_t port = cl->serialdata->oscam_ser_port;
1085 int32_t fd;
1087 // network connection to a TCP-exposed serial port
1088 if(port > 0)
1090 cs_strncpy(cl->reader->device, device, sizeof(cl->reader->device));
1091 cl->reader->r_port = cl->port = port;
1092 fd = network_tcp_connection_open(cl->reader);
1093 if(fd < 0)
1094 { return 0; }
1095 else
1096 { return fd; }
1098 else // standard serial port connection
1100 fd = open(device, O_RDWR | O_NOCTTY | O_SYNC | O_NONBLOCK);
1101 if(fd > 0)
1103 fcntl(fd, F_SETFL, 0);
1104 if(oscam_ser_set_serial_device(fd, baud) < 0) { cs_log("ERROR ioctl"); }
1105 if(tcflush(fd, TCIOFLUSH) < 0) { cs_log("ERROR flush"); }
1107 else
1109 fd = 0;
1110 cs_log("ERROR opening %s (errno=%d %s)", device, errno, strerror(errno));
1112 return (fd);
1116 static void oscam_copy_serialdata(struct s_serial_client *dest, struct s_serial_client *src)
1118 if(dest && src)
1120 dest->connected = src->connected;
1121 memcpy(&dest->tps, &src->tps, sizeof(dest->tps));
1122 memcpy(&dest->tpe, &src->tpe, sizeof(dest->tpe));
1123 memcpy(&dest->oscam_ser_usr, &src->oscam_ser_usr, sizeof(dest->oscam_ser_usr));
1124 memcpy(&dest->oscam_ser_device, &src->oscam_ser_device, sizeof(dest->oscam_ser_device));
1125 dest->oscam_ser_port = src->oscam_ser_port;
1126 dest->oscam_ser_baud = src->oscam_ser_baud;
1127 dest->oscam_ser_delay = src->oscam_ser_delay;
1128 dest->oscam_ser_timeout = src->oscam_ser_timeout;
1129 dest->oscam_ser_proto = src->oscam_ser_proto;
1130 dest->serial_errors = src->serial_errors;
1131 dest->dsr9500type = src->dsr9500type;
1132 dest->samsung_0a = src->samsung_0a; // number of 0A in ALL dcw sent into samsung
1133 dest->samsung_dcw = src->samsung_dcw; // number of dcw sent into samsung before echo or ecm is received
1135 dest->gbox_lens = src->gbox_lens;
1136 memcpy(&dest->sssp_tab, &src->sssp_tab, sizeof(dest->sssp_tab));
1137 dest->sssp_srvid = src->sssp_srvid;
1138 dest->sssp_num = src->sssp_num;
1139 dest->sssp_fix = src->sssp_fix;
1143 static void oscam_init_serialdata(struct s_serial_client *dest)
1145 if(dest)
1147 memset(dest, 0, sizeof(struct s_serial_client));
1148 dest->oscam_ser_timeout = 50;
1149 dest->dsr9500type = P_DSR_AUTO;
1153 static void *oscam_ser_fork(void *pthreadparam)
1155 struct s_thread_param *pparam = (struct s_thread_param *) pthreadparam;
1156 struct s_client *cl = create_client(get_null_ip());
1157 SAFE_SETSPECIFIC(getclient, cl);
1158 cl->thread = pthread_self();
1159 cl->typ = 'c';
1160 cl->module_idx = pparam->module_idx;
1161 cl->account = first_client->account;
1163 if(!cl->serialdata && !cs_malloc(&cl->serialdata, sizeof(struct s_serial_client)))
1164 { return NULL; }
1166 set_thread_name(__func__);
1167 oscam_init_serialdata(cl->serialdata);
1168 oscam_copy_serialdata(cl->serialdata, &pparam->serialdata);
1169 if(cl->serialdata->oscam_ser_port > 0)
1171 // reader struct for serial network connection
1172 struct s_reader *newrdr;
1173 if(!cs_malloc(&newrdr, sizeof(struct s_reader)))
1174 { return NULL; }
1175 memset(newrdr, 0, sizeof(struct s_reader));
1176 newrdr->client = cl;
1177 newrdr->ph = *serial_ph;
1178 cl->reader = newrdr;
1179 cs_strncpy(cl->reader->label, "network-socket", sizeof(cl->reader->label));
1181 cs_log("serial: initialized (%s@%s)", cl->serialdata->oscam_ser_proto > P_MAX ?
1182 "auto" : proto_txt[cl->serialdata->oscam_ser_proto], cl->serialdata->oscam_ser_device);
1184 SAFE_MUTEX_LOCK(&mutex);
1185 bcopy_end = 1;
1186 SAFE_MUTEX_UNLOCK(&mutex);
1187 SAFE_COND_SIGNAL(&cond);
1189 while(!exit_oscam)
1191 cl->login = time((time_t *)0);
1192 cl->pfd = init_oscam_ser_device(cl);
1193 if(cl->pfd)
1194 { oscam_ser_server(); }
1195 else
1196 { cs_sleepms(60000); } // retry in 1 min. (USB-Device ?)
1197 if(cl->pfd) { close(cl->pfd); }
1199 NULLFREE(cl->serialdata);
1200 NULLFREE(cl->reader);
1201 return NULL;
1204 void *init_oscam_ser(struct s_client *UNUSED(cl), uchar *UNUSED(mbuf), int32_t module_idx)
1206 char sdevice[512];
1207 int32_t ret;
1208 struct s_thread_param param;
1209 oscam_init_serialdata(&param.serialdata);
1210 if(cfg.ser_device)
1211 { cs_strncpy(sdevice, cfg.ser_device, sizeof(sdevice)); }
1212 else
1213 { memset(sdevice, 0, sizeof(sdevice)); }
1214 param.module_idx = module_idx;
1215 char *p;
1216 char cltype = 'c'; //now auto should work
1217 if(bcopy_end == -1) //mutex should be initialized only once
1219 cs_pthread_cond_init(__func__, &mutex, &cond);
1220 bcopy_end = 0;
1222 while((p = strrchr(sdevice, ';')))
1224 *p = 0;
1225 if(!(p + 1) || (!(p + 1)[0])) { return NULL; }
1226 if(!oscam_ser_parse_url(p + 1, &param.serialdata, &cltype)) { return NULL; }
1227 ret = start_thread("oscam_ser_fork", oscam_ser_fork, (void *) &param, NULL, 1, 1);
1228 if(ret)
1230 return NULL;
1232 else
1234 oscam_wait_ser_fork();
1238 if(!sdevice[0]) { return NULL; }
1239 if(!oscam_ser_parse_url(sdevice, &param.serialdata, &cltype)) { return NULL; }
1240 ret = start_thread("oscam_ser_fork", oscam_ser_fork, (void *) &param, NULL, 1, 1);
1241 if(ret)
1243 return NULL;
1245 else
1247 oscam_wait_ser_fork();
1249 return NULL;
1253 * client functions
1256 static int32_t oscam_ser_client_init(struct s_client *client)
1258 if(!client->serialdata && !cs_malloc(&client->serialdata, sizeof(struct s_serial_client)))
1259 { return 1; }
1261 oscam_init_serialdata(client->serialdata);
1263 if((!client->reader->device[0])) { cs_disconnect_client(client); }
1264 if(!oscam_ser_parse_url(client->reader->device, client->serialdata, NULL)) { cs_disconnect_client(client); }
1265 client->pfd = init_oscam_ser_device(client);
1267 if(client->serialdata->oscam_ser_proto == P_TWIN)
1269 if(client->pfd > 0)
1271 client->reader->tcp_connected = 1;
1272 client->reader->card_status = CARD_INSERTED;
1276 return ((client->pfd > 0) ? 0 : 1);
1279 static int32_t oscam_ser_twin_send(struct s_client *client, ECM_REQUEST *er)
1281 struct ecmtw tw;
1282 tw = get_twin(er);
1283 cs_debug_mask(D_CLIENT, "found channel: %04X:%06X:%04X:%04X:%04X", tw.caid, tw.provid, tw.deg, tw.freq, tw.srvid);
1284 uint8_t wbuf[32];
1285 wbuf[0] = 7;
1286 wbuf[1] = 6;
1287 wbuf[2] = tw.deg>>8;
1288 wbuf[3] = tw.deg&0xff;
1289 wbuf[4] = tw.freq>>8;
1290 wbuf[5] = tw.freq&0xff;
1291 wbuf[6] = tw.srvid>>8;
1292 wbuf[7] = tw.srvid&0xff;
1293 wbuf[8] = wbuf[0]^wbuf[1]^wbuf[2]^wbuf[3]^wbuf[4]^wbuf[5]^wbuf[6]^wbuf[7];
1294 oscam_ser_send(client, wbuf, 9);
1295 return(0);
1298 static int32_t oscam_ser_send_ecm(struct s_client *client, ECM_REQUEST *er)
1300 char *tmp;
1301 uchar *buf;
1302 if(!cs_malloc(&buf, er->ecmlen + 12))
1304 return(-1);
1307 switch(client->serialdata->oscam_ser_proto)
1309 case P_HSIC:
1310 memset(buf, 0, 12);
1311 buf[0] = 2;
1312 i2b_buf(2, er->caid, buf + 1);
1313 i2b_buf(3, er->prid, buf + 3);
1314 i2b_buf(2, er->pid, buf + 6);
1315 i2b_buf(2, er->srvid, buf + 10);
1316 memcpy(buf + 12, er->ecm, er->ecmlen);
1317 oscam_ser_send(client, buf, 12 + er->ecmlen);
1318 break;
1319 case P_BOMBA:
1320 oscam_ser_send(client, er->ecm, er->ecmlen);
1321 break;
1322 case P_DSR95:
1323 if(cs_malloc(&tmp, er->ecmlen * 2 + 1))
1325 if(client->serialdata->dsr9500type == P_DSR_WITHSID)
1327 snprintf((char *)buf, 512, "%c%08X%04X%s%04X\n\r",
1328 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1), er->srvid);
1329 oscam_ser_send(client, buf, (er->ecmlen << 1) + 19); // 1 + 8 + 4 + l*2 + 4 + 2
1331 else
1333 snprintf((char *)buf, 512, "%c%08X%04X%s\n\r",
1334 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1));
1335 oscam_ser_send(client, buf, (er->ecmlen << 1) + 15); // 1 + 8 + 4 + l*2 + 2
1337 NULLFREE(tmp);
1339 break;
1340 case P_ALPHA:
1341 buf[0] = 0x80;
1342 i2b_buf(2, 2 + er->ecmlen, buf + 1);
1343 i2b_buf(2, er->caid, buf + 3);
1344 memcpy(buf + 5, er->ecm, er->ecmlen);
1345 oscam_ser_send(client, buf, oscam_ser_alpha_convert(buf, 5 + er->ecmlen));
1346 break;
1347 case P_TWIN:
1348 oscam_ser_twin_send(client, er);
1349 break;
1351 NULLFREE(buf);
1352 return (0);
1355 static void oscam_ser_process_dcw(uchar *dcw, int32_t *rc, uchar *buf, int32_t l, struct s_client *client)
1357 switch(client->serialdata->oscam_ser_proto)
1359 case P_HSIC:
1360 if((l >= 23) && (buf[2] == 0x3A) && (buf[3] == 0x3A))
1362 int32_t i;
1363 uchar crc;
1364 for(i = 4, crc = HSIC_CRC; i < 20; i++)
1365 { crc ^= buf[i]; }
1366 if(crc == buf[20])
1368 memcpy(dcw, buf + 4, 16);
1369 *rc = 1;
1372 break;
1373 case P_BOMBA:
1374 if(l >= 16)
1376 memcpy(dcw, buf, 16);
1377 *rc = 1;
1379 break;
1380 case P_DSR95:
1381 if((l >= 17) && (buf[0] == 4))
1383 memcpy(dcw, buf + 1, 16);
1384 *rc = 1;
1386 break;
1387 case P_ALPHA:
1388 if((l >= 19) && (buf[0] == 0x88))
1390 memcpy(dcw, buf + 3, 16);
1391 *rc = 1;
1393 break;
1394 case P_TWIN:
1395 if ((l >= 19) && (buf[0] == 0xF7))
1397 memcpy(dcw, buf + 3, 16);
1398 *rc = 1;
1403 static int32_t oscam_ser_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n)
1405 *rc = (-1);
1406 switch(buf[0] >> 4)
1408 case IS_DCW:
1409 oscam_ser_process_dcw(dcw, rc, buf + 1, n - 1, client);
1410 break;
1412 return ((*rc < 0) ? (-1) : 0); // idx not supported in serial module
1416 * protocol structure
1419 void module_serial(struct s_module *ph)
1421 ph->desc = "serial";
1422 ph->type = MOD_CONN_SERIAL;
1423 ph->large_ecm_support = 1;
1424 ph->listenertype = LIS_SERIAL;
1425 ph->s_handler = init_oscam_ser;
1426 ph->recv = oscam_ser_recv;
1427 ph->send_dcw = oscam_ser_send_dcw;
1428 ph->c_init = oscam_ser_client_init;
1429 ph->c_recv_chk = oscam_ser_recv_chk;
1430 ph->c_send_ecm = oscam_ser_send_ecm;
1431 ph->num = R_SERIAL;
1432 serial_ph = ph;
1434 #endif