source: trunk/reader-viaccess.c @ 431

Last change on this file since 431 was 115, checked in by smurzch2, 10 years ago

Disable parental lock in viaccess if needed.

If the config ask to disable parental lock, do it for viaccess.

File size: 18.8 KB
Line 
1#include "globals.h"
2#include "reader-common.h"
3
4extern uchar cta_cmd[], cta_res[];
5extern ushort cta_lr;
6
7#define CMD_LEN 5
8
9struct geo_cache
10{
11  ulong provid;
12  uchar geo[256];
13  uchar geo_len;
14};
15
16static struct geo_cache last_geo;
17
18struct via_date {
19  ushort day_s   : 5;
20  ushort month_s : 4;
21  ushort year_s  : 7;
22
23  ushort day_e   : 5;
24  ushort month_e : 4;
25  ushort year_e  : 7;
26};
27
28static void parse_via_date(const uchar *buf, struct via_date *vd, int fend)
29{
30  ushort date;
31
32  date = (buf[0]<<8) | buf[1];
33  vd->day_s   = date & 0x1f;
34  vd->month_s = (date>>5) & 0x0f;
35  vd->year_s  = (date>>9) & 0x7f;
36
37  if( fend )
38  {
39    date = (buf[2]<<8) | buf[3];
40    vd->day_e   = date & 0x1f;
41    vd->month_e = (date>>5) & 0x0f;
42    vd->year_e  = (date>>9) & 0x7f;
43  }
44}
45
46static void show_class(const char *p, const uchar *b, int l)
47{
48  int i, j;
49
50  // b -> via date (4 bytes)
51  b+=4;
52  l-=4;
53
54  j=l-1;
55  for (; j>=0; j--)
56    for (i=0; i<8; i++)
57      if (b[j] & (1 << (i&7)))
58      {
59        uchar cls;
60        struct via_date vd;
61        parse_via_date(b-4, &vd, 1);
62        cls=(l-(j+1))*8+i;
63        if (p)
64          cs_log("%sclass: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", p, cls, 
65                  vd.year_s+1980, vd.month_s, vd.day_s,
66                  vd.year_e+1980, vd.month_e, vd.day_e);
67    else
68          cs_ri_log("class: %02X, expiry date: %04d/%02d/%02d - %04d/%02d/%02d", cls, 
69                  vd.year_s+1980, vd.month_s, vd.day_s,
70                  vd.year_e+1980, vd.month_e, vd.day_e);
71      }
72}
73
74static void show_subs(const uchar *emm)
75{ 
76  // emm -> A9, A6, B6
77
78  switch( emm[0] )
79  {
80    case 0xA9:
81      show_class("nano A9: ", emm+2, emm[1]);
82      break;
83/*
84    {
85      int i, j, byts;
86      const uchar *oemm;
87
88      oemm = emm;
89      byts = emm[1]-4;
90      emm+=6;
91
92      j=byts-1;
93      for( ; j>=0; j-- )
94        for( i=0; i<8; i++ )
95          if( emm[j] & (1 << (i&7)) )
96          {
97            uchar cls;
98            struct via_date vd;
99            parse_via_date(emm-4, &vd, 1);
100            cls=(byts-(j+1))*8+i;
101            cs_log("%sclass %02X: expiry date: %02d/%02d/%04d - %02d/%02d/%04d",
102                    fnano?"nano A9: ":"", cls,
103                    vd.day_s, vd.month_s, vd.year_s+1980,
104                    vd.day_e, vd.month_e, vd.year_e+1980);
105          }
106      break;
107    }
108*/
109    case 0xA6:
110    {
111      char szGeo[256];
112
113      memset(szGeo, 0, 256);
114      strncpy(szGeo, (char *)emm+2, emm[1]);
115      cs_log("nano A6: geo %s", szGeo);
116      break;
117    }
118    case 0xB6:
119    {
120      uchar m; // modexp
121      struct via_date vd;
122
123      m=emm[emm[1]+1];
124      parse_via_date(emm+2, &vd, 0);
125      cs_log("nano B6: modexp %d%d%d%d%d%d: %02d/%02d/%04d", (m&0x20)?1:0, 
126             (m&0x10)?1:0,(m&0x08)?1:0,(m&0x04)?1:0,(m&0x02)?1:0,(m&0x01)?1:0,
127             vd.day_s, vd.month_s, vd.year_s+1980);
128      break;
129    }
130  }
131}
132
133static int chk_prov(uchar *id, uchar keynr)
134{
135  int i, j, rc;
136  for (rc=i=0; (!rc) && (i<reader[ridx].nprov); i++)
137    if(!memcmp(&reader[ridx].prid[i][1], id, 3))
138      for (j=0; (!rc) && (j<16); j++)
139        if (reader[ridx].availkeys[i][j]==keynr)
140          rc=1;
141  return(rc);
142}
143
144static int card_write(const uchar *cmd, const uchar *data, int wflag)
145{
146  int l;
147  uchar buf[256];
148  memcpy(buf, cmd, CMD_LEN);
149  l=wflag ? cmd[4] : 0;
150  if (l && data) memcpy(buf+CMD_LEN, data, l);
151  l=reader_cmd2icc(buf, CMD_LEN+l);
152  return(l);
153}
154
155#define write_cmd(cmd, data) \
156{ \
157  if (card_write(cmd, data, 1)) return(0); \
158}
159
160#define read_cmd(cmd, data) \
161{ \
162  if (card_write(cmd, data, 0)) return(0); \
163}
164
165int viaccess_card_init(uchar *atr, int atrsize)
166{
167  int i;
168  uchar buf[256];
169  static uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
170  static uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
171  static uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
172  static uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
173
174  static uchar insFAC[] = { 0x87, 0x02, 0x00, 0x00, 0x03 }; // init FAC
175  static uchar FacDat[] = { 0x00, 0x00, 0x28 };
176
177  if ((atr[0]!=0x3f) || (atr[1]!=0x77) || (atr[2]!=0x18) || (atr[9]!=0x68)) return(0);
178
179  write_cmd(insFAC, FacDat);
180  if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
181    return(0);
182
183//  switch((atr[atrsize-4]<<8)|atr[atrsize-3])
184//  {
185//    case 0x6268: ver="2.3"; break;
186//    case 0x6668: ver="2.4(?)"; break;
187//    case 0xa268:
188//    default: ver="unknown"; break;
189//  }
190     
191  reader[ridx].caid[0]=0x500;
192  memset(reader[ridx].prid, 0xff, sizeof(reader[ridx].prid));
193  insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
194  insb8[4]=0x07; read_cmd(insb8, NULL); // read unique id
195  memcpy(reader[ridx].hexserial, cta_res+2, 5);
196//  cs_log("type: viaccess, ver: %s serial: %llu", ver, b2ll(5, cta_res+2));
197  cs_ri_log("type: viaccess(%sstandard atr), caid: %04X, serial: %llu",
198        atr[9]==0x68?"":"non-",reader[ridx].caid[0], b2ll(5, cta_res+2));
199
200  i=0;
201  insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
202  buf[0]=0;
203  while((cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0))
204  {
205    insc0[4]=0x1a; read_cmd(insc0, NULL); // show provider properties
206    cta_res[2]&=0xF0;
207    reader[ridx].prid[i][0]=0;
208    memcpy(&reader[ridx].prid[i][1], cta_res, 3);
209    memcpy(&reader[ridx].availkeys[i][0], cta_res+10, 16);
210    sprintf((char *)buf+strlen((char *)buf), ",%06lX", b2i(3, &reader[ridx].prid[i][1]));
211//cs_log("buf: %s", buf);
212
213    insac[2]=0xa5; write_cmd(insac, NULL); // request sa
214    insb8[4]=0x06; read_cmd(insb8, NULL); // read sa
215    memcpy(&reader[ridx].sa[i][0], cta_res+2, 4);
216
217/*
218    insac[2]=0xa7; write_cmd(insac, NULL); // request name
219    insb8[4]=0x02; read_cmd(insb8, NULL); // read name nano + len
220    l=cta_res[1];
221    insb8[4]=l; read_cmd(insb8, NULL); // read name
222    cta_res[l]=0;
223cs_log("name: %s", cta_res);
224*/
225
226    insa4[2]=0x02;
227    write_cmd(insa4, NULL); // select next issuer
228    i++;
229  }
230  reader[ridx].nprov=i;
231  cs_ri_log("providers: %d (%s)", reader[ridx].nprov, buf+1);
232
233  /* init the maybe existing aes key */
234  aes_set_key((char *)reader[ridx].aes_key);
235
236  /* disabling parental lock. assuming pin "0000" */
237  if (cfg->ulparent) {
238      static uchar inDPL[] = {0xca, 0x24, 0x02, 0x00, 0x09};
239      static uchar cmDPL[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F};
240      write_cmd(inDPL,cmDPL);
241      if( !(cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0) )
242          cs_log("Can't disable parental lock. Wrong PIN? I assumed 0000!");
243      else
244          cs_log("Parental lock disabled");
245  }
246
247  cs_log("ready for requests");
248  memset(&last_geo, 0, sizeof(last_geo));
249  return(1);
250}
251
252int viaccess_do_ecm(ECM_REQUEST *er)
253{
254  static unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
255  static unsigned char ins88[] = { 0xca,0x88,0x00,0x00,0x00 }; // set ecm
256  static unsigned char insf8[] = { 0xca,0xf8,0x00,0x00,0x00 }; // set geographic info
257  static unsigned char insc0[] = { 0xca,0xc0,0x00,0x00,0x12 }; // read dcw
258
259  const uchar *ecm88Data=er->ecm+4; //XXX what is the 4th byte for ??
260  int ecm88Len=SCT_LEN(er->ecm)-4;
261  ulong provid;
262  int rc=0;
263  int hasD2 = 0;
264  uchar DE04[256];
265
266  if(ecm88Data[0]==0xd2)
267  {
268      // FIXME: use the d2 arguments
269      int len = ecm88Data[1] + 2;
270      ecm88Data += len;
271      ecm88Len -= len;
272      hasD2 = 1;
273  }
274
275  if ((ecm88Data[0]==0x90 || ecm88Data[0]==0x40) && ecm88Data[1]==0x03)
276  {
277    uchar ident[3], keynr;
278    //uchar buff[256]; // MAX_LEN
279    uchar *ecmf8Data=0;
280    int ecmf8Len=0;
281
282    memcpy (ident, &ecm88Data[2], sizeof(ident));
283    provid = b2i(3, ident);
284    ident[2]&=0xF0;
285    keynr=ecm88Data[4]&0x0F;
286    if (!chk_prov(ident, keynr))
287    {
288      cs_debug("smartcardviaccess ecm: provider or key not found on card");
289      return(0);
290    }
291    ecm88Data+=5;
292    ecm88Len-=5;
293
294    // DE04
295    if (ecm88Data[0]==0xDE && ecm88Data[1]==0x04)
296    {
297        memcpy (DE04, &ecm88Data[0], 6);
298        ecm88Data+=6;
299    }
300    //
301
302    if( last_geo.provid != provid ) 
303    {
304      last_geo.provid = provid;
305      last_geo.geo_len = 0;
306      last_geo.geo[0]  = 0;
307      write_cmd(insa4, ident); // set provider
308    }
309
310    while(ecm88Len>0 && ecm88Data[0]<0xA0)
311    {
312      int nanoLen=ecm88Data[1]+2;
313      if (!ecmf8Data)
314        ecmf8Data=(uchar *)ecm88Data;
315      ecmf8Len+=nanoLen;
316      ecm88Len-=nanoLen;
317      ecm88Data+=nanoLen;
318    }
319    if(ecmf8Len)
320    {
321      if( last_geo.geo_len!=ecmf8Len || 
322         memcmp(last_geo.geo, ecmf8Data, last_geo.geo_len))
323      {
324        memcpy(last_geo.geo, ecmf8Data, ecmf8Len);
325        last_geo.geo_len= ecmf8Len;
326        insf8[3]=keynr;
327        insf8[4]=ecmf8Len;
328        write_cmd(insf8, ecmf8Data);
329      }
330    }
331    ins88[2]=ecmf8Len?1:0;
332    ins88[3]=keynr;
333    ins88[4]=ecm88Len;
334
335    // DE04
336    if (DE04[0]==0xDE)
337    {
338        memcpy(DE04+6, (uchar *)ecm88Data, ecm88Len-6);
339        write_cmd(ins88, DE04); // request dcw
340    }
341    else
342    {
343        write_cmd(ins88, (uchar *)ecm88Data); // request dcw
344    }
345    //
346   
347    read_cmd(insc0, NULL);  // read dcw
348    switch(cta_res[0])
349    {
350      case 0xe8: // even
351        if(cta_res[1]==8) { memcpy(er->cw,cta_res+2,8); rc=1; }
352        break;
353      case 0xe9: // odd
354        if(cta_res[1]==8) { memcpy(er->cw+8,cta_res+2,8); rc=1; }
355        break;
356      case 0xea: // complete
357        if(cta_res[1]==16) { memcpy(er->cw,cta_res+2,16); rc=1; }
358        break;
359    }
360  }
361
362  if (hasD2) {
363    aes_decrypt(er->cw, 16);
364  }
365
366  return(rc?1:0);
367}
368
369int viaccess_do_emm(EMM_PACKET *ep)
370{
371  static unsigned char insa4[] = { 0xca,0xa4,0x04,0x00,0x03 }; // set provider id
372  static unsigned char insf0[] = { 0xca,0xf0,0x00,0x01,0x22 }; // set adf
373  static unsigned char insf4[] = { 0xca,0xf4,0x00,0x01,0x00 }; // set adf, encrypted
374  static unsigned char ins18[] = { 0xca,0x18,0x01,0x01,0x00 }; // set subscription
375  static unsigned char ins1c[] = { 0xca,0x1c,0x01,0x01,0x00 }; // set subscription, encrypted
376  static unsigned char insc8[] = { 0xca,0xc8,0x00,0x00,0x02 }; // read extended status
377  static unsigned char insc8Data[] = { 0x00,0x00 }; // data for read extended status
378
379  int emmLen=SCT_LEN(ep->emm)-7;
380  int rc=0;
381
382  ///cs_dump(ep->emm, emmLen+7, "RECEIVED EMM VIACCESS");
383
384  int emmUpToEnd;
385  uchar *emmParsed = ep->emm+7;
386  int provider_ok = 0;
387  uchar keynr = 0;
388  int ins18Len = 0;
389  uchar ins18Data[512];
390  uchar insData[512];
391  uchar *nano81Data = 0;
392  uchar *nano91Data = 0;
393  uchar *nano92Data = 0;
394  uchar *nano9EData = 0;
395  uchar *nanoF0Data = 0;
396
397  for (emmUpToEnd=emmLen; (emmParsed[1] != 0) && (emmUpToEnd > 0); emmUpToEnd -= (2 + emmParsed[1]), emmParsed += (2 + emmParsed[1])) {
398    ///cs_dump (emmParsed, emmParsed[1] + 2, "NANO");
399
400    if (emmParsed[0]==0x90 && emmParsed[1]==0x03) {
401      /* identification of the service operator */
402
403      uchar soid[3], ident[3], i;
404
405      for (i=0; i<3; i++) {
406        soid[i]=ident[i]=emmParsed[2+i];
407      }
408      ident[2]&=0xF0;
409      keynr=soid[2]&0x0F;
410      if (chk_prov(ident, keynr)) {
411        provider_ok = 1;
412      } else {
413        cs_debug("smartcardviaccess emm: provider or key not found on card (%x, %x)", ident, keynr);
414        return 0;
415      }
416
417      // set provider
418      write_cmd(insa4, soid);             
419      if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
420        cs_dump(insa4, 5, "set provider cmd:");
421        cs_dump(soid, 3, "set provider data:");
422        cs_log("update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
423        return 0;
424      }
425    } else if (emmParsed[0]==0x9e && emmParsed[1]==0x20) {
426      /* adf */
427
428      if (!nano91Data) {
429        /* adf is not crypted, so test it */
430
431        uchar custwp;
432        uchar *afd;
433
434        custwp=reader[ridx].sa[0][3];
435        afd=(uchar*)emmParsed+2;
436
437        if( afd[31-custwp/8] & (1 << (custwp & 7)) )
438          cs_debug("emm for our card %08X", b2i(4, &reader[ridx].sa[0][0]));
439        else
440          return 2; // skipped
441      }
442
443      // memorize
444      nano9EData = emmParsed;
445
446    } else if (emmParsed[0]==0x81) {
447      nano81Data = emmParsed;
448    } else if (emmParsed[0]==0x91 && emmParsed[1]==0x08) {
449      nano91Data = emmParsed;
450    } else if (emmParsed[0]==0x92 && emmParsed[1]==0x08) {
451      nano92Data = emmParsed;
452    } else if (emmParsed[0]==0xF0 && emmParsed[1]==0x08) {
453      nanoF0Data = emmParsed;
454    } else if (emmParsed[0]==0x1D && emmParsed[0]==0x01 && emmParsed[0]==0x01) {
455      /* from cccam... skip it... */
456    } else {
457      /* other nanos */
458      show_subs(emmParsed);
459   
460      memcpy(ins18Data+ins18Len, emmParsed, emmParsed[1] + 2);
461      ins18Len += emmParsed [1] + 2;
462    }
463  }
464
465  if (!provider_ok) {
466    cs_debug("viaccess: provider not found in emm... continue anyway...");
467    // force key to 1...
468    keynr = 1;
469    ///return 0;
470  }
471
472  if (!nanoF0Data) {
473    cs_dump(ep->emm, ep->l, "can't find 0xf0 in emm...");
474    return 0; // error
475  }
476
477  if (nano9EData) {
478    if (!nano91Data) {
479      // set adf
480      insf0[3] = keynr;  // key
481      write_cmd(insf0, nano9EData); 
482      if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
483        cs_dump(insf0, 5, "set adf cmd:");
484        cs_dump(nano9EData, 0x22, "set adf data:");
485        cs_log("update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
486        return 0;
487      }
488    } else {
489      // set adf crypte
490      insf4[3] = keynr;  // key
491      insf4[4] = nano91Data[1] + 2 + nano9EData[1] + 2;
492      memcpy (insData, nano91Data, nano91Data[1] + 2);
493      memcpy (insData + nano91Data[1] + 2, nano9EData, nano9EData[1] + 2);
494      write_cmd(insf4, insData); 
495      if(( cta_res[cta_lr-2]!=0x90 && cta_res[cta_lr-2]!=0x91) || cta_res[cta_lr-1]!=0x00 ) {
496        cs_dump(insf4, 5, "set adf encrypted cmd:");
497        cs_dump(insData, insf4[4], "set adf encrypted data:");
498        cs_log("update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
499        return 0;
500      }
501    }
502  }
503
504  if (!nano92Data) {
505    // send subscription
506    ins18[4] = ins18Len + nanoF0Data[1] + 2;
507    memcpy (insData, ins18Data, ins18Len);
508    memcpy (insData + ins18Len, nanoF0Data, nanoF0Data[1] + 2);
509    write_cmd(ins18, insData);
510    if( cta_res[cta_lr-2]==0x90 && cta_res[cta_lr-1]==0x00 ) {
511      cs_debug("update successfully written");
512      rc=1; // written
513    } else {
514      cs_dump(ins18, 5, "set subscription cmd:");
515      cs_dump(insData, ins18[4], "set subscription data:");
516      cs_log("update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
517    }
518   
519  } else {
520    // send subscription encrypted
521
522    if (!nano81Data) {
523      cs_dump(ep->emm, ep->l, "0x92 found, but can't find 0x81 in emm...");
524      return 0; // error
525    }
526
527    ins1c[3] = keynr;  // key
528    ins1c[4] = nano92Data[1] + 2 + nano81Data[1] + 2 + nanoF0Data[1] + 2;
529    memcpy (insData, nano92Data, nano92Data[1] + 2);
530    memcpy (insData + nano92Data[1] + 2, nano81Data, nano81Data[1] + 2);
531    memcpy (insData + nano92Data[1] + 2 + nano81Data[1] + 2, nanoF0Data, nanoF0Data[1] + 2);
532    write_cmd(ins1c, insData); 
533    if( cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
534      /* maybe a 2nd level status, so read it */
535      ///cs_dump(ins1c, 5, "set subscription encrypted cmd:");
536      ///cs_dump(insData, ins1c[4], "set subscription encrypted data:");
537      ///cs_log("update error: %02X %02X", cta_res[cta_lr-2], cta_res[cta_lr-1]);
538
539      read_cmd(insc8, insc8Data); 
540      if( cta_res[0] != 0x00 || cta_res[1] != 00 || cta_res[cta_lr-2]!=0x90 || cta_res[cta_lr-1]!=0x00 ) {
541        ///cs_dump(cta_res, cta_lr, "extended status error:");
542        return 0;
543      } else {
544        cs_debug("update successfully written (with extended status OK)");
545        rc=1; // written
546      }
547    } else {
548      cs_debug("update successfully written");
549      rc=1; // written
550    }
551  }
552
553  memset(&last_geo, 0, sizeof(last_geo));
554
555  /*
556  Sub Main()
557    Sc.Write("CA A4 04 00 03")
558    RX
559    Sc.Write("02 07 11")
560    RX
561    Sc.Write("CA F0 00 01 22")
562    RX
563    Sc.Write("9E 20")
564    Sc.Write("10 10 08 8A 80 00 04 00 10 10 26 E8 54 80 1E 80")
565    Sc.Write("00 01 00 00 00 00 00 50 00 00 80 02 22 00 08 50")
566    RX
567    Sc.Write("CA 18 01 01 11")
568    RX
569    Sc.Write("A9 05 34 DE 34 FF 80")
570    Sc.Write("F0 08 1A 3E AF B5 2B EE E3 3B")
571    RX
572
573    End Sub
574*/
575  return rc;
576}
577
578int viaccess_card_info(void)
579{
580  int i, l, scls, show_cls;
581  static uchar insac[] = { 0xca, 0xac, 0x00, 0x00, 0x00 }; // select data
582  static uchar insb8[] = { 0xca, 0xb8, 0x00, 0x00, 0x00 }; // read selected data
583  static uchar insa4[] = { 0xca, 0xa4, 0x00, 0x00, 0x00 }; // select issuer
584  static uchar insc0[] = { 0xca, 0xc0, 0x00, 0x00, 0x00 }; // read data item
585  static uchar ins24[] = { 0xca, 0x24, 0x00, 0x00, 0x09 }; // set pin
586
587  static uchar cls[] = { 0x00, 0x21, 0xff, 0x9f};
588  static uchar pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
589
590  show_cls=reader[ridx].show_cls;
591  memset(&last_geo, 0, sizeof(last_geo));
592
593  cs_log("card detected"); 
594 
595  // set pin
596  write_cmd(ins24, pin);
597
598  insac[2]=0xa4; write_cmd(insac, NULL); // request unique id
599  insb8[4]=0x07; read_cmd(insb8, NULL); // read unique id
600  cs_log("serial: %llu", b2ll(5, cta_res+2));
601
602  scls=0;
603  insa4[2]=0x00; write_cmd(insa4, NULL); // select issuer 0
604  for (i=1; (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0); i++)
605  {
606    ulong l_provid, l_sa;
607    uchar l_name[64];
608    insc0[4]=0x1a; read_cmd(insc0, NULL); // show provider properties
609    cta_res[2]&=0xF0;
610    l_provid=b2i(3, cta_res);
611
612    insac[2]=0xa5; write_cmd(insac, NULL); // request sa
613    insb8[4]=0x06; read_cmd(insb8, NULL); // read sa
614    l_sa=b2i(4, cta_res+2);
615
616    insac[2]=0xa7; write_cmd(insac, NULL); // request name
617    insb8[4]=0x02; read_cmd(insb8, NULL); // read name nano + len
618    l=cta_res[1];
619    insb8[4]=l; read_cmd(insb8, NULL); // read name
620    cta_res[l]=0;
621    trim((char *)cta_res);
622    if (cta_res[0])
623      snprintf((char *)l_name, sizeof(l_name), ", name: %s", cta_res);
624    else
625      l_name[0]=0;
626
627    // read GEO
628    insac[2]=0xa6; write_cmd(insac, NULL); // request GEO
629    insb8[4]=0x02; read_cmd(insb8, NULL); // read GEO nano + len
630    l=cta_res[1];
631    insb8[4]=l; read_cmd(insb8, NULL); // read geo
632    cs_ri_log("provider: %d, id: %06X%s, sa: %08X, geo: %s",
633           i, l_provid, l_name, l_sa, (l<4) ? "empty" : cs_hexdump(1, cta_res, l));
634
635    // read classes subscription
636    insac[2]=0xa9; insac[4]=4;
637    write_cmd(insac, cls); // request class subs
638    scls=0;
639    while( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
640    {
641      insb8[4]=0x02; read_cmd(insb8, NULL); // read class subs nano + len
642      if( (cta_res[cta_lr-2]==0x90) && (cta_res[cta_lr-1]==0) )
643      {
644        int fshow;
645        l=cta_res[1];
646        //fshow=(client[cs_idx].dbglvl==D_DUMP)?1:(scls < show_cls)?1:0;
647        fshow=(scls<show_cls);
648        insb8[4]=l; read_cmd(insb8, NULL); // read class subs
649        if( (cta_res[cta_lr-2]==0x90) && (fshow) && 
650            (cta_res[cta_lr-1]==0x00 || cta_res[cta_lr-1]==0x08) )
651        {
652          show_class(NULL, cta_res, cta_lr-2);
653          scls++;
654        }
655      }
656    }
657
658    insac[4]=0;
659    insa4[2]=0x02; 
660    write_cmd(insa4, NULL); // select next provider
661  }
662
663  reader[ridx].online = 1;
664
665  return 0;
666}
Note: See TracBrowser for help on using the repository browser.