| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | HCI USB driver for Linux Bluetooth protocol stack (BlueZ) | 
|  | 3 | Copyright (C) 2000-2001 Qualcomm Incorporated | 
|  | 4 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | 
|  | 5 |  | 
|  | 6 | Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com> | 
|  | 7 |  | 
|  | 8 | This program is free software; you can redistribute it and/or modify | 
|  | 9 | it under the terms of the GNU General Public License version 2 as | 
|  | 10 | published by the Free Software Foundation; | 
|  | 11 |  | 
|  | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 
|  | 13 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|  | 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | 
|  | 15 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | 
|  | 16 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | 
|  | 17 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
|  | 18 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 
|  | 19 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
|  | 20 |  | 
|  | 21 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | 
|  | 22 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | 
|  | 23 | SOFTWARE IS DISCLAIMED. | 
|  | 24 | */ | 
|  | 25 |  | 
|  | 26 | /* Class, SubClass, and Protocol codes that describe a Bluetooth device */ | 
|  | 27 | #define HCI_DEV_CLASS		0xe0	/* Wireless class */ | 
|  | 28 | #define HCI_DEV_SUBCLASS	0x01	/* RF subclass */ | 
|  | 29 | #define HCI_DEV_PROTOCOL	0x01	/* Bluetooth programming protocol */ | 
|  | 30 |  | 
|  | 31 | #define HCI_IGNORE		0x01 | 
|  | 32 | #define HCI_RESET		0x02 | 
|  | 33 | #define HCI_DIGIANSWER		0x04 | 
| Marcel Holtmann | 0915e88 | 2005-09-13 01:32:37 +0200 | [diff] [blame] | 34 | #define HCI_CSR			0x08 | 
|  | 35 | #define HCI_SNIFFER		0x10 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 36 | #define HCI_BCM92035		0x20 | 
| Marcel Holtmann | 0915e88 | 2005-09-13 01:32:37 +0200 | [diff] [blame] | 37 | #define HCI_BROKEN_ISOC		0x40 | 
| Marcel Holtmann | da1f519 | 2006-07-03 10:02:29 +0200 | [diff] [blame] | 38 | #define HCI_WRONG_SCO_MTU	0x80 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 39 |  | 
|  | 40 | #define HCI_MAX_IFACE_NUM	3 | 
|  | 41 |  | 
|  | 42 | #define HCI_MAX_BULK_TX		4 | 
|  | 43 | #define HCI_MAX_BULK_RX		1 | 
|  | 44 |  | 
|  | 45 | #define HCI_MAX_ISOC_RX		2 | 
|  | 46 | #define HCI_MAX_ISOC_TX		2 | 
|  | 47 |  | 
|  | 48 | #define HCI_MAX_ISOC_FRAMES	10 | 
|  | 49 |  | 
|  | 50 | struct _urb_queue { | 
|  | 51 | struct list_head head; | 
|  | 52 | spinlock_t       lock; | 
|  | 53 | }; | 
|  | 54 |  | 
|  | 55 | struct _urb { | 
|  | 56 | struct list_head  list; | 
|  | 57 | struct _urb_queue *queue; | 
|  | 58 | int               type; | 
|  | 59 | void              *priv; | 
|  | 60 | struct urb        urb; | 
|  | 61 | }; | 
|  | 62 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 63 | static inline void _urb_queue_init(struct _urb_queue *q) | 
|  | 64 | { | 
|  | 65 | INIT_LIST_HEAD(&q->head); | 
|  | 66 | spin_lock_init(&q->lock); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb) | 
|  | 70 | { | 
|  | 71 | unsigned long flags; | 
|  | 72 | spin_lock_irqsave(&q->lock, flags); | 
| Pavel Machek | 026672d | 2008-05-02 16:45:10 -0700 | [diff] [blame] | 73 | /* _urb_unlink needs to know which spinlock to use, thus mb(). */ | 
|  | 74 | _urb->queue = q; mb(); list_add(&_urb->list, &q->head); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 | spin_unlock_irqrestore(&q->lock, flags); | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb) | 
|  | 79 | { | 
|  | 80 | unsigned long flags; | 
|  | 81 | spin_lock_irqsave(&q->lock, flags); | 
| Pavel Machek | 026672d | 2008-05-02 16:45:10 -0700 | [diff] [blame] | 82 | /* _urb_unlink needs to know which spinlock to use, thus mb(). */ | 
|  | 83 | _urb->queue = q; mb(); list_add_tail(&_urb->list, &q->head); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | spin_unlock_irqrestore(&q->lock, flags); | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | static inline void _urb_unlink(struct _urb *_urb) | 
|  | 88 | { | 
| Pavel Machek | 026672d | 2008-05-02 16:45:10 -0700 | [diff] [blame] | 89 | struct _urb_queue *q; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 | unsigned long flags; | 
| Pavel Machek | 026672d | 2008-05-02 16:45:10 -0700 | [diff] [blame] | 91 |  | 
|  | 92 | mb(); | 
|  | 93 | q = _urb->queue; | 
|  | 94 | /* If q is NULL, it will die at easy-to-debug NULL pointer dereference. | 
|  | 95 | No need to BUG(). */ | 
|  | 96 | spin_lock_irqsave(&q->lock, flags); | 
|  | 97 | list_del(&_urb->list); _urb->queue = NULL; | 
|  | 98 | spin_unlock_irqrestore(&q->lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 99 | } | 
|  | 100 |  | 
|  | 101 | struct hci_usb { | 
|  | 102 | struct hci_dev		*hdev; | 
|  | 103 |  | 
|  | 104 | unsigned long		state; | 
| Marcel Holtmann | babf4d4 | 2007-07-11 06:42:35 +0200 | [diff] [blame] | 105 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 106 | struct usb_device	*udev; | 
| Marcel Holtmann | babf4d4 | 2007-07-11 06:42:35 +0200 | [diff] [blame] | 107 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 108 | struct usb_host_endpoint	*bulk_in_ep; | 
|  | 109 | struct usb_host_endpoint	*bulk_out_ep; | 
|  | 110 | struct usb_host_endpoint	*intr_in_ep; | 
|  | 111 |  | 
|  | 112 | struct usb_interface		*isoc_iface; | 
|  | 113 | struct usb_host_endpoint	*isoc_out_ep; | 
|  | 114 | struct usb_host_endpoint	*isoc_in_ep; | 
|  | 115 |  | 
|  | 116 | __u8			ctrl_req; | 
|  | 117 |  | 
|  | 118 | struct sk_buff_head	transmit_q[4]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 119 |  | 
|  | 120 | rwlock_t		completion_lock; | 
|  | 121 |  | 
|  | 122 | atomic_t		pending_tx[4];		/* Number of pending requests */ | 
|  | 123 | struct _urb_queue	pending_q[4];		/* Pending requests */ | 
|  | 124 | struct _urb_queue	completed_q[4];		/* Completed requests */ | 
|  | 125 | }; | 
|  | 126 |  | 
|  | 127 | /* States  */ | 
|  | 128 | #define HCI_USB_TX_PROCESS	1 | 
|  | 129 | #define HCI_USB_TX_WAKEUP	2 |