source: trunk/reader-videoguard1.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: 15.1 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include "globals.h"
3#include "reader-common.h"
4#include "reader-videoguard-common.h"
5
6
7static int vg1_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
8{
9 ushort cta_lr;
10 unsigned char ins2[5];
11 memcpy(ins2, ins, 5);
12 unsigned char len = 0;
13 len = ins2[4];
14
15 unsigned char tmp[264];
16 if (!rxbuff) {
17 rxbuff = tmp;
18 }
19
20 if (txbuff == NULL) {
21 if (!write_cmd_vg(ins2, NULL) || !status_ok(cta_res + len)) {
22 return -1;
23 }
24 memcpy(rxbuff, ins2, 5);
25 memcpy(rxbuff + 5, cta_res, len);
26 memcpy(rxbuff + 5 + len, cta_res + len, 2);
27 } else {
28 if (!write_cmd_vg(ins2, (uchar *) txbuff) || !status_ok(cta_res)) {
29 return -2;
30 }
31 memcpy(rxbuff, ins2, 5);
32 memcpy(rxbuff + 5, txbuff, len);
33 memcpy(rxbuff + 5 + len, cta_res, 2);
34 }
35
36 return len;
37}
38
39static void read_tiers(struct s_reader *reader)
40{
41 def_resp;
42// static const unsigned char ins2a[5] = { 0x48, 0x2a, 0x00, 0x00, 0x00 };
43 int l;
44
45// return; // Not working at present so just do nothing
46
47// l = vg1_do_cmd(reader, ins2a, NULL, NULL, cta_res);
48// if (l < 0 || !status_ok(cta_res + l))
49// {
50// return;
51// }
52 static unsigned char ins76[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
53 ins76[3] = 0x7f;
54 ins76[4] = 2;
55 if (!write_cmd_vg(ins76, NULL) || !status_ok(cta_res + 2)) {
56 return;
57 }
58 ins76[3] = 0;
59 ins76[4] = 0x0a;
60 int num = cta_res[1];
61 int i;
62#ifdef CS_RDR_INIT_HIST
63 reader->init_history_pos = 0; //reset for re-read
64 memset(reader->init_history, 0, sizeof(reader->init_history));
65#endif
66 for (i = 0; i < num; i++) {
67 ins76[2] = i;
68 l = vg1_do_cmd(reader, ins76, NULL, NULL, cta_res);
69 if (l < 0 || !status_ok(cta_res + l)) {
70 return;
71 }
72 if (cta_res[2] == 0 && cta_res[3] == 0) {
73 break;
74 }
75 int y, m, d, H, M, S;
76 rev_date_calc(&cta_res[4], &y, &m, &d, &H, &M, &S, reader->card_baseyear);
77 unsigned short tier_id = (cta_res[2] << 8) | cta_res[3];
78 char *tier_name = get_tiername(tier_id, reader->caid[0]);
79 cs_ri_log(reader, "[videoguard1-reader] tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, y, m, d, H, M, S, tier_name);
80 }
81}
82
83int videoguard1_card_init(struct s_reader *reader, ATR newatr)
84{
85
86 get_hist;
87 /* 40 B0 09 4A 50 01 4E 5A */
88 if ((hist_size < 7) || (hist[1] != 0xB0) || (hist[3] != 0x4A) || (hist[4] != 0x50)) {
89 return ERROR;
90 }
91
92 get_atr;
93 def_resp;
94
95 // Copy the atr info into the reader, can we not do this in reader-common.c?
96 reader->atrlen = atr_size;
97 memcpy(reader->atr,atr,atr_size);
98
99 /* set information on the card stored in reader-videoguard-common.c */
100 set_known_card_info(reader);
101
102 if((reader->ndsversion != NDS1) && ((reader->card_system_version != NDS1) || (reader->ndsversion != NDSAUTO))) {
103 /* known ATR and not NDS1
104 or unknown ATR and not forced to NDS1
105 or known NDS1 ATR and forced to another NDS version
106 ... probably not NDS1 */
107 return ERROR;
108 }
109
110 cs_ri_log(reader, "[videoguard1-reader] type: %s, baseyear: %i", reader->card_desc, reader->card_baseyear);
111 if(reader->ndsversion == NDS1){
112 cs_log("[videoguard1-reader] forced to NDS1+");
113 }
114
115 /* NDS1 Class 48 only cards only need a very basic initialisation
116 NDS1 Class 48 only cards do not respond to vg1_do_cmd(ins7416)
117 nor do they return list of valid command therefore do not even try
118 NDS1 Class 48 only cards need to be told the length as (48, ins, 00, 80, 01)
119 does not return the length */
120
121 int l = 0;
122 unsigned char buff[256];
123
124 /* Try to get the boxid from the card, even if BoxID specified in the config file
125 also used to check if it is an NDS1 card as the returned information will
126 not be encrypted if it is an NDS1 card */
127
128 unsigned char ins36[5] = { 0x48, 0x36, 0x00, 0x00, 0x90 };
129 unsigned char boxID[4];
130 int boxidOK = 0;
131 l = vg1_do_cmd(reader, ins36, NULL, buff, cta_res);
132 if (buff[7] > 0x0F) {
133 cs_log("[videoguard1-reader] class48 ins36: encrypted - therefore not an NDS1 card");
134 return ERROR;
135 } else {
136 /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
137 int i = 9;
138 int gotUA = 0;
139 while (i < l) {
140 if (!gotUA && buff[i] < 0xF0) { /* then we guess that the next 4 bytes is the UA */
141 gotUA = 1;
142 i += 4;
143 } else {
144 switch (buff[i]) { /* object length vary depending on type */
145 case 0x00: /* padding */
146 {
147 i += 1;
148 break;
149 }
150 case 0xEF: /* card status */
151 {
152 i += 3;
153 break;
154 }
155 case 0xD1:
156 {
157 i += 4;
158 break;
159 }
160 case 0xDF: /* next server contact */
161 {
162 i += 5;
163 break;
164 }
165 case 0xF3: /* boxID */
166 {
167 memcpy(&boxID, &buff[i + 1], sizeof(boxID));
168 boxidOK = 1;
169 i += 5;
170 break;
171 }
172 case 0xF6:
173 {
174 i += 6;
175 break;
176 }
177 case 0xFC: /* No idea seems to with with NDS1 */
178 {
179 i += 14;
180 break;
181 }
182 case 0x01: /* date & time */
183 {
184 i += 7;
185 break;
186 }
187 case 0xFA:
188 {
189 i += 9;
190 break;
191 }
192 case 0x5E:
193 case 0x67: /* signature */
194 case 0xDE:
195 case 0xE2:
196 case 0xE9: /* tier dates */
197 case 0xF8: /* Old PPV Event Record */
198 case 0xFD:
199 {
200 i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
201 break;
202 }
203 default: /* default to assume a length byte */
204 {
205 cs_log("[videoguard1-reader] class48 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
206 i += buff[i + 1] + 2;
207 }
208 }
209 }
210 }
211 }
212
213 // cs_log("[videguard1nz-reader] calculated BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
214
215 /* the boxid is specified in the config */
216 if (reader->boxid > 0) {
217 int i;
218 for (i = 0; i < 4; i++) {
219 boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
220 }
221 // cs_log("[videguard1nz-reader] config BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
222 }
223
224 if (!boxidOK) {
225 cs_log("[videoguard1-reader] no boxID available");
226 return ERROR;
227 }
228
229 // Send BoxID
230 unsigned char ins4C[5] = { 0x48, 0x4C, 0x00, 0x00, 0x09 };
231 unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
232 memcpy(payload4C, boxID, 4);
233 if (!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l)) {
234 cs_log("[videoguard1-reader] class48 ins4C: sending boxid failed");
235 return ERROR;
236 }
237
238 unsigned char ins58[5] = { 0x48, 0x58, 0x00, 0x00, 0x17 };
239 l = vg1_do_cmd(reader, ins58, NULL, buff, cta_res);
240 if (l < 0) {
241 cs_log("[videoguard1-reader] class48 ins58: failed");
242 return ERROR;
243 }
244
245 memset(reader->hexserial, 0, 8);
246 memcpy(reader->hexserial + 2, cta_res + 1, 4);
247 memcpy(reader->sa, cta_res + 1, 3);
248 // reader->caid[0] = cta_res[24] * 0x100 + cta_res[25];
249 /* Force caid until can figure out how to get it */
250 reader->caid[0] = 0x9 * 0x100 + 0x69;
251
252 /* we have one provider, 0x0000 */
253 reader->nprov = 1;
254 memset(reader->prid, 0x00, sizeof(reader->prid));
255
256 cs_ri_log(reader,
257 "[videoguard1-reader] type: VideoGuard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
258 reader->caid[0], reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], boxID[0], boxID[1], boxID[2], boxID[3]);
259 cs_log("[videoguard1-reader] ready for requests - this is in testing please send -d 255 logs");
260
261 return OK;
262}
263
264int videoguard1_do_ecm(struct s_reader *reader, ECM_REQUEST * er)
265{
266 unsigned char cta_res[CTA_RES_LEN];
267 static unsigned char ins40[5] = { 0x48, 0x40, 0x00, 0x80, 0xFF };
268 static const unsigned char ins54[5] = { 0x48, 0x54, 0x00, 0x00, 0x0D };
269 int posECMpart2 = er->ecm[6] + 7;
270 int lenECMpart2 = er->ecm[posECMpart2];
271 unsigned char tbuff[264];
272 unsigned char rbuff[264];
273 memcpy(&tbuff[0], &(er->ecm[posECMpart2 + 1]), lenECMpart2 - 1);
274 ins40[4] = lenECMpart2;
275 int l;
276 l = vg1_do_cmd(reader, ins40, tbuff, NULL, cta_res);
277 if (l > 0 && status_ok(cta_res)) {
278 l = vg1_do_cmd(reader, ins54, NULL, rbuff, cta_res);
279 if (l > 0 && status_ok(cta_res + l)) {
280 if (!cw_is_valid(rbuff+5,0)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
281 {
282 cs_log("[videoguard1-reader] class48 ins54 status 90 00 but cw=00 -> channel not subscribed");
283 return ERROR;
284 }
285
286 if(er->ecm[0]&1) {
287 memset(er->cw+0, 0, 8);
288 memcpy(er->cw+8, rbuff + 5, 8);
289 } else {
290 memcpy(er->cw+0, rbuff + 5, 8);
291 memset(er->cw+8, 0, 8);
292 }
293 return OK;
294 }
295 }
296 cs_log("[videoguard1-reader] class48 ins54 (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
297 return ERROR;
298}
299
300static int num_addr(const unsigned char *data)
301{
302 return ((data[3] & 0x30) >> 4) + 1;
303}
304
305/*
306Example of GLOBAL EMM's
307This one has IRD-EMM + Card-EMM
30882 70 20 00 02 06 02 7D 0E 89 53 71 16 90 14 40
30901 ED 17 7D 9E 1F 28 CF 09 97 54 F1 8E 72 06 E7
31051 AF F5
311This one has only IRD-EMM
31282 70 6D 00 07 69 01 30 07 14 5E 0F FF FF 00 06
31300 0D 01 00 03 01 00 00 00 0F 00 00 00 5E 01 00
31401 0C 2E 70 E4 55 B6 D2 34 F7 44 86 9E 5C 91 14
31581 FC DF CB D0 86 65 77 DF A9 E1 6B A8 9F 9B DE
31690 92 B9 AA 6C B3 4E 87 D2 EC 92 DA FC 71 EF 27
317B3 C3 D0 17 CF 0B D6 5E 8C DB EB B3 37 55 6E 09
3187F 27 3C F1 85 29 C9 4E 0B EE DF 68 BE 00 C9 00
319*/
320static const unsigned char *payload_addr(uchar emmtype, const unsigned char *data, const unsigned char *a)
321{
322 int s;
323 int l;
324 const unsigned char *ptr = NULL;
325 int position = -1;
326 int numAddrs = 0;
327 switch (emmtype) {
328 case SHARED:
329 {
330 s = 3;
331 break;
332 }
333 case UNIQUE:
334 {
335 s = 4;
336 break;
337 }
338 default:
339 {
340 s = 0;
341 }
342 }
343
344 numAddrs = num_addr(data);
345 if (s > 0) {
346 for (l = 0; l < numAddrs; l++) {
347 if (!memcmp(&data[l * 4 + 4], a + 2, s)) {
348 position = l;
349 break;
350 }
351 }
352 }
353
354 int num_filter = (position == -1) ? 0 : numAddrs;
355 /* skip header and the filter list */
356 ptr = data + 4 + 4 * num_filter;
357 if (*ptr != 0x02 && *ptr != 0x07) // some clients omit 00 00 separator */
358 {
359 ptr += 2; // skip 00 00 separator
360 if (*ptr == 0x00)
361 ptr++; // skip optional 00
362 ptr++; // skip the 1st bitmap len
363 }
364
365 /* check for IRD-EMM */
366 if (*ptr != 0x02 && *ptr != 0x07) {
367 return NULL;
368 }
369
370 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
371 ptr += 2 + ptr[1];
372 /* check for EMM boundaries - ptr should not exceed EMM length */
373 if ((int) (ptr - (data + 3)) >= data[2]) {
374 return NULL;
375 }
376
377 for (l = 0; l < position; l++) {
378 /* skip the payload of the previous sub-EMM */
379 ptr += 1 + ptr[0];
380 /* check for EMM boundaries - ptr should not exceed EMM length */
381 if ((int) (ptr - (data + 3)) >= data[2]) {
382 return NULL;
383 }
384
385 /* skip optional 00 */
386 if (*ptr == 0x00) {
387 ptr++;
388 }
389
390 /* skip the bitmap len */
391 ptr++;
392 /* check for IRD-EMM */
393 if (*ptr != 0x02 && *ptr != 0x07) {
394 return NULL;
395 }
396
397 /* skip IRD-EMM part, 02 00 or 02 06 xx aabbccdd yy */
398 ptr += 2 + ptr[1];
399 }
400
401 return ptr;
402}
403
404int videoguard1_get_emm_type(EMM_PACKET * ep, struct s_reader *rdr)
405{
406
407/*
40882 30 ad 70 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 00
409d3 02 00 22 90 20 44 02 4a 50 1d 88 ab 02 ac 79 16 6c df a1 b1 b7 77 00 ba eb 63 b5 c9 a9 30 2b 43 e9 16 a9 d5 14 00
410d3 02 00 22 90 20 44 02 13 e3 40 bd 29 e4 90 97 c3 aa 93 db 8d f5 6b e4 92 dd 00 9b 51 03 c9 3d d0 e2 37 44 d3 bf 00
411d3 02 00 22 90 20 44 02 97 79 5d 18 96 5f 3a 67 70 55 bb b9 d2 49 31 bd 18 17 2a e9 6f eb d8 76 ec c3 c9 cc 53 39 00
412d2 02 00 21 90 1f 44 02 99 6d df 36 54 9c 7c 78 1b 21 54 d9 d4 9f c1 80 3c 46 10 76 aa 75 ef d6 82 27 2e 44 7b 00
413*/
414
415 int i, pos;
416 int serial_count = ((ep->emm[3] >> 4) & 3) + 1;
417 int serial_len = (ep->emm[3] & 0x80) ? 3 : 4;
418 uchar emmtype = (ep->emm[3] & VG_EMMTYPE_MASK) >> 6;
419 pos = 4 + (serial_len * serial_count) + 2;
420 switch (emmtype) {
421 case VG_EMMTYPE_G:
422 {
423 ep->type = GLOBAL;
424 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: GLOBAL");
425 return TRUE;
426 }
427 case VG_EMMTYPE_U:
428 {
429 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: UNIQUE");
430 ep->type = UNIQUE;
431 if (ep->emm[1] == 0) // detected UNIQUE EMM from cccam (there is no serial)
432 {
433 return TRUE;
434 }
435
436 for (i = 1; i <= serial_count; i++) {
437 if (!memcmp(rdr->hexserial + 2, ep->emm + (serial_len * i), serial_len)) {
438 memcpy(ep->hexserial, ep->emm + (serial_len * i), serial_len);
439 return TRUE;
440 }
441
442 pos = pos + ep->emm[pos + 5] + 5;
443 }
444 return FALSE; // if UNIQUE but no serial match return FALSE
445 }
446 case VG_EMMTYPE_S:
447 {
448 ep->type = SHARED;
449 cs_debug_mask(D_EMM, "VIDEOGUARD1 EMM: SHARED");
450 return TRUE; // FIXME: no check for SA
451 }
452 default:
453 {
454 if (ep->emm[pos - 2] != 0x00 && ep->emm[pos - 1] != 0x00 && ep->emm[pos - 1] != 0x01) {
455 //remote emm without serial
456 ep->type = UNKNOWN;
457 return TRUE;
458 }
459 return FALSE;
460 }
461 }
462}
463
464void videoguard1_get_emm_filter(struct s_reader *rdr, uchar * filter)
465{
466 filter[0] = 0xFF;
467 filter[1] = 3;
468 //ToDo videoguard1_get_emm_filter basic construction
469 filter[2] = UNIQUE;
470 filter[3] = 0;
471 filter[4 + 0] = 0x82;
472 filter[4 + 0 + 16] = 0xFF;
473 memcpy(filter + 4 + 2, rdr->hexserial + 2, 4);
474 memset(filter + 4 + 2 + 16, 0xFF, 4);
475 filter[36] = UNIQUE;
476 filter[37] = 0;
477 filter[38 + 0] = 0x82;
478 filter[38 + 0 + 16] = 0xFF;
479 memcpy(filter + 38 + 6, rdr->hexserial + 2, 4);
480 memset(filter + 38 + 6 + 16, 0xFF, 4);
481 filter[70] = UNIQUE;
482 filter[71] = 0;
483 filter[72 + 0] = 0x82;
484 filter[72 + 0 + 16] = 0xFF;
485 memcpy(filter + 72 + 10, rdr->hexserial + 2, 4);
486 memset(filter + 72 + 10 + 16, 0xFF, 4);
487 /* filter[104]=UNIQUE;
488 filter[105]=0;
489
490 filter[106+0] = 0x82;
491 filter[106+0+16] = 0xFF;
492
493 memcpy(filter+106+14, rdr->hexserial+2, 2);
494 memset(filter+106+14+16, 0xFF, 2); */
495 return;
496}
497
498int videoguard1_do_emm(struct s_reader *reader, EMM_PACKET * ep)
499{
500 unsigned char cta_res[CTA_RES_LEN];
501 unsigned char ins42[5] = {
502 0x48, 0x42, 0x00, 0x00, 0xFF
503 };
504 int rc = ERROR;
505 const unsigned char *payload = payload_addr(ep->type, ep->emm, reader->hexserial);
506 while (payload) {
507 ins42[4] = *payload;
508 int l = vg1_do_cmd(reader, ins42, payload + 1, NULL, cta_res);
509 if (l > 0 && status_ok(cta_res)) {
510 rc = OK;
511 }
512
513 cs_debug_mask(D_EMM, "[videoguard1-reader] EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
514 //cs_dump(ep->emm, 64, "EMM:");
515 if (status_ok(cta_res) && (cta_res[1] & 0x01)) {
516 read_tiers(reader);
517 }
518
519 if (num_addr(ep->emm) == 1 && (int) (&payload[1] - &ep->emm[0]) + *payload + 1 < ep->l) {
520 payload += *payload + 1;
521 if (*payload == 0x00) {
522 ++payload;
523 }
524 ++payload;
525 if (*payload != 0x02) {
526 break;
527 }
528 payload += 2 + payload[1];
529 } else {
530 payload = 0;
531 }
532
533 }
534
535 return (rc);
536}
537
538int videoguard1_card_info(struct s_reader *reader)
539{
540 /* info is displayed in init, or when processing info */
541 cs_log("[videoguard1-reader] card detected");
542 cs_log("[videoguard1-reader] type: %s", reader->card_desc);
543 read_tiers(reader);
544 return OK;
545}
546
547void reader_videoguard1(struct s_cardsystem *ph)
548{
549 ph->do_emm=videoguard1_do_emm;
550 ph->do_ecm=videoguard1_do_ecm;
551 ph->card_info=videoguard1_card_info;
552 ph->card_init=videoguard1_card_init;
553 ph->get_emm_type=videoguard1_get_emm_type;
554 ph->caids[0]=0x09;
555}
Note: See TracBrowser for help on using the repository browser.