Blame view
drivers/bluetooth/bcm203x.c
6.79 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* * * Broadcom Blutonium firmware driver * * Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2003 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include <linux/module.h> |
fc501ad7a Bluetooth: bcm203... |
25 |
#include <linux/atomic.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 29 30 |
#include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 36 37 |
#include <linux/device.h> #include <linux/firmware.h> #include <linux/usb.h> #include <net/bluetooth/bluetooth.h> |
943d56b0a [Bluetooth] Remov... |
38 |
#define VERSION "1.2" |
1da177e4c Linux-2.6.12-rc2 |
39 |
|
8978111e2 Bluetooth: Make U... |
40 |
static const struct usb_device_id bcm203x_table[] = { |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
/* Broadcom Blutonium (BCM2033) */ { USB_DEVICE(0x0a5c, 0x2033) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, bcm203x_table); #define BCM203X_ERROR 0 #define BCM203X_RESET 1 #define BCM203X_LOAD_MINIDRV 2 #define BCM203X_SELECT_MEMORY 3 #define BCM203X_CHECK_MEMORY 4 #define BCM203X_LOAD_FIRMWARE 5 #define BCM203X_CHECK_FIRMWARE 6 #define BCM203X_IN_EP 0x81 #define BCM203X_OUT_EP 0x02 struct bcm203x_data { struct usb_device *udev; unsigned long state; |
3f5306927 [Bluetooth] Use w... |
64 |
struct work_struct work; |
fc501ad7a Bluetooth: bcm203... |
65 |
atomic_t shutdown; |
1da177e4c Linux-2.6.12-rc2 |
66 67 68 69 70 71 72 73 |
struct urb *urb; unsigned char *buffer; unsigned char *fw_data; unsigned int fw_size; unsigned int fw_sent; }; |
7d12e780e IRQ: Maintain reg... |
74 |
static void bcm203x_complete(struct urb *urb) |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
{ struct bcm203x_data *data = urb->context; struct usb_device *udev = urb->dev; int len; BT_DBG("udev %p urb %p", udev, urb); if (urb->status) { BT_ERR("URB failed with status %d", urb->status); data->state = BCM203X_ERROR; return; } switch (data->state) { case BCM203X_LOAD_MINIDRV: memcpy(data->buffer, "#", 1); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), data->buffer, 1, bcm203x_complete, data); data->state = BCM203X_SELECT_MEMORY; |
fc501ad7a Bluetooth: bcm203... |
96 |
/* use workqueue to have a small delay */ |
3f5306927 [Bluetooth] Use w... |
97 |
schedule_work(&data->work); |
1da177e4c Linux-2.6.12-rc2 |
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
break; case BCM203X_SELECT_MEMORY: usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), data->buffer, 32, bcm203x_complete, data, 1); data->state = BCM203X_CHECK_MEMORY; if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); break; case BCM203X_CHECK_MEMORY: if (data->buffer[0] != '#') { BT_ERR("Memory select failed"); data->state = BCM203X_ERROR; break; } data->state = BCM203X_LOAD_FIRMWARE; case BCM203X_LOAD_FIRMWARE: if (data->fw_sent == data->fw_size) { usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), data->buffer, 32, bcm203x_complete, data, 1); data->state = BCM203X_CHECK_FIRMWARE; } else { len = min_t(uint, data->fw_size - data->fw_sent, 4096); usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), data->fw_data + data->fw_sent, len, bcm203x_complete, data); data->fw_sent += len; } if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); break; case BCM203X_CHECK_FIRMWARE: if (data->buffer[0] != '.') { BT_ERR("Firmware loading failed"); data->state = BCM203X_ERROR; break; } data->state = BCM203X_RESET; break; } } |
c4028958b WorkStruct: make ... |
149 |
static void bcm203x_work(struct work_struct *work) |
1da177e4c Linux-2.6.12-rc2 |
150 |
{ |
c4028958b WorkStruct: make ... |
151 152 |
struct bcm203x_data *data = container_of(work, struct bcm203x_data, work); |
1da177e4c Linux-2.6.12-rc2 |
153 |
|
fc501ad7a Bluetooth: bcm203... |
154 155 |
if (atomic_read(&data->shutdown)) return; |
b91a4e3e3 Bluetooth: bcm203... |
156 |
if (usb_submit_urb(data->urb, GFP_KERNEL) < 0) |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 162 163 164 165 166 167 |
BT_ERR("Can't submit URB"); } static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id) { const struct firmware *firmware; struct usb_device *udev = interface_to_usbdev(intf); struct bcm203x_data *data; int size; BT_DBG("intf %p id %p", intf, id); |
943d56b0a [Bluetooth] Remov... |
168 |
if (intf->cur_altsetting->desc.bInterfaceNumber != 0) |
1da177e4c Linux-2.6.12-rc2 |
169 |
return -ENODEV; |
089b1dbbd [PATCH] bluetooth... |
170 |
data = kzalloc(sizeof(*data), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
171 172 173 174 |
if (!data) { BT_ERR("Can't allocate memory for data structure"); return -ENOMEM; } |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
data->udev = udev; data->state = BCM203X_LOAD_MINIDRV; data->urb = usb_alloc_urb(0, GFP_KERNEL); if (!data->urb) { BT_ERR("Can't allocate URB"); kfree(data); return -ENOMEM; } if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { BT_ERR("Mini driver request failed"); usb_free_urb(data->urb); kfree(data); return -EIO; } |
a418b893a Bluetooth: Enable... |
191 |
BT_DBG("minidrv data %p size %zu", firmware->data, firmware->size); |
1da177e4c Linux-2.6.12-rc2 |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
size = max_t(uint, firmware->size, 4096); data->buffer = kmalloc(size, GFP_KERNEL); if (!data->buffer) { BT_ERR("Can't allocate memory for mini driver"); release_firmware(firmware); usb_free_urb(data->urb); kfree(data); return -ENOMEM; } memcpy(data->buffer, firmware->data, firmware->size); usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), data->buffer, firmware->size, bcm203x_complete, data); release_firmware(firmware); if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) { BT_ERR("Firmware request failed"); usb_free_urb(data->urb); kfree(data->buffer); kfree(data); return -EIO; } |
a418b893a Bluetooth: Enable... |
218 |
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); |
1da177e4c Linux-2.6.12-rc2 |
219 |
|
5ee283c06 Bluetooth: Use km... |
220 |
data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
221 222 |
if (!data->fw_data) { BT_ERR("Can't allocate memory for firmware image"); |
73ca66b97 [PATCH] release_f... |
223 |
release_firmware(firmware); |
1da177e4c Linux-2.6.12-rc2 |
224 225 226 227 228 |
usb_free_urb(data->urb); kfree(data->buffer); kfree(data); return -ENOMEM; } |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 232 |
data->fw_size = firmware->size; data->fw_sent = 0; release_firmware(firmware); |
c4028958b WorkStruct: make ... |
233 |
INIT_WORK(&data->work, bcm203x_work); |
1da177e4c Linux-2.6.12-rc2 |
234 235 |
usb_set_intfdata(intf, data); |
fc501ad7a Bluetooth: bcm203... |
236 |
/* use workqueue to have a small delay */ |
3f5306927 [Bluetooth] Use w... |
237 |
schedule_work(&data->work); |
1da177e4c Linux-2.6.12-rc2 |
238 239 240 241 242 243 244 245 246 |
return 0; } static void bcm203x_disconnect(struct usb_interface *intf) { struct bcm203x_data *data = usb_get_intfdata(intf); BT_DBG("intf %p", intf); |
fc501ad7a Bluetooth: bcm203... |
247 248 |
atomic_inc(&data->shutdown); cancel_work_sync(&data->work); |
1da177e4c Linux-2.6.12-rc2 |
249 250 251 252 253 254 255 256 257 258 259 |
usb_kill_urb(data->urb); usb_set_intfdata(intf, NULL); usb_free_urb(data->urb); kfree(data->fw_data); kfree(data->buffer); kfree(data); } static struct usb_driver bcm203x_driver = { |
1da177e4c Linux-2.6.12-rc2 |
260 261 262 263 264 |
.name = "bcm203x", .probe = bcm203x_probe, .disconnect = bcm203x_disconnect, .id_table = bcm203x_table, }; |
93f1508cf USB: convert driv... |
265 |
module_usb_driver(bcm203x_driver); |
1da177e4c Linux-2.6.12-rc2 |
266 |
|
1da177e4c Linux-2.6.12-rc2 |
267 268 269 270 |
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); |
2312119af [Bluetooth] Make ... |
271 272 |
MODULE_FIRMWARE("BCM2033-MD.hex"); MODULE_FIRMWARE("BCM2033-FW.bin"); |