bpa10x.c 10.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
/*
 *
 *  Digianswer Bluetooth USB driver
 *
5
 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
L
Linus Torvalds 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 *
 *  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/kernel.h>
25
#include <linux/module.h>
L
Linus Torvalds 已提交
26 27 28
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
29
#include <linux/sched.h>
L
Linus Torvalds 已提交
30
#include <linux/errno.h>
31
#include <linux/skbuff.h>
L
Linus Torvalds 已提交
32 33 34 35 36 37

#include <linux/usb.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>

38
#define VERSION "0.10"
L
Linus Torvalds 已提交
39

40
static const struct usb_device_id bpa10x_table[] = {
L
Linus Torvalds 已提交
41 42 43 44 45 46 47 48 49
	/* Tektronix BPA 100/105 (Digianswer) */
	{ USB_DEVICE(0x08fd, 0x0002) },

	{ }	/* Terminating entry */
};

MODULE_DEVICE_TABLE(usb, bpa10x_table);

struct bpa10x_data {
50 51
	struct hci_dev    *hdev;
	struct usb_device *udev;
L
Linus Torvalds 已提交
52

53 54
	struct usb_anchor tx_anchor;
	struct usb_anchor rx_anchor;
L
Linus Torvalds 已提交
55

56
	struct sk_buff *rx_skb[2];
L
Linus Torvalds 已提交
57 58
};

59
#define HCI_VENDOR_HDR_SIZE 5
L
Linus Torvalds 已提交
60 61

struct hci_vendor_hdr {
62 63 64
	__u8    type;
	__le16  snum;
	__le16  dlen;
65
} __packed;
L
Linus Torvalds 已提交
66

67
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
L
Linus Torvalds 已提交
68
{
69
	struct bpa10x_data *data = hci_get_drvdata(hdev);
70 71 72 73 74 75 76 77

	BT_DBG("%s queue %d buffer %p count %d", hdev->name,
							queue, buf, count);

	if (queue < 0 || queue > 1)
		return -EILSEQ;

	hdev->stat.byte_rx += count;
L
Linus Torvalds 已提交
78 79

	while (count) {
80 81 82
		struct sk_buff *skb = data->rx_skb[queue];
		struct { __u8 type; int expect; } *scb;
		int type, len = 0;
L
Linus Torvalds 已提交
83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 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
		if (!skb) {
			/* Start of the frame */

			type = *((__u8 *) buf);
			count--; buf++;

			switch (type) {
			case HCI_EVENT_PKT:
				if (count >= HCI_EVENT_HDR_SIZE) {
					struct hci_event_hdr *h = buf;
					len = HCI_EVENT_HDR_SIZE + h->plen;
				} else
					return -EILSEQ;
				break;

			case HCI_ACLDATA_PKT:
				if (count >= HCI_ACL_HDR_SIZE) {
					struct hci_acl_hdr *h = buf;
					len = HCI_ACL_HDR_SIZE +
							__le16_to_cpu(h->dlen);
				} else
					return -EILSEQ;
				break;

			case HCI_SCODATA_PKT:
				if (count >= HCI_SCO_HDR_SIZE) {
					struct hci_sco_hdr *h = buf;
					len = HCI_SCO_HDR_SIZE + h->dlen;
				} else
					return -EILSEQ;
				break;

			case HCI_VENDOR_PKT:
				if (count >= HCI_VENDOR_HDR_SIZE) {
					struct hci_vendor_hdr *h = buf;
					len = HCI_VENDOR_HDR_SIZE +
							__le16_to_cpu(h->dlen);
				} else
					return -EILSEQ;
				break;
L
Linus Torvalds 已提交
124 125 126
			}

			skb = bt_skb_alloc(len, GFP_ATOMIC);
127 128 129
			if (!skb) {
				BT_ERR("%s no memory for packet", hdev->name);
				return -ENOMEM;
L
Linus Torvalds 已提交
130 131
			}

132
			data->rx_skb[queue] = skb;
L
Linus Torvalds 已提交
133

134 135 136 137 138
			scb = (void *) skb->cb;
			scb->type = type;
			scb->expect = len;
		} else {
			/* Continuation */
L
Linus Torvalds 已提交
139

140 141
			scb = (void *) skb->cb;
			len = scb->expect;
L
Linus Torvalds 已提交
142 143
		}

144
		len = min(len, count);
L
Linus Torvalds 已提交
145

146
		memcpy(skb_put(skb, len), buf, len);
L
Linus Torvalds 已提交
147

148
		scb->expect -= len;
L
Linus Torvalds 已提交
149

150 151
		if (scb->expect == 0) {
			/* Complete frame */
L
Linus Torvalds 已提交
152

153
			data->rx_skb[queue] = NULL;
L
Linus Torvalds 已提交
154

155
			bt_cb(skb)->pkt_type = scb->type;
156
			hci_recv_frame(hdev, skb);
L
Linus Torvalds 已提交
157
		}
158 159

		count -= len; buf += len;
L
Linus Torvalds 已提交
160 161 162 163 164
	}

	return 0;
}

165
static void bpa10x_tx_complete(struct urb *urb)
L
Linus Torvalds 已提交
166
{
167 168
	struct sk_buff *skb = urb->context;
	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
L
Linus Torvalds 已提交
169

170 171
	BT_DBG("%s urb %p status %d count %d", hdev->name,
					urb, urb->status, urb->actual_length);
L
Linus Torvalds 已提交
172

173 174 175 176 177
	if (!test_bit(HCI_RUNNING, &hdev->flags))
		goto done;

	if (!urb->status)
		hdev->stat.byte_tx += urb->transfer_buffer_length;
L
Linus Torvalds 已提交
178
	else
179
		hdev->stat.err_tx++;
L
Linus Torvalds 已提交
180

181 182
done:
	kfree(urb->setup_packet);
L
Linus Torvalds 已提交
183

184 185 186 187 188 189
	kfree_skb(skb);
}

static void bpa10x_rx_complete(struct urb *urb)
{
	struct hci_dev *hdev = urb->context;
190
	struct bpa10x_data *data = hci_get_drvdata(hdev);
191
	int err;
L
Linus Torvalds 已提交
192

193 194
	BT_DBG("%s urb %p status %d count %d", hdev->name,
					urb, urb->status, urb->actual_length);
L
Linus Torvalds 已提交
195

196 197
	if (!test_bit(HCI_RUNNING, &hdev->flags))
		return;
L
Linus Torvalds 已提交
198

199 200 201 202 203 204 205
	if (urb->status == 0) {
		if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe),
						urb->transfer_buffer,
						urb->actual_length) < 0) {
			BT_ERR("%s corrupted event packet", hdev->name);
			hdev->stat.err_rx++;
		}
L
Linus Torvalds 已提交
206 207
	}

208 209 210 211 212 213 214
	usb_anchor_urb(urb, &data->rx_anchor);

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err < 0) {
		BT_ERR("%s urb %p failed to resubmit (%d)",
						hdev->name, urb, -err);
		usb_unanchor_urb(urb);
L
Linus Torvalds 已提交
215 216 217
	}
}

218
static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
L
Linus Torvalds 已提交
219
{
220
	struct bpa10x_data *data = hci_get_drvdata(hdev);
221 222 223 224
	struct urb *urb;
	unsigned char *buf;
	unsigned int pipe;
	int err, size = 16;
L
Linus Torvalds 已提交
225

226
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
227

228 229 230
	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb)
		return -ENOMEM;
L
Linus Torvalds 已提交
231

232 233 234 235 236
	buf = kmalloc(size, GFP_KERNEL);
	if (!buf) {
		usb_free_urb(urb);
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
237

238
	pipe = usb_rcvintpipe(data->udev, 0x81);
L
Linus Torvalds 已提交
239

240 241
	usb_fill_int_urb(urb, data->udev, pipe, buf, size,
						bpa10x_rx_complete, hdev, 1);
L
Linus Torvalds 已提交
242

243
	urb->transfer_flags |= URB_FREE_BUFFER;
L
Linus Torvalds 已提交
244

245
	usb_anchor_urb(urb, &data->rx_anchor);
L
Linus Torvalds 已提交
246

247 248 249 250 251
	err = usb_submit_urb(urb, GFP_KERNEL);
	if (err < 0) {
		BT_ERR("%s urb %p submission failed (%d)",
						hdev->name, urb, -err);
		usb_unanchor_urb(urb);
L
Linus Torvalds 已提交
252 253
	}

254
	usb_free_urb(urb);
L
Linus Torvalds 已提交
255

256
	return err;
L
Linus Torvalds 已提交
257 258
}

259
static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
L
Linus Torvalds 已提交
260
{
261
	struct bpa10x_data *data = hci_get_drvdata(hdev);
L
Linus Torvalds 已提交
262 263
	struct urb *urb;
	unsigned char *buf;
264 265
	unsigned int pipe;
	int err, size = 64;
L
Linus Torvalds 已提交
266

267
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
268

269
	urb = usb_alloc_urb(0, GFP_KERNEL);
L
Linus Torvalds 已提交
270
	if (!urb)
271
		return -ENOMEM;
L
Linus Torvalds 已提交
272

273
	buf = kmalloc(size, GFP_KERNEL);
L
Linus Torvalds 已提交
274 275
	if (!buf) {
		usb_free_urb(urb);
276
		return -ENOMEM;
L
Linus Torvalds 已提交
277 278
	}

279
	pipe = usb_rcvbulkpipe(data->udev, 0x82);
L
Linus Torvalds 已提交
280

281 282
	usb_fill_bulk_urb(urb, data->udev, pipe,
					buf, size, bpa10x_rx_complete, hdev);
L
Linus Torvalds 已提交
283

284
	urb->transfer_flags |= URB_FREE_BUFFER;
L
Linus Torvalds 已提交
285

286
	usb_anchor_urb(urb, &data->rx_anchor);
L
Linus Torvalds 已提交
287

288 289 290 291 292
	err = usb_submit_urb(urb, GFP_KERNEL);
	if (err < 0) {
		BT_ERR("%s urb %p submission failed (%d)",
						hdev->name, urb, -err);
		usb_unanchor_urb(urb);
L
Linus Torvalds 已提交
293 294 295
	}

	usb_free_urb(urb);
296 297

	return err;
L
Linus Torvalds 已提交
298 299 300 301
}

static int bpa10x_open(struct hci_dev *hdev)
{
302
	struct bpa10x_data *data = hci_get_drvdata(hdev);
L
Linus Torvalds 已提交
303 304
	int err;

305
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
306 307 308 309

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

310 311 312
	err = bpa10x_submit_intr_urb(hdev);
	if (err < 0)
		goto error;
L
Linus Torvalds 已提交
313

314 315 316
	err = bpa10x_submit_bulk_urb(hdev);
	if (err < 0)
		goto error;
L
Linus Torvalds 已提交
317

318
	return 0;
L
Linus Torvalds 已提交
319

320 321
error:
	usb_kill_anchored_urbs(&data->rx_anchor);
L
Linus Torvalds 已提交
322

323
	clear_bit(HCI_RUNNING, &hdev->flags);
L
Linus Torvalds 已提交
324 325 326 327 328 329

	return err;
}

static int bpa10x_close(struct hci_dev *hdev)
{
330
	struct bpa10x_data *data = hci_get_drvdata(hdev);
L
Linus Torvalds 已提交
331

332
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
333 334 335 336

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

337
	usb_kill_anchored_urbs(&data->rx_anchor);
L
Linus Torvalds 已提交
338 339 340 341 342 343

	return 0;
}

static int bpa10x_flush(struct hci_dev *hdev)
{
344
	struct bpa10x_data *data = hci_get_drvdata(hdev);
L
Linus Torvalds 已提交
345

346
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
347

348
	usb_kill_anchored_urbs(&data->tx_anchor);
L
Linus Torvalds 已提交
349 350 351 352

	return 0;
}

353
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
L
Linus Torvalds 已提交
354
{
355
	struct bpa10x_data *data = hci_get_drvdata(hdev);
356 357 358 359
	struct usb_ctrlrequest *dr;
	struct urb *urb;
	unsigned int pipe;
	int err;
L
Linus Torvalds 已提交
360

361
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
362

363 364
	skb->dev = (void *) hdev;

365 366 367
	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb)
		return -ENOMEM;
L
Linus Torvalds 已提交
368 369

	/* Prepend skb with frame type */
370
	*skb_push(skb, 1) = bt_cb(skb)->pkt_type;
L
Linus Torvalds 已提交
371

372
	switch (bt_cb(skb)->pkt_type) {
L
Linus Torvalds 已提交
373
	case HCI_COMMAND_PKT:
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
		dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
		if (!dr) {
			usb_free_urb(urb);
			return -ENOMEM;
		}

		dr->bRequestType = USB_TYPE_VENDOR;
		dr->bRequest     = 0;
		dr->wIndex       = 0;
		dr->wValue       = 0;
		dr->wLength      = __cpu_to_le16(skb->len);

		pipe = usb_sndctrlpipe(data->udev, 0x00);

		usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
				skb->data, skb->len, bpa10x_tx_complete, skb);

L
Linus Torvalds 已提交
391 392 393 394
		hdev->stat.cmd_tx++;
		break;

	case HCI_ACLDATA_PKT:
395 396 397 398 399
		pipe = usb_sndbulkpipe(data->udev, 0x02);

		usb_fill_bulk_urb(urb, data->udev, pipe,
				skb->data, skb->len, bpa10x_tx_complete, skb);

L
Linus Torvalds 已提交
400 401 402 403
		hdev->stat.acl_tx++;
		break;

	case HCI_SCODATA_PKT:
404 405 406 407 408
		pipe = usb_sndbulkpipe(data->udev, 0x02);

		usb_fill_bulk_urb(urb, data->udev, pipe,
				skb->data, skb->len, bpa10x_tx_complete, skb);

L
Linus Torvalds 已提交
409 410 411
		hdev->stat.sco_tx++;
		break;

412
	default:
413
		usb_free_urb(urb);
414 415 416 417
		return -EILSEQ;
	}

	usb_anchor_urb(urb, &data->tx_anchor);
L
Linus Torvalds 已提交
418

419 420 421 422 423 424
	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err < 0) {
		BT_ERR("%s urb %p submission failed", hdev->name, urb);
		kfree(urb->setup_packet);
		usb_unanchor_urb(urb);
	}
L
Linus Torvalds 已提交
425

426
	usb_free_urb(urb);
L
Linus Torvalds 已提交
427 428 429 430 431 432 433

	return 0;
}

static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct bpa10x_data *data;
434
	struct hci_dev *hdev;
L
Linus Torvalds 已提交
435 436 437 438
	int err;

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

439
	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
L
Linus Torvalds 已提交
440 441
		return -ENODEV;

442
	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
443
	if (!data)
L
Linus Torvalds 已提交
444 445
		return -ENOMEM;

446
	data->udev = interface_to_usbdev(intf);
L
Linus Torvalds 已提交
447

448 449
	init_usb_anchor(&data->tx_anchor);
	init_usb_anchor(&data->rx_anchor);
L
Linus Torvalds 已提交
450 451

	hdev = hci_alloc_dev();
452
	if (!hdev)
L
Linus Torvalds 已提交
453 454
		return -ENOMEM;

455
	hdev->bus = HCI_USB;
456
	hci_set_drvdata(hdev, data);
457 458 459

	data->hdev = hdev;

L
Linus Torvalds 已提交
460 461
	SET_HCIDEV_DEV(hdev, &intf->dev);

462 463 464 465
	hdev->open     = bpa10x_open;
	hdev->close    = bpa10x_close;
	hdev->flush    = bpa10x_flush;
	hdev->send     = bpa10x_send_frame;
L
Linus Torvalds 已提交
466

467
	set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
468

L
Linus Torvalds 已提交
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
	err = hci_register_dev(hdev);
	if (err < 0) {
		hci_free_dev(hdev);
		return err;
	}

	usb_set_intfdata(intf, data);

	return 0;
}

static void bpa10x_disconnect(struct usb_interface *intf)
{
	struct bpa10x_data *data = usb_get_intfdata(intf);

	BT_DBG("intf %p", intf);

486
	if (!data)
L
Linus Torvalds 已提交
487 488 489 490
		return;

	usb_set_intfdata(intf, NULL);

491
	hci_unregister_dev(data->hdev);
L
Linus Torvalds 已提交
492

493
	hci_free_dev(data->hdev);
494 495
	kfree_skb(data->rx_skb[0]);
	kfree_skb(data->rx_skb[1]);
L
Linus Torvalds 已提交
496 497 498 499 500 501 502
}

static struct usb_driver bpa10x_driver = {
	.name		= "bpa10x",
	.probe		= bpa10x_probe,
	.disconnect	= bpa10x_disconnect,
	.id_table	= bpa10x_table,
503
	.disable_hub_initiated_lpm = 1,
L
Linus Torvalds 已提交
504 505
};

506
module_usb_driver(bpa10x_driver);
L
Linus Torvalds 已提交
507 508 509 510 511

MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");