Blame view

drivers/bluetooth/bfusb.c 16.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   *
   *  AVM BlueFRITZ! USB driver
   *
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
5
   *  Copyright (C) 2003-2006  Marcel Holtmann <marcel@holtmann.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   *
   *
   *  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   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
  #include <linux/module.h>
  
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
34
35
36
37
38
  #include <linux/errno.h>
  #include <linux/skbuff.h>
  
  #include <linux/device.h>
  #include <linux/firmware.h>
  
  #include <linux/usb.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
943d56b0a   Marcel Holtmann   [Bluetooth] Remov...
39
  #define VERSION "1.2"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
50
  
  static struct usb_driver bfusb_driver;
  
  static struct usb_device_id bfusb_table[] = {
  	/* AVM BlueFRITZ! USB */
  	{ USB_DEVICE(0x057c, 0x2200) },
  
  	{ }	/* Terminating entry */
  };
  
  MODULE_DEVICE_TABLE(usb, bfusb_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
58
59
  #define BFUSB_MAX_BLOCK_SIZE	256
  
  #define BFUSB_BLOCK_TIMEOUT	3000
  
  #define BFUSB_TX_PROCESS	1
  #define BFUSB_TX_WAKEUP		2
  
  #define BFUSB_MAX_BULK_TX	2
  #define BFUSB_MAX_BULK_RX	2
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
60
  struct bfusb_data {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  	struct hci_dev		*hdev;
  
  	unsigned long		state;
  
  	struct usb_device	*udev;
  
  	unsigned int		bulk_in_ep;
  	unsigned int		bulk_out_ep;
  	unsigned int		bulk_pkt_size;
  
  	rwlock_t		lock;
  
  	struct sk_buff_head	transmit_q;
  
  	struct sk_buff		*reassembly;
  
  	atomic_t		pending_tx;
  	struct sk_buff_head	pending_q;
  	struct sk_buff_head	completed_q;
  };
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
81
  struct bfusb_data_scb {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	struct urb *urb;
  };
7d12e780e   David Howells   IRQ: Maintain reg...
84
85
  static void bfusb_tx_complete(struct urb *urb);
  static void bfusb_rx_complete(struct urb *urb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
87
  static struct urb *bfusb_get_completed(struct bfusb_data *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  {
  	struct sk_buff *skb;
  	struct urb *urb = NULL;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
91
  	BT_DBG("bfusb %p", data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
93
  	skb = skb_dequeue(&data->completed_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  	if (skb) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
95
  		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
  		kfree_skb(skb);
  	}
  
  	return urb;
  }
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
101
  static void bfusb_unlink_urbs(struct bfusb_data *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
  {
  	struct sk_buff *skb;
  	struct urb *urb;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
105
  	BT_DBG("bfusb %p", data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
107
108
  	while ((skb = skb_dequeue(&data->pending_q))) {
  		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  		usb_kill_urb(urb);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
110
  		skb_queue_tail(&data->completed_q, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
112
  	while ((urb = bfusb_get_completed(data)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
  		usb_free_urb(urb);
  }
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
115
  static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
117
118
  	struct bfusb_data_scb *scb = (void *) skb->cb;
  	struct urb *urb = bfusb_get_completed(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  	int err, pipe;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
120
  	BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
  
  	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
  		return -ENOMEM;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
124
  	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
126
  	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
  			bfusb_tx_complete, skb);
  
  	scb->urb = urb;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
130
  	skb_queue_tail(&data->pending_q, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
  
  	err = usb_submit_urb(urb, GFP_ATOMIC);
  	if (err) {
  		BT_ERR("%s bulk tx submit failed urb %p err %d", 
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
135
136
  					data->hdev->name, urb, err);
  		skb_unlink(skb, &data->pending_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  		usb_free_urb(urb);
  	} else
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
139
  		atomic_inc(&data->pending_tx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
  
  	return err;
  }
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
143
  static void bfusb_tx_wakeup(struct bfusb_data *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
  {
  	struct sk_buff *skb;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
146
  	BT_DBG("bfusb %p", data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
148
149
  	if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
  		set_bit(BFUSB_TX_WAKEUP, &data->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
  		return;
  	}
  
  	do {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
154
  		clear_bit(BFUSB_TX_WAKEUP, &data->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
156
157
158
159
  		while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) &&
  				(skb = skb_dequeue(&data->transmit_q))) {
  			if (bfusb_send_bulk(data, skb) < 0) {
  				skb_queue_head(&data->transmit_q, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
  				break;
  			}
  		}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
163
  	} while (test_bit(BFUSB_TX_WAKEUP, &data->state));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
165
  	clear_bit(BFUSB_TX_PROCESS, &data->state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  }
7d12e780e   David Howells   IRQ: Maintain reg...
167
  static void bfusb_tx_complete(struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  {
  	struct sk_buff *skb = (struct sk_buff *) urb->context;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
170
  	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
172
  	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
174
  	atomic_dec(&data->pending_tx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
176
  	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
  		return;
  
  	if (!urb->status)
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
180
  		data->hdev->stat.byte_tx += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
  	else
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
182
  		data->hdev->stat.err_tx++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
184
  	read_lock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
186
187
  	skb_unlink(skb, &data->pending_q);
  	skb_queue_tail(&data->completed_q, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
189
  	bfusb_tx_wakeup(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
191
  	read_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  }
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
193
  static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
195
  	struct bfusb_data_scb *scb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
  	struct sk_buff *skb;
  	int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
a418b893a   Marcel Holtmann   Bluetooth: Enable...
198
  	BT_DBG("bfusb %p urb %p", data, urb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  
  	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
  		return -ENOMEM;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
202
203
  	skb = bt_skb_alloc(size, GFP_ATOMIC);
  	if (!skb) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
  		usb_free_urb(urb);
  		return -ENOMEM;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
207
  	skb->dev = (void *) data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
209
  	scb = (struct bfusb_data_scb *) skb->cb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	scb->urb = urb;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
211
  	pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
213
  	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  			bfusb_rx_complete, skb);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
215
  	skb_queue_tail(&data->pending_q, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
  
  	err = usb_submit_urb(urb, GFP_ATOMIC);
  	if (err) {
  		BT_ERR("%s bulk rx submit failed urb %p err %d",
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
220
221
  					data->hdev->name, urb, err);
  		skb_unlink(skb, &data->pending_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
227
  		kfree_skb(skb);
  		usb_free_urb(urb);
  	}
  
  	return err;
  }
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
228
  static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
230
  	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
  
  	if (hdr & 0x10) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
233
  		BT_ERR("%s error in block", data->hdev->name);
b1fb06830   Wei Yongjun   Bluetooth: Remove...
234
  		kfree_skb(data->reassembly);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
235
  		data->reassembly = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
240
241
242
  		return -EIO;
  	}
  
  	if (hdr & 0x04) {
  		struct sk_buff *skb;
  		unsigned char pkt_type;
  		int pkt_len = 0;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
243
244
245
246
  		if (data->reassembly) {
  			BT_ERR("%s unexpected start block", data->hdev->name);
  			kfree_skb(data->reassembly);
  			data->reassembly = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
  		}
  
  		if (len < 1) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
250
  			BT_ERR("%s no packet type found", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
  			return -EPROTO;
  		}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
253
  		pkt_type = *buf++; len--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
  
  		switch (pkt_type) {
  		case HCI_EVENT_PKT:
  			if (len >= HCI_EVENT_HDR_SIZE) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
258
  				struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
  				pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
  			} else {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
261
  				BT_ERR("%s event block is too short", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
266
267
  				return -EILSEQ;
  			}
  			break;
  
  		case HCI_ACLDATA_PKT:
  			if (len >= HCI_ACL_HDR_SIZE) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
268
  				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
  				pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
  			} else {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
271
  				BT_ERR("%s data block is too short", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
277
  				return -EILSEQ;
  			}
  			break;
  
  		case HCI_SCODATA_PKT:
  			if (len >= HCI_SCO_HDR_SIZE) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
278
  				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  				pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
  			} else {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
281
  				BT_ERR("%s audio block is too short", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
287
288
  				return -EILSEQ;
  			}
  			break;
  		}
  
  		skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
  		if (!skb) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
289
  			BT_ERR("%s no memory for the packet", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
  			return -ENOMEM;
  		}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
292
  		skb->dev = (void *) data->hdev;
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
293
  		bt_cb(skb)->pkt_type = pkt_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
295
  		data->reassembly = skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  	} else {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
297
298
  		if (!data->reassembly) {
  			BT_ERR("%s unexpected continuation block", data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
  			return -EIO;
  		}
  	}
  
  	if (len > 0)
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
304
  		memcpy(skb_put(data->reassembly, len), buf, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  
  	if (hdr & 0x08) {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
307
308
  		hci_recv_frame(data->reassembly);
  		data->reassembly = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
312
  	}
  
  	return 0;
  }
7d12e780e   David Howells   IRQ: Maintain reg...
313
  static void bfusb_rx_complete(struct urb *urb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
  {
  	struct sk_buff *skb = (struct sk_buff *) urb->context;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
316
  	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
  	unsigned char *buf = urb->transfer_buffer;
  	int count = urb->actual_length;
  	int err, hdr, len;
a418b893a   Marcel Holtmann   Bluetooth: Enable...
320
  	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
322
  	read_lock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
324
  	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  		goto unlock;
  
  	if (urb->status || !count)
  		goto resubmit;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
329
  	data->hdev->stat.byte_rx += count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  
  	skb_put(skb, count);
  
  	while (count) {
  		hdr = buf[0] | (buf[1] << 8);
  
  		if (hdr & 0x4000) {
  			len = 0;
  			count -= 2;
  			buf   += 2;
  		} else {
  			len = (buf[2] == 0) ? 256 : buf[2];
  			count -= 3;
  			buf   += 3;
  		}
  
  		if (count < len) {
  			BT_ERR("%s block extends over URB buffer ranges",
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
348
  					data->hdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
  		}
  
  		if ((hdr & 0xe1) == 0xc1)
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
352
  			bfusb_recv_block(data, hdr, buf, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
356
  
  		count -= len;
  		buf   += len;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
357
  	skb_unlink(skb, &data->pending_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  	kfree_skb(skb);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
359
  	bfusb_rx_submit(data, urb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
361
  	read_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
  
  	return;
  
  resubmit:
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
366
  	urb->dev = data->udev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
  
  	err = usb_submit_urb(urb, GFP_ATOMIC);
  	if (err) {
  		BT_ERR("%s bulk resubmit failed urb %p err %d",
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
371
  					data->hdev->name, urb, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  	}
  
  unlock:
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
375
  	read_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
  static int bfusb_open(struct hci_dev *hdev)
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
379
  	struct bfusb_data *data = hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
  	unsigned long flags;
  	int i, err;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
382
  	BT_DBG("hdev %p bfusb %p", hdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
  
  	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
  		return 0;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
386
  	write_lock_irqsave(&data->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
388
  	err = bfusb_rx_submit(data, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
390
  	if (!err) {
  		for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
391
  			bfusb_rx_submit(data, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
  	} else {
  		clear_bit(HCI_RUNNING, &hdev->flags);
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
395
  	write_unlock_irqrestore(&data->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
  
  	return err;
  }
  
  static int bfusb_flush(struct hci_dev *hdev)
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
402
  	struct bfusb_data *data = hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
404
  	BT_DBG("hdev %p bfusb %p", hdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
406
  	skb_queue_purge(&data->transmit_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
410
411
412
  
  	return 0;
  }
  
  static int bfusb_close(struct hci_dev *hdev)
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
413
  	struct bfusb_data *data = hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  	unsigned long flags;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
415
  	BT_DBG("hdev %p bfusb %p", hdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
  
  	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
  		return 0;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
419
420
  	write_lock_irqsave(&data->lock, flags);
  	write_unlock_irqrestore(&data->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
422
  	bfusb_unlink_urbs(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
426
427
428
429
430
  	bfusb_flush(hdev);
  
  	return 0;
  }
  
  static int bfusb_send_frame(struct sk_buff *skb)
  {
  	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
431
  	struct bfusb_data *data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
  	struct sk_buff *nskb;
  	unsigned char buf[3];
  	int sent = 0, size, count;
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
435
  	BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
439
440
441
442
443
  
  	if (!hdev) {
  		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
  		return -ENODEV;
  	}
  
  	if (!test_bit(HCI_RUNNING, &hdev->flags))
  		return -EBUSY;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
444
  	data = hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445

0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
446
  	switch (bt_cb(skb)->pkt_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
448
449
450
451
452
453
454
455
456
457
458
  	case HCI_COMMAND_PKT:
  		hdev->stat.cmd_tx++;
  		break;
  	case HCI_ACLDATA_PKT:
  		hdev->stat.acl_tx++;
  		break;
  	case HCI_SCODATA_PKT:
  		hdev->stat.sco_tx++;
  		break;
  	};
  
  	/* Prepend skb with frame type */
0d48d9394   Marcel Holtmann   [Bluetooth]: Move...
459
  	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
  
  	count = skb->len;
  
  	/* Max HCI frame size seems to be 1511 + 1 */
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
464
465
  	nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
  	if (!nskb) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
468
  		BT_ERR("Can't allocate memory for new packet");
  		return -ENOMEM;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
469
  	nskb->dev = (void *) data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
471
472
473
474
475
476
477
478
  
  	while (count) {
  		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE);
  
  		buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0);
  		buf[1] = 0x00;
  		buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size;
  
  		memcpy(skb_put(nskb, 3), buf, 3);
d626f62b1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
479
  		skb_copy_from_linear_data_offset(skb, sent, skb_put(nskb, size), size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
485
  
  		sent  += size;
  		count -= size;
  	}
  
  	/* Don't send frame with multiple size of bulk max packet */
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
486
  	if ((nskb->len % data->bulk_pkt_size) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
  		buf[0] = 0xdd;
  		buf[1] = 0x00;
  		memcpy(skb_put(nskb, 2), buf, 2);
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
491
  	read_lock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
493
494
  	skb_queue_tail(&data->transmit_q, nskb);
  	bfusb_tx_wakeup(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
496
  	read_unlock(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
498
499
500
501
502
503
504
  
  	kfree_skb(skb);
  
  	return 0;
  }
  
  static void bfusb_destruct(struct hci_dev *hdev)
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
505
  	struct bfusb_data *data = hdev->driver_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
507
  	BT_DBG("hdev %p bfusb %p", hdev, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
509
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
512
513
514
515
  }
  
  static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
  {
  	return -ENOIOCTLCMD;
  }
8187b4fb9   David Woodhouse   bluetooth: treat ...
516
517
  static int bfusb_load_firmware(struct bfusb_data *data,
  			       const unsigned char *firmware, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
  {
  	unsigned char *buf;
  	int err, pipe, len, size, sent = 0;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
521
  	BT_DBG("bfusb %p udev %p", data, data->udev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
  
  	BT_INFO("BlueFRITZ! USB loading firmware");
6b441fab2   David Herrmann   Bluetooth: bfusb:...
524
525
526
527
528
  	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
  	if (!buf) {
  		BT_ERR("Can't allocate memory chunk for firmware");
  		return -ENOMEM;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
529
  	pipe = usb_sndctrlpipe(data->udev, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
531
  	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
  				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
  		BT_ERR("Can't change to loading configuration");
6b441fab2   David Herrmann   Bluetooth: bfusb:...
534
  		kfree(buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
  		return -EBUSY;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
537
  	data->udev->toggle[0] = data->udev->toggle[1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
539
  	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
  
  	while (count) {
  		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);
  
  		memcpy(buf, firmware + sent, size);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
545
  		err = usb_bulk_msg(data->udev, pipe, buf, size,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
550
551
552
553
554
555
  					&len, BFUSB_BLOCK_TIMEOUT);
  
  		if (err || (len != size)) {
  			BT_ERR("Error in firmware loading");
  			goto error;
  		}
  
  		sent  += size;
  		count -= size;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
556
557
558
  	err = usb_bulk_msg(data->udev, pipe, NULL, 0,
  					&len, BFUSB_BLOCK_TIMEOUT);
  	if (err < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
  		BT_ERR("Error in null packet request");
  		goto error;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
562
  	pipe = usb_sndctrlpipe(data->udev, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
564
565
566
  	err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
  				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
  	if (err < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
  		BT_ERR("Can't change to running configuration");
  		goto error;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
570
  	data->udev->toggle[0] = data->udev->toggle[1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
575
576
577
578
  
  	BT_INFO("BlueFRITZ! USB device ready");
  
  	kfree(buf);
  	return 0;
  
  error:
  	kfree(buf);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
579
  	pipe = usb_sndctrlpipe(data->udev, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
581
  	usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
587
588
589
590
591
592
593
  				0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
  
  	return err;
  }
  
  static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
  {
  	const struct firmware *firmware;
  	struct usb_device *udev = interface_to_usbdev(intf);
  	struct usb_host_endpoint *bulk_out_ep;
  	struct usb_host_endpoint *bulk_in_ep;
  	struct hci_dev *hdev;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
594
  	struct bfusb_data *data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
  
  	BT_DBG("intf %p id %p", intf, id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
601
602
603
604
605
606
607
608
609
  	/* Check number of endpoints */
  	if (intf->cur_altsetting->desc.bNumEndpoints < 2)
  		return -EIO;
  
  	bulk_out_ep = &intf->cur_altsetting->endpoint[0];
  	bulk_in_ep  = &intf->cur_altsetting->endpoint[1];
  
  	if (!bulk_out_ep || !bulk_in_ep) {
  		BT_ERR("Bulk endpoints not found");
  		goto done;
  	}
  
  	/* Initialize control structure and load firmware */
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
610
611
  	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
  	if (!data) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
  		BT_ERR("Can't allocate memory for control structure");
  		goto done;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
615
616
617
618
  	data->udev = udev;
  	data->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
  	data->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
  	data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
620
  	rwlock_init(&data->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
622
  	data->reassembly = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
624
625
626
  	skb_queue_head_init(&data->transmit_q);
  	skb_queue_head_init(&data->pending_q);
  	skb_queue_head_init(&data->completed_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
631
  
  	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
  		BT_ERR("Firmware request failed");
  		goto error;
  	}
a418b893a   Marcel Holtmann   Bluetooth: Enable...
632
  	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633

9c724357f   Marcel Holtmann   [Bluetooth] Code ...
634
  	if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
638
639
640
641
642
643
644
645
646
  		BT_ERR("Firmware loading failed");
  		goto release;
  	}
  
  	release_firmware(firmware);
  
  	/* Initialize and register HCI device */
  	hdev = hci_alloc_dev();
  	if (!hdev) {
  		BT_ERR("Can't allocate HCI device");
  		goto error;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
647
  	data->hdev = hdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648

c13854cef   Marcel Holtmann   Bluetooth: Conver...
649
  	hdev->bus = HCI_USB;
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
650
  	hdev->driver_data = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
  	SET_HCIDEV_DEV(hdev, &intf->dev);
  
  	hdev->open     = bfusb_open;
  	hdev->close    = bfusb_close;
  	hdev->flush    = bfusb_flush;
  	hdev->send     = bfusb_send_frame;
  	hdev->destruct = bfusb_destruct;
  	hdev->ioctl    = bfusb_ioctl;
  
  	hdev->owner = THIS_MODULE;
  
  	if (hci_register_dev(hdev) < 0) {
  		BT_ERR("Can't register HCI device");
  		hci_free_dev(hdev);
  		goto error;
  	}
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
667
  	usb_set_intfdata(intf, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
672
673
674
  
  	return 0;
  
  release:
  	release_firmware(firmware);
  
  error:
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
675
  	kfree(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
680
681
682
  
  done:
  	return -EIO;
  }
  
  static void bfusb_disconnect(struct usb_interface *intf)
  {
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
683
684
  	struct bfusb_data *data = usb_get_intfdata(intf);
  	struct hci_dev *hdev = data->hdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  
  	BT_DBG("intf %p", intf);
  
  	if (!hdev)
  		return;
  
  	usb_set_intfdata(intf, NULL);
  
  	bfusb_close(hdev);
  
  	if (hci_unregister_dev(hdev) < 0)
  		BT_ERR("Can't unregister HCI device %s", hdev->name);
  
  	hci_free_dev(hdev);
  }
  
  static struct usb_driver bfusb_driver = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
705
706
707
708
709
710
711
712
  	.name		= "bfusb",
  	.probe		= bfusb_probe,
  	.disconnect	= bfusb_disconnect,
  	.id_table	= bfusb_table,
  };
  
  static int __init bfusb_init(void)
  {
  	int err;
  
  	BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
9c724357f   Marcel Holtmann   [Bluetooth] Code ...
713
714
  	err = usb_register(&bfusb_driver);
  	if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
718
719
720
721
722
723
724
725
726
  		BT_ERR("Failed to register BlueFRITZ! USB driver");
  
  	return err;
  }
  
  static void __exit bfusb_exit(void)
  {
  	usb_deregister(&bfusb_driver);
  }
  
  module_init(bfusb_init);
  module_exit(bfusb_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
730
  MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
  MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
  MODULE_VERSION(VERSION);
  MODULE_LICENSE("GPL");
2312119af   Marcel Holtmann   [Bluetooth] Make ...
731
  MODULE_FIRMWARE("bfubase.frm");