Commit | Line | Data |
---|---|---|
de520b8b IPG |
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 <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 | * 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 | */ | |
de520b8b IPG |
54 | #include <linux/init.h> |
55 | #include <linux/module.h> | |
56 | #include <linux/usb.h> | |
57 | #include <linux/usb/wusb.h> | |
58 | #include <linux/usb/wusb-wa.h> | |
59 | #include <linux/uwb.h> | |
bce83697 | 60 | |
de520b8b | 61 | #include "uwb-internal.h" |
de520b8b | 62 | |
e477a498 AL |
63 | /* The device uses commands and events from the WHCI specification, although |
64 | * reporting itself as WUSB compliant. */ | |
65 | #define WUSB_QUIRK_WHCI_CMD_EVT 0x01 | |
de520b8b IPG |
66 | |
67 | /** | |
68 | * Descriptor for an instance of the UWB Radio Control Driver that | |
69 | * attaches to the RCI interface of the Host Wired Adapter. | |
70 | * | |
71 | * Unless there is a lock specific to the 'data members', all access | |
72 | * is protected by uwb_rc->mutex. | |
73 | * | |
74 | * The NEEP (Notification/Event EndPoint) URB (@neep_urb) writes to | |
75 | * @rd_buffer. Note there is no locking because it is perfectly (heh!) | |
76 | * serialized--probe() submits an URB, callback is called, processes | |
77 | * the data (synchronously), submits another URB, and so on. There is | |
78 | * no concurrent access to the buffer. | |
79 | */ | |
80 | struct hwarc { | |
81 | struct usb_device *usb_dev; | |
82 | struct usb_interface *usb_iface; | |
83 | struct uwb_rc *uwb_rc; /* UWB host controller */ | |
84 | struct urb *neep_urb; /* Notification endpoint handling */ | |
85 | struct edc neep_edc; | |
86 | void *rd_buffer; /* NEEP read buffer */ | |
87 | }; | |
88 | ||
89 | ||
90 | /* Beacon received notification (WUSB 1.0 [8.6.3.2]) */ | |
91 | struct uwb_rc_evt_beacon_WUSB_0100 { | |
92 | struct uwb_rceb rceb; | |
93 | u8 bChannelNumber; | |
94 | __le16 wBPSTOffset; | |
95 | u8 bLQI; | |
96 | u8 bRSSI; | |
97 | __le16 wBeaconInfoLength; | |
98 | u8 BeaconInfo[]; | |
99 | } __attribute__((packed)); | |
100 | ||
101 | /** | |
102 | * Filter WUSB 1.0 BEACON RCV notification to be WHCI 0.95 | |
103 | * | |
104 | * @header: the incoming event | |
105 | * @buf_size: size of buffer containing incoming event | |
106 | * @new_size: size of event after filtering completed | |
107 | * | |
108 | * The WHCI 0.95 spec has a "Beacon Type" field. This value is unknown at | |
109 | * the time we receive the beacon from WUSB so we just set it to | |
110 | * UWB_RC_BEACON_TYPE_NEIGHBOR as a default. | |
111 | * The solution below allocates memory upon receipt of every beacon from a | |
112 | * WUSB device. This will deteriorate performance. What is the right way to | |
113 | * do this? | |
114 | */ | |
115 | static | |
116 | int hwarc_filter_evt_beacon_WUSB_0100(struct uwb_rc *rc, | |
117 | struct uwb_rceb **header, | |
118 | const size_t buf_size, | |
119 | size_t *new_size) | |
120 | { | |
121 | struct uwb_rc_evt_beacon_WUSB_0100 *be; | |
122 | struct uwb_rc_evt_beacon *newbe; | |
123 | size_t bytes_left, ielength; | |
124 | struct device *dev = &rc->uwb_dev.dev; | |
125 | ||
126 | be = container_of(*header, struct uwb_rc_evt_beacon_WUSB_0100, rceb); | |
127 | bytes_left = buf_size; | |
128 | if (bytes_left < sizeof(*be)) { | |
129 | dev_err(dev, "Beacon Received Notification: Not enough data " | |
130 | "to decode for filtering (%zu vs %zu bytes needed)\n", | |
131 | bytes_left, sizeof(*be)); | |
132 | return -EINVAL; | |
133 | } | |
134 | bytes_left -= sizeof(*be); | |
135 | ielength = le16_to_cpu(be->wBeaconInfoLength); | |
136 | if (bytes_left < ielength) { | |
137 | dev_err(dev, "Beacon Received Notification: Not enough data " | |
138 | "to decode IEs (%zu vs %zu bytes needed)\n", | |
139 | bytes_left, ielength); | |
140 | return -EINVAL; | |
141 | } | |
142 | newbe = kzalloc(sizeof(*newbe) + ielength, GFP_ATOMIC); | |
143 | if (newbe == NULL) | |
144 | return -ENOMEM; | |
145 | newbe->rceb = be->rceb; | |
146 | newbe->bChannelNumber = be->bChannelNumber; | |
147 | newbe->bBeaconType = UWB_RC_BEACON_TYPE_NEIGHBOR; | |
148 | newbe->wBPSTOffset = be->wBPSTOffset; | |
149 | newbe->bLQI = be->bLQI; | |
150 | newbe->bRSSI = be->bRSSI; | |
151 | newbe->wBeaconInfoLength = be->wBeaconInfoLength; | |
152 | memcpy(newbe->BeaconInfo, be->BeaconInfo, ielength); | |
153 | *header = &newbe->rceb; | |
154 | *new_size = sizeof(*newbe) + ielength; | |
155 | return 1; /* calling function will free memory */ | |
156 | } | |
157 | ||
158 | ||
159 | /* DRP Availability change notification (WUSB 1.0 [8.6.3.8]) */ | |
160 | struct uwb_rc_evt_drp_avail_WUSB_0100 { | |
161 | struct uwb_rceb rceb; | |
162 | __le16 wIELength; | |
163 | u8 IEData[]; | |
164 | } __attribute__((packed)); | |
165 | ||
166 | /** | |
167 | * Filter WUSB 1.0 DRP AVAILABILITY CHANGE notification to be WHCI 0.95 | |
168 | * | |
169 | * @header: the incoming event | |
170 | * @buf_size: size of buffer containing incoming event | |
171 | * @new_size: size of event after filtering completed | |
172 | */ | |
173 | static | |
174 | int hwarc_filter_evt_drp_avail_WUSB_0100(struct uwb_rc *rc, | |
175 | struct uwb_rceb **header, | |
176 | const size_t buf_size, | |
177 | size_t *new_size) | |
178 | { | |
179 | struct uwb_rc_evt_drp_avail_WUSB_0100 *da; | |
180 | struct uwb_rc_evt_drp_avail *newda; | |
181 | struct uwb_ie_hdr *ie_hdr; | |
182 | size_t bytes_left, ielength; | |
183 | struct device *dev = &rc->uwb_dev.dev; | |
184 | ||
185 | ||
186 | da = container_of(*header, struct uwb_rc_evt_drp_avail_WUSB_0100, rceb); | |
187 | bytes_left = buf_size; | |
188 | if (bytes_left < sizeof(*da)) { | |
189 | dev_err(dev, "Not enough data to decode DRP Avail " | |
190 | "Notification for filtering. Expected %zu, " | |
191 | "received %zu.\n", (size_t)sizeof(*da), bytes_left); | |
192 | return -EINVAL; | |
193 | } | |
194 | bytes_left -= sizeof(*da); | |
195 | ielength = le16_to_cpu(da->wIELength); | |
196 | if (bytes_left < ielength) { | |
197 | dev_err(dev, "DRP Avail Notification filter: IE length " | |
198 | "[%zu bytes] does not match actual length " | |
199 | "[%zu bytes].\n", ielength, bytes_left); | |
200 | return -EINVAL; | |
201 | } | |
202 | if (ielength < sizeof(*ie_hdr)) { | |
203 | dev_err(dev, "DRP Avail Notification filter: Not enough " | |
204 | "data to decode IE [%zu bytes, %zu needed]\n", | |
205 | ielength, sizeof(*ie_hdr)); | |
206 | return -EINVAL; | |
207 | } | |
208 | ie_hdr = (void *) da->IEData; | |
209 | if (ie_hdr->length > 32) { | |
210 | dev_err(dev, "DRP Availability Change event has unexpected " | |
211 | "length for filtering. Expected < 32 bytes, " | |
212 | "got %zu bytes.\n", (size_t)ie_hdr->length); | |
213 | return -EINVAL; | |
214 | } | |
215 | newda = kzalloc(sizeof(*newda), GFP_ATOMIC); | |
216 | if (newda == NULL) | |
217 | return -ENOMEM; | |
218 | newda->rceb = da->rceb; | |
219 | memcpy(newda->bmp, (u8 *) ie_hdr + sizeof(*ie_hdr), ie_hdr->length); | |
220 | *header = &newda->rceb; | |
221 | *new_size = sizeof(*newda); | |
222 | return 1; /* calling function will free memory */ | |
223 | } | |
224 | ||
225 | ||
226 | /* DRP notification (WUSB 1.0 [8.6.3.9]) */ | |
227 | struct uwb_rc_evt_drp_WUSB_0100 { | |
228 | struct uwb_rceb rceb; | |
229 | struct uwb_dev_addr wSrcAddr; | |
230 | u8 bExplicit; | |
231 | __le16 wIELength; | |
232 | u8 IEData[]; | |
233 | } __attribute__((packed)); | |
234 | ||
235 | /** | |
236 | * Filter WUSB 1.0 DRP Notification to be WHCI 0.95 | |
237 | * | |
238 | * @header: the incoming event | |
239 | * @buf_size: size of buffer containing incoming event | |
240 | * @new_size: size of event after filtering completed | |
241 | * | |
242 | * It is hard to manage DRP reservations without having a Reason code. | |
243 | * Unfortunately there is none in the WUSB spec. We just set the default to | |
244 | * DRP IE RECEIVED. | |
245 | * We do not currently use the bBeaconSlotNumber value, so we set this to | |
246 | * zero for now. | |
247 | */ | |
248 | static | |
249 | int hwarc_filter_evt_drp_WUSB_0100(struct uwb_rc *rc, | |
250 | struct uwb_rceb **header, | |
251 | const size_t buf_size, | |
252 | size_t *new_size) | |
253 | { | |
254 | struct uwb_rc_evt_drp_WUSB_0100 *drpev; | |
255 | struct uwb_rc_evt_drp *newdrpev; | |
256 | size_t bytes_left, ielength; | |
257 | struct device *dev = &rc->uwb_dev.dev; | |
258 | ||
259 | drpev = container_of(*header, struct uwb_rc_evt_drp_WUSB_0100, rceb); | |
260 | bytes_left = buf_size; | |
261 | if (bytes_left < sizeof(*drpev)) { | |
262 | dev_err(dev, "Not enough data to decode DRP Notification " | |
263 | "for filtering. Expected %zu, received %zu.\n", | |
264 | (size_t)sizeof(*drpev), bytes_left); | |
265 | return -EINVAL; | |
266 | } | |
267 | ielength = le16_to_cpu(drpev->wIELength); | |
268 | bytes_left -= sizeof(*drpev); | |
269 | if (bytes_left < ielength) { | |
270 | dev_err(dev, "DRP Notification filter: header length [%zu " | |
271 | "bytes] does not match actual length [%zu " | |
272 | "bytes].\n", ielength, bytes_left); | |
273 | return -EINVAL; | |
274 | } | |
275 | newdrpev = kzalloc(sizeof(*newdrpev) + ielength, GFP_ATOMIC); | |
276 | if (newdrpev == NULL) | |
277 | return -ENOMEM; | |
278 | newdrpev->rceb = drpev->rceb; | |
279 | newdrpev->src_addr = drpev->wSrcAddr; | |
280 | newdrpev->reason = UWB_DRP_NOTIF_DRP_IE_RCVD; | |
281 | newdrpev->beacon_slot_number = 0; | |
282 | newdrpev->ie_length = drpev->wIELength; | |
283 | memcpy(newdrpev->ie_data, drpev->IEData, ielength); | |
284 | *header = &newdrpev->rceb; | |
285 | *new_size = sizeof(*newdrpev) + ielength; | |
286 | return 1; /* calling function will free memory */ | |
287 | } | |
288 | ||
289 | ||
290 | /* Scan Command (WUSB 1.0 [8.6.2.5]) */ | |
291 | struct uwb_rc_cmd_scan_WUSB_0100 { | |
292 | struct uwb_rccb rccb; | |
293 | u8 bChannelNumber; | |
294 | u8 bScanState; | |
295 | } __attribute__((packed)); | |
296 | ||
297 | /** | |
298 | * Filter WHCI 0.95 SCAN command to be WUSB 1.0 SCAN command | |
299 | * | |
300 | * @header: command sent to device (compliant to WHCI 0.95) | |
301 | * @size: size of command sent to device | |
302 | * | |
303 | * We only reduce the size by two bytes because the WUSB 1.0 scan command | |
304 | * does not have the last field (wStarttime). Also, make sure we don't send | |
305 | * the device an unexpected scan type. | |
306 | */ | |
307 | static | |
308 | int hwarc_filter_cmd_scan_WUSB_0100(struct uwb_rc *rc, | |
309 | struct uwb_rccb **header, | |
310 | size_t *size) | |
311 | { | |
312 | struct uwb_rc_cmd_scan *sc; | |
313 | ||
314 | sc = container_of(*header, struct uwb_rc_cmd_scan, rccb); | |
315 | ||
316 | if (sc->bScanState == UWB_SCAN_ONLY_STARTTIME) | |
317 | sc->bScanState = UWB_SCAN_ONLY; | |
318 | /* Don't send the last two bytes. */ | |
319 | *size -= 2; | |
320 | return 0; | |
321 | } | |
322 | ||
323 | ||
324 | /* SET DRP IE command (WUSB 1.0 [8.6.2.7]) */ | |
325 | struct uwb_rc_cmd_set_drp_ie_WUSB_0100 { | |
326 | struct uwb_rccb rccb; | |
327 | u8 bExplicit; | |
328 | __le16 wIELength; | |
329 | struct uwb_ie_drp IEData[]; | |
330 | } __attribute__((packed)); | |
331 | ||
332 | /** | |
333 | * Filter WHCI 0.95 SET DRP IE command to be WUSB 1.0 SET DRP IE command | |
334 | * | |
335 | * @header: command sent to device (compliant to WHCI 0.95) | |
336 | * @size: size of command sent to device | |
337 | * | |
338 | * WUSB has an extra bExplicit field - we assume always explicit | |
339 | * negotiation so this field is set. The command expected by the device is | |
340 | * thus larger than the one prepared by the driver so we need to | |
341 | * reallocate memory to accommodate this. | |
342 | * We trust the driver to send us the correct data so no checking is done | |
343 | * on incoming data - evn though it is variable length. | |
344 | */ | |
345 | static | |
346 | int hwarc_filter_cmd_set_drp_ie_WUSB_0100(struct uwb_rc *rc, | |
347 | struct uwb_rccb **header, | |
348 | size_t *size) | |
349 | { | |
350 | struct uwb_rc_cmd_set_drp_ie *orgcmd; | |
351 | struct uwb_rc_cmd_set_drp_ie_WUSB_0100 *cmd; | |
352 | size_t ielength; | |
353 | ||
354 | orgcmd = container_of(*header, struct uwb_rc_cmd_set_drp_ie, rccb); | |
355 | ielength = le16_to_cpu(orgcmd->wIELength); | |
356 | cmd = kzalloc(sizeof(*cmd) + ielength, GFP_KERNEL); | |
357 | if (cmd == NULL) | |
358 | return -ENOMEM; | |
359 | cmd->rccb = orgcmd->rccb; | |
360 | cmd->bExplicit = 0; | |
361 | cmd->wIELength = orgcmd->wIELength; | |
362 | memcpy(cmd->IEData, orgcmd->IEData, ielength); | |
363 | *header = &cmd->rccb; | |
364 | *size = sizeof(*cmd) + ielength; | |
365 | return 1; /* calling function will free memory */ | |
366 | } | |
367 | ||
368 | ||
369 | /** | |
370 | * Filter data from WHCI driver to WUSB device | |
371 | * | |
372 | * @header: WHCI 0.95 compliant command from driver | |
373 | * @size: length of command | |
374 | * | |
375 | * The routine managing commands to the device (uwb_rc_cmd()) will call the | |
376 | * filtering function pointer (if it exists) before it passes any data to | |
377 | * the device. At this time the command has been formatted according to | |
378 | * WHCI 0.95 and is ready to be sent to the device. | |
379 | * | |
380 | * The filter function will be provided with the current command and its | |
381 | * length. The function will manipulate the command if necessary and | |
382 | * potentially reallocate memory for a command that needed more memory that | |
383 | * the given command. If new memory was created the function will return 1 | |
384 | * to indicate to the calling function that the memory need to be freed | |
385 | * when not needed any more. The size will contain the new length of the | |
386 | * command. | |
387 | * If memory has not been allocated we rely on the original mechanisms to | |
388 | * free the memory of the command - even when we reduce the value of size. | |
389 | */ | |
390 | static | |
391 | int hwarc_filter_cmd_WUSB_0100(struct uwb_rc *rc, struct uwb_rccb **header, | |
392 | size_t *size) | |
393 | { | |
394 | int result; | |
395 | struct uwb_rccb *rccb = *header; | |
396 | int cmd = le16_to_cpu(rccb->wCommand); | |
397 | switch (cmd) { | |
398 | case UWB_RC_CMD_SCAN: | |
399 | result = hwarc_filter_cmd_scan_WUSB_0100(rc, header, size); | |
400 | break; | |
401 | case UWB_RC_CMD_SET_DRP_IE: | |
402 | result = hwarc_filter_cmd_set_drp_ie_WUSB_0100(rc, header, size); | |
403 | break; | |
404 | default: | |
405 | result = -ENOANO; | |
406 | break; | |
407 | } | |
408 | return result; | |
409 | } | |
410 | ||
411 | ||
412 | /** | |
413 | * Filter data from WHCI driver to WUSB device | |
414 | * | |
415 | * @header: WHCI 0.95 compliant command from driver | |
416 | * @size: length of command | |
417 | * | |
418 | * Filter commands based on which protocol the device supports. The WUSB | |
419 | * errata should be the same as WHCI 0.95 so we do not filter that here - | |
420 | * only WUSB 1.0. | |
421 | */ | |
422 | static | |
423 | int hwarc_filter_cmd(struct uwb_rc *rc, struct uwb_rccb **header, | |
424 | size_t *size) | |
425 | { | |
426 | int result = -ENOANO; | |
427 | if (rc->version == 0x0100) | |
428 | result = hwarc_filter_cmd_WUSB_0100(rc, header, size); | |
429 | return result; | |
430 | } | |
431 | ||
432 | ||
433 | /** | |
434 | * Compute return value as sum of incoming value and value at given offset | |
435 | * | |
436 | * @rceb: event for which we compute the size, it contains a variable | |
437 | * length field. | |
438 | * @core_size: size of the "non variable" part of the event | |
439 | * @offset: place in event where the length of the variable part is stored | |
440 | * @buf_size: total length of buffer in which event arrived - we need to make | |
441 | * sure we read the offset in memory that is still part of the event | |
442 | */ | |
443 | static | |
444 | ssize_t hwarc_get_event_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, | |
445 | size_t core_size, size_t offset, | |
446 | const size_t buf_size) | |
447 | { | |
448 | ssize_t size = -ENOSPC; | |
449 | const void *ptr = rceb; | |
450 | size_t type_size = sizeof(__le16); | |
451 | struct device *dev = &rc->uwb_dev.dev; | |
452 | ||
453 | if (offset + type_size >= buf_size) { | |
454 | dev_err(dev, "Not enough data to read extra size of event " | |
455 | "0x%02x/%04x/%02x, only got %zu bytes.\n", | |
456 | rceb->bEventType, le16_to_cpu(rceb->wEvent), | |
457 | rceb->bEventContext, buf_size); | |
458 | goto out; | |
459 | } | |
460 | ptr += offset; | |
461 | size = core_size + le16_to_cpu(*(__le16 *)ptr); | |
462 | out: | |
463 | return size; | |
464 | } | |
465 | ||
466 | ||
467 | /* Beacon slot change notification (WUSB 1.0 [8.6.3.5]) */ | |
468 | struct uwb_rc_evt_bp_slot_change_WUSB_0100 { | |
469 | struct uwb_rceb rceb; | |
470 | u8 bSlotNumber; | |
471 | } __attribute__((packed)); | |
472 | ||
473 | ||
474 | /** | |
475 | * Filter data from WUSB device to WHCI driver | |
476 | * | |
477 | * @header: incoming event | |
478 | * @buf_size: size of buffer in which event arrived | |
479 | * @_event_size: actual size of event in the buffer | |
480 | * @new_size: size of event after filtered | |
481 | * | |
482 | * We don't know how the buffer is constructed - there may be more than one | |
483 | * event in it so buffer length does not determine event length. We first | |
484 | * determine the expected size of the incoming event. This value is passed | |
485 | * back only if the actual filtering succeeded (so we know the computed | |
486 | * expected size is correct). This value will be zero if | |
487 | * the event did not need any filtering. | |
488 | * | |
489 | * WHCI interprets the BP Slot Change event's data differently than | |
490 | * WUSB. The event sizes are exactly the same. The data field | |
491 | * indicates the new beacon slot in which a RC is transmitting its | |
492 | * beacon. The maximum value of this is 96 (wMacBPLength ECMA-368 | |
493 | * 17.16 (Table 117)). We thus know that the WUSB value will not set | |
494 | * the bit bNoSlot, so we don't really do anything (placeholder). | |
495 | */ | |
496 | static | |
497 | int hwarc_filter_event_WUSB_0100(struct uwb_rc *rc, struct uwb_rceb **header, | |
498 | const size_t buf_size, size_t *_real_size, | |
499 | size_t *_new_size) | |
500 | { | |
501 | int result = -ENOANO; | |
502 | struct uwb_rceb *rceb = *header; | |
503 | int event = le16_to_cpu(rceb->wEvent); | |
94d72176 | 504 | ssize_t event_size; |
de520b8b IPG |
505 | size_t core_size, offset; |
506 | ||
507 | if (rceb->bEventType != UWB_RC_CET_GENERAL) | |
508 | goto out; | |
509 | switch (event) { | |
510 | case UWB_RC_EVT_BEACON: | |
511 | core_size = sizeof(struct uwb_rc_evt_beacon_WUSB_0100); | |
512 | offset = offsetof(struct uwb_rc_evt_beacon_WUSB_0100, | |
513 | wBeaconInfoLength); | |
514 | event_size = hwarc_get_event_size(rc, rceb, core_size, | |
515 | offset, buf_size); | |
516 | if (event_size < 0) | |
517 | goto out; | |
518 | *_real_size = event_size; | |
519 | result = hwarc_filter_evt_beacon_WUSB_0100(rc, header, | |
520 | buf_size, _new_size); | |
521 | break; | |
522 | case UWB_RC_EVT_BP_SLOT_CHANGE: | |
523 | *_new_size = *_real_size = | |
524 | sizeof(struct uwb_rc_evt_bp_slot_change_WUSB_0100); | |
525 | result = 0; | |
526 | break; | |
527 | ||
528 | case UWB_RC_EVT_DRP_AVAIL: | |
529 | core_size = sizeof(struct uwb_rc_evt_drp_avail_WUSB_0100); | |
530 | offset = offsetof(struct uwb_rc_evt_drp_avail_WUSB_0100, | |
531 | wIELength); | |
532 | event_size = hwarc_get_event_size(rc, rceb, core_size, | |
533 | offset, buf_size); | |
534 | if (event_size < 0) | |
535 | goto out; | |
536 | *_real_size = event_size; | |
537 | result = hwarc_filter_evt_drp_avail_WUSB_0100( | |
538 | rc, header, buf_size, _new_size); | |
539 | break; | |
540 | ||
541 | case UWB_RC_EVT_DRP: | |
542 | core_size = sizeof(struct uwb_rc_evt_drp_WUSB_0100); | |
543 | offset = offsetof(struct uwb_rc_evt_drp_WUSB_0100, wIELength); | |
544 | event_size = hwarc_get_event_size(rc, rceb, core_size, | |
545 | offset, buf_size); | |
546 | if (event_size < 0) | |
547 | goto out; | |
548 | *_real_size = event_size; | |
549 | result = hwarc_filter_evt_drp_WUSB_0100(rc, header, | |
550 | buf_size, _new_size); | |
551 | break; | |
552 | ||
553 | default: | |
554 | break; | |
555 | } | |
556 | out: | |
557 | return result; | |
558 | } | |
559 | ||
560 | /** | |
561 | * Filter data from WUSB device to WHCI driver | |
562 | * | |
563 | * @header: incoming event | |
564 | * @buf_size: size of buffer in which event arrived | |
565 | * @_event_size: actual size of event in the buffer | |
566 | * @_new_size: size of event after filtered | |
567 | * | |
568 | * Filter events based on which protocol the device supports. The WUSB | |
569 | * errata should be the same as WHCI 0.95 so we do not filter that here - | |
570 | * only WUSB 1.0. | |
571 | * | |
572 | * If we don't handle it, we return -ENOANO (why the weird error code? | |
573 | * well, so if I get it, I can pinpoint in the code that raised | |
574 | * it...after all, not too many places use the higher error codes). | |
575 | */ | |
576 | static | |
577 | int hwarc_filter_event(struct uwb_rc *rc, struct uwb_rceb **header, | |
578 | const size_t buf_size, size_t *_real_size, | |
579 | size_t *_new_size) | |
580 | { | |
581 | int result = -ENOANO; | |
582 | if (rc->version == 0x0100) | |
583 | result = hwarc_filter_event_WUSB_0100( | |
584 | rc, header, buf_size, _real_size, _new_size); | |
585 | return result; | |
586 | } | |
587 | ||
588 | ||
589 | /** | |
590 | * Execute an UWB RC command on HWA | |
591 | * | |
592 | * @rc: Instance of a Radio Controller that is a HWA | |
593 | * @cmd: Buffer containing the RCCB and payload to execute | |
594 | * @cmd_size: Size of the command buffer. | |
595 | * | |
596 | * NOTE: rc's mutex has to be locked | |
597 | */ | |
598 | static | |
599 | int hwarc_cmd(struct uwb_rc *uwb_rc, const struct uwb_rccb *cmd, size_t cmd_size) | |
600 | { | |
601 | struct hwarc *hwarc = uwb_rc->priv; | |
602 | return usb_control_msg( | |
603 | hwarc->usb_dev, usb_sndctrlpipe(hwarc->usb_dev, 0), | |
604 | WA_EXEC_RC_CMD, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | |
605 | 0, hwarc->usb_iface->cur_altsetting->desc.bInterfaceNumber, | |
606 | (void *) cmd, cmd_size, 100 /* FIXME: this is totally arbitrary */); | |
607 | } | |
608 | ||
609 | static | |
610 | int hwarc_reset(struct uwb_rc *uwb_rc) | |
611 | { | |
612 | struct hwarc *hwarc = uwb_rc->priv; | |
613 | return usb_reset_device(hwarc->usb_dev); | |
614 | } | |
615 | ||
616 | /** | |
617 | * Callback for the notification and event endpoint | |
618 | * | |
619 | * Check's that everything is fine and then passes the read data to | |
620 | * the notification/event handling mechanism (neh). | |
621 | */ | |
622 | static | |
623 | void hwarc_neep_cb(struct urb *urb) | |
624 | { | |
625 | struct hwarc *hwarc = urb->context; | |
626 | struct usb_interface *usb_iface = hwarc->usb_iface; | |
627 | struct device *dev = &usb_iface->dev; | |
628 | int result; | |
629 | ||
630 | switch (result = urb->status) { | |
631 | case 0: | |
de520b8b IPG |
632 | uwb_rc_neh_grok(hwarc->uwb_rc, urb->transfer_buffer, |
633 | urb->actual_length); | |
634 | break; | |
635 | case -ECONNRESET: /* Not an error, but a controlled situation; */ | |
636 | case -ENOENT: /* (we killed the URB)...so, no broadcast */ | |
de520b8b IPG |
637 | goto out; |
638 | case -ESHUTDOWN: /* going away! */ | |
de520b8b IPG |
639 | goto out; |
640 | default: /* On general errors, retry unless it gets ugly */ | |
641 | if (edc_inc(&hwarc->neep_edc, EDC_MAX_ERRORS, | |
642 | EDC_ERROR_TIMEFRAME)) | |
643 | goto error_exceeded; | |
644 | dev_err(dev, "NEEP: URB error %d\n", urb->status); | |
645 | } | |
646 | result = usb_submit_urb(urb, GFP_ATOMIC); | |
de520b8b IPG |
647 | if (result < 0) { |
648 | dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n", | |
649 | result); | |
650 | goto error; | |
651 | } | |
652 | out: | |
653 | return; | |
654 | ||
655 | error_exceeded: | |
656 | dev_err(dev, "NEEP: URB max acceptable errors " | |
657 | "exceeded, resetting device\n"); | |
658 | error: | |
659 | uwb_rc_neh_error(hwarc->uwb_rc, result); | |
660 | uwb_rc_reset_all(hwarc->uwb_rc); | |
661 | return; | |
662 | } | |
663 | ||
664 | static void hwarc_init(struct hwarc *hwarc) | |
665 | { | |
666 | edc_init(&hwarc->neep_edc); | |
667 | } | |
668 | ||
669 | /** | |
670 | * Initialize the notification/event endpoint stuff | |
671 | * | |
672 | * Note this is effectively a parallel thread; it knows that | |
673 | * hwarc->uwb_rc always exists because the existence of a 'hwarc' | |
674 | * means that there is a reverence on the hwarc->uwb_rc (see | |
675 | * _probe()), and thus _neep_cb() can execute safely. | |
676 | */ | |
677 | static int hwarc_neep_init(struct uwb_rc *rc) | |
678 | { | |
679 | struct hwarc *hwarc = rc->priv; | |
680 | struct usb_interface *iface = hwarc->usb_iface; | |
681 | struct usb_device *usb_dev = interface_to_usbdev(iface); | |
682 | struct device *dev = &iface->dev; | |
683 | int result; | |
684 | struct usb_endpoint_descriptor *epd; | |
685 | ||
686 | epd = &iface->cur_altsetting->endpoint[0].desc; | |
687 | hwarc->rd_buffer = (void *) __get_free_page(GFP_KERNEL); | |
688 | if (hwarc->rd_buffer == NULL) { | |
689 | dev_err(dev, "Unable to allocate notification's read buffer\n"); | |
690 | goto error_rd_buffer; | |
691 | } | |
692 | hwarc->neep_urb = usb_alloc_urb(0, GFP_KERNEL); | |
693 | if (hwarc->neep_urb == NULL) { | |
694 | dev_err(dev, "Unable to allocate notification URB\n"); | |
695 | goto error_urb_alloc; | |
696 | } | |
697 | usb_fill_int_urb(hwarc->neep_urb, usb_dev, | |
698 | usb_rcvintpipe(usb_dev, epd->bEndpointAddress), | |
699 | hwarc->rd_buffer, PAGE_SIZE, | |
700 | hwarc_neep_cb, hwarc, epd->bInterval); | |
701 | result = usb_submit_urb(hwarc->neep_urb, GFP_ATOMIC); | |
702 | if (result < 0) { | |
703 | dev_err(dev, "Cannot submit notification URB: %d\n", result); | |
704 | goto error_neep_submit; | |
705 | } | |
706 | return 0; | |
707 | ||
708 | error_neep_submit: | |
709 | usb_free_urb(hwarc->neep_urb); | |
710 | error_urb_alloc: | |
711 | free_page((unsigned long)hwarc->rd_buffer); | |
712 | error_rd_buffer: | |
713 | return -ENOMEM; | |
714 | } | |
715 | ||
716 | ||
717 | /** Clean up all the notification endpoint resources */ | |
718 | static void hwarc_neep_release(struct uwb_rc *rc) | |
719 | { | |
720 | struct hwarc *hwarc = rc->priv; | |
721 | ||
722 | usb_kill_urb(hwarc->neep_urb); | |
723 | usb_free_urb(hwarc->neep_urb); | |
724 | free_page((unsigned long)hwarc->rd_buffer); | |
725 | } | |
726 | ||
727 | /** | |
728 | * Get the version from class-specific descriptor | |
729 | * | |
730 | * NOTE: this descriptor comes with the big bundled configuration | |
731 | * descriptor that includes the interfaces' and endpoints', so | |
732 | * we just look for it in the cached copy kept by the USB stack. | |
733 | * | |
734 | * NOTE2: We convert LE fields to CPU order. | |
735 | */ | |
736 | static int hwarc_get_version(struct uwb_rc *rc) | |
737 | { | |
738 | int result; | |
739 | ||
740 | struct hwarc *hwarc = rc->priv; | |
741 | struct uwb_rc_control_intf_class_desc *descr; | |
742 | struct device *dev = &rc->uwb_dev.dev; | |
743 | struct usb_device *usb_dev = hwarc->usb_dev; | |
744 | char *itr; | |
745 | struct usb_descriptor_header *hdr; | |
746 | size_t itr_size, actconfig_idx; | |
747 | u16 version; | |
748 | ||
749 | actconfig_idx = (usb_dev->actconfig - usb_dev->config) / | |
750 | sizeof(usb_dev->config[0]); | |
751 | itr = usb_dev->rawdescriptors[actconfig_idx]; | |
752 | itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); | |
753 | while (itr_size >= sizeof(*hdr)) { | |
754 | hdr = (struct usb_descriptor_header *) itr; | |
bce83697 DV |
755 | dev_dbg(dev, "Extra device descriptor: " |
756 | "type %02x/%u bytes @ %zu (%zu left)\n", | |
757 | hdr->bDescriptorType, hdr->bLength, | |
758 | (itr - usb_dev->rawdescriptors[actconfig_idx]), | |
759 | itr_size); | |
de520b8b IPG |
760 | if (hdr->bDescriptorType == USB_DT_CS_RADIO_CONTROL) |
761 | goto found; | |
762 | itr += hdr->bLength; | |
763 | itr_size -= hdr->bLength; | |
764 | } | |
765 | dev_err(dev, "cannot find Radio Control Interface Class descriptor\n"); | |
766 | return -ENODEV; | |
767 | ||
768 | found: | |
769 | result = -EINVAL; | |
770 | if (hdr->bLength > itr_size) { /* is it available? */ | |
771 | dev_err(dev, "incomplete Radio Control Interface Class " | |
772 | "descriptor (%zu bytes left, %u needed)\n", | |
773 | itr_size, hdr->bLength); | |
774 | goto error; | |
775 | } | |
776 | if (hdr->bLength < sizeof(*descr)) { | |
777 | dev_err(dev, "short Radio Control Interface Class " | |
778 | "descriptor\n"); | |
779 | goto error; | |
780 | } | |
781 | descr = (struct uwb_rc_control_intf_class_desc *) hdr; | |
782 | /* Make LE fields CPU order */ | |
783 | version = __le16_to_cpu(descr->bcdRCIVersion); | |
784 | if (version != 0x0100) { | |
785 | dev_err(dev, "Device reports protocol version 0x%04x. We " | |
786 | "do not support that. \n", version); | |
787 | result = -EINVAL; | |
788 | goto error; | |
789 | } | |
790 | rc->version = version; | |
bce83697 | 791 | dev_dbg(dev, "Device supports WUSB protocol version 0x%04x \n", rc->version); |
de520b8b IPG |
792 | result = 0; |
793 | error: | |
794 | return result; | |
795 | } | |
796 | ||
797 | /* | |
798 | * By creating a 'uwb_rc', we have a reference on it -- that reference | |
799 | * is the one we drop when we disconnect. | |
800 | * | |
801 | * No need to switch altsettings; according to WUSB1.0[8.6.1.1], there | |
802 | * is only one altsetting allowed. | |
803 | */ | |
804 | static int hwarc_probe(struct usb_interface *iface, | |
805 | const struct usb_device_id *id) | |
806 | { | |
807 | int result; | |
808 | struct uwb_rc *uwb_rc; | |
809 | struct hwarc *hwarc; | |
810 | struct device *dev = &iface->dev; | |
811 | ||
812 | result = -ENOMEM; | |
813 | uwb_rc = uwb_rc_alloc(); | |
814 | if (uwb_rc == NULL) { | |
815 | dev_err(dev, "unable to allocate RC instance\n"); | |
816 | goto error_rc_alloc; | |
817 | } | |
818 | hwarc = kzalloc(sizeof(*hwarc), GFP_KERNEL); | |
819 | if (hwarc == NULL) { | |
820 | dev_err(dev, "unable to allocate HWA RC instance\n"); | |
821 | goto error_alloc; | |
822 | } | |
823 | hwarc_init(hwarc); | |
824 | hwarc->usb_dev = usb_get_dev(interface_to_usbdev(iface)); | |
825 | hwarc->usb_iface = usb_get_intf(iface); | |
826 | hwarc->uwb_rc = uwb_rc; | |
827 | ||
828 | uwb_rc->owner = THIS_MODULE; | |
829 | uwb_rc->start = hwarc_neep_init; | |
830 | uwb_rc->stop = hwarc_neep_release; | |
831 | uwb_rc->cmd = hwarc_cmd; | |
832 | uwb_rc->reset = hwarc_reset; | |
e477a498 AL |
833 | if (id->driver_info & WUSB_QUIRK_WHCI_CMD_EVT) { |
834 | uwb_rc->filter_cmd = NULL; | |
835 | uwb_rc->filter_event = NULL; | |
836 | } else { | |
837 | uwb_rc->filter_cmd = hwarc_filter_cmd; | |
838 | uwb_rc->filter_event = hwarc_filter_event; | |
839 | } | |
de520b8b IPG |
840 | |
841 | result = uwb_rc_add(uwb_rc, dev, hwarc); | |
842 | if (result < 0) | |
843 | goto error_rc_add; | |
844 | result = hwarc_get_version(uwb_rc); | |
845 | if (result < 0) { | |
846 | dev_err(dev, "cannot retrieve version of RC \n"); | |
847 | goto error_get_version; | |
848 | } | |
849 | usb_set_intfdata(iface, hwarc); | |
850 | return 0; | |
851 | ||
852 | error_get_version: | |
853 | uwb_rc_rm(uwb_rc); | |
854 | error_rc_add: | |
855 | usb_put_intf(iface); | |
856 | usb_put_dev(hwarc->usb_dev); | |
857 | error_alloc: | |
858 | uwb_rc_put(uwb_rc); | |
859 | error_rc_alloc: | |
860 | return result; | |
861 | } | |
862 | ||
863 | static void hwarc_disconnect(struct usb_interface *iface) | |
864 | { | |
865 | struct hwarc *hwarc = usb_get_intfdata(iface); | |
866 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | |
867 | ||
868 | usb_set_intfdata(hwarc->usb_iface, NULL); | |
869 | uwb_rc_rm(uwb_rc); | |
870 | usb_put_intf(hwarc->usb_iface); | |
871 | usb_put_dev(hwarc->usb_dev); | |
de520b8b IPG |
872 | kfree(hwarc); |
873 | uwb_rc_put(uwb_rc); /* when creating the device, refcount = 1 */ | |
874 | } | |
875 | ||
307ba6dd DV |
876 | static int hwarc_pre_reset(struct usb_interface *iface) |
877 | { | |
878 | struct hwarc *hwarc = usb_get_intfdata(iface); | |
879 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | |
880 | ||
881 | uwb_rc_pre_reset(uwb_rc); | |
882 | return 0; | |
883 | } | |
884 | ||
885 | static int hwarc_post_reset(struct usb_interface *iface) | |
886 | { | |
887 | struct hwarc *hwarc = usb_get_intfdata(iface); | |
888 | struct uwb_rc *uwb_rc = hwarc->uwb_rc; | |
889 | ||
890 | uwb_rc_post_reset(uwb_rc); | |
891 | return 0; | |
892 | } | |
893 | ||
de520b8b IPG |
894 | /** USB device ID's that we handle */ |
895 | static struct usb_device_id hwarc_id_table[] = { | |
e477a498 AL |
896 | /* D-Link DUB-1210 */ |
897 | { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3d02, 0xe0, 0x01, 0x02), | |
898 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, | |
fa211833 AL |
899 | /* Intel i1480 (using firmware 1.3PA2-20070828) */ |
900 | { USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02), | |
901 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, | |
e477a498 | 902 | /* Generic match for the Radio Control interface */ |
de520b8b IPG |
903 | { USB_INTERFACE_INFO(0xe0, 0x01, 0x02), }, |
904 | { }, | |
905 | }; | |
906 | MODULE_DEVICE_TABLE(usb, hwarc_id_table); | |
907 | ||
908 | static struct usb_driver hwarc_driver = { | |
909 | .name = "hwa-rc", | |
307ba6dd | 910 | .id_table = hwarc_id_table, |
de520b8b IPG |
911 | .probe = hwarc_probe, |
912 | .disconnect = hwarc_disconnect, | |
307ba6dd DV |
913 | .pre_reset = hwarc_pre_reset, |
914 | .post_reset = hwarc_post_reset, | |
de520b8b IPG |
915 | }; |
916 | ||
917 | static int __init hwarc_driver_init(void) | |
918 | { | |
bce83697 | 919 | return usb_register(&hwarc_driver); |
de520b8b IPG |
920 | } |
921 | module_init(hwarc_driver_init); | |
922 | ||
923 | static void __exit hwarc_driver_exit(void) | |
924 | { | |
925 | usb_deregister(&hwarc_driver); | |
926 | } | |
927 | module_exit(hwarc_driver_exit); | |
928 | ||
929 | MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>"); | |
930 | MODULE_DESCRIPTION("Host Wireless Adapter Radio Control Driver"); | |
931 | MODULE_LICENSE("GPL"); |