2005-04-16 15:20:36 -07:00
/*
* Belkin USB Serial Adapter Driver
*
* Copyright ( C ) 2000 William Greathouse ( wgreathouse @ smva . com )
* Copyright ( C ) 2000 - 2001 Greg Kroah - Hartman ( greg @ kroah . com )
*
* This program is largely derived from work by the linux - usb group
* and associated source files . Please see the usb / serial files for
* individual credits and copyrights .
2008-07-22 11:09:39 +01:00
*
2005-04-16 15:20:36 -07:00
* 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 .
*
2008-07-22 11:09:39 +01:00
* See Documentation / usb / usb - serial . txt for more information on using this
* driver
2005-04-16 15:20:36 -07:00
*
* TODO :
* - - Add true modem contol line query capability . Currently we track the
* states reported by the interrupt and the states we request .
* - - Add error reporting back to application for UART error conditions .
* Just point me at how to implement this and I ' ll do it . I ' ve put the
* framework in , but haven ' t analyzed the " tty_flip " interface yet .
* - - Add support for flush commands
* - - Add everything that is missing : )
*
* 27 - Nov - 2001 gkh
* compressed all the differnent device entries into 1.
*
* 30 - May - 2001 gkh
2008-07-22 11:09:39 +01:00
* switched from using spinlock to a semaphore , which fixes lots of
* problems .
2005-04-16 15:20:36 -07:00
*
* 08 - Apr - 2001 gb
* - Identify version on module load .
*
* 12 - Mar - 2001 gkh
* - Added support for the GoHubs GO - COM232 device which is the same as the
* Peracom device .
*
* 06 - Nov - 2000 gkh
* - Added support for the old Belkin and Peracom devices .
* - Made the port able to be opened multiple times .
* - Added some defaults incase the line settings are things these devices
2008-07-22 11:09:39 +01:00
* can ' t support .
2005-04-16 15:20:36 -07:00
*
* 18 - Oct - 2000 William Greathouse
* Released into the wild ( linux - usb - devel )
*
* 17 - Oct - 2000 William Greathouse
* Add code to recognize firmware version and set hardware flow control
* appropriately . Belkin states that firmware prior to 3.05 does not
* operate correctly in hardware handshake mode . I have verified this
* on firmware 2.05 - - for both RTS and DTR input flow control , the control
* line is not reset . The test performed by the Belkin Win * driver is
* to enable hardware flow control for firmware 2.06 or greater and
* for 1.00 or prior . I am only enabling for 2.06 or greater .
*
* 12 - Oct - 2000 William Greathouse
* First cut at supporting Belkin USB Serial Adapter F5U103
* I did not have a copy of the original work to support this
* adapter , so pardon any stupid mistakes . All of the information
* I am using to write this driver was acquired by using a modified
* UsbSnoop on Windows2000 and from examining the other USB drivers .
*/
# 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>
2008-07-22 11:09:39 +01:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
# include <linux/usb.h>
2006-07-11 21:22:58 -07:00
# include <linux/usb/serial.h>
2005-04-16 15:20:36 -07:00
# include "belkin_sa.h"
static int debug ;
/*
* Version Information
*/
# define DRIVER_VERSION "v1.2"
# define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
# define DRIVER_DESC "USB Belkin Serial converter driver"
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
2008-07-22 11:09:39 +01:00
static int belkin_sa_startup ( struct usb_serial * serial ) ;
2009-06-02 11:53:55 -04:00
static void belkin_sa_release ( struct usb_serial * serial ) ;
2008-07-22 11:09:39 +01:00
static int belkin_sa_open ( struct tty_struct * tty ,
2009-09-19 13:13:26 -07:00
struct usb_serial_port * port ) ;
2009-06-11 12:26:29 +01:00
static void belkin_sa_close ( struct usb_serial_port * port ) ;
2008-07-22 11:09:39 +01:00
static void belkin_sa_read_int_callback ( struct urb * urb ) ;
static void belkin_sa_set_termios ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ktermios * old ) ;
static void belkin_sa_break_ctl ( struct tty_struct * tty , int break_state ) ;
static int belkin_sa_tiocmget ( struct tty_struct * tty , struct file * file ) ;
static int belkin_sa_tiocmset ( struct tty_struct * tty , struct file * file ,
unsigned int set , unsigned int clear ) ;
2005-04-16 15:20:36 -07:00
static struct usb_device_id id_table_combined [ ] = {
{ USB_DEVICE ( BELKIN_SA_VID , BELKIN_SA_PID ) } ,
{ USB_DEVICE ( BELKIN_OLD_VID , BELKIN_OLD_PID ) } ,
{ USB_DEVICE ( PERACOM_VID , PERACOM_PID ) } ,
{ USB_DEVICE ( GOHUBS_VID , GOHUBS_PID ) } ,
{ USB_DEVICE ( GOHUBS_VID , HANDYLINK_PID ) } ,
{ USB_DEVICE ( BELKIN_DOCKSTATION_VID , BELKIN_DOCKSTATION_PID ) } ,
2008-07-22 11:09:39 +01:00
{ } /* Terminating entry */
2005-04-16 15:20:36 -07:00
} ;
2008-07-22 11:09:39 +01:00
MODULE_DEVICE_TABLE ( usb , id_table_combined ) ;
2005-04-16 15:20:36 -07:00
static struct usb_driver belkin_driver = {
. name = " belkin " ,
. probe = usb_serial_probe ,
. disconnect = usb_serial_disconnect ,
. id_table = id_table_combined ,
2005-11-16 13:41:28 -08:00
. no_dynamic_id = 1 ,
2005-04-16 15:20:36 -07:00
} ;
/* All of the device info needed for the serial converters */
2005-06-20 21:15:16 -07:00
static struct usb_serial_driver belkin_device = {
2005-06-20 21:15:16 -07:00
. driver = {
. owner = THIS_MODULE ,
2005-06-20 21:15:16 -07:00
. name = " belkin " ,
2005-06-20 21:15:16 -07:00
} ,
2005-06-20 21:15:16 -07:00
. description = " Belkin / Peracom / GoHubs USB Serial Adapter " ,
2006-12-17 21:50:24 +01:00
. usb_driver = & belkin_driver ,
2005-04-16 15:20:36 -07:00
. id_table = id_table_combined ,
. num_ports = 1 ,
. open = belkin_sa_open ,
. close = belkin_sa_close ,
2008-07-22 11:09:39 +01:00
. read_int_callback = belkin_sa_read_int_callback ,
/* How we get the status info */
2005-04-16 15:20:36 -07:00
. set_termios = belkin_sa_set_termios ,
. break_ctl = belkin_sa_break_ctl ,
. tiocmget = belkin_sa_tiocmget ,
. tiocmset = belkin_sa_tiocmset ,
. attach = belkin_sa_startup ,
2009-06-02 11:53:55 -04:00
. release = belkin_sa_release ,
2005-04-16 15:20:36 -07:00
} ;
struct belkin_sa_private {
spinlock_t lock ;
unsigned long control_state ;
unsigned char last_lsr ;
unsigned char last_msr ;
int bad_flow_control ;
} ;
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Belkin USB Serial Adapter F5U103 specific driver functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# define WDR_TIMEOUT 5000 /* default urb timeout */
/* assumes that struct usb_serial *serial is available */
2008-07-22 11:09:39 +01:00
# define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
2005-04-16 15:20:36 -07:00
( c ) , BELKIN_SA_SET_REQUEST_TYPE , \
( v ) , 0 , NULL , 0 , WDR_TIMEOUT )
/* do some startup allocations not currently performed by usb_serial_probe() */
2008-07-22 11:09:39 +01:00
static int belkin_sa_startup ( struct usb_serial * serial )
2005-04-16 15:20:36 -07:00
{
struct usb_device * dev = serial - > dev ;
struct belkin_sa_private * priv ;
/* allocate the private data structure */
priv = kmalloc ( sizeof ( struct belkin_sa_private ) , GFP_KERNEL ) ;
if ( ! priv )
2008-07-22 11:09:39 +01:00
return - 1 ; /* error */
2005-04-16 15:20:36 -07:00
/* set initial values for control structures */
spin_lock_init ( & priv - > lock ) ;
priv - > control_state = 0 ;
priv - > last_lsr = 0 ;
priv - > last_msr = 0 ;
/* see comments at top of file */
2008-07-22 11:09:39 +01:00
priv - > bad_flow_control =
( le16_to_cpu ( dev - > descriptor . bcdDevice ) < = 0x0206 ) ? 1 : 0 ;
2008-08-18 13:21:04 -07:00
dev_info ( & dev - > dev , " bcdDevice: %04x, bfc: %d \n " ,
2008-07-22 11:09:39 +01:00
le16_to_cpu ( dev - > descriptor . bcdDevice ) ,
priv - > bad_flow_control ) ;
2005-04-16 15:20:36 -07:00
init_waitqueue_head ( & serial - > port [ 0 ] - > write_wait ) ;
usb_set_serial_port_data ( serial - > port [ 0 ] , priv ) ;
2008-07-22 11:09:39 +01:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2009-06-02 11:53:55 -04:00
static void belkin_sa_release ( struct usb_serial * serial )
2005-04-16 15:20:36 -07:00
{
struct belkin_sa_private * priv ;
int i ;
2008-07-22 11:09:39 +01:00
dbg ( " %s " , __func__ ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:39 +01:00
for ( i = 0 ; i < serial - > num_ports ; + + i ) {
2005-04-16 15:20:36 -07:00
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data ( serial - > port [ i ] ) ;
2005-04-18 17:39:34 -07:00
kfree ( priv ) ;
2005-04-16 15:20:36 -07:00
}
}
2008-07-22 11:09:39 +01:00
static int belkin_sa_open ( struct tty_struct * tty ,
2009-09-19 13:13:26 -07:00
struct usb_serial_port * port )
2005-04-16 15:20:36 -07:00
{
int retval = 0 ;
2008-03-03 16:08:34 -08:00
dbg ( " %s port %d " , __func__ , port - > number ) ;
2005-04-16 15:20:36 -07:00
/*Start reading from the device*/
/* TODO: Look at possibility of submitting multiple URBs to device to
* enhance buffering . Win trace shows 16 initial read URBs .
*/
port - > read_urb - > dev = port - > serial - > dev ;
retval = usb_submit_urb ( port - > read_urb , GFP_KERNEL ) ;
if ( retval ) {
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " usb_submit_urb(read bulk) failed \n " ) ;
2005-04-16 15:20:36 -07:00
goto exit ;
}
port - > interrupt_in_urb - > dev = port - > serial - > dev ;
retval = usb_submit_urb ( port - > interrupt_in_urb , GFP_KERNEL ) ;
if ( retval ) {
usb_kill_urb ( port - > read_urb ) ;
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " usb_submit_urb(read int) failed \n " ) ;
2005-04-16 15:20:36 -07:00
}
exit :
return retval ;
} /* belkin_sa_open */
2009-06-11 12:26:29 +01:00
static void belkin_sa_close ( struct usb_serial_port * port )
2005-04-16 15:20:36 -07:00
{
2008-03-03 16:08:34 -08:00
dbg ( " %s port %d " , __func__ , port - > number ) ;
2005-04-16 15:20:36 -07:00
/* shutdown our bulk reads and writes */
usb_kill_urb ( port - > write_urb ) ;
usb_kill_urb ( port - > read_urb ) ;
usb_kill_urb ( port - > interrupt_in_urb ) ;
} /* belkin_sa_close */
2008-07-22 11:09:07 +01:00
static void belkin_sa_read_int_callback ( struct urb * urb )
2005-04-16 15:20:36 -07:00
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2005-04-16 15:20:36 -07:00
struct belkin_sa_private * priv ;
unsigned char * data = urb - > transfer_buffer ;
int retval ;
2007-06-15 15:44:13 -07:00
int status = urb - > status ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2007-06-15 15:44:13 -07:00
switch ( status ) {
2005-04-16 15:20:36 -07:00
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
2007-06-15 15:44:13 -07:00
dbg ( " %s - urb shutting down with status: %d " ,
2008-03-03 16:08:34 -08:00
__func__ , status ) ;
2005-04-16 15:20:36 -07:00
return ;
default :
2007-06-15 15:44:13 -07:00
dbg ( " %s - nonzero urb status received: %d " ,
2008-03-03 16:08:34 -08:00
__func__ , status ) ;
2005-04-16 15:20:36 -07:00
goto exit ;
}
2008-07-22 11:09:39 +01:00
usb_serial_debug_data ( debug , & port - > dev , __func__ ,
urb - > actual_length , data ) ;
2005-04-16 15:20:36 -07:00
/* Handle known interrupt data */
/* ignore data[0] and data[1] */
priv = usb_get_serial_port_data ( port ) ;
spin_lock_irqsave ( & priv - > lock , flags ) ;
priv - > last_msr = data [ BELKIN_SA_MSR_INDEX ] ;
2008-07-22 11:09:39 +01:00
2005-04-16 15:20:36 -07:00
/* Record Control Line states */
if ( priv - > last_msr & BELKIN_SA_MSR_DSR )
priv - > control_state | = TIOCM_DSR ;
else
priv - > control_state & = ~ TIOCM_DSR ;
if ( priv - > last_msr & BELKIN_SA_MSR_CTS )
priv - > control_state | = TIOCM_CTS ;
else
priv - > control_state & = ~ TIOCM_CTS ;
if ( priv - > last_msr & BELKIN_SA_MSR_RI )
priv - > control_state | = TIOCM_RI ;
else
priv - > control_state & = ~ TIOCM_RI ;
if ( priv - > last_msr & BELKIN_SA_MSR_CD )
priv - > control_state | = TIOCM_CD ;
else
priv - > control_state & = ~ TIOCM_CD ;
/* Now to report any errors */
priv - > last_lsr = data [ BELKIN_SA_LSR_INDEX ] ;
#if 0
/*
* fill in the flip buffer here , but I do not know the relation
* to the current / next receive buffer or characters . I need
* to look in to this before committing any code .
*/
if ( priv - > last_lsr & BELKIN_SA_LSR_ERR ) {
2008-10-13 10:39:46 +01:00
tty = tty_port_tty_get ( & port - > port ) ;
2005-04-16 15:20:36 -07:00
/* Overrun Error */
if ( priv - > last_lsr & BELKIN_SA_LSR_OE ) {
}
/* Parity Error */
if ( priv - > last_lsr & BELKIN_SA_LSR_PE ) {
}
/* Framing Error */
if ( priv - > last_lsr & BELKIN_SA_LSR_FE ) {
}
/* Break Indicator */
if ( priv - > last_lsr & BELKIN_SA_LSR_BI ) {
}
2008-10-13 10:39:46 +01:00
tty_kref_put ( tty ) ;
2005-04-16 15:20:36 -07:00
}
# endif
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
exit :
2008-07-22 11:09:39 +01:00
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
2005-04-16 15:20:36 -07:00
if ( retval )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " %s - usb_submit_urb failed with "
" result %d \n " , __func__ , retval ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-22 11:09:07 +01:00
static void belkin_sa_set_termios ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ktermios * old_termios )
2005-04-16 15:20:36 -07:00
{
struct usb_serial * serial = port - > serial ;
struct belkin_sa_private * priv = usb_get_serial_port_data ( port ) ;
unsigned int iflag ;
unsigned int cflag ;
unsigned int old_iflag = 0 ;
unsigned int old_cflag = 0 ;
__u16 urb_value = 0 ; /* Will hold the new flags */
unsigned long flags ;
unsigned long control_state ;
int bad_flow_control ;
2007-06-22 14:40:18 +01:00
speed_t baud ;
2008-07-22 11:09:07 +01:00
struct ktermios * termios = tty - > termios ;
2008-07-22 11:09:39 +01:00
2007-12-13 16:15:26 -08:00
iflag = termios - > c_iflag ;
cflag = termios - > c_cflag ;
2005-04-16 15:20:36 -07:00
2007-12-13 16:15:26 -08:00
termios - > c_cflag & = ~ CMSPAR ;
2005-04-16 15:20:36 -07:00
/* get a local copy of the current port settings */
spin_lock_irqsave ( & priv - > lock , flags ) ;
control_state = priv - > control_state ;
bad_flow_control = priv - > bad_flow_control ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
2008-07-22 11:09:39 +01:00
2007-06-22 14:40:18 +01:00
old_iflag = old_termios - > c_iflag ;
old_cflag = old_termios - > c_cflag ;
2005-04-16 15:20:36 -07:00
/* Set the baud rate */
2007-12-13 16:15:26 -08:00
if ( ( cflag & CBAUD ) ! = ( old_cflag & CBAUD ) ) {
2005-04-16 15:20:36 -07:00
/* reassert DTR and (maybe) RTS on transition from B0 */
2008-07-22 11:09:39 +01:00
if ( ( old_cflag & CBAUD ) = = B0 ) {
2005-04-16 15:20:36 -07:00
control_state | = ( TIOCM_DTR | TIOCM_RTS ) ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_DTR_REQUEST , 1 ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set DTR error \n " ) ;
2005-04-16 15:20:36 -07:00
/* don't set RTS if using hardware flow control */
2007-12-13 16:15:26 -08:00
if ( ! ( old_cflag & CRTSCTS ) )
2008-07-22 11:09:39 +01:00
if ( BSA_USB_CMD ( BELKIN_SA_SET_RTS_REQUEST
, 1 ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set RTS error \n " ) ;
2005-04-16 15:20:36 -07:00
}
2007-06-22 14:40:18 +01:00
}
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:07 +01:00
baud = tty_get_baud_rate ( tty ) ;
2007-12-13 16:15:26 -08:00
if ( baud ) {
urb_value = BELKIN_SA_BAUD ( baud ) ;
/* Clip to maximum speed */
if ( urb_value = = 0 )
urb_value = 1 ;
/* Turn it back into a resulting real baud rate */
baud = BELKIN_SA_BAUD ( urb_value ) ;
/* Report the actual baud rate back to the caller */
2008-07-22 11:09:07 +01:00
tty_encode_baud_rate ( tty , baud , baud ) ;
2007-06-22 14:40:18 +01:00
if ( BSA_USB_CMD ( BELKIN_SA_SET_BAUDRATE_REQUEST , urb_value ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set baudrate error \n " ) ;
2007-06-22 14:40:18 +01:00
} else {
/* Disable flow control */
2008-07-22 11:09:39 +01:00
if ( BSA_USB_CMD ( BELKIN_SA_SET_FLOW_CTRL_REQUEST ,
BELKIN_SA_FLOW_NONE ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Disable flowcontrol error \n " ) ;
2007-06-22 14:40:18 +01:00
/* Drop RTS and DTR */
control_state & = ~ ( TIOCM_DTR | TIOCM_RTS ) ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_DTR_REQUEST , 0 ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " DTR LOW error \n " ) ;
2007-06-22 14:40:18 +01:00
if ( BSA_USB_CMD ( BELKIN_SA_SET_RTS_REQUEST , 0 ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " RTS LOW error \n " ) ;
2005-04-16 15:20:36 -07:00
}
/* set the parity */
2008-07-22 11:09:39 +01:00
if ( ( cflag ^ old_cflag ) & ( PARENB | PARODD ) ) {
2005-04-16 15:20:36 -07:00
if ( cflag & PARENB )
2008-07-22 11:09:39 +01:00
urb_value = ( cflag & PARODD ) ? BELKIN_SA_PARITY_ODD
: BELKIN_SA_PARITY_EVEN ;
2005-04-16 15:20:36 -07:00
else
urb_value = BELKIN_SA_PARITY_NONE ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_PARITY_REQUEST , urb_value ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set parity error \n " ) ;
2005-04-16 15:20:36 -07:00
}
/* set the number of data bits */
2008-07-22 11:09:39 +01:00
if ( ( cflag & CSIZE ) ! = ( old_cflag & CSIZE ) ) {
2005-04-16 15:20:36 -07:00
switch ( cflag & CSIZE ) {
2008-07-22 11:09:39 +01:00
case CS5 :
urb_value = BELKIN_SA_DATA_BITS ( 5 ) ;
break ;
case CS6 :
urb_value = BELKIN_SA_DATA_BITS ( 6 ) ;
break ;
case CS7 :
urb_value = BELKIN_SA_DATA_BITS ( 7 ) ;
break ;
case CS8 :
urb_value = BELKIN_SA_DATA_BITS ( 8 ) ;
break ;
default : dbg ( " CSIZE was not CS5-CS8, using default of 8 " ) ;
urb_value = BELKIN_SA_DATA_BITS ( 8 ) ;
break ;
2005-04-16 15:20:36 -07:00
}
if ( BSA_USB_CMD ( BELKIN_SA_SET_DATA_BITS_REQUEST , urb_value ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set data bits error \n " ) ;
2005-04-16 15:20:36 -07:00
}
/* set the number of stop bits */
2008-07-22 11:09:39 +01:00
if ( ( cflag & CSTOPB ) ! = ( old_cflag & CSTOPB ) ) {
urb_value = ( cflag & CSTOPB ) ? BELKIN_SA_STOP_BITS ( 2 )
: BELKIN_SA_STOP_BITS ( 1 ) ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_STOP_BITS_REQUEST ,
urb_value ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set stop bits error \n " ) ;
2005-04-16 15:20:36 -07:00
}
/* Set flow control */
2008-07-22 11:09:39 +01:00
if ( ( ( iflag ^ old_iflag ) & ( IXOFF | IXON ) ) | |
( ( cflag ^ old_cflag ) & CRTSCTS ) ) {
2005-04-16 15:20:36 -07:00
urb_value = 0 ;
if ( ( iflag & IXOFF ) | | ( iflag & IXON ) )
urb_value | = ( BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON ) ;
else
urb_value & = ~ ( BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON ) ;
if ( cflag & CRTSCTS )
urb_value | = ( BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS ) ;
else
urb_value & = ~ ( BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS ) ;
if ( bad_flow_control )
urb_value & = ~ ( BELKIN_SA_FLOW_IRTS ) ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_FLOW_CTRL_REQUEST , urb_value ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set flow control error \n " ) ;
2005-04-16 15:20:36 -07:00
}
/* save off the modified port settings */
spin_lock_irqsave ( & priv - > lock , flags ) ;
priv - > control_state = control_state ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
} /* belkin_sa_set_termios */
2008-07-22 11:09:07 +01:00
static void belkin_sa_break_ctl ( struct tty_struct * tty , int break_state )
2005-04-16 15:20:36 -07:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-16 15:20:36 -07:00
struct usb_serial * serial = port - > serial ;
if ( BSA_USB_CMD ( BELKIN_SA_SET_BREAK_REQUEST , break_state ? 1 : 0 ) < 0 )
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set break_ctl %d \n " , break_state ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-22 11:09:07 +01:00
static int belkin_sa_tiocmget ( struct tty_struct * tty , struct file * file )
2005-04-16 15:20:36 -07:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-16 15:20:36 -07:00
struct belkin_sa_private * priv = usb_get_serial_port_data ( port ) ;
unsigned long control_state ;
unsigned long flags ;
2008-07-22 11:09:39 +01:00
2008-03-03 16:08:34 -08:00
dbg ( " %s " , __func__ ) ;
2005-04-16 15:20:36 -07:00
spin_lock_irqsave ( & priv - > lock , flags ) ;
control_state = priv - > control_state ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
return control_state ;
}
2008-07-22 11:09:07 +01:00
static int belkin_sa_tiocmset ( struct tty_struct * tty , struct file * file ,
2005-04-16 15:20:36 -07:00
unsigned int set , unsigned int clear )
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-16 15:20:36 -07:00
struct usb_serial * serial = port - > serial ;
struct belkin_sa_private * priv = usb_get_serial_port_data ( port ) ;
unsigned long control_state ;
unsigned long flags ;
int retval ;
int rts = 0 ;
int dtr = 0 ;
2008-07-22 11:09:39 +01:00
2008-03-03 16:08:34 -08:00
dbg ( " %s " , __func__ ) ;
2005-04-16 15:20:36 -07:00
spin_lock_irqsave ( & priv - > lock , flags ) ;
control_state = priv - > control_state ;
if ( set & TIOCM_RTS ) {
control_state | = TIOCM_RTS ;
rts = 1 ;
}
if ( set & TIOCM_DTR ) {
control_state | = TIOCM_DTR ;
dtr = 1 ;
}
if ( clear & TIOCM_RTS ) {
control_state & = ~ TIOCM_RTS ;
rts = 0 ;
}
if ( clear & TIOCM_DTR ) {
control_state & = ~ TIOCM_DTR ;
dtr = 0 ;
}
priv - > control_state = control_state ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
retval = BSA_USB_CMD ( BELKIN_SA_SET_RTS_REQUEST , rts ) ;
if ( retval < 0 ) {
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set RTS error %d \n " , retval ) ;
2005-04-16 15:20:36 -07:00
goto exit ;
}
retval = BSA_USB_CMD ( BELKIN_SA_SET_DTR_REQUEST , dtr ) ;
if ( retval < 0 ) {
2008-08-20 16:56:34 -07:00
dev_err ( & port - > dev , " Set DTR error %d \n " , retval ) ;
2005-04-16 15:20:36 -07:00
goto exit ;
}
exit :
return retval ;
}
2008-07-22 11:09:07 +01:00
static int __init belkin_sa_init ( void )
2005-04-16 15:20:36 -07:00
{
int retval ;
retval = usb_serial_register ( & belkin_device ) ;
if ( retval )
goto failed_usb_serial_register ;
retval = usb_register ( & belkin_driver ) ;
if ( retval )
goto failed_usb_register ;
2008-08-18 13:21:04 -07:00
printk ( KERN_INFO KBUILD_MODNAME " : " DRIVER_VERSION " : "
DRIVER_DESC " \n " ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
failed_usb_register :
usb_serial_deregister ( & belkin_device ) ;
failed_usb_serial_register :
return retval ;
}
static void __exit belkin_sa_exit ( void )
{
2008-07-22 11:09:39 +01:00
usb_deregister ( & belkin_driver ) ;
2008-07-22 11:09:07 +01:00
usb_serial_deregister ( & belkin_device ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-22 11:09:39 +01:00
module_init ( belkin_sa_init ) ;
module_exit ( belkin_sa_exit ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:39 +01:00
MODULE_AUTHOR ( DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_VERSION ( DRIVER_VERSION ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;
module_param ( debug , bool , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( debug , " Debug enabled or not " ) ;