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