📄 bluetooth.c
字号:
printk ("%.2x ", data[i]); } printk ("\n"); }#endif#ifdef BTBUGGYHARDWARE if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00) && (data[2] == 0x00) && (data[3] == 0x00)) { urb->actual_length = 0; FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, bluetooth_read_bulk_callback, bluetooth); result = usb_submit_urb(bluetooth->read_urb); if (result) err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); return; }#endif /* We add a packet type identifier to the beginning of each HCI frame. This makes the data in the tty look like a serial USB devices. Each HCI frame can be broken across multiple URBs so we buffer them until we have a full hci packet */ if (!bluetooth->bulk_packet_pos) { bluetooth->bulk_buffer[0] = ACL_PKT; bluetooth->bulk_packet_pos++; } if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) { err("%s - exceeded ACL_BUFFER_SIZE", __FUNCTION__); bluetooth->bulk_packet_pos = 0; goto exit; } memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos], urb->transfer_buffer, count); bluetooth->bulk_packet_pos += count; urb->actual_length = 0; if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) { packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]); } else { goto exit; } if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) { err("%s - packet was too long", __FUNCTION__); bluetooth->bulk_packet_pos = 0; goto exit; } if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) { for (i = 0; i < bluetooth->bulk_packet_pos; ++i) { /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(bluetooth->tty); } tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0); } tty_flip_buffer_push(bluetooth->tty); bluetooth->bulk_packet_pos = 0; } exit: if (!bluetooth || !bluetooth->open_count) return; FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress), bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, bluetooth_read_bulk_callback, bluetooth); result = usb_submit_urb(bluetooth->read_urb); if (result) err ("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); return;}static void bluetooth_write_bulk_callback (struct urb *urb){ struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__); dbg("%s", __FUNCTION__); if (!bluetooth) { dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); return; } if (urb->status) { dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); return; } /* wake up our little function to let the tty layer know that something happened */ queue_task(&bluetooth->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); return;}static void bluetooth_softint(void *private){ struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__); struct tty_struct *tty; dbg("%s", __FUNCTION__); if (!bluetooth) { return; } tty = bluetooth->tty; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { dbg("%s - write wakeup call.", __FUNCTION__); (tty->ldisc.write_wakeup)(tty); } wake_up_interruptible(&tty->write_wait);}static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_bluetooth *bluetooth = NULL; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *interrupt_in_endpoint[8]; struct usb_endpoint_descriptor *bulk_in_endpoint[8]; struct usb_endpoint_descriptor *bulk_out_endpoint[8]; int control_out_endpoint; int minor; int buffer_size; int i; int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; interface = &dev->actconfig->interface[ifnum].altsetting[0]; control_out_endpoint = interface->bInterfaceNumber; /* find the endpoints that we need */ for (i = 0; i < interface->bNumEndpoints; ++i) { endpoint = &interface->endpoint[i]; if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ dbg("found bulk in"); bulk_in_endpoint[num_bulk_in] = endpoint; ++num_bulk_in; } if (((endpoint->bEndpointAddress & 0x80) == 0x00) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk out endpoint */ dbg("found bulk out"); bulk_out_endpoint[num_bulk_out] = endpoint; ++num_bulk_out; } if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x03)) { /* we found a interrupt in endpoint */ dbg("found interrupt in"); interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } } /* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */ if ((num_bulk_in != 1) || (num_bulk_out != 1) || (num_interrupt_in != 1)) { dbg ("%s - improper number of endpoints. Bluetooth driver not bound.", __FUNCTION__); return NULL; } MOD_INC_USE_COUNT; info("USB Bluetooth converter detected"); for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor) ; if (bluetooth_table[minor]) { err("No more free Bluetooth devices"); MOD_DEC_USE_COUNT; return NULL; } if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) { err("Out of memory"); MOD_DEC_USE_COUNT; return NULL; } memset(bluetooth, 0, sizeof(struct usb_bluetooth)); bluetooth->magic = USB_BLUETOOTH_MAGIC; bluetooth->dev = dev; bluetooth->minor = minor; bluetooth->tqueue.routine = bluetooth_softint; bluetooth->tqueue.data = bluetooth; init_MUTEX(&bluetooth->lock); /* record the interface number for the control out */ bluetooth->control_out_bInterfaceNum = control_out_endpoint; /* create our control out urb pool */ for (i = 0; i < NUM_CONTROL_URBS; ++i) { struct urb *urb = usb_alloc_urb(0); if (urb == NULL) { err("No free urbs available"); goto probe_error; } urb->transfer_buffer = NULL; bluetooth->control_urb_pool[i] = urb; } /* set up the endpoint information */ endpoint = bulk_in_endpoint[0]; bluetooth->read_urb = usb_alloc_urb (0); if (!bluetooth->read_urb) { err("No free urbs available"); goto probe_error; } bluetooth->bulk_in_buffer_size = buffer_size = endpoint->wMaxPacketSize; bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress; bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!bluetooth->bulk_in_buffer) { err("Couldn't allocate bulk_in_buffer"); goto probe_error; } FILL_BULK_URB(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth); endpoint = bulk_out_endpoint[0]; bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress; bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2; /* create our write urb pool */ for (i = 0; i < NUM_BULK_URBS; ++i) { struct urb *urb = usb_alloc_urb(0); if (urb == NULL) { err("No free urbs available"); goto probe_error; } urb->transfer_buffer = kmalloc (bluetooth->bulk_out_buffer_size, GFP_KERNEL); if (urb->transfer_buffer == NULL) { err("out of memory"); goto probe_error; } bluetooth->write_urb_pool[i] = urb; } endpoint = interrupt_in_endpoint[0]; bluetooth->interrupt_in_urb = usb_alloc_urb(0); if (!bluetooth->interrupt_in_urb) { err("No free urbs available"); goto probe_error; } bluetooth->interrupt_in_buffer_size = buffer_size = endpoint->wMaxPacketSize; bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress; bluetooth->interrupt_in_interval = endpoint->bInterval; bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL); if (!bluetooth->interrupt_in_buffer) { err("Couldn't allocate interrupt_in_buffer"); goto probe_error; } FILL_INT_URB(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback, bluetooth, endpoint->bInterval); /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ tty_register_devfs (&bluetooth_tty_driver, 0, minor); info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor); bluetooth_table[minor] = bluetooth; return bluetooth; /* success */probe_error: if (bluetooth->read_urb) usb_free_urb (bluetooth->read_urb); if (bluetooth->bulk_in_buffer) kfree (bluetooth->bulk_in_buffer); if (bluetooth->interrupt_in_urb) usb_free_urb (bluetooth->interrupt_in_urb); if (bluetooth->interrupt_in_buffer) kfree (bluetooth->interrupt_in_buffer); for (i = 0; i < NUM_BULK_URBS; ++i) if (bluetooth->write_urb_pool[i]) { if (bluetooth->write_urb_pool[i]->transfer_buffer) kfree (bluetooth->write_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->write_urb_pool[i]); } for (i = 0; i < NUM_CONTROL_URBS; ++i) if (bluetooth->control_urb_pool[i]) { if (bluetooth->control_urb_pool[i]->transfer_buffer) kfree (bluetooth->control_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->control_urb_pool[i]); } bluetooth_table[minor] = NULL; /* free up any memory that we allocated */ kfree (bluetooth); MOD_DEC_USE_COUNT; return NULL;}static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr){ struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr; int i; if (bluetooth) { if ((bluetooth->open_count) && (bluetooth->tty)) tty_hangup(bluetooth->tty); bluetooth->open_count = 0; if (bluetooth->read_urb) { usb_unlink_urb (bluetooth->read_urb); usb_free_urb (bluetooth->read_urb); } if (bluetooth->bulk_in_buffer) kfree (bluetooth->bulk_in_buffer); if (bluetooth->interrupt_in_urb) { usb_unlink_urb (bluetooth->interrupt_in_urb); usb_free_urb (bluetooth->interrupt_in_urb); } if (bluetooth->interrupt_in_buffer) kfree (bluetooth->interrupt_in_buffer); tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor); for (i = 0; i < NUM_BULK_URBS; ++i) { if (bluetooth->write_urb_pool[i]) { usb_unlink_urb (bluetooth->write_urb_pool[i]); if (bluetooth->write_urb_pool[i]->transfer_buffer) kfree (bluetooth->write_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->write_urb_pool[i]); } } for (i = 0; i < NUM_CONTROL_URBS; ++i) { if (bluetooth->control_urb_pool[i]) { usb_unlink_urb (bluetooth->control_urb_pool[i]); if (bluetooth->control_urb_pool[i]->transfer_buffer) kfree (bluetooth->control_urb_pool[i]->transfer_buffer); usb_free_urb (bluetooth->control_urb_pool[i]); } } info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor); bluetooth_table[bluetooth->minor] = NULL; /* free up any memory that we allocated */ kfree (bluetooth); } else { info("device disconnected"); } MOD_DEC_USE_COUNT;}static struct tty_driver bluetooth_tty_driver = { .magic = TTY_DRIVER_MAGIC, .driver_name = "usb-bluetooth", .name = "usb/ttub/%d", .major = BLUETOOTH_TTY_MAJOR, .minor_start = 0, .num = BLUETOOTH_TTY_MINORS, .type = TTY_DRIVER_TYPE_SERIAL, .subtype = SERIAL_TYPE_NORMAL, .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, .refcount = &bluetooth_refcount, .table = bluetooth_tty, .termios = bluetooth_termios, .termios_locked = bluetooth_termios_locked, .open = bluetooth_open, .close = bluetooth_close, .write = bluetooth_write, .write_room = bluetooth_write_room, .ioctl = bluetooth_ioctl, .set_termios = bluetooth_set_termios, .throttle = bluetooth_throttle, .unthrottle = bluetooth_unthrottle, .chars_in_buffer = bluetooth_chars_in_buffer,};int usb_bluetooth_init(void){ int i; int result; /* Initalize our global data */ for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) { bluetooth_table[i] = NULL; } info ("USB Bluetooth support registered"); /* register the tty driver */ bluetooth_tty_driver.init_termios = tty_std_termios; bluetooth_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; if (tty_register_driver (&bluetooth_tty_driver)) { err("%s - failed to register tty driver", __FUNCTION__); return -1; } /* register the USB driver */ result = usb_register(&usb_bluetooth_driver); if (result < 0) { tty_unregister_driver(&bluetooth_tty_driver); err("usb_register failed for the USB bluetooth driver. Error number %d", result); return -1; } info(DRIVER_DESC " " DRIVER_VERSION); return 0;}void usb_bluetooth_exit(void){ usb_deregister(&usb_bluetooth_driver); tty_unregister_driver(&bluetooth_tty_driver);}module_init(usb_bluetooth_init);module_exit(usb_bluetooth_exit);/* Module information */MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -