1 | #include "globals.h"
|
---|
2 | #include "reader-common.h"
|
---|
3 |
|
---|
4 | static int cw_is_valid(unsigned char *cw) //returns 1 if cw_is_valid, returns 0 if cw is all zeros
|
---|
5 | {
|
---|
6 | int i;
|
---|
7 |
|
---|
8 | for (i = 0; i < 8; i++)
|
---|
9 | {
|
---|
10 | if (cw[i] != 0) //test if cw = 00
|
---|
11 | {
|
---|
12 | return OK;
|
---|
13 | }
|
---|
14 | }
|
---|
15 | return ERROR;
|
---|
16 | }
|
---|
17 |
|
---|
18 | static int tongfang_read_data(struct s_reader *reader, uchar size, uchar *cta_res, ushort *status)
|
---|
19 | {
|
---|
20 | uchar read_data_cmd[]={0x00,0xc0,0x00,0x00,0xff};
|
---|
21 | ushort cta_lr;
|
---|
22 |
|
---|
23 | read_data_cmd[4] = size;
|
---|
24 | write_cmd(read_data_cmd, NULL);
|
---|
25 |
|
---|
26 | *status = (cta_res[cta_lr - 2] << 8) | cta_res[cta_lr - 1];
|
---|
27 |
|
---|
28 | return(cta_lr - 2);
|
---|
29 | }
|
---|
30 |
|
---|
31 | static int tongfang_card_init(struct s_reader *reader, ATR newatr)
|
---|
32 | {
|
---|
33 | static const uchar begin_cmd[] = {0x00,0xa4,0x04,0x00,0x05,0xf9,0x5a,0x54,0x00,0x06};
|
---|
34 | static const uchar get_serial_cmd[] = {0x80,0x46,0x00,0x00,0x04,0x01,0x00,0x00,0x04};
|
---|
35 | uchar pairing_cmd[] = {0x80,0x4c,0x00,0x00,0x04,0xFF,0xFF,0xFF,0xFF};
|
---|
36 |
|
---|
37 | uchar data[257];
|
---|
38 | int data_len = 0;
|
---|
39 | ushort status = 0;
|
---|
40 | uchar boxID[] = {0xFF, 0xFF, 0xFF, 0xFF};
|
---|
41 | int i;
|
---|
42 |
|
---|
43 | def_resp;
|
---|
44 | get_hist;
|
---|
45 |
|
---|
46 | if ((hist_size < 4) || (memcmp(hist, "NTIC",4))) return ERROR;
|
---|
47 |
|
---|
48 | reader->caid[0] = 0x4A02;
|
---|
49 | // For now, only one provider, 0000
|
---|
50 | reader->nprov = 1;
|
---|
51 | memset(reader->prid, 0x00, sizeof(reader->prid));
|
---|
52 |
|
---|
53 | cs_ri_log(reader, "[reader-tongfang] Tongfang card detected");
|
---|
54 |
|
---|
55 | write_cmd(begin_cmd, begin_cmd + 5);
|
---|
56 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) return ERROR;
|
---|
57 |
|
---|
58 | write_cmd(get_serial_cmd, get_serial_cmd + 5);
|
---|
59 | if((cta_res[cta_lr - 2] & 0xf0) != 0x60) return ERROR;
|
---|
60 | data_len = tongfang_read_data(reader, cta_res[cta_lr - 1], data, &status);
|
---|
61 |
|
---|
62 | if(data_len < 0) return ERROR;
|
---|
63 | if(status != 0x9000) return ERROR;
|
---|
64 |
|
---|
65 | memset(reader->hexserial, 0, 8);
|
---|
66 | memcpy(reader->hexserial + 2, data, 4); // might be incorrect offset
|
---|
67 |
|
---|
68 | if (reader->boxid > 0)
|
---|
69 | {
|
---|
70 | /* the boxid is specified in the config */
|
---|
71 | for (i = 0; i < 4; i++)
|
---|
72 | {
|
---|
73 | boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
|
---|
74 | }
|
---|
75 | }
|
---|
76 | memcpy(pairing_cmd + 5, boxID, sizeof(boxID));
|
---|
77 | write_cmd(pairing_cmd, pairing_cmd + 5);
|
---|
78 |
|
---|
79 | cs_ri_log(reader, "type: Tongfang, caid: %04X, serial: %llu, hex serial: %02x%02x%02x%02x, BoxID: %02X%02X%02X%02X",
|
---|
80 | reader->caid[0], b2ll(6, reader->hexserial), reader->hexserial[2],
|
---|
81 | reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
|
---|
82 | boxID[0], boxID[1], boxID[2], boxID[3]);
|
---|
83 |
|
---|
84 | return OK;
|
---|
85 | }
|
---|
86 |
|
---|
87 | /*
|
---|
88 | Example ecm:
|
---|
89 | 03 85 80 70 61 8E 2A 16 4F 00 12 0F 21 5A E5 6A
|
---|
90 | 8F 4D C1 57 4E 24 2A 38 3C 26 8A 4C C2 74 A1 23
|
---|
91 | 9F 12 43 80 3A 16 4F 3E 8E 2A C0 40 0F 22 94 E4
|
---|
92 | 6A 89 F1 09 38 8F DF 3D 08 A6 29 1A 61 98 31 82
|
---|
93 | 7F 34 55 74 0E A3 54 38 01 09 00 01 00 01 D9 31
|
---|
94 | A5 1B 8B CA A8 95 E0 D1 24 7D 36 8C F6 89 4A F7
|
---|
95 | B2 3A 74 3D D1 D4
|
---|
96 | */
|
---|
97 | static int tongfang_do_ecm(struct s_reader *reader, ECM_REQUEST *er)
|
---|
98 | {
|
---|
99 | uchar ecm_cmd[200];
|
---|
100 | int ecm_len;
|
---|
101 | uchar* pbuf = er->ecm;
|
---|
102 | int i = 0;
|
---|
103 | int write_len = 0;
|
---|
104 | def_resp;
|
---|
105 | int read_size = 0;
|
---|
106 | uchar data[100];
|
---|
107 | int data_len = 0;
|
---|
108 | ushort status = 0;
|
---|
109 |
|
---|
110 | if((ecm_len = check_sct_len(er->ecm, 3)) < 0) return ERROR;
|
---|
111 |
|
---|
112 | cs_debug_mask(D_IFD, "ECM: %s", cs_hexdump(1, er->ecm, ecm_len));
|
---|
113 |
|
---|
114 | for(i = 0; i < (ecm_len - 1); i++)
|
---|
115 | {
|
---|
116 | if ((pbuf[0]==0x80)&&(pbuf[1]==0x3a))
|
---|
117 | {
|
---|
118 | break;
|
---|
119 | }
|
---|
120 | pbuf++;
|
---|
121 | }
|
---|
122 | write_len = pbuf[4] + 5;
|
---|
123 |
|
---|
124 | memcpy(ecm_cmd, pbuf, write_len);
|
---|
125 |
|
---|
126 | write_cmd(ecm_cmd, ecm_cmd + 5);
|
---|
127 |
|
---|
128 | if ((cta_lr - 2) >= 2)
|
---|
129 | {
|
---|
130 | read_size = cta_res[1];
|
---|
131 | }
|
---|
132 | else
|
---|
133 | {
|
---|
134 | if((cta_res[cta_lr - 2] & 0xf0) == 0x60)
|
---|
135 | {
|
---|
136 | read_size = cta_res[cta_lr - 1];
|
---|
137 | }
|
---|
138 | else
|
---|
139 | {
|
---|
140 | return ERROR;
|
---|
141 | }
|
---|
142 | }
|
---|
143 |
|
---|
144 | data_len = tongfang_read_data(reader, read_size, data, &status);
|
---|
145 |
|
---|
146 | if(data_len < 23) return ERROR;
|
---|
147 |
|
---|
148 | if(!(er->ecm[0] & 0x01))
|
---|
149 | {
|
---|
150 | memcpy(er->cw, data + 8, 16);
|
---|
151 | }
|
---|
152 | else
|
---|
153 | {
|
---|
154 | memcpy(er->cw, data + 16, 8);
|
---|
155 | memcpy(er->cw + 8, data + 8, 8);
|
---|
156 | }
|
---|
157 |
|
---|
158 | // All zeroes is no valid CW, can be a result of wrong boxid
|
---|
159 | if (!cw_is_valid(er->cw) || !cw_is_valid(er->cw + 8)) return ERROR;
|
---|
160 |
|
---|
161 | return OK;
|
---|
162 | }
|
---|
163 |
|
---|
164 | static int tongfang_get_emm_type(EMM_PACKET *ep, struct s_reader *UNUSED(reader))
|
---|
165 | {
|
---|
166 | ep->type = UNKNOWN;
|
---|
167 | return TRUE;
|
---|
168 | }
|
---|
169 |
|
---|
170 | static int tongfang_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
171 | {
|
---|
172 | uchar emm_cmd[200];
|
---|
173 | def_resp;
|
---|
174 | int write_len;
|
---|
175 |
|
---|
176 | if(ep->emm[2] < 5) return ERROR;
|
---|
177 |
|
---|
178 | write_len = ep->emm[15] + 5;
|
---|
179 | memcpy(emm_cmd, ep->emm + 11, write_len);
|
---|
180 |
|
---|
181 | write_cmd(emm_cmd, emm_cmd + 5);
|
---|
182 |
|
---|
183 | return OK;
|
---|
184 | }
|
---|
185 |
|
---|
186 | static int tongfang_card_info(struct s_reader * reader)
|
---|
187 | {
|
---|
188 | static const uchar get_provider_cmd[] = {0x80,0x44,0x00,0x00,0x08};
|
---|
189 | def_resp;
|
---|
190 | int i;
|
---|
191 |
|
---|
192 | write_cmd(get_provider_cmd, NULL);
|
---|
193 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) return ERROR;
|
---|
194 |
|
---|
195 | for(i = 0; i < 4; i++)
|
---|
196 | {
|
---|
197 | cs_ri_log(reader, "[reader-tongfang] Provider:%02x%02x", cta_res[i * 2], cta_res[i * 2 + 1]);
|
---|
198 | }
|
---|
199 | return OK;
|
---|
200 | }
|
---|
201 |
|
---|
202 | void reader_tongfang(struct s_cardsystem *ph)
|
---|
203 | {
|
---|
204 | ph->do_emm=tongfang_do_emm;
|
---|
205 | ph->do_ecm=tongfang_do_ecm;
|
---|
206 | ph->card_info=tongfang_card_info;
|
---|
207 | ph->card_init=tongfang_card_init;
|
---|
208 | ph->get_emm_type=tongfang_get_emm_type;
|
---|
209 | ph->caids[0]=0x4B;
|
---|
210 | ph->desc="tongfang";
|
---|
211 | }
|
---|