source: trunk/reader-videoguard12.c @ 5375

Last change on this file since 5375 was 5309, checked in by Admin, 8 years ago

Get rid of some static variables and cl->dump usage as they are not threadsafe.

File size: 11.1 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include "reader-videoguard-common.h"
4
5// Redefine logging funtion to include reader name
6#define cs_log(x...)  cs_log("[videoguard12-reader] "x)
7#define cs_ri_log(x,y...)  cs_ri_log(x,"[videoguard12-reader] "y)
8#ifdef WITH_DEBUG
9  #define cs_debug_mask(x,y...) cs_debug_mask(x, "[videoguard12-reader] "y)
10#endif
11
12static int32_t vg12_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
13{
14  uint16_t cta_lr;
15  unsigned char ins2[5];
16  memcpy(ins2, ins, 5);
17  unsigned char len = 0;
18  len = ins2[4];
19
20  unsigned char tmp[264];
21  if (!rxbuff) {
22    rxbuff = tmp;
23  }
24
25  if (txbuff == NULL) {
26    if (!write_cmd_vg(ins2, NULL) || !status_ok(cta_res + len)) {
27      return -1;
28    }
29    memcpy(rxbuff, ins2, 5);
30    memcpy(rxbuff + 5, cta_res, len);
31    memcpy(rxbuff + 5 + len, cta_res + len, 2);
32  } else {
33    if (!write_cmd_vg(ins2, (uchar *) txbuff) || !status_ok(cta_res)) {
34      return -2;
35    }
36    memcpy(rxbuff, ins2, 5);
37    memcpy(rxbuff + 5, txbuff, len);
38    memcpy(rxbuff + 5 + len, cta_res, 2);
39  }
40  return len;
41}
42
43static void read_tiers(struct s_reader *reader)
44{
45  def_resp;
46
47  static const unsigned char ins2A[5] = {  0x48, 0x2A, 0x00, 0x00, 0x90  };
48  int32_t l;
49
50  if (!write_cmd_vg(ins2A,NULL) || !status_ok(cta_res+cta_lr-2)) {
51    cs_log("class48 ins2A: failed");
52    return;
53  }
54
55  // return at present as not sure how to parse this
56  return;
57
58  unsigned char ins76[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
59  ins76[3] = 0x7f;
60  ins76[4] = 2;
61  if (!write_cmd_vg(ins76, NULL) || !status_ok(cta_res + 2)) {
62    return;
63  }
64  ins76[3] = 0;
65  ins76[4] = 0x0a;
66  int32_t num = cta_res[1];
67  int32_t i;
68
69  for (i = 0; i < num; i++) {
70    ins76[2] = i;
71    l = vg12_do_cmd(reader, ins76, NULL, NULL, cta_res);
72    if (l < 0 || !status_ok(cta_res + l)) {
73      return;
74    }
75    if (cta_res[2] == 0 && cta_res[3] == 0) {
76      break;
77    }
78    int32_t y, m, d, H, M, S;
79    rev_date_calc(&cta_res[4], &y, &m, &d, &H, &M, &S, reader->card_baseyear);
80    uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
81    char tiername[83];
82    cs_ri_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, y, m, d, H, M, S, get_tiername(tier_id, reader->caid, tiername));
83  }
84}
85
86static int32_t videoguard12_card_init(struct s_reader *reader, ATR newatr)
87{
88
89  get_hist;
90
91  if ((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50)){
92    cs_debug_mask(D_READER, "failed history check");
93    return ERROR;
94  }
95  cs_debug_mask(D_READER, "passed history check");
96
97  get_atr;
98  def_resp;
99
100  /* set information on the card stored in reader-videoguard-common.c */
101  set_known_card_info(reader,atr,&atr_size);
102
103  if((reader->ndsversion != NDS12) && ((reader->card_system_version != NDS12) || (reader->ndsversion != NDSAUTO))) {
104    /* known ATR and not NDS12
105       or unknown ATR and not forced to NDS12
106       or known NDS12 ATR and forced to another NDS version
107       ... probably not NDS12 */
108    return ERROR;
109  }
110
111  cs_ri_log(reader, "type: %s, baseyear: %i", reader->card_desc, reader->card_baseyear);
112  if(reader->ndsversion == NDS12){
113    cs_log("forced to NDS12");
114  }
115
116  /* NDS12 Class 48/49/4A/4B cards only need a very basic initialisation
117     NDS12 Class 48/49/4A/4B cards do not respond to ins7416
118     nor do they return list of valid command therefore do not even try
119     NDS12 Class 48/49/4A/4B cards need to be told the length as (48, ins, 00, 80, 01)
120     does not return the length */
121
122  static const unsigned char ins4852[5] = { 0x48, 0x52, 0x00, 0x00, 0x14 };
123  if (!write_cmd_vg(ins4852,NULL) || !status_ok(cta_res+cta_lr-2)) {
124    cs_log("class48 ins52: failed");
125    //return ERROR;
126  }
127  if (!write_cmd_vg(ins4852,NULL) || !status_ok(cta_res+cta_lr-2)) {
128    cs_log("class48 ins52: failed");
129    //return ERROR;
130  }
131
132  unsigned char boxID[4];
133  int32_t boxidOK = 0;
134
135/*
136  // Try to get the boxid from the card, even if BoxID specified in the config file
137  unsigned char ins36[5] = { 0x48, 0x36, 0x00, 0x00, 0x53 };
138
139  // get the length of ins36
140  static const unsigned char ins38[5] = { 0x48, 0x38, 0x80, 0x00, 0x02 };
141  if (!write_cmd_vg(ins38,NULL) || !status_ok(cta_res+cta_lr-2)) {
142    cs_log("class48 ins38: failed");
143    //return ERROR;
144  } else {
145    ins36[3] = cta_res[0];
146    ins36[4] = cta_res[1];
147  }
148
149
150  if (!write_cmd_vg(ins36,NULL) || !status_ok(cta_res+cta_lr-2)) {
151    cs_log("class48 ins36: failed");
152    //return ERROR;
153  }
154
155  if (cta_res[2] > 0x0F) {
156    cs_log("class48 ins36: encrypted - therefore not an NDS12 card");
157    // return ERROR;
158  } else {
159    // skipping the initial fixed fields: encr/rev++ (4)
160    int32_t i = 4;
161    int32_t gotUA = 0;
162    while (i < (cta_lr-2)) {
163      if (!gotUA && cta_res[i] < 0xF0) {    // then we guess that the next 4 bytes is the UA
164        gotUA = 1;
165        i += 4;
166      } else {
167        switch (cta_res[i]) {   // object length vary depending on type
168          case 0x00:        // padding
169            {
170              i += 1;
171              break;
172            }
173          case 0xEF:        // card status
174            {
175              i += 3;
176              break;
177            }
178          case 0xD1:
179            {
180              i += 4;
181              break;
182            }
183          case 0xDF:        // next server contact
184            {
185              i += 5;
186              break;
187            }
188          case 0xF3:        // boxID
189            {
190              memcpy(&boxID, &cta_res[i + 1], sizeof(boxID));
191              boxidOK = 1;
192              i += 5;
193              break;
194            }
195          case 0xF6:
196            {
197              i += 6;
198              break;
199            }
200          case 0xFC:        // No idea NDS1/NDS12
201            {
202              i += 14;
203              break;
204            }
205          case 0x01:        // date & time
206            {
207              i += 7;
208              break;
209            }
210          case 0xFA:
211            {
212              i += 9;
213              break;
214            }
215          case 0x5E:
216          case 0x67:        // signature
217          case 0xDE:
218          case 0xE2:
219          case 0xE9:        // tier dates
220          case 0xF8:        // Old PPV Event Record
221          case 0xFD:
222            {
223              i += cta_res[i + 1] + 2;  // skip length + 2 bytes (type and length)
224              break;
225            }
226          default:      // default to assume a length byte
227            {
228              cs_log("class48 ins36: returned unknown type=0x%02X - parsing may fail", cta_res[i]);
229              i += cta_res[i + 1] + 2;
230            }
231          } //switch
232        }//else
233      }//while
234    }//ele
235
236  cs_debug_mask(D_READER, "calculated BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
237*/
238
239  /* the boxid is specified in the config */
240  if (reader->boxid > 0) {
241    int32_t i;
242    for (i = 0; i < 4; i++) {
243      boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
244    }
245    cs_debug_mask(D_READER, "oscam.server BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
246  }
247
248  if (!boxidOK) {
249    cs_log("no boxID available");
250    return ERROR;
251  }
252
253  // Send BoxID
254  static const unsigned char ins484C[5] = { 0x48, 0x4C, 0x00, 0x00, 0x09 };
255  unsigned char payload4C[9] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02 };
256  memcpy(payload4C, boxID, 4);
257  if (!write_cmd_vg(ins484C,payload4C) || !status_ok(cta_res+cta_lr-2)) {
258    cs_log("class48 ins4C: sending boxid failed");
259    //return ERROR;
260  }
261
262  static const unsigned char ins4858[5] = { 0x48, 0x58, 0x00, 0x00, 0x35 };
263  if (!write_cmd_vg(ins4858,NULL) || !status_ok(cta_res+cta_lr-2)) {
264    cs_log("class48 ins58: failed");
265    return ERROR;
266  }
267
268  memset(reader->hexserial, 0, 8);
269  memcpy(reader->hexserial + 2, cta_res + 4, 4);
270  memcpy(reader->sa, cta_res + 4, 3);
271  reader->caid = cta_res[2] * 0x100 + cta_res[3];
272
273  /* we have one provider, 0x0000 */
274  reader->nprov = 1;
275  memset(reader->prid, 0x00, sizeof(reader->prid));
276
277  static const unsigned char insBE[5] = { 0x4B, 0xBE, 0x00, 0x00, 0x12 };
278  if (!write_cmd_vg(insBE,NULL) || !status_ok(cta_res+cta_lr-2)) {
279    cs_log("class4B ins52: failed");
280    //return ERROR;
281  }
282
283  static const unsigned char ins4952[5] = { 0x49, 0x52, 0x00, 0x00, 0x14 };
284  if (!write_cmd_vg(ins4952,NULL) || !status_ok(cta_res+cta_lr-2)) {
285    cs_log("class49 ins52: failed");
286    //return ERROR;
287  }
288
289  static const unsigned char ins4958[5] = { 0x49, 0x58, 0x00, 0x00, 0x35 };
290  if (!write_cmd_vg(ins4958,NULL) || !status_ok(cta_res+cta_lr-2)) {
291    cs_log("class49 ins58: failed");
292    //return ERROR;
293  }
294
295  // Send BoxID class 49
296  static const unsigned char ins494C[5] = { 0x49, 0x4C, 0x00, 0x00, 0x09 };
297  if (!write_cmd_vg(ins494C,payload4C) || !status_ok(cta_res+cta_lr-2)) {
298    cs_log("class49 ins4C: sending boxid failed");
299    //return ERROR;
300  }
301
302  static const unsigned char ins0C[5] = { 0x49, 0x0C, 0x00, 0x00, 0x0A };
303  if (!write_cmd_vg(ins0C,NULL) || !status_ok(cta_res+cta_lr-2)) {
304    cs_log("class49 ins0C: failed");
305    //return ERROR;
306  }
307
308  cs_ri_log(reader,
309            "type: VideoGuard, caid: %04X, serial: %02X%02X%02X%02X, BoxID: %02X%02X%02X%02X",
310            reader->caid, reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5], boxID[0], boxID[1], boxID[2], boxID[3]);
311  cs_log("ready for requests - this is in testing please send -d 255 logs to rebdog");
312
313  return OK;
314}
315
316static int32_t videoguard12_do_ecm(struct s_reader *reader, ECM_REQUEST * er)
317{
318  unsigned char cta_res[CTA_RES_LEN];
319  unsigned char ins40[5] = { 0x49, 0x40, 0x40, 0x80, 0xFF };
320  static const unsigned char ins54[5] = { 0x4B, 0x54, 0x00, 0x00, 0x17 };
321  int32_t posECMpart2 = er->ecm[6] + 7;
322  int32_t lenECMpart2 = er->ecm[posECMpart2];
323  unsigned char tbuff[264];
324  unsigned char rbuff[264];
325  memcpy(&tbuff[0], &(er->ecm[posECMpart2 + 1]), lenECMpart2 - 1);
326  ins40[4] = lenECMpart2;
327  int32_t l;
328  l = vg12_do_cmd(reader, ins40, tbuff, NULL, cta_res);
329  if (l > 0 && status_ok(cta_res)) {
330    l = vg12_do_cmd(reader, ins54, NULL, rbuff, cta_res);
331    if (l > 0 && status_ok(cta_res + l)) {
332      if (!cw_is_valid(rbuff+5,0))    //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
333      {
334        cs_log("class4B ins54 status 90 00 but cw=00 -> channel not subscribed");
335        return ERROR;
336      }
337
338      if(er->ecm[0]&1) {
339        memset(er->cw+0, 0, 8);
340        memcpy(er->cw+8, rbuff + 5, 8);
341      } else {
342        memcpy(er->cw+0, rbuff + 5, 8);
343        memset(er->cw+8, 0, 8);
344      }
345      return OK;
346    }
347  }
348  cs_log("class4B ins54 (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
349  return ERROR;
350}
351
352static int32_t videoguard12_do_emm(struct s_reader *reader, EMM_PACKET * ep)
353{
354   return videoguard_do_emm(reader, ep, 0x49, read_tiers, vg12_do_cmd);
355}
356
357static int32_t videoguard12_card_info(struct s_reader *reader)
358{
359  /* info is displayed in init, or when processing info */
360  cs_log("%s card detected", reader->label);
361  cs_log("type: %s", reader->card_desc);
362  read_tiers(reader);
363  return OK;
364}
365
366void reader_videoguard12(struct s_cardsystem *ph) 
367{
368  ph->do_emm=videoguard12_do_emm;
369  ph->do_ecm=videoguard12_do_ecm;
370  ph->card_info=videoguard12_card_info;
371  ph->card_init=videoguard12_card_init;
372  ph->get_emm_type=videoguard_get_emm_type;
373  ph->get_emm_filter=videoguard_get_emm_filter;
374  ph->caids[0]=0x09;
375}
Note: See TracBrowser for help on using the repository browser.