blob: 97d6212b53458af6966b7ed0c89062cf150c8544 [file] [log] [blame]
Harald Welte8d186ad2019-05-15 19:40:29 +02001#pragma once
Harald Weltea67be5f2020-09-03 10:04:36 +02002/* CCID Device handling
3 *
4 * (C) 2019-2020 by Harald Welte <laforge@gnumonks.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19 */
20
Harald Welte8d186ad2019-05-15 19:40:29 +020021#include <stdbool.h>
22#include <stdint.h>
23
Harald Weltecab5d152019-05-16 13:31:16 +020024#include "ccid_proto.h"
Harald Welte06348362019-05-19 00:45:17 +020025#include "logging.h"
Harald Welte8d186ad2019-05-15 19:40:29 +020026
27#define NR_SLOTS 8
28
29#define LOGPCI(ci, lvl, fmt, args ...) LOGP(DCCID, lvl, "%s: " fmt, (ci)->name, ## args)
30#define LOGPCS(cs, lvl, fmt, args ...) \
Harald Weltee73a1df2019-05-15 22:27:02 +020031 LOGP(DCCID, lvl, "%s(%u): " fmt, (cs)->ci->name, (cs)->slot_nr, ## args)
Harald Welte8d186ad2019-05-15 19:40:29 +020032
33struct msgb;
34
35struct ccid_pars_decoded {
36 /* global for T0/T1 */
Harald Welte860d0062019-05-18 11:18:39 +020037 uint32_t fi;
38 uint32_t di;
Harald Welte8d186ad2019-05-15 19:40:29 +020039 enum ccid_clock_stop clock_stop;
40 bool inverse_convention;
41
42 struct {
43 uint8_t guard_time_etu;
44 uint8_t waiting_integer;
45 } t0;
46
47 struct {
48 enum ccid_t1_csum_type csum_type;
49 uint8_t guard_time_t1;
50 uint8_t bwi;
51 uint8_t cwi;
52 uint8_t ifsc;
53 uint8_t nad;
54 } t1;
55};
56
57struct ccid_slot {
58 /* back-pointer to the ccid_instance */
59 struct ccid_instance *ci;
60 /* number of this slot (0 = first) */
61 uint8_t slot_nr;
62 /* is there an ICC physically present (card detect)? */
63 bool icc_present;
64 /* was there an ICC present during the last NotifSlotStatus?
65 * should be set to zero every USB resume and setConfig != 0 */
66 bool icc_present_last;
67 /* is the ICC physically powered? */
68 bool icc_powered;
69 /* is the ICC currently in reset? */
70 bool icc_in_reset;
71 /* is this slot currently busy with processing a CCID command? */
72 bool cmd_busy;
73 /* decided CCID parameters */
74 struct ccid_pars_decoded pars;
Eric Wildad1edce2019-11-27 16:51:08 +010075 /* proposed CCID parameters */
76 struct ccid_pars_decoded proposed_pars;
Harald Weltecab5d152019-05-16 13:31:16 +020077 /* default parameters; applied on ResetParameters */
78 const struct ccid_pars_decoded *default_pars;
Eric Wild759a6462019-11-11 14:22:52 +010079 volatile uint32_t event;
80 volatile void* event_data;
Harald Welte8d186ad2019-05-15 19:40:29 +020081};
82
Harald Weltecab5d152019-05-16 13:31:16 +020083/* CCID operations provided by USB transport layer */
Harald Welte8d186ad2019-05-15 19:40:29 +020084struct ccid_ops {
Harald Weltee6ac4162019-05-16 11:18:00 +020085 /* msgb ownership in below functions is transferred, i.e. whoever
86 * provides the callback function must make sure to msgb_free() them
87 * once transmission on IN or INT EP has completed. */
Harald Welte8d186ad2019-05-15 19:40:29 +020088 int (*send_in)(struct ccid_instance *ci, struct msgb *msg);
Harald Weltea7da5042019-05-16 11:08:35 +020089 int (*send_int)(struct ccid_instance *ci, struct msgb *msg);
Harald Welte8d186ad2019-05-15 19:40:29 +020090};
91
Harald Weltecab5d152019-05-16 13:31:16 +020092/* CCID operations provided by actual slot hardware */
93struct ccid_slot_ops {
94 /* called once on start-up for initialization */
95 int (*init)(struct ccid_slot *cs);
96 /* called before processing any command for a slot; used e.g. to
97 * update the (power/clock/...) status from the hardware */
98 void (*pre_proc_cb)(struct ccid_slot *cs, struct msgb *msg);
99
Harald Welte505d4412019-05-16 17:26:09 +0200100 void (*icc_power_on_async)(struct ccid_slot *cs, struct msgb *msg,
101 const struct ccid_pc_to_rdr_icc_power_on *ipo);
Eric Wild9e622dc2019-11-27 14:43:16 +0100102 int (*xfr_block_async)(struct ccid_slot *cs, struct msgb *msg,
Harald Welte505d4412019-05-16 17:26:09 +0200103 const struct ccid_pc_to_rdr_xfr_block *xfb);
Harald Weltecab5d152019-05-16 13:31:16 +0200104 void (*set_power)(struct ccid_slot *cs, bool enable);
105 void (*set_clock)(struct ccid_slot *cs, enum ccid_clock_command cmd);
Eric Wildad1edce2019-11-27 16:51:08 +0100106 int (*set_params)(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,
Harald Weltecab5d152019-05-16 13:31:16 +0200107 const struct ccid_pars_decoded *pars_dec);
Eric Wild56a50552020-01-28 16:07:23 +0100108 int (*set_rate_and_clock)(struct ccid_slot *cs, uint32_t* freq_hz, uint32_t* rate_bps);
Eric Wild9e622dc2019-11-27 14:43:16 +0100109 void (*icc_set_insertion_status)(struct ccid_slot *cs, bool present);
Eric Wild759a6462019-11-11 14:22:52 +0100110 int (*handle_fsm_events)(struct ccid_slot *cs, bool enable);
Harald Weltecab5d152019-05-16 13:31:16 +0200111};
112
Harald Welte8d186ad2019-05-15 19:40:29 +0200113/* An instance of CCID (i.e. a card reader device) */
114struct ccid_instance {
115 /* slots within the reader */
116 struct ccid_slot slot[NR_SLOTS];
117 /* set of function pointers implementing specific operations */
Harald Weltebcbc1972019-05-15 21:57:32 +0200118 const struct ccid_ops *ops;
Harald Weltecab5d152019-05-16 13:31:16 +0200119 const struct ccid_slot_ops *slot_ops;
Harald Welte6982fab2019-05-16 23:01:35 +0200120 /* USB CCID Class Specific Descriptor */
121 const struct usb_ccid_class_descriptor *class_desc;
122 /* array of permitted data rates; length: bNumDataRatesSupported */
123 const uint32_t *data_rates;
124 /* array of permitted clock frequencies; length: bNumClockSupported */
125 const uint32_t *clock_freqs;
Harald Welte8d186ad2019-05-15 19:40:29 +0200126 const char *name;
Harald Weltebcbc1972019-05-15 21:57:32 +0200127 /* user-supplied opaque data */
128 void *priv;
Harald Welte8d186ad2019-05-15 19:40:29 +0200129};
130
Harald Welte005b09d2019-05-16 17:24:29 +0200131int ccid_slot_send(struct ccid_slot *cs, struct msgb *msg);
132int ccid_slot_send_unbusy(struct ccid_slot *cs, struct msgb *msg);
133struct msgb *ccid_gen_slot_status(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
134 enum ccid_error_code err);
135
136struct msgb *ccid_gen_data_block(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
137 enum ccid_error_code err, const uint8_t *data,
138 uint32_t data_len);
139
Harald Weltecab5d152019-05-16 13:31:16 +0200140void ccid_instance_init(struct ccid_instance *ci, const struct ccid_ops *ops,
Harald Welte6982fab2019-05-16 23:01:35 +0200141 const struct ccid_slot_ops *slot_ops,
142 const struct usb_ccid_class_descriptor *class_desc,
143 const uint32_t *data_rates, const uint32_t *clock_freqs,
144 const char *name, void *priv);
Harald Welte8d186ad2019-05-15 19:40:29 +0200145int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg);
Eric Wildad1edce2019-11-27 16:51:08 +0100146struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
147 enum ccid_error_code err);
148struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
149 enum ccid_error_code err);
Harald Welte6982fab2019-05-16 23:01:35 +0200150
151/* Invalid request received: Please return STALL */
152#define CCID_CTRL_RET_INVALID -1
153/* Unknown request received: Not something CCID is supposed to handle */
154#define CCID_CTRL_RET_UNKNOWN 0
155/* Request OK. In case of a CTRL-IN: continue by sending wLength bytes to host */
156#define CCID_CTRL_RET_OK 1
157
158int ccid_handle_ctrl(struct ccid_instance *ci, const uint8_t *ctrl_req, const uint8_t **data_in);