⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bfusb.c

📁 嵌入式Linux的蓝牙模块驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -