1d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* 2d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * This code was developed for the Quatech USB line for linux, it used 3d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * much of the code developed by Greg Kroah-Hartman for USB serial devices 4d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * 5d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 6d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 7d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/errno.h> 8d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/init.h> 9d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/slab.h> 10d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty.h> 11d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_driver.h> 12d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/tty_flip.h> 13d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/module.h> 14d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/serial.h> 15d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb.h> 16d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/usb/serial.h> 17d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#include <linux/uaccess.h> 18d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1990ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool debug; 20d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 21d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* Version Information */ 22d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_VERSION "v2.14" 23d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc" 24d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DRIVER_DESC "Quatech USB to Serial Driver" 25d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 26d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ 27d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU200 0xC030 /* SSU200 */ 28d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100 0xC040 /* DSU100 */ 29d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU200 0xC050 /* DSU200 */ 30d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100 0xC060 /* QSU100 */ 31d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU200 0xC070 /* QSU200 */ 32d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100A 0xC080 /* ESU100A */ 33d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100B 0xC081 /* ESU100B */ 34d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200A 0xC0A0 /* ESU200A */ 35d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU200B 0xC0A1 /* ESU200B */ 36d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100A 0xC090 /* HSU100A */ 37d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100B 0xC091 /* HSU100B */ 38d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100C 0xC092 /* HSU100C */ 39d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU100D 0xC093 /* HSU100D */ 40d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200A 0xC0B0 /* HSU200A */ 41d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200B 0xC0B1 /* HSU200B */ 42d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200C 0xC0B2 /* HSU200C */ 43d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_HSU200D 0xC0B3 /* HSU200D */ 44d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_SSU100_2 0xC120 /* SSU100_2 */ 45d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU100_2 0xC140 /* DSU100_2 */ 46d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_DSU400_2 0xC150 /* DSU400_2 */ 47d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU100_2 0xC160 /* QSU100_2 */ 48d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_QSU400_2 0xC170 /* QSU400_2 */ 49d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU400_2 0xC180 /* ESU400_2 */ 50d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QUATECH_ESU100_2 0xC1A0 /* ESU100_2 */ 51d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 52d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_GET_DEVICE 0xc2 53d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_OPEN_CLOSE_CHANNEL 0xca 54d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc 55d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SET_ATF 0xcd 56d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_REGISTER 0xc0 57d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_GET_SET_UART 0xc1 58d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_HW_FLOW_CONTROL_MASK 0xc5 59d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_MASK 0xc6 60d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_SW_FLOW_CONTROL_DISABLE 0xc7 61d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define QT_BREAK_CONTROL 0xc8 62d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 63d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_IN 0xc0 64d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define USBD_TRANSFER_DIRECTION_OUT 0x40 65d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 66d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MAX_BAUD_RATE 460800 67d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MAX_BAUD_REMAINDER 4608 68d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 69d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DIV_LATCH_LS 0x00 70d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define XMT_HOLD_REGISTER 0x00 71d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define XVR_BUFFER_REGISTER 0x00 72d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DIV_LATCH_MS 0x01 73d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define FIFO_CONTROL_REGISTER 0x02 74d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define LINE_CONTROL_REGISTER 0x03 75d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MODEM_CONTROL_REGISTER 0x04 76d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define LINE_STATUS_REGISTER 0x05 77d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MODEM_STATUS_REGISTER 0x06 78d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 79d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MCR_DTR 0x01 80d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MCR_RTS 0x02 81d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MCR_LOOP 0x10 82d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 83d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_CTS 0x10 84d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_CD 0x80 85d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_RI 0x40 86d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_DSR 0x20 87d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_MASK 0xf0 88d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 89d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_8_DATA 0x03 90d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_7_DATA 0x02 91d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_6_DATA 0x01 92d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_5_DATA 0x00 93d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 94d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_ODD_PARITY 0X08 95d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_EVEN_PARITY 0X18 96d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_TWO_STOPB 0x04 97d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_ONE_STOPB 0x00 98d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 99d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_DIVISOR 0x30 /* gives 9600 baud rate */ 100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DEFAULT_LCR SERIAL_8_DATA /* 8, none , 1 */ 101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define FULLPWRBIT 0x00000080 103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define NEXT_BOARD_POWER_BIT 0x00000004 104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_OE 0x02 106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_PE 0x04 107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_FE 0x08 108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_LSR_BI 0x10 109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_CTS 0x10 111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_CD 0x80 112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_RI 0x40 113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_DSR 0x20 114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define SERIAL_MSR_MASK 0xf0 115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define PREFUFF_LEVEL_CONSERVATIVE 128 117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ATC_DISABLED 0x0 118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RR_BITS 0x03 /* for clearing clock bits */ 120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define DUPMODE_BITS 0xc0 121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define CLKS_X4 0x02 122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define LOOPMODE_BITS 0x41 /* LOOP1 = b6, LOOP0 = b0 (PORT B) */ 124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define ALL_LOOPBACK 0x01 125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define MODEM_CTRL 0x40 126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton#define RS232_MODE 0x00 127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 128a457732b836b970c82c7ba35b4cfc938c9c543f9Németh Mártonstatic const struct usb_device_id serqt_id_table[] = { 129d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)}, 130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)}, 131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU200)}, 132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100)}, 133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU200)}, 134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100A)}, 135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100B)}, 136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200A)}, 137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU200B)}, 138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100A)}, 139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100B)}, 140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100C)}, 141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU100D)}, 142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200A)}, 143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200B)}, 144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200C)}, 145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_HSU200D)}, 146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100_2)}, 147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100_2)}, 148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU400_2)}, 149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU100_2)}, 150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_QSU400_2)}, 151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU400_2)}, 152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_ESU100_2)}, 153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton {} /* Terminating entry */ 154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DEVICE_TABLE(usb, serqt_id_table); 157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_get_device_data { 159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 porta; 160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 portb; 161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 portc; 162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct qt_open_channel_data { 165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 line_status; 166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 modem_status; 167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstruct quatech_port { 170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int port_num; /* number of the port */ 171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct urb *write_urb; /* write URB for this port */ 172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct urb *read_urb; /* read URB for this port */ 173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct urb *int_urb; 174d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 shadowLCR; /* last LCR value received */ 176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 shadowMCR; /* last MCR value received */ 177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 shadowMSR; /* last MSR value received */ 178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 shadowLSR; /* last LSR value received */ 179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton char open_ports; 180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Used for TIOCMIWAIT */ 182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton wait_queue_head_t msr_wait; 183d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton char prev_status, diff_status; 184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton wait_queue_head_t wait; 186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct async_icount icount; 188d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port; /* owner of this object */ 190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_get_device_data DeviceData; 191fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov struct mutex lock; 192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton bool read_urb_busy; 193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int RxHolding; 194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int ReadBulkStopped; 195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton char closePending; 196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_driver serqt_usb_driver = { 199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .name = "quatech-usb-serial", 200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .probe = usb_serial_probe, 201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .disconnect = usb_serial_disconnect, 202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .id_table = serqt_id_table, 203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int port_paranoia_check(struct usb_serial_port *port, 206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton const char *function) 207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!port) { 209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port == NULL", function); 210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -1; 211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!port->serial) { 213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port->serial == NULL\n", function); 214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -1; 215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int serial_paranoia_check(struct usb_serial *serial, 221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton const char *function) 222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) { 224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - serial == NULL\n", function); 225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -1; 226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial->type) { 229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - serial->type == NULL!", function); 230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -1; 231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline struct quatech_port *qt_get_port_private(struct usb_serial_port 237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton *port) 238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return (struct quatech_port *)usb_get_serial_port_data(port); 240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline void qt_set_port_private(struct usb_serial_port *port, 243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *data) 244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_set_serial_port_data(port, (void *)data); 246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial *get_usb_serial(struct usb_serial_port *port, 249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton const char *function) 250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* if no port was specified, or it fails a paranoia check */ 252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!port || 253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port_paranoia_check(port, function) || 254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial_paranoia_check(port->serial, function)) { 255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* 256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * then say that we dont have a valid usb_serial thing, 257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * which will end up genrating -ENODEV return values 258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return NULL; 260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return port->serial; 263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessLineStatus(struct quatech_port *qt_port, 266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char line_status) 267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->shadowLSR = 270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | 271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton SERIAL_LSR_BI); 272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 274d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void ProcessModemStatus(struct quatech_port *qt_port, 276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char modem_status) 277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->shadowMSR = modem_status; 280d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton wake_up_interruptible(&qt_port->wait); 281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 28494362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Coxstatic void ProcessRxChar(struct tty_struct *tty, struct usb_serial_port *port, 28594362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox unsigned char data) 286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 287d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct urb *urb = port->read_urb; 28894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox if (urb->actual_length) 28994362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox tty_insert_flip_char(tty, data, TTY_NORMAL); 290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 291d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 292d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_write_bulk_callback(struct urb *urb) 293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct tty_struct *tty; 295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *quatech_port; 297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = urb->status; 299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status) { 301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("nonzero write bulk status received:%d\n", status); 302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port = urb->context; 306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, quatech_port->port_num); 308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty = tty_port_tty_get(&quatech_port->port->port); 310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (tty) 312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty_wakeup(tty); 313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty_kref_put(tty); 314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_interrupt_callback(struct urb *urb) 317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* FIXME */ 319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_read_bulk_callback(struct urb *urb) 322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = urb->context; 325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port = qt_get_port_private(port); 327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char *data; 328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct tty_struct *tty; 329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int RxCount; 331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int i, result; 332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int flag, flag_data; 333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (urb->status) { 335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->ReadBulkStopped = 1; 336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - nonzero write bulk status received: %d\n", 337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, urb->status); 338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty = tty_port_tty_get(&port->port); 342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!tty) { 343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - bad tty pointer - exiting", __func__); 344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton data = urb->transfer_buffer; 348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton RxCount = urb->actual_length; 350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* index = MINOR(port->tty->device) - serial->minor; */ 352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); 356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port_paranoia_check(port, __func__) != 0) { 358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port_paranoia_check, exiting\n", __func__); 359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->ReadBulkStopped = 1; 360f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton goto exit; 361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 363d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) { 364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - bad serial pointer, exiting\n", __func__); 365f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton goto exit; 366d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (qt_port->closePending == 1) { 368d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Were closing , stop reading */ 369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - (qt_port->closepending == 1\n", __func__); 370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->ReadBulkStopped = 1; 371f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton goto exit; 372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 374d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* 375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * RxHolding is asserted by throttle, if we assert it, we're not 376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * receiving any more characters and let the box handle the flow 377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * control 378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 379d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (qt_port->RxHolding == 1) { 380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->ReadBulkStopped = 1; 381f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton goto exit; 382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 384d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (urb->status) { 385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->ReadBulkStopped = 1; 386d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - nonzero read bulk status received: %d\n", 388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, urb->status); 389f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton goto exit; 390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 392d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (tty && RxCount) { 393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton flag_data = 0; 394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton for (i = 0; i < RxCount; ++i) { 395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Look ahead code here */ 396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if ((i <= (RxCount - 3)) && (data[i] == 0x1b) 397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton && (data[i + 1] == 0x1b)) { 398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton flag = 0; 399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton switch (data[i + 2]) { 400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case 0x00: 401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* line status change 4th byte must follow */ 402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (i > (RxCount - 4)) { 403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("Illegal escape seuences in received data\n"); 404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ProcessLineStatus(qt_port, data[i + 3]); 407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton i += 3; 408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton flag = 1; 409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case 0x01: 412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Modem status status change 4th byte must follow */ 4131695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("Modem status status.\n"); 414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (i > (RxCount - 4)) { 415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("Illegal escape sequences in received data\n"); 416d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ProcessModemStatus(qt_port, 419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton data[i + 3]); 420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton i += 3; 421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton flag = 1; 422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case 0xff: 4241695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("No status sequence.\n"); 425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 42694362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox if (tty) { 42794362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox ProcessRxChar(tty, port, data[i]); 42894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox ProcessRxChar(tty, port, data[i + 1]); 42994362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox } 430d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton i += 2; 431d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 432d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (flag == 1) 434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton continue; 435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 43794362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox if (tty && urb->actual_length) 43894362fd7fbad653c9517efa4aa7cd8fdadd527b1Alan Cox tty_insert_flip_char(tty, data[i], TTY_NORMAL); 439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 440d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 441d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty_flip_buffer_push(tty); 442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Continue trying to always read */ 445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_fill_bulk_urb(port->read_urb, serial->dev, 446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_rcvbulkpipe(serial->dev, 447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->bulk_in_endpointAddress), 448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->read_urb->transfer_buffer, 449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->read_urb->transfer_buffer_length, 450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_read_bulk_callback, port); 451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result) 453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - failed resubmitting read urb, error %d", 454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, result); 455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else { 456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (tty && RxCount) { 457d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty_flip_buffer_push(tty); 458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty_schedule_flip(tty); 459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton schedule_work(&port->work); 463f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonexit: 464f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton tty_kref_put(tty); 465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 466d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 467d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* 468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_get_device 469d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * Issue a GET_DEVICE vendor-specific request on the default control pipe If 470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * successful, fills in the qt_get_device_data structure pointed to by 471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * device_data, otherwise return a negative error number of the problem. 472d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 474d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_get_device(struct usb_serial *serial, 475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_get_device_data *device_data) 476d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char *transfer_buffer; 479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 480d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton transfer_buffer = 481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton kmalloc(sizeof(struct qt_get_device_data), GFP_KERNEL); 482d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!transfer_buffer) 483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENOMEM; 484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_SET_GET_DEVICE, 0xc0, 0, 0, 487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton transfer_buffer, 488d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton sizeof(struct qt_get_device_data), 300); 489d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result > 0) 490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton memcpy(device_data, transfer_buffer, 491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton sizeof(struct qt_get_device_data)); 492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton kfree(transfer_buffer); 493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 494d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 496d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**************************************************************************** 498d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * BoxSetPrebufferLevel 499d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton TELLS BOX WHEN TO ASSERT FLOW CONTROL 500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ****************************************************************************/ 501d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetPrebufferLevel(struct usb_serial *serial) 502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 buffer_length; 505d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton buffer_length = PREFUFF_LEVEL_CONSERVATIVE; 507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 508d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_GET_SET_PREBUF_TRIG_LVL, 0x40, 509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton buffer_length, 0, NULL, 0, 300); 510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**************************************************************************** 514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * BoxSetATC 515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton TELLS BOX WHEN TO ASSERT automatic transmitter control 516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton ****************************************************************************/ 517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetATC(struct usb_serial *serial, __u16 n_Mode) 518d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 buffer_length; 521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton buffer_length = PREFUFF_LEVEL_CONSERVATIVE; 523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 524d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_SET_ATF, 0x40, n_Mode, 0, NULL, 0, 300); 527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/** 532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_set_device 533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * Issue a SET_DEVICE vendor-specific request on the default control pipe If 534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * successful returns the number of bytes written, otherwise it returns a 535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * negative error number of the problem. 536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_set_device(struct usb_serial *serial, 538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_get_device_data *device_data) 539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 540d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 length; 542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 PortSettings; 543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton PortSettings = ((__u16) (device_data->portb)); 545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton PortSettings = (PortSettings << 8); 546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton PortSettings += ((__u16) (device_data->porta)); 547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton length = sizeof(struct qt_get_device_data); 549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings); 550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_SET_GET_DEVICE, 0x40, PortSettings, 553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 0, NULL, 0, 300); 554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_open_channel(struct usb_serial *serial, __u16 Uart_Number, 558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_open_channel_data *pDeviceData) 559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_OPEN_CLOSE_CHANNEL, 564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton USBD_TRANSFER_DIRECTION_IN, 1, Uart_Number, 565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton pDeviceData, 566d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton sizeof(struct qt_open_channel_data), 300); 567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_close_channel(struct usb_serial *serial, __u16 Uart_Number) 573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 575d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 577d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_OPEN_CLOSE_CHANNEL, 578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton USBD_TRANSFER_DIRECTION_OUT, 0, Uart_Number, 579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton NULL, 0, 300); 580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**************************************************************************** 586d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxGetRegister 587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* issuse a GET_REGISTER vendor-spcific request on the default control pipe 588d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* If successful, fills in the pValue with the register value asked for 589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/ 590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number, 591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned short Register_Num, __u8 *pValue) 592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 current_length; 595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton current_length = sizeof(struct qt_get_device_data); 597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_GET_SET_REGISTER, 0xC0, Register_Num, 601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton Uart_Number, (void *)pValue, sizeof(*pValue), 300); 602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/**************************************************************************** 607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* BoxSetRegister 608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* issuse a GET_REGISTER vendor-spcific request on the default control pipe 609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton* If successful, fills in the pValue with the register value asked for 610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton****************************************************************************/ 611d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, 612d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned short Register_Num, unsigned short Value) 613d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 614d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 615d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned short RegAndByte; 616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton RegAndByte = Value; 618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton RegAndByte = RegAndByte << 8; 619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton RegAndByte = RegAndByte + Register_Num; 620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* 622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 623d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_GET_SET_REGISTER, 0xC0, Register_Num, 624d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton Uart_Number, NULL, 0, 300); 625d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton*/ 626d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 627d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 628d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 629d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_GET_SET_REGISTER, 0x40, RegAndByte, Uart_Number, 630d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton NULL, 0, 300); 631d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 632d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 633d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 634d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 635d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* 636d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * qt_setuart 637d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * issuse a SET_UART vendor-spcific request on the default control pipe 638d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * If successful sets baud rate divisor and LCR value 639d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 640d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_setuart(struct usb_serial *serial, unsigned short Uart_Number, 641d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned short default_divisor, unsigned char default_LCR) 642d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 643d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 644d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned short UartNumandLCR; 645d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 646d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton UartNumandLCR = (default_LCR << 8) + Uart_Number; 647d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 648d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 649d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 650d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_GET_SET_UART, 0x40, default_divisor, 651d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton UartNumandLCR, NULL, 0, 300); 652d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 653d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 654d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 655d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 656d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int index, 657d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int bSet) 658d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 659d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 mcr = 0; 660d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u8 msr = 0, MOUT_Value = 0; 661d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int status; 662d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 663d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (bSet == 1) { 664d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* flow control, box will clear RTS line to prevent remote */ 665d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr = SERIAL_MCR_RTS; 666d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } /* device from xmitting more chars */ 667d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else { 668d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* no flow control to remote device */ 669d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr = 0; 670d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 671d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 672d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton MOUT_Value = mcr << 8; 673d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 674d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (bSet == 1) { 675d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* flow control, box will inhibit xmit data if CTS line is 676d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * asserted */ 677d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton msr = SERIAL_MSR_CTS; 678d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } else { 679d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Box will not inhimbe xmit data due to CTS line */ 680d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton msr = 0; 681d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 682d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton MOUT_Value |= msr; 683d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 684d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 685d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 686d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_HW_FLOW_CONTROL_MASK, 0x40, MOUT_Value, 687d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index, NULL, 0, 300); 688d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return status; 689d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 690d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 691d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 692d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 index, 693d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char stop_char, unsigned char start_char) 694d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 695d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __u16 nSWflowout; 696d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 697d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 698d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton nSWflowout = start_char << 8; 699d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton nSWflowout = (unsigned short)stop_char; 700d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 701d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 702d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 703d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_SW_FLOW_CONTROL_MASK, 0x40, nSWflowout, 704d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index, NULL, 0, 300); 705d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 706d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 707d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 708d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 709d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index) 710d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 711d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 712d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 713d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 714d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 715d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_SW_FLOW_CONTROL_DISABLE, 0x40, 0, index, 716d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton NULL, 0, 300); 717d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 718d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 719d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 720d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 721d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_startup(struct usb_serial *serial) 722d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 723d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port; 724d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 725d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_get_device_data DeviceData; 726d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int i; 727d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 728d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 729d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("enterting %s", __func__); 730d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 731d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Now setup per port private data */ 732d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton for (i = 0; i < serial->num_ports; i++) { 733d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port = serial->port[i]; 734d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL); 735d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!qt_port) { 736d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s: kmalloc for quatech_port (%d) failed!.", 737d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, i); 7381695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev for (--i; i >= 0; i--) { 739de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum port = serial->port[i]; 740de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum kfree(usb_get_serial_port_data(port)); 741de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum usb_set_serial_port_data(port, NULL); 742de8f8bd63334fe2014be7d9ab3a81ce9b96e5d19Oliver Neukum } 743d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENOMEM; 744d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 745fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_init(&qt_port->lock); 746d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 747d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_set_serial_port_data(port, qt_port); 748d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 749d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 750d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 751d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = qt_get_device(serial, &DeviceData); 752d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 753d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "box_get_device failed"); 754d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 755d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 756d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 757d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); 758d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 759d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb &= ~FULLPWRBIT; 760d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); 761d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 762d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = qt_set_device(serial, &DeviceData); 763d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 764d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_set_device failed\n"); 765d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 766d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 767d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 768d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = qt_get_device(serial, &DeviceData); 769d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 770d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_get_device failed"); 771d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 772d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 773d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 774d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton switch (serial->dev->descriptor.idProduct) { 775d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_DSU100: 776d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_QSU100: 777d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_ESU100A: 778d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_ESU100B: 779d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU100A: 780d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU100B: 781d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU100C: 782d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU100D: 783d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); 784d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta |= CLKS_X4; 785d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb &= ~(LOOPMODE_BITS); 786d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb |= RS232_MODE; 787d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 788d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 789d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_SSU200: 790d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_DSU200: 791d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_QSU200: 792d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_ESU200A: 793d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_ESU200B: 794d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU200A: 795d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU200B: 796d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU200C: 797d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case QUATECH_HSU200D: 798d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); 799d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta |= CLKS_X4; 800d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb &= ~(LOOPMODE_BITS); 801d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb |= ALL_LOOPBACK; 802d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 803d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton default: 804d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS); 805d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.porta |= CLKS_X4; 806d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb &= ~(LOOPMODE_BITS); 807d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb |= RS232_MODE; 808d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 809d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 810d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 811d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 812d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = BoxSetPrebufferLevel(serial); /* sets to default value */ 813d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 814d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetPrebufferLevel failed\n"); 815d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 816d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 817d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 818d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = BoxSetATC(serial, ATC_DISABLED); 819d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 820d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetATC failed\n"); 821d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 822d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 823d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 824d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); 825d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 826d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton DeviceData.portb |= NEXT_BOARD_POWER_BIT; 827d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); 828d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 829d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = qt_set_device(serial, &DeviceData); 830d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 831d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_set_device failed\n"); 832d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton goto startup_error; 833d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 834d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 835d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("Exit Success %s\n", __func__); 836d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 837d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 838d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 839d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstartup_error: 840d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton for (i = 0; i < serial->num_ports; i++) { 841d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port = serial->port[i]; 842d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 843d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton kfree(qt_port); 844d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_set_serial_port_data(port, NULL); 845d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 846d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 847d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("Exit fail %s\n", __func__); 848d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 849d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -EIO; 850d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 851d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 852d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_release(struct usb_serial *serial) 853d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 854d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port; 855d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 856d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int i; 857d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 858d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("enterting %s", __func__); 859d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 860d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton for (i = 0; i < serial->num_ports; i++) { 861d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port = serial->port[i]; 862d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!port) 863d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton continue; 864d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 865d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = usb_get_serial_port_data(port); 866d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton kfree(qt_port); 867d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_set_serial_port_data(port, NULL); 868d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 869d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 870d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 871d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 87235e2bed559ab80641f1764aae570d92711ddc2faBill Pembertonstatic int qt_open(struct tty_struct *tty, 8732386b331802b1b2664c35f9f4c7aef778aac725fBill Pemberton struct usb_serial_port *port) 874d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 875d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial; 876d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *quatech_port; 877d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *port0; 878d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct qt_open_channel_data ChannelData; 879d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 880d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 881d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 882d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port_paranoia_check(port, __func__)) 883d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 884d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 885d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 886d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 887d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial = port->serial; 888d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 889d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial_paranoia_check(serial, __func__)) 890d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 891d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 892d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port = qt_get_port_private(port); 893d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port0 = qt_get_port_private(serial->port[0]); 894d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 895d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (quatech_port == NULL || port0 == NULL) 896d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 897d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 898d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_clear_halt(serial->dev, port->write_urb->pipe); 899d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_clear_halt(serial->dev, port->read_urb->pipe); 900d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port0->open_ports++; 901d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 902d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = qt_get_device(serial, &port0->DeviceData); 903d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 904d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Port specific setups */ 905d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = qt_open_channel(serial, port->number, &ChannelData); 906d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result < 0) { 907d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_open_channel failed\n"); 908d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 909d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 910d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_open_channel completed.\n"); 911d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 912d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton/* FIXME: are these needed? Does it even do anything useful? */ 913d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->shadowLSR = ChannelData.line_status & 914d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI); 915d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 916d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->shadowMSR = ChannelData.modem_status & 917d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); 918d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 919d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Set Baud rate to default and turn off (default)flow control here */ 920d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR); 921d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result < 0) { 922d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_setuart failed\n"); 923d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 924d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 925d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_setuart completed.\n"); 926d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 927d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* 928bbc9a9916bc1cd997f3bf303e7930d5f3c804d37André Goddard Rosa * Put this here to make it responsive to stty and defaults set by 929d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * the tty layer 930d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 931d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* FIXME: is this needed? */ 932d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* qt_set_termios(tty, port, NULL); */ 933d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 934d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Check to see if we've set up our endpoint info yet */ 935d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port0->open_ports == 1) { 936d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->port[0]->interrupt_in_buffer == NULL) { 937d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* set up interrupt urb */ 938d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_fill_int_urb(serial->port[0]->interrupt_in_urb, 939d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->dev, 940d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_rcvintpipe(serial->dev, 941d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->port[0]->interrupt_in_endpointAddress), 942d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->port[0]->interrupt_in_buffer, 943d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->port[0]-> 944d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton interrupt_in_urb->transfer_buffer_length, 945d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_interrupt_callback, serial, 946d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->port[0]-> 947d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton interrupt_in_urb->interval); 948d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 949d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 950d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_submit_urb(serial->port[0]->interrupt_in_urb, 951d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton GFP_KERNEL); 952d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result) { 953d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dev_err(&port->dev, 954d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton "%s - Error %d submitting " 955d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton "interrupt urb\n", __func__, result); 956d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 957d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 958d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 959d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 960d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 961d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 9621695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("port number is %d\n", port->number); 9631695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("serial number is %d\n", port->serial->minor); 9641695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); 9651695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); 9661695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); 967d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("port's number in the device is %d\n", quatech_port->port_num); 968d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->read_urb = port->read_urb; 969d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 970d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* set up our bulk in urb */ 971d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 972d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_fill_bulk_urb(quatech_port->read_urb, 973d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial->dev, 974d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_rcvbulkpipe(serial->dev, 975d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->bulk_in_endpointAddress), 976d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->bulk_in_buffer, 977d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->read_urb->transfer_buffer_length, 978d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_read_bulk_callback, quatech_port); 979d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 980d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress); 981d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->read_urb_busy = true; 982d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL); 983d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result) { 984d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dev_err(&port->dev, 985d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton "%s - Error %d submitting control urb\n", 986d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, result); 987d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton quatech_port->read_urb_busy = false; 988d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 989d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 990d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* initialize our wait queues */ 991d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton init_waitqueue_head(&quatech_port->wait); 992d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton init_waitqueue_head(&quatech_port->msr_wait); 993d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 994d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* initialize our icount structure */ 995d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton memset(&(quatech_port->icount), 0x00, sizeof(quatech_port->icount)); 996d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 997d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 998d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 999d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1000d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1001d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_chars_in_buffer(struct tty_struct *tty) 1002d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1003d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1004d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial; 1005d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int chars = 0; 1006d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1007d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial = get_usb_serial(port, __func__); 1008d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1009d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1010d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1011d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->num_bulk_out) { 1012d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port->write_urb->status == -EINPROGRESS) 1013d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton chars = port->write_urb->transfer_buffer_length; 1014d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1015d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1016d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - returns %d\n", __func__, chars); 1017d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1018d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return chars; 1019d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1020d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1021d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_block_until_empty(struct tty_struct *tty, 1022d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port) 1023d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1024d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int timeout = HZ / 10; 1025d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int wait = 30; 1026d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int count; 1027d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1028d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton while (1) { 1029d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1030d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton count = qt_chars_in_buffer(tty); 1031d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1032d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (count <= 0) 1033d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1034d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1035d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton interruptible_sleep_on_timeout(&qt_port->wait, timeout); 1036d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1037d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton wait--; 1038d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (wait == 0) { 1039d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - TIMEOUT", __func__); 1040d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1041d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } else { 1042d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton wait = 30; 1043d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1044d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1045d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1046d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1047f3a756883ac028c536479e2eb283477fec80c828Bill Pembertonstatic void qt_close(struct usb_serial_port *port) 1048d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1049d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = port->serial; 1050d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 1051d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *port0; 1052d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton struct tty_struct *tty; 1053d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 1054d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 1055d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 0; 1056d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1057d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1058d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton 1059d9dea3c1c0814a87cc579b425e9776b8ed46b31fBill Pemberton tty = tty_port_tty_get(&port->port); 1060d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 1061d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1062d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 1063d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port0 = qt_get_port_private(serial->port[0]); 1064d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1065d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* shutdown any bulk reads that might be going on */ 1066d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->num_bulk_out) 1067d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_unlink_urb(port->write_urb); 1068d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->num_bulk_in) 1069d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_unlink_urb(port->read_urb); 1070d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1071d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* wait up to for transmitter to empty */ 1072d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->dev) 1073d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_block_until_empty(tty, qt_port); 1074f3a756883ac028c536479e2eb283477fec80c828Bill Pemberton tty_kref_put(tty); 1075d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1076d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Close uart channel */ 1077d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = qt_close_channel(serial, index); 1078d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) 1079d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d qt_close_channel failed.\n", 1080d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, port->number); 1081d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1082d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port0->open_ports--; 1083d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1084d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("qt_num_open_ports in close%d:in port%d\n", 1085d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port0->open_ports, port->number); 1086d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1087d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port0->open_ports == 0) { 1088d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->port[0]->interrupt_in_urb) { 1089d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s", "Shutdown interrupt_in_urb\n"); 1090d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_kill_urb(serial->port[0]->interrupt_in_urb); 1091d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1092d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1093d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1094d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1095d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (qt_port->write_urb) { 1096d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* if this urb had a transfer buffer already (old tx) free it */ 1097ef055f10000c5013d269cac9fc92c200bf314e40Ilia Mirkin kfree(qt_port->write_urb->transfer_buffer); 1098d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_free_urb(qt_port->write_urb); 1099d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1100d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1101d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1102d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1103d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write(struct tty_struct *tty, struct usb_serial_port *port, 1104d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton const unsigned char *buf, int count) 1105d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1106d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int result; 1107d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1108d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1109d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial == NULL) 1110d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 1111d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1112d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1113d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1114d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (count == 0) { 1115d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - write request of 0 bytes\n", __func__); 1116d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1117d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1118d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1119d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* only do something if we have a bulk out endpoint */ 1120d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->num_bulk_out) { 1121d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port->write_urb->status == -EINPROGRESS) { 1122d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - already writing\n", __func__); 1123d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1124d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1125d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1126d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton count = 1127d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (count > port->bulk_out_size) ? port->bulk_out_size : count; 1128d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton memcpy(port->write_urb->transfer_buffer, buf, count); 1129d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1130d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* set up our urb */ 1131d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1132d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_fill_bulk_urb(port->write_urb, serial->dev, 1133d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_sndbulkpipe(serial->dev, 1134d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port-> 1135d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton bulk_out_endpointAddress), 1136d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->write_urb->transfer_buffer, count, 1137d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_write_bulk_callback, port); 1138d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1139d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* send the data out the bulk port */ 1140d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_submit_urb(port->write_urb, GFP_ATOMIC); 1141d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result) 1142d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - failed submitting write urb, error %d\n", 1143d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, result); 1144d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else 1145d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = count; 1146d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1147d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 1148d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1149d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1150d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* no bulk out, so return 0 bytes written */ 1151d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1152d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1153d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1154d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_write_room(struct tty_struct *tty) 1155d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1156d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1157d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial; 1158d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 1159d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1160d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int retval = -EINVAL; 1161d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1162d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port_paranoia_check(port, __func__)) { 1163d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s", "Invalid port\n"); 1164d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -1; 1165d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1166d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1167d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton serial = get_usb_serial(port, __func__); 1168d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1169d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) 1170d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 1171d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1172d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 1173d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1174fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1175d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1176d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1177d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1178d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (serial->num_bulk_out) { 1179d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (port->write_urb->status != -EINPROGRESS) 1180d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton retval = port->bulk_out_size; 1181d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1182d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1183fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1184d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return retval; 1185d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1186d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1187d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 118800a0d0d65b61241a718d0aee96f46b9a2d93bf26Alan Coxstatic int qt_ioctl(struct tty_struct *tty, 1189d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int cmd, unsigned long arg) 1190d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1191d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1192d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port = qt_get_port_private(port); 1193d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1194d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 1195d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1196d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s cmd 0x%04x", __func__, cmd); 1197d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1198d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 1199d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1200d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (cmd == TIOCMIWAIT) { 1201d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton while (qt_port != NULL) { 1202d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton interruptible_sleep_on(&qt_port->msr_wait); 1203d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (signal_pending(current)) 1204d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ERESTARTSYS; 1205d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else { 1206d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton char diff = qt_port->diff_status; 1207d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1208d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (diff == 0) 1209d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -EIO; /* no change => error */ 1210d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1211d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Consume all events */ 1212d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->diff_status = 0; 1213d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1214d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (((arg & TIOCM_RNG) 1215d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton && (diff & SERIAL_MSR_RI)) 1216d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton || ((arg & TIOCM_DSR) 1217d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton && (diff & SERIAL_MSR_DSR)) 1218d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton || ((arg & TIOCM_CD) 1219d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton && (diff & SERIAL_MSR_CD)) 1220d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton || ((arg & TIOCM_CTS) 1221d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton && (diff & SERIAL_MSR_CTS))) { 1222d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1223d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1224d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1225d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1226d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1227d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1228d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1229d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s -No ioctl for that one. port = %d\n", __func__, port->number); 1230d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENOIOCTLCMD; 1231d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1232d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1233d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_set_termios(struct tty_struct *tty, 1234d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port, 1235d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct ktermios *old_termios) 1236d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1237d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct ktermios *termios = tty->termios; 1238d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char new_LCR = 0; 1239d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int cflag = termios->c_cflag; 1240d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 1241d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int baud, divisor, remainder; 1242d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 1243d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1244d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s", __func__); 1245d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1246d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - port->serial->minor; 1247d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1248d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton switch (cflag) { 1249d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case CS5: 1250d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_5_DATA; 1251d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 1252d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case CS6: 1253d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_6_DATA; 1254d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 1255d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case CS7: 1256d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_7_DATA; 1257d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 1258d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton default: 1259d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton case CS8: 1260d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_8_DATA; 1261d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton break; 1262d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1263d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1264d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Parity stuff */ 1265d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (cflag & PARENB) { 1266d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (cflag & PARODD) 1267d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_ODD_PARITY; 1268d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else 1269d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_EVEN_PARITY; 1270d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1271d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (cflag & CSTOPB) 1272d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton new_LCR |= SERIAL_TWO_STOPB; 1273d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else 127435f077dca73132dcac2cac1706417229a68f38c3Roel Kluin new_LCR |= SERIAL_ONE_STOPB; 1275d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1276d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - 4\n", __func__); 1277d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1278d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Thats the LCR stuff, go ahead and set it */ 1279d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton baud = tty_get_baud_rate(tty); 1280d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!baud) 1281d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* pick a default, any default... */ 1282d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton baud = 9600; 1283d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1284d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - got baud = %d\n", __func__, baud); 1285d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1286d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton divisor = MAX_BAUD_RATE / baud; 1287d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton remainder = MAX_BAUD_RATE % baud; 1288d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Round to nearest divisor */ 1289d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (((remainder * 2) >= baud) && (baud != 110)) 1290d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton divisor++; 1291d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1292d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* 1293d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * Set Baud rate to default and turn off (default)flow control here 1294d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 1295d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1296d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR); 1297d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 1298d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "qt_setuart failed\n"); 1299d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1300d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1301d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1302d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Now determine flow control */ 1303d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (cflag & CRTSCTS) { 1304d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - Enabling HW flow control port %d\n", __func__, 1305d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->number); 1306d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1307d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Enable RTS/CTS flow control */ 1308d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = BoxSetHW_FlowCtrl(port->serial, index, 1); 1309d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1310d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 1311d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); 1312d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1313d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1314d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } else { 1315d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Disable RTS/CTS flow control */ 1316d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - disabling HW flow control port %d\n", __func__, 1317d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->number); 1318d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1319d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = BoxSetHW_FlowCtrl(port->serial, index, 0); 1320d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) { 1321d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); 1322d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1323d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1324d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1325d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1326d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1327d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* if we are implementing XON/XOFF, set the start and stop character in 1328d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * the device */ 1329d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (I_IXOFF(tty) || I_IXON(tty)) { 1330d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char stop_char = STOP_CHAR(tty); 1331d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned char start_char = START_CHAR(tty); 1332d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1333d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton BoxSetSW_FlowCtrl(port->serial, index, stop_char, 1334d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton start_char); 1335d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) 1336d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n"); 1337d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1338d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } else { 1339d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* disable SW flow control */ 1340d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = BoxDisable_SW_FlowCtrl(port->serial, index); 1341d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) 1342d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n"); 1343d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1344d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1345d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton tty->termios->c_cflag &= ~CMSPAR; 1346d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* FIXME: Error cases should be returning the actual bits changed only */ 1347d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1348d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1349d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_break(struct tty_struct *tty, int break_state) 1350d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1351d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1352d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1353d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 1354d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton u16 index, onoff; 1355d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int result; 1356d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1357d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 1358d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1359d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 1360d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1361d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (break_state == -1) 1362d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton onoff = 1; 1363d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else 1364d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton onoff = 0; 1365d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1366fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1367d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1368d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1369d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1370d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = 1371d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 1372d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton QT_BREAK_CONTROL, 0x40, onoff, index, NULL, 0, 300); 1373d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1374fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1375d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1376d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1377d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmget(struct tty_struct *tty, 1378d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port, 137960b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox struct usb_serial *serial) 1380d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1381d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1382d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton u8 mcr; 1383d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton u8 msr; 1384d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int result = 0; 1385d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 1386d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 1387d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1388d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d, tty =0x%p\n", __func__, port->number, tty); 1389d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1390d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 1391d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1392d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); 1393d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status >= 0) { 1394d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1395d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton BoxGetRegister(port->serial, index, 1396d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton MODEM_STATUS_REGISTER, &msr); 1397d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1398d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1399d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1400d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status >= 0) { 1401d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = ((mcr & SERIAL_MCR_DTR) ? TIOCM_DTR : 0) 1402d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* DTR IS SET */ 1403d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton | ((mcr & SERIAL_MCR_RTS) ? TIOCM_RTS : 0) 1404d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* RTS IS SET */ 1405d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton | ((msr & SERIAL_MSR_CTS) ? TIOCM_CTS : 0) 1406d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* CTS is set */ 1407d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton | ((msr & SERIAL_MSR_CD) ? TIOCM_CAR : 0) 1408d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Carrier detect is set */ 1409d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton | ((msr & SERIAL_MSR_RI) ? TIOCM_RI : 0) 1410d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Ring indicator set */ 1411d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton | ((msr & SERIAL_MSR_DSR) ? TIOCM_DSR : 0); 1412d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* DSR is set */ 1413d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return result; 1414d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1415d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } else 1416d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ESPIPE; 1417d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1418d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1419d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic inline int qt_real_tiocmset(struct tty_struct *tty, 1420d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port, 1421d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial, 1422d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int value) 1423d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1424d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1425d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton u8 mcr; 1426d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int status; 1427d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int index; 1428d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1429d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1430d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1431d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton index = tty->index - serial->minor; 1432d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1433d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); 1434d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) 1435d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ESPIPE; 1436d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1437d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* 1438d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * Turn off the RTS and DTR and loopbcck and then only turn on what was 1439d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton * asked for 1440d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton */ 1441d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP); 1442d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (value & TIOCM_RTS) 1443d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr |= SERIAL_MCR_RTS; 1444d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (value & TIOCM_DTR) 1445d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr |= SERIAL_MCR_DTR; 1446d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (value & TIOCM_LOOP) 1447d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton mcr |= SERIAL_MCR_LOOP; 1448d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1449d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton status = 1450d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton BoxSetRegister(port->serial, index, MODEM_CONTROL_REGISTER, mcr); 1451d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (status < 0) 1452d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ESPIPE; 1453d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton else 1454d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return 0; 1455d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1456d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 145760b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int qt_tiocmget(struct tty_struct *tty) 1458d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1459d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1460d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1461d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port = qt_get_port_private(port); 1462d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int retval = -ENODEV; 1463d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 14641695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("In %s\n", __func__); 1465d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1466d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) 1467d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 1468d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1469fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1470d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1471d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1472d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); 1473d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 147460b33c133ca0b7c0b6072c87234b63fee6e80558Alan Cox retval = qt_real_tiocmget(tty, port, serial); 1475d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1476fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1477d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return retval; 1478d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1479d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 148020b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int qt_tiocmset(struct tty_struct *tty, 1481d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int set, unsigned int clear) 1482d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1483d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1484d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1485d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1486d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port = qt_get_port_private(port); 1487d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int retval = -ENODEV; 1488d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 14891695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("In %s\n", __func__); 1490d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1491d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) 1492d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return -ENODEV; 1493d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1494fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1495d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 14961695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("%s - port %d\n", __func__, port->number); 1497d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding); 1498d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 149920b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Cox retval = qt_real_tiocmset(tty, port, serial, set); 1500d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1501fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1502d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return retval; 1503d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1504d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1505d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_throttle(struct tty_struct *tty) 1506d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1507d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1508d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1509d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 1510d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1511d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1512d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1513d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) 1514d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1515d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1516d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 1517d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1518fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1519d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1520d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* pass on to the driver specific version of this function */ 1521d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->RxHolding = 1; 1522d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port->RxHolding = 1\n", __func__); 1523d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1524fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1525d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1526d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1527d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1528d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic void qt_unthrottle(struct tty_struct *tty) 1529d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1530d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial_port *port = tty->driver_data; 1531d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct usb_serial *serial = get_usb_serial(port, __func__); 1532d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton struct quatech_port *qt_port; 1533d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton unsigned int result; 1534d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1535d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (!serial) 1536d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1537d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1538d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port = qt_get_port_private(port); 1539d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1540fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_lock(&qt_port->lock); 1541d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1542d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - port %d\n", __func__, port->number); 1543d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1544d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (qt_port->RxHolding == 1) { 1545d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s -qt_port->RxHolding == 1\n", __func__); 1546d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1547d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_port->RxHolding = 0; 1548d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton dbg("%s - qt_port->RxHolding = 0\n", __func__); 1549d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1550d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* if we have a bulk endpoint, start it up */ 1551d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) { 1552d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton /* Start reading from the device */ 1553d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_fill_bulk_urb(port->read_urb, serial->dev, 1554d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton usb_rcvbulkpipe(serial->dev, 1555d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->bulk_in_endpointAddress), 1556d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->read_urb->transfer_buffer, 1557d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton port->read_urb-> 1558d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton transfer_buffer_length, 1559d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton qt_read_bulk_callback, port); 1560d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton result = usb_submit_urb(port->read_urb, GFP_ATOMIC); 1561d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton if (result) 1562d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton err("%s - failed restarting read urb, error %d", 1563d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton __func__, result); 1564d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1565d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton } 1566fa2d8bbb6360ec4bf831802e925d9db06d3c9649Alexey Khoroshilov mutex_unlock(&qt_port->lock); 1567d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return; 1568d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1569d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1570d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1571d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic int qt_calc_num_ports(struct usb_serial *serial) 1572d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton{ 1573d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton int num_ports; 1574d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 15751695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("numberofendpoints: %d\n", 1576d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (int)serial->interface->cur_altsetting->desc.bNumEndpoints); 15771695eb36bf4616c6ec062d2dc2c3abe54d3aa313Ruslan Pisarev dbg("numberofendpoints: %d\n", 1578d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (int)serial->interface->altsetting->desc.bNumEndpoints); 1579d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1580d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton num_ports = 1581d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2; 1582d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1583d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton return num_ports; 1584d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton} 1585d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1586d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonstatic struct usb_serial_driver quatech_device = { 1587d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .driver = { 1588d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .owner = THIS_MODULE, 1589d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .name = "serqt", 1590d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton }, 1591d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .description = DRIVER_DESC, 1592d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .id_table = serqt_id_table, 1593d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .num_ports = 8, 1594d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .open = qt_open, 1595d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .close = qt_close, 1596d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .write = qt_write, 1597d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .write_room = qt_write_room, 1598d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .chars_in_buffer = qt_chars_in_buffer, 1599d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .throttle = qt_throttle, 1600d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .unthrottle = qt_unthrottle, 1601d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .calc_num_ports = qt_calc_num_ports, 1602d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .ioctl = qt_ioctl, 1603d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .set_termios = qt_set_termios, 1604d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .break_ctl = qt_break, 1605d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .tiocmget = qt_tiocmget, 1606d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .tiocmset = qt_tiocmset, 1607d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .attach = qt_startup, 1608d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton .release = qt_release, 1609d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton}; 1610d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 161169276a33bd1d272dc9c3bd577038954811bd1831Alan Sternstatic struct usb_serial_driver * const serial_drivers[] = { 161269276a33bd1d272dc9c3bd577038954811bd1831Alan Stern &quatech_device, NULL 161369276a33bd1d272dc9c3bd577038954811bd1831Alan Stern}; 161469276a33bd1d272dc9c3bd577038954811bd1831Alan Stern 1615e42f85f3d410a5457a2db61d883437ac9e32ceccGreg Kroah-Hartmanmodule_usb_serial_driver(serqt_usb_driver, serial_drivers); 1616d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1617d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_AUTHOR(DRIVER_AUTHOR); 1618d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_DESCRIPTION(DRIVER_DESC); 1619d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_LICENSE("GPL"); 1620d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pemberton 1621d75662e164d5175c5e5f9339ff4d6f6980613d96Bill Pembertonmodule_param(debug, bool, S_IRUGO | S_IWUSR); 1622d75662e164d5175c5e5f9339ff4d6f6980613d96Bill PembertonMODULE_PARM_DESC(debug, "Debug enabled or not"); 1623