source: trunk/reader-viaccess.c@ 431

Last change on this file since 431 was 115, checked in by smurzch2, 11 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.