aboutsummaryrefslogtreecommitdiffstats
path: root/bad
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2007-01-04 16:55:20 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2007-01-04 16:55:20 -0800
commita88452c7db70791f9febf76174c4c928c903444e (patch)
tree97a60640b4b18692acde21e3e185cb819518ef4a /bad
parentaa79741c8ee7af51c5ca9e47387154f260b745c3 (diff)
downloadpatches-a88452c7db70791f9febf76174c4c928c903444e.tar.gz
add a few more patches
Diffstat (limited to 'bad')
-rw-r--r--bad/usb-serial-serqt_usb.patch3034
1 files changed, 3034 insertions, 0 deletions
diff --git a/bad/usb-serial-serqt_usb.patch b/bad/usb-serial-serqt_usb.patch
new file mode 100644
index 00000000000000..1fd0227afac139
--- /dev/null
+++ b/bad/usb-serial-serqt_usb.patch
@@ -0,0 +1,3034 @@
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Subject: USB: add USB serial Quatech driver
+
+Add support for all Quatech usb to serial devices.
+
+Based on an original driver from Quatech.
+
+Cleaned up and forward ported by me.
+
+(yes, I know it still doesn't follow coding standard, and it doesn't use
+the usb-serial layer, but I'm still fixing it up...)
+
+Cc: Tim Gobeli <tgobeli@quatech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/Kconfig | 10
+ drivers/usb/serial/Makefile | 1
+ drivers/usb/serial/serqt_usb.c | 2981 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 2992 insertions(+)
+
+--- gregkh-2.6.orig/drivers/usb/serial/Kconfig
++++ gregkh-2.6/drivers/usb/serial/Kconfig
+@@ -464,6 +464,16 @@ config USB_SERIAL_PL2303
+ To compile this driver as a module, choose M here: the
+ module will be called pl2303.
+
++config USB_SERIAL_QUATECH_ESU100
++ tristate "USB Quatech ESU-100 8 Port Serial Driver"
++ depends on USB_SERIAL
++ help
++ Say Y here if you want to use the Quatech ESU-100 8 port usb to
++ serial adapter.
++
++ To compile this driver as a module, choose M here: the
++ module will be called serqt_usb.
++
+ config USB_SERIAL_HP4X
+ tristate "USB HP4x Calculators support"
+ depends on USB_SERIAL
+--- gregkh-2.6.orig/drivers/usb/serial/Makefile
++++ gregkh-2.6/drivers/usb/serial/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_USB_SERIAL_NAVMAN) += nav
+ obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
+ obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
+ obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
++obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb.o
+ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
+ obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
+ obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
+--- /dev/null
++++ gregkh-2.6/drivers/usb/serial/serqt_usb.c
+@@ -0,0 +1,2981 @@
++/*
++ * This code was developed for the Quatech USB line for linux, it used
++ * much of the code developed by Greg Kroah-Hartman for USB serial devices
++ *
++ */
++
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/module.h>
++#include <linux/usb.h>
++#include <linux/wait.h>
++#include <linux/types.h>
++#include <linux/version.h>
++
++#include <asm/uaccess.h>
++
++/* Use our own dbg macro */
++//#define DEBUG_ON
++//#undef dbg
++#ifdef DEBUG_ON
++ #define mydbg(const...) printk(const)
++#else
++ #define mydbg(const...)
++#endif
++
++
++/* parity check flag */
++#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
++
++
++#define SERIAL_TTY_MAJOR 0 /* Nice legal number now */
++#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
++#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
++#define PREFUFF_LEVEL_CONSERVATIVE 128
++#define ATC_DISABLED 0x00
++
++#define RR_BITS 0x03 //for clearing clock bits
++#define DUPMODE_BITS 0xc0
++
++#define RS232_MODE 0x00
++#define RTSCTS_TO_CONNECTOR 0x40
++#define CLKS_X4 0x02 ///
++
++#define LOOPMODE_BITS 0x41 //LOOP1 = b6, LOOP0 = b0 (PORT B)
++#define ALL_LOOPBACK 0x01
++#define MODEM_CTRL 0x40
++
++
++#define THISCHAR data[i]
++#define NEXTCHAR data[i + 1]
++#define THIRDCHAR data[i + 2]
++#define FOURTHCHAR data[i + 3]
++
++//*************************************************
++// Useful defintions for port A, Port B and Port C
++#define FULLPWRBIT 0x00000080
++#define NEXT_BOARD_POWER_BIT 0x00000004
++
++
++#define SERIAL_LSR_OE 0x02
++#define SERIAL_LSR_PE 0x04
++#define SERIAL_LSR_FE 0x08
++#define SERIAL_LSR_BI 0x10
++
++#define SERIAL_LSR_TEMT 0x40
++
++#define DIV_LATCH_LS 0x00
++#define XMT_HOLD_REGISTER 0x00
++#define XVR_BUFFER_REGISTER 0x00
++#define DIV_LATCH_MS 0x01
++#define FIFO_CONTROL_REGISTER 0x02
++#define LINE_CONTROL_REGISTER 0x03
++#define MODEM_CONTROL_REGISTER 0x04
++#define LINE_STATUS_REGISTER 0x05
++#define MODEM_STATUS_REGISTER 0x06
++
++
++#define SERIAL_MCR_DTR 0x01
++#define SERIAL_MCR_RTS 0x02
++#define SERIAL_MCR_LOOP 0x10
++
++#define SERIAL_MSR_CTS 0x10
++#define SERIAL_MSR_CD 0x80
++#define SERIAL_MSR_RI 0x40
++#define SERIAL_MSR_DSR 0x20
++#define SERIAL_MSR_MASK 0xf0
++
++#define SERIAL_8_DATA 0x03
++#define SERIAL_7_DATA 0x02
++#define SERIAL_6_DATA 0x01
++#define SERIAL_5_DATA 0x00
++
++#define SERIAL_ODD_PARITY 0X08
++#define SERIAL_EVEN_PARITY 0X18
++#define SERIAL_TWO_STOPB 0x04
++#define SERIAL_ONE_STOPB 0x00
++
++#define MAX_BAUD_RATE 460800
++#define MAX_BAUD_REMAINDER 4608
++
++
++#define QT_SET_GET_DEVICE 0xc2
++#define QT_OPEN_CLOSE_CHANNEL 0xca
++#define QT_GET_SET_PREBUF_TRIG_LVL 0xcc
++#define QT_SET_ATF 0xcd
++#define QT_GET_SET_REGISTER 0xc0
++#define QT_GET_SET_UART 0xc1
++#define QT_HW_FLOW_CONTROL_MASK 0xc5
++#define QT_SW_FLOW_CONTROL_MASK 0xc6
++#define QT_SW_FLOW_CONTROL_DISABLE 0xc7
++#define QT_BREAK_CONTROL 0xc8
++
++#define SERIALQT_PCI_IOC_MAGIC 'k'
++#define SERIALQT_WRITE_QOPR _IOW(SERIALQT_PCI_IOC_MAGIC, 0, int)
++#define SERIALQT_WRITE_QMCR _IOW(SERIALQT_PCI_IOC_MAGIC, 1, int)
++#define SERIALQT_GET_NUMOF_UNITS _IOR(SERIALQT_PCI_IOC_MAGIC, 2, void *)
++#define SERIALQT_GET_THIS_UNIT _IOR(SERIALQT_PCI_IOC_MAGIC, 3, void *)
++#define SERIALQT_READ_QOPR _IOR(SERIALQT_PCI_IOC_MAGIC, 4, int)
++#define SERIALQT_READ_QMCR _IOR(SERIALQT_PCI_IOC_MAGIC, 5, int)
++#define SERIALQT_IS422_EXTENDED _IOR(SERIALQT_PCI_IOC_MAGIC, 6, int) //returns successful if 422 extended
++
++
++#define USBD_TRANSFER_DIRECTION_IN 0xc0
++#define USBD_TRANSFER_DIRECTION_OUT 0x40
++
++#define ATC_DISABLED 0x00
++#define ATC_RTS_ENABLED 0x02
++#define ATC_DTR_ENABLED 0x01
++
++#define RR_BITS 0x03 //for clearing clock bits
++#define DUPMODE_BITS 0xc0
++
++#define FULL_DUPLEX 0x00
++#define HALF_DUPLEX_RTS 0x40
++#define HALF_DUPLEX_DTR 0x80
++
++#define QMCR_FULL_DUPLEX 0x00
++#define QMCR_HALF_DUPLEX_RTS 0x02
++#define QMCR_HALF_DUPLEX_DTR 0x01
++#define QMCR_HALF_DUPLEX_MASK 0x03
++#define QMCR_CONNECTOR_MASK 0x1C
++
++#define QMCR_RX_EN_MASK 0x20
++
++#define QMCR_ALL_LOOPBACK 0x10
++#define QMCR_MODEM_CONTROL 0X00
++
++
++
++#define SERIALQT_IOC_MAXNR 6
++
++struct usb_serial_port {
++ struct usb_serial *serial; /* pointer back to the owner of this port */
++ struct tty_struct * tty; /* the coresponding tty for this port */
++ unsigned char number;
++ char active; /* someone has this device open */
++
++ unsigned char * interrupt_in_buffer;
++ struct urb * interrupt_in_urb;
++ __u8 interrupt_in_endpointAddress;
++
++ unsigned char * bulk_in_buffer;
++ unsigned char * xfer_to_tty_buffer;
++ struct urb * read_urb;
++ __u8 bulk_in_endpointAddress;
++
++ unsigned char * bulk_out_buffer;
++ int bulk_out_size;
++ struct urb * write_urb;
++ __u8 bulk_out_endpointAddress;
++
++ wait_queue_head_t write_wait;
++ wait_queue_head_t wait;
++ struct work_struct work;
++
++ int open_count; /* number of times this port has been opened */
++ struct semaphore sem; /* locks this structure */
++
++ __u8 shadowLCR; /* last LCR value received */
++ __u8 shadowMCR; /* last MCR value received */
++ __u8 shadowMSR; /* last MSR value received */
++ __u8 shadowLSR; /* last LSR value received */
++ int RxHolding;
++ char closePending;
++ int ReadBulkStopped;
++
++ void * private; /* data private to the specific port */
++};
++
++struct identity {
++ int index;
++ int n_identity;
++};
++
++struct usb_serial {
++ struct usb_device * dev;
++ struct usb_interface * interface; /* the interface for this device */
++ struct tty_driver * tty_driver; /* the tty_driver for this device */
++ unsigned char minor; /* the starting minor number for this device */
++ unsigned char num_ports; /* the number of ports this device has */
++ char num_interrupt_in; /* number of interrupt in endpoints we have */
++ char num_bulk_in; /* number of bulk in endpoints we have */
++ char num_bulk_out; /* number of bulk out endpoints we have */
++ unsigned char num_OpenCount; /* the number of ports this device has */
++
++
++ __u16 vendor; /* vendor id of this device */
++ __u16 product; /* product id of this device */
++ struct usb_serial_port port[MAX_NUM_PORTS];
++
++ void * private; /* data private to the specific driver */
++};
++
++
++
++static inline int port_paranoia_check (struct usb_serial_port *port, const char *function)
++{
++ if (!port) {
++ dbg("%s - port == NULL", function);
++ return -1;
++ }
++ if (!port->serial) {
++ dbg("%s - port->serial == NULL\n", function);
++ return -1;
++ }
++ if (!port->tty) {
++ dbg("%s - port->tty == NULL\n", function);
++ return -1;
++ }
++
++ return 0;
++}
++
++
++/* Inline functions to check the sanity of a pointer that is passed to us */
++static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
++{
++ if (!serial) {
++ dbg("%s - serial == NULL\n", function);
++ return -1;
++ }
++
++ return 0;
++}
++
++
++static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function)
++{
++ /* if no port was specified, or it fails a paranoia check */
++ if (!port ||
++ port_paranoia_check (port, function) ||
++ serial_paranoia_check (port->serial, function)) {
++ /* then say that we dont have a valid usb_serial thing, which will
++ * end up genrating -ENODEV return values */
++ return NULL;
++ }
++
++ return port->serial;
++}
++
++
++struct qt_get_device_data
++{
++ __u8 porta;
++ __u8 portb;
++ __u8 portc;
++};
++
++struct qt_open_channel_data
++{
++ __u8 line_status;
++ __u8 modem_status;
++};
++
++static void ProcessLineStatus(struct usb_serial_port *port, unsigned char line_status);
++static void ProcessModemStatus(struct usb_serial_port *port, unsigned char modem_status);
++static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data);
++static struct usb_serial *get_free_serial (int num_ports, int *minor);
++
++
++static int serqt_probe(struct usb_interface *interface,
++ const struct usb_device_id *id);
++
++
++static void serqt_usb_disconnect(struct usb_interface *interface);
++static int box_set_device(struct usb_serial *serial, struct qt_get_device_data *pDeviceData);
++static int box_get_device(struct usb_serial *serial, struct qt_get_device_data *pDeviceData);
++static int serial_open (struct tty_struct *tty, struct file * filp);
++static void serial_close(struct tty_struct *tty, struct file * filp);
++static int serial_write_room (struct tty_struct *tty);
++static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
++static void serial_set_termios (struct tty_struct *tty, struct ktermios * old);
++static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count);
++
++static void serial_throttle (struct tty_struct * tty);
++static void serial_unthrottle (struct tty_struct * tty);
++static void serial_break (struct tty_struct *tty, int break_state);
++static int serial_chars_in_buffer (struct tty_struct *tty);
++static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data);
++
++static int qt_open (struct usb_serial_port *port, struct file *filp);
++static int BoxSetPrebufferLevel(struct usb_serial *serial);
++
++static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode);
++static int BoxSetUart(struct usb_serial *serial, unsigned short Uart_Number, unsigned short default_divisor, unsigned char default_LCR );
++
++
++static int BoxOPenCloseChannel(struct usb_serial *serial, __u16 Uart_Number, __u16 OpenClose, struct qt_open_channel_data *pDeviceData);
++static void qt_close (struct usb_serial_port *port, struct file * filp);
++static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number,unsigned short Register_Num, __u8 *pValue);
++static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number, unsigned short Register_Num, unsigned short Value );
++static void qt_write_bulk_callback(struct urb *urb);
++static int qt_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
++static void port_softint(struct work_struct *work);
++static int qt_write_room (struct usb_serial_port *port);
++static int qt_chars_in_buffer (struct usb_serial_port *port);
++static int qt_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
++static void qt_set_termios(struct usb_serial_port *port, struct ktermios *old_termios);
++static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int UartNumber, int bSet);
++static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber);
++static int EmulateWriteQMCR_Reg(int index, unsigned uc_value);
++static int EmulateReadQMCR_Reg(int index, unsigned *uc_value);
++static struct usb_serial *find_the_box(unsigned int index);
++int ioctl_serial_usb (struct inode *innod, struct file *filp, unsigned int cmd, unsigned long arg);
++
++
++static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 Uart, unsigned char stop_char, unsigned char start_char);
++static void qt_read_bulk_callback(struct urb *urb);
++
++static void port_sofrint(void *private);
++
++static void return_serial(struct usb_serial *serial);
++
++
++static int serial_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
++static int serial_tiocmget(struct tty_struct *tty, struct file *file);
++
++
++
++static int qt_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int value);
++
++static int qt_tiocmget(struct usb_serial_port *port, struct file * file);
++
++
++
++/* Version Information */
++#define DRIVER_VERSION "v2.14"
++#define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc"
++#define DRIVER_DESC "Quatech USB to Serial Driver"
++
++#define USB_VENDOR_ID_QUATECH 0x061d // Quatech VID
++#define DEVICE_ID_QUATECH_RS232_SINGLE_PORT 0xC020 //SSU100
++#define DEVICE_ID_QUATECH_RS422_SINGLE_PORT 0xC030 //SSU200
++#define DEVICE_ID_QUATECH_RS232_DUAL_PORT 0xC040 //DSU100
++#define DEVICE_ID_QUATECH_RS422_DUAL_PORT 0xC050 //DSU200
++#define DEVICE_ID_QUATECH_RS232_FOUR_PORT 0xC060 //QSU100
++#define DEVICE_ID_QUATECH_RS422_FOUR_PORT 0xC070 //QSU200
++#define DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A 0xC080 //ESU100A
++#define DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B 0xC081 //ESU100B
++#define DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A 0xC0A0 //ESU200A
++#define DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B 0xC0A1 //ESU200B
++#define DEVICE_ID_QUATECH_RS232_16_PORT_A 0xC090 //HSU100A
++#define DEVICE_ID_QUATECH_RS232_16_PORT_B 0xC091 //HSU100B
++#define DEVICE_ID_QUATECH_RS232_16_PORT_C 0xC092 //HSU100C
++#define DEVICE_ID_QUATECH_RS232_16_PORT_D 0xC093 //HSU100D
++#define DEVICE_ID_QUATECH_RS422_16_PORT_A 0xC0B0 //HSU200A
++#define DEVICE_ID_QUATECH_RS422_16_PORT_B 0xC0B1 //HSU200B
++#define DEVICE_ID_QUATECH_RS422_16_PORT_C 0xC0B2 //HSU200C
++#define DEVICE_ID_QUATECH_RS422_16_PORT_D 0xC0B3 //HSU200D
++
++
++/* table of Quatech devices */
++static struct usb_device_id serqt_table [] = {
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_SINGLE_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_SINGLE_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_DUAL_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_DUAL_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_FOUR_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_FOUR_PORT)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_A)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_B)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_C)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS232_16_PORT_D)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_A)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_B)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_C)},
++ { USB_DEVICE(USB_VENDOR_ID_QUATECH, DEVICE_ID_QUATECH_RS422_16_PORT_D)},
++ {} /* Terminating entry */
++};
++MODULE_DEVICE_TABLE(usb, serqt_table);
++
++static int major_number;
++static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
++
++
++/* table of Quatech 422devices */
++static unsigned int serqt_422_table[] = {
++ DEVICE_ID_QUATECH_RS422_SINGLE_PORT,
++ DEVICE_ID_QUATECH_RS422_DUAL_PORT,
++ DEVICE_ID_QUATECH_RS422_FOUR_PORT,
++ DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A,
++ DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B,
++ DEVICE_ID_QUATECH_RS422_16_PORT_A,
++ DEVICE_ID_QUATECH_RS422_16_PORT_B,
++ DEVICE_ID_QUATECH_RS422_16_PORT_C,
++ DEVICE_ID_QUATECH_RS422_16_PORT_D,
++ 0 /* terminate with zero */
++};
++
++
++
++/* usb specific object needed to register this driver with the usb subsystem */
++static struct usb_driver serqt_usb_driver = {
++ .name = "quatech-usb-serial",
++ .probe = serqt_probe,
++ .disconnect = serqt_usb_disconnect,
++ .id_table = serqt_table,
++};
++
++static struct ktermios *serial_termios[SERIAL_TTY_MINORS];
++static struct ktermios *serial_termios_locked[SERIAL_TTY_MINORS];
++
++static struct tty_driver serial_tty_driver = {
++ .magic = TTY_DRIVER_MAGIC,
++ .driver_name = "Quatech usb-serial",
++ .name = "ttyQT_USB",
++ .major = SERIAL_TTY_MAJOR,
++ .minor_start = 0,
++ .num = SERIAL_TTY_MINORS,
++ .type = TTY_DRIVER_TYPE_SERIAL,
++ .subtype = SERIAL_TYPE_NORMAL,
++ .flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,
++
++ .termios = serial_termios,
++ .termios_locked = serial_termios_locked,
++ .tiocmset = serial_tiocmset,
++ .tiocmget = serial_tiocmget,
++ .init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL,
++
++ .init_termios.c_iflag = ICRNL | IXON,
++ .init_termios.c_oflag = OPOST,
++
++ .init_termios.c_lflag= ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN,
++
++
++
++
++ .open = serial_open,
++ .close = serial_close,
++ .write = serial_write,
++ .write_room = serial_write_room,
++ .ioctl = serial_ioctl,
++ .set_termios = serial_set_termios,
++ .throttle = serial_throttle,
++ .unthrottle = serial_unthrottle,
++ .break_ctl = serial_break,
++ .chars_in_buffer = serial_chars_in_buffer,
++ .read_proc = serial_read_proc,
++};
++
++//fops for parent device
++struct file_operations serialqt_usb_fops = {
++ .ioctl = ioctl_serial_usb,
++
++};
++
++
++ /**
++ * serqt_probe
++ *
++ * Called by the usb core when a new device is connected that it thinks
++ * this driver might be interested in.
++ *
++ */
++static int serqt_probe(struct usb_interface *interface,
++ const struct usb_device_id *id)
++{
++ struct usb_device *dev = interface_to_usbdev(interface);
++ struct usb_serial *serial = NULL;
++ struct usb_serial_port *port;
++ struct usb_endpoint_descriptor *endpoint;
++ struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
++ struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
++ struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
++ int minor;
++ int buffer_size;
++ int i;
++ struct usb_host_interface *iface_desc;
++ int num_interrupt_in = 0;
++ int num_bulk_in = 0;
++ int num_bulk_out = 0;
++ int num_ports;
++ struct qt_get_device_data DeviceData;
++ int status;
++
++ mydbg("In %s\n", __FUNCTION__);
++
++ /* let's find the endpoints needed */
++ /* check out the endpoints */
++ iface_desc = interface->cur_altsetting;;
++ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
++ {
++ endpoint = &iface_desc->endpoint[i].desc;
++
++ if ((endpoint->bEndpointAddress & 0x80) &&
++ ((endpoint->bmAttributes & 3) == 0x02))
++ {
++ /* we found a bulk in endpoint */
++ mydbg("found bulk in");
++ bulk_in_endpoint[num_bulk_in] = endpoint;
++ ++num_bulk_in;
++ }
++
++ if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
++ ((endpoint->bmAttributes & 3) == 0x02))
++ {
++ /* we found a bulk out endpoint */
++ mydbg("found bulk out\n");
++ bulk_out_endpoint[num_bulk_out] = endpoint;
++ ++num_bulk_out;
++ }
++
++ if ((endpoint->bEndpointAddress & 0x80) &&
++ ((endpoint->bmAttributes & 3) == 0x03))
++ {
++ /* we found a interrupt in endpoint */
++ mydbg("found interrupt in\n");
++ interrupt_in_endpoint[num_interrupt_in] = endpoint;
++ ++num_interrupt_in;
++ }
++ }
++
++ /* found all that we need */
++ info("Quatech converter detected");
++ num_ports = num_bulk_out;
++ if (num_ports == 0)
++ {
++ err("Quatech device with no bulk out, not allowed.");
++ return -ENODEV;
++
++ }
++
++ serial = get_free_serial (num_ports, &minor);
++ if (serial == NULL)
++ {
++ err("No more free serial devices");
++ return -ENODEV;
++ }
++
++ serial->dev = dev;
++ serial->interface = interface;
++ serial->minor = minor;
++ serial->num_ports = num_ports;
++ serial->num_bulk_in = num_bulk_in;
++ serial->num_bulk_out = num_bulk_out;
++ serial->num_interrupt_in = num_interrupt_in;
++ serial->vendor = dev->descriptor.idVendor;
++ serial->product = dev->descriptor.idProduct;
++
++
++ /* set up the endpoint information */
++ for (i = 0; i < num_bulk_in; ++i)
++ {
++ endpoint = bulk_in_endpoint[i];
++ port = &serial->port[i];
++ port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
++ if (!port->read_urb)
++ {
++ err("No free urbs available");
++ goto probe_error;
++ }
++ buffer_size = endpoint->wMaxPacketSize;
++ port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
++ port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
++ port->xfer_to_tty_buffer = kmalloc (buffer_size, GFP_KERNEL);
++ if (!port->bulk_in_buffer)
++ {
++ err("Couldn't allocate bulk_in_buffer");
++ goto probe_error;
++ }
++ usb_fill_bulk_urb (port->read_urb, dev,
++ usb_rcvbulkpipe (dev,
++ endpoint->bEndpointAddress),
++ port->bulk_in_buffer, buffer_size,
++ qt_read_bulk_callback,
++ port);
++ }
++
++ for (i = 0; i < num_bulk_out; ++i)
++ {
++ endpoint = bulk_out_endpoint[i];
++ port = &serial->port[i];
++ port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
++ if (!port->write_urb)
++ {
++ err("No free urbs available");
++ goto probe_error;
++ }
++ buffer_size = endpoint->wMaxPacketSize;
++ port->bulk_out_size = buffer_size;
++ port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
++ port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
++ if (!port->bulk_out_buffer)
++ {
++ err("Couldn't allocate bulk_out_buffer");
++ goto probe_error;
++ }
++ usb_fill_bulk_urb (port->write_urb, dev,
++ usb_sndbulkpipe (dev,
++ endpoint->bEndpointAddress),
++ port->bulk_out_buffer, buffer_size,
++ qt_write_bulk_callback,
++ port);
++
++
++ }
++
++ //For us numb of bulkin or out = number of ports
++
++ mydbg("%s - setting up %d port structures for this device\n", __FUNCTION__, num_bulk_in);
++ for (i = 0; i < num_bulk_in; ++i)
++ {
++ port = &serial->port[i];
++ port->number = i + serial->minor;
++ port->serial = serial;
++
++ INIT_WORK(&port->work, port_softint);
++
++ init_MUTEX (&port->sem);
++
++
++
++ }
++ status = box_get_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_get_device failed");
++ goto probe_error;
++ }
++
++ mydbg(__FILE__"DeviceData.portb = 0x%x",DeviceData.portb);
++
++ DeviceData.portb &= ~FULLPWRBIT;
++ mydbg(__FILE__"Changing DeviceData.portb to 0x%x",DeviceData.portb);
++
++ status = box_set_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_set_device failed\n");
++ goto probe_error;
++ }
++
++
++
++ /* initialize the devfs nodes for this device and let the user know what ports we are bound to */
++ for (i = 0; i < serial->num_ports; ++i)
++ {
++ info("Converter now attached to ttyUSB%d (or usb/tts/%d for devfs)",
++ serial->port[i].number, serial->port[i].number);
++ }
++
++ //usb_serial_console_init (debug, minor);
++
++ ///***********TAG add start next board here ****///
++ status = box_get_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_get_device failed");
++ goto probe_error;
++ }
++
++ //*****************and before we power up lets initialiaze parnent device stuff here before
++ //*****************we set thmem via any other method such as the property pages
++ switch (serial->product)
++ {
++ case DEVICE_ID_QUATECH_RS232_SINGLE_PORT:
++ case DEVICE_ID_QUATECH_RS232_DUAL_PORT:
++ case DEVICE_ID_QUATECH_RS232_FOUR_PORT:
++ case DEVICE_ID_QUATECH_RS232_EIGHT_PORT_A:
++ case DEVICE_ID_QUATECH_RS232_EIGHT_PORT_B:
++ case DEVICE_ID_QUATECH_RS232_16_PORT_A:
++ case DEVICE_ID_QUATECH_RS232_16_PORT_B:
++ case DEVICE_ID_QUATECH_RS232_16_PORT_C:
++ case DEVICE_ID_QUATECH_RS232_16_PORT_D:
++ DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++ DeviceData.porta |= CLKS_X4;
++ DeviceData.portb &= ~(LOOPMODE_BITS);
++ DeviceData.portb |= RS232_MODE;
++ break;
++
++
++ case DEVICE_ID_QUATECH_RS422_SINGLE_PORT:
++ case DEVICE_ID_QUATECH_RS422_DUAL_PORT:
++ case DEVICE_ID_QUATECH_RS422_FOUR_PORT:
++ case DEVICE_ID_QUATECH_RS422_EIGHT_PORT_A:
++ case DEVICE_ID_QUATECH_RS422_EIGHT_PORT_B:
++ case DEVICE_ID_QUATECH_RS422_16_PORT_A:
++ case DEVICE_ID_QUATECH_RS422_16_PORT_B:
++ case DEVICE_ID_QUATECH_RS422_16_PORT_C:
++ case DEVICE_ID_QUATECH_RS422_16_PORT_D:
++ DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++ DeviceData.porta |= CLKS_X4;
++ DeviceData.portb &= ~(LOOPMODE_BITS);
++ DeviceData.portb |= ALL_LOOPBACK;
++ break;
++ default:
++ DeviceData.porta &= ~(RR_BITS | DUPMODE_BITS);
++ DeviceData.porta |= CLKS_X4;
++ DeviceData.portb &= ~(LOOPMODE_BITS);
++ DeviceData.portb |= RS232_MODE;
++ break;
++
++ }
++ status = BoxSetPrebufferLevel(serial); //sets to default vaue
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetPrebufferLevel failed\n");
++ goto probe_error;
++ }
++
++ status = BoxSetATC(serial, ATC_DISABLED);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetATC failed\n");
++ goto probe_error;
++ }
++ //****************************************************************************
++ mydbg(__FILE__"DeviceData.portb = 0x%x",DeviceData.portb);
++
++ DeviceData.portb |= NEXT_BOARD_POWER_BIT;
++ mydbg(__FILE__"Changing DeviceData.portb to 0x%x",DeviceData.portb);
++
++ status = box_set_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_set_device failed\n");
++ goto probe_error;
++ }
++
++
++ mydbg("Exit Success %s\n", __FUNCTION__);
++
++ usb_set_intfdata (interface, serial);
++ return 0;
++
++
++
++ probe_error:
++
++ for (i = 0; i < num_bulk_in; ++i)
++ {
++ port = &serial->port[i];
++ if (port->read_urb)
++ usb_free_urb (port->read_urb);
++ if (port->bulk_in_buffer)
++ kfree (port->bulk_in_buffer);
++ }
++ for (i = 0; i < num_bulk_out; ++i)
++ {
++ port = &serial->port[i];
++ if (port->write_urb)
++ usb_free_urb (port->write_urb);
++ if (port->bulk_out_buffer)
++ kfree (port->bulk_out_buffer);
++
++ if (port->xfer_to_tty_buffer)
++ kfree (port->xfer_to_tty_buffer);
++ }
++ for (i = 0; i < num_interrupt_in; ++i)
++ {
++ port = &serial->port[i];
++ if (port->interrupt_in_urb)
++ usb_free_urb (port->interrupt_in_urb);
++ if (port->interrupt_in_buffer)
++ kfree (port->interrupt_in_buffer);
++ }
++
++
++ /* return the minor range that this device had */
++ return_serial (serial);
++ mydbg("Exit fail %s\n", __FUNCTION__);
++
++ /* free up any memory that we allocated */
++ kfree (serial);
++ return -EIO;
++}
++
++
++
++
++
++
++//returns the serial_table array pointers that are taken
++//up in consecutive positions for each port to a common usb_serial structure
++//back to NULL
++static void return_serial(struct usb_serial *serial)
++{
++ int i;
++
++ mydbg("%s\n", __FUNCTION__);
++
++ if (serial == NULL)
++ return;
++
++ for (i = 0; i < serial->num_ports; ++i)
++ {
++ serial_table[serial->minor + i] = NULL;
++ }
++
++ return;
++}
++
++//Finds the first locatio int the serial_table array where it can fit
++//num_ports number of consecutive points to a common usb_serial structure
++//,allocates a stucture points to it in all the structures, and returns the index
++//to the first location in the array in the "minor" variable.
++
++static struct usb_serial *get_free_serial (int num_ports, int *minor)
++{
++ struct usb_serial *serial = NULL;
++ int i, j;
++ int good_spot;
++
++ mydbg("%s %d\n", __FUNCTION__, num_ports);
++
++ *minor = 0;
++ for (i = 0; i < SERIAL_TTY_MINORS; ++i)
++ {
++ if (serial_table[i])
++ continue;
++
++ good_spot = 1;
++ //find a spot in the array where you can fit consecutive positions
++ //to put the pointers to the usb_serail allocated structure for all
++ //the minor numbers (ie. ports)
++ for (j = 1; j <= num_ports-1; ++j)
++ if (serial_table[i+j])
++ good_spot = 0;
++ if (good_spot == 0)
++ continue;
++
++ if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL)))
++ {
++ err("%s - Out of memory", __FUNCTION__);
++ return NULL;
++ }
++ memset(serial, 0, sizeof(struct usb_serial));
++ serial_table[i] = serial;
++ *minor = i;
++ mydbg("%s - minor base = %d\n", __FUNCTION__, *minor);
++ //copy in the pointer into the array starting a the *minor position
++ //*minor is the index into the array
++ for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
++ serial_table[i] = serial;
++ return serial;
++ }
++ return NULL;
++}
++
++static int flip_that( struct tty_struct *tty, __u16 UartNumber, struct usb_serial *serial)
++{
++ tty_flip_buffer_push(tty);
++ tty_schedule_flip(tty);
++ return 0;
++}
++
++//Handles processing and moving data to the tty layer
++static void port_sofrint(void *private)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *)private;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ struct tty_struct *tty = port->tty;
++ unsigned char *data = port->read_urb->transfer_buffer;
++ unsigned int UartNumber;
++ struct urb *urb = port->read_urb;
++ unsigned int RxCount = urb->actual_length;
++ int i, result;
++ int flag, flag_data;
++
++ //UartNumber = MINOR(port->tty->device) - serial->minor;
++ UartNumber = tty->index - serial->minor;
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++ mydbg ("%s - port->RxHolding = %d\n", __FUNCTION__, port->RxHolding);
++
++ if (port_paranoia_check (port, __FUNCTION__) != 0) {
++ mydbg("%s - port_paranoia_check, exiting\n", __FUNCTION__);
++ port->ReadBulkStopped = 1;
++ return;
++ }
++
++ if (!serial) {
++ mydbg("%s - bad serial pointer, exiting\n", __FUNCTION__);
++ return;
++ }
++ if (port->closePending == 1) //Were closing , stop reading
++ {
++ mydbg("%s - (port->closepending == 1\n", __FUNCTION__);
++ port->ReadBulkStopped = 1;
++ return;
++ }
++
++ //RxHolding is asserted by throttle, if we assert it, we're not receiving any more
++ //characters and let the box handle the flow control
++ if (port->RxHolding == 1) {
++ port->ReadBulkStopped = 1;
++ return;
++ }
++
++ if (urb->status) {
++ port->ReadBulkStopped = 1;
++
++ mydbg("%s - nonzero read bulk status received: %d\n", __FUNCTION__, urb->status);
++ return;
++ }
++
++
++ tty = port->tty;
++ mydbg("%s - port %d, tty =0x%p\n", __FUNCTION__, port->number, tty);
++
++
++ if (tty && RxCount) {
++ flag_data = 0;
++ for (i = 0; i < RxCount ; ++i) {
++ //Look ahead code here
++
++ if ((i <= (RxCount - 3)) && (THISCHAR == 0x1b) && (NEXTCHAR == 0x1b)) {
++ flag = 0;
++ switch (THIRDCHAR) {
++ case 0x00:
++ //Line status change 4th byte must follow
++ if (i > (RxCount - 4)) {
++ mydbg("Illegal escape sequences in received data\n");
++ break;
++ }
++ ProcessLineStatus(port, FOURTHCHAR);
++ i += 3;
++ flag = 1;
++ break;
++
++ case 0x01:
++ //Modem status status change 4th byte must follow
++ mydbg("Modem status status. \n");
++
++ if (i > (RxCount - 4)) {
++ mydbg("Illegal escape sequences in received data\n");
++ break;
++ }
++ ProcessModemStatus(port, FOURTHCHAR);
++ i += 3;
++ flag = 1;
++ break;
++ case 0xff:
++ mydbg("No status sequence. \n");
++
++ ProcessRxChar(port, THISCHAR);
++ ProcessRxChar(port, NEXTCHAR);
++ i += 2;
++ break;
++
++ }//end switch
++ if (flag == 1)
++ continue;
++ } //endif
++
++ if(tty && urb->actual_length) {
++ tty_buffer_request_room(tty, 1);
++ tty_insert_flip_string(tty, (data + i), 1);
++ }
++
++
++ }//endfor
++
++ tty_flip_buffer_push(tty);
++
++ }//endif
++
++ /* Continue trying to always read */
++ usb_fill_bulk_urb (port->read_urb, serial->dev,
++ usb_rcvbulkpipe (serial->dev,
++ port->bulk_in_endpointAddress),
++ port->read_urb->transfer_buffer,
++ port->read_urb->transfer_buffer_length,
++ qt_read_bulk_callback, port);
++ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
++ if (result)
++ mydbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++ else
++ {
++ if (tty && RxCount)
++ flip_that(tty, UartNumber, serial);
++ }
++
++
++ return;
++
++ }
++
++
++
++static void qt_read_bulk_callback(struct urb *urb)
++{
++
++ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++
++
++ if (urb->status)
++ {
++
++ port->ReadBulkStopped = 1;
++ mydbg("%s - nonzero write bulk status received: %d\n", __FUNCTION__, urb->status);
++ return;
++ }
++
++ port_sofrint((void *) port);
++ schedule_work(&port->work);
++}
++
++
++static void ProcessRxChar(struct usb_serial_port *port, unsigned char Data){
++ struct tty_struct *tty;
++ struct urb *urb = port->read_urb;
++ tty = port->tty;
++ /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
++
++ if(tty && urb->actual_length)
++ {
++ tty_buffer_request_room(tty, 1);
++ tty_insert_flip_string(tty, &Data, 1);
++ //tty_flip_buffer_push(tty);
++
++
++ }
++
++ return;
++}
++
++static void ProcessLineStatus(struct usb_serial_port *port, unsigned char line_status){
++
++ port->shadowLSR = line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE |
++ SERIAL_LSR_BI);
++ return;
++}
++
++
++static void ProcessModemStatus(struct usb_serial_port *port, unsigned char modem_status){
++
++ port->shadowMSR = modem_status;
++ wake_up_interruptible(&port->wait);
++ return;
++}
++
++
++
++
++
++
++static void serqt_usb_disconnect(struct usb_interface *interface){
++ struct usb_serial *serial = usb_get_intfdata (interface);
++ //struct device *dev = &interface->dev;
++ struct usb_serial_port *port;
++ int i;
++
++ mydbg ("%s\n", __FUNCTION__);
++ if (serial)
++ {
++
++ serial->dev = NULL;
++
++ for (i = 0; i < serial->num_ports; ++i)
++ serial->port[i].open_count = 0;
++
++ for (i = 0; i < serial->num_bulk_in; ++i)
++ {
++ port = &serial->port[i];
++ if (port->read_urb)
++ {
++ usb_unlink_urb (port->read_urb);
++ usb_free_urb (port->read_urb);
++ }
++ if (port->bulk_in_buffer)
++ kfree (port->bulk_in_buffer);
++ }
++ for (i = 0; i < serial->num_bulk_out; ++i)
++ {
++ port = &serial->port[i];
++ if (port->write_urb)
++ {
++ usb_unlink_urb (port->write_urb);
++ usb_free_urb (port->write_urb);
++ }
++ if (port->bulk_out_buffer)
++ kfree (port->bulk_out_buffer);
++ }
++ for (i = 0; i < serial->num_interrupt_in; ++i)
++ {
++ port = &serial->port[i];
++ if (port->interrupt_in_urb)
++ {
++ usb_unlink_urb (port->interrupt_in_urb);
++ usb_free_urb (port->interrupt_in_urb);
++ }
++ if (port->interrupt_in_buffer)
++ kfree (port->interrupt_in_buffer);
++ }
++
++
++ /* return the minor range that this device had */
++ return_serial (serial);
++
++ /* free up any memory that we allocated */
++ kfree (serial);
++
++
++
++ } else
++ {
++ info("device disconnected");
++ }
++
++
++}
++
++
++
++
++
++
++
++static struct usb_serial *get_serial_by_minor (unsigned int minor)
++{
++ return serial_table[minor];
++}
++
++/*****************************************************************************
++ * Driver tty interface functions
++ *****************************************************************************/
++static int serial_open (struct tty_struct *tty, struct file * filp){
++ struct usb_serial *serial;
++ struct usb_serial_port *port;
++ unsigned int portNumber;
++ int retval = 0;
++
++ mydbg("%s\n", __FUNCTION__);
++
++ /* initialize the pointer incase something fails */
++ tty->driver_data = NULL;
++
++ /* get the serial object associated with this tty pointer */
++ //serial = get_serial_by_minor (MINOR(tty->device));
++
++ /* get the serial object associated with this tty pointer */
++ serial = get_serial_by_minor(tty->index);
++
++
++ if (serial_paranoia_check (serial, __FUNCTION__))
++ return -ENODEV;
++
++
++ /* set up our port structure making the tty driver remember our port object, and us it */
++ portNumber = tty->index - serial->minor;
++ port = &serial->port[portNumber];
++ tty->driver_data = port;
++
++ down (&port->sem);
++ port->tty = tty;
++
++
++ ++port->open_count;
++ if (port->open_count == 1)
++ {
++ port->closePending = 0;
++ mydbg("%s port->closepending = 0\n", __FUNCTION__);
++
++ port->RxHolding = 0;
++ mydbg("%s port->RxHolding = 0\n", __FUNCTION__);
++
++ retval = qt_open(port, filp);
++ }
++
++ if (retval)
++ {
++ port->open_count = 0;
++ }
++ mydbg("%s returning port->closePending = %d\n", __FUNCTION__, port->closePending);
++
++ up (&port->sem);
++ return retval;
++}
++/*****************************************************************************
++ *device's specific driver functions
++ *****************************************************************************/
++static int qt_open (struct usb_serial_port *port, struct file *filp){
++ struct usb_serial *serial = port->serial;
++ int result = 0;
++ unsigned int UartNumber;
++ struct qt_get_device_data DeviceData;
++ struct qt_open_channel_data ChannelData;
++ unsigned short default_divisor = 0x30; //gives 9600 baud rate
++ unsigned char default_LCR = SERIAL_8_DATA; // 8, none , 1
++ int status = 0;
++
++
++
++
++ if (port_paranoia_check (port, __FUNCTION__))
++ return -ENODEV;
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ /* force low_latency on so that our tty_push actually forces the data through,
++ otherwise it is scheduled, and with high data rates (like with OHCI) data
++ can get lost. */
++ if (port->tty)
++ port->tty->low_latency = 0;
++
++
++ UartNumber = port->tty->index - serial->minor;
++
++ status = box_get_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_get_device failed\n");
++ return status;
++ }
++ serial->num_OpenCount++;
++ mydbg("%s serial->num_OpenCount = %d\n", __FUNCTION__, serial->num_OpenCount);
++ //Open uart channel
++
++ //Port specific setups
++ status = BoxOPenCloseChannel(serial, UartNumber, 1, &ChannelData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxOPenCloseChannel failed\n");
++ return status;
++ }
++ mydbg(__FILE__"BoxOPenCloseChannel completed.\n");
++
++ port->shadowLSR = ChannelData.line_status &
++ (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE | SERIAL_LSR_BI);
++
++ port->shadowMSR = ChannelData.modem_status &
++ (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD);
++
++
++ //Set Baud rate to default and turn off (default)flow control here
++ status = BoxSetUart(serial, UartNumber, default_divisor, default_LCR);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetUart failed\n");
++ return status;
++ }
++ mydbg(__FILE__"BoxSetUart completed.\n");
++
++
++ //Put this here to make it responsive to stty and defauls set by the tty layer
++ qt_set_termios(port, NULL);
++
++
++ //Initialize the wait que head
++ init_waitqueue_head(&(port->wait));
++
++ /* if we have a bulk endpoint, start reading from it */
++ if (serial->num_bulk_in)
++ {
++ /* Start reading from the device */
++ usb_fill_bulk_urb (port->read_urb, serial->dev,
++ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
++ port->read_urb->transfer_buffer,
++ port->read_urb->transfer_buffer_length,
++ qt_read_bulk_callback,
++ port);
++
++ port->ReadBulkStopped = 0;
++
++ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
++
++ if (result)
++ {
++ err("%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
++ port->ReadBulkStopped = 1;
++ }
++
++ }
++
++ return result;
++}
++
++static void serial_close(struct tty_struct *tty, struct file * filp){
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++
++ if (!serial)
++ return;
++
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ /* if disconnect beat us to the punch here, there's nothing to do */
++ if (tty->driver_data)
++ {
++ if (!port->open_count)
++ {
++ mydbg ("%s - port not opened\n", __FUNCTION__);
++ goto exit;
++ }
++
++ --port->open_count;
++ if (port->open_count <= 0)
++ {
++ port->closePending = 1;
++ mydbg ("%s - port->closePending = 1\n", __FUNCTION__);
++
++ if (serial->dev)
++ {
++ qt_close(port, filp);
++ port->open_count = 0;
++ }
++ }
++
++ }
++
++ exit:
++ up (&port->sem);
++
++ mydbg("%s - %d return\n", __FUNCTION__, port->number);
++
++
++}
++
++static void qt_close (struct usb_serial_port *port, struct file *filp){
++ unsigned long jift = jiffies + 10 * HZ;
++ __u8 LSR_Value, MCR_Value;
++ struct usb_serial *serial = port->serial;
++ int status;
++ unsigned int UartNumber;
++
++ struct qt_open_channel_data ChannelData;
++ status = 0;
++ LSR_Value = 0;
++
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++ UartNumber = port->tty->index - serial->minor;
++
++ /* shutdown any bulk reads that might be going on */
++ if (serial->num_bulk_out)
++ usb_unlink_urb (port->write_urb);
++ if (serial->num_bulk_in)
++ usb_unlink_urb (port->read_urb);
++
++
++ //wait up to 30 seconds for transmitter to empty
++ do
++ {
++ status = BoxGetRegister(serial, UartNumber, LINE_STATUS_REGISTER, &LSR_Value);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_get_device failed\n");
++ break;
++ }
++
++ if ((LSR_Value & SERIAL_LSR_TEMT) && (port->ReadBulkStopped == 1))
++ break;
++ schedule();
++
++
++ }
++ while (jiffies <= jift);
++
++ if(jiffies > jift)
++ mydbg("%s - port %d timout of checking transmitter empty\n", __FUNCTION__, port->number);
++ else
++ mydbg("%s - port %d checking transmitter empty succeded\n", __FUNCTION__, port->number);
++
++
++
++ status = BoxGetRegister(serial, UartNumber, MODEM_CONTROL_REGISTER, &MCR_Value);
++ mydbg(__FILE__"BoxGetRegister MCR = 0x%x.\n", MCR_Value);
++
++
++ if (status >= 0)
++ {
++ MCR_Value &= ~(SERIAL_MCR_DTR | SERIAL_MCR_RTS);
++// status = BoxSetRegister(serial, UartNumber, MODEM_CONTROL_REGISTER, MCR_Value);
++ }
++
++
++ //Close uart channel
++ status = BoxOPenCloseChannel(serial, UartNumber, 0, &ChannelData);
++ if(status < 0)
++ mydbg("%s - port %d BoxOPenCloseChannel failed.\n", __FUNCTION__, port->number);
++
++ serial->num_OpenCount--;
++
++
++}
++
++
++
++static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial;
++ int retval = -EINVAL;
++ unsigned int UartNumber;
++ int from_user = 0;
++
++
++ serial = get_usb_serial (port, __FUNCTION__);
++ if(serial == NULL)
++ return -ENODEV;
++ //This can happen if we get disconnected a
++ if (port->open_count == 0)
++ {
++ return -ENODEV;
++ }
++ UartNumber = port->tty->index - serial->minor;
++
++ mydbg("%s - port %d, %d byte(s)\n", __FUNCTION__, port->number, count);
++ mydbg("%s - port->RxHolding = %d\n", __FUNCTION__, port->RxHolding);
++
++ if (!port->open_count)
++ {
++ mydbg("%s - port not opened\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_write(port, from_user, buf, count);
++
++ exit:
++ return retval;
++}
++
++
++static int qt_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){
++ int result;
++ unsigned int UartNumber;
++
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ if(serial == NULL)
++ return -ENODEV;
++
++
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (count == 0)
++ {
++ mydbg("%s - write request of 0 bytes\n", __FUNCTION__);
++ return(0);
++ }
++
++
++ UartNumber = port->tty->index - serial->minor;
++ /* only do something if we have a bulk out endpoint */
++ if (serial->num_bulk_out)
++ {
++ if (port->write_urb->status == -EINPROGRESS)
++ {
++ mydbg("%s - already writing\n", __FUNCTION__);
++ return(0);
++ }
++
++ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
++
++ if (from_user)
++ {
++ if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
++ return -EFAULT;
++ } else
++ {
++ memcpy (port->write_urb->transfer_buffer, buf, count);
++ }
++
++ //usb_serial_debug_data(__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
++
++ /* set up our urb */
++
++
++ usb_fill_bulk_urb (port->write_urb, serial->dev,
++ usb_sndbulkpipe (serial->dev,
++ port->bulk_out_endpointAddress),
++ port->write_urb->transfer_buffer, count,
++ qt_write_bulk_callback, port);
++
++
++
++
++
++ /* send the data out the bulk port */
++ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
++ if (result)
++ mydbg("%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
++ else
++ result = count;
++
++ return result;
++ }
++
++ /* no bulk out, so return 0 bytes written */
++ return(0);
++}
++
++
++
++static void qt_write_bulk_callback(struct urb *urb)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!serial)
++ {
++ mydbg("%s - bad serial pointer, exiting\n", __FUNCTION__);
++ return;
++ }
++
++ if (urb->status)
++ {
++ mydbg("%s - nonzero write bulk status received: %d\n", __FUNCTION__, urb->status);
++ return;
++ }
++ //
++ port_softint(&port->work);
++ schedule_work(&port->work);
++
++ return;
++}
++
++
++static void port_softint(struct work_struct *work)
++{
++ struct usb_serial_port *port =
++ container_of(work, struct usb_serial_port, work);
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ struct tty_struct *tty;
++
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++
++
++ if (!serial)
++ return;
++
++
++ tty = port->tty;
++ if (!tty)
++ return;
++
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
++ {
++ mydbg("%s - write wakeup call.\n", __FUNCTION__);
++ (tty->ldisc.write_wakeup)(tty);
++ }
++
++ wake_up_interruptible(&tty->write_wait);
++}
++static int serial_write_room (struct tty_struct *tty)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ int retval = -EINVAL;
++
++ if (!serial)
++ return -ENODEV;
++
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!port->open_count)
++ {
++ mydbg("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_write_room(port);
++
++ exit:
++ up (&port->sem);
++ return retval;
++}
++static int qt_write_room (struct usb_serial_port *port)
++{
++ struct usb_serial *serial = port->serial;
++ int room = 0;
++ if (port->closePending == 1)
++ {
++ mydbg("%s - port->closePending == 1\n", __FUNCTION__);
++ return -ENODEV;
++ }
++
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (serial->num_bulk_out)
++ {
++ if (port->write_urb->status != -EINPROGRESS)
++ room = port->bulk_out_size;
++ }
++
++ mydbg("%s - returns %d\n", __FUNCTION__, room);
++ return(room);
++}
++static int serial_chars_in_buffer (struct tty_struct *tty)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ int retval = -EINVAL;
++
++ if (!serial)
++ return -ENODEV;
++
++ down (&port->sem);
++
++ mydbg("%s = port %d\n", __FUNCTION__, port->number);
++
++ if (!port->open_count) {
++ mydbg("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_chars_in_buffer(port);
++
++exit:
++ up (&port->sem);
++ return retval;
++}
++
++
++
++static int qt_chars_in_buffer (struct usb_serial_port *port)
++{
++ struct usb_serial *serial = port->serial;
++ int chars = 0;
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (serial->num_bulk_out)
++ {
++ if (port->write_urb->status == -EINPROGRESS)
++ chars = port->write_urb->transfer_buffer_length;
++ }
++
++ mydbg("%s - returns %d\n", __FUNCTION__, chars);
++ return(chars);
++}
++
++
++static int serial_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear)
++{
++
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ int retval = -ENODEV;
++ unsigned int UartNumber;
++ mydbg("In %s \n", __FUNCTION__);
++
++ if (!serial)
++ return -ENODEV;
++
++
++ UartNumber = port->tty->index - serial->minor;
++
++
++ down (&port->sem);
++
++ mydbg("%s - port %d \n", __FUNCTION__, port->number);
++ mydbg ("%s - port->RxHolding = %d\n", __FUNCTION__, port->RxHolding);
++
++ if (!port->open_count)
++ {
++ mydbg ("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_tiocmset(port, file, set);
++
++ exit:
++ up (&port->sem);
++ return retval;
++}
++
++
++static int qt_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int value)
++{
++
++ __u8 MCR_Value;
++ int status;
++ unsigned int UartNumber;
++
++
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ if(serial == NULL)
++ return -ENODEV;
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ /**************************************************************************************/
++ /** TIOCMGET
++ */
++ UartNumber = port->tty->index - serial->minor;
++ status = BoxGetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, &MCR_Value);
++ if (status < 0)
++ return -ESPIPE;
++
++ //Turn off the RTS and DTR and loopbcck and then only
++ //trun on what was asked for
++ MCR_Value &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP);
++ if (value & TIOCM_RTS)
++ MCR_Value |= SERIAL_MCR_RTS;
++ if (value & TIOCM_DTR)
++ MCR_Value |= SERIAL_MCR_DTR;
++ if (value & TIOCM_LOOP)
++ MCR_Value |= SERIAL_MCR_LOOP;
++
++ status = BoxSetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, MCR_Value);
++ if (status < 0)
++ return -ESPIPE;
++ else
++ return 0;
++}
++
++static int serial_tiocmget(struct tty_struct *tty, struct file *file)
++{
++
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ int retval = -ENODEV;
++ unsigned int UartNumber;
++ mydbg("In %s \n", __FUNCTION__);
++
++ if (!serial)
++ return -ENODEV;
++
++
++ UartNumber = port->tty->index - serial->minor;
++
++
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++ mydbg ("%s - port->RxHolding = %d\n", __FUNCTION__, port->RxHolding);
++
++ if (!port->open_count)
++ {
++ mydbg ("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_tiocmget(port, file);
++
++ exit:
++ up (&port->sem);
++ return retval;
++}
++
++
++
++static int qt_tiocmget(struct usb_serial_port *port, struct file * file)
++{
++
++ __u8 MCR_Value;
++ __u8 MSR_Value;
++ unsigned int result = 0;
++ int status;
++ unsigned int UartNumber;
++ struct tty_struct * tty;
++
++
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ if(serial == NULL)
++ return -ENODEV;
++ tty = port->tty;
++
++ mydbg("%s - port %d, tty =0x%p\n", __FUNCTION__, port->number, tty);
++
++ /**************************************************************************************/
++ /** TIOCMGET
++ */
++ UartNumber = port->tty->index - serial->minor;
++ status = BoxGetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, &MCR_Value);
++ if (status >= 0)
++ {
++ status = BoxGetRegister(port->serial, UartNumber, MODEM_STATUS_REGISTER, &MSR_Value);
++
++ }
++
++ if (status >= 0)
++ {
++ result = ((MCR_Value & SERIAL_MCR_DTR) ? TIOCM_DTR: 0)
++ //DTR IS SET
++ | ((MCR_Value & SERIAL_MCR_RTS) ? TIOCM_RTS: 0)
++ //RTS IS SET
++ | ((MSR_Value & SERIAL_MSR_CTS) ? TIOCM_CTS: 0)
++ //CTS is set
++ | ((MSR_Value & SERIAL_MSR_CD) ? TIOCM_CAR: 0)
++ //Carrier detect is set
++ | ((MSR_Value & SERIAL_MSR_RI) ? TIOCM_RI: 0)
++ //Ring indicator set
++ | ((MSR_Value & SERIAL_MSR_DSR) ? TIOCM_DSR: 0);
++ //DSR is set
++ return result;
++
++ }
++ else
++ return -ESPIPE;
++ //endif tatus => 0
++}
++
++
++
++static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
++{
++
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ int retval = -ENODEV;
++ unsigned int UartNumber;
++ mydbg("In %s \n", __FUNCTION__);
++
++ if (!serial)
++ return -ENODEV;
++
++
++ UartNumber = port->tty->index - serial->minor;
++
++
++ down (&port->sem);
++
++ mydbg("%s - port %d, cmd 0x%.4x\n", __FUNCTION__, port->number, cmd);
++ mydbg ("%s - port->RxHolding = %d\n", __FUNCTION__, port->RxHolding);
++
++ if (!port->open_count)
++ {
++ mydbg ("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ retval = qt_ioctl(port, file, cmd, arg);
++
++ exit:
++ up (&port->sem);
++ return retval;
++}
++static int qt_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
++{
++ __u8 MCR_Value;
++ __u8 MSR_Value;
++ unsigned short Prev_MSR_Value;
++ unsigned int value, result = 0;
++ int status;
++ unsigned int UartNumber;
++ struct tty_struct * tty;
++
++
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ if(serial == NULL)
++ return -ENODEV;
++ tty = port->tty;
++
++ mydbg("%s - port %d, tty =0x%p\n", __FUNCTION__, port->number, tty);
++
++ /**************************************************************************************/
++ /** TIOCMGET
++ */
++ UartNumber = port->tty->index - serial->minor;
++
++ if(cmd == TIOCMGET)
++ {
++ MCR_Value = port->shadowMCR;
++ MSR_Value = port->shadowMSR;
++
++ {
++ result = ((MCR_Value & SERIAL_MCR_DTR) ? TIOCM_DTR: 0)
++ //DTR IS SET
++ | ((MCR_Value & SERIAL_MCR_RTS) ? TIOCM_RTS: 0)
++ //RTS IS SET
++ | ((MSR_Value & SERIAL_MSR_CTS) ? TIOCM_CTS: 0)
++ //CTS is set
++ | ((MSR_Value & SERIAL_MSR_CD) ? TIOCM_CAR: 0)
++ //Carrier detect is set
++ | ((MSR_Value & SERIAL_MSR_RI) ? TIOCM_RI: 0)
++ //Ring indicator set
++ | ((MSR_Value & SERIAL_MSR_DSR) ? TIOCM_DSR: 0);
++ //DSR is set
++ if(copy_to_user((unsigned int *)arg, &result, sizeof(unsigned int)))
++ return -EFAULT;
++ return 0;
++
++ }//endif tatus => 0
++
++ }//endif(cmd == TIOCMGET)
++ /**************************************************************************************/
++ /** End TIOCMGET
++ */
++ /**************************************************************************************/
++ /** TIOCMBIS, TIOCMBIC, AND TIOCMSET */
++
++ /**************************************************************************************/
++
++ if(cmd == TIOCMBIS || cmd == TIOCMBIC || cmd == TIOCMSET)
++ {
++ status = BoxGetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, &MCR_Value);
++ if (status < 0)
++ return -ESPIPE;
++ if (copy_from_user(&value, (unsigned int *)arg, sizeof(unsigned int)))
++ return -EFAULT;
++
++ switch (cmd)
++ {
++ case TIOCMBIS:
++ if (value & TIOCM_RTS)
++ MCR_Value |= SERIAL_MCR_RTS;
++ if (value & TIOCM_DTR)
++ MCR_Value |= SERIAL_MCR_DTR;
++ if (value & TIOCM_LOOP)
++ MCR_Value |= SERIAL_MCR_LOOP;
++ break;
++ case TIOCMBIC:
++ if (value & TIOCM_RTS)
++ MCR_Value &= ~SERIAL_MCR_RTS;
++ if (value & TIOCM_DTR)
++ MCR_Value &= ~SERIAL_MCR_DTR;
++ if (value & TIOCM_LOOP)
++ MCR_Value &= ~SERIAL_MCR_LOOP;
++ break;
++ case TIOCMSET:
++ //Turn off the RTS and DTR and loopbcck and then only
++ //trun on what was asked for
++ MCR_Value &= ~(SERIAL_MCR_RTS | SERIAL_MCR_DTR | SERIAL_MCR_LOOP);
++ if (value & TIOCM_RTS)
++ MCR_Value |= SERIAL_MCR_RTS;
++ if (value & TIOCM_DTR)
++ MCR_Value |= SERIAL_MCR_DTR;
++ if (value & TIOCM_LOOP)
++ MCR_Value |= SERIAL_MCR_LOOP;
++ break;
++ default:
++ break;
++
++ }
++ status = BoxSetRegister(port->serial, UartNumber, MODEM_CONTROL_REGISTER, MCR_Value);
++ if (status < 0)
++ return -ESPIPE;
++ else
++ {
++ port->shadowMCR = MCR_Value;
++ return 0;
++ }
++
++
++ }
++ /**************************************************************************************/
++ /** TIOCMBIS, TIOCMBIC, AND TIOCMSET end
++ */
++ /**************************************************************************************/
++
++ if(cmd == TIOCMIWAIT)
++ {
++ DECLARE_WAITQUEUE(wait, current);
++ Prev_MSR_Value = port->shadowMSR & SERIAL_MSR_MASK;
++ while(1)
++ {
++ add_wait_queue(&port->wait, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule();
++ remove_wait_queue(&port->wait, &wait);
++ /* see if a signal woke us up */
++ if(signal_pending(current))
++ return -ERESTARTSYS;
++ MSR_Value = port->shadowMSR & SERIAL_MSR_MASK;
++ if(MSR_Value == Prev_MSR_Value)
++ return -EIO; //no change error
++
++ if((arg & TIOCM_RNG && ((Prev_MSR_Value & SERIAL_MSR_RI) ==
++ (MSR_Value & SERIAL_MSR_RI))) ||
++ (arg & TIOCM_DSR && ((Prev_MSR_Value & SERIAL_MSR_DSR) ==
++ (MSR_Value & SERIAL_MSR_DSR))) ||
++ (arg & TIOCM_CD && ((Prev_MSR_Value & SERIAL_MSR_CD) ==
++ (MSR_Value & SERIAL_MSR_CD))) ||
++ (arg & TIOCM_CTS && ((Prev_MSR_Value & SERIAL_MSR_CTS) ==
++ (MSR_Value & SERIAL_MSR_CTS))))
++ {
++ return 0;
++ }
++
++ }//endwhile
++
++ }
++ mydbg("%s -No ioctl for that one. port = %d\n", __FUNCTION__, port->number);
++
++
++ return -ENOIOCTLCMD;
++}
++
++static void serial_set_termios (struct tty_struct *tty, struct ktermios *old)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++
++ if (!serial)
++ return;
++
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!port->open_count) {
++ mydbg("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ /* pass on to the driver specific version of this function if it is available */
++ qt_set_termios(port, old);
++
++exit:
++ up (&port->sem);
++}
++
++static void qt_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
++{
++ unsigned int cflag;
++ int baud, divisor, remainder;
++ unsigned char LCR_change_to = 0;
++ struct tty_struct *tty;
++ int status;
++ struct usb_serial *serial;
++ __u16 UartNumber;
++ __u16 tmp, tmp2;
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ tmp = port->tty->index;
++ mydbg("%s - MINOR(port->tty->index) = %d\n", __FUNCTION__, tmp);
++
++
++ serial = port->serial;
++ tmp2 = serial->minor;
++ mydbg("%s - serial->minor = %d\n", __FUNCTION__, tmp2);
++
++
++
++ UartNumber = port->tty->index - serial->minor;
++
++ tty = port->tty;
++
++ cflag = tty->termios->c_cflag;
++
++ if (old_termios)
++ {
++ if((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(tty->termios->c_iflag) ==
++ RELEVANT_IFLAG(old_termios->c_iflag)))
++ {
++ mydbg("%s - Nothing to change\n", __FUNCTION__);
++ return;
++ }
++
++
++ }
++
++ mydbg("%s - 3\n", __FUNCTION__);
++
++ switch(cflag)
++ {
++ case CS5:
++ LCR_change_to |= SERIAL_5_DATA;
++ break;
++ case CS6:
++ LCR_change_to |= SERIAL_6_DATA;
++ break;
++ case CS7:
++ LCR_change_to |= SERIAL_7_DATA;
++ break;
++ default:
++ case CS8:
++ LCR_change_to |= SERIAL_8_DATA;
++ break;
++ }
++
++ //Parity stuff
++ if(cflag & PARENB)
++ {
++ if(cflag & PARODD)
++ LCR_change_to |= SERIAL_ODD_PARITY;
++ else
++ LCR_change_to |= SERIAL_EVEN_PARITY;
++ }
++ if(cflag & CSTOPB)
++ LCR_change_to |= SERIAL_TWO_STOPB;
++ else
++ LCR_change_to |= SERIAL_TWO_STOPB;
++
++ mydbg("%s - 4\n", __FUNCTION__);
++ //Thats the LCR stuff, go ahead and set it
++ baud = tty_get_baud_rate(tty);
++ if (!baud) {
++ /* pick a default, any default... */
++ baud = 9600;
++ }
++
++ mydbg("%s - got baud = %d\n", __FUNCTION__, baud);
++
++
++ divisor = MAX_BAUD_RATE / baud;
++ remainder = MAX_BAUD_RATE % baud;
++ //Round to nearest divisor
++ if(((remainder * 2) >= baud) && (baud != 110))
++ divisor++;
++
++ //Set Baud rate to default and turn off (default)flow control here
++ status = BoxSetUart(serial, UartNumber, (unsigned short) divisor, LCR_change_to);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetUart failed\n");
++ return;
++ }
++ //************************Now determine flow control
++
++ if(cflag & CRTSCTS)
++ {
++ mydbg("%s - Enabling HW flow control port %d\n", __FUNCTION__, port->number);
++
++ //Enable RTS/CTS flow control
++ status = BoxSetHW_FlowCtrl(serial, UartNumber, 1);
++
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetHW_FlowCtrl failed\n");
++ return;
++ }
++ }
++ else
++ {
++ //Disable RTS/CTS flow control
++ mydbg("%s - disabling HW flow control port %d\n", __FUNCTION__, port->number);
++
++ status = BoxSetHW_FlowCtrl(serial, UartNumber, 0);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetHW_FlowCtrl failed\n");
++ return;
++ }
++
++
++ }
++
++ //*************************************************
++ /* if we are implementing XON/XOFF, set the start and stop character in the device */
++ if (I_IXOFF(tty) || I_IXON(tty))
++ {
++ unsigned char stop_char = STOP_CHAR(tty);
++ unsigned char start_char = START_CHAR(tty);
++ status = BoxSetSW_FlowCtrl(serial, UartNumber, stop_char, start_char);
++ if(status < 0)
++ mydbg(__FILE__"BoxSetSW_FlowCtrl (enabled) failed\n");
++
++ }
++ else
++ {
++ //disable SW flow control
++ status = BoxDisable_SW_FlowCtrl(serial, UartNumber);
++ if(status < 0)
++ mydbg(__FILE__"BoxSetSW_FlowCtrl (diabling) failed\n");
++
++ }
++
++
++
++}
++/****************************************************************************
++* BoxGetRegister
++* issuse a GET_REGISTER vendor-spcific request on the default control pipe
++* If successful, fills in the pValue with the register value asked for
++****************************************************************************/
++static int BoxGetRegister(struct usb_serial *serial, unsigned short Uart_Number,
++ unsigned short Register_Num, __u8 *pValue )
++{
++ int result;
++ __u16 current_length;
++
++
++ current_length = sizeof(struct qt_get_device_data);
++
++ result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), QT_GET_SET_REGISTER,
++ 0xC0, Register_Num, Uart_Number, (void *)pValue, sizeof(*pValue), 300);
++
++ return result;
++}
++/****************************************************************************
++* BoxSetRegister
++* issuse a GET_REGISTER vendor-spcific request on the default control pipe
++* If successful, fills in the pValue with the register value asked for
++****************************************************************************/
++static int BoxSetRegister(struct usb_serial *serial, unsigned short Uart_Number,
++ unsigned short Register_Num, unsigned short Value )
++{
++ int result;
++ unsigned short RegAndByte;
++
++
++ RegAndByte = Value;
++ RegAndByte = RegAndByte << 8;
++ RegAndByte = RegAndByte + Register_Num;
++
++// result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_GET_SET_REGISTER,
++// 0xC0, Register_Num, Uart_Number, NULL, 0, 300);
++
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_GET_SET_REGISTER,
++ 0x40, RegAndByte, Uart_Number, NULL,0, 300);
++
++
++ return result;
++}
++
++
++
++/**
++ * box_get_device
++ * Issue a GET_DEVICE vendor-specific request on the default control pipe If
++ * successful, fills in the qt_get_device_data structure pointed to by
++ * device_data, otherwise return a negative error number of the problem.
++ */
++static int box_get_device(struct usb_serial *serial,
++ struct qt_get_device_data *device_data)
++{
++ int result;
++ __u16 current_length;
++ unsigned char *transfer_buffer;
++
++ current_length = sizeof(struct qt_get_device_data);
++ transfer_buffer = kmalloc(current_length, GFP_KERNEL);
++ if (!transfer_buffer)
++ return -ENOMEM;
++
++ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
++ QT_SET_GET_DEVICE, 0xc0, 0, 0,
++ transfer_buffer, current_length, 300);
++ if (result > 0)
++ memcpy(device_data, transfer_buffer, current_length);
++ kfree(transfer_buffer);
++
++ return result;
++}
++
++/**
++ * box_set_device
++ * Issue a SET_DEVICE vendor-specific request on the default control pipe If
++ * successful returns the number of bytes written, otherwise it returns a
++ * negative error number of the problem.
++ */
++static int box_set_device(struct usb_serial *serial, struct qt_get_device_data *device_data)
++{
++ int result;
++ __u16 length;
++ __u16 PortSettings;
++
++ PortSettings = ((__u16)(device_data->portb));
++ PortSettings = (PortSettings << 8);
++ PortSettings += ((__u16)(device_data->porta));
++
++ length = sizeof(struct qt_get_device_data);
++ mydbg("%s - PortSettings = 0x%x\n", __FUNCTION__, PortSettings);
++
++ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ QT_SET_GET_DEVICE, 0x40, PortSettings,
++ 0, NULL, 0, 300);
++ return result;
++}
++
++/****************************************************************************
++ * BoxOPenCloseChannel
++ * This funciotn notifies the device that the device driver wishes to open a particular UART channel. its
++ * purpose is to allow the device driver and the device to synchronize state information.
++ * OpenClose = 1 for open , 0 for close
++ ****************************************************************************/
++static int BoxOPenCloseChannel(struct usb_serial *serial, __u16 Uart_Number, __u16 OpenClose, struct qt_open_channel_data *pDeviceData)
++{
++ int result;
++ __u16 length;
++ __u8 Direcion;
++ unsigned int pipe;
++ length = sizeof(struct qt_open_channel_data);
++
++ if (OpenClose == 1) //IF OPENING
++ {
++ Direcion = USBD_TRANSFER_DIRECTION_IN;
++ pipe = usb_rcvctrlpipe(serial->dev, 0);
++ result = usb_control_msg (serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL,
++ Direcion, OpenClose, Uart_Number, pDeviceData, length, 300);
++
++
++ }
++ else
++ {
++ Direcion = USBD_TRANSFER_DIRECTION_OUT;
++ pipe = usb_sndctrlpipe(serial->dev, 0);
++ result = usb_control_msg (serial->dev, pipe, QT_OPEN_CLOSE_CHANNEL,
++ Direcion, OpenClose, Uart_Number, NULL, 0, 300);
++
++ }
++
++
++
++ return result;
++}
++
++/****************************************************************************
++ * BoxSetPrebufferLevel
++ TELLS BOX WHEN TO ASSERT FLOW CONTROL
++ ****************************************************************************/
++static int BoxSetPrebufferLevel(struct usb_serial *serial)
++{
++ int result;
++ __u16 buffer_length;
++
++ buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
++ result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
++ QT_GET_SET_PREBUF_TRIG_LVL, 0x40,
++ buffer_length, 0, NULL, 0, 300);
++ return result;
++}
++
++
++
++/****************************************************************************
++ * BoxSetATC
++ TELLS BOX WHEN TO ASSERT automatic transmitter control
++ ****************************************************************************/
++static int BoxSetATC(struct usb_serial *serial, __u16 n_Mode)
++{
++ int result;
++ __u16 buffer_length;
++
++
++ buffer_length = PREFUFF_LEVEL_CONSERVATIVE;
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_SET_ATF,
++ 0x40, n_Mode, 0, NULL, 0, 300);
++
++ return result;
++}
++
++/****************************************************************************
++* BoxSetUart
++* issuse a SET_UART vendor-spcific request on the default control pipe
++* If successful sets baud rate divisor and LCR value
++****************************************************************************/
++static int BoxSetUart(struct usb_serial *serial, unsigned short Uart_Number,
++ unsigned short default_divisor, unsigned char default_LCR )
++{
++ int result;
++ unsigned short UartNumandLCR;
++
++ UartNumandLCR = (default_LCR << 8) + Uart_Number;
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_GET_SET_UART,
++ 0x40, default_divisor, UartNumandLCR, NULL, 0, 300);
++
++ return result;
++}
++
++
++static int BoxSetHW_FlowCtrl(struct usb_serial *serial, unsigned int UartNumber, int bSet)
++{
++ __u8 MCR_Value = 0;
++ __u8 MSR_Value = 0, MOUT_Value = 0;
++ struct usb_serial_port *port;
++ unsigned int status;
++
++ port = serial->port;
++
++ if (bSet == 1)
++ {
++ MCR_Value = SERIAL_MCR_RTS; //flow control, box will clear RTS line to prevent remote
++ } //device from xmitting more chars
++ else
++ { //no flow control to remote device
++ MCR_Value = 0;
++
++ }
++ MOUT_Value = MCR_Value << 8;
++
++
++ if(bSet == 1)
++ {
++ MSR_Value = SERIAL_MSR_CTS; //flow control, box will inhibit xmit data if CTS line is asserted
++ }
++ else
++ {
++ MSR_Value = 0; //Box will not inhimbe xmit data due to CTS line
++ }
++ MOUT_Value |= MSR_Value;
++
++
++ status = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_HW_FLOW_CONTROL_MASK,
++ 0x40, MOUT_Value, UartNumber, NULL, 0, 300);
++ return status;
++
++}
++
++static int BoxSetSW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber, unsigned char stop_char, unsigned char start_char)
++{
++ __u16 nSWflowout;
++ int result;
++
++ nSWflowout = start_char << 8;
++ nSWflowout = (unsigned short)stop_char;
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_SW_FLOW_CONTROL_MASK,
++ 0x40, nSWflowout, UartNumber, NULL, 0, 300);
++ return result;
++
++}
++static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 UartNumber)
++{
++ int result;
++
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_SW_FLOW_CONTROL_DISABLE,
++ 0x40, 0, UartNumber, NULL, 0, 300);
++ return result;
++
++}
++
++
++/*****************************************************************************
++ * SerialThrottle
++ * this function is called by the tty driver when it wants to stop the data
++ * being read from the port.
++ *****************************************************************************/
++
++
++static void serial_throttle (struct tty_struct * tty)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!serial)
++ return;
++
++ down (&port->sem);
++
++
++ if (!port->open_count) {
++ mydbg ("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++ //shut down any bulk reads that may be going on
++// usb_unlink_urb (port->read_urb);
++ /* pass on to the driver specific version of this function */
++ port->RxHolding = 1;
++ mydbg("%s - port->RxHolding = 1\n", __FUNCTION__);
++
++
++exit:
++ up (&port->sem);
++ return;
++}
++
++static void serial_unthrottle (struct tty_struct * tty)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ unsigned int result;
++
++ if (!serial)
++ return;
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!port->open_count) {
++ mydbg ("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ if(port->RxHolding == 1)
++ {
++ mydbg ("%s -port->RxHolding == 1\n", __FUNCTION__);
++
++ port->RxHolding = 0;
++ mydbg ("%s - port->RxHolding = 0\n", __FUNCTION__);
++
++ /* if we have a bulk endpoint, start it up */
++ if ((serial->num_bulk_in) && (port->ReadBulkStopped == 1))
++ {
++ /* Start reading from the device */
++ usb_fill_bulk_urb (port->read_urb, serial->dev,
++ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
++ port->read_urb->transfer_buffer,
++ port->read_urb->transfer_buffer_length,
++ qt_read_bulk_callback,
++ port);
++ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
++ if (result)
++ err("%s - failed restarting read urb, error %d", __FUNCTION__, result);
++ }
++ }
++ exit:
++ up (&port->sem);
++ return;
++
++
++
++}
++
++
++static void serial_break (struct tty_struct *tty, int break_state)
++{
++ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
++ struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
++ __u16 UartNumber, Break_Value;
++ unsigned int result;
++
++ UartNumber = port->tty->index - serial->minor;
++ if (!serial)
++ return;
++
++ if(break_state == -1)
++ Break_Value = 1;
++ else
++ Break_Value = 0;
++
++ down (&port->sem);
++
++ mydbg("%s - port %d\n", __FUNCTION__, port->number);
++
++ if (!port->open_count) {
++ mydbg("%s - port not open\n", __FUNCTION__);
++ goto exit;
++ }
++
++ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_BREAK_CONTROL,
++ 0x40, Break_Value, UartNumber, NULL, 0, 300);
++
++exit:
++ up (&port->sem);
++}
++
++
++
++
++static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ struct usb_serial *serial;
++ int length = 0;
++ int i;
++ off_t begin = 0;
++
++ mydbg("%s\n", __FUNCTION__);
++ length += sprintf (page, "usbserinfo:1.0 driver:%s\n", DRIVER_VERSION);
++ for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
++ serial = get_serial_by_minor(i);
++ if (serial == NULL)
++ continue;
++
++ length += sprintf (page+length, "%d:\n", i);
++ length += sprintf (page+length, " vendor:%04x product:%04x\n", serial->vendor, serial->product);
++ length += sprintf (page+length, " num_ports:%d\n", serial->num_ports);
++ length += sprintf (page+length, " port:%d\n", i - serial->minor + 1);
++
++// usb_make_path(serial->dev, tmp, sizeof(tmp));
++// length += sprintf (page+length, " path:%s", tmp);
++
++ length += sprintf (page+length, "\n");
++ if ((length + begin) > (off + count))
++ goto done;
++ if ((length + begin) < off) {
++ begin += length;
++ length = 0;
++ }
++ }
++ *eof = 1;
++done:
++ if (off >= (length + begin))
++ return 0;
++ *start = page + (off-begin);
++ return ((count < begin+length-off) ? count : begin+length-off);
++}
++
++
++
++int ioctl_serial_usb (struct inode *innod, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++
++ unsigned err;
++ unsigned ucOPR_NewValue, uc_Value;
++ int *p_Num_of_adapters, counts, index, *p_QMCR_Value;
++ struct identity *p_Identity_of;
++ struct identity Identity_of;
++ struct usb_serial *lastserial, *serial;
++
++ mydbg(KERN_DEBUG"ioctl_serial_usb cmd =\n");
++ if (_IOC_TYPE(cmd) != SERIALQT_PCI_IOC_MAGIC)
++ return -ENOTTY;
++ if (_IOC_NR(cmd) > SERIALQT_IOC_MAXNR)
++ return -ENOTTY;
++ mydbg(KERN_DEBUG"ioctl_serial_usb cmd = 0x%x\n", cmd);
++ err = 0;
++ switch (cmd)
++ {
++
++
++ case SERIALQT_WRITE_QMCR:
++ err = -ENOTTY; //initialize as error so if we don't find this one we give//an error.
++ index = arg >> 16;
++ counts = 0;
++
++ ucOPR_NewValue = arg;
++
++
++ err = EmulateWriteQMCR_Reg(index, ucOPR_NewValue);
++ break;
++
++ case SERIALQT_READ_QMCR:
++ err = -ENOTTY; //initialize as error so if we don't find this one we give
++ //an error.
++ p_QMCR_Value = (int *)arg;
++ index = arg >> 16;
++ counts = 0;
++
++
++
++ err = EmulateReadQMCR_Reg(index, &uc_Value);
++ if (err == 0)
++ {
++ err = put_user(uc_Value, p_QMCR_Value);
++ }
++ break;
++
++ case SERIALQT_GET_NUMOF_UNITS:
++ p_Num_of_adapters = (int *)arg;
++ counts = 0; //Initialize counts to zero
++ //struct usb_serial *lastserial = serial_table[0], *serial;
++ lastserial = serial_table[0];
++
++ mydbg(KERN_DEBUG"SERIALQT_GET_NUMOF_UNITS \n");
++ //if first pointer is nonull, we at least have one box
++ if(lastserial)
++ counts = 1; //we at least have one box
++
++ for (index = 1; index < SERIAL_TTY_MINORS ; index++)
++ {
++ serial = serial_table[index];
++ if(serial)
++ {
++ if(serial != lastserial)
++ {
++ //we had a change in the array, hence another box is there
++ lastserial = serial;
++ counts++;
++ }
++ }
++ else
++ break;
++ }
++
++ mydbg(KERN_DEBUG"ioctl_serial_usb writting counts = %d", counts);
++
++ err = put_user(counts, p_Num_of_adapters);
++
++
++ break;
++ case SERIALQT_GET_THIS_UNIT:
++ counts = 0;
++ p_Identity_of = (struct identity *)arg;
++ //copy user structure to local variable
++ get_user(Identity_of.index, &p_Identity_of->index);
++ mydbg(KERN_DEBUG"SERIALQT_GET_THIS_UNIT Identity_of.index\n");
++ mydbg(KERN_DEBUG"SERIALQT_GET_THIS_UNIT Identity_of.index= 0x%x\n", Identity_of.index);
++
++ err = -ENOTTY; //initialize as error so if we don't find this one we give
++ //an error.
++ serial = find_the_box(Identity_of.index);
++ if(serial)
++ {
++ err = put_user(serial->product, &p_Identity_of->n_identity);
++
++ }
++ break;
++
++ case SERIALQT_IS422_EXTENDED:
++ err = -ENOTTY; //initialize as error so if we don't find this one we give
++ mydbg(KERN_DEBUG"SERIALQT_IS422_EXTENDED \n");
++ //an error.
++ index = arg >> 16;
++
++
++ counts = 0;
++
++ mydbg(KERN_DEBUG"SERIALQT_IS422_EXTENDED, looking Identity_of.indext = 0x%x\n",index);
++ serial = find_the_box(index);
++ if(serial)
++ {
++ mydbg("%s index = 0x%x, serial = 0x%p\n", __FUNCTION__, index, serial);
++ for (counts = 0; serqt_422_table[counts] != 0; counts++)
++ {
++
++ mydbg("%s serial->product = = 0x%x, serqt_422_table[counts] = 0x%x\n", __FUNCTION__, serial->product, serqt_422_table[counts]);
++ if(serial->product == serqt_422_table[counts])
++ {
++ err = 0;
++
++ mydbg("%s found match for 422extended\n", __FUNCTION__);
++ break;
++ }
++ }
++ }
++ break;
++
++
++
++
++ default:
++ err = -ENOTTY;
++
++
++
++
++ } //End switch
++
++ mydbg("%s returning err = 0x%x\n", __FUNCTION__, err);
++ return err;
++}
++
++
++
++static struct usb_serial *find_the_box(unsigned int index)
++{
++ struct usb_serial *lastserial, *foundserial, *serial;
++ int counts = 0, index2;
++ lastserial = serial_table[0];
++ foundserial = NULL;
++ for (index2 = 0; index2 < SERIAL_TTY_MINORS ; index2++)
++ {
++ serial = serial_table[index2];
++
++ mydbg("%s index = 0x%x, index2 = 0x%x, serial = 0x%p\n", __FUNCTION__, index, index2, serial);
++
++ if(serial)
++ {
++ //first see if this is the unit we'er looking for
++ mydbg("%s inside if(serial) counts = 0x%x , index = 0x%x\n", __FUNCTION__, counts, index);
++ if(counts == index)
++ {
++ //we found the one we're looking for, copythe product Id to user
++
++ mydbg("%s we found the one we're looking for serial = 0x%p\n", __FUNCTION__, serial);
++ foundserial = serial;
++ break;
++ }
++
++ if(serial != lastserial)
++ {
++ //when we have a change in the pointer
++ lastserial = serial;
++ counts++;
++ }
++ }
++ else
++ break; // no matches
++ }
++
++ mydbg("%s returning foundserial = 0x%p\n", __FUNCTION__, foundserial);
++ return foundserial;
++}
++
++
++
++ static int EmulateWriteQMCR_Reg(int index, unsigned uc_value)
++ {
++
++ __u16 ATC_Mode = 0;
++ struct usb_serial *serial;
++ int status;
++ struct qt_get_device_data DeviceData;
++ unsigned uc_temp = 0;
++ mydbg("Inside %s, uc_value = 0x%x\n", __FUNCTION__, uc_value);
++
++ DeviceData.porta = 0;
++ DeviceData.portb = 0;
++ serial = find_the_box(index);
++ //Determine Duplex mode
++ if(!(serial))
++ return -ENOTTY;
++ status = box_get_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_set_device failed\n");
++ return status;
++ }
++
++ uc_temp = uc_value & QMCR_HALF_DUPLEX_MASK;
++ switch (uc_temp)
++ {
++ case QMCR_FULL_DUPLEX:
++ DeviceData.porta &= ~DUPMODE_BITS;
++ DeviceData.porta |= FULL_DUPLEX;
++ ATC_Mode = ATC_DISABLED;
++ break;
++ case QMCR_HALF_DUPLEX_RTS:
++ DeviceData.porta &= ~DUPMODE_BITS;
++ DeviceData.porta |= HALF_DUPLEX_RTS;
++ ATC_Mode = ATC_RTS_ENABLED;
++ break;
++ case QMCR_HALF_DUPLEX_DTR:
++ DeviceData.porta &= ~DUPMODE_BITS;
++ DeviceData.porta |= HALF_DUPLEX_DTR;
++ ATC_Mode = ATC_DTR_ENABLED;
++ break;
++ default:
++ break;
++ }
++
++ uc_temp = uc_value & QMCR_CONNECTOR_MASK;
++ switch (uc_temp)
++ {
++ case QMCR_MODEM_CONTROL:
++ DeviceData.portb &= ~LOOPMODE_BITS; //reset connection bits
++ DeviceData.portb |= MODEM_CTRL;
++ break;
++ case QMCR_ALL_LOOPBACK:
++ DeviceData.portb &= ~LOOPMODE_BITS; //reset connection bits
++ DeviceData.portb |= ALL_LOOPBACK;
++ break;
++ }
++
++ mydbg(__FILE__"Calling box_set_device with failed\n");
++ status = box_set_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_set_device failed\n");
++ return status;
++ }
++
++ if(uc_value & QMCR_RX_EN_MASK) //This bit (otherwise unused) i'll used to detect whether ATC is selected
++ {
++
++ mydbg(__FILE__"calling BoxsetATC with DeviceData.porta = 0x%x and DeviceData.portb = 0x%x\n", DeviceData.porta, DeviceData.portb);
++ status = BoxSetATC(serial, ATC_Mode);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetATC failed\n");
++ return status;
++ }
++ }
++ else
++ {
++
++ mydbg(__FILE__"calling BoxsetATC with DeviceData.porta = 0x%x and DeviceData.portb = 0x%x\n", DeviceData.porta, DeviceData.portb);
++ status = BoxSetATC(serial, ATC_DISABLED);
++ if (status < 0)
++ {
++ mydbg(__FILE__"BoxSetATC failed\n");
++ return status;
++ }
++ }
++
++
++ return 0;
++
++ }
++
++
++static int EmulateReadQMCR_Reg(int index, unsigned *uc_value)
++{
++ struct usb_serial *serial;
++ int status;
++ struct qt_get_device_data DeviceData;
++ __u8 uc_temp;
++
++ *uc_value = 0;
++
++ serial = find_the_box(index);
++ if(!(serial))
++ return -ENOTTY;
++
++ status = box_get_device(serial, &DeviceData);
++ if (status < 0)
++ {
++ mydbg(__FILE__"box_get_device failed\n");
++ return status;
++ }
++ uc_temp = DeviceData.porta & DUPMODE_BITS;
++ switch (uc_temp)
++ {
++ case FULL_DUPLEX:
++ *uc_value |= QMCR_FULL_DUPLEX;
++ break;
++ case HALF_DUPLEX_RTS:
++ *uc_value |= QMCR_HALF_DUPLEX_RTS;
++ break;
++ case HALF_DUPLEX_DTR:
++ *uc_value |= QMCR_HALF_DUPLEX_DTR;
++ break;
++ default:
++ break;
++ }
++
++ uc_temp = DeviceData.portb & LOOPMODE_BITS; //I use this for ATC control se
++
++ switch (uc_temp)
++ {
++ case ALL_LOOPBACK:
++ *uc_value |= QMCR_ALL_LOOPBACK;
++ break;
++ case MODEM_CTRL:
++ *uc_value |= QMCR_MODEM_CONTROL;
++ break;
++ default:
++ break;
++
++ }
++ return 0;
++
++
++ }
++
++static int __init serqt_usb_init(void)
++{
++ int i, result;
++ int status = 0;
++
++ mydbg("%s\n", __FUNCTION__);
++ result = tty_register_driver(&serial_tty_driver);
++ if (result) {
++ mydbg("tty_register_driver failed error = 0x%x", result);
++ return result;
++ }
++
++ /* Initalize our global data */
++ for (i = 0; i < SERIAL_TTY_MINORS; ++i)
++ serial_table[i] = NULL;
++
++ /* register this driver with the USB subsystem */
++ result = usb_register(&serqt_usb_driver);
++ if (result < 0) {
++ err("usb_register failed for the "__FILE__" driver. Error number %d", result);
++ return result;
++ }
++ status = 0; // Dynamic assignment of major number
++ major_number = register_chrdev(status, "SerialQT_USB", &serialqt_usb_fops);
++ if (major_number < 0) {
++ mydbg(KERN_DEBUG"No devices found \n\n");
++ return -EBUSY;
++ } else
++ mydbg(KERN_DEBUG"SerQT_USB major number assignment = %d \n\n", major_number);
++
++ info(DRIVER_DESC " " DRIVER_VERSION);
++ return 0;
++}
++
++static void __exit serqt_usb_exit(void)
++{
++ /* deregister this driver with the USB subsystem */
++ usb_deregister(&serqt_usb_driver);
++ tty_unregister_driver(&serial_tty_driver);
++ unregister_chrdev(major_number, "SerialQT_USB");
++}
++
++module_init(serqt_usb_init);
++module_exit(serqt_usb_exit);
++
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL");