summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/usb/usba/whcdi.h
blob: c5fbafb67a66bb2d821eb34f52bf2f294c4a74da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_USB_WHCDI_H
#define	_SYS_USB_WHCDI_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/usb/usba/usba_types.h>
#include <sys/usb/usba/wusba.h>
#include <sys/usb/usba/wusba_io.h>
#include <sys/usb/usba/wa.h>	/* for wusb_secrt_data_t */


/*
 * This file contains data structures and functions that might be
 * shared by HWA and WHCI drivers.
 */

typedef struct wusb_hc_cc_list {
	wusb_cc_t		cc;
	struct wusb_hc_cc_list	*next;
} wusb_hc_cc_list_t;

struct wusb_hc_data;

typedef struct wusb_dev_info {
	struct wusb_hc_data	*wdev_hc; /* the HC this device attaches */
	uint8_t			wdev_cdid[16];
	uint16_t		wdev_addr;
	uint16_t		wdev_state;
	uint8_t			wdev_is_newconn;
	uint8_t			wdev_beacon_attr;
	usb_pipe_handle_t	wdev_ph;	/* used before authenticated */
	wusb_secrt_data_t	wdev_secrt_data;
	usb_uwb_cap_descr_t	*wdev_uwb_descr;
	wusb_cc_t		*wdev_cc;
	uint8_t			wdev_ptk[16];
	uint8_t			wdev_tkid[3];
	timeout_id_t		wdev_trust_timer; /* TrustTimeout timer */
	uint8_t			wdev_active;
} wusb_dev_info_t;

_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_dev_info::wdev_addr))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_dev_info::wdev_uwb_descr))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_dev_info::wdev_hc))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_dev_info::wdev_secrt_data))

/*
 * According to WUSB 1.0 spec, WUSB hosts can support up to 127 devices.
 * To comply with USB bus convention that bus address 1 is assigned
 * to the host controller device, the addresses assigned to WUSB devices
 * would start from 2. So the max device number is reduced to 126.
 */
#define	WUSB_MAX_PORTS		126

#define	WUSB_CHILD_ZAP		0x1

typedef struct wusb_hc_data {
	dev_info_t		*hc_dip;
	void			*hc_private_data;
	uint8_t			hc_chid[16];
	uint8_t			hc_cluster_id;
	uint8_t			hc_num_mmcies;
	kmutex_t		hc_mutex;
	wusb_ie_header_t	**hc_mmcie_list;

	boolean_t		hc_newcon_enabled;

	/* save the often used IEs so as not to allocate them each time */
	wusb_ie_keepalive_t		hc_alive_ie;

	/* children info structures */
	uint8_t			hc_num_ports;
	wusb_dev_info_t		**hc_dev_infos;
	dev_info_t		**hc_children_dips;
	size_t			hc_cd_list_length;
	usba_device_t		**hc_usba_devices;

	/* for bus unconfig */
	uint8_t			hc_children_state[WUSB_MAX_PORTS + 1];

	/* child connection functions */
	void	(*disconnect_dev)(dev_info_t *, usb_port_t);
	void	(*reconnect_dev)(dev_info_t *, usb_port_t);
	int	(*create_child)(dev_info_t *, usb_port_t);
	int	(*destroy_child)(dev_info_t *, usb_port_t);

	/*
	 * some necessary host functions:
	 * Both HWA and HCI must implement these entries to support basic
	 * host controller operations.
	 */
	int	(*set_encrypt)(dev_info_t *, usb_port_t, uint8_t);
	int	(*set_ptk)(dev_info_t *, usb_key_descr_t *, size_t, usb_port_t);
	int	(*set_gtk)(dev_info_t *, usb_key_descr_t *, size_t);
	int	(*set_device_info)(dev_info_t *, wusb_dev_info_t *, usb_port_t);
	int	(*set_cluster_id) (dev_info_t *, uint8_t id);
	int	(*set_stream_idx) (dev_info_t *, uint8_t idx);
	int	(*set_wusb_mas)	(dev_info_t *, uint8_t *data);
	int	(*add_mmc_ie)	(dev_info_t *, uint8_t interval, uint8_t rcnt,
				uint8_t iehdl, uint16_t len, uint8_t *data);
	int	(*rem_mmc_ie)	(dev_info_t *, uint8_t iehdl);
	int	(*stop_ch)	(dev_info_t *, uint32_t time);
	int	(*set_num_dnts)	(dev_info_t *, uint8_t interval, uint8_t nslot);
	int	(*get_time)	(dev_info_t *, uint8_t timetype,
				uint16_t timelen, uint32_t *time);

	/* host addr in MAC layer */
	uint16_t		hc_addr;

	/* beaconing channel */
	uint8_t			hc_channel;

	/* reserved MASes. bitmaps */
	uint8_t			hc_mas[WUSB_SET_WUSB_MAS_LEN];

	/* connection context list for the host */
	wusb_hc_cc_list_t	*hc_cc_list;

	/* group temporal key */
	usb_key_descr_t		hc_gtk;
	uint8_t			hc_gtk_padding[15];
} wusb_hc_data_t;

_NOTE(MUTEX_PROTECTS_DATA(wusb_hc_data_t::hc_mutex, wusb_dev_info_t))
_NOTE(MUTEX_PROTECTS_DATA(wusb_hc_data_t::hc_mutex, wusb_hc_data_t))

_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::hc_num_ports))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::hc_num_mmcies))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::hc_dip))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::hc_gtk))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::add_mmc_ie))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::rem_mmc_ie))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_cluster_id))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_encrypt))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_gtk))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_ptk))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_num_dnts))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_stream_idx))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::set_wusb_mas))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::stop_ch))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::create_child))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::destroy_child))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::disconnect_dev))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::reconnect_dev))
_NOTE(DATA_READABLE_WITHOUT_LOCK(wusb_hc_data_t::get_time))

_NOTE(SCHEME_PROTECTS_DATA("local use only",
				wusb_ie_host_disconnect::bLength))
_NOTE(SCHEME_PROTECTS_DATA("local use only",
				wusb_ie_host_disconnect::bIEIdentifier))
_NOTE(SCHEME_PROTECTS_DATA("local use only",
				wusb_ccm_nonce::sfn))
/*
 * WUSB 1.0 4.3.8.5 says the range of cluster id is in 0x80-0xfe,
 * we limit the maximum WUSB host controller numbers to 31 now,
 * and take the upper portion of this range as the broadcast
 * cluster id
 */
#define	WUSB_CLUSTER_ID_COUNT		31
#define	WUSB_MIN_CLUSTER_ID		0xe0

#define	WUSB_TRUST_TIMEOUT	4 /* WUSB 4.15.1 TrustTimeout = 4s */
#define	WUSB_TRUST_TIMEOUT_US	WUSB_TRUST_TIMEOUT * MICROSEC

#define	WUSB_PERIODIC_ENDPOINT(endpoint) (((endpoint->bmAttributes & \
	USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) ||\
	((endpoint->bmAttributes &\
	USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH))

#define	WUSB_ISOC_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
	USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH))

#define	WUSB_INTR_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
	USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR))

/* helper functions */
uint8_t	wusb_hc_get_cluster_id();
void	wusb_hc_free_cluster_id(uint8_t id);
int	wusb_hc_get_iehdl(wusb_hc_data_t *hc_data, wusb_ie_header_t *hdr,
	uint8_t *iehdl);
void	wusb_hc_free_iehdl(wusb_hc_data_t *hc_data, uint8_t iehdl);

uint_t	wusb_hc_is_dev_connected(wusb_hc_data_t *hc_data, uint8_t *cdid,
	usb_port_t *port);
uint_t	wusb_hc_is_addr_valid(wusb_hc_data_t *hc_data, uint8_t addr,
	usb_port_t *port);
usb_port_t	wusb_hc_get_free_port(wusb_hc_data_t *hc_data);

/* device notification support */
int	wusb_hc_ack_conn(wusb_hc_data_t *hc_data, usb_port_t port);
int	wusb_hc_ack_disconn(wusb_hc_data_t *hc_data, uint8_t addr);
void	wusb_hc_rm_ack(wusb_hc_data_t *hc_data);
int	wusb_hc_send_keepalive_ie(wusb_hc_data_t *hc_data, uint8_t addr);
int	wusb_hc_auth_dev(wusb_hc_data_t *hc_data, usb_port_t port,
	usb_pipe_handle_t ph, uint8_t ifc, wusb_secrt_data_t *secrt_data);
int	wusb_hc_handle_port_connect(wusb_hc_data_t *hc_data, usb_port_t port,
	usb_pipe_handle_t ph, uint8_t ifc, wusb_secrt_data_t *secrt_data);
void	wusb_hc_handle_dn_connect(wusb_hc_data_t *hc_data,
	usb_pipe_handle_t ph, uint8_t ifc, uint8_t *data, size_t len,
	wusb_secrt_data_t *secrt_data);
void	wusb_hc_handle_dn_disconnect(wusb_hc_data_t *hc_data, uint8_t addr,
	uint8_t *data, size_t len);

/* wusb common device function */
int	wusb_create_child_devi(dev_info_t *dip, char *node_name,
	usba_hcdi_ops_t *usba_hcdi_ops, dev_info_t *usb_root_hub_dip,
	usb_port_status_t port_status, usba_device_t *usba_device,
	dev_info_t **child_dip);
int	wusb_get_dev_security_descr(usb_pipe_handle_t ph,
	wusb_secrt_data_t *secrt_data);
int	wusb_get_bos_cloud(dev_info_t *child_dip, usba_device_t *child_ud);
int	wusb_get_rc_dev_by_hc(dev_info_t *dip, dev_t *dev);

int16_t	wusb_get_ccm_encryption_value(wusb_secrt_data_t *secrt_data);

/* device dynamical configuration functions */
void	wusb_hc_disconnect_dev(wusb_hc_data_t *hc_data, usb_port_t port);
void	wusb_hc_reconnect_dev(wusb_hc_data_t *hc_data, usb_port_t port);
int	wusb_hc_create_child(wusb_hc_data_t *hc_data, usb_port_t port);
int	wusb_hc_destroy_child(wusb_hc_data_t *hc_data, usb_port_t port);

/* WUSB HC common requests */
int	wusb_hc_set_cluster_id(wusb_hc_data_t *hc_data, uint8_t cluster_id);

int	wusb_hc_set_stream_idx(wusb_hc_data_t *hc_data, uint8_t stream_idx);

int	wusb_hc_set_wusb_mas(wusb_hc_data_t *hc_data, uint8_t *data);

int	wusb_hc_add_mmc_ie(wusb_hc_data_t *hc_data, uint8_t interval,
	uint8_t rcnt, uint8_t iehdl, uint16_t len, uint8_t *data);

int	wusb_hc_remove_mmc_ie(wusb_hc_data_t *hc_data, uint8_t iehdl);
void	wusb_hc_rem_ie(wusb_hc_data_t *hc_data, wusb_ie_header_t *ieh);

int	wusb_hc_stop_ch(wusb_hc_data_t *hc_data, uint32_t timeoff);

int	wusb_hc_set_num_dnts(wusb_hc_data_t *hc_data, uint8_t interval,
	uint8_t nslots);

int	wusb_hc_get_time(wusb_hc_data_t *hc_data, uint8_t time_type,
	uint16_t len, uint32_t *time);

int	wusb_hc_add_host_info(wusb_hc_data_t *hc_data, uint8_t stream_idx);

void	wusb_hc_rem_host_info(wusb_hc_data_t *hc_data);

int	wusb_hc_send_host_disconnect(wusb_hc_data_t *hc_data);

int	wusb_hc_set_device_info(wusb_hc_data_t *hc_data, usb_port_t port);

/* WUSB HC connection context list operations */
void	wusb_hc_add_cc(wusb_hc_cc_list_t **cc_list, wusb_hc_cc_list_t *new_cc);
void	wusb_hc_rem_cc(wusb_hc_cc_list_t **cc_list, wusb_cc_t *old_cc);
void	wusb_hc_free_cc_list(wusb_hc_cc_list_t *cc_list);
wusb_cc_t *wusb_hc_cc_matched(wusb_hc_cc_list_t *cc_list, uint8_t *cdid);

/* security functions */
int	wusb_dev_set_encrypt(usb_pipe_handle_t ph, uint8_t value);
int	wusb_enable_dev_encrypt(wusb_hc_data_t *hc, wusb_dev_info_t *dev_info);
int	wusb_dev_set_key(usb_pipe_handle_t ph, uint8_t key_index,
	usb_key_descr_t *key, size_t klen);
int	wusb_hc_set_encrypt(wusb_hc_data_t *hc_data, usb_port_t port,
	uint8_t type);
int	wusb_hc_set_ptk(wusb_hc_data_t *hc_data, uint8_t *key_data,
	usb_port_t port);
int	wusb_hc_set_gtk(wusb_hc_data_t *hc_data, uint8_t *key_data,
	uint8_t *tkid);

/* crypto functions */
int	PRF(const uchar_t *key, size_t klen, wusb_ccm_nonce_t *nonce,
	const uchar_t *adata, size_t alen,
	const uchar_t *bdata, size_t blen,
	uchar_t *out, size_t bitlen);

#define	PRF_64(key, klen, nonce, adata, alen, bdata, blen, out)	\
	PRF(key, klen, nonce, adata, alen, bdata, blen, out, 64)

#define	PRF_128(key, klen, nonce, adata, alen, bdata, blen, out)	\
	PRF(key, klen, nonce, adata, alen, bdata, blen, out, 128)

#define	PRF_256(key, klen, nonce, adata, alen, bdata, blen, out)	\
	PRF(key, klen, nonce, adata, alen, bdata, blen, out, 256)

int	wusb_gen_random_nonce(wusb_hc_data_t *hc_data,
	wusb_dev_info_t *dev_info, uchar_t *rbuf);

int	wusb_4way_handshake(wusb_hc_data_t *hc_data, usb_port_t port,
	usb_pipe_handle_t ph, uint8_t ifc);

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_USB_WHCDI_H */