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