diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/Kconfig | 168 | ||||
-rw-r--r-- | drivers/bluetooth/Makefile | 19 | ||||
-rw-r--r-- | drivers/bluetooth/bcm203x.c | 314 | ||||
-rw-r--r-- | drivers/bluetooth/bfusb.c | 806 | ||||
-rw-r--r-- | drivers/bluetooth/bluecard_cs.c | 1114 | ||||
-rw-r--r-- | drivers/bluetooth/bpa10x.c | 657 | ||||
-rw-r--r-- | drivers/bluetooth/bt3c_cs.c | 960 | ||||
-rw-r--r-- | drivers/bluetooth/btuart_cs.c | 880 | ||||
-rw-r--r-- | drivers/bluetooth/dtl1_cs.c | 832 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcsp.c | 749 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcsp.h | 70 | ||||
-rw-r--r-- | drivers/bluetooth/hci_h4.c | 282 | ||||
-rw-r--r-- | drivers/bluetooth/hci_h4.h | 44 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 593 | ||||
-rw-r--r-- | drivers/bluetooth/hci_uart.h | 82 | ||||
-rw-r--r-- | drivers/bluetooth/hci_usb.c | 1075 | ||||
-rw-r--r-- | drivers/bluetooth/hci_usb.h | 128 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 364 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.h | 50 |
19 files changed, 9187 insertions, 0 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig new file mode 100644 index 000000000000..543f93e0f23f --- /dev/null +++ b/drivers/bluetooth/Kconfig | |||
@@ -0,0 +1,168 @@ | |||
1 | |||
2 | menu "Bluetooth device drivers" | ||
3 | depends on BT | ||
4 | |||
5 | config BT_HCIUSB | ||
6 | tristate "HCI USB driver" | ||
7 | depends on USB | ||
8 | help | ||
9 | Bluetooth HCI USB driver. | ||
10 | This driver is required if you want to use Bluetooth devices with | ||
11 | USB interface. | ||
12 | |||
13 | Say Y here to compile support for Bluetooth USB devices into the | ||
14 | kernel or say M to compile it as module (hci_usb). | ||
15 | |||
16 | config BT_HCIUSB_SCO | ||
17 | bool "SCO (voice) support" | ||
18 | depends on BT_HCIUSB | ||
19 | help | ||
20 | This option enables the SCO support in the HCI USB driver. You need this | ||
21 | to transmit voice data with your Bluetooth USB device. | ||
22 | |||
23 | Say Y here to compile support for SCO over HCI USB. | ||
24 | |||
25 | config BT_HCIUART | ||
26 | tristate "HCI UART driver" | ||
27 | help | ||
28 | Bluetooth HCI UART driver. | ||
29 | This driver is required if you want to use Bluetooth devices with | ||
30 | serial port interface. You will also need this driver if you have | ||
31 | UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card | ||
32 | adapter and BrainBoxes Bluetooth PC Card. | ||
33 | |||
34 | Say Y here to compile support for Bluetooth UART devices into the | ||
35 | kernel or say M to compile it as module (hci_uart). | ||
36 | |||
37 | config BT_HCIUART_H4 | ||
38 | bool "UART (H4) protocol support" | ||
39 | depends on BT_HCIUART | ||
40 | help | ||
41 | UART (H4) is serial protocol for communication between Bluetooth | ||
42 | device and host. This protocol is required for most Bluetooth devices | ||
43 | with UART interface, including PCMCIA and CF cards. | ||
44 | |||
45 | Say Y here to compile support for HCI UART (H4) protocol. | ||
46 | |||
47 | config BT_HCIUART_BCSP | ||
48 | bool "BCSP protocol support" | ||
49 | depends on BT_HCIUART | ||
50 | help | ||
51 | BCSP (BlueCore Serial Protocol) is serial protocol for communication | ||
52 | between Bluetooth device and host. This protocol is required for non | ||
53 | USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and | ||
54 | CF cards. | ||
55 | |||
56 | Say Y here to compile support for HCI BCSP protocol. | ||
57 | |||
58 | config BT_HCIUART_BCSP_TXCRC | ||
59 | bool "Transmit CRC with every BCSP packet" | ||
60 | depends on BT_HCIUART_BCSP | ||
61 | help | ||
62 | If you say Y here, a 16-bit CRC checksum will be transmitted along with | ||
63 | every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip. | ||
64 | This increases reliability, but slightly reduces efficiency. | ||
65 | |||
66 | config BT_HCIBCM203X | ||
67 | tristate "HCI BCM203x USB driver" | ||
68 | depends on USB | ||
69 | select FW_LOADER | ||
70 | help | ||
71 | Bluetooth HCI BCM203x USB driver. | ||
72 | This driver provides the firmware loading mechanism for the Broadcom | ||
73 | Blutonium based devices. | ||
74 | |||
75 | Say Y here to compile support for HCI BCM203x devices into the | ||
76 | kernel or say M to compile it as module (bcm203x). | ||
77 | |||
78 | config BT_HCIBPA10X | ||
79 | tristate "HCI BPA10x USB driver" | ||
80 | depends on USB | ||
81 | help | ||
82 | Bluetooth HCI BPA10x USB driver. | ||
83 | This driver provides support for the Digianswer BPA 100/105 Bluetooth | ||
84 | sniffer devices. | ||
85 | |||
86 | Say Y here to compile support for HCI BPA10x devices into the | ||
87 | kernel or say M to compile it as module (bpa10x). | ||
88 | |||
89 | config BT_HCIBFUSB | ||
90 | tristate "HCI BlueFRITZ! USB driver" | ||
91 | depends on USB | ||
92 | select FW_LOADER | ||
93 | help | ||
94 | Bluetooth HCI BlueFRITZ! USB driver. | ||
95 | This driver provides support for Bluetooth USB devices with AVM | ||
96 | interface: | ||
97 | AVM BlueFRITZ! USB | ||
98 | |||
99 | Say Y here to compile support for HCI BFUSB devices into the | ||
100 | kernel or say M to compile it as module (bfusb). | ||
101 | |||
102 | config BT_HCIDTL1 | ||
103 | tristate "HCI DTL1 (PC Card) driver" | ||
104 | depends on PCMCIA | ||
105 | help | ||
106 | Bluetooth HCI DTL1 (PC Card) driver. | ||
107 | This driver provides support for Bluetooth PCMCIA devices with | ||
108 | Nokia DTL1 interface: | ||
109 | Nokia Bluetooth Card | ||
110 | Socket Bluetooth CF Card | ||
111 | |||
112 | Say Y here to compile support for HCI DTL1 devices into the | ||
113 | kernel or say M to compile it as module (dtl1_cs). | ||
114 | |||
115 | config BT_HCIBT3C | ||
116 | tristate "HCI BT3C (PC Card) driver" | ||
117 | depends on PCMCIA | ||
118 | select FW_LOADER | ||
119 | help | ||
120 | Bluetooth HCI BT3C (PC Card) driver. | ||
121 | This driver provides support for Bluetooth PCMCIA devices with | ||
122 | 3Com BT3C interface: | ||
123 | 3Com Bluetooth Card (3CRWB6096) | ||
124 | HP Bluetooth Card | ||
125 | |||
126 | Say Y here to compile support for HCI BT3C devices into the | ||
127 | kernel or say M to compile it as module (bt3c_cs). | ||
128 | |||
129 | config BT_HCIBLUECARD | ||
130 | tristate "HCI BlueCard (PC Card) driver" | ||
131 | depends on PCMCIA | ||
132 | help | ||
133 | Bluetooth HCI BlueCard (PC Card) driver. | ||
134 | This driver provides support for Bluetooth PCMCIA devices with | ||
135 | Anycom BlueCard interface: | ||
136 | Anycom Bluetooth PC Card | ||
137 | Anycom Bluetooth CF Card | ||
138 | |||
139 | Say Y here to compile support for HCI BlueCard devices into the | ||
140 | kernel or say M to compile it as module (bluecard_cs). | ||
141 | |||
142 | config BT_HCIBTUART | ||
143 | tristate "HCI UART (PC Card) device driver" | ||
144 | depends on PCMCIA | ||
145 | help | ||
146 | Bluetooth HCI UART (PC Card) driver. | ||
147 | This driver provides support for Bluetooth PCMCIA devices with | ||
148 | an UART interface: | ||
149 | Xircom CreditCard Bluetooth Adapter | ||
150 | Xircom RealPort2 Bluetooth Adapter | ||
151 | Sphinx PICO Card | ||
152 | H-Soft blue+Card | ||
153 | Cyber-blue Compact Flash Card | ||
154 | |||
155 | Say Y here to compile support for HCI UART devices into the | ||
156 | kernel or say M to compile it as module (btuart_cs). | ||
157 | |||
158 | config BT_HCIVHCI | ||
159 | tristate "HCI VHCI (Virtual HCI device) driver" | ||
160 | help | ||
161 | Bluetooth Virtual HCI device driver. | ||
162 | This driver is required if you want to use HCI Emulation software. | ||
163 | |||
164 | Say Y here to compile support for virtual HCI devices into the | ||
165 | kernel or say M to compile it as module (hci_vhci). | ||
166 | |||
167 | endmenu | ||
168 | |||
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile new file mode 100644 index 000000000000..08c10e178e02 --- /dev/null +++ b/drivers/bluetooth/Makefile | |||
@@ -0,0 +1,19 @@ | |||
1 | # | ||
2 | # Makefile for the Linux Bluetooth HCI device drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_BT_HCIUSB) += hci_usb.o | ||
6 | obj-$(CONFIG_BT_HCIVHCI) += hci_vhci.o | ||
7 | obj-$(CONFIG_BT_HCIUART) += hci_uart.o | ||
8 | obj-$(CONFIG_BT_HCIBCM203X) += bcm203x.o | ||
9 | obj-$(CONFIG_BT_HCIBPA10X) += bpa10x.o | ||
10 | obj-$(CONFIG_BT_HCIBFUSB) += bfusb.o | ||
11 | obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o | ||
12 | obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o | ||
13 | obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o | ||
14 | obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o | ||
15 | |||
16 | hci_uart-y := hci_ldisc.o | ||
17 | hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o | ||
18 | hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o | ||
19 | hci_uart-objs := $(hci_uart-y) | ||
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c new file mode 100644 index 000000000000..5fd3e4cb7525 --- /dev/null +++ b/drivers/bluetooth/bcm203x.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Broadcom Blutonium firmware driver | ||
4 | * | ||
5 | * Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/config.h> | ||
26 | #include <linux/module.h> | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/timer.h> | ||
34 | |||
35 | #include <linux/device.h> | ||
36 | #include <linux/firmware.h> | ||
37 | |||
38 | #include <linux/usb.h> | ||
39 | |||
40 | #include <net/bluetooth/bluetooth.h> | ||
41 | |||
42 | #ifndef CONFIG_BT_HCIBCM203X_DEBUG | ||
43 | #undef BT_DBG | ||
44 | #define BT_DBG(D...) | ||
45 | #endif | ||
46 | |||
47 | #define VERSION "1.0" | ||
48 | |||
49 | static int ignore = 0; | ||
50 | |||
51 | static struct usb_device_id bcm203x_table[] = { | ||
52 | /* Broadcom Blutonium (BCM2033) */ | ||
53 | { USB_DEVICE(0x0a5c, 0x2033) }, | ||
54 | |||
55 | { } /* Terminating entry */ | ||
56 | }; | ||
57 | |||
58 | MODULE_DEVICE_TABLE(usb, bcm203x_table); | ||
59 | |||
60 | #define BCM203X_ERROR 0 | ||
61 | #define BCM203X_RESET 1 | ||
62 | #define BCM203X_LOAD_MINIDRV 2 | ||
63 | #define BCM203X_SELECT_MEMORY 3 | ||
64 | #define BCM203X_CHECK_MEMORY 4 | ||
65 | #define BCM203X_LOAD_FIRMWARE 5 | ||
66 | #define BCM203X_CHECK_FIRMWARE 6 | ||
67 | |||
68 | #define BCM203X_IN_EP 0x81 | ||
69 | #define BCM203X_OUT_EP 0x02 | ||
70 | |||
71 | struct bcm203x_data { | ||
72 | struct usb_device *udev; | ||
73 | |||
74 | unsigned long state; | ||
75 | |||
76 | struct timer_list timer; | ||
77 | |||
78 | struct urb *urb; | ||
79 | unsigned char *buffer; | ||
80 | |||
81 | unsigned char *fw_data; | ||
82 | unsigned int fw_size; | ||
83 | unsigned int fw_sent; | ||
84 | }; | ||
85 | |||
86 | static void bcm203x_complete(struct urb *urb, struct pt_regs *regs) | ||
87 | { | ||
88 | struct bcm203x_data *data = urb->context; | ||
89 | struct usb_device *udev = urb->dev; | ||
90 | int len; | ||
91 | |||
92 | BT_DBG("udev %p urb %p", udev, urb); | ||
93 | |||
94 | if (urb->status) { | ||
95 | BT_ERR("URB failed with status %d", urb->status); | ||
96 | data->state = BCM203X_ERROR; | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | switch (data->state) { | ||
101 | case BCM203X_LOAD_MINIDRV: | ||
102 | memcpy(data->buffer, "#", 1); | ||
103 | |||
104 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), | ||
105 | data->buffer, 1, bcm203x_complete, data); | ||
106 | |||
107 | data->state = BCM203X_SELECT_MEMORY; | ||
108 | |||
109 | mod_timer(&data->timer, jiffies + (HZ / 10)); | ||
110 | break; | ||
111 | |||
112 | case BCM203X_SELECT_MEMORY: | ||
113 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), | ||
114 | data->buffer, 32, bcm203x_complete, data, 1); | ||
115 | |||
116 | data->state = BCM203X_CHECK_MEMORY; | ||
117 | |||
118 | if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) | ||
119 | BT_ERR("Can't submit URB"); | ||
120 | break; | ||
121 | |||
122 | case BCM203X_CHECK_MEMORY: | ||
123 | if (data->buffer[0] != '#') { | ||
124 | BT_ERR("Memory select failed"); | ||
125 | data->state = BCM203X_ERROR; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | data->state = BCM203X_LOAD_FIRMWARE; | ||
130 | |||
131 | case BCM203X_LOAD_FIRMWARE: | ||
132 | if (data->fw_sent == data->fw_size) { | ||
133 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), | ||
134 | data->buffer, 32, bcm203x_complete, data, 1); | ||
135 | |||
136 | data->state = BCM203X_CHECK_FIRMWARE; | ||
137 | } else { | ||
138 | len = min_t(uint, data->fw_size - data->fw_sent, 4096); | ||
139 | |||
140 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), | ||
141 | data->fw_data + data->fw_sent, len, bcm203x_complete, data); | ||
142 | |||
143 | data->fw_sent += len; | ||
144 | } | ||
145 | |||
146 | if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) | ||
147 | BT_ERR("Can't submit URB"); | ||
148 | break; | ||
149 | |||
150 | case BCM203X_CHECK_FIRMWARE: | ||
151 | if (data->buffer[0] != '.') { | ||
152 | BT_ERR("Firmware loading failed"); | ||
153 | data->state = BCM203X_ERROR; | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | data->state = BCM203X_RESET; | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static void bcm203x_timer(unsigned long user_data) | ||
163 | { | ||
164 | struct bcm203x_data *data = (struct bcm203x_data *) user_data; | ||
165 | |||
166 | if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) | ||
167 | BT_ERR("Can't submit URB"); | ||
168 | } | ||
169 | |||
170 | static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
171 | { | ||
172 | const struct firmware *firmware; | ||
173 | struct usb_device *udev = interface_to_usbdev(intf); | ||
174 | struct bcm203x_data *data; | ||
175 | int size; | ||
176 | |||
177 | BT_DBG("intf %p id %p", intf, id); | ||
178 | |||
179 | if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0)) | ||
180 | return -ENODEV; | ||
181 | |||
182 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
183 | if (!data) { | ||
184 | BT_ERR("Can't allocate memory for data structure"); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | |||
188 | memset(data, 0, sizeof(*data)); | ||
189 | |||
190 | data->udev = udev; | ||
191 | data->state = BCM203X_LOAD_MINIDRV; | ||
192 | |||
193 | data->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
194 | if (!data->urb) { | ||
195 | BT_ERR("Can't allocate URB"); | ||
196 | kfree(data); | ||
197 | return -ENOMEM; | ||
198 | } | ||
199 | |||
200 | if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { | ||
201 | BT_ERR("Mini driver request failed"); | ||
202 | usb_free_urb(data->urb); | ||
203 | kfree(data); | ||
204 | return -EIO; | ||
205 | } | ||
206 | |||
207 | BT_DBG("minidrv data %p size %d", firmware->data, firmware->size); | ||
208 | |||
209 | size = max_t(uint, firmware->size, 4096); | ||
210 | |||
211 | data->buffer = kmalloc(size, GFP_KERNEL); | ||
212 | if (!data->buffer) { | ||
213 | BT_ERR("Can't allocate memory for mini driver"); | ||
214 | release_firmware(firmware); | ||
215 | usb_free_urb(data->urb); | ||
216 | kfree(data); | ||
217 | return -ENOMEM; | ||
218 | } | ||
219 | |||
220 | memcpy(data->buffer, firmware->data, firmware->size); | ||
221 | |||
222 | usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), | ||
223 | data->buffer, firmware->size, bcm203x_complete, data); | ||
224 | |||
225 | release_firmware(firmware); | ||
226 | |||
227 | if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) { | ||
228 | BT_ERR("Firmware request failed"); | ||
229 | usb_free_urb(data->urb); | ||
230 | kfree(data->buffer); | ||
231 | kfree(data); | ||
232 | return -EIO; | ||
233 | } | ||
234 | |||
235 | BT_DBG("firmware data %p size %d", firmware->data, firmware->size); | ||
236 | |||
237 | data->fw_data = kmalloc(firmware->size, GFP_KERNEL); | ||
238 | if (!data->fw_data) { | ||
239 | BT_ERR("Can't allocate memory for firmware image"); | ||
240 | usb_free_urb(data->urb); | ||
241 | kfree(data->buffer); | ||
242 | kfree(data); | ||
243 | return -ENOMEM; | ||
244 | } | ||
245 | |||
246 | memcpy(data->fw_data, firmware->data, firmware->size); | ||
247 | data->fw_size = firmware->size; | ||
248 | data->fw_sent = 0; | ||
249 | |||
250 | release_firmware(firmware); | ||
251 | |||
252 | init_timer(&data->timer); | ||
253 | data->timer.function = bcm203x_timer; | ||
254 | data->timer.data = (unsigned long) data; | ||
255 | |||
256 | usb_set_intfdata(intf, data); | ||
257 | |||
258 | mod_timer(&data->timer, jiffies + HZ); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void bcm203x_disconnect(struct usb_interface *intf) | ||
264 | { | ||
265 | struct bcm203x_data *data = usb_get_intfdata(intf); | ||
266 | |||
267 | BT_DBG("intf %p", intf); | ||
268 | |||
269 | usb_kill_urb(data->urb); | ||
270 | |||
271 | usb_set_intfdata(intf, NULL); | ||
272 | |||
273 | usb_free_urb(data->urb); | ||
274 | kfree(data->fw_data); | ||
275 | kfree(data->buffer); | ||
276 | kfree(data); | ||
277 | } | ||
278 | |||
279 | static struct usb_driver bcm203x_driver = { | ||
280 | .owner = THIS_MODULE, | ||
281 | .name = "bcm203x", | ||
282 | .probe = bcm203x_probe, | ||
283 | .disconnect = bcm203x_disconnect, | ||
284 | .id_table = bcm203x_table, | ||
285 | }; | ||
286 | |||
287 | static int __init bcm203x_init(void) | ||
288 | { | ||
289 | int err; | ||
290 | |||
291 | BT_INFO("Broadcom Blutonium firmware driver ver %s", VERSION); | ||
292 | |||
293 | err = usb_register(&bcm203x_driver); | ||
294 | if (err < 0) | ||
295 | BT_ERR("Failed to register USB driver"); | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static void __exit bcm203x_exit(void) | ||
301 | { | ||
302 | usb_deregister(&bcm203x_driver); | ||
303 | } | ||
304 | |||
305 | module_init(bcm203x_init); | ||
306 | module_exit(bcm203x_exit); | ||
307 | |||
308 | module_param(ignore, bool, 0644); | ||
309 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); | ||
310 | |||
311 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
312 | MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION); | ||
313 | MODULE_VERSION(VERSION); | ||
314 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c new file mode 100644 index 000000000000..c42d7e6ac1c5 --- /dev/null +++ b/drivers/bluetooth/bfusb.c | |||
@@ -0,0 +1,806 @@ | |||
1 | /* | ||
2 | * | ||
3 | * AVM BlueFRITZ! USB driver | ||
4 | * | ||
5 | * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | |||
35 | #include <linux/device.h> | ||
36 | #include <linux/firmware.h> | ||
37 | |||
38 | #include <linux/usb.h> | ||
39 | |||
40 | #include <net/bluetooth/bluetooth.h> | ||
41 | #include <net/bluetooth/hci_core.h> | ||
42 | |||
43 | #ifndef CONFIG_BT_HCIBFUSB_DEBUG | ||
44 | #undef BT_DBG | ||
45 | #define BT_DBG(D...) | ||
46 | #endif | ||
47 | |||
48 | #define VERSION "1.1" | ||
49 | |||
50 | static int ignore = 0; | ||
51 | |||
52 | static struct usb_driver bfusb_driver; | ||
53 | |||
54 | static struct usb_device_id bfusb_table[] = { | ||
55 | /* AVM BlueFRITZ! USB */ | ||
56 | { USB_DEVICE(0x057c, 0x2200) }, | ||
57 | |||
58 | { } /* Terminating entry */ | ||
59 | }; | ||
60 | |||
61 | MODULE_DEVICE_TABLE(usb, bfusb_table); | ||
62 | |||
63 | |||
64 | #define BFUSB_MAX_BLOCK_SIZE 256 | ||
65 | |||
66 | #define BFUSB_BLOCK_TIMEOUT 3000 | ||
67 | |||
68 | #define BFUSB_TX_PROCESS 1 | ||
69 | #define BFUSB_TX_WAKEUP 2 | ||
70 | |||
71 | #define BFUSB_MAX_BULK_TX 2 | ||
72 | #define BFUSB_MAX_BULK_RX 2 | ||
73 | |||
74 | struct bfusb { | ||
75 | struct hci_dev *hdev; | ||
76 | |||
77 | unsigned long state; | ||
78 | |||
79 | struct usb_device *udev; | ||
80 | |||
81 | unsigned int bulk_in_ep; | ||
82 | unsigned int bulk_out_ep; | ||
83 | unsigned int bulk_pkt_size; | ||
84 | |||
85 | rwlock_t lock; | ||
86 | |||
87 | struct sk_buff_head transmit_q; | ||
88 | |||
89 | struct sk_buff *reassembly; | ||
90 | |||
91 | atomic_t pending_tx; | ||
92 | struct sk_buff_head pending_q; | ||
93 | struct sk_buff_head completed_q; | ||
94 | }; | ||
95 | |||
96 | struct bfusb_scb { | ||
97 | struct urb *urb; | ||
98 | }; | ||
99 | |||
100 | static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs); | ||
101 | static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs); | ||
102 | |||
103 | static struct urb *bfusb_get_completed(struct bfusb *bfusb) | ||
104 | { | ||
105 | struct sk_buff *skb; | ||
106 | struct urb *urb = NULL; | ||
107 | |||
108 | BT_DBG("bfusb %p", bfusb); | ||
109 | |||
110 | skb = skb_dequeue(&bfusb->completed_q); | ||
111 | if (skb) { | ||
112 | urb = ((struct bfusb_scb *) skb->cb)->urb; | ||
113 | kfree_skb(skb); | ||
114 | } | ||
115 | |||
116 | return urb; | ||
117 | } | ||
118 | |||
119 | static void bfusb_unlink_urbs(struct bfusb *bfusb) | ||
120 | { | ||
121 | struct sk_buff *skb; | ||
122 | struct urb *urb; | ||
123 | |||
124 | BT_DBG("bfusb %p", bfusb); | ||
125 | |||
126 | while ((skb = skb_dequeue(&bfusb->pending_q))) { | ||
127 | urb = ((struct bfusb_scb *) skb->cb)->urb; | ||
128 | usb_kill_urb(urb); | ||
129 | skb_queue_tail(&bfusb->completed_q, skb); | ||
130 | } | ||
131 | |||
132 | while ((urb = bfusb_get_completed(bfusb))) | ||
133 | usb_free_urb(urb); | ||
134 | } | ||
135 | |||
136 | |||
137 | static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb) | ||
138 | { | ||
139 | struct bfusb_scb *scb = (void *) skb->cb; | ||
140 | struct urb *urb = bfusb_get_completed(bfusb); | ||
141 | int err, pipe; | ||
142 | |||
143 | BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len); | ||
144 | |||
145 | if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep); | ||
149 | |||
150 | usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, skb->len, | ||
151 | bfusb_tx_complete, skb); | ||
152 | |||
153 | scb->urb = urb; | ||
154 | |||
155 | skb_queue_tail(&bfusb->pending_q, skb); | ||
156 | |||
157 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
158 | if (err) { | ||
159 | BT_ERR("%s bulk tx submit failed urb %p err %d", | ||
160 | bfusb->hdev->name, urb, err); | ||
161 | skb_unlink(skb); | ||
162 | usb_free_urb(urb); | ||
163 | } else | ||
164 | atomic_inc(&bfusb->pending_tx); | ||
165 | |||
166 | return err; | ||
167 | } | ||
168 | |||
169 | static void bfusb_tx_wakeup(struct bfusb *bfusb) | ||
170 | { | ||
171 | struct sk_buff *skb; | ||
172 | |||
173 | BT_DBG("bfusb %p", bfusb); | ||
174 | |||
175 | if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) { | ||
176 | set_bit(BFUSB_TX_WAKEUP, &bfusb->state); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | do { | ||
181 | clear_bit(BFUSB_TX_WAKEUP, &bfusb->state); | ||
182 | |||
183 | while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) && | ||
184 | (skb = skb_dequeue(&bfusb->transmit_q))) { | ||
185 | if (bfusb_send_bulk(bfusb, skb) < 0) { | ||
186 | skb_queue_head(&bfusb->transmit_q, skb); | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | } while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state)); | ||
192 | |||
193 | clear_bit(BFUSB_TX_PROCESS, &bfusb->state); | ||
194 | } | ||
195 | |||
196 | static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs) | ||
197 | { | ||
198 | struct sk_buff *skb = (struct sk_buff *) urb->context; | ||
199 | struct bfusb *bfusb = (struct bfusb *) skb->dev; | ||
200 | |||
201 | BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len); | ||
202 | |||
203 | atomic_dec(&bfusb->pending_tx); | ||
204 | |||
205 | if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags)) | ||
206 | return; | ||
207 | |||
208 | if (!urb->status) | ||
209 | bfusb->hdev->stat.byte_tx += skb->len; | ||
210 | else | ||
211 | bfusb->hdev->stat.err_tx++; | ||
212 | |||
213 | read_lock(&bfusb->lock); | ||
214 | |||
215 | skb_unlink(skb); | ||
216 | skb_queue_tail(&bfusb->completed_q, skb); | ||
217 | |||
218 | bfusb_tx_wakeup(bfusb); | ||
219 | |||
220 | read_unlock(&bfusb->lock); | ||
221 | } | ||
222 | |||
223 | |||
224 | static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb) | ||
225 | { | ||
226 | struct bfusb_scb *scb; | ||
227 | struct sk_buff *skb; | ||
228 | int err, pipe, size = HCI_MAX_FRAME_SIZE + 32; | ||
229 | |||
230 | BT_DBG("bfusb %p urb %p", bfusb, urb); | ||
231 | |||
232 | if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) | ||
233 | return -ENOMEM; | ||
234 | |||
235 | if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) { | ||
236 | usb_free_urb(urb); | ||
237 | return -ENOMEM; | ||
238 | } | ||
239 | |||
240 | skb->dev = (void *) bfusb; | ||
241 | |||
242 | scb = (struct bfusb_scb *) skb->cb; | ||
243 | scb->urb = urb; | ||
244 | |||
245 | pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep); | ||
246 | |||
247 | usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, size, | ||
248 | bfusb_rx_complete, skb); | ||
249 | |||
250 | skb_queue_tail(&bfusb->pending_q, skb); | ||
251 | |||
252 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
253 | if (err) { | ||
254 | BT_ERR("%s bulk rx submit failed urb %p err %d", | ||
255 | bfusb->hdev->name, urb, err); | ||
256 | skb_unlink(skb); | ||
257 | kfree_skb(skb); | ||
258 | usb_free_urb(urb); | ||
259 | } | ||
260 | |||
261 | return err; | ||
262 | } | ||
263 | |||
264 | static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len) | ||
265 | { | ||
266 | BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len); | ||
267 | |||
268 | if (hdr & 0x10) { | ||
269 | BT_ERR("%s error in block", bfusb->hdev->name); | ||
270 | if (bfusb->reassembly) | ||
271 | kfree_skb(bfusb->reassembly); | ||
272 | bfusb->reassembly = NULL; | ||
273 | return -EIO; | ||
274 | } | ||
275 | |||
276 | if (hdr & 0x04) { | ||
277 | struct sk_buff *skb; | ||
278 | unsigned char pkt_type; | ||
279 | int pkt_len = 0; | ||
280 | |||
281 | if (bfusb->reassembly) { | ||
282 | BT_ERR("%s unexpected start block", bfusb->hdev->name); | ||
283 | kfree_skb(bfusb->reassembly); | ||
284 | bfusb->reassembly = NULL; | ||
285 | } | ||
286 | |||
287 | if (len < 1) { | ||
288 | BT_ERR("%s no packet type found", bfusb->hdev->name); | ||
289 | return -EPROTO; | ||
290 | } | ||
291 | |||
292 | pkt_type = *data++; len--; | ||
293 | |||
294 | switch (pkt_type) { | ||
295 | case HCI_EVENT_PKT: | ||
296 | if (len >= HCI_EVENT_HDR_SIZE) { | ||
297 | struct hci_event_hdr *hdr = (struct hci_event_hdr *) data; | ||
298 | pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen; | ||
299 | } else { | ||
300 | BT_ERR("%s event block is too short", bfusb->hdev->name); | ||
301 | return -EILSEQ; | ||
302 | } | ||
303 | break; | ||
304 | |||
305 | case HCI_ACLDATA_PKT: | ||
306 | if (len >= HCI_ACL_HDR_SIZE) { | ||
307 | struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data; | ||
308 | pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen); | ||
309 | } else { | ||
310 | BT_ERR("%s data block is too short", bfusb->hdev->name); | ||
311 | return -EILSEQ; | ||
312 | } | ||
313 | break; | ||
314 | |||
315 | case HCI_SCODATA_PKT: | ||
316 | if (len >= HCI_SCO_HDR_SIZE) { | ||
317 | struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data; | ||
318 | pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen; | ||
319 | } else { | ||
320 | BT_ERR("%s audio block is too short", bfusb->hdev->name); | ||
321 | return -EILSEQ; | ||
322 | } | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | skb = bt_skb_alloc(pkt_len, GFP_ATOMIC); | ||
327 | if (!skb) { | ||
328 | BT_ERR("%s no memory for the packet", bfusb->hdev->name); | ||
329 | return -ENOMEM; | ||
330 | } | ||
331 | |||
332 | skb->dev = (void *) bfusb->hdev; | ||
333 | skb->pkt_type = pkt_type; | ||
334 | |||
335 | bfusb->reassembly = skb; | ||
336 | } else { | ||
337 | if (!bfusb->reassembly) { | ||
338 | BT_ERR("%s unexpected continuation block", bfusb->hdev->name); | ||
339 | return -EIO; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | if (len > 0) | ||
344 | memcpy(skb_put(bfusb->reassembly, len), data, len); | ||
345 | |||
346 | if (hdr & 0x08) { | ||
347 | hci_recv_frame(bfusb->reassembly); | ||
348 | bfusb->reassembly = NULL; | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs) | ||
355 | { | ||
356 | struct sk_buff *skb = (struct sk_buff *) urb->context; | ||
357 | struct bfusb *bfusb = (struct bfusb *) skb->dev; | ||
358 | unsigned char *buf = urb->transfer_buffer; | ||
359 | int count = urb->actual_length; | ||
360 | int err, hdr, len; | ||
361 | |||
362 | BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len); | ||
363 | |||
364 | read_lock(&bfusb->lock); | ||
365 | |||
366 | if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags)) | ||
367 | goto unlock; | ||
368 | |||
369 | if (urb->status || !count) | ||
370 | goto resubmit; | ||
371 | |||
372 | bfusb->hdev->stat.byte_rx += count; | ||
373 | |||
374 | skb_put(skb, count); | ||
375 | |||
376 | while (count) { | ||
377 | hdr = buf[0] | (buf[1] << 8); | ||
378 | |||
379 | if (hdr & 0x4000) { | ||
380 | len = 0; | ||
381 | count -= 2; | ||
382 | buf += 2; | ||
383 | } else { | ||
384 | len = (buf[2] == 0) ? 256 : buf[2]; | ||
385 | count -= 3; | ||
386 | buf += 3; | ||
387 | } | ||
388 | |||
389 | if (count < len) { | ||
390 | BT_ERR("%s block extends over URB buffer ranges", | ||
391 | bfusb->hdev->name); | ||
392 | } | ||
393 | |||
394 | if ((hdr & 0xe1) == 0xc1) | ||
395 | bfusb_recv_block(bfusb, hdr, buf, len); | ||
396 | |||
397 | count -= len; | ||
398 | buf += len; | ||
399 | } | ||
400 | |||
401 | skb_unlink(skb); | ||
402 | kfree_skb(skb); | ||
403 | |||
404 | bfusb_rx_submit(bfusb, urb); | ||
405 | |||
406 | read_unlock(&bfusb->lock); | ||
407 | |||
408 | return; | ||
409 | |||
410 | resubmit: | ||
411 | urb->dev = bfusb->udev; | ||
412 | |||
413 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
414 | if (err) { | ||
415 | BT_ERR("%s bulk resubmit failed urb %p err %d", | ||
416 | bfusb->hdev->name, urb, err); | ||
417 | } | ||
418 | |||
419 | unlock: | ||
420 | read_unlock(&bfusb->lock); | ||
421 | } | ||
422 | |||
423 | |||
424 | static int bfusb_open(struct hci_dev *hdev) | ||
425 | { | ||
426 | struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; | ||
427 | unsigned long flags; | ||
428 | int i, err; | ||
429 | |||
430 | BT_DBG("hdev %p bfusb %p", hdev, bfusb); | ||
431 | |||
432 | if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) | ||
433 | return 0; | ||
434 | |||
435 | write_lock_irqsave(&bfusb->lock, flags); | ||
436 | |||
437 | err = bfusb_rx_submit(bfusb, NULL); | ||
438 | if (!err) { | ||
439 | for (i = 1; i < BFUSB_MAX_BULK_RX; i++) | ||
440 | bfusb_rx_submit(bfusb, NULL); | ||
441 | } else { | ||
442 | clear_bit(HCI_RUNNING, &hdev->flags); | ||
443 | } | ||
444 | |||
445 | write_unlock_irqrestore(&bfusb->lock, flags); | ||
446 | |||
447 | return err; | ||
448 | } | ||
449 | |||
450 | static int bfusb_flush(struct hci_dev *hdev) | ||
451 | { | ||
452 | struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; | ||
453 | |||
454 | BT_DBG("hdev %p bfusb %p", hdev, bfusb); | ||
455 | |||
456 | skb_queue_purge(&bfusb->transmit_q); | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static int bfusb_close(struct hci_dev *hdev) | ||
462 | { | ||
463 | struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; | ||
464 | unsigned long flags; | ||
465 | |||
466 | BT_DBG("hdev %p bfusb %p", hdev, bfusb); | ||
467 | |||
468 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
469 | return 0; | ||
470 | |||
471 | write_lock_irqsave(&bfusb->lock, flags); | ||
472 | write_unlock_irqrestore(&bfusb->lock, flags); | ||
473 | |||
474 | bfusb_unlink_urbs(bfusb); | ||
475 | bfusb_flush(hdev); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int bfusb_send_frame(struct sk_buff *skb) | ||
481 | { | ||
482 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
483 | struct bfusb *bfusb; | ||
484 | struct sk_buff *nskb; | ||
485 | unsigned char buf[3]; | ||
486 | int sent = 0, size, count; | ||
487 | |||
488 | BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len); | ||
489 | |||
490 | if (!hdev) { | ||
491 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
492 | return -ENODEV; | ||
493 | } | ||
494 | |||
495 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
496 | return -EBUSY; | ||
497 | |||
498 | bfusb = (struct bfusb *) hdev->driver_data; | ||
499 | |||
500 | switch (skb->pkt_type) { | ||
501 | case HCI_COMMAND_PKT: | ||
502 | hdev->stat.cmd_tx++; | ||
503 | break; | ||
504 | case HCI_ACLDATA_PKT: | ||
505 | hdev->stat.acl_tx++; | ||
506 | break; | ||
507 | case HCI_SCODATA_PKT: | ||
508 | hdev->stat.sco_tx++; | ||
509 | break; | ||
510 | }; | ||
511 | |||
512 | /* Prepend skb with frame type */ | ||
513 | memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); | ||
514 | |||
515 | count = skb->len; | ||
516 | |||
517 | /* Max HCI frame size seems to be 1511 + 1 */ | ||
518 | if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) { | ||
519 | BT_ERR("Can't allocate memory for new packet"); | ||
520 | return -ENOMEM; | ||
521 | } | ||
522 | |||
523 | nskb->dev = (void *) bfusb; | ||
524 | |||
525 | while (count) { | ||
526 | size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE); | ||
527 | |||
528 | buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0); | ||
529 | buf[1] = 0x00; | ||
530 | buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size; | ||
531 | |||
532 | memcpy(skb_put(nskb, 3), buf, 3); | ||
533 | memcpy(skb_put(nskb, size), skb->data + sent, size); | ||
534 | |||
535 | sent += size; | ||
536 | count -= size; | ||
537 | } | ||
538 | |||
539 | /* Don't send frame with multiple size of bulk max packet */ | ||
540 | if ((nskb->len % bfusb->bulk_pkt_size) == 0) { | ||
541 | buf[0] = 0xdd; | ||
542 | buf[1] = 0x00; | ||
543 | memcpy(skb_put(nskb, 2), buf, 2); | ||
544 | } | ||
545 | |||
546 | read_lock(&bfusb->lock); | ||
547 | |||
548 | skb_queue_tail(&bfusb->transmit_q, nskb); | ||
549 | bfusb_tx_wakeup(bfusb); | ||
550 | |||
551 | read_unlock(&bfusb->lock); | ||
552 | |||
553 | kfree_skb(skb); | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static void bfusb_destruct(struct hci_dev *hdev) | ||
559 | { | ||
560 | struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; | ||
561 | |||
562 | BT_DBG("hdev %p bfusb %p", hdev, bfusb); | ||
563 | |||
564 | kfree(bfusb); | ||
565 | } | ||
566 | |||
567 | static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
568 | { | ||
569 | return -ENOIOCTLCMD; | ||
570 | } | ||
571 | |||
572 | |||
573 | static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count) | ||
574 | { | ||
575 | unsigned char *buf; | ||
576 | int err, pipe, len, size, sent = 0; | ||
577 | |||
578 | BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev); | ||
579 | |||
580 | BT_INFO("BlueFRITZ! USB loading firmware"); | ||
581 | |||
582 | pipe = usb_sndctrlpipe(bfusb->udev, 0); | ||
583 | |||
584 | if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, | ||
585 | 0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) { | ||
586 | BT_ERR("Can't change to loading configuration"); | ||
587 | return -EBUSY; | ||
588 | } | ||
589 | |||
590 | bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0; | ||
591 | |||
592 | buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC); | ||
593 | if (!buf) { | ||
594 | BT_ERR("Can't allocate memory chunk for firmware"); | ||
595 | return -ENOMEM; | ||
596 | } | ||
597 | |||
598 | pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep); | ||
599 | |||
600 | while (count) { | ||
601 | size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3); | ||
602 | |||
603 | memcpy(buf, firmware + sent, size); | ||
604 | |||
605 | err = usb_bulk_msg(bfusb->udev, pipe, buf, size, | ||
606 | &len, BFUSB_BLOCK_TIMEOUT); | ||
607 | |||
608 | if (err || (len != size)) { | ||
609 | BT_ERR("Error in firmware loading"); | ||
610 | goto error; | ||
611 | } | ||
612 | |||
613 | sent += size; | ||
614 | count -= size; | ||
615 | } | ||
616 | |||
617 | if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0, | ||
618 | &len, BFUSB_BLOCK_TIMEOUT)) < 0) { | ||
619 | BT_ERR("Error in null packet request"); | ||
620 | goto error; | ||
621 | } | ||
622 | |||
623 | pipe = usb_sndctrlpipe(bfusb->udev, 0); | ||
624 | |||
625 | if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, | ||
626 | 0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) { | ||
627 | BT_ERR("Can't change to running configuration"); | ||
628 | goto error; | ||
629 | } | ||
630 | |||
631 | bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0; | ||
632 | |||
633 | BT_INFO("BlueFRITZ! USB device ready"); | ||
634 | |||
635 | kfree(buf); | ||
636 | return 0; | ||
637 | |||
638 | error: | ||
639 | kfree(buf); | ||
640 | |||
641 | pipe = usb_sndctrlpipe(bfusb->udev, 0); | ||
642 | |||
643 | usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, | ||
644 | 0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
645 | |||
646 | return err; | ||
647 | } | ||
648 | |||
649 | static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
650 | { | ||
651 | const struct firmware *firmware; | ||
652 | struct usb_device *udev = interface_to_usbdev(intf); | ||
653 | struct usb_host_endpoint *bulk_out_ep; | ||
654 | struct usb_host_endpoint *bulk_in_ep; | ||
655 | struct hci_dev *hdev; | ||
656 | struct bfusb *bfusb; | ||
657 | |||
658 | BT_DBG("intf %p id %p", intf, id); | ||
659 | |||
660 | if (ignore) | ||
661 | return -ENODEV; | ||
662 | |||
663 | /* Check number of endpoints */ | ||
664 | if (intf->cur_altsetting->desc.bNumEndpoints < 2) | ||
665 | return -EIO; | ||
666 | |||
667 | bulk_out_ep = &intf->cur_altsetting->endpoint[0]; | ||
668 | bulk_in_ep = &intf->cur_altsetting->endpoint[1]; | ||
669 | |||
670 | if (!bulk_out_ep || !bulk_in_ep) { | ||
671 | BT_ERR("Bulk endpoints not found"); | ||
672 | goto done; | ||
673 | } | ||
674 | |||
675 | /* Initialize control structure and load firmware */ | ||
676 | if (!(bfusb = kmalloc(sizeof(struct bfusb), GFP_KERNEL))) { | ||
677 | BT_ERR("Can't allocate memory for control structure"); | ||
678 | goto done; | ||
679 | } | ||
680 | |||
681 | memset(bfusb, 0, sizeof(struct bfusb)); | ||
682 | |||
683 | bfusb->udev = udev; | ||
684 | bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress; | ||
685 | bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; | ||
686 | bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize); | ||
687 | |||
688 | rwlock_init(&bfusb->lock); | ||
689 | |||
690 | bfusb->reassembly = NULL; | ||
691 | |||
692 | skb_queue_head_init(&bfusb->transmit_q); | ||
693 | skb_queue_head_init(&bfusb->pending_q); | ||
694 | skb_queue_head_init(&bfusb->completed_q); | ||
695 | |||
696 | if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { | ||
697 | BT_ERR("Firmware request failed"); | ||
698 | goto error; | ||
699 | } | ||
700 | |||
701 | BT_DBG("firmware data %p size %d", firmware->data, firmware->size); | ||
702 | |||
703 | if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) { | ||
704 | BT_ERR("Firmware loading failed"); | ||
705 | goto release; | ||
706 | } | ||
707 | |||
708 | release_firmware(firmware); | ||
709 | |||
710 | /* Initialize and register HCI device */ | ||
711 | hdev = hci_alloc_dev(); | ||
712 | if (!hdev) { | ||
713 | BT_ERR("Can't allocate HCI device"); | ||
714 | goto error; | ||
715 | } | ||
716 | |||
717 | bfusb->hdev = hdev; | ||
718 | |||
719 | hdev->type = HCI_USB; | ||
720 | hdev->driver_data = bfusb; | ||
721 | SET_HCIDEV_DEV(hdev, &intf->dev); | ||
722 | |||
723 | hdev->open = bfusb_open; | ||
724 | hdev->close = bfusb_close; | ||
725 | hdev->flush = bfusb_flush; | ||
726 | hdev->send = bfusb_send_frame; | ||
727 | hdev->destruct = bfusb_destruct; | ||
728 | hdev->ioctl = bfusb_ioctl; | ||
729 | |||
730 | hdev->owner = THIS_MODULE; | ||
731 | |||
732 | if (hci_register_dev(hdev) < 0) { | ||
733 | BT_ERR("Can't register HCI device"); | ||
734 | hci_free_dev(hdev); | ||
735 | goto error; | ||
736 | } | ||
737 | |||
738 | usb_set_intfdata(intf, bfusb); | ||
739 | |||
740 | return 0; | ||
741 | |||
742 | release: | ||
743 | release_firmware(firmware); | ||
744 | |||
745 | error: | ||
746 | kfree(bfusb); | ||
747 | |||
748 | done: | ||
749 | return -EIO; | ||
750 | } | ||
751 | |||
752 | static void bfusb_disconnect(struct usb_interface *intf) | ||
753 | { | ||
754 | struct bfusb *bfusb = usb_get_intfdata(intf); | ||
755 | struct hci_dev *hdev = bfusb->hdev; | ||
756 | |||
757 | BT_DBG("intf %p", intf); | ||
758 | |||
759 | if (!hdev) | ||
760 | return; | ||
761 | |||
762 | usb_set_intfdata(intf, NULL); | ||
763 | |||
764 | bfusb_close(hdev); | ||
765 | |||
766 | if (hci_unregister_dev(hdev) < 0) | ||
767 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
768 | |||
769 | hci_free_dev(hdev); | ||
770 | } | ||
771 | |||
772 | static struct usb_driver bfusb_driver = { | ||
773 | .owner = THIS_MODULE, | ||
774 | .name = "bfusb", | ||
775 | .probe = bfusb_probe, | ||
776 | .disconnect = bfusb_disconnect, | ||
777 | .id_table = bfusb_table, | ||
778 | }; | ||
779 | |||
780 | static int __init bfusb_init(void) | ||
781 | { | ||
782 | int err; | ||
783 | |||
784 | BT_INFO("BlueFRITZ! USB driver ver %s", VERSION); | ||
785 | |||
786 | if ((err = usb_register(&bfusb_driver)) < 0) | ||
787 | BT_ERR("Failed to register BlueFRITZ! USB driver"); | ||
788 | |||
789 | return err; | ||
790 | } | ||
791 | |||
792 | static void __exit bfusb_exit(void) | ||
793 | { | ||
794 | usb_deregister(&bfusb_driver); | ||
795 | } | ||
796 | |||
797 | module_init(bfusb_init); | ||
798 | module_exit(bfusb_exit); | ||
799 | |||
800 | module_param(ignore, bool, 0644); | ||
801 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); | ||
802 | |||
803 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
804 | MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION); | ||
805 | MODULE_VERSION(VERSION); | ||
806 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c new file mode 100644 index 000000000000..e481cc411b5d --- /dev/null +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Bluetooth driver for the Anycom BlueCard (LSE039/LSE041) | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * | ||
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 | * Software distributed under the License is distributed on an "AS | ||
13 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
14 | * implied. See the License for the specific language governing | ||
15 | * rights and limitations under the License. | ||
16 | * | ||
17 | * The initial developer of the original code is David A. Hinds | ||
18 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
19 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/timer.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/moduleparam.h> | ||
38 | #include <linux/wait.h> | ||
39 | |||
40 | #include <linux/skbuff.h> | ||
41 | #include <asm/io.h> | ||
42 | |||
43 | #include <pcmcia/version.h> | ||
44 | #include <pcmcia/cs_types.h> | ||
45 | #include <pcmcia/cs.h> | ||
46 | #include <pcmcia/cistpl.h> | ||
47 | #include <pcmcia/ciscode.h> | ||
48 | #include <pcmcia/ds.h> | ||
49 | #include <pcmcia/cisreg.h> | ||
50 | |||
51 | #include <net/bluetooth/bluetooth.h> | ||
52 | #include <net/bluetooth/hci_core.h> | ||
53 | |||
54 | |||
55 | |||
56 | /* ======================== Module parameters ======================== */ | ||
57 | |||
58 | |||
59 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
60 | MODULE_DESCRIPTION("Bluetooth driver for the Anycom BlueCard (LSE039/LSE041)"); | ||
61 | MODULE_LICENSE("GPL"); | ||
62 | |||
63 | |||
64 | |||
65 | /* ======================== Local structures ======================== */ | ||
66 | |||
67 | |||
68 | typedef struct bluecard_info_t { | ||
69 | dev_link_t link; | ||
70 | dev_node_t node; | ||
71 | |||
72 | struct hci_dev *hdev; | ||
73 | |||
74 | spinlock_t lock; /* For serializing operations */ | ||
75 | struct timer_list timer; /* For LED control */ | ||
76 | |||
77 | struct sk_buff_head txq; | ||
78 | unsigned long tx_state; | ||
79 | |||
80 | unsigned long rx_state; | ||
81 | unsigned long rx_count; | ||
82 | struct sk_buff *rx_skb; | ||
83 | |||
84 | unsigned char ctrl_reg; | ||
85 | unsigned long hw_state; /* Status of the hardware and LED control */ | ||
86 | } bluecard_info_t; | ||
87 | |||
88 | |||
89 | static void bluecard_config(dev_link_t *link); | ||
90 | static void bluecard_release(dev_link_t *link); | ||
91 | static int bluecard_event(event_t event, int priority, event_callback_args_t *args); | ||
92 | |||
93 | static dev_info_t dev_info = "bluecard_cs"; | ||
94 | |||
95 | static dev_link_t *bluecard_attach(void); | ||
96 | static void bluecard_detach(dev_link_t *); | ||
97 | |||
98 | static dev_link_t *dev_list = NULL; | ||
99 | |||
100 | |||
101 | /* Default baud rate: 57600, 115200, 230400 or 460800 */ | ||
102 | #define DEFAULT_BAUD_RATE 230400 | ||
103 | |||
104 | |||
105 | /* Hardware states */ | ||
106 | #define CARD_READY 1 | ||
107 | #define CARD_HAS_PCCARD_ID 4 | ||
108 | #define CARD_HAS_POWER_LED 5 | ||
109 | #define CARD_HAS_ACTIVITY_LED 6 | ||
110 | |||
111 | /* Transmit states */ | ||
112 | #define XMIT_SENDING 1 | ||
113 | #define XMIT_WAKEUP 2 | ||
114 | #define XMIT_BUFFER_NUMBER 5 /* unset = buffer one, set = buffer two */ | ||
115 | #define XMIT_BUF_ONE_READY 6 | ||
116 | #define XMIT_BUF_TWO_READY 7 | ||
117 | #define XMIT_SENDING_READY 8 | ||
118 | |||
119 | /* Receiver states */ | ||
120 | #define RECV_WAIT_PACKET_TYPE 0 | ||
121 | #define RECV_WAIT_EVENT_HEADER 1 | ||
122 | #define RECV_WAIT_ACL_HEADER 2 | ||
123 | #define RECV_WAIT_SCO_HEADER 3 | ||
124 | #define RECV_WAIT_DATA 4 | ||
125 | |||
126 | /* Special packet types */ | ||
127 | #define PKT_BAUD_RATE_57600 0x80 | ||
128 | #define PKT_BAUD_RATE_115200 0x81 | ||
129 | #define PKT_BAUD_RATE_230400 0x82 | ||
130 | #define PKT_BAUD_RATE_460800 0x83 | ||
131 | |||
132 | |||
133 | /* These are the register offsets */ | ||
134 | #define REG_COMMAND 0x20 | ||
135 | #define REG_INTERRUPT 0x21 | ||
136 | #define REG_CONTROL 0x22 | ||
137 | #define REG_RX_CONTROL 0x24 | ||
138 | #define REG_CARD_RESET 0x30 | ||
139 | #define REG_LED_CTRL 0x30 | ||
140 | |||
141 | /* REG_COMMAND */ | ||
142 | #define REG_COMMAND_TX_BUF_ONE 0x01 | ||
143 | #define REG_COMMAND_TX_BUF_TWO 0x02 | ||
144 | #define REG_COMMAND_RX_BUF_ONE 0x04 | ||
145 | #define REG_COMMAND_RX_BUF_TWO 0x08 | ||
146 | #define REG_COMMAND_RX_WIN_ONE 0x00 | ||
147 | #define REG_COMMAND_RX_WIN_TWO 0x10 | ||
148 | |||
149 | /* REG_CONTROL */ | ||
150 | #define REG_CONTROL_BAUD_RATE_57600 0x00 | ||
151 | #define REG_CONTROL_BAUD_RATE_115200 0x01 | ||
152 | #define REG_CONTROL_BAUD_RATE_230400 0x02 | ||
153 | #define REG_CONTROL_BAUD_RATE_460800 0x03 | ||
154 | #define REG_CONTROL_RTS 0x04 | ||
155 | #define REG_CONTROL_BT_ON 0x08 | ||
156 | #define REG_CONTROL_BT_RESET 0x10 | ||
157 | #define REG_CONTROL_BT_RES_PU 0x20 | ||
158 | #define REG_CONTROL_INTERRUPT 0x40 | ||
159 | #define REG_CONTROL_CARD_RESET 0x80 | ||
160 | |||
161 | /* REG_RX_CONTROL */ | ||
162 | #define RTS_LEVEL_SHIFT_BITS 0x02 | ||
163 | |||
164 | |||
165 | |||
166 | /* ======================== LED handling routines ======================== */ | ||
167 | |||
168 | |||
169 | static void bluecard_activity_led_timeout(u_long arg) | ||
170 | { | ||
171 | bluecard_info_t *info = (bluecard_info_t *)arg; | ||
172 | unsigned int iobase = info->link.io.BasePort1; | ||
173 | |||
174 | if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) | ||
175 | return; | ||
176 | |||
177 | if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { | ||
178 | /* Disable activity LED */ | ||
179 | outb(0x08 | 0x20, iobase + 0x30); | ||
180 | } else { | ||
181 | /* Disable power LED */ | ||
182 | outb(0x00, iobase + 0x30); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | |||
187 | static void bluecard_enable_activity_led(bluecard_info_t *info) | ||
188 | { | ||
189 | unsigned int iobase = info->link.io.BasePort1; | ||
190 | |||
191 | if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) | ||
192 | return; | ||
193 | |||
194 | if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { | ||
195 | /* Enable activity LED */ | ||
196 | outb(0x10 | 0x40, iobase + 0x30); | ||
197 | |||
198 | /* Stop the LED after HZ/4 */ | ||
199 | mod_timer(&(info->timer), jiffies + HZ / 4); | ||
200 | } else { | ||
201 | /* Enable power LED */ | ||
202 | outb(0x08 | 0x20, iobase + 0x30); | ||
203 | |||
204 | /* Stop the LED after HZ/2 */ | ||
205 | mod_timer(&(info->timer), jiffies + HZ / 2); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | |||
210 | |||
211 | /* ======================== Interrupt handling ======================== */ | ||
212 | |||
213 | |||
214 | static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len) | ||
215 | { | ||
216 | int i, actual; | ||
217 | |||
218 | actual = (len > 15) ? 15 : len; | ||
219 | |||
220 | outb_p(actual, iobase + offset); | ||
221 | |||
222 | for (i = 0; i < actual; i++) | ||
223 | outb_p(buf[i], iobase + offset + i + 1); | ||
224 | |||
225 | return actual; | ||
226 | } | ||
227 | |||
228 | |||
229 | static void bluecard_write_wakeup(bluecard_info_t *info) | ||
230 | { | ||
231 | if (!info) { | ||
232 | BT_ERR("Unknown device"); | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | if (!test_bit(XMIT_SENDING_READY, &(info->tx_state))) | ||
237 | return; | ||
238 | |||
239 | if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { | ||
240 | set_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | do { | ||
245 | register unsigned int iobase = info->link.io.BasePort1; | ||
246 | register unsigned int offset; | ||
247 | register unsigned char command; | ||
248 | register unsigned long ready_bit; | ||
249 | register struct sk_buff *skb; | ||
250 | register int len; | ||
251 | |||
252 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
253 | |||
254 | if (!(info->link.state & DEV_PRESENT)) | ||
255 | return; | ||
256 | |||
257 | if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { | ||
258 | if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state))) | ||
259 | break; | ||
260 | offset = 0x10; | ||
261 | command = REG_COMMAND_TX_BUF_TWO; | ||
262 | ready_bit = XMIT_BUF_TWO_READY; | ||
263 | } else { | ||
264 | if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state))) | ||
265 | break; | ||
266 | offset = 0x00; | ||
267 | command = REG_COMMAND_TX_BUF_ONE; | ||
268 | ready_bit = XMIT_BUF_ONE_READY; | ||
269 | } | ||
270 | |||
271 | if (!(skb = skb_dequeue(&(info->txq)))) | ||
272 | break; | ||
273 | |||
274 | if (skb->pkt_type & 0x80) { | ||
275 | /* Disable RTS */ | ||
276 | info->ctrl_reg |= REG_CONTROL_RTS; | ||
277 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
278 | } | ||
279 | |||
280 | /* Activate LED */ | ||
281 | bluecard_enable_activity_led(info); | ||
282 | |||
283 | /* Send frame */ | ||
284 | len = bluecard_write(iobase, offset, skb->data, skb->len); | ||
285 | |||
286 | /* Tell the FPGA to send the data */ | ||
287 | outb_p(command, iobase + REG_COMMAND); | ||
288 | |||
289 | /* Mark the buffer as dirty */ | ||
290 | clear_bit(ready_bit, &(info->tx_state)); | ||
291 | |||
292 | if (skb->pkt_type & 0x80) { | ||
293 | DECLARE_WAIT_QUEUE_HEAD(wq); | ||
294 | DEFINE_WAIT(wait); | ||
295 | |||
296 | unsigned char baud_reg; | ||
297 | |||
298 | switch (skb->pkt_type) { | ||
299 | case PKT_BAUD_RATE_460800: | ||
300 | baud_reg = REG_CONTROL_BAUD_RATE_460800; | ||
301 | break; | ||
302 | case PKT_BAUD_RATE_230400: | ||
303 | baud_reg = REG_CONTROL_BAUD_RATE_230400; | ||
304 | break; | ||
305 | case PKT_BAUD_RATE_115200: | ||
306 | baud_reg = REG_CONTROL_BAUD_RATE_115200; | ||
307 | break; | ||
308 | case PKT_BAUD_RATE_57600: | ||
309 | /* Fall through... */ | ||
310 | default: | ||
311 | baud_reg = REG_CONTROL_BAUD_RATE_57600; | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | /* Wait until the command reaches the baseband */ | ||
316 | prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); | ||
317 | schedule_timeout(HZ/10); | ||
318 | finish_wait(&wq, &wait); | ||
319 | |||
320 | /* Set baud on baseband */ | ||
321 | info->ctrl_reg &= ~0x03; | ||
322 | info->ctrl_reg |= baud_reg; | ||
323 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
324 | |||
325 | /* Enable RTS */ | ||
326 | info->ctrl_reg &= ~REG_CONTROL_RTS; | ||
327 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
328 | |||
329 | /* Wait before the next HCI packet can be send */ | ||
330 | prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE); | ||
331 | schedule_timeout(HZ); | ||
332 | finish_wait(&wq, &wait); | ||
333 | } | ||
334 | |||
335 | if (len == skb->len) { | ||
336 | kfree_skb(skb); | ||
337 | } else { | ||
338 | skb_pull(skb, len); | ||
339 | skb_queue_head(&(info->txq), skb); | ||
340 | } | ||
341 | |||
342 | info->hdev->stat.byte_tx += len; | ||
343 | |||
344 | /* Change buffer */ | ||
345 | change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state)); | ||
346 | |||
347 | } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); | ||
348 | |||
349 | clear_bit(XMIT_SENDING, &(info->tx_state)); | ||
350 | } | ||
351 | |||
352 | |||
353 | static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size) | ||
354 | { | ||
355 | int i, n, len; | ||
356 | |||
357 | outb(REG_COMMAND_RX_WIN_ONE, iobase + REG_COMMAND); | ||
358 | |||
359 | len = inb(iobase + offset); | ||
360 | n = 0; | ||
361 | i = 1; | ||
362 | |||
363 | while (n < len) { | ||
364 | |||
365 | if (i == 16) { | ||
366 | outb(REG_COMMAND_RX_WIN_TWO, iobase + REG_COMMAND); | ||
367 | i = 0; | ||
368 | } | ||
369 | |||
370 | buf[n] = inb(iobase + offset + i); | ||
371 | |||
372 | n++; | ||
373 | i++; | ||
374 | |||
375 | } | ||
376 | |||
377 | return len; | ||
378 | } | ||
379 | |||
380 | |||
381 | static void bluecard_receive(bluecard_info_t *info, unsigned int offset) | ||
382 | { | ||
383 | unsigned int iobase; | ||
384 | unsigned char buf[31]; | ||
385 | int i, len; | ||
386 | |||
387 | if (!info) { | ||
388 | BT_ERR("Unknown device"); | ||
389 | return; | ||
390 | } | ||
391 | |||
392 | iobase = info->link.io.BasePort1; | ||
393 | |||
394 | if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) | ||
395 | bluecard_enable_activity_led(info); | ||
396 | |||
397 | len = bluecard_read(iobase, offset, buf, sizeof(buf)); | ||
398 | |||
399 | for (i = 0; i < len; i++) { | ||
400 | |||
401 | /* Allocate packet */ | ||
402 | if (info->rx_skb == NULL) { | ||
403 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
404 | info->rx_count = 0; | ||
405 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | ||
406 | BT_ERR("Can't allocate mem for new packet"); | ||
407 | return; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | ||
412 | |||
413 | info->rx_skb->dev = (void *) info->hdev; | ||
414 | info->rx_skb->pkt_type = buf[i]; | ||
415 | |||
416 | switch (info->rx_skb->pkt_type) { | ||
417 | |||
418 | case 0x00: | ||
419 | /* init packet */ | ||
420 | if (offset != 0x00) { | ||
421 | set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); | ||
422 | set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); | ||
423 | set_bit(XMIT_SENDING_READY, &(info->tx_state)); | ||
424 | bluecard_write_wakeup(info); | ||
425 | } | ||
426 | |||
427 | kfree_skb(info->rx_skb); | ||
428 | info->rx_skb = NULL; | ||
429 | break; | ||
430 | |||
431 | case HCI_EVENT_PKT: | ||
432 | info->rx_state = RECV_WAIT_EVENT_HEADER; | ||
433 | info->rx_count = HCI_EVENT_HDR_SIZE; | ||
434 | break; | ||
435 | |||
436 | case HCI_ACLDATA_PKT: | ||
437 | info->rx_state = RECV_WAIT_ACL_HEADER; | ||
438 | info->rx_count = HCI_ACL_HDR_SIZE; | ||
439 | break; | ||
440 | |||
441 | case HCI_SCODATA_PKT: | ||
442 | info->rx_state = RECV_WAIT_SCO_HEADER; | ||
443 | info->rx_count = HCI_SCO_HDR_SIZE; | ||
444 | break; | ||
445 | |||
446 | default: | ||
447 | /* unknown packet */ | ||
448 | BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); | ||
449 | info->hdev->stat.err_rx++; | ||
450 | |||
451 | kfree_skb(info->rx_skb); | ||
452 | info->rx_skb = NULL; | ||
453 | break; | ||
454 | |||
455 | } | ||
456 | |||
457 | } else { | ||
458 | |||
459 | *skb_put(info->rx_skb, 1) = buf[i]; | ||
460 | info->rx_count--; | ||
461 | |||
462 | if (info->rx_count == 0) { | ||
463 | |||
464 | int dlen; | ||
465 | struct hci_event_hdr *eh; | ||
466 | struct hci_acl_hdr *ah; | ||
467 | struct hci_sco_hdr *sh; | ||
468 | |||
469 | switch (info->rx_state) { | ||
470 | |||
471 | case RECV_WAIT_EVENT_HEADER: | ||
472 | eh = (struct hci_event_hdr *)(info->rx_skb->data); | ||
473 | info->rx_state = RECV_WAIT_DATA; | ||
474 | info->rx_count = eh->plen; | ||
475 | break; | ||
476 | |||
477 | case RECV_WAIT_ACL_HEADER: | ||
478 | ah = (struct hci_acl_hdr *)(info->rx_skb->data); | ||
479 | dlen = __le16_to_cpu(ah->dlen); | ||
480 | info->rx_state = RECV_WAIT_DATA; | ||
481 | info->rx_count = dlen; | ||
482 | break; | ||
483 | |||
484 | case RECV_WAIT_SCO_HEADER: | ||
485 | sh = (struct hci_sco_hdr *)(info->rx_skb->data); | ||
486 | info->rx_state = RECV_WAIT_DATA; | ||
487 | info->rx_count = sh->dlen; | ||
488 | break; | ||
489 | |||
490 | case RECV_WAIT_DATA: | ||
491 | hci_recv_frame(info->rx_skb); | ||
492 | info->rx_skb = NULL; | ||
493 | break; | ||
494 | |||
495 | } | ||
496 | |||
497 | } | ||
498 | |||
499 | } | ||
500 | |||
501 | |||
502 | } | ||
503 | |||
504 | info->hdev->stat.byte_rx += len; | ||
505 | } | ||
506 | |||
507 | |||
508 | static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *regs) | ||
509 | { | ||
510 | bluecard_info_t *info = dev_inst; | ||
511 | unsigned int iobase; | ||
512 | unsigned char reg; | ||
513 | |||
514 | if (!info || !info->hdev) { | ||
515 | BT_ERR("Call of irq %d for unknown device", irq); | ||
516 | return IRQ_NONE; | ||
517 | } | ||
518 | |||
519 | if (!test_bit(CARD_READY, &(info->hw_state))) | ||
520 | return IRQ_HANDLED; | ||
521 | |||
522 | iobase = info->link.io.BasePort1; | ||
523 | |||
524 | spin_lock(&(info->lock)); | ||
525 | |||
526 | /* Disable interrupt */ | ||
527 | info->ctrl_reg &= ~REG_CONTROL_INTERRUPT; | ||
528 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
529 | |||
530 | reg = inb(iobase + REG_INTERRUPT); | ||
531 | |||
532 | if ((reg != 0x00) && (reg != 0xff)) { | ||
533 | |||
534 | if (reg & 0x04) { | ||
535 | bluecard_receive(info, 0x00); | ||
536 | outb(0x04, iobase + REG_INTERRUPT); | ||
537 | outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); | ||
538 | } | ||
539 | |||
540 | if (reg & 0x08) { | ||
541 | bluecard_receive(info, 0x10); | ||
542 | outb(0x08, iobase + REG_INTERRUPT); | ||
543 | outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); | ||
544 | } | ||
545 | |||
546 | if (reg & 0x01) { | ||
547 | set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); | ||
548 | outb(0x01, iobase + REG_INTERRUPT); | ||
549 | bluecard_write_wakeup(info); | ||
550 | } | ||
551 | |||
552 | if (reg & 0x02) { | ||
553 | set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); | ||
554 | outb(0x02, iobase + REG_INTERRUPT); | ||
555 | bluecard_write_wakeup(info); | ||
556 | } | ||
557 | |||
558 | } | ||
559 | |||
560 | /* Enable interrupt */ | ||
561 | info->ctrl_reg |= REG_CONTROL_INTERRUPT; | ||
562 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
563 | |||
564 | spin_unlock(&(info->lock)); | ||
565 | |||
566 | return IRQ_HANDLED; | ||
567 | } | ||
568 | |||
569 | |||
570 | |||
571 | /* ======================== Device specific HCI commands ======================== */ | ||
572 | |||
573 | |||
574 | static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud) | ||
575 | { | ||
576 | bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); | ||
577 | struct sk_buff *skb; | ||
578 | |||
579 | /* Ericsson baud rate command */ | ||
580 | unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; | ||
581 | |||
582 | if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | ||
583 | BT_ERR("Can't allocate mem for new packet"); | ||
584 | return -1; | ||
585 | } | ||
586 | |||
587 | switch (baud) { | ||
588 | case 460800: | ||
589 | cmd[4] = 0x00; | ||
590 | skb->pkt_type = PKT_BAUD_RATE_460800; | ||
591 | break; | ||
592 | case 230400: | ||
593 | cmd[4] = 0x01; | ||
594 | skb->pkt_type = PKT_BAUD_RATE_230400; | ||
595 | break; | ||
596 | case 115200: | ||
597 | cmd[4] = 0x02; | ||
598 | skb->pkt_type = PKT_BAUD_RATE_115200; | ||
599 | break; | ||
600 | case 57600: | ||
601 | /* Fall through... */ | ||
602 | default: | ||
603 | cmd[4] = 0x03; | ||
604 | skb->pkt_type = PKT_BAUD_RATE_57600; | ||
605 | break; | ||
606 | } | ||
607 | |||
608 | memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); | ||
609 | |||
610 | skb_queue_tail(&(info->txq), skb); | ||
611 | |||
612 | bluecard_write_wakeup(info); | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | |||
618 | |||
619 | /* ======================== HCI interface ======================== */ | ||
620 | |||
621 | |||
622 | static int bluecard_hci_flush(struct hci_dev *hdev) | ||
623 | { | ||
624 | bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); | ||
625 | |||
626 | /* Drop TX queue */ | ||
627 | skb_queue_purge(&(info->txq)); | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | |||
633 | static int bluecard_hci_open(struct hci_dev *hdev) | ||
634 | { | ||
635 | bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); | ||
636 | unsigned int iobase = info->link.io.BasePort1; | ||
637 | |||
638 | if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) | ||
639 | bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); | ||
640 | |||
641 | if (test_and_set_bit(HCI_RUNNING, &(hdev->flags))) | ||
642 | return 0; | ||
643 | |||
644 | if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { | ||
645 | /* Enable LED */ | ||
646 | outb(0x08 | 0x20, iobase + 0x30); | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | |||
653 | static int bluecard_hci_close(struct hci_dev *hdev) | ||
654 | { | ||
655 | bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); | ||
656 | unsigned int iobase = info->link.io.BasePort1; | ||
657 | |||
658 | if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) | ||
659 | return 0; | ||
660 | |||
661 | bluecard_hci_flush(hdev); | ||
662 | |||
663 | if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { | ||
664 | /* Disable LED */ | ||
665 | outb(0x00, iobase + 0x30); | ||
666 | } | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | |||
672 | static int bluecard_hci_send_frame(struct sk_buff *skb) | ||
673 | { | ||
674 | bluecard_info_t *info; | ||
675 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
676 | |||
677 | if (!hdev) { | ||
678 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
679 | return -ENODEV; | ||
680 | } | ||
681 | |||
682 | info = (bluecard_info_t *)(hdev->driver_data); | ||
683 | |||
684 | switch (skb->pkt_type) { | ||
685 | case HCI_COMMAND_PKT: | ||
686 | hdev->stat.cmd_tx++; | ||
687 | break; | ||
688 | case HCI_ACLDATA_PKT: | ||
689 | hdev->stat.acl_tx++; | ||
690 | break; | ||
691 | case HCI_SCODATA_PKT: | ||
692 | hdev->stat.sco_tx++; | ||
693 | break; | ||
694 | }; | ||
695 | |||
696 | /* Prepend skb with frame type */ | ||
697 | memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); | ||
698 | skb_queue_tail(&(info->txq), skb); | ||
699 | |||
700 | bluecard_write_wakeup(info); | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | |||
706 | static void bluecard_hci_destruct(struct hci_dev *hdev) | ||
707 | { | ||
708 | } | ||
709 | |||
710 | |||
711 | static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
712 | { | ||
713 | return -ENOIOCTLCMD; | ||
714 | } | ||
715 | |||
716 | |||
717 | |||
718 | /* ======================== Card services HCI interaction ======================== */ | ||
719 | |||
720 | |||
721 | static int bluecard_open(bluecard_info_t *info) | ||
722 | { | ||
723 | unsigned int iobase = info->link.io.BasePort1; | ||
724 | struct hci_dev *hdev; | ||
725 | unsigned char id; | ||
726 | |||
727 | spin_lock_init(&(info->lock)); | ||
728 | |||
729 | init_timer(&(info->timer)); | ||
730 | info->timer.function = &bluecard_activity_led_timeout; | ||
731 | info->timer.data = (u_long)info; | ||
732 | |||
733 | skb_queue_head_init(&(info->txq)); | ||
734 | |||
735 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
736 | info->rx_count = 0; | ||
737 | info->rx_skb = NULL; | ||
738 | |||
739 | /* Initialize HCI device */ | ||
740 | hdev = hci_alloc_dev(); | ||
741 | if (!hdev) { | ||
742 | BT_ERR("Can't allocate HCI device"); | ||
743 | return -ENOMEM; | ||
744 | } | ||
745 | |||
746 | info->hdev = hdev; | ||
747 | |||
748 | hdev->type = HCI_PCCARD; | ||
749 | hdev->driver_data = info; | ||
750 | |||
751 | hdev->open = bluecard_hci_open; | ||
752 | hdev->close = bluecard_hci_close; | ||
753 | hdev->flush = bluecard_hci_flush; | ||
754 | hdev->send = bluecard_hci_send_frame; | ||
755 | hdev->destruct = bluecard_hci_destruct; | ||
756 | hdev->ioctl = bluecard_hci_ioctl; | ||
757 | |||
758 | hdev->owner = THIS_MODULE; | ||
759 | |||
760 | id = inb(iobase + 0x30); | ||
761 | |||
762 | if ((id & 0x0f) == 0x02) | ||
763 | set_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)); | ||
764 | |||
765 | if (id & 0x10) | ||
766 | set_bit(CARD_HAS_POWER_LED, &(info->hw_state)); | ||
767 | |||
768 | if (id & 0x20) | ||
769 | set_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state)); | ||
770 | |||
771 | /* Reset card */ | ||
772 | info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET; | ||
773 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
774 | |||
775 | /* Turn FPGA off */ | ||
776 | outb(0x80, iobase + 0x30); | ||
777 | |||
778 | /* Wait some time */ | ||
779 | msleep(10); | ||
780 | |||
781 | /* Turn FPGA on */ | ||
782 | outb(0x00, iobase + 0x30); | ||
783 | |||
784 | /* Activate card */ | ||
785 | info->ctrl_reg = REG_CONTROL_BT_ON | REG_CONTROL_BT_RES_PU; | ||
786 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
787 | |||
788 | /* Enable interrupt */ | ||
789 | outb(0xff, iobase + REG_INTERRUPT); | ||
790 | info->ctrl_reg |= REG_CONTROL_INTERRUPT; | ||
791 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
792 | |||
793 | if ((id & 0x0f) == 0x03) { | ||
794 | /* Disable RTS */ | ||
795 | info->ctrl_reg |= REG_CONTROL_RTS; | ||
796 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
797 | |||
798 | /* Set baud rate */ | ||
799 | info->ctrl_reg |= 0x03; | ||
800 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
801 | |||
802 | /* Enable RTS */ | ||
803 | info->ctrl_reg &= ~REG_CONTROL_RTS; | ||
804 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
805 | |||
806 | set_bit(XMIT_BUF_ONE_READY, &(info->tx_state)); | ||
807 | set_bit(XMIT_BUF_TWO_READY, &(info->tx_state)); | ||
808 | set_bit(XMIT_SENDING_READY, &(info->tx_state)); | ||
809 | } | ||
810 | |||
811 | /* Start the RX buffers */ | ||
812 | outb(REG_COMMAND_RX_BUF_ONE, iobase + REG_COMMAND); | ||
813 | outb(REG_COMMAND_RX_BUF_TWO, iobase + REG_COMMAND); | ||
814 | |||
815 | /* Signal that the hardware is ready */ | ||
816 | set_bit(CARD_READY, &(info->hw_state)); | ||
817 | |||
818 | /* Drop TX queue */ | ||
819 | skb_queue_purge(&(info->txq)); | ||
820 | |||
821 | /* Control the point at which RTS is enabled */ | ||
822 | outb((0x0f << RTS_LEVEL_SHIFT_BITS) | 1, iobase + REG_RX_CONTROL); | ||
823 | |||
824 | /* Timeout before it is safe to send the first HCI packet */ | ||
825 | msleep(1250); | ||
826 | |||
827 | /* Register HCI device */ | ||
828 | if (hci_register_dev(hdev) < 0) { | ||
829 | BT_ERR("Can't register HCI device"); | ||
830 | info->hdev = NULL; | ||
831 | hci_free_dev(hdev); | ||
832 | return -ENODEV; | ||
833 | } | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | |||
839 | static int bluecard_close(bluecard_info_t *info) | ||
840 | { | ||
841 | unsigned int iobase = info->link.io.BasePort1; | ||
842 | struct hci_dev *hdev = info->hdev; | ||
843 | |||
844 | if (!hdev) | ||
845 | return -ENODEV; | ||
846 | |||
847 | bluecard_hci_close(hdev); | ||
848 | |||
849 | clear_bit(CARD_READY, &(info->hw_state)); | ||
850 | |||
851 | /* Reset card */ | ||
852 | info->ctrl_reg = REG_CONTROL_BT_RESET | REG_CONTROL_CARD_RESET; | ||
853 | outb(info->ctrl_reg, iobase + REG_CONTROL); | ||
854 | |||
855 | /* Turn FPGA off */ | ||
856 | outb(0x80, iobase + 0x30); | ||
857 | |||
858 | if (hci_unregister_dev(hdev) < 0) | ||
859 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
860 | |||
861 | hci_free_dev(hdev); | ||
862 | |||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static dev_link_t *bluecard_attach(void) | ||
867 | { | ||
868 | bluecard_info_t *info; | ||
869 | client_reg_t client_reg; | ||
870 | dev_link_t *link; | ||
871 | int ret; | ||
872 | |||
873 | /* Create new info device */ | ||
874 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
875 | if (!info) | ||
876 | return NULL; | ||
877 | memset(info, 0, sizeof(*info)); | ||
878 | |||
879 | link = &info->link; | ||
880 | link->priv = info; | ||
881 | |||
882 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
883 | link->io.NumPorts1 = 8; | ||
884 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
885 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
886 | |||
887 | link->irq.Handler = bluecard_interrupt; | ||
888 | link->irq.Instance = info; | ||
889 | |||
890 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
891 | link->conf.Vcc = 50; | ||
892 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
893 | |||
894 | /* Register with Card Services */ | ||
895 | link->next = dev_list; | ||
896 | dev_list = link; | ||
897 | client_reg.dev_info = &dev_info; | ||
898 | client_reg.EventMask = | ||
899 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
900 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
901 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
902 | client_reg.event_handler = &bluecard_event; | ||
903 | client_reg.Version = 0x0210; | ||
904 | client_reg.event_callback_args.client_data = link; | ||
905 | |||
906 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
907 | if (ret != CS_SUCCESS) { | ||
908 | cs_error(link->handle, RegisterClient, ret); | ||
909 | bluecard_detach(link); | ||
910 | return NULL; | ||
911 | } | ||
912 | |||
913 | return link; | ||
914 | } | ||
915 | |||
916 | |||
917 | static void bluecard_detach(dev_link_t *link) | ||
918 | { | ||
919 | bluecard_info_t *info = link->priv; | ||
920 | dev_link_t **linkp; | ||
921 | int ret; | ||
922 | |||
923 | /* Locate device structure */ | ||
924 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
925 | if (*linkp == link) | ||
926 | break; | ||
927 | |||
928 | if (*linkp == NULL) | ||
929 | return; | ||
930 | |||
931 | if (link->state & DEV_CONFIG) | ||
932 | bluecard_release(link); | ||
933 | |||
934 | if (link->handle) { | ||
935 | ret = pcmcia_deregister_client(link->handle); | ||
936 | if (ret != CS_SUCCESS) | ||
937 | cs_error(link->handle, DeregisterClient, ret); | ||
938 | } | ||
939 | |||
940 | /* Unlink device structure, free bits */ | ||
941 | *linkp = link->next; | ||
942 | |||
943 | kfree(info); | ||
944 | } | ||
945 | |||
946 | |||
947 | static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
948 | { | ||
949 | int i; | ||
950 | |||
951 | i = pcmcia_get_first_tuple(handle, tuple); | ||
952 | if (i != CS_SUCCESS) | ||
953 | return CS_NO_MORE_ITEMS; | ||
954 | |||
955 | i = pcmcia_get_tuple_data(handle, tuple); | ||
956 | if (i != CS_SUCCESS) | ||
957 | return i; | ||
958 | |||
959 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
960 | } | ||
961 | |||
962 | static void bluecard_config(dev_link_t *link) | ||
963 | { | ||
964 | client_handle_t handle = link->handle; | ||
965 | bluecard_info_t *info = link->priv; | ||
966 | tuple_t tuple; | ||
967 | u_short buf[256]; | ||
968 | cisparse_t parse; | ||
969 | config_info_t config; | ||
970 | int i, n, last_ret, last_fn; | ||
971 | |||
972 | tuple.TupleData = (cisdata_t *)buf; | ||
973 | tuple.TupleOffset = 0; | ||
974 | tuple.TupleDataMax = 255; | ||
975 | tuple.Attributes = 0; | ||
976 | |||
977 | /* Get configuration register information */ | ||
978 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
979 | last_ret = first_tuple(handle, &tuple, &parse); | ||
980 | if (last_ret != CS_SUCCESS) { | ||
981 | last_fn = ParseTuple; | ||
982 | goto cs_failed; | ||
983 | } | ||
984 | link->conf.ConfigBase = parse.config.base; | ||
985 | link->conf.Present = parse.config.rmask[0]; | ||
986 | |||
987 | /* Configure card */ | ||
988 | link->state |= DEV_CONFIG; | ||
989 | i = pcmcia_get_configuration_info(handle, &config); | ||
990 | link->conf.Vcc = config.Vcc; | ||
991 | |||
992 | link->conf.ConfigIndex = 0x20; | ||
993 | link->io.NumPorts1 = 64; | ||
994 | link->io.IOAddrLines = 6; | ||
995 | |||
996 | for (n = 0; n < 0x400; n += 0x40) { | ||
997 | link->io.BasePort1 = n ^ 0x300; | ||
998 | i = pcmcia_request_io(link->handle, &link->io); | ||
999 | if (i == CS_SUCCESS) | ||
1000 | break; | ||
1001 | } | ||
1002 | |||
1003 | if (i != CS_SUCCESS) { | ||
1004 | cs_error(link->handle, RequestIO, i); | ||
1005 | goto failed; | ||
1006 | } | ||
1007 | |||
1008 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
1009 | if (i != CS_SUCCESS) { | ||
1010 | cs_error(link->handle, RequestIRQ, i); | ||
1011 | link->irq.AssignedIRQ = 0; | ||
1012 | } | ||
1013 | |||
1014 | i = pcmcia_request_configuration(link->handle, &link->conf); | ||
1015 | if (i != CS_SUCCESS) { | ||
1016 | cs_error(link->handle, RequestConfiguration, i); | ||
1017 | goto failed; | ||
1018 | } | ||
1019 | |||
1020 | if (bluecard_open(info) != 0) | ||
1021 | goto failed; | ||
1022 | |||
1023 | strcpy(info->node.dev_name, info->hdev->name); | ||
1024 | link->dev = &info->node; | ||
1025 | link->state &= ~DEV_CONFIG_PENDING; | ||
1026 | |||
1027 | return; | ||
1028 | |||
1029 | cs_failed: | ||
1030 | cs_error(link->handle, last_fn, last_ret); | ||
1031 | |||
1032 | failed: | ||
1033 | bluecard_release(link); | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | static void bluecard_release(dev_link_t *link) | ||
1038 | { | ||
1039 | bluecard_info_t *info = link->priv; | ||
1040 | |||
1041 | if (link->state & DEV_PRESENT) | ||
1042 | bluecard_close(info); | ||
1043 | |||
1044 | del_timer(&(info->timer)); | ||
1045 | |||
1046 | link->dev = NULL; | ||
1047 | |||
1048 | pcmcia_release_configuration(link->handle); | ||
1049 | pcmcia_release_io(link->handle, &link->io); | ||
1050 | pcmcia_release_irq(link->handle, &link->irq); | ||
1051 | |||
1052 | link->state &= ~DEV_CONFIG; | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | static int bluecard_event(event_t event, int priority, event_callback_args_t *args) | ||
1057 | { | ||
1058 | dev_link_t *link = args->client_data; | ||
1059 | bluecard_info_t *info = link->priv; | ||
1060 | |||
1061 | switch (event) { | ||
1062 | case CS_EVENT_CARD_REMOVAL: | ||
1063 | link->state &= ~DEV_PRESENT; | ||
1064 | if (link->state & DEV_CONFIG) { | ||
1065 | bluecard_close(info); | ||
1066 | bluecard_release(link); | ||
1067 | } | ||
1068 | break; | ||
1069 | case CS_EVENT_CARD_INSERTION: | ||
1070 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
1071 | bluecard_config(link); | ||
1072 | break; | ||
1073 | case CS_EVENT_PM_SUSPEND: | ||
1074 | link->state |= DEV_SUSPEND; | ||
1075 | /* Fall through... */ | ||
1076 | case CS_EVENT_RESET_PHYSICAL: | ||
1077 | if (link->state & DEV_CONFIG) | ||
1078 | pcmcia_release_configuration(link->handle); | ||
1079 | break; | ||
1080 | case CS_EVENT_PM_RESUME: | ||
1081 | link->state &= ~DEV_SUSPEND; | ||
1082 | /* Fall through... */ | ||
1083 | case CS_EVENT_CARD_RESET: | ||
1084 | if (DEV_OK(link)) | ||
1085 | pcmcia_request_configuration(link->handle, &link->conf); | ||
1086 | break; | ||
1087 | } | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static struct pcmcia_driver bluecard_driver = { | ||
1093 | .owner = THIS_MODULE, | ||
1094 | .drv = { | ||
1095 | .name = "bluecard_cs", | ||
1096 | }, | ||
1097 | .attach = bluecard_attach, | ||
1098 | .detach = bluecard_detach, | ||
1099 | }; | ||
1100 | |||
1101 | static int __init init_bluecard_cs(void) | ||
1102 | { | ||
1103 | return pcmcia_register_driver(&bluecard_driver); | ||
1104 | } | ||
1105 | |||
1106 | |||
1107 | static void __exit exit_bluecard_cs(void) | ||
1108 | { | ||
1109 | pcmcia_unregister_driver(&bluecard_driver); | ||
1110 | BUG_ON(dev_list != NULL); | ||
1111 | } | ||
1112 | |||
1113 | module_init(init_bluecard_cs); | ||
1114 | module_exit(exit_bluecard_cs); | ||
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c new file mode 100644 index 000000000000..2771c861f185 --- /dev/null +++ b/drivers/bluetooth/bpa10x.c | |||
@@ -0,0 +1,657 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Digianswer Bluetooth USB driver | ||
4 | * | ||
5 | * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * | ||
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 as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/errno.h> | ||
32 | |||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <net/bluetooth/bluetooth.h> | ||
36 | #include <net/bluetooth/hci_core.h> | ||
37 | |||
38 | #ifndef CONFIG_BT_HCIBPA10X_DEBUG | ||
39 | #undef BT_DBG | ||
40 | #define BT_DBG(D...) | ||
41 | #endif | ||
42 | |||
43 | #define VERSION "0.8" | ||
44 | |||
45 | static int ignore = 0; | ||
46 | |||
47 | static struct usb_device_id bpa10x_table[] = { | ||
48 | /* Tektronix BPA 100/105 (Digianswer) */ | ||
49 | { USB_DEVICE(0x08fd, 0x0002) }, | ||
50 | |||
51 | { } /* Terminating entry */ | ||
52 | }; | ||
53 | |||
54 | MODULE_DEVICE_TABLE(usb, bpa10x_table); | ||
55 | |||
56 | #define BPA10X_CMD_EP 0x00 | ||
57 | #define BPA10X_EVT_EP 0x81 | ||
58 | #define BPA10X_TX_EP 0x02 | ||
59 | #define BPA10X_RX_EP 0x82 | ||
60 | |||
61 | #define BPA10X_CMD_BUF_SIZE 252 | ||
62 | #define BPA10X_EVT_BUF_SIZE 16 | ||
63 | #define BPA10X_TX_BUF_SIZE 384 | ||
64 | #define BPA10X_RX_BUF_SIZE 384 | ||
65 | |||
66 | struct bpa10x_data { | ||
67 | struct hci_dev *hdev; | ||
68 | struct usb_device *udev; | ||
69 | |||
70 | rwlock_t lock; | ||
71 | |||
72 | struct sk_buff_head cmd_queue; | ||
73 | struct urb *cmd_urb; | ||
74 | struct urb *evt_urb; | ||
75 | struct sk_buff *evt_skb; | ||
76 | unsigned int evt_len; | ||
77 | |||
78 | struct sk_buff_head tx_queue; | ||
79 | struct urb *tx_urb; | ||
80 | struct urb *rx_urb; | ||
81 | }; | ||
82 | |||
83 | #define HCI_VENDOR_HDR_SIZE 5 | ||
84 | |||
85 | struct hci_vendor_hdr { | ||
86 | __u8 type; | ||
87 | __u16 snum; | ||
88 | __u16 dlen; | ||
89 | } __attribute__ ((packed)); | ||
90 | |||
91 | static void bpa10x_recv_bulk(struct bpa10x_data *data, unsigned char *buf, int count) | ||
92 | { | ||
93 | struct hci_acl_hdr *ah; | ||
94 | struct hci_sco_hdr *sh; | ||
95 | struct hci_vendor_hdr *vh; | ||
96 | struct sk_buff *skb; | ||
97 | int len; | ||
98 | |||
99 | while (count) { | ||
100 | switch (*buf++) { | ||
101 | case HCI_ACLDATA_PKT: | ||
102 | ah = (struct hci_acl_hdr *) buf; | ||
103 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(ah->dlen); | ||
104 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
105 | if (skb) { | ||
106 | memcpy(skb_put(skb, len), buf, len); | ||
107 | skb->dev = (void *) data->hdev; | ||
108 | skb->pkt_type = HCI_ACLDATA_PKT; | ||
109 | hci_recv_frame(skb); | ||
110 | } | ||
111 | break; | ||
112 | |||
113 | case HCI_SCODATA_PKT: | ||
114 | sh = (struct hci_sco_hdr *) buf; | ||
115 | len = HCI_SCO_HDR_SIZE + sh->dlen; | ||
116 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
117 | if (skb) { | ||
118 | memcpy(skb_put(skb, len), buf, len); | ||
119 | skb->dev = (void *) data->hdev; | ||
120 | skb->pkt_type = HCI_SCODATA_PKT; | ||
121 | hci_recv_frame(skb); | ||
122 | } | ||
123 | break; | ||
124 | |||
125 | case HCI_VENDOR_PKT: | ||
126 | vh = (struct hci_vendor_hdr *) buf; | ||
127 | len = HCI_VENDOR_HDR_SIZE + __le16_to_cpu(vh->dlen); | ||
128 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
129 | if (skb) { | ||
130 | memcpy(skb_put(skb, len), buf, len); | ||
131 | skb->dev = (void *) data->hdev; | ||
132 | skb->pkt_type = HCI_VENDOR_PKT; | ||
133 | hci_recv_frame(skb); | ||
134 | } | ||
135 | break; | ||
136 | |||
137 | default: | ||
138 | len = count - 1; | ||
139 | break; | ||
140 | } | ||
141 | |||
142 | buf += len; | ||
143 | count -= (len + 1); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static int bpa10x_recv_event(struct bpa10x_data *data, unsigned char *buf, int size) | ||
148 | { | ||
149 | BT_DBG("data %p buf %p size %d", data, buf, size); | ||
150 | |||
151 | if (data->evt_skb) { | ||
152 | struct sk_buff *skb = data->evt_skb; | ||
153 | |||
154 | memcpy(skb_put(skb, size), buf, size); | ||
155 | |||
156 | if (skb->len == data->evt_len) { | ||
157 | data->evt_skb = NULL; | ||
158 | data->evt_len = 0; | ||
159 | hci_recv_frame(skb); | ||
160 | } | ||
161 | } else { | ||
162 | struct sk_buff *skb; | ||
163 | struct hci_event_hdr *hdr; | ||
164 | unsigned char pkt_type; | ||
165 | int pkt_len = 0; | ||
166 | |||
167 | if (size < HCI_EVENT_HDR_SIZE + 1) { | ||
168 | BT_ERR("%s event packet block with size %d is too short", | ||
169 | data->hdev->name, size); | ||
170 | return -EILSEQ; | ||
171 | } | ||
172 | |||
173 | pkt_type = *buf++; | ||
174 | size--; | ||
175 | |||
176 | if (pkt_type != HCI_EVENT_PKT) { | ||
177 | BT_ERR("%s unexpected event packet start byte 0x%02x", | ||
178 | data->hdev->name, pkt_type); | ||
179 | return -EPROTO; | ||
180 | } | ||
181 | |||
182 | hdr = (struct hci_event_hdr *) buf; | ||
183 | pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen; | ||
184 | |||
185 | skb = bt_skb_alloc(pkt_len, GFP_ATOMIC); | ||
186 | if (!skb) { | ||
187 | BT_ERR("%s no memory for new event packet", | ||
188 | data->hdev->name); | ||
189 | return -ENOMEM; | ||
190 | } | ||
191 | |||
192 | skb->dev = (void *) data->hdev; | ||
193 | skb->pkt_type = pkt_type; | ||
194 | |||
195 | memcpy(skb_put(skb, size), buf, size); | ||
196 | |||
197 | if (pkt_len == size) { | ||
198 | hci_recv_frame(skb); | ||
199 | } else { | ||
200 | data->evt_skb = skb; | ||
201 | data->evt_len = pkt_len; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static void bpa10x_wakeup(struct bpa10x_data *data) | ||
209 | { | ||
210 | struct urb *urb; | ||
211 | struct sk_buff *skb; | ||
212 | int err; | ||
213 | |||
214 | BT_DBG("data %p", data); | ||
215 | |||
216 | urb = data->cmd_urb; | ||
217 | if (urb->status == -EINPROGRESS) | ||
218 | skb = NULL; | ||
219 | else | ||
220 | skb = skb_dequeue(&data->cmd_queue); | ||
221 | |||
222 | if (skb) { | ||
223 | struct usb_ctrlrequest *cr; | ||
224 | |||
225 | if (skb->len > BPA10X_CMD_BUF_SIZE) { | ||
226 | BT_ERR("%s command packet with size %d is too big", | ||
227 | data->hdev->name, skb->len); | ||
228 | kfree_skb(skb); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | cr = (struct usb_ctrlrequest *) urb->setup_packet; | ||
233 | cr->wLength = __cpu_to_le16(skb->len); | ||
234 | |||
235 | memcpy(urb->transfer_buffer, skb->data, skb->len); | ||
236 | urb->transfer_buffer_length = skb->len; | ||
237 | |||
238 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
239 | if (err < 0 && err != -ENODEV) { | ||
240 | BT_ERR("%s submit failed for command urb %p with error %d", | ||
241 | data->hdev->name, urb, err); | ||
242 | skb_queue_head(&data->cmd_queue, skb); | ||
243 | } else | ||
244 | kfree_skb(skb); | ||
245 | } | ||
246 | |||
247 | urb = data->tx_urb; | ||
248 | if (urb->status == -EINPROGRESS) | ||
249 | skb = NULL; | ||
250 | else | ||
251 | skb = skb_dequeue(&data->tx_queue); | ||
252 | |||
253 | if (skb) { | ||
254 | memcpy(urb->transfer_buffer, skb->data, skb->len); | ||
255 | urb->transfer_buffer_length = skb->len; | ||
256 | |||
257 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
258 | if (err < 0 && err != -ENODEV) { | ||
259 | BT_ERR("%s submit failed for command urb %p with error %d", | ||
260 | data->hdev->name, urb, err); | ||
261 | skb_queue_head(&data->tx_queue, skb); | ||
262 | } else | ||
263 | kfree_skb(skb); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void bpa10x_complete(struct urb *urb, struct pt_regs *regs) | ||
268 | { | ||
269 | struct bpa10x_data *data = urb->context; | ||
270 | unsigned char *buf = urb->transfer_buffer; | ||
271 | int err, count = urb->actual_length; | ||
272 | |||
273 | BT_DBG("data %p urb %p buf %p count %d", data, urb, buf, count); | ||
274 | |||
275 | read_lock(&data->lock); | ||
276 | |||
277 | if (!test_bit(HCI_RUNNING, &data->hdev->flags)) | ||
278 | goto unlock; | ||
279 | |||
280 | if (urb->status < 0 || !count) | ||
281 | goto resubmit; | ||
282 | |||
283 | if (usb_pipein(urb->pipe)) { | ||
284 | data->hdev->stat.byte_rx += count; | ||
285 | |||
286 | if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) | ||
287 | bpa10x_recv_event(data, buf, count); | ||
288 | |||
289 | if (usb_pipetype(urb->pipe) == PIPE_BULK) | ||
290 | bpa10x_recv_bulk(data, buf, count); | ||
291 | } else { | ||
292 | data->hdev->stat.byte_tx += count; | ||
293 | |||
294 | bpa10x_wakeup(data); | ||
295 | } | ||
296 | |||
297 | resubmit: | ||
298 | if (usb_pipein(urb->pipe)) { | ||
299 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
300 | if (err < 0 && err != -ENODEV) { | ||
301 | BT_ERR("%s urb %p type %d resubmit status %d", | ||
302 | data->hdev->name, urb, usb_pipetype(urb->pipe), err); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | unlock: | ||
307 | read_unlock(&data->lock); | ||
308 | } | ||
309 | |||
310 | static inline struct urb *bpa10x_alloc_urb(struct usb_device *udev, unsigned int pipe, size_t size, int flags, void *data) | ||
311 | { | ||
312 | struct urb *urb; | ||
313 | struct usb_ctrlrequest *cr; | ||
314 | unsigned char *buf; | ||
315 | |||
316 | BT_DBG("udev %p data %p", udev, data); | ||
317 | |||
318 | urb = usb_alloc_urb(0, flags); | ||
319 | if (!urb) | ||
320 | return NULL; | ||
321 | |||
322 | buf = kmalloc(size, flags); | ||
323 | if (!buf) { | ||
324 | usb_free_urb(urb); | ||
325 | return NULL; | ||
326 | } | ||
327 | |||
328 | switch (usb_pipetype(pipe)) { | ||
329 | case PIPE_CONTROL: | ||
330 | cr = kmalloc(sizeof(*cr), flags); | ||
331 | if (!cr) { | ||
332 | kfree(buf); | ||
333 | usb_free_urb(urb); | ||
334 | return NULL; | ||
335 | } | ||
336 | |||
337 | cr->bRequestType = USB_TYPE_VENDOR; | ||
338 | cr->bRequest = 0; | ||
339 | cr->wIndex = 0; | ||
340 | cr->wValue = 0; | ||
341 | cr->wLength = __cpu_to_le16(0); | ||
342 | |||
343 | usb_fill_control_urb(urb, udev, pipe, (void *) cr, buf, 0, bpa10x_complete, data); | ||
344 | break; | ||
345 | |||
346 | case PIPE_INTERRUPT: | ||
347 | usb_fill_int_urb(urb, udev, pipe, buf, size, bpa10x_complete, data, 1); | ||
348 | break; | ||
349 | |||
350 | case PIPE_BULK: | ||
351 | usb_fill_bulk_urb(urb, udev, pipe, buf, size, bpa10x_complete, data); | ||
352 | break; | ||
353 | |||
354 | default: | ||
355 | kfree(buf); | ||
356 | usb_free_urb(urb); | ||
357 | return NULL; | ||
358 | } | ||
359 | |||
360 | return urb; | ||
361 | } | ||
362 | |||
363 | static inline void bpa10x_free_urb(struct urb *urb) | ||
364 | { | ||
365 | BT_DBG("urb %p", urb); | ||
366 | |||
367 | if (!urb) | ||
368 | return; | ||
369 | |||
370 | if (urb->setup_packet) | ||
371 | kfree(urb->setup_packet); | ||
372 | |||
373 | if (urb->transfer_buffer) | ||
374 | kfree(urb->transfer_buffer); | ||
375 | |||
376 | usb_free_urb(urb); | ||
377 | } | ||
378 | |||
379 | static int bpa10x_open(struct hci_dev *hdev) | ||
380 | { | ||
381 | struct bpa10x_data *data = hdev->driver_data; | ||
382 | struct usb_device *udev = data->udev; | ||
383 | unsigned long flags; | ||
384 | int err; | ||
385 | |||
386 | BT_DBG("hdev %p data %p", hdev, data); | ||
387 | |||
388 | if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) | ||
389 | return 0; | ||
390 | |||
391 | data->cmd_urb = bpa10x_alloc_urb(udev, usb_sndctrlpipe(udev, BPA10X_CMD_EP), | ||
392 | BPA10X_CMD_BUF_SIZE, GFP_KERNEL, data); | ||
393 | if (!data->cmd_urb) { | ||
394 | err = -ENOMEM; | ||
395 | goto done; | ||
396 | } | ||
397 | |||
398 | data->evt_urb = bpa10x_alloc_urb(udev, usb_rcvintpipe(udev, BPA10X_EVT_EP), | ||
399 | BPA10X_EVT_BUF_SIZE, GFP_KERNEL, data); | ||
400 | if (!data->evt_urb) { | ||
401 | bpa10x_free_urb(data->cmd_urb); | ||
402 | err = -ENOMEM; | ||
403 | goto done; | ||
404 | } | ||
405 | |||
406 | data->rx_urb = bpa10x_alloc_urb(udev, usb_rcvbulkpipe(udev, BPA10X_RX_EP), | ||
407 | BPA10X_RX_BUF_SIZE, GFP_KERNEL, data); | ||
408 | if (!data->rx_urb) { | ||
409 | bpa10x_free_urb(data->evt_urb); | ||
410 | bpa10x_free_urb(data->cmd_urb); | ||
411 | err = -ENOMEM; | ||
412 | goto done; | ||
413 | } | ||
414 | |||
415 | data->tx_urb = bpa10x_alloc_urb(udev, usb_sndbulkpipe(udev, BPA10X_TX_EP), | ||
416 | BPA10X_TX_BUF_SIZE, GFP_KERNEL, data); | ||
417 | if (!data->rx_urb) { | ||
418 | bpa10x_free_urb(data->rx_urb); | ||
419 | bpa10x_free_urb(data->evt_urb); | ||
420 | bpa10x_free_urb(data->cmd_urb); | ||
421 | err = -ENOMEM; | ||
422 | goto done; | ||
423 | } | ||
424 | |||
425 | write_lock_irqsave(&data->lock, flags); | ||
426 | |||
427 | err = usb_submit_urb(data->evt_urb, GFP_ATOMIC); | ||
428 | if (err < 0) { | ||
429 | BT_ERR("%s submit failed for event urb %p with error %d", | ||
430 | data->hdev->name, data->evt_urb, err); | ||
431 | } else { | ||
432 | err = usb_submit_urb(data->rx_urb, GFP_ATOMIC); | ||
433 | if (err < 0) { | ||
434 | BT_ERR("%s submit failed for rx urb %p with error %d", | ||
435 | data->hdev->name, data->evt_urb, err); | ||
436 | usb_kill_urb(data->evt_urb); | ||
437 | } | ||
438 | } | ||
439 | |||
440 | write_unlock_irqrestore(&data->lock, flags); | ||
441 | |||
442 | done: | ||
443 | if (err < 0) | ||
444 | clear_bit(HCI_RUNNING, &hdev->flags); | ||
445 | |||
446 | return err; | ||
447 | } | ||
448 | |||
449 | static int bpa10x_close(struct hci_dev *hdev) | ||
450 | { | ||
451 | struct bpa10x_data *data = hdev->driver_data; | ||
452 | unsigned long flags; | ||
453 | |||
454 | BT_DBG("hdev %p data %p", hdev, data); | ||
455 | |||
456 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
457 | return 0; | ||
458 | |||
459 | write_lock_irqsave(&data->lock, flags); | ||
460 | |||
461 | skb_queue_purge(&data->cmd_queue); | ||
462 | usb_kill_urb(data->cmd_urb); | ||
463 | usb_kill_urb(data->evt_urb); | ||
464 | usb_kill_urb(data->rx_urb); | ||
465 | usb_kill_urb(data->tx_urb); | ||
466 | |||
467 | write_unlock_irqrestore(&data->lock, flags); | ||
468 | |||
469 | bpa10x_free_urb(data->cmd_urb); | ||
470 | bpa10x_free_urb(data->evt_urb); | ||
471 | bpa10x_free_urb(data->rx_urb); | ||
472 | bpa10x_free_urb(data->tx_urb); | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int bpa10x_flush(struct hci_dev *hdev) | ||
478 | { | ||
479 | struct bpa10x_data *data = hdev->driver_data; | ||
480 | |||
481 | BT_DBG("hdev %p data %p", hdev, data); | ||
482 | |||
483 | skb_queue_purge(&data->cmd_queue); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int bpa10x_send_frame(struct sk_buff *skb) | ||
489 | { | ||
490 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
491 | struct bpa10x_data *data; | ||
492 | |||
493 | BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len); | ||
494 | |||
495 | if (!hdev) { | ||
496 | BT_ERR("Frame for unknown HCI device"); | ||
497 | return -ENODEV; | ||
498 | } | ||
499 | |||
500 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
501 | return -EBUSY; | ||
502 | |||
503 | data = hdev->driver_data; | ||
504 | |||
505 | /* Prepend skb with frame type */ | ||
506 | memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); | ||
507 | |||
508 | switch (skb->pkt_type) { | ||
509 | case HCI_COMMAND_PKT: | ||
510 | hdev->stat.cmd_tx++; | ||
511 | skb_queue_tail(&data->cmd_queue, skb); | ||
512 | break; | ||
513 | |||
514 | case HCI_ACLDATA_PKT: | ||
515 | hdev->stat.acl_tx++; | ||
516 | skb_queue_tail(&data->tx_queue, skb); | ||
517 | break; | ||
518 | |||
519 | case HCI_SCODATA_PKT: | ||
520 | hdev->stat.sco_tx++; | ||
521 | skb_queue_tail(&data->tx_queue, skb); | ||
522 | break; | ||
523 | }; | ||
524 | |||
525 | read_lock(&data->lock); | ||
526 | |||
527 | bpa10x_wakeup(data); | ||
528 | |||
529 | read_unlock(&data->lock); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static void bpa10x_destruct(struct hci_dev *hdev) | ||
535 | { | ||
536 | struct bpa10x_data *data = hdev->driver_data; | ||
537 | |||
538 | BT_DBG("hdev %p data %p", hdev, data); | ||
539 | |||
540 | kfree(data); | ||
541 | } | ||
542 | |||
543 | static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
544 | { | ||
545 | struct usb_device *udev = interface_to_usbdev(intf); | ||
546 | struct hci_dev *hdev; | ||
547 | struct bpa10x_data *data; | ||
548 | int err; | ||
549 | |||
550 | BT_DBG("intf %p id %p", intf, id); | ||
551 | |||
552 | if (ignore) | ||
553 | return -ENODEV; | ||
554 | |||
555 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
556 | if (!data) { | ||
557 | BT_ERR("Can't allocate data structure"); | ||
558 | return -ENOMEM; | ||
559 | } | ||
560 | |||
561 | memset(data, 0, sizeof(*data)); | ||
562 | |||
563 | data->udev = udev; | ||
564 | |||
565 | rwlock_init(&data->lock); | ||
566 | |||
567 | skb_queue_head_init(&data->cmd_queue); | ||
568 | skb_queue_head_init(&data->tx_queue); | ||
569 | |||
570 | hdev = hci_alloc_dev(); | ||
571 | if (!hdev) { | ||
572 | BT_ERR("Can't allocate HCI device"); | ||
573 | kfree(data); | ||
574 | return -ENOMEM; | ||
575 | } | ||
576 | |||
577 | data->hdev = hdev; | ||
578 | |||
579 | hdev->type = HCI_USB; | ||
580 | hdev->driver_data = data; | ||
581 | SET_HCIDEV_DEV(hdev, &intf->dev); | ||
582 | |||
583 | hdev->open = bpa10x_open; | ||
584 | hdev->close = bpa10x_close; | ||
585 | hdev->flush = bpa10x_flush; | ||
586 | hdev->send = bpa10x_send_frame; | ||
587 | hdev->destruct = bpa10x_destruct; | ||
588 | |||
589 | hdev->owner = THIS_MODULE; | ||
590 | |||
591 | err = hci_register_dev(hdev); | ||
592 | if (err < 0) { | ||
593 | BT_ERR("Can't register HCI device"); | ||
594 | kfree(data); | ||
595 | hci_free_dev(hdev); | ||
596 | return err; | ||
597 | } | ||
598 | |||
599 | usb_set_intfdata(intf, data); | ||
600 | |||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static void bpa10x_disconnect(struct usb_interface *intf) | ||
605 | { | ||
606 | struct bpa10x_data *data = usb_get_intfdata(intf); | ||
607 | struct hci_dev *hdev = data->hdev; | ||
608 | |||
609 | BT_DBG("intf %p", intf); | ||
610 | |||
611 | if (!hdev) | ||
612 | return; | ||
613 | |||
614 | usb_set_intfdata(intf, NULL); | ||
615 | |||
616 | if (hci_unregister_dev(hdev) < 0) | ||
617 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
618 | |||
619 | hci_free_dev(hdev); | ||
620 | } | ||
621 | |||
622 | static struct usb_driver bpa10x_driver = { | ||
623 | .owner = THIS_MODULE, | ||
624 | .name = "bpa10x", | ||
625 | .probe = bpa10x_probe, | ||
626 | .disconnect = bpa10x_disconnect, | ||
627 | .id_table = bpa10x_table, | ||
628 | }; | ||
629 | |||
630 | static int __init bpa10x_init(void) | ||
631 | { | ||
632 | int err; | ||
633 | |||
634 | BT_INFO("Digianswer Bluetooth USB driver ver %s", VERSION); | ||
635 | |||
636 | err = usb_register(&bpa10x_driver); | ||
637 | if (err < 0) | ||
638 | BT_ERR("Failed to register USB driver"); | ||
639 | |||
640 | return err; | ||
641 | } | ||
642 | |||
643 | static void __exit bpa10x_exit(void) | ||
644 | { | ||
645 | usb_deregister(&bpa10x_driver); | ||
646 | } | ||
647 | |||
648 | module_init(bpa10x_init); | ||
649 | module_exit(bpa10x_exit); | ||
650 | |||
651 | module_param(ignore, bool, 0644); | ||
652 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); | ||
653 | |||
654 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
655 | MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION); | ||
656 | MODULE_VERSION(VERSION); | ||
657 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c new file mode 100644 index 000000000000..f71e5c76963d --- /dev/null +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -0,0 +1,960 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Driver for the 3Com Bluetooth PCMCIA card | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * Jose Orlando Pereira <jop@di.uminho.pt> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation; | ||
12 | * | ||
13 | * Software distributed under the License is distributed on an "AS | ||
14 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
15 | * implied. See the License for the specific language governing | ||
16 | * rights and limitations under the License. | ||
17 | * | ||
18 | * The initial developer of the original code is David A. Hinds | ||
19 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
20 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/moduleparam.h> | ||
38 | |||
39 | #include <linux/skbuff.h> | ||
40 | #include <linux/string.h> | ||
41 | #include <linux/serial.h> | ||
42 | #include <linux/serial_reg.h> | ||
43 | #include <linux/bitops.h> | ||
44 | #include <asm/system.h> | ||
45 | #include <asm/io.h> | ||
46 | |||
47 | #include <linux/device.h> | ||
48 | #include <linux/firmware.h> | ||
49 | |||
50 | #include <pcmcia/version.h> | ||
51 | #include <pcmcia/cs_types.h> | ||
52 | #include <pcmcia/cs.h> | ||
53 | #include <pcmcia/cistpl.h> | ||
54 | #include <pcmcia/ciscode.h> | ||
55 | #include <pcmcia/ds.h> | ||
56 | #include <pcmcia/cisreg.h> | ||
57 | |||
58 | #include <net/bluetooth/bluetooth.h> | ||
59 | #include <net/bluetooth/hci_core.h> | ||
60 | |||
61 | |||
62 | |||
63 | /* ======================== Module parameters ======================== */ | ||
64 | |||
65 | |||
66 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>"); | ||
67 | MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); | ||
68 | MODULE_LICENSE("GPL"); | ||
69 | |||
70 | |||
71 | |||
72 | /* ======================== Local structures ======================== */ | ||
73 | |||
74 | |||
75 | typedef struct bt3c_info_t { | ||
76 | dev_link_t link; | ||
77 | dev_node_t node; | ||
78 | |||
79 | struct hci_dev *hdev; | ||
80 | |||
81 | spinlock_t lock; /* For serializing operations */ | ||
82 | |||
83 | struct sk_buff_head txq; | ||
84 | unsigned long tx_state; | ||
85 | |||
86 | unsigned long rx_state; | ||
87 | unsigned long rx_count; | ||
88 | struct sk_buff *rx_skb; | ||
89 | } bt3c_info_t; | ||
90 | |||
91 | |||
92 | static void bt3c_config(dev_link_t *link); | ||
93 | static void bt3c_release(dev_link_t *link); | ||
94 | static int bt3c_event(event_t event, int priority, event_callback_args_t *args); | ||
95 | |||
96 | static dev_info_t dev_info = "bt3c_cs"; | ||
97 | |||
98 | static dev_link_t *bt3c_attach(void); | ||
99 | static void bt3c_detach(dev_link_t *); | ||
100 | |||
101 | static dev_link_t *dev_list = NULL; | ||
102 | |||
103 | |||
104 | /* Transmit states */ | ||
105 | #define XMIT_SENDING 1 | ||
106 | #define XMIT_WAKEUP 2 | ||
107 | #define XMIT_WAITING 8 | ||
108 | |||
109 | /* Receiver states */ | ||
110 | #define RECV_WAIT_PACKET_TYPE 0 | ||
111 | #define RECV_WAIT_EVENT_HEADER 1 | ||
112 | #define RECV_WAIT_ACL_HEADER 2 | ||
113 | #define RECV_WAIT_SCO_HEADER 3 | ||
114 | #define RECV_WAIT_DATA 4 | ||
115 | |||
116 | |||
117 | |||
118 | /* ======================== Special I/O functions ======================== */ | ||
119 | |||
120 | |||
121 | #define DATA_L 0 | ||
122 | #define DATA_H 1 | ||
123 | #define ADDR_L 2 | ||
124 | #define ADDR_H 3 | ||
125 | #define CONTROL 4 | ||
126 | |||
127 | |||
128 | static inline void bt3c_address(unsigned int iobase, unsigned short addr) | ||
129 | { | ||
130 | outb(addr & 0xff, iobase + ADDR_L); | ||
131 | outb((addr >> 8) & 0xff, iobase + ADDR_H); | ||
132 | } | ||
133 | |||
134 | |||
135 | static inline void bt3c_put(unsigned int iobase, unsigned short value) | ||
136 | { | ||
137 | outb(value & 0xff, iobase + DATA_L); | ||
138 | outb((value >> 8) & 0xff, iobase + DATA_H); | ||
139 | } | ||
140 | |||
141 | |||
142 | static inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value) | ||
143 | { | ||
144 | bt3c_address(iobase, addr); | ||
145 | bt3c_put(iobase, value); | ||
146 | } | ||
147 | |||
148 | |||
149 | static inline unsigned short bt3c_get(unsigned int iobase) | ||
150 | { | ||
151 | unsigned short value = inb(iobase + DATA_L); | ||
152 | |||
153 | value |= inb(iobase + DATA_H) << 8; | ||
154 | |||
155 | return value; | ||
156 | } | ||
157 | |||
158 | |||
159 | static inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr) | ||
160 | { | ||
161 | bt3c_address(iobase, addr); | ||
162 | |||
163 | return bt3c_get(iobase); | ||
164 | } | ||
165 | |||
166 | |||
167 | |||
168 | /* ======================== Interrupt handling ======================== */ | ||
169 | |||
170 | |||
171 | static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) | ||
172 | { | ||
173 | int actual = 0; | ||
174 | |||
175 | bt3c_address(iobase, 0x7080); | ||
176 | |||
177 | /* Fill FIFO with current frame */ | ||
178 | while (actual < len) { | ||
179 | /* Transmit next byte */ | ||
180 | bt3c_put(iobase, buf[actual]); | ||
181 | actual++; | ||
182 | } | ||
183 | |||
184 | bt3c_io_write(iobase, 0x7005, actual); | ||
185 | |||
186 | return actual; | ||
187 | } | ||
188 | |||
189 | |||
190 | static void bt3c_write_wakeup(bt3c_info_t *info) | ||
191 | { | ||
192 | if (!info) { | ||
193 | BT_ERR("Unknown device"); | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) | ||
198 | return; | ||
199 | |||
200 | do { | ||
201 | register unsigned int iobase = info->link.io.BasePort1; | ||
202 | register struct sk_buff *skb; | ||
203 | register int len; | ||
204 | |||
205 | if (!(info->link.state & DEV_PRESENT)) | ||
206 | break; | ||
207 | |||
208 | |||
209 | if (!(skb = skb_dequeue(&(info->txq)))) { | ||
210 | clear_bit(XMIT_SENDING, &(info->tx_state)); | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | /* Send frame */ | ||
215 | len = bt3c_write(iobase, 256, skb->data, skb->len); | ||
216 | |||
217 | if (len != skb->len) { | ||
218 | BT_ERR("Very strange"); | ||
219 | } | ||
220 | |||
221 | kfree_skb(skb); | ||
222 | |||
223 | info->hdev->stat.byte_tx += len; | ||
224 | |||
225 | } while (0); | ||
226 | } | ||
227 | |||
228 | |||
229 | static void bt3c_receive(bt3c_info_t *info) | ||
230 | { | ||
231 | unsigned int iobase; | ||
232 | int size = 0, avail; | ||
233 | |||
234 | if (!info) { | ||
235 | BT_ERR("Unknown device"); | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | iobase = info->link.io.BasePort1; | ||
240 | |||
241 | avail = bt3c_read(iobase, 0x7006); | ||
242 | //printk("bt3c_cs: receiving %d bytes\n", avail); | ||
243 | |||
244 | bt3c_address(iobase, 0x7480); | ||
245 | while (size < avail) { | ||
246 | size++; | ||
247 | info->hdev->stat.byte_rx++; | ||
248 | |||
249 | /* Allocate packet */ | ||
250 | if (info->rx_skb == NULL) { | ||
251 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
252 | info->rx_count = 0; | ||
253 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | ||
254 | BT_ERR("Can't allocate mem for new packet"); | ||
255 | return; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | |||
260 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | ||
261 | |||
262 | info->rx_skb->dev = (void *) info->hdev; | ||
263 | info->rx_skb->pkt_type = inb(iobase + DATA_L); | ||
264 | inb(iobase + DATA_H); | ||
265 | //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type); | ||
266 | |||
267 | switch (info->rx_skb->pkt_type) { | ||
268 | |||
269 | case HCI_EVENT_PKT: | ||
270 | info->rx_state = RECV_WAIT_EVENT_HEADER; | ||
271 | info->rx_count = HCI_EVENT_HDR_SIZE; | ||
272 | break; | ||
273 | |||
274 | case HCI_ACLDATA_PKT: | ||
275 | info->rx_state = RECV_WAIT_ACL_HEADER; | ||
276 | info->rx_count = HCI_ACL_HDR_SIZE; | ||
277 | break; | ||
278 | |||
279 | case HCI_SCODATA_PKT: | ||
280 | info->rx_state = RECV_WAIT_SCO_HEADER; | ||
281 | info->rx_count = HCI_SCO_HDR_SIZE; | ||
282 | break; | ||
283 | |||
284 | default: | ||
285 | /* Unknown packet */ | ||
286 | BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); | ||
287 | info->hdev->stat.err_rx++; | ||
288 | clear_bit(HCI_RUNNING, &(info->hdev->flags)); | ||
289 | |||
290 | kfree_skb(info->rx_skb); | ||
291 | info->rx_skb = NULL; | ||
292 | break; | ||
293 | |||
294 | } | ||
295 | |||
296 | } else { | ||
297 | |||
298 | __u8 x = inb(iobase + DATA_L); | ||
299 | |||
300 | *skb_put(info->rx_skb, 1) = x; | ||
301 | inb(iobase + DATA_H); | ||
302 | info->rx_count--; | ||
303 | |||
304 | if (info->rx_count == 0) { | ||
305 | |||
306 | int dlen; | ||
307 | struct hci_event_hdr *eh; | ||
308 | struct hci_acl_hdr *ah; | ||
309 | struct hci_sco_hdr *sh; | ||
310 | |||
311 | switch (info->rx_state) { | ||
312 | |||
313 | case RECV_WAIT_EVENT_HEADER: | ||
314 | eh = (struct hci_event_hdr *)(info->rx_skb->data); | ||
315 | info->rx_state = RECV_WAIT_DATA; | ||
316 | info->rx_count = eh->plen; | ||
317 | break; | ||
318 | |||
319 | case RECV_WAIT_ACL_HEADER: | ||
320 | ah = (struct hci_acl_hdr *)(info->rx_skb->data); | ||
321 | dlen = __le16_to_cpu(ah->dlen); | ||
322 | info->rx_state = RECV_WAIT_DATA; | ||
323 | info->rx_count = dlen; | ||
324 | break; | ||
325 | |||
326 | case RECV_WAIT_SCO_HEADER: | ||
327 | sh = (struct hci_sco_hdr *)(info->rx_skb->data); | ||
328 | info->rx_state = RECV_WAIT_DATA; | ||
329 | info->rx_count = sh->dlen; | ||
330 | break; | ||
331 | |||
332 | case RECV_WAIT_DATA: | ||
333 | hci_recv_frame(info->rx_skb); | ||
334 | info->rx_skb = NULL; | ||
335 | break; | ||
336 | |||
337 | } | ||
338 | |||
339 | } | ||
340 | |||
341 | } | ||
342 | |||
343 | } | ||
344 | |||
345 | bt3c_io_write(iobase, 0x7006, 0x0000); | ||
346 | } | ||
347 | |||
348 | |||
349 | static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) | ||
350 | { | ||
351 | bt3c_info_t *info = dev_inst; | ||
352 | unsigned int iobase; | ||
353 | int iir; | ||
354 | |||
355 | if (!info || !info->hdev) { | ||
356 | BT_ERR("Call of irq %d for unknown device", irq); | ||
357 | return IRQ_NONE; | ||
358 | } | ||
359 | |||
360 | iobase = info->link.io.BasePort1; | ||
361 | |||
362 | spin_lock(&(info->lock)); | ||
363 | |||
364 | iir = inb(iobase + CONTROL); | ||
365 | if (iir & 0x80) { | ||
366 | int stat = bt3c_read(iobase, 0x7001); | ||
367 | |||
368 | if ((stat & 0xff) == 0x7f) { | ||
369 | BT_ERR("Very strange (stat=0x%04x)", stat); | ||
370 | } else if ((stat & 0xff) != 0xff) { | ||
371 | if (stat & 0x0020) { | ||
372 | int stat = bt3c_read(iobase, 0x7002) & 0x10; | ||
373 | BT_INFO("%s: Antenna %s", info->hdev->name, | ||
374 | stat ? "out" : "in"); | ||
375 | } | ||
376 | if (stat & 0x0001) | ||
377 | bt3c_receive(info); | ||
378 | if (stat & 0x0002) { | ||
379 | //BT_ERR("Ack (stat=0x%04x)", stat); | ||
380 | clear_bit(XMIT_SENDING, &(info->tx_state)); | ||
381 | bt3c_write_wakeup(info); | ||
382 | } | ||
383 | |||
384 | bt3c_io_write(iobase, 0x7001, 0x0000); | ||
385 | |||
386 | outb(iir, iobase + CONTROL); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | spin_unlock(&(info->lock)); | ||
391 | |||
392 | return IRQ_HANDLED; | ||
393 | } | ||
394 | |||
395 | |||
396 | |||
397 | /* ======================== HCI interface ======================== */ | ||
398 | |||
399 | |||
400 | static int bt3c_hci_flush(struct hci_dev *hdev) | ||
401 | { | ||
402 | bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data); | ||
403 | |||
404 | /* Drop TX queue */ | ||
405 | skb_queue_purge(&(info->txq)); | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | |||
411 | static int bt3c_hci_open(struct hci_dev *hdev) | ||
412 | { | ||
413 | set_bit(HCI_RUNNING, &(hdev->flags)); | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | |||
419 | static int bt3c_hci_close(struct hci_dev *hdev) | ||
420 | { | ||
421 | if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) | ||
422 | return 0; | ||
423 | |||
424 | bt3c_hci_flush(hdev); | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | |||
430 | static int bt3c_hci_send_frame(struct sk_buff *skb) | ||
431 | { | ||
432 | bt3c_info_t *info; | ||
433 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
434 | unsigned long flags; | ||
435 | |||
436 | if (!hdev) { | ||
437 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
438 | return -ENODEV; | ||
439 | } | ||
440 | |||
441 | info = (bt3c_info_t *) (hdev->driver_data); | ||
442 | |||
443 | switch (skb->pkt_type) { | ||
444 | case HCI_COMMAND_PKT: | ||
445 | hdev->stat.cmd_tx++; | ||
446 | break; | ||
447 | case HCI_ACLDATA_PKT: | ||
448 | hdev->stat.acl_tx++; | ||
449 | break; | ||
450 | case HCI_SCODATA_PKT: | ||
451 | hdev->stat.sco_tx++; | ||
452 | break; | ||
453 | }; | ||
454 | |||
455 | /* Prepend skb with frame type */ | ||
456 | memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); | ||
457 | skb_queue_tail(&(info->txq), skb); | ||
458 | |||
459 | spin_lock_irqsave(&(info->lock), flags); | ||
460 | |||
461 | bt3c_write_wakeup(info); | ||
462 | |||
463 | spin_unlock_irqrestore(&(info->lock), flags); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | |||
469 | static void bt3c_hci_destruct(struct hci_dev *hdev) | ||
470 | { | ||
471 | } | ||
472 | |||
473 | |||
474 | static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
475 | { | ||
476 | return -ENOIOCTLCMD; | ||
477 | } | ||
478 | |||
479 | |||
480 | |||
481 | /* ======================== Card services HCI interaction ======================== */ | ||
482 | |||
483 | |||
484 | static struct device *bt3c_device(void) | ||
485 | { | ||
486 | static struct device dev = { | ||
487 | .bus_id = "pcmcia", | ||
488 | }; | ||
489 | kobject_set_name(&dev.kobj, "bt3c"); | ||
490 | kobject_init(&dev.kobj); | ||
491 | |||
492 | return &dev; | ||
493 | } | ||
494 | |||
495 | |||
496 | static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count) | ||
497 | { | ||
498 | char *ptr = (char *) firmware; | ||
499 | char b[9]; | ||
500 | unsigned int iobase, size, addr, fcs, tmp; | ||
501 | int i, err = 0; | ||
502 | |||
503 | iobase = info->link.io.BasePort1; | ||
504 | |||
505 | /* Reset */ | ||
506 | bt3c_io_write(iobase, 0x8040, 0x0404); | ||
507 | bt3c_io_write(iobase, 0x8040, 0x0400); | ||
508 | |||
509 | udelay(1); | ||
510 | |||
511 | bt3c_io_write(iobase, 0x8040, 0x0404); | ||
512 | |||
513 | udelay(17); | ||
514 | |||
515 | /* Load */ | ||
516 | while (count) { | ||
517 | if (ptr[0] != 'S') { | ||
518 | BT_ERR("Bad address in firmware"); | ||
519 | err = -EFAULT; | ||
520 | goto error; | ||
521 | } | ||
522 | |||
523 | memset(b, 0, sizeof(b)); | ||
524 | memcpy(b, ptr + 2, 2); | ||
525 | size = simple_strtol(b, NULL, 16); | ||
526 | |||
527 | memset(b, 0, sizeof(b)); | ||
528 | memcpy(b, ptr + 4, 8); | ||
529 | addr = simple_strtol(b, NULL, 16); | ||
530 | |||
531 | memset(b, 0, sizeof(b)); | ||
532 | memcpy(b, ptr + (size * 2) + 2, 2); | ||
533 | fcs = simple_strtol(b, NULL, 16); | ||
534 | |||
535 | memset(b, 0, sizeof(b)); | ||
536 | for (tmp = 0, i = 0; i < size; i++) { | ||
537 | memcpy(b, ptr + (i * 2) + 2, 2); | ||
538 | tmp += simple_strtol(b, NULL, 16); | ||
539 | } | ||
540 | |||
541 | if (((tmp + fcs) & 0xff) != 0xff) { | ||
542 | BT_ERR("Checksum error in firmware"); | ||
543 | err = -EILSEQ; | ||
544 | goto error; | ||
545 | } | ||
546 | |||
547 | if (ptr[1] == '3') { | ||
548 | bt3c_address(iobase, addr); | ||
549 | |||
550 | memset(b, 0, sizeof(b)); | ||
551 | for (i = 0; i < (size - 4) / 2; i++) { | ||
552 | memcpy(b, ptr + (i * 4) + 12, 4); | ||
553 | tmp = simple_strtol(b, NULL, 16); | ||
554 | bt3c_put(iobase, tmp); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | ptr += (size * 2) + 6; | ||
559 | count -= (size * 2) + 6; | ||
560 | } | ||
561 | |||
562 | udelay(17); | ||
563 | |||
564 | /* Boot */ | ||
565 | bt3c_address(iobase, 0x3000); | ||
566 | outb(inb(iobase + CONTROL) | 0x40, iobase + CONTROL); | ||
567 | |||
568 | error: | ||
569 | udelay(17); | ||
570 | |||
571 | /* Clear */ | ||
572 | bt3c_io_write(iobase, 0x7006, 0x0000); | ||
573 | bt3c_io_write(iobase, 0x7005, 0x0000); | ||
574 | bt3c_io_write(iobase, 0x7001, 0x0000); | ||
575 | |||
576 | return err; | ||
577 | } | ||
578 | |||
579 | |||
580 | static int bt3c_open(bt3c_info_t *info) | ||
581 | { | ||
582 | const struct firmware *firmware; | ||
583 | struct hci_dev *hdev; | ||
584 | int err; | ||
585 | |||
586 | spin_lock_init(&(info->lock)); | ||
587 | |||
588 | skb_queue_head_init(&(info->txq)); | ||
589 | |||
590 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
591 | info->rx_count = 0; | ||
592 | info->rx_skb = NULL; | ||
593 | |||
594 | /* Initialize HCI device */ | ||
595 | hdev = hci_alloc_dev(); | ||
596 | if (!hdev) { | ||
597 | BT_ERR("Can't allocate HCI device"); | ||
598 | return -ENOMEM; | ||
599 | } | ||
600 | |||
601 | info->hdev = hdev; | ||
602 | |||
603 | hdev->type = HCI_PCCARD; | ||
604 | hdev->driver_data = info; | ||
605 | |||
606 | hdev->open = bt3c_hci_open; | ||
607 | hdev->close = bt3c_hci_close; | ||
608 | hdev->flush = bt3c_hci_flush; | ||
609 | hdev->send = bt3c_hci_send_frame; | ||
610 | hdev->destruct = bt3c_hci_destruct; | ||
611 | hdev->ioctl = bt3c_hci_ioctl; | ||
612 | |||
613 | hdev->owner = THIS_MODULE; | ||
614 | |||
615 | /* Load firmware */ | ||
616 | err = request_firmware(&firmware, "BT3CPCC.bin", bt3c_device()); | ||
617 | if (err < 0) { | ||
618 | BT_ERR("Firmware request failed"); | ||
619 | goto error; | ||
620 | } | ||
621 | |||
622 | err = bt3c_load_firmware(info, firmware->data, firmware->size); | ||
623 | |||
624 | release_firmware(firmware); | ||
625 | |||
626 | if (err < 0) { | ||
627 | BT_ERR("Firmware loading failed"); | ||
628 | goto error; | ||
629 | } | ||
630 | |||
631 | /* Timeout before it is safe to send the first HCI packet */ | ||
632 | msleep(1000); | ||
633 | |||
634 | /* Register HCI device */ | ||
635 | err = hci_register_dev(hdev); | ||
636 | if (err < 0) { | ||
637 | BT_ERR("Can't register HCI device"); | ||
638 | goto error; | ||
639 | } | ||
640 | |||
641 | return 0; | ||
642 | |||
643 | error: | ||
644 | info->hdev = NULL; | ||
645 | hci_free_dev(hdev); | ||
646 | return err; | ||
647 | } | ||
648 | |||
649 | |||
650 | static int bt3c_close(bt3c_info_t *info) | ||
651 | { | ||
652 | struct hci_dev *hdev = info->hdev; | ||
653 | |||
654 | if (!hdev) | ||
655 | return -ENODEV; | ||
656 | |||
657 | bt3c_hci_close(hdev); | ||
658 | |||
659 | if (hci_unregister_dev(hdev) < 0) | ||
660 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
661 | |||
662 | hci_free_dev(hdev); | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static dev_link_t *bt3c_attach(void) | ||
668 | { | ||
669 | bt3c_info_t *info; | ||
670 | client_reg_t client_reg; | ||
671 | dev_link_t *link; | ||
672 | int ret; | ||
673 | |||
674 | /* Create new info device */ | ||
675 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
676 | if (!info) | ||
677 | return NULL; | ||
678 | memset(info, 0, sizeof(*info)); | ||
679 | |||
680 | link = &info->link; | ||
681 | link->priv = info; | ||
682 | |||
683 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
684 | link->io.NumPorts1 = 8; | ||
685 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
686 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
687 | |||
688 | link->irq.Handler = bt3c_interrupt; | ||
689 | link->irq.Instance = info; | ||
690 | |||
691 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
692 | link->conf.Vcc = 50; | ||
693 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
694 | |||
695 | /* Register with Card Services */ | ||
696 | link->next = dev_list; | ||
697 | dev_list = link; | ||
698 | client_reg.dev_info = &dev_info; | ||
699 | client_reg.EventMask = | ||
700 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
701 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
702 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
703 | client_reg.event_handler = &bt3c_event; | ||
704 | client_reg.Version = 0x0210; | ||
705 | client_reg.event_callback_args.client_data = link; | ||
706 | |||
707 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
708 | if (ret != CS_SUCCESS) { | ||
709 | cs_error(link->handle, RegisterClient, ret); | ||
710 | bt3c_detach(link); | ||
711 | return NULL; | ||
712 | } | ||
713 | |||
714 | return link; | ||
715 | } | ||
716 | |||
717 | |||
718 | static void bt3c_detach(dev_link_t *link) | ||
719 | { | ||
720 | bt3c_info_t *info = link->priv; | ||
721 | dev_link_t **linkp; | ||
722 | int ret; | ||
723 | |||
724 | /* Locate device structure */ | ||
725 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
726 | if (*linkp == link) | ||
727 | break; | ||
728 | |||
729 | if (*linkp == NULL) | ||
730 | return; | ||
731 | |||
732 | if (link->state & DEV_CONFIG) | ||
733 | bt3c_release(link); | ||
734 | |||
735 | if (link->handle) { | ||
736 | ret = pcmcia_deregister_client(link->handle); | ||
737 | if (ret != CS_SUCCESS) | ||
738 | cs_error(link->handle, DeregisterClient, ret); | ||
739 | } | ||
740 | |||
741 | /* Unlink device structure, free bits */ | ||
742 | *linkp = link->next; | ||
743 | |||
744 | kfree(info); | ||
745 | } | ||
746 | |||
747 | static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
748 | { | ||
749 | int i; | ||
750 | |||
751 | i = pcmcia_get_tuple_data(handle, tuple); | ||
752 | if (i != CS_SUCCESS) | ||
753 | return i; | ||
754 | |||
755 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
756 | } | ||
757 | |||
758 | static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
759 | { | ||
760 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) | ||
761 | return CS_NO_MORE_ITEMS; | ||
762 | return get_tuple(handle, tuple, parse); | ||
763 | } | ||
764 | |||
765 | static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
766 | { | ||
767 | if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) | ||
768 | return CS_NO_MORE_ITEMS; | ||
769 | return get_tuple(handle, tuple, parse); | ||
770 | } | ||
771 | |||
772 | static void bt3c_config(dev_link_t *link) | ||
773 | { | ||
774 | static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
775 | client_handle_t handle = link->handle; | ||
776 | bt3c_info_t *info = link->priv; | ||
777 | tuple_t tuple; | ||
778 | u_short buf[256]; | ||
779 | cisparse_t parse; | ||
780 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
781 | config_info_t config; | ||
782 | int i, j, try, last_ret, last_fn; | ||
783 | |||
784 | tuple.TupleData = (cisdata_t *)buf; | ||
785 | tuple.TupleOffset = 0; | ||
786 | tuple.TupleDataMax = 255; | ||
787 | tuple.Attributes = 0; | ||
788 | |||
789 | /* Get configuration register information */ | ||
790 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
791 | last_ret = first_tuple(handle, &tuple, &parse); | ||
792 | if (last_ret != CS_SUCCESS) { | ||
793 | last_fn = ParseTuple; | ||
794 | goto cs_failed; | ||
795 | } | ||
796 | link->conf.ConfigBase = parse.config.base; | ||
797 | link->conf.Present = parse.config.rmask[0]; | ||
798 | |||
799 | /* Configure card */ | ||
800 | link->state |= DEV_CONFIG; | ||
801 | i = pcmcia_get_configuration_info(handle, &config); | ||
802 | link->conf.Vcc = config.Vcc; | ||
803 | |||
804 | /* First pass: look for a config entry that looks normal. */ | ||
805 | tuple.TupleData = (cisdata_t *)buf; | ||
806 | tuple.TupleOffset = 0; | ||
807 | tuple.TupleDataMax = 255; | ||
808 | tuple.Attributes = 0; | ||
809 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
810 | /* Two tries: without IO aliases, then with aliases */ | ||
811 | for (try = 0; try < 2; try++) { | ||
812 | i = first_tuple(handle, &tuple, &parse); | ||
813 | while (i != CS_NO_MORE_ITEMS) { | ||
814 | if (i != CS_SUCCESS) | ||
815 | goto next_entry; | ||
816 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
817 | link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
818 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { | ||
819 | link->conf.ConfigIndex = cf->index; | ||
820 | link->io.BasePort1 = cf->io.win[0].base; | ||
821 | link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
822 | i = pcmcia_request_io(link->handle, &link->io); | ||
823 | if (i == CS_SUCCESS) | ||
824 | goto found_port; | ||
825 | } | ||
826 | next_entry: | ||
827 | i = next_tuple(handle, &tuple, &parse); | ||
828 | } | ||
829 | } | ||
830 | |||
831 | /* Second pass: try to find an entry that isn't picky about | ||
832 | its base address, then try to grab any standard serial port | ||
833 | address, and finally try to get any free port. */ | ||
834 | i = first_tuple(handle, &tuple, &parse); | ||
835 | while (i != CS_NO_MORE_ITEMS) { | ||
836 | if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
837 | link->conf.ConfigIndex = cf->index; | ||
838 | for (j = 0; j < 5; j++) { | ||
839 | link->io.BasePort1 = base[j]; | ||
840 | link->io.IOAddrLines = base[j] ? 16 : 3; | ||
841 | i = pcmcia_request_io(link->handle, &link->io); | ||
842 | if (i == CS_SUCCESS) | ||
843 | goto found_port; | ||
844 | } | ||
845 | } | ||
846 | i = next_tuple(handle, &tuple, &parse); | ||
847 | } | ||
848 | |||
849 | found_port: | ||
850 | if (i != CS_SUCCESS) { | ||
851 | BT_ERR("No usable port range found"); | ||
852 | cs_error(link->handle, RequestIO, i); | ||
853 | goto failed; | ||
854 | } | ||
855 | |||
856 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
857 | if (i != CS_SUCCESS) { | ||
858 | cs_error(link->handle, RequestIRQ, i); | ||
859 | link->irq.AssignedIRQ = 0; | ||
860 | } | ||
861 | |||
862 | i = pcmcia_request_configuration(link->handle, &link->conf); | ||
863 | if (i != CS_SUCCESS) { | ||
864 | cs_error(link->handle, RequestConfiguration, i); | ||
865 | goto failed; | ||
866 | } | ||
867 | |||
868 | if (bt3c_open(info) != 0) | ||
869 | goto failed; | ||
870 | |||
871 | strcpy(info->node.dev_name, info->hdev->name); | ||
872 | link->dev = &info->node; | ||
873 | link->state &= ~DEV_CONFIG_PENDING; | ||
874 | |||
875 | return; | ||
876 | |||
877 | cs_failed: | ||
878 | cs_error(link->handle, last_fn, last_ret); | ||
879 | |||
880 | failed: | ||
881 | bt3c_release(link); | ||
882 | } | ||
883 | |||
884 | |||
885 | static void bt3c_release(dev_link_t *link) | ||
886 | { | ||
887 | bt3c_info_t *info = link->priv; | ||
888 | |||
889 | if (link->state & DEV_PRESENT) | ||
890 | bt3c_close(info); | ||
891 | |||
892 | link->dev = NULL; | ||
893 | |||
894 | pcmcia_release_configuration(link->handle); | ||
895 | pcmcia_release_io(link->handle, &link->io); | ||
896 | pcmcia_release_irq(link->handle, &link->irq); | ||
897 | |||
898 | link->state &= ~DEV_CONFIG; | ||
899 | } | ||
900 | |||
901 | |||
902 | static int bt3c_event(event_t event, int priority, event_callback_args_t *args) | ||
903 | { | ||
904 | dev_link_t *link = args->client_data; | ||
905 | bt3c_info_t *info = link->priv; | ||
906 | |||
907 | switch (event) { | ||
908 | case CS_EVENT_CARD_REMOVAL: | ||
909 | link->state &= ~DEV_PRESENT; | ||
910 | if (link->state & DEV_CONFIG) { | ||
911 | bt3c_close(info); | ||
912 | bt3c_release(link); | ||
913 | } | ||
914 | break; | ||
915 | case CS_EVENT_CARD_INSERTION: | ||
916 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
917 | bt3c_config(link); | ||
918 | break; | ||
919 | case CS_EVENT_PM_SUSPEND: | ||
920 | link->state |= DEV_SUSPEND; | ||
921 | /* Fall through... */ | ||
922 | case CS_EVENT_RESET_PHYSICAL: | ||
923 | if (link->state & DEV_CONFIG) | ||
924 | pcmcia_release_configuration(link->handle); | ||
925 | break; | ||
926 | case CS_EVENT_PM_RESUME: | ||
927 | link->state &= ~DEV_SUSPEND; | ||
928 | /* Fall through... */ | ||
929 | case CS_EVENT_CARD_RESET: | ||
930 | if (DEV_OK(link)) | ||
931 | pcmcia_request_configuration(link->handle, &link->conf); | ||
932 | break; | ||
933 | } | ||
934 | |||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | static struct pcmcia_driver bt3c_driver = { | ||
939 | .owner = THIS_MODULE, | ||
940 | .drv = { | ||
941 | .name = "bt3c_cs", | ||
942 | }, | ||
943 | .attach = bt3c_attach, | ||
944 | .detach = bt3c_detach, | ||
945 | }; | ||
946 | |||
947 | static int __init init_bt3c_cs(void) | ||
948 | { | ||
949 | return pcmcia_register_driver(&bt3c_driver); | ||
950 | } | ||
951 | |||
952 | |||
953 | static void __exit exit_bt3c_cs(void) | ||
954 | { | ||
955 | pcmcia_unregister_driver(&bt3c_driver); | ||
956 | BUG_ON(dev_list != NULL); | ||
957 | } | ||
958 | |||
959 | module_init(init_bt3c_cs); | ||
960 | module_exit(exit_bt3c_cs); | ||
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c new file mode 100644 index 000000000000..ad8d972444a5 --- /dev/null +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -0,0 +1,880 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Driver for Bluetooth PCMCIA cards with HCI UART interface | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * | ||
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 | * Software distributed under the License is distributed on an "AS | ||
13 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
14 | * implied. See the License for the specific language governing | ||
15 | * rights and limitations under the License. | ||
16 | * | ||
17 | * The initial developer of the original code is David A. Hinds | ||
18 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
19 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/ptrace.h> | ||
34 | #include <linux/ioport.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/moduleparam.h> | ||
37 | |||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/serial.h> | ||
41 | #include <linux/serial_reg.h> | ||
42 | #include <linux/bitops.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/io.h> | ||
45 | |||
46 | #include <pcmcia/version.h> | ||
47 | #include <pcmcia/cs_types.h> | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | ||
50 | #include <pcmcia/ciscode.h> | ||
51 | #include <pcmcia/ds.h> | ||
52 | #include <pcmcia/cisreg.h> | ||
53 | |||
54 | #include <net/bluetooth/bluetooth.h> | ||
55 | #include <net/bluetooth/hci_core.h> | ||
56 | |||
57 | |||
58 | |||
59 | /* ======================== Module parameters ======================== */ | ||
60 | |||
61 | |||
62 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
63 | MODULE_DESCRIPTION("Bluetooth driver for Bluetooth PCMCIA cards with HCI UART interface"); | ||
64 | MODULE_LICENSE("GPL"); | ||
65 | |||
66 | |||
67 | |||
68 | /* ======================== Local structures ======================== */ | ||
69 | |||
70 | |||
71 | typedef struct btuart_info_t { | ||
72 | dev_link_t link; | ||
73 | dev_node_t node; | ||
74 | |||
75 | struct hci_dev *hdev; | ||
76 | |||
77 | spinlock_t lock; /* For serializing operations */ | ||
78 | |||
79 | struct sk_buff_head txq; | ||
80 | unsigned long tx_state; | ||
81 | |||
82 | unsigned long rx_state; | ||
83 | unsigned long rx_count; | ||
84 | struct sk_buff *rx_skb; | ||
85 | } btuart_info_t; | ||
86 | |||
87 | |||
88 | static void btuart_config(dev_link_t *link); | ||
89 | static void btuart_release(dev_link_t *link); | ||
90 | static int btuart_event(event_t event, int priority, event_callback_args_t *args); | ||
91 | |||
92 | static dev_info_t dev_info = "btuart_cs"; | ||
93 | |||
94 | static dev_link_t *btuart_attach(void); | ||
95 | static void btuart_detach(dev_link_t *); | ||
96 | |||
97 | static dev_link_t *dev_list = NULL; | ||
98 | |||
99 | |||
100 | /* Maximum baud rate */ | ||
101 | #define SPEED_MAX 115200 | ||
102 | |||
103 | /* Default baud rate: 57600, 115200, 230400 or 460800 */ | ||
104 | #define DEFAULT_BAUD_RATE 115200 | ||
105 | |||
106 | |||
107 | /* Transmit states */ | ||
108 | #define XMIT_SENDING 1 | ||
109 | #define XMIT_WAKEUP 2 | ||
110 | #define XMIT_WAITING 8 | ||
111 | |||
112 | /* Receiver states */ | ||
113 | #define RECV_WAIT_PACKET_TYPE 0 | ||
114 | #define RECV_WAIT_EVENT_HEADER 1 | ||
115 | #define RECV_WAIT_ACL_HEADER 2 | ||
116 | #define RECV_WAIT_SCO_HEADER 3 | ||
117 | #define RECV_WAIT_DATA 4 | ||
118 | |||
119 | |||
120 | |||
121 | /* ======================== Interrupt handling ======================== */ | ||
122 | |||
123 | |||
124 | static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) | ||
125 | { | ||
126 | int actual = 0; | ||
127 | |||
128 | /* Tx FIFO should be empty */ | ||
129 | if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) | ||
130 | return 0; | ||
131 | |||
132 | /* Fill FIFO with current frame */ | ||
133 | while ((fifo_size-- > 0) && (actual < len)) { | ||
134 | /* Transmit next byte */ | ||
135 | outb(buf[actual], iobase + UART_TX); | ||
136 | actual++; | ||
137 | } | ||
138 | |||
139 | return actual; | ||
140 | } | ||
141 | |||
142 | |||
143 | static void btuart_write_wakeup(btuart_info_t *info) | ||
144 | { | ||
145 | if (!info) { | ||
146 | BT_ERR("Unknown device"); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { | ||
151 | set_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | do { | ||
156 | register unsigned int iobase = info->link.io.BasePort1; | ||
157 | register struct sk_buff *skb; | ||
158 | register int len; | ||
159 | |||
160 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
161 | |||
162 | if (!(info->link.state & DEV_PRESENT)) | ||
163 | return; | ||
164 | |||
165 | if (!(skb = skb_dequeue(&(info->txq)))) | ||
166 | break; | ||
167 | |||
168 | /* Send frame */ | ||
169 | len = btuart_write(iobase, 16, skb->data, skb->len); | ||
170 | set_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
171 | |||
172 | if (len == skb->len) { | ||
173 | kfree_skb(skb); | ||
174 | } else { | ||
175 | skb_pull(skb, len); | ||
176 | skb_queue_head(&(info->txq), skb); | ||
177 | } | ||
178 | |||
179 | info->hdev->stat.byte_tx += len; | ||
180 | |||
181 | } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); | ||
182 | |||
183 | clear_bit(XMIT_SENDING, &(info->tx_state)); | ||
184 | } | ||
185 | |||
186 | |||
187 | static void btuart_receive(btuart_info_t *info) | ||
188 | { | ||
189 | unsigned int iobase; | ||
190 | int boguscount = 0; | ||
191 | |||
192 | if (!info) { | ||
193 | BT_ERR("Unknown device"); | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | iobase = info->link.io.BasePort1; | ||
198 | |||
199 | do { | ||
200 | info->hdev->stat.byte_rx++; | ||
201 | |||
202 | /* Allocate packet */ | ||
203 | if (info->rx_skb == NULL) { | ||
204 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
205 | info->rx_count = 0; | ||
206 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | ||
207 | BT_ERR("Can't allocate mem for new packet"); | ||
208 | return; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | if (info->rx_state == RECV_WAIT_PACKET_TYPE) { | ||
213 | |||
214 | info->rx_skb->dev = (void *) info->hdev; | ||
215 | info->rx_skb->pkt_type = inb(iobase + UART_RX); | ||
216 | |||
217 | switch (info->rx_skb->pkt_type) { | ||
218 | |||
219 | case HCI_EVENT_PKT: | ||
220 | info->rx_state = RECV_WAIT_EVENT_HEADER; | ||
221 | info->rx_count = HCI_EVENT_HDR_SIZE; | ||
222 | break; | ||
223 | |||
224 | case HCI_ACLDATA_PKT: | ||
225 | info->rx_state = RECV_WAIT_ACL_HEADER; | ||
226 | info->rx_count = HCI_ACL_HDR_SIZE; | ||
227 | break; | ||
228 | |||
229 | case HCI_SCODATA_PKT: | ||
230 | info->rx_state = RECV_WAIT_SCO_HEADER; | ||
231 | info->rx_count = HCI_SCO_HDR_SIZE; | ||
232 | break; | ||
233 | |||
234 | default: | ||
235 | /* Unknown packet */ | ||
236 | BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); | ||
237 | info->hdev->stat.err_rx++; | ||
238 | clear_bit(HCI_RUNNING, &(info->hdev->flags)); | ||
239 | |||
240 | kfree_skb(info->rx_skb); | ||
241 | info->rx_skb = NULL; | ||
242 | break; | ||
243 | |||
244 | } | ||
245 | |||
246 | } else { | ||
247 | |||
248 | *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); | ||
249 | info->rx_count--; | ||
250 | |||
251 | if (info->rx_count == 0) { | ||
252 | |||
253 | int dlen; | ||
254 | struct hci_event_hdr *eh; | ||
255 | struct hci_acl_hdr *ah; | ||
256 | struct hci_sco_hdr *sh; | ||
257 | |||
258 | |||
259 | switch (info->rx_state) { | ||
260 | |||
261 | case RECV_WAIT_EVENT_HEADER: | ||
262 | eh = (struct hci_event_hdr *)(info->rx_skb->data); | ||
263 | info->rx_state = RECV_WAIT_DATA; | ||
264 | info->rx_count = eh->plen; | ||
265 | break; | ||
266 | |||
267 | case RECV_WAIT_ACL_HEADER: | ||
268 | ah = (struct hci_acl_hdr *)(info->rx_skb->data); | ||
269 | dlen = __le16_to_cpu(ah->dlen); | ||
270 | info->rx_state = RECV_WAIT_DATA; | ||
271 | info->rx_count = dlen; | ||
272 | break; | ||
273 | |||
274 | case RECV_WAIT_SCO_HEADER: | ||
275 | sh = (struct hci_sco_hdr *)(info->rx_skb->data); | ||
276 | info->rx_state = RECV_WAIT_DATA; | ||
277 | info->rx_count = sh->dlen; | ||
278 | break; | ||
279 | |||
280 | case RECV_WAIT_DATA: | ||
281 | hci_recv_frame(info->rx_skb); | ||
282 | info->rx_skb = NULL; | ||
283 | break; | ||
284 | |||
285 | } | ||
286 | |||
287 | } | ||
288 | |||
289 | } | ||
290 | |||
291 | /* Make sure we don't stay here too long */ | ||
292 | if (boguscount++ > 16) | ||
293 | break; | ||
294 | |||
295 | } while (inb(iobase + UART_LSR) & UART_LSR_DR); | ||
296 | } | ||
297 | |||
298 | |||
299 | static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *regs) | ||
300 | { | ||
301 | btuart_info_t *info = dev_inst; | ||
302 | unsigned int iobase; | ||
303 | int boguscount = 0; | ||
304 | int iir, lsr; | ||
305 | |||
306 | if (!info || !info->hdev) { | ||
307 | BT_ERR("Call of irq %d for unknown device", irq); | ||
308 | return IRQ_NONE; | ||
309 | } | ||
310 | |||
311 | iobase = info->link.io.BasePort1; | ||
312 | |||
313 | spin_lock(&(info->lock)); | ||
314 | |||
315 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; | ||
316 | while (iir) { | ||
317 | |||
318 | /* Clear interrupt */ | ||
319 | lsr = inb(iobase + UART_LSR); | ||
320 | |||
321 | switch (iir) { | ||
322 | case UART_IIR_RLSI: | ||
323 | BT_ERR("RLSI"); | ||
324 | break; | ||
325 | case UART_IIR_RDI: | ||
326 | /* Receive interrupt */ | ||
327 | btuart_receive(info); | ||
328 | break; | ||
329 | case UART_IIR_THRI: | ||
330 | if (lsr & UART_LSR_THRE) { | ||
331 | /* Transmitter ready for data */ | ||
332 | btuart_write_wakeup(info); | ||
333 | } | ||
334 | break; | ||
335 | default: | ||
336 | BT_ERR("Unhandled IIR=%#x", iir); | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | /* Make sure we don't stay here too long */ | ||
341 | if (boguscount++ > 100) | ||
342 | break; | ||
343 | |||
344 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; | ||
345 | |||
346 | } | ||
347 | |||
348 | spin_unlock(&(info->lock)); | ||
349 | |||
350 | return IRQ_HANDLED; | ||
351 | } | ||
352 | |||
353 | |||
354 | static void btuart_change_speed(btuart_info_t *info, unsigned int speed) | ||
355 | { | ||
356 | unsigned long flags; | ||
357 | unsigned int iobase; | ||
358 | int fcr; /* FIFO control reg */ | ||
359 | int lcr; /* Line control reg */ | ||
360 | int divisor; | ||
361 | |||
362 | if (!info) { | ||
363 | BT_ERR("Unknown device"); | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | iobase = info->link.io.BasePort1; | ||
368 | |||
369 | spin_lock_irqsave(&(info->lock), flags); | ||
370 | |||
371 | /* Turn off interrupts */ | ||
372 | outb(0, iobase + UART_IER); | ||
373 | |||
374 | divisor = SPEED_MAX / speed; | ||
375 | |||
376 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT; | ||
377 | |||
378 | /* | ||
379 | * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and | ||
380 | * almost 1,7 ms at 19200 bps. At speeds above that we can just forget | ||
381 | * about this timeout since it will always be fast enough. | ||
382 | */ | ||
383 | |||
384 | if (speed < 38400) | ||
385 | fcr |= UART_FCR_TRIGGER_1; | ||
386 | else | ||
387 | fcr |= UART_FCR_TRIGGER_14; | ||
388 | |||
389 | /* Bluetooth cards use 8N1 */ | ||
390 | lcr = UART_LCR_WLEN8; | ||
391 | |||
392 | outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */ | ||
393 | outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */ | ||
394 | outb(divisor >> 8, iobase + UART_DLM); | ||
395 | outb(lcr, iobase + UART_LCR); /* Set 8N1 */ | ||
396 | outb(fcr, iobase + UART_FCR); /* Enable FIFO's */ | ||
397 | |||
398 | /* Turn on interrups */ | ||
399 | outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); | ||
400 | |||
401 | spin_unlock_irqrestore(&(info->lock), flags); | ||
402 | } | ||
403 | |||
404 | |||
405 | |||
406 | /* ======================== HCI interface ======================== */ | ||
407 | |||
408 | |||
409 | static int btuart_hci_flush(struct hci_dev *hdev) | ||
410 | { | ||
411 | btuart_info_t *info = (btuart_info_t *)(hdev->driver_data); | ||
412 | |||
413 | /* Drop TX queue */ | ||
414 | skb_queue_purge(&(info->txq)); | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | |||
420 | static int btuart_hci_open(struct hci_dev *hdev) | ||
421 | { | ||
422 | set_bit(HCI_RUNNING, &(hdev->flags)); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | |||
428 | static int btuart_hci_close(struct hci_dev *hdev) | ||
429 | { | ||
430 | if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) | ||
431 | return 0; | ||
432 | |||
433 | btuart_hci_flush(hdev); | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | |||
439 | static int btuart_hci_send_frame(struct sk_buff *skb) | ||
440 | { | ||
441 | btuart_info_t *info; | ||
442 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
443 | |||
444 | if (!hdev) { | ||
445 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
446 | return -ENODEV; | ||
447 | } | ||
448 | |||
449 | info = (btuart_info_t *)(hdev->driver_data); | ||
450 | |||
451 | switch (skb->pkt_type) { | ||
452 | case HCI_COMMAND_PKT: | ||
453 | hdev->stat.cmd_tx++; | ||
454 | break; | ||
455 | case HCI_ACLDATA_PKT: | ||
456 | hdev->stat.acl_tx++; | ||
457 | break; | ||
458 | case HCI_SCODATA_PKT: | ||
459 | hdev->stat.sco_tx++; | ||
460 | break; | ||
461 | }; | ||
462 | |||
463 | /* Prepend skb with frame type */ | ||
464 | memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); | ||
465 | skb_queue_tail(&(info->txq), skb); | ||
466 | |||
467 | btuart_write_wakeup(info); | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | |||
473 | static void btuart_hci_destruct(struct hci_dev *hdev) | ||
474 | { | ||
475 | } | ||
476 | |||
477 | |||
478 | static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
479 | { | ||
480 | return -ENOIOCTLCMD; | ||
481 | } | ||
482 | |||
483 | |||
484 | |||
485 | /* ======================== Card services HCI interaction ======================== */ | ||
486 | |||
487 | |||
488 | static int btuart_open(btuart_info_t *info) | ||
489 | { | ||
490 | unsigned long flags; | ||
491 | unsigned int iobase = info->link.io.BasePort1; | ||
492 | struct hci_dev *hdev; | ||
493 | |||
494 | spin_lock_init(&(info->lock)); | ||
495 | |||
496 | skb_queue_head_init(&(info->txq)); | ||
497 | |||
498 | info->rx_state = RECV_WAIT_PACKET_TYPE; | ||
499 | info->rx_count = 0; | ||
500 | info->rx_skb = NULL; | ||
501 | |||
502 | /* Initialize HCI device */ | ||
503 | hdev = hci_alloc_dev(); | ||
504 | if (!hdev) { | ||
505 | BT_ERR("Can't allocate HCI device"); | ||
506 | return -ENOMEM; | ||
507 | } | ||
508 | |||
509 | info->hdev = hdev; | ||
510 | |||
511 | hdev->type = HCI_PCCARD; | ||
512 | hdev->driver_data = info; | ||
513 | |||
514 | hdev->open = btuart_hci_open; | ||
515 | hdev->close = btuart_hci_close; | ||
516 | hdev->flush = btuart_hci_flush; | ||
517 | hdev->send = btuart_hci_send_frame; | ||
518 | hdev->destruct = btuart_hci_destruct; | ||
519 | hdev->ioctl = btuart_hci_ioctl; | ||
520 | |||
521 | hdev->owner = THIS_MODULE; | ||
522 | |||
523 | spin_lock_irqsave(&(info->lock), flags); | ||
524 | |||
525 | /* Reset UART */ | ||
526 | outb(0, iobase + UART_MCR); | ||
527 | |||
528 | /* Turn off interrupts */ | ||
529 | outb(0, iobase + UART_IER); | ||
530 | |||
531 | /* Initialize UART */ | ||
532 | outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ | ||
533 | outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); | ||
534 | |||
535 | /* Turn on interrupts */ | ||
536 | // outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); | ||
537 | |||
538 | spin_unlock_irqrestore(&(info->lock), flags); | ||
539 | |||
540 | btuart_change_speed(info, DEFAULT_BAUD_RATE); | ||
541 | |||
542 | /* Timeout before it is safe to send the first HCI packet */ | ||
543 | msleep(1000); | ||
544 | |||
545 | /* Register HCI device */ | ||
546 | if (hci_register_dev(hdev) < 0) { | ||
547 | BT_ERR("Can't register HCI device"); | ||
548 | info->hdev = NULL; | ||
549 | hci_free_dev(hdev); | ||
550 | return -ENODEV; | ||
551 | } | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | |||
557 | static int btuart_close(btuart_info_t *info) | ||
558 | { | ||
559 | unsigned long flags; | ||
560 | unsigned int iobase = info->link.io.BasePort1; | ||
561 | struct hci_dev *hdev = info->hdev; | ||
562 | |||
563 | if (!hdev) | ||
564 | return -ENODEV; | ||
565 | |||
566 | btuart_hci_close(hdev); | ||
567 | |||
568 | spin_lock_irqsave(&(info->lock), flags); | ||
569 | |||
570 | /* Reset UART */ | ||
571 | outb(0, iobase + UART_MCR); | ||
572 | |||
573 | /* Turn off interrupts */ | ||
574 | outb(0, iobase + UART_IER); | ||
575 | |||
576 | spin_unlock_irqrestore(&(info->lock), flags); | ||
577 | |||
578 | if (hci_unregister_dev(hdev) < 0) | ||
579 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
580 | |||
581 | hci_free_dev(hdev); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static dev_link_t *btuart_attach(void) | ||
587 | { | ||
588 | btuart_info_t *info; | ||
589 | client_reg_t client_reg; | ||
590 | dev_link_t *link; | ||
591 | int ret; | ||
592 | |||
593 | /* Create new info device */ | ||
594 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
595 | if (!info) | ||
596 | return NULL; | ||
597 | memset(info, 0, sizeof(*info)); | ||
598 | |||
599 | link = &info->link; | ||
600 | link->priv = info; | ||
601 | |||
602 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
603 | link->io.NumPorts1 = 8; | ||
604 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
605 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
606 | |||
607 | link->irq.Handler = btuart_interrupt; | ||
608 | link->irq.Instance = info; | ||
609 | |||
610 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
611 | link->conf.Vcc = 50; | ||
612 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
613 | |||
614 | /* Register with Card Services */ | ||
615 | link->next = dev_list; | ||
616 | dev_list = link; | ||
617 | client_reg.dev_info = &dev_info; | ||
618 | client_reg.EventMask = | ||
619 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
620 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
621 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
622 | client_reg.event_handler = &btuart_event; | ||
623 | client_reg.Version = 0x0210; | ||
624 | client_reg.event_callback_args.client_data = link; | ||
625 | |||
626 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
627 | if (ret != CS_SUCCESS) { | ||
628 | cs_error(link->handle, RegisterClient, ret); | ||
629 | btuart_detach(link); | ||
630 | return NULL; | ||
631 | } | ||
632 | |||
633 | return link; | ||
634 | } | ||
635 | |||
636 | |||
637 | static void btuart_detach(dev_link_t *link) | ||
638 | { | ||
639 | btuart_info_t *info = link->priv; | ||
640 | dev_link_t **linkp; | ||
641 | int ret; | ||
642 | |||
643 | /* Locate device structure */ | ||
644 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
645 | if (*linkp == link) | ||
646 | break; | ||
647 | |||
648 | if (*linkp == NULL) | ||
649 | return; | ||
650 | |||
651 | if (link->state & DEV_CONFIG) | ||
652 | btuart_release(link); | ||
653 | |||
654 | if (link->handle) { | ||
655 | ret = pcmcia_deregister_client(link->handle); | ||
656 | if (ret != CS_SUCCESS) | ||
657 | cs_error(link->handle, DeregisterClient, ret); | ||
658 | } | ||
659 | |||
660 | /* Unlink device structure, free bits */ | ||
661 | *linkp = link->next; | ||
662 | |||
663 | kfree(info); | ||
664 | } | ||
665 | |||
666 | static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
667 | { | ||
668 | int i; | ||
669 | |||
670 | i = pcmcia_get_tuple_data(handle, tuple); | ||
671 | if (i != CS_SUCCESS) | ||
672 | return i; | ||
673 | |||
674 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
675 | } | ||
676 | |||
677 | static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
678 | { | ||
679 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) | ||
680 | return CS_NO_MORE_ITEMS; | ||
681 | return get_tuple(handle, tuple, parse); | ||
682 | } | ||
683 | |||
684 | static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
685 | { | ||
686 | if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) | ||
687 | return CS_NO_MORE_ITEMS; | ||
688 | return get_tuple(handle, tuple, parse); | ||
689 | } | ||
690 | |||
691 | static void btuart_config(dev_link_t *link) | ||
692 | { | ||
693 | static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
694 | client_handle_t handle = link->handle; | ||
695 | btuart_info_t *info = link->priv; | ||
696 | tuple_t tuple; | ||
697 | u_short buf[256]; | ||
698 | cisparse_t parse; | ||
699 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
700 | config_info_t config; | ||
701 | int i, j, try, last_ret, last_fn; | ||
702 | |||
703 | tuple.TupleData = (cisdata_t *)buf; | ||
704 | tuple.TupleOffset = 0; | ||
705 | tuple.TupleDataMax = 255; | ||
706 | tuple.Attributes = 0; | ||
707 | |||
708 | /* Get configuration register information */ | ||
709 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
710 | last_ret = first_tuple(handle, &tuple, &parse); | ||
711 | if (last_ret != CS_SUCCESS) { | ||
712 | last_fn = ParseTuple; | ||
713 | goto cs_failed; | ||
714 | } | ||
715 | link->conf.ConfigBase = parse.config.base; | ||
716 | link->conf.Present = parse.config.rmask[0]; | ||
717 | |||
718 | /* Configure card */ | ||
719 | link->state |= DEV_CONFIG; | ||
720 | i = pcmcia_get_configuration_info(handle, &config); | ||
721 | link->conf.Vcc = config.Vcc; | ||
722 | |||
723 | /* First pass: look for a config entry that looks normal. */ | ||
724 | tuple.TupleData = (cisdata_t *) buf; | ||
725 | tuple.TupleOffset = 0; | ||
726 | tuple.TupleDataMax = 255; | ||
727 | tuple.Attributes = 0; | ||
728 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
729 | /* Two tries: without IO aliases, then with aliases */ | ||
730 | for (try = 0; try < 2; try++) { | ||
731 | i = first_tuple(handle, &tuple, &parse); | ||
732 | while (i != CS_NO_MORE_ITEMS) { | ||
733 | if (i != CS_SUCCESS) | ||
734 | goto next_entry; | ||
735 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
736 | link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
737 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { | ||
738 | link->conf.ConfigIndex = cf->index; | ||
739 | link->io.BasePort1 = cf->io.win[0].base; | ||
740 | link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
741 | i = pcmcia_request_io(link->handle, &link->io); | ||
742 | if (i == CS_SUCCESS) | ||
743 | goto found_port; | ||
744 | } | ||
745 | next_entry: | ||
746 | i = next_tuple(handle, &tuple, &parse); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | /* Second pass: try to find an entry that isn't picky about | ||
751 | its base address, then try to grab any standard serial port | ||
752 | address, and finally try to get any free port. */ | ||
753 | i = first_tuple(handle, &tuple, &parse); | ||
754 | while (i != CS_NO_MORE_ITEMS) { | ||
755 | if ((i == CS_SUCCESS) && (cf->io.nwin > 0) | ||
756 | && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
757 | link->conf.ConfigIndex = cf->index; | ||
758 | for (j = 0; j < 5; j++) { | ||
759 | link->io.BasePort1 = base[j]; | ||
760 | link->io.IOAddrLines = base[j] ? 16 : 3; | ||
761 | i = pcmcia_request_io(link->handle, &link->io); | ||
762 | if (i == CS_SUCCESS) | ||
763 | goto found_port; | ||
764 | } | ||
765 | } | ||
766 | i = next_tuple(handle, &tuple, &parse); | ||
767 | } | ||
768 | |||
769 | found_port: | ||
770 | if (i != CS_SUCCESS) { | ||
771 | BT_ERR("No usable port range found"); | ||
772 | cs_error(link->handle, RequestIO, i); | ||
773 | goto failed; | ||
774 | } | ||
775 | |||
776 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
777 | if (i != CS_SUCCESS) { | ||
778 | cs_error(link->handle, RequestIRQ, i); | ||
779 | link->irq.AssignedIRQ = 0; | ||
780 | } | ||
781 | |||
782 | i = pcmcia_request_configuration(link->handle, &link->conf); | ||
783 | if (i != CS_SUCCESS) { | ||
784 | cs_error(link->handle, RequestConfiguration, i); | ||
785 | goto failed; | ||
786 | } | ||
787 | |||
788 | if (btuart_open(info) != 0) | ||
789 | goto failed; | ||
790 | |||
791 | strcpy(info->node.dev_name, info->hdev->name); | ||
792 | link->dev = &info->node; | ||
793 | link->state &= ~DEV_CONFIG_PENDING; | ||
794 | |||
795 | return; | ||
796 | |||
797 | cs_failed: | ||
798 | cs_error(link->handle, last_fn, last_ret); | ||
799 | |||
800 | failed: | ||
801 | btuart_release(link); | ||
802 | } | ||
803 | |||
804 | |||
805 | static void btuart_release(dev_link_t *link) | ||
806 | { | ||
807 | btuart_info_t *info = link->priv; | ||
808 | |||
809 | if (link->state & DEV_PRESENT) | ||
810 | btuart_close(info); | ||
811 | |||
812 | link->dev = NULL; | ||
813 | |||
814 | pcmcia_release_configuration(link->handle); | ||
815 | pcmcia_release_io(link->handle, &link->io); | ||
816 | pcmcia_release_irq(link->handle, &link->irq); | ||
817 | |||
818 | link->state &= ~DEV_CONFIG; | ||
819 | } | ||
820 | |||
821 | |||
822 | static int btuart_event(event_t event, int priority, event_callback_args_t *args) | ||
823 | { | ||
824 | dev_link_t *link = args->client_data; | ||
825 | btuart_info_t *info = link->priv; | ||
826 | |||
827 | switch (event) { | ||
828 | case CS_EVENT_CARD_REMOVAL: | ||
829 | link->state &= ~DEV_PRESENT; | ||
830 | if (link->state & DEV_CONFIG) { | ||
831 | btuart_close(info); | ||
832 | btuart_release(link); | ||
833 | } | ||
834 | break; | ||
835 | case CS_EVENT_CARD_INSERTION: | ||
836 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
837 | btuart_config(link); | ||
838 | break; | ||
839 | case CS_EVENT_PM_SUSPEND: | ||
840 | link->state |= DEV_SUSPEND; | ||
841 | /* Fall through... */ | ||
842 | case CS_EVENT_RESET_PHYSICAL: | ||
843 | if (link->state & DEV_CONFIG) | ||
844 | pcmcia_release_configuration(link->handle); | ||
845 | break; | ||
846 | case CS_EVENT_PM_RESUME: | ||
847 | link->state &= ~DEV_SUSPEND; | ||
848 | /* Fall through... */ | ||
849 | case CS_EVENT_CARD_RESET: | ||
850 | if (DEV_OK(link)) | ||
851 | pcmcia_request_configuration(link->handle, &link->conf); | ||
852 | break; | ||
853 | } | ||
854 | |||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static struct pcmcia_driver btuart_driver = { | ||
859 | .owner = THIS_MODULE, | ||
860 | .drv = { | ||
861 | .name = "btuart_cs", | ||
862 | }, | ||
863 | .attach = btuart_attach, | ||
864 | .detach = btuart_detach, | ||
865 | }; | ||
866 | |||
867 | static int __init init_btuart_cs(void) | ||
868 | { | ||
869 | return pcmcia_register_driver(&btuart_driver); | ||
870 | } | ||
871 | |||
872 | |||
873 | static void __exit exit_btuart_cs(void) | ||
874 | { | ||
875 | pcmcia_unregister_driver(&btuart_driver); | ||
876 | BUG_ON(dev_list != NULL); | ||
877 | } | ||
878 | |||
879 | module_init(init_btuart_cs); | ||
880 | module_exit(exit_btuart_cs); | ||
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c new file mode 100644 index 000000000000..fe954e5d9a1d --- /dev/null +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -0,0 +1,832 @@ | |||
1 | /* | ||
2 | * | ||
3 | * A driver for Nokia Connectivity Card DTL-1 devices | ||
4 | * | ||
5 | * Copyright (C) 2001-2002 Marcel Holtmann <marcel@holtmann.org> | ||
6 | * | ||
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 | * Software distributed under the License is distributed on an "AS | ||
13 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | ||
14 | * implied. See the License for the specific language governing | ||
15 | * rights and limitations under the License. | ||
16 | * | ||
17 | * The initial developer of the original code is David A. Hinds | ||
18 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
19 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/ptrace.h> | ||
34 | #include <linux/ioport.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/moduleparam.h> | ||
37 | |||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/serial.h> | ||
41 | #include <linux/serial_reg.h> | ||
42 | #include <linux/bitops.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/io.h> | ||
45 | |||
46 | #include <pcmcia/version.h> | ||
47 | #include <pcmcia/cs_types.h> | ||
48 | #include <pcmcia/cs.h> | ||
49 | #include <pcmcia/cistpl.h> | ||
50 | #include <pcmcia/ciscode.h> | ||
51 | #include <pcmcia/ds.h> | ||
52 | #include <pcmcia/cisreg.h> | ||
53 | |||
54 | #include <net/bluetooth/bluetooth.h> | ||
55 | #include <net/bluetooth/hci_core.h> | ||
56 | |||
57 | |||
58 | |||
59 | /* ======================== Module parameters ======================== */ | ||
60 | |||
61 | |||
62 | MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | ||
63 | MODULE_DESCRIPTION("Bluetooth driver for Nokia Connectivity Card DTL-1"); | ||
64 | MODULE_LICENSE("GPL"); | ||
65 | |||
66 | |||
67 | |||
68 | /* ======================== Local structures ======================== */ | ||
69 | |||
70 | |||
71 | typedef struct dtl1_info_t { | ||
72 | dev_link_t link; | ||
73 | dev_node_t node; | ||
74 | |||
75 | struct hci_dev *hdev; | ||
76 | |||
77 | spinlock_t lock; /* For serializing operations */ | ||
78 | |||
79 | unsigned long flowmask; /* HCI flow mask */ | ||
80 | int ri_latch; | ||
81 | |||
82 | struct sk_buff_head txq; | ||
83 | unsigned long tx_state; | ||
84 | |||
85 | unsigned long rx_state; | ||
86 | unsigned long rx_count; | ||
87 | struct sk_buff *rx_skb; | ||
88 | } dtl1_info_t; | ||
89 | |||
90 | |||
91 | static void dtl1_config(dev_link_t *link); | ||
92 | static void dtl1_release(dev_link_t *link); | ||
93 | static int dtl1_event(event_t event, int priority, event_callback_args_t *args); | ||
94 | |||
95 | static dev_info_t dev_info = "dtl1_cs"; | ||
96 | |||
97 | static dev_link_t *dtl1_attach(void); | ||
98 | static void dtl1_detach(dev_link_t *); | ||
99 | |||
100 | static dev_link_t *dev_list = NULL; | ||
101 | |||
102 | |||
103 | /* Transmit states */ | ||
104 | #define XMIT_SENDING 1 | ||
105 | #define XMIT_WAKEUP 2 | ||
106 | #define XMIT_WAITING 8 | ||
107 | |||
108 | /* Receiver States */ | ||
109 | #define RECV_WAIT_NSH 0 | ||
110 | #define RECV_WAIT_DATA 1 | ||
111 | |||
112 | |||
113 | typedef struct { | ||
114 | u8 type; | ||
115 | u8 zero; | ||
116 | u16 len; | ||
117 | } __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */ | ||
118 | |||
119 | #define NSHL 4 /* Nokia Specific Header Length */ | ||
120 | |||
121 | |||
122 | |||
123 | /* ======================== Interrupt handling ======================== */ | ||
124 | |||
125 | |||
126 | static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) | ||
127 | { | ||
128 | int actual = 0; | ||
129 | |||
130 | /* Tx FIFO should be empty */ | ||
131 | if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) | ||
132 | return 0; | ||
133 | |||
134 | /* Fill FIFO with current frame */ | ||
135 | while ((fifo_size-- > 0) && (actual < len)) { | ||
136 | /* Transmit next byte */ | ||
137 | outb(buf[actual], iobase + UART_TX); | ||
138 | actual++; | ||
139 | } | ||
140 | |||
141 | return actual; | ||
142 | } | ||
143 | |||
144 | |||
145 | static void dtl1_write_wakeup(dtl1_info_t *info) | ||
146 | { | ||
147 | if (!info) { | ||
148 | BT_ERR("Unknown device"); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | if (test_bit(XMIT_WAITING, &(info->tx_state))) { | ||
153 | set_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) { | ||
158 | set_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | do { | ||
163 | register unsigned int iobase = info->link.io.BasePort1; | ||
164 | register struct sk_buff *skb; | ||
165 | register int len; | ||
166 | |||
167 | clear_bit(XMIT_WAKEUP, &(info->tx_state)); | ||
168 | |||
169 | if (!(info->link.state & DEV_PRESENT)) | ||
170 | return; | ||
171 | |||
172 | if (!(skb = skb_dequeue(&(info->txq)))) | ||
173 | break; | ||
174 | |||
175 | /* Send frame */ | ||
176 | len = dtl1_write(iobase, 32, skb->data, skb->len); | ||
177 | |||
178 | if (len == skb->len) { | ||
179 | set_bit(XMIT_WAITING, &(info->tx_state)); | ||
180 | kfree_skb(skb); | ||
181 | } else { | ||
182 | skb_pull(skb, len); | ||
183 | skb_queue_head(&(info->txq), skb); | ||
184 | } | ||
185 | |||
186 | info->hdev->stat.byte_tx += len; | ||
187 | |||
188 | } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); | ||
189 | |||
190 | clear_bit(XMIT_SENDING, &(info->tx_state)); | ||
191 | } | ||
192 | |||
193 | |||
194 | static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) | ||
195 | { | ||
196 | u8 flowmask = *(u8 *)skb->data; | ||
197 | int i; | ||
198 | |||
199 | printk(KERN_INFO "Bluetooth: Nokia control data ="); | ||
200 | for (i = 0; i < skb->len; i++) { | ||
201 | printk(" %02x", skb->data[i]); | ||
202 | } | ||
203 | printk("\n"); | ||
204 | |||
205 | /* transition to active state */ | ||
206 | if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) { | ||
207 | clear_bit(XMIT_WAITING, &(info->tx_state)); | ||
208 | dtl1_write_wakeup(info); | ||
209 | } | ||
210 | |||
211 | info->flowmask = flowmask; | ||
212 | |||
213 | kfree_skb(skb); | ||
214 | } | ||
215 | |||
216 | |||
217 | static void dtl1_receive(dtl1_info_t *info) | ||
218 | { | ||
219 | unsigned int iobase; | ||
220 | nsh_t *nsh; | ||
221 | int boguscount = 0; | ||
222 | |||
223 | if (!info) { | ||
224 | BT_ERR("Unknown device"); | ||
225 | return; | ||
226 | } | ||
227 | |||
228 | iobase = info->link.io.BasePort1; | ||
229 | |||
230 | do { | ||
231 | info->hdev->stat.byte_rx++; | ||
232 | |||
233 | /* Allocate packet */ | ||
234 | if (info->rx_skb == NULL) | ||
235 | if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { | ||
236 | BT_ERR("Can't allocate mem for new packet"); | ||
237 | info->rx_state = RECV_WAIT_NSH; | ||
238 | info->rx_count = NSHL; | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX); | ||
243 | nsh = (nsh_t *)info->rx_skb->data; | ||
244 | |||
245 | info->rx_count--; | ||
246 | |||
247 | if (info->rx_count == 0) { | ||
248 | |||
249 | switch (info->rx_state) { | ||
250 | case RECV_WAIT_NSH: | ||
251 | info->rx_state = RECV_WAIT_DATA; | ||
252 | info->rx_count = nsh->len + (nsh->len & 0x0001); | ||
253 | break; | ||
254 | case RECV_WAIT_DATA: | ||
255 | info->rx_skb->pkt_type = nsh->type; | ||
256 | |||
257 | /* remove PAD byte if it exists */ | ||
258 | if (nsh->len & 0x0001) { | ||
259 | info->rx_skb->tail--; | ||
260 | info->rx_skb->len--; | ||
261 | } | ||
262 | |||
263 | /* remove NSH */ | ||
264 | skb_pull(info->rx_skb, NSHL); | ||
265 | |||
266 | switch (info->rx_skb->pkt_type) { | ||
267 | case 0x80: | ||
268 | /* control data for the Nokia Card */ | ||
269 | dtl1_control(info, info->rx_skb); | ||
270 | break; | ||
271 | case 0x82: | ||
272 | case 0x83: | ||
273 | case 0x84: | ||
274 | /* send frame to the HCI layer */ | ||
275 | info->rx_skb->dev = (void *) info->hdev; | ||
276 | info->rx_skb->pkt_type &= 0x0f; | ||
277 | hci_recv_frame(info->rx_skb); | ||
278 | break; | ||
279 | default: | ||
280 | /* unknown packet */ | ||
281 | BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); | ||
282 | kfree_skb(info->rx_skb); | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | info->rx_state = RECV_WAIT_NSH; | ||
287 | info->rx_count = NSHL; | ||
288 | info->rx_skb = NULL; | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | } | ||
293 | |||
294 | /* Make sure we don't stay here too long */ | ||
295 | if (boguscount++ > 32) | ||
296 | break; | ||
297 | |||
298 | } while (inb(iobase + UART_LSR) & UART_LSR_DR); | ||
299 | } | ||
300 | |||
301 | |||
302 | static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) | ||
303 | { | ||
304 | dtl1_info_t *info = dev_inst; | ||
305 | unsigned int iobase; | ||
306 | unsigned char msr; | ||
307 | int boguscount = 0; | ||
308 | int iir, lsr; | ||
309 | |||
310 | if (!info || !info->hdev) { | ||
311 | BT_ERR("Call of irq %d for unknown device", irq); | ||
312 | return IRQ_NONE; | ||
313 | } | ||
314 | |||
315 | iobase = info->link.io.BasePort1; | ||
316 | |||
317 | spin_lock(&(info->lock)); | ||
318 | |||
319 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; | ||
320 | while (iir) { | ||
321 | |||
322 | /* Clear interrupt */ | ||
323 | lsr = inb(iobase + UART_LSR); | ||
324 | |||
325 | switch (iir) { | ||
326 | case UART_IIR_RLSI: | ||
327 | BT_ERR("RLSI"); | ||
328 | break; | ||
329 | case UART_IIR_RDI: | ||
330 | /* Receive interrupt */ | ||
331 | dtl1_receive(info); | ||
332 | break; | ||
333 | case UART_IIR_THRI: | ||
334 | if (lsr & UART_LSR_THRE) { | ||
335 | /* Transmitter ready for data */ | ||
336 | dtl1_write_wakeup(info); | ||
337 | } | ||
338 | break; | ||
339 | default: | ||
340 | BT_ERR("Unhandled IIR=%#x", iir); | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | /* Make sure we don't stay here too long */ | ||
345 | if (boguscount++ > 100) | ||
346 | break; | ||
347 | |||
348 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; | ||
349 | |||
350 | } | ||
351 | |||
352 | msr = inb(iobase + UART_MSR); | ||
353 | |||
354 | if (info->ri_latch ^ (msr & UART_MSR_RI)) { | ||
355 | info->ri_latch = msr & UART_MSR_RI; | ||
356 | clear_bit(XMIT_WAITING, &(info->tx_state)); | ||
357 | dtl1_write_wakeup(info); | ||
358 | } | ||
359 | |||
360 | spin_unlock(&(info->lock)); | ||
361 | |||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | |||
366 | |||
367 | /* ======================== HCI interface ======================== */ | ||
368 | |||
369 | |||
370 | static int dtl1_hci_open(struct hci_dev *hdev) | ||
371 | { | ||
372 | set_bit(HCI_RUNNING, &(hdev->flags)); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | |||
378 | static int dtl1_hci_flush(struct hci_dev *hdev) | ||
379 | { | ||
380 | dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data); | ||
381 | |||
382 | /* Drop TX queue */ | ||
383 | skb_queue_purge(&(info->txq)); | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | |||
389 | static int dtl1_hci_close(struct hci_dev *hdev) | ||
390 | { | ||
391 | if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) | ||
392 | return 0; | ||
393 | |||
394 | dtl1_hci_flush(hdev); | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | |||
400 | static int dtl1_hci_send_frame(struct sk_buff *skb) | ||
401 | { | ||
402 | dtl1_info_t *info; | ||
403 | struct hci_dev *hdev = (struct hci_dev *)(skb->dev); | ||
404 | struct sk_buff *s; | ||
405 | nsh_t nsh; | ||
406 | |||
407 | if (!hdev) { | ||
408 | BT_ERR("Frame for unknown HCI device (hdev=NULL)"); | ||
409 | return -ENODEV; | ||
410 | } | ||
411 | |||
412 | info = (dtl1_info_t *)(hdev->driver_data); | ||
413 | |||
414 | switch (skb->pkt_type) { | ||
415 | case HCI_COMMAND_PKT: | ||
416 | hdev->stat.cmd_tx++; | ||
417 | nsh.type = 0x81; | ||
418 | break; | ||
419 | case HCI_ACLDATA_PKT: | ||
420 | hdev->stat.acl_tx++; | ||
421 | nsh.type = 0x82; | ||
422 | break; | ||
423 | case HCI_SCODATA_PKT: | ||
424 | hdev->stat.sco_tx++; | ||
425 | nsh.type = 0x83; | ||
426 | break; | ||
427 | }; | ||
428 | |||
429 | nsh.zero = 0; | ||
430 | nsh.len = skb->len; | ||
431 | |||
432 | s = bt_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC); | ||
433 | skb_reserve(s, NSHL); | ||
434 | memcpy(skb_put(s, skb->len), skb->data, skb->len); | ||
435 | if (skb->len & 0x0001) | ||
436 | *skb_put(s, 1) = 0; /* PAD */ | ||
437 | |||
438 | /* Prepend skb with Nokia frame header and queue */ | ||
439 | memcpy(skb_push(s, NSHL), &nsh, NSHL); | ||
440 | skb_queue_tail(&(info->txq), s); | ||
441 | |||
442 | dtl1_write_wakeup(info); | ||
443 | |||
444 | kfree_skb(skb); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | |||
450 | static void dtl1_hci_destruct(struct hci_dev *hdev) | ||
451 | { | ||
452 | } | ||
453 | |||
454 | |||
455 | static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) | ||
456 | { | ||
457 | return -ENOIOCTLCMD; | ||
458 | } | ||
459 | |||
460 | |||
461 | |||
462 | /* ======================== Card services HCI interaction ======================== */ | ||
463 | |||
464 | |||
465 | static int dtl1_open(dtl1_info_t *info) | ||
466 | { | ||
467 | unsigned long flags; | ||
468 | unsigned int iobase = info->link.io.BasePort1; | ||
469 | struct hci_dev *hdev; | ||
470 | |||
471 | spin_lock_init(&(info->lock)); | ||
472 | |||
473 | skb_queue_head_init(&(info->txq)); | ||
474 | |||
475 | info->rx_state = RECV_WAIT_NSH; | ||
476 | info->rx_count = NSHL; | ||
477 | info->rx_skb = NULL; | ||
478 | |||
479 | set_bit(XMIT_WAITING, &(info->tx_state)); | ||
480 | |||
481 | /* Initialize HCI device */ | ||
482 | hdev = hci_alloc_dev(); | ||
483 | if (!hdev) { | ||
484 | BT_ERR("Can't allocate HCI device"); | ||
485 | return -ENOMEM; | ||
486 | } | ||
487 | |||
488 | info->hdev = hdev; | ||
489 | |||
490 | hdev->type = HCI_PCCARD; | ||
491 | hdev->driver_data = info; | ||
492 | |||
493 | hdev->open = dtl1_hci_open; | ||
494 | hdev->close = dtl1_hci_close; | ||
495 | hdev->flush = dtl1_hci_flush; | ||
496 | hdev->send = dtl1_hci_send_frame; | ||
497 | hdev->destruct = dtl1_hci_destruct; | ||
498 | hdev->ioctl = dtl1_hci_ioctl; | ||
499 | |||
500 | hdev->owner = THIS_MODULE; | ||
501 | |||
502 | spin_lock_irqsave(&(info->lock), flags); | ||
503 | |||
504 | /* Reset UART */ | ||
505 | outb(0, iobase + UART_MCR); | ||
506 | |||
507 | /* Turn off interrupts */ | ||
508 | outb(0, iobase + UART_IER); | ||
509 | |||
510 | /* Initialize UART */ | ||
511 | outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ | ||
512 | outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); | ||
513 | |||
514 | info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; | ||
515 | |||
516 | /* Turn on interrupts */ | ||
517 | outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); | ||
518 | |||
519 | spin_unlock_irqrestore(&(info->lock), flags); | ||
520 | |||
521 | /* Timeout before it is safe to send the first HCI packet */ | ||
522 | msleep(2000); | ||
523 | |||
524 | /* Register HCI device */ | ||
525 | if (hci_register_dev(hdev) < 0) { | ||
526 | BT_ERR("Can't register HCI device"); | ||
527 | info->hdev = NULL; | ||
528 | hci_free_dev(hdev); | ||
529 | return -ENODEV; | ||
530 | } | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | |||
536 | static int dtl1_close(dtl1_info_t *info) | ||
537 | { | ||
538 | unsigned long flags; | ||
539 | unsigned int iobase = info->link.io.BasePort1; | ||
540 | struct hci_dev *hdev = info->hdev; | ||
541 | |||
542 | if (!hdev) | ||
543 | return -ENODEV; | ||
544 | |||
545 | dtl1_hci_close(hdev); | ||
546 | |||
547 | spin_lock_irqsave(&(info->lock), flags); | ||
548 | |||
549 | /* Reset UART */ | ||
550 | outb(0, iobase + UART_MCR); | ||
551 | |||
552 | /* Turn off interrupts */ | ||
553 | outb(0, iobase + UART_IER); | ||
554 | |||
555 | spin_unlock_irqrestore(&(info->lock), flags); | ||
556 | |||
557 | if (hci_unregister_dev(hdev) < 0) | ||
558 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
559 | |||
560 | hci_free_dev(hdev); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static dev_link_t *dtl1_attach(void) | ||
566 | { | ||
567 | dtl1_info_t *info; | ||
568 | client_reg_t client_reg; | ||
569 | dev_link_t *link; | ||
570 | int ret; | ||
571 | |||
572 | /* Create new info device */ | ||
573 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
574 | if (!info) | ||
575 | return NULL; | ||
576 | memset(info, 0, sizeof(*info)); | ||
577 | |||
578 | link = &info->link; | ||
579 | link->priv = info; | ||
580 | |||
581 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
582 | link->io.NumPorts1 = 8; | ||
583 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
584 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
585 | |||
586 | link->irq.Handler = dtl1_interrupt; | ||
587 | link->irq.Instance = info; | ||
588 | |||
589 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
590 | link->conf.Vcc = 50; | ||
591 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
592 | |||
593 | /* Register with Card Services */ | ||
594 | link->next = dev_list; | ||
595 | dev_list = link; | ||
596 | client_reg.dev_info = &dev_info; | ||
597 | client_reg.EventMask = | ||
598 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | | ||
599 | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | | ||
600 | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; | ||
601 | client_reg.event_handler = &dtl1_event; | ||
602 | client_reg.Version = 0x0210; | ||
603 | client_reg.event_callback_args.client_data = link; | ||
604 | |||
605 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
606 | if (ret != CS_SUCCESS) { | ||
607 | cs_error(link->handle, RegisterClient, ret); | ||
608 | dtl1_detach(link); | ||
609 | return NULL; | ||
610 | } | ||
611 | |||
612 | return link; | ||
613 | } | ||
614 | |||
615 | |||
616 | static void dtl1_detach(dev_link_t *link) | ||
617 | { | ||
618 | dtl1_info_t *info = link->priv; | ||
619 | dev_link_t **linkp; | ||
620 | int ret; | ||
621 | |||
622 | /* Locate device structure */ | ||
623 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
624 | if (*linkp == link) | ||
625 | break; | ||
626 | |||
627 | if (*linkp == NULL) | ||
628 | return; | ||
629 | |||
630 | if (link->state & DEV_CONFIG) | ||
631 | dtl1_release(link); | ||
632 | |||
633 | if (link->handle) { | ||
634 | ret = pcmcia_deregister_client(link->handle); | ||
635 | if (ret != CS_SUCCESS) | ||
636 | cs_error(link->handle, DeregisterClient, ret); | ||
637 | } | ||
638 | |||
639 | /* Unlink device structure, free bits */ | ||
640 | *linkp = link->next; | ||
641 | |||
642 | kfree(info); | ||
643 | } | ||
644 | |||
645 | static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
646 | { | ||
647 | int i; | ||
648 | |||
649 | i = pcmcia_get_tuple_data(handle, tuple); | ||
650 | if (i != CS_SUCCESS) | ||
651 | return i; | ||
652 | |||
653 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
654 | } | ||
655 | |||
656 | static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
657 | { | ||
658 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) | ||
659 | return CS_NO_MORE_ITEMS; | ||
660 | return get_tuple(handle, tuple, parse); | ||
661 | } | ||
662 | |||
663 | static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | ||
664 | { | ||
665 | if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) | ||
666 | return CS_NO_MORE_ITEMS; | ||
667 | return get_tuple(handle, tuple, parse); | ||
668 | } | ||
669 | |||
670 | static void dtl1_config(dev_link_t *link) | ||
671 | { | ||
672 | client_handle_t handle = link->handle; | ||
673 | dtl1_info_t *info = link->priv; | ||
674 | tuple_t tuple; | ||
675 | u_short buf[256]; | ||
676 | cisparse_t parse; | ||
677 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | ||
678 | config_info_t config; | ||
679 | int i, last_ret, last_fn; | ||
680 | |||
681 | tuple.TupleData = (cisdata_t *)buf; | ||
682 | tuple.TupleOffset = 0; | ||
683 | tuple.TupleDataMax = 255; | ||
684 | tuple.Attributes = 0; | ||
685 | |||
686 | /* Get configuration register information */ | ||
687 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
688 | last_ret = first_tuple(handle, &tuple, &parse); | ||
689 | if (last_ret != CS_SUCCESS) { | ||
690 | last_fn = ParseTuple; | ||
691 | goto cs_failed; | ||
692 | } | ||
693 | link->conf.ConfigBase = parse.config.base; | ||
694 | link->conf.Present = parse.config.rmask[0]; | ||
695 | |||
696 | /* Configure card */ | ||
697 | link->state |= DEV_CONFIG; | ||
698 | i = pcmcia_get_configuration_info(handle, &config); | ||
699 | link->conf.Vcc = config.Vcc; | ||
700 | |||
701 | tuple.TupleData = (cisdata_t *)buf; | ||
702 | tuple.TupleOffset = 0; | ||
703 | tuple.TupleDataMax = 255; | ||
704 | tuple.Attributes = 0; | ||
705 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
706 | |||
707 | /* Look for a generic full-sized window */ | ||
708 | link->io.NumPorts1 = 8; | ||
709 | i = first_tuple(handle, &tuple, &parse); | ||
710 | while (i != CS_NO_MORE_ITEMS) { | ||
711 | if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { | ||
712 | link->conf.ConfigIndex = cf->index; | ||
713 | link->io.BasePort1 = cf->io.win[0].base; | ||
714 | link->io.NumPorts1 = cf->io.win[0].len; /*yo */ | ||
715 | link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; | ||
716 | i = pcmcia_request_io(link->handle, &link->io); | ||
717 | if (i == CS_SUCCESS) | ||
718 | break; | ||
719 | } | ||
720 | i = next_tuple(handle, &tuple, &parse); | ||
721 | } | ||
722 | |||
723 | if (i != CS_SUCCESS) { | ||
724 | cs_error(link->handle, RequestIO, i); | ||
725 | goto failed; | ||
726 | } | ||
727 | |||
728 | i = pcmcia_request_irq(link->handle, &link->irq); | ||
729 | if (i != CS_SUCCESS) { | ||
730 | cs_error(link->handle, RequestIRQ, i); | ||
731 | link->irq.AssignedIRQ = 0; | ||
732 | } | ||
733 | |||
734 | i = pcmcia_request_configuration(link->handle, &link->conf); | ||
735 | if (i != CS_SUCCESS) { | ||
736 | cs_error(link->handle, RequestConfiguration, i); | ||
737 | goto failed; | ||
738 | } | ||
739 | |||
740 | if (dtl1_open(info) != 0) | ||
741 | goto failed; | ||
742 | |||
743 | strcpy(info->node.dev_name, info->hdev->name); | ||
744 | link->dev = &info->node; | ||
745 | link->state &= ~DEV_CONFIG_PENDING; | ||
746 | |||
747 | return; | ||
748 | |||
749 | cs_failed: | ||
750 | cs_error(link->handle, last_fn, last_ret); | ||
751 | |||
752 | failed: | ||
753 | dtl1_release(link); | ||
754 | } | ||
755 | |||
756 | |||
757 | static void dtl1_release(dev_link_t *link) | ||
758 | { | ||
759 | dtl1_info_t *info = link->priv; | ||
760 | |||
761 | if (link->state & DEV_PRESENT) | ||
762 | dtl1_close(info); | ||
763 | |||
764 | link->dev = NULL; | ||
765 | |||
766 | pcmcia_release_configuration(link->handle); | ||
767 | pcmcia_release_io(link->handle, &link->io); | ||
768 | pcmcia_release_irq(link->handle, &link->irq); | ||
769 | |||
770 | link->state &= ~DEV_CONFIG; | ||
771 | } | ||
772 | |||
773 | |||
774 | static int dtl1_event(event_t event, int priority, event_callback_args_t *args) | ||
775 | { | ||
776 | dev_link_t *link = args->client_data; | ||
777 | dtl1_info_t *info = link->priv; | ||
778 | |||
779 | switch (event) { | ||
780 | case CS_EVENT_CARD_REMOVAL: | ||
781 | link->state &= ~DEV_PRESENT; | ||
782 | if (link->state & DEV_CONFIG) { | ||
783 | dtl1_close(info); | ||
784 | dtl1_release(link); | ||
785 | } | ||
786 | break; | ||
787 | case CS_EVENT_CARD_INSERTION: | ||
788 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
789 | dtl1_config(link); | ||
790 | break; | ||
791 | case CS_EVENT_PM_SUSPEND: | ||
792 | link->state |= DEV_SUSPEND; | ||
793 | /* Fall through... */ | ||
794 | case CS_EVENT_RESET_PHYSICAL: | ||
795 | if (link->state & DEV_CONFIG) | ||
796 | pcmcia_release_configuration(link->handle); | ||
797 | break; | ||
798 | case CS_EVENT_PM_RESUME: | ||
799 | link->state &= ~DEV_SUSPEND; | ||
800 | /* Fall through... */ | ||
801 | case CS_EVENT_CARD_RESET: | ||
802 | if (DEV_OK(link)) | ||
803 | pcmcia_request_configuration(link->handle, &link->conf); | ||
804 | break; | ||
805 | } | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static struct pcmcia_driver dtl1_driver = { | ||
811 | .owner = THIS_MODULE, | ||
812 | .drv = { | ||
813 | .name = "dtl1_cs", | ||
814 | }, | ||
815 | .attach = dtl1_attach, | ||
816 | .detach = dtl1_detach, | ||
817 | }; | ||
818 | |||
819 | static int __init init_dtl1_cs(void) | ||
820 | { | ||
821 | return pcmcia_register_driver(&dtl1_driver); | ||
822 | } | ||
823 | |||
824 | |||
825 | static void __exit exit_dtl1_cs(void) | ||
826 | { | ||
827 | pcmcia_unregister_driver(&dtl1_driver); | ||
828 | BUG_ON(dev_list != NULL); | ||
829 | } | ||
830 | |||
831 | module_init(init_dtl1_cs); | ||
832 | module_exit(exit_dtl1_cs); | ||
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c new file mode 100644 index 000000000000..c0ed213fc857 --- /dev/null +++ b/drivers/bluetooth/hci_bcsp.c | |||
@@ -0,0 +1,749 @@ | |||
1 | /* | ||
2 | BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ). | ||
3 | Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com> | ||
4 | |||
5 | Based on | ||
6 | hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com> | ||
7 | ABCSP by Carl Orsborn <cjo@csr.com> | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License version 2 as | ||
11 | published by the Free Software Foundation; | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
14 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
16 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
17 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
18 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
19 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
20 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
21 | |||
22 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
23 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
24 | SOFTWARE IS DISCLAIMED. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $ | ||
29 | */ | ||
30 | |||
31 | #define VERSION "0.2" | ||
32 | |||
33 | #include <linux/config.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/fcntl.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/ptrace.h> | ||
43 | #include <linux/poll.h> | ||
44 | |||
45 | #include <linux/slab.h> | ||
46 | #include <linux/tty.h> | ||
47 | #include <linux/errno.h> | ||
48 | #include <linux/string.h> | ||
49 | #include <linux/signal.h> | ||
50 | #include <linux/ioctl.h> | ||
51 | #include <linux/skbuff.h> | ||
52 | |||
53 | #include <net/bluetooth/bluetooth.h> | ||
54 | #include <net/bluetooth/hci_core.h> | ||
55 | #include "hci_uart.h" | ||
56 | #include "hci_bcsp.h" | ||
57 | |||
58 | #ifndef CONFIG_BT_HCIUART_DEBUG | ||
59 | #undef BT_DBG | ||
60 | #define BT_DBG( A... ) | ||
61 | #undef BT_DMP | ||
62 | #define BT_DMP( A... ) | ||
63 | #endif | ||
64 | |||
65 | static int hciextn = 1; | ||
66 | |||
67 | /* ---- BCSP CRC calculation ---- */ | ||
68 | |||
69 | /* Table for calculating CRC for polynomial 0x1021, LSB processed first, | ||
70 | initial value 0xffff, bits shifted in reverse order. */ | ||
71 | |||
72 | static const u16 crc_table[] = { | ||
73 | 0x0000, 0x1081, 0x2102, 0x3183, | ||
74 | 0x4204, 0x5285, 0x6306, 0x7387, | ||
75 | 0x8408, 0x9489, 0xa50a, 0xb58b, | ||
76 | 0xc60c, 0xd68d, 0xe70e, 0xf78f | ||
77 | }; | ||
78 | |||
79 | /* Initialise the crc calculator */ | ||
80 | #define BCSP_CRC_INIT(x) x = 0xffff | ||
81 | |||
82 | /* | ||
83 | Update crc with next data byte | ||
84 | |||
85 | Implementation note | ||
86 | The data byte is treated as two nibbles. The crc is generated | ||
87 | in reverse, i.e., bits are fed into the register from the top. | ||
88 | */ | ||
89 | static void bcsp_crc_update(u16 *crc, u8 d) | ||
90 | { | ||
91 | u16 reg = *crc; | ||
92 | |||
93 | reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f]; | ||
94 | reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f]; | ||
95 | |||
96 | *crc = reg; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | Get reverse of generated crc | ||
101 | |||
102 | Implementation note | ||
103 | The crc generator (bcsp_crc_init() and bcsp_crc_update()) | ||
104 | creates a reversed crc, so it needs to be swapped back before | ||
105 | being passed on. | ||
106 | */ | ||
107 | static u16 bcsp_crc_reverse(u16 crc) | ||
108 | { | ||
109 | u16 b, rev; | ||
110 | |||
111 | for (b = 0, rev = 0; b < 16; b++) { | ||
112 | rev = rev << 1; | ||
113 | rev |= (crc & 1); | ||
114 | crc = crc >> 1; | ||
115 | } | ||
116 | return (rev); | ||
117 | } | ||
118 | |||
119 | /* ---- BCSP core ---- */ | ||
120 | |||
121 | static void bcsp_slip_msgdelim(struct sk_buff *skb) | ||
122 | { | ||
123 | const char pkt_delim = 0xc0; | ||
124 | memcpy(skb_put(skb, 1), &pkt_delim, 1); | ||
125 | } | ||
126 | |||
127 | static void bcsp_slip_one_byte(struct sk_buff *skb, u8 c) | ||
128 | { | ||
129 | const char esc_c0[2] = { 0xdb, 0xdc }; | ||
130 | const char esc_db[2] = { 0xdb, 0xdd }; | ||
131 | |||
132 | switch (c) { | ||
133 | case 0xc0: | ||
134 | memcpy(skb_put(skb, 2), &esc_c0, 2); | ||
135 | break; | ||
136 | case 0xdb: | ||
137 | memcpy(skb_put(skb, 2), &esc_db, 2); | ||
138 | break; | ||
139 | default: | ||
140 | memcpy(skb_put(skb, 1), &c, 1); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb) | ||
145 | { | ||
146 | struct bcsp_struct *bcsp = hu->priv; | ||
147 | |||
148 | if (skb->len > 0xFFF) { | ||
149 | BT_ERR("Packet too long"); | ||
150 | kfree_skb(skb); | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | switch (skb->pkt_type) { | ||
155 | case HCI_ACLDATA_PKT: | ||
156 | case HCI_COMMAND_PKT: | ||
157 | skb_queue_tail(&bcsp->rel, skb); | ||
158 | break; | ||
159 | |||
160 | case HCI_SCODATA_PKT: | ||
161 | skb_queue_tail(&bcsp->unrel, skb); | ||
162 | break; | ||
163 | |||
164 | default: | ||
165 | BT_ERR("Unknown packet type"); | ||
166 | kfree_skb(skb); | ||
167 | break; | ||
168 | } | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, | ||
174 | int len, int pkt_type) | ||
175 | { | ||
176 | struct sk_buff *nskb; | ||
177 | u8 hdr[4], chan; | ||
178 | int rel, i; | ||
179 | |||
180 | #ifdef CONFIG_BT_HCIUART_BCSP_TXCRC | ||
181 | u16 BCSP_CRC_INIT(bcsp_txmsg_crc); | ||
182 | #endif | ||
183 | |||
184 | switch (pkt_type) { | ||
185 | case HCI_ACLDATA_PKT: | ||
186 | chan = 6; /* BCSP ACL channel */ | ||
187 | rel = 1; /* reliable channel */ | ||
188 | break; | ||
189 | case HCI_COMMAND_PKT: | ||
190 | chan = 5; /* BCSP cmd/evt channel */ | ||
191 | rel = 1; /* reliable channel */ | ||
192 | break; | ||
193 | case HCI_SCODATA_PKT: | ||
194 | chan = 7; /* BCSP SCO channel */ | ||
195 | rel = 0; /* unreliable channel */ | ||
196 | break; | ||
197 | case BCSP_LE_PKT: | ||
198 | chan = 1; /* BCSP LE channel */ | ||
199 | rel = 0; /* unreliable channel */ | ||
200 | break; | ||
201 | case BCSP_ACK_PKT: | ||
202 | chan = 0; /* BCSP internal channel */ | ||
203 | rel = 0; /* unreliable channel */ | ||
204 | break; | ||
205 | default: | ||
206 | BT_ERR("Unknown packet type"); | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | if (hciextn && chan == 5) { | ||
211 | struct hci_command_hdr *hdr = (struct hci_command_hdr *) data; | ||
212 | |||
213 | if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == OGF_VENDOR_CMD) { | ||
214 | u8 desc = *(data + HCI_COMMAND_HDR_SIZE); | ||
215 | if ((desc & 0xf0) == 0xc0) { | ||
216 | data += HCI_COMMAND_HDR_SIZE + 1; | ||
217 | len -= HCI_COMMAND_HDR_SIZE + 1; | ||
218 | chan = desc & 0x0f; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2 | ||
224 | (because bytes 0xc0 and 0xdb are escaped, worst case is | ||
225 | when the packet is all made of 0xc0 and 0xdb :) ) | ||
226 | + 2 (0xc0 delimiters at start and end). */ | ||
227 | |||
228 | nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC); | ||
229 | if (!nskb) | ||
230 | return NULL; | ||
231 | |||
232 | nskb->pkt_type = pkt_type; | ||
233 | |||
234 | bcsp_slip_msgdelim(nskb); | ||
235 | |||
236 | hdr[0] = bcsp->rxseq_txack << 3; | ||
237 | bcsp->txack_req = 0; | ||
238 | BT_DBG("We request packet no %u to card", bcsp->rxseq_txack); | ||
239 | |||
240 | if (rel) { | ||
241 | hdr[0] |= 0x80 + bcsp->msgq_txseq; | ||
242 | BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq); | ||
243 | bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07; | ||
244 | } | ||
245 | #ifdef CONFIG_BT_HCIUART_BCSP_TXCRC | ||
246 | hdr[0] |= 0x40; | ||
247 | #endif | ||
248 | |||
249 | hdr[1] = ((len << 4) & 0xff) | chan; | ||
250 | hdr[2] = len >> 4; | ||
251 | hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]); | ||
252 | |||
253 | /* Put BCSP header */ | ||
254 | for (i = 0; i < 4; i++) { | ||
255 | bcsp_slip_one_byte(nskb, hdr[i]); | ||
256 | #ifdef CONFIG_BT_HCIUART_BCSP_TXCRC | ||
257 | bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]); | ||
258 | #endif | ||
259 | } | ||
260 | |||
261 | /* Put payload */ | ||
262 | for (i = 0; i < len; i++) { | ||
263 | bcsp_slip_one_byte(nskb, data[i]); | ||
264 | #ifdef CONFIG_BT_HCIUART_BCSP_TXCRC | ||
265 | bcsp_crc_update(&bcsp_txmsg_crc, data[i]); | ||
266 | #endif | ||
267 | } | ||
268 | |||
269 | #ifdef CONFIG_BT_HCIUART_BCSP_TXCRC | ||
270 | /* Put CRC */ | ||
271 | bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc); | ||
272 | bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff)); | ||
273 | bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff)); | ||
274 | #endif | ||
275 | |||
276 | bcsp_slip_msgdelim(nskb); | ||
277 | return nskb; | ||
278 | } | ||
279 | |||
280 | /* This is a rewrite of pkt_avail in ABCSP */ | ||
281 | static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) | ||
282 | { | ||
283 | struct bcsp_struct *bcsp = hu->priv; | ||
284 | unsigned long flags; | ||
285 | struct sk_buff *skb; | ||
286 | |||
287 | /* First of all, check for unreliable messages in the queue, | ||
288 | since they have priority */ | ||
289 | |||
290 | if ((skb = skb_dequeue(&bcsp->unrel)) != NULL) { | ||
291 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type); | ||
292 | if (nskb) { | ||
293 | kfree_skb(skb); | ||
294 | return nskb; | ||
295 | } else { | ||
296 | skb_queue_head(&bcsp->unrel, skb); | ||
297 | BT_ERR("Could not dequeue pkt because alloc_skb failed"); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* Now, try to send a reliable pkt. We can only send a | ||
302 | reliable packet if the number of packets sent but not yet ack'ed | ||
303 | is < than the winsize */ | ||
304 | |||
305 | spin_lock_irqsave(&bcsp->unack.lock, flags); | ||
306 | |||
307 | if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) { | ||
308 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, skb->pkt_type); | ||
309 | if (nskb) { | ||
310 | __skb_queue_tail(&bcsp->unack, skb); | ||
311 | mod_timer(&bcsp->tbcsp, jiffies + HZ / 4); | ||
312 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); | ||
313 | return nskb; | ||
314 | } else { | ||
315 | skb_queue_head(&bcsp->rel, skb); | ||
316 | BT_ERR("Could not dequeue pkt because alloc_skb failed"); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); | ||
321 | |||
322 | |||
323 | /* We could not send a reliable packet, either because there are | ||
324 | none or because there are too many unack'ed pkts. Did we receive | ||
325 | any packets we have not acknowledged yet ? */ | ||
326 | |||
327 | if (bcsp->txack_req) { | ||
328 | /* if so, craft an empty ACK pkt and send it on BCSP unreliable | ||
329 | channel 0 */ | ||
330 | struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT); | ||
331 | return nskb; | ||
332 | } | ||
333 | |||
334 | /* We have nothing to send */ | ||
335 | return NULL; | ||
336 | } | ||
337 | |||
338 | static int bcsp_flush(struct hci_uart *hu) | ||
339 | { | ||
340 | BT_DBG("hu %p", hu); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | /* Remove ack'ed packets */ | ||
345 | static void bcsp_pkt_cull(struct bcsp_struct *bcsp) | ||
346 | { | ||
347 | unsigned long flags; | ||
348 | struct sk_buff *skb; | ||
349 | int i, pkts_to_be_removed; | ||
350 | u8 seqno; | ||
351 | |||
352 | spin_lock_irqsave(&bcsp->unack.lock, flags); | ||
353 | |||
354 | pkts_to_be_removed = bcsp->unack.qlen; | ||
355 | seqno = bcsp->msgq_txseq; | ||
356 | |||
357 | while (pkts_to_be_removed) { | ||
358 | if (bcsp->rxack == seqno) | ||
359 | break; | ||
360 | pkts_to_be_removed--; | ||
361 | seqno = (seqno - 1) & 0x07; | ||
362 | } | ||
363 | |||
364 | if (bcsp->rxack != seqno) | ||
365 | BT_ERR("Peer acked invalid packet"); | ||
366 | |||
367 | BT_DBG("Removing %u pkts out of %u, up to seqno %u", | ||
368 | pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07); | ||
369 | |||
370 | for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed | ||
371 | && skb != (struct sk_buff *) &bcsp->unack; i++) { | ||
372 | struct sk_buff *nskb; | ||
373 | |||
374 | nskb = skb->next; | ||
375 | __skb_unlink(skb, &bcsp->unack); | ||
376 | kfree_skb(skb); | ||
377 | skb = nskb; | ||
378 | } | ||
379 | if (bcsp->unack.qlen == 0) | ||
380 | del_timer(&bcsp->tbcsp); | ||
381 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); | ||
382 | |||
383 | if (i != pkts_to_be_removed) | ||
384 | BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed); | ||
385 | } | ||
386 | |||
387 | /* Handle BCSP link-establishment packets. When we | ||
388 | detect a "sync" packet, symptom that the BT module has reset, | ||
389 | we do nothing :) (yet) */ | ||
390 | static void bcsp_handle_le_pkt(struct hci_uart *hu) | ||
391 | { | ||
392 | struct bcsp_struct *bcsp = hu->priv; | ||
393 | u8 conf_pkt[4] = { 0xad, 0xef, 0xac, 0xed }; | ||
394 | u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 }; | ||
395 | u8 sync_pkt[4] = { 0xda, 0xdc, 0xed, 0xed }; | ||
396 | |||
397 | /* spot "conf" pkts and reply with a "conf rsp" pkt */ | ||
398 | if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 && | ||
399 | !memcmp(&bcsp->rx_skb->data[4], conf_pkt, 4)) { | ||
400 | struct sk_buff *nskb = alloc_skb(4, GFP_ATOMIC); | ||
401 | |||
402 | BT_DBG("Found a LE conf pkt"); | ||
403 | if (!nskb) | ||
404 | return; | ||
405 | memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4); | ||
406 | nskb->pkt_type = BCSP_LE_PKT; | ||
407 | |||
408 | skb_queue_head(&bcsp->unrel, nskb); | ||
409 | hci_uart_tx_wakeup(hu); | ||
410 | } | ||
411 | /* Spot "sync" pkts. If we find one...disaster! */ | ||
412 | else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 && | ||
413 | !memcmp(&bcsp->rx_skb->data[4], sync_pkt, 4)) { | ||
414 | BT_ERR("Found a LE sync pkt, card has reset"); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char byte) | ||
419 | { | ||
420 | const u8 c0 = 0xc0, db = 0xdb; | ||
421 | |||
422 | switch (bcsp->rx_esc_state) { | ||
423 | case BCSP_ESCSTATE_NOESC: | ||
424 | switch (byte) { | ||
425 | case 0xdb: | ||
426 | bcsp->rx_esc_state = BCSP_ESCSTATE_ESC; | ||
427 | break; | ||
428 | default: | ||
429 | memcpy(skb_put(bcsp->rx_skb, 1), &byte, 1); | ||
430 | if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && | ||
431 | bcsp->rx_state != BCSP_W4_CRC) | ||
432 | bcsp_crc_update(&bcsp->message_crc, byte); | ||
433 | bcsp->rx_count--; | ||
434 | } | ||
435 | break; | ||
436 | |||
437 | case BCSP_ESCSTATE_ESC: | ||
438 | switch (byte) { | ||
439 | case 0xdc: | ||
440 | memcpy(skb_put(bcsp->rx_skb, 1), &c0, 1); | ||
441 | if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && | ||
442 | bcsp->rx_state != BCSP_W4_CRC) | ||
443 | bcsp_crc_update(&bcsp-> message_crc, 0xc0); | ||
444 | bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; | ||
445 | bcsp->rx_count--; | ||
446 | break; | ||
447 | |||
448 | case 0xdd: | ||
449 | memcpy(skb_put(bcsp->rx_skb, 1), &db, 1); | ||
450 | if ((bcsp->rx_skb-> data[0] & 0x40) != 0 && | ||
451 | bcsp->rx_state != BCSP_W4_CRC) | ||
452 | bcsp_crc_update(&bcsp-> message_crc, 0xdb); | ||
453 | bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; | ||
454 | bcsp->rx_count--; | ||
455 | break; | ||
456 | |||
457 | default: | ||
458 | BT_ERR ("Invalid byte %02x after esc byte", byte); | ||
459 | kfree_skb(bcsp->rx_skb); | ||
460 | bcsp->rx_skb = NULL; | ||
461 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
462 | bcsp->rx_count = 0; | ||
463 | } | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) | ||
468 | { | ||
469 | struct bcsp_struct *bcsp = hu->priv; | ||
470 | int pass_up; | ||
471 | |||
472 | if (bcsp->rx_skb->data[0] & 0x80) { /* reliable pkt */ | ||
473 | BT_DBG("Received seqno %u from card", bcsp->rxseq_txack); | ||
474 | bcsp->rxseq_txack++; | ||
475 | bcsp->rxseq_txack %= 0x8; | ||
476 | bcsp->txack_req = 1; | ||
477 | |||
478 | /* If needed, transmit an ack pkt */ | ||
479 | hci_uart_tx_wakeup(hu); | ||
480 | } | ||
481 | |||
482 | bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07; | ||
483 | BT_DBG("Request for pkt %u from card", bcsp->rxack); | ||
484 | |||
485 | bcsp_pkt_cull(bcsp); | ||
486 | if ((bcsp->rx_skb->data[1] & 0x0f) == 6 && | ||
487 | bcsp->rx_skb->data[0] & 0x80) { | ||
488 | bcsp->rx_skb->pkt_type = HCI_ACLDATA_PKT; | ||
489 | pass_up = 1; | ||
490 | } else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 && | ||
491 | bcsp->rx_skb->data[0] & 0x80) { | ||
492 | bcsp->rx_skb->pkt_type = HCI_EVENT_PKT; | ||
493 | pass_up = 1; | ||
494 | } else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) { | ||
495 | bcsp->rx_skb->pkt_type = HCI_SCODATA_PKT; | ||
496 | pass_up = 1; | ||
497 | } else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 && | ||
498 | !(bcsp->rx_skb->data[0] & 0x80)) { | ||
499 | bcsp_handle_le_pkt(hu); | ||
500 | pass_up = 0; | ||
501 | } else | ||
502 | pass_up = 0; | ||
503 | |||
504 | if (!pass_up) { | ||
505 | struct hci_event_hdr hdr; | ||
506 | u8 desc = (bcsp->rx_skb->data[1] & 0x0f); | ||
507 | |||
508 | if (desc != 0 && desc != 1) { | ||
509 | if (hciextn) { | ||
510 | desc |= 0xc0; | ||
511 | skb_pull(bcsp->rx_skb, 4); | ||
512 | memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1); | ||
513 | |||
514 | hdr.evt = 0xff; | ||
515 | hdr.plen = bcsp->rx_skb->len; | ||
516 | memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE); | ||
517 | bcsp->rx_skb->pkt_type = HCI_EVENT_PKT; | ||
518 | |||
519 | hci_recv_frame(bcsp->rx_skb); | ||
520 | } else { | ||
521 | BT_ERR ("Packet for unknown channel (%u %s)", | ||
522 | bcsp->rx_skb->data[1] & 0x0f, | ||
523 | bcsp->rx_skb->data[0] & 0x80 ? | ||
524 | "reliable" : "unreliable"); | ||
525 | kfree_skb(bcsp->rx_skb); | ||
526 | } | ||
527 | } else | ||
528 | kfree_skb(bcsp->rx_skb); | ||
529 | } else { | ||
530 | /* Pull out BCSP hdr */ | ||
531 | skb_pull(bcsp->rx_skb, 4); | ||
532 | |||
533 | hci_recv_frame(bcsp->rx_skb); | ||
534 | } | ||
535 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
536 | bcsp->rx_skb = NULL; | ||
537 | } | ||
538 | |||
539 | /* Recv data */ | ||
540 | static int bcsp_recv(struct hci_uart *hu, void *data, int count) | ||
541 | { | ||
542 | struct bcsp_struct *bcsp = hu->priv; | ||
543 | register unsigned char *ptr; | ||
544 | |||
545 | BT_DBG("hu %p count %d rx_state %d rx_count %ld", | ||
546 | hu, count, bcsp->rx_state, bcsp->rx_count); | ||
547 | |||
548 | ptr = data; | ||
549 | while (count) { | ||
550 | if (bcsp->rx_count) { | ||
551 | if (*ptr == 0xc0) { | ||
552 | BT_ERR("Short BCSP packet"); | ||
553 | kfree_skb(bcsp->rx_skb); | ||
554 | bcsp->rx_state = BCSP_W4_PKT_START; | ||
555 | bcsp->rx_count = 0; | ||
556 | } else | ||
557 | bcsp_unslip_one_byte(bcsp, *ptr); | ||
558 | |||
559 | ptr++; count--; | ||
560 | continue; | ||
561 | } | ||
562 | |||
563 | switch (bcsp->rx_state) { | ||
564 | case BCSP_W4_BCSP_HDR: | ||
565 | if ((0xff & (u8) ~ (bcsp->rx_skb->data[0] + bcsp->rx_skb->data[1] + | ||
566 | bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) { | ||
567 | BT_ERR("Error in BCSP hdr checksum"); | ||
568 | kfree_skb(bcsp->rx_skb); | ||
569 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
570 | bcsp->rx_count = 0; | ||
571 | continue; | ||
572 | } | ||
573 | if (bcsp->rx_skb->data[0] & 0x80 /* reliable pkt */ | ||
574 | && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) { | ||
575 | BT_ERR ("Out-of-order packet arrived, got %u expected %u", | ||
576 | bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack); | ||
577 | |||
578 | kfree_skb(bcsp->rx_skb); | ||
579 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
580 | bcsp->rx_count = 0; | ||
581 | continue; | ||
582 | } | ||
583 | bcsp->rx_state = BCSP_W4_DATA; | ||
584 | bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + | ||
585 | (bcsp->rx_skb->data[2] << 4); /* May be 0 */ | ||
586 | continue; | ||
587 | |||
588 | case BCSP_W4_DATA: | ||
589 | if (bcsp->rx_skb->data[0] & 0x40) { /* pkt with crc */ | ||
590 | bcsp->rx_state = BCSP_W4_CRC; | ||
591 | bcsp->rx_count = 2; | ||
592 | } else | ||
593 | bcsp_complete_rx_pkt(hu); | ||
594 | continue; | ||
595 | |||
596 | case BCSP_W4_CRC: | ||
597 | if (bcsp_crc_reverse(bcsp->message_crc) != | ||
598 | (bcsp->rx_skb->data[bcsp->rx_skb->len - 2] << 8) + | ||
599 | bcsp->rx_skb->data[bcsp->rx_skb->len - 1]) { | ||
600 | |||
601 | BT_ERR ("Checksum failed: computed %04x received %04x", | ||
602 | bcsp_crc_reverse(bcsp->message_crc), | ||
603 | (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) + | ||
604 | bcsp->rx_skb->data[bcsp->rx_skb->len - 1]); | ||
605 | |||
606 | kfree_skb(bcsp->rx_skb); | ||
607 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
608 | bcsp->rx_count = 0; | ||
609 | continue; | ||
610 | } | ||
611 | skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2); | ||
612 | bcsp_complete_rx_pkt(hu); | ||
613 | continue; | ||
614 | |||
615 | case BCSP_W4_PKT_DELIMITER: | ||
616 | switch (*ptr) { | ||
617 | case 0xc0: | ||
618 | bcsp->rx_state = BCSP_W4_PKT_START; | ||
619 | break; | ||
620 | default: | ||
621 | /*BT_ERR("Ignoring byte %02x", *ptr);*/ | ||
622 | break; | ||
623 | } | ||
624 | ptr++; count--; | ||
625 | break; | ||
626 | |||
627 | case BCSP_W4_PKT_START: | ||
628 | switch (*ptr) { | ||
629 | case 0xc0: | ||
630 | ptr++; count--; | ||
631 | break; | ||
632 | |||
633 | default: | ||
634 | bcsp->rx_state = BCSP_W4_BCSP_HDR; | ||
635 | bcsp->rx_count = 4; | ||
636 | bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; | ||
637 | BCSP_CRC_INIT(bcsp->message_crc); | ||
638 | |||
639 | /* Do not increment ptr or decrement count | ||
640 | * Allocate packet. Max len of a BCSP pkt= | ||
641 | * 0xFFF (payload) +4 (header) +2 (crc) */ | ||
642 | |||
643 | bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC); | ||
644 | if (!bcsp->rx_skb) { | ||
645 | BT_ERR("Can't allocate mem for new packet"); | ||
646 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
647 | bcsp->rx_count = 0; | ||
648 | return 0; | ||
649 | } | ||
650 | bcsp->rx_skb->dev = (void *) hu->hdev; | ||
651 | break; | ||
652 | } | ||
653 | break; | ||
654 | } | ||
655 | } | ||
656 | return count; | ||
657 | } | ||
658 | |||
659 | /* Arrange to retransmit all messages in the relq. */ | ||
660 | static void bcsp_timed_event(unsigned long arg) | ||
661 | { | ||
662 | struct hci_uart *hu = (struct hci_uart *) arg; | ||
663 | struct bcsp_struct *bcsp = hu->priv; | ||
664 | struct sk_buff *skb; | ||
665 | unsigned long flags; | ||
666 | |||
667 | BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen); | ||
668 | |||
669 | spin_lock_irqsave(&bcsp->unack.lock, flags); | ||
670 | |||
671 | while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) { | ||
672 | bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07; | ||
673 | skb_queue_head(&bcsp->rel, skb); | ||
674 | } | ||
675 | |||
676 | spin_unlock_irqrestore(&bcsp->unack.lock, flags); | ||
677 | |||
678 | hci_uart_tx_wakeup(hu); | ||
679 | } | ||
680 | |||
681 | static int bcsp_open(struct hci_uart *hu) | ||
682 | { | ||
683 | struct bcsp_struct *bcsp; | ||
684 | |||
685 | BT_DBG("hu %p", hu); | ||
686 | |||
687 | bcsp = kmalloc(sizeof(*bcsp), GFP_ATOMIC); | ||
688 | if (!bcsp) | ||
689 | return -ENOMEM; | ||
690 | memset(bcsp, 0, sizeof(*bcsp)); | ||
691 | |||
692 | hu->priv = bcsp; | ||
693 | skb_queue_head_init(&bcsp->unack); | ||
694 | skb_queue_head_init(&bcsp->rel); | ||
695 | skb_queue_head_init(&bcsp->unrel); | ||
696 | |||
697 | init_timer(&bcsp->tbcsp); | ||
698 | bcsp->tbcsp.function = bcsp_timed_event; | ||
699 | bcsp->tbcsp.data = (u_long) hu; | ||
700 | |||
701 | bcsp->rx_state = BCSP_W4_PKT_DELIMITER; | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int bcsp_close(struct hci_uart *hu) | ||
707 | { | ||
708 | struct bcsp_struct *bcsp = hu->priv; | ||
709 | hu->priv = NULL; | ||
710 | |||
711 | BT_DBG("hu %p", hu); | ||
712 | |||
713 | skb_queue_purge(&bcsp->unack); | ||
714 | skb_queue_purge(&bcsp->rel); | ||
715 | skb_queue_purge(&bcsp->unrel); | ||
716 | del_timer(&bcsp->tbcsp); | ||
717 | |||
718 | kfree(bcsp); | ||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static struct hci_uart_proto bcsp = { | ||
723 | .id = HCI_UART_BCSP, | ||
724 | .open = bcsp_open, | ||
725 | .close = bcsp_close, | ||
726 | .enqueue = bcsp_enqueue, | ||
727 | .dequeue = bcsp_dequeue, | ||
728 | .recv = bcsp_recv, | ||
729 | .flush = bcsp_flush | ||
730 | }; | ||
731 | |||
732 | int bcsp_init(void) | ||
733 | { | ||
734 | int err = hci_uart_register_proto(&bcsp); | ||
735 | if (!err) | ||
736 | BT_INFO("HCI BCSP protocol initialized"); | ||
737 | else | ||
738 | BT_ERR("HCI BCSP protocol registration failed"); | ||
739 | |||
740 | return err; | ||
741 | } | ||
742 | |||
743 | int bcsp_deinit(void) | ||
744 | { | ||
745 | return hci_uart_unregister_proto(&bcsp); | ||
746 | } | ||
747 | |||
748 | module_param(hciextn, bool, 0644); | ||
749 | MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets"); | ||
diff --git a/drivers/bluetooth/hci_bcsp.h b/drivers/bluetooth/hci_bcsp.h new file mode 100644 index 000000000000..a2b3bb92274b --- /dev/null +++ b/drivers/bluetooth/hci_bcsp.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ). | ||
3 | Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com> | ||
4 | |||
5 | Based on | ||
6 | hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com> | ||
7 | ABCSP by Carl Orsborn <cjo@csr.com> | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License version 2 as | ||
11 | published by the Free Software Foundation; | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
14 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
16 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
17 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
18 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
19 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
20 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
21 | |||
22 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
23 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
24 | SOFTWARE IS DISCLAIMED. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * $Id: hci_bcsp.h,v 1.2 2002/09/26 05:05:14 maxk Exp $ | ||
29 | */ | ||
30 | |||
31 | #ifndef __HCI_BCSP_H__ | ||
32 | #define __HCI_BCSP_H__ | ||
33 | |||
34 | #define BCSP_TXWINSIZE 4 | ||
35 | |||
36 | #define BCSP_ACK_PKT 0x05 | ||
37 | #define BCSP_LE_PKT 0x06 | ||
38 | |||
39 | struct bcsp_struct { | ||
40 | struct sk_buff_head unack; /* Unack'ed packets queue */ | ||
41 | struct sk_buff_head rel; /* Reliable packets queue */ | ||
42 | struct sk_buff_head unrel; /* Unreliable packets queue */ | ||
43 | |||
44 | unsigned long rx_count; | ||
45 | struct sk_buff *rx_skb; | ||
46 | u8 rxseq_txack; /* rxseq == txack. */ | ||
47 | u8 rxack; /* Last packet sent by us that the peer ack'ed */ | ||
48 | struct timer_list tbcsp; | ||
49 | |||
50 | enum { | ||
51 | BCSP_W4_PKT_DELIMITER, | ||
52 | BCSP_W4_PKT_START, | ||
53 | BCSP_W4_BCSP_HDR, | ||
54 | BCSP_W4_DATA, | ||
55 | BCSP_W4_CRC | ||
56 | } rx_state; | ||
57 | |||
58 | enum { | ||
59 | BCSP_ESCSTATE_NOESC, | ||
60 | BCSP_ESCSTATE_ESC | ||
61 | } rx_esc_state; | ||
62 | |||
63 | u16 message_crc; | ||
64 | u8 txack_req; /* Do we need to send ack's to the peer? */ | ||
65 | |||
66 | /* Reliable packet sequence number - used to assign seq to each rel pkt. */ | ||
67 | u8 msgq_txseq; | ||
68 | }; | ||
69 | |||
70 | #endif /* __HCI_BCSP_H__ */ | ||
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c new file mode 100644 index 000000000000..ade94a57bb11 --- /dev/null +++ b/drivers/bluetooth/hci_h4.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Bluetooth HCI UART(H4) protocol. | ||
27 | * | ||
28 | * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $ | ||
29 | */ | ||
30 | #define VERSION "1.2" | ||
31 | |||
32 | #include <linux/config.h> | ||
33 | #include <linux/module.h> | ||
34 | |||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/fcntl.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/ptrace.h> | ||
42 | #include <linux/poll.h> | ||
43 | |||
44 | #include <linux/slab.h> | ||
45 | #include <linux/tty.h> | ||
46 | #include <linux/errno.h> | ||
47 | #include <linux/string.h> | ||
48 | #include <linux/signal.h> | ||
49 | #include <linux/ioctl.h> | ||
50 | #include <linux/skbuff.h> | ||
51 | |||
52 | #include <net/bluetooth/bluetooth.h> | ||
53 | #include <net/bluetooth/hci_core.h> | ||
54 | #include "hci_uart.h" | ||
55 | #include "hci_h4.h" | ||
56 | |||
57 | #ifndef CONFIG_BT_HCIUART_DEBUG | ||
58 | #undef BT_DBG | ||
59 | #define BT_DBG( A... ) | ||
60 | #undef BT_DMP | ||
61 | #define BT_DMP( A... ) | ||
62 | #endif | ||
63 | |||
64 | /* Initialize protocol */ | ||
65 | static int h4_open(struct hci_uart *hu) | ||
66 | { | ||
67 | struct h4_struct *h4; | ||
68 | |||
69 | BT_DBG("hu %p", hu); | ||
70 | |||
71 | h4 = kmalloc(sizeof(*h4), GFP_ATOMIC); | ||
72 | if (!h4) | ||
73 | return -ENOMEM; | ||
74 | memset(h4, 0, sizeof(*h4)); | ||
75 | |||
76 | skb_queue_head_init(&h4->txq); | ||
77 | |||
78 | hu->priv = h4; | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /* Flush protocol data */ | ||
83 | static int h4_flush(struct hci_uart *hu) | ||
84 | { | ||
85 | struct h4_struct *h4 = hu->priv; | ||
86 | |||
87 | BT_DBG("hu %p", hu); | ||
88 | skb_queue_purge(&h4->txq); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* Close protocol */ | ||
93 | static int h4_close(struct hci_uart *hu) | ||
94 | { | ||
95 | struct h4_struct *h4 = hu->priv; | ||
96 | hu->priv = NULL; | ||
97 | |||
98 | BT_DBG("hu %p", hu); | ||
99 | |||
100 | skb_queue_purge(&h4->txq); | ||
101 | if (h4->rx_skb) | ||
102 | kfree_skb(h4->rx_skb); | ||
103 | |||
104 | hu->priv = NULL; | ||
105 | kfree(h4); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | /* Enqueue frame for transmittion (padding, crc, etc) */ | ||
110 | static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) | ||
111 | { | ||
112 | struct h4_struct *h4 = hu->priv; | ||
113 | |||
114 | BT_DBG("hu %p skb %p", hu, skb); | ||
115 | |||
116 | /* Prepend skb with frame type */ | ||
117 | memcpy(skb_push(skb, 1), &skb->pkt_type, 1); | ||
118 | skb_queue_tail(&h4->txq, skb); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static inline int h4_check_data_len(struct h4_struct *h4, int len) | ||
123 | { | ||
124 | register int room = skb_tailroom(h4->rx_skb); | ||
125 | |||
126 | BT_DBG("len %d room %d", len, room); | ||
127 | if (!len) { | ||
128 | BT_DMP(h4->rx_skb->data, h4->rx_skb->len); | ||
129 | hci_recv_frame(h4->rx_skb); | ||
130 | } else if (len > room) { | ||
131 | BT_ERR("Data length is too large"); | ||
132 | kfree_skb(h4->rx_skb); | ||
133 | } else { | ||
134 | h4->rx_state = H4_W4_DATA; | ||
135 | h4->rx_count = len; | ||
136 | return len; | ||
137 | } | ||
138 | |||
139 | h4->rx_state = H4_W4_PACKET_TYPE; | ||
140 | h4->rx_skb = NULL; | ||
141 | h4->rx_count = 0; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | /* Recv data */ | ||
146 | static int h4_recv(struct hci_uart *hu, void *data, int count) | ||
147 | { | ||
148 | struct h4_struct *h4 = hu->priv; | ||
149 | register char *ptr; | ||
150 | struct hci_event_hdr *eh; | ||
151 | struct hci_acl_hdr *ah; | ||
152 | struct hci_sco_hdr *sh; | ||
153 | register int len, type, dlen; | ||
154 | |||
155 | BT_DBG("hu %p count %d rx_state %ld rx_count %ld", | ||
156 | hu, count, h4->rx_state, h4->rx_count); | ||
157 | |||
158 | ptr = data; | ||
159 | while (count) { | ||
160 | if (h4->rx_count) { | ||
161 | len = min_t(unsigned int, h4->rx_count, count); | ||
162 | memcpy(skb_put(h4->rx_skb, len), ptr, len); | ||
163 | h4->rx_count -= len; count -= len; ptr += len; | ||
164 | |||
165 | if (h4->rx_count) | ||
166 | continue; | ||
167 | |||
168 | switch (h4->rx_state) { | ||
169 | case H4_W4_DATA: | ||
170 | BT_DBG("Complete data"); | ||
171 | |||
172 | BT_DMP(h4->rx_skb->data, h4->rx_skb->len); | ||
173 | |||
174 | hci_recv_frame(h4->rx_skb); | ||
175 | |||
176 | h4->rx_state = H4_W4_PACKET_TYPE; | ||
177 | h4->rx_skb = NULL; | ||
178 | continue; | ||
179 | |||
180 | case H4_W4_EVENT_HDR: | ||
181 | eh = (struct hci_event_hdr *) h4->rx_skb->data; | ||
182 | |||
183 | BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); | ||
184 | |||
185 | h4_check_data_len(h4, eh->plen); | ||
186 | continue; | ||
187 | |||
188 | case H4_W4_ACL_HDR: | ||
189 | ah = (struct hci_acl_hdr *) h4->rx_skb->data; | ||
190 | dlen = __le16_to_cpu(ah->dlen); | ||
191 | |||
192 | BT_DBG("ACL header: dlen %d", dlen); | ||
193 | |||
194 | h4_check_data_len(h4, dlen); | ||
195 | continue; | ||
196 | |||
197 | case H4_W4_SCO_HDR: | ||
198 | sh = (struct hci_sco_hdr *) h4->rx_skb->data; | ||
199 | |||
200 | BT_DBG("SCO header: dlen %d", sh->dlen); | ||
201 | |||
202 | h4_check_data_len(h4, sh->dlen); | ||
203 | continue; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | /* H4_W4_PACKET_TYPE */ | ||
208 | switch (*ptr) { | ||
209 | case HCI_EVENT_PKT: | ||
210 | BT_DBG("Event packet"); | ||
211 | h4->rx_state = H4_W4_EVENT_HDR; | ||
212 | h4->rx_count = HCI_EVENT_HDR_SIZE; | ||
213 | type = HCI_EVENT_PKT; | ||
214 | break; | ||
215 | |||
216 | case HCI_ACLDATA_PKT: | ||
217 | BT_DBG("ACL packet"); | ||
218 | h4->rx_state = H4_W4_ACL_HDR; | ||
219 | h4->rx_count = HCI_ACL_HDR_SIZE; | ||
220 | type = HCI_ACLDATA_PKT; | ||
221 | break; | ||
222 | |||
223 | case HCI_SCODATA_PKT: | ||
224 | BT_DBG("SCO packet"); | ||
225 | h4->rx_state = H4_W4_SCO_HDR; | ||
226 | h4->rx_count = HCI_SCO_HDR_SIZE; | ||
227 | type = HCI_SCODATA_PKT; | ||
228 | break; | ||
229 | |||
230 | default: | ||
231 | BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); | ||
232 | hu->hdev->stat.err_rx++; | ||
233 | ptr++; count--; | ||
234 | continue; | ||
235 | }; | ||
236 | ptr++; count--; | ||
237 | |||
238 | /* Allocate packet */ | ||
239 | h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); | ||
240 | if (!h4->rx_skb) { | ||
241 | BT_ERR("Can't allocate mem for new packet"); | ||
242 | h4->rx_state = H4_W4_PACKET_TYPE; | ||
243 | h4->rx_count = 0; | ||
244 | return 0; | ||
245 | } | ||
246 | h4->rx_skb->dev = (void *) hu->hdev; | ||
247 | h4->rx_skb->pkt_type = type; | ||
248 | } | ||
249 | return count; | ||
250 | } | ||
251 | |||
252 | static struct sk_buff *h4_dequeue(struct hci_uart *hu) | ||
253 | { | ||
254 | struct h4_struct *h4 = hu->priv; | ||
255 | return skb_dequeue(&h4->txq); | ||
256 | } | ||
257 | |||
258 | static struct hci_uart_proto h4p = { | ||
259 | .id = HCI_UART_H4, | ||
260 | .open = h4_open, | ||
261 | .close = h4_close, | ||
262 | .recv = h4_recv, | ||
263 | .enqueue = h4_enqueue, | ||
264 | .dequeue = h4_dequeue, | ||
265 | .flush = h4_flush, | ||
266 | }; | ||
267 | |||
268 | int h4_init(void) | ||
269 | { | ||
270 | int err = hci_uart_register_proto(&h4p); | ||
271 | if (!err) | ||
272 | BT_INFO("HCI H4 protocol initialized"); | ||
273 | else | ||
274 | BT_ERR("HCI H4 protocol registration failed"); | ||
275 | |||
276 | return err; | ||
277 | } | ||
278 | |||
279 | int h4_deinit(void) | ||
280 | { | ||
281 | return hci_uart_unregister_proto(&h4p); | ||
282 | } | ||
diff --git a/drivers/bluetooth/hci_h4.h b/drivers/bluetooth/hci_h4.h new file mode 100644 index 000000000000..b95ff54bfd47 --- /dev/null +++ b/drivers/bluetooth/hci_h4.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * $Id: hci_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $ | ||
27 | */ | ||
28 | |||
29 | #ifdef __KERNEL__ | ||
30 | struct h4_struct { | ||
31 | unsigned long rx_state; | ||
32 | unsigned long rx_count; | ||
33 | struct sk_buff *rx_skb; | ||
34 | struct sk_buff_head txq; | ||
35 | }; | ||
36 | |||
37 | /* H4 receiver States */ | ||
38 | #define H4_W4_PACKET_TYPE 0 | ||
39 | #define H4_W4_EVENT_HDR 1 | ||
40 | #define H4_W4_ACL_HDR 2 | ||
41 | #define H4_W4_SCO_HDR 3 | ||
42 | #define H4_W4_DATA 4 | ||
43 | |||
44 | #endif /* __KERNEL__ */ | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c new file mode 100644 index 000000000000..9075bbb56ad4 --- /dev/null +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -0,0 +1,593 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Bluetooth HCI UART driver. | ||
27 | * | ||
28 | * $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $ | ||
29 | */ | ||
30 | #define VERSION "2.1" | ||
31 | |||
32 | #include <linux/config.h> | ||
33 | #include <linux/module.h> | ||
34 | |||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/fcntl.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/ptrace.h> | ||
42 | #include <linux/poll.h> | ||
43 | |||
44 | #include <linux/slab.h> | ||
45 | #include <linux/tty.h> | ||
46 | #include <linux/errno.h> | ||
47 | #include <linux/string.h> | ||
48 | #include <linux/signal.h> | ||
49 | #include <linux/ioctl.h> | ||
50 | #include <linux/skbuff.h> | ||
51 | |||
52 | #include <net/bluetooth/bluetooth.h> | ||
53 | #include <net/bluetooth/hci_core.h> | ||
54 | |||
55 | #include "hci_uart.h" | ||
56 | |||
57 | #ifndef CONFIG_BT_HCIUART_DEBUG | ||
58 | #undef BT_DBG | ||
59 | #define BT_DBG( A... ) | ||
60 | #undef BT_DMP | ||
61 | #define BT_DMP( A... ) | ||
62 | #endif | ||
63 | |||
64 | static int reset = 0; | ||
65 | |||
66 | static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO]; | ||
67 | |||
68 | int hci_uart_register_proto(struct hci_uart_proto *p) | ||
69 | { | ||
70 | if (p->id >= HCI_UART_MAX_PROTO) | ||
71 | return -EINVAL; | ||
72 | |||
73 | if (hup[p->id]) | ||
74 | return -EEXIST; | ||
75 | |||
76 | hup[p->id] = p; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | int hci_uart_unregister_proto(struct hci_uart_proto *p) | ||
81 | { | ||
82 | if (p->id >= HCI_UART_MAX_PROTO) | ||
83 | return -EINVAL; | ||
84 | |||
85 | if (!hup[p->id]) | ||
86 | return -EINVAL; | ||
87 | |||
88 | hup[p->id] = NULL; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static struct hci_uart_proto *hci_uart_get_proto(unsigned int id) | ||
93 | { | ||
94 | if (id >= HCI_UART_MAX_PROTO) | ||
95 | return NULL; | ||
96 | return hup[id]; | ||
97 | } | ||
98 | |||
99 | static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) | ||
100 | { | ||
101 | struct hci_dev *hdev = hu->hdev; | ||
102 | |||
103 | /* Update HCI stat counters */ | ||
104 | switch (pkt_type) { | ||
105 | case HCI_COMMAND_PKT: | ||
106 | hdev->stat.cmd_tx++; | ||
107 | break; | ||
108 | |||
109 | case HCI_ACLDATA_PKT: | ||
110 | hdev->stat.acl_tx++; | ||
111 | break; | ||
112 | |||
113 | case HCI_SCODATA_PKT: | ||
114 | hdev->stat.cmd_tx++; | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) | ||
120 | { | ||
121 | struct sk_buff *skb = hu->tx_skb; | ||
122 | if (!skb) | ||
123 | skb = hu->proto->dequeue(hu); | ||
124 | else | ||
125 | hu->tx_skb = NULL; | ||
126 | return skb; | ||
127 | } | ||
128 | |||
129 | int hci_uart_tx_wakeup(struct hci_uart *hu) | ||
130 | { | ||
131 | struct tty_struct *tty = hu->tty; | ||
132 | struct hci_dev *hdev = hu->hdev; | ||
133 | struct sk_buff *skb; | ||
134 | |||
135 | if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { | ||
136 | set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | BT_DBG(""); | ||
141 | |||
142 | restart: | ||
143 | clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); | ||
144 | |||
145 | while ((skb = hci_uart_dequeue(hu))) { | ||
146 | int len; | ||
147 | |||
148 | set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
149 | len = tty->driver->write(tty, skb->data, skb->len); | ||
150 | hdev->stat.byte_tx += len; | ||
151 | |||
152 | skb_pull(skb, len); | ||
153 | if (skb->len) { | ||
154 | hu->tx_skb = skb; | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | hci_uart_tx_complete(hu, skb->pkt_type); | ||
159 | kfree_skb(skb); | ||
160 | } | ||
161 | |||
162 | if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) | ||
163 | goto restart; | ||
164 | |||
165 | clear_bit(HCI_UART_SENDING, &hu->tx_state); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* ------- Interface to HCI layer ------ */ | ||
170 | /* Initialize device */ | ||
171 | static int hci_uart_open(struct hci_dev *hdev) | ||
172 | { | ||
173 | BT_DBG("%s %p", hdev->name, hdev); | ||
174 | |||
175 | /* Nothing to do for UART driver */ | ||
176 | |||
177 | set_bit(HCI_RUNNING, &hdev->flags); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* Reset device */ | ||
182 | static int hci_uart_flush(struct hci_dev *hdev) | ||
183 | { | ||
184 | struct hci_uart *hu = (struct hci_uart *) hdev->driver_data; | ||
185 | struct tty_struct *tty = hu->tty; | ||
186 | |||
187 | BT_DBG("hdev %p tty %p", hdev, tty); | ||
188 | |||
189 | if (hu->tx_skb) { | ||
190 | kfree_skb(hu->tx_skb); hu->tx_skb = NULL; | ||
191 | } | ||
192 | |||
193 | /* Flush any pending characters in the driver and discipline. */ | ||
194 | tty_ldisc_flush(tty); | ||
195 | if (tty->driver->flush_buffer) | ||
196 | tty->driver->flush_buffer(tty); | ||
197 | |||
198 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | ||
199 | hu->proto->flush(hu); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* Close device */ | ||
205 | static int hci_uart_close(struct hci_dev *hdev) | ||
206 | { | ||
207 | BT_DBG("hdev %p", hdev); | ||
208 | |||
209 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
210 | return 0; | ||
211 | |||
212 | hci_uart_flush(hdev); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | /* Send frames from HCI layer */ | ||
217 | static int hci_uart_send_frame(struct sk_buff *skb) | ||
218 | { | ||
219 | struct hci_dev* hdev = (struct hci_dev *) skb->dev; | ||
220 | struct tty_struct *tty; | ||
221 | struct hci_uart *hu; | ||
222 | |||
223 | if (!hdev) { | ||
224 | BT_ERR("Frame for uknown device (hdev=NULL)"); | ||
225 | return -ENODEV; | ||
226 | } | ||
227 | |||
228 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
229 | return -EBUSY; | ||
230 | |||
231 | hu = (struct hci_uart *) hdev->driver_data; | ||
232 | tty = hu->tty; | ||
233 | |||
234 | BT_DBG("%s: type %d len %d", hdev->name, skb->pkt_type, skb->len); | ||
235 | |||
236 | hu->proto->enqueue(hu, skb); | ||
237 | |||
238 | hci_uart_tx_wakeup(hu); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static void hci_uart_destruct(struct hci_dev *hdev) | ||
243 | { | ||
244 | struct hci_uart *hu; | ||
245 | |||
246 | if (!hdev) return; | ||
247 | |||
248 | BT_DBG("%s", hdev->name); | ||
249 | |||
250 | hu = (struct hci_uart *) hdev->driver_data; | ||
251 | kfree(hu); | ||
252 | } | ||
253 | |||
254 | /* ------ LDISC part ------ */ | ||
255 | /* hci_uart_tty_open | ||
256 | * | ||
257 | * Called when line discipline changed to HCI_UART. | ||
258 | * | ||
259 | * Arguments: | ||
260 | * tty pointer to tty info structure | ||
261 | * Return Value: | ||
262 | * 0 if success, otherwise error code | ||
263 | */ | ||
264 | static int hci_uart_tty_open(struct tty_struct *tty) | ||
265 | { | ||
266 | struct hci_uart *hu = (void *) tty->disc_data; | ||
267 | |||
268 | BT_DBG("tty %p", tty); | ||
269 | |||
270 | if (hu) | ||
271 | return -EEXIST; | ||
272 | |||
273 | if (!(hu = kmalloc(sizeof(struct hci_uart), GFP_KERNEL))) { | ||
274 | BT_ERR("Can't allocate controll structure"); | ||
275 | return -ENFILE; | ||
276 | } | ||
277 | memset(hu, 0, sizeof(struct hci_uart)); | ||
278 | |||
279 | tty->disc_data = hu; | ||
280 | hu->tty = tty; | ||
281 | |||
282 | spin_lock_init(&hu->rx_lock); | ||
283 | |||
284 | /* Flush any pending characters in the driver and line discipline. */ | ||
285 | /* FIXME: why is this needed. Note don't use ldisc_ref here as the | ||
286 | open path is before the ldisc is referencable */ | ||
287 | if (tty->ldisc.flush_buffer) | ||
288 | tty->ldisc.flush_buffer(tty); | ||
289 | |||
290 | if (tty->driver->flush_buffer) | ||
291 | tty->driver->flush_buffer(tty); | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | /* hci_uart_tty_close() | ||
297 | * | ||
298 | * Called when the line discipline is changed to something | ||
299 | * else, the tty is closed, or the tty detects a hangup. | ||
300 | */ | ||
301 | static void hci_uart_tty_close(struct tty_struct *tty) | ||
302 | { | ||
303 | struct hci_uart *hu = (void *)tty->disc_data; | ||
304 | |||
305 | BT_DBG("tty %p", tty); | ||
306 | |||
307 | /* Detach from the tty */ | ||
308 | tty->disc_data = NULL; | ||
309 | |||
310 | if (hu) { | ||
311 | struct hci_dev *hdev = hu->hdev; | ||
312 | hci_uart_close(hdev); | ||
313 | |||
314 | if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { | ||
315 | hu->proto->close(hu); | ||
316 | hci_unregister_dev(hdev); | ||
317 | hci_free_dev(hdev); | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* hci_uart_tty_wakeup() | ||
323 | * | ||
324 | * Callback for transmit wakeup. Called when low level | ||
325 | * device driver can accept more send data. | ||
326 | * | ||
327 | * Arguments: tty pointer to associated tty instance data | ||
328 | * Return Value: None | ||
329 | */ | ||
330 | static void hci_uart_tty_wakeup(struct tty_struct *tty) | ||
331 | { | ||
332 | struct hci_uart *hu = (void *)tty->disc_data; | ||
333 | |||
334 | BT_DBG(""); | ||
335 | |||
336 | if (!hu) | ||
337 | return; | ||
338 | |||
339 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
340 | |||
341 | if (tty != hu->tty) | ||
342 | return; | ||
343 | |||
344 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | ||
345 | hci_uart_tx_wakeup(hu); | ||
346 | } | ||
347 | |||
348 | /* hci_uart_tty_room() | ||
349 | * | ||
350 | * Callback function from tty driver. Return the amount of | ||
351 | * space left in the receiver's buffer to decide if remote | ||
352 | * transmitter is to be throttled. | ||
353 | * | ||
354 | * Arguments: tty pointer to associated tty instance data | ||
355 | * Return Value: number of bytes left in receive buffer | ||
356 | */ | ||
357 | static int hci_uart_tty_room (struct tty_struct *tty) | ||
358 | { | ||
359 | return 65536; | ||
360 | } | ||
361 | |||
362 | /* hci_uart_tty_receive() | ||
363 | * | ||
364 | * Called by tty low level driver when receive data is | ||
365 | * available. | ||
366 | * | ||
367 | * Arguments: tty pointer to tty isntance data | ||
368 | * data pointer to received data | ||
369 | * flags pointer to flags for data | ||
370 | * count count of received data in bytes | ||
371 | * | ||
372 | * Return Value: None | ||
373 | */ | ||
374 | static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count) | ||
375 | { | ||
376 | struct hci_uart *hu = (void *)tty->disc_data; | ||
377 | |||
378 | if (!hu || tty != hu->tty) | ||
379 | return; | ||
380 | |||
381 | if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) | ||
382 | return; | ||
383 | |||
384 | spin_lock(&hu->rx_lock); | ||
385 | hu->proto->recv(hu, (void *) data, count); | ||
386 | hu->hdev->stat.byte_rx += count; | ||
387 | spin_unlock(&hu->rx_lock); | ||
388 | |||
389 | if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle) | ||
390 | tty->driver->unthrottle(tty); | ||
391 | } | ||
392 | |||
393 | static int hci_uart_register_dev(struct hci_uart *hu) | ||
394 | { | ||
395 | struct hci_dev *hdev; | ||
396 | |||
397 | BT_DBG(""); | ||
398 | |||
399 | /* Initialize and register HCI device */ | ||
400 | hdev = hci_alloc_dev(); | ||
401 | if (!hdev) { | ||
402 | BT_ERR("Can't allocate HCI device"); | ||
403 | return -ENOMEM; | ||
404 | } | ||
405 | |||
406 | hu->hdev = hdev; | ||
407 | |||
408 | hdev->type = HCI_UART; | ||
409 | hdev->driver_data = hu; | ||
410 | |||
411 | hdev->open = hci_uart_open; | ||
412 | hdev->close = hci_uart_close; | ||
413 | hdev->flush = hci_uart_flush; | ||
414 | hdev->send = hci_uart_send_frame; | ||
415 | hdev->destruct = hci_uart_destruct; | ||
416 | |||
417 | hdev->owner = THIS_MODULE; | ||
418 | |||
419 | if (reset) | ||
420 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); | ||
421 | |||
422 | if (hci_register_dev(hdev) < 0) { | ||
423 | BT_ERR("Can't register HCI device"); | ||
424 | hci_free_dev(hdev); | ||
425 | return -ENODEV; | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int hci_uart_set_proto(struct hci_uart *hu, int id) | ||
432 | { | ||
433 | struct hci_uart_proto *p; | ||
434 | int err; | ||
435 | |||
436 | p = hci_uart_get_proto(id); | ||
437 | if (!p) | ||
438 | return -EPROTONOSUPPORT; | ||
439 | |||
440 | err = p->open(hu); | ||
441 | if (err) | ||
442 | return err; | ||
443 | |||
444 | hu->proto = p; | ||
445 | |||
446 | err = hci_uart_register_dev(hu); | ||
447 | if (err) { | ||
448 | p->close(hu); | ||
449 | return err; | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | /* hci_uart_tty_ioctl() | ||
455 | * | ||
456 | * Process IOCTL system call for the tty device. | ||
457 | * | ||
458 | * Arguments: | ||
459 | * | ||
460 | * tty pointer to tty instance data | ||
461 | * file pointer to open file object for device | ||
462 | * cmd IOCTL command code | ||
463 | * arg argument for IOCTL call (cmd dependent) | ||
464 | * | ||
465 | * Return Value: Command dependent | ||
466 | */ | ||
467 | static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, | ||
468 | unsigned int cmd, unsigned long arg) | ||
469 | { | ||
470 | struct hci_uart *hu = (void *)tty->disc_data; | ||
471 | int err = 0; | ||
472 | |||
473 | BT_DBG(""); | ||
474 | |||
475 | /* Verify the status of the device */ | ||
476 | if (!hu) | ||
477 | return -EBADF; | ||
478 | |||
479 | switch (cmd) { | ||
480 | case HCIUARTSETPROTO: | ||
481 | if (!test_and_set_bit(HCI_UART_PROTO_SET, &hu->flags)) { | ||
482 | err = hci_uart_set_proto(hu, arg); | ||
483 | if (err) { | ||
484 | clear_bit(HCI_UART_PROTO_SET, &hu->flags); | ||
485 | return err; | ||
486 | } | ||
487 | tty->low_latency = 1; | ||
488 | } else | ||
489 | return -EBUSY; | ||
490 | |||
491 | case HCIUARTGETPROTO: | ||
492 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | ||
493 | return hu->proto->id; | ||
494 | return -EUNATCH; | ||
495 | |||
496 | default: | ||
497 | err = n_tty_ioctl(tty, file, cmd, arg); | ||
498 | break; | ||
499 | }; | ||
500 | |||
501 | return err; | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * We don't provide read/write/poll interface for user space. | ||
506 | */ | ||
507 | static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr) | ||
508 | { | ||
509 | return 0; | ||
510 | } | ||
511 | static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) | ||
512 | { | ||
513 | return 0; | ||
514 | } | ||
515 | static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait) | ||
516 | { | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | #ifdef CONFIG_BT_HCIUART_H4 | ||
521 | int h4_init(void); | ||
522 | int h4_deinit(void); | ||
523 | #endif | ||
524 | #ifdef CONFIG_BT_HCIUART_BCSP | ||
525 | int bcsp_init(void); | ||
526 | int bcsp_deinit(void); | ||
527 | #endif | ||
528 | |||
529 | static int __init hci_uart_init(void) | ||
530 | { | ||
531 | static struct tty_ldisc hci_uart_ldisc; | ||
532 | int err; | ||
533 | |||
534 | BT_INFO("HCI UART driver ver %s", VERSION); | ||
535 | |||
536 | /* Register the tty discipline */ | ||
537 | |||
538 | memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc)); | ||
539 | hci_uart_ldisc.magic = TTY_LDISC_MAGIC; | ||
540 | hci_uart_ldisc.name = "n_hci"; | ||
541 | hci_uart_ldisc.open = hci_uart_tty_open; | ||
542 | hci_uart_ldisc.close = hci_uart_tty_close; | ||
543 | hci_uart_ldisc.read = hci_uart_tty_read; | ||
544 | hci_uart_ldisc.write = hci_uart_tty_write; | ||
545 | hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; | ||
546 | hci_uart_ldisc.poll = hci_uart_tty_poll; | ||
547 | hci_uart_ldisc.receive_room= hci_uart_tty_room; | ||
548 | hci_uart_ldisc.receive_buf = hci_uart_tty_receive; | ||
549 | hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; | ||
550 | hci_uart_ldisc.owner = THIS_MODULE; | ||
551 | |||
552 | if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { | ||
553 | BT_ERR("HCI line discipline registration failed. (%d)", err); | ||
554 | return err; | ||
555 | } | ||
556 | |||
557 | #ifdef CONFIG_BT_HCIUART_H4 | ||
558 | h4_init(); | ||
559 | #endif | ||
560 | #ifdef CONFIG_BT_HCIUART_BCSP | ||
561 | bcsp_init(); | ||
562 | #endif | ||
563 | |||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static void __exit hci_uart_exit(void) | ||
568 | { | ||
569 | int err; | ||
570 | |||
571 | #ifdef CONFIG_BT_HCIUART_H4 | ||
572 | h4_deinit(); | ||
573 | #endif | ||
574 | #ifdef CONFIG_BT_HCIUART_BCSP | ||
575 | bcsp_deinit(); | ||
576 | #endif | ||
577 | |||
578 | /* Release tty registration of line discipline */ | ||
579 | if ((err = tty_register_ldisc(N_HCI, NULL))) | ||
580 | BT_ERR("Can't unregister HCI line discipline (%d)", err); | ||
581 | } | ||
582 | |||
583 | module_init(hci_uart_init); | ||
584 | module_exit(hci_uart_exit); | ||
585 | |||
586 | module_param(reset, bool, 0644); | ||
587 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); | ||
588 | |||
589 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | ||
590 | MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION); | ||
591 | MODULE_VERSION(VERSION); | ||
592 | MODULE_LICENSE("GPL"); | ||
593 | MODULE_ALIAS_LDISC(N_HCI); | ||
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h new file mode 100644 index 000000000000..0a57d72790ec --- /dev/null +++ b/drivers/bluetooth/hci_uart.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * $Id: hci_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $ | ||
27 | */ | ||
28 | |||
29 | #ifndef N_HCI | ||
30 | #define N_HCI 15 | ||
31 | #endif | ||
32 | |||
33 | /* Ioctls */ | ||
34 | #define HCIUARTSETPROTO _IOW('U', 200, int) | ||
35 | #define HCIUARTGETPROTO _IOR('U', 201, int) | ||
36 | |||
37 | /* UART protocols */ | ||
38 | #define HCI_UART_MAX_PROTO 4 | ||
39 | |||
40 | #define HCI_UART_H4 0 | ||
41 | #define HCI_UART_BCSP 1 | ||
42 | #define HCI_UART_3WIRE 2 | ||
43 | #define HCI_UART_H4DS 3 | ||
44 | |||
45 | #ifdef __KERNEL__ | ||
46 | struct hci_uart; | ||
47 | |||
48 | struct hci_uart_proto { | ||
49 | unsigned int id; | ||
50 | int (*open)(struct hci_uart *hu); | ||
51 | int (*close)(struct hci_uart *hu); | ||
52 | int (*flush)(struct hci_uart *hu); | ||
53 | int (*recv)(struct hci_uart *hu, void *data, int len); | ||
54 | int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb); | ||
55 | struct sk_buff *(*dequeue)(struct hci_uart *hu); | ||
56 | }; | ||
57 | |||
58 | struct hci_uart { | ||
59 | struct tty_struct *tty; | ||
60 | struct hci_dev *hdev; | ||
61 | unsigned long flags; | ||
62 | |||
63 | struct hci_uart_proto *proto; | ||
64 | void *priv; | ||
65 | |||
66 | struct sk_buff *tx_skb; | ||
67 | unsigned long tx_state; | ||
68 | spinlock_t rx_lock; | ||
69 | }; | ||
70 | |||
71 | /* HCI_UART flag bits */ | ||
72 | #define HCI_UART_PROTO_SET 0 | ||
73 | |||
74 | /* TX states */ | ||
75 | #define HCI_UART_SENDING 1 | ||
76 | #define HCI_UART_TX_WAKEUP 2 | ||
77 | |||
78 | int hci_uart_register_proto(struct hci_uart_proto *p); | ||
79 | int hci_uart_unregister_proto(struct hci_uart_proto *p); | ||
80 | int hci_uart_tx_wakeup(struct hci_uart *hu); | ||
81 | |||
82 | #endif /* __KERNEL__ */ | ||
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c new file mode 100644 index 000000000000..b120ecf7b8c9 --- /dev/null +++ b/drivers/bluetooth/hci_usb.c | |||
@@ -0,0 +1,1075 @@ | |||
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 | /* | ||
27 | * Bluetooth HCI USB driver. | ||
28 | * Based on original USB Bluetooth driver for Linux kernel | ||
29 | * Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com> | ||
30 | * Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu> | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/config.h> | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/sched.h> | ||
40 | #include <linux/unistd.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/moduleparam.h> | ||
44 | |||
45 | #include <linux/slab.h> | ||
46 | #include <linux/errno.h> | ||
47 | #include <linux/string.h> | ||
48 | #include <linux/skbuff.h> | ||
49 | |||
50 | #include <linux/usb.h> | ||
51 | |||
52 | #include <net/bluetooth/bluetooth.h> | ||
53 | #include <net/bluetooth/hci_core.h> | ||
54 | |||
55 | #include "hci_usb.h" | ||
56 | |||
57 | #ifndef CONFIG_BT_HCIUSB_DEBUG | ||
58 | #undef BT_DBG | ||
59 | #define BT_DBG(D...) | ||
60 | #undef BT_DMP | ||
61 | #define BT_DMP(D...) | ||
62 | #endif | ||
63 | |||
64 | #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET | ||
65 | #undef URB_ZERO_PACKET | ||
66 | #define URB_ZERO_PACKET 0 | ||
67 | #endif | ||
68 | |||
69 | static int ignore = 0; | ||
70 | static int reset = 0; | ||
71 | |||
72 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
73 | static int isoc = 2; | ||
74 | #endif | ||
75 | |||
76 | #define VERSION "2.8" | ||
77 | |||
78 | static struct usb_driver hci_usb_driver; | ||
79 | |||
80 | static struct usb_device_id bluetooth_ids[] = { | ||
81 | /* Generic Bluetooth USB device */ | ||
82 | { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) }, | ||
83 | |||
84 | /* AVM BlueFRITZ! USB v2.0 */ | ||
85 | { USB_DEVICE(0x057c, 0x3800) }, | ||
86 | |||
87 | /* Bluetooth Ultraport Module from IBM */ | ||
88 | { USB_DEVICE(0x04bf, 0x030a) }, | ||
89 | |||
90 | /* ALPS Modules with non-standard id */ | ||
91 | { USB_DEVICE(0x044e, 0x3001) }, | ||
92 | { USB_DEVICE(0x044e, 0x3002) }, | ||
93 | |||
94 | /* Ericsson with non-standard id */ | ||
95 | { USB_DEVICE(0x0bdb, 0x1002) }, | ||
96 | |||
97 | { } /* Terminating entry */ | ||
98 | }; | ||
99 | |||
100 | MODULE_DEVICE_TABLE (usb, bluetooth_ids); | ||
101 | |||
102 | static struct usb_device_id blacklist_ids[] = { | ||
103 | /* Broadcom BCM2033 without firmware */ | ||
104 | { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, | ||
105 | |||
106 | /* Broadcom BCM2035 */ | ||
107 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC }, | ||
108 | { USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 }, | ||
109 | |||
110 | /* Microsoft Wireless Transceiver for Bluetooth 2.0 */ | ||
111 | { USB_DEVICE(0x045e, 0x009c), .driver_info = HCI_RESET }, | ||
112 | |||
113 | /* ISSC Bluetooth Adapter v3.1 */ | ||
114 | { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, | ||
115 | |||
116 | /* RTX Telecom based adapter with buggy SCO support */ | ||
117 | { USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, | ||
118 | |||
119 | /* Digianswer devices */ | ||
120 | { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, | ||
121 | { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE }, | ||
122 | |||
123 | /* CSR BlueCore Bluetooth Sniffer */ | ||
124 | { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER }, | ||
125 | |||
126 | { } /* Terminating entry */ | ||
127 | }; | ||
128 | |||
129 | static struct _urb *_urb_alloc(int isoc, int gfp) | ||
130 | { | ||
131 | struct _urb *_urb = kmalloc(sizeof(struct _urb) + | ||
132 | sizeof(struct usb_iso_packet_descriptor) * isoc, gfp); | ||
133 | if (_urb) { | ||
134 | memset(_urb, 0, sizeof(*_urb)); | ||
135 | usb_init_urb(&_urb->urb); | ||
136 | } | ||
137 | return _urb; | ||
138 | } | ||
139 | |||
140 | static struct _urb *_urb_dequeue(struct _urb_queue *q) | ||
141 | { | ||
142 | struct _urb *_urb = NULL; | ||
143 | unsigned long flags; | ||
144 | spin_lock_irqsave(&q->lock, flags); | ||
145 | { | ||
146 | struct list_head *head = &q->head; | ||
147 | struct list_head *next = head->next; | ||
148 | if (next != head) { | ||
149 | _urb = list_entry(next, struct _urb, list); | ||
150 | list_del(next); _urb->queue = NULL; | ||
151 | } | ||
152 | } | ||
153 | spin_unlock_irqrestore(&q->lock, flags); | ||
154 | return _urb; | ||
155 | } | ||
156 | |||
157 | static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs); | ||
158 | static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs); | ||
159 | |||
160 | #define __pending_tx(husb, type) (&husb->pending_tx[type-1]) | ||
161 | #define __pending_q(husb, type) (&husb->pending_q[type-1]) | ||
162 | #define __completed_q(husb, type) (&husb->completed_q[type-1]) | ||
163 | #define __transmit_q(husb, type) (&husb->transmit_q[type-1]) | ||
164 | #define __reassembly(husb, type) (husb->reassembly[type-1]) | ||
165 | |||
166 | static inline struct _urb *__get_completed(struct hci_usb *husb, int type) | ||
167 | { | ||
168 | return _urb_dequeue(__completed_q(husb, type)); | ||
169 | } | ||
170 | |||
171 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
172 | static void __fill_isoc_desc(struct urb *urb, int len, int mtu) | ||
173 | { | ||
174 | int offset = 0, i; | ||
175 | |||
176 | BT_DBG("len %d mtu %d", len, mtu); | ||
177 | |||
178 | for (i=0; i < HCI_MAX_ISOC_FRAMES && len >= mtu; i++, offset += mtu, len -= mtu) { | ||
179 | urb->iso_frame_desc[i].offset = offset; | ||
180 | urb->iso_frame_desc[i].length = mtu; | ||
181 | BT_DBG("desc %d offset %d len %d", i, offset, mtu); | ||
182 | } | ||
183 | if (len && i < HCI_MAX_ISOC_FRAMES) { | ||
184 | urb->iso_frame_desc[i].offset = offset; | ||
185 | urb->iso_frame_desc[i].length = len; | ||
186 | BT_DBG("desc %d offset %d len %d", i, offset, len); | ||
187 | i++; | ||
188 | } | ||
189 | urb->number_of_packets = i; | ||
190 | } | ||
191 | #endif | ||
192 | |||
193 | static int hci_usb_intr_rx_submit(struct hci_usb *husb) | ||
194 | { | ||
195 | struct _urb *_urb; | ||
196 | struct urb *urb; | ||
197 | int err, pipe, interval, size; | ||
198 | void *buf; | ||
199 | |||
200 | BT_DBG("%s", husb->hdev->name); | ||
201 | |||
202 | size = le16_to_cpu(husb->intr_in_ep->desc.wMaxPacketSize); | ||
203 | |||
204 | buf = kmalloc(size, GFP_ATOMIC); | ||
205 | if (!buf) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | _urb = _urb_alloc(0, GFP_ATOMIC); | ||
209 | if (!_urb) { | ||
210 | kfree(buf); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | _urb->type = HCI_EVENT_PKT; | ||
214 | _urb_queue_tail(__pending_q(husb, _urb->type), _urb); | ||
215 | |||
216 | urb = &_urb->urb; | ||
217 | pipe = usb_rcvintpipe(husb->udev, husb->intr_in_ep->desc.bEndpointAddress); | ||
218 | interval = husb->intr_in_ep->desc.bInterval; | ||
219 | usb_fill_int_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb, interval); | ||
220 | |||
221 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
222 | if (err) { | ||
223 | BT_ERR("%s intr rx submit failed urb %p err %d", | ||
224 | husb->hdev->name, urb, err); | ||
225 | _urb_unlink(_urb); | ||
226 | _urb_free(_urb); | ||
227 | kfree(buf); | ||
228 | } | ||
229 | return err; | ||
230 | } | ||
231 | |||
232 | static int hci_usb_bulk_rx_submit(struct hci_usb *husb) | ||
233 | { | ||
234 | struct _urb *_urb; | ||
235 | struct urb *urb; | ||
236 | int err, pipe, size = HCI_MAX_FRAME_SIZE; | ||
237 | void *buf; | ||
238 | |||
239 | buf = kmalloc(size, GFP_ATOMIC); | ||
240 | if (!buf) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | _urb = _urb_alloc(0, GFP_ATOMIC); | ||
244 | if (!_urb) { | ||
245 | kfree(buf); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | _urb->type = HCI_ACLDATA_PKT; | ||
249 | _urb_queue_tail(__pending_q(husb, _urb->type), _urb); | ||
250 | |||
251 | urb = &_urb->urb; | ||
252 | pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress); | ||
253 | usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb); | ||
254 | urb->transfer_flags = 0; | ||
255 | |||
256 | BT_DBG("%s urb %p", husb->hdev->name, urb); | ||
257 | |||
258 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
259 | if (err) { | ||
260 | BT_ERR("%s bulk rx submit failed urb %p err %d", | ||
261 | husb->hdev->name, urb, err); | ||
262 | _urb_unlink(_urb); | ||
263 | _urb_free(_urb); | ||
264 | kfree(buf); | ||
265 | } | ||
266 | return err; | ||
267 | } | ||
268 | |||
269 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
270 | static int hci_usb_isoc_rx_submit(struct hci_usb *husb) | ||
271 | { | ||
272 | struct _urb *_urb; | ||
273 | struct urb *urb; | ||
274 | int err, mtu, size; | ||
275 | void *buf; | ||
276 | |||
277 | mtu = le16_to_cpu(husb->isoc_in_ep->desc.wMaxPacketSize); | ||
278 | size = mtu * HCI_MAX_ISOC_FRAMES; | ||
279 | |||
280 | buf = kmalloc(size, GFP_ATOMIC); | ||
281 | if (!buf) | ||
282 | return -ENOMEM; | ||
283 | |||
284 | _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC); | ||
285 | if (!_urb) { | ||
286 | kfree(buf); | ||
287 | return -ENOMEM; | ||
288 | } | ||
289 | _urb->type = HCI_SCODATA_PKT; | ||
290 | _urb_queue_tail(__pending_q(husb, _urb->type), _urb); | ||
291 | |||
292 | urb = &_urb->urb; | ||
293 | |||
294 | urb->context = husb; | ||
295 | urb->dev = husb->udev; | ||
296 | urb->pipe = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress); | ||
297 | urb->complete = hci_usb_rx_complete; | ||
298 | |||
299 | urb->interval = husb->isoc_in_ep->desc.bInterval; | ||
300 | |||
301 | urb->transfer_buffer_length = size; | ||
302 | urb->transfer_buffer = buf; | ||
303 | urb->transfer_flags = URB_ISO_ASAP; | ||
304 | |||
305 | __fill_isoc_desc(urb, size, mtu); | ||
306 | |||
307 | BT_DBG("%s urb %p", husb->hdev->name, urb); | ||
308 | |||
309 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
310 | if (err) { | ||
311 | BT_ERR("%s isoc rx submit failed urb %p err %d", | ||
312 | husb->hdev->name, urb, err); | ||
313 | _urb_unlink(_urb); | ||
314 | _urb_free(_urb); | ||
315 | kfree(buf); | ||
316 | } | ||
317 | return err; | ||
318 | } | ||
319 | #endif | ||
320 | |||
321 | /* Initialize device */ | ||
322 | static int hci_usb_open(struct hci_dev *hdev) | ||
323 | { | ||
324 | struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; | ||
325 | int i, err; | ||
326 | unsigned long flags; | ||
327 | |||
328 | BT_DBG("%s", hdev->name); | ||
329 | |||
330 | if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) | ||
331 | return 0; | ||
332 | |||
333 | write_lock_irqsave(&husb->completion_lock, flags); | ||
334 | |||
335 | err = hci_usb_intr_rx_submit(husb); | ||
336 | if (!err) { | ||
337 | for (i = 0; i < HCI_MAX_BULK_RX; i++) | ||
338 | hci_usb_bulk_rx_submit(husb); | ||
339 | |||
340 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
341 | if (husb->isoc_iface) | ||
342 | for (i = 0; i < HCI_MAX_ISOC_RX; i++) | ||
343 | hci_usb_isoc_rx_submit(husb); | ||
344 | #endif | ||
345 | } else { | ||
346 | clear_bit(HCI_RUNNING, &hdev->flags); | ||
347 | } | ||
348 | |||
349 | write_unlock_irqrestore(&husb->completion_lock, flags); | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | /* Reset device */ | ||
354 | static int hci_usb_flush(struct hci_dev *hdev) | ||
355 | { | ||
356 | struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; | ||
357 | int i; | ||
358 | |||
359 | BT_DBG("%s", hdev->name); | ||
360 | |||
361 | for (i = 0; i < 4; i++) | ||
362 | skb_queue_purge(&husb->transmit_q[i]); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static void hci_usb_unlink_urbs(struct hci_usb *husb) | ||
367 | { | ||
368 | int i; | ||
369 | |||
370 | BT_DBG("%s", husb->hdev->name); | ||
371 | |||
372 | for (i = 0; i < 4; i++) { | ||
373 | struct _urb *_urb; | ||
374 | struct urb *urb; | ||
375 | |||
376 | /* Kill pending requests */ | ||
377 | while ((_urb = _urb_dequeue(&husb->pending_q[i]))) { | ||
378 | urb = &_urb->urb; | ||
379 | BT_DBG("%s unlinking _urb %p type %d urb %p", | ||
380 | husb->hdev->name, _urb, _urb->type, urb); | ||
381 | usb_kill_urb(urb); | ||
382 | _urb_queue_tail(__completed_q(husb, _urb->type), _urb); | ||
383 | } | ||
384 | |||
385 | /* Release completed requests */ | ||
386 | while ((_urb = _urb_dequeue(&husb->completed_q[i]))) { | ||
387 | urb = &_urb->urb; | ||
388 | BT_DBG("%s freeing _urb %p type %d urb %p", | ||
389 | husb->hdev->name, _urb, _urb->type, urb); | ||
390 | if (urb->setup_packet) | ||
391 | kfree(urb->setup_packet); | ||
392 | if (urb->transfer_buffer) | ||
393 | kfree(urb->transfer_buffer); | ||
394 | _urb_free(_urb); | ||
395 | } | ||
396 | |||
397 | /* Release reassembly buffers */ | ||
398 | if (husb->reassembly[i]) { | ||
399 | kfree_skb(husb->reassembly[i]); | ||
400 | husb->reassembly[i] = NULL; | ||
401 | } | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /* Close device */ | ||
406 | static int hci_usb_close(struct hci_dev *hdev) | ||
407 | { | ||
408 | struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; | ||
409 | unsigned long flags; | ||
410 | |||
411 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
412 | return 0; | ||
413 | |||
414 | BT_DBG("%s", hdev->name); | ||
415 | |||
416 | /* Synchronize with completion handlers */ | ||
417 | write_lock_irqsave(&husb->completion_lock, flags); | ||
418 | write_unlock_irqrestore(&husb->completion_lock, flags); | ||
419 | |||
420 | hci_usb_unlink_urbs(husb); | ||
421 | hci_usb_flush(hdev); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static int __tx_submit(struct hci_usb *husb, struct _urb *_urb) | ||
426 | { | ||
427 | struct urb *urb = &_urb->urb; | ||
428 | int err; | ||
429 | |||
430 | BT_DBG("%s urb %p type %d", husb->hdev->name, urb, _urb->type); | ||
431 | |||
432 | _urb_queue_tail(__pending_q(husb, _urb->type), _urb); | ||
433 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
434 | if (err) { | ||
435 | BT_ERR("%s tx submit failed urb %p type %d err %d", | ||
436 | husb->hdev->name, urb, _urb->type, err); | ||
437 | _urb_unlink(_urb); | ||
438 | _urb_queue_tail(__completed_q(husb, _urb->type), _urb); | ||
439 | } else | ||
440 | atomic_inc(__pending_tx(husb, _urb->type)); | ||
441 | |||
442 | return err; | ||
443 | } | ||
444 | |||
445 | static inline int hci_usb_send_ctrl(struct hci_usb *husb, struct sk_buff *skb) | ||
446 | { | ||
447 | struct _urb *_urb = __get_completed(husb, skb->pkt_type); | ||
448 | struct usb_ctrlrequest *dr; | ||
449 | struct urb *urb; | ||
450 | |||
451 | if (!_urb) { | ||
452 | _urb = _urb_alloc(0, GFP_ATOMIC); | ||
453 | if (!_urb) | ||
454 | return -ENOMEM; | ||
455 | _urb->type = skb->pkt_type; | ||
456 | |||
457 | dr = kmalloc(sizeof(*dr), GFP_ATOMIC); | ||
458 | if (!dr) { | ||
459 | _urb_free(_urb); | ||
460 | return -ENOMEM; | ||
461 | } | ||
462 | } else | ||
463 | dr = (void *) _urb->urb.setup_packet; | ||
464 | |||
465 | dr->bRequestType = husb->ctrl_req; | ||
466 | dr->bRequest = 0; | ||
467 | dr->wIndex = 0; | ||
468 | dr->wValue = 0; | ||
469 | dr->wLength = __cpu_to_le16(skb->len); | ||
470 | |||
471 | urb = &_urb->urb; | ||
472 | usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0), | ||
473 | (void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb); | ||
474 | |||
475 | BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); | ||
476 | |||
477 | _urb->priv = skb; | ||
478 | return __tx_submit(husb, _urb); | ||
479 | } | ||
480 | |||
481 | static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb) | ||
482 | { | ||
483 | struct _urb *_urb = __get_completed(husb, skb->pkt_type); | ||
484 | struct urb *urb; | ||
485 | int pipe; | ||
486 | |||
487 | if (!_urb) { | ||
488 | _urb = _urb_alloc(0, GFP_ATOMIC); | ||
489 | if (!_urb) | ||
490 | return -ENOMEM; | ||
491 | _urb->type = skb->pkt_type; | ||
492 | } | ||
493 | |||
494 | urb = &_urb->urb; | ||
495 | pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress); | ||
496 | usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len, | ||
497 | hci_usb_tx_complete, husb); | ||
498 | urb->transfer_flags = URB_ZERO_PACKET; | ||
499 | |||
500 | BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); | ||
501 | |||
502 | _urb->priv = skb; | ||
503 | return __tx_submit(husb, _urb); | ||
504 | } | ||
505 | |||
506 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
507 | static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb) | ||
508 | { | ||
509 | struct _urb *_urb = __get_completed(husb, skb->pkt_type); | ||
510 | struct urb *urb; | ||
511 | |||
512 | if (!_urb) { | ||
513 | _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC); | ||
514 | if (!_urb) | ||
515 | return -ENOMEM; | ||
516 | _urb->type = skb->pkt_type; | ||
517 | } | ||
518 | |||
519 | BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); | ||
520 | |||
521 | urb = &_urb->urb; | ||
522 | |||
523 | urb->context = husb; | ||
524 | urb->dev = husb->udev; | ||
525 | urb->pipe = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress); | ||
526 | urb->complete = hci_usb_tx_complete; | ||
527 | urb->transfer_flags = URB_ISO_ASAP; | ||
528 | |||
529 | urb->interval = husb->isoc_out_ep->desc.bInterval; | ||
530 | |||
531 | urb->transfer_buffer = skb->data; | ||
532 | urb->transfer_buffer_length = skb->len; | ||
533 | |||
534 | __fill_isoc_desc(urb, skb->len, le16_to_cpu(husb->isoc_out_ep->desc.wMaxPacketSize)); | ||
535 | |||
536 | _urb->priv = skb; | ||
537 | return __tx_submit(husb, _urb); | ||
538 | } | ||
539 | #endif | ||
540 | |||
541 | static void hci_usb_tx_process(struct hci_usb *husb) | ||
542 | { | ||
543 | struct sk_buff_head *q; | ||
544 | struct sk_buff *skb; | ||
545 | |||
546 | BT_DBG("%s", husb->hdev->name); | ||
547 | |||
548 | do { | ||
549 | clear_bit(HCI_USB_TX_WAKEUP, &husb->state); | ||
550 | |||
551 | /* Process command queue */ | ||
552 | q = __transmit_q(husb, HCI_COMMAND_PKT); | ||
553 | if (!atomic_read(__pending_tx(husb, HCI_COMMAND_PKT)) && | ||
554 | (skb = skb_dequeue(q))) { | ||
555 | if (hci_usb_send_ctrl(husb, skb) < 0) | ||
556 | skb_queue_head(q, skb); | ||
557 | } | ||
558 | |||
559 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
560 | /* Process SCO queue */ | ||
561 | q = __transmit_q(husb, HCI_SCODATA_PKT); | ||
562 | if (atomic_read(__pending_tx(husb, HCI_SCODATA_PKT)) < HCI_MAX_ISOC_TX && | ||
563 | (skb = skb_dequeue(q))) { | ||
564 | if (hci_usb_send_isoc(husb, skb) < 0) | ||
565 | skb_queue_head(q, skb); | ||
566 | } | ||
567 | #endif | ||
568 | |||
569 | /* Process ACL queue */ | ||
570 | q = __transmit_q(husb, HCI_ACLDATA_PKT); | ||
571 | while (atomic_read(__pending_tx(husb, HCI_ACLDATA_PKT)) < HCI_MAX_BULK_TX && | ||
572 | (skb = skb_dequeue(q))) { | ||
573 | if (hci_usb_send_bulk(husb, skb) < 0) { | ||
574 | skb_queue_head(q, skb); | ||
575 | break; | ||
576 | } | ||
577 | } | ||
578 | } while(test_bit(HCI_USB_TX_WAKEUP, &husb->state)); | ||
579 | } | ||
580 | |||
581 | static inline void hci_usb_tx_wakeup(struct hci_usb *husb) | ||
582 | { | ||
583 | /* Serialize TX queue processing to avoid data reordering */ | ||
584 | if (!test_and_set_bit(HCI_USB_TX_PROCESS, &husb->state)) { | ||
585 | hci_usb_tx_process(husb); | ||
586 | clear_bit(HCI_USB_TX_PROCESS, &husb->state); | ||
587 | } else | ||
588 | set_bit(HCI_USB_TX_WAKEUP, &husb->state); | ||
589 | } | ||
590 | |||
591 | /* Send frames from HCI layer */ | ||
592 | static int hci_usb_send_frame(struct sk_buff *skb) | ||
593 | { | ||
594 | struct hci_dev *hdev = (struct hci_dev *) skb->dev; | ||
595 | struct hci_usb *husb; | ||
596 | |||
597 | if (!hdev) { | ||
598 | BT_ERR("frame for uknown device (hdev=NULL)"); | ||
599 | return -ENODEV; | ||
600 | } | ||
601 | |||
602 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
603 | return -EBUSY; | ||
604 | |||
605 | BT_DBG("%s type %d len %d", hdev->name, skb->pkt_type, skb->len); | ||
606 | |||
607 | husb = (struct hci_usb *) hdev->driver_data; | ||
608 | |||
609 | switch (skb->pkt_type) { | ||
610 | case HCI_COMMAND_PKT: | ||
611 | hdev->stat.cmd_tx++; | ||
612 | break; | ||
613 | |||
614 | case HCI_ACLDATA_PKT: | ||
615 | hdev->stat.acl_tx++; | ||
616 | break; | ||
617 | |||
618 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
619 | case HCI_SCODATA_PKT: | ||
620 | hdev->stat.sco_tx++; | ||
621 | break; | ||
622 | #endif | ||
623 | |||
624 | default: | ||
625 | kfree_skb(skb); | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | read_lock(&husb->completion_lock); | ||
630 | |||
631 | skb_queue_tail(__transmit_q(husb, skb->pkt_type), skb); | ||
632 | hci_usb_tx_wakeup(husb); | ||
633 | |||
634 | read_unlock(&husb->completion_lock); | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count) | ||
639 | { | ||
640 | BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count); | ||
641 | |||
642 | husb->hdev->stat.byte_rx += count; | ||
643 | |||
644 | while (count) { | ||
645 | struct sk_buff *skb = __reassembly(husb, type); | ||
646 | struct { int expect; } *scb; | ||
647 | int len = 0; | ||
648 | |||
649 | if (!skb) { | ||
650 | /* Start of the frame */ | ||
651 | |||
652 | switch (type) { | ||
653 | case HCI_EVENT_PKT: | ||
654 | if (count >= HCI_EVENT_HDR_SIZE) { | ||
655 | struct hci_event_hdr *h = data; | ||
656 | len = HCI_EVENT_HDR_SIZE + h->plen; | ||
657 | } else | ||
658 | return -EILSEQ; | ||
659 | break; | ||
660 | |||
661 | case HCI_ACLDATA_PKT: | ||
662 | if (count >= HCI_ACL_HDR_SIZE) { | ||
663 | struct hci_acl_hdr *h = data; | ||
664 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); | ||
665 | } else | ||
666 | return -EILSEQ; | ||
667 | break; | ||
668 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
669 | case HCI_SCODATA_PKT: | ||
670 | if (count >= HCI_SCO_HDR_SIZE) { | ||
671 | struct hci_sco_hdr *h = data; | ||
672 | len = HCI_SCO_HDR_SIZE + h->dlen; | ||
673 | } else | ||
674 | return -EILSEQ; | ||
675 | break; | ||
676 | #endif | ||
677 | } | ||
678 | BT_DBG("new packet len %d", len); | ||
679 | |||
680 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
681 | if (!skb) { | ||
682 | BT_ERR("%s no memory for the packet", husb->hdev->name); | ||
683 | return -ENOMEM; | ||
684 | } | ||
685 | skb->dev = (void *) husb->hdev; | ||
686 | skb->pkt_type = type; | ||
687 | |||
688 | __reassembly(husb, type) = skb; | ||
689 | |||
690 | scb = (void *) skb->cb; | ||
691 | scb->expect = len; | ||
692 | } else { | ||
693 | /* Continuation */ | ||
694 | scb = (void *) skb->cb; | ||
695 | len = scb->expect; | ||
696 | } | ||
697 | |||
698 | len = min(len, count); | ||
699 | |||
700 | memcpy(skb_put(skb, len), data, len); | ||
701 | |||
702 | scb->expect -= len; | ||
703 | if (!scb->expect) { | ||
704 | /* Complete frame */ | ||
705 | __reassembly(husb, type) = NULL; | ||
706 | hci_recv_frame(skb); | ||
707 | } | ||
708 | |||
709 | count -= len; data += len; | ||
710 | } | ||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | static void hci_usb_rx_complete(struct urb *urb, struct pt_regs *regs) | ||
715 | { | ||
716 | struct _urb *_urb = container_of(urb, struct _urb, urb); | ||
717 | struct hci_usb *husb = (void *) urb->context; | ||
718 | struct hci_dev *hdev = husb->hdev; | ||
719 | int err, count = urb->actual_length; | ||
720 | |||
721 | BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb, | ||
722 | _urb->type, urb->status, count, urb->transfer_flags); | ||
723 | |||
724 | read_lock(&husb->completion_lock); | ||
725 | |||
726 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
727 | goto unlock; | ||
728 | |||
729 | if (urb->status || !count) | ||
730 | goto resubmit; | ||
731 | |||
732 | if (_urb->type == HCI_SCODATA_PKT) { | ||
733 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
734 | int i; | ||
735 | for (i=0; i < urb->number_of_packets; i++) { | ||
736 | BT_DBG("desc %d status %d offset %d len %d", i, | ||
737 | urb->iso_frame_desc[i].status, | ||
738 | urb->iso_frame_desc[i].offset, | ||
739 | urb->iso_frame_desc[i].actual_length); | ||
740 | |||
741 | if (!urb->iso_frame_desc[i].status) | ||
742 | __recv_frame(husb, _urb->type, | ||
743 | urb->transfer_buffer + urb->iso_frame_desc[i].offset, | ||
744 | urb->iso_frame_desc[i].actual_length); | ||
745 | } | ||
746 | #else | ||
747 | ; | ||
748 | #endif | ||
749 | } else { | ||
750 | err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count); | ||
751 | if (err < 0) { | ||
752 | BT_ERR("%s corrupted packet: type %d count %d", | ||
753 | husb->hdev->name, _urb->type, count); | ||
754 | hdev->stat.err_rx++; | ||
755 | } | ||
756 | } | ||
757 | |||
758 | resubmit: | ||
759 | urb->dev = husb->udev; | ||
760 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
761 | BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb, | ||
762 | _urb->type, err); | ||
763 | |||
764 | unlock: | ||
765 | read_unlock(&husb->completion_lock); | ||
766 | } | ||
767 | |||
768 | static void hci_usb_tx_complete(struct urb *urb, struct pt_regs *regs) | ||
769 | { | ||
770 | struct _urb *_urb = container_of(urb, struct _urb, urb); | ||
771 | struct hci_usb *husb = (void *) urb->context; | ||
772 | struct hci_dev *hdev = husb->hdev; | ||
773 | |||
774 | BT_DBG("%s urb %p status %d flags %x", hdev->name, urb, | ||
775 | urb->status, urb->transfer_flags); | ||
776 | |||
777 | atomic_dec(__pending_tx(husb, _urb->type)); | ||
778 | |||
779 | urb->transfer_buffer = NULL; | ||
780 | kfree_skb((struct sk_buff *) _urb->priv); | ||
781 | |||
782 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
783 | return; | ||
784 | |||
785 | if (!urb->status) | ||
786 | hdev->stat.byte_tx += urb->transfer_buffer_length; | ||
787 | else | ||
788 | hdev->stat.err_tx++; | ||
789 | |||
790 | read_lock(&husb->completion_lock); | ||
791 | |||
792 | _urb_unlink(_urb); | ||
793 | _urb_queue_tail(__completed_q(husb, _urb->type), _urb); | ||
794 | |||
795 | hci_usb_tx_wakeup(husb); | ||
796 | |||
797 | read_unlock(&husb->completion_lock); | ||
798 | } | ||
799 | |||
800 | static void hci_usb_destruct(struct hci_dev *hdev) | ||
801 | { | ||
802 | struct hci_usb *husb = (struct hci_usb *) hdev->driver_data; | ||
803 | |||
804 | BT_DBG("%s", hdev->name); | ||
805 | |||
806 | kfree(husb); | ||
807 | } | ||
808 | |||
809 | static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt) | ||
810 | { | ||
811 | BT_DBG("%s evt %d", hdev->name, evt); | ||
812 | } | ||
813 | |||
814 | static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
815 | { | ||
816 | struct usb_device *udev = interface_to_usbdev(intf); | ||
817 | struct usb_host_endpoint *bulk_out_ep = NULL; | ||
818 | struct usb_host_endpoint *bulk_in_ep = NULL; | ||
819 | struct usb_host_endpoint *intr_in_ep = NULL; | ||
820 | struct usb_host_endpoint *ep; | ||
821 | struct usb_host_interface *uif; | ||
822 | struct usb_interface *isoc_iface; | ||
823 | struct hci_usb *husb; | ||
824 | struct hci_dev *hdev; | ||
825 | int i, e, size, isoc_ifnum, isoc_alts; | ||
826 | |||
827 | BT_DBG("udev %p intf %p", udev, intf); | ||
828 | |||
829 | if (!id->driver_info) { | ||
830 | const struct usb_device_id *match; | ||
831 | match = usb_match_id(intf, blacklist_ids); | ||
832 | if (match) | ||
833 | id = match; | ||
834 | } | ||
835 | |||
836 | if (ignore || id->driver_info & HCI_IGNORE) | ||
837 | return -ENODEV; | ||
838 | |||
839 | if (intf->cur_altsetting->desc.bInterfaceNumber > 0) | ||
840 | return -ENODEV; | ||
841 | |||
842 | /* Find endpoints that we need */ | ||
843 | uif = intf->cur_altsetting; | ||
844 | for (e = 0; e < uif->desc.bNumEndpoints; e++) { | ||
845 | ep = &uif->endpoint[e]; | ||
846 | |||
847 | switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
848 | case USB_ENDPOINT_XFER_INT: | ||
849 | if (ep->desc.bEndpointAddress & USB_DIR_IN) | ||
850 | intr_in_ep = ep; | ||
851 | break; | ||
852 | |||
853 | case USB_ENDPOINT_XFER_BULK: | ||
854 | if (ep->desc.bEndpointAddress & USB_DIR_IN) | ||
855 | bulk_in_ep = ep; | ||
856 | else | ||
857 | bulk_out_ep = ep; | ||
858 | break; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) { | ||
863 | BT_DBG("Bulk endpoints not found"); | ||
864 | goto done; | ||
865 | } | ||
866 | |||
867 | if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { | ||
868 | BT_ERR("Can't allocate: control structure"); | ||
869 | goto done; | ||
870 | } | ||
871 | |||
872 | memset(husb, 0, sizeof(struct hci_usb)); | ||
873 | |||
874 | husb->udev = udev; | ||
875 | husb->bulk_out_ep = bulk_out_ep; | ||
876 | husb->bulk_in_ep = bulk_in_ep; | ||
877 | husb->intr_in_ep = intr_in_ep; | ||
878 | |||
879 | if (id->driver_info & HCI_DIGIANSWER) | ||
880 | husb->ctrl_req = USB_TYPE_VENDOR; | ||
881 | else | ||
882 | husb->ctrl_req = USB_TYPE_CLASS; | ||
883 | |||
884 | /* Find isochronous endpoints that we can use */ | ||
885 | size = 0; | ||
886 | isoc_iface = NULL; | ||
887 | isoc_alts = 0; | ||
888 | isoc_ifnum = 1; | ||
889 | |||
890 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
891 | if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER))) | ||
892 | isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum); | ||
893 | |||
894 | if (isoc_iface) { | ||
895 | int a; | ||
896 | struct usb_host_endpoint *isoc_out_ep = NULL; | ||
897 | struct usb_host_endpoint *isoc_in_ep = NULL; | ||
898 | |||
899 | for (a = 0; a < isoc_iface->num_altsetting; a++) { | ||
900 | uif = &isoc_iface->altsetting[a]; | ||
901 | for (e = 0; e < uif->desc.bNumEndpoints; e++) { | ||
902 | ep = &uif->endpoint[e]; | ||
903 | |||
904 | switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
905 | case USB_ENDPOINT_XFER_ISOC: | ||
906 | if (le16_to_cpu(ep->desc.wMaxPacketSize) < size || | ||
907 | uif->desc.bAlternateSetting != isoc) | ||
908 | break; | ||
909 | size = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
910 | |||
911 | isoc_alts = uif->desc.bAlternateSetting; | ||
912 | |||
913 | if (ep->desc.bEndpointAddress & USB_DIR_IN) | ||
914 | isoc_in_ep = ep; | ||
915 | else | ||
916 | isoc_out_ep = ep; | ||
917 | break; | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | |||
922 | if (!isoc_in_ep || !isoc_out_ep) | ||
923 | BT_DBG("Isoc endpoints not found"); | ||
924 | else { | ||
925 | BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts); | ||
926 | if (usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb) != 0) | ||
927 | BT_ERR("Can't claim isoc interface"); | ||
928 | else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) { | ||
929 | BT_ERR("Can't set isoc interface settings"); | ||
930 | husb->isoc_iface = isoc_iface; | ||
931 | usb_driver_release_interface(&hci_usb_driver, isoc_iface); | ||
932 | husb->isoc_iface = NULL; | ||
933 | } else { | ||
934 | husb->isoc_iface = isoc_iface; | ||
935 | husb->isoc_in_ep = isoc_in_ep; | ||
936 | husb->isoc_out_ep = isoc_out_ep; | ||
937 | } | ||
938 | } | ||
939 | } | ||
940 | #endif | ||
941 | |||
942 | rwlock_init(&husb->completion_lock); | ||
943 | |||
944 | for (i = 0; i < 4; i++) { | ||
945 | skb_queue_head_init(&husb->transmit_q[i]); | ||
946 | _urb_queue_init(&husb->pending_q[i]); | ||
947 | _urb_queue_init(&husb->completed_q[i]); | ||
948 | } | ||
949 | |||
950 | /* Initialize and register HCI device */ | ||
951 | hdev = hci_alloc_dev(); | ||
952 | if (!hdev) { | ||
953 | BT_ERR("Can't allocate HCI device"); | ||
954 | goto probe_error; | ||
955 | } | ||
956 | |||
957 | husb->hdev = hdev; | ||
958 | |||
959 | hdev->type = HCI_USB; | ||
960 | hdev->driver_data = husb; | ||
961 | SET_HCIDEV_DEV(hdev, &intf->dev); | ||
962 | |||
963 | hdev->open = hci_usb_open; | ||
964 | hdev->close = hci_usb_close; | ||
965 | hdev->flush = hci_usb_flush; | ||
966 | hdev->send = hci_usb_send_frame; | ||
967 | hdev->destruct = hci_usb_destruct; | ||
968 | hdev->notify = hci_usb_notify; | ||
969 | |||
970 | hdev->owner = THIS_MODULE; | ||
971 | |||
972 | if (reset || id->driver_info & HCI_RESET) | ||
973 | set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); | ||
974 | |||
975 | if (id->driver_info & HCI_SNIFFER) { | ||
976 | if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) | ||
977 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | ||
978 | } | ||
979 | |||
980 | if (id->driver_info & HCI_BCM92035) { | ||
981 | unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 }; | ||
982 | struct sk_buff *skb; | ||
983 | |||
984 | skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); | ||
985 | if (skb) { | ||
986 | memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd)); | ||
987 | skb_queue_tail(&hdev->driver_init, skb); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | if (hci_register_dev(hdev) < 0) { | ||
992 | BT_ERR("Can't register HCI device"); | ||
993 | hci_free_dev(hdev); | ||
994 | goto probe_error; | ||
995 | } | ||
996 | |||
997 | usb_set_intfdata(intf, husb); | ||
998 | return 0; | ||
999 | |||
1000 | probe_error: | ||
1001 | if (husb->isoc_iface) | ||
1002 | usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface); | ||
1003 | kfree(husb); | ||
1004 | |||
1005 | done: | ||
1006 | return -EIO; | ||
1007 | } | ||
1008 | |||
1009 | static void hci_usb_disconnect(struct usb_interface *intf) | ||
1010 | { | ||
1011 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
1012 | struct hci_dev *hdev; | ||
1013 | |||
1014 | if (!husb || intf == husb->isoc_iface) | ||
1015 | return; | ||
1016 | |||
1017 | usb_set_intfdata(intf, NULL); | ||
1018 | hdev = husb->hdev; | ||
1019 | |||
1020 | BT_DBG("%s", hdev->name); | ||
1021 | |||
1022 | hci_usb_close(hdev); | ||
1023 | |||
1024 | if (husb->isoc_iface) | ||
1025 | usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface); | ||
1026 | |||
1027 | if (hci_unregister_dev(hdev) < 0) | ||
1028 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
1029 | |||
1030 | hci_free_dev(hdev); | ||
1031 | } | ||
1032 | |||
1033 | static struct usb_driver hci_usb_driver = { | ||
1034 | .owner = THIS_MODULE, | ||
1035 | .name = "hci_usb", | ||
1036 | .probe = hci_usb_probe, | ||
1037 | .disconnect = hci_usb_disconnect, | ||
1038 | .id_table = bluetooth_ids, | ||
1039 | }; | ||
1040 | |||
1041 | static int __init hci_usb_init(void) | ||
1042 | { | ||
1043 | int err; | ||
1044 | |||
1045 | BT_INFO("HCI USB driver ver %s", VERSION); | ||
1046 | |||
1047 | if ((err = usb_register(&hci_usb_driver)) < 0) | ||
1048 | BT_ERR("Failed to register HCI USB driver"); | ||
1049 | |||
1050 | return err; | ||
1051 | } | ||
1052 | |||
1053 | static void __exit hci_usb_exit(void) | ||
1054 | { | ||
1055 | usb_deregister(&hci_usb_driver); | ||
1056 | } | ||
1057 | |||
1058 | module_init(hci_usb_init); | ||
1059 | module_exit(hci_usb_exit); | ||
1060 | |||
1061 | module_param(ignore, bool, 0644); | ||
1062 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); | ||
1063 | |||
1064 | module_param(reset, bool, 0644); | ||
1065 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); | ||
1066 | |||
1067 | #ifdef CONFIG_BT_HCIUSB_SCO | ||
1068 | module_param(isoc, int, 0644); | ||
1069 | MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support"); | ||
1070 | #endif | ||
1071 | |||
1072 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>"); | ||
1073 | MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); | ||
1074 | MODULE_VERSION(VERSION); | ||
1075 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h new file mode 100644 index 000000000000..29936b43d4f8 --- /dev/null +++ b/drivers/bluetooth/hci_usb.h | |||
@@ -0,0 +1,128 @@ | |||
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 | ||
34 | #define HCI_SNIFFER 0x08 | ||
35 | #define HCI_BROKEN_ISOC 0x10 | ||
36 | #define HCI_BCM92035 0x20 | ||
37 | |||
38 | #define HCI_MAX_IFACE_NUM 3 | ||
39 | |||
40 | #define HCI_MAX_BULK_TX 4 | ||
41 | #define HCI_MAX_BULK_RX 1 | ||
42 | |||
43 | #define HCI_MAX_ISOC_RX 2 | ||
44 | #define HCI_MAX_ISOC_TX 2 | ||
45 | |||
46 | #define HCI_MAX_ISOC_FRAMES 10 | ||
47 | |||
48 | struct _urb_queue { | ||
49 | struct list_head head; | ||
50 | spinlock_t lock; | ||
51 | }; | ||
52 | |||
53 | struct _urb { | ||
54 | struct list_head list; | ||
55 | struct _urb_queue *queue; | ||
56 | int type; | ||
57 | void *priv; | ||
58 | struct urb urb; | ||
59 | }; | ||
60 | |||
61 | static inline void _urb_free(struct _urb *_urb) | ||
62 | { | ||
63 | kfree(_urb); | ||
64 | } | ||
65 | |||
66 | static inline void _urb_queue_init(struct _urb_queue *q) | ||
67 | { | ||
68 | INIT_LIST_HEAD(&q->head); | ||
69 | spin_lock_init(&q->lock); | ||
70 | } | ||
71 | |||
72 | static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb) | ||
73 | { | ||
74 | unsigned long flags; | ||
75 | spin_lock_irqsave(&q->lock, flags); | ||
76 | list_add(&_urb->list, &q->head); _urb->queue = q; | ||
77 | spin_unlock_irqrestore(&q->lock, flags); | ||
78 | } | ||
79 | |||
80 | static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb) | ||
81 | { | ||
82 | unsigned long flags; | ||
83 | spin_lock_irqsave(&q->lock, flags); | ||
84 | list_add_tail(&_urb->list, &q->head); _urb->queue = q; | ||
85 | spin_unlock_irqrestore(&q->lock, flags); | ||
86 | } | ||
87 | |||
88 | static inline void _urb_unlink(struct _urb *_urb) | ||
89 | { | ||
90 | struct _urb_queue *q = _urb->queue; | ||
91 | unsigned long flags; | ||
92 | if (q) { | ||
93 | spin_lock_irqsave(&q->lock, flags); | ||
94 | list_del(&_urb->list); _urb->queue = NULL; | ||
95 | spin_unlock_irqrestore(&q->lock, flags); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | struct hci_usb { | ||
100 | struct hci_dev *hdev; | ||
101 | |||
102 | unsigned long state; | ||
103 | |||
104 | struct usb_device *udev; | ||
105 | |||
106 | struct usb_host_endpoint *bulk_in_ep; | ||
107 | struct usb_host_endpoint *bulk_out_ep; | ||
108 | struct usb_host_endpoint *intr_in_ep; | ||
109 | |||
110 | struct usb_interface *isoc_iface; | ||
111 | struct usb_host_endpoint *isoc_out_ep; | ||
112 | struct usb_host_endpoint *isoc_in_ep; | ||
113 | |||
114 | __u8 ctrl_req; | ||
115 | |||
116 | struct sk_buff_head transmit_q[4]; | ||
117 | struct sk_buff *reassembly[4]; /* Reassembly buffers */ | ||
118 | |||
119 | rwlock_t completion_lock; | ||
120 | |||
121 | atomic_t pending_tx[4]; /* Number of pending requests */ | ||
122 | struct _urb_queue pending_q[4]; /* Pending requests */ | ||
123 | struct _urb_queue completed_q[4]; /* Completed requests */ | ||
124 | }; | ||
125 | |||
126 | /* States */ | ||
127 | #define HCI_USB_TX_PROCESS 1 | ||
128 | #define HCI_USB_TX_WAKEUP 2 | ||
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c new file mode 100644 index 000000000000..3256192dcde8 --- /dev/null +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Bluetooth HCI virtual device driver. | ||
27 | * | ||
28 | * $Id: hci_vhci.c,v 1.3 2002/04/17 17:37:20 maxk Exp $ | ||
29 | */ | ||
30 | #define VERSION "1.1" | ||
31 | |||
32 | #include <linux/config.h> | ||
33 | #include <linux/module.h> | ||
34 | |||
35 | #include <linux/errno.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/major.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/poll.h> | ||
41 | #include <linux/fcntl.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/random.h> | ||
44 | |||
45 | #include <linux/skbuff.h> | ||
46 | #include <linux/miscdevice.h> | ||
47 | |||
48 | #include <asm/system.h> | ||
49 | #include <asm/uaccess.h> | ||
50 | |||
51 | #include <net/bluetooth/bluetooth.h> | ||
52 | #include <net/bluetooth/hci_core.h> | ||
53 | #include "hci_vhci.h" | ||
54 | |||
55 | /* HCI device part */ | ||
56 | |||
57 | static int hci_vhci_open(struct hci_dev *hdev) | ||
58 | { | ||
59 | set_bit(HCI_RUNNING, &hdev->flags); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int hci_vhci_flush(struct hci_dev *hdev) | ||
64 | { | ||
65 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) hdev->driver_data; | ||
66 | skb_queue_purge(&hci_vhci->readq); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int hci_vhci_close(struct hci_dev *hdev) | ||
71 | { | ||
72 | if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) | ||
73 | return 0; | ||
74 | |||
75 | hci_vhci_flush(hdev); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static void hci_vhci_destruct(struct hci_dev *hdev) | ||
80 | { | ||
81 | struct hci_vhci_struct *vhci; | ||
82 | |||
83 | if (!hdev) return; | ||
84 | |||
85 | vhci = (struct hci_vhci_struct *) hdev->driver_data; | ||
86 | kfree(vhci); | ||
87 | } | ||
88 | |||
89 | static int hci_vhci_send_frame(struct sk_buff *skb) | ||
90 | { | ||
91 | struct hci_dev* hdev = (struct hci_dev *) skb->dev; | ||
92 | struct hci_vhci_struct *hci_vhci; | ||
93 | |||
94 | if (!hdev) { | ||
95 | BT_ERR("Frame for uknown device (hdev=NULL)"); | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | if (!test_bit(HCI_RUNNING, &hdev->flags)) | ||
100 | return -EBUSY; | ||
101 | |||
102 | hci_vhci = (struct hci_vhci_struct *) hdev->driver_data; | ||
103 | |||
104 | memcpy(skb_push(skb, 1), &skb->pkt_type, 1); | ||
105 | skb_queue_tail(&hci_vhci->readq, skb); | ||
106 | |||
107 | if (hci_vhci->flags & VHCI_FASYNC) | ||
108 | kill_fasync(&hci_vhci->fasync, SIGIO, POLL_IN); | ||
109 | wake_up_interruptible(&hci_vhci->read_wait); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* Character device part */ | ||
115 | |||
116 | /* Poll */ | ||
117 | static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait) | ||
118 | { | ||
119 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; | ||
120 | |||
121 | poll_wait(file, &hci_vhci->read_wait, wait); | ||
122 | |||
123 | if (skb_queue_len(&hci_vhci->readq)) | ||
124 | return POLLIN | POLLRDNORM; | ||
125 | |||
126 | return POLLOUT | POLLWRNORM; | ||
127 | } | ||
128 | |||
129 | /* Get packet from user space buffer(already verified) */ | ||
130 | static inline ssize_t hci_vhci_get_user(struct hci_vhci_struct *hci_vhci, const char __user *buf, size_t count) | ||
131 | { | ||
132 | struct sk_buff *skb; | ||
133 | |||
134 | if (count > HCI_MAX_FRAME_SIZE) | ||
135 | return -EINVAL; | ||
136 | |||
137 | if (!(skb = bt_skb_alloc(count, GFP_KERNEL))) | ||
138 | return -ENOMEM; | ||
139 | |||
140 | if (copy_from_user(skb_put(skb, count), buf, count)) { | ||
141 | kfree_skb(skb); | ||
142 | return -EFAULT; | ||
143 | } | ||
144 | |||
145 | skb->dev = (void *) hci_vhci->hdev; | ||
146 | skb->pkt_type = *((__u8 *) skb->data); | ||
147 | skb_pull(skb, 1); | ||
148 | |||
149 | hci_recv_frame(skb); | ||
150 | |||
151 | return count; | ||
152 | } | ||
153 | |||
154 | /* Write */ | ||
155 | static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf, | ||
156 | size_t count, loff_t *pos) | ||
157 | { | ||
158 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; | ||
159 | |||
160 | if (!access_ok(VERIFY_READ, buf, count)) | ||
161 | return -EFAULT; | ||
162 | |||
163 | return hci_vhci_get_user(hci_vhci, buf, count); | ||
164 | } | ||
165 | |||
166 | /* Put packet to user space buffer(already verified) */ | ||
167 | static inline ssize_t hci_vhci_put_user(struct hci_vhci_struct *hci_vhci, | ||
168 | struct sk_buff *skb, char __user *buf, | ||
169 | int count) | ||
170 | { | ||
171 | int len = count, total = 0; | ||
172 | char __user *ptr = buf; | ||
173 | |||
174 | len = min_t(unsigned int, skb->len, len); | ||
175 | if (copy_to_user(ptr, skb->data, len)) | ||
176 | return -EFAULT; | ||
177 | total += len; | ||
178 | |||
179 | hci_vhci->hdev->stat.byte_tx += len; | ||
180 | switch (skb->pkt_type) { | ||
181 | case HCI_COMMAND_PKT: | ||
182 | hci_vhci->hdev->stat.cmd_tx++; | ||
183 | break; | ||
184 | |||
185 | case HCI_ACLDATA_PKT: | ||
186 | hci_vhci->hdev->stat.acl_tx++; | ||
187 | break; | ||
188 | |||
189 | case HCI_SCODATA_PKT: | ||
190 | hci_vhci->hdev->stat.cmd_tx++; | ||
191 | break; | ||
192 | }; | ||
193 | |||
194 | return total; | ||
195 | } | ||
196 | |||
197 | /* Read */ | ||
198 | static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t count, loff_t *pos) | ||
199 | { | ||
200 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; | ||
201 | DECLARE_WAITQUEUE(wait, current); | ||
202 | struct sk_buff *skb; | ||
203 | ssize_t ret = 0; | ||
204 | |||
205 | add_wait_queue(&hci_vhci->read_wait, &wait); | ||
206 | while (count) { | ||
207 | set_current_state(TASK_INTERRUPTIBLE); | ||
208 | |||
209 | /* Read frames from device queue */ | ||
210 | if (!(skb = skb_dequeue(&hci_vhci->readq))) { | ||
211 | if (file->f_flags & O_NONBLOCK) { | ||
212 | ret = -EAGAIN; | ||
213 | break; | ||
214 | } | ||
215 | if (signal_pending(current)) { | ||
216 | ret = -ERESTARTSYS; | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | /* Nothing to read, let's sleep */ | ||
221 | schedule(); | ||
222 | continue; | ||
223 | } | ||
224 | |||
225 | if (access_ok(VERIFY_WRITE, buf, count)) | ||
226 | ret = hci_vhci_put_user(hci_vhci, skb, buf, count); | ||
227 | else | ||
228 | ret = -EFAULT; | ||
229 | |||
230 | kfree_skb(skb); | ||
231 | break; | ||
232 | } | ||
233 | set_current_state(TASK_RUNNING); | ||
234 | remove_wait_queue(&hci_vhci->read_wait, &wait); | ||
235 | |||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static loff_t hci_vhci_chr_lseek(struct file * file, loff_t offset, int origin) | ||
240 | { | ||
241 | return -ESPIPE; | ||
242 | } | ||
243 | |||
244 | static int hci_vhci_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
245 | { | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | |||
249 | static int hci_vhci_chr_fasync(int fd, struct file *file, int on) | ||
250 | { | ||
251 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; | ||
252 | int ret; | ||
253 | |||
254 | if ((ret = fasync_helper(fd, file, on, &hci_vhci->fasync)) < 0) | ||
255 | return ret; | ||
256 | |||
257 | if (on) | ||
258 | hci_vhci->flags |= VHCI_FASYNC; | ||
259 | else | ||
260 | hci_vhci->flags &= ~VHCI_FASYNC; | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int hci_vhci_chr_open(struct inode *inode, struct file * file) | ||
266 | { | ||
267 | struct hci_vhci_struct *hci_vhci = NULL; | ||
268 | struct hci_dev *hdev; | ||
269 | |||
270 | if (!(hci_vhci = kmalloc(sizeof(struct hci_vhci_struct), GFP_KERNEL))) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | memset(hci_vhci, 0, sizeof(struct hci_vhci_struct)); | ||
274 | |||
275 | skb_queue_head_init(&hci_vhci->readq); | ||
276 | init_waitqueue_head(&hci_vhci->read_wait); | ||
277 | |||
278 | /* Initialize and register HCI device */ | ||
279 | hdev = hci_alloc_dev(); | ||
280 | if (!hdev) { | ||
281 | kfree(hci_vhci); | ||
282 | return -ENOMEM; | ||
283 | } | ||
284 | |||
285 | hci_vhci->hdev = hdev; | ||
286 | |||
287 | hdev->type = HCI_VHCI; | ||
288 | hdev->driver_data = hci_vhci; | ||
289 | |||
290 | hdev->open = hci_vhci_open; | ||
291 | hdev->close = hci_vhci_close; | ||
292 | hdev->flush = hci_vhci_flush; | ||
293 | hdev->send = hci_vhci_send_frame; | ||
294 | hdev->destruct = hci_vhci_destruct; | ||
295 | |||
296 | hdev->owner = THIS_MODULE; | ||
297 | |||
298 | if (hci_register_dev(hdev) < 0) { | ||
299 | kfree(hci_vhci); | ||
300 | hci_free_dev(hdev); | ||
301 | return -EBUSY; | ||
302 | } | ||
303 | |||
304 | file->private_data = hci_vhci; | ||
305 | return nonseekable_open(inode, file); | ||
306 | } | ||
307 | |||
308 | static int hci_vhci_chr_close(struct inode *inode, struct file *file) | ||
309 | { | ||
310 | struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; | ||
311 | struct hci_dev *hdev = hci_vhci->hdev; | ||
312 | |||
313 | if (hci_unregister_dev(hdev) < 0) { | ||
314 | BT_ERR("Can't unregister HCI device %s", hdev->name); | ||
315 | } | ||
316 | |||
317 | hci_free_dev(hdev); | ||
318 | |||
319 | file->private_data = NULL; | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static struct file_operations hci_vhci_fops = { | ||
324 | .owner = THIS_MODULE, | ||
325 | .llseek = hci_vhci_chr_lseek, | ||
326 | .read = hci_vhci_chr_read, | ||
327 | .write = hci_vhci_chr_write, | ||
328 | .poll = hci_vhci_chr_poll, | ||
329 | .ioctl = hci_vhci_chr_ioctl, | ||
330 | .open = hci_vhci_chr_open, | ||
331 | .release = hci_vhci_chr_close, | ||
332 | .fasync = hci_vhci_chr_fasync | ||
333 | }; | ||
334 | |||
335 | static struct miscdevice hci_vhci_miscdev= | ||
336 | { | ||
337 | VHCI_MINOR, | ||
338 | "hci_vhci", | ||
339 | &hci_vhci_fops | ||
340 | }; | ||
341 | |||
342 | static int __init hci_vhci_init(void) | ||
343 | { | ||
344 | BT_INFO("VHCI driver ver %s", VERSION); | ||
345 | |||
346 | if (misc_register(&hci_vhci_miscdev)) { | ||
347 | BT_ERR("Can't register misc device %d\n", VHCI_MINOR); | ||
348 | return -EIO; | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static void hci_vhci_cleanup(void) | ||
355 | { | ||
356 | misc_deregister(&hci_vhci_miscdev); | ||
357 | } | ||
358 | |||
359 | module_init(hci_vhci_init); | ||
360 | module_exit(hci_vhci_cleanup); | ||
361 | |||
362 | MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>"); | ||
363 | MODULE_DESCRIPTION("Bluetooth VHCI driver ver " VERSION); | ||
364 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/bluetooth/hci_vhci.h b/drivers/bluetooth/hci_vhci.h new file mode 100644 index 000000000000..53b11f9ef76d --- /dev/null +++ b/drivers/bluetooth/hci_vhci.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | BlueZ - Bluetooth protocol stack for Linux | ||
3 | Copyright (C) 2000-2001 Qualcomm Incorporated | ||
4 | |||
5 | Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License version 2 as | ||
9 | published by the Free Software Foundation; | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
12 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
14 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
15 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
16 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | |||
20 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
21 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
22 | SOFTWARE IS DISCLAIMED. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * $Id: hci_vhci.h,v 1.1.1.1 2002/03/08 21:03:15 maxk Exp $ | ||
27 | */ | ||
28 | |||
29 | #ifndef __HCI_VHCI_H | ||
30 | #define __HCI_VHCI_H | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | struct hci_vhci_struct { | ||
35 | struct hci_dev *hdev; | ||
36 | __u32 flags; | ||
37 | wait_queue_head_t read_wait; | ||
38 | struct sk_buff_head readq; | ||
39 | struct fasync_struct *fasync; | ||
40 | }; | ||
41 | |||
42 | /* VHCI device flags */ | ||
43 | #define VHCI_FASYNC 0x0010 | ||
44 | |||
45 | #endif /* __KERNEL__ */ | ||
46 | |||
47 | #define VHCI_DEV "/dev/vhci" | ||
48 | #define VHCI_MINOR 250 | ||
49 | |||
50 | #endif /* __HCI_VHCI_H */ | ||