summaryrefslogtreecommitdiffstats
path: root/drivers/staging/uc2322
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2009-01-27 23:28:27 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-03 14:53:36 -0700
commite6d69d91d575d0fb573d3103e1fdff6ec98e52b6 (patch)
treea94a8b2082fe1e35842b0c6e9f9e03ebac04d7f1 /drivers/staging/uc2322
parent793bccbd0e5d22903ab4e28a598159a9bf59a0f1 (diff)
Staging: add aten2011 usb to serial converter driver.
Many thanks to Russell Lang <gsview@ghostgum.com.au> for his help in getting this working on newer kernel versions and for pointing out this driver in the first place. Cc: Russell Lang <gsview@ghostgum.com.au> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/uc2322')
-rw-r--r--drivers/staging/uc2322/Kconfig10
-rw-r--r--drivers/staging/uc2322/Makefile1
-rw-r--r--drivers/staging/uc2322/TODO8
-rw-r--r--drivers/staging/uc2322/aten2011.c3625
-rw-r--r--drivers/staging/uc2322/aten2011.h383
-rw-r--r--drivers/staging/uc2322/aten2011_16C50.h58
6 files changed, 4085 insertions, 0 deletions
diff --git a/drivers/staging/uc2322/Kconfig b/drivers/staging/uc2322/Kconfig
new file mode 100644
index 000000000000..2e0c6e79df2b
--- /dev/null
+++ b/drivers/staging/uc2322/Kconfig
@@ -0,0 +1,10 @@
+config USB_SERIAL_ATEN2011
+ tristate "ATEN 2011 USB to serial device support"
+ depends on USB_SERIAL
+ default N
+ ---help---
+ Say Y here if you want to use a ATEN 2011 dual port USB to serial
+ adapter.
+
+ To compile this driver as a module, choose M here: the module will be
+ called aten2011.
diff --git a/drivers/staging/uc2322/Makefile b/drivers/staging/uc2322/Makefile
new file mode 100644
index 000000000000..49c18d6e579f
--- /dev/null
+++ b/drivers/staging/uc2322/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_SERIAL_ATEN2011) += aten2011.o
diff --git a/drivers/staging/uc2322/TODO b/drivers/staging/uc2322/TODO
new file mode 100644
index 000000000000..8d96ad42a43b
--- /dev/null
+++ b/drivers/staging/uc2322/TODO
@@ -0,0 +1,8 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse cleanups
+ - remove dead and useless code (auditing the tty ioctls to
+ verify that they really are correct and needed.)
+
+Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
+Russell Lang <gsview@ghostgum.com.au>.
diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c
new file mode 100644
index 000000000000..2c3e477d8d73
--- /dev/null
+++ b/drivers/staging/uc2322/aten2011.c
@@ -0,0 +1,3625 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/*************************************************************************
+ *** --------------------------------------------------------------------
+ ***
+ *** Project Name: ATENINTL
+ ***
+ *** Module Name: ATEN2011
+ ***
+ *** File: aten2011.c
+ ***
+ ***
+ *** File Revision: 1.2
+ ***
+ *** Revision Date: 2009-01-16
+ ***
+ ***
+ *** Purpose : It gives an interface between USB to 4 Serial
+ *** and serves as a Serial Driver for the high
+ *** level layers /applications.
+ ***
+ *** Change History:
+ *** Modified from ATEN revision 1.2 for Linux kernel 2.6.26 or later
+ ***
+ *** LEGEND :
+ ***
+ ***
+ *** DBG - Code inserted due to as part of debugging
+ *** DPRINTK - Debug Print statement
+ ***
+ *************************************************************************/
+
+/* all file inclusion goes here */
+
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+//#include <linux/spinlock.h>
+#include <linux/serial.h>
+//#include <linux/ioctl.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+
+#define KERNEL_2_6 1
+
+#include <linux/usb/serial.h>
+#include "aten2011.h" /* ATEN2011 Defines */
+#include "aten2011_16C50.h" /* 16C50 UART defines */
+
+/* all defines goes here */
+
+/*
+ * Debug related defines
+ */
+
+/* 1: Enables the debugging -- 0: Disable the debugging */
+
+//#define printk //
+
+#define ATEN_DEBUG 0
+
+#ifdef ATEN_DEBUG
+ static int debug = 0;
+ #define DPRINTK(fmt, args...) printk( "%s: " fmt, __FUNCTION__ , ## args)
+
+#else
+ static int debug = 0;
+ #define DPRINTK(fmt, args...)
+
+#endif
+//#undef DPRINTK
+// #define DPRINTK(fmt, args...)
+
+
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.3.1"
+#define DRIVER_DESC "ATENINTL 2011 USB Serial Adapter"
+
+/*
+ * Defines used for sending commands to port
+ */
+
+#define WAIT_FOR_EVER (HZ * 0 ) /* timeout urb is wait for ever*/
+#define ATEN_WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+#define ATEN_PORT1 0x0200
+#define ATEN_PORT2 0x0300
+#define ATEN_VENREG 0x0000
+#define ATEN_MAX_PORT 0x02
+#define ATEN_WRITE 0x0E
+#define ATEN_READ 0x0D
+
+/* Requests */
+#define ATEN_RD_RTYPE 0xC0
+#define ATEN_WR_RTYPE 0x40
+#define ATEN_RDREQ 0x0D
+#define ATEN_WRREQ 0x0E
+#define ATEN_CTRL_TIMEOUT 500
+#define VENDOR_READ_LENGTH (0x01)
+
+
+int ATEN2011_Thr_cnt;
+//int ATEN2011_spectrum_2or4ports; //this says the number of ports in the device
+//int NoOfOpenPorts;
+
+int RS485mode=0; //set to 1 for RS485 mode and 0 for RS232 mode
+
+static struct usb_serial* ATEN2011_get_usb_serial (struct usb_serial_port *port, const
+char *function);
+static int ATEN2011_serial_paranoia_check (struct usb_serial *serial, const char
+*function);
+static int ATEN2011_port_paranoia_check (struct usb_serial_port *port, const char
+*function);
+
+
+/* setting and get register values */
+static int ATEN2011_set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val);
+static int ATEN2011_get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 * val);
+static int ATEN2011_set_Uart_Reg(struct usb_serial_port *port, __u16 reg, __u16 val);
+static int ATEN2011_get_Uart_Reg(struct usb_serial_port *port, __u16 reg, __u16 * val);
+
+void ATEN2011_Dump_serial_port(struct ATENINTL_port *ATEN2011_port);
+
+/************************************************************************/
+/************************************************************************/
+/* I N T E R F A C E F U N C T I O N S */
+/* I N T E R F A C E F U N C T I O N S */
+/************************************************************************/
+/************************************************************************/
+
+static inline void ATEN2011_set_serial_private(struct usb_serial *serial, struct ATENINTL_serial *data)
+{
+ usb_set_serial_data(serial, (void *)data );
+}
+
+static inline struct ATENINTL_serial * ATEN2011_get_serial_private(struct usb_serial *serial)
+{
+ return (struct ATENINTL_serial*) usb_get_serial_data(serial);
+}
+
+static inline void ATEN2011_set_port_private(struct usb_serial_port *port, struct ATENINTL_port *data)
+{
+ usb_set_serial_port_data(port, (void*)data );
+}
+
+static inline struct ATENINTL_port * ATEN2011_get_port_private(struct usb_serial_port *port)
+{
+ return (struct ATENINTL_port*) usb_get_serial_port_data(port);
+}
+
+/*
+Description:- To set the Control register by calling usb_fill_control_urb function by passing usb_sndctrlpipe function as parameter.
+
+Input Parameters:
+usb_serial_port: Data Structure usb_serialport correponding to that seril port.
+Reg: Register Address
+Val: Value to set in the Register.
+ */
+
+static int ATEN2011_set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val)
+{
+ struct usb_device *dev = port->serial->dev;
+ val = val & 0x00ff;
+ DPRINTK("ATEN2011_set_reg_sync offset is %x, value %x\n",reg,val);
+
+
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ,
+ ATEN_WR_RTYPE, val, reg, NULL, 0,ATEN_WDR_TIMEOUT);
+}
+
+
+
+/*
+Description:- To set the Uart register by calling usb_fill_control_urb function by passing usb_rcvctrlpipe function as parameter.
+
+Input Parameters:
+usb_serial_port: Data Structure usb_serialport correponding to that seril port.
+Reg: Register Address
+Val: Value to receive from the Register.
+ */
+
+static int ATEN2011_get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 * val)
+{
+ struct usb_device *dev = port->serial->dev;
+ int ret=0;
+
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ,
+ ATEN_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,ATEN_WDR_TIMEOUT);
+ DPRINTK("ATEN2011_get_reg_sync offset is %x, return val %x\n",reg,*val);
+ *val = (*val) & 0x00ff;
+ return ret;
+}
+
+
+
+/*
+Description:- To set the Uart register by calling usb_fill_control_urb function by passing usb_sndctrlpipe function as parameter.
+
+Input Parameters:
+usb_serial_port: Data Structure usb_serialport correponding to that seril port.
+Reg: Register Address
+Val: Value to set in the Register.
+ */
+
+static int ATEN2011_set_Uart_Reg(struct usb_serial_port *port, __u16 reg, __u16 val)
+{
+
+
+ struct usb_device *dev = port->serial->dev;
+ struct ATENINTL_serial *ATEN2011_serial;
+ int minor;
+ ATEN2011_serial = ATEN2011_get_serial_private(port->serial);
+ minor = port->serial->minor;
+ if (minor == SERIAL_TTY_NO_MINOR)
+ minor = 0;
+ val = val & 0x00ff;
+ // For the UART control registers, the application number need to be Or'ed
+
+ if(ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4)
+ {
+ val |= (((__u16)port->number - (__u16)(minor))+1)<<8;
+ DPRINTK("ATEN2011_set_Uart_Reg application number is %x\n",val);
+ }
+ else
+ {
+ if( ((__u16)port->number - (__u16)(minor)) == 0)
+ {
+ // val= 0x100;
+ val |= (((__u16)port->number - (__u16)(minor))+1)<<8;
+ DPRINTK("ATEN2011_set_Uart_Reg application number is %x\n",val);
+ }
+ else
+ {
+ // val=0x300;
+ val |= (((__u16)port->number - (__u16)(minor))+2)<<8;
+ DPRINTK("ATEN2011_set_Uart_Reg application number is %x\n",val);
+ }
+ }
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ,
+ ATEN_WR_RTYPE, val, reg, NULL, 0,ATEN_WDR_TIMEOUT);
+
+}
+
+
+/*
+Description:- To set the Control register by calling usb_fill_control_urb function by passing usb_rcvctrlpipe function as parameter.
+
+Input Parameters:
+usb_serial_port: Data Structure usb_serialport correponding to that seril port.
+Reg: Register Address
+Val: Value to receive from the Register.
+ */
+static int ATEN2011_get_Uart_Reg(struct usb_serial_port *port, __u16 reg, __u16 * val)
+{
+ struct usb_device *dev = port->serial->dev;
+ int ret=0;
+ __u16 Wval;
+ struct ATENINTL_serial *ATEN2011_serial;
+ int minor = port->serial->minor;
+ ATEN2011_serial = ATEN2011_get_serial_private(port->serial);
+ if (minor == SERIAL_TTY_NO_MINOR)
+ minor = 0;
+
+ //DPRINTK("application number is %4x \n",(((__u16)port->number - (__u16)(minor))+1)<<8);
+ /*Wval is same as application number*/
+ if(ATEN2011_serial->ATEN2011_spectrum_2or4ports ==4)
+ {
+ Wval=(((__u16)port->number - (__u16)(minor))+1)<<8;
+ DPRINTK("ATEN2011_get_Uart_Reg application number is %x\n",Wval);
+ }
+ else
+ {
+ if( ((__u16)port->number - (__u16)(minor)) == 0)
+ {
+ // Wval= 0x100;
+ Wval=(((__u16)port->number - (__u16)(minor))+1)<<8;
+ DPRINTK("ATEN2011_get_Uart_Reg application number is %x\n",Wval);
+ }
+ else
+ {
+ // Wval=0x300;
+ Wval=(((__u16)port->number - (__u16)(minor))+2)<<8;
+ DPRINTK("ATEN2011_get_Uart_Reg application number is %x\n",Wval);
+ }
+ }
+ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ,
+ ATEN_RD_RTYPE, Wval, reg, val,VENDOR_READ_LENGTH,ATEN_WDR_TIMEOUT);
+ *val = (*val) & 0x00ff;
+ return ret;
+}
+
+
+
+void ATEN2011_Dump_serial_port(struct ATENINTL_port *ATEN2011_port)
+{
+
+ DPRINTK("***************************************\n");
+ DPRINTK("Application number is %4x\n",ATEN2011_port->AppNum);
+ DPRINTK("SpRegOffset is %2x\n",ATEN2011_port->SpRegOffset);
+ DPRINTK("ControlRegOffset is %2x \n",ATEN2011_port->ControlRegOffset);
+ DPRINTK("DCRRegOffset is %2x \n",ATEN2011_port->DcrRegOffset);
+ //DPRINTK("ClkSelectRegOffset is %2x \n",ATEN2011_port->ClkSelectRegOffset);
+ DPRINTK("***************************************\n");
+
+}
+
+/* all structre defination goes here */
+/****************************************************************************
+ * ATENINTL2011_4port_device
+ * Structure defining ATEN2011, usb serial device
+ ****************************************************************************/
+static struct usb_serial_driver ATENINTL2011_4port_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ATEN2011",
+ },
+ .description = DRIVER_DESC,
+ .id_table = ATENINTL_port_id_table,
+ .open = ATEN2011_open,
+ .close = ATEN2011_close,
+ .write = ATEN2011_write,
+ .write_room = ATEN2011_write_room,
+ .chars_in_buffer = ATEN2011_chars_in_buffer,
+ .throttle = ATEN2011_throttle,
+ .unthrottle = ATEN2011_unthrottle,
+ .calc_num_ports = ATEN2011_calc_num_ports,
+
+#ifdef ATENSerialProbe
+ .probe = ATEN2011_serial_probe,
+#endif
+ .ioctl = ATEN2011_ioctl,
+ .set_termios = ATEN2011_set_termios,
+ .break_ctl = ATEN2011_break,
+// .break_ctl = ATEN2011_break_ctl,
+ .tiocmget = ATEN2011_tiocmget,
+ .tiocmset = ATEN2011_tiocmset,
+ .attach = ATEN2011_startup,
+ .shutdown = ATEN2011_shutdown,
+ .read_bulk_callback = ATEN2011_bulk_in_callback,
+ .read_int_callback = ATEN2011_interrupt_callback,
+};
+
+static struct usb_driver io_driver = {
+ .name = "ATEN2011",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table_combined,
+};
+
+
+
+/************************************************************************/
+/************************************************************************/
+/* U S B C A L L B A C K F U N C T I O N S */
+/* U S B C A L L B A C K F U N C T I O N S */
+/************************************************************************/
+/************************************************************************/
+
+/*****************************************************************************
+ * ATEN2011_interrupt_callback
+ * this is the callback function for when we have received data on the
+ * interrupt endpoint.
+ * Input : 1 Input
+ * pointer to the URB packet,
+ *
+ *****************************************************************************/
+//#ifdef ATEN2011
+static void ATEN2011_interrupt_callback (struct urb *urb)
+{
+ int result;
+ int length ;
+ struct ATENINTL_port *ATEN2011_port;
+ struct ATENINTL_serial *ATEN2011_serial;
+ struct usb_serial *serial;
+ __u16 Data;
+ unsigned char *data;
+ __u8 sp[5],st;
+ int i;
+ __u16 wval;
+ int minor;
+ //printk("in the function ATEN2011_interrupt_callback Length %d, Data %x \n",urb->actual_length,(unsigned int)urb->transfer_buffer);
+ DPRINTK("%s"," : Entering\n");
+
+ ATEN2011_serial= (struct ATENINTL_serial *)urb->context;
+ if(!urb)// || ATEN2011_serial->status_polling_started == FALSE )
+ {
+ DPRINTK("%s","Invalid Pointer !!!!:\n");
+ return;
+ }
+
+ switch (urb->status)
+ {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+ length = urb->actual_length;
+ data = urb->transfer_buffer;
+
+ //ATEN2011_serial= (struct ATENINTL_serial *)urb->context;
+ //serial = ATEN2011_get_usb_serial(port,__FUNCTION__);
+ serial = ATEN2011_serial->serial;
+
+ /* ATENINTL get 5 bytes
+ * Byte 1 IIR Port 1 (port.number is 0)
+ * Byte 2 IIR Port 2 (port.number is 1)
+ * Byte 3 IIR Port 3 (port.number is 2)
+ * Byte 4 IIR Port 4 (port.number is 3)
+ * Byte 5 FIFO status for both */
+
+ if(length && length>5)
+ {
+ DPRINTK("%s \n","Wrong data !!!");
+ return;
+ }
+
+ /* MATRIX */
+ if(ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4)
+ {
+ sp[0]=(__u8)data[0];
+ sp[1]=(__u8)data[1];
+ sp[2]=(__u8)data[2];
+ sp[3]=(__u8)data[3];
+ st=(__u8)data[4];
+ }
+ else
+ {
+ sp[0]=(__u8)data[0];
+ sp[1]=(__u8)data[2];
+ //sp[2]=(__u8)data[2];
+ //sp[3]=(__u8)data[3];
+ st=(__u8)data[4];
+
+ }
+ // printk("%s data is sp1:%x sp2:%x sp3:%x sp4:%x status:%x\n",__FUNCTION__,sp1,sp2,sp3,sp4,st);
+ for(i=0;i<serial->num_ports;i++)
+ {
+ ATEN2011_port = ATEN2011_get_port_private(serial->port[i]);
+ minor = serial->minor;
+ if (minor == SERIAL_TTY_NO_MINOR)
+ minor = 0;
+ if((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2) && (i != 0))
+ wval = (((__u16)serial->port[i]->number - (__u16)(minor))+2)<<8;
+ else
+ wval = (((__u16)serial->port[i]->number - (__u16)(minor))+1)<<8;
+ if(ATEN2011_port->open != FALSE)
+ {
+ //printk("%s wval is:(for 2011) %x\n",__FUNCTION__,wval);
+
+ if(sp[i] & 0x01)
+ {
+ DPRINTK("SP%d No Interrupt !!!\n",i);
+ }
+ else
+ {
+ switch(sp[i] & 0x0f)
+ {
+ case SERIAL_IIR_RLS:
+ DPRINTK("Serial Port %d: Receiver status error or ",i);
+ DPRINTK("address bit detected in 9-bit mode\n");
+ ATEN2011_port->MsrLsr=1;
+ ATEN2011_get_reg(ATEN2011_port,wval,LINE_STATUS_REGISTER,&Data);
+ break;
+ case SERIAL_IIR_MS:
+ DPRINTK("Serial Port %d: Modem status change\n",i);
+ ATEN2011_port->MsrLsr=0;
+ ATEN2011_get_reg(ATEN2011_port,wval, MODEM_STATUS_REGISTER, &Data);
+ break;
+ }
+ }
+ }
+
+ }
+exit:
+ if( ATEN2011_serial->status_polling_started == FALSE )
+ return;
+
+ result = usb_submit_urb (urb, GFP_ATOMIC);
+ if (result)
+ {
+ dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n", __FUNCTION__, result);
+ }
+
+ return;
+
+}
+//#endif
+static void ATEN2011_control_callback(struct urb *urb)
+{
+ unsigned char *data;
+ struct ATENINTL_port *ATEN2011_port;
+ __u8 regval=0x0;
+
+ if(!urb)
+ {
+ DPRINTK("%s","Invalid Pointer !!!!:\n");
+ return;
+ }
+
+ switch (urb->status)
+ {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+
+ ATEN2011_port = (struct ATENINTL_port *)urb->context;
+
+ DPRINTK("%s urb buffer size is %d\n",__FUNCTION__,urb->actual_length);
+ DPRINTK("%s ATEN2011_port->MsrLsr is %d port %d\n",__FUNCTION__,ATEN2011_port->MsrLsr,ATEN2011_port->port_num);
+ data=urb->transfer_buffer;
+ regval=(__u8)data[0];
+ DPRINTK("%s data is %x\n",__FUNCTION__,regval);
+ if(ATEN2011_port->MsrLsr==0)
+ handle_newMsr(ATEN2011_port,regval);
+ else if(ATEN2011_port->MsrLsr==1)
+ handle_newLsr(ATEN2011_port,regval);
+
+exit:
+ return;
+}
+int handle_newMsr(struct ATENINTL_port *port,__u8 newMsr)
+{
+ struct ATENINTL_port *ATEN2011_port;
+ struct async_icount *icount;
+ ATEN2011_port=port;
+ icount = &ATEN2011_port->icount;
+ if (newMsr & (ATEN_MSR_DELTA_CTS | ATEN_MSR_DELTA_DSR | ATEN_MSR_DELTA_RI | ATEN_MSR_DELTA_CD)) {
+ icount = &ATEN2011_port->icount;
+
+ /* update input line counters */
+ if (newMsr & ATEN_MSR_DELTA_CTS) {
+ icount->cts++;
+ }
+ if (newMsr & ATEN_MSR_DELTA_DSR) {
+ icount->dsr++;
+ }
+ if (newMsr & ATEN_MSR_DELTA_CD) {
+ icount->dcd++;
+ }
+ if (newMsr & ATEN_MSR_DELTA_RI) {
+ icount->rng++;
+ }
+ }
+
+
+ return 0;
+}
+int handle_newLsr(struct ATENINTL_port *port,__u8 newLsr)
+{
+ struct async_icount *icount;
+
+ dbg("%s - %02x", __FUNCTION__, newLsr);
+
+
+ if (newLsr & SERIAL_LSR_BI) {
+ //
+ // Parity and Framing errors only count if they
+ // occur exclusive of a break being
+ // received.
+ //
+ newLsr &= (__u8)(SERIAL_LSR_OE | SERIAL_LSR_BI);
+ }
+
+
+ /* update input line counters */
+ icount = &port->icount;
+ if (newLsr & SERIAL_LSR_BI) {
+ icount->brk++;
+ }
+ if (newLsr & SERIAL_LSR_OE) {
+ icount->overrun++;
+ }
+ if (newLsr & SERIAL_LSR_PE) {
+ icount->parity++;
+ }
+ if (newLsr & SERIAL_LSR_FE) {
+ icount->frame++;
+ }
+
+
+ return 0;
+}
+static int ATEN2011_get_reg(struct ATENINTL_port *ATEN,__u16 Wval, __u16 reg, __u16 * val)
+{
+ struct usb_device *dev = ATEN->port->serial->dev;
+ struct usb_ctrlrequest *dr=NULL;
+ unsigned char *buffer=NULL;
+ int ret=0;
+ buffer= (__u8 *)ATEN->ctrl_buf;
+
+// dr=(struct usb_ctrlrequest *)(buffer);
+ dr=(void *)(buffer + 2);
+ dr->bRequestType = ATEN_RD_RTYPE;
+ dr->bRequest = ATEN_RDREQ;
+ dr->wValue = cpu_to_le16(Wval);//0;
+ dr->wIndex = cpu_to_le16(reg);
+ dr->wLength = cpu_to_le16(2);
+
+ usb_fill_control_urb(ATEN->control_urb,dev,usb_rcvctrlpipe(dev,0),(unsigned char *)dr,buffer,2,ATEN2011_control_callback,ATEN);
+ ATEN->control_urb->transfer_buffer_length = 2;
+ ret=usb_submit_urb(ATEN->control_urb,GFP_ATOMIC);
+ return ret;
+}
+
+/*****************************************************************************
+ * ATEN2011_bulk_in_callback
+ * this is the callback function for when we have received data on the
+ * bulk in endpoint.
+ * Input : 1 Input
+ * pointer to the URB packet,
+ *
+ *****************************************************************************/
+static void ATEN2011_bulk_in_callback (struct urb *urb)
+{
+ int status;
+ unsigned char *data ;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct ATENINTL_serial *ATEN2011_serial;
+ struct ATENINTL_port *ATEN2011_port;
+ struct tty_struct *tty;
+ if(!urb)
+ {
+ DPRINTK("%s","Invalid Pointer !!!!:\n");
+ return;
+ }
+
+ if (urb->status)
+ {
+ DPRINTK("nonzero read bulk status received: %d",urb->status);
+// if(urb->status==84)
+ //ThreadState=1;
+ return;
+ }
+
+ ATEN2011_port= (struct ATENINTL_port*)urb->context;
+ if(!ATEN2011_port)
+ {
+ DPRINTK("%s","NULL ATEN2011_port pointer \n");
+ return ;
+ }
+
+ port = (struct usb_serial_port *)ATEN2011_port->port;
+ if (ATEN2011_port_paranoia_check (port, __FUNCTION__))
+ {
+ DPRINTK("%s","Port Paranoia failed \n");
+ return;
+ }
+
+ serial = ATEN2011_get_usb_serial(port,__FUNCTION__);
+ if(!serial)
+ {
+ DPRINTK("%s\n","Bad serial pointer ");
+ return;
+ }
+
+ DPRINTK("%s\n","Entering... \n");
+
+ data = urb->transfer_buffer;
+ ATEN2011_serial = ATEN2011_get_serial_private(serial);
+
+ DPRINTK("%s","Entering ........... \n");
+
+ if (urb->actual_length)
+ {
+//MATRIX
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ tty = tty_port_tty_get(&ATEN2011_port->port->port);
+#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,27)
+ tty = ATEN2011_port->port->port.tty;
+#else
+ tty = ATEN2011_port->port->tty;
+#endif
+ if (tty)
+ {
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ DPRINTK(" %s \n",data);
+ tty_flip_buffer_push(tty);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ tty_kref_put(tty);
+#endif
+ }
+
+
+ ATEN2011_port->icount.rx += urb->actual_length;
+ DPRINTK("ATEN2011_port->icount.rx is %d:\n",ATEN2011_port->icount.rx);
+//MATRIX
+ }
+
+ if(!ATEN2011_port->read_urb)
+ {
+ DPRINTK("%s","URB KILLED !!!\n");
+ return;
+ }
+
+ if(ATEN2011_port->read_urb->status!=-EINPROGRESS)
+ {
+ ATEN2011_port->read_urb->dev = serial->dev;
+
+ status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC);
+
+ if (status)
+ {
+ DPRINTK(" usb_submit_urb(read bulk) failed, status = %d", status);
+ }
+ }
+}
+
+/*****************************************************************************
+ * ATEN2011_bulk_out_data_callback
+ * this is the callback function for when we have finished sending serial data
+ * on the bulk out endpoint.
+ * Input : 1 Input
+ * pointer to the URB packet,
+ *
+ *****************************************************************************/
+static void ATEN2011_bulk_out_data_callback (struct urb *urb)
+{
+ struct ATENINTL_port *ATEN2011_port ;
+ struct tty_struct *tty;
+ if(!urb)
+ {
+ DPRINTK("%s","Invalid Pointer !!!!:\n");
+ return;
+ }
+
+ if (urb->status)
+ {
+ DPRINTK("nonzero write bulk status received:%d\n", urb->status);
+ return;
+ }
+
+ ATEN2011_port = (struct ATENINTL_port *)urb->context;
+ if(!ATEN2011_port)
+ {
+ DPRINTK("%s","NULL ATEN2011_port pointer \n");
+ return ;
+ }
+
+ if (ATEN2011_port_paranoia_check (ATEN2011_port->port, __FUNCTION__))
+ {
+ DPRINTK("%s","Port Paranoia failed \n");
+ return;
+ }
+
+ DPRINTK("%s \n","Entering .........");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ tty = tty_port_tty_get(&ATEN2011_port->port->port);
+#elif LINUX_VERSION_CODE == KERNEL_VERSION(2,6,27)
+ tty = ATEN2011_port->port->port.tty;
+#else
+ tty = ATEN2011_port->port->tty;
+#endif
+
+ if (tty && ATEN2011_port->open)
+ {
+ /* let the tty driver wakeup if it has a special *
+ * write_wakeup function */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+ (tty->ldisc.write_wakeup)(tty);
+ }
+#endif
+
+ /* tell the tty driver that something has changed */
+ wake_up_interruptible(&tty->write_wait);
+ }
+
+ /* Release the Write URB */
+ ATEN2011_port->write_in_progress = FALSE;
+
+//schedule_work(&ATEN2011_port->port->work);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ tty_kref_put(tty);
+#endif
+
+}
+
+
+
+
+
+
+/************************************************************************/
+/* D R I V E R T T Y I N T E R F A C E F U N C T I O N S */
+/************************************************************************/
+#ifdef ATENSerialProbe
+static int ATEN2011_serial_probe(struct usb_serial *serial, const struct usb_device_id *id)
+{
+
+ /*need to implement the mode_reg reading and updating\
+ structures usb_serial_ device_type\
+ (i.e num_ports, num_bulkin,bulkout etc)*/
+ /* Also we can update the changes attach */
+ return 1;
+}
+#endif
+
+/*****************************************************************************
+ * SerialOpen
+ * this function is called by the tty driver when a port is opened
+ * If successful, we return 0
+ * Otherwise we return a negative error number.
+ *****************************************************************************/
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port, struct file * filp)
+#else
+static int ATEN2011_open(struct usb_serial_port *port, struct file * filp)
+#endif
+{
+ int response;
+ int j;
+ struct usb_serial *serial;
+// struct usb_serial_port *port0;
+ struct urb *urb;
+ __u16 Data;
+ int status;
+ struct ATENINTL_serial *ATEN2011_serial;
+ struct ATENINTL_port *ATEN2011_port;
+ struct ktermios tmp_termios;
+ int minor;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
+ struct tty_struct *tty = NULL;
+#endif
+ if (ATEN2011_port_paranoia_check (port, __FUNCTION__))
+ {
+ DPRINTK("%s","Port Paranoia failed \n");
+ return -ENODEV;
+ }
+
+ //ATEN2011_serial->NoOfOpenPorts++;
+ serial = port->serial;
+
+ if (ATEN2011_serial_paranoia_check (serial, __FUNCTION__))
+ {
+ DPRINTK("%s","Serial Paranoia failed \n");
+ return -ENODEV;
+ }
+
+ ATEN2011_port = ATEN2011_get_port_private(port);
+
+ if (ATEN2011_port == NULL)
+ return -ENODEV;
+/*
+ if (ATEN2011_port->ctrl_buf==NULL)
+ {
+ ATEN2011_port->ctrl_buf = kmalloc(16,GFP_KERNEL);
+ if (ATEN2011_port->ctrl_buf == NULL) {
+ printk(", Can't allocate ctrl buff\n");
+ return -ENOMEM;
+ }
+
+ }
+
+ if(!ATEN2011_port->control_urb)
+ {
+ ATEN2011_port->control_urb=kmalloc(sizeof(struct urb),GFP_KERNEL);
+ }
+*/
+// port0 = serial->port[0];
+
+ ATEN2011_serial = ATEN2011_get_serial_private(serial);
+
+ if (ATEN2011_serial == NULL )//|| port0 == NULL)
+ {
+ return -ENODEV;
+ }
+ // increment the number of opened ports counter here
+ ATEN2011_serial->NoOfOpenPorts++;
+ //printk("the num of ports opend is:%d\n",ATEN2011_serial->NoOfOpenPorts);
+
+
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+ /* Initialising the write urb pool */
+ for (j = 0; j < NUM_URBS; ++j)
+ {
+ urb = usb_alloc_urb(0,GFP_ATOMIC);
+ ATEN2011_port->write_urb_pool[j] = urb;
+
+ if (urb == NULL)
+ {
+ err("No more urbs???");
+ continue;
+ }
+
+ urb->transfer_buffer = NULL;
+ urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+ if (!urb->transfer_buffer)
+ {
+ err("%s-out of memory for urb buffers.", __FUNCTION__);
+ continue;
+ }
+ }
+
+
+/*****************************************************************************
+ * Initialize ATEN2011 -- Write Init values to corresponding Registers
+ *
+ * Register Index
+ * 1 : IER
+ * 2 : FCR
+ * 3 : LCR
+ * 4 : MCR
+ *
+ * 0x08 : SP1/2 Control Reg
+ *****************************************************************************/
+
+//NEED to check the fallowing Block
+
+ status=0;
+ Data=0x0;
+ status=ATEN2011_get_reg_sync(port,ATEN2011_port->SpRegOffset,&Data);
+ if(status<0){
+ DPRINTK("Reading Spreg failed\n");
+ return -1;
+ }
+ Data |= 0x80;
+ status = ATEN2011_set_reg_sync(port,ATEN2011_port->SpRegOffset,Data);
+ if(status<0){
+ DPRINTK("writing Spreg failed\n");
+ return -1;
+ }
+
+ Data &= ~0x80;
+ status = ATEN2011_set_reg_sync(port,ATEN2011_port->SpRegOffset,Data);
+ if(status<0){
+ DPRINTK("writing Spreg failed\n");
+ return -1;
+ }
+
+
+//End of block to be checked
+//**************************CHECK***************************//
+
+ if(RS485mode==0)
+ Data = 0xC0;
+ else
+ Data = 0x00;
+ status=0;
+ status=ATEN2011_set_Uart_Reg(port,SCRATCH_PAD_REGISTER,Data);
+ if(status<0) {
+ DPRINTK("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+ return -1;
+ }
+ else DPRINTK("SCRATCH_PAD_REGISTER Writing success status%d\n",status);
+
+
+//**************************CHECK***************************//
+
+ status=0;
+ Data=0x0;
+ status=ATEN2011_get_reg_sync(port,ATEN2011_port->ControlRegOffset,&Data);
+ if(status<0){
+ DPRINTK("Reading Controlreg failed\n");
+ return -1;
+ }
+ Data |= 0x08;//Driver done bit
+ /*
+ status = ATEN2011_set_reg_sync(port,ATEN2011_port->ControlRegOffset,Data);
+ if(status<0){
+ DPRINTK("writing Controlreg failed\n");
+ return -1;
+ }
+ */
+ Data |= 0x20;//rx_disable
+ status=0;
+ status = ATEN2011_set_reg_sync(port,ATEN2011_port->ControlRegOffset,Data);
+ if(status<0){
+ DPRINTK("writing Controlreg failed\n");
+ return -1;
+ }
+
+ //do register settings here
+ // Set all regs to the device default values.
+ ////////////////////////////////////