• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Dongle BUS interface
3  * USB Linux Implementation
4  *
5  * Copyright (C) 1999-2016, Broadcom Corporation
6  *
7  *      Unless you and Broadcom execute a separate written software license
8  * agreement governing use of this software, this software is licensed to you
9  * under the terms of the GNU General Public License version 2 (the "GPL"),
10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11  * following added to such license:
12  *
13  *      As a special exception, the copyright holders of this software give you
14  * permission to link this software with independent modules, and to copy and
15  * distribute the resulting executable under terms of your choice, provided that
16  * you also meet, for each linked independent module, the terms and conditions
17  * of the license of that module.  An independent module is a module which is
18  * not derived from this software.  The special exception does not apply to any
19  * modifications of the software.
20  *
21  *      Notwithstanding the above, under no circumstances may you combine this
22  * software in any way with any other Broadcom software provided under a license
23  * other than the GPL, without Broadcom's express prior written consent.
24  *
25  *
26  * <<Broadcom-WL-IPTag/Open:>>
27  *
28  * $Id: dbus_usb_linux.c 564663 2015-06-18 02:34:42Z $
29  */
30 
31 /**
32  * @file @brief
33  * This file contains DBUS code that is USB *and* OS (Linux) specific. DBUS is a
34  * Broadcom proprietary host specific abstraction layer.
35  */
36 
37 #include <typedefs.h>
38 #include <osl.h>
39 
40 /**
41  * DBUS_LINUX_RXDPC is created for router platform performance tuning. A
42  * separate thread is created to handle USB RX and avoid the call chain getting
43  * too long and enhance cache hit rate.
44  *
45  * DBUS_LINUX_RXDPC setting is in wlconfig file.
46  */
47 
48 /*
49  * If DBUS_LINUX_RXDPC is off, spin_lock_bh() for CTFPOOL in
50  * linux_osl.c has to be changed to spin_lock_irqsave() because
51  * PKTGET/PKTFREE are no longer in bottom half.
52  *
53  * Right now we have another queue rpcq in wl_linux.c. Maybe we
54  * can eliminate that one to reduce the overhead.
55  *
56  * Enabling 2nd EP and DBUS_LINUX_RXDPC causing traffic from
57  * both EP's to be queued in the same rx queue. If we want
58  * RXDPC to work with 2nd EP. The EP for RPC call return
59  * should bypass the dpc and go directly up.
60  */
61 
62 #include <usbrdl.h>
63 #include <bcmendian.h>
64 #include <linux/init.h>
65 #include <linux/kernel.h>
66 #include <linux/slab.h>
67 #include <linux/usb.h>
68 #include <linux/skbuff.h>
69 #include <linux/netdevice.h>
70 #include <linux/random.h>
71 #include <linux/spinlock.h>
72 #include <linux/list.h>
73 #include <asm/uaccess.h>
74 #include <asm/unaligned.h>
75 #include <dbus.h>
76 #include <bcmutils.h>
77 #include <bcmdevs.h>
78 #include <linux/usb.h>
79 #include <usbrdl.h>
80 #include <linux/firmware.h>
81 #include <dngl_stats.h>
82 #include <dhd.h>
83 
84 #if defined(USBOS_THREAD) || defined(USBOS_TX_THREAD)
85 
86 /**
87  * The usb-thread is designed to provide currency on multiprocessors and SMP
88  * linux kernels. On the dual cores platform, the WLAN driver, without threads,
89  * executed only on CPU0. The driver consumed almost of 100% on CPU0, while CPU1
90  * remained idle. The behavior was observed on Broadcom's STB.
91  *
92  * The WLAN driver consumed most of CPU0 and not CPU1 because tasklets/queues,
93  * software irq, and hardware irq are executing from CPU0, only. CPU0 became the
94  * system's bottle-neck. TPUT is lower and system's responsiveness is slower.
95  *
96  * To improve system responsiveness and TPUT usb-thread was implemented. The
97  * system's threads could be scheduled to run on any core. One core could be
98  * processing data in the usb-layer and the other core could be processing data
99  * in the wl-layer.
100  *
101  * For further info see [WlThreadAndUsbThread] Twiki.
102  */
103 
104 #include <linux/kthread.h>
105 #include <linux/interrupt.h>
106 #include <linux/irq.h>
107 #include <asm/hardirq.h>
108 #include <linux/list.h>
109 #include <linux_osl.h>
110 #endif /* USBOS_THREAD || USBOS_TX_THREAD */
111 
112 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
113 #define KERNEL26
114 #endif
115 
116 /**
117  * Starting with the 3.10 kernel release, dynamic PM support for USB is present
118  * whenever the kernel was built with CONFIG_PM_RUNTIME enabled. The
119  * CONFIG_USB_SUSPEND option has been eliminated.
120  */
121 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)) &&                       \
122      defined(CONFIG_USB_SUSPEND)) ||                                           \
123     ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) &&                       \
124      defined(CONFIG_PM_RUNTIME)) ||                                            \
125     (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
126 /* For USB power management support, see Linux kernel:
127  * Documentation/usb/power-management.txt */
128 #define USB_SUSPEND_AVAILABLE
129 #endif
130 
131 /* Define alternate fw/nvram paths used in Android */
132 #ifdef OEM_ANDROID
133 #define CONFIG_ANDROID_BCMDHD_FW_PATH "broadcom/dhd/firmware/fw.bin.trx"
134 #define CONFIG_ANDROID_BCMDHD_NVRAM_PATH "broadcom/dhd/nvrams/nvm.txt"
135 #endif /* OEM_ANDROID */
136 
usb_submit_urb_linux(struct urb * urb)137 static inline int usb_submit_urb_linux(struct urb *urb)
138 {
139 #ifdef BCM_MAX_URB_LEN
140     if (urb && (urb->transfer_buffer_length > BCM_MAX_URB_LEN)) {
141         DBUSERR(("URB transfer length=%d exceeded %d ra=%p\n",
142                  urb->transfer_buffer_length, BCM_MAX_URB_LEN,
143                  __builtin_return_address(0)));
144         return DBUS_ERR;
145     }
146 #endif
147 
148 #ifdef KERNEL26
149     return usb_submit_urb(urb, GFP_ATOMIC);
150 #else
151     return usb_submit_urb(urb);
152 #endif
153 }
154 
155 #define USB_SUBMIT_URB(urb) usb_submit_urb_linux(urb)
156 
157 #ifdef KERNEL26
158 
159 #define USB_ALLOC_URB() usb_alloc_urb(0, GFP_ATOMIC)
160 #define USB_UNLINK_URB(urb) (usb_kill_urb(urb))
161 #define USB_FREE_URB(urb) (usb_free_urb(urb))
162 #define USB_REGISTER() usb_register(&dbus_usbdev)
163 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
164 
165 #ifdef USB_SUSPEND_AVAILABLE
166 
167 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
168 #define USB_AUTOPM_SET_INTERFACE(intf) usb_autopm_set_interface(intf)
169 #else
170 #define USB_ENABLE_AUTOSUSPEND(udev) usb_enable_autosuspend(udev)
171 #define USB_DISABLE_AUTOSUSPEND(udev) usb_disable_autosuspend(udev)
172 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))  */
173 
174 #define USB_AUTOPM_GET_INTERFACE(intf) usb_autopm_get_interface(intf)
175 #define USB_AUTOPM_PUT_INTERFACE(intf) usb_autopm_put_interface(intf)
176 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf)                                   \
177     usb_autopm_get_interface_async(intf)
178 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf)                                   \
179     usb_autopm_put_interface_async(intf)
180 #define USB_MARK_LAST_BUSY(dev) usb_mark_last_busy(dev)
181 
182 #else /* USB_SUSPEND_AVAILABLE */
183 
184 #define USB_AUTOPM_GET_INTERFACE(intf)                                         \
185     do {                                                                       \
186     } while (0)
187 #define USB_AUTOPM_PUT_INTERFACE(intf)                                         \
188     do {                                                                       \
189     } while (0)
190 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf)                                   \
191     do {                                                                       \
192     } while (0)
193 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf)                                   \
194     do {                                                                       \
195     } while (0)
196 #define USB_MARK_LAST_BUSY(dev)                                                \
197     do {                                                                       \
198     } while (0)
199 #endif /* USB_SUSPEND_AVAILABLE */
200 
201 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data,   \
202                         size, timeout)                                         \
203     usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
204                     (data), (size), (timeout))
205 #define USB_BULK_MSG(dev, pipe, data, len, actual_length, timeout)             \
206     usb_bulk_msg((dev), (pipe), (data), (len), (actual_length), (timeout))
207 #define USB_BUFFER_ALLOC(dev, size, mem, dma)                                  \
208     usb_buffer_alloc(dev, size, mem, dma)
209 #define USB_BUFFER_FREE(dev, size, data, dma)                                  \
210     usb_buffer_free(dev, size, data, dma)
211 
212 #ifdef WL_URB_ZPKT
213 #define URB_QUEUE_BULK URB_ZERO_PACKET
214 #else
215 #define URB_QUEUE_BULK 0
216 #endif /* WL_URB_ZPKT */
217 
218 #define CALLBACK_ARGS struct urb *urb, struct pt_regs *regs
219 #define CALLBACK_ARGS_DATA urb, regs
220 #define CONFIGDESC(usb) (&((usb)->actconfig)->desc)
221 #define IFPTR(usb, idx) ((usb)->actconfig->interface[idx])
222 #define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0])
223 #define IFDESC(usb, idx) IFALTS((usb), (idx)).desc
224 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep]).desc
225 
226 #else /* KERNEL26 */
227 
228 #define USB_ALLOC_URB() usb_alloc_urb(0)
229 #define USB_UNLINK_URB(urb) usb_unlink_urb(urb)
230 #define USB_FREE_URB(urb) (usb_free_urb(urb))
231 #define USB_REGISTER() usb_register(&dbus_usbdev)
232 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
233 #define USB_AUTOPM_GET_INTERFACE(intf)                                         \
234     do {                                                                       \
235     } while (0)
236 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf)                                   \
237     do {                                                                       \
238     } while (0)
239 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf)                                   \
240     do {                                                                       \
241     } while (0)
242 #define USB_MARK_LAST_BUSY(dev)                                                \
243     do {                                                                       \
244     } while (0)
245 
246 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data,   \
247                         size, timeout)                                         \
248     usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
249                     (data), (size), (timeout))
250 #define USB_BUFFER_ALLOC(dev, size, mem, dma) kmalloc(size, mem)
251 #define USB_BUFFER_FREE(dev, size, data, dma) kfree(data)
252 
253 #ifdef WL_URB_ZPKT
254 #define URB_QUEUE_BULK USB_QUEUE_BULK | URB_ZERO_PACKET
255 #else
256 #define URB_QUEUE_BULK 0
257 #endif /*  WL_URB_ZPKT */
258 
259 #define CALLBACK_ARGS struct urb *urb
260 #define CALLBACK_ARGS_DATA urb
261 #define CONFIGDESC(usb) ((usb)->actconfig)
262 #define IFPTR(usb, idx) (&(usb)->actconfig->interface[idx])
263 #define IFALTS(usb, idx) ((usb)->actconfig->interface[idx].altsetting[0])
264 #define IFDESC(usb, idx) IFALTS((usb), (idx))
265 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep])
266 
267 #endif /* KERNEL26 */
268 
269 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
270 #define USB_SPEED_SUPER 5
271 #endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) */
272 
273 #define CONTROL_IF 0
274 #define BULK_IF 0
275 
276 #ifdef BCMUSBDEV_COMPOSITE
277 #define USB_COMPIF_MAX 4
278 
279 #define USB_CLASS_WIRELESS 0xe0
280 #define USB_CLASS_MISC 0xef
281 #define USB_SUBCLASS_COMMON 0x02
282 #define USB_PROTO_IAD 0x01
283 #define USB_PROTO_VENDOR 0xff
284 
285 #define USB_QUIRK_NO_SET_INTF 0x04 /* device does not support set_interface */
286 #endif                             /* BCMUSBDEV_COMPOSITE */
287 
288 #define USB_SYNC_WAIT_TIMEOUT 300 /* ms */
289 
290 /* Private data kept in skb */
291 #define SKB_PRIV(skb, idx) (&((void **)skb->cb)[idx])
292 #define SKB_PRIV_URB(skb) (*(struct urb **)SKB_PRIV(skb, 0))
293 
294 #ifndef DBUS_USB_RXQUEUE_BATCH_ADD
295 /* items to add each time within limit */
296 #define DBUS_USB_RXQUEUE_BATCH_ADD 8
297 #endif
298 
299 #ifndef DBUS_USB_RXQUEUE_LOWER_WATERMARK
300 /* add a new batch req to rx queue when waiting item count reduce to this number
301  */
302 #define DBUS_USB_RXQUEUE_LOWER_WATERMARK 4
303 #endif
304 
305 enum usbos_suspend_state {
306     USBOS_SUSPEND_STATE_DEVICE_ACTIVE =
307         0, /* Device is busy, won't allow suspend */
308     USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be suspended */
309                                          /* Wating PM to suspend */
310     USBOS_SUSPEND_STATE_SUSPENDED        /* Device suspended */
311 };
312 
313 enum usbos_request_state {
314     USBOS_REQUEST_STATE_UNSCHEDULED = 0, /* USB TX request not scheduled */
315     USBOS_REQUEST_STATE_SCHEDULED,       /* USB TX request given to TX thread */
316     USBOS_REQUEST_STATE_SUBMITTED        /* USB TX request submitted */
317 };
318 
319 typedef struct {
320     uint32 notification;
321     uint32 reserved;
322 } intr_t;
323 
324 typedef struct {
325     dbus_pub_t *pub;
326 
327     void *cbarg;
328     dbus_intf_callbacks_t *cbs;
329 
330     /* Imported */
331     struct usb_device *usb; /* USB device pointer from OS */
332     struct urb *intr_urb;   /* URB for interrupt endpoint */
333     struct list_head req_rxfreeq;
334     struct list_head req_txfreeq;
335     struct list_head req_rxpostedq; /* Posted down to USB driver for RX */
336     struct list_head req_txpostedq; /* Posted down to USB driver for TX */
337     spinlock_t rxfree_lock;         /* Lock for rx free list */
338     spinlock_t txfree_lock;         /* Lock for tx free list */
339     spinlock_t rxposted_lock;       /* Lock for rx posted list */
340     spinlock_t txposted_lock;       /* Lock for tx posted list */
341     uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; /* Pipe numbers for USB I/O */
342     uint rxbuf_len;
343 
344     struct list_head req_rxpendingq; /* RXDPC: Pending for dpc to send up */
345     spinlock_t rxpending_lock;       /* RXDPC: Lock for rx pending list */
346     long dpc_pid;
347     struct semaphore dpc_sem;
348     struct completion dpc_exited;
349     int rxpending;
350 
351     struct urb *ctl_urb;
352     int ctl_in_pipe, ctl_out_pipe;
353     struct usb_ctrlrequest ctl_write;
354     struct usb_ctrlrequest ctl_read;
355     struct semaphore ctl_lock; /* Lock for CTRL transfers via tx_thread */
356 #ifdef USBOS_TX_THREAD
357     enum usbos_request_state ctl_state;
358 #endif /* USBOS_TX_THREAD */
359 
360     spinlock_t rxlock; /* Lock for rxq management */
361     spinlock_t txlock; /* Lock for txq management */
362 
363     int intr_size; /* Size of interrupt message */
364     int interval;  /* Interrupt polling interval */
365     intr_t intr;   /* Data buffer for interrupt endpoint */
366 
367     int maxps;
368     atomic_t txposted;
369     atomic_t rxposted;
370     atomic_t txallocated;
371     atomic_t rxallocated;
372     bool rxctl_deferrespok; /* Get a response for setup from dongle */
373 
374     wait_queue_head_t wait;
375     bool waitdone;
376     int sync_urb_status;
377 
378     struct urb *blk_urb; /* Used for downloading embedded image */
379 
380 #ifdef USBOS_THREAD
381     spinlock_t ctrl_lock;
382     spinlock_t usbos_list_lock;
383     struct list_head usbos_list;
384     struct list_head usbos_free_list;
385     atomic_t usbos_list_cnt;
386     wait_queue_head_t usbos_queue_head;
387     struct task_struct *usbos_kt;
388 #endif /* USBOS_THREAD */
389 
390 #ifdef USBOS_TX_THREAD
391     spinlock_t usbos_tx_list_lock;
392     struct list_head usbos_tx_list;
393     wait_queue_head_t usbos_tx_queue_head;
394     struct task_struct *usbos_tx_kt;
395 #endif /* USBOS_TX_THREAD */
396 
397     struct dma_pool *qtd_pool;     /* QTD pool for USB optimization only */
398     int tx_ep, rx_ep, rx2_ep;      /* EPs for USB optimization */
399     struct usb_device *usb_device; /* USB device for optimization */
400 } usbos_info_t;
401 
402 typedef struct urb_req {
403     void *pkt;
404     int buf_len;
405     struct urb *urb;
406     void *arg;
407     usbos_info_t *usbinfo;
408     struct list_head urb_list;
409 } urb_req_t;
410 
411 #ifdef USBOS_THREAD
412 typedef struct usbos_list_entry {
413     struct list_head list; /* must be first */
414     void *urb_context;
415     int urb_length;
416     int urb_status;
417 } usbos_list_entry_t;
418 
419 static void *dbus_usbos_thread_init(usbos_info_t *usbos_info);
420 static void dbus_usbos_thread_deinit(usbos_info_t *usbos_info);
421 static void dbus_usbos_dispatch_schedule(CALLBACK_ARGS);
422 static int dbus_usbos_thread_func(void *data);
423 #endif /* USBOS_THREAD */
424 
425 #ifdef USBOS_TX_THREAD
426 void *dbus_usbos_tx_thread_init(usbos_info_t *usbos_info);
427 void dbus_usbos_tx_thread_deinit(usbos_info_t *usbos_info);
428 int dbus_usbos_tx_thread_func(void *data);
429 #endif /* USBOS_TX_THREAD */
430 
431 /* Shared Function prototypes */
432 bool dbus_usbos_dl_cmd(usbos_info_t *usbinfo, uint8 cmd, void *buffer,
433                        int buflen);
434 int dbus_usbos_wait(usbos_info_t *usbinfo, uint16 ms);
435 bool dbus_usbos_dl_send_bulk(usbos_info_t *usbinfo, void *buffer, int len);
436 int dbus_write_membytes(usbos_info_t *usbinfo, bool set, uint32 address,
437                         uint8 *data, uint size);
438 
439 /* Local function prototypes */
440 static void dbus_usbos_send_complete(CALLBACK_ARGS);
441 static void dbus_usbos_recv_complete(CALLBACK_ARGS);
442 static int dbus_usbos_errhandler(void *bus, int err);
443 static int dbus_usbos_state_change(void *bus, int state);
444 static void dbusos_stop(usbos_info_t *usbos_info);
445 
446 #ifdef KERNEL26
447 static int dbus_usbos_probe(struct usb_interface *intf,
448                             const struct usb_device_id *id);
449 static void dbus_usbos_disconnect(struct usb_interface *intf);
450 #if defined(USB_SUSPEND_AVAILABLE)
451 static int dbus_usbos_resume(struct usb_interface *intf);
452 static int dbus_usbos_suspend(struct usb_interface *intf, pm_message_t message);
453 /* at the moment, used for full dongle host driver only */
454 static int dbus_usbos_reset_resume(struct usb_interface *intf);
455 #endif /* USB_SUSPEND_AVAILABLE */
456 #else  /* KERNEL26 */
457 static void *dbus_usbos_probe(struct usb_device *usb, unsigned int ifnum,
458                               const struct usb_device_id *id);
459 static void dbus_usbos_disconnect(struct usb_device *usb, void *ptr);
460 #endif /* KERNEL26 */
461 
462 /**
463  * have to disable missing-field-initializers warning as last element {}
464  * triggers it and different versions of kernel have different number of members
465  * so it is impossible to specify the initializer. BTW issuing the warning here
466  * is bug og GCC as  universal zero {0} specified in C99 standard as correct way
467  * of initialization of struct to all zeros
468  */
469 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) &&                       \
470     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
471 #pragma GCC diagnostic push
472 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
473 #endif
474 
475 static struct usb_device_id devid_table[] = {
476     {USB_DEVICE(BCM_DNGL_VID, 0x0000)}, /* Configurable via register() */
477 #if defined(BCM_REQUEST_FW)
478     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4328)},
479     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4322)},
480     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4319)},
481     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43236)},
482     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43143)},
483     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43242)},
484     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4360)},
485     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4350)},
486     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43569)},
487 #endif
488 #ifdef EXTENDED_VID_PID
489     EXTENDED_VID_PID,
490 #endif                                            /* EXTENDED_VID_PID */
491     {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BDC_PID)}, /* Default BDC */
492     {}};
493 
494 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) &&                       \
495     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
496 #pragma GCC diagnostic pop
497 #endif
498 
499 MODULE_DEVICE_TABLE(usb, devid_table);
500 
501 /** functions called by the Linux kernel USB subsystem */
502 static struct usb_driver dbus_usbdev = {
503     name : "dbus_usbdev",
504     probe : dbus_usbos_probe,
505     disconnect : dbus_usbos_disconnect,
506     id_table : devid_table,
507 #if defined(USB_SUSPEND_AVAILABLE)
508     suspend : dbus_usbos_suspend,
509     resume : dbus_usbos_resume,
510     reset_resume : dbus_usbos_reset_resume,
511     /* Linux USB core will allow autosuspend for devices bound to this driver */
512     supports_autosuspend : 1
513 #endif /* USB_SUSPEND_AVAILABLE */
514 };
515 
516 /**
517  * This stores USB info during Linux probe callback since attach() is not called
518  * yet at this point
519  */
520 typedef struct {
521     void *usbos_info;
522     struct usb_device *usb; /* USB device pointer from OS */
523     uint rx_pipe;           /* Pipe numbers for USB I/O */
524     uint tx_pipe;           /* Pipe numbers for USB I/O */
525     uint intr_pipe;         /* Pipe numbers for USB I/O */
526     uint rx_pipe2;          /* Pipe numbers for USB I/O */
527     int intr_size;          /* Size of interrupt message */
528     int interval;           /* Interrupt polling interval */
529     bool dldone;
530     int vid;
531     int pid;
532     bool dereged;
533     bool disc_cb_done;
534     DEVICE_SPEED device_speed;
535     enum usbos_suspend_state suspend_state;
536     struct usb_interface *intf;
537 } probe_info_t;
538 
539 /*
540  * USB Linux dbus_intf_t
541  */
542 static void *dbus_usbos_intf_attach(dbus_pub_t *pub, void *cbarg,
543                                     dbus_intf_callbacks_t *cbs);
544 static void dbus_usbos_intf_detach(dbus_pub_t *pub, void *info);
545 static int dbus_usbos_intf_send_irb(void *bus, dbus_irb_tx_t *txirb);
546 static int dbus_usbos_intf_recv_irb(void *bus, dbus_irb_rx_t *rxirb);
547 static int dbus_usbos_intf_recv_irb_from_ep(void *bus, dbus_irb_rx_t *rxirb,
548                                             uint32 ep_idx);
549 static int dbus_usbos_intf_cancel_irb(void *bus, dbus_irb_tx_t *txirb);
550 static int dbus_usbos_intf_send_ctl(void *bus, uint8 *buf, int len);
551 static int dbus_usbos_intf_recv_ctl(void *bus, uint8 *buf, int len);
552 static int dbus_usbos_intf_get_attrib(void *bus, dbus_attrib_t *attrib);
553 static int dbus_usbos_intf_up(void *bus);
554 static int dbus_usbos_intf_down(void *bus);
555 static int dbus_usbos_intf_stop(void *bus);
556 static int dbus_usbos_readreg(void *bus, uint32 regaddr, int datalen,
557                               uint32 *value);
558 extern int dbus_usbos_loopback_tx(void *usbos_info_ptr, int cnt, int size);
559 int dbus_usbos_writereg(void *bus, uint32 regaddr, int datalen, uint32 data);
560 static int dbus_usbos_intf_set_config(void *bus, dbus_config_t *config);
561 static bool dbus_usbos_intf_recv_needed(void *bus);
562 static void *dbus_usbos_intf_exec_rxlock(void *bus, exec_cb_t cb,
563                                          struct exec_parms *args);
564 static void *dbus_usbos_intf_exec_txlock(void *bus, exec_cb_t cb,
565                                          struct exec_parms *args);
566 #ifdef BCMUSBDEV_COMPOSITE
567 static int dbus_usbos_intf_wlan(struct usb_device *usb);
568 #endif /* BCMUSBDEV_COMPOSITE */
569 
570 /** functions called by dbus_usb.c */
571 static dbus_intf_t dbus_usbos_intf = {
572     .attach = dbus_usbos_intf_attach,
573     .detach = dbus_usbos_intf_detach,
574     .up = dbus_usbos_intf_up,
575     .down = dbus_usbos_intf_down,
576     .send_irb = dbus_usbos_intf_send_irb,
577     .recv_irb = dbus_usbos_intf_recv_irb,
578     .cancel_irb = dbus_usbos_intf_cancel_irb,
579     .send_ctl = dbus_usbos_intf_send_ctl,
580     .recv_ctl = dbus_usbos_intf_recv_ctl,
581     .get_stats = NULL,
582     .get_attrib = dbus_usbos_intf_get_attrib,
583     .remove = NULL,
584     .resume = NULL,
585     .suspend = NULL,
586     .stop = dbus_usbos_intf_stop,
587     .reset = NULL,
588     .pktget = NULL,
589     .pktfree = NULL,
590     .iovar_op = NULL,
591     .dump = NULL,
592     .set_config = dbus_usbos_intf_set_config,
593     .get_config = NULL,
594     .device_exists = NULL,
595     .dlneeded = NULL,
596     .dlstart = NULL,
597     .dlrun = NULL,
598     .recv_needed = dbus_usbos_intf_recv_needed,
599     .exec_rxlock = dbus_usbos_intf_exec_rxlock,
600     .exec_txlock = dbus_usbos_intf_exec_txlock,
601 
602     .tx_timer_init = NULL,
603     .tx_timer_start = NULL,
604     .tx_timer_stop = NULL,
605 
606     .sched_dpc = NULL,
607     .lock = NULL,
608     .unlock = NULL,
609     .sched_probe_cb = NULL,
610 
611     .shutdown = NULL,
612 
613     .recv_stop = NULL,
614     .recv_resume = NULL,
615 
616     .recv_irb_from_ep = dbus_usbos_intf_recv_irb_from_ep,
617     .readreg = dbus_usbos_readreg};
618 
619 static probe_info_t g_probe_info;
620 static probe_cb_t probe_cb = NULL;
621 static disconnect_cb_t disconnect_cb = NULL;
622 static void *probe_arg = NULL;
623 static void *disc_arg = NULL;
624 
625 static volatile int loopback_rx_cnt, loopback_tx_cnt;
626 int loopback_size;
627 bool is_loopback_pkt(void *buf);
628 int matches_loopback_pkt(void *buf);
629 
630 /**
631  * multiple code paths in this file dequeue a URB request, this function makes
632  * sure that it happens in a concurrency save manner. Don't call this from a
633  * sleepable process context.
634  */
dbus_usbos_qdeq(struct list_head * urbreq_q,spinlock_t * lock)635 static urb_req_t *BCMFASTPATH dbus_usbos_qdeq(struct list_head *urbreq_q,
636                                               spinlock_t *lock)
637 {
638     unsigned long flags;
639     urb_req_t *req;
640 
641     ASSERT(urbreq_q != NULL);
642 
643     spin_lock_irqsave(lock, flags);
644 
645     if (list_empty(urbreq_q)) {
646         req = NULL;
647     } else {
648         ASSERT(urbreq_q->next != NULL);
649         ASSERT(urbreq_q->next != urbreq_q);
650 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
651 #pragma GCC diagnostic push
652 #pragma GCC diagnostic ignored "-Wcast-qual"
653 #endif
654         req = list_entry(urbreq_q->next, urb_req_t, urb_list);
655 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
656 #pragma GCC diagnostic pop
657 #endif
658         list_del_init(&req->urb_list);
659     }
660 
661     spin_unlock_irqrestore(lock, flags);
662 
663     return req;
664 }
665 
dbus_usbos_qenq(struct list_head * urbreq_q,urb_req_t * req,spinlock_t * lock)666 static void BCMFASTPATH dbus_usbos_qenq(struct list_head *urbreq_q,
667                                         urb_req_t *req, spinlock_t *lock)
668 {
669     unsigned long flags;
670 
671     spin_lock_irqsave(lock, flags);
672 
673     list_add_tail(&req->urb_list, urbreq_q);
674 
675     spin_unlock_irqrestore(lock, flags);
676 }
677 
678 /**
679  * multiple code paths in this file remove a URB request from a list, this
680  * function makes sure that it happens in a concurrency save manner. Don't call
681  * this from a sleepable process context. Is quite similar to dbus_usbos_qdeq(),
682  * I wonder why this function is needed.
683  */
dbus_usbos_req_del(urb_req_t * req,spinlock_t * lock)684 static void dbus_usbos_req_del(urb_req_t *req, spinlock_t *lock)
685 {
686     unsigned long flags;
687 
688     spin_lock_irqsave(lock, flags);
689 
690     list_del_init(&req->urb_list);
691 
692     spin_unlock_irqrestore(lock, flags);
693 }
694 
695 /**
696  * Driver requires a pool of URBs to operate. This function is called during
697  * initialization (attach phase), allocates a number of URBs, and puts them
698  * on the free (req_rxfreeq and req_txfreeq) queue
699  */
dbus_usbos_urbreqs_alloc(usbos_info_t * usbos_info,uint32 count,bool is_rx)700 static int dbus_usbos_urbreqs_alloc(usbos_info_t *usbos_info, uint32 count,
701                                     bool is_rx)
702 {
703     int i;
704     int allocated = 0;
705     int err = DBUS_OK;
706 
707     for (i = 0; i < count; i++) {
708         urb_req_t *req;
709 
710         req = MALLOC(usbos_info->pub->osh, sizeof(urb_req_t));
711         if (req == NULL) {
712             DBUSERR(("%s: MALLOC req failed\n", __FUNCTION__));
713             err = DBUS_ERR_NOMEM;
714             goto fail;
715         }
716         bzero(req, sizeof(urb_req_t));
717 
718         req->urb = USB_ALLOC_URB();
719         if (req->urb == NULL) {
720             DBUSERR(("%s: USB_ALLOC_URB req->urb failed\n", __FUNCTION__));
721             err = DBUS_ERR_NOMEM;
722             goto fail;
723         }
724 
725         INIT_LIST_HEAD(&req->urb_list);
726 
727         if (is_rx) {
728 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
729             /* don't allocate now. Do it on demand */
730             req->pkt = NULL;
731 #else
732             /* pre-allocate  buffers never to be released */
733             req->pkt = MALLOC(usbos_info->pub->osh, usbos_info->rxbuf_len);
734             if (req->pkt == NULL) {
735                 DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__));
736                 err = DBUS_ERR_NOMEM;
737                 goto fail;
738             }
739 #endif
740             req->buf_len = usbos_info->rxbuf_len;
741             dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
742                             &usbos_info->rxfree_lock);
743         } else {
744             req->buf_len = 0;
745             dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
746                             &usbos_info->txfree_lock);
747         }
748         allocated++;
749         continue;
750 
751     fail:
752         if (req) {
753             if (is_rx && req->pkt) {
754 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
755                 /* req->pkt is NULL in "NOCOPY" mode */
756 #else
757                 MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
758 #endif
759             }
760             if (req->urb) {
761                 USB_FREE_URB(req->urb);
762             }
763             MFREE(usbos_info->pub->osh, req, sizeof(urb_req_t));
764         }
765         break;
766     }
767 
768     atomic_add(allocated,
769                is_rx ? &usbos_info->rxallocated : &usbos_info->txallocated);
770 
771     if (is_rx) {
772         DBUSTRACE(("%s: add %d (total %d) rx buf, each has %d bytes\n",
773                    __FUNCTION__, allocated,
774                    atomic_read(&usbos_info->rxallocated),
775                    usbos_info->rxbuf_len));
776     } else {
777         DBUSTRACE(("%s: add %d (total %d) tx req\n", __FUNCTION__, allocated,
778                    atomic_read(&usbos_info->txallocated)));
779     }
780 
781     return err;
782 } /* dbus_usbos_urbreqs_alloc */
783 
784 /** Typically called during detach or when attach failed. Don't call until all
785  * URBs unlinked */
dbus_usbos_urbreqs_free(usbos_info_t * usbos_info,bool is_rx)786 static int dbus_usbos_urbreqs_free(usbos_info_t *usbos_info, bool is_rx)
787 {
788     int rtn = 0;
789     urb_req_t *req;
790     struct list_head *req_q;
791     spinlock_t *lock;
792 
793     if (is_rx) {
794         req_q = &usbos_info->req_rxfreeq;
795         lock = &usbos_info->rxfree_lock;
796     } else {
797         req_q = &usbos_info->req_txfreeq;
798         lock = &usbos_info->txfree_lock;
799     }
800     while ((req = dbus_usbos_qdeq(req_q, lock)) != NULL) {
801         if (is_rx) {
802             if (req->pkt) {
803                 /* We do MFREE instead of PKTFREE because the pkt has been
804                  * converted to native already
805                  */
806                 MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
807                 req->pkt = NULL;
808                 req->buf_len = 0;
809             }
810         } else {
811             /* sending req should not be assigned pkt buffer */
812             ASSERT(req->pkt == NULL);
813         }
814 
815         if (req->urb) {
816             USB_FREE_URB(req->urb);
817             req->urb = NULL;
818         }
819         MFREE(usbos_info->pub->osh, req, sizeof(urb_req_t));
820 
821         rtn++;
822     }
823     return rtn;
824 } /* dbus_usbos_urbreqs_free */
825 
826 /**
827  * called by Linux kernel on URB completion. Upper DBUS layer (dbus_usb.c) has
828  * to be notified of send completion.
829  */
dbus_usbos_send_complete(CALLBACK_ARGS)830 void dbus_usbos_send_complete(CALLBACK_ARGS)
831 {
832     urb_req_t *req = urb->context;
833     dbus_irb_tx_t *txirb = req->arg;
834     usbos_info_t *usbos_info = req->usbinfo;
835     unsigned long flags;
836     int status = DBUS_OK;
837     int txposted;
838 
839     USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
840 
841     spin_lock_irqsave(&usbos_info->txlock, flags);
842 
843     dbus_usbos_req_del(req, &usbos_info->txposted_lock);
844     txposted = atomic_dec_return(&usbos_info->txposted);
845     if (unlikely(txposted < 0)) {
846         DBUSERR(("%s ERROR: txposted is negative (%d)!!\n", __FUNCTION__,
847                  txposted));
848     }
849     spin_unlock_irqrestore(&usbos_info->txlock, flags);
850 
851     if (unlikely(urb->status)) {
852         status = DBUS_ERR_TXFAIL;
853         DBUSTRACE(("txfail status %d\n", urb->status));
854     }
855 
856 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
857     /* sending req should not be assigned pkt buffer */
858     ASSERT(req->pkt == NULL);
859 #endif
860     /*  txirb should always be set, except for ZLP. ZLP is reusing this callback
861      * function. */
862     if (txirb != NULL) {
863         if (txirb->send_buf != NULL) {
864             MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
865             txirb->send_buf = NULL;
866             req->buf_len = 0;
867         }
868         if (likely(usbos_info->cbarg && usbos_info->cbs)) {
869             if (likely(usbos_info->cbs->send_irb_complete != NULL)) {
870                 usbos_info->cbs->send_irb_complete(usbos_info->cbarg, txirb,
871                                                    status);
872             }
873         }
874     }
875 
876     dbus_usbos_qenq(&usbos_info->req_txfreeq, req, &usbos_info->txfree_lock);
877 } /* dbus_usbos_send_complete */
878 
879 /**
880  * In order to receive USB traffic from the dongle, we need to supply the Linux
881  * kernel with a free URB that is going to contain received data.
882  */
dbus_usbos_recv_urb_submit(usbos_info_t * usbos_info,dbus_irb_rx_t * rxirb,uint32 ep_idx)883 static int BCMFASTPATH dbus_usbos_recv_urb_submit(usbos_info_t *usbos_info,
884                                                   dbus_irb_rx_t *rxirb,
885                                                   uint32 ep_idx)
886 {
887     urb_req_t *req;
888     int ret = DBUS_OK;
889     unsigned long flags;
890     void *p;
891     uint rx_pipe;
892     int rxposted;
893 
894     BCM_REFERENCE(rxposted);
895 
896     if (!(req = dbus_usbos_qdeq(&usbos_info->req_rxfreeq,
897                                 &usbos_info->rxfree_lock))) {
898         DBUSTRACE(("%s No free URB!\n", __FUNCTION__));
899         return DBUS_ERR_RXDROP;
900     }
901 
902     spin_lock_irqsave(&usbos_info->rxlock, flags);
903 
904 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
905     req->pkt = rxirb->pkt = PKTGET(usbos_info->pub->osh, req->buf_len, FALSE);
906     if (!rxirb->pkt) {
907         DBUSERR(("%s: PKTGET failed\n", __FUNCTION__));
908         dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
909                         &usbos_info->rxfree_lock);
910         ret = DBUS_ERR_RXDROP;
911         goto fail;
912     }
913     /* consider the packet "native" so we don't count it as MALLOCED in the osl
914      */
915     PKTTONATIVE(usbos_info->pub->osh, req->pkt);
916     rxirb->buf = NULL;
917     p = PKTDATA(usbos_info->pub->osh, req->pkt);
918 #else
919     if (req->buf_len != usbos_info->rxbuf_len) {
920         ASSERT(req->pkt);
921         MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
922         DBUSTRACE(("%s: replace rx buff: old len %d, new len %d\n",
923                    __FUNCTION__, req->buf_len, usbos_info->rxbuf_len));
924         req->buf_len = 0;
925         req->pkt = MALLOC(usbos_info->pub->osh, usbos_info->rxbuf_len);
926         if (req->pkt == NULL) {
927             DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__));
928             ret = DBUS_ERR_NOMEM;
929             goto fail;
930         }
931         req->buf_len = usbos_info->rxbuf_len;
932     }
933     rxirb->buf = req->pkt;
934     p = rxirb->buf;
935 #endif /* defined(BCM_RPC_NOCOPY) */
936     rxirb->buf_len = req->buf_len;
937     req->usbinfo = usbos_info;
938     req->arg = rxirb;
939     if (ep_idx == 0) {
940         rx_pipe = usbos_info->rx_pipe;
941     } else {
942         rx_pipe = usbos_info->rx_pipe2;
943         ASSERT(usbos_info->rx_pipe2);
944     }
945     /* Prepare the URB */
946     usb_fill_bulk_urb(req->urb, usbos_info->usb, rx_pipe, p, rxirb->buf_len,
947                       (usb_complete_t)dbus_usbos_recv_complete, req);
948     req->urb->transfer_flags |= URB_QUEUE_BULK;
949 
950     if ((ret = USB_SUBMIT_URB(req->urb))) {
951         DBUSERR(("%s USB_SUBMIT_URB failed. status %d\n", __FUNCTION__, ret));
952         dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
953                         &usbos_info->rxfree_lock);
954         ret = DBUS_ERR_RXFAIL;
955         goto fail;
956     }
957     rxposted = atomic_inc_return(&usbos_info->rxposted);
958 
959     dbus_usbos_qenq(&usbos_info->req_rxpostedq, req,
960                     &usbos_info->rxposted_lock);
961 fail:
962     spin_unlock_irqrestore(&usbos_info->rxlock, flags);
963     return ret;
964 } /* dbus_usbos_recv_urb_submit */
965 
966 /**
967  * Called by worked thread when a 'receive URB' completed or Linux kernel when
968  * it returns a URB to this driver.
969  */
dbus_usbos_recv_complete_handle(urb_req_t * req,int len,int status)970 static void BCMFASTPATH dbus_usbos_recv_complete_handle(urb_req_t *req, int len,
971                                                         int status)
972 {
973     dbus_irb_rx_t *rxirb = req->arg;
974     usbos_info_t *usbos_info = req->usbinfo;
975     unsigned long flags;
976     int rxallocated, rxposted;
977     int dbus_status = DBUS_OK;
978     bool killed =
979         (g_probe_info.suspend_state == USBOS_SUSPEND_STATE_SUSPEND_PENDING) ? 1
980                                                                             : 0;
981 
982     spin_lock_irqsave(&usbos_info->rxlock, flags);
983     dbus_usbos_req_del(req, &usbos_info->rxposted_lock);
984     rxposted = atomic_dec_return(&usbos_info->rxposted);
985     rxallocated = atomic_read(&usbos_info->rxallocated);
986     spin_unlock_irqrestore(&usbos_info->rxlock, flags);
987 
988     if ((rxallocated < usbos_info->pub->nrxq) && (!status) &&
989         (rxposted == DBUS_USB_RXQUEUE_LOWER_WATERMARK)) {
990         DBUSTRACE(("%s: need more rx buf: rxallocated %d rxposted %d!\n",
991                    __FUNCTION__, rxallocated, rxposted));
992         dbus_usbos_urbreqs_alloc(usbos_info,
993                                  MIN(DBUS_USB_RXQUEUE_BATCH_ADD,
994                                      usbos_info->pub->nrxq - rxallocated),
995                                  TRUE);
996     }
997 
998     /* Handle errors */
999     if (status) {
1000         /*
1001          * Linux 2.4 disconnect: -ENOENT or -EILSEQ for CRC error; rmmod:
1002          * -ENOENT Linux 2.6 disconnect: -EPROTO, rmmod: -ESHUTDOWN
1003          */
1004         if ((status == -ENOENT && (!killed)) || status == -ESHUTDOWN) {
1005             /* NOTE: unlink() can not be called from URB callback().
1006              * Do not call dbusos_stop() here.
1007              */
1008             DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1009             dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1010         } else if (status == -EPROTO) {
1011             DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1012         } else if (killed && (status == -EHOSTUNREACH || status == -ENOENT)) {
1013             /* Device is suspended */
1014         } else {
1015             DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1016             dbus_usbos_errhandler(usbos_info, DBUS_ERR_RXFAIL);
1017         }
1018 
1019         /* On error, don't submit more URBs yet */
1020         rxirb->buf = NULL;
1021         rxirb->actual_len = 0;
1022         dbus_status = DBUS_ERR_RXFAIL;
1023         goto fail;
1024     }
1025 
1026     /* Make the skb represent the received urb */
1027     rxirb->actual_len = len;
1028 
1029     if (rxirb->actual_len < sizeof(uint32)) {
1030         DBUSTRACE(("small pkt len %d, process as ZLP\n", rxirb->actual_len));
1031         dbus_status = DBUS_ERR_RXZLP;
1032     }
1033 
1034 fail:
1035 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
1036     /* detach the packet from the queue */
1037     req->pkt = NULL;
1038 #endif /* BCM_RPC_NOCOPY || BCM_RPC_RXNOCOPY */
1039 
1040     if (usbos_info->cbarg && usbos_info->cbs) {
1041         if (usbos_info->cbs->recv_irb_complete) {
1042             usbos_info->cbs->recv_irb_complete(usbos_info->cbarg, rxirb,
1043                                                dbus_status);
1044         }
1045     }
1046 
1047     dbus_usbos_qenq(&usbos_info->req_rxfreeq, req, &usbos_info->rxfree_lock);
1048 
1049     /* Mark the interface as busy to reset USB autosuspend timer */
1050     USB_MARK_LAST_BUSY(usbos_info->usb);
1051 } /* dbus_usbos_recv_complete_handle */
1052 
1053 /** called by Linux kernel when it returns a URB to this driver */
dbus_usbos_recv_complete(CALLBACK_ARGS)1054 static void dbus_usbos_recv_complete(CALLBACK_ARGS)
1055 {
1056 #ifdef USBOS_THREAD
1057     dbus_usbos_dispatch_schedule(CALLBACK_ARGS_DATA);
1058 #else  /*  !USBOS_THREAD */
1059     dbus_usbos_recv_complete_handle(urb->context, urb->actual_length,
1060                                     urb->status);
1061 #endif /*  USBOS_THREAD */
1062 }
1063 
1064 /**
1065  * If Linux notifies our driver that a control read or write URB has completed,
1066  * we should notify the DBUS layer above us (dbus_usb.c in this case).
1067  */
dbus_usbos_ctl_complete(usbos_info_t * usbos_info,int type,int urbstatus)1068 static void dbus_usbos_ctl_complete(usbos_info_t *usbos_info, int type,
1069                                     int urbstatus)
1070 {
1071     int status = DBUS_ERR;
1072 
1073     if (usbos_info == NULL) {
1074         return;
1075     }
1076 
1077     switch (urbstatus) {
1078         case 0:
1079             status = DBUS_OK;
1080             break;
1081         case -EINPROGRESS:
1082         case -ENOENT:
1083         default:
1084 #ifdef INTR_EP_ENABLE
1085             DBUSERR((
1086                 "%s:%d fail status %d bus:%d susp:%d intr:%d ctli:%d ctlo:%d\n",
1087                 __FUNCTION__, type, urbstatus, usbos_info->pub->busstate,
1088                 g_probe_info.suspend_state, usbos_info->intr_urb_submitted,
1089                 usbos_info->ctlin_urb_submitted,
1090                 usbos_info->ctlout_urb_submitted));
1091 #else
1092             DBUSERR(("%s: failed with status %d\n", __FUNCTION__, urbstatus));
1093             status = DBUS_ERR;
1094             break;
1095 #endif /* INTR_EP_ENABLE */
1096     }
1097 
1098     if (usbos_info->cbarg && usbos_info->cbs) {
1099         if (usbos_info->cbs->ctl_complete) {
1100             usbos_info->cbs->ctl_complete(usbos_info->cbarg, type, status);
1101         }
1102     }
1103 }
1104 
1105 /** called by Linux */
dbus_usbos_ctlread_complete(CALLBACK_ARGS)1106 static void dbus_usbos_ctlread_complete(CALLBACK_ARGS)
1107 {
1108     usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1109 
1110     ASSERT(urb);
1111     usbos_info = (usbos_info_t *)urb->context;
1112 
1113     dbus_usbos_ctl_complete(usbos_info, DBUS_CBCTL_READ, urb->status);
1114 
1115 #ifdef USBOS_THREAD
1116     if (usbos_info->rxctl_deferrespok) {
1117         usbos_info->ctl_read.bRequestType =
1118             USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
1119         usbos_info->ctl_read.bRequest = 1;
1120     }
1121 #endif
1122 
1123     up(&usbos_info->ctl_lock);
1124 
1125     USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
1126 }
1127 
1128 /** called by Linux */
dbus_usbos_ctlwrite_complete(CALLBACK_ARGS)1129 static void dbus_usbos_ctlwrite_complete(CALLBACK_ARGS)
1130 {
1131     usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1132 
1133     ASSERT(urb);
1134     usbos_info = (usbos_info_t *)urb->context;
1135 
1136     dbus_usbos_ctl_complete(usbos_info, DBUS_CBCTL_WRITE, urb->status);
1137 
1138 #ifdef USBOS_TX_THREAD
1139     usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
1140 #endif /* USBOS_TX_THREAD */
1141 
1142     up(&usbos_info->ctl_lock);
1143 
1144     USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
1145 }
1146 
1147 #ifdef INTR_EP_ENABLE
1148 /** called by Linux */
dbus_usbos_intr_complete(CALLBACK_ARGS)1149 static void dbus_usbos_intr_complete(CALLBACK_ARGS)
1150 {
1151     usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1152     bool killed =
1153         (g_probe_info.suspend_state == USBOS_SUSPEND_STATE_SUSPEND_PENDING) ? 1
1154                                                                             : 0;
1155 
1156     if (usbos_info == NULL || usbos_info->pub == NULL) {
1157         return;
1158     }
1159     if ((urb->status == -ENOENT && (!killed)) || urb->status == -ESHUTDOWN ||
1160         urb->status == -ENODEV) {
1161         dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1162     }
1163 
1164     if (usbos_info->pub->busstate == DBUS_STATE_DOWN) {
1165         DBUSERR(("%s: intr cb when DBUS down, ignoring\n", __FUNCTION__));
1166         return;
1167     }
1168     dbus_usbos_ctl_complete(usbos_info, DBUS_CBINTR_POLL, urb->status);
1169 }
1170 #endif /* INTR_EP_ENABLE */
1171 
1172 /**
1173  * when the bus is going to sleep or halt, the Linux kernel requires us to take
1174  * ownership of our URBs again. Multiple code paths in this file require a list
1175  * of URBs to be cancelled in a concurrency save manner.
1176  */
dbus_usbos_unlink(struct list_head * urbreq_q,spinlock_t * lock)1177 static void dbus_usbos_unlink(struct list_head *urbreq_q, spinlock_t *lock)
1178 {
1179     urb_req_t *req;
1180 
1181     /* dbus_usbos_recv_complete() adds req back to req_freeq */
1182     while ((req = dbus_usbos_qdeq(urbreq_q, lock)) != NULL) {
1183         ASSERT(req->urb != NULL);
1184         USB_UNLINK_URB(req->urb);
1185     }
1186 }
1187 
1188 /** multiple code paths in this file require the bus to stop */
dbus_usbos_cancel_all_urbs(usbos_info_t * usbos_info)1189 static void dbus_usbos_cancel_all_urbs(usbos_info_t *usbos_info)
1190 {
1191     int rxposted, txposted;
1192 
1193     DBUSTRACE(("%s: unlink all URBs\n", __FUNCTION__));
1194 
1195 #ifdef USBOS_TX_THREAD
1196     usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
1197 
1198     /* Yield the CPU to TX thread so all pending requests are submitted */
1199     while (!list_empty(&usbos_info->usbos_tx_list)) {
1200         wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
1201         OSL_SLEEP(0xA);
1202     }
1203 #endif /* USBOS_TX_THREAD */
1204 
1205     /* tell Linux kernel to cancel a single intr, ctl and blk URB */
1206     if (usbos_info->intr_urb) {
1207         USB_UNLINK_URB(usbos_info->intr_urb);
1208     }
1209     if (usbos_info->ctl_urb) {
1210         USB_UNLINK_URB(usbos_info->ctl_urb);
1211     }
1212     if (usbos_info->blk_urb) {
1213         USB_UNLINK_URB(usbos_info->blk_urb);
1214     }
1215 
1216     dbus_usbos_unlink(&usbos_info->req_txpostedq, &usbos_info->txposted_lock);
1217     dbus_usbos_unlink(&usbos_info->req_rxpostedq, &usbos_info->rxposted_lock);
1218 
1219     /* Wait until the callbacks for all submitted URBs have been called, because
1220      * the handler needs to know is an USB suspend is in progress.
1221      */
1222     SPINWAIT((atomic_read(&usbos_info->txposted) != 0 ||
1223               atomic_read(&usbos_info->rxposted) != 0),
1224              0x2710);
1225 
1226     txposted = atomic_read(&usbos_info->txposted);
1227     rxposted = atomic_read(&usbos_info->rxposted);
1228     if (txposted != 0 || rxposted != 0) {
1229         DBUSERR(("%s ERROR: REQs posted, rx=%d tx=%d!\n", __FUNCTION__,
1230                  rxposted, txposted));
1231     }
1232 } /* dbus_usbos_cancel_all_urbs */
1233 
1234 /** multiple code paths require the bus to stop */
dbusos_stop(usbos_info_t * usbos_info)1235 static void dbusos_stop(usbos_info_t *usbos_info)
1236 {
1237     urb_req_t *req;
1238     int rxposted;
1239     req = NULL;
1240     BCM_REFERENCE(req);
1241 
1242     ASSERT(usbos_info);
1243 
1244     dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1245 
1246     dbus_usbos_cancel_all_urbs(usbos_info);
1247 
1248 #ifdef USBOS_THREAD
1249     /* yield the CPU to rx packet thread */
1250     while (1) {
1251         if (atomic_read(&usbos_info->usbos_list_cnt) <= 0) {
1252             break;
1253         }
1254         wake_up_interruptible(&usbos_info->usbos_queue_head);
1255         OSL_SLEEP(0x3);
1256     }
1257 #endif /* USBOS_THREAD */
1258 
1259     rxposted = atomic_read(&usbos_info->rxposted);
1260     if (rxposted > 0) {
1261         DBUSERR(
1262             ("%s ERROR: rx REQs posted=%d in stop!\n", __FUNCTION__, rxposted));
1263     }
1264 
1265     ASSERT(atomic_read(&usbos_info->txposted) == 0 && rxposted == 0);
1266 } /* dbusos_stop */
1267 
1268 #if defined(USB_SUSPEND_AVAILABLE)
1269 
1270 /**
1271  * Linux kernel sports a 'USB auto suspend' feature. See:
1272  * http://lwn.net/Articles/373550/ The suspend method is called by the Linux
1273  * kernel to warn the driver that the device is going to be suspended.  If the
1274  * driver returns a negative error code, the suspend will be aborted. If the
1275  * driver returns 0, it must cancel all outstanding URBs (usb_kill_urb()) and
1276  * not submit any more.
1277  */
dbus_usbos_suspend(struct usb_interface * intf,pm_message_t message)1278 static int dbus_usbos_suspend(struct usb_interface *intf, pm_message_t message)
1279 {
1280     DBUSERR(
1281         ("%s suspend state: %d\n", __FUNCTION__, g_probe_info.suspend_state));
1282     /* DHD for full dongle model */
1283     g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPEND_PENDING;
1284     dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1285                             DBUS_STATE_SLEEP);
1286     dbus_usbos_cancel_all_urbs((usbos_info_t *)g_probe_info.usbos_info);
1287     g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
1288 
1289     return 0;
1290 }
1291 
1292 /**
1293  * The resume method is called to tell the driver that the device has been
1294  * resumed and the driver can return to normal operation.  URBs may once more be
1295  * submitted.
1296  */
dbus_usbos_resume(struct usb_interface * intf)1297 static int dbus_usbos_resume(struct usb_interface *intf)
1298 {
1299     DBUSERR(("%s Device resumed\n", __FUNCTION__));
1300 
1301     dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1302                             DBUS_STATE_UP);
1303     g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1304     return 0;
1305 }
1306 
1307 /**
1308  * This function is directly called by the Linux kernel, when the suspended
1309  * device has been reset instead of being resumed
1310  */
dbus_usbos_reset_resume(struct usb_interface * intf)1311 static int dbus_usbos_reset_resume(struct usb_interface *intf)
1312 {
1313     DBUSERR(("%s Device reset resumed\n", __FUNCTION__));
1314 
1315     /* The device may have lost power, so a firmware download may be required */
1316     dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1317                             DBUS_STATE_DL_NEEDED);
1318     g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1319     return 0;
1320 }
1321 
1322 #endif /* USB_SUSPEND_AVAILABLE */
1323 
1324 /**
1325  * Called by Linux kernel at initialization time, kernel wants to know if our
1326  * driver will accept the caller supplied USB interface. Note that USB drivers
1327  * are bound to interfaces, and not to USB devices.
1328  */
1329 #ifdef KERNEL26
1330 #define DBUS_USBOS_PROBE()                                                     \
1331     static int dbus_usbos_probe(struct usb_interface *intf,                    \
1332                                 const struct usb_device_id *id)
1333 #define DBUS_USBOS_DISCONNECT()                                                \
1334     static void dbus_usbos_disconnect(struct usb_interface *intf)
1335 #else
1336 #define DBUS_USBOS_PROBE()                                                     \
1337     static void *dbus_usbos_probe(struct usb_device *usb, unsigned int ifnum,  \
1338                                   const struct usb_device_id *id)
1339 #define DBUS_USBOS_DISCONNECT()                                                \
1340     static void dbus_usbos_disconnect(struct usb_device *usb, void *ptr)
1341 #endif /* KERNEL26 */
1342 
DBUS_USBOS_PROBE()1343 DBUS_USBOS_PROBE()
1344 {
1345     int ep;
1346     struct usb_endpoint_descriptor *endpoint;
1347     int ret = 0;
1348 #ifdef KERNEL26
1349     struct usb_device *usb = interface_to_usbdev(intf);
1350 #else
1351     int claimed = 0;
1352 #endif
1353     int num_of_eps;
1354 #ifdef BCMUSBDEV_COMPOSITE
1355     int wlan_if = -1;
1356     bool intr_ep = FALSE;
1357 #endif /* BCMUSBDEV_COMPOSITE */
1358     wifi_adapter_info_t *adapter;
1359 
1360     DHD_MUTEX_LOCK();
1361 
1362     DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
1363              usb->bus->busnum, usb->portnum));
1364     adapter = dhd_wifi_platform_attach_adapter(
1365         USB_BUS, usb->bus->busnum, usb->portnum, WIFI_STATUS_POWER_ON);
1366     if (adapter == NULL) {
1367         DBUSERR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
1368         goto fail;
1369     }
1370 
1371 #ifdef BCMUSBDEV_COMPOSITE
1372     wlan_if = dbus_usbos_intf_wlan(usb);
1373 #ifdef KERNEL26
1374     if ((wlan_if >= 0) && (IFPTR(usb, wlan_if) == intf))
1375 #else
1376     if (wlan_if == ifnum)
1377 #endif /* KERNEL26 */
1378     {
1379 #endif /* BCMUSBDEV_COMPOSITE */
1380         g_probe_info.usb = usb;
1381         g_probe_info.dldone = TRUE;
1382 #ifdef BCMUSBDEV_COMPOSITE
1383     } else {
1384         DBUSTRACE(("dbus_usbos_probe: skip probe for non WLAN interface\n"));
1385         ret = BCME_UNSUPPORTED;
1386         goto fail;
1387     }
1388 #endif /* BCMUSBDEV_COMPOSITE */
1389 
1390 #ifdef KERNEL26
1391     g_probe_info.intf = intf;
1392 #endif /* KERNEL26 */
1393 
1394 #ifdef BCMUSBDEV_COMPOSITE
1395     if (IFDESC(usb, wlan_if).bInterfaceNumber > USB_COMPIF_MAX)
1396 #else
1397     if (IFDESC(usb, CONTROL_IF).bInterfaceNumber)
1398 #endif /* BCMUSBDEV_COMPOSITE */
1399     {
1400         ret = -1;
1401         goto fail;
1402     }
1403     if (id != NULL) {
1404         g_probe_info.vid = id->idVendor;
1405         g_probe_info.pid = id->idProduct;
1406     }
1407 
1408 #ifdef KERNEL26
1409     usb_set_intfdata(intf, &g_probe_info);
1410 #endif
1411 
1412     /* Check that the device supports only one configuration */
1413     if (usb->descriptor.bNumConfigurations != 1) {
1414         ret = -1;
1415         goto fail;
1416     }
1417 
1418     if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
1419 #ifdef BCMUSBDEV_COMPOSITE
1420         if ((usb->descriptor.bDeviceClass != USB_CLASS_MISC) &&
1421             (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS)) {
1422 #endif /* BCMUSBDEV_COMPOSITE */
1423             ret = -1;
1424             goto fail;
1425 #ifdef BCMUSBDEV_COMPOSITE
1426         }
1427 #endif /* BCMUSBDEV_COMPOSITE */
1428     }
1429 
1430     /*
1431      * Only the BDC interface configuration is supported:
1432      *	Device class: USB_CLASS_VENDOR_SPEC
1433      *	if0 class: USB_CLASS_VENDOR_SPEC
1434      *	if0/ep0: control
1435      *	if0/ep1: bulk in
1436      *	if0/ep2: bulk out (ok if swapped with bulk in)
1437      */
1438     if (CONFIGDESC(usb)->bNumInterfaces != 1) {
1439 #ifdef BCMUSBDEV_COMPOSITE
1440         if (CONFIGDESC(usb)->bNumInterfaces > USB_COMPIF_MAX) {
1441 #endif /* BCMUSBDEV_COMPOSITE */
1442             ret = -1;
1443             goto fail;
1444 #ifdef BCMUSBDEV_COMPOSITE
1445         }
1446 #endif /* BCMUSBDEV_COMPOSITE */
1447     }
1448 
1449     /* Check interface */
1450 #ifndef KERNEL26
1451 #ifdef BCMUSBDEV_COMPOSITE
1452     if (usb_interface_claimed(IFPTR(usb, wlan_if)))
1453 #else
1454     if (usb_interface_claimed(IFPTR(usb, CONTROL_IF)))
1455 #endif /* BCMUSBDEV_COMPOSITE */
1456     {
1457         ret = -1;
1458         goto fail;
1459     }
1460 #endif /* !KERNEL26 */
1461 
1462 #ifdef BCMUSBDEV_COMPOSITE
1463     if ((IFDESC(usb, wlan_if).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1464          IFDESC(usb, wlan_if).bInterfaceSubClass != 0x2 ||
1465          IFDESC(usb, wlan_if).bInterfaceProtocol != 0xff) &&
1466         (IFDESC(usb, wlan_if).bInterfaceClass != USB_CLASS_MISC ||
1467          IFDESC(usb, wlan_if).bInterfaceSubClass != USB_SUBCLASS_COMMON ||
1468          IFDESC(usb, wlan_if).bInterfaceProtocol != USB_PROTO_IAD))
1469 #else
1470     if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1471         IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 0x2 ||
1472         IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff)
1473 #endif /* BCMUSBDEV_COMPOSITE */
1474     {
1475 #ifdef BCMUSBDEV_COMPOSITE
1476         DBUSERR(
1477             ("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1478              __FUNCTION__, IFDESC(usb, wlan_if).bInterfaceClass,
1479              IFDESC(usb, wlan_if).bInterfaceSubClass,
1480              IFDESC(usb, wlan_if).bInterfaceProtocol));
1481 #else
1482         DBUSERR(
1483             ("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1484              __FUNCTION__, IFDESC(usb, CONTROL_IF).bInterfaceClass,
1485              IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
1486              IFDESC(usb, CONTROL_IF).bInterfaceProtocol));
1487 #endif /* BCMUSBDEV_COMPOSITE */
1488         ret = -1;
1489         goto fail;
1490     }
1491 
1492     /* Check control endpoint */
1493 #ifdef BCMUSBDEV_COMPOSITE
1494     endpoint = &IFEPDESC(usb, wlan_if, 0);
1495 #else
1496     endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
1497 #endif /* BCMUSBDEV_COMPOSITE */
1498     if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1499         USB_ENDPOINT_XFER_INT) {
1500 #ifdef BCMUSBDEV_COMPOSITE
1501         if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1502             USB_ENDPOINT_XFER_BULK) {
1503 #endif /* BCMUSBDEV_COMPOSITE */
1504             DBUSERR(("%s: invalid control endpoint %d\n", __FUNCTION__,
1505                      endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
1506             ret = -1;
1507             goto fail;
1508 #ifdef BCMUSBDEV_COMPOSITE
1509         }
1510 #endif /* BCMUSBDEV_COMPOSITE */
1511     }
1512 
1513 #ifdef BCMUSBDEV_COMPOSITE
1514     if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
1515         USB_ENDPOINT_XFER_INT) {
1516 #endif /* BCMUSBDEV_COMPOSITE */
1517         g_probe_info.intr_pipe = usb_rcvintpipe(
1518             usb, endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
1519 #ifdef BCMUSBDEV_COMPOSITE
1520         intr_ep = TRUE;
1521     }
1522 #endif /* BCMUSBDEV_COMPOSITE */
1523 
1524 #ifndef KERNEL26
1525     /* Claim interface */
1526 #ifdef BCMUSBDEV_COMPOSITE
1527     usb_driver_claim_interface(&dbus_usbdev, IFPTR(usb, wlan_if),
1528                                &g_probe_info);
1529 #else
1530     usb_driver_claim_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF),
1531                                &g_probe_info);
1532 #endif /* BCMUSBDEV_COMPOSITE */
1533     claimed = 1;
1534 #endif /* !KERNEL26 */
1535     g_probe_info.rx_pipe = 0;
1536     g_probe_info.rx_pipe2 = 0;
1537     g_probe_info.tx_pipe = 0;
1538 #ifdef BCMUSBDEV_COMPOSITE
1539     if (intr_ep) {
1540         ep = 1;
1541     } else {
1542         ep = 0;
1543     }
1544     num_of_eps = IFDESC(usb, wlan_if).bNumEndpoints - 1;
1545 #else
1546     num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
1547 #endif /* BCMUSBDEV_COMPOSITE */
1548 
1549     if ((num_of_eps != 0x2) && (num_of_eps != 0x3)) {
1550 #ifdef BCMUSBDEV_COMPOSITE
1551         if (num_of_eps > 0x7)
1552 #endif /* BCMUSBDEV_COMPOSITE */
1553             ASSERT(0);
1554     }
1555     /* Check data endpoints and get pipes */
1556 #ifdef BCMUSBDEV_COMPOSITE
1557     for (; ep <= num_of_eps; ep++)
1558 #else
1559     for (ep = 1; ep <= num_of_eps; ep++)
1560 #endif /* BCMUSBDEV_COMPOSITE */
1561     {
1562 #ifdef BCMUSBDEV_COMPOSITE
1563         endpoint = &IFEPDESC(usb, wlan_if, ep);
1564 #else
1565         endpoint = &IFEPDESC(usb, BULK_IF, ep);
1566 #endif /* BCMUSBDEV_COMPOSITE */
1567         if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1568             USB_ENDPOINT_XFER_BULK) {
1569             DBUSERR(("%s: invalid data endpoint %d\n", __FUNCTION__, ep));
1570             ret = -1;
1571             goto fail;
1572         }
1573 
1574         if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
1575             USB_DIR_IN) {
1576             /* direction: dongle->host */
1577             if (!g_probe_info.rx_pipe) {
1578                 g_probe_info.rx_pipe =
1579                     usb_rcvbulkpipe(usb, (endpoint->bEndpointAddress &
1580                                           USB_ENDPOINT_NUMBER_MASK));
1581             } else {
1582                 g_probe_info.rx_pipe2 =
1583                     usb_rcvbulkpipe(usb, (endpoint->bEndpointAddress &
1584                                           USB_ENDPOINT_NUMBER_MASK));
1585             }
1586         } else {
1587             g_probe_info.tx_pipe = usb_sndbulkpipe(
1588                 usb, (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK));
1589         }
1590     }
1591 
1592     /* Allocate interrupt URB and data buffer */
1593     /* RNDIS says 8-byte intr, our old drivers used 4-byte */
1594 #ifdef BCMUSBDEV_COMPOSITE
1595     g_probe_info.intr_size =
1596         (IFEPDESC(usb, wlan_if, 0).wMaxPacketSize == 0x10) ? 0x8 : 0x4;
1597     g_probe_info.interval = IFEPDESC(usb, wlan_if, 0).bInterval;
1598 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21))
1599     usb->quirks |= USB_QUIRK_NO_SET_INTF;
1600 #endif
1601 #else
1602     g_probe_info.intr_size =
1603         (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == 0x10) ? 0x8 : 0x4;
1604     g_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
1605 #endif /* BCMUSBDEV_COMPOSITE */
1606 
1607 #ifndef KERNEL26
1608     /* usb_fill_int_urb does the interval decoding in 2.6 */
1609     if (usb->speed == USB_SPEED_HIGH) {
1610         g_probe_info.interval = 1 << (g_probe_info.interval - 1);
1611     }
1612 #endif
1613     if (usb->speed == USB_SPEED_SUPER) {
1614         g_probe_info.device_speed = SUPER_SPEED;
1615         DBUSERR(("super speed device detected\n"));
1616     } else if (usb->speed == USB_SPEED_HIGH) {
1617         g_probe_info.device_speed = HIGH_SPEED;
1618         DBUSERR(("high speed device detected\n"));
1619     } else {
1620         g_probe_info.device_speed = FULL_SPEED;
1621         DBUSERR(("full speed device detected\n"));
1622     }
1623     if (g_probe_info.dereged == FALSE && probe_cb) {
1624         disc_arg =
1625             probe_cb(probe_arg, "", USB_BUS, usb->bus->busnum, usb->portnum, 0);
1626     }
1627 
1628     g_probe_info.disc_cb_done = FALSE;
1629 
1630 #ifdef KERNEL26
1631     intf->needs_remote_wakeup = 1;
1632 #endif /* KERNEL26 */
1633     DHD_MUTEX_UNLOCK();
1634 
1635     /* Success */
1636 #ifdef KERNEL26
1637     return DBUS_OK;
1638 #else
1639     usb_inc_dev_use(usb);
1640     return &g_probe_info;
1641 #endif
1642 
1643 fail:
1644     printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
1645 #ifdef BCMUSBDEV_COMPOSITE
1646     if (ret != BCME_UNSUPPORTED)
1647 #endif /* BCMUSBDEV_COMPOSITE */
1648         DBUSERR(("%s: failed with errno %d\n", __FUNCTION__, ret));
1649 #ifndef KERNEL26
1650     if (claimed)
1651 #ifdef BCMUSBDEV_COMPOSITE
1652         usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, wlan_if));
1653 #else
1654         usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF));
1655 #endif /* BCMUSBDEV_COMPOSITE */
1656 #endif /* !KERNEL26 */
1657 
1658     DHD_MUTEX_UNLOCK();
1659 #ifdef KERNEL26
1660     usb_set_intfdata(intf, NULL);
1661     return ret;
1662 #else
1663     return NULL;
1664 #endif
1665 } /* dbus_usbos_probe */
1666 
1667 /** Called by Linux kernel, is the counter part of dbus_usbos_probe() */
DBUS_USBOS_DISCONNECT()1668 DBUS_USBOS_DISCONNECT()
1669 {
1670 #ifdef KERNEL26
1671     struct usb_device *usb = interface_to_usbdev(intf);
1672     probe_info_t *probe_usb_init_data = usb_get_intfdata(intf);
1673 #else
1674     probe_info_t *probe_usb_init_data = (probe_info_t *)ptr;
1675 #endif
1676     usbos_info_t *usbos_info;
1677 
1678     DHD_MUTEX_LOCK();
1679 
1680     DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
1681              usb->bus->busnum, usb->portnum));
1682 
1683     if (probe_usb_init_data) {
1684         usbos_info = (usbos_info_t *)probe_usb_init_data->usbos_info;
1685         if (usbos_info) {
1686             if ((probe_usb_init_data->dereged == FALSE) && disconnect_cb &&
1687                 disc_arg) {
1688                 disconnect_cb(disc_arg);
1689                 disc_arg = NULL;
1690                 probe_usb_init_data->disc_cb_done = TRUE;
1691             }
1692         }
1693     }
1694 
1695     if (usb) {
1696 #ifndef KERNEL26
1697 #ifdef BCMUSBDEV_COMPOSITE
1698         usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, wlan_if));
1699 #else
1700         usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF));
1701 #endif /* BCMUSBDEV_COMPOSITE */
1702         usb_dec_dev_use(usb);
1703 #endif /* !KERNEL26 */
1704     }
1705     DHD_MUTEX_UNLOCK();
1706 } /* dbus_usbos_disconnect */
1707 
1708 #define LOOPBACK_PKT_START 0xBABE1234
1709 
is_loopback_pkt(void * buf)1710 bool is_loopback_pkt(void *buf)
1711 {
1712     uint32 *buf_ptr = (uint32 *)buf;
1713 
1714     if (*buf_ptr == LOOPBACK_PKT_START) {
1715         return TRUE;
1716     }
1717     return FALSE;
1718 }
1719 
matches_loopback_pkt(void * buf)1720 int matches_loopback_pkt(void *buf)
1721 {
1722     int i, j;
1723     unsigned char *cbuf = (unsigned char *)buf;
1724 
1725     for (i = 0x4; i < loopback_size; i++) {
1726         if (cbuf[i] != (i % 0x100)) {
1727             printf("%s: mismatch at i=%d %d : ", __FUNCTION__, i, cbuf[i]);
1728             for (j = i; ((j < i + 0x10) && (j < loopback_size)); j++) {
1729                 printf("%d ", cbuf[j]);
1730             }
1731             printf("\n");
1732             return 0;
1733         }
1734     }
1735     loopback_rx_cnt++;
1736     return 1;
1737 }
1738 
dbus_usbos_loopback_tx(void * usbos_info_ptr,int cnt,int size)1739 int dbus_usbos_loopback_tx(void *usbos_info_ptr, int cnt, int size)
1740 {
1741     usbos_info_t *usbos_info = (usbos_info_t *)usbos_info_ptr;
1742     unsigned char *buf;
1743     int j;
1744     void *p = NULL;
1745     int rc, last_rx_cnt;
1746     int tx_failed_cnt;
1747     int max_size = 1650;
1748     int usb_packet_size = 512;
1749     int min_packet_size = 10;
1750 
1751     if (size % usb_packet_size == 0) {
1752         size = size - 1;
1753         DBUSERR(("%s: overriding size=%d \n", __FUNCTION__, size));
1754     }
1755 
1756     if (size < min_packet_size) {
1757         size = min_packet_size;
1758         DBUSERR(("%s: overriding size=%d\n", __FUNCTION__, min_packet_size));
1759     }
1760     if (size > max_size) {
1761         size = max_size;
1762         DBUSERR(("%s: overriding size=%d\n", __FUNCTION__, max_size));
1763     }
1764 
1765     loopback_tx_cnt = 0;
1766     loopback_rx_cnt = 0;
1767     tx_failed_cnt = 0;
1768     loopback_size = size;
1769 
1770     while (loopback_tx_cnt < cnt) {
1771         uint32 *x;
1772         int pkt_size = loopback_size;
1773 
1774         p = PKTGET(usbos_info->pub->osh, pkt_size, TRUE);
1775         if (p == NULL) {
1776             DBUSERR(("%s:%d Failed to allocate packet sz=%d\n", __FUNCTION__,
1777                      __LINE__, pkt_size));
1778             return BCME_ERROR;
1779         }
1780         x = (uint32 *)PKTDATA(usbos_info->pub->osh, p);
1781         *x = LOOPBACK_PKT_START;
1782         buf = (unsigned char *)x;
1783         for (j = 0x4; j < pkt_size; j++) {
1784             buf[j] = j % 0x100;
1785         }
1786         rc = dbus_send_buf(usbos_info->pub, buf, pkt_size, p);
1787         if (rc != BCME_OK) {
1788             DBUSERR(("%s:%d Freeing packet \n", __FUNCTION__, __LINE__));
1789             PKTFREE(usbos_info->pub->osh, p, TRUE);
1790             dbus_usbos_wait(usbos_info, 1);
1791             tx_failed_cnt++;
1792         } else {
1793             loopback_tx_cnt++;
1794             tx_failed_cnt = 0;
1795         }
1796         if (tx_failed_cnt == 0x5) {
1797             DBUSERR(("%s : Failed to send loopback packets cnt=%d "
1798                      "loopback_tx_cnt=%d\n",
1799                      __FUNCTION__, cnt, loopback_tx_cnt));
1800             break;
1801         }
1802     }
1803     printf("Transmitted %d loopback packets of size %d\n", loopback_tx_cnt,
1804            loopback_size);
1805 
1806     last_rx_cnt = loopback_rx_cnt;
1807     while (loopback_rx_cnt < loopback_tx_cnt) {
1808         dbus_usbos_wait(usbos_info, 1);
1809         if (loopback_rx_cnt <= last_rx_cnt) {
1810             DBUSERR(("%s: Matched rx cnt stuck at %d \n", __FUNCTION__,
1811                      last_rx_cnt));
1812             return BCME_ERROR;
1813         }
1814         last_rx_cnt = loopback_rx_cnt;
1815     }
1816     printf("Received %d loopback packets of size %d\n", loopback_tx_cnt,
1817            loopback_size);
1818 
1819     return BCME_OK;
1820 } /* dbus_usbos_loopback_tx */
1821 
1822 /**
1823  * Higher layer (dbus_usb.c) wants to transmit an I/O Request Block
1824  *     @param[in] txirb txirb->pkt, if non-zero, contains a single or a chain of
1825  * packets
1826  */
dbus_usbos_intf_send_irb(void * bus,dbus_irb_tx_t * txirb)1827 static int dbus_usbos_intf_send_irb(void *bus, dbus_irb_tx_t *txirb)
1828 {
1829     usbos_info_t *usbos_info = (usbos_info_t *)bus;
1830     urb_req_t *req, *req_zlp = NULL;
1831     int ret = DBUS_OK;
1832     unsigned long flags;
1833     void *pkt;
1834     uint32 buffer_length;
1835     uint8 *buf;
1836 
1837     if ((usbos_info == NULL) || !usbos_info->tx_pipe) {
1838         return DBUS_ERR;
1839     }
1840 
1841     if (txirb->pkt != NULL) {
1842         buffer_length = pkttotlen(usbos_info->pub->osh, txirb->pkt);
1843         /* In case of multiple packets the values below may be overwritten */
1844         txirb->send_buf = NULL;
1845         buf = PKTDATA(usbos_info->pub->osh, txirb->pkt);
1846     } else { /* txirb->buf != NULL */
1847         ASSERT(txirb->buf != NULL);
1848         ASSERT(txirb->send_buf == NULL);
1849         buffer_length = txirb->len;
1850         buf = txirb->buf;
1851     }
1852 
1853     if (!(req = dbus_usbos_qdeq(&usbos_info->req_txfreeq,
1854                                 &usbos_info->txfree_lock))) {
1855         DBUSERR(("%s No free URB!\n", __FUNCTION__));
1856         return DBUS_ERR_TXDROP;
1857     }
1858 
1859     /* If not using standard Linux kernel functionality for handling Zero Length
1860      * Packet(ZLP), the dbus needs to generate ZLP when length is multiple of
1861      * MaxPacketSize.
1862      */
1863 #ifndef WL_URB_ZPKT
1864     if (!(buffer_length % usbos_info->maxps)) {
1865         if (!(req_zlp = dbus_usbos_qdeq(&usbos_info->req_txfreeq,
1866                                         &usbos_info->txfree_lock))) {
1867             DBUSERR(("%s No free URB for ZLP!\n", __FUNCTION__));
1868             dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
1869                             &usbos_info->txfree_lock);
1870             return DBUS_ERR_TXDROP;
1871         }
1872 
1873         /* No txirb, so that dbus_usbos_send_complete can differentiate between
1874          * DATA and ZLP.
1875          */
1876         req_zlp->arg = NULL;
1877         req_zlp->usbinfo = usbos_info;
1878         req_zlp->buf_len = 0;
1879 
1880         usb_fill_bulk_urb(req_zlp->urb, usbos_info->usb, usbos_info->tx_pipe,
1881                           NULL, 0, (usb_complete_t)dbus_usbos_send_complete,
1882                           req_zlp);
1883 
1884         req_zlp->urb->transfer_flags |= URB_QUEUE_BULK;
1885     }
1886 #endif /* !WL_URB_ZPKT */
1887 
1888 #ifndef USBOS_TX_THREAD
1889     /* Disable USB autosuspend until this request completes, request USB resume
1890      * if needed. Because this call runs asynchronously, there is no guarantee
1891      * the bus is resumed before the URB is submitted, and the URB might be
1892      * dropped. Use USBOS_TX_THREAD to avoid this.
1893      */
1894     USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
1895 #endif /* !USBOS_TX_THREAD */
1896 
1897     spin_lock_irqsave(&usbos_info->txlock, flags);
1898 
1899     req->arg = txirb;
1900     req->usbinfo = usbos_info;
1901     req->buf_len = 0;
1902 
1903     /* Prepare the URB */
1904     if (txirb->pkt != NULL) {
1905         uint32 pktlen;
1906         uint8 *transfer_buf;
1907 
1908         /* For multiple packets, allocate contiguous buffer and copy packet data
1909          * to it */
1910         if (PKTNEXT(usbos_info->pub->osh, txirb->pkt)) {
1911             transfer_buf = MALLOC(usbos_info->pub->osh, buffer_length);
1912             if (!transfer_buf) {
1913                 ret = DBUS_ERR_TXDROP;
1914                 DBUSERR(("fail to alloc to usb buffer\n"));
1915                 goto fail;
1916             }
1917 
1918             pkt = txirb->pkt;
1919             txirb->send_buf = transfer_buf;
1920             req->buf_len = buffer_length;
1921 
1922             while (pkt) {
1923                 pktlen = PKTLEN(usbos_info->pub->osh, pkt);
1924                 bcopy(PKTDATA(usbos_info->pub->osh, pkt), transfer_buf, pktlen);
1925                 transfer_buf += pktlen;
1926                 pkt = PKTNEXT(usbos_info->pub->osh, pkt);
1927             }
1928 
1929             ASSERT(((uint8 *)txirb->send_buf + buffer_length) == transfer_buf);
1930 
1931             /* Overwrite buf pointer with pointer to allocated contiguous
1932              * transfer_buf
1933              */
1934             buf = txirb->send_buf;
1935         }
1936     }
1937 
1938     usb_fill_bulk_urb(req->urb, usbos_info->usb, usbos_info->tx_pipe, buf,
1939                       buffer_length, (usb_complete_t)dbus_usbos_send_complete,
1940                       req);
1941 
1942     req->urb->transfer_flags |= URB_QUEUE_BULK;
1943 
1944 #ifdef USBOS_TX_THREAD
1945     /* Enqueue TX request, the TX thread will resume the bus if needed and
1946      * submit it asynchronously
1947      */
1948     dbus_usbos_qenq(&usbos_info->usbos_tx_list, req,
1949                     &usbos_info->usbos_tx_list_lock);
1950     if (req_zlp != NULL) {
1951         dbus_usbos_qenq(&usbos_info->usbos_tx_list, req_zlp,
1952                         &usbos_info->usbos_tx_list_lock);
1953     }
1954     spin_unlock_irqrestore(&usbos_info->txlock, flags);
1955 
1956     wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
1957     return DBUS_OK;
1958 #else
1959     if ((ret = USB_SUBMIT_URB(req->urb))) {
1960         ret = DBUS_ERR_TXDROP;
1961         goto fail;
1962     }
1963 
1964     dbus_usbos_qenq(&usbos_info->req_txpostedq, req,
1965                     &usbos_info->txposted_lock);
1966     atomic_inc(&usbos_info->txposted);
1967 
1968     if (req_zlp != NULL) {
1969         if ((ret = USB_SUBMIT_URB(req_zlp->urb))) {
1970             DBUSERR(("failed to submit ZLP URB!\n"));
1971             ASSERT(0);
1972             ret = DBUS_ERR_TXDROP;
1973             goto fail2;
1974         }
1975 
1976         dbus_usbos_qenq(&usbos_info->req_txpostedq, req_zlp,
1977                         &usbos_info->txposted_lock);
1978         /* Also increment txposted for zlp packet, as it will be decremented in
1979          * dbus_usbos_send_complete()
1980          */
1981         atomic_inc(&usbos_info->txposted);
1982     }
1983 
1984     spin_unlock_irqrestore(&usbos_info->txlock, flags);
1985     return DBUS_OK;
1986 #endif /* USBOS_TX_THREAD */
1987 
1988 fail:
1989     if (txirb->send_buf != NULL) {
1990         MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
1991         txirb->send_buf = NULL;
1992         req->buf_len = 0;
1993     }
1994     dbus_usbos_qenq(&usbos_info->req_txfreeq, req, &usbos_info->txfree_lock);
1995 #ifndef USBOS_TX_THREAD
1996 fail2:
1997 #endif
1998     if (req_zlp != NULL) {
1999         dbus_usbos_qenq(&usbos_info->req_txfreeq, req_zlp,
2000                         &usbos_info->txfree_lock);
2001     }
2002 
2003     spin_unlock_irqrestore(&usbos_info->txlock, flags);
2004 
2005 #ifndef USBOS_TX_THREAD
2006     USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2007 #endif /* !USBOS_TX_THREAD */
2008 
2009     return ret;
2010 } /* dbus_usbos_intf_send_irb */
2011 
2012 /** Higher layer (dbus_usb.c) recycles a received (and used) packet. */
dbus_usbos_intf_recv_irb(void * bus,dbus_irb_rx_t * rxirb)2013 static int dbus_usbos_intf_recv_irb(void *bus, dbus_irb_rx_t *rxirb)
2014 {
2015     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2016     int ret = DBUS_OK;
2017 
2018     if (usbos_info == NULL) {
2019         return DBUS_ERR;
2020     }
2021 
2022     ret = dbus_usbos_recv_urb_submit(usbos_info, rxirb, 0);
2023     return ret;
2024 }
2025 
dbus_usbos_intf_recv_irb_from_ep(void * bus,dbus_irb_rx_t * rxirb,uint32 ep_idx)2026 static int dbus_usbos_intf_recv_irb_from_ep(void *bus, dbus_irb_rx_t *rxirb,
2027                                             uint32 ep_idx)
2028 {
2029     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2030     int ret = DBUS_OK;
2031 
2032     if (usbos_info == NULL) {
2033         return DBUS_ERR;
2034     }
2035 
2036 #ifdef INTR_EP_ENABLE
2037     /* By specifying the ep_idx value of 0xff, the cdc layer is asking to
2038      * submit an interrupt URB
2039      */
2040     if (rxirb == NULL && ep_idx == 0xff) {
2041         /* submit intr URB */
2042         if ((ret = USB_SUBMIT_URB(usbos_info->intr_urb)) < 0) {
2043             DBUSERR(("%s intr USB_SUBMIT_URB failed, status %d\n", __FUNCTION__,
2044                      ret));
2045         }
2046         return ret;
2047     }
2048 #else
2049     if (rxirb == NULL) {
2050         return DBUS_ERR;
2051     }
2052 #endif /* INTR_EP_ENABLE */
2053 
2054     ret = dbus_usbos_recv_urb_submit(usbos_info, rxirb, ep_idx);
2055     return ret;
2056 }
2057 
2058 /** Higher layer (dbus_usb.c) want to cancel an IRB */
dbus_usbos_intf_cancel_irb(void * bus,dbus_irb_tx_t * txirb)2059 static int dbus_usbos_intf_cancel_irb(void *bus, dbus_irb_tx_t *txirb)
2060 {
2061     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2062 
2063     if (usbos_info == NULL) {
2064         return DBUS_ERR;
2065     }
2066 
2067     return DBUS_ERR;
2068 }
2069 
2070 /** Only one CTL transfer can be pending at any time. This function may block.
2071  */
dbus_usbos_intf_send_ctl(void * bus,uint8 * buf,int len)2072 static int dbus_usbos_intf_send_ctl(void *bus, uint8 *buf, int len)
2073 {
2074     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2075     uint16 size;
2076 #ifndef USBOS_TX_THREAD
2077     int status;
2078 #endif /* USBOS_TX_THREAD */
2079 
2080     if ((usbos_info == NULL) || (buf == NULL) || (len == 0)) {
2081         return DBUS_ERR;
2082     }
2083 
2084     if (usbos_info->ctl_urb == NULL) {
2085         return DBUS_ERR;
2086     }
2087 
2088     /* Block until a pending CTL transfer has completed */
2089     if (down_interruptible(&usbos_info->ctl_lock) != 0) {
2090         return DBUS_ERR_TXCTLFAIL;
2091     }
2092 
2093 #ifdef USBOS_TX_THREAD
2094     ASSERT(usbos_info->ctl_state == USBOS_REQUEST_STATE_UNSCHEDULED);
2095 #else
2096     /* Disable USB autosuspend until this request completes, request USB resume
2097      * if needed. Because this call runs asynchronously, there is no guarantee
2098      * the bus is resumed before the URB is submitted, and the URB might be
2099      * dropped. Use USBOS_TX_THREAD to avoid this.
2100      */
2101     USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
2102 #endif /* USBOS_TX_THREAD */
2103 
2104     size = len;
2105     usbos_info->ctl_write.wLength = cpu_to_le16p(&size);
2106     usbos_info->ctl_urb->transfer_buffer_length = size;
2107 
2108     usb_fill_control_urb(usbos_info->ctl_urb, usbos_info->usb,
2109                          usb_sndctrlpipe(usbos_info->usb, 0),
2110                          (unsigned char *)&usbos_info->ctl_write, buf, size,
2111                          (usb_complete_t)dbus_usbos_ctlwrite_complete,
2112                          usbos_info);
2113 
2114 #ifdef USBOS_TX_THREAD
2115     /* Enqueue CTRL request for transmission by the TX thread. The
2116      * USB bus will first be resumed if needed.
2117      */
2118     usbos_info->ctl_state = USBOS_REQUEST_STATE_SCHEDULED;
2119     wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
2120 #else
2121     status = USB_SUBMIT_URB(usbos_info->ctl_urb);
2122     if (status < 0) {
2123         DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__, status));
2124         up(&usbos_info->ctl_lock);
2125 
2126         USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2127 
2128         return DBUS_ERR_TXCTLFAIL;
2129     }
2130 #endif /* USBOS_TX_THREAD */
2131 
2132     return DBUS_OK;
2133 } /* dbus_usbos_intf_send_ctl */
2134 
2135 /** This function does not seem to be called by anyone, including dbus_usb.c */
dbus_usbos_intf_recv_ctl(void * bus,uint8 * buf,int len)2136 static int dbus_usbos_intf_recv_ctl(void *bus, uint8 *buf, int len)
2137 {
2138     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2139     int status;
2140     uint16 size;
2141 
2142     if ((usbos_info == NULL) || (buf == NULL) || (len == 0)) {
2143         return DBUS_ERR;
2144     }
2145 
2146     if (usbos_info->ctl_urb == NULL) {
2147         return DBUS_ERR;
2148     }
2149 
2150     /* Block until a pending CTRL transfer has completed */
2151     if (down_interruptible(&usbos_info->ctl_lock) != 0) {
2152         return DBUS_ERR_TXCTLFAIL;
2153     }
2154 
2155     /* Disable USB autosuspend until this request completes, request USB resume
2156      * if needed. */
2157     USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
2158 
2159     size = len;
2160     usbos_info->ctl_read.wLength = cpu_to_le16p(&size);
2161     usbos_info->ctl_urb->transfer_buffer_length = size;
2162 
2163     if (usbos_info->rxctl_deferrespok) {
2164         /* BMAC model */
2165         usbos_info->ctl_read.bRequestType =
2166             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
2167         usbos_info->ctl_read.bRequest = DL_DEFER_RESP_OK;
2168     } else {
2169         /* full dongle model */
2170         usbos_info->ctl_read.bRequestType =
2171             USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2172         usbos_info->ctl_read.bRequest = 1;
2173     }
2174 
2175     usb_fill_control_urb(usbos_info->ctl_urb, usbos_info->usb,
2176                          usb_rcvctrlpipe(usbos_info->usb, 0),
2177                          (unsigned char *)&usbos_info->ctl_read, buf, size,
2178                          (usb_complete_t)dbus_usbos_ctlread_complete,
2179                          usbos_info);
2180 
2181     status = USB_SUBMIT_URB(usbos_info->ctl_urb);
2182     if (status < 0) {
2183         DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__, status));
2184         up(&usbos_info->ctl_lock);
2185 
2186         USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2187 
2188         return DBUS_ERR_RXCTLFAIL;
2189     }
2190 
2191     return DBUS_OK;
2192 }
2193 
dbus_usbos_intf_get_attrib(void * bus,dbus_attrib_t * attrib)2194 static int dbus_usbos_intf_get_attrib(void *bus, dbus_attrib_t *attrib)
2195 {
2196     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2197 
2198     if ((usbos_info == NULL) || (attrib == NULL)) {
2199         return DBUS_ERR;
2200     }
2201 
2202     attrib->bustype = DBUS_USB;
2203     attrib->vid = g_probe_info.vid;
2204     attrib->pid = g_probe_info.pid;
2205     attrib->devid = 0x4322;
2206 
2207     attrib->nchan = 1;
2208 
2209     /* MaxPacketSize for USB hi-speed bulk out is 512 bytes
2210      * and 64-bytes for full-speed.
2211      * When sending pkt > MaxPacketSize, Host SW breaks it
2212      * up into multiple packets.
2213      */
2214     attrib->mtu = usbos_info->maxps;
2215 
2216     return DBUS_OK;
2217 }
2218 
2219 /** Called by higher layer (dbus_usb.c) when it wants to 'up' the USB interface
2220  * to the dongle */
dbus_usbos_intf_up(void * bus)2221 static int dbus_usbos_intf_up(void *bus)
2222 {
2223     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2224     uint16 ifnum;
2225 #ifdef BCMUSBDEV_COMPOSITE
2226     int wlan_if = 0;
2227 #endif
2228     if (usbos_info == NULL) {
2229         return DBUS_ERR;
2230     }
2231 
2232     if (usbos_info->usb == NULL) {
2233         return DBUS_ERR;
2234     }
2235 
2236 #if defined(INTR_EP_ENABLE)
2237     /* full dongle use intr EP, bmac doesn't use it */
2238     if (usbos_info->intr_urb) {
2239         int ret;
2240 
2241         usb_fill_int_urb(usbos_info->intr_urb, usbos_info->usb,
2242                          usbos_info->intr_pipe, &usbos_info->intr,
2243                          usbos_info->intr_size,
2244                          (usb_complete_t)dbus_usbos_intr_complete, usbos_info,
2245                          usbos_info->interval);
2246 
2247         if ((ret = USB_SUBMIT_URB(usbos_info->intr_urb))) {
2248             DBUSERR(("%s USB_SUBMIT_URB failed with status %d\n", __FUNCTION__,
2249                      ret));
2250             return DBUS_ERR;
2251         }
2252     }
2253 #endif
2254 
2255     if (usbos_info->ctl_urb) {
2256         usbos_info->ctl_in_pipe = usb_rcvctrlpipe(usbos_info->usb, 0);
2257         usbos_info->ctl_out_pipe = usb_sndctrlpipe(usbos_info->usb, 0);
2258 
2259 #ifdef BCMUSBDEV_COMPOSITE
2260         wlan_if = dbus_usbos_intf_wlan(usbos_info->usb);
2261         ifnum = cpu_to_le16(IFDESC(usbos_info->usb, wlan_if).bInterfaceNumber);
2262 #else
2263         ifnum =
2264             cpu_to_le16(IFDESC(usbos_info->usb, CONTROL_IF).bInterfaceNumber);
2265 #endif /* BCMUSBDEV_COMPOSITE */
2266         /* CTL Write */
2267         usbos_info->ctl_write.bRequestType =
2268             USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2269         usbos_info->ctl_write.bRequest = 0;
2270         usbos_info->ctl_write.wValue = cpu_to_le16(0);
2271         usbos_info->ctl_write.wIndex = cpu_to_le16p(&ifnum);
2272 
2273         /* CTL Read */
2274         usbos_info->ctl_read.bRequestType =
2275             USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2276         usbos_info->ctl_read.bRequest = 1;
2277         usbos_info->ctl_read.wValue = cpu_to_le16(0);
2278         usbos_info->ctl_read.wIndex = cpu_to_le16p(&ifnum);
2279     }
2280 
2281     /* Success, indicate usbos_info is fully up */
2282     dbus_usbos_state_change(usbos_info, DBUS_STATE_UP);
2283 
2284     return DBUS_OK;
2285 } /* dbus_usbos_intf_up */
2286 
dbus_usbos_intf_down(void * bus)2287 static int dbus_usbos_intf_down(void *bus)
2288 {
2289     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2290 
2291     if (usbos_info == NULL) {
2292         return DBUS_ERR;
2293     }
2294 
2295     dbusos_stop(usbos_info);
2296     return DBUS_OK;
2297 }
2298 
dbus_usbos_intf_stop(void * bus)2299 static int dbus_usbos_intf_stop(void *bus)
2300 {
2301     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2302 
2303     if (usbos_info == NULL) {
2304         return DBUS_ERR;
2305     }
2306 
2307     dbusos_stop(usbos_info);
2308     return DBUS_OK;
2309 }
2310 
2311 /** Called by higher layer (dbus_usb.c) */
dbus_usbos_intf_set_config(void * bus,dbus_config_t * config)2312 static int dbus_usbos_intf_set_config(void *bus, dbus_config_t *config)
2313 {
2314     int err = DBUS_ERR;
2315     usbos_info_t *usbos_info = bus;
2316 
2317     if (config->config_id == DBUS_CONFIG_ID_RXCTL_DEFERRES) {
2318         usbos_info->rxctl_deferrespok = config->rxctl_deferrespok;
2319         err = DBUS_OK;
2320     } else if (config->config_id == DBUS_CONFIG_ID_AGGR_LIMIT) {
2321         /* DBUS_CONFIG_ID_AGGR_LIMIT shouldn't be called after probe stage */
2322         ASSERT(disc_arg == NULL);
2323         ASSERT(config->aggr_param.maxrxsf > 0);
2324         ASSERT(config->aggr_param.maxrxsize > 0);
2325         if (config->aggr_param.maxrxsize > usbos_info->rxbuf_len) {
2326             int state = usbos_info->pub->busstate;
2327             dbus_usbos_unlink(&usbos_info->req_rxpostedq,
2328                               &usbos_info->rxposted_lock);
2329             while (atomic_read(&usbos_info->rxposted)) {
2330                 DBUSTRACE(("%s rxposted is %d, delay 1 ms\n", __FUNCTION__,
2331                            atomic_read(&usbos_info->rxposted)));
2332                 dbus_usbos_wait(usbos_info, 1);
2333             }
2334             usbos_info->rxbuf_len = config->aggr_param.maxrxsize;
2335             dbus_usbos_state_change(usbos_info, state);
2336         }
2337         err = DBUS_OK;
2338     }
2339 
2340     return err;
2341 }
2342 
2343 /** Called by dbus_usb.c when it wants to download firmware into the dongle */
dbus_usbos_dl_cmd(usbos_info_t * usbinfo,uint8 cmd,void * buffer,int buflen)2344 bool dbus_usbos_dl_cmd(usbos_info_t *usbinfo, uint8 cmd, void *buffer,
2345                        int buflen)
2346 {
2347     int transferred;
2348     int index = 0;
2349     char *tmpbuf;
2350 
2351     if ((usbinfo == NULL) || (buffer == NULL) || (buflen == 0)) {
2352         return FALSE;
2353     }
2354 
2355     tmpbuf = (char *)MALLOC(usbinfo->pub->osh, buflen);
2356     if (!tmpbuf) {
2357         DBUSERR(("%s: Unable to allocate memory \n", __FUNCTION__));
2358         return FALSE;
2359     }
2360 
2361 #ifdef BCM_REQUEST_FW
2362     if (cmd == DL_GO) {
2363         index = 1;
2364     }
2365 #endif
2366 
2367     /* Disable USB autosuspend until this request completes, request USB resume
2368      * if needed. */
2369     USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2370 
2371     transferred =
2372         USB_CONTROL_MSG(usbinfo->usb, usb_rcvctrlpipe(usbinfo->usb, 0), cmd,
2373                         (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 0,
2374                         index, (void *)tmpbuf, buflen, USB_CTRL_EP_TIMEOUT);
2375     if (transferred == buflen) {
2376         memcpy(buffer, tmpbuf, buflen);
2377     } else {
2378         DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2379     }
2380 
2381     USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2382 
2383     MFREE(usbinfo->pub->osh, tmpbuf, buflen);
2384     return (transferred == buflen);
2385 }
2386 
2387 /**
2388  * Called by dbus_usb.c when it wants to download a buffer into the dongle (e.g.
2389  * as part of the download process, when writing nvram variables).
2390  */
dbus_write_membytes(usbos_info_t * usbinfo,bool set,uint32 address,uint8 * data,uint size)2391 int dbus_write_membytes(usbos_info_t *usbinfo, bool set, uint32 address,
2392                         uint8 *data, uint size)
2393 {
2394     hwacc_t hwacc;
2395     int write_bytes = 4;
2396     int status;
2397     int retval = 0;
2398 
2399     DBUSTRACE(("Enter:%s\n", __FUNCTION__));
2400 
2401     /* Read is not supported */
2402     if (set == 0) {
2403         DBUSERR(("Currently read is not supported!!\n"));
2404         return -1;
2405     }
2406 
2407     USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2408 
2409     hwacc.cmd = DL_CMD_WRHW;
2410     hwacc.addr = address;
2411 
2412     DBUSTRACE(("Address:%x size:%d", hwacc.addr, size));
2413     do {
2414         if (size >= 0x4) {
2415             write_bytes = 0x4;
2416         } else if (size >= 0x2) {
2417             write_bytes = 0x2;
2418         } else {
2419             write_bytes = 1;
2420         }
2421 
2422         hwacc.len = write_bytes;
2423 
2424         while (size >= write_bytes) {
2425             hwacc.data = *((unsigned int *)data);
2426 
2427             status = USB_CONTROL_MSG(
2428                 usbinfo->usb, usb_sndctrlpipe(usbinfo->usb, 0), DL_WRHW,
2429                 (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 1, 0,
2430                 (char *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2431             if (status < 0) {
2432                 retval = -1;
2433                 DBUSERR((" Ctrl write hwacc failed w/status %d @ address:%x \n",
2434                          status, hwacc.addr));
2435                 goto err;
2436             }
2437 
2438             hwacc.addr += write_bytes;
2439             data += write_bytes;
2440             size -= write_bytes;
2441         }
2442     } while (size > 0);
2443 
2444 err:
2445     USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2446 
2447     return retval;
2448 }
2449 
dbus_usbos_readreg(void * bus,uint32 regaddr,int datalen,uint32 * value)2450 int dbus_usbos_readreg(void *bus, uint32 regaddr, int datalen, uint32 *value)
2451 {
2452     usbos_info_t *usbinfo = (usbos_info_t *)bus;
2453     int ret = DBUS_OK;
2454     int transferred;
2455     uint32 cmd;
2456     hwacc_t hwacc;
2457 
2458     if (usbinfo == NULL) {
2459         return DBUS_ERR;
2460     }
2461 
2462     if (datalen == 1) {
2463         cmd = DL_RDHW8;
2464     } else if (datalen == 0x2) {
2465         cmd = DL_RDHW16;
2466     } else {
2467         cmd = DL_RDHW32;
2468     }
2469 
2470     USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2471 
2472     transferred =
2473         USB_CONTROL_MSG(usbinfo->usb, usb_rcvctrlpipe(usbinfo->usb, 0), cmd,
2474                         (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE),
2475                         (uint16)(regaddr), (uint16)(regaddr >> 16),
2476                         (void *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2477     if (transferred >= sizeof(hwacc_t)) {
2478         *value = hwacc.data;
2479     } else {
2480         DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2481         ret = DBUS_ERR;
2482     }
2483 
2484     USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2485 
2486     return ret;
2487 }
2488 
dbus_usbos_writereg(void * bus,uint32 regaddr,int datalen,uint32 data)2489 int dbus_usbos_writereg(void *bus, uint32 regaddr, int datalen, uint32 data)
2490 {
2491     usbos_info_t *usbinfo = (usbos_info_t *)bus;
2492     int ret = DBUS_OK;
2493     int transferred;
2494     uint32 cmd = DL_WRHW;
2495     hwacc_t hwacc;
2496 
2497     if (usbinfo == NULL) {
2498         return DBUS_ERR;
2499     }
2500 
2501     USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2502 
2503     hwacc.cmd = DL_WRHW;
2504     hwacc.addr = regaddr;
2505     hwacc.data = data;
2506     hwacc.len = datalen;
2507 
2508     transferred = USB_CONTROL_MSG(
2509         usbinfo->usb, usb_sndctrlpipe(usbinfo->usb, 0), cmd,
2510         (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 1, 0,
2511         (void *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2512     if (transferred != sizeof(hwacc_t)) {
2513         DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2514         ret = DBUS_ERR;
2515     }
2516 
2517     USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2518 
2519     return ret;
2520 }
2521 
dbus_usbos_wait(usbos_info_t * usbinfo,uint16 ms)2522 int dbus_usbos_wait(usbos_info_t *usbinfo, uint16 ms)
2523 {
2524 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
2525     if (in_interrupt()) {
2526         mdelay(ms);
2527     } else {
2528         msleep_interruptible(ms);
2529     }
2530 #else
2531     wait_ms(ms);
2532 #endif
2533     return DBUS_OK;
2534 }
2535 
2536 /** Called by dbus_usb.c as part of the firmware download process */
dbus_usbos_dl_send_bulk(usbos_info_t * usbinfo,void * buffer,int len)2537 bool dbus_usbos_dl_send_bulk(usbos_info_t *usbinfo, void *buffer, int len)
2538 {
2539     bool ret = TRUE;
2540     int status;
2541     int transferred = 0;
2542 
2543     if (usbinfo == NULL) {
2544         return DBUS_ERR;
2545     }
2546 
2547     USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2548 
2549     status = USB_BULK_MSG(usbinfo->usb, usbinfo->tx_pipe, buffer, len,
2550                           &transferred, USB_BULK_EP_TIMEOUT);
2551     if (status < 0) {
2552         DBUSERR(("%s: usb_bulk_msg failed %d\n", __FUNCTION__, status));
2553         ret = FALSE;
2554     }
2555 
2556     USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2557 
2558     return ret;
2559 }
2560 
dbus_usbos_intf_recv_needed(void * bus)2561 static bool dbus_usbos_intf_recv_needed(void *bus)
2562 {
2563     return FALSE;
2564 }
2565 
2566 /**
2567  * Higher layer (dbus_usb.c) wants to execute a function on the condition that
2568  * the rx spin lock has been acquired.
2569  */
dbus_usbos_intf_exec_rxlock(void * bus,exec_cb_t cb,struct exec_parms * args)2570 static void *dbus_usbos_intf_exec_rxlock(void *bus, exec_cb_t cb,
2571                                          struct exec_parms *args)
2572 {
2573     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2574     void *ret;
2575     unsigned long flags;
2576 
2577     if (usbos_info == NULL) {
2578         return NULL;
2579     }
2580 
2581     spin_lock_irqsave(&usbos_info->rxlock, flags);
2582     ret = cb(args);
2583     spin_unlock_irqrestore(&usbos_info->rxlock, flags);
2584 
2585     return ret;
2586 }
2587 
dbus_usbos_intf_exec_txlock(void * bus,exec_cb_t cb,struct exec_parms * args)2588 static void *dbus_usbos_intf_exec_txlock(void *bus, exec_cb_t cb,
2589                                          struct exec_parms *args)
2590 {
2591     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2592     void *ret;
2593     unsigned long flags;
2594 
2595     if (usbos_info == NULL) {
2596         return NULL;
2597     }
2598 
2599     spin_lock_irqsave(&usbos_info->txlock, flags);
2600     ret = cb(args);
2601     spin_unlock_irqrestore(&usbos_info->txlock, flags);
2602 
2603     return ret;
2604 }
2605 
2606 /**
2607  * if an error condition was detected in this module, the higher DBUS layer
2608  * (dbus_usb.c) has to be notified.
2609  */
dbus_usbos_errhandler(void * bus,int err)2610 int dbus_usbos_errhandler(void *bus, int err)
2611 {
2612     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2613 
2614     if (usbos_info == NULL) {
2615         return DBUS_ERR;
2616     }
2617 
2618     if (usbos_info->cbarg && usbos_info->cbs) {
2619         if (usbos_info->cbs->errhandler) {
2620             usbos_info->cbs->errhandler(usbos_info->cbarg, err);
2621         }
2622     }
2623 
2624     return DBUS_OK;
2625 }
2626 
2627 /**
2628  * if a change in bus state was detected in this module, the higher DBUS layer
2629  * (dbus_usb.c) has to be notified.
2630  */
dbus_usbos_state_change(void * bus,int state)2631 int dbus_usbos_state_change(void *bus, int state)
2632 {
2633     usbos_info_t *usbos_info = (usbos_info_t *)bus;
2634 
2635     if (usbos_info == NULL) {
2636         return DBUS_ERR;
2637     }
2638 
2639     if (usbos_info->cbarg && usbos_info->cbs) {
2640         if (usbos_info->cbs->state_change) {
2641             usbos_info->cbs->state_change(usbos_info->cbarg, state);
2642         }
2643     }
2644 
2645     usbos_info->pub->busstate = state;
2646     return DBUS_OK;
2647 }
2648 
dbus_bus_osl_register(int vid,int pid,probe_cb_t prcb,disconnect_cb_t discb,void * prarg,dbus_intf_t ** intf,void * param1,void * param2)2649 int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb,
2650                           disconnect_cb_t discb, void *prarg,
2651                           dbus_intf_t **intf, void *param1, void *param2)
2652 {
2653     bzero(&g_probe_info, sizeof(probe_info_t));
2654 
2655     probe_cb = prcb;
2656     disconnect_cb = discb;
2657     probe_arg = prarg;
2658 
2659     devid_table[0].idVendor = vid;
2660     devid_table[0].idProduct = pid;
2661 
2662     *intf = &dbus_usbos_intf;
2663 
2664     USB_REGISTER();
2665 
2666     return DBUS_ERR_NODEVICE;
2667 }
2668 
dbus_bus_osl_deregister()2669 int dbus_bus_osl_deregister()
2670 {
2671     g_probe_info.dereged = TRUE;
2672 
2673     DHD_MUTEX_LOCK();
2674     if (disconnect_cb && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
2675         disconnect_cb(disc_arg);
2676         disc_arg = NULL;
2677     }
2678     DHD_MUTEX_UNLOCK();
2679 
2680     USB_DEREGISTER();
2681 
2682     return DBUS_OK;
2683 }
2684 
dbus_usbos_intf_attach(dbus_pub_t * pub,void * cbarg,dbus_intf_callbacks_t * cbs)2685 void *dbus_usbos_intf_attach(dbus_pub_t *pub, void *cbarg,
2686                              dbus_intf_callbacks_t *cbs)
2687 {
2688     usbos_info_t *usbos_info;
2689 
2690     if (g_probe_info.dldone == FALSE) {
2691         DBUSERR(("%s: err device not downloaded!\n", __FUNCTION__));
2692         return NULL;
2693     }
2694 
2695     /* Sanity check for BUS_INFO() */
2696     ASSERT(OFFSETOF(usbos_info_t, pub) == 0);
2697 
2698     usbos_info = MALLOC(pub->osh, sizeof(usbos_info_t));
2699     if (usbos_info == NULL) {
2700         return NULL;
2701     }
2702 
2703     bzero(usbos_info, sizeof(usbos_info_t));
2704 
2705     usbos_info->pub = pub;
2706     usbos_info->cbarg = cbarg;
2707     usbos_info->cbs = cbs;
2708 
2709     /* Needed for disconnect() */
2710     g_probe_info.usbos_info = usbos_info;
2711 
2712     /* Update USB Info */
2713     usbos_info->usb = g_probe_info.usb;
2714     usbos_info->rx_pipe = g_probe_info.rx_pipe;
2715     usbos_info->rx_pipe2 = g_probe_info.rx_pipe2;
2716     usbos_info->tx_pipe = g_probe_info.tx_pipe;
2717     usbos_info->intr_pipe = g_probe_info.intr_pipe;
2718     usbos_info->intr_size = g_probe_info.intr_size;
2719     usbos_info->interval = g_probe_info.interval;
2720     usbos_info->pub->device_speed = g_probe_info.device_speed;
2721     if (usbos_info->rx_pipe2) {
2722         usbos_info->pub->attrib.has_2nd_bulk_in_ep = 1;
2723     } else {
2724         usbos_info->pub->attrib.has_2nd_bulk_in_ep = 0;
2725     }
2726 
2727     if (usbos_info->tx_pipe) {
2728         usbos_info->maxps = usb_maxpacket(usbos_info->usb, usbos_info->tx_pipe,
2729                                           usb_pipeout(usbos_info->tx_pipe));
2730     }
2731 
2732     INIT_LIST_HEAD(&usbos_info->req_rxfreeq);
2733     INIT_LIST_HEAD(&usbos_info->req_txfreeq);
2734     INIT_LIST_HEAD(&usbos_info->req_rxpostedq);
2735     INIT_LIST_HEAD(&usbos_info->req_txpostedq);
2736     spin_lock_init(&usbos_info->rxfree_lock);
2737     spin_lock_init(&usbos_info->txfree_lock);
2738     spin_lock_init(&usbos_info->rxposted_lock);
2739     spin_lock_init(&usbos_info->txposted_lock);
2740     spin_lock_init(&usbos_info->rxlock);
2741     spin_lock_init(&usbos_info->txlock);
2742 
2743     atomic_set(&usbos_info->rxposted, 0);
2744     atomic_set(&usbos_info->txposted, 0);
2745 
2746 #ifdef USB_DISABLE_INT_EP
2747     usbos_info->intr_urb = NULL;
2748 #else
2749     if (!(usbos_info->intr_urb = USB_ALLOC_URB())) {
2750         DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2751         goto fail;
2752     }
2753 #endif
2754 
2755     if (!(usbos_info->ctl_urb = USB_ALLOC_URB())) {
2756         DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2757         goto fail;
2758     }
2759 
2760     init_waitqueue_head(&usbos_info->wait);
2761 
2762     if (!(usbos_info->blk_urb =
2763               USB_ALLOC_URB())) { /* for embedded image downloading */
2764         DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2765         goto fail;
2766     }
2767 
2768     usbos_info->rxbuf_len = (uint)usbos_info->pub->rxsize;
2769 
2770     atomic_set(&usbos_info->txallocated, 0);
2771     if (DBUS_OK !=
2772         dbus_usbos_urbreqs_alloc(usbos_info, usbos_info->pub->ntxq, FALSE)) {
2773         goto fail;
2774     }
2775 
2776     atomic_set(&usbos_info->rxallocated, 0);
2777     if (DBUS_OK != dbus_usbos_urbreqs_alloc(usbos_info,
2778                                             MIN(DBUS_USB_RXQUEUE_BATCH_ADD, usbos_info->pub->nrxq),
2779                                             TRUE)) {
2780         goto fail;
2781     }
2782 
2783     sema_init(&usbos_info->ctl_lock, 1);
2784 
2785 #ifdef USBOS_THREAD
2786     if (dbus_usbos_thread_init(usbos_info) == NULL) {
2787         goto fail;
2788     }
2789 #endif /* USBOS_THREAD */
2790 
2791 #ifdef USBOS_TX_THREAD
2792     if (dbus_usbos_tx_thread_init(usbos_info) == NULL) {
2793         goto fail;
2794     }
2795 #endif /* USBOS_TX_THREAD */
2796 
2797     pub->dev_info = g_probe_info.usb;
2798 
2799     return (void *)usbos_info;
2800 fail:
2801     if (usbos_info->intr_urb) {
2802         USB_FREE_URB(usbos_info->intr_urb);
2803         usbos_info->intr_urb = NULL;
2804     }
2805 
2806     if (usbos_info->ctl_urb) {
2807         USB_FREE_URB(usbos_info->ctl_urb);
2808         usbos_info->ctl_urb = NULL;
2809     }
2810 
2811 #if defined(BCM_REQUEST_FW)
2812     if (usbos_info->blk_urb) {
2813         USB_FREE_URB(usbos_info->blk_urb);
2814         usbos_info->blk_urb = NULL;
2815     }
2816 #endif
2817 
2818     dbus_usbos_urbreqs_free(usbos_info, TRUE);
2819     atomic_set(&usbos_info->rxallocated, 0);
2820     dbus_usbos_urbreqs_free(usbos_info, FALSE);
2821     atomic_set(&usbos_info->txallocated, 0);
2822 
2823     g_probe_info.usbos_info = NULL;
2824 
2825     MFREE(pub->osh, usbos_info, sizeof(usbos_info_t));
2826     return NULL;
2827 } /* dbus_usbos_intf_attach */
2828 
dbus_usbos_intf_detach(dbus_pub_t * pub,void * info)2829 void dbus_usbos_intf_detach(dbus_pub_t *pub, void *info)
2830 {
2831     usbos_info_t *usbos_info = (usbos_info_t *)info;
2832     osl_t *osh = pub->osh;
2833 
2834     if (usbos_info == NULL) {
2835         return;
2836     }
2837 
2838 #ifdef USBOS_TX_THREAD
2839     dbus_usbos_tx_thread_deinit(usbos_info);
2840 #endif /* USBOS_TX_THREAD */
2841 
2842     /* Must unlink all URBs prior to driver unload;
2843      * otherwise an URB callback can occur after driver
2844      * has been de-allocated and rmmod'd
2845      */
2846     dbusos_stop(usbos_info);
2847 
2848     if (usbos_info->intr_urb) {
2849         USB_FREE_URB(usbos_info->intr_urb);
2850         usbos_info->intr_urb = NULL;
2851     }
2852 
2853     if (usbos_info->ctl_urb) {
2854         USB_FREE_URB(usbos_info->ctl_urb);
2855         usbos_info->ctl_urb = NULL;
2856     }
2857 
2858     if (usbos_info->blk_urb) {
2859         USB_FREE_URB(usbos_info->blk_urb);
2860         usbos_info->blk_urb = NULL;
2861     }
2862 
2863     dbus_usbos_urbreqs_free(usbos_info, TRUE);
2864     atomic_set(&usbos_info->rxallocated, 0);
2865     dbus_usbos_urbreqs_free(usbos_info, FALSE);
2866     atomic_set(&usbos_info->txallocated, 0);
2867 
2868 #ifdef USBOS_THREAD
2869     dbus_usbos_thread_deinit(usbos_info);
2870 #endif /* USBOS_THREAD */
2871 
2872     g_probe_info.usbos_info = NULL;
2873     MFREE(osh, usbos_info, sizeof(usbos_info_t));
2874 } /* dbus_usbos_intf_detach */
2875 
2876 #ifdef USBOS_TX_THREAD
2877 
dbus_usbos_tx_thread_init(usbos_info_t * usbos_info)2878 void *dbus_usbos_tx_thread_init(usbos_info_t *usbos_info)
2879 {
2880     spin_lock_init(&usbos_info->usbos_tx_list_lock);
2881     INIT_LIST_HEAD(&usbos_info->usbos_tx_list);
2882     init_waitqueue_head(&usbos_info->usbos_tx_queue_head);
2883 
2884     usbos_info->usbos_tx_kt =
2885         kthread_create(dbus_usbos_tx_thread_func, usbos_info, "usb-tx-thread");
2886 
2887     if (IS_ERR(usbos_info->usbos_tx_kt)) {
2888         DBUSERR(("Thread Creation failed\n"));
2889         return (NULL);
2890     }
2891 
2892     usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
2893     wake_up_process(usbos_info->usbos_tx_kt);
2894 
2895     return (usbos_info->usbos_tx_kt);
2896 }
2897 
dbus_usbos_tx_thread_deinit(usbos_info_t * usbos_info)2898 void dbus_usbos_tx_thread_deinit(usbos_info_t *usbos_info)
2899 {
2900     urb_req_t *req;
2901 
2902     if (usbos_info->usbos_tx_kt) {
2903         wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
2904         kthread_stop(usbos_info->usbos_tx_kt);
2905     }
2906 
2907     /* Move pending requests to free queue so they can be freed */
2908     while ((req = dbus_usbos_qdeq(&usbos_info->usbos_tx_list,
2909                                   &usbos_info->usbos_tx_list_lock)) != NULL) {
2910         dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
2911                         &usbos_info->txfree_lock);
2912     }
2913 }
2914 
2915 /**
2916  * Allow USB in-band resume to block by submitting CTRL and DATA URBs on a
2917  * separate thread.
2918  */
dbus_usbos_tx_thread_func(void * data)2919 int dbus_usbos_tx_thread_func(void *data)
2920 {
2921     usbos_info_t *usbos_info = (usbos_info_t *)data;
2922     urb_req_t *req;
2923     dbus_irb_tx_t *txirb;
2924     int ret;
2925     unsigned long flags;
2926 
2927 #ifdef WL_THREADNICE
2928     set_user_nice(current, WL_THREADNICE);
2929 #endif
2930 
2931     while (1) {
2932         /* Wait until there are URBs to submit */
2933         wait_event_interruptible_timeout(
2934             usbos_info->usbos_tx_queue_head,
2935             !list_empty(&usbos_info->usbos_tx_list) ||
2936                 usbos_info->ctl_state == USBOS_REQUEST_STATE_SCHEDULED,
2937             0x64);
2938 
2939         if (kthread_should_stop()) {
2940             break;
2941         }
2942 
2943         /* Submit CTRL URB if needed */
2944         if (usbos_info->ctl_state == USBOS_REQUEST_STATE_SCHEDULED) {
2945             /* Disable USB autosuspend until this request completes. If the
2946              * interface was suspended, this call blocks until it has been
2947              * resumed.
2948              */
2949             USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2950 
2951             usbos_info->ctl_state = USBOS_REQUEST_STATE_SUBMITTED;
2952 
2953             ret = USB_SUBMIT_URB(usbos_info->ctl_urb);
2954             if (ret != 0) {
2955                 DBUSERR(("%s CTRL USB_SUBMIT_URB failed, status %d\n",
2956                          __FUNCTION__, ret));
2957 
2958                 usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
2959                 up(&usbos_info->ctl_lock);
2960 
2961                 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2962             }
2963         }
2964 
2965         /* Submit all available TX URBs */
2966         while ((req = dbus_usbos_qdeq(&usbos_info->usbos_tx_list,
2967                                       &usbos_info->usbos_tx_list_lock)) !=
2968                NULL) {
2969             /* Disable USB autosuspend until this request completes. If the
2970              * interface was suspended, this call blocks until it has been
2971              * resumed.
2972              */
2973             USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2974 
2975             spin_lock_irqsave(&usbos_info->txlock, flags);
2976 
2977             ret = USB_SUBMIT_URB(req->urb);
2978             if (ret == 0) {
2979                 /* URB submitted successfully */
2980                 dbus_usbos_qenq(&usbos_info->req_txpostedq, req,
2981                                 &usbos_info->txposted_lock);
2982                 atomic_inc(&usbos_info->txposted);
2983             } else {
2984                 /* Submitting the URB failed. */
2985                 DBUSERR(("%s TX USB_SUBMIT_URB failed, status %d\n",
2986                          __FUNCTION__, ret));
2987 
2988                 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2989             }
2990 
2991             spin_unlock_irqrestore(&usbos_info->txlock, flags);
2992 
2993             if (ret != 0) {
2994                 /* Cleanup and notify higher layers */
2995                 dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
2996                                 &usbos_info->txfree_lock);
2997 
2998                 txirb = req->arg;
2999                 if (txirb->send_buf) {
3000                     MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
3001                     txirb->send_buf = NULL;
3002                     req->buf_len = 0;
3003                 }
3004 
3005                 if (likely(usbos_info->cbarg && usbos_info->cbs)) {
3006                     if (likely(usbos_info->cbs->send_irb_complete != NULL)) {
3007                         usbos_info->cbs->send_irb_complete(
3008                             usbos_info->cbarg, txirb, DBUS_ERR_TXDROP);
3009                     }
3010                 }
3011             }
3012         }
3013     }
3014 
3015     return 0;
3016 } /* dbus_usbos_tx_thread_func */
3017 
3018 #endif /* USBOS_TX_THREAD */
3019 
3020 #ifdef USBOS_THREAD
3021 
3022 /**
3023  * Increase system performance by creating a USB thread that runs parallel to
3024  * other system activity.
3025  */
dbus_usbos_thread_init(usbos_info_t * usbos_info)3026 static void *dbus_usbos_thread_init(usbos_info_t *usbos_info)
3027 {
3028     usbos_list_entry_t *entry;
3029     unsigned long flags, ii;
3030 
3031     spin_lock_init(&usbos_info->usbos_list_lock);
3032     spin_lock_init(&usbos_info->ctrl_lock);
3033     INIT_LIST_HEAD(&usbos_info->usbos_list);
3034     INIT_LIST_HEAD(&usbos_info->usbos_free_list);
3035     init_waitqueue_head(&usbos_info->usbos_queue_head);
3036     atomic_set(&usbos_info->usbos_list_cnt, 0);
3037 
3038     for (ii = 0; ii < (usbos_info->pub->nrxq + usbos_info->pub->ntxq); ii++) {
3039         entry = MALLOC(usbos_info->pub->osh, sizeof(usbos_list_entry_t));
3040         if (entry) {
3041             spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3042             list_add_tail((struct list_head *)entry,
3043                           &usbos_info->usbos_free_list);
3044             spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3045         } else {
3046             DBUSERR(("Failed to create list\n"));
3047         }
3048     }
3049 
3050     usbos_info->usbos_kt =
3051         kthread_create(dbus_usbos_thread_func, usbos_info, "usb-thread");
3052 
3053     if (IS_ERR(usbos_info->usbos_kt)) {
3054         DBUSERR(("Thread Creation failed\n"));
3055         return (NULL);
3056     }
3057 
3058     wake_up_process(usbos_info->usbos_kt);
3059 
3060     return (usbos_info->usbos_kt);
3061 }
3062 
dbus_usbos_thread_deinit(usbos_info_t * usbos_info)3063 static void dbus_usbos_thread_deinit(usbos_info_t *usbos_info)
3064 {
3065     struct list_head *cur, *next;
3066     usbos_list_entry_t *entry;
3067     unsigned long flags;
3068 
3069     if (usbos_info->usbos_kt) {
3070         wake_up_interruptible(&usbos_info->usbos_queue_head);
3071         kthread_stop(usbos_info->usbos_kt);
3072     }
3073 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3074 #pragma GCC diagnostic push
3075 #pragma GCC diagnostic ignored "-Wcast-qual"
3076 #endif
3077     list_for_each_safe(cur, next, &usbos_info->usbos_list)
3078     {
3079         entry = list_entry(cur, struct usbos_list_entry, list);
3080         /* detach this entry from the list and then free the entry */
3081         spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3082         list_del(cur);
3083         MFREE(usbos_info->pub->osh, entry, sizeof(usbos_list_entry_t));
3084         spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3085     }
3086 
3087     list_for_each_safe(cur, next, &usbos_info->usbos_free_list)
3088     {
3089         entry = list_entry(cur, struct usbos_list_entry, list);
3090         /* detach this entry from the list and then free the entry */
3091         spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3092         list_del(cur);
3093         MFREE(usbos_info->pub->osh, entry, sizeof(usbos_list_entry_t));
3094         spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3095     }
3096 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3097 #pragma GCC diagnostic pop
3098 #endif
3099 }
3100 
3101 /** Process completed URBs in a worker thread */
dbus_usbos_thread_func(void * data)3102 static int dbus_usbos_thread_func(void *data)
3103 {
3104     usbos_info_t *usbos_info = (usbos_info_t *)data;
3105     usbos_list_entry_t *entry;
3106     struct list_head *cur, *next;
3107     unsigned long flags;
3108 
3109 #ifdef WL_THREADNICE
3110     set_user_nice(current, WL_THREADNICE);
3111 #endif
3112 
3113     while (1) {
3114         /* If the list is empty, then go to sleep */
3115         wait_event_interruptible_timeout(
3116             usbos_info->usbos_queue_head,
3117             atomic_read(&usbos_info->usbos_list_cnt) > 0, 0x64);
3118 
3119         if (kthread_should_stop()) {
3120             break;
3121         }
3122 
3123         spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3124 
3125         /* For each entry on the list, process it.  Remove the entry from
3126          * the list when done.
3127          */
3128 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3129 #pragma GCC diagnostic push
3130 #pragma GCC diagnostic ignored "-Wcast-qual"
3131 #endif
3132         list_for_each_safe(cur, next, &usbos_info->usbos_list)
3133         {
3134             urb_req_t *req;
3135             int len;
3136             int stat;
3137             usbos_info_t *usbos_info_local;
3138 
3139             entry = list_entry(cur, struct usbos_list_entry, list);
3140             if (entry == NULL) {
3141                 break;
3142             }
3143 
3144             req = entry->urb_context;
3145             len = entry->urb_length;
3146             stat = entry->urb_status;
3147             usbos_info_local = req->usbinfo;
3148 
3149             /* detach this entry from the list and attach it to the free list */
3150             list_del_init(cur);
3151             spin_unlock_irqrestore(&usbos_info_local->usbos_list_lock, flags);
3152 
3153             dbus_usbos_recv_complete_handle(req, len, stat);
3154 
3155             spin_lock_irqsave(&usbos_info_local->usbos_list_lock, flags);
3156 
3157             list_add_tail(cur, &usbos_info_local->usbos_free_list);
3158 
3159             atomic_dec(&usbos_info_local->usbos_list_cnt);
3160         }
3161 
3162         spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3163     }
3164 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3165 #pragma GCC diagnostic pop
3166 #endif
3167 
3168     return 0;
3169 } /* dbus_usbos_thread_func */
3170 
3171 /** Called on Linux calling URB callback, see dbus_usbos_recv_complete() */
dbus_usbos_dispatch_schedule(CALLBACK_ARGS)3172 static void dbus_usbos_dispatch_schedule(CALLBACK_ARGS)
3173 {
3174     urb_req_t *req = urb->context;
3175     usbos_info_t *usbos_info = req->usbinfo;
3176     usbos_list_entry_t *entry;
3177     unsigned long flags;
3178     struct list_head *cur;
3179 
3180     spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3181 
3182     cur = usbos_info->usbos_free_list.next;
3183 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3184 #pragma GCC diagnostic push
3185 #pragma GCC diagnostic ignored "-Wcast-qual"
3186 #endif
3187     entry = list_entry(cur, struct usbos_list_entry, list);
3188 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3189 #pragma GCC diagnostic pop
3190 #endif
3191 
3192     /* detach this entry from the free list and prepare it insert it to use list
3193      */
3194     list_del_init(cur);
3195 
3196     if (entry) {
3197         entry->urb_context = urb->context;
3198         entry->urb_length = urb->actual_length;
3199         entry->urb_status = urb->status;
3200 
3201         atomic_inc(&usbos_info->usbos_list_cnt);
3202         list_add_tail(cur, &usbos_info->usbos_list);
3203     } else {
3204         DBUSERR(("!!!!!!OUT OF MEMORY!!!!!!!\n"));
3205     }
3206 
3207     spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3208 
3209     /* thread */
3210     wake_up_interruptible(&usbos_info->usbos_queue_head);
3211 } /* dbus_usbos_dispatch_schedule */
3212 
3213 #endif /* USBOS_THREAD */
3214 
3215 #ifdef BCM_REQUEST_FW
3216 
3217 struct request_fw_context {
3218     const struct firmware *firmware;
3219     struct semaphore lock;
3220 };
3221 
3222 /*
3223  * Callback for dbus_request_firmware().
3224  */
dbus_request_firmware_done(const struct firmware * firmware,void * ctx)3225 static void dbus_request_firmware_done(const struct firmware *firmware,
3226                                        void *ctx)
3227 {
3228     struct request_fw_context *context = (struct request_fw_context *)ctx;
3229 
3230     /* Store the received firmware handle in the context and wake requester */
3231     context->firmware = firmware;
3232     up(&context->lock);
3233 }
3234 
3235 /*
3236  * Send a firmware request and wait for completion.
3237  *
3238  * The use of the asynchronous version of request_firmware() is needed to avoid
3239  * kernel oopses when we just come out of system hibernate.
3240  */
dbus_request_firmware(const char * name,const struct firmware ** firmware)3241 static int dbus_request_firmware(const char *name,
3242                                  const struct firmware **firmware)
3243 {
3244     struct request_fw_context *context;
3245     int ret;
3246 
3247     context = kzalloc(sizeof(*context), GFP_KERNEL);
3248     if (!context) {
3249         return -ENOMEM;
3250     }
3251 
3252     sema_init(&context->lock, 0);
3253 
3254     ret = request_firmware_nowait(THIS_MODULE, true, name,
3255                                   &g_probe_info.usb->dev, GFP_KERNEL, context,
3256                                   dbus_request_firmware_done);
3257     if (ret) {
3258         kfree(context);
3259         return ret;
3260     }
3261 
3262     /* Wait for completion */
3263     if (down_interruptible(&context->lock) != 0) {
3264         kfree(context);
3265         return -ERESTARTSYS;
3266     }
3267 
3268     *firmware = context->firmware;
3269     kfree(context);
3270 
3271     return *firmware != NULL ? 0 : -ENOENT;
3272 }
3273 
dbus_get_fwfile(int devid,int chiprev,uint8 ** fw,int * fwlen,uint16 boardtype,uint16 boardrev)3274 static void *dbus_get_fwfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3275                              uint16 boardtype, uint16 boardrev)
3276 {
3277     const struct firmware *firmware = NULL;
3278 #ifndef OEM_ANDROID
3279     s8 *device_id = NULL;
3280     s8 *chip_rev = "";
3281 #endif /* OEM_ANDROID */
3282     s8 file_name[64];
3283     int ret;
3284 
3285 #ifndef OEM_ANDROID
3286     switch (devid) {
3287         case BCM4350_CHIP_ID:
3288         case BCM4354_CHIP_ID:
3289         case BCM43556_CHIP_ID:
3290         case BCM43558_CHIP_ID:
3291         case BCM43566_CHIP_ID:
3292         case BCM43568_CHIP_ID:
3293         case BCM43570_CHIP_ID:
3294         case BCM4358_CHIP_ID:
3295             device_id = "4350";
3296             break;
3297         case BCM43143_CHIP_ID:
3298             device_id = "43143";
3299             break;
3300         case BCM43234_CHIP_ID:
3301         case BCM43235_CHIP_ID:
3302         case BCM43236_CHIP_ID:
3303             device_id = "43236";
3304             break;
3305         case BCM43242_CHIP_ID:
3306             device_id = "43242";
3307             break;
3308         case BCM43238_CHIP_ID:
3309             device_id = "43238";
3310             break;
3311         case BCM43526_CHIP_ID:
3312             device_id = "43526";
3313             break;
3314         case BCM43569_CHIP_ID:
3315             device_id = "43569";
3316             switch (chiprev) {
3317                 case 0:
3318                     chip_rev = "a0";
3319                     break;
3320                 case 0x2:
3321                     chip_rev = "a2";
3322                     break;
3323                 default:
3324                     break;
3325             }
3326             break;
3327         default:
3328             DBUSERR(("unsupported device %x\n", devid));
3329             return NULL;
3330     }
3331 
3332     /* Load firmware */
3333     snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s-firmware.bin",
3334              device_id, chip_rev);
3335 #else
3336     snprintf(file_name, sizeof(file_name), "%s", CONFIG_ANDROID_BCMDHD_FW_PATH);
3337 #endif /* OEM_ANDROID */
3338 
3339     ret = dbus_request_firmware(file_name, &firmware);
3340     if (ret) {
3341         DBUSERR(("fail to request firmware %s\n", file_name));
3342         return NULL;
3343     }
3344 
3345     *fwlen = firmware->size;
3346     *fw = (uint8 *)firmware->data;
3347     return (void *)firmware;
3348 }
3349 
dbus_get_nvfile(int devid,int chiprev,uint8 ** fw,int * fwlen,uint16 boardtype,uint16 boardrev)3350 static void *dbus_get_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3351                              uint16 boardtype, uint16 boardrev)
3352 {
3353     const struct firmware *firmware = NULL;
3354 #ifndef OEM_ANDROID
3355     s8 *device_id = NULL;
3356     s8 *chip_rev = "";
3357 #endif /* OEM_ANDROID */
3358     s8 file_name[64];
3359     int ret;
3360 
3361 #ifndef OEM_ANDROID
3362     switch (devid) {
3363         case BCM4350_CHIP_ID:
3364         case BCM4354_CHIP_ID:
3365         case BCM43556_CHIP_ID:
3366         case BCM43558_CHIP_ID:
3367         case BCM43566_CHIP_ID:
3368         case BCM43568_CHIP_ID:
3369         case BCM43570_CHIP_ID:
3370         case BCM4358_CHIP_ID:
3371             device_id = "4350";
3372             break;
3373         case BCM43143_CHIP_ID:
3374             device_id = "43143";
3375             break;
3376         case BCM43234_CHIP_ID:
3377             device_id = "43234";
3378             break;
3379         case BCM43235_CHIP_ID:
3380             device_id = "43235";
3381             break;
3382         case BCM43236_CHIP_ID:
3383             device_id = "43236";
3384             break;
3385         case BCM43238_CHIP_ID:
3386             device_id = "43238";
3387             break;
3388         case BCM43242_CHIP_ID:
3389             device_id = "43242";
3390             break;
3391         case BCM43526_CHIP_ID:
3392             device_id = "43526";
3393             break;
3394         case BCM43569_CHIP_ID:
3395             device_id = "43569";
3396             switch (chiprev) {
3397                 case 0:
3398                     chip_rev = "a0";
3399                     break;
3400                 case 0x2:
3401                     chip_rev = "a2";
3402                     break;
3403                 default:
3404                     break;
3405             }
3406             break;
3407         default:
3408             DBUSERR(("unsupported device %x\n", devid));
3409             return NULL;
3410     }
3411 
3412     /* Load board specific nvram file */
3413     snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s-%2x-%2x.nvm",
3414              device_id, chip_rev, boardtype, boardrev);
3415 #else
3416     snprintf(file_name, sizeof(file_name), "%s",
3417              CONFIG_ANDROID_BCMDHD_NVRAM_PATH);
3418 #endif /* OEM_ANDROID */
3419 
3420     ret = dbus_request_firmware(file_name, &firmware);
3421     if (ret) {
3422         DBUSERR(("fail to request nvram %s\n", file_name));
3423 
3424 #ifndef OEM_ANDROID
3425         /* Load generic nvram file */
3426         snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s.nvm", device_id,
3427                  chip_rev);
3428 
3429         ret = dbus_request_firmware(file_name, &firmware);
3430 #endif /* OEM_ANDROID */
3431         if (ret) {
3432             DBUSERR(("fail to request nvram %s\n", file_name));
3433             return NULL;
3434         }
3435     }
3436 
3437     *fwlen = firmware->size;
3438     *fw = (uint8 *)firmware->data;
3439     return (void *)firmware;
3440 }
3441 
dbus_get_fw_nvfile(int devid,int chiprev,uint8 ** fw,int * fwlen,int type,uint16 boardtype,uint16 boardrev)3442 void *dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3443                          int type, uint16 boardtype, uint16 boardrev)
3444 {
3445     switch (type) {
3446         case DBUS_FIRMWARE:
3447             return dbus_get_fwfile(devid, chiprev, fw, fwlen, boardtype,
3448                                    boardrev);
3449         case DBUS_NVFILE:
3450             return dbus_get_nvfile(devid, chiprev, fw, fwlen, boardtype,
3451                                    boardrev);
3452         default:
3453             return NULL;
3454     }
3455 }
3456 
dbus_release_fw_nvfile(void * firmware)3457 void dbus_release_fw_nvfile(void *firmware)
3458 {
3459     release_firmware((struct firmware *)firmware);
3460 }
3461 #endif /* BCM_REQUEST_FW */
3462 
3463 #ifdef BCMUSBDEV_COMPOSITE
3464 /**
3465  * For a composite device the interface order is not guaranteed, scan the device
3466  * struct for the WLAN interface.
3467  */
dbus_usbos_intf_wlan(struct usb_device * usb)3468 static int dbus_usbos_intf_wlan(struct usb_device *usb)
3469 {
3470     int i, num_of_eps, ep, intf_wlan = -1;
3471     int num_intf = CONFIGDESC(usb)->bNumInterfaces;
3472     struct usb_endpoint_descriptor *endpoint;
3473 
3474     for (i = 0; i < num_intf; i++) {
3475         if (IFDESC(usb, i).bInterfaceClass != USB_CLASS_VENDOR_SPEC) {
3476             continue;
3477         }
3478         num_of_eps = IFDESC(usb, i).bNumEndpoints;
3479 
3480         for (ep = 0; ep < num_of_eps; ep++) {
3481             endpoint = &IFEPDESC(usb, i, ep);
3482             if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
3483                 USB_ENDPOINT_XFER_BULK) {
3484                 intf_wlan = i;
3485                 break;
3486             }
3487         }
3488         if (ep < num_of_eps) {
3489             break;
3490         }
3491     }
3492 
3493     return intf_wlan;
3494 }
3495 #endif /* BCMUSBDEV_COMPOSITE */
3496