source: trunk/reader-videoguard1.c@ 4149

Last change on this file since 4149 was 3893, checked in by schlocke, 13 years ago

webinf/Entitlements cccam: OK

File size: 9.7 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3#include "reader-videoguard-common.h"
4
5
6static int vg1_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
7{
8 ushort 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 int 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 int num = cta_res[1];
60 int 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 int y, m, d, H, M, S;
72 rev_date_calc(&cta_res[4], &y, &m, &d, &H, &M, &S, reader->card_baseyear);
73 unsigned short tier_id = (cta_res[2] << 8) | cta_res[3];
74 char *tier_name = get_tiername(tier_id, reader->caid[0]);
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, tier_name);
76 }
77}
78
79static int 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 int 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 int 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 int i = 9;
130 int 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 int 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[0] = cta_res[24] * 0x100 + cta_res[25];
241 /* Force caid until can figure out how to get it */
242 reader->caid[0] = 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[0], 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 int 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 int posECMpart2 = er->ecm[6] + 7;
262 int 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 int 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 int videoguard1_do_emm(struct s_reader *reader, EMM_PACKET * ep)
293{
294 unsigned char cta_res[CTA_RES_LEN];
295 unsigned char ins42[5] = { 0x48, 0x42, 0x00, 0x00, 0xFF };
296 int rc = ERROR;
297 const unsigned char *payload = payload_addr(ep->type, ep->emm, reader->hexserial);
298 while (payload) {
299 ins42[4] = *payload;
300 int l = vg1_do_cmd(reader, ins42, payload + 1, NULL, cta_res);
301 if (l > 0 && status_ok(cta_res)) {
302 rc = OK;
303 }
304
305 cs_debug_mask(D_EMM, "[videoguard1-reader] EMM request return code : %02X%02X", cta_res[0], cta_res[1]);
306 //cs_dump(ep->emm, 64, "EMM:");
307 if (status_ok(cta_res) && (cta_res[1] & 0x01)) {
308 read_tiers(reader);
309 }
310
311 if (num_addr(ep->emm) == 1 && (int) (&payload[1] - &ep->emm[0]) + *payload + 1 < ep->l) {
312 payload += *payload + 1;
313 if (*payload == 0x00) {
314 ++payload;
315 }
316 ++payload;
317 if (*payload != 0x02) {
318 break;
319 }
320 payload += 2 + payload[1];
321 } else {
322 payload = 0;
323 }
324
325 }
326
327 return (rc);
328}
329
330static int videoguard1_card_info(struct s_reader *reader)
331{
332 /* info is displayed in init, or when processing info */
333 cs_log("[videoguard1-reader] card detected");
334 cs_log("[videoguard1-reader] type: %s", reader->card_desc);
335 read_tiers(reader);
336 return OK;
337}
338
339void reader_videoguard1(struct s_cardsystem *ph)
340{
341 ph->do_emm=videoguard1_do_emm;
342 ph->do_ecm=videoguard1_do_ecm;
343 ph->card_info=videoguard1_card_info;
344 ph->card_init=videoguard1_card_init;
345 ph->get_emm_type=videoguard_get_emm_type;
346 ph->get_emm_filter=videoguard_get_emm_filter;
347 ph->caids[0]=0x09;
348 ph->desc="videoguard1";
349}
Note: See TracBrowser for help on using the repository browser.