📄 hci_usb.c
字号:
} /* Allocate skb */ if (!(skb = bluez_skb_alloc(len, GFP_ATOMIC))) { ERR("Can't allocate mem for new packet"); return; } skb->dev = (void *) &husb->hdev; skb->pkt_type = HCI_EVENT_PKT; husb->intr_skb = skb; husb->intr_count = len; } else { /* Continuation */ if (count > husb->intr_count) { ERR("%s bad frame len %d (expected %d)", husb->hdev.name, count, husb->intr_count); kfree_skb(skb); husb->intr_skb = NULL; husb->intr_count = 0; return; } } memcpy(skb_put(skb, count), data, count); husb->intr_count -= count; DMP(data, count); if (!husb->intr_count) { /* Got complete frame */ husb->hdev.stat.byte_rx += skb->len; hci_recv_frame(skb); husb->intr_skb = NULL; }}static void hci_usb_bulk_read(struct urb *urb){ struct hci_usb *husb = (struct hci_usb *) urb->context; unsigned char *data = urb->transfer_buffer; int count = urb->actual_length, status; struct sk_buff *skb; hci_acl_hdr *ah; register __u16 dlen; if (!husb) return; DBG("%s status %d, count %d, flags %x", husb->hdev.name, urb->status, count, urb->transfer_flags); if (urb->status) { /* Do not re-submit URB on critical errors */ switch (urb->status) { case -ENOENT: return; default: goto resubmit; }; } if (!count) goto resubmit; DMP(data, count); ah = (hci_acl_hdr *) data; dlen = le16_to_cpu(ah->dlen); /* Verify frame len and completeness */ if ((count - HCI_ACL_HDR_SIZE) != dlen) { ERR("%s corrupted ACL packet: count %d, plen %d", husb->hdev.name, count, dlen); goto resubmit; } /* Allocate packet */ if (!(skb = bluez_skb_alloc(count, GFP_ATOMIC))) { ERR("Can't allocate mem for new packet"); goto resubmit; } memcpy(skb_put(skb, count), data, count); skb->dev = (void *) &husb->hdev; skb->pkt_type = HCI_ACLDATA_PKT; husb->hdev.stat.byte_rx += skb->len; hci_recv_frame(skb);resubmit: husb->read_urb->dev = husb->udev; if ((status = usb_submit_urb(husb->read_urb))) DBG("%s read URB submit failed %d", husb->hdev.name, status); DBG("%s read URB re-submited", husb->hdev.name);}static int hci_usb_ctrl_msg(struct hci_usb *husb, struct sk_buff *skb){ struct urb *urb = husb->ctrl_urb; devrequest *dr = &husb->dev_req; int pipe, status; DBG("%s len %d", husb->hdev.name, skb->len); pipe = usb_sndctrlpipe(husb->udev, 0); dr->requesttype = HCI_CTRL_REQ; dr->request = 0; dr->index = 0; dr->value = 0; dr->length = cpu_to_le16(skb->len); FILL_CONTROL_URB(urb, husb->udev, pipe, (void*)dr, skb->data, skb->len, hci_usb_ctrl, skb); if ((status = usb_submit_urb(urb))) { DBG("%s control URB submit failed %d", husb->hdev.name, status); return status; } return 0;}static int hci_usb_write_msg(struct hci_usb *husb, struct sk_buff *skb){ struct urb *urb = husb->write_urb; int pipe, status; DBG("%s len %d", husb->hdev.name, skb->len); pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep_addr); FILL_BULK_URB(urb, husb->udev, pipe, skb->data, skb->len, hci_usb_bulk_write, skb); urb->transfer_flags |= USB_QUEUE_BULK; if ((status = usb_submit_urb(urb))) { DBG("%s write URB submit failed %d", husb->hdev.name, status); return status; } return 0;}static void * hci_usb_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_endpoint_descriptor *bulk_out_ep, *intr_in_ep, *bulk_in_ep; struct usb_interface_descriptor *uif; struct usb_endpoint_descriptor *ep; struct hci_usb *husb; struct hci_dev *hdev; int i, size, pipe; __u8 * buf; DBG("udev %p ifnum %d", udev, ifnum); /* Check device signature */ if ((udev->descriptor.bDeviceClass != HCI_DEV_CLASS) || (udev->descriptor.bDeviceSubClass != HCI_DEV_SUBCLASS)|| (udev->descriptor.bDeviceProtocol != HCI_DEV_PROTOCOL) ) return NULL; MOD_INC_USE_COUNT; uif = &udev->actconfig->interface[ifnum].altsetting[0]; if (uif->bNumEndpoints != 3) { DBG("Wrong number of endpoints %d", uif->bNumEndpoints); MOD_DEC_USE_COUNT; return NULL; } bulk_out_ep = intr_in_ep = bulk_in_ep = NULL; /* Find endpoints that we need */ for ( i = 0; i < uif->bNumEndpoints; ++i) { ep = &uif->endpoint[i]; switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_BULK: if (ep->bEndpointAddress & USB_DIR_IN) bulk_in_ep = ep; else bulk_out_ep = ep; break; case USB_ENDPOINT_XFER_INT: intr_in_ep = ep; break; }; } if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) { DBG("Endpoints not found: %p %p %p", bulk_in_ep, bulk_out_ep, intr_in_ep); MOD_DEC_USE_COUNT; return NULL; } if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { ERR("Can't allocate: control structure"); MOD_DEC_USE_COUNT; return NULL; } memset(husb, 0, sizeof(struct hci_usb)); husb->udev = udev; husb->bulk_out_ep_addr = bulk_out_ep->bEndpointAddress; if (!(husb->ctrl_urb = usb_alloc_urb(0))) { ERR("Can't allocate: control URB"); goto probe_error; } if (!(husb->write_urb = usb_alloc_urb(0))) { ERR("Can't allocate: write URB"); goto probe_error; } if (!(husb->read_urb = usb_alloc_urb(0))) { ERR("Can't allocate: read URB"); goto probe_error; } ep = bulk_in_ep; pipe = usb_rcvbulkpipe(udev, ep->bEndpointAddress); size = HCI_MAX_FRAME_SIZE; if (!(buf = kmalloc(size, GFP_KERNEL))) { ERR("Can't allocate: read buffer"); goto probe_error; } FILL_BULK_URB(husb->read_urb, udev, pipe, buf, size, hci_usb_bulk_read, husb); husb->read_urb->transfer_flags |= USB_QUEUE_BULK; ep = intr_in_ep; pipe = usb_rcvintpipe(udev, ep->bEndpointAddress); size = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); if (!(husb->intr_urb = usb_alloc_urb(0))) { ERR("Can't allocate: interrupt URB"); goto probe_error; } if (!(buf = kmalloc(size, GFP_KERNEL))) { ERR("Can't allocate: interrupt buffer"); goto probe_error; } FILL_INT_URB(husb->intr_urb, udev, pipe, buf, size, hci_usb_intr, husb, ep->bInterval); skb_queue_head_init(&husb->tx_ctrl_q); skb_queue_head_init(&husb->tx_write_q); /* Initialize and register HCI device */ hdev = &husb->hdev; hdev->type = HCI_USB; hdev->driver_data = husb; hdev->open = hci_usb_open; hdev->close = hci_usb_close; hdev->flush = hci_usb_flush; hdev->send = hci_usb_send_frame; if (hci_register_dev(hdev) < 0) { ERR("Can't register HCI device %s", hdev->name); goto probe_error; } return husb;probe_error: hci_usb_free_bufs(husb); kfree(husb); MOD_DEC_USE_COUNT; return NULL;}static void hci_usb_disconnect(struct usb_device *udev, void *ptr){ struct hci_usb *husb = (struct hci_usb *) ptr; struct hci_dev *hdev = &husb->hdev; if (!husb) return; DBG("%s", hdev->name); hci_usb_close(hdev); if (hci_unregister_dev(hdev) < 0) { ERR("Can't unregister HCI device %s", hdev->name); } hci_usb_free_bufs(husb); kfree(husb); MOD_DEC_USE_COUNT;}static struct usb_driver hci_usb_driver ={ name: "hci_usb", probe: hci_usb_probe, disconnect: hci_usb_disconnect, id_table: usb_bluetooth_ids,};int hci_usb_init(void){ int err; INF("BlueZ HCI USB driver ver %s Copyright (C) 2000,2001 Qualcomm Inc", VERSION); INF("Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>"); if ((err = usb_register(&hci_usb_driver)) < 0) ERR("Failed to register HCI USB driver"); return err;}void hci_usb_cleanup(void){ usb_deregister(&hci_usb_driver);}module_init(hci_usb_init);module_exit(hci_usb_cleanup);MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");MODULE_DESCRIPTION("BlueZ HCI USB driver ver " VERSION);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -