Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/bluetooth/bpa10x.c
48869 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
*
4
* Digianswer Bluetooth USB driver
5
*
6
* Copyright (C) 2004-2007 Marcel Holtmann <[email protected]>
7
*/
8
9
#include <linux/kernel.h>
10
#include <linux/module.h>
11
#include <linux/init.h>
12
#include <linux/slab.h>
13
#include <linux/types.h>
14
#include <linux/sched.h>
15
#include <linux/errno.h>
16
#include <linux/skbuff.h>
17
18
#include <linux/usb.h>
19
20
#include <net/bluetooth/bluetooth.h>
21
#include <net/bluetooth/hci_core.h>
22
23
#include "hci_uart.h"
24
25
#define VERSION "0.11"
26
27
static const struct usb_device_id bpa10x_table[] = {
28
/* Tektronix BPA 100/105 (Digianswer) */
29
{ USB_DEVICE(0x08fd, 0x0002) },
30
31
{ } /* Terminating entry */
32
};
33
34
MODULE_DEVICE_TABLE(usb, bpa10x_table);
35
36
struct bpa10x_data {
37
struct hci_dev *hdev;
38
struct usb_device *udev;
39
40
struct usb_anchor tx_anchor;
41
struct usb_anchor rx_anchor;
42
43
struct sk_buff *rx_skb[2];
44
struct hci_uart hu;
45
};
46
47
static void bpa10x_tx_complete(struct urb *urb)
48
{
49
struct sk_buff *skb = urb->context;
50
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
51
52
BT_DBG("%s urb %p status %d count %d", hdev->name,
53
urb, urb->status, urb->actual_length);
54
55
if (!test_bit(HCI_RUNNING, &hdev->flags))
56
goto done;
57
58
if (!urb->status)
59
hdev->stat.byte_tx += urb->transfer_buffer_length;
60
else
61
hdev->stat.err_tx++;
62
63
done:
64
kfree(urb->setup_packet);
65
66
kfree_skb(skb);
67
}
68
69
#define HCI_VENDOR_HDR_SIZE 5
70
71
#define HCI_RECV_VENDOR \
72
.type = HCI_VENDOR_PKT, \
73
.hlen = HCI_VENDOR_HDR_SIZE, \
74
.loff = 3, \
75
.lsize = 2, \
76
.maxlen = HCI_MAX_FRAME_SIZE
77
78
static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
79
{ H4_RECV_ACL, .recv = hci_recv_frame },
80
{ H4_RECV_SCO, .recv = hci_recv_frame },
81
{ H4_RECV_EVENT, .recv = hci_recv_frame },
82
{ HCI_RECV_VENDOR, .recv = hci_recv_diag },
83
};
84
85
static void bpa10x_rx_complete(struct urb *urb)
86
{
87
struct hci_dev *hdev = urb->context;
88
struct bpa10x_data *data = hci_get_drvdata(hdev);
89
int err;
90
91
BT_DBG("%s urb %p status %d count %d", hdev->name,
92
urb, urb->status, urb->actual_length);
93
94
if (!test_bit(HCI_RUNNING, &hdev->flags))
95
return;
96
97
if (urb->status == 0) {
98
bool idx = usb_pipebulk(urb->pipe);
99
100
data->rx_skb[idx] = h4_recv_buf(&data->hu, data->rx_skb[idx],
101
urb->transfer_buffer,
102
urb->actual_length,
103
bpa10x_recv_pkts,
104
ARRAY_SIZE(bpa10x_recv_pkts));
105
if (IS_ERR(data->rx_skb[idx])) {
106
bt_dev_err(hdev, "corrupted event packet");
107
hdev->stat.err_rx++;
108
data->rx_skb[idx] = NULL;
109
}
110
}
111
112
usb_anchor_urb(urb, &data->rx_anchor);
113
114
err = usb_submit_urb(urb, GFP_ATOMIC);
115
if (err < 0) {
116
bt_dev_err(hdev, "urb %p failed to resubmit (%d)", urb, -err);
117
usb_unanchor_urb(urb);
118
}
119
}
120
121
static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
122
{
123
struct bpa10x_data *data = hci_get_drvdata(hdev);
124
struct urb *urb;
125
unsigned char *buf;
126
unsigned int pipe;
127
int err, size = 16;
128
129
BT_DBG("%s", hdev->name);
130
131
urb = usb_alloc_urb(0, GFP_KERNEL);
132
if (!urb)
133
return -ENOMEM;
134
135
buf = kmalloc(size, GFP_KERNEL);
136
if (!buf) {
137
usb_free_urb(urb);
138
return -ENOMEM;
139
}
140
141
pipe = usb_rcvintpipe(data->udev, 0x81);
142
143
usb_fill_int_urb(urb, data->udev, pipe, buf, size,
144
bpa10x_rx_complete, hdev, 1);
145
146
urb->transfer_flags |= URB_FREE_BUFFER;
147
148
usb_anchor_urb(urb, &data->rx_anchor);
149
150
err = usb_submit_urb(urb, GFP_KERNEL);
151
if (err < 0) {
152
bt_dev_err(hdev, "urb %p submission failed (%d)", urb, -err);
153
usb_unanchor_urb(urb);
154
}
155
156
usb_free_urb(urb);
157
158
return err;
159
}
160
161
static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
162
{
163
struct bpa10x_data *data = hci_get_drvdata(hdev);
164
struct urb *urb;
165
unsigned char *buf;
166
unsigned int pipe;
167
int err, size = 64;
168
169
BT_DBG("%s", hdev->name);
170
171
urb = usb_alloc_urb(0, GFP_KERNEL);
172
if (!urb)
173
return -ENOMEM;
174
175
buf = kmalloc(size, GFP_KERNEL);
176
if (!buf) {
177
usb_free_urb(urb);
178
return -ENOMEM;
179
}
180
181
pipe = usb_rcvbulkpipe(data->udev, 0x82);
182
183
usb_fill_bulk_urb(urb, data->udev, pipe,
184
buf, size, bpa10x_rx_complete, hdev);
185
186
urb->transfer_flags |= URB_FREE_BUFFER;
187
188
usb_anchor_urb(urb, &data->rx_anchor);
189
190
err = usb_submit_urb(urb, GFP_KERNEL);
191
if (err < 0) {
192
bt_dev_err(hdev, "urb %p submission failed (%d)", urb, -err);
193
usb_unanchor_urb(urb);
194
}
195
196
usb_free_urb(urb);
197
198
return err;
199
}
200
201
static int bpa10x_open(struct hci_dev *hdev)
202
{
203
struct bpa10x_data *data = hci_get_drvdata(hdev);
204
int err;
205
206
BT_DBG("%s", hdev->name);
207
208
err = bpa10x_submit_intr_urb(hdev);
209
if (err < 0)
210
goto error;
211
212
err = bpa10x_submit_bulk_urb(hdev);
213
if (err < 0)
214
goto error;
215
216
return 0;
217
218
error:
219
usb_kill_anchored_urbs(&data->rx_anchor);
220
221
return err;
222
}
223
224
static int bpa10x_close(struct hci_dev *hdev)
225
{
226
struct bpa10x_data *data = hci_get_drvdata(hdev);
227
228
BT_DBG("%s", hdev->name);
229
230
usb_kill_anchored_urbs(&data->rx_anchor);
231
232
return 0;
233
}
234
235
static int bpa10x_flush(struct hci_dev *hdev)
236
{
237
struct bpa10x_data *data = hci_get_drvdata(hdev);
238
239
BT_DBG("%s", hdev->name);
240
241
usb_kill_anchored_urbs(&data->tx_anchor);
242
243
return 0;
244
}
245
246
static int bpa10x_setup(struct hci_dev *hdev)
247
{
248
static const u8 req[] = { 0x07 };
249
struct sk_buff *skb;
250
251
BT_DBG("%s", hdev->name);
252
253
/* Read revision string */
254
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
255
if (IS_ERR(skb))
256
return PTR_ERR(skb);
257
258
bt_dev_info(hdev, "%s", (char *)(skb->data + 1));
259
260
hci_set_fw_info(hdev, "%s", skb->data + 1);
261
262
kfree_skb(skb);
263
return 0;
264
}
265
266
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
267
{
268
struct bpa10x_data *data = hci_get_drvdata(hdev);
269
struct usb_ctrlrequest *dr;
270
struct urb *urb;
271
unsigned int pipe;
272
int err;
273
274
BT_DBG("%s", hdev->name);
275
276
skb->dev = (void *) hdev;
277
278
urb = usb_alloc_urb(0, GFP_KERNEL);
279
if (!urb)
280
return -ENOMEM;
281
282
/* Prepend skb with frame type */
283
*(u8 *)skb_push(skb, 1) = hci_skb_pkt_type(skb);
284
285
switch (hci_skb_pkt_type(skb)) {
286
case HCI_COMMAND_PKT:
287
dr = kmalloc(sizeof(*dr), GFP_KERNEL);
288
if (!dr) {
289
usb_free_urb(urb);
290
return -ENOMEM;
291
}
292
293
dr->bRequestType = USB_TYPE_VENDOR;
294
dr->bRequest = 0;
295
dr->wIndex = 0;
296
dr->wValue = 0;
297
dr->wLength = __cpu_to_le16(skb->len);
298
299
pipe = usb_sndctrlpipe(data->udev, 0x00);
300
301
usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
302
skb->data, skb->len, bpa10x_tx_complete, skb);
303
304
hdev->stat.cmd_tx++;
305
break;
306
307
case HCI_ACLDATA_PKT:
308
pipe = usb_sndbulkpipe(data->udev, 0x02);
309
310
usb_fill_bulk_urb(urb, data->udev, pipe,
311
skb->data, skb->len, bpa10x_tx_complete, skb);
312
313
hdev->stat.acl_tx++;
314
break;
315
316
case HCI_SCODATA_PKT:
317
pipe = usb_sndbulkpipe(data->udev, 0x02);
318
319
usb_fill_bulk_urb(urb, data->udev, pipe,
320
skb->data, skb->len, bpa10x_tx_complete, skb);
321
322
hdev->stat.sco_tx++;
323
break;
324
325
default:
326
usb_free_urb(urb);
327
return -EILSEQ;
328
}
329
330
usb_anchor_urb(urb, &data->tx_anchor);
331
332
err = usb_submit_urb(urb, GFP_KERNEL);
333
if (err < 0) {
334
bt_dev_err(hdev, "urb %p submission failed", urb);
335
kfree(urb->setup_packet);
336
usb_unanchor_urb(urb);
337
}
338
339
usb_free_urb(urb);
340
341
return err;
342
}
343
344
static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
345
{
346
const u8 req[] = { 0x00, enable };
347
struct sk_buff *skb;
348
349
BT_DBG("%s", hdev->name);
350
351
if (!test_bit(HCI_RUNNING, &hdev->flags))
352
return -ENETDOWN;
353
354
/* Enable sniffer operation */
355
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
356
if (IS_ERR(skb))
357
return PTR_ERR(skb);
358
359
kfree_skb(skb);
360
return 0;
361
}
362
363
static int bpa10x_probe(struct usb_interface *intf,
364
const struct usb_device_id *id)
365
{
366
struct bpa10x_data *data;
367
struct hci_dev *hdev;
368
int err;
369
370
BT_DBG("intf %p id %p", intf, id);
371
372
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
373
return -ENODEV;
374
375
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
376
if (!data)
377
return -ENOMEM;
378
379
data->udev = interface_to_usbdev(intf);
380
381
init_usb_anchor(&data->tx_anchor);
382
init_usb_anchor(&data->rx_anchor);
383
384
hdev = hci_alloc_dev();
385
if (!hdev)
386
return -ENOMEM;
387
388
hdev->bus = HCI_USB;
389
hci_set_drvdata(hdev, data);
390
391
data->hdev = hdev;
392
data->hu.hdev = hdev;
393
394
SET_HCIDEV_DEV(hdev, &intf->dev);
395
396
hdev->open = bpa10x_open;
397
hdev->close = bpa10x_close;
398
hdev->flush = bpa10x_flush;
399
hdev->setup = bpa10x_setup;
400
hdev->send = bpa10x_send_frame;
401
hdev->set_diag = bpa10x_set_diag;
402
403
hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE);
404
405
err = hci_register_dev(hdev);
406
if (err < 0) {
407
hci_free_dev(hdev);
408
return err;
409
}
410
411
usb_set_intfdata(intf, data);
412
413
return 0;
414
}
415
416
static void bpa10x_disconnect(struct usb_interface *intf)
417
{
418
struct bpa10x_data *data = usb_get_intfdata(intf);
419
420
BT_DBG("intf %p", intf);
421
422
if (!data)
423
return;
424
425
usb_set_intfdata(intf, NULL);
426
427
hci_unregister_dev(data->hdev);
428
429
hci_free_dev(data->hdev);
430
kfree_skb(data->rx_skb[0]);
431
kfree_skb(data->rx_skb[1]);
432
}
433
434
static struct usb_driver bpa10x_driver = {
435
.name = "bpa10x",
436
.probe = bpa10x_probe,
437
.disconnect = bpa10x_disconnect,
438
.id_table = bpa10x_table,
439
.disable_hub_initiated_lpm = 1,
440
};
441
442
module_usb_driver(bpa10x_driver);
443
444
MODULE_AUTHOR("Marcel Holtmann <[email protected]>");
445
MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION);
446
MODULE_VERSION(VERSION);
447
MODULE_LICENSE("GPL");
448
449