source: trunk/reader-videoguard12.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: 11.9 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 int vg12_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
13{
14 ushort 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 int 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 int num = cta_res[1];
67 int 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 int y, m, d, H, M, S;
79 rev_date_calc(&cta_res[4], &y, &m, &d, &H, &M, &S, reader->card_baseyear);
80 unsigned short tier_id = (cta_res[2] << 8) | cta_res[3];
81 char *tier_name = get_tiername(tier_id, reader->caid[0]);
82 cs_ri_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, y, m, d, H, M, S, tier_name);
83 }
84}
85
86static int 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 int 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 int i = 4;
161 int 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 int 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[0] = 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[0], 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 int 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 int posECMpart2 = er->ecm[6] + 7;
322 int 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 int 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 int videoguard12_do_emm(struct s_reader *reader, EMM_PACKET * ep)
353{
354 unsigned char cta_res[CTA_RES_LEN];
355 unsigned char ins42[5] = { 0x49, 0x42, 0x00, 0x00, 0xFF };
356 int rc = ERROR;
357 const unsigned char *payload = payload_addr(ep->type, ep->emm, reader->hexserial);
358 while (payload) {
359 ins42[4] = *payload;
360 int l = vg12_do_cmd(reader, ins42, payload + 1, NULL, cta_res);
361 if (l > 0 && status_ok(cta_res)) {
362 rc = OK;
363 }
364
365 cs_debug_mask(D_EMM, "EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
366 //cs_dump(ep->emm, 64, "EMM:");
367 if (status_ok(cta_res) && (cta_res[1] & 0x01)) {
368 read_tiers(reader);
369 }
370
371 if (num_addr(ep->emm) == 1 && (int) (&payload[1] - &ep->emm[0]) + *payload + 1 < ep->l) {
372 payload += *payload + 1;
373 if (*payload == 0x00) {
374 ++payload;
375 }
376 ++payload;
377 if (*payload != 0x02) {
378 break;
379 }
380 payload += 2 + payload[1];
381 } else {
382 payload = 0;
383 }
384
385 }
386
387 return (rc);
388}
389
390static int videoguard12_card_info(struct s_reader *reader)
391{
392 /* info is displayed in init, or when processing info */
393 cs_log("%s card detected", reader->label);
394 cs_log("type: %s", reader->card_desc);
395 read_tiers(reader);
396 return OK;
397}
398
399void reader_videoguard12(struct s_cardsystem *ph)
400{
401 ph->do_emm=videoguard12_do_emm;
402 ph->do_ecm=videoguard12_do_ecm;
403 ph->card_info=videoguard12_card_info;
404 ph->card_init=videoguard12_card_init;
405 ph->get_emm_type=videoguard_get_emm_type;
406 ph->get_emm_filter=videoguard_get_emm_filter;
407 ph->caids[0]=0x09;
408}
Note: See TracBrowser for help on using the repository browser.