bfusb.c 16.6 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
/*
 *
 *  AVM BlueFRITZ! USB driver
 *
5
 *  Copyright (C) 2003-2006  Marcel Holtmann <marcel@holtmann.org>
Linus Torvalds's avatar
Linus Torvalds committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *
 *
 *  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
 *
 */

#include <linux/module.h>

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#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>

41
#define VERSION "1.2"
Linus Torvalds's avatar
Linus Torvalds committed
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

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);

#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

64
struct bfusb_data {
Linus Torvalds's avatar
Linus Torvalds committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
	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;
};

86
struct bfusb_data_scb {
Linus Torvalds's avatar
Linus Torvalds committed
87
88
89
	struct urb *urb;
};

90
91
static void bfusb_tx_complete(struct urb *urb);
static void bfusb_rx_complete(struct urb *urb);
Linus Torvalds's avatar
Linus Torvalds committed
92

93
static struct urb *bfusb_get_completed(struct bfusb_data *data)
Linus Torvalds's avatar
Linus Torvalds committed
94
95
96
97
{
	struct sk_buff *skb;
	struct urb *urb = NULL;

98
	BT_DBG("bfusb %p", data);
Linus Torvalds's avatar
Linus Torvalds committed
99

100
	skb = skb_dequeue(&data->completed_q);
Linus Torvalds's avatar
Linus Torvalds committed
101
	if (skb) {
102
		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
Linus Torvalds's avatar
Linus Torvalds committed
103
104
105
106
107
108
		kfree_skb(skb);
	}

	return urb;
}

109
static void bfusb_unlink_urbs(struct bfusb_data *data)
Linus Torvalds's avatar
Linus Torvalds committed
110
111
112
113
{
	struct sk_buff *skb;
	struct urb *urb;

114
	BT_DBG("bfusb %p", data);
Linus Torvalds's avatar
Linus Torvalds committed
115

116
117
	while ((skb = skb_dequeue(&data->pending_q))) {
		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
Linus Torvalds's avatar
Linus Torvalds committed
118
		usb_kill_urb(urb);
119
		skb_queue_tail(&data->completed_q, skb);
Linus Torvalds's avatar
Linus Torvalds committed
120
121
	}

122
	while ((urb = bfusb_get_completed(data)))
Linus Torvalds's avatar
Linus Torvalds committed
123
124
125
		usb_free_urb(urb);
}

126
static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
127
{
128
129
	struct bfusb_data_scb *scb = (void *) skb->cb;
	struct urb *urb = bfusb_get_completed(data);
Linus Torvalds's avatar
Linus Torvalds committed
130
131
	int err, pipe;

132
	BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
Linus Torvalds's avatar
Linus Torvalds committed
133
134
135
136

	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
		return -ENOMEM;

137
	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
Linus Torvalds's avatar
Linus Torvalds committed
138

139
	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
Linus Torvalds's avatar
Linus Torvalds committed
140
141
142
143
			bfusb_tx_complete, skb);

	scb->urb = urb;

144
	skb_queue_tail(&data->pending_q, skb);
Linus Torvalds's avatar
Linus Torvalds committed
145
146
147
148

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err) {
		BT_ERR("%s bulk tx submit failed urb %p err %d", 
149
150
					data->hdev->name, urb, err);
		skb_unlink(skb, &data->pending_q);
Linus Torvalds's avatar
Linus Torvalds committed
151
152
		usb_free_urb(urb);
	} else
153
		atomic_inc(&data->pending_tx);
Linus Torvalds's avatar
Linus Torvalds committed
154
155
156
157

	return err;
}

158
static void bfusb_tx_wakeup(struct bfusb_data *data)
Linus Torvalds's avatar
Linus Torvalds committed
159
160
161
{
	struct sk_buff *skb;

162
	BT_DBG("bfusb %p", data);
Linus Torvalds's avatar
Linus Torvalds committed
163

164
165
	if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
		set_bit(BFUSB_TX_WAKEUP, &data->state);
Linus Torvalds's avatar
Linus Torvalds committed
166
167
168
169
		return;
	}

	do {
170
		clear_bit(BFUSB_TX_WAKEUP, &data->state);
Linus Torvalds's avatar
Linus Torvalds committed
171

172
173
174
175
		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);
Linus Torvalds's avatar
Linus Torvalds committed
176
177
178
179
				break;
			}
		}

180
	} while (test_bit(BFUSB_TX_WAKEUP, &data->state));
Linus Torvalds's avatar
Linus Torvalds committed
181

182
	clear_bit(BFUSB_TX_PROCESS, &data->state);
Linus Torvalds's avatar
Linus Torvalds committed
183
184
}

185
static void bfusb_tx_complete(struct urb *urb)
Linus Torvalds's avatar
Linus Torvalds committed
186
187
{
	struct sk_buff *skb = (struct sk_buff *) urb->context;
188
	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
Linus Torvalds's avatar
Linus Torvalds committed
189

190
	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
Linus Torvalds's avatar
Linus Torvalds committed
191

192
	atomic_dec(&data->pending_tx);
Linus Torvalds's avatar
Linus Torvalds committed
193

194
	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
Linus Torvalds's avatar
Linus Torvalds committed
195
196
197
		return;

	if (!urb->status)
198
		data->hdev->stat.byte_tx += skb->len;
Linus Torvalds's avatar
Linus Torvalds committed
199
	else
200
		data->hdev->stat.err_tx++;
Linus Torvalds's avatar
Linus Torvalds committed
201

202
	read_lock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
203

204
205
	skb_unlink(skb, &data->pending_q);
	skb_queue_tail(&data->completed_q, skb);
Linus Torvalds's avatar
Linus Torvalds committed
206

207
	bfusb_tx_wakeup(data);
Linus Torvalds's avatar
Linus Torvalds committed
208

209
	read_unlock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
210
211
212
}


213
static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
Linus Torvalds's avatar
Linus Torvalds committed
214
{
215
	struct bfusb_data_scb *scb;
Linus Torvalds's avatar
Linus Torvalds committed
216
217
218
	struct sk_buff *skb;
	int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;

219
	BT_DBG("bfusb %p urb %p", data, urb);
Linus Torvalds's avatar
Linus Torvalds committed
220
221
222
223

	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
		return -ENOMEM;

224
225
	skb = bt_skb_alloc(size, GFP_ATOMIC);
	if (!skb) {
Linus Torvalds's avatar
Linus Torvalds committed
226
227
228
229
		usb_free_urb(urb);
		return -ENOMEM;
	}

230
	skb->dev = (void *) data;
Linus Torvalds's avatar
Linus Torvalds committed
231

232
	scb = (struct bfusb_data_scb *) skb->cb;
Linus Torvalds's avatar
Linus Torvalds committed
233
234
	scb->urb = urb;

235
	pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
Linus Torvalds's avatar
Linus Torvalds committed
236

237
	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
Linus Torvalds's avatar
Linus Torvalds committed
238
239
			bfusb_rx_complete, skb);

240
	skb_queue_tail(&data->pending_q, skb);
Linus Torvalds's avatar
Linus Torvalds committed
241
242
243
244

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err) {
		BT_ERR("%s bulk rx submit failed urb %p err %d",
245
246
					data->hdev->name, urb, err);
		skb_unlink(skb, &data->pending_q);
Linus Torvalds's avatar
Linus Torvalds committed
247
248
249
250
251
252
253
		kfree_skb(skb);
		usb_free_urb(urb);
	}

	return err;
}

254
static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
Linus Torvalds's avatar
Linus Torvalds committed
255
{
256
	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
Linus Torvalds's avatar
Linus Torvalds committed
257
258

	if (hdr & 0x10) {
259
		BT_ERR("%s error in block", data->hdev->name);
260
		kfree_skb(data->reassembly);
261
		data->reassembly = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
262
263
264
265
266
267
268
269
		return -EIO;
	}

	if (hdr & 0x04) {
		struct sk_buff *skb;
		unsigned char pkt_type;
		int pkt_len = 0;

270
271
272
273
		if (data->reassembly) {
			BT_ERR("%s unexpected start block", data->hdev->name);
			kfree_skb(data->reassembly);
			data->reassembly = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
274
275
276
		}

		if (len < 1) {
277
			BT_ERR("%s no packet type found", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
278
279
280
			return -EPROTO;
		}

281
		pkt_type = *buf++; len--;
Linus Torvalds's avatar
Linus Torvalds committed
282
283
284
285

		switch (pkt_type) {
		case HCI_EVENT_PKT:
			if (len >= HCI_EVENT_HDR_SIZE) {
286
				struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
Linus Torvalds's avatar
Linus Torvalds committed
287
288
				pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
			} else {
289
				BT_ERR("%s event block is too short", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
290
291
292
293
294
295
				return -EILSEQ;
			}
			break;

		case HCI_ACLDATA_PKT:
			if (len >= HCI_ACL_HDR_SIZE) {
296
				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
Linus Torvalds's avatar
Linus Torvalds committed
297
298
				pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
			} else {
299
				BT_ERR("%s data block is too short", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
300
301
302
303
304
305
				return -EILSEQ;
			}
			break;

		case HCI_SCODATA_PKT:
			if (len >= HCI_SCO_HDR_SIZE) {
306
				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
Linus Torvalds's avatar
Linus Torvalds committed
307
308
				pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
			} else {
309
				BT_ERR("%s audio block is too short", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
310
311
312
313
314
315
316
				return -EILSEQ;
			}
			break;
		}

		skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
		if (!skb) {
317
			BT_ERR("%s no memory for the packet", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
318
319
320
			return -ENOMEM;
		}

321
		skb->dev = (void *) data->hdev;
322
		bt_cb(skb)->pkt_type = pkt_type;
Linus Torvalds's avatar
Linus Torvalds committed
323

324
		data->reassembly = skb;
Linus Torvalds's avatar
Linus Torvalds committed
325
	} else {
326
327
		if (!data->reassembly) {
			BT_ERR("%s unexpected continuation block", data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
328
329
330
331
332
			return -EIO;
		}
	}

	if (len > 0)
333
		memcpy(skb_put(data->reassembly, len), buf, len);
Linus Torvalds's avatar
Linus Torvalds committed
334
335

	if (hdr & 0x08) {
336
337
		hci_recv_frame(data->reassembly);
		data->reassembly = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
338
339
340
341
342
	}

	return 0;
}

343
static void bfusb_rx_complete(struct urb *urb)
Linus Torvalds's avatar
Linus Torvalds committed
344
345
{
	struct sk_buff *skb = (struct sk_buff *) urb->context;
346
	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
Linus Torvalds's avatar
Linus Torvalds committed
347
348
349
350
	unsigned char *buf = urb->transfer_buffer;
	int count = urb->actual_length;
	int err, hdr, len;

351
	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
Linus Torvalds's avatar
Linus Torvalds committed
352

353
	read_lock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
354

355
	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
Linus Torvalds's avatar
Linus Torvalds committed
356
357
358
359
360
		goto unlock;

	if (urb->status || !count)
		goto resubmit;

361
	data->hdev->stat.byte_rx += count;
Linus Torvalds's avatar
Linus Torvalds committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

	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",
380
					data->hdev->name);
Linus Torvalds's avatar
Linus Torvalds committed
381
382
383
		}

		if ((hdr & 0xe1) == 0xc1)
384
			bfusb_recv_block(data, hdr, buf, len);
Linus Torvalds's avatar
Linus Torvalds committed
385
386
387
388
389

		count -= len;
		buf   += len;
	}

390
	skb_unlink(skb, &data->pending_q);
Linus Torvalds's avatar
Linus Torvalds committed
391
392
	kfree_skb(skb);

393
	bfusb_rx_submit(data, urb);
Linus Torvalds's avatar
Linus Torvalds committed
394

395
	read_unlock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
396
397
398
399

	return;

resubmit:
400
	urb->dev = data->udev;
Linus Torvalds's avatar
Linus Torvalds committed
401
402
403
404

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err) {
		BT_ERR("%s bulk resubmit failed urb %p err %d",
405
					data->hdev->name, urb, err);
Linus Torvalds's avatar
Linus Torvalds committed
406
407
408
	}

unlock:
409
	read_unlock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
410
411
412
413
}

static int bfusb_open(struct hci_dev *hdev)
{
414
	struct bfusb_data *data = hdev->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
415
416
417
	unsigned long flags;
	int i, err;

418
	BT_DBG("hdev %p bfusb %p", hdev, data);
Linus Torvalds's avatar
Linus Torvalds committed
419
420
421
422

	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
		return 0;

423
	write_lock_irqsave(&data->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
424

425
	err = bfusb_rx_submit(data, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
426
427
	if (!err) {
		for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
428
			bfusb_rx_submit(data, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
429
430
431
432
	} else {
		clear_bit(HCI_RUNNING, &hdev->flags);
	}

433
	write_unlock_irqrestore(&data->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
434
435
436
437
438
439

	return err;
}

static int bfusb_flush(struct hci_dev *hdev)
{
440
	struct bfusb_data *data = hdev->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
441

442
	BT_DBG("hdev %p bfusb %p", hdev, data);
Linus Torvalds's avatar
Linus Torvalds committed
443

444
	skb_queue_purge(&data->transmit_q);
Linus Torvalds's avatar
Linus Torvalds committed
445
446
447
448
449
450

	return 0;
}

static int bfusb_close(struct hci_dev *hdev)
{
451
	struct bfusb_data *data = hdev->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
452
453
	unsigned long flags;

454
	BT_DBG("hdev %p bfusb %p", hdev, data);
Linus Torvalds's avatar
Linus Torvalds committed
455
456
457
458

	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
		return 0;

459
460
	write_lock_irqsave(&data->lock, flags);
	write_unlock_irqrestore(&data->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
461

462
	bfusb_unlink_urbs(data);
Linus Torvalds's avatar
Linus Torvalds committed
463
464
465
466
467
468
469
470
	bfusb_flush(hdev);

	return 0;
}

static int bfusb_send_frame(struct sk_buff *skb)
{
	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
471
	struct bfusb_data *data;
Linus Torvalds's avatar
Linus Torvalds committed
472
473
474
475
	struct sk_buff *nskb;
	unsigned char buf[3];
	int sent = 0, size, count;

476
	BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
Linus Torvalds's avatar
Linus Torvalds committed
477
478
479
480
481
482
483
484
485

	if (!hdev) {
		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
		return -ENODEV;
	}

	if (!test_bit(HCI_RUNNING, &hdev->flags))
		return -EBUSY;

486
	data = hdev->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
487

488
	switch (bt_cb(skb)->pkt_type) {
Linus Torvalds's avatar
Linus Torvalds committed
489
490
491
492
493
494
495
496
497
498
499
500
	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 */
501
	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
Linus Torvalds's avatar
Linus Torvalds committed
502
503
504
505

	count = skb->len;

	/* Max HCI frame size seems to be 1511 + 1 */
506
507
	nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
	if (!nskb) {
Linus Torvalds's avatar
Linus Torvalds committed
508
509
510
511
		BT_ERR("Can't allocate memory for new packet");
		return -ENOMEM;
	}

512
	nskb->dev = (void *) data;
Linus Torvalds's avatar
Linus Torvalds committed
513
514
515
516
517
518
519
520
521

	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);
522
		skb_copy_from_linear_data_offset(skb, sent, skb_put(nskb, size), size);
Linus Torvalds's avatar
Linus Torvalds committed
523
524
525
526
527
528

		sent  += size;
		count -= size;
	}

	/* Don't send frame with multiple size of bulk max packet */
529
	if ((nskb->len % data->bulk_pkt_size) == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
530
531
532
533
534
		buf[0] = 0xdd;
		buf[1] = 0x00;
		memcpy(skb_put(nskb, 2), buf, 2);
	}

535
	read_lock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
536

537
538
	skb_queue_tail(&data->transmit_q, nskb);
	bfusb_tx_wakeup(data);
Linus Torvalds's avatar
Linus Torvalds committed
539

540
	read_unlock(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
541
542
543
544
545
546
547
548

	kfree_skb(skb);

	return 0;
}

static void bfusb_destruct(struct hci_dev *hdev)
{
549
	struct bfusb_data *data = hdev->driver_data;
Linus Torvalds's avatar
Linus Torvalds committed
550

551
	BT_DBG("hdev %p bfusb %p", hdev, data);
Linus Torvalds's avatar
Linus Torvalds committed
552

553
	kfree(data);
Linus Torvalds's avatar
Linus Torvalds committed
554
555
556
557
558
559
560
}

static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
{
	return -ENOIOCTLCMD;
}

561
562
static int bfusb_load_firmware(struct bfusb_data *data,
			       const unsigned char *firmware, int count)
Linus Torvalds's avatar
Linus Torvalds committed
563
564
565
566
{
	unsigned char *buf;
	int err, pipe, len, size, sent = 0;

567
	BT_DBG("bfusb %p udev %p", data, data->udev);
Linus Torvalds's avatar
Linus Torvalds committed
568
569
570

	BT_INFO("BlueFRITZ! USB loading firmware");

571
572
573
574
575
576
	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
	if (!buf) {
		BT_ERR("Can't allocate memory chunk for firmware");
		return -ENOMEM;
	}

577
	pipe = usb_sndctrlpipe(data->udev, 0);
Linus Torvalds's avatar
Linus Torvalds committed
578

579
	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
Linus Torvalds's avatar
Linus Torvalds committed
580
581
				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
		BT_ERR("Can't change to loading configuration");
582
		kfree(buf);
Linus Torvalds's avatar
Linus Torvalds committed
583
584
585
		return -EBUSY;
	}

586
	data->udev->toggle[0] = data->udev->toggle[1] = 0;
Linus Torvalds's avatar
Linus Torvalds committed
587

588
	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
Linus Torvalds's avatar
Linus Torvalds committed
589
590
591
592
593
594

	while (count) {
		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);

		memcpy(buf, firmware + sent, size);

595
		err = usb_bulk_msg(data->udev, pipe, buf, size,
Linus Torvalds's avatar
Linus Torvalds committed
596
597
598
599
600
601
602
603
604
605
606
					&len, BFUSB_BLOCK_TIMEOUT);

		if (err || (len != size)) {
			BT_ERR("Error in firmware loading");
			goto error;
		}

		sent  += size;
		count -= size;
	}

607
608
609
	err = usb_bulk_msg(data->udev, pipe, NULL, 0,
					&len, BFUSB_BLOCK_TIMEOUT);
	if (err < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
610
611
612
613
		BT_ERR("Error in null packet request");
		goto error;
	}

614
	pipe = usb_sndctrlpipe(data->udev, 0);
Linus Torvalds's avatar
Linus Torvalds committed
615

616
617
618
	err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
	if (err < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
619
620
621
622
		BT_ERR("Can't change to running configuration");
		goto error;
	}

623
	data->udev->toggle[0] = data->udev->toggle[1] = 0;
Linus Torvalds's avatar
Linus Torvalds committed
624
625
626
627
628
629
630
631
632

	BT_INFO("BlueFRITZ! USB device ready");

	kfree(buf);
	return 0;

error:
	kfree(buf);

633
	pipe = usb_sndctrlpipe(data->udev, 0);
Linus Torvalds's avatar
Linus Torvalds committed
634

635
	usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
Linus Torvalds's avatar
Linus Torvalds committed
636
637
638
639
640
641
642
643
644
645
646
647
				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;
648
	struct bfusb_data *data;
Linus Torvalds's avatar
Linus Torvalds committed
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

	BT_DBG("intf %p id %p", intf, id);

	/* 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 */
665
666
	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
	if (!data) {
Linus Torvalds's avatar
Linus Torvalds committed
667
668
669
670
		BT_ERR("Can't allocate memory for control structure");
		goto done;
	}

671
672
673
674
	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);
Linus Torvalds's avatar
Linus Torvalds committed
675

676
	rwlock_init(&data->lock);
Linus Torvalds's avatar
Linus Torvalds committed
677

678
	data->reassembly = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
679

680
681
682
	skb_queue_head_init(&data->transmit_q);
	skb_queue_head_init(&data->pending_q);
	skb_queue_head_init(&data->completed_q);
Linus Torvalds's avatar
Linus Torvalds committed
683
684
685
686
687
688

	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
		BT_ERR("Firmware request failed");
		goto error;
	}

689
	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
Linus Torvalds's avatar
Linus Torvalds committed
690

691
	if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
692
693
694
695
696
697
698
699
700
701
702
703
704
		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;
	}

705
	data->hdev = hdev;
Linus Torvalds's avatar
Linus Torvalds committed
706

707
	hdev->bus = HCI_USB;
708
	hdev->driver_data = data;
Linus Torvalds's avatar
Linus Torvalds committed
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
	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;
	}

726
	usb_set_intfdata(intf, data);
Linus Torvalds's avatar
Linus Torvalds committed
727
728
729
730
731
732
733

	return 0;

release:
	release_firmware(firmware);

error:
734
	kfree(data);
Linus Torvalds's avatar
Linus Torvalds committed
735
736
737
738
739
740
741

done:
	return -EIO;
}

static void bfusb_disconnect(struct usb_interface *intf)
{
742
743
	struct bfusb_data *data = usb_get_intfdata(intf);
	struct hci_dev *hdev = data->hdev;
Linus Torvalds's avatar
Linus Torvalds committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

	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 = {
	.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);

773
774
	err = usb_register(&bfusb_driver);
	if (err < 0)
Linus Torvalds's avatar
Linus Torvalds committed
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
		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);

MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
792
MODULE_FIRMWARE("bfubase.frm");