2005-04-16 15:20:36 -07:00
/*
* USB Serial Converter Generic functions
*
2010-05-05 23:57:37 +02:00
* Copyright ( C ) 2010 Johan Hovold ( jhovold @ gmail . com )
2005-04-16 15:20:36 -07:00
* Copyright ( C ) 1999 - 2002 Greg Kroah - Hartman ( greg @ kroah . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation .
*
*/
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/slab.h>
2010-03-25 11:29:16 -07:00
# include <linux/sysrq.h>
2005-04-16 15:20:36 -07:00
# include <linux/tty.h>
# include <linux/tty_flip.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/usb.h>
2006-07-11 21:22:58 -07:00
# include <linux/usb/serial.h>
2008-07-22 11:11:55 +01:00
# include <linux/uaccess.h>
2009-08-28 12:54:27 -07:00
# include <linux/kfifo.h>
2010-02-17 10:05:47 -05:00
# include <linux/serial.h>
2006-12-17 21:50:24 +01:00
2005-04-16 15:20:36 -07:00
static int debug ;
# ifdef CONFIG_USB_SERIAL_GENERIC
2007-03-23 12:51:55 -07:00
static int generic_probe ( struct usb_interface * interface ,
const struct usb_device_id * id ) ;
2005-04-16 15:20:36 -07:00
static __u16 vendor = 0x05f9 ;
static __u16 product = 0xffff ;
module_param ( vendor , ushort , 0 ) ;
MODULE_PARM_DESC ( vendor , " User specified USB idVendor " ) ;
module_param ( product , ushort , 0 ) ;
MODULE_PARM_DESC ( product , " User specified USB idProduct " ) ;
static struct usb_device_id generic_device_ids [ 2 ] ; /* Initially all zeroes. */
2006-12-17 21:50:24 +01:00
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
2010-01-10 15:34:24 +01:00
static const struct usb_device_id generic_serial_ids [ ] = {
2006-12-17 21:50:24 +01:00
{ . driver_info = 42 } ,
{ }
} ;
static struct usb_driver generic_driver = {
. name = " usbserial_generic " ,
. probe = generic_probe ,
. disconnect = usb_serial_disconnect ,
. id_table = generic_serial_ids ,
. no_dynamic_id = 1 ,
} ;
2005-04-16 15:20:36 -07:00
/* All of the device info needed for the Generic Serial Converter */
2005-06-20 21:15:16 -07:00
struct usb_serial_driver usb_serial_generic_device = {
2005-06-20 21:15:16 -07:00
. driver = {
. owner = THIS_MODULE ,
2005-06-20 21:15:16 -07:00
. name = " generic " ,
2005-06-20 21:15:16 -07:00
} ,
2005-04-16 15:20:36 -07:00
. id_table = generic_device_ids ,
2006-12-17 21:50:24 +01:00
. usb_driver = & generic_driver ,
2005-04-16 15:20:36 -07:00
. num_ports = 1 ,
2009-06-02 11:53:55 -04:00
. disconnect = usb_serial_generic_disconnect ,
. release = usb_serial_generic_release ,
2007-02-01 20:08:18 +01:00
. throttle = usb_serial_generic_throttle ,
. unthrottle = usb_serial_generic_unthrottle ,
2007-04-27 20:54:57 +02:00
. resume = usb_serial_generic_resume ,
2005-04-16 15:20:36 -07:00
} ;
static int generic_probe ( struct usb_interface * interface ,
const struct usb_device_id * id )
{
const struct usb_device_id * id_pattern ;
id_pattern = usb_match_id ( interface , generic_device_ids ) ;
if ( id_pattern ! = NULL )
return usb_serial_probe ( interface , id ) ;
return - ENODEV ;
}
# endif
2008-07-22 11:11:55 +01:00
int usb_serial_generic_register ( int _debug )
2005-04-16 15:20:36 -07:00
{
int retval = 0 ;
debug = _debug ;
# ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids [ 0 ] . idVendor = vendor ;
generic_device_ids [ 0 ] . idProduct = product ;
2008-07-22 11:11:55 +01:00
generic_device_ids [ 0 ] . match_flags =
USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT ;
2005-04-16 15:20:36 -07:00
/* register our generic driver with ourselves */
2008-07-22 11:11:55 +01:00
retval = usb_serial_register ( & usb_serial_generic_device ) ;
2005-04-16 15:20:36 -07:00
if ( retval )
goto exit ;
retval = usb_register ( & generic_driver ) ;
if ( retval )
usb_serial_deregister ( & usb_serial_generic_device ) ;
exit :
# endif
return retval ;
}
2008-07-22 11:11:55 +01:00
void usb_serial_generic_deregister ( void )
2005-04-16 15:20:36 -07:00
{
# ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_deregister ( & generic_driver ) ;
2008-07-22 11:11:55 +01:00
usb_serial_deregister ( & usb_serial_generic_device ) ;
2005-04-16 15:20:36 -07:00
# endif
}
2009-09-19 13:13:26 -07:00
int usb_serial_generic_open ( struct tty_struct * tty , struct usb_serial_port * port )
2005-04-16 15:20:36 -07:00
{
int result = 0 ;
2007-02-01 20:08:18 +01:00
unsigned long flags ;
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
2007-02-01 20:08:18 +01:00
/* clear the throttle flags */
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > throttled = 0 ;
port - > throttle_req = 0 ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
/* if we have a bulk endpoint, start reading from it */
2010-03-17 23:05:53 +01:00
if ( port - > bulk_in_size )
result = usb_serial_generic_submit_read_urb ( port , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
return result ;
}
2006-05-12 11:05:29 -07:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_open ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:07 +01:00
static void generic_cleanup ( struct usb_serial_port * port )
2005-04-16 15:20:36 -07:00
{
struct usb_serial * serial = port - > serial ;
2010-03-17 23:00:44 +01:00
unsigned long flags ;
2010-05-05 23:57:37 +02:00
int i ;
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
if ( serial - > dev ) {
2010-02-27 16:24:49 +01:00
/* shutdown any bulk transfers that might be going on */
2010-03-17 23:00:44 +01:00
if ( port - > bulk_out_size ) {
2005-04-16 15:20:36 -07:00
usb_kill_urb ( port - > write_urb ) ;
2010-05-05 23:57:37 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( port - > write_urbs ) ; + + i )
usb_kill_urb ( port - > write_urbs [ i ] ) ;
2010-03-17 23:00:44 +01:00
spin_lock_irqsave ( & port - > lock , flags ) ;
kfifo_reset_out ( & port - > write_fifo ) ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
}
2010-02-27 16:24:49 +01:00
if ( port - > bulk_in_size )
2005-04-16 15:20:36 -07:00
usb_kill_urb ( port - > read_urb ) ;
}
}
2009-06-11 12:26:29 +01:00
void usb_serial_generic_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 ) ;
2008-07-22 11:11:55 +01:00
generic_cleanup ( port ) ;
2005-04-16 15:20:36 -07:00
}
2010-03-17 23:00:45 +01:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_close ) ;
2005-04-16 15:20:36 -07:00
2010-03-17 23:06:08 +01:00
int usb_serial_generic_prepare_write_buffer ( struct usb_serial_port * port ,
2010-05-05 23:58:13 +02:00
void * dest , size_t size )
2010-03-17 23:06:08 +01:00
{
2010-05-05 23:58:13 +02:00
return kfifo_out_locked ( & port - > write_fifo , dest , size , & port - > lock ) ;
2009-05-11 15:24:07 -05:00
}
2009-08-28 12:54:27 -07:00
/**
* usb_serial_generic_write_start - kick off an URB write
* @ port : Pointer to the & struct usb_serial_port data
*
2010-05-05 23:57:37 +02:00
* Returns zero on success , or a negative errno value
2009-08-28 12:54:27 -07:00
*/
static int usb_serial_generic_write_start ( struct usb_serial_port * port )
{
2010-05-05 23:57:37 +02:00
struct urb * urb ;
int count , result ;
2009-08-28 12:54:27 -07:00
unsigned long flags ;
2010-05-05 23:57:37 +02:00
int i ;
2009-08-28 12:54:27 -07:00
2010-05-05 23:57:37 +02:00
if ( test_and_set_bit_lock ( USB_SERIAL_WRITE_BUSY , & port - > flags ) )
return 0 ;
retry :
2009-08-28 12:54:27 -07:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2010-05-05 23:57:37 +02:00
if ( ! port - > write_urbs_free | | ! kfifo_len ( & port - > write_fifo ) ) {
clear_bit_unlock ( USB_SERIAL_WRITE_BUSY , & port - > flags ) ;
2010-03-17 23:06:02 +01:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
return 0 ;
2009-08-28 12:54:27 -07:00
}
2010-05-05 23:57:37 +02:00
i = ( int ) find_first_bit ( & port - > write_urbs_free ,
ARRAY_SIZE ( port - > write_urbs ) ) ;
2009-08-28 12:54:27 -07:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2010-05-05 23:57:37 +02:00
urb = port - > write_urbs [ i ] ;
2010-03-17 23:06:08 +01:00
count = port - > serial - > type - > prepare_write_buffer ( port ,
2010-05-05 23:58:13 +02:00
urb - > transfer_buffer ,
port - > bulk_out_size ) ;
2010-05-05 23:57:37 +02:00
urb - > transfer_buffer_length = count ;
usb_serial_debug_data ( debug , & port - > dev , __func__ , count ,
urb - > transfer_buffer ) ;
result = usb_submit_urb ( urb , GFP_ATOMIC ) ;
2009-08-28 12:54:27 -07:00
if ( result ) {
2010-03-17 23:06:01 +01:00
dev_err ( & port - > dev , " %s - error submitting urb: %d \n " ,
2009-08-28 12:54:27 -07:00
__func__ , result ) ;
2010-05-05 23:57:37 +02:00
clear_bit_unlock ( USB_SERIAL_WRITE_BUSY , & port - > flags ) ;
2010-03-17 23:00:42 +01:00
return result ;
}
2010-05-05 23:57:37 +02:00
clear_bit ( i , & port - > write_urbs_free ) ;
2009-08-28 12:54:27 -07:00
2010-03-17 23:00:42 +01:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2010-03-17 23:06:07 +01:00
port - > tx_bytes + = count ;
2010-03-17 23:00:42 +01:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2010-05-05 23:57:37 +02:00
/* Try sending off another urb, unless in irq context (in which case
* there will be no free urb ) . */
if ( ! in_irq ( ) )
goto retry ;
clear_bit_unlock ( USB_SERIAL_WRITE_BUSY , & port - > flags ) ;
return 0 ;
2009-08-28 12:54:27 -07:00
}
/**
* usb_serial_generic_write - generic write function for serial USB devices
* @ tty : Pointer to & struct tty_struct for the device
* @ port : Pointer to the & usb_serial_port structure for the device
* @ buf : Pointer to the data to write
* @ count : Number of bytes to write
*
* Returns the number of characters actually written , which may be anything
* from zero to @ count . If an error occurs , it returns the negative errno
* value .
*/
2008-07-22 11:09:07 +01:00
int usb_serial_generic_write ( struct tty_struct * tty ,
struct usb_serial_port * port , const unsigned char * buf , int count )
2005-04-16 15:20:36 -07:00
{
int result ;
2008-03-03 16:08:34 -08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-16 15:20:36 -07:00
2010-02-27 16:24:49 +01:00
/* only do something if we have a bulk out endpoint */
if ( ! port - > bulk_out_size )
return - ENODEV ;
2010-03-17 23:06:01 +01:00
if ( ! count )
2008-07-22 11:11:55 +01:00
return 0 ;
2005-04-16 15:20:36 -07:00
2009-12-23 09:10:48 +01:00
count = kfifo_in_locked ( & port - > write_fifo , buf , count , & port - > lock ) ;
2009-08-28 12:54:27 -07:00
result = usb_serial_generic_write_start ( port ) ;
2010-05-05 23:58:13 +02:00
if ( result )
return result ;
2005-04-16 15:20:36 -07:00
2010-05-05 23:58:13 +02:00
return count ;
2005-04-16 15:20:36 -07:00
}
2009-05-11 15:24:09 -05:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_write ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:11:55 +01:00
int usb_serial_generic_write_room ( struct tty_struct * tty )
2005-04-16 15:20:36 -07:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2009-05-11 15:24:07 -05:00
unsigned long flags ;
2010-03-17 23:06:07 +01:00
int room ;
2005-04-16 15:20:36 -07:00
2008-03-03 16:08:34 -08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2010-02-27 16:24:49 +01:00
if ( ! port - > bulk_out_size )
return 0 ;
2009-05-11 15:24:07 -05:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2010-05-05 23:58:13 +02:00
room = kfifo_avail ( & port - > write_fifo ) ;
2009-05-11 15:24:07 -05:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2005-04-16 15:20:36 -07:00
2008-03-03 16:08:34 -08:00
dbg ( " %s - returns %d " , __func__ , room ) ;
2008-04-08 17:16:06 +01:00
return room ;
2005-04-16 15:20:36 -07:00
}
2008-07-22 11:09:07 +01:00
int usb_serial_generic_chars_in_buffer ( struct tty_struct * tty )
2005-04-16 15:20:36 -07:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2009-05-11 15:24:07 -05:00
unsigned long flags ;
2010-02-27 16:24:49 +01:00
int chars ;
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
2010-02-27 16:24:49 +01:00
if ( ! port - > bulk_out_size )
return 0 ;
2010-01-05 14:30:31 +01:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2010-05-05 23:58:13 +02:00
chars = kfifo_len ( & port - > write_fifo ) + port - > tx_bytes ;
2010-01-05 14:30:31 +01:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2005-04-16 15:20:36 -07:00
2008-03-03 16:08:34 -08:00
dbg ( " %s - returns %d " , __func__ , chars ) ;
2008-07-22 11:09:07 +01:00
return chars ;
2005-04-16 15:20:36 -07:00
}
2010-03-17 23:05:53 +01:00
int usb_serial_generic_submit_read_urb ( struct usb_serial_port * port ,
gfp_t mem_flags )
2005-04-16 15:20:36 -07:00
{
int result ;
2010-03-17 23:05:54 +01:00
result = usb_submit_urb ( port - > read_urb , mem_flags ) ;
2010-02-27 14:05:46 +01:00
if ( result & & result ! = - EPERM ) {
2010-03-17 23:06:01 +01:00
dev_err ( & port - > dev , " %s - error submitting urb: %d \n " ,
2008-07-22 11:11:55 +01:00
__func__ , result ) ;
2010-02-27 14:05:46 +01:00
}
2010-03-17 23:05:53 +01:00
return result ;
2005-04-16 15:20:36 -07:00
}
2010-03-17 23:05:53 +01:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_submit_read_urb ) ;
2007-02-01 20:08:18 +01:00
2010-03-17 23:05:57 +01:00
void usb_serial_generic_process_read_urb ( struct urb * urb )
2007-05-07 12:09:33 +02:00
{
2010-03-17 23:05:56 +01:00
struct usb_serial_port * port = urb - > context ;
struct tty_struct * tty ;
2009-05-11 15:24:09 -05:00
char * ch = ( char * ) urb - > transfer_buffer ;
int i ;
2010-03-17 23:05:56 +01:00
tty = tty_port_tty_get ( & port - > port ) ;
2009-05-11 15:24:09 -05:00
if ( ! tty )
2010-03-17 23:05:56 +01:00
return ;
2007-05-07 12:09:33 +02:00
2009-07-09 13:35:52 +01:00
/* The per character mucking around with sysrq path it too slow for
stuff like 3 G modems , so shortcircuit it in the 99.9999999 % of cases
where the USB serial is not a console anyway */
2010-03-08 21:50:12 -06:00
if ( ! port - > port . console | | ! port - > sysrq )
2009-07-09 13:35:52 +01:00
tty_insert_flip_string ( tty , ch , urb - > actual_length ) ;
else {
for ( i = 0 ; i < urb - > actual_length ; i + + , ch + + ) {
2009-07-09 13:36:22 +01:00
if ( ! usb_serial_handle_sysrq_char ( tty , port , * ch ) )
2009-07-09 13:35:52 +01:00
tty_insert_flip_char ( tty , * ch , TTY_NORMAL ) ;
}
2007-05-07 12:09:33 +02:00
}
2009-05-11 15:24:09 -05:00
tty_flip_buffer_push ( tty ) ;
2008-10-13 10:39:46 +01:00
tty_kref_put ( tty ) ;
2007-05-07 12:09:33 +02:00
}
2010-03-17 23:05:57 +01:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_process_read_urb ) ;
2007-05-07 12:09:33 +02:00
2008-07-22 11:09:07 +01:00
void usb_serial_generic_read_bulk_callback ( struct urb * urb )
2007-02-01 20:08:18 +01:00
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-02-01 20:08:18 +01:00
unsigned char * data = urb - > transfer_buffer ;
2007-06-15 15:44:13 -07:00
int status = urb - > status ;
2007-10-28 13:24:16 +01:00
unsigned long flags ;
2007-02-01 20:08:18 +01:00
2008-03-03 16:08:34 -08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 20:08:18 +01:00
2007-06-15 15:44:13 -07:00
if ( unlikely ( status ! = 0 ) ) {
dbg ( " %s - nonzero read bulk status received: %d " ,
2008-03-03 16:08:34 -08:00
__func__ , status ) ;
2007-02-01 20:08:18 +01:00
return ;
}
2008-07-22 11:11:55 +01:00
usb_serial_debug_data ( debug , & port - > dev , __func__ ,
urb - > actual_length , data ) ;
2010-03-17 23:05:57 +01:00
port - > serial - > type - > process_read_urb ( urb ) ;
2007-02-01 20:08:18 +01:00
/* Throttle the device if requested by tty */
2007-10-28 13:24:16 +01:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2008-07-22 11:11:55 +01:00
port - > throttled = port - > throttle_req ;
if ( ! port - > throttled ) {
2008-03-04 23:28:42 -08:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2010-03-17 23:05:56 +01:00
usb_serial_generic_submit_read_urb ( port , GFP_ATOMIC ) ;
2008-07-22 11:11:55 +01:00
} else
2008-03-04 23:28:42 -08:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2007-02-01 20:08:18 +01:00
}
2006-07-11 14:19:25 -03:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_read_bulk_callback ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:07 +01:00
void usb_serial_generic_write_bulk_callback ( struct urb * urb )
2005-04-16 15:20:36 -07:00
{
2009-05-11 15:24:07 -05:00
unsigned long flags ;
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-06-15 15:44:13 -07:00
int status = urb - > status ;
2010-05-05 23:57:37 +02:00
int i ;
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
2010-05-05 23:58:13 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( port - > write_urbs ) ; + + i )
if ( port - > write_urbs [ i ] = = urb )
break ;
2010-01-06 15:48:42 -08:00
2010-05-05 23:58:13 +02:00
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > tx_bytes - = urb - > transfer_buffer_length ;
set_bit ( i , & port - > write_urbs_free ) ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
if ( status ) {
dbg ( " %s - non-zero urb status: %d " , __func__ , status ) ;
2010-05-05 23:57:37 +02:00
2010-03-17 23:00:42 +01:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2010-05-05 23:58:13 +02:00
kfifo_reset_out ( & port - > write_fifo ) ;
2010-03-17 23:00:42 +01:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2010-05-05 23:58:13 +02:00
} else {
usb_serial_generic_write_start ( port ) ;
2005-04-16 15:20:36 -07:00
}
2009-08-28 12:54:27 -07:00
2006-05-22 21:58:49 -07:00
usb_serial_port_softint ( port ) ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 09:48:18 -08:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_write_bulk_callback ) ;
2005-04-16 15:20:36 -07:00
2008-07-22 11:09:07 +01:00
void usb_serial_generic_throttle ( struct tty_struct * tty )
2007-02-01 20:08:18 +01:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2007-02-01 20:08:18 +01:00
unsigned long flags ;
2008-03-03 16:08:34 -08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 20:08:18 +01:00
/* Set the throttle request flag. It will be picked up
* by usb_serial_generic_read_bulk_callback ( ) . */
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > throttle_req = 1 ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
}
2010-03-17 23:05:59 +01:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_throttle ) ;
2007-02-01 20:08:18 +01:00
2008-07-22 11:09:07 +01:00
void usb_serial_generic_unthrottle ( struct tty_struct * tty )
2007-02-01 20:08:18 +01:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2007-02-01 20:08:18 +01:00
int was_throttled ;
2008-03-03 16:08:34 -08:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 20:08:18 +01:00
/* Clear the throttle flags */
2010-03-17 23:05:56 +01:00
spin_lock_irq ( & port - > lock ) ;
2007-02-01 20:08:18 +01:00
was_throttled = port - > throttled ;
port - > throttled = port - > throttle_req = 0 ;
2010-03-17 23:05:56 +01:00
spin_unlock_irq ( & port - > lock ) ;
2007-02-01 20:08:18 +01:00
2010-03-17 23:05:56 +01:00
if ( was_throttled )
usb_serial_generic_submit_read_urb ( port , GFP_KERNEL ) ;
2007-02-01 20:08:18 +01:00
}
2010-03-17 23:05:59 +01:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_unthrottle ) ;
2007-02-01 20:08:18 +01:00
2010-03-25 11:29:16 -07:00
# ifdef CONFIG_MAGIC_SYSRQ
2009-07-09 13:36:22 +01:00
int usb_serial_handle_sysrq_char ( struct tty_struct * tty ,
struct usb_serial_port * port , unsigned int ch )
2009-05-11 15:24:09 -05:00
{
2010-03-08 21:50:12 -06:00
if ( port - > sysrq & & port - > port . console ) {
2009-05-11 15:24:09 -05:00
if ( ch & & time_before ( jiffies , port - > sysrq ) ) {
2009-07-09 13:36:22 +01:00
handle_sysrq ( ch , tty ) ;
2009-05-11 15:24:09 -05:00
port - > sysrq = 0 ;
return 1 ;
}
port - > sysrq = 0 ;
}
return 0 ;
}
2010-03-25 11:29:16 -07:00
# else
int usb_serial_handle_sysrq_char ( struct tty_struct * tty ,
struct usb_serial_port * port , unsigned int ch )
{
return 0 ;
}
# endif
2009-05-11 15:24:09 -05:00
EXPORT_SYMBOL_GPL ( usb_serial_handle_sysrq_char ) ;
int usb_serial_handle_break ( struct usb_serial_port * port )
{
if ( ! port - > sysrq ) {
port - > sysrq = jiffies + HZ * 5 ;
return 1 ;
}
port - > sysrq = 0 ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( usb_serial_handle_break ) ;
2009-08-28 12:54:27 -07:00
int usb_serial_generic_resume ( struct usb_serial * serial )
{
struct usb_serial_port * port ;
int i , c = 0 , r ;
for ( i = 0 ; i < serial - > num_ports ; i + + ) {
port = serial - > port [ i ] ;
2010-02-17 10:05:47 -05:00
if ( ! test_bit ( ASYNCB_INITIALIZED , & port - > port . flags ) )
2009-08-28 12:54:27 -07:00
continue ;
if ( port - > read_urb ) {
r = usb_submit_urb ( port - > read_urb , GFP_NOIO ) ;
if ( r < 0 )
c + + ;
}
2010-05-05 23:57:37 +02:00
if ( port - > bulk_out_size ) {
2009-08-28 12:54:27 -07:00
r = usb_serial_generic_write_start ( port ) ;
if ( r < 0 )
c + + ;
}
}
return c ? - EIO : 0 ;
}
EXPORT_SYMBOL_GPL ( usb_serial_generic_resume ) ;
2009-06-02 11:53:55 -04:00
void usb_serial_generic_disconnect ( struct usb_serial * serial )
2005-04-16 15:20:36 -07:00
{
int i ;
2008-03-03 16:08:34 -08:00
dbg ( " %s " , __func__ ) ;
2005-04-16 15:20:36 -07:00
/* stop reads and writes on all ports */
2008-07-22 11:11:55 +01:00
for ( i = 0 ; i < serial - > num_ports ; + + i )
2005-04-16 15:20:36 -07:00
generic_cleanup ( serial - > port [ i ] ) ;
}
2009-06-02 11:53:55 -04:00
void usb_serial_generic_release ( struct usb_serial * serial )
{
dbg ( " %s " , __func__ ) ;
}