2 * Griffin card reader for OSCAM
3 * Copyright (C) 2013 Unix Solutions Ltd.
5 * Author(s): Georgi Chorbadzhiyski (gf@unixsol.org)
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.
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.
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/>.
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.
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 * =========================================================================
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)
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)
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)
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)
53 * The command number is (base + number, the numbers bellow are for base==20)
56 * 24 - get ascii serial
58 * 28 - get card addresses
59 * 30 - unknown command
60 * 34 - unknown command
63 * 40 - get subscription info
64 * 42 - unknown command
65 * 4a - unknown command
66 * 50 - unknown command
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)
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)
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......)
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/)
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)
87 * DC 42 00 00 00 -- 90 03
88 * DC 12 00 00 03 -- 1C 01 00 90 00
90 * DC 34 00 00 00 -- 90 00
91 * DC 30 00 00 00 -- 90 00
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
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
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
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
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
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
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
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
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
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
134 * DC 4A 00 00 00 -- 90 06
135 * DC 12 00 00 06 -- 1D 04 00 00 00 00 90 00
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
144 #ifdef READER_GRIFFIN
145 #include "reader-common.h"
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
158 #define cmd_buf_len 512
162 uint8_t cmd_base
; // Command base, depends on the card
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
)
170 memset(cmd_buf
, 0, cmd_buf_len
);
171 cmd_buf
[0] = 0xDC; // Command start
175 cmd_buf
[4] = data_len
; // Set payload length
178 { memcpy(cmd_buf
+ cmd_len
, data
, data_len
); }
180 uint32_t len
= cmd_len
+ (data
? data_len
: 0);
185 rdr_log(rdr
, "SEND[-] -> %s", cs_hexdump(1, cmd_buf
, len
, tmp
, sizeof(tmp
)));
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
)
192 struct griffin_data
*csystem_data
= rdr
->csystem_data
;
193 uint8_t buf
[cmd_buf_len
];
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
);
201 rdr_log(rdr
, "RECV[1] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response
, *response_length
, tmp
, sizeof(tmp
)), ret
, *response_length
);
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
209 uint8_t cmd_read_response
= 0x02;
210 if(csystem_data
->cmd_base
> 0x10)
211 { cmd_read_response
+= csystem_data
->cmd_base
- 0x10; }
213 ret
= reader_cmd2icc(rdr
, buf
, griffin_init_cmd(rdr
, buf
, cmd_read_response
, NULL
, response
[1]), response
, response_length
);
218 rdr_log(rdr
, "RECV[2] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response
, *response_length
, tmp
, sizeof(tmp
)), ret
, *response_length
);
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
227 #define griffin_cmd(_cmd_op, _data, _data_len, _min_resp_len) \
229 if (!griffin_exec_cmd(rdr, _cmd_op, _data, _data_len, cta_res, &cta_lr) || cta_lr < _min_resp_len) \
233 static int32_t griffin_card_init(struct s_reader
*rdr
, ATR
*newatr
)
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)
251 if(!cs_malloc(&rdr
->csystem_data
, sizeof(struct griffin_data
)))
256 struct griffin_data
*csystem_data
= rdr
->csystem_data
;
259 memset(rdr
->sa
, 0, sizeof(rdr
->sa
));
260 memset(rdr
->prid
, 0, sizeof(rdr
->prid
));
261 memset(rdr
->hexserial
, 0, sizeof(rdr
->hexserial
));
263 rdr
->caid
= (0x55 << 8) | atr
[2];
264 memcpy(rdr
->hexserial
, atr
+ 4, 4);
265 csystem_data
->cmd_base
= atr
[8];
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]);
270 griffin_cmd(GRIFFIN_CMD_INIT
, NULL
, 0, 2);
271 csystem_data
->cmd_base
= cta_res
[2]; // already set from ATR
273 griffin_cmd(GRIFFIN_CMD_GET_HEX_SERIAL
, NULL
, 0, 6);
274 memcpy(rdr
->hexserial
, cta_res
+ 2, 4);
277 memset(serial
, 0, sizeof(serial
));
278 griffin_cmd(GRIFFIN_CMD_GET_ASCII_SERIAL
, NULL
, 0, 14);
279 memcpy(serial
, cta_res
+ 2, 12);
281 griffin_cmd(GRIFFIN_CMD_GET_CAID
, NULL
, 0, 4);
282 rdr
->caid
= (cta_res
[2] << 8) | cta_res
[3];
284 griffin_cmd(GRIFFIN_CMD_GET_CARD_ADDRESS
, NULL
, 0, 48);
286 for(i
= 1 ; i
< CS_MAXPROV
; i
++)
288 if(3 + (i
* 16) + 4 > cta_lr
)
292 memcpy(rdr
->sa
[i
- 1], cta_res
+ 3 + (i
* 16), 4);
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);
302 for(i
= 0 ; i
< CS_MAXPROV
; i
++)
304 if(array_has_nonzero_byte(rdr
->sa
[i
], 4))
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]);
312 rdr_log(rdr
, "Ready for requests.");
316 static int32_t griffin_do_ecm(struct s_reader
*rdr
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
319 griffin_cmd(GRIFFIN_CMD_SEND_ECM
, er
->ecm
, er
->ecm
[2] + 3, 24);
320 memcpy(ea
->cw
, cta_res
+ 8, 16);
324 static int32_t griffin_get_emm_type(EMM_PACKET
*ep
, struct s_reader
*rdr
)
326 memcpy(ep
->hexserial
, ep
->emm
+ 3, 4);
331 if(memcmp(ep
->hexserial
, rdr
->sa
[0], 4) == 0)
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]);
340 if(memcmp(ep
->hexserial
, rdr
->sa
[1], 4) == 0)
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]);
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]);
359 static int32_t griffin_do_emm(struct s_reader
*rdr
, EMM_PACKET
*ep
)
362 griffin_cmd(GRIFFIN_CMD_SEND_EMM
, ep
->emm
, SCT_LEN(ep
->emm
), 2);
366 static int32_t griffin_get_emm_filter(struct s_reader
*rdr
, struct s_csystem_emm_filter
**emm_filters
, unsigned int *filter_count
)
368 if(*emm_filters
== NULL
)
370 const unsigned int max_filter_count
= 4;
371 if(!cs_malloc(emm_filters
, max_filter_count
* sizeof(struct s_csystem_emm_filter
)))
376 struct s_csystem_emm_filter
*filters
= *emm_filters
;
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;
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;
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;
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;
443 static int32_t griffin_card_info(struct s_reader
*rdr
)
447 rdr_log(rdr
, "Reading subscription info.");
449 griffin_cmd(GRIFFIN_CMD_SUBSCRIPTION_INFO
, NULL
, 0, 16);
451 if(cta_res
[0] == 0x0b) // Old cards
453 for(i
= 0; i
< cta_lr
- 8; i
+= 9)
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]);
460 else if(cta_res
[0] == 0x1b) // Newer cards
462 for(i
= 0; i
< cta_lr
; i
+= 4)
464 rdr_log(rdr
, " Subscription stream #%02d - 0x%04x",
465 r
++, b2i(2, cta_res
+ i
+ 2));
469 rdr_log(rdr
, "End subscription info.");
473 const struct s_cardsystem reader_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
,