1 | /*
|
---|
2 | * Griffin card reader for OSCAM
|
---|
3 | * Copyright (C) 2013 Unix Solutions Ltd.
|
---|
4 | *
|
---|
5 | * Author(s): Georgi Chorbadzhiyski (gf@unixsol.org)
|
---|
6 | *
|
---|
7 | * This program is free software: you can redistribute it and/or modify
|
---|
8 | * it under the terms of the GNU General Public License as published by
|
---|
9 | * the Free Software Foundation, either version 3 of the License, or
|
---|
10 | * (at your option) any later version.
|
---|
11 | *
|
---|
12 | * This program is distributed in the hope that it will be useful,
|
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | * GNU General Public License for more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU General Public License
|
---|
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | *
|
---|
20 | * =========================================================================
|
---|
21 | * Once upon a time Bulsatcom in Bulgaria used Griffin CAS. Their cards were
|
---|
22 | * known as "strawberry cards" because they had a strawberry picture on the
|
---|
23 | * front. These cards have CAID 0x5501. You can't get EMM and ECM stream
|
---|
24 | * for these cards but if you can, then the reader would probably work.
|
---|
25 | *
|
---|
26 | * This reader is tested with working card that have CAID 0x5504. This card
|
---|
27 | * is used by KaTe Nova Gorica provider in Slovenia.
|
---|
28 | * =========================================================================
|
---|
29 | *
|
---|
30 | * Griffin reader card protocol:
|
---|
31 | * ATR from CAID 0x5501
|
---|
32 | * 3B 08 01 01 xx xx xx xx 10 00
|
---|
33 | * (01 - last two octets in caid (0x01 = CAID 0x5501)
|
---|
34 | * (xx - card hex serial number)
|
---|
35 | * (10 - command base)
|
---|
36 | *
|
---|
37 | * ATR from CAID 0x5504
|
---|
38 | * 3B 08 04 01 xx xx xx xx 20 00
|
---|
39 | * (04 - last two octets in caid (0x04 = CAID 0x5504)
|
---|
40 | * (xx - card hex serial number)
|
---|
41 | * (20 - command base)
|
---|
42 | *
|
---|
43 | * The basic card conversation looks like this:
|
---|
44 | * Send DC xx 00 00 yy zz zz zz (xx = command op, yy payload length, zz - payload if payload_len > 0)
|
---|
45 | * Recv 90 03 (90 = command ok, 03 = length of the response)
|
---|
46 | * Send DC 12 00 00 xx (Read response , xx = length of the response)
|
---|
47 | * Recv xx yy zz 90 00 (Response , xx = response code, yy - data length, zz - data, 90 00 at the end)
|
---|
48 | *
|
---|
49 | * Command ops (hex), these commands are for card with base == 20:
|
---|
50 | * 02 - read command response (for base cards with base 10)
|
---|
51 | * 12 - read command response (for base cards with base 20)
|
---|
52 | *
|
---|
53 | * The command number is (base + number, the numbers bellow are for base==20)
|
---|
54 | * 20 - card init
|
---|
55 | * 22 - get hex serial
|
---|
56 | * 24 - get ascii serial
|
---|
57 | * 26 - get caid
|
---|
58 | * 28 - get card addresses
|
---|
59 | * 30 - unknown command
|
---|
60 | * 34 - unknown command
|
---|
61 | * 36 - send_ecm
|
---|
62 | * 32 - send_emm
|
---|
63 | * 40 - get subscription info
|
---|
64 | * 42 - unknown command
|
---|
65 | * 4a - unknown command
|
---|
66 | * 50 - unknown command
|
---|
67 | *
|
---|
68 | * Perform card INIT
|
---|
69 | * DC 20 00 00 00 -- 90 03 (card init /get base/)
|
---|
70 | * DC 12 00 00 03 -- 11 01 20 90 00 (20 == cmd base)
|
---|
71 | *
|
---|
72 | * DC 22 00 00 00 -- 90 06 (get hex serial)
|
---|
73 | * DC 12 00 00 06 -- 12 04 xx xx xx xx 90 00 (xx - hex serial)
|
---|
74 | *
|
---|
75 | * DC 24 00 00 00 -- 90 0E (get ascii serial)
|
---|
76 | * DC 12 00 00 0E -- 13 0C 47 43 30 34 53 xx xx xx xx xx xx 00 90 00 (xx - ascii serial - GC04S......)
|
---|
77 | *
|
---|
78 | * DC 26 00 00 00 -- 90 04 (get caid)
|
---|
79 | * DC 12 00 00 04 -- 14 02 xx xx 90 00 (xx xx = 55 04 /the caid/)
|
---|
80 | *
|
---|
81 | * DC 28 00 00 00 -- 90 32
|
---|
82 | * DC 12 00 00 32 -- 15 30 \
|
---|
83 | * 80 00 00 00 00 00 00 00 F0 FF FF FF FF 00 00 00 \
|
---|
84 | * 80 yy yy yy yy 00 00 00 F0 FF FF FF FF 00 00 00 \ (yy = shared card address)
|
---|
85 | * 80 xx xx xx xx 00 00 00 F0 FF FF FF FF 00 00 00 90 00 (xx = card hex serial)
|
---|
86 | *
|
---|
87 | * DC 42 00 00 00 -- 90 03
|
---|
88 | * DC 12 00 00 03 -- 1C 01 00 90 00
|
---|
89 | *
|
---|
90 | * DC 34 00 00 00 -- 90 00
|
---|
91 | * DC 30 00 00 00 -- 90 00
|
---|
92 | *
|
---|
93 | * Send ECMs
|
---|
94 | * DC 36 00 00 42 -- 81 70 3F C6 71 A3 97 A3 91 36 76 C9 69 EC A8 46 CA FB 0B 31 D2 4B 2A BD 43 FF 5E A4 C0 CD 06 A9 48 1B 2B 6C 3D 28 B2 92 3A C0 C2 1C 38 35 29 D0 9D B2 16 6D 26 E3 27 A3 20 6F 8E 72 5D 0B A3 00 65 EC 90 18
|
---|
95 | * DC 36 00 00 42 -- 80 70 3F 09 D2 9B F3 03 E3 81 5A E4 44 F4 18 9E 84 18 D5 6E 81 D8 1F A2 E8 CB 1B B6 A9 3D 5D C2 CA FE 6A C2 69 1A CD 15 7F 2C A6 77 8B CF 0C 4E 4F 74 04 97 17 15 93 4F 2E 93 10 B8 6B B0 FF 1C 20 7D 90 18
|
---|
96 | *
|
---|
97 | * DC 36 00 00 41 -- 81 70 3E 09 EC 39 F4 35 CF 45 80 AB 17 56 56 64 F0 BB 39 97 BE 7F 9E D3 F7 70 6A B2 8A 52 56 BD B4 B3 77 14 22 13 70 7F 9D 03 2A BB 88 85 3E 1D AB 9D E1 C7 A1 CB B9 99 34 F6 EB 2C 15 7F 52 E5 1C 90 18
|
---|
98 | * DC 36 00 00 41 -- 80 70 3E F4 7E B1 C4 30 56 C2 61 AA 31 29 FB 09 1C 79 13 14 8E 64 43 5F 4B 97 71 A0 D3 BA A4 08 AC 8B E4 21 B7 C6 8A A5 9F 72 19 A5 51 75 9B F2 40 B2 C9 8F E8 63 98 2C 5D 84 21 88 8F F1 DA CF 32 90 18
|
---|
99 | *
|
---|
100 | * DC 36 00 00 3E -- 81 70 3B 07 76 06 C8 8D 9F 57 C8 19 30 1C 3B 93 9B A1 E1 88 E7 82 C3 E5 7A 05 44 DF 7D 90 CB F9 E1 43 C7 6F 39 75 3A A5 15 73 AA 5F 8C 1D 5B B6 52 2B 0B C2 02 88 7C C2 E8 4F D6 6A 73 A6 90 18
|
---|
101 | * DC 36 00 00 3E -- 80 70 3B CE B9 CC BC 95 D8 BB 4A C0 7B 7C 7E 9C 39 00 10 47 E1 67 A7 CD 34 9F E6 43 CB 50 2E 77 9A 54 87 54 25 49 FC 4F 6A A6 56 FD 51 74 08 37 C3 00 04 BD 72 04 CB DB D9 7C 37 76 71 A7 90 18
|
---|
102 | *
|
---|
103 | * DC 36 00 00 3D -- 81 70 3A 22 06 2B 48 2A 99 4B 82 20 C4 80 B4 55 72 CD B3 C9 FD BA 84 89 66 F4 F8 51 7F CD AC 38 4E 0E 6A 91 11 E9 E1 A4 0E 8D E7 56 43 11 56 F5 DA 78 19 42 37 B3 CA BA 33 11 69 B9 96 90 18
|
---|
104 | * DC 36 00 00 3D -- 80 70 3A FB 09 20 41 48 2D 12 4F E8 13 E3 23 AD B9 25 CE DA 95 F2 C8 ED D6 08 2E 23 6A 13 19 A8 A7 9F 9A 8B 12 F3 97 95 09 5B F6 F6 AA 64 EA 46 3C AD 62 93 DC B5 07 FB 16 81 F8 A6 D3 90 18
|
---|
105 | *
|
---|
106 | * DC 36 00 00 3A -- 81 70 37 16 21 7A 01 9A A5 BB C8 9E 93 88 79 56 C1 41 B4 37 5F 1F 3A 69 1E 4A CA DB 56 77 98 3A 02 9E 2C 8A FE 24 51 DD 5E F9 23 79 AF 4D 63 27 34 A0 28 44 11 45 BA 72 F2 92 90 18
|
---|
107 | * DC 36 00 00 3A -- 80 70 37 79 E6 26 6E 93 D8 8E F1 DC A1 70 7A 36 77 6D 68 AE 36 1B 85 E4 85 EE 35 E8 33 5A 4D 84 AC AA 87 5B 7B EF F3 DF 76 20 7B 0A 91 B3 B1 3D 97 FE 21 8C 52 E2 8F 01 5D 50 90 18
|
---|
108 | *
|
---|
109 | * Read DCWs (after sending ECM)
|
---|
110 | * DC 12 00 00 18 -- 19 04 00 00 00 00 1A 10 F9 EE 8F 76 A9 85 DC 0A E3 92 51 C6 40 B4 B0 A4 90 00
|
---|
111 | * DC 12 00 00 18 -- 19 04 00 00 00 00 1A 10 F9 EE 8F 76 A9 85 DC 0A 51 AB 96 92 7C A0 7F 9B 90 00
|
---|
112 | * DC 12 00 00 18 -- 19 04 00 00 00 00 1A 10 F6 51 8F D6 E6 F0 5E 34 AA 41 86 71 CC C0 29 B5 90 00
|
---|
113 | * DC 12 00 00 18 -- 19 04 00 00 00 00 1A 10 F6 51 8F D6 E6 F0 5E 34 51 AB 96 92 7C A0 7F 9B 90 00
|
---|
114 | *
|
---|
115 | * Send EMMs
|
---|
116 | * DC 32 00 00 B2 -- 83 70 AF -- -- -- -- 3F 38 ED 59 0B 52 7D 8B D9 43 B5 51 6F C5 1D F2 36 35 C4 90 92 83 92 3E A2 99 47 76 3A CF 81 79 5C A1 4E B3 5D 09 D0 7E 86 3F DD C8 56 30 72 B4 E0 DE 0F 76 03 6F 16 F4 1F 4E 35 DC 6F 36 E8 DB E8 F3 75 BB CF 7B FE 46 91 8F F9 1C 7D 18 27 98 27 31 5A A4 39 44 E5 62 B0 DA 81 73 65 58 08 0B 44 20 57 37 DA 20 19 6B 35 F4 07 74 BA 42 75 AD 4A C5 86 C1 E3 03 C1 A2 05 C2 A3 C2 4C 57 B8 7E 3E DE 74 FB 5D 32 4A 7F 68 2B 74 E8 84 B6 33 52 6A B8 3D FD 3F 14 C4 39 39 39 28 80 B1 AC 77 39 A0 EF 8A 3C F5 4F F6 99 67 90 A4 90 0A
|
---|
117 | * DC 12 00 00 0A -- 1F 04 51 06 B5 B5 16 02 01 00 90 00
|
---|
118 | *
|
---|
119 | * DC 32 00 00 AF -- 82 70 AC -- -- -- -- C6 94 A0 54 68 47 D0 3F FB 05 C6 A3 C5 FA 5F F0 A7 56 96 19 A5 F6 31 95 CD F1 8D 71 C3 FE 96 FD 75 2A DE 1F 12 08 8C 53 5D B6 4E FC 34 5D F0 BB 52 84 6C 71 C3 EA CE 4C 8A 08 45 22 E3 74 4A 37 48 39 75 37 0C 4A A9 8B 62 D8 F5 EE EC 28 E2 92 66 2D DA FF 8C 2B BD 97 C5 95 6B A0 6F 8B 82 79 09 79 E6 63 66 77 0A AB 8F EC 65 4F EC 05 75 2B FD DF 78 85 48 6C 2C A0 4D 4C 96 B6 08 21 A1 01 8D 74 CC F3 92 04 D2 15 49 F7 CE 74 6B 38 D9 22 66 2D 7E D6 78 BB 3D 0B 30 A7 64 A1 DC AE 0E 54 90 D0 83 BC 89 9F CA 50 90 00
|
---|
120 | *
|
---|
121 | * Get subscription info (for base 20 cards - CAID 5504)
|
---|
122 | * DC 40 00 00 00 -- 90 3C
|
---|
123 | * DC 12 00 00 3C -- 1B 02 07 FF 1B 02 07 FF 1B 02 07 FF 1B 02 07 FF 1B 02 00 0F 1B 02 00 00 \
|
---|
124 | * 1B 02 00 00 1B 02 00 00 1B 02 00 00 1B 02 00 00 1B 02 00 00 1B 02 00 00 \
|
---|
125 | * 1B 02 00 00 1B 02 00 00 1B 02 00 00 90 00
|
---|
126 | *
|
---|
127 | * Get subscription info (for base 10 cards - CAID 5501)
|
---|
128 | * DC 30 00 00 00 -- 90 2D
|
---|
129 | * DC 02 00 00 2D -- 0B 07 30 30 30 30 36 30 00 0B 07 30 30 30 30 36 30 00 \
|
---|
130 | * 0B 07 30 30 30 30 36 30 00 0B 07 30 30 30 30 36 30 00 \
|
---|
131 | * 0B 07 30 30 30 30 31 32 00 90 00
|
---|
132 | *
|
---|
133 | * Unknown commands
|
---|
134 | * DC 4A 00 00 00 -- 90 06
|
---|
135 | * DC 12 00 00 06 -- 1D 04 00 00 00 00 90 00
|
---|
136 | *
|
---|
137 | * DC 50 00 00 00 -- 90 0E
|
---|
138 | * DC 12 00 00 0E -- 1E 0C 00 0F 42 40 00 3D 09 00 00 1F 01 74 90 00
|
---|
139 | *
|
---|
140 | */
|
---|
141 |
|
---|
142 | #include "globals.h"
|
---|
143 |
|
---|
144 | #ifdef READER_GRIFFIN
|
---|
145 | #include "reader-common.h"
|
---|
146 |
|
---|
147 | #define DEBUG 0
|
---|
148 |
|
---|
149 | #define GRIFFIN_CMD_INIT 0x00
|
---|
150 | #define GRIFFIN_CMD_GET_HEX_SERIAL 0x02
|
---|
151 | #define GRIFFIN_CMD_GET_ASCII_SERIAL 0x04
|
---|
152 | #define GRIFFIN_CMD_GET_CAID 0x06
|
---|
153 | #define GRIFFIN_CMD_GET_CARD_ADDRESS 0x08
|
---|
154 | #define GRIFFIN_CMD_SEND_EMM 0x12
|
---|
155 | #define GRIFFIN_CMD_SEND_ECM 0x16
|
---|
156 | #define GRIFFIN_CMD_SUBSCRIPTION_INFO 0x20
|
---|
157 |
|
---|
158 | #define cmd_buf_len 512
|
---|
159 |
|
---|
160 | struct griffin_data
|
---|
161 | {
|
---|
162 | uint8_t cmd_base; // Command base, depends on the card
|
---|
163 | };
|
---|
164 |
|
---|
165 | // Sets cmd_buf and returns buf_len
|
---|
166 | static uint32_t griffin_init_cmd(struct s_reader *rdr, uint8_t *cmd_buf, uint8_t cmd_op, const uint8_t *data, uint8_t data_len)
|
---|
167 | {
|
---|
168 | #define cmd_len 5
|
---|
169 |
|
---|
170 | memset(cmd_buf, 0, cmd_buf_len);
|
---|
171 | cmd_buf[0] = 0xDC; // Command start
|
---|
172 | cmd_buf[1] = cmd_op;
|
---|
173 | cmd_buf[2] = 0x00;
|
---|
174 | cmd_buf[3] = 0x00;
|
---|
175 | cmd_buf[4] = data_len; // Set payload length
|
---|
176 |
|
---|
177 | if(data && data_len)
|
---|
178 | { memcpy(cmd_buf + cmd_len, data, data_len); }
|
---|
179 |
|
---|
180 | uint32_t len = cmd_len + (data ? data_len : 0);
|
---|
181 |
|
---|
182 | if(DEBUG)
|
---|
183 | {
|
---|
184 | char tmp[1024];
|
---|
185 | rdr_log(rdr, "SEND[-] -> %s", cs_hexdump(1, cmd_buf, len, tmp, sizeof(tmp)));
|
---|
186 | }
|
---|
187 | return len;
|
---|
188 | }
|
---|
189 |
|
---|
190 | static int32_t griffin_exec_cmd(struct s_reader *rdr, uint8_t cmd_op, const uint8_t *data, uint8_t data_len, uint8_t *response, uint16_t *response_length)
|
---|
191 | {
|
---|
192 | struct griffin_data *csystem_data = rdr->csystem_data;
|
---|
193 | uint8_t buf[cmd_buf_len];
|
---|
194 |
|
---|
195 | int32_t ret = reader_cmd2icc(rdr, buf, griffin_init_cmd(rdr, buf, csystem_data->cmd_base + cmd_op,
|
---|
196 | data, data_len), response, response_length);
|
---|
197 |
|
---|
198 | if(DEBUG)
|
---|
199 | {
|
---|
200 | char tmp[1024];
|
---|
201 | rdr_log(rdr, "RECV[1] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length);
|
---|
202 | }
|
---|
203 |
|
---|
204 | if(ret || *response_length < 2) { return ERROR; } // Response is two short
|
---|
205 | if(response[0] != 0x90) { return ERROR; } // Invalid response
|
---|
206 | if(response[1] == 0) { return OK; } // Nothing to retrieve, command OK
|
---|
207 |
|
---|
208 | // Retrieve response
|
---|
209 | uint8_t cmd_read_response = 0x02;
|
---|
210 | if(csystem_data->cmd_base > 0x10)
|
---|
211 | { cmd_read_response += csystem_data->cmd_base - 0x10; }
|
---|
212 |
|
---|
213 | ret = reader_cmd2icc(rdr, buf, griffin_init_cmd(rdr, buf, cmd_read_response, NULL, response[1]), response, response_length);
|
---|
214 |
|
---|
215 | if(DEBUG)
|
---|
216 | {
|
---|
217 | char tmp[1024];
|
---|
218 | rdr_log(rdr, "RECV[2] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length);
|
---|
219 | }
|
---|
220 |
|
---|
221 | if(ret || *response_length < 2) { return ERROR; } // Response is two short
|
---|
222 | if(response[*response_length - 2] != 0x90) { return ERROR; } // Invalid response
|
---|
223 | if(response[*response_length - 1] != 0x00) { return ERROR; } // We don't expect command_op 0x12 to return more data
|
---|
224 | return OK;
|
---|
225 | }
|
---|
226 |
|
---|
227 | #define griffin_cmd(_cmd_op, _data, _data_len, _min_resp_len) \
|
---|
228 | do { \
|
---|
229 | if (!griffin_exec_cmd(rdr, _cmd_op, _data, _data_len, cta_res, &cta_lr) || cta_lr < _min_resp_len) \
|
---|
230 | return ERROR; \
|
---|
231 | } while(0)
|
---|
232 |
|
---|
233 | static int32_t griffin_card_init(struct s_reader *rdr, ATR *newatr)
|
---|
234 | {
|
---|
235 | int32_t i;
|
---|
236 | get_atr
|
---|
237 | def_resp
|
---|
238 |
|
---|
239 | if(atr_size < 10)
|
---|
240 | {
|
---|
241 | return ERROR;
|
---|
242 | }
|
---|
243 |
|
---|
244 | // 0 1 2 3 4 5 6 7 8 9
|
---|
245 | // ATR: 3B 08 yy 01 xx xx xx xx 10 00
|
---|
246 | if(atr[0] != 0x3b || atr[1] != 0x08 || atr[3] != 0x01 || atr[9] != 0x00)
|
---|
247 | {
|
---|
248 | return ERROR;
|
---|
249 | }
|
---|
250 |
|
---|
251 | if(!cs_malloc(&rdr->csystem_data, sizeof(struct griffin_data)))
|
---|
252 | {
|
---|
253 | return ERROR;
|
---|
254 | }
|
---|
255 |
|
---|
256 | struct griffin_data *csystem_data = rdr->csystem_data;
|
---|
257 |
|
---|
258 | rdr->nprov = 1;
|
---|
259 | memset(rdr->sa, 0, sizeof(rdr->sa));
|
---|
260 | memset(rdr->prid, 0, sizeof(rdr->prid));
|
---|
261 | memset(rdr->hexserial, 0, sizeof(rdr->hexserial));
|
---|
262 |
|
---|
263 | rdr->caid = (0x55 << 8) | atr[2];
|
---|
264 | memcpy(rdr->hexserial, atr + 4, 4);
|
---|
265 | csystem_data->cmd_base = atr[8];
|
---|
266 |
|
---|
267 | rdr_log_sensitive(rdr, "[griffin-reader] card detected, cmd_base: %02X caid: %04X hexserial: {%02X %02X %02X %02X}",
|
---|
268 | csystem_data->cmd_base, rdr->caid, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3]);
|
---|
269 |
|
---|
270 | griffin_cmd(GRIFFIN_CMD_INIT, NULL, 0, 2);
|
---|
271 | csystem_data->cmd_base = cta_res[2]; // already set from ATR
|
---|
272 |
|
---|
273 | griffin_cmd(GRIFFIN_CMD_GET_HEX_SERIAL, NULL, 0, 6);
|
---|
274 | memcpy(rdr->hexserial, cta_res + 2, 4);
|
---|
275 |
|
---|
276 | char serial[16];
|
---|
277 | memset(serial, 0, sizeof(serial));
|
---|
278 | griffin_cmd(GRIFFIN_CMD_GET_ASCII_SERIAL, NULL, 0, 14);
|
---|
279 | memcpy(serial, cta_res + 2, 12);
|
---|
280 |
|
---|
281 | griffin_cmd(GRIFFIN_CMD_GET_CAID, NULL, 0, 4);
|
---|
282 | rdr->caid = (cta_res[2] << 8) | cta_res[3];
|
---|
283 |
|
---|
284 | griffin_cmd(GRIFFIN_CMD_GET_CARD_ADDRESS, NULL, 0, 48);
|
---|
285 |
|
---|
286 | for(i = 1 ; i < CS_MAXPROV; i++)
|
---|
287 | {
|
---|
288 | if(3 + (i * 16) + 4 > cta_lr)
|
---|
289 | {
|
---|
290 | break;
|
---|
291 | }
|
---|
292 | memcpy(rdr->sa[i - 1], cta_res + 3 + (i * 16), 4);
|
---|
293 | }
|
---|
294 |
|
---|
295 | // Unknown commands
|
---|
296 | griffin_cmd(0x22, NULL, 0, 2);
|
---|
297 | griffin_cmd(0x10, NULL, 0, 2);
|
---|
298 | griffin_cmd(0x14, NULL, 0, 2);
|
---|
299 | //griffin_cmd(0x2a, NULL, 0, 2);
|
---|
300 | //griffin_cmd(0x30, NULL, 0, 2);
|
---|
301 |
|
---|
302 | for(i = 0 ; i < CS_MAXPROV; i++)
|
---|
303 | {
|
---|
304 | if(array_has_nonzero_byte(rdr->sa[i], 4))
|
---|
305 | {
|
---|
306 | rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%s}, HexSerial: {%02X %02X %02X %02X} Addr: {%02X %02X %02X %02X}",
|
---|
307 | rdr->caid, serial, rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2], rdr->hexserial[3],
|
---|
308 | rdr->sa[i][0], rdr->sa[i][1], rdr->sa[i][2], rdr->sa[i][3]);
|
---|
309 | }
|
---|
310 | }
|
---|
311 |
|
---|
312 | rdr_log(rdr, "Ready for requests.");
|
---|
313 | return OK;
|
---|
314 | }
|
---|
315 |
|
---|
316 | static int32_t griffin_do_ecm(struct s_reader *rdr, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
317 | {
|
---|
318 | def_resp
|
---|
319 | griffin_cmd(GRIFFIN_CMD_SEND_ECM, er->ecm, er->ecm[2] + 3, 24);
|
---|
320 | memcpy(ea->cw, cta_res + 8, 16);
|
---|
321 | return OK;
|
---|
322 | }
|
---|
323 |
|
---|
324 | static int32_t griffin_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
|
---|
325 | {
|
---|
326 | memcpy(ep->hexserial, ep->emm + 3, 4);
|
---|
327 | switch(ep->emm[0])
|
---|
328 | {
|
---|
329 | case 0x82:
|
---|
330 | case 0x83:
|
---|
331 | if(memcmp(ep->hexserial, rdr->sa[0], 4) == 0)
|
---|
332 | {
|
---|
333 | if(DEBUG)
|
---|
334 | {
|
---|
335 | rdr_log_sensitive(rdr, "SHARED EMM TYPE:%02X SA:{%02X %02X %02X %02X}",
|
---|
336 | ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
|
---|
337 | }
|
---|
338 | ep->type = SHARED;
|
---|
339 | }
|
---|
340 | if(memcmp(ep->hexserial, rdr->sa[1], 4) == 0)
|
---|
341 | {
|
---|
342 | if(DEBUG)
|
---|
343 | {
|
---|
344 | rdr_log_sensitive(rdr, "UNIQUE EMM TYPE:%02X SA:{%02X %02X %02X %02X}",
|
---|
345 | ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
|
---|
346 | }
|
---|
347 | ep->type = UNIQUE;
|
---|
348 | }
|
---|
349 | break;
|
---|
350 |
|
---|
351 | default:
|
---|
352 | ep->type = UNKNOWN;
|
---|
353 | rdr_log_dbg(rdr, D_EMM, "UNKNOWN EMM TYPE:%02X SA:%02X %02X %02X %02X",
|
---|
354 | ep->emm[0], ep->emm[3], ep->emm[4], ep->emm[5], ep->emm[6]);
|
---|
355 | }
|
---|
356 | return OK;
|
---|
357 | }
|
---|
358 |
|
---|
359 | static int32_t griffin_do_emm(struct s_reader *rdr, EMM_PACKET *ep)
|
---|
360 | {
|
---|
361 | def_resp
|
---|
362 | griffin_cmd(GRIFFIN_CMD_SEND_EMM, ep->emm, SCT_LEN(ep->emm), 2);
|
---|
363 | return OK;
|
---|
364 | }
|
---|
365 |
|
---|
366 | static int32_t griffin_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
|
---|
367 | {
|
---|
368 | if(*emm_filters == NULL)
|
---|
369 | {
|
---|
370 | const unsigned int max_filter_count = 4;
|
---|
371 | if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
|
---|
372 | {
|
---|
373 | return ERROR;
|
---|
374 | }
|
---|
375 |
|
---|
376 | struct s_csystem_emm_filter *filters = *emm_filters;
|
---|
377 | *filter_count = 0;
|
---|
378 |
|
---|
379 | int32_t idx = 0;
|
---|
380 |
|
---|
381 | filters[idx].type = EMM_SHARED;
|
---|
382 | filters[idx].enabled = 1;
|
---|
383 | filters[idx].filter[0] = 0x82;
|
---|
384 | filters[idx].filter[1] = rdr->sa[0][0];
|
---|
385 | filters[idx].filter[2] = rdr->sa[0][1];
|
---|
386 | filters[idx].filter[3] = rdr->sa[0][2];
|
---|
387 | filters[idx].filter[4] = rdr->sa[0][3];
|
---|
388 | filters[idx].mask[0] = 0xFF;
|
---|
389 | filters[idx].mask[1] = 0xFF;
|
---|
390 | filters[idx].mask[2] = 0xFF;
|
---|
391 | filters[idx].mask[3] = 0xFF;
|
---|
392 | filters[idx].mask[4] = 0xFF;
|
---|
393 | idx++;
|
---|
394 |
|
---|
395 | filters[idx].type = EMM_SHARED;
|
---|
396 | filters[idx].enabled = 1;
|
---|
397 | filters[idx].filter[0] = 0x82;
|
---|
398 | filters[idx].filter[1] = rdr->sa[1][0];
|
---|
399 | filters[idx].filter[2] = rdr->sa[1][1];
|
---|
400 | filters[idx].filter[3] = rdr->sa[1][2];
|
---|
401 | filters[idx].filter[4] = rdr->sa[1][3];
|
---|
402 | filters[idx].mask[0] = 0xFF;
|
---|
403 | filters[idx].mask[1] = 0xFF;
|
---|
404 | filters[idx].mask[2] = 0xFF;
|
---|
405 | filters[idx].mask[3] = 0xFF;
|
---|
406 | filters[idx].mask[4] = 0xFF;
|
---|
407 | idx++;
|
---|
408 |
|
---|
409 | filters[idx].type = EMM_UNIQUE;
|
---|
410 | filters[idx].enabled = 1;
|
---|
411 | filters[idx].filter[0] = 0x83;
|
---|
412 | filters[idx].filter[1] = rdr->sa[0][0];
|
---|
413 | filters[idx].filter[2] = rdr->sa[0][1];
|
---|
414 | filters[idx].filter[3] = rdr->sa[0][2];
|
---|
415 | filters[idx].filter[4] = rdr->sa[0][3];
|
---|
416 | filters[idx].mask[0] = 0xF0;
|
---|
417 | filters[idx].mask[1] = 0xFF;
|
---|
418 | filters[idx].mask[2] = 0xFF;
|
---|
419 | filters[idx].mask[3] = 0xFF;
|
---|
420 | filters[idx].mask[4] = 0xFF;
|
---|
421 | idx++;
|
---|
422 |
|
---|
423 | filters[idx].type = EMM_UNIQUE;
|
---|
424 | filters[idx].enabled = 1;
|
---|
425 | filters[idx].filter[0] = 0x83;
|
---|
426 | filters[idx].filter[1] = rdr->sa[1][0];
|
---|
427 | filters[idx].filter[2] = rdr->sa[1][1];
|
---|
428 | filters[idx].filter[3] = rdr->sa[1][2];
|
---|
429 | filters[idx].filter[4] = rdr->sa[1][3];
|
---|
430 | filters[idx].mask[0] = 0xF0;
|
---|
431 | filters[idx].mask[1] = 0xFF;
|
---|
432 | filters[idx].mask[2] = 0xFF;
|
---|
433 | filters[idx].mask[3] = 0xFF;
|
---|
434 | filters[idx].mask[4] = 0xFF;
|
---|
435 | idx++;
|
---|
436 |
|
---|
437 | *filter_count = idx;
|
---|
438 | }
|
---|
439 |
|
---|
440 | return OK;
|
---|
441 | }
|
---|
442 |
|
---|
443 | static int32_t griffin_card_info(struct s_reader *rdr)
|
---|
444 | {
|
---|
445 | def_resp
|
---|
446 | int i, r = 0;
|
---|
447 | rdr_log(rdr, "Reading subscription info.");
|
---|
448 |
|
---|
449 | griffin_cmd(GRIFFIN_CMD_SUBSCRIPTION_INFO, NULL, 0, 16);
|
---|
450 |
|
---|
451 | if(cta_res[0] == 0x0b) // Old cards
|
---|
452 | {
|
---|
453 | for(i = 0; i < cta_lr - 8; i += 9)
|
---|
454 | {
|
---|
455 | rdr_log(rdr, " Subscription stream %d - %c%c%c%c%c%c",
|
---|
456 | r++, cta_res[i + 2], cta_res[i + 3], cta_res[i + 4],
|
---|
457 | cta_res[i + 5], cta_res[i + 6], cta_res[i + 7]);
|
---|
458 | }
|
---|
459 | }
|
---|
460 | else if(cta_res[0] == 0x1b) // Newer cards
|
---|
461 | {
|
---|
462 | for(i = 0; i < cta_lr; i += 4)
|
---|
463 | {
|
---|
464 | rdr_log(rdr, " Subscription stream #%02d - 0x%04x",
|
---|
465 | r++, b2i(2, cta_res + i + 2));
|
---|
466 | }
|
---|
467 | }
|
---|
468 |
|
---|
469 | rdr_log(rdr, "End subscription info.");
|
---|
470 | return OK;
|
---|
471 | }
|
---|
472 |
|
---|
473 | const struct s_cardsystem reader_griffin =
|
---|
474 | {
|
---|
475 | .desc = "griffin",
|
---|
476 | .caids = (uint16_t[]){ 0x5501, 0x5502, 0x5504, 0x5506, 0x5508, 0x5509, 0x550E, 0x5511, 0x551A, 0 },
|
---|
477 | .do_emm = griffin_do_emm,
|
---|
478 | .do_ecm = griffin_do_ecm,
|
---|
479 | .card_info = griffin_card_info,
|
---|
480 | .card_init = griffin_card_init,
|
---|
481 | .get_emm_type = griffin_get_emm_type,
|
---|
482 | .get_emm_filter = griffin_get_emm_filter,
|
---|
483 | };
|
---|
484 |
|
---|
485 | #endif
|
---|