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/mutex.h>
96 #include <linux/uwb.h>
97 #include <linux/usb/wusb.h>
98 #include <linux/usb/association.h>
100 #define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */
102 /* An instance of a Cable-Based-Association-Framework device */
104 struct usb_device
*usb_dev
;
105 struct usb_interface
*usb_iface
;
109 struct wusb_ckhdid chid
;
110 char host_name
[CBA_NAME_LEN
];
111 u16 host_band_groups
;
113 struct wusb_ckhdid cdid
;
114 char device_name
[CBA_NAME_LEN
];
115 u16 device_band_groups
;
117 struct wusb_ckhdid ck
;
121 * Verify that a CBAF USB-interface has what we need
123 * According to [WUSB-AM], CBA devices should provide at least two
125 * - RETRIEVE_HOST_INFO
128 * If the device doesn't provide these interfaces, we do not know how
131 static int cbaf_check(struct cbaf
*cbaf
)
134 struct device
*dev
= &cbaf
->usb_iface
->dev
;
135 struct wusb_cbaf_assoc_info
*assoc_info
;
136 struct wusb_cbaf_assoc_request
*assoc_request
;
139 int ar_rhi
= 0, ar_assoc
= 0;
141 result
= usb_control_msg(
142 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
143 CBAF_REQ_GET_ASSOCIATION_INFORMATION
,
144 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
145 0, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
146 cbaf
->buffer
, cbaf
->buffer_size
, 1000 /* FIXME: arbitrary */);
148 dev_err(dev
, "Cannot get available association types: %d\n",
153 assoc_info
= cbaf
->buffer
;
154 if (result
< sizeof(*assoc_info
)) {
155 dev_err(dev
, "Not enough data to decode association info "
156 "header (%zu vs %zu bytes required)\n",
157 (size_t)result
, sizeof(*assoc_info
));
161 assoc_size
= le16_to_cpu(assoc_info
->Length
);
162 if (result
< assoc_size
) {
163 dev_err(dev
, "Not enough data to decode association info "
164 "(%zu vs %zu bytes required)\n",
165 (size_t)assoc_size
, sizeof(*assoc_info
));
169 * From now on, we just verify, but won't error out unless we
170 * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
173 itr
= cbaf
->buffer
+ sizeof(*assoc_info
);
174 top
= cbaf
->buffer
+ assoc_size
;
175 dev_dbg(dev
, "Found %u association requests (%zu bytes)\n",
176 assoc_info
->NumAssociationRequests
, assoc_size
);
179 u16 ar_type
, ar_subtype
;
185 if (top
- itr
< sizeof(*assoc_request
)) {
186 dev_err(dev
, "Not enough data to decode associaton "
187 "request (%zu vs %zu bytes needed)\n",
188 top
- itr
, sizeof(*assoc_request
));
192 ar_type
= le16_to_cpu(assoc_request
->AssociationTypeId
);
193 ar_subtype
= le16_to_cpu(assoc_request
->AssociationSubTypeId
);
194 ar_size
= le32_to_cpu(assoc_request
->AssociationTypeInfoSize
);
199 /* Verify we have what is mandated by [WUSB-AM]. */
200 switch (ar_subtype
) {
201 case AR_TYPE_WUSB_RETRIEVE_HOST_INFO
:
202 ar_name
= "RETRIEVE_HOST_INFO";
205 case AR_TYPE_WUSB_ASSOCIATE
:
206 /* send assoc data */
207 ar_name
= "ASSOCIATE";
214 dev_dbg(dev
, "Association request #%02u: 0x%04x/%04x "
216 assoc_request
->AssociationDataIndex
, ar_type
,
217 ar_subtype
, (size_t)ar_size
, ar_name
);
219 itr
+= sizeof(*assoc_request
);
223 dev_err(dev
, "Missing RETRIEVE_HOST_INFO association "
228 dev_err(dev
, "Missing ASSOCIATE association request\n");
235 static const struct wusb_cbaf_host_info cbaf_host_info_defaults
= {
236 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
237 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
238 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
239 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO
),
240 .CHID_hdr
= WUSB_AR_CHID
,
241 .LangID_hdr
= WUSB_AR_LangID
,
242 .HostFriendlyName_hdr
= WUSB_AR_HostFriendlyName
,
245 /* Send WUSB host information (CHID and name) to a CBAF device */
246 static int cbaf_send_host_info(struct cbaf
*cbaf
)
248 struct wusb_cbaf_host_info
*hi
;
253 memset(hi
, 0, sizeof(*hi
));
254 *hi
= cbaf_host_info_defaults
;
255 hi
->CHID
= cbaf
->chid
;
256 hi
->LangID
= 0; /* FIXME: I guess... */
257 strlcpy(hi
->HostFriendlyName
, cbaf
->host_name
, CBA_NAME_LEN
);
258 name_len
= strlen(cbaf
->host_name
);
259 hi
->HostFriendlyName_hdr
.len
= cpu_to_le16(name_len
);
260 hi_size
= sizeof(*hi
) + name_len
;
262 return usb_control_msg(cbaf
->usb_dev
, usb_sndctrlpipe(cbaf
->usb_dev
, 0),
263 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
264 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
266 cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
267 hi
, hi_size
, 1000 /* FIXME: arbitrary */);
271 * Get device's information (CDID) associated to CHID
273 * The device will return it's information (CDID, name, bandgroups)
274 * associated to the CHID we have set before, or 0 CDID and default
275 * name and bandgroup if no CHID set or unknown.
277 static int cbaf_cdid_get(struct cbaf
*cbaf
)
280 struct device
*dev
= &cbaf
->usb_iface
->dev
;
281 struct wusb_cbaf_device_info
*di
;
285 result
= usb_control_msg(
286 cbaf
->usb_dev
, usb_rcvctrlpipe(cbaf
->usb_dev
, 0),
287 CBAF_REQ_GET_ASSOCIATION_REQUEST
,
288 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
289 0x0200, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
290 di
, cbaf
->buffer_size
, 1000 /* FIXME: arbitrary */);
292 dev_err(dev
, "Cannot request device information: %d\n", result
);
296 needed
= result
< sizeof(*di
) ? sizeof(*di
) : le32_to_cpu(di
->Length
);
297 if (result
< needed
) {
298 dev_err(dev
, "Not enough data in DEVICE_INFO reply (%zu vs "
299 "%zu bytes needed)\n", (size_t)result
, needed
);
303 strlcpy(cbaf
->device_name
, di
->DeviceFriendlyName
, CBA_NAME_LEN
);
304 cbaf
->cdid
= di
->CDID
;
305 cbaf
->device_band_groups
= le16_to_cpu(di
->BandGroups
);
310 static ssize_t
cbaf_wusb_chid_show(struct device
*dev
,
311 struct device_attribute
*attr
,
314 struct usb_interface
*iface
= to_usb_interface(dev
);
315 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
316 char pr_chid
[WUSB_CKHDID_STRSIZE
];
318 ckhdid_printf(pr_chid
, sizeof(pr_chid
), &cbaf
->chid
);
319 return scnprintf(buf
, PAGE_SIZE
, "%s\n", pr_chid
);
322 static ssize_t
cbaf_wusb_chid_store(struct device
*dev
,
323 struct device_attribute
*attr
,
324 const char *buf
, size_t size
)
327 struct usb_interface
*iface
= to_usb_interface(dev
);
328 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
331 "%02hhx %02hhx %02hhx %02hhx "
332 "%02hhx %02hhx %02hhx %02hhx "
333 "%02hhx %02hhx %02hhx %02hhx "
334 "%02hhx %02hhx %02hhx %02hhx",
335 &cbaf
->chid
.data
[0] , &cbaf
->chid
.data
[1],
336 &cbaf
->chid
.data
[2] , &cbaf
->chid
.data
[3],
337 &cbaf
->chid
.data
[4] , &cbaf
->chid
.data
[5],
338 &cbaf
->chid
.data
[6] , &cbaf
->chid
.data
[7],
339 &cbaf
->chid
.data
[8] , &cbaf
->chid
.data
[9],
340 &cbaf
->chid
.data
[10], &cbaf
->chid
.data
[11],
341 &cbaf
->chid
.data
[12], &cbaf
->chid
.data
[13],
342 &cbaf
->chid
.data
[14], &cbaf
->chid
.data
[15]);
347 result
= cbaf_send_host_info(cbaf
);
350 result
= cbaf_cdid_get(cbaf
);
355 static DEVICE_ATTR(wusb_chid
, 0600, cbaf_wusb_chid_show
, cbaf_wusb_chid_store
);
357 static ssize_t
cbaf_wusb_host_name_show(struct device
*dev
,
358 struct device_attribute
*attr
,
361 struct usb_interface
*iface
= to_usb_interface(dev
);
362 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
364 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->host_name
);
367 static ssize_t
cbaf_wusb_host_name_store(struct device
*dev
,
368 struct device_attribute
*attr
,
369 const char *buf
, size_t size
)
372 struct usb_interface
*iface
= to_usb_interface(dev
);
373 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
375 result
= sscanf(buf
, "%63s", cbaf
->host_name
);
381 static DEVICE_ATTR(wusb_host_name
, 0600, cbaf_wusb_host_name_show
,
382 cbaf_wusb_host_name_store
);
384 static ssize_t
cbaf_wusb_host_band_groups_show(struct device
*dev
,
385 struct device_attribute
*attr
,
388 struct usb_interface
*iface
= to_usb_interface(dev
);
389 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
391 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->host_band_groups
);
394 static ssize_t
cbaf_wusb_host_band_groups_store(struct device
*dev
,
395 struct device_attribute
*attr
,
396 const char *buf
, size_t size
)
399 struct usb_interface
*iface
= to_usb_interface(dev
);
400 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
403 result
= sscanf(buf
, "%04hx", &band_groups
);
407 cbaf
->host_band_groups
= band_groups
;
412 static DEVICE_ATTR(wusb_host_band_groups
, 0600,
413 cbaf_wusb_host_band_groups_show
,
414 cbaf_wusb_host_band_groups_store
);
416 static const struct wusb_cbaf_device_info cbaf_device_info_defaults
= {
417 .Length_hdr
= WUSB_AR_Length
,
418 .CDID_hdr
= WUSB_AR_CDID
,
419 .BandGroups_hdr
= WUSB_AR_BandGroups
,
420 .LangID_hdr
= WUSB_AR_LangID
,
421 .DeviceFriendlyName_hdr
= WUSB_AR_DeviceFriendlyName
,
424 static ssize_t
cbaf_wusb_cdid_show(struct device
*dev
,
425 struct device_attribute
*attr
, char *buf
)
427 struct usb_interface
*iface
= to_usb_interface(dev
);
428 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
429 char pr_cdid
[WUSB_CKHDID_STRSIZE
];
431 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &cbaf
->cdid
);
432 return scnprintf(buf
, PAGE_SIZE
, "%s\n", pr_cdid
);
435 static ssize_t
cbaf_wusb_cdid_store(struct device
*dev
,
436 struct device_attribute
*attr
,
437 const char *buf
, size_t size
)
440 struct usb_interface
*iface
= to_usb_interface(dev
);
441 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
442 struct wusb_ckhdid cdid
;
445 "%02hhx %02hhx %02hhx %02hhx "
446 "%02hhx %02hhx %02hhx %02hhx "
447 "%02hhx %02hhx %02hhx %02hhx "
448 "%02hhx %02hhx %02hhx %02hhx",
449 &cdid
.data
[0] , &cdid
.data
[1],
450 &cdid
.data
[2] , &cdid
.data
[3],
451 &cdid
.data
[4] , &cdid
.data
[5],
452 &cdid
.data
[6] , &cdid
.data
[7],
453 &cdid
.data
[8] , &cdid
.data
[9],
454 &cdid
.data
[10], &cdid
.data
[11],
455 &cdid
.data
[12], &cdid
.data
[13],
456 &cdid
.data
[14], &cdid
.data
[15]);
464 static DEVICE_ATTR(wusb_cdid
, 0600, cbaf_wusb_cdid_show
, cbaf_wusb_cdid_store
);
466 static ssize_t
cbaf_wusb_device_band_groups_show(struct device
*dev
,
467 struct device_attribute
*attr
,
470 struct usb_interface
*iface
= to_usb_interface(dev
);
471 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
473 return scnprintf(buf
, PAGE_SIZE
, "0x%04x\n", cbaf
->device_band_groups
);
476 static DEVICE_ATTR(wusb_device_band_groups
, 0600,
477 cbaf_wusb_device_band_groups_show
,
480 static ssize_t
cbaf_wusb_device_name_show(struct device
*dev
,
481 struct device_attribute
*attr
,
484 struct usb_interface
*iface
= to_usb_interface(dev
);
485 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
487 return scnprintf(buf
, PAGE_SIZE
, "%s\n", cbaf
->device_name
);
489 static DEVICE_ATTR(wusb_device_name
, 0600, cbaf_wusb_device_name_show
, NULL
);
491 static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults
= {
492 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
493 .AssociationTypeId
= cpu_to_le16(AR_TYPE_WUSB
),
494 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
495 .AssociationSubTypeId
= cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE
),
496 .Length_hdr
= WUSB_AR_Length
,
497 .Length
= cpu_to_le32(sizeof(struct wusb_cbaf_cc_data
)),
498 .ConnectionContext_hdr
= WUSB_AR_ConnectionContext
,
499 .BandGroups_hdr
= WUSB_AR_BandGroups
,
502 static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults
= {
503 .AssociationTypeId_hdr
= WUSB_AR_AssociationTypeId
,
504 .AssociationSubTypeId_hdr
= WUSB_AR_AssociationSubTypeId
,
505 .Length_hdr
= WUSB_AR_Length
,
506 .AssociationStatus_hdr
= WUSB_AR_AssociationStatus
,
510 * Send a new CC to the device.
512 static int cbaf_cc_upload(struct cbaf
*cbaf
)
515 struct device
*dev
= &cbaf
->usb_iface
->dev
;
516 struct wusb_cbaf_cc_data
*ccd
;
517 char pr_cdid
[WUSB_CKHDID_STRSIZE
];
520 *ccd
= cbaf_cc_data_defaults
;
521 ccd
->CHID
= cbaf
->chid
;
522 ccd
->CDID
= cbaf
->cdid
;
524 ccd
->BandGroups
= cpu_to_le16(cbaf
->host_band_groups
);
526 dev_dbg(dev
, "Trying to upload CC:\n");
527 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &ccd
->CHID
);
528 dev_dbg(dev
, " CHID %s\n", pr_cdid
);
529 ckhdid_printf(pr_cdid
, sizeof(pr_cdid
), &ccd
->CDID
);
530 dev_dbg(dev
, " CDID %s\n", pr_cdid
);
531 dev_dbg(dev
, " Bandgroups 0x%04x\n", cbaf
->host_band_groups
);
533 result
= usb_control_msg(
534 cbaf
->usb_dev
, usb_sndctrlpipe(cbaf
->usb_dev
, 0),
535 CBAF_REQ_SET_ASSOCIATION_RESPONSE
,
536 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
,
537 0x0201, cbaf
->usb_iface
->cur_altsetting
->desc
.bInterfaceNumber
,
538 ccd
, sizeof(*ccd
), 1000 /* FIXME: arbitrary */);
543 static ssize_t
cbaf_wusb_ck_store(struct device
*dev
,
544 struct device_attribute
*attr
,
545 const char *buf
, size_t size
)
548 struct usb_interface
*iface
= to_usb_interface(dev
);
549 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
552 "%02hhx %02hhx %02hhx %02hhx "
553 "%02hhx %02hhx %02hhx %02hhx "
554 "%02hhx %02hhx %02hhx %02hhx "
555 "%02hhx %02hhx %02hhx %02hhx",
556 &cbaf
->ck
.data
[0] , &cbaf
->ck
.data
[1],
557 &cbaf
->ck
.data
[2] , &cbaf
->ck
.data
[3],
558 &cbaf
->ck
.data
[4] , &cbaf
->ck
.data
[5],
559 &cbaf
->ck
.data
[6] , &cbaf
->ck
.data
[7],
560 &cbaf
->ck
.data
[8] , &cbaf
->ck
.data
[9],
561 &cbaf
->ck
.data
[10], &cbaf
->ck
.data
[11],
562 &cbaf
->ck
.data
[12], &cbaf
->ck
.data
[13],
563 &cbaf
->ck
.data
[14], &cbaf
->ck
.data
[15]);
567 result
= cbaf_cc_upload(cbaf
);
573 static DEVICE_ATTR(wusb_ck
, 0600, NULL
, cbaf_wusb_ck_store
);
575 static struct attribute
*cbaf_dev_attrs
[] = {
576 &dev_attr_wusb_host_name
.attr
,
577 &dev_attr_wusb_host_band_groups
.attr
,
578 &dev_attr_wusb_chid
.attr
,
579 &dev_attr_wusb_cdid
.attr
,
580 &dev_attr_wusb_device_name
.attr
,
581 &dev_attr_wusb_device_band_groups
.attr
,
582 &dev_attr_wusb_ck
.attr
,
586 static struct attribute_group cbaf_dev_attr_group
= {
587 .name
= NULL
, /* we want them in the same directory */
588 .attrs
= cbaf_dev_attrs
,
591 static int cbaf_probe(struct usb_interface
*iface
,
592 const struct usb_device_id
*id
)
595 struct device
*dev
= &iface
->dev
;
596 int result
= -ENOMEM
;
598 cbaf
= kzalloc(sizeof(*cbaf
), GFP_KERNEL
);
601 cbaf
->buffer
= kmalloc(512, GFP_KERNEL
);
602 if (cbaf
->buffer
== NULL
)
603 goto error_kmalloc_buffer
;
605 cbaf
->buffer_size
= 512;
606 cbaf
->usb_dev
= usb_get_dev(interface_to_usbdev(iface
));
607 cbaf
->usb_iface
= usb_get_intf(iface
);
608 result
= cbaf_check(cbaf
);
610 dev_err(dev
, "This device is not WUSB-CBAF compliant"
611 "and is not supported yet.\n");
615 result
= sysfs_create_group(&dev
->kobj
, &cbaf_dev_attr_group
);
617 dev_err(dev
, "Can't register sysfs attr group: %d\n", result
);
618 goto error_create_group
;
620 usb_set_intfdata(iface
, cbaf
);
626 error_kmalloc_buffer
:
632 static void cbaf_disconnect(struct usb_interface
*iface
)
634 struct cbaf
*cbaf
= usb_get_intfdata(iface
);
635 struct device
*dev
= &iface
->dev
;
636 sysfs_remove_group(&dev
->kobj
, &cbaf_dev_attr_group
);
637 usb_set_intfdata(iface
, NULL
);
640 /* paranoia: clean up crypto keys */
644 static struct usb_device_id cbaf_id_table
[] = {
645 { USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
648 MODULE_DEVICE_TABLE(usb
, cbaf_id_table
);
650 static struct usb_driver cbaf_driver
= {
652 .id_table
= cbaf_id_table
,
654 .disconnect
= cbaf_disconnect
,
657 static int __init
cbaf_driver_init(void)
659 return usb_register(&cbaf_driver
);
661 module_init(cbaf_driver_init
);
663 static void __exit
cbaf_driver_exit(void)
665 usb_deregister(&cbaf_driver
);
667 module_exit(cbaf_driver_exit
);
669 MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
670 MODULE_DESCRIPTION("Wireless USB Cable Based Association");
671 MODULE_LICENSE("GPL");