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
)
10 unsigned char ins2
[5];
12 unsigned char len
= 0;
19 if(!write_cmd_vg(ins2
, NULL
) || !status_ok(cta_res
+ len
))
25 memcpy(rxbuff
, ins2
, 5);
26 memcpy(rxbuff
+ 5, cta_res
, len
);
27 memcpy(rxbuff
+ 5 + len
, cta_res
+ len
, 2);
32 if(!write_cmd_vg(ins2
, (uchar
*) txbuff
) || !status_ok(cta_res
))
38 memcpy(rxbuff
, ins2
, 5);
39 memcpy(rxbuff
+ 5, txbuff
, len
);
40 memcpy(rxbuff
+ 5 + len
, cta_res
, 2);
47 static void read_tiers(struct s_reader
*reader
)
49 struct videoguard_data
*csystem_data
= reader
->csystem_data
;
51 // const unsigned char ins2a[5] = { 0x48, 0x2a, 0x00, 0x00, 0x00 };
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))
61 unsigned char ins76
[5] = { 0x48, 0x76, 0x00, 0x00, 0x00 };
64 if(!write_cmd_vg(ins76
, NULL
) || !status_ok(cta_res
+ 2))
70 int32_t num
= cta_res
[1];
73 cs_clear_entitlement(reader
); //reset the entitlements
75 for(i
= 0; i
< num
; i
++)
78 l
= vg1_do_cmd(reader
, ins76
, NULL
, NULL
, cta_res
);
79 if(l
< 0 || !status_ok(cta_res
+ l
))
83 if(cta_res
[2] == 0 && cta_res
[3] == 0)
87 uint16_t tier_id
= (cta_res
[2] << 8) | cta_res
[3];
88 // add entitlements to list
90 memset(&timeinfo
, 0, sizeof(struct tm
));
91 rev_date_calc_tm(&cta_res
[4], &timeinfo
, csystem_data
->card_baseyear
);
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
)
102 /* 40 B0 09 4A 50 01 4E 5A */
103 if((hist_size
< 7) || (hist
[1] != 0xB0) || (hist
[3] != 0x4A) || (hist
[4] != 0x50))
111 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct videoguard_data
)))
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 */
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 */
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];
150 l
= vg1_do_cmd(reader
, ins36
, NULL
, buff
, cta_res
);
153 rdr_log(reader
, "class48 ins36: encrypted - therefore not an NDS1 card");
158 /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
163 if(!gotUA
&& buff
[i
] < 0xF0) /* then we guess that the next 4 bytes is the UA */
170 switch(buff
[i
]) /* object length vary depending on type */
172 case 0x00: /* padding */
177 case 0xEF: /* card status */
187 case 0xDF: /* next server contact */
192 case 0xF3: /* boxID */
194 memcpy(&boxID
, &buff
[i
+ 1], sizeof(boxID
));
204 case 0xFC: /* No idea seems to with with NDS1 */
209 case 0x01: /* date & time */
220 case 0x67: /* signature */
223 case 0xE9: /* tier dates */
224 case 0xF8: /* Old PPV Event Record */
227 i
+= buff
[i
+ 1] + 2; /* skip length + 2 bytes (type and length) */
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)
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]);
255 rdr_log(reader
, "no boxID available");
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");
269 static const unsigned char ins58
[5] = { 0x48, 0x58, 0x00, 0x00, 0x17 };
270 l
= vg1_do_cmd(reader
, ins58
, NULL
, buff
, cta_res
);
273 rdr_log(reader
, "class48 ins58: failed");
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 */
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");
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
;
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");
322 memset(ea
->cw
+ 0, 0, 8);
323 memcpy(ea
->cw
+ 8, rbuff
+ 5, 8);
327 memcpy(ea
->cw
+ 0, rbuff
+ 5, 8);
328 memset(ea
->cw
+ 8, 0, 8);
333 rdr_log(reader
, "class48 ins54 (%d) status not ok %02x %02x", l
, cta_res
[0], cta_res
[1]);
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
);
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
,