1 // SPDX-License-Identifier: GPL-2.0
3 * Wireless USB - Cable Based Association
6 * Copyright (C) 2006 Intel Corporation
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
10 * WUSB devices have to be paired (associated in WUSB lingo) so
11 * that they can connect to the system.
13 * One way of pairing is using CBA-Cable Based Association. First
14 * time you plug the device with a cable, association is done between
15 * host and device and subsequent times, you can connect wirelessly
16 * without having to associate again. That's the idea.
18 * This driver does nothing Earth shattering. It just provides an
19 * interface to chat with the wire-connected device so we can get a
20 * CDID (device ID) that might have been previously associated to a
21 * CHID (host ID) and to set up a new <CHID,CDID,CK> triplet
22 * (connection context), with the CK being the secret, or connection
23 * key. This is the pairing data.
25 * When a device with the CBA capability connects, the probe routine
26 * just creates a bunch of sysfs files that a user space enumeration
27 * manager uses to allow it to connect wirelessly to the system or not.
29 * The process goes like this:
31 * 1. Device plugs, cbaf is loaded, notifications happen.
33 * 2. The connection manager (CM) sees a device with CBAF capability
34 * (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE).
36 * 3. The CM writes the host name, supported band groups, and the CHID
37 * (host ID) into the wusb_host_name, wusb_host_band_groups and
38 * wusb_chid files. These get sent to the device and the CDID (if
39 * any) for this host is requested.
41 * 4. The CM can verify that the device's supported band groups
42 * (wusb_device_band_groups) are compatible with the host.
44 * 5. The CM reads the wusb_cdid file.
46 * 6. The CM looks up its database
48 * 6.1 If it has a matching CHID,CDID entry, the device has been
49 * authorized before (paired) and nothing further needs to be
52 * 6.2 If the CDID is zero (or the CM doesn't find a matching CDID in
53 * its database), the device is assumed to be not known. The CM
54 * may associate the host with device by: writing a randomly
55 * generated CDID to wusb_cdid and then a random CK to wusb_ck
56 * (this uploads the new CC to the device).
58 * CMD may choose to prompt the user before associating with a new
61 * 7. Device is unplugged.
63 * When the device tries to connect wirelessly, it will present its
64 * CDID to the WUSB host controller. The CM will query the
65 * database. If the CHID/CDID pair found, it will (with a 4-way
66 * handshake) challenge the device to demonstrate it has the CK secret
67 * key (from our database) without actually exchanging it. Once
68 * satisfied, crypto keys are derived from the CK, the device is
69 * connected and all communication is encrypted.
72 * [WUSB-AM] Association Models Supplement to the Certified Wireless
73 * Universal Serial Bus Specification, version 1.0.
75 #include <linux/module.h>
76 #include <linux/ctype.h>
77 #include <linux/usb.h>
78 #include <linux/interrupt.h>
79 #include <linux/delay.h>
80 #include <linux/random.h>
81 #include <linux/slab.h>
82 #include <linux/mutex.h>
83 #include <linux/uwb.h>
84 #include <linux/usb/wusb.h>
85 #include <linux/usb/association.h>
87 #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */
89 /* An instance of a Cable-Based-Association-Framework device */
91 struct usb_device
*usb_dev
;
92 struct usb_interface
*usb_iface
;
96 struct wusb_ckhdid chid
;
97 char host_name
[CBA_NAME_LEN
];
100 struct wusb_ckhdid cdid
;
101 char device_name
[CBA_NAME_LEN
];
102 u16 device_band_groups
;
104 struct wusb_ckhdid ck
;
108 * Verify that a CBAF USB-interface has what we need
110 * According to [WUSB-AM], CBA devices should provide at least two
112 * - RETRIEVE_HOST_INFO
115 * If the device doesn't provide these interfaces, we do not know how
118 static int cbaf_check(struct cbaf
*cbaf
)
121 struct device
*dev
= &cbaf
->usb_iface
->dev
;
122 struct wusb_cbaf_assoc_info
*assoc_info
;
123 struct wusb_cbaf_assoc_request
*assoc_request
;
126 int ar_rhi
= 0, ar_assoc
= 0;
128 result
= usb_control_msg(
129 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
130 CBAF_REQ_GET_ASSOCIATION_INFORMATION
,
131 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
132 0, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
133 cbaf
->buffer
, cbaf
->buffer_size
, USB_CTRL_GET_TIMEOUT
);
135 dev_err(dev
, "Cannot get available association types: %d\n",
140 assoc_info
= cbaf
->buffer
;
141 if (result
< sizeof(*assoc_info
)) {
142 dev_err(dev
, "Not enough data to decode association info "
143 "header (%zu vs %zu bytes required)\n",
144 (size_t)result
, sizeof(*assoc_info
));
148 assoc_size
= le16_to_cpu(assoc_info
->Length
);
149 if (result
< assoc_size
) {
150 dev_err(dev
, "Not enough data to decode association info "
151 "(%zu vs %zu bytes required)\n",
152 (size_t)assoc_size
, sizeof(*assoc_info
));
156 * From now on, we just verify, but won't error out unless we
157 * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
160 itr
= cbaf
->buffer
+ sizeof(*assoc_info
);
161 top
= cbaf
->buffer
+ assoc_size
;
162 dev_dbg(dev
, "Found %u association requests (%zu bytes)\n",
163 assoc_info
->NumAssociationRequests
, assoc_size
);
166 u16 ar_type
, ar_subtype
;
172 if (top
- itr
< sizeof(*assoc_request
)) {
173 dev_err(dev
, "Not enough data to decode association "
174 "request (%zu vs %zu bytes needed)\n",
175 top
- itr
, sizeof(*assoc_request
));
179 ar_type
= le16_to_cpu(assoc_request
->AssociationTypeId
);
180 ar_subtype
= le16_to_cpu(assoc_request
->AssociationSubTypeId
);
181 ar_size
= le32_to_cpu(assoc_request
->AssociationTypeInfoSize
);
186 /* Verify we have what is mandated by [WUSB-AM]. */
187 switch (ar_subtype
) {
188 case AR_TYPE_WUSB_RETRIEVE_HOST_INFO
:
189 ar_name
= "RETRIEVE_HOST_INFO";
192 case AR_TYPE_WUSB_ASSOCIATE
:
193 /* send assoc data */
194 ar_name
= "ASSOCIATE";
201 dev_dbg(dev
, "Association request #%02u: 0x%04x/%04x "
203 assoc_request
->AssociationDataIndex
, ar_type
,
204 ar_subtype
, (size_t)ar_size
, ar_name
);
206 itr
+= sizeof(*assoc_request
);
210 dev_err(dev
, "Missing RETRIEVE_HOST_INFO association "
215 dev_err(dev
, "Missing ASSOCIATE association request\n");
222 static const struct wusb_cbaf_host_info cbaf_host_info_defaults
= {
223 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
224 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
225 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
226 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO
),
227 .CHID_hdr
= WUSB_AR_CHID
,
228 .LangID_hdr
= WUSB_AR_LangID
,
229 .HostFriendlyName_hdr
= WUSB_AR_HostFriendlyName
,
232 /* Send WUSB host information (CHID and name) to a CBAF device */
233 static int cbaf_send_host_info(struct cbaf
*cbaf
)
235 struct wusb_cbaf_host_info
*hi
;
240 memset(hi
, 0, sizeof(*hi
));
241 *hi
= cbaf_host_info_defaults
;
242 hi
->CHID
= cbaf
->chid
;
243 hi
->LangID
= 0; /* FIXME: I guess... */
244 strlcpy(hi
->HostFriendlyName
, cbaf
->host_name
, CBA_NAME_LEN
);
245 name_len
= strlen(cbaf
->host_name
);
246 hi
->HostFriendlyName_hdr
.len
= cpu_to_le16(name_len
);
247 hi_size
= sizeof(*hi
) + name_len
;
249 return usb_control_msg(cbaf
->usb_dev
,
250 usb_sndctrlpipe(cbaf
->usb_dev
, 0),
251 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
252 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
254 cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
255 hi
, hi_size
, USB_CTRL_SET_TIMEOUT
);
259 * Get device's information (CDID) associated to CHID
261 * The device will return it's information (CDID, name, bandgroups)
262 * associated to the CHID we have set before, or 0 CDID and default
263 * name and bandgroup if no CHID set or unknown.
265 static int cbaf_cdid_get(struct cbaf
*cbaf
)
268 struct device
*dev
= &cbaf
->usb_iface
->dev
;
269 struct wusb_cbaf_device_info
*di
;
273 result
= usb_control_msg(
274 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
275 CBAF_REQ_GET_ASSOCIATION_REQUEST
,
276 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
277 0x0200, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
278 di
, cbaf
->buffer_size
, USB_CTRL_GET_TIMEOUT
);
280 dev_err(dev
, "Cannot request device information: %d\n",
285 needed
= result
< sizeof(*di
) ? sizeof(*di
) : le32_to_cpu(di
->Length
);
286 if (result
< needed
) {
287 dev_err(dev
, "Not enough data in DEVICE_INFO reply (%zu vs "
288 "%zu bytes needed)\n", (size_t)result
, needed
);
292 strlcpy(cbaf
->device_name
, di
->DeviceFriendlyName
, CBA_NAME_LEN
);
293 cbaf
->cdid
= di
->CDID
;
294 cbaf
->device_band_groups
= le16_to_cpu(di
->BandGroups
);
299 static ssize_t
cbaf_wusb_chid_show(struct device
*dev
,
300 struct device_attribute
*attr
,
303 struct usb_interface
*iface
= to_usb_interface(dev
);
304 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
306 return sprintf(buf
, "%16ph\n", cbaf
->chid
.data
);
309 static ssize_t
cbaf_wusb_chid_store(struct device
*dev
,
310 struct device_attribute
*attr
,
311 const char *buf
, size_t size
)
314 struct usb_interface
*iface
= to_usb_interface(dev
);
315 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
318 "%02hhx %02hhx %02hhx %02hhx "
319 "%02hhx %02hhx %02hhx %02hhx "
320 "%02hhx %02hhx %02hhx %02hhx "
321 "%02hhx %02hhx %02hhx %02hhx",
322 &cbaf
->chid
.data
[0] , &cbaf
->chid
.data
[1],
323 &cbaf
->chid
.data
[2] , &cbaf
->chid
.data
[3],
324 &cbaf
->chid
.data
[4] , &cbaf
->chid
.data
[5],
325 &cbaf
->chid
.data
[6] , &cbaf
->chid
.data
[7],
326 &cbaf
->chid
.data
[8] , &cbaf
->chid
.data
[9],
327 &cbaf
->chid
.data
[10], &cbaf
->chid
.data
[11],
328 &cbaf
->chid
.data
[12], &cbaf
->chid
.data
[13],
329 &cbaf
->chid
.data
[14], &cbaf
->chid
.data
[15]);
334 result
= cbaf_send_host_info(cbaf
);
337 result
= cbaf_cdid_get(cbaf
);
342 static DEVICE_ATTR(wusb_chid
, 0600, cbaf_wusb_chid_show
, cbaf_wusb_chid_store
);
344 static ssize_t
cbaf_wusb_host_name_show(struct device
*dev
,
345 struct device_attribute
*attr
,
348 struct usb_interface
*iface
= to_usb_interface(dev
);
349 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
351 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->host_name
);
354 static ssize_t
cbaf_wusb_host_name_store(struct device
*dev
,
355 struct device_attribute
*attr
,
356 const char *buf
, size_t size
)
359 struct usb_interface
*iface
= to_usb_interface(dev
);
360 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
362 result
= sscanf(buf
, "%63s", cbaf
->host_name
);
368 static DEVICE_ATTR(wusb_host_name
, 0600, cbaf_wusb_host_name_show
,
369 cbaf_wusb_host_name_store
);
371 static ssize_t
cbaf_wusb_host_band_groups_show(struct device
*dev
,
372 struct device_attribute
*attr
,
375 struct usb_interface
*iface
= to_usb_interface(dev
);
376 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
378 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->host_band_groups
);
381 static ssize_t
cbaf_wusb_host_band_groups_store(struct device
*dev
,
382 struct device_attribute
*attr
,
383 const char *buf
, size_t size
)
386 struct usb_interface
*iface
= to_usb_interface(dev
);
387 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
390 result
= sscanf(buf
, "%04hx", &band_groups
);
394 cbaf
->host_band_groups
= band_groups
;
399 static DEVICE_ATTR(wusb_host_band_groups
, 0600,
400 cbaf_wusb_host_band_groups_show
,
401 cbaf_wusb_host_band_groups_store
);
403 static const struct wusb_cbaf_device_info cbaf_device_info_defaults
= {
404 .Length_hdr
= WUSB_AR_Length
,
405 .CDID_hdr
= WUSB_AR_CDID
,
406 .BandGroups_hdr
= WUSB_AR_BandGroups
,
407 .LangID_hdr
= WUSB_AR_LangID
,
408 .DeviceFriendlyName_hdr
= WUSB_AR_DeviceFriendlyName
,
411 static ssize_t
cbaf_wusb_cdid_show(struct device
*dev
,
412 struct device_attribute
*attr
, char *buf
)
414 struct usb_interface
*iface
= to_usb_interface(dev
);
415 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
417 return sprintf(buf
, "%16ph\n", cbaf
->cdid
.data
);
420 static ssize_t
cbaf_wusb_cdid_store(struct device
*dev
,
421 struct device_attribute
*attr
,
422 const char *buf
, size_t size
)
425 struct usb_interface
*iface
= to_usb_interface(dev
);
426 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
427 struct wusb_ckhdid cdid
;
430 "%02hhx %02hhx %02hhx %02hhx "
431 "%02hhx %02hhx %02hhx %02hhx "
432 "%02hhx %02hhx %02hhx %02hhx "
433 "%02hhx %02hhx %02hhx %02hhx",
434 &cdid
.data
[0] , &cdid
.data
[1],
435 &cdid
.data
[2] , &cdid
.data
[3],
436 &cdid
.data
[4] , &cdid
.data
[5],
437 &cdid
.data
[6] , &cdid
.data
[7],
438 &cdid
.data
[8] , &cdid
.data
[9],
439 &cdid
.data
[10], &cdid
.data
[11],
440 &cdid
.data
[12], &cdid
.data
[13],
441 &cdid
.data
[14], &cdid
.data
[15]);
449 static DEVICE_ATTR(wusb_cdid
, 0600, cbaf_wusb_cdid_show
, cbaf_wusb_cdid_store
);
451 static ssize_t
cbaf_wusb_device_band_groups_show(struct device
*dev
,
452 struct device_attribute
*attr
,
455 struct usb_interface
*iface
= to_usb_interface(dev
);
456 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
458 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->device_band_groups
);
461 static DEVICE_ATTR(wusb_device_band_groups
, 0600,
462 cbaf_wusb_device_band_groups_show
,
465 static ssize_t
cbaf_wusb_device_name_show(struct device
*dev
,
466 struct device_attribute
*attr
,
469 struct usb_interface
*iface
= to_usb_interface(dev
);
470 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
472 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->device_name
);
474 static DEVICE_ATTR(wusb_device_name
, 0600, cbaf_wusb_device_name_show
, NULL
);
476 static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults
= {
477 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
478 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
479 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
480 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE
),
481 .Length_hdr
= WUSB_AR_Length
,
482 .Length
= cpu_to_le32(sizeof(struct wusb_cbaf_cc_data
)),
483 .ConnectionContext_hdr
= WUSB_AR_ConnectionContext
,
484 .BandGroups_hdr
= WUSB_AR_BandGroups
,
487 static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults
= {
488 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
489 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
490 .Length_hdr
= WUSB_AR_Length
,
491 .AssociationStatus_hdr
= WUSB_AR_AssociationStatus
,
495 * Send a new CC to the device.
497 static int cbaf_cc_upload(struct cbaf
*cbaf
)
500 struct device
*dev
= &cbaf
->usb_iface
->dev
;
501 struct wusb_cbaf_cc_data
*ccd
;
504 *ccd
= cbaf_cc_data_defaults
;
505 ccd
->CHID
= cbaf
->chid
;
506 ccd
->CDID
= cbaf
->cdid
;
508 ccd
->BandGroups
= cpu_to_le16(cbaf
->host_band_groups
);
510 dev_dbg(dev
, "Trying to upload CC:\n");
511 dev_dbg(dev
, " CHID %16ph\n", ccd
->CHID
.data
);
512 dev_dbg(dev
, " CDID %16ph\n", ccd
->CDID
.data
);
513 dev_dbg(dev
, " Bandgroups 0x%04x\n", cbaf
->host_band_groups
);
515 result
= usb_control_msg(
516 cbaf
->usb_dev
, usb_sndctrlpipe(cbaf
->usb_dev
, 0),
517 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
518 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
519 0x0201, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
520 ccd
, sizeof(*ccd
), USB_CTRL_SET_TIMEOUT
);
525 static ssize_t
cbaf_wusb_ck_store(struct device
*dev
,
526 struct device_attribute
*attr
,
527 const char *buf
, size_t size
)
530 struct usb_interface
*iface
= to_usb_interface(dev
);
531 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
534 "%02hhx %02hhx %02hhx %02hhx "
535 "%02hhx %02hhx %02hhx %02hhx "
536 "%02hhx %02hhx %02hhx %02hhx "
537 "%02hhx %02hhx %02hhx %02hhx",
538 &cbaf
->ck
.data
[0] , &cbaf
->ck
.data
[1],
539 &cbaf
->ck
.data
[2] , &cbaf
->ck
.data
[3],
540 &cbaf
->ck
.data
[4] , &cbaf
->ck
.data
[5],
541 &cbaf
->ck
.data
[6] , &cbaf
->ck
.data
[7],
542 &cbaf
->ck
.data
[8] , &cbaf
->ck
.data
[9],
543 &cbaf
->ck
.data
[10], &cbaf
->ck
.data
[11],
544 &cbaf
->ck
.data
[12], &cbaf
->ck
.data
[13],
545 &cbaf
->ck
.data
[14], &cbaf
->ck
.data
[15]);
549 result
= cbaf_cc_upload(cbaf
);
555 static DEVICE_ATTR(wusb_ck
, 0600, NULL
, cbaf_wusb_ck_store
);
557 static struct attribute
*cbaf_dev_attrs
[] = {
558 &dev_attr_wusb_host_name
.attr
,
559 &dev_attr_wusb_host_band_groups
.attr
,
560 &dev_attr_wusb_chid
.attr
,
561 &dev_attr_wusb_cdid
.attr
,
562 &dev_attr_wusb_device_name
.attr
,
563 &dev_attr_wusb_device_band_groups
.attr
,
564 &dev_attr_wusb_ck
.attr
,
568 static const struct attribute_group cbaf_dev_attr_group
= {
569 .name
= NULL
, /* we want them in the same directory */
570 .attrs
= cbaf_dev_attrs
,
573 static int cbaf_probe(struct usb_interface
*iface
,
574 const struct usb_device_id
*id
)
577 struct device
*dev
= &iface
->dev
;
578 int result
= -ENOMEM
;
580 cbaf
= kzalloc(sizeof(*cbaf
), GFP_KERNEL
);
583 cbaf
->buffer
= kmalloc(512, GFP_KERNEL
);
584 if (cbaf
->buffer
== NULL
)
585 goto error_kmalloc_buffer
;
587 cbaf
->buffer_size
= 512;
588 cbaf
->usb_dev
= usb_get_dev(interface_to_usbdev(iface
));
589 cbaf
->usb_iface
= usb_get_intf(iface
);
590 result
= cbaf_check(cbaf
);
592 dev_err(dev
, "This device is not WUSB-CBAF compliant and is not supported yet.\n");
596 result
= sysfs_create_group(&dev
->kobj
, &cbaf_dev_attr_group
);
598 dev_err(dev
, "Can't register sysfs attr group: %d\n", result
);
599 goto error_create_group
;
601 usb_set_intfdata(iface
, cbaf
);
607 usb_put_dev(cbaf
->usb_dev
);
609 error_kmalloc_buffer
:
615 static void cbaf_disconnect(struct usb_interface
*iface
)
617 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
618 struct device
*dev
= &iface
->dev
;
619 sysfs_remove_group(&dev
->kobj
, &cbaf_dev_attr_group
);
620 usb_set_intfdata(iface
, NULL
);
622 usb_put_dev(cbaf
->usb_dev
);
624 /* paranoia: clean up crypto keys */
628 static const struct usb_device_id cbaf_id_table
[] = {
629 { USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
632 MODULE_DEVICE_TABLE(usb
, cbaf_id_table
);
634 static struct usb_driver cbaf_driver
= {
636 .id_table
= cbaf_id_table
,
638 .disconnect
= cbaf_disconnect
,
641 module_usb_driver(cbaf_driver
);
643 MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
644 MODULE_DESCRIPTION("Wireless USB Cable Based Association");
645 MODULE_LICENSE("GPL");