source: trunk/reader-videoguard1.c

Last change on this file was 11478, checked in by Gorgone Impertinence, 9 months ago

big cleanup pack 4

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