OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [bluetooth/] [bcm203x.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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/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/device.h>
34
#include <linux/firmware.h>
35
 
36
#include <linux/usb.h>
37
 
38
#include <net/bluetooth/bluetooth.h>
39
 
40
#ifndef CONFIG_BT_HCIBCM203X_DEBUG
41
#undef  BT_DBG
42
#define BT_DBG(D...)
43
#endif
44
 
45
#define VERSION "1.1"
46
 
47
static int ignore = 0;
48
 
49
static struct usb_device_id bcm203x_table[] = {
50
        /* Broadcom Blutonium (BCM2033) */
51
        { USB_DEVICE(0x0a5c, 0x2033) },
52
 
53
        { }     /* Terminating entry */
54
};
55
 
56
MODULE_DEVICE_TABLE(usb, bcm203x_table);
57
 
58
#define BCM203X_ERROR           0
59
#define BCM203X_RESET           1
60
#define BCM203X_LOAD_MINIDRV    2
61
#define BCM203X_SELECT_MEMORY   3
62
#define BCM203X_CHECK_MEMORY    4
63
#define BCM203X_LOAD_FIRMWARE   5
64
#define BCM203X_CHECK_FIRMWARE  6
65
 
66
#define BCM203X_IN_EP           0x81
67
#define BCM203X_OUT_EP          0x02
68
 
69
struct bcm203x_data {
70
        struct usb_device       *udev;
71
 
72
        unsigned long           state;
73
 
74
        struct work_struct      work;
75
 
76
        struct urb              *urb;
77
        unsigned char           *buffer;
78
 
79
        unsigned char           *fw_data;
80
        unsigned int            fw_size;
81
        unsigned int            fw_sent;
82
};
83
 
84
static void bcm203x_complete(struct urb *urb)
85
{
86
        struct bcm203x_data *data = urb->context;
87
        struct usb_device *udev = urb->dev;
88
        int len;
89
 
90
        BT_DBG("udev %p urb %p", udev, urb);
91
 
92
        if (urb->status) {
93
                BT_ERR("URB failed with status %d", urb->status);
94
                data->state = BCM203X_ERROR;
95
                return;
96
        }
97
 
98
        switch (data->state) {
99
        case BCM203X_LOAD_MINIDRV:
100
                memcpy(data->buffer, "#", 1);
101
 
102
                usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
103
                                data->buffer, 1, bcm203x_complete, data);
104
 
105
                data->state = BCM203X_SELECT_MEMORY;
106
 
107
                schedule_work(&data->work);
108
                break;
109
 
110
        case BCM203X_SELECT_MEMORY:
111
                usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
112
                                data->buffer, 32, bcm203x_complete, data, 1);
113
 
114
                data->state = BCM203X_CHECK_MEMORY;
115
 
116
                if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
117
                        BT_ERR("Can't submit URB");
118
                break;
119
 
120
        case BCM203X_CHECK_MEMORY:
121
                if (data->buffer[0] != '#') {
122
                        BT_ERR("Memory select failed");
123
                        data->state = BCM203X_ERROR;
124
                        break;
125
                }
126
 
127
                data->state = BCM203X_LOAD_FIRMWARE;
128
 
129
        case BCM203X_LOAD_FIRMWARE:
130
                if (data->fw_sent == data->fw_size) {
131
                        usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP),
132
                                data->buffer, 32, bcm203x_complete, data, 1);
133
 
134
                        data->state = BCM203X_CHECK_FIRMWARE;
135
                } else {
136
                        len = min_t(uint, data->fw_size - data->fw_sent, 4096);
137
 
138
                        usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
139
                                data->fw_data + data->fw_sent, len, bcm203x_complete, data);
140
 
141
                        data->fw_sent += len;
142
                }
143
 
144
                if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
145
                        BT_ERR("Can't submit URB");
146
                break;
147
 
148
        case BCM203X_CHECK_FIRMWARE:
149
                if (data->buffer[0] != '.') {
150
                        BT_ERR("Firmware loading failed");
151
                        data->state = BCM203X_ERROR;
152
                        break;
153
                }
154
 
155
                data->state = BCM203X_RESET;
156
                break;
157
        }
158
}
159
 
160
static void bcm203x_work(struct work_struct *work)
161
{
162
        struct bcm203x_data *data =
163
                container_of(work, struct bcm203x_data, work);
164
 
165
        if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
166
                BT_ERR("Can't submit URB");
167
}
168
 
169
static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id)
170
{
171
        const struct firmware *firmware;
172
        struct usb_device *udev = interface_to_usbdev(intf);
173
        struct bcm203x_data *data;
174
        int size;
175
 
176
        BT_DBG("intf %p id %p", intf, id);
177
 
178
        if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0))
179
                return -ENODEV;
180
 
181
        data = kzalloc(sizeof(*data), GFP_KERNEL);
182
        if (!data) {
183
                BT_ERR("Can't allocate memory for data structure");
184
                return -ENOMEM;
185
        }
186
 
187
        data->udev  = udev;
188
        data->state = BCM203X_LOAD_MINIDRV;
189
 
190
        data->urb = usb_alloc_urb(0, GFP_KERNEL);
191
        if (!data->urb) {
192
                BT_ERR("Can't allocate URB");
193
                kfree(data);
194
                return -ENOMEM;
195
        }
196
 
197
        if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
198
                BT_ERR("Mini driver request failed");
199
                usb_free_urb(data->urb);
200
                kfree(data);
201
                return -EIO;
202
        }
203
 
204
        BT_DBG("minidrv data %p size %d", firmware->data, firmware->size);
205
 
206
        size = max_t(uint, firmware->size, 4096);
207
 
208
        data->buffer = kmalloc(size, GFP_KERNEL);
209
        if (!data->buffer) {
210
                BT_ERR("Can't allocate memory for mini driver");
211
                release_firmware(firmware);
212
                usb_free_urb(data->urb);
213
                kfree(data);
214
                return -ENOMEM;
215
        }
216
 
217
        memcpy(data->buffer, firmware->data, firmware->size);
218
 
219
        usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP),
220
                        data->buffer, firmware->size, bcm203x_complete, data);
221
 
222
        release_firmware(firmware);
223
 
224
        if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) {
225
                BT_ERR("Firmware request failed");
226
                usb_free_urb(data->urb);
227
                kfree(data->buffer);
228
                kfree(data);
229
                return -EIO;
230
        }
231
 
232
        BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
233
 
234
        data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
235
        if (!data->fw_data) {
236
                BT_ERR("Can't allocate memory for firmware image");
237
                release_firmware(firmware);
238
                usb_free_urb(data->urb);
239
                kfree(data->buffer);
240
                kfree(data);
241
                return -ENOMEM;
242
        }
243
 
244
        memcpy(data->fw_data, firmware->data, firmware->size);
245
        data->fw_size = firmware->size;
246
        data->fw_sent = 0;
247
 
248
        release_firmware(firmware);
249
 
250
        INIT_WORK(&data->work, bcm203x_work);
251
 
252
        usb_set_intfdata(intf, data);
253
 
254
        schedule_work(&data->work);
255
 
256
        return 0;
257
}
258
 
259
static void bcm203x_disconnect(struct usb_interface *intf)
260
{
261
        struct bcm203x_data *data = usb_get_intfdata(intf);
262
 
263
        BT_DBG("intf %p", intf);
264
 
265
        usb_kill_urb(data->urb);
266
 
267
        usb_set_intfdata(intf, NULL);
268
 
269
        usb_free_urb(data->urb);
270
        kfree(data->fw_data);
271
        kfree(data->buffer);
272
        kfree(data);
273
}
274
 
275
static struct usb_driver bcm203x_driver = {
276
        .name           = "bcm203x",
277
        .probe          = bcm203x_probe,
278
        .disconnect     = bcm203x_disconnect,
279
        .id_table       = bcm203x_table,
280
};
281
 
282
static int __init bcm203x_init(void)
283
{
284
        int err;
285
 
286
        BT_INFO("Broadcom Blutonium firmware driver ver %s", VERSION);
287
 
288
        err = usb_register(&bcm203x_driver);
289
        if (err < 0)
290
                BT_ERR("Failed to register USB driver");
291
 
292
        return err;
293
}
294
 
295
static void __exit bcm203x_exit(void)
296
{
297
        usb_deregister(&bcm203x_driver);
298
}
299
 
300
module_init(bcm203x_init);
301
module_exit(bcm203x_exit);
302
 
303
module_param(ignore, bool, 0644);
304
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
305
 
306
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
307
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
308
MODULE_VERSION(VERSION);
309
MODULE_LICENSE("GPL");
310
MODULE_FIRMWARE("BCM2033-MD.hex");
311
MODULE_FIRMWARE("BCM2033-FW.bin");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.