/* * serial.c -- USB Serial Function driver * * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com) * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. * * This code is based in part on the Gadget Zero driver, which * is Copyright (C) 2003 by David Brownell, all rights reserved. * * This code also borrows from usbserial.c, which is * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2000 Peter Berger (pberger@brimson.com) * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com) * * All source code in this file is licensed under the following license except * where indicated. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, you can find it at http://www.fsf.org * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "usb_function.h" #include /* Defines */ #define GS_VERSION_STR "v2.2" #define GS_VERSION_NUM 0x0202 #define GS_LONG_NAME "Serial Function" #define GS_SHORT_NAME "serial" static int instances = 2; #define MAX_INSTANCES 2 #define GS_MAJOR 127 #define GS_MINOR_START 0 #define GS_NUM_PORTS 16 #define GS_NO_CONFIG_ID 0 #define GS_ACM_CONFIG_ID 2 #define GS_MAX_DESC_LEN 256 /* defines for maintaining serial states */ #define MSR_CTS (1 << 4) #define MSR_DSR (1 << 5) #define MSR_RI (1 << 6) #define MSR_CD (1 << 7) #define MCR_DTR (1 << 0) #define MCR_RTS (1 << 1) #define MCR_LOOP (1 << 4) /* USB CDC control line state defines */ #define USB_CDC_SET_CONTROL_LINE_STATE_DTR 0x1 #define USB_CDC_SET_CONTROL_LINE_STATE_RTS 0x2 #define GS_DEFAULT_READ_Q_SIZE 16 #define GS_DEFAULT_WRITE_Q_SIZE 16 #define GS_DEFAULT_INT_REQ 1 #define GS_DEFAULT_WRITE_BUF_SIZE 8192 #define GS_TMP_BUF_SIZE 8192 #define GS_CLOSE_TIMEOUT 15 #define GS_DEFAULT_USE_ACM 0 #define GS_DEFAULT_DTE_RATE 9600 #define GS_DEFAULT_DATA_BITS 8 #define GS_DEFAULT_PARITY USB_CDC_NO_PARITY #define GS_DEFAULT_CHAR_FORMAT USB_CDC_1_STOP_BITS /* #define GS_DEBUG */ /* debug settings */ #ifdef GS_DEBUG static int debug = 1; #define gs_debug(format, arg...) \ do { if (debug) printk(KERN_DEBUG format, ## arg); } while (0) #define gs_debug_level(level, format, arg...) \ do { if (debug >= level) printk(KERN_DEBUG format, ## arg); } while (0) #else #define gs_debug(format, arg...) \ do { } while (0) #define gs_debug_level(level, format, arg...) \ do { } while (0) #endif /* GS_DEBUG */ #define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ #define GS_NOTIFY_MAXPACKET 8 #define SERIAL_CONFIGURED 1 #define SERIAL_UNCONFIGURED 0 /* Structures */ struct gs_dev; /* circular buffer */ struct gs_buf { unsigned int buf_size; char *buf_buf; char *buf_get; char *buf_put; }; /* list of requests */ struct gs_req_entry { struct list_head re_entry; struct usb_request *re_req; }; /* the port structure holds info for each port, one for each minor number */ struct gs_port { struct gs_dev *port_dev; /* pointer to device struct */ struct tty_struct *port_tty; /* pointer to tty struct */ spinlock_t port_lock; struct mutex mutex_lock; /* protect open/close */ int port_num; int port_open_count; int port_in_use; /* open/close in progress */ wait_queue_head_t port_write_wait; /* waiting to write */ struct gs_buf *port_write_buf; struct usb_cdc_line_coding port_line_coding; struct list_head read_pool; struct list_head read_queue; struct list_head write_pool; unsigned n_read; unsigned int msr; unsigned int prev_msr; unsigned int mcr; struct work_struct push_work; }; /*-------------------------------------------------------------*/ /*Allocate DMA buffer in non interrupt context(gs_bind)*/ struct gs_reqbuf { void *buf; }; /*-------------------------------------------------------------*/ /* the device structure holds info for the USB device */ struct gs_dev { /* lock for set/reset config */ spinlock_t dev_lock; /* configuration number */ int dev_config; /* address of notify endpoint */ struct usb_endpoint *dev_notify_ep; /* address of in endpoint */ struct usb_endpoint *dev_in_ep; struct usb_request *notify_req; unsigned long notify_queued; /* address of out endpoint */ struct usb_endpoint *dev_out_ep; /* list of write requests */ struct list_head dev_req_list; /* round robin port scheduled */ int dev_sched_port; struct gs_port *dev_port[GS_NUM_PORTS]; /* the ports */ struct gs_reqbuf statusreqbuf; u16 interface_num; /*interface, endpoint descriptors*/ struct usb_interface_descriptor gs_ifc_desc; struct usb_endpoint_descriptor gs_hs_bulkin_desc, gs_fs_bulkin_desc; struct usb_endpoint_descriptor gs_hs_bulkout_desc, gs_fs_bulkout_desc; struct usb_endpoint_descriptor gs_hs_notifyin_desc, gs_fs_notifyin_desc; struct usb_descriptor_header **gs_fullspeed_header; struct usb_descriptor_header **gs_highspeed_header; struct usb_function *func; int configured; int bound; }; /* Functions */ /* module */ static int __init gs_module_init(void); static void __exit gs_module_exit(void); static void send_notify_data(struct usb_endpoint *ep, struct usb_request *req); /* tty driver */ static int gs_open(struct tty_struct *tty, struct file *file); static void gs_close(struct tty_struct *tty, struct file *file); static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count); static int gs_put_char(struct tty_struct *tty, unsigned char ch); static void gs_flush_chars(struct tty_struct *tty); static int gs_write_room(struct tty_struct *tty); static int gs_chars_in_buffer(struct tty_struct *tty); static void gs_throttle(struct tty_struct *tty); static void gs_unthrottle(struct tty_struct *tty); static int gs_break(struct tty_struct *tty, int break_state); static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); static unsigned gs_start_rx(struct gs_dev *dev); static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size); static void gs_read_complete(struct usb_endpoint *ep, struct usb_request *req); static void gs_write_complete(struct usb_endpoint *ep, struct usb_request *req); static int gs_tiocmget(struct tty_struct *tty, struct file *file); static int gs_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); /* Function driver */ static void gs_bind(void *); static void gs_unbind(void *); static int gs_setup(struct usb_ctrlrequest *req, void *buf, int len, void *_ctxt); static void gs_configure(int config, void *_ctxt); static void gs_disconnect(void *_ctxt); static void gs_reset_config(struct gs_dev *dev); static struct usb_request *gs_alloc_req(struct usb_endpoint *ep, unsigned int len); static void gs_free_req(struct usb_endpoint *ep, struct usb_request *req); static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags); static void gs_free_ports(struct gs_dev *dev); /* circular buffer */ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags); static void gs_buf_free(struct gs_buf *gb); static void gs_buf_clear(struct gs_buf *gb); static unsigned int gs_buf_data_avail(struct gs_buf *gb); static unsigned int gs_buf_space_avail(struct gs_buf *gb); static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count); static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count); /* Globals */ static struct gs_dev **gs_devices; static struct semaphore gs_open_close_sem[GS_NUM_PORTS]; static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; static struct workqueue_struct *gs_tty_wq; /* tty driver struct */ static const struct tty_operations gs_tty_ops = { .open = gs_open, .close = gs_close, .write = gs_write, .put_char = gs_put_char, .flush_chars = gs_flush_chars, .write_room = gs_write_room, .ioctl = gs_ioctl, .set_termios = gs_set_termios, .throttle = gs_throttle, .unthrottle = gs_unthrottle, .break_ctl = gs_break, .chars_in_buffer = gs_chars_in_buffer, .tiocmget = gs_tiocmget, .tiocmset = gs_tiocmset, }; static struct tty_driver *gs_tty_driver; /* Function driver struct */ static struct usb_function usb_function_serial[2]; struct usb_function *global_func_serial; struct gs_dev **dum_device; /* Module */ MODULE_DESCRIPTION(GS_LONG_NAME); MODULE_AUTHOR("Al Borchers"); MODULE_LICENSE("GPL"); #ifdef GS_DEBUG module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); #endif module_param(read_q_size, uint, S_IRUGO); MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); module_param(write_q_size, uint, S_IRUGO); MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32"); module_param(write_buf_size, uint, S_IRUGO); MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192"); module_param(instances, int, 0); MODULE_PARM_DESC(instances, "Number of serial instances"); module_init(gs_module_init); module_exit(gs_module_exit); /******************************************************************************/ /* * CDC-ACM Class specific Descriptors */ static const struct usb_cdc_header_desc gs_header_desc = { .bLength = sizeof(gs_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, .bcdCDC = __constant_cpu_to_le16(0x0110), }; static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = { .bLength = sizeof(gs_call_mgmt_descriptor), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, .bmCapabilities = 0, .bDataInterface = 0, }; static struct usb_cdc_acm_descriptor gs_acm_descriptor = { .bLength = sizeof(gs_acm_descriptor), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_ACM_TYPE, .bmCapabilities = 3, /* bits should be 00000011 (refer to 5.2.3.3) */ }; static const struct usb_cdc_union_desc gs_union_desc = { .bLength = sizeof(gs_union_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_UNION_TYPE, .bMasterInterface0 = 0, .bSlaveInterface0 = 0, }; static void gs_init_ifc_desc(struct usb_interface_descriptor *ifc_desc) { ifc_desc->bLength = USB_DT_INTERFACE_SIZE; ifc_desc->bDescriptorType = USB_DT_INTERFACE; ifc_desc->bNumEndpoints = 3; ifc_desc->bInterfaceClass = USB_CLASS_VENDOR_SPEC; ifc_desc->bInterfaceSubClass = USB_CLASS_VENDOR_SPEC; ifc_desc->bInterfaceProtocol = USB_CLASS_VENDOR_SPEC; ifc_desc->iInterface = 0; } #define HIGHSPEED 1 #define FULLSPEED 2 #define BULK 1 #define INTERRUPT 2 static void gs_init_ep_desc(struct usb_endpoint_descriptor *ep_desc, unsigned type, unsigned speed) { ep_desc->bLength = USB_DT_ENDPOINT_SIZE; ep_desc->bDescriptorType = USB_DT_ENDPOINT; if (type == BULK) { ep_desc->bmAttributes = USB_ENDPOINT_XFER_BULK; if (speed == HIGHSPEED) ep_desc->wMaxPacketSize = 512; else ep_desc->wMaxPacketSize = 64; } else { ep_desc->bmAttributes = USB_ENDPOINT_XFER_INT; ep_desc->wMaxPacketSize = 64; ep_desc->bInterval = 4; } } static void gs_init_header_desc(struct gs_dev *dev) { dev->gs_highspeed_header[0] = (struct usb_descriptor_header *)&dev->gs_ifc_desc; dev->gs_highspeed_header[1] = (struct usb_descriptor_header *)&dev->gs_hs_bulkin_desc; dev->gs_highspeed_header[2] = (struct usb_descriptor_header *)&dev->gs_hs_bulkout_desc; dev->gs_highspeed_header[3] = (struct usb_descriptor_header *)&dev->gs_hs_notifyin_desc; dev->gs_highspeed_header[4] = NULL; dev->gs_fullspeed_header[0] = (struct usb_descriptor_header *)&dev->gs_ifc_desc; dev->gs_fullspeed_header[1] = (struct usb_descriptor_header *)&dev->gs_fs_bulkin_desc; dev->gs_fullspeed_header[2] = (struct usb_descriptor_header *)&dev->gs_fs_bulkout_desc; dev->gs_fullspeed_header[3] = (struct usb_descriptor_header *)&dev->gs_fs_notifyin_desc; dev->gs_fullspeed_header[4] = NULL; } /*****************************************************************************/ /* * gs_module_init * * Register as a USB gadget driver and a tty driver. */ char *a[] = {"modem", "nmea"}; static int __init gs_module_init(void) { int i, retval; struct usb_function *func; if (instances > MAX_INSTANCES || instances == 0) { printk(KERN_ERR "Incorrect instances entered \n"); return -ENODEV; } gs_tty_wq = create_singlethread_workqueue("gs_tty"); if (gs_tty_wq == 0) return -ENOMEM; gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS); if (!gs_tty_driver) { destroy_workqueue(gs_tty_wq); return -ENOMEM; } gs_tty_driver->owner = THIS_MODULE; gs_tty_driver->driver_name = GS_SHORT_NAME; gs_tty_driver->name = "ttyHSUSB"; gs_tty_driver->major = GS_MAJOR; gs_tty_driver->minor_start = GS_MINOR_START; gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_RESET_TERMIOS; gs_tty_driver->init_termios = tty_std_termios; gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(gs_tty_driver, &gs_tty_ops); for (i = 0; i < GS_NUM_PORTS; i++) sema_init(&gs_open_close_sem[i], 1); retval = tty_register_driver(gs_tty_driver); if (retval) { /*usb_function_unregister(&usb_func_serial); */ put_tty_driver(gs_tty_driver); printk(KERN_ERR "gs_module_init: cannot register tty driver,ret = %d\n", retval); return retval; } for (i = 0; i < MAX_INSTANCES; i++) tty_register_device(gs_tty_driver, i, NULL); gs_devices = kzalloc(sizeof(struct gs_dev *) * instances, GFP_KERNEL); if (!gs_devices) return -ENOMEM; for (i = 0; i < instances; i++) { func = &usb_function_serial[i]; gs_devices[i] = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); if (!gs_devices[i]) return -ENOMEM; spin_lock_init(&gs_devices[i]->dev_lock); INIT_LIST_HEAD(&gs_devices[i]->dev_req_list); gs_devices[i]->func = func; /*1 - Interface, 3 Endpoints-> Total 4 + 1 for NULL*/ gs_devices[i]->gs_fullspeed_header = kmalloc(sizeof(struct usb_descriptor_header *) * 5, GFP_KERNEL); gs_devices[i]->gs_highspeed_header = kmalloc(sizeof(struct usb_descriptor_header *) * 5, GFP_KERNEL); gs_init_ifc_desc(&gs_devices[i]->gs_ifc_desc); gs_init_ep_desc(&gs_devices[i]->gs_hs_bulkin_desc, BULK, HIGHSPEED); gs_init_ep_desc(&gs_devices[i]->gs_hs_bulkout_desc, BULK, HIGHSPEED); gs_init_ep_desc(&gs_devices[i]->gs_hs_notifyin_desc, INTERRUPT, HIGHSPEED); gs_init_ep_desc(&gs_devices[i]->gs_fs_bulkin_desc, BULK, FULLSPEED); gs_init_ep_desc(&gs_devices[i]->gs_fs_bulkout_desc, BULK, FULLSPEED); gs_init_ep_desc(&gs_devices[i]->gs_fs_notifyin_desc, INTERRUPT, FULLSPEED); gs_init_header_desc(gs_devices[i]); /*Initializing Directions*/ gs_devices[i]->gs_hs_bulkin_desc.bEndpointAddress = USB_DIR_IN; gs_devices[i]->gs_hs_bulkout_desc.bEndpointAddress = USB_DIR_OUT; gs_devices[i]->gs_hs_notifyin_desc.bEndpointAddress = USB_DIR_IN; gs_devices[i]->gs_fs_bulkin_desc.bEndpointAddress = USB_DIR_IN; gs_devices[i]->gs_fs_bulkout_desc.bEndpointAddress = USB_DIR_OUT; gs_devices[i]->gs_fs_notifyin_desc.bEndpointAddress = USB_DIR_IN; func->bind = gs_bind; func->unbind = gs_unbind; func->configure = gs_configure; func->disconnect = gs_disconnect; func->setup = gs_setup; func->name = a[i]; func->context = gs_devices[i]; func->fs_descriptors = gs_devices[i]->gs_fullspeed_header; func->hs_descriptors = gs_devices[i]->gs_highspeed_header; retval = usb_function_register(func); if (retval) { printk(KERN_ERR "gs_module_init: cannot register Function driver, ret = %d\n", retval); return retval; } } return 0; } /* * gs_module_exit * * Unregister as a tty driver and a USB gadget driver. */ static void __exit gs_module_exit(void) { int i; for (i = 0; i < instances; i++) usb_function_unregister(&usb_function_serial[i]); for (i = 0; i < instances; ++i) { kfree(gs_devices[i]->gs_fullspeed_header); kfree(gs_devices[i]->gs_highspeed_header); kfree(gs_devices[i]); } for (i = 0; i < MAX_INSTANCES; i++) tty_unregister_device(gs_tty_driver, i); tty_unregister_driver(gs_tty_driver); put_tty_driver(gs_tty_driver); printk(KERN_INFO "gs_module_exit: %s %s unloaded\n", GS_LONG_NAME, GS_VERSION_STR); } /* TTY Driver */ /* * gs_open */ static int gs_open(struct tty_struct *tty, struct file *file) { int port_num; unsigned long flags; struct gs_port *port; struct gs_dev *dev; struct gs_buf *buf; struct semaphore *sem; int ret; port_num = tty->index; gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file); if (port_num < 0 || port_num >= GS_NUM_PORTS) { printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n", port_num, tty, file); return -ENODEV; } dev = gs_devices[tty->index]; if (dev == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n", port_num, tty, file); return -ENODEV; } sem = &gs_open_close_sem[port_num]; if (down_interruptible(sem)) { printk(KERN_ERR "gs_open: (%d,%p,%p) interrupted waiting for semaphore\n", port_num, tty, file); return -ERESTARTSYS; } spin_lock_irqsave(&dev->dev_lock, flags); port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n", port_num, tty, file); ret = -ENODEV; goto exit_unlock_dev; } spin_unlock_irqrestore(&dev->dev_lock, flags); spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n", port_num, tty, file); ret = -EIO; goto exit_unlock_port; } if (port->port_open_count > 0) { ++port->port_open_count; gs_debug("gs_open: (%d,%p,%p) already open\n", port_num, tty, file); ret = 0; goto exit_unlock_port; } tty->driver_data = NULL; /* mark port as in use, we can drop port lock and sleep if necessary */ port->port_in_use = 1; /* allocate write buffer on first open */ if (port->port_write_buf == NULL) { spin_unlock_irqrestore(&port->port_lock, flags); buf = gs_buf_alloc(write_buf_size, GFP_KERNEL); spin_lock_irqsave(&port->port_lock, flags); /* might have been disconnected while asleep, check */ if (port->port_dev == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (2)\n", port_num, tty, file); port->port_in_use = 0; ret = -EIO; goto exit_unlock_port; } port->port_write_buf = buf; if (port->port_write_buf == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n", port_num, tty, file); port->port_in_use = 0; ret = -ENOMEM; goto exit_unlock_port; } } /* wait for carrier detect (not implemented) */ /* might have been disconnected while asleep, check */ if (port->port_dev == NULL) { printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n", port_num, tty, file); port->port_in_use = 0; ret = -EIO; goto exit_unlock_port; } tty->driver_data = port; port->port_tty = tty; port->port_tty->low_latency = 1; port->port_open_count = 1; port->port_in_use = 0; gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file); /* Queue RX requests */ port->n_read = 0; gs_start_rx(dev); ret = 0; exit_unlock_port: spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return ret; exit_unlock_dev: spin_unlock_irqrestore(&dev->dev_lock, flags); up(sem); return ret; } /* * gs_close */ #define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ ({ \ int cond; \ \ spin_lock_irq(&(p)->port_lock); \ cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ spin_unlock_irq(&(p)->port_lock); \ cond; \ }) static void gs_close(struct tty_struct *tty, struct file *file) { struct gs_port *port = tty->driver_data; struct semaphore *sem; if (port == NULL) { printk(KERN_ERR "gs_close: NULL port pointer\n"); return; } gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file); sem = &gs_open_close_sem[port->port_num]; down(sem); spin_lock_irq(&port->port_lock); if (port->port_open_count == 0) { printk(KERN_ERR "gs_close: (%d,%p,%p) port is already closed\n", port->port_num, tty, file); goto exit; } if (port->port_open_count > 1) { --port->port_open_count; goto exit; } /* free disconnected port on final close */ if (port->port_dev == NULL) goto exit; /* mark port as closed but in use, we can drop port lock */ /* and sleep if necessary */ port->port_in_use = 1; port->port_open_count = 0; /* wait for write buffer to drain, or */ /* at most GS_CLOSE_TIMEOUT seconds */ if (gs_buf_data_avail(port->port_write_buf) > 0) { spin_unlock_irq(&port->port_lock); wait_event_interruptible_timeout(port->port_write_wait, GS_WRITE_FINISHED_EVENT_SAFELY (port), GS_CLOSE_TIMEOUT * HZ); spin_lock_irq(&port->port_lock); } /* free disconnected port on final close */ /* (might have happened during the above sleep) */ if (port->port_dev == NULL) goto exit; gs_buf_clear(port->port_write_buf); /* Flush bulk-out pipe */ usb_ept_fifo_flush(port->port_dev->dev_out_ep); tty->driver_data = NULL; port->port_tty = NULL; port->port_in_use = 0; gs_debug("gs_close: (%d,%p,%p) completed\n", port->port_num, tty, file); exit: spin_unlock_irq(&port->port_lock); up(sem); if (port->port_dev == NULL) kfree(port); } /* * gs_write */ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) { unsigned long flags; struct gs_port *port = tty->driver_data; int ret; if (port == NULL) { printk(KERN_ERR "gs_write: NULL port pointer\n"); return -EIO; } gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty, count); if (count == 0) return 0; spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n", port->port_num, tty); ret = -EIO; goto exit; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_write: (%d,%p) port is closed\n", port->port_num, tty); ret = -EBADF; goto exit; } count = gs_buf_put(port->port_write_buf, buf, count); if (port->port_dev->dev_config) gs_send(gs_devices[tty->index]); spin_unlock_irqrestore(&port->port_lock, flags); gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty, count); return count; exit: spin_unlock_irqrestore(&port->port_lock, flags); return ret; } /* * gs_put_char */ static int gs_put_char(struct tty_struct *tty, unsigned char ch) { unsigned long flags; int ret = 0; struct gs_port *port = tty->driver_data; if (port == NULL) { printk(KERN_ERR "gs_put_char: NULL port pointer\n"); goto out; } gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2)); spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_put_char: (%d,%p) port is not connected\n", port->port_num, tty); goto exit_unlock; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n", port->port_num, tty); goto exit_unlock; } ret = gs_buf_put(port->port_write_buf, &ch, 1); exit_unlock: spin_unlock_irqrestore(&port->port_lock, flags); out: return ret; } /* * gs_flush_chars */ static void gs_flush_chars(struct tty_struct *tty) { unsigned long flags; struct gs_port *port = tty->driver_data; if (port == NULL) { printk(KERN_ERR "gs_flush_chars: NULL port pointer\n"); return; } gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty); spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev == NULL) { printk(KERN_ERR "gs_flush_chars: (%d,%p) port is not connected\n", port->port_num, tty); goto exit; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n", port->port_num, tty); goto exit; } if (port->port_dev->dev_config) gs_send(gs_devices[tty->index]); spin_unlock_irqrestore(&port->port_lock, flags); return; exit: spin_unlock_irqrestore(&port->port_lock, flags); } /* * gs_write_room */ static int gs_write_room(struct tty_struct *tty) { int room = 0; unsigned long flags; struct gs_port *port = tty->driver_data; if (port == NULL) return 0; spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev != NULL && port->port_open_count > 0 && port->port_write_buf != NULL) room = gs_buf_space_avail(port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); gs_debug("gs_write_room: (%d,%p) room=%d\n", port->port_num, tty, room); return room; } /* * gs_chars_in_buffer */ static int gs_chars_in_buffer(struct tty_struct *tty) { int chars = 0; unsigned long flags; struct gs_port *port = tty->driver_data; if (port == NULL) return 0; spin_lock_irqsave(&port->port_lock, flags); if (port->port_dev != NULL && port->port_open_count > 0 && port->port_write_buf != NULL) chars = gs_buf_data_avail(port->port_write_buf); spin_unlock_irqrestore(&port->port_lock, flags); gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n", port->port_num, tty, chars); return chars; } /* * gs_throttle */ static void gs_throttle(struct tty_struct *tty) { } /* * gs_unthrottle */ static void gs_unthrottle(struct tty_struct *tty) { struct gs_port *port = tty->driver_data; unsigned long flags; spin_lock_irqsave(&port->port_lock, flags); queue_work(gs_tty_wq, &port->push_work); spin_unlock_irqrestore(&port->port_lock, flags); } /* * gs_break */ static int gs_break(struct tty_struct *tty, int break_state) { return 0; } /* * gs_ioctl */ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { /* could not handle ioctl */ return -ENOIOCTLCMD; } /* * gs_set_termios */ static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } /* * gs_send * * This function finds available write requests, calls * gs_send_packet to fill these packets with data, and * continues until either there are no more write requests * available or no more data to send. This function is * run whenever data arrives or write requests are available. */ static int gs_send(struct gs_dev *dev) { struct gs_port *port = dev->dev_port[0]; struct list_head *pool = &port->write_pool; int status = 0; static long prev_len; bool do_tty_wake = false; struct usb_endpoint *ep = dev->dev_in_ep; while (!list_empty(pool)) { struct usb_request *req; int len; req = list_entry(pool->next, struct usb_request, list); len = gs_send_packet(dev, req->buf, usb_ept_get_max_packet(ep)); if (len == 0) { /* Queue zero length packet */ if (prev_len == usb_ept_get_max_packet(ep)) { req->length = 0; list_del(&req->list); spin_unlock(&port->port_lock); status = usb_ept_queue_xfer(ep, req); spin_lock(&port->port_lock); if (status) { printk(KERN_ERR "%s: %s err %d\n", __func__, "queue", status); list_add(&req->list, pool); } prev_len = 0; } wake_up_interruptible(&port->port_write_wait); break; } do_tty_wake = true; req->length = len; list_del(&req->list); /* Drop lock while we call out of driver; completions * could be issued while we do so. Disconnection may * happen too; maybe immediately before we queue this! * NOTE that we may keep sending data for a while after * the TTY closed (dev->ioport->port_tty is NULL). */ spin_unlock(&port->port_lock); status = usb_ept_queue_xfer(ep, req); spin_lock(&port->port_lock); if (status) { printk(KERN_ERR "%s: %s err %d\n", __func__, "queue", status); list_add(&req->list, pool); break; } prev_len = req->length; } if (do_tty_wake && port->port_tty) tty_wakeup(port->port_tty); return status; } /* * gs_send_packet * * If there is data to send, a packet is built in the given * buffer and the size is returned. If there is no data to * send, 0 is returned. If there is any error a negative * error number is returned. * * Called during USB completion routine, on interrupt time. * * We assume that disconnect will not happen until all completion * routines have completed, so we can assume that the dev_port * array does not change during the lifetime of this function. */ static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size) { unsigned int len; struct gs_port *port; if (dev == NULL) { printk(KERN_ERR "gs_recv_packet:NULL device pointer\n"); return -EIO; } /* TEMPORARY -- only port 0 is supported right now */ port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR "gs_send_packet: port=%d, NULL port pointer\n", 0); return -EIO; } len = gs_buf_data_avail(port->port_write_buf); if (len < size) size = len; if (size != 0) size = gs_buf_get(port->port_write_buf, packet, size); if (port->port_tty) tty_wakeup(port->port_tty); return size; } static void gs_rx_push(struct work_struct *work) { struct gs_port *port = container_of(work, struct gs_port, push_work); struct tty_struct *tty; struct list_head *queue = &port->read_queue; bool do_push = false; struct gs_dev *dev = port->port_dev; /* hand any queued data to the tty */ spin_lock_irq(&port->port_lock); tty = port->port_tty; while (!list_empty(queue)) { struct usb_request *req; req = list_first_entry(queue, struct usb_request, list); /* discard data if tty was closed */ if (!tty) goto recycle; if (req->actual) { char *packet = req->buf; unsigned size = req->actual; unsigned n; int count; /* we may have pushed part of this packet already... */ n = port->n_read; if (n) { packet += n; size -= n; } /*printk(KERN_INFO "tty_push:%d\n",size);*/ count = tty_insert_flip_string(tty, packet, size); if (count == 0) printk(KERN_INFO "%s: tty buffer is full: throttle\n", __func__); if (count) do_push = true; if (count != size) { /* stop pushing; TTY layer can't handle more */ port->n_read += count; break; } port->n_read = 0; } recycle: list_move(&req->list, &port->read_pool); } if (tty && do_push) { spin_unlock_irq(&port->port_lock); tty_flip_buffer_push(tty); wake_up_interruptible(&tty->read_wait); spin_lock_irq(&port->port_lock); /* tty may have been closed */ tty = port->port_tty; } if (!list_empty(queue) && tty) { if (!test_bit(TTY_THROTTLED, &tty->flags)) { if (do_push) queue_work(gs_tty_wq, &port->push_work); } } gs_start_rx(dev); spin_unlock_irq(&port->port_lock); } /* * gs_read_complete */ static void gs_read_complete(struct usb_endpoint *ep, struct usb_request *req) { /* used global variable */ struct gs_dev *dev = (struct gs_dev *)req->device; struct gs_port *port; struct tty_struct *tty; if (dev == NULL) { printk(KERN_ERR "gs_read_complete: NULL device pointer\n"); return; } port = dev->dev_port[0]; tty = port->port_tty; switch (req->status) { case 0: spin_lock(&port->port_lock); list_add_tail(&req->list, &port->read_queue); if (!test_bit(TTY_THROTTLED, &tty->flags)) queue_work(gs_tty_wq, &port->push_work); spin_unlock(&port->port_lock); break; case -ESHUTDOWN: /* disconnect */ gs_debug("gs_read_complete: shutdown\n"); gs_free_req(ep, req); break; case -ENODEV: list_add_tail(&req->list, &port->read_pool); /* Implemented handling in future if needed */ break; default: list_add_tail(&req->list, &port->read_pool); printk(KERN_ERR "gs_read_complete: unexpected status error, status=%d\n", req->status); /* goto requeue; */ break; } } /* * gs_write_complete */ static void gs_write_complete(struct usb_endpoint *ep, struct usb_request *req) { struct gs_dev *dev = (struct gs_dev *)req->device; struct gs_port *port = dev->dev_port[0]; unsigned long flags; if (dev == NULL) { printk(KERN_ERR "gs_write_complete: NULL device pointer\n"); return; } spin_lock_irqsave(&port->port_lock, flags); list_add(&req->list, &port->write_pool); switch (req->status) { default: /* presumably a transient fault */ printk(KERN_ERR "%s: unexpected status %d\n", __func__, req->status); /* FALL THROUGH */ case 0: /* normal completion */ if ((req->length == 0) && (gs_buf_data_avail(port->port_write_buf) == 0)) { break; } if (dev->dev_config) gs_send(dev); break; case -ESHUTDOWN: /* disconnect */ printk(KERN_DEBUG "%s: shutdown\n", __func__); break; } spin_unlock_irqrestore(&port->port_lock, flags); } /* Send Notification to host if Status changes */ static void send_notify_data(struct usb_endpoint *ep, struct usb_request *req) { struct gs_dev *dev = (struct gs_dev *)req->device; struct usb_cdc_notification *notify; struct gs_port *port; unsigned int msr, ret; __le16 *data; if (dev == NULL) { printk(KERN_ERR "send_notify_data: NULL device pointer\n"); return; } port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR"send_notify_data:port is NULL\n"); return; } if (test_bit(0, &dev->notify_queued)) usb_ept_cancel_xfer(dev->dev_notify_ep, dev->notify_req); notify = req->buf; msr = port->msr; notify->bmRequestType = 0xA1; notify->bNotificationType = USB_CDC_NOTIFY_SERIAL_STATE; notify->wValue = __constant_cpu_to_le16(0); notify->wIndex = __constant_cpu_to_le16(dev->interface_num); notify->wLength = __constant_cpu_to_le16(2); data = req->buf + sizeof *notify; data[0] = __constant_cpu_to_le16(((msr & MSR_CD) ? 1 : 0) | ((msr & MSR_DSR) ? (1<<1) : (0<<1)) | ((msr & MSR_RI) ? (1<<3) : (0<<3))); set_bit(0, &dev->notify_queued); ret = usb_ept_queue_xfer(ep, req); if (ret) { clear_bit(0, &dev->notify_queued); printk(KERN_ERR "send_notify_data: cannot queue status request,ret = %d\n", ret); } } /* Free request if -ESHUTDOWN */ static void gs_status_complete(struct usb_endpoint *ep, struct usb_request *req) { struct gs_dev *dev = (struct gs_dev *)req->device; struct gs_port *port; if (dev == NULL) { printk(KERN_ERR"gs_status_complete : NULL device pointer\n"); return; } port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR "gs_status_complete: NULL port pointer\n"); return; } clear_bit(0, &dev->notify_queued); switch (req->status) { case 0: gs_debug("%s:port->msr=%x,dev=%p,ep=%p,req=%p", __func__, port->msr, dev, dev->dev_notify_ep, dev->notify_req); /* executed only if data missed because of ** request already in queue and user modifies using tiocmset */ if (port->prev_msr != port->msr) { send_notify_data(dev->dev_notify_ep, dev->notify_req); port->prev_msr = port->msr; } break; case -ESHUTDOWN: /* disconnect */ gs_debug("gs_status_complete: shutdown\n"); gs_free_req(ep, req); break; default: printk(KERN_ERR "gs_status_complete: unexpected status error, status=%d\n", req->status); break; } } /* Function Driver */ /* * gs_bind * * Called on module load. Allocates and initializes the device * structure and a control request. */ static void gs_bind(void *_ctxt) { struct usb_endpoint *ep; struct gs_dev *dev = _ctxt; struct usb_function *func = dev->func; int i = 0; int ret; if (func == NULL) { pr_err("%s: NULL function pointer\n", __func__); return; } ret = gs_alloc_ports(dev, GFP_KERNEL); if (ret != 0) { pr_err("%s: cannot allocate ports\n", __func__); gs_unbind(_ctxt); return; } ret = usb_msm_get_next_ifc_number(func); dev->gs_ifc_desc.bInterfaceNumber = ret; dev->gs_ifc_desc.iInterface = 0; /*Configuring IN Endpoint*/ ep = dev->dev_in_ep = usb_alloc_endpoint(USB_DIR_IN); if (!ep) { pr_err("%s: in endpoint allocation failed\n", __func__); return; } dev->gs_hs_bulkin_desc.bEndpointAddress = USB_DIR_IN | ep->num; dev->gs_fs_bulkin_desc.bEndpointAddress = USB_DIR_IN | ep->num; pr_debug("%s: bulk_in_endpoint Number = %d\n", __func__, ep->num); /*Configuring OUT endpoint*/ ep = dev->dev_out_ep = usb_alloc_endpoint(USB_DIR_OUT); if (!ep) { pr_err("out endpoint allocation failed\n"); return; } dev->gs_hs_bulkout_desc.bEndpointAddress = USB_DIR_OUT | ep->num; dev->gs_fs_bulkout_desc.bEndpointAddress = USB_DIR_OUT | ep->num; pr_debug("%s: bulk_out_endpoint Number = %d\n", __func__, ep->num); /*Configuring NOTIFY endpoint*/ ep = dev->dev_notify_ep = usb_alloc_endpoint(USB_DIR_IN); if (!ep) { pr_err("notify endpoint allocation failed\n"); return; } dev->gs_hs_notifyin_desc.bEndpointAddress = USB_DIR_IN | ep->num; dev->gs_fs_notifyin_desc.bEndpointAddress = USB_DIR_IN | ep->num; pr_debug("%s: notify_in_endpoint Number = %d\n", __func__, ep->num); for (i = 0; i < GS_DEFAULT_INT_REQ; ++i) { struct gs_reqbuf *bh = &dev->statusreqbuf; bh->buf = kmalloc(64, GFP_KERNEL); if (!bh->buf) return; } dev->bound = 1; return; } /* * gs_unbind * * Called on module unload. Frees the control request and device * structure. */ static void /* __init_or_exit */ gs_unbind(void *_ctxt) { struct gs_dev *dev = _ctxt; if (!dev) { pr_err("%s: error: null device\n", __func__); return; } if (!dev->bound) return; kfree(dev->statusreqbuf.buf); if (dev->dev_in_ep) { usb_ept_fifo_flush(dev->dev_in_ep); usb_ept_enable(dev->dev_in_ep, 0); usb_free_endpoint(dev->dev_in_ep); } if (dev->dev_out_ep) { usb_ept_fifo_flush(dev->dev_out_ep); usb_ept_enable(dev->dev_out_ep, 0); usb_free_endpoint(dev->dev_out_ep); } if (dev->dev_notify_ep) { usb_ept_fifo_flush(dev->dev_notify_ep); usb_ept_enable(dev->dev_notify_ep, 0); usb_free_endpoint(dev->dev_notify_ep); } gs_free_ports(dev); dev->bound = 0; pr_debug("%s: %s %s\n", __func__, GS_LONG_NAME, GS_VERSION_STR); } static void gser_complete_set_line_coding(struct usb_endpoint *ep, struct usb_request *req) { struct gs_dev *dev = (struct gs_dev *)req->device; struct gs_port *port; struct usb_cdc_line_coding *value; struct usb_request *in_req; port = dev->dev_port[0]; if (!(dev && dev->dev_port[0])) { printk(KERN_ERR "%s(): dev or dev_port is null\n", __func__); usb_ept_set_halt(dev->func->ep0_in); return; } if (req->actual != sizeof(port->port_line_coding)) { printk(KERN_ERR "%s(): received wrong data\n", __func__); usb_ept_set_halt(dev->func->ep0_in); return; } port = dev->dev_port[0]; /* Use Host assigned port_line setting */ value = req->buf; port->port_line_coding = *value; /* Send ACK on EP0 IN */ in_req = dev->func->ep0_in_req; in_req->length = 0; in_req->complete = 0; usb_ept_queue_xfer(dev->func->ep0_in, in_req); } static int gs_setup(struct usb_ctrlrequest *ctrl, void *buf, int len, void *_ctxt) { int ret = -EOPNOTSUPP; struct gs_dev *dev = _ctxt; struct gs_port *port;/* ACM only has one port */ u16 wIndex = le16_to_cpu(ctrl->wIndex); u16 wValue = le16_to_cpu(ctrl->wValue); u16 wLength = le16_to_cpu(ctrl->wLength); if (dev == NULL) { printk(KERN_ERR"gs_setup:device pointer NULL\n"); return 0; } port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR"gs_setup: port pointer is NULL\n"); return 0; } switch (ctrl->bRequest) { case USB_CDC_REQ_SET_LINE_CODING: if (port) { struct usb_request *req = dev->func->ep0_out_req; ret = min(wLength, (u16) sizeof(struct usb_cdc_line_coding)); if (ret != sizeof(struct usb_cdc_line_coding)) ret = -EOPNOTSUPP; else { req->device = dev; req->complete = gser_complete_set_line_coding; } } else ret = -ENODEV; break; case USB_CDC_REQ_GET_LINE_CODING: port = dev->dev_port[0];/* ACM only has one port */ ret = min(wLength, (u16) sizeof(struct usb_cdc_line_coding)); if (port) { spin_lock(&port->port_lock); memcpy(buf, &port->port_line_coding, ret); spin_unlock(&port->port_lock); } break; case USB_CDC_REQ_SET_CONTROL_LINE_STATE: port = dev->dev_port[0];/* ACM only has one port */ if (wValue & USB_CDC_SET_CONTROL_LINE_STATE_DTR) { port->mcr |= MCR_DTR; } else { port->mcr &= ~MCR_DTR; } if (wValue & USB_CDC_SET_CONTROL_LINE_STATE_RTS) port->mcr |= MCR_RTS; else port->mcr &= ~MCR_RTS; dev->interface_num = wIndex; ret = 0; break; default: break; } return ret; } static void gs_disconnect(void *_ctxt) { struct gs_dev *dev = _ctxt; struct gs_port *port = dev->dev_port[0]; unsigned long flags; /* tell the TTY glue not to do I/O here any more */ spin_lock_irqsave(&port->port_lock, flags); dev->dev_config = 0; if (port->port_open_count > 0 || port->port_in_use) { wake_up_interruptible(&port->port_write_wait); if (port->port_tty) { wake_up_interruptible(&port->port_tty->read_wait); wake_up_interruptible(&port->port_tty->write_wait); tty_hangup(port->port_tty); } } port->mcr = 0; port->msr = 0; spin_unlock_irqrestore(&port->port_lock, flags); } /* * gs_configure * * Configures the device by enabling device specific * optimizations, setting up the endpoints, allocating * read and write requests and queuing read requests. * * The device lock must be held when calling this function. */ static void gs_configure(int config, void *_ctxt) { int i, ret = 0; unsigned MaxPacketSize; struct gs_dev *dev = _ctxt; struct usb_endpoint *ep; struct usb_request *req; struct gs_port *port; struct list_head *rhead; struct list_head *whead; unsigned started = 0; if (dev == NULL) { printk(KERN_ERR "gs_configure: NULL device pointer\n"); return; } if (!dev->bound) return; port = dev->dev_port[0]; rhead = &port->read_pool; whead = &port->write_pool; if (port == NULL) { printk(KERN_ERR "gs_configure:port is NULL\n"); return; } if (!config) { gs_debug("gs_configure: Deconfigure\n"); dev->configured = SERIAL_UNCONFIGURED; gs_reset_config(dev); return; } dev->dev_config = config; if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL || (dev->dev_notify_ep == NULL)) { printk(KERN_ERR "gs_configure : cannot find endpoints\n"); ret = -ENODEV; goto reset_config; } if (usb_msm_get_speed() == USB_SPEED_HIGH) { usb_configure_endpoint(dev->dev_in_ep, &dev->gs_hs_bulkin_desc); usb_configure_endpoint(dev->dev_out_ep, &dev->gs_hs_bulkout_desc); usb_configure_endpoint(dev->dev_notify_ep, &dev->gs_hs_notifyin_desc); } else { usb_configure_endpoint(dev->dev_in_ep, &dev->gs_fs_bulkin_desc); usb_configure_endpoint(dev->dev_out_ep, &dev->gs_fs_bulkout_desc); usb_configure_endpoint(dev->dev_notify_ep, &dev->gs_fs_notifyin_desc); } usb_ept_enable(dev->dev_in_ep, 1); usb_ept_enable(dev->dev_out_ep, 1); usb_ept_enable(dev->dev_notify_ep, 1); gs_debug("gs_configure: endpoint sizes and buffers\n"); /* allocate and queue read requests */ ep = dev->dev_out_ep; MaxPacketSize = usb_ept_get_max_packet(ep); for (i = 0; i < read_q_size; i++) { req = gs_alloc_req(ep, MaxPacketSize); if (req) { req->device = (void *)dev; req->length = MaxPacketSize; req->complete = gs_read_complete; list_add_tail(&req->list, rhead); gs_debug("gs_configure: queuing read request(%d)\n", i); } else { printk(KERN_ERR "gs_configure: cannot allocate read request(%d)\n", i); goto reset_config; } } /* allocate write requests, and put on free list */ ep = dev->dev_in_ep; MaxPacketSize = usb_ept_get_max_packet(ep); for (i = 0; i < write_q_size; i++) { req = gs_alloc_req(ep, MaxPacketSize); if (req) { req->device = (void *)dev; req->length = MaxPacketSize; req->complete = gs_write_complete; list_add_tail(&req->list, whead); } else { printk(KERN_ERR "gs_configure: cannot allocate write request(%d)\n", i); goto reset_config; } } ep = dev->dev_notify_ep; MaxPacketSize = usb_ept_get_max_packet(ep); for (i = 0; i < GS_DEFAULT_INT_REQ; ++i) { struct gs_reqbuf *bh = &dev->statusreqbuf; dev->notify_req = req = gs_alloc_req(ep, 0); if (req) { req->device = (void *)dev; req->buf = bh->buf; req->length = MaxPacketSize; req->complete = gs_status_complete; } } if (port->port_open_count) { unsigned long flags; spin_lock_irqsave(&port->port_lock, flags); started = gs_start_rx(dev); spin_unlock_irqrestore(&port->port_lock, flags); if (started) tty_wakeup(port->port_tty); } dev->configured = SERIAL_CONFIGURED; return; reset_config: printk(KERN_ERR "gs_configure(end): error, calling gs_reset_config\n"); gs_reset_config(dev); return; } static unsigned gs_start_rx(struct gs_dev *dev) { struct gs_port *port = dev->dev_port[0]; struct list_head *pool = &port->read_pool; unsigned ret = 0; struct usb_endpoint *ep = dev->dev_out_ep; unsigned started = 0; while (!list_empty(pool)) { struct usb_request *req; struct tty_struct *tty; tty = port->port_tty; if (!tty) { printk(KERN_ERR "%s: tty is null\n", __func__); break; } req = list_entry(pool->next, struct usb_request, list); list_del(&req->list); spin_unlock(&port->port_lock); ret = usb_ept_queue_xfer(ep, req); spin_lock(&port->port_lock); if (ret) { list_add(&req->list, pool); break; } started++; } return started; } /* * gs_reset_config * * Mark the device as not configured, disable all endpoints, * which forces completion of pending I/O and frees queued * requests, and free the remaining write requests on the * free list. * * The device lock must be held when calling this function. */ static void gs_reset_config(struct gs_dev *dev) { struct gs_port *port; struct usb_request *req; unsigned long flags; if (dev == NULL) { printk(KERN_ERR "gs_reset_config: NULL device pointer\n"); return; } port = dev->dev_port[0]; if (dev->dev_out_ep) usb_free_endpoint_all_req(dev->dev_out_ep); if (dev->dev_in_ep) usb_free_endpoint_all_req(dev->dev_in_ep); if (dev->dev_notify_ep) usb_free_endpoint_all_req(dev->dev_notify_ep); spin_lock_irqsave(&port->port_lock, flags); dev->dev_config = GS_NO_CONFIG_ID; /* free write requests on the free list */ while (!list_empty(&port->write_pool)) { req = list_entry(port->write_pool.next, struct usb_request, list); list_del(&req->list); gs_free_req(dev->dev_in_ep, req); } /* free read requests from read pool */ while (!list_empty(&port->read_pool)) { req = list_entry(port->read_pool.next, struct usb_request, list); list_del(&req->list); gs_free_req(dev->dev_out_ep, req); } /* free read requests from read queue */ while (!list_empty(&port->read_queue)) { req = list_entry(port->read_queue.next, struct usb_request, list); list_del(&req->list); gs_free_req(dev->dev_out_ep, req); } spin_unlock_irqrestore(&port->port_lock, flags); } /* * gs_alloc_req * * Allocate a usb_request and its buffer. Returns a pointer to the * usb_request or NULL if there is an error. */ static struct usb_request *gs_alloc_req(struct usb_endpoint *ep, unsigned int len) { struct usb_request *req; if (ep == NULL) return NULL; req = usb_ept_alloc_req(ep, len); return req; } /* * gs_free_req * * Free a usb_request and its buffer. */ static void gs_free_req(struct usb_endpoint *ep, struct usb_request *req) { if (ep != NULL && req != NULL) usb_ept_free_req(ep, req); } /* * gs_alloc_ports * * Allocate all ports and set the gs_dev struct to point to them. * Return 0 if successful, or a negative error number. * * The device lock is normally held when calling this function. */ static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags) { int i; struct gs_port *port; if (dev == NULL) return -EIO; for (i = 0; i < GS_NUM_PORTS; i++) { port = kzalloc(sizeof(struct gs_port), kmalloc_flags); if (port == NULL) return -ENOMEM; INIT_WORK(&port->push_work, gs_rx_push); INIT_LIST_HEAD(&port->read_pool); INIT_LIST_HEAD(&port->read_queue); INIT_LIST_HEAD(&port->write_pool); port->msr = 0; port->prev_msr = 0; port->mcr = 0; port->port_dev = dev; port->port_num = i; port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE); port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT; port->port_line_coding.bParityType = GS_DEFAULT_PARITY; port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS; spin_lock_init(&port->port_lock); mutex_init(&port->mutex_lock); init_waitqueue_head(&port->port_write_wait); dev->dev_port[i] = port; } return 0; } /* * gs_free_ports * * Free all closed ports. Open ports are disconnected by * freeing their write buffers, setting their device pointers * and the pointers to them in the device to NULL. These * ports will be freed when closed. * * The device lock is normally held when calling this function. */ static void gs_free_ports(struct gs_dev *dev) { int i; unsigned long flags; struct gs_port *port; if (dev == NULL) return; for (i = 0; i < GS_NUM_PORTS; i++) { port = dev->dev_port[i]; if (port != NULL) { dev->dev_port[i] = NULL; spin_lock_irqsave(&port->port_lock, flags); if (port->port_write_buf != NULL) { gs_buf_free(port->port_write_buf); port->port_write_buf = NULL; } if (port->port_open_count > 0 || port->port_in_use) { port->port_dev = NULL; wake_up_interruptible(&port->port_write_wait); if (port->port_tty) { wake_up_interruptible (&port->port_tty->read_wait); wake_up_interruptible (&port->port_tty->write_wait); } spin_unlock_irqrestore(&port->port_lock, flags); } else { spin_unlock_irqrestore(&port->port_lock, flags); kfree(port); } } } } /* Circular Buffer */ /* * gs_buf_alloc * * Allocate a circular buffer and all associated memory. */ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) { struct gs_buf *gb; if (size == 0) return NULL; gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags); if (gb == NULL) return NULL; gb->buf_buf = kmalloc(size, kmalloc_flags); if (gb->buf_buf == NULL) { kfree(gb); return NULL; } gb->buf_size = size; gb->buf_get = gb->buf_put = gb->buf_buf; return gb; } /* * gs_buf_free * * Free the buffer and all associated memory. */ void gs_buf_free(struct gs_buf *gb) { if (gb) { kfree(gb->buf_buf); kfree(gb); } } /* * gs_buf_clear * * Clear out all data in the circular buffer. */ void gs_buf_clear(struct gs_buf *gb) { if (gb != NULL) gb->buf_get = gb->buf_put; /* equivalent to a get of all data available */ } /* * gs_buf_data_avail * * Return the number of bytes of data available in the circular * buffer. */ unsigned int gs_buf_data_avail(struct gs_buf *gb) { if (gb != NULL) return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; else return 0; } /* * gs_buf_space_avail * * Return the number of bytes of space available in the circular * buffer. */ unsigned int gs_buf_space_avail(struct gs_buf *gb) { if (gb != NULL) return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; else return 0; } /* * gs_buf_put * * Copy data data from a user buffer and put it into the circular buffer. * Restrict to the amount of space available. * * Return the number of bytes copied. */ unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count) { unsigned int len; if (gb == NULL) return 0; len = gs_buf_space_avail(gb); if (count > len) count = len; if (count == 0) return 0; len = gb->buf_buf + gb->buf_size - gb->buf_put; if (count > len) { memcpy(gb->buf_put, buf, len); memcpy(gb->buf_buf, buf + len, count - len); gb->buf_put = gb->buf_buf + count - len; } else { memcpy(gb->buf_put, buf, count); if (count < len) gb->buf_put += count; else /* count == len */ gb->buf_put = gb->buf_buf; } return count; } /* * gs_buf_get * * Get data from the circular buffer and copy to the given buffer. * Restrict to the amount of data available. * * Return the number of bytes copied. */ unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) { unsigned int len; if (gb == NULL) return 0; len = gs_buf_data_avail(gb); if (count > len) count = len; if (count == 0) return 0; len = gb->buf_buf + gb->buf_size - gb->buf_get; if (count > len) { memcpy(buf, gb->buf_get, len); memcpy(buf + len, gb->buf_buf, count - len); gb->buf_get = gb->buf_buf + count - len; } else { memcpy(buf, gb->buf_get, count); if (count < len) gb->buf_get += count; else /* count == len */ gb->buf_get = gb->buf_buf; } return count; } /* * gs_tiocmget */ static int gs_tiocmget(struct tty_struct *tty, struct file *file) { struct gs_port *port; unsigned int mcr, msr; unsigned int result = 0; struct gs_dev *dev = gs_devices[tty->index]; if (dev == NULL) return -EIO; port = dev->dev_port[0]; if (port == NULL) return -EIO; mutex_lock(&port->mutex_lock); mcr = port->mcr; msr = port->msr; result = ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | ((msr & MSR_CD) ? TIOCM_CD : 0) | ((msr & MSR_RI) ? TIOCM_RI : 0) | ((msr & MSR_DSR) ? TIOCM_DSR : 0) | ((msr & MSR_CTS) ? TIOCM_CTS : 0); mutex_unlock(&port->mutex_lock); return result; } /* * gs_tiocmset */ static int gs_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct gs_port *port; unsigned int mcr; unsigned int msr; struct gs_dev *dev = gs_devices[tty->index]; if (dev == NULL) return -EIO; port = dev->dev_port[0]; if (port == NULL) return -EIO; mcr = port->mcr; msr = port->msr; if (dev->configured != SERIAL_CONFIGURED) return -EIO; set &= TIOCM_DSR | TIOCM_RI | TIOCM_CD | TIOCM_CTS; if (set & TIOCM_DSR) msr |= MSR_DSR; if (set & TIOCM_RI) msr |= MSR_RI; if (set & TIOCM_CD) msr |= MSR_CD; if (set & TIOCM_CTS) msr |= MSR_CTS; clear &= TIOCM_DSR | TIOCM_RI | TIOCM_CD | TIOCM_CTS; if (clear & TIOCM_RI) msr &= ~MSR_RI; if (clear & TIOCM_DSR) msr &= ~MSR_DSR; if (clear & TIOCM_CD) msr &= ~MSR_CD; if (clear & TIOCM_CTS) msr &= ~MSR_CTS; mutex_lock(&port->mutex_lock); port->mcr = mcr; port->msr = msr; if (port->prev_msr != port->msr) { send_notify_data(dev->dev_notify_ep, dev->notify_req); port->prev_msr = port->msr; } mutex_unlock(&port->mutex_lock); return 0; }