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 v3.4-rc2 843 lines 26 kB view raw
1/* 2 * Host Wire Adapter: 3 * Driver glue, HWA-specific functions, bridges to WAHC and WUSBHC 4 * 5 * Copyright (C) 2005-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 * The HWA driver is a simple layer that forwards requests to the WAHC 24 * (Wire Adater Host Controller) or WUSBHC (Wireless USB Host 25 * Controller) layers. 26 * 27 * Host Wire Adapter is the 'WUSB 1.0 standard' name for Wireless-USB 28 * Host Controller that is connected to your system via USB (a USB 29 * dongle that implements a USB host...). There is also a Device Wired 30 * Adaptor, DWA (Wireless USB hub) that uses the same mechanism for 31 * transferring data (it is after all a USB host connected via 32 * Wireless USB), we have a common layer called Wire Adapter Host 33 * Controller that does all the hard work. The WUSBHC (Wireless USB 34 * Host Controller) is the part common to WUSB Host Controllers, the 35 * HWA and the PCI-based one, that is implemented following the WHCI 36 * spec. All these layers are implemented in ../wusbcore. 37 * 38 * The main functions are hwahc_op_urb_{en,de}queue(), that pass the 39 * job of converting a URB to a Wire Adapter 40 * 41 * Entry points: 42 * 43 * hwahc_driver_*() Driver initialization, registration and 44 * teardown. 45 * 46 * hwahc_probe() New device came up, create an instance for 47 * it [from device enumeration]. 48 * 49 * hwahc_disconnect() Remove device instance [from device 50 * enumeration]. 51 * 52 * [__]hwahc_op_*() Host-Wire-Adaptor specific functions for 53 * starting/stopping/etc (some might be made also 54 * DWA). 55 */ 56#include <linux/kernel.h> 57#include <linux/init.h> 58#include <linux/slab.h> 59#include <linux/module.h> 60#include <linux/workqueue.h> 61#include <linux/wait.h> 62#include <linux/completion.h> 63#include "../wusbcore/wa-hc.h" 64#include "../wusbcore/wusbhc.h" 65 66struct hwahc { 67 struct wusbhc wusbhc; /* has to be 1st */ 68 struct wahc wa; 69}; 70 71/* 72 * FIXME should be wusbhc 73 * 74 * NOTE: we need to cache the Cluster ID because later...there is no 75 * way to get it :) 76 */ 77static int __hwahc_set_cluster_id(struct hwahc *hwahc, u8 cluster_id) 78{ 79 int result; 80 struct wusbhc *wusbhc = &hwahc->wusbhc; 81 struct wahc *wa = &hwahc->wa; 82 struct device *dev = &wa->usb_iface->dev; 83 84 result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 85 WUSB_REQ_SET_CLUSTER_ID, 86 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 87 cluster_id, 88 wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, 89 NULL, 0, 1000 /* FIXME: arbitrary */); 90 if (result < 0) 91 dev_err(dev, "Cannot set WUSB Cluster ID to 0x%02x: %d\n", 92 cluster_id, result); 93 else 94 wusbhc->cluster_id = cluster_id; 95 dev_info(dev, "Wireless USB Cluster ID set to 0x%02x\n", cluster_id); 96 return result; 97} 98 99static int __hwahc_op_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots) 100{ 101 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 102 struct wahc *wa = &hwahc->wa; 103 104 return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 105 WUSB_REQ_SET_NUM_DNTS, 106 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 107 interval << 8 | slots, 108 wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, 109 NULL, 0, 1000 /* FIXME: arbitrary */); 110} 111 112/* 113 * Reset a WUSB host controller and wait for it to complete doing it. 114 * 115 * @usb_hcd: Pointer to WUSB Host Controller instance. 116 * 117 */ 118static int hwahc_op_reset(struct usb_hcd *usb_hcd) 119{ 120 int result; 121 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 122 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 123 struct device *dev = &hwahc->wa.usb_iface->dev; 124 125 mutex_lock(&wusbhc->mutex); 126 wa_nep_disarm(&hwahc->wa); 127 result = __wa_set_feature(&hwahc->wa, WA_RESET); 128 if (result < 0) { 129 dev_err(dev, "error commanding HC to reset: %d\n", result); 130 goto error_unlock; 131 } 132 result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0); 133 if (result < 0) { 134 dev_err(dev, "error waiting for HC to reset: %d\n", result); 135 goto error_unlock; 136 } 137error_unlock: 138 mutex_unlock(&wusbhc->mutex); 139 return result; 140} 141 142/* 143 * FIXME: break this function up 144 */ 145static int hwahc_op_start(struct usb_hcd *usb_hcd) 146{ 147 u8 addr; 148 int result; 149 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 150 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 151 152 result = -ENOSPC; 153 mutex_lock(&wusbhc->mutex); 154 addr = wusb_cluster_id_get(); 155 if (addr == 0) 156 goto error_cluster_id_get; 157 result = __hwahc_set_cluster_id(hwahc, addr); 158 if (result < 0) 159 goto error_set_cluster_id; 160 161 usb_hcd->uses_new_polling = 1; 162 set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags); 163 usb_hcd->state = HC_STATE_RUNNING; 164 result = 0; 165out: 166 mutex_unlock(&wusbhc->mutex); 167 return result; 168 169error_set_cluster_id: 170 wusb_cluster_id_put(wusbhc->cluster_id); 171error_cluster_id_get: 172 goto out; 173 174} 175 176/* 177 * No need to abort pipes, as when this is called, all the children 178 * has been disconnected and that has done it [through 179 * usb_disable_interface() -> usb_disable_endpoint() -> 180 * hwahc_op_ep_disable() - >rpipe_ep_disable()]. 181 */ 182static void hwahc_op_stop(struct usb_hcd *usb_hcd) 183{ 184 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 185 186 mutex_lock(&wusbhc->mutex); 187 wusb_cluster_id_put(wusbhc->cluster_id); 188 mutex_unlock(&wusbhc->mutex); 189} 190 191static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd) 192{ 193 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 194 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 195 196 dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, 197 usb_hcd, hwahc); 198 return -ENOSYS; 199} 200 201static int hwahc_op_urb_enqueue(struct usb_hcd *usb_hcd, struct urb *urb, 202 gfp_t gfp) 203{ 204 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 205 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 206 207 return wa_urb_enqueue(&hwahc->wa, urb->ep, urb, gfp); 208} 209 210static int hwahc_op_urb_dequeue(struct usb_hcd *usb_hcd, struct urb *urb, 211 int status) 212{ 213 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 214 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 215 216 return wa_urb_dequeue(&hwahc->wa, urb); 217} 218 219/* 220 * Release resources allocated for an endpoint 221 * 222 * If there is an associated rpipe to this endpoint, go ahead and put it. 223 */ 224static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd, 225 struct usb_host_endpoint *ep) 226{ 227 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 228 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 229 230 rpipe_ep_disable(&hwahc->wa, ep); 231} 232 233static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) 234{ 235 int result; 236 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 237 struct device *dev = &hwahc->wa.usb_iface->dev; 238 239 result = __wa_set_feature(&hwahc->wa, WA_ENABLE); 240 if (result < 0) { 241 dev_err(dev, "error commanding HC to start: %d\n", result); 242 goto error_stop; 243 } 244 result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); 245 if (result < 0) { 246 dev_err(dev, "error waiting for HC to start: %d\n", result); 247 goto error_stop; 248 } 249 result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); 250 if (result < 0) { 251 dev_err(dev, "cannot listen to notifications: %d\n", result); 252 goto error_stop; 253 } 254 return result; 255 256error_stop: 257 __wa_clear_feature(&hwahc->wa, WA_ENABLE); 258 return result; 259} 260 261static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay) 262{ 263 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 264 struct wahc *wa = &hwahc->wa; 265 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 266 int ret; 267 268 ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 269 WUSB_REQ_CHAN_STOP, 270 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 271 delay * 1000, 272 iface_no, 273 NULL, 0, 1000 /* FIXME: arbitrary */); 274 if (ret == 0) 275 msleep(delay); 276 277 wa_nep_disarm(&hwahc->wa); 278 __wa_stop(&hwahc->wa); 279} 280 281/* 282 * Set the UWB MAS allocation for the WUSB cluster 283 * 284 * @stream_index: stream to use (-1 for cancelling the allocation) 285 * @mas: mas bitmap to use 286 */ 287static int __hwahc_op_bwa_set(struct wusbhc *wusbhc, s8 stream_index, 288 const struct uwb_mas_bm *mas) 289{ 290 int result; 291 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 292 struct wahc *wa = &hwahc->wa; 293 struct device *dev = &wa->usb_iface->dev; 294 u8 mas_le[UWB_NUM_MAS/8]; 295 296 /* Set the stream index */ 297 result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 298 WUSB_REQ_SET_STREAM_IDX, 299 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 300 stream_index, 301 wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, 302 NULL, 0, 1000 /* FIXME: arbitrary */); 303 if (result < 0) { 304 dev_err(dev, "Cannot set WUSB stream index: %d\n", result); 305 goto out; 306 } 307 uwb_mas_bm_copy_le(mas_le, mas); 308 /* Set the MAS allocation */ 309 result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 310 WUSB_REQ_SET_WUSB_MAS, 311 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 312 0, wa->usb_iface->cur_altsetting->desc.bInterfaceNumber, 313 mas_le, 32, 1000 /* FIXME: arbitrary */); 314 if (result < 0) 315 dev_err(dev, "Cannot set WUSB MAS allocation: %d\n", result); 316out: 317 return result; 318} 319 320/* 321 * Add an IE to the host's MMC 322 * 323 * @interval: See WUSB1.0[8.5.3.1] 324 * @repeat_cnt: See WUSB1.0[8.5.3.1] 325 * @handle: See WUSB1.0[8.5.3.1] 326 * @wuie: Pointer to the header of the WUSB IE data to add. 327 * MUST BE allocated in a kmalloc buffer (no stack or 328 * vmalloc). 329 * 330 * NOTE: the format of the WUSB IEs for MMCs are different to the 331 * normal MBOA MAC IEs (IE Id + Length in MBOA MAC vs. Length + 332 * Id in WUSB IEs). Standards...you gotta love'em. 333 */ 334static int __hwahc_op_mmcie_add(struct wusbhc *wusbhc, u8 interval, 335 u8 repeat_cnt, u8 handle, 336 struct wuie_hdr *wuie) 337{ 338 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 339 struct wahc *wa = &hwahc->wa; 340 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 341 342 return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 343 WUSB_REQ_ADD_MMC_IE, 344 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 345 interval << 8 | repeat_cnt, 346 handle << 8 | iface_no, 347 wuie, wuie->bLength, 1000 /* FIXME: arbitrary */); 348} 349 350/* 351 * Remove an IE to the host's MMC 352 * 353 * @handle: See WUSB1.0[8.5.3.1] 354 */ 355static int __hwahc_op_mmcie_rm(struct wusbhc *wusbhc, u8 handle) 356{ 357 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 358 struct wahc *wa = &hwahc->wa; 359 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 360 return usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 361 WUSB_REQ_REMOVE_MMC_IE, 362 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 363 0, handle << 8 | iface_no, 364 NULL, 0, 1000 /* FIXME: arbitrary */); 365} 366 367/* 368 * Update device information for a given fake port 369 * 370 * @port_idx: Fake port to which device is connected (wusbhc index, not 371 * USB port number). 372 */ 373static int __hwahc_op_dev_info_set(struct wusbhc *wusbhc, 374 struct wusb_dev *wusb_dev) 375{ 376 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 377 struct wahc *wa = &hwahc->wa; 378 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 379 struct hwa_dev_info *dev_info; 380 int ret; 381 382 /* fill out the Device Info buffer and send it */ 383 dev_info = kzalloc(sizeof(struct hwa_dev_info), GFP_KERNEL); 384 if (!dev_info) 385 return -ENOMEM; 386 uwb_mas_bm_copy_le(dev_info->bmDeviceAvailability, 387 &wusb_dev->availability); 388 dev_info->bDeviceAddress = wusb_dev->addr; 389 390 /* 391 * If the descriptors haven't been read yet, use a default PHY 392 * rate of 53.3 Mbit/s only. The correct value will be used 393 * when this will be called again as part of the 394 * authentication process (which occurs after the descriptors 395 * have been read). 396 */ 397 if (wusb_dev->wusb_cap_descr) 398 dev_info->wPHYRates = wusb_dev->wusb_cap_descr->wPHYRates; 399 else 400 dev_info->wPHYRates = cpu_to_le16(USB_WIRELESS_PHY_53); 401 402 ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 403 WUSB_REQ_SET_DEV_INFO, 404 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 405 0, wusb_dev->port_idx << 8 | iface_no, 406 dev_info, sizeof(struct hwa_dev_info), 407 1000 /* FIXME: arbitrary */); 408 kfree(dev_info); 409 return ret; 410} 411 412/* 413 * Set host's idea of which encryption (and key) method to use when 414 * talking to ad evice on a given port. 415 * 416 * If key is NULL, it means disable encryption for that "virtual port" 417 * (used when we disconnect). 418 */ 419static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, 420 const void *key, size_t key_size, 421 u8 key_idx) 422{ 423 int result = -ENOMEM; 424 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 425 struct wahc *wa = &hwahc->wa; 426 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 427 struct usb_key_descriptor *keyd; 428 size_t keyd_len; 429 430 keyd_len = sizeof(*keyd) + key_size; 431 keyd = kzalloc(keyd_len, GFP_KERNEL); 432 if (keyd == NULL) 433 return -ENOMEM; 434 435 keyd->bLength = keyd_len; 436 keyd->bDescriptorType = USB_DT_KEY; 437 keyd->tTKID[0] = (tkid >> 0) & 0xff; 438 keyd->tTKID[1] = (tkid >> 8) & 0xff; 439 keyd->tTKID[2] = (tkid >> 16) & 0xff; 440 memcpy(keyd->bKeyData, key, key_size); 441 442 result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 443 USB_REQ_SET_DESCRIPTOR, 444 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 445 USB_DT_KEY << 8 | key_idx, 446 port_idx << 8 | iface_no, 447 keyd, keyd_len, 1000 /* FIXME: arbitrary */); 448 449 kzfree(keyd); /* clear keys etc. */ 450 return result; 451} 452 453/* 454 * Set host's idea of which encryption (and key) method to use when 455 * talking to ad evice on a given port. 456 * 457 * If key is NULL, it means disable encryption for that "virtual port" 458 * (used when we disconnect). 459 */ 460static int __hwahc_op_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, 461 const void *key, size_t key_size) 462{ 463 int result = -ENOMEM; 464 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 465 struct wahc *wa = &hwahc->wa; 466 u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; 467 u8 encryption_value; 468 469 /* Tell the host which key to use to talk to the device */ 470 if (key) { 471 u8 key_idx = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_PTK, 472 WUSB_KEY_INDEX_ORIGINATOR_HOST); 473 474 result = __hwahc_dev_set_key(wusbhc, port_idx, tkid, 475 key, key_size, key_idx); 476 if (result < 0) 477 goto error_set_key; 478 encryption_value = wusbhc->ccm1_etd->bEncryptionValue; 479 } else { 480 /* FIXME: this should come from wusbhc->etd[UNSECURE].value */ 481 encryption_value = 0; 482 } 483 484 /* Set the encryption type for communicating with the device */ 485 result = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), 486 USB_REQ_SET_ENCRYPTION, 487 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 488 encryption_value, port_idx << 8 | iface_no, 489 NULL, 0, 1000 /* FIXME: arbitrary */); 490 if (result < 0) 491 dev_err(wusbhc->dev, "Can't set host's WUSB encryption for " 492 "port index %u to %s (value %d): %d\n", port_idx, 493 wusb_et_name(wusbhc->ccm1_etd->bEncryptionType), 494 wusbhc->ccm1_etd->bEncryptionValue, result); 495error_set_key: 496 return result; 497} 498 499/* 500 * Set host's GTK key 501 */ 502static int __hwahc_op_set_gtk(struct wusbhc *wusbhc, u32 tkid, 503 const void *key, size_t key_size) 504{ 505 u8 key_idx = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK, 506 WUSB_KEY_INDEX_ORIGINATOR_HOST); 507 508 return __hwahc_dev_set_key(wusbhc, 0, tkid, key, key_size, key_idx); 509} 510 511/* 512 * Get the Wire Adapter class-specific descriptor 513 * 514 * NOTE: this descriptor comes with the big bundled configuration 515 * descriptor that includes the interfaces' and endpoints', so 516 * we just look for it in the cached copy kept by the USB stack. 517 * 518 * NOTE2: We convert LE fields to CPU order. 519 */ 520static int wa_fill_descr(struct wahc *wa) 521{ 522 int result; 523 struct device *dev = &wa->usb_iface->dev; 524 char *itr; 525 struct usb_device *usb_dev = wa->usb_dev; 526 struct usb_descriptor_header *hdr; 527 struct usb_wa_descriptor *wa_descr; 528 size_t itr_size, actconfig_idx; 529 530 actconfig_idx = (usb_dev->actconfig - usb_dev->config) / 531 sizeof(usb_dev->config[0]); 532 itr = usb_dev->rawdescriptors[actconfig_idx]; 533 itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); 534 while (itr_size >= sizeof(*hdr)) { 535 hdr = (struct usb_descriptor_header *) itr; 536 dev_dbg(dev, "Extra device descriptor: " 537 "type %02x/%u bytes @ %zu (%zu left)\n", 538 hdr->bDescriptorType, hdr->bLength, 539 (itr - usb_dev->rawdescriptors[actconfig_idx]), 540 itr_size); 541 if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER) 542 goto found; 543 itr += hdr->bLength; 544 itr_size -= hdr->bLength; 545 } 546 dev_err(dev, "cannot find Wire Adapter Class descriptor\n"); 547 return -ENODEV; 548 549found: 550 result = -EINVAL; 551 if (hdr->bLength > itr_size) { /* is it available? */ 552 dev_err(dev, "incomplete Wire Adapter Class descriptor " 553 "(%zu bytes left, %u needed)\n", 554 itr_size, hdr->bLength); 555 goto error; 556 } 557 if (hdr->bLength < sizeof(*wa->wa_descr)) { 558 dev_err(dev, "short Wire Adapter Class descriptor\n"); 559 goto error; 560 } 561 wa->wa_descr = wa_descr = (struct usb_wa_descriptor *) hdr; 562 /* Make LE fields CPU order */ 563 wa_descr->bcdWAVersion = le16_to_cpu(wa_descr->bcdWAVersion); 564 wa_descr->wNumRPipes = le16_to_cpu(wa_descr->wNumRPipes); 565 wa_descr->wRPipeMaxBlock = le16_to_cpu(wa_descr->wRPipeMaxBlock); 566 if (wa_descr->bcdWAVersion > 0x0100) 567 dev_warn(dev, "Wire Adapter v%d.%d newer than groked v1.0\n", 568 wa_descr->bcdWAVersion & 0xff00 >> 8, 569 wa_descr->bcdWAVersion & 0x00ff); 570 result = 0; 571error: 572 return result; 573} 574 575static struct hc_driver hwahc_hc_driver = { 576 .description = "hwa-hcd", 577 .product_desc = "Wireless USB HWA host controller", 578 .hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd), 579 .irq = NULL, /* FIXME */ 580 .flags = HCD_USB2, /* FIXME */ 581 .reset = hwahc_op_reset, 582 .start = hwahc_op_start, 583 .stop = hwahc_op_stop, 584 .get_frame_number = hwahc_op_get_frame_number, 585 .urb_enqueue = hwahc_op_urb_enqueue, 586 .urb_dequeue = hwahc_op_urb_dequeue, 587 .endpoint_disable = hwahc_op_endpoint_disable, 588 589 .hub_status_data = wusbhc_rh_status_data, 590 .hub_control = wusbhc_rh_control, 591 .bus_suspend = wusbhc_rh_suspend, 592 .bus_resume = wusbhc_rh_resume, 593 .start_port_reset = wusbhc_rh_start_port_reset, 594}; 595 596static int hwahc_security_create(struct hwahc *hwahc) 597{ 598 int result; 599 struct wusbhc *wusbhc = &hwahc->wusbhc; 600 struct usb_device *usb_dev = hwahc->wa.usb_dev; 601 struct device *dev = &usb_dev->dev; 602 struct usb_security_descriptor *secd; 603 struct usb_encryption_descriptor *etd; 604 void *itr, *top; 605 size_t itr_size, needed, bytes; 606 u8 index; 607 char buf[64]; 608 609 /* Find the host's security descriptors in the config descr bundle */ 610 index = (usb_dev->actconfig - usb_dev->config) / 611 sizeof(usb_dev->config[0]); 612 itr = usb_dev->rawdescriptors[index]; 613 itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); 614 top = itr + itr_size; 615 result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], 616 le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), 617 USB_DT_SECURITY, (void **) &secd); 618 if (result == -1) { 619 dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); 620 return 0; 621 } 622 needed = sizeof(*secd); 623 if (top - (void *)secd < needed) { 624 dev_err(dev, "BUG? Not enough data to process security " 625 "descriptor header (%zu bytes left vs %zu needed)\n", 626 top - (void *) secd, needed); 627 return 0; 628 } 629 needed = le16_to_cpu(secd->wTotalLength); 630 if (top - (void *)secd < needed) { 631 dev_err(dev, "BUG? Not enough data to process security " 632 "descriptors (%zu bytes left vs %zu needed)\n", 633 top - (void *) secd, needed); 634 return 0; 635 } 636 /* Walk over the sec descriptors and store CCM1's on wusbhc */ 637 itr = (void *) secd + sizeof(*secd); 638 top = (void *) secd + le16_to_cpu(secd->wTotalLength); 639 index = 0; 640 bytes = 0; 641 while (itr < top) { 642 etd = itr; 643 if (top - itr < sizeof(*etd)) { 644 dev_err(dev, "BUG: bad host security descriptor; " 645 "not enough data (%zu vs %zu left)\n", 646 top - itr, sizeof(*etd)); 647 break; 648 } 649 if (etd->bLength < sizeof(*etd)) { 650 dev_err(dev, "BUG: bad host encryption descriptor; " 651 "descriptor is too short " 652 "(%zu vs %zu needed)\n", 653 (size_t)etd->bLength, sizeof(*etd)); 654 break; 655 } 656 itr += etd->bLength; 657 bytes += snprintf(buf + bytes, sizeof(buf) - bytes, 658 "%s (0x%02x) ", 659 wusb_et_name(etd->bEncryptionType), 660 etd->bEncryptionValue); 661 wusbhc->ccm1_etd = etd; 662 } 663 dev_info(dev, "supported encryption types: %s\n", buf); 664 if (wusbhc->ccm1_etd == NULL) { 665 dev_err(dev, "E: host doesn't support CCM-1 crypto\n"); 666 return 0; 667 } 668 /* Pretty print what we support */ 669 return 0; 670} 671 672static void hwahc_security_release(struct hwahc *hwahc) 673{ 674 /* nothing to do here so far... */ 675} 676 677static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface) 678{ 679 int result; 680 struct device *dev = &iface->dev; 681 struct wusbhc *wusbhc = &hwahc->wusbhc; 682 struct wahc *wa = &hwahc->wa; 683 struct usb_device *usb_dev = interface_to_usbdev(iface); 684 685 wa->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */ 686 wa->usb_iface = usb_get_intf(iface); 687 wusbhc->dev = dev; 688 wusbhc->uwb_rc = uwb_rc_get_by_grandpa(iface->dev.parent); 689 if (wusbhc->uwb_rc == NULL) { 690 result = -ENODEV; 691 dev_err(dev, "Cannot get associated UWB Host Controller\n"); 692 goto error_rc_get; 693 } 694 result = wa_fill_descr(wa); /* Get the device descriptor */ 695 if (result < 0) 696 goto error_fill_descriptor; 697 if (wa->wa_descr->bNumPorts > USB_MAXCHILDREN) { 698 dev_err(dev, "FIXME: USB_MAXCHILDREN too low for WUSB " 699 "adapter (%u ports)\n", wa->wa_descr->bNumPorts); 700 wusbhc->ports_max = USB_MAXCHILDREN; 701 } else { 702 wusbhc->ports_max = wa->wa_descr->bNumPorts; 703 } 704 wusbhc->mmcies_max = wa->wa_descr->bNumMMCIEs; 705 wusbhc->start = __hwahc_op_wusbhc_start; 706 wusbhc->stop = __hwahc_op_wusbhc_stop; 707 wusbhc->mmcie_add = __hwahc_op_mmcie_add; 708 wusbhc->mmcie_rm = __hwahc_op_mmcie_rm; 709 wusbhc->dev_info_set = __hwahc_op_dev_info_set; 710 wusbhc->bwa_set = __hwahc_op_bwa_set; 711 wusbhc->set_num_dnts = __hwahc_op_set_num_dnts; 712 wusbhc->set_ptk = __hwahc_op_set_ptk; 713 wusbhc->set_gtk = __hwahc_op_set_gtk; 714 result = hwahc_security_create(hwahc); 715 if (result < 0) { 716 dev_err(dev, "Can't initialize security: %d\n", result); 717 goto error_security_create; 718 } 719 wa->wusb = wusbhc; /* FIXME: ugly, need to fix */ 720 result = wusbhc_create(&hwahc->wusbhc); 721 if (result < 0) { 722 dev_err(dev, "Can't create WUSB HC structures: %d\n", result); 723 goto error_wusbhc_create; 724 } 725 result = wa_create(&hwahc->wa, iface); 726 if (result < 0) 727 goto error_wa_create; 728 return 0; 729 730error_wa_create: 731 wusbhc_destroy(&hwahc->wusbhc); 732error_wusbhc_create: 733 /* WA Descr fill allocs no resources */ 734error_security_create: 735error_fill_descriptor: 736 uwb_rc_put(wusbhc->uwb_rc); 737error_rc_get: 738 usb_put_intf(iface); 739 usb_put_dev(usb_dev); 740 return result; 741} 742 743static void hwahc_destroy(struct hwahc *hwahc) 744{ 745 struct wusbhc *wusbhc = &hwahc->wusbhc; 746 747 mutex_lock(&wusbhc->mutex); 748 __wa_destroy(&hwahc->wa); 749 wusbhc_destroy(&hwahc->wusbhc); 750 hwahc_security_release(hwahc); 751 hwahc->wusbhc.dev = NULL; 752 uwb_rc_put(wusbhc->uwb_rc); 753 usb_put_intf(hwahc->wa.usb_iface); 754 usb_put_dev(hwahc->wa.usb_dev); 755 mutex_unlock(&wusbhc->mutex); 756} 757 758static void hwahc_init(struct hwahc *hwahc) 759{ 760 wa_init(&hwahc->wa); 761} 762 763static int hwahc_probe(struct usb_interface *usb_iface, 764 const struct usb_device_id *id) 765{ 766 int result; 767 struct usb_hcd *usb_hcd; 768 struct wusbhc *wusbhc; 769 struct hwahc *hwahc; 770 struct device *dev = &usb_iface->dev; 771 772 result = -ENOMEM; 773 usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa"); 774 if (usb_hcd == NULL) { 775 dev_err(dev, "unable to allocate instance\n"); 776 goto error_alloc; 777 } 778 usb_hcd->wireless = 1; 779 wusbhc = usb_hcd_to_wusbhc(usb_hcd); 780 hwahc = container_of(wusbhc, struct hwahc, wusbhc); 781 hwahc_init(hwahc); 782 result = hwahc_create(hwahc, usb_iface); 783 if (result < 0) { 784 dev_err(dev, "Cannot initialize internals: %d\n", result); 785 goto error_hwahc_create; 786 } 787 result = usb_add_hcd(usb_hcd, 0, 0); 788 if (result < 0) { 789 dev_err(dev, "Cannot add HCD: %d\n", result); 790 goto error_add_hcd; 791 } 792 result = wusbhc_b_create(&hwahc->wusbhc); 793 if (result < 0) { 794 dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); 795 goto error_wusbhc_b_create; 796 } 797 return 0; 798 799error_wusbhc_b_create: 800 usb_remove_hcd(usb_hcd); 801error_add_hcd: 802 hwahc_destroy(hwahc); 803error_hwahc_create: 804 usb_put_hcd(usb_hcd); 805error_alloc: 806 return result; 807} 808 809static void hwahc_disconnect(struct usb_interface *usb_iface) 810{ 811 struct usb_hcd *usb_hcd; 812 struct wusbhc *wusbhc; 813 struct hwahc *hwahc; 814 815 usb_hcd = usb_get_intfdata(usb_iface); 816 wusbhc = usb_hcd_to_wusbhc(usb_hcd); 817 hwahc = container_of(wusbhc, struct hwahc, wusbhc); 818 819 wusbhc_b_destroy(&hwahc->wusbhc); 820 usb_remove_hcd(usb_hcd); 821 hwahc_destroy(hwahc); 822 usb_put_hcd(usb_hcd); 823} 824 825static struct usb_device_id hwahc_id_table[] = { 826 /* FIXME: use class labels for this */ 827 { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), }, 828 {}, 829}; 830MODULE_DEVICE_TABLE(usb, hwahc_id_table); 831 832static struct usb_driver hwahc_driver = { 833 .name = "hwa-hc", 834 .probe = hwahc_probe, 835 .disconnect = hwahc_disconnect, 836 .id_table = hwahc_id_table, 837}; 838 839module_usb_driver(hwahc_driver); 840 841MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>"); 842MODULE_DESCRIPTION("Host Wired Adapter USB Host Control Driver"); 843MODULE_LICENSE("GPL");