bpa10x.c 10.3 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 41 42 43 44 45 46 47 48 49

static struct usb_device_id bpa10x_table[] = {
	/* 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
			skb->dev = (void *) hdev;
L
Linus Torvalds 已提交
133

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

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

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

146
		len = min(len, count);
L
Linus Torvalds 已提交
147

148
		memcpy(skb_put(skb, len), buf, len);
L
Linus Torvalds 已提交
149

150
		scb->expect -= len;
L
Linus Torvalds 已提交
151

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

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

157
			bt_cb(skb)->pkt_type = scb->type;
L
Linus Torvalds 已提交
158 159
			hci_recv_frame(skb);
		}
160 161

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

	return 0;
}

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

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

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

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

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

186 187 188 189 190 191
	kfree_skb(skb);
}

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

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

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

201 202 203 204 205 206 207
	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 已提交
208 209
	}

210 211 212 213 214 215 216
	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 已提交
217 218 219
	}
}

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

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

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

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

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

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

245
	urb->transfer_flags |= URB_FREE_BUFFER;
L
Linus Torvalds 已提交
246

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

249 250 251 252 253
	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 已提交
254 255
	}

256
	usb_free_urb(urb);
L
Linus Torvalds 已提交
257

258
	return err;
L
Linus Torvalds 已提交
259 260
}

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

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

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

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

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

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

286
	urb->transfer_flags |= URB_FREE_BUFFER;
L
Linus Torvalds 已提交
287

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

290 291 292 293 294
	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 已提交
295 296 297
	}

	usb_free_urb(urb);
298 299

	return err;
L
Linus Torvalds 已提交
300 301 302 303
}

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

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

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

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

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

320
	return 0;
L
Linus Torvalds 已提交
321

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

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

	return err;
}

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

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

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

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

	return 0;
}

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

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

350
	usb_kill_anchored_urbs(&data->tx_anchor);
L
Linus Torvalds 已提交
351 352 353 354 355 356 357

	return 0;
}

static int bpa10x_send_frame(struct sk_buff *skb)
{
	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
358
	struct bpa10x_data *data = hci_get_drvdata(hdev);
359 360 361 362
	struct usb_ctrlrequest *dr;
	struct urb *urb;
	unsigned int pipe;
	int err;
L
Linus Torvalds 已提交
363

364
	BT_DBG("%s", hdev->name);
L
Linus Torvalds 已提交
365 366 367 368

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

369 370 371
	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb)
		return -ENOMEM;
L
Linus Torvalds 已提交
372 373

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

376
	switch (bt_cb(skb)->pkt_type) {
L
Linus Torvalds 已提交
377
	case HCI_COMMAND_PKT:
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
		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 已提交
395 396 397 398
		hdev->stat.cmd_tx++;
		break;

	case HCI_ACLDATA_PKT:
399 400 401 402 403
		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 已提交
404 405 406 407
		hdev->stat.acl_tx++;
		break;

	case HCI_SCODATA_PKT:
408 409 410 411 412
		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 已提交
413 414 415
		hdev->stat.sco_tx++;
		break;

416
	default:
417
		usb_free_urb(urb);
418 419 420 421
		return -EILSEQ;
	}

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

423 424 425 426 427 428
	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 已提交
429

430
	usb_free_urb(urb);
L
Linus Torvalds 已提交
431 432 433 434 435 436 437

	return 0;
}

static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct bpa10x_data *data;
438
	struct hci_dev *hdev;
L
Linus Torvalds 已提交
439 440 441 442
	int err;

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

443
	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
L
Linus Torvalds 已提交
444 445
		return -ENODEV;

446
	data = kzalloc(sizeof(*data), GFP_KERNEL);
447
	if (!data)
L
Linus Torvalds 已提交
448 449
		return -ENOMEM;

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

452 453
	init_usb_anchor(&data->tx_anchor);
	init_usb_anchor(&data->rx_anchor);
L
Linus Torvalds 已提交
454 455 456 457 458 459 460

	hdev = hci_alloc_dev();
	if (!hdev) {
		kfree(data);
		return -ENOMEM;
	}

461
	hdev->bus = HCI_USB;
462
	hci_set_drvdata(hdev, data);
463 464 465

	data->hdev = hdev;

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

468 469 470 471
	hdev->open     = bpa10x_open;
	hdev->close    = bpa10x_close;
	hdev->flush    = bpa10x_flush;
	hdev->send     = bpa10x_send_frame;
L
Linus Torvalds 已提交
472

473 474
	set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);

L
Linus Torvalds 已提交
475 476 477
	err = hci_register_dev(hdev);
	if (err < 0) {
		hci_free_dev(hdev);
478
		kfree(data);
L
Linus Torvalds 已提交
479 480 481 482 483 484 485 486 487 488 489 490 491 492
		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);

493
	if (!data)
L
Linus Torvalds 已提交
494 495 496 497
		return;

	usb_set_intfdata(intf, NULL);

498
	hci_unregister_dev(data->hdev);
L
Linus Torvalds 已提交
499

500
	hci_free_dev(data->hdev);
501 502 503
	kfree_skb(data->rx_skb[0]);
	kfree_skb(data->rx_skb[1]);
	kfree(data);
L
Linus Torvalds 已提交
504 505 506 507 508 509 510
}

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

514
module_usb_driver(bpa10x_driver);
L
Linus Torvalds 已提交
515 516 517 518 519

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