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