revert breaks some stupid old compilers
[oscam.git] / reader-videoguard1.c
blobf414d6896eda03fc8319fa66237be9a6541289f1
1 #include "globals.h"
2 #ifdef READER_VIDEOGUARD
3 #include "reader-common.h"
4 #include "reader-videoguard-common.h"
7 static int32_t vg1_do_cmd(struct s_reader *reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res)
9 uint16_t cta_lr;
10 unsigned char ins2[5];
11 memcpy(ins2, ins, 5);
12 unsigned char len = 0;
13 len = ins2[4];
17 if(txbuff == NULL)
19 if(!write_cmd_vg(ins2, NULL) || !status_ok(cta_res + len))
21 return -1;
23 if(rxbuff != NULL)
25 memcpy(rxbuff, ins2, 5);
26 memcpy(rxbuff + 5, cta_res, len);
27 memcpy(rxbuff + 5 + len, cta_res + len, 2);
30 else
32 if(!write_cmd_vg(ins2, (uchar *) txbuff) || !status_ok(cta_res))
34 return -2;
36 if(rxbuff != NULL)
38 memcpy(rxbuff, ins2, 5);
39 memcpy(rxbuff + 5, txbuff, len);
40 memcpy(rxbuff + 5 + len, cta_res, 2);
44 return len;
47 static void read_tiers(struct s_reader *reader)
49 struct videoguard_data *csystem_data = reader->csystem_data;
50 def_resp;
51 // const unsigned char ins2a[5] = { 0x48, 0x2a, 0x00, 0x00, 0x00 };
52 int32_t l;
54 // return; // Not working at present so just do nothing
56 // l = vg1_do_cmd(reader, ins2a, NULL, NULL, cta_res);
57 // if (l < 0 || !status_ok(cta_res + l))
58 // {
59 // return;
60 // }
61 unsigned char ins76[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
62 ins76[3] = 0x7f;
63 ins76[4] = 2;
64 if(!write_cmd_vg(ins76, NULL) || !status_ok(cta_res + 2))
66 return;
68 ins76[3] = 0;
69 ins76[4] = 0x0a;
70 int32_t num = cta_res[1];
71 int32_t i;
73 cs_clear_entitlement(reader); //reset the entitlements
75 for(i = 0; i < num; i++)
77 ins76[2] = i;
78 l = vg1_do_cmd(reader, ins76, NULL, NULL, cta_res);
79 if(l < 0 || !status_ok(cta_res + l))
81 return;
83 if(cta_res[2] == 0 && cta_res[3] == 0)
85 break;
87 uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
88 // add entitlements to list
89 struct tm timeinfo;
90 memset(&timeinfo, 0, sizeof(struct tm));
91 rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
92 char tiername[83];
93 cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4, 1);
94 rdr_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
98 static int32_t videoguard1_card_init(struct s_reader *reader, ATR *newatr)
101 get_hist;
102 /* 40 B0 09 4A 50 01 4E 5A */
103 if((hist_size < 7) || (hist[1] != 0xB0) || (hist[3] != 0x4A) || (hist[4] != 0x50))
105 return ERROR;
108 get_atr;
109 def_resp;
111 if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
112 { return ERROR; }
113 struct videoguard_data *csystem_data = reader->csystem_data;
115 /* set information on the card stored in reader-videoguard-common.c */
116 set_known_card_info(reader, atr, &atr_size);
118 if((reader->ndsversion != NDS1) && ((csystem_data->card_system_version != NDS1) || (reader->ndsversion != NDSAUTO)))
120 /* known ATR and not NDS1
121 or unknown ATR and not forced to NDS1
122 or known NDS1 ATR and forced to another NDS version
123 ... probably not NDS1 */
124 return ERROR;
127 rdr_log(reader, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
128 if(reader->ndsversion == NDS1)
130 rdr_log(reader, "forced to NDS1+");
133 /* NDS1 Class 48 only cards only need a very basic initialisation
134 NDS1 Class 48 only cards do not respond to vg1_do_cmd(ins7416)
135 nor do they return list of valid command therefore do not even try
136 NDS1 Class 48 only cards need to be told the length as (48, ins, 00, 80, 01)
137 does not return the length */
139 int32_t l = 0;
140 unsigned char buff[256];
141 memset(buff, 0, sizeof(buff));
143 /* Try to get the boxid from the card, even if BoxID specified in the config file
144 also used to check if it is an NDS1 card as the returned information will
145 not be encrypted if it is an NDS1 card */
147 static const unsigned char ins36[5] = { 0x48, 0x36, 0x00, 0x00, 0x90 };
148 unsigned char boxID[4];
149 int32_t boxidOK = 0;
150 l = vg1_do_cmd(reader, ins36, NULL, buff, cta_res);
151 if(buff[7] > 0x0F)
153 rdr_log(reader, "class48 ins36: encrypted - therefore not an NDS1 card");
154 return ERROR;
156 else
158 /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
159 int32_t i = 9;
160 int32_t gotUA = 0;
161 while(i < l)
163 if(!gotUA && buff[i] < 0xF0) /* then we guess that the next 4 bytes is the UA */
165 gotUA = 1;
166 i += 4;
168 else
170 switch(buff[i]) /* object length vary depending on type */
172 case 0x00: /* padding */
174 i += 1;
175 break;
177 case 0xEF: /* card status */
179 i += 3;
180 break;
182 case 0xD1:
184 i += 4;
185 break;
187 case 0xDF: /* next server contact */
189 i += 5;
190 break;
192 case 0xF3: /* boxID */
194 memcpy(&boxID, &buff[i + 1], sizeof(boxID));
195 boxidOK = 1;
196 i += 5;
197 break;
199 case 0xF6:
201 i += 6;
202 break;
204 case 0xFC: /* No idea seems to with with NDS1 */
206 i += 14;
207 break;
209 case 0x01: /* date & time */
211 i += 7;
212 break;
214 case 0xFA:
216 i += 9;
217 break;
219 case 0x5E:
220 case 0x67: /* signature */
221 case 0xDE:
222 case 0xE2:
223 case 0xE9: /* tier dates */
224 case 0xF8: /* Old PPV Event Record */
225 case 0xFD:
227 i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
228 break;
230 default: /* default to assume a length byte */
232 rdr_log(reader, "class48 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
233 i += buff[i + 1] + 2;
240 // rdr_log(reader, "calculated BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
242 /* the boxid is specified in the config */
243 if(reader->boxid > 0)
245 int32_t i;
246 for(i = 0; i < 4; i++)
248 boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
250 // rdr_log(reader, "config BoxID: %02X%02X%02X%02X", boxID[0], boxID[1], boxID[2], boxID[3]);
253 if(!boxidOK)
255 rdr_log(reader, "no boxID available");
256 return ERROR;
259 // Send BoxID
260 static const unsigned char ins4C[5] = { 0x48, 0x4C, 0x00, 0x00, 0x09 };
261 unsigned char payload4C[9] = { 0, 0, 0, 0, 3, 0, 0, 0, 4 };
262 memcpy(payload4C, boxID, 4);
263 if(!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res + l))
265 rdr_log(reader, "class48 ins4C: sending boxid failed");
266 return ERROR;
269 static const unsigned char ins58[5] = { 0x48, 0x58, 0x00, 0x00, 0x17 };
270 l = vg1_do_cmd(reader, ins58, NULL, buff, cta_res);
271 if(l < 0)
273 rdr_log(reader, "class48 ins58: failed");
274 return ERROR;
277 memset(reader->hexserial, 0, 8);
278 memcpy(reader->hexserial + 2, cta_res + 1, 4);
279 memcpy(reader->sa, cta_res + 1, 3);
280 // reader->caid = cta_res[24] * 0x100 + cta_res[25];
281 /* Force caid until can figure out how to get it */
282 reader->caid = 0x9 * 0x100 + 0x69;
284 /* we have one provider, 0x0000 */
285 reader->nprov = 1;
286 memset(reader->prid, 0x00, sizeof(reader->prid));
288 rdr_log_sensitive(reader, "type: VideoGuard, caid: %04X, serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}",
289 reader->caid, reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
290 boxID[0], boxID[1], boxID[2], boxID[3]);
291 rdr_log(reader, "ready for requests - this is in testing please send -d 255 logs");
293 return OK;
296 static int32_t videoguard1_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
298 unsigned char cta_res[CTA_RES_LEN];
299 unsigned char ins40[5] = { 0x48, 0x40, 0x00, 0x80, 0xFF };
300 static const unsigned char ins54[5] = { 0x48, 0x54, 0x00, 0x00, 0x0D };
301 int32_t posECMpart2 = er->ecm[6] + 7;
302 int32_t lenECMpart2 = er->ecm[posECMpart2];
303 unsigned char tbuff[264];
304 unsigned char rbuff[264];
305 memcpy(&tbuff[0], &(er->ecm[posECMpart2 + 1]), lenECMpart2);
306 ins40[4] = lenECMpart2;
307 int32_t l;
308 l = vg1_do_cmd(reader, ins40, tbuff, NULL, cta_res);
309 if(l > 0 && status_ok(cta_res))
311 l = vg1_do_cmd(reader, ins54, NULL, rbuff, cta_res);
312 if(l > 0 && status_ok(cta_res + l))
314 if(!cw_is_valid(rbuff + 5)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
316 rdr_log(reader, "class48 ins54 status 90 00 but cw=00 -> channel not subscribed");
317 return ERROR;
320 if(er->ecm[0] & 1)
322 memset(ea->cw + 0, 0, 8);
323 memcpy(ea->cw + 8, rbuff + 5, 8);
325 else
327 memcpy(ea->cw + 0, rbuff + 5, 8);
328 memset(ea->cw + 8, 0, 8);
330 return OK;
333 rdr_log(reader, "class48 ins54 (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
334 return ERROR;
337 static int32_t videoguard1_do_emm(struct s_reader *reader, EMM_PACKET *ep)
339 return videoguard_do_emm(reader, ep, 0x48, read_tiers, vg1_do_cmd);
342 static int32_t videoguard1_card_info(struct s_reader *reader)
344 /* info is displayed in init, or when processing info */
345 struct videoguard_data *csystem_data = reader->csystem_data;
346 rdr_log(reader, "card detected");
347 rdr_log(reader, "type: %s", csystem_data->card_desc);
348 read_tiers(reader);
349 return OK;
352 const struct s_cardsystem reader_videoguard1 =
354 .desc = "videoguard1",
355 .caids = (uint16_t[]){ 0x09, 0 },
356 .do_emm = videoguard1_do_emm,
357 .do_ecm = videoguard1_do_ecm,
358 .card_info = videoguard1_card_info,
359 .card_init = videoguard1_card_init,
360 .get_emm_type = videoguard_get_emm_type,
361 .get_emm_filter = videoguard_get_emm_filter,
364 #endif