option.c revision ab1958905514da3b6c06d61523ebed142a16cc72
158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* 214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs USB Driver for GSM modems 358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> 558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs This driver is free software; you can redistribute it and/or modify 758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs it under the terms of Version 2 of the GNU General Public License as 858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs published by the Free Software Foundation. 958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 1058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org> 1158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 12b3fdab59b8f5d8e42fa339be74cd015dc1a3192fMatthias Urlichs History: see the git log. 13ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs 14ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs Work sponsored by: Sigos GmbH, Germany <info@sigos.de> 15ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs 1614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs This driver exists because the "normal" serial driver doesn't work too well 1714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs with GSM modems. Issues: 1814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs - data loss -- one single Receive URB is not nearly enough 197c1c2f73e00b5d0413399a14b7ab9e80db94926fMatthias Urlichs - nonstandard flow (Option devices) control 2014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs - controlling the baud rate doesn't make sense 2114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs 2214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs This driver is named "option" because the most common device it's 2314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs used for is a PC-Card (with an internal OHCI-USB interface, behind 2414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs which the GSM interface sits), made by Option Inc. 2514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs 2614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs Some of the "one port" devices actually exhibit multiple USB instances 2714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs on the USB bus. This is not a bug, these ports are used for different 2814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs device features. 2958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs*/ 30ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs 31e37de9e0d6591706a76cff63582cbc721c317333Matthias Urlichs#define DRIVER_VERSION "v0.7.1" 3258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" 3314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define DRIVER_DESC "USB Driver for GSM modems" 3458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 3558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/kernel.h> 3658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/jiffies.h> 3758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/errno.h> 3858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/tty.h> 3958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/tty_flip.h> 4058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/module.h> 4158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/usb.h> 42a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h> 4358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 4458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Function prototypes */ 457bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_open(struct usb_serial_port *port, struct file *filp); 467bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_close(struct usb_serial_port *port, struct file *filp); 477bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_startup(struct usb_serial *serial); 487bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_shutdown(struct usb_serial *serial); 497bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_rx_throttle(struct usb_serial_port *port); 507bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_rx_unthrottle(struct usb_serial_port *port); 517bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_write_room(struct usb_serial_port *port); 5258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 537d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb); 5458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 557bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_write(struct usb_serial_port *port, 567bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton const unsigned char *buf, int count); 5758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 587bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_chars_in_buffer(struct usb_serial_port *port); 597bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_ioctl(struct usb_serial_port *port, struct file *file, 607bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton unsigned int cmd, unsigned long arg); 617bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_set_termios(struct usb_serial_port *port, 62606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old); 637bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_break_ctl(struct usb_serial_port *port, int break_state); 647bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_tiocmget(struct usb_serial_port *port, struct file *file); 657bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_tiocmset(struct usb_serial_port *port, struct file *file, 667bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton unsigned int set, unsigned int clear); 677bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_send_setup(struct usb_serial_port *port); 6858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 6958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Vendor and product IDs */ 7014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define OPTION_VENDOR_ID 0x0AF0 7114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define HUAWEI_VENDOR_ID 0x12D1 7214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define AUDIOVOX_VENDOR_ID 0x0F3D 7314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define NOVATELWIRELESS_VENDOR_ID 0x1410 7431fcbb733812bca52e8bee96d62ba56df0fc408bMatthias Urlichs#define ANYDATA_VENDOR_ID 0x16d5 7514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs 7614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define OPTION_PRODUCT_OLD 0x5000 7714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define OPTION_PRODUCT_FUSION 0x6000 7814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define OPTION_PRODUCT_FUSION2 0x6300 7914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define OPTION_PRODUCT_COBRA 0x6500 80e37de9e0d6591706a76cff63582cbc721c317333Matthias Urlichs#define OPTION_PRODUCT_COBRA2 0x6600 8114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define HUAWEI_PRODUCT_E600 0x1001 82ab1958905514da3b6c06d61523ebed142a16cc72Johann Wilhelm#define HUAWEI_PRODUCT_E220 0x1003 8314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define AUDIOVOX_PRODUCT_AIRCARD 0x0112 8414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define NOVATELWIRELESS_PRODUCT_U740 0x1400 8531fcbb733812bca52e8bee96d62ba56df0fc408bMatthias Urlichs#define ANYDATA_PRODUCT_ID 0x6501 8658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 8758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_device_id option_ids[] = { 8858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, 89ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, 90ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, 9114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, 92e37de9e0d6591706a76cff63582cbc721c317333Matthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, 93b6137383bda844a433d65e027502df7b20ba45c2Matthias Urlichs { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, 94ab1958905514da3b6c06d61523ebed142a16cc72Johann Wilhelm { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, 95b6137383bda844a433d65e027502df7b20ba45c2Matthias Urlichs { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, 9614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, 9731fcbb733812bca52e8bee96d62ba56df0fc408bMatthias Urlichs { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, 9814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { } /* Terminating entry */ 9914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs}; 10014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs 10114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsstatic struct usb_device_id option_ids1[] = { 10214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, 10314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, 10414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, 10514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, 106e37de9e0d6591706a76cff63582cbc721c317333Matthias Urlichs { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, 10714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, 108ab1958905514da3b6c06d61523ebed142a16cc72Johann Wilhelm { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, 10914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, 11014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, 11131fcbb733812bca52e8bee96d62ba56df0fc408bMatthias Urlichs { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, 11214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs { } /* Terminating entry */ 11314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs}; 11458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 11558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DEVICE_TABLE(usb, option_ids); 11658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 11758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_driver option_driver = { 11858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs .name = "option", 11958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs .probe = usb_serial_probe, 12058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs .disconnect = usb_serial_disconnect, 12158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs .id_table = option_ids, 122ba9dc657af86d05d2971633e57d1f6f94ed60472Greg Kroah-Hartman .no_dynamic_id = 1, 12358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}; 12458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 125c30fe7f73194650148b58ee80908c1bc38246397Uwe Zeisberger/* The card has three separate interfaces, which the serial driver 12658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs * recognizes separately, thus num_port=1. 12758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs */ 12814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs 12914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsstatic struct usb_serial_driver option_1port_device = { 13014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs .driver = { 13114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs .owner = THIS_MODULE, 13202b2ac5b0370b1157a5a99f2fdf006644b9b86d5Matthias Urlichs .name = "option1", 13314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs }, 13414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs .description = "GSM modem (1-port)", 13514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs .id_table = option_ids1, 136ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .num_interrupt_in = NUM_DONT_CARE, 137ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .num_bulk_in = NUM_DONT_CARE, 138ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .num_bulk_out = NUM_DONT_CARE, 13914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs .num_ports = 1, 140ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .open = option_open, 141ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .close = option_close, 142ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .write = option_write, 143ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .write_room = option_write_room, 144ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .chars_in_buffer = option_chars_in_buffer, 145ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .throttle = option_rx_throttle, 146ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .unthrottle = option_rx_unthrottle, 147ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .ioctl = option_ioctl, 148ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .set_termios = option_set_termios, 149ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .break_ctl = option_break_ctl, 150ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .tiocmget = option_tiocmget, 151ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .tiocmset = option_tiocmset, 152ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .attach = option_startup, 153ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .shutdown = option_shutdown, 154ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs .read_int_callback = option_instat_callback, 15558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}; 15658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 157ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#ifdef CONFIG_USB_DEBUG 15858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic int debug; 159ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#else 160ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define debug 0 161ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#endif 162ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs 16358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* per port private data */ 16458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 165ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define N_IN_URB 4 166ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define N_OUT_URB 1 167b27c73dcab61826e5f1228d69d56f469b0abfc05Matthias Urlichs#define IN_BUFLEN 4096 168ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define OUT_BUFLEN 128 16958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 17058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstruct option_port_private { 17158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Input endpoints and buffer for this port */ 172ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct urb *in_urbs[N_IN_URB]; 173ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs char in_buffer[N_IN_URB][IN_BUFLEN]; 17458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Output endpoints and buffer for this port */ 175ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct urb *out_urbs[N_OUT_URB]; 176ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs char out_buffer[N_OUT_URB][OUT_BUFLEN]; 17758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 17858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Settings for the port */ 179ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int rts_state; /* Handshaking pins (outputs) */ 180ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int dtr_state; 181ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int cts_state; /* Handshaking pins (inputs) */ 182ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int dsr_state; 183ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int dcd_state; 184ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int ri_state; 185ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs 186ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs unsigned long tx_start_time[N_OUT_URB]; 18758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}; 18858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 18958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Functions used by new usb-serial code. */ 1907bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int __init option_init(void) 19158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 19258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int retval; 19314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs retval = usb_serial_register(&option_1port_device); 19414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs if (retval) 19514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs goto failed_1port_device_register; 19658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs retval = usb_register(&option_driver); 19758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (retval) 19858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs goto failed_driver_register; 19958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 20058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs info(DRIVER_DESC ": " DRIVER_VERSION); 20158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 20258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return 0; 20358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 20458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsfailed_driver_register: 20514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs usb_serial_deregister (&option_1port_device); 20614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsfailed_1port_device_register: 20758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return retval; 20858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 20958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2107bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void __exit option_exit(void) 21158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 21258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_deregister (&option_driver); 21314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs usb_serial_deregister (&option_1port_device); 21458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 21558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 21658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_init(option_init); 21758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_exit(option_exit); 21858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2197bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_rx_throttle(struct usb_serial_port *port) 22058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 22158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 22258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 22358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2247bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_rx_unthrottle(struct usb_serial_port *port) 22558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 22658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 22758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 22858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2297bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_break_ctl(struct usb_serial_port *port, int break_state) 23058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 23158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Unfortunately, I don't know how to send a break */ 232ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs dbg("%s", __FUNCTION__); 23358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 23458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2357bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_set_termios(struct usb_serial_port *port, 236606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Cox struct ktermios *old_termios) 23758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 23858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 23958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 24058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs option_send_setup(port); 24158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 24258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2437bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_tiocmget(struct usb_serial_port *port, struct file *file) 24458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 245ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs unsigned int value; 246ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 24758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 24858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 24958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 25058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs value = ((portdata->rts_state) ? TIOCM_RTS : 0) | 25158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs ((portdata->dtr_state) ? TIOCM_DTR : 0) | 25258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs ((portdata->cts_state) ? TIOCM_CTS : 0) | 25358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs ((portdata->dsr_state) ? TIOCM_DSR : 0) | 25458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs ((portdata->dcd_state) ? TIOCM_CAR : 0) | 25558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs ((portdata->ri_state) ? TIOCM_RNG : 0); 25658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 25758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return value; 25858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 25958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2607bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_tiocmset(struct usb_serial_port *port, struct file *file, 2617bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton unsigned int set, unsigned int clear) 26258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 263ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 26458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 26558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 26658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 26758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (set & TIOCM_RTS) 26858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->rts_state = 1; 26958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (set & TIOCM_DTR) 27058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dtr_state = 1; 27158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 27258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (clear & TIOCM_RTS) 27358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->rts_state = 0; 27458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (clear & TIOCM_DTR) 27558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dtr_state = 0; 27658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return option_send_setup(port); 27758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 27858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 2797bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_ioctl(struct usb_serial_port *port, struct file *file, 2807bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton unsigned int cmd, unsigned long arg) 28158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 28258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return -ENOIOCTLCMD; 28358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 28458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 28558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Write */ 2867bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_write(struct usb_serial_port *port, 2877bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton const unsigned char *buf, int count) 28858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 289ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 290ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int i; 291ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int left, todo; 292ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct urb *this_urb = NULL; /* spurious */ 293ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int err; 29458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 29558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 29658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 29758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: write (%d chars)", __FUNCTION__, count); 29858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 29958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs i = 0; 30058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs left = count; 301ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs for (i=0; left > 0 && i < N_OUT_URB; i++) { 30258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs todo = left; 30358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (todo > OUT_BUFLEN) 30458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs todo = OUT_BUFLEN; 30558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 306ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs this_urb = portdata->out_urbs[i]; 307ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs if (this_urb->status == -EINPROGRESS) { 3087bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton if (time_before(jiffies, 3097bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton portdata->tx_start_time[i] + 10 * HZ)) 31058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 31158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_unlink_urb(this_urb); 312ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs continue; 31358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 314ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs if (this_urb->status != 0) 3157bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("usb_write %p failed (err=%d)", 3167bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton this_urb, this_urb->status); 31758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 3187bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: endpoint %d buf %d", __FUNCTION__, 3197bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton usb_pipeendpoint(this_urb->pipe), i); 32058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 321ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs /* send the data */ 32258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs memcpy (this_urb->transfer_buffer, buf, todo); 32358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs this_urb->transfer_buffer_length = todo; 32458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 32558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs this_urb->dev = port->serial->dev; 32658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs err = usb_submit_urb(this_urb, GFP_ATOMIC); 32758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (err) { 3287bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("usb_submit_urb %p (write bulk) failed " 3297bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton "(%d, has %d)", this_urb, 3307bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton err, this_urb->status); 33158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 33258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 33358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->tx_start_time[i] = jiffies; 33458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs buf += todo; 33558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs left -= todo; 33658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 33758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 33858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs count -= left; 33958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: wrote (did %d)", __FUNCTION__, count); 34058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return count; 34158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 34258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 3437d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_indat_callback(struct urb *urb) 34458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 34533f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox int err; 34658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int endpoint; 34758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_serial_port *port; 34858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct tty_struct *tty; 34958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs unsigned char *data = urb->transfer_buffer; 35058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 35158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: %p", __FUNCTION__, urb); 35258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 35358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs endpoint = usb_pipeendpoint(urb->pipe); 35458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = (struct usb_serial_port *) urb->context; 35558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 35658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb->status) { 35758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: nonzero status: %d on endpoint %02x.", 35858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs __FUNCTION__, urb->status, endpoint); 35958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } else { 36058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs tty = port->tty; 36158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb->actual_length) { 36233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox tty_buffer_request_room(tty, urb->actual_length); 36333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox tty_insert_flip_string(tty, data, urb->actual_length); 36458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs tty_flip_buffer_push(tty); 36558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } else { 36658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: empty read urb received", __FUNCTION__); 36758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 36858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 36958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Resubmit urb so we continue receiving */ 37058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (port->open_count && urb->status != -ESHUTDOWN) { 37158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs err = usb_submit_urb(urb, GFP_ATOMIC); 37258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (err) 3737bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton printk(KERN_ERR "%s: resubmit read urb failed. " 3747bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton "(%d)", __FUNCTION__, err); 37558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 37658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 37758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return; 37858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 37958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 3807d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_outdat_callback(struct urb *urb) 38158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 38258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_serial_port *port; 38358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 38458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 38558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 38658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = (struct usb_serial_port *) urb->context; 38758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 388cf2c7481d2ff7f0c266de873b2fe93883e9782f9Pete Zaitcev usb_serial_port_softint(port); 38958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 39058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 3917d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb) 39258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 39358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int err; 39458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 39558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct option_port_private *portdata = usb_get_serial_port_data(port); 39658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_serial *serial = port->serial; 39758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 39858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 39958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); 40058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 40158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb->status == 0) { 40258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_ctrlrequest *req_pkt = 40358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs (struct usb_ctrlrequest *)urb->transfer_buffer; 40458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 40558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (!req_pkt) { 40658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: NULL req_pkt\n", __FUNCTION__); 40758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return; 40858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 4097bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton if ((req_pkt->bRequestType == 0xA1) && 4107bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton (req_pkt->bRequest == 0x20)) { 41158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int old_dcd_state; 41258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs unsigned char signals = *((unsigned char *) 4137bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton urb->transfer_buffer + 4147bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton sizeof(struct usb_ctrlrequest)); 41558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 41658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: signal x%x", __FUNCTION__, signals); 41758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 41858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs old_dcd_state = portdata->dcd_state; 41958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->cts_state = 1; 42058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dcd_state = ((signals & 0x01) ? 1 : 0); 42158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dsr_state = ((signals & 0x02) ? 1 : 0); 42258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->ri_state = ((signals & 0x08) ? 1 : 0); 42358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 4247bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton if (port->tty && !C_CLOCAL(port->tty) && 4257bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton old_dcd_state && !portdata->dcd_state) 42658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs tty_hangup(port->tty); 4277bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton } else { 4287bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: type %x req %x", __FUNCTION__, 4297bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton req_pkt->bRequestType,req_pkt->bRequest); 4307bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton } 43158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } else 43258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: error %d", __FUNCTION__, urb->status); 43358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 43458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Resubmit urb so we continue receiving IRQ data */ 43558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb->status != -ESHUTDOWN) { 43658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb->dev = serial->dev; 43758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs err = usb_submit_urb(urb, GFP_ATOMIC); 43858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (err) 4397bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: resubmit intr urb failed. (%d)", 4407bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton __FUNCTION__, err); 44158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 44258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 44358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 4447bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_write_room(struct usb_serial_port *port) 44558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 44658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct option_port_private *portdata; 44758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int i; 44858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int data_len = 0; 44958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct urb *this_urb; 45058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 45158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 45258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 453ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs for (i=0; i < N_OUT_URB; i++) { 45458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs this_urb = portdata->out_urbs[i]; 45558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (this_urb && this_urb->status != -EINPROGRESS) 45658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs data_len += OUT_BUFLEN; 457ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs } 45858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 45958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: %d", __FUNCTION__, data_len); 46058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return data_len; 46158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 46258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 4637bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_chars_in_buffer(struct usb_serial_port *port) 46458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 46558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct option_port_private *portdata; 46658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int i; 46758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int data_len = 0; 46858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct urb *this_urb; 46958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 47058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 47158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 472ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs for (i=0; i < N_OUT_URB; i++) { 47358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs this_urb = portdata->out_urbs[i]; 47458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (this_urb && this_urb->status == -EINPROGRESS) 47558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs data_len += this_urb->transfer_buffer_length; 476ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs } 47758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: %d", __FUNCTION__, data_len); 47858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return data_len; 47958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 48058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 4817bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_open(struct usb_serial_port *port, struct file *filp) 48258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 483ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 484ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct usb_serial *serial = port->serial; 485ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int i, err; 486ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct urb *urb; 48758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 48858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 48958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 49058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 49158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 49258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Set some sane defaults */ 49358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->rts_state = 1; 49458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dtr_state = 1; 49558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 49658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Reset low level data toggle and start reading from endpoints */ 49758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < N_IN_URB; i++) { 49858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb = portdata->in_urbs[i]; 49958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (! urb) 50058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 50158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb->dev != serial->dev) { 5027bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: dev %p != %p", __FUNCTION__, 5037bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton urb->dev, serial->dev); 50458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 50558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 50658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 5077bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton /* 5087bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton * make sure endpoint data toggle is synchronized with the 5097bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton * device 5107bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton */ 51158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_clear_halt(urb->dev, urb->pipe); 51258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 51358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs err = usb_submit_urb(urb, GFP_KERNEL); 51458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (err) { 5157bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: submit urb %d failed (%d) %d", 5167bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton __FUNCTION__, i, err, 51758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb->transfer_buffer_length); 51858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 51958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 52058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 52158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Reset low level data toggle on out endpoints */ 52258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < N_OUT_URB; i++) { 52358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb = portdata->out_urbs[i]; 52458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (! urb) 52558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 52658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb->dev = serial->dev; 5277bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 5287bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton usb_pipeout(urb->pipe), 0); */ 52958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 53058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 53158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port->tty->low_latency = 1; 53258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 53358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs option_send_setup(port); 53458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 53558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return (0); 53658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 53758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 5387bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic inline void stop_urb(struct urb *urb) 53958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 540242cf670c09c05504ce53dfc27f8331a072f169dGreg Kroah-Hartman if (urb && urb->status == -EINPROGRESS) 54158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_kill_urb(urb); 54258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 54358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 5447bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_close(struct usb_serial_port *port, struct file *filp) 54558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 546ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int i; 547ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct usb_serial *serial = port->serial; 548ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 54958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 55058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 55158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 55258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 55358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->rts_state = 0; 55458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->dtr_state = 0; 55558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 55658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (serial->dev) { 55758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs option_send_setup(port); 55858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 55958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Stop reading/writing urbs */ 56058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < N_IN_URB; i++) 56158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs stop_urb(portdata->in_urbs[i]); 56258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < N_OUT_URB; i++) 56358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs stop_urb(portdata->out_urbs[i]); 56458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 56558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port->tty = NULL; 56658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 56758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 56858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Helper functions used by option_setup_urbs */ 5697bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, 5707bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton int dir, void *ctx, char *buf, int len, 5717d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells void (*callback)(struct urb *)) 57258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 57358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct urb *urb; 57458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 57558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (endpoint == -1) 57658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return NULL; /* endpoint not needed */ 57758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 57858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ 57958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (urb == NULL) { 58058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); 58158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return NULL; 58258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 58358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 58458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Fill URB using supplied data. */ 58558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_fill_bulk_urb(urb, serial->dev, 58658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_sndbulkpipe(serial->dev, endpoint) | dir, 58758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs buf, len, callback, ctx); 58858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 58958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return urb; 59058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 59158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 59258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Setup urbs */ 5937bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_setup_urbs(struct usb_serial *serial) 59458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 59514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs int i,j; 596ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct usb_serial_port *port; 597ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 59858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 59958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 60058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 60114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs for (i = 0; i < serial->num_ports; i++) { 60214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs port = serial->port[i]; 60314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs portdata = usb_get_serial_port_data(port); 60458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 60558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Do indat endpoints first */ 60614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs for (j = 0; j < N_IN_URB; ++j) { 60714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs portdata->in_urbs[j] = option_setup_urb (serial, 60814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs port->bulk_in_endpointAddress, USB_DIR_IN, port, 60914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); 61014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs } 61158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 61214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs /* outdat endpoints */ 61314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs for (j = 0; j < N_OUT_URB; ++j) { 61414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs portdata->out_urbs[j] = option_setup_urb (serial, 61514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs port->bulk_out_endpointAddress, USB_DIR_OUT, port, 61614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); 61714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs } 61858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 61958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 62058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 6217bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_send_setup(struct usb_serial_port *port) 62258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 62358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct usb_serial *serial = port->serial; 62458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs struct option_port_private *portdata; 62558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 62658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 62758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 62858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 62958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 63058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (port->tty) { 63158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs int val = 0; 63258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (portdata->dtr_state) 63358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs val |= 0x01; 63458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (portdata->rts_state) 63558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs val |= 0x02; 63658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 6377bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton return usb_control_msg(serial->dev, 6387bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton usb_rcvctrlpipe(serial->dev, 0), 6397bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); 64058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 64158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 64258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return 0; 64358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 64458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 6457bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_startup(struct usb_serial *serial) 64658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 647ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int i, err; 648ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct usb_serial_port *port; 649ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 65058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 65158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 65258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 65358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Now setup per port private data */ 65458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < serial->num_ports; i++) { 65558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = serial->port[i]; 65680b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); 65758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (!portdata) { 6587bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: kmalloc for option_port_private (%d) failed!.", 6597bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton __FUNCTION__, i); 66058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return (1); 66158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 66258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 66358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_set_serial_port_data(port, portdata); 66458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 66558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (! port->interrupt_in_urb) 66658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs continue; 66758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); 66858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (err) 6697bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton dbg("%s: submit irq_in urb failed %d", 6707bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton __FUNCTION__, err); 67158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 67258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 67358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs option_setup_urbs(serial); 67458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 67558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs return (0); 67658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 67758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 6787bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_shutdown(struct usb_serial *serial) 67958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{ 680ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs int i, j; 681ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct usb_serial_port *port; 682ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs struct option_port_private *portdata; 68358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 68458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs dbg("%s", __FUNCTION__); 68558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 68658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Stop reading/writing urbs */ 68758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < serial->num_ports; ++i) { 68858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = serial->port[i]; 68958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 69058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (j = 0; j < N_IN_URB; j++) 69158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs stop_urb(portdata->in_urbs[j]); 69258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (j = 0; j < N_OUT_URB; j++) 69358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs stop_urb(portdata->out_urbs[j]); 69458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 69558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 69658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Now free them */ 69758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < serial->num_ports; ++i) { 69858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = serial->port[i]; 69958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata = usb_get_serial_port_data(port); 70058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 70158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (j = 0; j < N_IN_URB; j++) { 70258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (portdata->in_urbs[j]) { 70358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_free_urb(portdata->in_urbs[j]); 70458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->in_urbs[j] = NULL; 70558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 70658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 70758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (j = 0; j < N_OUT_URB; j++) { 70858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs if (portdata->out_urbs[j]) { 70958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs usb_free_urb(portdata->out_urbs[j]); 71058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs portdata->out_urbs[j] = NULL; 71158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 71258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 71358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 71458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 71558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs /* Now free per port private data */ 71658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs for (i = 0; i < serial->num_ports; i++) { 71758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs port = serial->port[i]; 71858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs kfree(usb_get_serial_port_data(port)); 71958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs } 72058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs} 72158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 72258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_AUTHOR(DRIVER_AUTHOR); 72358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DESCRIPTION(DRIVER_DESC); 72458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_VERSION(DRIVER_VERSION); 72558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_LICENSE("GPL"); 72658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 727ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#ifdef CONFIG_USB_DEBUG 72858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_param(debug, bool, S_IRUGO | S_IWUSR); 72958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_PARM_DESC(debug, "Debug messages"); 730ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#endif 73158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs 732