2 * Wireless USB - Cable Based Association
5 * Copyright (C) 2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * WUSB devices have to be paired (associated in WUSB lingo) so
25 * that they can connect to the system.
27 * One way of pairing is using CBA-Cable Based Association. First
28 * time you plug the device with a cable, association is done between
29 * host and device and subsequent times, you can connect wirelessly
30 * without having to associate again. That's the idea.
32 * This driver does nothing Earth shattering. It just provides an
33 * interface to chat with the wire-connected device so we can get a
34 * CDID (device ID) that might have been previously associated to a
35 * CHID (host ID) and to set up a new <CHID,CDID,CK> triplet
36 * (connection context), with the CK being the secret, or connection
37 * key. This is the pairing data.
39 * When a device with the CBA capability connects, the probe routine
40 * just creates a bunch of sysfs files that a user space enumeration
41 * manager uses to allow it to connect wirelessly to the system or not.
43 * The process goes like this:
45 * 1. Device plugs, cbaf is loaded, notifications happen.
47 * 2. The connection manager (CM) sees a device with CBAF capability
48 * (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE).
50 * 3. The CM writes the host name, supported band groups, and the CHID
51 * (host ID) into the wusb_host_name, wusb_host_band_groups and
52 * wusb_chid files. These get sent to the device and the CDID (if
53 * any) for this host is requested.
55 * 4. The CM can verify that the device's supported band groups
56 * (wusb_device_band_groups) are compatible with the host.
58 * 5. The CM reads the wusb_cdid file.
60 * 6. The CM looks up its database
62 * 6.1 If it has a matching CHID,CDID entry, the device has been
63 * authorized before (paired) and nothing further needs to be
66 * 6.2 If the CDID is zero (or the CM doesn't find a matching CDID in
67 * its database), the device is assumed to be not known. The CM
68 * may associate the host with device by: writing a randomly
69 * generated CDID to wusb_cdid and then a random CK to wusb_ck
70 * (this uploads the new CC to the device).
72 * CMD may choose to prompt the user before associating with a new
75 * 7. Device is unplugged.
77 * When the device tries to connect wirelessly, it will present its
78 * CDID to the WUSB host controller. The CM will query the
79 * database. If the CHID/CDID pair found, it will (with a 4-way
80 * handshake) challenge the device to demonstrate it has the CK secret
81 * key (from our database) without actually exchanging it. Once
82 * satisfied, crypto keys are derived from the CK, the device is
83 * connected and all communication is encrypted.
86 * [WUSB-AM] Association Models Supplement to the Certified Wireless
87 * Universal Serial Bus Specification, version 1.0.
89 #include <linux/module.h>
90 #include <linux/ctype.h>
91 #include <linux/usb.h>
92 #include <linux/interrupt.h>
93 #include <linux/delay.h>
94 #include <linux/random.h>
95 #include <linux/slab.h>
96 #include <linux/mutex.h>
97 #include <linux/uwb.h>
98 #include <linux/usb/wusb.h>
99 #include <linux/usb/association.h>
101 #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */
103 /* An instance of a Cable-Based-Association-Framework device */
105 struct usb_device
*usb_dev
;
106 struct usb_interface
*usb_iface
;
110 struct wusb_ckhdid chid
;
111 char host_name
[CBA_NAME_LEN
];
112 u16 host_band_groups
;
114 struct wusb_ckhdid cdid
;
115 char device_name
[CBA_NAME_LEN
];
116 u16 device_band_groups
;
118 struct wusb_ckhdid ck
;
122 * Verify that a CBAF USB-interface has what we need
124 * According to [WUSB-AM], CBA devices should provide at least two
126 * - RETRIEVE_HOST_INFO
129 * If the device doesn't provide these interfaces, we do not know how
132 static int cbaf_check(struct cbaf
*cbaf
)
135 struct device
*dev
= &cbaf
->usb_iface
->dev
;
136 struct wusb_cbaf_assoc_info
*assoc_info
;
137 struct wusb_cbaf_assoc_request
*assoc_request
;
140 int ar_rhi
= 0, ar_assoc
= 0;
142 result
= usb_control_msg(
143 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
144 CBAF_REQ_GET_ASSOCIATION_INFORMATION
,
145 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
146 0, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
147 cbaf
->buffer
, cbaf
->buffer_size
, 1000 /* FIXME: arbitrary */);
149 dev_err(dev
, "Cannot get available association types: %d\n",
154 assoc_info
= cbaf
->buffer
;
155 if (result
< sizeof(*assoc_info
)) {
156 dev_err(dev
, "Not enough data to decode association info "
157 "header (%zu vs %zu bytes required)\n",
158 (size_t)result
, sizeof(*assoc_info
));
162 assoc_size
= le16_to_cpu(assoc_info
->Length
);
163 if (result
< assoc_size
) {
164 dev_err(dev
, "Not enough data to decode association info "
165 "(%zu vs %zu bytes required)\n",
166 (size_t)assoc_size
, sizeof(*assoc_info
));
170 * From now on, we just verify, but won't error out unless we
171 * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
174 itr
= cbaf
->buffer
+ sizeof(*assoc_info
);
175 top
= cbaf
->buffer
+ assoc_size
;
176 dev_dbg(dev
, "Found %u association requests (%zu bytes)\n",
177 assoc_info
->NumAssociationRequests
, assoc_size
);
180 u16 ar_type
, ar_subtype
;
186 if (top
- itr
< sizeof(*assoc_request
)) {
187 dev_err(dev
, "Not enough data to decode associaton "
188 "request (%zu vs %zu bytes needed)\n",
189 top
- itr
, sizeof(*assoc_request
));
193 ar_type
= le16_to_cpu(assoc_request
->AssociationTypeId
);
194 ar_subtype
= le16_to_cpu(assoc_request
->AssociationSubTypeId
);
195 ar_size
= le32_to_cpu(assoc_request
->AssociationTypeInfoSize
);
200 /* Verify we have what is mandated by [WUSB-AM]. */
201 switch (ar_subtype
) {
202 case AR_TYPE_WUSB_RETRIEVE_HOST_INFO
:
203 ar_name
= "RETRIEVE_HOST_INFO";
206 case AR_TYPE_WUSB_ASSOCIATE
:
207 /* send assoc data */
208 ar_name
= "ASSOCIATE";
215 dev_dbg(dev
, "Association request #%02u: 0x%04x/%04x "
217 assoc_request
->AssociationDataIndex
, ar_type
,
218 ar_subtype
, (size_t)ar_size
, ar_name
);
220 itr
+= sizeof(*assoc_request
);
224 dev_err(dev
, "Missing RETRIEVE_HOST_INFO association "
229 dev_err(dev
, "Missing ASSOCIATE association request\n");
236 static const struct wusb_cbaf_host_info cbaf_host_info_defaults
= {
237 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
238 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
239 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
240 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO
),
241 .CHID_hdr
= WUSB_AR_CHID
,
242 .LangID_hdr
= WUSB_AR_LangID
,
243 .HostFriendlyName_hdr
= WUSB_AR_HostFriendlyName
,
246 /* Send WUSB host information (CHID and name) to a CBAF device */
247 static int cbaf_send_host_info(struct cbaf
*cbaf
)
249 struct wusb_cbaf_host_info
*hi
;
254 memset(hi
, 0, sizeof(*hi
));
255 *hi
= cbaf_host_info_defaults
;
256 hi
->CHID
= cbaf
->chid
;
257 hi
->LangID
= 0; /* FIXME: I guess... */
258 strlcpy(hi
->HostFriendlyName
, cbaf
->host_name
, CBA_NAME_LEN
);
259 name_len
= strlen(cbaf
->host_name
);
260 hi
->HostFriendlyName_hdr
.len
= cpu_to_le16(name_len
);
261 hi_size
= sizeof(*hi
) + name_len
;
263 return usb_control_msg(cbaf
->usb_dev
, usb_sndctrlpipe(cbaf
->usb_dev
, 0),
264 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
265 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
267 cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
268 hi
, hi_size
, 1000 /* FIXME: arbitrary */);
272 * Get device's information (CDID) associated to CHID
274 * The device will return it's information (CDID, name, bandgroups)
275 * associated to the CHID we have set before, or 0 CDID and default
276 * name and bandgroup if no CHID set or unknown.
278 static int cbaf_cdid_get(struct cbaf
*cbaf
)
281 struct device
*dev
= &cbaf
->usb_iface
->dev
;
282 struct wusb_cbaf_device_info
*di
;
286 result
= usb_control_msg(
287 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
288 CBAF_REQ_GET_ASSOCIATION_REQUEST
,
289 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
290 0x0200, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
291 di
, cbaf
->buffer_size
, 1000 /* FIXME: arbitrary */);
293 dev_err(dev
, "Cannot request device information: %d\n", result
);
297 needed
= result
< sizeof(*di
) ? sizeof(*di
) : le32_to_cpu(di
->Length
);
298 if (result
< needed
) {
299 dev_err(dev
, "Not enough data in DEVICE_INFO reply (%zu vs "
300 "%zu bytes needed)\n", (size_t)result
, needed
);
304 strlcpy(cbaf
->device_name
, di
->DeviceFriendlyName
, CBA_NAME_LEN
);
305 cbaf
->cdid
= di
->CDID
;
306 cbaf
->device_band_groups
= le16_to_cpu(di
->BandGroups
);
311 static ssize_t
cbaf_wusb_chid_show(struct device
*dev
,
312 struct device_attribute
*attr
,
315 struct usb_interface
*iface
= to_usb_interface(dev
);
316 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
317 char pr_chid
[WUSB_CKHDID_STRSIZE
];
319 ckhdid_printf(pr_chid
, sizeof(pr_chid
), &cbaf
->chid
);
320 return scnprintf(buf
, PAGE_SIZE
, "%s\n", pr_chid
);
323 static ssize_t
cbaf_wusb_chid_store(struct device
*dev
,
324 struct device_attribute
*attr
,
325 const char *buf
, size_t size
)
328 struct usb_interface
*iface
= to_usb_interface(dev
);
329 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
332 "%02hhx %02hhx %02hhx %02hhx "
333 "%02hhx %02hhx %02hhx %02hhx "
334 "%02hhx %02hhx %02hhx %02hhx "
335 "%02hhx %02hhx %02hhx %02hhx",
336 &cbaf
->chid
.data
[0] , &cbaf
->chid
.data
[1],
337 &cbaf
->chid
.data
[2] , &cbaf
->chid
.data
[3],
338 &cbaf
->chid
.data
[4] , &cbaf
->chid
.data
[5],
339 &cbaf
->chid
.data
[6] , &cbaf
->chid
.data
[7],
340 &cbaf
->chid
.data
[8] , &cbaf
->chid
.data
[9],
341 &cbaf
->chid
.data
[10], &cbaf
->chid
.data
[11],
342 &cbaf
->chid
.data
[12], &cbaf
->chid
.data
[13],
343 &cbaf
->chid
.data
[14], &cbaf
->chid
.data
[15]);
348 result
= cbaf_send_host_info(cbaf
);
351 result
= cbaf_cdid_get(cbaf
);
356 static DEVICE_ATTR(wusb_chid
, 0600, cbaf_wusb_chid_show
, cbaf_wusb_chid_store
);
358 static ssize_t
cbaf_wusb_host_name_show(struct device
*dev
,
359 struct device_attribute
*attr
,
362 struct usb_interface
*iface
= to_usb_interface(dev
);
363 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
365 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->host_name
);
368 static ssize_t
cbaf_wusb_host_name_store(struct device
*dev
,
369 struct device_attribute
*attr
,
370 const char *buf
, size_t size
)
373 struct usb_interface
*iface
= to_usb_interface(dev
);
374 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
376 result
= sscanf(buf
, "%63s", cbaf
->host_name
);
382 static DEVICE_ATTR(wusb_host_name
, 0600, cbaf_wusb_host_name_show
,
383 cbaf_wusb_host_name_store
);
385 static ssize_t
cbaf_wusb_host_band_groups_show(struct device
*dev
,
386 struct device_attribute
*attr
,
389 struct usb_interface
*iface
= to_usb_interface(dev
);
390 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
392 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->host_band_groups
);
395 static ssize_t
cbaf_wusb_host_band_groups_store(struct device
*dev
,
396 struct device_attribute
*attr
,
397 const char *buf
, size_t size
)
400 struct usb_interface
*iface
= to_usb_interface(dev
);
401 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
404 result
= sscanf(buf
, "%04hx", &band_groups
);
408 cbaf
->host_band_groups
= band_groups
;
413 static DEVICE_ATTR(wusb_host_band_groups
, 0600,
414 cbaf_wusb_host_band_groups_show
,
415 cbaf_wusb_host_band_groups_store
);
417 static const struct wusb_cbaf_device_info cbaf_device_info_defaults
= {
418 .Length_hdr
= WUSB_AR_Length
,
419 .CDID_hdr
= WUSB_AR_CDID
,
420 .BandGroups_hdr
= WUSB_AR_BandGroups
,
421 .LangID_hdr
= WUSB_AR_LangID
,
422 .DeviceFriendlyName_hdr
= WUSB_AR_DeviceFriendlyName
,
425 static ssize_t
cbaf_wusb_cdid_show(struct device
*dev
,
426 struct device_attribute
*attr
, char *buf
)
428 struct usb_interface
*iface
= to_usb_interface(dev
);
429 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
430 char pr_cdid
[WUSB_CKHDID_STRSIZE
];
432 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &cbaf
->cdid
);
433 return scnprintf(buf
, PAGE_SIZE
, "%s\n", pr_cdid
);
436 static ssize_t
cbaf_wusb_cdid_store(struct device
*dev
,
437 struct device_attribute
*attr
,
438 const char *buf
, size_t size
)
441 struct usb_interface
*iface
= to_usb_interface(dev
);
442 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
443 struct wusb_ckhdid cdid
;
446 "%02hhx %02hhx %02hhx %02hhx "
447 "%02hhx %02hhx %02hhx %02hhx "
448 "%02hhx %02hhx %02hhx %02hhx "
449 "%02hhx %02hhx %02hhx %02hhx",
450 &cdid
.data
[0] , &cdid
.data
[1],
451 &cdid
.data
[2] , &cdid
.data
[3],
452 &cdid
.data
[4] , &cdid
.data
[5],
453 &cdid
.data
[6] , &cdid
.data
[7],
454 &cdid
.data
[8] , &cdid
.data
[9],
455 &cdid
.data
[10], &cdid
.data
[11],
456 &cdid
.data
[12], &cdid
.data
[13],
457 &cdid
.data
[14], &cdid
.data
[15]);
465 static DEVICE_ATTR(wusb_cdid
, 0600, cbaf_wusb_cdid_show
, cbaf_wusb_cdid_store
);
467 static ssize_t
cbaf_wusb_device_band_groups_show(struct device
*dev
,
468 struct device_attribute
*attr
,
471 struct usb_interface
*iface
= to_usb_interface(dev
);
472 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
474 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->device_band_groups
);
477 static DEVICE_ATTR(wusb_device_band_groups
, 0600,
478 cbaf_wusb_device_band_groups_show
,
481 static ssize_t
cbaf_wusb_device_name_show(struct device
*dev
,
482 struct device_attribute
*attr
,
485 struct usb_interface
*iface
= to_usb_interface(dev
);
486 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
488 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->device_name
);
490 static DEVICE_ATTR(wusb_device_name
, 0600, cbaf_wusb_device_name_show
, NULL
);
492 static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults
= {
493 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
494 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
495 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
496 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE
),
497 .Length_hdr
= WUSB_AR_Length
,
498 .Length
= cpu_to_le32(sizeof(struct wusb_cbaf_cc_data
)),
499 .ConnectionContext_hdr
= WUSB_AR_ConnectionContext
,
500 .BandGroups_hdr
= WUSB_AR_BandGroups
,
503 static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults
= {
504 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
505 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
506 .Length_hdr
= WUSB_AR_Length
,
507 .AssociationStatus_hdr
= WUSB_AR_AssociationStatus
,
511 * Send a new CC to the device.
513 static int cbaf_cc_upload(struct cbaf
*cbaf
)
516 struct device
*dev
= &cbaf
->usb_iface
->dev
;
517 struct wusb_cbaf_cc_data
*ccd
;
518 char pr_cdid
[WUSB_CKHDID_STRSIZE
];
521 *ccd
= cbaf_cc_data_defaults
;
522 ccd
->CHID
= cbaf
->chid
;
523 ccd
->CDID
= cbaf
->cdid
;
525 ccd
->BandGroups
= cpu_to_le16(cbaf
->host_band_groups
);
527 dev_dbg(dev
, "Trying to upload CC:\n");
528 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &ccd
->CHID
);
529 dev_dbg(dev
, " CHID %s\n", pr_cdid
);
530 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &ccd
->CDID
);
531 dev_dbg(dev
, " CDID %s\n", pr_cdid
);
532 dev_dbg(dev
, " Bandgroups 0x%04x\n", cbaf
->host_band_groups
);
534 result
= usb_control_msg(
535 cbaf
->usb_dev
, usb_sndctrlpipe(cbaf
->usb_dev
, 0),
536 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
537 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
538 0x0201, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
539 ccd
, sizeof(*ccd
), 1000 /* FIXME: arbitrary */);
544 static ssize_t
cbaf_wusb_ck_store(struct device
*dev
,
545 struct device_attribute
*attr
,
546 const char *buf
, size_t size
)
549 struct usb_interface
*iface
= to_usb_interface(dev
);
550 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
553 "%02hhx %02hhx %02hhx %02hhx "
554 "%02hhx %02hhx %02hhx %02hhx "
555 "%02hhx %02hhx %02hhx %02hhx "
556 "%02hhx %02hhx %02hhx %02hhx",
557 &cbaf
->ck
.data
[0] , &cbaf
->ck
.data
[1],
558 &cbaf
->ck
.data
[2] , &cbaf
->ck
.data
[3],
559 &cbaf
->ck
.data
[4] , &cbaf
->ck
.data
[5],
560 &cbaf
->ck
.data
[6] , &cbaf
->ck
.data
[7],
561 &cbaf
->ck
.data
[8] , &cbaf
->ck
.data
[9],
562 &cbaf
->ck
.data
[10], &cbaf
->ck
.data
[11],
563 &cbaf
->ck
.data
[12], &cbaf
->ck
.data
[13],
564 &cbaf
->ck
.data
[14], &cbaf
->ck
.data
[15]);
568 result
= cbaf_cc_upload(cbaf
);
574 static DEVICE_ATTR(wusb_ck
, 0600, NULL
, cbaf_wusb_ck_store
);
576 static struct attribute
*cbaf_dev_attrs
[] = {
577 &dev_attr_wusb_host_name
.attr
,
578 &dev_attr_wusb_host_band_groups
.attr
,
579 &dev_attr_wusb_chid
.attr
,
580 &dev_attr_wusb_cdid
.attr
,
581 &dev_attr_wusb_device_name
.attr
,
582 &dev_attr_wusb_device_band_groups
.attr
,
583 &dev_attr_wusb_ck
.attr
,
587 static struct attribute_group cbaf_dev_attr_group
= {
588 .name
= NULL
, /* we want them in the same directory */
589 .attrs
= cbaf_dev_attrs
,
592 static int cbaf_probe(struct usb_interface
*iface
,
593 const struct usb_device_id
*id
)
596 struct device
*dev
= &iface
->dev
;
597 int result
= -ENOMEM
;
599 cbaf
= kzalloc(sizeof(*cbaf
), GFP_KERNEL
);
602 cbaf
->buffer
= kmalloc(512, GFP_KERNEL
);
603 if (cbaf
->buffer
== NULL
)
604 goto error_kmalloc_buffer
;
606 cbaf
->buffer_size
= 512;
607 cbaf
->usb_dev
= usb_get_dev(interface_to_usbdev(iface
));
608 cbaf
->usb_iface
= usb_get_intf(iface
);
609 result
= cbaf_check(cbaf
);
611 dev_err(dev
, "This device is not WUSB-CBAF compliant"
612 "and is not supported yet.\n");
616 result
= sysfs_create_group(&dev
->kobj
, &cbaf_dev_attr_group
);
618 dev_err(dev
, "Can't register sysfs attr group: %d\n", result
);
619 goto error_create_group
;
621 usb_set_intfdata(iface
, cbaf
);
627 error_kmalloc_buffer
:
633 static void cbaf_disconnect(struct usb_interface
*iface
)
635 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
636 struct device
*dev
= &iface
->dev
;
637 sysfs_remove_group(&dev
->kobj
, &cbaf_dev_attr_group
);
638 usb_set_intfdata(iface
, NULL
);
641 /* paranoia: clean up crypto keys */
645 static const struct usb_device_id cbaf_id_table
[] = {
646 { USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
649 MODULE_DEVICE_TABLE(usb
, cbaf_id_table
);
651 static struct usb_driver cbaf_driver
= {
653 .id_table
= cbaf_id_table
,
655 .disconnect
= cbaf_disconnect
,
658 module_usb_driver(cbaf_driver
);
660 MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
661 MODULE_DESCRIPTION("Wireless USB Cable Based Association");
662 MODULE_LICENSE("GPL");