blob: 38a71db0fa581bf6d26b973f2c69b35dcc1d20d4 [file] [log] [blame]
Harald Welte8d186ad2019-05-15 19:40:29 +02001#pragma once
2#include <stdbool.h>
3#include <stdint.h>
4
Harald Weltecab5d152019-05-16 13:31:16 +02005#include "ccid_proto.h"
Harald Welte06348362019-05-19 00:45:17 +02006#include "logging.h"
Harald Welte8d186ad2019-05-15 19:40:29 +02007
8#define NR_SLOTS 8
9
10#define LOGPCI(ci, lvl, fmt, args ...) LOGP(DCCID, lvl, "%s: " fmt, (ci)->name, ## args)
11#define LOGPCS(cs, lvl, fmt, args ...) \
Harald Weltee73a1df2019-05-15 22:27:02 +020012 LOGP(DCCID, lvl, "%s(%u): " fmt, (cs)->ci->name, (cs)->slot_nr, ## args)
Harald Welte8d186ad2019-05-15 19:40:29 +020013
14struct msgb;
15
16struct ccid_pars_decoded {
17 /* global for T0/T1 */
Harald Welte860d0062019-05-18 11:18:39 +020018 uint32_t fi;
19 uint32_t di;
Harald Welte8d186ad2019-05-15 19:40:29 +020020 enum ccid_clock_stop clock_stop;
21 bool inverse_convention;
22
23 struct {
24 uint8_t guard_time_etu;
25 uint8_t waiting_integer;
26 } t0;
27
28 struct {
29 enum ccid_t1_csum_type csum_type;
30 uint8_t guard_time_t1;
31 uint8_t bwi;
32 uint8_t cwi;
33 uint8_t ifsc;
34 uint8_t nad;
35 } t1;
36};
37
38struct ccid_slot {
39 /* back-pointer to the ccid_instance */
40 struct ccid_instance *ci;
41 /* number of this slot (0 = first) */
42 uint8_t slot_nr;
43 /* is there an ICC physically present (card detect)? */
44 bool icc_present;
45 /* was there an ICC present during the last NotifSlotStatus?
46 * should be set to zero every USB resume and setConfig != 0 */
47 bool icc_present_last;
48 /* is the ICC physically powered? */
49 bool icc_powered;
50 /* is the ICC currently in reset? */
51 bool icc_in_reset;
52 /* is this slot currently busy with processing a CCID command? */
53 bool cmd_busy;
54 /* decided CCID parameters */
55 struct ccid_pars_decoded pars;
Eric Wildad1edce2019-11-27 16:51:08 +010056 /* proposed CCID parameters */
57 struct ccid_pars_decoded proposed_pars;
Harald Weltecab5d152019-05-16 13:31:16 +020058 /* default parameters; applied on ResetParameters */
59 const struct ccid_pars_decoded *default_pars;
Harald Welte8d186ad2019-05-15 19:40:29 +020060};
61
Harald Weltecab5d152019-05-16 13:31:16 +020062/* CCID operations provided by USB transport layer */
Harald Welte8d186ad2019-05-15 19:40:29 +020063struct ccid_ops {
Harald Weltee6ac4162019-05-16 11:18:00 +020064 /* msgb ownership in below functions is transferred, i.e. whoever
65 * provides the callback function must make sure to msgb_free() them
66 * once transmission on IN or INT EP has completed. */
Harald Welte8d186ad2019-05-15 19:40:29 +020067 int (*send_in)(struct ccid_instance *ci, struct msgb *msg);
Harald Weltea7da5042019-05-16 11:08:35 +020068 int (*send_int)(struct ccid_instance *ci, struct msgb *msg);
Harald Welte8d186ad2019-05-15 19:40:29 +020069};
70
Harald Weltecab5d152019-05-16 13:31:16 +020071/* CCID operations provided by actual slot hardware */
72struct ccid_slot_ops {
73 /* called once on start-up for initialization */
74 int (*init)(struct ccid_slot *cs);
75 /* called before processing any command for a slot; used e.g. to
76 * update the (power/clock/...) status from the hardware */
77 void (*pre_proc_cb)(struct ccid_slot *cs, struct msgb *msg);
78
Harald Welte505d4412019-05-16 17:26:09 +020079 void (*icc_power_on_async)(struct ccid_slot *cs, struct msgb *msg,
80 const struct ccid_pc_to_rdr_icc_power_on *ipo);
Eric Wild9e622dc2019-11-27 14:43:16 +010081 int (*xfr_block_async)(struct ccid_slot *cs, struct msgb *msg,
Harald Welte505d4412019-05-16 17:26:09 +020082 const struct ccid_pc_to_rdr_xfr_block *xfb);
Harald Weltecab5d152019-05-16 13:31:16 +020083 void (*set_power)(struct ccid_slot *cs, bool enable);
84 void (*set_clock)(struct ccid_slot *cs, enum ccid_clock_command cmd);
Eric Wildad1edce2019-11-27 16:51:08 +010085 int (*set_params)(struct ccid_slot *cs, uint8_t seq, enum ccid_protocol_num proto,
Harald Weltecab5d152019-05-16 13:31:16 +020086 const struct ccid_pars_decoded *pars_dec);
87 int (*set_rate_and_clock)(struct ccid_slot *cs, uint32_t freq_hz, uint32_t rate_bps);
Eric Wild9e622dc2019-11-27 14:43:16 +010088 void (*icc_set_insertion_status)(struct ccid_slot *cs, bool present);
Harald Weltecab5d152019-05-16 13:31:16 +020089};
90
Harald Welte8d186ad2019-05-15 19:40:29 +020091/* An instance of CCID (i.e. a card reader device) */
92struct ccid_instance {
93 /* slots within the reader */
94 struct ccid_slot slot[NR_SLOTS];
95 /* set of function pointers implementing specific operations */
Harald Weltebcbc1972019-05-15 21:57:32 +020096 const struct ccid_ops *ops;
Harald Weltecab5d152019-05-16 13:31:16 +020097 const struct ccid_slot_ops *slot_ops;
Harald Welte6982fab2019-05-16 23:01:35 +020098 /* USB CCID Class Specific Descriptor */
99 const struct usb_ccid_class_descriptor *class_desc;
100 /* array of permitted data rates; length: bNumDataRatesSupported */
101 const uint32_t *data_rates;
102 /* array of permitted clock frequencies; length: bNumClockSupported */
103 const uint32_t *clock_freqs;
Harald Welte8d186ad2019-05-15 19:40:29 +0200104 const char *name;
Harald Weltebcbc1972019-05-15 21:57:32 +0200105 /* user-supplied opaque data */
106 void *priv;
Harald Welte8d186ad2019-05-15 19:40:29 +0200107};
108
Harald Welte005b09d2019-05-16 17:24:29 +0200109int ccid_slot_send(struct ccid_slot *cs, struct msgb *msg);
110int ccid_slot_send_unbusy(struct ccid_slot *cs, struct msgb *msg);
111struct msgb *ccid_gen_slot_status(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
112 enum ccid_error_code err);
113
114struct msgb *ccid_gen_data_block(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
115 enum ccid_error_code err, const uint8_t *data,
116 uint32_t data_len);
117
Harald Weltecab5d152019-05-16 13:31:16 +0200118void ccid_instance_init(struct ccid_instance *ci, const struct ccid_ops *ops,
Harald Welte6982fab2019-05-16 23:01:35 +0200119 const struct ccid_slot_ops *slot_ops,
120 const struct usb_ccid_class_descriptor *class_desc,
121 const uint32_t *data_rates, const uint32_t *clock_freqs,
122 const char *name, void *priv);
Harald Welte8d186ad2019-05-15 19:40:29 +0200123int ccid_handle_out(struct ccid_instance *ci, struct msgb *msg);
Eric Wildad1edce2019-11-27 16:51:08 +0100124struct msgb *ccid_gen_parameters_t0(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
125 enum ccid_error_code err);
126struct msgb *ccid_gen_parameters_t1(struct ccid_slot *cs, uint8_t seq, uint8_t cmd_sts,
127 enum ccid_error_code err);
Harald Welte6982fab2019-05-16 23:01:35 +0200128
129/* Invalid request received: Please return STALL */
130#define CCID_CTRL_RET_INVALID -1
131/* Unknown request received: Not something CCID is supposed to handle */
132#define CCID_CTRL_RET_UNKNOWN 0
133/* Request OK. In case of a CTRL-IN: continue by sending wLength bytes to host */
134#define CCID_CTRL_RET_OK 1
135
136int ccid_handle_ctrl(struct ccid_instance *ci, const uint8_t *ctrl_req, const uint8_t **data_in);