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
			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 353 354 355

	return 0;
}

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

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

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

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

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

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

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

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

414
	default:
415
		usb_free_urb(urb);
416 417 418 419
		return -EILSEQ;
	}

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

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

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

	return 0;
}

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

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

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

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

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

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

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

457
	hdev->bus = HCI_USB;
458
	hci_set_drvdata(hdev, data);
459 460 461

	data->hdev = hdev;

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

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

469
	set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
470

L
Linus Torvalds 已提交
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
	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);

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

	usb_set_intfdata(intf, NULL);

493
	hci_unregister_dev(data->hdev);
L
Linus Torvalds 已提交
494

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

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

508
module_usb_driver(bpa10x_driver);
L
Linus Torvalds 已提交
509 510 511 512 513

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