📄 bluetty.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, GFP_KERNEL);
if (result)
err (__FUNCTION__ " - failed resubmitting read urb, error %d", 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(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE");
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(__FUNCTION__ " - packet was too long");
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, GFP_KERNEL);
if (result)
err (__FUNCTION__ " - failed resubmitting read urb, error %d", 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(__FUNCTION__);
if (!bluetooth) {
dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
return;
}
if (urb->status) {
dbg(__FUNCTION__ " - nonzero write bulk status received: %d", 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(__FUNCTION__);
if (!bluetooth) {
return;
}
tty = bluetooth->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
dbg(__FUNCTION__ " - write wakeup call.");
(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 (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound.");
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, GFP_KERNEL);
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, GFP_KERNEL);
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;
/* create our write urb pool */
for (i = 0; i < NUM_BULK_URBS; ++i) {
struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
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;
}
bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
endpoint = interrupt_in_endpoint[0];
bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
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(__FUNCTION__ " - failed to register tty driver");
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 + -