Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(565)

Side by Side Diff: chromeos/compat-wireless/drivers/bluetooth/fwload.c

Issue 5326002: Update compat-wireless to 2.6.36-5-spn (Closed) Base URL: http://git.chromium.org/git/kernel.git@master
Patch Set: Fixes for !ACK handling, missing local changes, log message fixes Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 *
3 * Generic Bluetooth USB DFU driver to download firmware to target RAM
4 *
5 * Copyright (c) 2009-2010 Atheros Communications Inc.
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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/types.h>
28 #include <linux/device.h>
29 #include <linux/firmware.h>
30 #include <linux/usb.h>
31 #include <net/bluetooth/bluetooth.h>
32
33 #define USB_REQ_DFU_DNLOAD 1
34 #define USB_REQ_GET_STATE 5
35 #define USB_FIRMWARE_RAM_MODE 11
36 #define USB_FIRMWARE_FLASH_MODE 12
37 #define BULK_SIZE 4096
38 #define VERSION "1.0"
39
40 struct firmware_data {
41 struct usb_device *udev;
42 u8 *fw_data;
43 u32 fw_size;
44 u32 fw_sent;
45 };
46
47 static int load_firmware(struct firmware_data *data,
48 unsigned char *firmware,
49 int count)
50 {
51 u8 *send_buf;
52 int err, pipe, len, size, sent = 0;
53 char ucFirmware = 0;
54
55 BT_DBG("ath3k %p udev %p", data, data->udev);
56
57 if ((usb_control_msg(data->udev, usb_rcvctrlpipe(data->udev, 0),
58 USB_REQ_GET_STATE,
59 USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
60 &ucFirmware, 1, USB_CTRL_SET_TIMEOUT)) < 0) {
61 BT_ERR("Can't change to loading configuration err");
62 return -EBUSY;
63 }
64
65 if (ucFirmware == USB_FIRMWARE_RAM_MODE) {
66 /* RAM based firmware is available in the target.
67 * No need to load the firmware to RAM */
68 BT_DBG("RAM based firmware is available");
69 return 0;
70 }
71
72 pipe = usb_sndctrlpipe(data->udev, 0);
73 if ((usb_control_msg(data->udev, pipe,
74 USB_REQ_DFU_DNLOAD,
75 USB_TYPE_VENDOR, 0, 0,
76 firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
77 BT_ERR("Can't change to loading configuration err");
78 return -EBUSY;
79 }
80 sent += 20;
81 count -= 20;
82
83 send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
84 if (!send_buf) {
85 BT_ERR("Can't allocate memory chunk for firmware");
86 return -ENOMEM;
87 }
88
89 while (count) {
90 size = min_t(uint, count, BULK_SIZE);
91 pipe = usb_sndbulkpipe(data->udev, 0x02);
92 memcpy(send_buf, firmware + sent, size);
93
94 err = usb_bulk_msg(data->udev, pipe, send_buf, size,
95 &len, 3000);
96
97 if (err || (len != size)) {
98 BT_ERR("Error in firmware loading err = %d,"
99 "len = %d, size = %d", err, len, size);
100 goto error;
101 }
102
103 sent += size;
104 count -= size;
105 }
106
107 kfree(send_buf);
108 return 0;
109
110 error:
111 kfree(send_buf);
112 return err;
113 }
114
115 void *ath_fw_load(struct usb_interface *intf,
116 const char *fwfile, bool *suspend)
117 {
118 const struct firmware *firmware;
119 struct usb_device *udev = interface_to_usbdev(intf);
120 static struct firmware_data *data;
121 int size;
122
123 BT_DBG("\nintf %p suspend %d\n", intf, *suspend);
124
125 if (*suspend) {
126 load_firmware(data, data->fw_data, data->fw_size);
127 *suspend = 0;
128 return data;
129 }
130
131 if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
132 return NULL;
133
134 data = kzalloc(sizeof(*data), GFP_KERNEL);
135 if (!data)
136 return NULL;
137 data->udev = udev;
138
139 if (request_firmware(&firmware, fwfile, &udev->dev) < 0) {
140 kfree(data);
141 return NULL;
142 }
143
144 size = max_t(uint, firmware->size, 4096);
145 data->fw_data = kmalloc(size, GFP_KERNEL);
146 if (!data->fw_data) {
147 release_firmware(firmware);
148 kfree(data);
149 return NULL;
150 }
151
152 memcpy(data->fw_data, firmware->data, firmware->size);
153 data->fw_size = firmware->size;
154 data->fw_sent = 0;
155 release_firmware(firmware);
156
157 if (load_firmware(data, data->fw_data, data->fw_size)) {
158 kfree(data->fw_data);
159 kfree(data);
160 return NULL;
161 }
162 return data;
163 }
164 EXPORT_SYMBOL(ath_fw_load);
165
166 void ath_fw_unload(void *pdata, bool bsuspend)
167 {
168 struct firmware_data *data = (struct firmware_data *)pdata;
169
170 if (data == NULL)
171 return;
172
173 /* do not free the data on suspend as we will
174 * use it on resume */
175 if (!bsuspend) {
176 kfree(data->fw_data);
177 kfree(data);
178 }
179 }
180 EXPORT_SYMBOL(ath_fw_unload);
181
182 static int __init fwload_init(void)
183 {
184 BT_INFO("Firmware load driver init. Version:%s", VERSION);
185 return 0;
186 }
187
188 static void __exit fwload_deinit(void)
189 {
190 BT_INFO("Firmware load driver deinit");
191 }
192
193 module_init(fwload_init);
194 module_exit(fwload_deinit);
195
196 MODULE_AUTHOR("Atheros Communications");
197 MODULE_DESCRIPTION("Firmware load driver");
198 MODULE_VERSION(VERSION);
199 MODULE_LICENSE("GPL");
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698