Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16-rc7 652 lines 20 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Wireless USB - Cable Based Association 4 * 5 * 6 * Copyright (C) 2006 Intel Corporation 7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 8 * Copyright (C) 2008 Cambridge Silicon Radio Ltd. 9 * 10 * WUSB devices have to be paired (associated in WUSB lingo) so 11 * that they can connect to the system. 12 * 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. 17 * 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. 24 * 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. 28 * 29 * The process goes like this: 30 * 31 * 1. Device plugs, cbaf is loaded, notifications happen. 32 * 33 * 2. The connection manager (CM) sees a device with CBAF capability 34 * (the wusb_chid etc. files in /sys/devices/blah/OURDEVICE). 35 * 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. 40 * 41 * 4. The CM can verify that the device's supported band groups 42 * (wusb_device_band_groups) are compatible with the host. 43 * 44 * 5. The CM reads the wusb_cdid file. 45 * 46 * 6. The CM looks up its database 47 * 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 50 * done. 51 * 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). 57 * 58 * CMD may choose to prompt the user before associating with a new 59 * device. 60 * 61 * 7. Device is unplugged. 62 * 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. 70 * 71 * References: 72 * [WUSB-AM] Association Models Supplement to the Certified Wireless 73 * Universal Serial Bus Specification, version 1.0. 74 */ 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> 86 87#define CBA_NAME_LEN 0x40 /* [WUSB-AM] table 4-7 */ 88 89/* An instance of a Cable-Based-Association-Framework device */ 90struct cbaf { 91 struct usb_device *usb_dev; 92 struct usb_interface *usb_iface; 93 void *buffer; 94 size_t buffer_size; 95 96 struct wusb_ckhdid chid; 97 char host_name[CBA_NAME_LEN]; 98 u16 host_band_groups; 99 100 struct wusb_ckhdid cdid; 101 char device_name[CBA_NAME_LEN]; 102 u16 device_band_groups; 103 104 struct wusb_ckhdid ck; 105}; 106 107/* 108 * Verify that a CBAF USB-interface has what we need 109 * 110 * According to [WUSB-AM], CBA devices should provide at least two 111 * interfaces: 112 * - RETRIEVE_HOST_INFO 113 * - ASSOCIATE 114 * 115 * If the device doesn't provide these interfaces, we do not know how 116 * to deal with it. 117 */ 118static int cbaf_check(struct cbaf *cbaf) 119{ 120 int result; 121 struct device *dev = &cbaf->usb_iface->dev; 122 struct wusb_cbaf_assoc_info *assoc_info; 123 struct wusb_cbaf_assoc_request *assoc_request; 124 size_t assoc_size; 125 void *itr, *top; 126 int ar_rhi = 0, ar_assoc = 0; 127 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); 134 if (result < 0) { 135 dev_err(dev, "Cannot get available association types: %d\n", 136 result); 137 return result; 138 } 139 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)); 145 return result; 146 } 147 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)); 153 return result; 154 } 155 /* 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} 158 * types. 159 */ 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); 164 165 while (itr < top) { 166 u16 ar_type, ar_subtype; 167 u32 ar_size; 168 const char *ar_name; 169 170 assoc_request = itr; 171 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)); 176 break; 177 } 178 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); 182 ar_name = "unknown"; 183 184 switch (ar_type) { 185 case AR_TYPE_WUSB: 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"; 190 ar_rhi = 1; 191 break; 192 case AR_TYPE_WUSB_ASSOCIATE: 193 /* send assoc data */ 194 ar_name = "ASSOCIATE"; 195 ar_assoc = 1; 196 break; 197 } 198 break; 199 } 200 201 dev_dbg(dev, "Association request #%02u: 0x%04x/%04x " 202 "(%zu bytes): %s\n", 203 assoc_request->AssociationDataIndex, ar_type, 204 ar_subtype, (size_t)ar_size, ar_name); 205 206 itr += sizeof(*assoc_request); 207 } 208 209 if (!ar_rhi) { 210 dev_err(dev, "Missing RETRIEVE_HOST_INFO association " 211 "request\n"); 212 return -EINVAL; 213 } 214 if (!ar_assoc) { 215 dev_err(dev, "Missing ASSOCIATE association request\n"); 216 return -EINVAL; 217 } 218 219 return 0; 220} 221 222static 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, 230}; 231 232/* Send WUSB host information (CHID and name) to a CBAF device */ 233static int cbaf_send_host_info(struct cbaf *cbaf) 234{ 235 struct wusb_cbaf_host_info *hi; 236 size_t name_len; 237 size_t hi_size; 238 239 hi = cbaf->buffer; 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; 248 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, 253 0x0101, 254 cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, 255 hi, hi_size, USB_CTRL_SET_TIMEOUT); 256} 257 258/* 259 * Get device's information (CDID) associated to CHID 260 * 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. 264 */ 265static int cbaf_cdid_get(struct cbaf *cbaf) 266{ 267 int result; 268 struct device *dev = &cbaf->usb_iface->dev; 269 struct wusb_cbaf_device_info *di; 270 size_t needed; 271 272 di = cbaf->buffer; 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); 279 if (result < 0) { 280 dev_err(dev, "Cannot request device information: %d\n", 281 result); 282 return result; 283 } 284 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); 289 return -ENOENT; 290 } 291 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); 295 296 return 0; 297} 298 299static ssize_t cbaf_wusb_chid_show(struct device *dev, 300 struct device_attribute *attr, 301 char *buf) 302{ 303 struct usb_interface *iface = to_usb_interface(dev); 304 struct cbaf *cbaf = usb_get_intfdata(iface); 305 char pr_chid[WUSB_CKHDID_STRSIZE]; 306 307 ckhdid_printf(pr_chid, sizeof(pr_chid), &cbaf->chid); 308 return scnprintf(buf, PAGE_SIZE, "%s\n", pr_chid); 309} 310 311static ssize_t cbaf_wusb_chid_store(struct device *dev, 312 struct device_attribute *attr, 313 const char *buf, size_t size) 314{ 315 ssize_t result; 316 struct usb_interface *iface = to_usb_interface(dev); 317 struct cbaf *cbaf = usb_get_intfdata(iface); 318 319 result = sscanf(buf, 320 "%02hhx %02hhx %02hhx %02hhx " 321 "%02hhx %02hhx %02hhx %02hhx " 322 "%02hhx %02hhx %02hhx %02hhx " 323 "%02hhx %02hhx %02hhx %02hhx", 324 &cbaf->chid.data[0] , &cbaf->chid.data[1], 325 &cbaf->chid.data[2] , &cbaf->chid.data[3], 326 &cbaf->chid.data[4] , &cbaf->chid.data[5], 327 &cbaf->chid.data[6] , &cbaf->chid.data[7], 328 &cbaf->chid.data[8] , &cbaf->chid.data[9], 329 &cbaf->chid.data[10], &cbaf->chid.data[11], 330 &cbaf->chid.data[12], &cbaf->chid.data[13], 331 &cbaf->chid.data[14], &cbaf->chid.data[15]); 332 333 if (result != 16) 334 return -EINVAL; 335 336 result = cbaf_send_host_info(cbaf); 337 if (result < 0) 338 return result; 339 result = cbaf_cdid_get(cbaf); 340 if (result < 0) 341 return result; 342 return size; 343} 344static DEVICE_ATTR(wusb_chid, 0600, cbaf_wusb_chid_show, cbaf_wusb_chid_store); 345 346static ssize_t cbaf_wusb_host_name_show(struct device *dev, 347 struct device_attribute *attr, 348 char *buf) 349{ 350 struct usb_interface *iface = to_usb_interface(dev); 351 struct cbaf *cbaf = usb_get_intfdata(iface); 352 353 return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->host_name); 354} 355 356static ssize_t cbaf_wusb_host_name_store(struct device *dev, 357 struct device_attribute *attr, 358 const char *buf, size_t size) 359{ 360 ssize_t result; 361 struct usb_interface *iface = to_usb_interface(dev); 362 struct cbaf *cbaf = usb_get_intfdata(iface); 363 364 result = sscanf(buf, "%63s", cbaf->host_name); 365 if (result != 1) 366 return -EINVAL; 367 368 return size; 369} 370static DEVICE_ATTR(wusb_host_name, 0600, cbaf_wusb_host_name_show, 371 cbaf_wusb_host_name_store); 372 373static ssize_t cbaf_wusb_host_band_groups_show(struct device *dev, 374 struct device_attribute *attr, 375 char *buf) 376{ 377 struct usb_interface *iface = to_usb_interface(dev); 378 struct cbaf *cbaf = usb_get_intfdata(iface); 379 380 return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->host_band_groups); 381} 382 383static ssize_t cbaf_wusb_host_band_groups_store(struct device *dev, 384 struct device_attribute *attr, 385 const char *buf, size_t size) 386{ 387 ssize_t result; 388 struct usb_interface *iface = to_usb_interface(dev); 389 struct cbaf *cbaf = usb_get_intfdata(iface); 390 u16 band_groups = 0; 391 392 result = sscanf(buf, "%04hx", &band_groups); 393 if (result != 1) 394 return -EINVAL; 395 396 cbaf->host_band_groups = band_groups; 397 398 return size; 399} 400 401static DEVICE_ATTR(wusb_host_band_groups, 0600, 402 cbaf_wusb_host_band_groups_show, 403 cbaf_wusb_host_band_groups_store); 404 405static const struct wusb_cbaf_device_info cbaf_device_info_defaults = { 406 .Length_hdr = WUSB_AR_Length, 407 .CDID_hdr = WUSB_AR_CDID, 408 .BandGroups_hdr = WUSB_AR_BandGroups, 409 .LangID_hdr = WUSB_AR_LangID, 410 .DeviceFriendlyName_hdr = WUSB_AR_DeviceFriendlyName, 411}; 412 413static ssize_t cbaf_wusb_cdid_show(struct device *dev, 414 struct device_attribute *attr, char *buf) 415{ 416 struct usb_interface *iface = to_usb_interface(dev); 417 struct cbaf *cbaf = usb_get_intfdata(iface); 418 char pr_cdid[WUSB_CKHDID_STRSIZE]; 419 420 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &cbaf->cdid); 421 return scnprintf(buf, PAGE_SIZE, "%s\n", pr_cdid); 422} 423 424static ssize_t cbaf_wusb_cdid_store(struct device *dev, 425 struct device_attribute *attr, 426 const char *buf, size_t size) 427{ 428 ssize_t result; 429 struct usb_interface *iface = to_usb_interface(dev); 430 struct cbaf *cbaf = usb_get_intfdata(iface); 431 struct wusb_ckhdid cdid; 432 433 result = sscanf(buf, 434 "%02hhx %02hhx %02hhx %02hhx " 435 "%02hhx %02hhx %02hhx %02hhx " 436 "%02hhx %02hhx %02hhx %02hhx " 437 "%02hhx %02hhx %02hhx %02hhx", 438 &cdid.data[0] , &cdid.data[1], 439 &cdid.data[2] , &cdid.data[3], 440 &cdid.data[4] , &cdid.data[5], 441 &cdid.data[6] , &cdid.data[7], 442 &cdid.data[8] , &cdid.data[9], 443 &cdid.data[10], &cdid.data[11], 444 &cdid.data[12], &cdid.data[13], 445 &cdid.data[14], &cdid.data[15]); 446 if (result != 16) 447 return -EINVAL; 448 449 cbaf->cdid = cdid; 450 451 return size; 452} 453static DEVICE_ATTR(wusb_cdid, 0600, cbaf_wusb_cdid_show, cbaf_wusb_cdid_store); 454 455static ssize_t cbaf_wusb_device_band_groups_show(struct device *dev, 456 struct device_attribute *attr, 457 char *buf) 458{ 459 struct usb_interface *iface = to_usb_interface(dev); 460 struct cbaf *cbaf = usb_get_intfdata(iface); 461 462 return scnprintf(buf, PAGE_SIZE, "0x%04x\n", cbaf->device_band_groups); 463} 464 465static DEVICE_ATTR(wusb_device_band_groups, 0600, 466 cbaf_wusb_device_band_groups_show, 467 NULL); 468 469static ssize_t cbaf_wusb_device_name_show(struct device *dev, 470 struct device_attribute *attr, 471 char *buf) 472{ 473 struct usb_interface *iface = to_usb_interface(dev); 474 struct cbaf *cbaf = usb_get_intfdata(iface); 475 476 return scnprintf(buf, PAGE_SIZE, "%s\n", cbaf->device_name); 477} 478static DEVICE_ATTR(wusb_device_name, 0600, cbaf_wusb_device_name_show, NULL); 479 480static const struct wusb_cbaf_cc_data cbaf_cc_data_defaults = { 481 .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, 482 .AssociationTypeId = cpu_to_le16(AR_TYPE_WUSB), 483 .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId, 484 .AssociationSubTypeId = cpu_to_le16(AR_TYPE_WUSB_ASSOCIATE), 485 .Length_hdr = WUSB_AR_Length, 486 .Length = cpu_to_le32(sizeof(struct wusb_cbaf_cc_data)), 487 .ConnectionContext_hdr = WUSB_AR_ConnectionContext, 488 .BandGroups_hdr = WUSB_AR_BandGroups, 489}; 490 491static const struct wusb_cbaf_cc_data_fail cbaf_cc_data_fail_defaults = { 492 .AssociationTypeId_hdr = WUSB_AR_AssociationTypeId, 493 .AssociationSubTypeId_hdr = WUSB_AR_AssociationSubTypeId, 494 .Length_hdr = WUSB_AR_Length, 495 .AssociationStatus_hdr = WUSB_AR_AssociationStatus, 496}; 497 498/* 499 * Send a new CC to the device. 500 */ 501static int cbaf_cc_upload(struct cbaf *cbaf) 502{ 503 int result; 504 struct device *dev = &cbaf->usb_iface->dev; 505 struct wusb_cbaf_cc_data *ccd; 506 char pr_cdid[WUSB_CKHDID_STRSIZE]; 507 508 ccd = cbaf->buffer; 509 *ccd = cbaf_cc_data_defaults; 510 ccd->CHID = cbaf->chid; 511 ccd->CDID = cbaf->cdid; 512 ccd->CK = cbaf->ck; 513 ccd->BandGroups = cpu_to_le16(cbaf->host_band_groups); 514 515 dev_dbg(dev, "Trying to upload CC:\n"); 516 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CHID); 517 dev_dbg(dev, " CHID %s\n", pr_cdid); 518 ckhdid_printf(pr_cdid, sizeof(pr_cdid), &ccd->CDID); 519 dev_dbg(dev, " CDID %s\n", pr_cdid); 520 dev_dbg(dev, " Bandgroups 0x%04x\n", cbaf->host_band_groups); 521 522 result = usb_control_msg( 523 cbaf->usb_dev, usb_sndctrlpipe(cbaf->usb_dev, 0), 524 CBAF_REQ_SET_ASSOCIATION_RESPONSE, 525 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 526 0x0201, cbaf->usb_iface->cur_altsetting->desc.bInterfaceNumber, 527 ccd, sizeof(*ccd), USB_CTRL_SET_TIMEOUT); 528 529 return result; 530} 531 532static ssize_t cbaf_wusb_ck_store(struct device *dev, 533 struct device_attribute *attr, 534 const char *buf, size_t size) 535{ 536 ssize_t result; 537 struct usb_interface *iface = to_usb_interface(dev); 538 struct cbaf *cbaf = usb_get_intfdata(iface); 539 540 result = sscanf(buf, 541 "%02hhx %02hhx %02hhx %02hhx " 542 "%02hhx %02hhx %02hhx %02hhx " 543 "%02hhx %02hhx %02hhx %02hhx " 544 "%02hhx %02hhx %02hhx %02hhx", 545 &cbaf->ck.data[0] , &cbaf->ck.data[1], 546 &cbaf->ck.data[2] , &cbaf->ck.data[3], 547 &cbaf->ck.data[4] , &cbaf->ck.data[5], 548 &cbaf->ck.data[6] , &cbaf->ck.data[7], 549 &cbaf->ck.data[8] , &cbaf->ck.data[9], 550 &cbaf->ck.data[10], &cbaf->ck.data[11], 551 &cbaf->ck.data[12], &cbaf->ck.data[13], 552 &cbaf->ck.data[14], &cbaf->ck.data[15]); 553 if (result != 16) 554 return -EINVAL; 555 556 result = cbaf_cc_upload(cbaf); 557 if (result < 0) 558 return result; 559 560 return size; 561} 562static DEVICE_ATTR(wusb_ck, 0600, NULL, cbaf_wusb_ck_store); 563 564static struct attribute *cbaf_dev_attrs[] = { 565 &dev_attr_wusb_host_name.attr, 566 &dev_attr_wusb_host_band_groups.attr, 567 &dev_attr_wusb_chid.attr, 568 &dev_attr_wusb_cdid.attr, 569 &dev_attr_wusb_device_name.attr, 570 &dev_attr_wusb_device_band_groups.attr, 571 &dev_attr_wusb_ck.attr, 572 NULL, 573}; 574 575static const struct attribute_group cbaf_dev_attr_group = { 576 .name = NULL, /* we want them in the same directory */ 577 .attrs = cbaf_dev_attrs, 578}; 579 580static int cbaf_probe(struct usb_interface *iface, 581 const struct usb_device_id *id) 582{ 583 struct cbaf *cbaf; 584 struct device *dev = &iface->dev; 585 int result = -ENOMEM; 586 587 cbaf = kzalloc(sizeof(*cbaf), GFP_KERNEL); 588 if (cbaf == NULL) 589 goto error_kzalloc; 590 cbaf->buffer = kmalloc(512, GFP_KERNEL); 591 if (cbaf->buffer == NULL) 592 goto error_kmalloc_buffer; 593 594 cbaf->buffer_size = 512; 595 cbaf->usb_dev = usb_get_dev(interface_to_usbdev(iface)); 596 cbaf->usb_iface = usb_get_intf(iface); 597 result = cbaf_check(cbaf); 598 if (result < 0) { 599 dev_err(dev, "This device is not WUSB-CBAF compliant and is not supported yet.\n"); 600 goto error_check; 601 } 602 603 result = sysfs_create_group(&dev->kobj, &cbaf_dev_attr_group); 604 if (result < 0) { 605 dev_err(dev, "Can't register sysfs attr group: %d\n", result); 606 goto error_create_group; 607 } 608 usb_set_intfdata(iface, cbaf); 609 return 0; 610 611error_create_group: 612error_check: 613 usb_put_intf(iface); 614 usb_put_dev(cbaf->usb_dev); 615 kfree(cbaf->buffer); 616error_kmalloc_buffer: 617 kfree(cbaf); 618error_kzalloc: 619 return result; 620} 621 622static void cbaf_disconnect(struct usb_interface *iface) 623{ 624 struct cbaf *cbaf = usb_get_intfdata(iface); 625 struct device *dev = &iface->dev; 626 sysfs_remove_group(&dev->kobj, &cbaf_dev_attr_group); 627 usb_set_intfdata(iface, NULL); 628 usb_put_intf(iface); 629 usb_put_dev(cbaf->usb_dev); 630 kfree(cbaf->buffer); 631 /* paranoia: clean up crypto keys */ 632 kzfree(cbaf); 633} 634 635static const struct usb_device_id cbaf_id_table[] = { 636 { USB_INTERFACE_INFO(0xef, 0x03, 0x01), }, 637 { }, 638}; 639MODULE_DEVICE_TABLE(usb, cbaf_id_table); 640 641static struct usb_driver cbaf_driver = { 642 .name = "wusb-cbaf", 643 .id_table = cbaf_id_table, 644 .probe = cbaf_probe, 645 .disconnect = cbaf_disconnect, 646}; 647 648module_usb_driver(cbaf_driver); 649 650MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>"); 651MODULE_DESCRIPTION("Wireless USB Cable Based Association"); 652MODULE_LICENSE("GPL");