blob: 0490dcd4476636e84344831d9107a3b937dd5a4f [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file sim.h
2 * Routines for helping with SIM (ISO/IEC 7816-4 more generally) communication.
3 */
4
Harald Welted54c2ee2012-01-17 18:25:50 +01005#ifndef _OSMOCOM_SIM_H
6#define _OSMOCOM_SIM_H
7
8#include <osmocom/core/msgb.h>
9#include <osmocom/core/linuxlist.h>
10
11#define APDU_HDR_LEN 5
12
Neels Hofmeyr87e45502017-06-20 00:17:59 +020013/*! command-response pairs cases
Kevin Redon43eabee2012-09-16 18:40:02 +020014 *
15 * Enumeration used to identify the APDU structure based on command-response pair case , as specified in ISO/IEC 7816-3:2006(E) §12.1.
16 */
Harald Welted54c2ee2012-01-17 18:25:50 +010017enum osim_apdu_case {
Kevin Redon43eabee2012-09-16 18:40:02 +020018 APDU_CASE_1, /*!< command header, no command data field, no response data field */
19 APDU_CASE_2S, /*!< command header, no command data field, response data field (short) */
20 APDU_CASE_2E, /*!< command header, no command data field, response data field (extended) */
21 APDU_CASE_3S, /*!< command header, command data field (short), no response data field */
22 APDU_CASE_3E, /*!< command header, command data field (extended), no response data field */
23 APDU_CASE_4S, /*!< command header, command data field (short), response data field (short) */
24 APDU_CASE_4E /*!< command header, command data field (extended), response data field (extended) */
Harald Welted54c2ee2012-01-17 18:25:50 +010025};
26
Neels Hofmeyr87e45502017-06-20 00:17:59 +020027/*! APDU/TPDU command header
Kevin Redon43eabee2012-09-16 18:40:02 +020028 *
29 * This structure encode an APDU/TPDU command header, as specified in ISO/IEC 7816-3:2006(E) §12.2 and §12.3.
30 * The APDU (application layer) can be encoded as different TPDUs (transport layer), depending on the transport protocol used.
31 * The TPDU encoding by T=1 of the APDU command header is identical to the APDU.
32 * The TPDU encoding by T=0 of the APDU command header adds a Parameter 3 field, generally used instead of Lc/Le.
33 *
34 * @todo have different structures for APDU, TPDU by T=0, and TPDU by T=1.
35 */
Harald Welted54c2ee2012-01-17 18:25:50 +010036struct osim_apdu_cmd_hdr {
Kevin Redon43eabee2012-09-16 18:40:02 +020037 uint8_t cla; /*!< CLASS byte */
38 uint8_t ins; /*!< INSTRUCTION byte */
39 uint8_t p1; /*!< Parameter 1 byte */
40 uint8_t p2; /*!< Parameter 2 byte */
41 uint8_t p3; /*!< Parameter 3 byte, used for TPDU by T=0 */
Harald Welted54c2ee2012-01-17 18:25:50 +010042} __attribute__ ((packed));
43
44#define msgb_apdu_dr(__x)
45
Neels Hofmeyr87e45502017-06-20 00:17:59 +020046/*! APDU command body
Kevin Redon43eabee2012-09-16 18:40:02 +020047 *
48 * This structure encode a command body, as specified in ISO/IEC 7816-3:2006(E) §12.1.
49 * The data and response contents should be provided along with this structure.
50 */
Harald Welted54c2ee2012-01-17 18:25:50 +010051struct osim_msgb_cb {
Kevin Redon43eabee2012-09-16 18:40:02 +020052 enum osim_apdu_case apduc; /*!< command-response pair case, defining the encoding of Lc and Le */
53 uint16_t lc; /*!< number of bytes in the command data field Nc, which will encoded in 0, 1 or 3 bytes into Lc, depending on the case */
54 uint16_t le; /*!< maximum number of bytes expected in the response data field, which will encoded in 0, 1, 2 or 3 bytes into Le, depending on the case */
55 uint16_t sw; /*!< status word, composed of SW1 and SW2 bytes */
Harald Weltee8dd2bd2014-05-04 13:42:38 +020056} __attribute__((__may_alias__));
Harald Welted54c2ee2012-01-17 18:25:50 +010057#define OSIM_MSGB_CB(__msgb) ((struct osim_msgb_cb *)&((__msgb)->cb[0]))
Neels Hofmeyr87e45502017-06-20 00:17:59 +020058/*! status word from msgb->cb */
Harald Welted54c2ee2012-01-17 18:25:50 +010059#define msgb_apdu_case(__x) OSIM_MSGB_CB(__x)->apduc
60#define msgb_apdu_lc(__x) OSIM_MSGB_CB(__x)->lc
61#define msgb_apdu_le(__x) OSIM_MSGB_CB(__x)->le
62#define msgb_apdu_sw(__x) OSIM_MSGB_CB(__x)->sw
Neels Hofmeyr87e45502017-06-20 00:17:59 +020063/*! pointer to the command header of the APDU */
Harald Welted54c2ee2012-01-17 18:25:50 +010064#define msgb_apdu_h(__x) ((struct osim_apdu_cmd_hdr *)(__x)->l2h)
65
66#define msgb_apdu_dc(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr))
67#define msgb_apdu_de(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr) + msgb_apdu_lc(__x))
68
Harald Welte586d7102014-05-04 17:01:16 +020069/* FILES */
70
Harald Welted54c2ee2012-01-17 18:25:50 +010071struct osim_file;
72struct osim_file_desc;
73struct osim_decoded_data;
74
Neels Hofmeyr87e45502017-06-20 00:17:59 +020075/*! Operations for a given File */
Harald Welted54c2ee2012-01-17 18:25:50 +010076struct osim_file_ops {
Harald Welte586d7102014-05-04 17:01:16 +020077 /*! Parse binary file data into osim_decoded_data */
Harald Welted54c2ee2012-01-17 18:25:50 +010078 int (*parse)(struct osim_decoded_data *dd,
79 const struct osim_file_desc *desc,
80 int len, uint8_t *data);
Harald Welte586d7102014-05-04 17:01:16 +020081 /*! Encode osim_decoded_data into binary file */
Harald Welte6729a972014-10-26 19:04:56 +010082 struct msgb * (*encode)(const struct osim_file_desc *desc,
Harald Welted54c2ee2012-01-17 18:25:50 +010083 const struct osim_decoded_data *decoded);
84};
85
86enum osim_element_type {
87 ELEM_T_NONE,
88 ELEM_T_BOOL, /*!< a boolean flag */
89 ELEM_T_UINT8, /*!< unsigned integer */
90 ELEM_T_UINT16, /*!< unsigned integer */
91 ELEM_T_UINT32, /*!< unsigned integer */
92 ELEM_T_STRING, /*!< generic string */
93 ELEM_T_BCD, /*!< BCD encoded digits */
94 ELEM_T_BYTES, /*!< BCD encoded digits */
95 ELEM_T_GROUP, /*!< group container, has siblings */
96};
97
98enum osim_element_repr {
99 ELEM_REPR_NONE,
100 ELEM_REPR_DEC,
101 ELEM_REPR_HEX,
102};
103
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200104/*! A single decoded element inside a file */
Harald Welted54c2ee2012-01-17 18:25:50 +0100105struct osim_decoded_element {
106 struct llist_head list;
107
108 enum osim_element_type type;
109 enum osim_element_repr representation;
110 const char *name;
111
112 unsigned int length;
113 union {
114 uint8_t u8;
115 uint16_t u16;
116 uint32_t u32;
117 uint8_t *buf;
Harald Welte586d7102014-05-04 17:01:16 +0200118 /*! A list of sibling decoded_items */
Harald Welted54c2ee2012-01-17 18:25:50 +0100119 struct llist_head siblings;
120 } u;
121};
122
Harald Welte586d7102014-05-04 17:01:16 +0200123/*! Decoded data for a single file, consisting of all decoded elements */
Harald Welted54c2ee2012-01-17 18:25:50 +0100124struct osim_decoded_data {
125 /*! file to which we belong */
126 const struct osim_file *file;
127 /*! list of 'struct decoded_element' */
128 struct llist_head decoded_elements;
129};
130
131
132enum osim_file_type {
133 TYPE_NONE,
Harald Welte586d7102014-05-04 17:01:16 +0200134 TYPE_DF, /*!< Dedicated File */
135 TYPE_ADF, /*!< Application Dedicated File */
136 TYPE_EF, /*!< Entry File */
137 TYPE_EF_INT, /*!< Internal Entry File */
Harald Welted54c2ee2012-01-17 18:25:50 +0100138};
139
140enum osim_ef_type {
Harald Welte586d7102014-05-04 17:01:16 +0200141 EF_TYPE_TRANSP, /*!< Transparent EF */
142 EF_TYPE_RECORD_FIXED, /*!< Fixed-Size Record EF */
143 EF_TYPE_RECORD_CYCLIC, /*!< Cyclic Record EF */
144 EF_TYPE_KEY, /*!< Key file as used in TETRA */
Harald Welted54c2ee2012-01-17 18:25:50 +0100145};
146
147#define F_OPTIONAL 0x0001
148
Harald Welte2656e652014-05-03 14:23:44 +0200149#define SFI_NONE 0xFF
150
Harald Welted54c2ee2012-01-17 18:25:50 +0100151struct osim_file_desc {
152 struct llist_head list; /*!< local element in list */
153 struct llist_head child_list; /*!< list of children EF in DF */
154 struct osim_file_desc *parent; /*!< parent DF */
155
Harald Welte586d7102014-05-04 17:01:16 +0200156 enum osim_file_type type; /*!< Type of the file (EF, DF, ...) */
157 enum osim_ef_type ef_type; /*!< Type of the EF, if type == TYPE_EF */
Harald Welted54c2ee2012-01-17 18:25:50 +0100158
159 uint16_t fid; /*!< File Identifier */
160 uint8_t sfid; /*!< Short File IDentifier */
Harald Welte6729a972014-10-26 19:04:56 +0100161 const uint8_t *df_name;
Harald Welted54c2ee2012-01-17 18:25:50 +0100162 uint8_t df_name_len;
163
164 const char *short_name; /*!< Short Name (like EF.ICCID) */
165 const char *long_name; /*!< Long / description */
166 unsigned int flags;
167
Harald Welte586d7102014-05-04 17:01:16 +0200168 struct osim_file_ops ops; /*!< Operations (parse/encode */
Harald Welte1e0dfda2014-05-03 14:22:12 +0200169
170 struct {
171 size_t min; /*!< Minimum size of the file
172 (transparent) or record in
173 cyclic / linear file */
174 size_t rec; /*!< Recommended size */
175 } size;
Harald Welted54c2ee2012-01-17 18:25:50 +0100176};
177
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200178/*! A single instance of a file: Descriptor and contents */
Harald Welted54c2ee2012-01-17 18:25:50 +0100179struct osim_file {
Harald Welte586d7102014-05-04 17:01:16 +0200180 /*! Descriptor for the file */
Harald Welted54c2ee2012-01-17 18:25:50 +0100181 const struct osim_file_desc *desc;
182
Harald Welte586d7102014-05-04 17:01:16 +0200183 /*! Encoded file contents */
Harald Welted54c2ee2012-01-17 18:25:50 +0100184 struct msgb *encoded_data;
Harald Welte586d7102014-05-04 17:01:16 +0200185 /*! Parsed/Decoded file contents */
Harald Welted54c2ee2012-01-17 18:25:50 +0100186 struct osim_decoded_data *decoded_data;
187};
188
Harald Welte586d7102014-05-04 17:01:16 +0200189/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200190#define EF(pfid, sfi, pns, pflags, pnl, ptype, smin, srec, pdec, penc) \
Harald Welted54c2ee2012-01-17 18:25:50 +0100191 { \
192 .fid = pfid, \
Harald Welte2656e652014-05-03 14:23:44 +0200193 .sfid = sfi, \
Harald Welted54c2ee2012-01-17 18:25:50 +0100194 .type = TYPE_EF, \
195 .ef_type = ptype, \
196 .short_name = pns, \
197 .long_name = pnl, \
198 .flags = pflags, \
199 .ops = { .encode = penc, .parse = pdec }, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200200 .size = { .min = smin, .rec = srec}, \
Harald Welted54c2ee2012-01-17 18:25:50 +0100201 }
202
203
Harald Welte586d7102014-05-04 17:01:16 +0200204/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200205#define EF_TRANSP(fid, sfi, ns, flags, smin, srec, nl, dec, enc) \
206 EF(fid, sfi, ns, flags, nl, EF_TYPE_TRANSP, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200207 smin, srec, dec, enc)
Harald Welte586d7102014-05-04 17:01:16 +0200208/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200209#define EF_TRANSP_N(fid, sfi, ns, flags, smin, srec, nl) \
210 EF_TRANSP(fid, sfi, ns, flags, smin, srec, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200211 nl, &default_decode, NULL)
Harald Welted54c2ee2012-01-17 18:25:50 +0100212
Harald Welte586d7102014-05-04 17:01:16 +0200213/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200214#define EF_CYCLIC(fid, sfi, ns, flags, smin, srec, nl, dec, enc) \
215 EF(fid, sfi, ns, flags, nl, EF_TYPE_RECORD_CYCLIC, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200216 smin, srec, dec, enc)
Harald Welte586d7102014-05-04 17:01:16 +0200217/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200218#define EF_CYCLIC_N(fid, sfi, ns, flags, smin, srec, nl) \
219 EF_CYCLIC(fid, sfi, ns, flags, smin, srec, nl, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200220 &default_decode, NULL)
Harald Welted54c2ee2012-01-17 18:25:50 +0100221
Harald Welte586d7102014-05-04 17:01:16 +0200222/*! Convenience macros for defining EF */
Harald Welte2656e652014-05-03 14:23:44 +0200223#define EF_LIN_FIX(fid, sfi, ns, flags, smin, srec, nl, dec, enc) \
224 EF(fid, sfi, ns, flags, nl, EF_TYPE_RECORD_FIXED, \
Harald Welte1e0dfda2014-05-03 14:22:12 +0200225 smin, srec, dec, enc)
Harald Welte586d7102014-05-04 17:01:16 +0200226/*! Convenience macros for defining EF */
Harald Welte1e0dfda2014-05-03 14:22:12 +0200227#define EF_LIN_FIX_N(fid, sfi, ns, flags, smin, srec, nl) \
228 EF_LIN_FIX(fid, sfi, ns, flags, smin, srec, nl, \
229 &default_decode, NULL)
Harald Welted54c2ee2012-01-17 18:25:50 +0100230
Harald Welte586d7102014-05-04 17:01:16 +0200231/*! Convenience macros for defining EF */
Harald Welteaad7e062014-05-04 16:31:24 +0200232#define EF_KEY(fid, sfi, ns, flags, smin, srec, nl, dec, enc) \
233 EF(fid, sfi, ns, flags, nl, EF_TYPE_KEY, \
234 smin, srec, dec, enc)
Harald Welte586d7102014-05-04 17:01:16 +0200235/*! Convenience macros for defining EF */
Harald Welteaad7e062014-05-04 16:31:24 +0200236#define EF_KEY_N(fid, sfi, ns, flags, smin, srec, nl) \
237 EF_KEY(fid, sfi, ns, flags, smin, srec, nl, \
238 &default_decode, NULL)
239
240
Harald Welted54c2ee2012-01-17 18:25:50 +0100241struct osim_file_desc *
Harald Welte5ffb5032016-03-11 09:40:56 +0700242osim_file_desc_find_name(struct osim_file_desc *parent, const char *name);
Harald Welted54c2ee2012-01-17 18:25:50 +0100243
Harald Weltec28f4cd2016-03-11 09:35:07 +0700244struct osim_file_desc *
Harald Welte5ffb5032016-03-11 09:40:56 +0700245osim_file_desc_find_fid(struct osim_file_desc *parent, uint16_t fid);
Harald Weltec28f4cd2016-03-11 09:35:07 +0700246
247struct osim_file_desc *
Harald Welte5ffb5032016-03-11 09:40:56 +0700248osim_file_desc_find_sfid(struct osim_file_desc *parent, uint8_t sfid);
Harald Weltec28f4cd2016-03-11 09:35:07 +0700249
Harald Welte586d7102014-05-04 17:01:16 +0200250/* STATUS WORDS */
251
Harald Welted54c2ee2012-01-17 18:25:50 +0100252enum osim_card_sw_type {
253 SW_TYPE_NONE,
254 SW_TYPE_STR,
255};
256
257enum osim_card_sw_class {
258 SW_CLS_NONE,
259 SW_CLS_OK,
260 SW_CLS_POSTP,
261 SW_CLS_WARN,
262 SW_CLS_ERROR,
263};
264
Harald Welte586d7102014-05-04 17:01:16 +0200265/*! A card status word (SW) */
Harald Welted54c2ee2012-01-17 18:25:50 +0100266struct osim_card_sw {
Harald Welte586d7102014-05-04 17:01:16 +0200267 /*! status word code (2 bytes) */
Harald Welted54c2ee2012-01-17 18:25:50 +0100268 uint16_t code;
Harald Welte586d7102014-05-04 17:01:16 +0200269 /*! status word mask (2 bytes), to match range/prefix of SW */
Harald Welted54c2ee2012-01-17 18:25:50 +0100270 uint16_t mask;
271 enum osim_card_sw_type type;
272 enum osim_card_sw_class class;
273 union {
Harald Welte586d7102014-05-04 17:01:16 +0200274 /*! Human-readable meaning of SW */
Harald Welted54c2ee2012-01-17 18:25:50 +0100275 const char *str;
276 } u;
277};
278
Harald Welte76749602012-09-19 20:55:54 +0200279#define OSIM_CARD_SW_LAST (const struct osim_card_sw) { \
Harald Welted54c2ee2012-01-17 18:25:50 +0100280 .code = 0, .mask = 0, .type = SW_TYPE_NONE, \
281 .class = SW_CLS_NONE, .u.str = NULL \
282}
283
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200284/*! A card profile (e.g. SIM card */
Harald Welted54c2ee2012-01-17 18:25:50 +0100285struct osim_card_profile {
286 const char *name;
Harald Welte586d7102014-05-04 17:01:16 +0200287 /*! Descriptor for the MF (root directory */
Harald Welted54c2ee2012-01-17 18:25:50 +0100288 struct osim_file_desc *mf;
Harald Welte586d7102014-05-04 17:01:16 +0200289 /*! Array of pointers to status words */
Harald Welte76749602012-09-19 20:55:54 +0200290 const struct osim_card_sw **sws;
Harald Welted54c2ee2012-01-17 18:25:50 +0100291};
292
Harald Welte76749602012-09-19 20:55:54 +0200293const struct osim_card_sw *osim_find_sw(const struct osim_card_profile *cp,
294 uint16_t sw);
Harald Welted83d2962013-03-04 17:52:33 +0000295enum osim_card_sw_class osim_sw_class(const struct osim_card_profile *cp,
296 uint16_t sw_in);
Harald Welte76749602012-09-19 20:55:54 +0200297
298struct osim_card_hdl;
Harald Welte4a62eda2019-03-18 18:27:00 +0100299char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_card_hdl *ch, uint16_t sw_in);
Harald Welte76749602012-09-19 20:55:54 +0200300char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in);
301
Harald Welted54c2ee2012-01-17 18:25:50 +0100302extern const struct tlv_definition ts102221_fcp_tlv_def;
Holger Hans Peter Freytherc2b44582015-04-11 19:31:03 +0200303extern const struct value_string ts102221_fcp_vals[14];
Harald Welted54c2ee2012-01-17 18:25:50 +0100304
305/* 11.1.1.3 */
306enum ts102221_fcp_tag {
307 UICC_FCP_T_FCP = 0x62,
308 UICC_FCP_T_FILE_SIZE = 0x80,
309 UICC_FCP_T_TOT_F_SIZE = 0x81,
310 UICC_FCP_T_FILE_DESC = 0x82,
311 UICC_FCP_T_FILE_ID = 0x83,
312 UICC_FCP_T_DF_NAME = 0x84,
313 UICC_FCP_T_SFID = 0x88,
314 UICC_FCP_T_LIFEC_STS = 0x8A,
315 UICC_FCP_T_SEC_ATTR_REFEXP= 0x8B,
316 UICC_FCP_T_SEC_ATTR_COMP= 0x8C,
317 UICC_FCP_T_PROPRIETARY = 0xA5,
318 UICC_FCP_T_SEC_ATTR_EXP = 0xAB,
319 UICC_FCP_T_PIN_STS_DO = 0xC6,
320};
321
322struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1,
323 uint8_t p2, uint16_t lc, uint16_t le);
324
Harald Welte586d7102014-05-04 17:01:16 +0200325/* CARD READERS */
326
Harald Welte55790aa2014-10-26 18:46:50 +0100327enum osim_proto {
328 OSIM_PROTO_T0 = 0,
329 OSIM_PROTO_T1 = 1,
330};
331
332enum osim_reader_driver {
333 OSIM_READER_DRV_PCSC = 0,
334 OSIM_READER_DRV_OPENCT = 1,
335 OSIM_READER_DRV_SERIAL = 2,
336};
337
Harald Welte932d2d42016-03-19 21:18:40 +0100338struct osim_reader_ops {
339 const char *name;
340 struct osim_reader_hdl *(*reader_open)(int idx, const char *name, void *ctx);
341 struct osim_card_hdl *(*card_open)(struct osim_reader_hdl *rh, enum osim_proto proto);
342 int (*transceive)(struct osim_reader_hdl *rh, struct msgb *msg);
343};
344
Harald Welted54c2ee2012-01-17 18:25:50 +0100345struct osim_reader_hdl {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200346 /*! member in global list of readers */
Harald Welted54c2ee2012-01-17 18:25:50 +0100347 struct llist_head list;
Harald Welte67354b12014-10-26 18:47:30 +0100348 const struct osim_reader_ops *ops;
Harald Welte55790aa2014-10-26 18:46:50 +0100349 uint32_t proto_supported;
Harald Welted54c2ee2012-01-17 18:25:50 +0100350 void *priv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200351 /*! current card, if any */
Harald Welted54c2ee2012-01-17 18:25:50 +0100352 struct osim_card_hdl *card;
353};
354
355struct osim_card_hdl {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200356 /*! member in global list of cards */
Harald Welted54c2ee2012-01-17 18:25:50 +0100357 struct llist_head list;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200358 /*! reader through which card is accessed */
Harald Welted54c2ee2012-01-17 18:25:50 +0100359 struct osim_reader_hdl *reader;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200360 /*! card profile */
Harald Welted54c2ee2012-01-17 18:25:50 +0100361 struct osim_card_profile *prof;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200362 /*! card protocol */
Harald Welte55790aa2014-10-26 18:46:50 +0100363 enum osim_proto proto;
Harald Welted54c2ee2012-01-17 18:25:50 +0100364
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200365 /*! list of channels for this card */
Harald Welted54c2ee2012-01-17 18:25:50 +0100366 struct llist_head channels;
367};
368
369struct osim_chan_hdl {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200370 /*! linked to card->channels */
Harald Welted54c2ee2012-01-17 18:25:50 +0100371 struct llist_head list;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200372 /*! card to which this channel belongs */
Harald Welted54c2ee2012-01-17 18:25:50 +0100373 struct osim_card_hdl *card;
374 const struct osim_file_desc *cwd;
375};
376
377/* reader.c */
378int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg);
Harald Welte55790aa2014-10-26 18:46:50 +0100379struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver drv, int idx,
380 const char *name, void *ctx);
381struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh, enum osim_proto proto);
Harald Welted54c2ee2012-01-17 18:25:50 +0100382#endif /* _OSMOCOM_SIM_H */