Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwa-rc.c
Go to the documentation of this file.
1 /*
2  * WUSB Host Wire Adapter: Radio Control Interface (WUSB[8.6])
3  * Radio Control command/event transport
4  *
5  * Copyright (C) 2005-2006 Intel Corporation
6  * Inaky Perez-Gonzalez <[email protected]>
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  * Initialize the Radio Control interface Driver.
24  *
25  * For each device probed, creates an 'struct hwarc' which contains
26  * just the representation of the UWB Radio Controller, and the logic
27  * for reading notifications and passing them to the UWB Core.
28  *
29  * So we initialize all of those, register the UWB Radio Controller
30  * and setup the notification/event handle to pipe the notifications
31  * to the UWB management Daemon.
32  *
33  * Command and event filtering.
34  *
35  * This is the driver for the Radio Control Interface described in WUSB
36  * 1.0. The core UWB module assumes that all drivers are compliant to the
37  * WHCI 0.95 specification. We thus create a filter that parses all
38  * incoming messages from the (WUSB 1.0) device and manipulate them to
39  * conform to the WHCI 0.95 specification. Similarly, outgoing messages
40  * are parsed and manipulated to conform to the WUSB 1.0 compliant messages
41  * that the device expects. Only a few messages are affected:
42  * Affected events:
43  * UWB_RC_EVT_BEACON
44  * UWB_RC_EVT_BP_SLOT_CHANGE
45  * UWB_RC_EVT_DRP_AVAIL
46  * UWB_RC_EVT_DRP
47  * Affected commands:
48  * UWB_RC_CMD_SCAN
49  * UWB_RC_CMD_SET_DRP_IE
50  *
51  *
52  *
53  */
54 #include <linux/init.h>
55 #include <linux/module.h>
56 #include <linux/slab.h>
57 #include <linux/usb.h>
58 #include <linux/usb/wusb.h>
59 #include <linux/usb/wusb-wa.h>
60 #include <linux/uwb.h>
61 
62 #include "uwb-internal.h"
63 
64 /* The device uses commands and events from the WHCI specification, although
65  * reporting itself as WUSB compliant. */
66 #define WUSB_QUIRK_WHCI_CMD_EVT 0x01
67 
81 struct hwarc {
82  struct usb_device *usb_dev;
84  struct uwb_rc *uwb_rc; /* UWB host controller */
85  struct urb *neep_urb; /* Notification endpoint handling */
86  struct edc neep_edc;
87  void *rd_buffer; /* NEEP read buffer */
88 };
89 
90 
91 /* Beacon received notification (WUSB 1.0 [8.6.3.2]) */
93  struct uwb_rceb rceb;
100 } __attribute__((packed));
116 static
117 int hwarc_filter_evt_beacon_WUSB_0100(struct uwb_rc *rc,
118  struct uwb_rceb **header,
119  const size_t buf_size,
120  size_t *new_size)
121 {
122  struct uwb_rc_evt_beacon_WUSB_0100 *be;
123  struct uwb_rc_evt_beacon *newbe;
124  size_t bytes_left, ielength;
125  struct device *dev = &rc->uwb_dev.dev;
126 
127  be = container_of(*header, struct uwb_rc_evt_beacon_WUSB_0100, rceb);
128  bytes_left = buf_size;
129  if (bytes_left < sizeof(*be)) {
130  dev_err(dev, "Beacon Received Notification: Not enough data "
131  "to decode for filtering (%zu vs %zu bytes needed)\n",
132  bytes_left, sizeof(*be));
133  return -EINVAL;
134  }
135  bytes_left -= sizeof(*be);
136  ielength = le16_to_cpu(be->wBeaconInfoLength);
137  if (bytes_left < ielength) {
138  dev_err(dev, "Beacon Received Notification: Not enough data "
139  "to decode IEs (%zu vs %zu bytes needed)\n",
140  bytes_left, ielength);
141  return -EINVAL;
142  }
143  newbe = kzalloc(sizeof(*newbe) + ielength, GFP_ATOMIC);
144  if (newbe == NULL)
145  return -ENOMEM;
146  newbe->rceb = be->rceb;
147  newbe->bChannelNumber = be->bChannelNumber;
149  newbe->wBPSTOffset = be->wBPSTOffset;
150  newbe->bLQI = be->bLQI;
151  newbe->bRSSI = be->bRSSI;
153  memcpy(newbe->BeaconInfo, be->BeaconInfo, ielength);
154  *header = &newbe->rceb;
155  *new_size = sizeof(*newbe) + ielength;
156  return 1; /* calling function will free memory */
157 }
158 
159 
160 /* DRP Availability change notification (WUSB 1.0 [8.6.3.8]) */
162  struct uwb_rceb rceb;
165 } __attribute__((packed));
166 
174 static
175 int hwarc_filter_evt_drp_avail_WUSB_0100(struct uwb_rc *rc,
176  struct uwb_rceb **header,
177  const size_t buf_size,
178  size_t *new_size)
179 {
181  struct uwb_rc_evt_drp_avail *newda;
182  struct uwb_ie_hdr *ie_hdr;
183  size_t bytes_left, ielength;
184  struct device *dev = &rc->uwb_dev.dev;
185 
186 
187  da = container_of(*header, struct uwb_rc_evt_drp_avail_WUSB_0100, rceb);
188  bytes_left = buf_size;
189  if (bytes_left < sizeof(*da)) {
190  dev_err(dev, "Not enough data to decode DRP Avail "
191  "Notification for filtering. Expected %zu, "
192  "received %zu.\n", (size_t)sizeof(*da), bytes_left);
193  return -EINVAL;
194  }
195  bytes_left -= sizeof(*da);
196  ielength = le16_to_cpu(da->wIELength);
197  if (bytes_left < ielength) {
198  dev_err(dev, "DRP Avail Notification filter: IE length "
199  "[%zu bytes] does not match actual length "
200  "[%zu bytes].\n", ielength, bytes_left);
201  return -EINVAL;
202  }
203  if (ielength < sizeof(*ie_hdr)) {
204  dev_err(dev, "DRP Avail Notification filter: Not enough "
205  "data to decode IE [%zu bytes, %zu needed]\n",
206  ielength, sizeof(*ie_hdr));
207  return -EINVAL;
208  }
209  ie_hdr = (void *) da->IEData;
210  if (ie_hdr->length > 32) {
211  dev_err(dev, "DRP Availability Change event has unexpected "
212  "length for filtering. Expected < 32 bytes, "
213  "got %zu bytes.\n", (size_t)ie_hdr->length);
214  return -EINVAL;
215  }
216  newda = kzalloc(sizeof(*newda), GFP_ATOMIC);
217  if (newda == NULL)
218  return -ENOMEM;
219  newda->rceb = da->rceb;
220  memcpy(newda->bmp, (u8 *) ie_hdr + sizeof(*ie_hdr), ie_hdr->length);
221  *header = &newda->rceb;
222  *new_size = sizeof(*newda);
223  return 1; /* calling function will free memory */
224 }
225 
226 
227 /* DRP notification (WUSB 1.0 [8.6.3.9]) */
229  struct uwb_rceb rceb;
234 } __attribute__((packed));
235 
249 static
250 int hwarc_filter_evt_drp_WUSB_0100(struct uwb_rc *rc,
251  struct uwb_rceb **header,
252  const size_t buf_size,
253  size_t *new_size)
254 {
255  struct uwb_rc_evt_drp_WUSB_0100 *drpev;
256  struct uwb_rc_evt_drp *newdrpev;
257  size_t bytes_left, ielength;
258  struct device *dev = &rc->uwb_dev.dev;
259 
260  drpev = container_of(*header, struct uwb_rc_evt_drp_WUSB_0100, rceb);
261  bytes_left = buf_size;
262  if (bytes_left < sizeof(*drpev)) {
263  dev_err(dev, "Not enough data to decode DRP Notification "
264  "for filtering. Expected %zu, received %zu.\n",
265  (size_t)sizeof(*drpev), bytes_left);
266  return -EINVAL;
267  }
268  ielength = le16_to_cpu(drpev->wIELength);
269  bytes_left -= sizeof(*drpev);
270  if (bytes_left < ielength) {
271  dev_err(dev, "DRP Notification filter: header length [%zu "
272  "bytes] does not match actual length [%zu "
273  "bytes].\n", ielength, bytes_left);
274  return -EINVAL;
275  }
276  newdrpev = kzalloc(sizeof(*newdrpev) + ielength, GFP_ATOMIC);
277  if (newdrpev == NULL)
278  return -ENOMEM;
279  newdrpev->rceb = drpev->rceb;
280  newdrpev->src_addr = drpev->wSrcAddr;
281  newdrpev->reason = UWB_DRP_NOTIF_DRP_IE_RCVD;
282  newdrpev->beacon_slot_number = 0;
283  newdrpev->ie_length = drpev->wIELength;
284  memcpy(newdrpev->ie_data, drpev->IEData, ielength);
285  *header = &newdrpev->rceb;
286  *new_size = sizeof(*newdrpev) + ielength;
287  return 1; /* calling function will free memory */
288 }
289 
290 
291 /* Scan Command (WUSB 1.0 [8.6.2.5]) */
293  struct uwb_rccb rccb;
296 } __attribute__((packed));
308 static
309 int hwarc_filter_cmd_scan_WUSB_0100(struct uwb_rc *rc,
310  struct uwb_rccb **header,
311  size_t *size)
312 {
313  struct uwb_rc_cmd_scan *sc;
314 
315  sc = container_of(*header, struct uwb_rc_cmd_scan, rccb);
316 
319  /* Don't send the last two bytes. */
320  *size -= 2;
321  return 0;
322 }
323 
324 
325 /* SET DRP IE command (WUSB 1.0 [8.6.2.7]) */
327  struct uwb_rccb rccb;
330  struct uwb_ie_drp IEData[];
331 } __attribute__((packed));
332 
346 static
347 int hwarc_filter_cmd_set_drp_ie_WUSB_0100(struct uwb_rc *rc,
348  struct uwb_rccb **header,
349  size_t *size)
350 {
351  struct uwb_rc_cmd_set_drp_ie *orgcmd;
353  size_t ielength;
354 
355  orgcmd = container_of(*header, struct uwb_rc_cmd_set_drp_ie, rccb);
356  ielength = le16_to_cpu(orgcmd->wIELength);
357  cmd = kzalloc(sizeof(*cmd) + ielength, GFP_KERNEL);
358  if (cmd == NULL)
359  return -ENOMEM;
360  cmd->rccb = orgcmd->rccb;
361  cmd->bExplicit = 0;
362  cmd->wIELength = orgcmd->wIELength;
363  memcpy(cmd->IEData, orgcmd->IEData, ielength);
364  *header = &cmd->rccb;
365  *size = sizeof(*cmd) + ielength;
366  return 1; /* calling function will free memory */
367 }
368 
369 
391 static
392 int hwarc_filter_cmd_WUSB_0100(struct uwb_rc *rc, struct uwb_rccb **header,
393  size_t *size)
394 {
395  int result;
396  struct uwb_rccb *rccb = *header;
397  int cmd = le16_to_cpu(rccb->wCommand);
398  switch (cmd) {
399  case UWB_RC_CMD_SCAN:
400  result = hwarc_filter_cmd_scan_WUSB_0100(rc, header, size);
401  break;
403  result = hwarc_filter_cmd_set_drp_ie_WUSB_0100(rc, header, size);
404  break;
405  default:
406  result = -ENOANO;
407  break;
408  }
409  return result;
410 }
411 
412 
423 static
424 int hwarc_filter_cmd(struct uwb_rc *rc, struct uwb_rccb **header,
425  size_t *size)
426 {
427  int result = -ENOANO;
428  if (rc->version == 0x0100)
429  result = hwarc_filter_cmd_WUSB_0100(rc, header, size);
430  return result;
431 }
432 
433 
444 static
445 ssize_t hwarc_get_event_size(struct uwb_rc *rc, const struct uwb_rceb *rceb,
446  size_t core_size, size_t offset,
447  const size_t buf_size)
448 {
449  ssize_t size = -ENOSPC;
450  const void *ptr = rceb;
451  size_t type_size = sizeof(__le16);
452  struct device *dev = &rc->uwb_dev.dev;
453 
454  if (offset + type_size >= buf_size) {
455  dev_err(dev, "Not enough data to read extra size of event "
456  "0x%02x/%04x/%02x, only got %zu bytes.\n",
457  rceb->bEventType, le16_to_cpu(rceb->wEvent),
458  rceb->bEventContext, buf_size);
459  goto out;
460  }
461  ptr += offset;
462  size = core_size + le16_to_cpu(*(__le16 *)ptr);
463 out:
464  return size;
465 }
466 
467 
468 /* Beacon slot change notification (WUSB 1.0 [8.6.3.5]) */
470  struct uwb_rceb rceb;
472 } __attribute__((packed));
473 
497 static
498 int hwarc_filter_event_WUSB_0100(struct uwb_rc *rc, struct uwb_rceb **header,
499  const size_t buf_size, size_t *_real_size,
500  size_t *_new_size)
501 {
502  int result = -ENOANO;
503  struct uwb_rceb *rceb = *header;
504  int event = le16_to_cpu(rceb->wEvent);
505  ssize_t event_size;
506  size_t core_size, offset;
507 
508  if (rceb->bEventType != UWB_RC_CET_GENERAL)
509  goto out;
510  switch (event) {
511  case UWB_RC_EVT_BEACON:
512  core_size = sizeof(struct uwb_rc_evt_beacon_WUSB_0100);
513  offset = offsetof(struct uwb_rc_evt_beacon_WUSB_0100,
515  event_size = hwarc_get_event_size(rc, rceb, core_size,
516  offset, buf_size);
517  if (event_size < 0)
518  goto out;
519  *_real_size = event_size;
520  result = hwarc_filter_evt_beacon_WUSB_0100(rc, header,
521  buf_size, _new_size);
522  break;
524  *_new_size = *_real_size =
526  result = 0;
527  break;
528 
530  core_size = sizeof(struct uwb_rc_evt_drp_avail_WUSB_0100);
532  wIELength);
533  event_size = hwarc_get_event_size(rc, rceb, core_size,
534  offset, buf_size);
535  if (event_size < 0)
536  goto out;
537  *_real_size = event_size;
538  result = hwarc_filter_evt_drp_avail_WUSB_0100(
539  rc, header, buf_size, _new_size);
540  break;
541 
542  case UWB_RC_EVT_DRP:
543  core_size = sizeof(struct uwb_rc_evt_drp_WUSB_0100);
544  offset = offsetof(struct uwb_rc_evt_drp_WUSB_0100, wIELength);
545  event_size = hwarc_get_event_size(rc, rceb, core_size,
546  offset, buf_size);
547  if (event_size < 0)
548  goto out;
549  *_real_size = event_size;
550  result = hwarc_filter_evt_drp_WUSB_0100(rc, header,
551  buf_size, _new_size);
552  break;
553 
554  default:
555  break;
556  }
557 out:
558  return result;
559 }
560 
577 static
578 int hwarc_filter_event(struct uwb_rc *rc, struct uwb_rceb **header,
579  const size_t buf_size, size_t *_real_size,
580  size_t *_new_size)
581 {
582  int result = -ENOANO;
583  if (rc->version == 0x0100)
584  result = hwarc_filter_event_WUSB_0100(
585  rc, header, buf_size, _real_size, _new_size);
586  return result;
587 }
588 
589 
599 static
600 int hwarc_cmd(struct uwb_rc *uwb_rc, const struct uwb_rccb *cmd, size_t cmd_size)
601 {
602  struct hwarc *hwarc = uwb_rc->priv;
603  return usb_control_msg(
604  hwarc->usb_dev, usb_sndctrlpipe(hwarc->usb_dev, 0),
606  0, hwarc->usb_iface->cur_altsetting->desc.bInterfaceNumber,
607  (void *) cmd, cmd_size, 100 /* FIXME: this is totally arbitrary */);
608 }
609 
610 static
611 int hwarc_reset(struct uwb_rc *uwb_rc)
612 {
613  struct hwarc *hwarc = uwb_rc->priv;
614  return usb_reset_device(hwarc->usb_dev);
615 }
616 
623 static
624 void hwarc_neep_cb(struct urb *urb)
625 {
626  struct hwarc *hwarc = urb->context;
627  struct usb_interface *usb_iface = hwarc->usb_iface;
628  struct device *dev = &usb_iface->dev;
629  int result;
630 
631  switch (result = urb->status) {
632  case 0:
633  uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer,
634  urb->actual_length);
635  break;
636  case -ECONNRESET: /* Not an error, but a controlled situation; */
637  case -ENOENT: /* (we killed the URB)...so, no broadcast */
638  goto out;
639  case -ESHUTDOWN: /* going away! */
640  goto out;
641  default: /* On general errors, retry unless it gets ugly */
642  if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS,
644  goto error_exceeded;
645  dev_err(dev, "NEEP: URB error %d\n", urb->status);
646  }
647  result = usb_submit_urb(urb, GFP_ATOMIC);
648  if (result < 0 && result != -ENODEV && result != -EPERM) {
649  /* ignoring unrecoverable errors */
650  dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
651  result);
652  goto error;
653  }
654 out:
655  return;
656 
657 error_exceeded:
658  dev_err(dev, "NEEP: URB max acceptable errors "
659  "exceeded, resetting device\n");
660 error:
661  uwb_rc_neh_error(hwarc->uwb_rc, result);
662  uwb_rc_reset_all(hwarc->uwb_rc);
663  return;
664 }
665 
666 static void hwarc_init(struct hwarc *hwarc)
667 {
668  edc_init(&hwarc->neep_edc);
669 }
670 
679 static int hwarc_neep_init(struct uwb_rc *rc)
680 {
681  struct hwarc *hwarc = rc->priv;
682  struct usb_interface *iface = hwarc->usb_iface;
683  struct usb_device *usb_dev = interface_to_usbdev(iface);
684  struct device *dev = &iface->dev;
685  int result;
686  struct usb_endpoint_descriptor *epd;
687 
688  epd = &iface->cur_altsetting->endpoint[0].desc;
689  hwarc->rd_buffer = (void *) __get_free_page(GFP_KERNEL);
690  if (hwarc->rd_buffer == NULL) {
691  dev_err(dev, "Unable to allocate notification's read buffer\n");
692  goto error_rd_buffer;
693  }
694  hwarc->neep_urb = usb_alloc_urb(0, GFP_KERNEL);
695  if (hwarc->neep_urb == NULL) {
696  dev_err(dev, "Unable to allocate notification URB\n");
697  goto error_urb_alloc;
698  }
699  usb_fill_int_urb(hwarc->neep_urb, usb_dev,
700  usb_rcvintpipe(usb_dev, epd->bEndpointAddress),
701  hwarc->rd_buffer, PAGE_SIZE,
702  hwarc_neep_cb, hwarc, epd->bInterval);
703  result = usb_submit_urb(hwarc->neep_urb, GFP_ATOMIC);
704  if (result < 0) {
705  dev_err(dev, "Cannot submit notification URB: %d\n", result);
706  goto error_neep_submit;
707  }
708  return 0;
709 
710 error_neep_submit:
711  usb_free_urb(hwarc->neep_urb);
712 error_urb_alloc:
713  free_page((unsigned long)hwarc->rd_buffer);
714 error_rd_buffer:
715  return -ENOMEM;
716 }
717 
718 
720 static void hwarc_neep_release(struct uwb_rc *rc)
721 {
722  struct hwarc *hwarc = rc->priv;
723 
724  usb_kill_urb(hwarc->neep_urb);
725  usb_free_urb(hwarc->neep_urb);
726  free_page((unsigned long)hwarc->rd_buffer);
727 }
728 
738 static int hwarc_get_version(struct uwb_rc *rc)
739 {
740  int result;
741 
742  struct hwarc *hwarc = rc->priv;
744  struct device *dev = &rc->uwb_dev.dev;
745  struct usb_device *usb_dev = hwarc->usb_dev;
746  char *itr;
747  struct usb_descriptor_header *hdr;
748  size_t itr_size, actconfig_idx;
749  u16 version;
750 
751  actconfig_idx = (usb_dev->actconfig - usb_dev->config) /
752  sizeof(usb_dev->config[0]);
753  itr = usb_dev->rawdescriptors[actconfig_idx];
754  itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength);
755  while (itr_size >= sizeof(*hdr)) {
756  hdr = (struct usb_descriptor_header *) itr;
757  dev_dbg(dev, "Extra device descriptor: "
758  "type %02x/%u bytes @ %zu (%zu left)\n",
759  hdr->bDescriptorType, hdr->bLength,
760  (itr - usb_dev->rawdescriptors[actconfig_idx]),
761  itr_size);
763  goto found;
764  itr += hdr->bLength;
765  itr_size -= hdr->bLength;
766  }
767  dev_err(dev, "cannot find Radio Control Interface Class descriptor\n");
768  return -ENODEV;
769 
770 found:
771  result = -EINVAL;
772  if (hdr->bLength > itr_size) { /* is it available? */
773  dev_err(dev, "incomplete Radio Control Interface Class "
774  "descriptor (%zu bytes left, %u needed)\n",
775  itr_size, hdr->bLength);
776  goto error;
777  }
778  if (hdr->bLength < sizeof(*descr)) {
779  dev_err(dev, "short Radio Control Interface Class "
780  "descriptor\n");
781  goto error;
782  }
783  descr = (struct uwb_rc_control_intf_class_desc *) hdr;
784  /* Make LE fields CPU order */
785  version = __le16_to_cpu(descr->bcdRCIVersion);
786  if (version != 0x0100) {
787  dev_err(dev, "Device reports protocol version 0x%04x. We "
788  "do not support that. \n", version);
789  result = -EINVAL;
790  goto error;
791  }
792  rc->version = version;
793  dev_dbg(dev, "Device supports WUSB protocol version 0x%04x \n", rc->version);
794  result = 0;
795 error:
796  return result;
797 }
798 
799 /*
800  * By creating a 'uwb_rc', we have a reference on it -- that reference
801  * is the one we drop when we disconnect.
802  *
803  * No need to switch altsettings; according to WUSB1.0[8.6.1.1], there
804  * is only one altsetting allowed.
805  */
806 static int hwarc_probe(struct usb_interface *iface,
807  const struct usb_device_id *id)
808 {
809  int result;
810  struct uwb_rc *uwb_rc;
811  struct hwarc *hwarc;
812  struct device *dev = &iface->dev;
813 
814  result = -ENOMEM;
815  uwb_rc = uwb_rc_alloc();
816  if (uwb_rc == NULL) {
817  dev_err(dev, "unable to allocate RC instance\n");
818  goto error_rc_alloc;
819  }
820  hwarc = kzalloc(sizeof(*hwarc), GFP_KERNEL);
821  if (hwarc == NULL) {
822  dev_err(dev, "unable to allocate HWA RC instance\n");
823  goto error_alloc;
824  }
825  hwarc_init(hwarc);
826  hwarc->usb_dev = usb_get_dev(interface_to_usbdev(iface));
827  hwarc->usb_iface = usb_get_intf(iface);
828  hwarc->uwb_rc = uwb_rc;
829 
830  uwb_rc->owner = THIS_MODULE;
831  uwb_rc->start = hwarc_neep_init;
832  uwb_rc->stop = hwarc_neep_release;
833  uwb_rc->cmd = hwarc_cmd;
834  uwb_rc->reset = hwarc_reset;
835  if (id->driver_info & WUSB_QUIRK_WHCI_CMD_EVT) {
836  uwb_rc->filter_cmd = NULL;
837  uwb_rc->filter_event = NULL;
838  } else {
839  uwb_rc->filter_cmd = hwarc_filter_cmd;
840  uwb_rc->filter_event = hwarc_filter_event;
841  }
842 
843  result = uwb_rc_add(uwb_rc, dev, hwarc);
844  if (result < 0)
845  goto error_rc_add;
846  result = hwarc_get_version(uwb_rc);
847  if (result < 0) {
848  dev_err(dev, "cannot retrieve version of RC \n");
849  goto error_get_version;
850  }
851  usb_set_intfdata(iface, hwarc);
852  return 0;
853 
854 error_get_version:
855  uwb_rc_rm(uwb_rc);
856 error_rc_add:
857  usb_put_intf(iface);
858  usb_put_dev(hwarc->usb_dev);
859 error_alloc:
860  uwb_rc_put(uwb_rc);
861 error_rc_alloc:
862  return result;
863 }
864 
865 static void hwarc_disconnect(struct usb_interface *iface)
866 {
867  struct hwarc *hwarc = usb_get_intfdata(iface);
868  struct uwb_rc *uwb_rc = hwarc->uwb_rc;
869 
870  usb_set_intfdata(hwarc->usb_iface, NULL);
871  uwb_rc_rm(uwb_rc);
872  usb_put_intf(hwarc->usb_iface);
873  usb_put_dev(hwarc->usb_dev);
874  kfree(hwarc);
875  uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */
876 }
877 
878 static int hwarc_pre_reset(struct usb_interface *iface)
879 {
880  struct hwarc *hwarc = usb_get_intfdata(iface);
881  struct uwb_rc *uwb_rc = hwarc->uwb_rc;
882 
883  uwb_rc_pre_reset(uwb_rc);
884  return 0;
885 }
886 
887 static int hwarc_post_reset(struct usb_interface *iface)
888 {
889  struct hwarc *hwarc = usb_get_intfdata(iface);
890  struct uwb_rc *uwb_rc = hwarc->uwb_rc;
891 
892  return uwb_rc_post_reset(uwb_rc);
893 }
894 
896 static const struct usb_device_id hwarc_id_table[] = {
897  /* D-Link DUB-1210 */
898  { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3d02, 0xe0, 0x01, 0x02),
899  .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
900  /* Intel i1480 (using firmware 1.3PA2-20070828) */
901  { USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02),
902  .driver_info = WUSB_QUIRK_WHCI_CMD_EVT },
903  /* Generic match for the Radio Control interface */
904  { USB_INTERFACE_INFO(0xe0, 0x01, 0x02), },
905  { },
906 };
907 MODULE_DEVICE_TABLE(usb, hwarc_id_table);
908 
909 static struct usb_driver hwarc_driver = {
910  .name = "hwa-rc",
911  .id_table = hwarc_id_table,
912  .probe = hwarc_probe,
913  .disconnect = hwarc_disconnect,
914  .pre_reset = hwarc_pre_reset,
915  .post_reset = hwarc_post_reset,
916 };
917 
918 module_usb_driver(hwarc_driver);
919 
920 MODULE_AUTHOR("Inaky Perez-Gonzalez <[email protected]>");
921 MODULE_DESCRIPTION("Host Wireless Adapter Radio Control Driver");
922 MODULE_LICENSE("GPL");