wusb: add the USB wusb-cbaf driver
[linux-2.6.git] / drivers / usb / wusbcore / cbaf.c
1 /*
2  * Wireless USB - Cable Based Association
3  *
4  *
5  * Copyright (C) 2006 Intel Corporation
6  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version
10  * 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  *
22  *
23  * WUSB devices have to be paired (authenticated in WUSB lingo) so
24  * that they can connect to the system.
25  *
26  * One way of pairing is using CBA-Cable Based Authentication, devices
27  * that can connect via wired or wireless USB. First time you plug
28  * them with a cable, pairing is done between host and device and
29  * subsequent times, you can connect wirelessly without having to
30  * pair. That's the idea.
31  *
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.
38  *
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.
42  *
43  * The process goes like this:
44  *
45  * 1. device plugs, cbaf is loaded, notifications happen
46  *
47  * 2. the connection manager sees a device with CBAF capability (the
48  *    wusb_{host_info,cdid,cc} files are in /sys/device/blah/OURDEVICE).
49  *
50  * 3. CM (connection manager) writes the CHID (host ID) and a host
51  *    name into the wusb_host_info file. This gets sent to the device.
52  *
53  * 4. CM cats the wusb_cdid file; this asks the device if it has any
54  *    CDID associated to the CHDI we just wrote before. If it does, it
55  *    is printed, along with the device 'friendly name' and the band
56  *    groups the device supports.
57  *
58  * 5. CM looks up its database
59  *
60  * 5.1  If it has a matching CHID,CDID entry, the device has been
61  *      authorized before (paired). Now we can optionally ask the user
62  *      if he wants to allow the device to connect. Then we generate a
63  *      new CDID and CK, send it to the device and update the database
64  *      (writing to the wusb_cc file so they are uploaded to the device).
65  *
66  * 5.2  If the CDID is zero (or we didn't find a matching CDID in our
67  *      database), we assume the device is not known. We ask the user
68  *      if s/he wants to allow the device to be connected wirelessly
69  *      to the system. If nope, nothing else is done (FIXME: maybe
70  *      send a zero CDID to clean up our CHID?). If yes, we generate
71  *      random CDID and CKs (and write them to the wusb_cc file so
72  *      they are uploaded to the device).
73  *
74  * 6. device is unplugged
75  *
76  * When the device tries to connect wirelessly, it will present it's
77  * CDID to the WUSB host controller with ID CHID, which will query the
78  * database. If found, the host will (with a 4way handshake) challenge
79  * the device to demonstrate it has the CK secret key (from our
80  * database) without actually exchanging it. Once satisfied, crypto
81  * keys are derived from the CK, the device is connected and all
82  * communication is crypted.
83  *
84  *
85  * NOTES ABOUT THE IMPLEMENTATION
86  *
87  * The descriptors sent back and forth use this horrible format from
88  * hell on which each field is actually a field ID, field length and
89  * then the field itself. How stupid can that get, taking into account
90  * the structures are defined by the spec?? oh well.
91  *
92  *
93  * FIXME: we don't provide a way to tell the device the pairing failed
94  *        (ie: send a CC_DATA_FAIL). Should add some day.
95  */
96 #include <linux/module.h>
97 #include <linux/ctype.h>
98 #include <linux/version.h>
99 #include <linux/usb.h>
100 #include <linux/interrupt.h>
101 #include <linux/delay.h>
102 #include <linux/random.h>
103 #include <linux/mutex.h>
104 #include <linux/uwb.h>
105 #include <linux/usb/wusb.h>
106 #include <linux/usb/association.h>
107
108 #undef D_LOCAL
109 #define D_LOCAL 6
110 #include <linux/uwb/debug.h>
111
112 /* An instance of a Cable-Based-Association-Framework device */
113 struct cbaf {
114         struct usb_device *usb_dev;
115         struct usb_interface *usb_iface;
116         void *buffer;
117         size_t buffer_size;
118
119         struct wusb_ckhdid chid;/* Host Information */
120         char host_name[65];     /* max length:
121                                         Assoc Models Suplement 1.0[T4-7] */
122         u16 host_band_groups;
123
124         struct wusb_ckhdid cdid;/* Device Information */
125         char device_name[65];   /* max length:
126                                         Assoc Models Suplement 1.0[T4-7] */
127         u16 device_band_groups;
128         struct wusb_ckhdid ck;  /* Connection Key */
129 };
130
131 /*
132  * Verify that a CBAF USB-interface has what we need
133  *
134  * (like we care, we are going to fail the enumeration if not :)
135  *
136  * FIXME: ugly function, need to split
137  */
138 static int cbaf_check(struct cbaf *cbaf)
139 {
140         int result;
141         struct device *dev = &cbaf->usb_iface->dev;
142         struct wusb_cbaf_assoc_info *assoc_info;
143         struct wusb_cbaf_assoc_request *assoc_request;
144         size_t assoc_size;
145         void *itr, *top;
146         unsigned ar_index;
147         int ar_rhi_idx = -1, ar_assoc_idx = -1;
148
149         result = usb_control_msg(
150                 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
151                 CBAF_REQ_GET_ASSOCIATION_INFORMATION,
152                 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
153                 0, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
154                 cbaf->buffer, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
155         if (result < 0) {
156                 dev_err(dev, "cannot get available association types: %d\n",
157                         result);
158                 goto error_get_assoc_types;
159         }
160         assoc_info = cbaf->buffer;
161         if (result < sizeof(*assoc_info)) {
162                 dev_err(dev, "not enough data to decode association info "
163                         "header (%zu vs %zu bytes required)\n",
164                         (size_t)result, sizeof(*assoc_info));
165                 goto error_bad_header;
166         }
167         assoc_size = le16_to_cpu(assoc_info->Length);
168         if (result < assoc_size) {
169                 dev_err(dev, "not enough data to decode association info "
170                         "(%zu vs %zu bytes required)\n",
171                         (size_t)assoc_size, sizeof(*assoc_info));
172                 goto error_bad_data;
173         }
174         /*
175          * From now on, we just verify, but won't error out unless we
176          * don't find the AR_TYPE_WUSB_{RETRIEVE_HOST_INFO,ASSOCIATE}
177          * types.
178          */
179         ar_index = 0;
180         itr = cbaf->buffer + sizeof(*assoc_info);
181         top = cbaf->buffer + assoc_size;
182         d_printf(1, dev, "Found %u association requests (%zu bytes)\n",
183                  assoc_info->NumAssociationRequests, assoc_size);
184         while (itr < top) {
185                 u16 ar_type, ar_subtype;
186                 u32 ar_size;
187                 const char *ar_name;
188
189                 assoc_request = itr;
190                 if (top - itr < sizeof(*assoc_request)) {
191                         dev_err(dev, "not enough data to decode associaton "
192                                 "request (%zu vs %zu bytes needed)\n",
193                                 top - itr, sizeof(*assoc_request));
194                         break;
195                 }
196                 ar_type = le16_to_cpu(assoc_request->AssociationTypeId);
197                 ar_subtype = le16_to_cpu(assoc_request->AssociationSubTypeId);
198                 ar_size = le32_to_cpu(assoc_request->AssociationTypeInfoSize);
199                 switch (ar_type) {
200                 case AR_TYPE_WUSB:
201                         /* Verify we have what is mandated by AMS1.0 */
202                         switch (ar_subtype) {
203                         case AR_TYPE_WUSB_RETRIEVE_HOST_INFO:
204                                 ar_name = "retrieve_host_info";
205                                 ar_rhi_idx = ar_index;
206                                 break;
207                         case AR_TYPE_WUSB_ASSOCIATE:
208                                 /* send assoc data */
209                                 ar_name = "associate";
210                                 ar_assoc_idx = ar_index;
211                                 break;
212                         default:
213                                 ar_name = "unknown";
214                         };
215                         break;
216                 default:
217                         ar_name = "unknown";
218                 };
219                 d_printf(1, dev, "association request #%02u: 0x%04x/%04x "
220                          "(%zu bytes): %s\n",
221                          assoc_request->AssociationDataIndex, ar_type,
222                          ar_subtype, (size_t)ar_size, ar_name);
223
224                 itr += sizeof(*assoc_request);
225                 ar_index++;
226         }
227         if (ar_rhi_idx == -1) {
228                 dev_err(dev, "Missing RETRIEVE_HOST_INFO association "
229                         "request\n");
230                 goto error_bad_reqs;
231         }
232         if (ar_assoc_idx == -1) {
233                 dev_err(dev, "Missing ASSOCIATE association request\n");
234                 goto error_bad_reqs;
235         }
236         return 0;
237
238 error_bad_header:
239 error_bad_data:
240 error_bad_reqs:
241 error_get_assoc_types:
242         return -EINVAL;
243 }
244
245 static const struct wusb_cbaf_host_info cbaf_host_info_defaults = {
246         .AssociationTypeId_hdr    = WUSB_AR_AssociationTypeId,
247         .AssociationTypeId        = cpu_to_le16(AR_TYPE_WUSB),
248         .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
249         .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_RETRIEVE_HOST_INFO),
250         .CHID_hdr                 = WUSB_AR_CHID,
251         .LangID_hdr               = WUSB_AR_LangID,
252         .HostFriendlyName_hdr     = WUSB_AR_HostFriendlyName,
253 };
254
255 /* Send WUSB host information (CHID and name) to a CBAF device */
256 static int cbaf_send_host_info(struct cbaf *cbaf)
257 {
258         struct wusb_cbaf_host_info *hi;
259         size_t hi_size;
260
261         hi = cbaf->buffer;
262         memset(hi, 0, sizeof(*hi));
263         *hi = cbaf_host_info_defaults;
264         hi->CHID = cbaf->chid;
265         hi->LangID = 0; /* FIXME: I guess... */
266         strncpy(hi->HostFriendlyName, cbaf->host_name,
267                 hi->HostFriendlyName_hdr.len);
268         hi->HostFriendlyName_hdr.len =
269                                 cpu_to_le16(strlen(hi->HostFriendlyName));
270         hi_size = sizeof(*hi) + strlen(hi->HostFriendlyName);
271         return usb_control_msg(cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
272                         CBAF_REQ_SET_ASSOCIATION_RESPONSE,
273                         USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
274                         0x0101,
275                         cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
276                         hi, hi_size, 1000 /* FIXME: arbitrary */);
277 }
278
279 /* Show current CHID info we have set from user space */
280 static ssize_t cbaf_wusb_host_info_show(struct device *dev,
281                                         struct device_attribute *attr,
282                                         char *buf)
283 {
284         struct usb_interface *iface = to_usb_interface(dev);
285         struct cbaf *cbaf = usb_get_intfdata(iface);
286         char pr_chid[WUSB_CKHDID_STRSIZE];
287
288         ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid);
289         return scnprintf(buf, PAGE_SIZE, "CHID: %s\nName: %s\n",
290                          pr_chid, cbaf->host_name);
291 }
292
293 /*
294  * Get a host info CHID from user space and send it to the device.
295  *
296  * The user can recover a CC from the device associated to that CHID
297  * by cat'ing wusb_connection_context.
298  */
299 static ssize_t cbaf_wusb_host_info_store(struct device *dev,
300                                          struct device_attribute *attr,
301                                          const char *buf, size_t size)
302 {
303         ssize_t result;
304         struct usb_interface *iface = to_usb_interface(dev);
305         struct cbaf *cbaf = usb_get_intfdata(iface);
306
307         result = sscanf(buf,
308                         "%02hhx %02hhx %02hhx %02hhx "
309                         "%02hhx %02hhx %02hhx %02hhx "
310                         "%02hhx %02hhx %02hhx %02hhx "
311                         "%02hhx %02hhx %02hhx %02hhx "
312                         "%04hx %64s\n",
313                         &cbaf->chid.data[0] , &cbaf->chid.data[1],
314                         &cbaf->chid.data[2] , &cbaf->chid.data[3],
315                         &cbaf->chid.data[4] , &cbaf->chid.data[5],
316                         &cbaf->chid.data[6] , &cbaf->chid.data[7],
317                         &cbaf->chid.data[8] , &cbaf->chid.data[9],
318                         &cbaf->chid.data[10], &cbaf->chid.data[11],
319                         &cbaf->chid.data[12], &cbaf->chid.data[13],
320                         &cbaf->chid.data[14], &cbaf->chid.data[15],
321                         &cbaf->host_band_groups, cbaf->host_name);
322         if (result != 18) {
323                 dev_err(dev, "Unrecognized CHID (need 16 8-bit hex digits, "
324                         "a 16 bit hex band group mask "
325                         "and a host name, got only %d)\n", (int)result);
326                 return -EINVAL;
327         }
328         result = cbaf_send_host_info(cbaf);
329         if (result < 0)
330                 dev_err(dev, "Couldn't send host information to device: %d\n",
331                         (int)result);
332         else
333                 d_printf(1, dev, "HI sent, wusb_cc can be read now\n");
334         return result < 0 ? result : size;
335 }
336 static DEVICE_ATTR(wusb_host_info, 0600, cbaf_wusb_host_info_show,
337                                          cbaf_wusb_host_info_store);
338
339 static const struct wusb_cbaf_device_info cbaf_device_info_defaults = {
340         .Length_hdr               = WUSB_AR_Length,
341         .CDID_hdr                 = WUSB_AR_CDID,
342         .BandGroups_hdr           = WUSB_AR_BandGroups,
343         .LangID_hdr               = WUSB_AR_LangID,
344         .DeviceFriendlyName_hdr   = WUSB_AR_DeviceFriendlyName,
345 };
346
347 /*
348  * Get device's information (CDID) associated to CHID
349  *
350  * The device will return it's information (CDID, name, bandgroups)
351  * associated to the CHID we have set before, or 0 CDID and default
352  * name and bandgroup if no CHID set or unknown.
353  */
354 static int cbaf_cdid_get(struct cbaf *cbaf)
355 {
356         int result;
357         struct device *dev = &cbaf->usb_iface->dev;
358         struct wusb_cbaf_device_info *di;
359         size_t needed, dev_name_size;
360
361         di = cbaf->buffer;
362         result = usb_control_msg(
363                 cbaf->usb_dev, usb_rcvctrlpipe(cbaf->usb_dev, 0),
364                 CBAF_REQ_GET_ASSOCIATION_REQUEST,
365                 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
366                 0x0200, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
367                 di, cbaf->buffer_size, 1000 /* FIXME: arbitrary */);
368         if (result < 0) {
369                 dev_err(dev, "Cannot request device information: %d\n", result);
370                 goto error_req_di;
371         }
372         needed = result < sizeof(*di) ? sizeof(*di) : le32_to_cpu(di->Length);
373         if (result < needed) {
374                 dev_err(dev, "Not enough data in DEVICE_INFO reply (%zu vs "
375                         "%zu bytes needed)\n", (size_t)result, needed);
376                 goto error_bad_di;
377         }
378         cbaf->cdid = di->CDID;
379         dev_name_size = le16_to_cpu(di->DeviceFriendlyName_hdr.len);
380         dev_name_size = dev_name_size > 65 - 1 ? 65 - 1 : dev_name_size;
381         memcpy(cbaf->device_name, di->DeviceFriendlyName, dev_name_size);
382         cbaf->device_name[dev_name_size] = 0;
383         cbaf->device_band_groups = le16_to_cpu(di->BandGroups);
384         result = 0;
385 error_req_di:
386 error_bad_di:
387         return result;
388 }
389
390 /*
391  * Get device information and print it to sysfs
392  *
393  * See cbaf_cdid_get()
394  */
395 static ssize_t cbaf_wusb_cdid_show(struct device *dev,
396                                    struct device_attribute *attr, char *buf)
397 {
398         ssize_t result;
399         struct usb_interface *iface = to_usb_interface(dev);
400         struct cbaf *cbaf = usb_get_intfdata(iface);
401         char pr_cdid[WUSB_CKHDID_STRSIZE];
402
403         result = cbaf_cdid_get(cbaf);
404         if (result < 0) {
405                 dev_err(dev, "Cannot read device information: %d\n",
406                         (int)result);
407                 goto error_get_di;
408         }
409         ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid);
410         result = scnprintf(buf, PAGE_SIZE,
411                            "CDID: %s\nName: %s\nBand_groups: 0x%04x\n",
412                            pr_cdid, cbaf->device_name,
413                            cbaf->device_band_groups);
414 error_get_di:
415         return result;
416 }
417 static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, NULL);
418
419 static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = {
420         .AssociationTypeId_hdr    = WUSB_AR_AssociationTypeId,
421         .AssociationTypeId        = cpu_to_le16(AR_TYPE_WUSB),
422         .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
423         .AssociationSubTypeId     = cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE),
424         .Length_hdr               = WUSB_AR_Length,
425         .Length                   = cpu_to_le32(sizeof(struct wusb_cbaf_cc_data)),
426         .ConnectionContext_hdr    = WUSB_AR_ConnectionContext,
427         .BandGroups_hdr           = WUSB_AR_BandGroups,
428 };
429
430 static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults = {
431         .AssociationTypeId_hdr    = WUSB_AR_AssociationTypeId,
432         .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId,
433         .Length_hdr               = WUSB_AR_Length,
434         .AssociationStatus_hdr    = WUSB_AR_AssociationStatus,
435 };
436
437 /*
438  * Send a new CC to the device
439  *
440  * So we update the CK and send the whole thing to the device
441  */
442 static int cbaf_cc_upload(struct cbaf *cbaf)
443 {
444         int result;
445         struct device *dev = &cbaf->usb_iface->dev;
446         struct wusb_cbaf_cc_data *ccd;
447         char pr_cdid[WUSB_CKHDID_STRSIZE];
448
449         ccd =  cbaf->buffer;
450         *ccd = cbaf_cc_data_defaults;
451         ccd->CHID = cbaf->chid;
452         ccd->CDID = cbaf->cdid;
453         ccd->CK = cbaf->ck;
454         ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups);
455         result = usb_control_msg(
456                 cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0),
457                 CBAF_REQ_SET_ASSOCIATION_RESPONSE,
458                 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
459                 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber,
460                 ccd, sizeof(*ccd), 1000 /* FIXME: arbitrary */);
461         d_printf(1, dev, "Uploaded CC:\n");
462         ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID);
463         d_printf(1, dev, "  CHID       %s\n", pr_cdid);
464         ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID);
465         d_printf(1, dev, "  CDID       %s\n", pr_cdid);
466         ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CK);
467         d_printf(1, dev, "  CK         %s\n", pr_cdid);
468         d_printf(1, dev, "  bandgroups 0x%04x\n", cbaf->host_band_groups);
469         return result;
470 }
471
472 /*
473  * Send a new CC to the device
474  *
475  * We take the CDID and CK from user space, the rest from the info we
476  * set with host_info.
477  */
478 static ssize_t cbaf_wusb_cc_store(struct device *dev,
479                                   struct device_attribute *attr,
480                                   const char *buf, size_t size)
481 {
482         ssize_t result;
483         struct usb_interface *iface = to_usb_interface(dev);
484         struct cbaf *cbaf = usb_get_intfdata(iface);
485
486         result = sscanf(buf,
487                         "CDID: %02hhx %02hhx %02hhx %02hhx "
488                         "%02hhx %02hhx %02hhx %02hhx "
489                         "%02hhx %02hhx %02hhx %02hhx "
490                         "%02hhx %02hhx %02hhx %02hhx\n"
491                         "CK: %02hhx %02hhx %02hhx %02hhx "
492                         "%02hhx %02hhx %02hhx %02hhx "
493                         "%02hhx %02hhx %02hhx %02hhx "
494                         "%02hhx %02hhx %02hhx %02hhx\n",
495                         &cbaf->cdid.data[0] , &cbaf->cdid.data[1],
496                         &cbaf->cdid.data[2] , &cbaf->cdid.data[3],
497                         &cbaf->cdid.data[4] , &cbaf->cdid.data[5],
498                         &cbaf->cdid.data[6] , &cbaf->cdid.data[7],
499                         &cbaf->cdid.data[8] , &cbaf->cdid.data[9],
500                         &cbaf->cdid.data[10], &cbaf->cdid.data[11],
501                         &cbaf->cdid.data[12], &cbaf->cdid.data[13],
502                         &cbaf->cdid.data[14], &cbaf->cdid.data[15],
503
504                         &cbaf->ck.data[0] , &cbaf->ck.data[1],
505                         &cbaf->ck.data[2] , &cbaf->ck.data[3],
506                         &cbaf->ck.data[4] , &cbaf->ck.data[5],
507                         &cbaf->ck.data[6] , &cbaf->ck.data[7],
508                         &cbaf->ck.data[8] , &cbaf->ck.data[9],
509                         &cbaf->ck.data[10], &cbaf->ck.data[11],
510                         &cbaf->ck.data[12], &cbaf->ck.data[13],
511                         &cbaf->ck.data[14], &cbaf->ck.data[15]);
512         if (result != 32) {
513                 dev_err(dev, "Unrecognized CHID/CK (need 32 8-bit "
514                         "hex digits, got only %d)\n", (int)result);
515                 return -EINVAL;
516         }
517         result = cbaf_cc_upload(cbaf);
518         if (result < 0)
519                 dev_err(dev, "Couldn't upload connection context: %d\n",
520                         (int)result);
521         else
522                 d_printf(1, dev, "Connection context uploaded\n");
523         return result < 0 ? result : size;
524 }
525 static DEVICE_ATTR(wusb_cc, 0600, NULL, cbaf_wusb_cc_store);
526
527 static struct attribute *cbaf_dev_attrs[] = {
528         &dev_attr_wusb_host_info.attr,
529         &dev_attr_wusb_cdid.attr,
530         &dev_attr_wusb_cc.attr,
531         NULL,
532 };
533
534 static struct attribute_group cbaf_dev_attr_group = {
535         .name = NULL,   /* we want them in the same directory */
536         .attrs = cbaf_dev_attrs,
537 };
538
539 static int cbaf_probe(struct usb_interface *iface,
540                       const struct usb_device_id *id)
541 {
542         int result;
543         struct cbaf *cbaf;
544         struct device *dev = &iface->dev;
545
546         result = -ENOMEM;
547         cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL);
548         if (cbaf == NULL) {
549                 dev_err(dev, "Unable to allocate instance\n");
550                 goto error_kzalloc;
551         }
552         cbaf->buffer = kmalloc(512, GFP_KERNEL);
553         if (cbaf->buffer == NULL)
554                 goto error_kmalloc_buffer;
555         cbaf->buffer_size = 512;
556         cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface));
557         cbaf->usb_iface = usb_get_intf(iface);
558         result = cbaf_check(cbaf);
559         if (result < 0)
560                 goto error_check;
561         result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group);
562         if (result < 0) {
563                 dev_err(dev, "Can't register sysfs attr group: %d\n", result);
564                 goto error_create_group;
565         }
566         usb_set_intfdata(iface, cbaf);
567         d_printf(2, dev, "CBA attached\n");
568         return 0;
569
570 error_create_group:
571 error_check:
572         kfree(cbaf->buffer);
573 error_kmalloc_buffer:
574         kfree(cbaf);
575 error_kzalloc:
576         return result;
577 }
578
579 static void cbaf_disconnect(struct usb_interface *iface)
580 {
581         struct cbaf *cbaf = usb_get_intfdata(iface);
582         struct device *dev = &iface->dev;
583         sysfs_remove_group(&dev->kobj, &cbaf_dev_attr_group);
584         usb_set_intfdata(iface, NULL);
585         usb_put_intf(iface);
586         kfree(cbaf->buffer);
587         /* paranoia: clean up crypto keys */
588         memset(cbaf, 0, sizeof(*cbaf));
589         kfree(cbaf);
590         d_printf(1, dev, "CBA detached\n");
591 }
592
593 static struct usb_device_id cbaf_id_table[] = {
594         { USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
595         { },
596 };
597 MODULE_DEVICE_TABLE(usb, cbaf_id_table);
598
599 static struct usb_driver cbaf_driver = {
600         .name =         "wusb-cbaf",
601         .id_table =     cbaf_id_table,
602         .probe =        cbaf_probe,
603         .disconnect =   cbaf_disconnect,
604 };
605
606 static int __init cbaf_driver_init(void)
607 {
608         return usb_register(&cbaf_driver);
609 }
610 module_init(cbaf_driver_init);
611
612 static void __exit cbaf_driver_exit(void)
613 {
614         usb_deregister(&cbaf_driver);
615 }
616 module_exit(cbaf_driver_exit);
617
618 MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
619 MODULE_DESCRIPTION("Wireless USB Cable Based Association");
620 MODULE_LICENSE("GPL");