diff options
-rw-r--r-- | drivers/usb/serial/baseband_usb_chr.c | 511 |
1 files changed, 262 insertions, 249 deletions
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c index c0f45dafd4c8..bb2649dc4c36 100644 --- a/drivers/usb/serial/baseband_usb_chr.c +++ b/drivers/usb/serial/baseband_usb_chr.c @@ -34,7 +34,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <asm/ioctls.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "baseband_usb_chr.h" MODULE_LICENSE("GPL"); @@ -52,6 +52,8 @@ MODULE_PARM_DESC(baseband_usb_chr_intf, "baseband (usb chr) - USB interface"); static struct baseband_usb *baseband_usb_chr; +static atomic_t g_rx_count = ATOMIC_INIT(0); + /* baseband ipc functions */ static void baseband_ipc_dump(const char *prefix, unsigned long int offset, @@ -59,8 +61,7 @@ static void baseband_ipc_dump(const char *prefix, unsigned long int offset, { size_t i; - for (i = 0; i < bufsiz; i += 16) - { + for (i = 0; i < bufsiz; i += 16) { pr_debug("%s" "[%lx+%x] %p " "%02x %02x %02x %02x " @@ -71,22 +72,38 @@ static void baseband_ipc_dump(const char *prefix, unsigned long int offset, offset, i, ((const unsigned char *) buf) + i, - (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0] : 0xff, - (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1] : 0xff, - (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2] : 0xff, - (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3] : 0xff, - (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4] : 0xff, - (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5] : 0xff, - (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6] : 0xff, - (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7] : 0xff, - (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8] : 0xff, - (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9] : 0xff, - (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10] : 0xff, - (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11] : 0xff, - (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12] : 0xff, - (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13] : 0xff, - (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14] : 0xff, - (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15] : 0xff); + (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0] + : 0xff, + (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1] + : 0xff, + (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2] + : 0xff, + (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3] + : 0xff, + (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4] + : 0xff, + (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5] + : 0xff, + (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6] + : 0xff, + (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7] + : 0xff, + (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8] + : 0xff, + (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9] + : 0xff, + (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10] + : 0xff, + (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11] + : 0xff, + (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12] + : 0xff, + (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13] + : 0xff, + (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14] + : 0xff, + (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15] + : 0xff); } } @@ -119,11 +136,10 @@ static size_t peek_ipc_tx_bufsiz(struct baseband_ipc *ipc, pr_debug("peek_ipc_tx_bufsiz - " "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n", ipc_buf, ipc_buf->offset, ipc_buf->count); - if (ipc_buf->count > bufsiz - tx_bufsiz) { + if (ipc_buf->count > bufsiz - tx_bufsiz) break; - } else { + else tx_bufsiz += ipc_buf->count; - } } /* release tx buffer semaphores */ @@ -145,9 +161,8 @@ static size_t get_ipc_tx_buf(struct baseband_ipc *ipc, pr_err("!ipc || !buf\n"); return 0; } - if (!bufsiz) { + if (!bufsiz) return 0; - } /* acquire tx buffer semaphores */ if (down_interruptible(&ipc->buf_sem)) { @@ -213,9 +228,8 @@ static size_t put_ipc_rx_buf(struct baseband_ipc *ipc, pr_err("!ipc || !buf\n"); return 0; } - if (!bufsiz) { + if (!bufsiz) return 0; - } /* acquire rx buffer semaphores */ retry: @@ -474,14 +488,10 @@ static void baseband_ipc_close(struct baseband_ipc *ipc) memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait)); /* destroy data buffers */ - if (ipc->ipc_tx) { - kfree(ipc->ipc_tx); - ipc->ipc_tx = (unsigned char *) 0; - } - if (ipc->ipc_rx) { - kfree(ipc->ipc_rx); - ipc->ipc_rx = (unsigned char *) 0; - } + kfree(ipc->ipc_tx); + ipc->ipc_tx = (unsigned char *) 0; + kfree(ipc->ipc_rx); + ipc->ipc_rx = (unsigned char *) 0; list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list) { kfree(ipc_buf); @@ -514,16 +524,14 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, { struct baseband_ipc *ipc; struct baseband_ipc_buf *ipc_buf; - int err; int i; pr_debug("baseband_ipc_open {\n"); /* allocate baseband ipc structure */ - ipc = (struct baseband_ipc *) kzalloc(sizeof(struct baseband_ipc), - GFP_KERNEL); + ipc = kzalloc(sizeof(struct baseband_ipc), GFP_KERNEL); if (!ipc) - return ((struct baseband_ipc *) 0); + return (struct baseband_ipc *) 0; /* create semaphores */ sema_init(&ipc->buf_sem, 1); @@ -537,7 +545,8 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, ipc_buf = (struct baseband_ipc_buf *) kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL); if (!ipc_buf) { - pr_err("cannot allocate baseband ipc rx buffer #%d\n", i); + pr_err("cannot allocate baseband ipc rx buffer #%d\n", + i); goto error_exit; } pr_debug("baseband_ipc_open - " @@ -549,7 +558,8 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, ipc_buf = (struct baseband_ipc_buf *) kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL); if (!ipc_buf) { - pr_err("cannot allocate baseband ipc tx buffer #%d\n", i); + pr_err("cannot allocate baseband ipc tx buffer #%d\n", + i); goto error_exit; } pr_debug("baseband_ipc_open - " @@ -573,77 +583,121 @@ static struct baseband_ipc *baseband_ipc_open(work_func_t work_func, pr_err("cannot create workqueue\n"); goto error_exit; } - if (work_func) { + if (work_func) INIT_WORK(&ipc->work, work_func); - } - if (rx_work_func) { + if (rx_work_func) INIT_WORK(&ipc->rx_work, rx_work_func); - } - if (tx_work_func) { + if (tx_work_func) INIT_WORK(&ipc->tx_work, tx_work_func); - } pr_debug("baseband_ipc_open }\n"); return ipc; error_exit: baseband_ipc_close(ipc); - return ((struct baseband_ipc *) 0); + return (struct baseband_ipc *) 0; } -/* usb functions */ +/* usb rx */ -static unsigned int g_usb_interface_index; -static struct usb_interface *g_usb_interface; +static void baseband_usb_chr_rx_urb_comp(struct urb *urb) +{ + struct baseband_usb *usb = (struct baseband_usb *) urb->context; -static int baseband_usb_driver_probe(struct usb_interface *intf, - const struct usb_device_id *id) + pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb); + + /* queue rx urb completion work */ + queue_work(usb->ipc->workqueue, &usb->ipc->rx_work); + + pr_debug("baseband_usb_chr_rx_urb_comp }\n"); +} + +static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb) { - pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id); + struct urb *urb; + void *buf; + int err; - pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n", - intf->cur_altsetting->desc.bInterfaceNumber); - pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n", - intf->cur_altsetting->desc.bAlternateSetting); - pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n", - intf->cur_altsetting->desc.bNumEndpoints); - pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n", - intf->cur_altsetting->desc.bInterfaceClass); - pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n", - intf->cur_altsetting->desc.bInterfaceSubClass); - pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n", - intf->cur_altsetting->desc.bInterfaceProtocol); - pr_debug("intf->cur_altsetting->desc.iInterface %02x\n", - intf->cur_altsetting->desc.iInterface); + pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb); - if (g_usb_interface_index != - intf->cur_altsetting->desc.bInterfaceNumber) { - pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__); - return -ENODEV; - } else { - g_usb_interface = intf; + /* check input */ + if (usb->usb.rx_urb) { + pr_err("previous urb still active\n"); + return -1; } - pr_debug("%s(%d) }\n", __func__, __LINE__); - return 0; + /* allocate rx urb */ + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + pr_err("usb_alloc_urb() failed\n"); + return -ENOMEM; + } + buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC); + if (!buf) { + pr_err("usb buffer kzalloc() failed\n"); + usb_free_urb(urb); + return -ENOMEM; + } + usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in, + buf, USB_CHR_RX_BUFSIZ, + baseband_usb_chr_rx_urb_comp, + usb); + urb->transfer_flags = 0; + + /* submit rx urb */ + usb->usb.rx_urb = urb; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { + pr_err("usb_submit_urb() failed - err %d\n", err); + usb->usb.rx_urb = (struct urb *) 0; + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return err; + } + + pr_debug("baseband_usb_chr_rx_urb_submit }\n"); + return err; } -static void baseband_usb_driver_disconnect(struct usb_interface *intf) +static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work) { - pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf); - pr_debug("%s(%d) }\n", __func__, __LINE__); -} + struct baseband_usb *usb = baseband_usb_chr; + struct urb *urb = usb->usb.rx_urb; + size_t len; -static char baseband_usb_driver_name[32]; + pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work); -static struct usb_device_id baseband_usb_driver_id_table[2]; + /* put rx urb data in rx buffer */ + if (urb->actual_length) { + pr_debug("baseband_usb_chr_rx_urb_comp_work - " + "urb->actual_length %d\n", urb->actual_length); + len = put_ipc_rx_buf(usb->ipc, + urb->transfer_buffer, urb->actual_length); + baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work" + " - rx buf ", 0, + urb->transfer_buffer, len > 16 ? 16 : len); + if (len != urb->actual_length) { + pr_err("baseband_usb_chr_rx_urb_comp_work - " + "put_ipx_rx_buf() only put %d/%d bytes\n", + len, urb->actual_length); + } + /* increment count of available rx bytes */ + atomic_add(len, &g_rx_count); + } -static struct usb_driver baseband_usb_driver = { - .name = baseband_usb_driver_name, - .probe = baseband_usb_driver_probe, - .disconnect = baseband_usb_driver_disconnect, - .id_table = baseband_usb_driver_id_table, -}; + /* free rx urb */ + kfree(urb->transfer_buffer); + urb->transfer_buffer = (void *) 0; + usb_free_urb(urb); + usb->usb.rx_urb = (struct urb *) 0; + + /* submit next rx urb */ + baseband_usb_chr_rx_urb_submit(usb); + + pr_debug("baseband_usb_chr_rx_urb_comp_work }\n"); +} + +/* usb functions */ static void find_usb_pipe(struct baseband_usb *usb) { @@ -684,6 +738,88 @@ static void find_usb_pipe(struct baseband_usb *usb) } } +static int baseband_usb_driver_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int err; + + pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id); + + pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n", + intf->cur_altsetting->desc.bInterfaceNumber); + pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n", + intf->cur_altsetting->desc.bAlternateSetting); + pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n", + intf->cur_altsetting->desc.bNumEndpoints); + pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n", + intf->cur_altsetting->desc.bInterfaceClass); + pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n", + intf->cur_altsetting->desc.bInterfaceSubClass); + pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n", + intf->cur_altsetting->desc.bInterfaceProtocol); + pr_debug("intf->cur_altsetting->desc.iInterface %02x\n", + intf->cur_altsetting->desc.iInterface); + + /* usb interface mismatch */ + if (baseband_usb_chr_intf != + intf->cur_altsetting->desc.bInterfaceNumber) { + pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__); + return -ENODEV; + } + + /* usb interface match */ + baseband_usb_chr->usb.device = interface_to_usbdev(intf); + baseband_usb_chr->usb.interface = intf; + find_usb_pipe(baseband_usb_chr); + baseband_usb_chr->usb.rx_urb = (struct urb *) 0; + baseband_usb_chr->usb.tx_urb = (struct urb *) 0; + pr_debug("baseband_usb_chr->usb.driver->name %s\n", + baseband_usb_chr->usb.driver->name); + pr_debug("baseband_usb_chr->usb.device %p\n", + baseband_usb_chr->usb.device); + pr_debug("baseband_usb_chr->usb.interface %p\n", + baseband_usb_chr->usb.interface); + pr_debug("baseband_usb_chr->usb.pipe.isoch.in %x\n", + baseband_usb_chr->usb.pipe.isoch.in); + pr_debug("baseband_usb_chr->usb.pipe.isoch.out %x\n", + baseband_usb_chr->usb.pipe.isoch.out); + pr_debug("baseband_usb_chr->usb.pipe.bulk.in %x\n", + baseband_usb_chr->usb.pipe.bulk.in); + pr_debug("baseband_usb_chr->usb.pipe.bulk.out %x\n", + baseband_usb_chr->usb.pipe.bulk.out); + pr_debug("baseband_usb_chr->usb.pipe.interrupt.in %x\n", + baseband_usb_chr->usb.pipe.interrupt.in); + pr_debug("baseband_usb_chr->usb.pipe.interrupt.out %x\n", + baseband_usb_chr->usb.pipe.interrupt.out); + + /* start usb rx */ + err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr); + if (err < 0) { + pr_err("submit rx failed - err %d\n", err); + return -ENODEV; + } + + pr_debug("%s(%d) }\n", __func__, __LINE__); + return 0; +} + +static void baseband_usb_driver_disconnect(struct usb_interface *intf) +{ + pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf); + pr_debug("%s(%d) }\n", __func__, __LINE__); +} + +static char baseband_usb_driver_name[32]; + +static struct usb_device_id baseband_usb_driver_id_table[2]; + +static struct usb_driver baseband_usb_driver = { + .name = baseband_usb_driver_name, + .probe = baseband_usb_driver_probe, + .disconnect = baseband_usb_driver_disconnect, + .id_table = baseband_usb_driver_id_table, +}; + static void baseband_usb_chr_work(struct work_struct *work) { struct baseband_usb *usb = baseband_usb_chr; @@ -702,10 +838,17 @@ static void baseband_usb_chr_work(struct work_struct *work) "usb not open\n"); return; } + if (!usb->usb.device) { + pr_err("baseband_usb_chr_work - " + "usb device not probed yet\n"); + mdelay(10); + queue_work(usb->ipc->workqueue, &usb->ipc->work); + return; + } /* allocate buffers on first transaction (will be freed on close) */ if (!usb->ipc->ipc_rx) { - usb->ipc->ipc_rx = (unsigned char *) kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); + usb->ipc->ipc_rx = kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL); if (!usb->ipc->ipc_rx) { pr_err("baseband_usb_chr_work - " "cannot allocate usb->ipc->ipc_rx\n"); @@ -713,7 +856,7 @@ static void baseband_usb_chr_work(struct work_struct *work) } } if (!usb->ipc->ipc_tx) { - usb->ipc->ipc_tx = (unsigned char *) kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL); + usb->ipc->ipc_tx = kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL); if (!usb->ipc->ipc_tx) { pr_err("baseband_usb_chr_work - " "cannot allocate usb->ipc->ipc_tx\n"); @@ -724,9 +867,8 @@ static void baseband_usb_chr_work(struct work_struct *work) /* usb transaction loop */ rx.buf = usb->ipc->ipc_rx; tx.buf = usb->ipc->ipc_tx; - while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc, USB_CHR_TX_BUFSIZ)) - != 0) - { + while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc, + USB_CHR_TX_BUFSIZ)) != 0) { get_ipc_tx_buf(usb->ipc, tx.buf, tx.bufsiz_byte); err = usb_bulk_msg(usb->usb.device, usb->usb.pipe.bulk.out, tx.buf, tx.bufsiz_byte, &ipc_tx_byte, USB_CHR_TIMEOUT); @@ -736,7 +878,8 @@ static void baseband_usb_chr_work(struct work_struct *work) continue; } if (tx.bufsiz_byte != ipc_tx_byte) { - pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n", tx.bufsiz_byte, ipc_tx_byte); + pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n", + tx.bufsiz_byte, ipc_tx_byte); continue; } } @@ -746,8 +889,6 @@ static void baseband_usb_chr_work(struct work_struct *work) /* usb character file operations */ -static atomic_t g_rx_count = ATOMIC_INIT(0); - static int baseband_usb_chr_open(struct inode *inode, struct file *file) { pr_debug("baseband_usb_chr_open\n"); @@ -760,29 +901,35 @@ static int baseband_usb_chr_release(struct inode *inode, struct file *file) return 0; } -static ssize_t baseband_usb_chr_read(struct file *file, char *buf, size_t count, loff_t *pos) +static ssize_t baseband_usb_chr_read(struct file *file, char *buf, + size_t count, loff_t *pos) { ssize_t ret; pr_debug("baseband_usb_chr_read\n"); - ret = baseband_ipc_file_read(baseband_usb_chr->ipc, file, buf, count, pos); + ret = baseband_ipc_file_read(baseband_usb_chr->ipc, + file, buf, count, pos); if (ret > 0) { /* decrement count of available rx bytes */ int val = atomic_read(&g_rx_count); - pr_debug("baseband_usb_chr_read - read %d unread %d\n", ret, val - ret); + pr_debug("baseband_usb_chr_read - read %d unread %d\n", + ret, val - ret); atomic_sub(ret, &g_rx_count); } return ret; } -static ssize_t baseband_usb_chr_write(struct file *file, const char *buf, size_t count, loff_t *pos) +static ssize_t baseband_usb_chr_write(struct file *file, const char *buf, + size_t count, loff_t *pos) { pr_debug("baseband_usb_chr_write\n"); - return baseband_ipc_file_write(baseband_usb_chr->ipc, file, buf, count, pos); + return baseband_ipc_file_write(baseband_usb_chr->ipc, + file, buf, count, pos); } -static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { pr_debug("baseband_usb_chr_ioctl\n"); switch (cmd) { @@ -807,12 +954,12 @@ static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd, unsigned return -ENODEV; } -static struct file_operations baseband_usb_chr_fops = { - open: baseband_usb_chr_open, - release: baseband_usb_chr_release, - read: baseband_usb_chr_read, - write: baseband_usb_chr_write, - unlocked_ioctl: baseband_usb_chr_ioctl, +static const struct file_operations baseband_usb_chr_fops = { + .open = baseband_usb_chr_open, + .release = baseband_usb_chr_release, + .read = baseband_usb_chr_read, + .write = baseband_usb_chr_write, + .unlocked_ioctl = baseband_usb_chr_ioctl, }; /* usb device driver functions */ @@ -858,10 +1005,10 @@ static struct baseband_usb *baseband_usb_open(unsigned int vid, pr_debug("baseband_usb_open {\n"); /* allocate baseband usb structure */ - usb = (struct baseband_usb *) kzalloc(sizeof(struct baseband_usb), - GFP_KERNEL); + usb = kzalloc(sizeof(struct baseband_usb), GFP_KERNEL); if (!usb) - return ((struct baseband_usb *) 0); + return (struct baseband_usb *) 0; + baseband_usb_chr = usb; /* open baseband ipc */ usb->ipc = baseband_ipc_open(work_func, @@ -876,149 +1023,24 @@ static struct baseband_usb *baseband_usb_open(unsigned int vid, sprintf(baseband_usb_driver_name, "baseband_usb_%x_%x_%x", vid, pid, intf); - baseband_usb_driver_id_table[0].match_flags = USB_DEVICE_ID_MATCH_DEVICE; + baseband_usb_driver_id_table[0].match_flags + = USB_DEVICE_ID_MATCH_DEVICE; baseband_usb_driver_id_table[0].idVendor = vid; baseband_usb_driver_id_table[0].idProduct = pid; - g_usb_interface_index = intf; - g_usb_interface = (struct usb_interface *) 0; + usb->usb.driver = &baseband_usb_driver; err = usb_register(&baseband_usb_driver); if (err < 0) { pr_err("cannot open usb driver - err %d\n", err); goto error_exit; } - usb->usb.driver = &baseband_usb_driver; - if (!g_usb_interface) { - pr_err("cannot open usb driver - !g_usb_interface\n"); - goto error_exit; - } - usb->usb.device = interface_to_usbdev(g_usb_interface); - usb->usb.interface = g_usb_interface; - find_usb_pipe(usb); - usb->usb.rx_urb = (struct urb *) 0; - usb->usb.tx_urb = (struct urb *) 0; - g_usb_interface_index = ~0U; - g_usb_interface = (struct usb_interface *) 0; - pr_debug("usb->usb.driver->name %s\n", usb->usb.driver->name); - pr_debug("usb->usb.device %p\n", usb->usb.device); - pr_debug("usb->usb.interface %p\n", usb->usb.interface); - pr_debug("usb->usb.pipe.isoch.in %x\n", usb->usb.pipe.isoch.in); - pr_debug("usb->usb.pipe.isoch.out %x\n", usb->usb.pipe.isoch.out); - pr_debug("usb->usb.pipe.bulk.in %x\n", usb->usb.pipe.bulk.in); - pr_debug("usb->usb.pipe.bulk.out %x\n", usb->usb.pipe.bulk.out); - pr_debug("usb->usb.pipe.interrupt.in %x\n", usb->usb.pipe.interrupt.in); - pr_debug("usb->usb.pipe.interrupt.out %x\n", usb->usb.pipe.interrupt.out); pr_debug("baseband_usb_open }\n"); return usb; error_exit: baseband_usb_close(usb); - return ((struct baseband_usb *) 0); -} - -/* usb rx */ - -static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb); -static void baseband_usb_chr_rx_urb_comp(struct urb *urb); -static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work); - -static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb) -{ - struct urb *urb; - void *buf; - int err; - - pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb); - - /* check input */ - if (usb->usb.rx_urb) { - pr_err("previous urb still active\n"); - return -1; - } - - /* allocate rx urb */ - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - pr_err("usb_alloc_urb() failed\n"); - return -ENOMEM; - } - buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC); - if (!buf) { - pr_err("usb buffer kzalloc() failed\n"); - usb_free_urb(urb); - return -ENOMEM; - } - usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in, - buf, USB_CHR_RX_BUFSIZ, - baseband_usb_chr_rx_urb_comp, - usb); - urb->transfer_flags = 0; - - /* submit rx urb */ - usb->usb.rx_urb = urb; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - pr_err("usb_submit_urb() failed - err %d\n", err); - usb->usb.rx_urb = (struct urb *) 0; - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return err; - } - - pr_debug("baseband_usb_chr_rx_urb_submit }\n"); - return err; -} - -static void baseband_usb_chr_rx_urb_comp(struct urb *urb) -{ - struct baseband_usb *usb = (struct baseband_usb *) urb->context; - - pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb); - - /* queue rx urb completion work */ - queue_work(usb->ipc->workqueue, &usb->ipc->rx_work); - - pr_debug("baseband_usb_chr_rx_urb_comp }\n"); -} - -static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work) -{ - struct baseband_usb *usb = baseband_usb_chr; - struct urb *urb = usb->usb.rx_urb; - size_t len; - - pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work); - - /* put rx urb data in rx buffer */ - if (urb->actual_length) { - pr_debug("baseband_usb_chr_rx_urb_comp_work - " - "urb->actual_length %d\n", urb->actual_length); - len = put_ipc_rx_buf(usb->ipc, - urb->transfer_buffer, urb->actual_length); - baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work" - " - rx buf ", 0, - urb->transfer_buffer, len > 16 ? 16 : len); - if (len != urb->actual_length) { - pr_err("baseband_usb_chr_rx_urb_comp_work - " - "put_ipx_rx_buf() only put %d/%d bytes\n", - len, urb->actual_length); - } - /* increment count of available rx bytes */ - atomic_add(len, &g_rx_count); - } - - /* free rx urb */ - if (urb->transfer_buffer) { - kfree(urb->transfer_buffer); - urb->transfer_buffer = (void *) 0; - } - usb_free_urb(urb); - usb->usb.rx_urb = (struct urb *) 0; - - /* submit next rx urb */ - baseband_usb_chr_rx_urb_submit(usb); - - pr_debug("baseband_usb_chr_rx_urb_comp_work }\n"); + baseband_usb_chr = (struct baseband_usb *) 0; + return (struct baseband_usb *) 0; } /* module init / exit functions */ @@ -1054,17 +1076,8 @@ static int baseband_usb_chr_init(void) pr_debug("registered baseband usb character device - major %d\n", BASEBAND_USB_CHR_DEV_MAJOR); - /* start usb rx */ - err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr); - if (err < 0) { - pr_err("submit rx failed - err %d\n", err); - goto err3; - } - pr_debug("baseband_usb_chr_init }\n"); return 0; -err3: unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR, - BASEBAND_USB_CHR_DEV_NAME); err2: baseband_usb_close(baseband_usb_chr); baseband_usb_chr = (struct baseband_usb *) 0; err1: return err; |