📄 bfusb.c
字号:
bfusb_rx_submit(bfusb, urb); read_unlock(&bfusb->lock); return;resubmit: urb->dev = bfusb->udev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk resubmit failed urb %p err %d", bfusb->hdev->name, urb, err); }unlock: read_unlock(&bfusb->lock);}static int bfusb_open(struct hci_dev *hdev){ struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; unsigned long flags; int i, err; BT_DBG("hdev %p bfusb %p", hdev, bfusb); if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) return 0; write_lock_irqsave(&bfusb->lock, flags); err = bfusb_rx_submit(bfusb, NULL); if (!err) { for (i = 1; i < BFUSB_MAX_BULK_RX; i++) bfusb_rx_submit(bfusb, NULL); } else { clear_bit(HCI_RUNNING, &hdev->flags); } write_unlock_irqrestore(&bfusb->lock, flags); return err;}static int bfusb_flush(struct hci_dev *hdev){ struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; BT_DBG("hdev %p bfusb %p", hdev, bfusb); skb_queue_purge(&bfusb->transmit_q); return 0;}static int bfusb_close(struct hci_dev *hdev){ struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; unsigned long flags; BT_DBG("hdev %p bfusb %p", hdev, bfusb); if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; write_lock_irqsave(&bfusb->lock, flags); write_unlock_irqrestore(&bfusb->lock, flags); bfusb_unlink_urbs(bfusb); bfusb_flush(hdev); return 0;}static int bfusb_send_frame(struct sk_buff *skb){ struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct bfusb *bfusb; struct sk_buff *nskb; unsigned char buf[3]; int sent = 0, size, count; BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, skb->pkt_type, skb->len); if (!hdev) { BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; bfusb = (struct bfusb *) hdev->driver_data; switch (skb->pkt_type) { case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; }; /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &(skb->pkt_type), 1); count = skb->len; /* Max HCI frame size seems to be 1511 + 1 */ if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) { BT_ERR("Can't allocate memory for new packet"); return -ENOMEM; } nskb->dev = (void *) bfusb; while (count) { size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE); buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0); buf[1] = 0x00; buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size; memcpy(skb_put(nskb, 3), buf, 3); memcpy(skb_put(nskb, size), skb->data + sent, size); sent += size; count -= size; } /* Don't send frame with multiple size of bulk max packet */ if ((nskb->len % bfusb->bulk_pkt_size) == 0) { buf[0] = 0xdd; buf[1] = 0x00; memcpy(skb_put(nskb, 2), buf, 2); } read_lock(&bfusb->lock); skb_queue_tail(&bfusb->transmit_q, nskb); bfusb_tx_wakeup(bfusb); read_unlock(&bfusb->lock); kfree_skb(skb); return 0;}static void bfusb_destruct(struct hci_dev *hdev){ struct bfusb *bfusb = (struct bfusb *) hdev->driver_data; BT_DBG("hdev %p bfusb %p", hdev, bfusb); kfree(bfusb);}static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg){ return -ENOIOCTLCMD;}static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count){ unsigned char *buf; int err, pipe, len, size, sent = 0; BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev); BT_INFO("BlueFRITZ! USB loading firmware"); pipe = usb_sndctrlpipe(bfusb->udev, 0); if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT) < 0) { BT_ERR("Can't change to loading configuration"); return -EBUSY; } bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0; buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC); if (!buf) { BT_ERR("Can't allocate memory chunk for firmware"); return -ENOMEM; } pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep); while (count) { size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3); memcpy(buf, firmware + sent, size); err = usb_bulk_msg(bfusb->udev, pipe, buf, size, &len, BFUSB_BLOCK_TIMEOUT); if (err || (len != size)) { BT_ERR("Error in firmware loading"); goto error; } sent += size; count -= size; } if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0, &len, BFUSB_BLOCK_TIMEOUT)) < 0) { BT_ERR("Error in null packet request"); goto error; } pipe = usb_sndctrlpipe(bfusb->udev, 0); if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, 0, 2, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) { BT_ERR("Can't change to running configuration"); goto error; } bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0; BT_INFO("BlueFRITZ! USB device ready"); kfree(buf); return 0;error: kfree(buf); pipe = usb_sndctrlpipe(bfusb->udev, 0); usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION, 0, 0, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); return err;}static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *id){ const struct firmware *firmware; struct usb_device *udev = interface_to_usbdev(intf); struct usb_host_endpoint *bulk_out_ep; struct usb_host_endpoint *bulk_in_ep; struct hci_dev *hdev; struct bfusb *bfusb; BT_DBG("intf %p id %p", intf, id); /* Check number of endpoints */ if (intf->cur_altsetting->desc.bNumEndpoints < 2) return -EIO; bulk_out_ep = &intf->cur_altsetting->endpoint[0]; bulk_in_ep = &intf->cur_altsetting->endpoint[1]; if (!bulk_out_ep || !bulk_in_ep) { BT_ERR("Bulk endpoints not found"); goto done; } /* Initialize control structure and load firmware */ if (!(bfusb = kmalloc(sizeof(struct bfusb), GFP_KERNEL))) { BT_ERR("Can't allocate memory for control structure"); goto done; } memset(bfusb, 0, sizeof(struct bfusb)); bfusb->udev = udev; bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress; bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; bfusb->bulk_pkt_size = bulk_out_ep->desc.wMaxPacketSize; bfusb->lock = RW_LOCK_UNLOCKED; bfusb->reassembly = NULL; skb_queue_head_init(&bfusb->transmit_q); skb_queue_head_init(&bfusb->pending_q); skb_queue_head_init(&bfusb->completed_q); if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { BT_ERR("Firmware request failed"); goto error; } BT_DBG("firmware data %p size %d", firmware->data, firmware->size); if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) { BT_ERR("Firmware loading failed"); goto release; } release_firmware(firmware); /* Initialize and register HCI device */ hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can't allocate HCI device"); goto error; } bfusb->hdev = hdev; hdev->type = HCI_USB; hdev->driver_data = bfusb; SET_HCIDEV_DEV(hdev, &intf->dev); hdev->open = bfusb_open; hdev->close = bfusb_close; hdev->flush = bfusb_flush; hdev->send = bfusb_send_frame; hdev->destruct = bfusb_destruct; hdev->ioctl = bfusb_ioctl; hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); goto error; } usb_set_intfdata(intf, bfusb); return 0;release: release_firmware(firmware);error: kfree(bfusb);done: return -EIO;}static void bfusb_disconnect(struct usb_interface *intf){ struct bfusb *bfusb = usb_get_intfdata(intf); struct hci_dev *hdev = bfusb->hdev; BT_DBG("intf %p", intf); if (!hdev) return; usb_set_intfdata(intf, NULL); bfusb_close(hdev); if (hci_unregister_dev(hdev) < 0) BT_ERR("Can't unregister HCI device %s", hdev->name); hci_free_dev(hdev);}static struct usb_driver bfusb_driver = { .owner = THIS_MODULE, .name = "bfusb", .probe = bfusb_probe, .disconnect = bfusb_disconnect, .id_table = bfusb_table,};static int __init bfusb_init(void){ int err; BT_INFO("BlueFRITZ! USB driver ver %s", VERSION); if ((err = usb_register(&bfusb_driver)) < 0) BT_ERR("Failed to register BlueFRITZ! USB driver"); return err;}static void __exit bfusb_exit(void){ usb_deregister(&bfusb_driver);}module_init(bfusb_init);module_exit(bfusb_exit);MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);MODULE_VERSION(VERSION);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -