2005-04-17 02:20:36 +04:00
/*
* USB Serial Converter Generic functions
*
* 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 21:29:16 +03:00
# include <linux/sysrq.h>
2005-04-17 02:20:36 +04:00
# include <linux/tty.h>
# include <linux/tty_flip.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/usb.h>
2006-07-12 08:22:58 +04:00
# include <linux/usb/serial.h>
2008-07-22 14:11:55 +04:00
# include <linux/uaccess.h>
2009-08-28 23:54:27 +04:00
# include <linux/kfifo.h>
2010-02-17 18:05:47 +03:00
# include <linux/serial.h>
2006-12-17 23:50:24 +03:00
2005-04-17 02:20:36 +04:00
static int debug ;
# ifdef CONFIG_USB_SERIAL_GENERIC
2007-03-23 22:51:55 +03:00
static int generic_probe ( struct usb_interface * interface ,
const struct usb_device_id * id ) ;
2005-04-17 02:20:36 +04: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 23:50:24 +03:00
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
2010-01-10 17:34:24 +03:00
static const struct usb_device_id generic_serial_ids [ ] = {
2006-12-17 23:50:24 +03: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-17 02:20:36 +04:00
/* All of the device info needed for the Generic Serial Converter */
2005-06-21 08:15:16 +04:00
struct usb_serial_driver usb_serial_generic_device = {
2005-06-21 08:15:16 +04:00
. driver = {
. owner = THIS_MODULE ,
2005-06-21 08:15:16 +04:00
. name = " generic " ,
2005-06-21 08:15:16 +04:00
} ,
2005-04-17 02:20:36 +04:00
. id_table = generic_device_ids ,
2006-12-17 23:50:24 +03:00
. usb_driver = & generic_driver ,
2005-04-17 02:20:36 +04:00
. num_ports = 1 ,
2009-06-02 19:53:55 +04:00
. disconnect = usb_serial_generic_disconnect ,
. release = usb_serial_generic_release ,
2007-02-01 22:08:18 +03:00
. throttle = usb_serial_generic_throttle ,
. unthrottle = usb_serial_generic_unthrottle ,
2007-04-27 22:54:57 +04:00
. resume = usb_serial_generic_resume ,
2005-04-17 02:20:36 +04: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 14:11:55 +04:00
int usb_serial_generic_register ( int _debug )
2005-04-17 02:20:36 +04: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 14:11:55 +04:00
generic_device_ids [ 0 ] . match_flags =
USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT ;
2005-04-17 02:20:36 +04:00
/* register our generic driver with ourselves */
2008-07-22 14:11:55 +04:00
retval = usb_serial_register ( & usb_serial_generic_device ) ;
2005-04-17 02:20:36 +04: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 14:11:55 +04:00
void usb_serial_generic_deregister ( void )
2005-04-17 02:20:36 +04:00
{
# ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_deregister ( & generic_driver ) ;
2008-07-22 14:11:55 +04:00
usb_serial_deregister ( & usb_serial_generic_device ) ;
2005-04-17 02:20:36 +04:00
# endif
}
2009-09-20 00:13:26 +04:00
int usb_serial_generic_open ( struct tty_struct * tty , struct usb_serial_port * port )
2005-04-17 02:20:36 +04:00
{
struct usb_serial * serial = port - > serial ;
int result = 0 ;
2007-02-01 22:08:18 +03:00
unsigned long flags ;
2005-04-17 02:20:36 +04:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 02:20:36 +04:00
2007-02-01 22:08:18 +03: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-02-27 18:24:49 +03:00
if ( port - > bulk_in_size ) {
2005-04-17 02:20:36 +04:00
/* Start reading from the device */
2008-07-22 14:11:55 +04:00
usb_fill_bulk_urb ( port - > read_urb , serial - > dev ,
usb_rcvbulkpipe ( serial - > dev ,
port - > bulk_in_endpointAddress ) ,
2005-04-17 02:20:36 +04:00
port - > read_urb - > transfer_buffer ,
port - > read_urb - > transfer_buffer_length ,
( ( serial - > type - > read_bulk_callback ) ?
serial - > type - > read_bulk_callback :
usb_serial_generic_read_bulk_callback ) ,
port ) ;
result = usb_submit_urb ( port - > read_urb , GFP_KERNEL ) ;
if ( result )
2008-07-22 14:11:55 +04:00
dev_err ( & port - > dev ,
" %s - failed resubmitting read urb, error %d \n " ,
__func__ , result ) ;
2005-04-17 02:20:36 +04:00
}
return result ;
}
2006-05-12 22:05:29 +04:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_open ) ;
2005-04-17 02:20:36 +04:00
2008-07-22 14:09:07 +04:00
static void generic_cleanup ( struct usb_serial_port * port )
2005-04-17 02:20:36 +04:00
{
struct usb_serial * serial = port - > serial ;
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 02:20:36 +04:00
if ( serial - > dev ) {
2010-02-27 18:24:49 +03:00
/* shutdown any bulk transfers that might be going on */
if ( port - > bulk_out_size )
2005-04-17 02:20:36 +04:00
usb_kill_urb ( port - > write_urb ) ;
2010-02-27 18:24:49 +03:00
if ( port - > bulk_in_size )
2005-04-17 02:20:36 +04:00
usb_kill_urb ( port - > read_urb ) ;
}
}
2009-06-11 15:26:29 +04:00
void usb_serial_generic_close ( struct usb_serial_port * port )
2005-04-17 02:20:36 +04:00
{
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2008-07-22 14:11:55 +04:00
generic_cleanup ( port ) ;
2005-04-17 02:20:36 +04:00
}
2009-05-12 00:24:07 +04:00
static int usb_serial_multi_urb_write ( struct tty_struct * tty ,
struct usb_serial_port * port , const unsigned char * buf , int count )
{
unsigned long flags ;
struct urb * urb ;
unsigned char * buffer ;
int status ;
int towrite ;
int bwrite = 0 ;
dbg ( " %s - port %d " , __func__ , port - > number ) ;
if ( count = = 0 )
dbg ( " %s - write request of 0 bytes " , __func__ ) ;
while ( count > 0 ) {
towrite = ( count > port - > bulk_out_size ) ?
port - > bulk_out_size : count ;
spin_lock_irqsave ( & port - > lock , flags ) ;
if ( port - > urbs_in_flight >
port - > serial - > type - > max_in_flight_urbs ) {
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2010-02-06 03:50:08 +03:00
dbg ( " %s - write limit hit " , __func__ ) ;
2009-05-12 00:24:07 +04:00
return bwrite ;
}
port - > tx_bytes_flight + = towrite ;
port - > urbs_in_flight + + ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
buffer = kmalloc ( towrite , GFP_ATOMIC ) ;
if ( ! buffer ) {
dev_err ( & port - > dev ,
" %s ran out of kernel memory for urb ... \n " , __func__ ) ;
goto error_no_buffer ;
}
urb = usb_alloc_urb ( 0 , GFP_ATOMIC ) ;
if ( ! urb ) {
dev_err ( & port - > dev , " %s - no more free urbs \n " ,
__func__ ) ;
goto error_no_urb ;
}
/* Copy data */
memcpy ( buffer , buf + bwrite , towrite ) ;
usb_serial_debug_data ( debug , & port - > dev , __func__ ,
towrite , buffer ) ;
/* fill the buffer and send it */
usb_fill_bulk_urb ( urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
buffer , towrite ,
usb_serial_generic_write_bulk_callback , port ) ;
status = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( status ) {
dev_err ( & port - > dev ,
" %s - failed submitting write urb, error %d \n " ,
__func__ , status ) ;
goto error ;
}
/* This urb is the responsibility of the host driver now */
usb_free_urb ( urb ) ;
dbg ( " %s write: %d " , __func__ , towrite ) ;
count - = towrite ;
bwrite + = towrite ;
}
return bwrite ;
error :
usb_free_urb ( urb ) ;
error_no_urb :
kfree ( buffer ) ;
error_no_buffer :
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > urbs_in_flight - - ;
port - > tx_bytes_flight - = towrite ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
return bwrite ;
}
2009-08-28 23:54:27 +04:00
/**
* usb_serial_generic_write_start - kick off an URB write
* @ port : Pointer to the & struct usb_serial_port data
*
* Returns the number of bytes queued on success . This will be zero if there
* was nothing to send . Otherwise , it returns a negative errno value
*/
static int usb_serial_generic_write_start ( struct usb_serial_port * port )
{
struct usb_serial * serial = port - > serial ;
unsigned char * data ;
int result ;
int count ;
unsigned long flags ;
bool start_io ;
/* Atomically determine whether we can and need to start a USB
* operation . */
spin_lock_irqsave ( & port - > lock , flags ) ;
if ( port - > write_urb_busy )
start_io = false ;
else {
2009-12-23 11:10:48 +03:00
start_io = ( kfifo_len ( & port - > write_fifo ) ! = 0 ) ;
2009-08-28 23:54:27 +04:00
port - > write_urb_busy = start_io ;
}
spin_unlock_irqrestore ( & port - > lock , flags ) ;
if ( ! start_io )
return 0 ;
data = port - > write_urb - > transfer_buffer ;
2009-12-23 11:10:48 +03:00
count = kfifo_out_locked ( & port - > write_fifo , data , port - > bulk_out_size , & port - > lock ) ;
2009-08-28 23:54:27 +04:00
usb_serial_debug_data ( debug , & port - > dev , __func__ , count , data ) ;
/* 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 ,
( ( serial - > type - > write_bulk_callback ) ?
serial - > type - > write_bulk_callback :
usb_serial_generic_write_bulk_callback ) ,
port ) ;
/* send the data out the bulk port */
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
if ( result ) {
dev_err ( & port - > dev ,
" %s - failed submitting write urb, error %d \n " ,
__func__ , result ) ;
/* don't have to grab the lock here, as we will
retry if ! = 0 */
port - > write_urb_busy = 0 ;
2010-03-18 01:00:42 +03:00
return result ;
}
2009-08-28 23:54:27 +04:00
2010-03-18 01:00:42 +03:00
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > tx_bytes_flight + = count ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
return count ;
2009-08-28 23:54:27 +04: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 14:09:07 +04:00
int usb_serial_generic_write ( struct tty_struct * tty ,
struct usb_serial_port * port , const unsigned char * buf , int count )
2005-04-17 02:20:36 +04:00
{
struct usb_serial * serial = port - > serial ;
int result ;
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 02:20:36 +04:00
2010-02-27 18:24:49 +03:00
/* only do something if we have a bulk out endpoint */
if ( ! port - > bulk_out_size )
return - ENODEV ;
2005-04-17 02:20:36 +04:00
if ( count = = 0 ) {
2008-03-04 03:08:34 +03:00
dbg ( " %s - write request of 0 bytes " , __func__ ) ;
2008-07-22 14:11:55 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2009-08-28 23:54:27 +04:00
if ( serial - > type - > max_in_flight_urbs )
return usb_serial_multi_urb_write ( tty , port ,
buf , count ) ;
2005-04-17 02:20:36 +04:00
2009-12-23 11:10:48 +03:00
count = kfifo_in_locked ( & port - > write_fifo , buf , count , & port - > lock ) ;
2009-08-28 23:54:27 +04:00
result = usb_serial_generic_write_start ( port ) ;
2005-04-17 02:20:36 +04:00
2009-08-28 23:54:27 +04:00
if ( result > = 0 )
result = count ;
2005-04-17 02:20:36 +04:00
2009-08-28 23:54:27 +04:00
return result ;
2005-04-17 02:20:36 +04:00
}
2009-05-12 00:24:09 +04:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_write ) ;
2005-04-17 02:20:36 +04:00
2008-07-22 14:11:55 +04:00
int usb_serial_generic_write_room ( struct tty_struct * tty )
2005-04-17 02:20:36 +04:00
{
2008-07-22 14:09:07 +04:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-17 02:20:36 +04:00
struct usb_serial * serial = port - > serial ;
2009-05-12 00:24:07 +04:00
unsigned long flags ;
2005-04-17 02:20:36 +04:00
int room = 0 ;
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2010-02-27 18:24:49 +03:00
if ( ! port - > bulk_out_size )
return 0 ;
2009-05-12 00:24:07 +04:00
spin_lock_irqsave ( & port - > lock , flags ) ;
if ( serial - > type - > max_in_flight_urbs ) {
if ( port - > urbs_in_flight < serial - > type - > max_in_flight_urbs )
2009-05-12 00:24:09 +04:00
room = port - > bulk_out_size *
( serial - > type - > max_in_flight_urbs -
port - > urbs_in_flight ) ;
2010-02-27 18:24:49 +03:00
} else {
2009-12-23 11:10:48 +03:00
room = kfifo_avail ( & port - > write_fifo ) ;
2010-02-27 18:24:49 +03:00
}
2009-05-12 00:24:07 +04:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - returns %d " , __func__ , room ) ;
2008-04-08 20:16:06 +04:00
return room ;
2005-04-17 02:20:36 +04:00
}
2008-07-22 14:09:07 +04:00
int usb_serial_generic_chars_in_buffer ( struct tty_struct * tty )
2005-04-17 02:20:36 +04:00
{
2008-07-22 14:09:07 +04:00
struct usb_serial_port * port = tty - > driver_data ;
2005-04-17 02:20:36 +04:00
struct usb_serial * serial = port - > serial ;
2009-05-12 00:24:07 +04:00
unsigned long flags ;
2010-02-27 18:24:49 +03:00
int chars ;
2005-04-17 02:20:36 +04:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 02:20:36 +04:00
2010-02-27 18:24:49 +03:00
if ( ! port - > bulk_out_size )
return 0 ;
2010-01-05 16:30:31 +03:00
spin_lock_irqsave ( & port - > lock , flags ) ;
if ( serial - > type - > max_in_flight_urbs )
2009-05-12 00:24:07 +04:00
chars = port - > tx_bytes_flight ;
2010-02-27 18:24:49 +03:00
else
2010-03-18 01:00:42 +03:00
chars = kfifo_len ( & port - > write_fifo ) + port - > tx_bytes_flight ;
2010-01-05 16:30:31 +03:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - returns %d " , __func__ , chars ) ;
2008-07-22 14:09:07 +04:00
return chars ;
2005-04-17 02:20:36 +04:00
}
2007-05-07 14:09:33 +04:00
2009-05-12 00:24:09 +04:00
void usb_serial_generic_resubmit_read_urb ( struct usb_serial_port * port ,
gfp_t mem_flags )
2005-04-17 02:20:36 +04:00
{
2007-02-01 22:08:18 +03:00
struct urb * urb = port - > read_urb ;
2007-05-07 14:09:33 +04:00
struct usb_serial * serial = port - > serial ;
2005-04-17 02:20:36 +04:00
int result ;
2007-02-01 22:08:18 +03:00
/* Continue reading from device */
2008-07-22 14:11:55 +04:00
usb_fill_bulk_urb ( urb , serial - > dev ,
usb_rcvbulkpipe ( serial - > dev ,
port - > bulk_in_endpointAddress ) ,
2007-05-07 14:09:33 +04:00
urb - > transfer_buffer ,
urb - > transfer_buffer_length ,
2008-07-22 14:11:55 +04:00
( ( serial - > type - > read_bulk_callback ) ?
serial - > type - > read_bulk_callback :
2005-04-17 02:20:36 +04:00
usb_serial_generic_read_bulk_callback ) , port ) ;
2010-02-27 16:05:46 +03:00
2007-05-07 14:09:33 +04:00
result = usb_submit_urb ( urb , mem_flags ) ;
2010-02-27 16:05:46 +03:00
if ( result & & result ! = - EPERM ) {
2008-07-22 14:11:55 +04:00
dev_err ( & port - > dev ,
" %s - failed resubmitting read urb, error %d \n " ,
__func__ , result ) ;
2010-02-27 16:05:46 +03:00
}
2005-04-17 02:20:36 +04:00
}
2009-05-12 00:24:09 +04:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_resubmit_read_urb ) ;
2007-02-01 22:08:18 +03:00
2007-05-07 14:09:33 +04:00
/* Push data to tty layer and resubmit the bulk read URB */
2008-07-22 14:09:07 +04:00
static void flush_and_resubmit_read_urb ( struct usb_serial_port * port )
2007-05-07 14:09:33 +04:00
{
struct urb * urb = port - > read_urb ;
2008-10-13 13:39:46 +04:00
struct tty_struct * tty = tty_port_tty_get ( & port - > port ) ;
2009-05-12 00:24:09 +04:00
char * ch = ( char * ) urb - > transfer_buffer ;
int i ;
if ( ! tty )
goto done ;
2007-05-07 14:09:33 +04:00
2009-07-09 16:35:52 +04: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-09 06:50:12 +03:00
if ( ! port - > port . console | | ! port - > sysrq )
2009-07-09 16:35:52 +04:00
tty_insert_flip_string ( tty , ch , urb - > actual_length ) ;
else {
/* Push data to tty */
for ( i = 0 ; i < urb - > actual_length ; i + + , ch + + ) {
2009-07-09 16:36:22 +04:00
if ( ! usb_serial_handle_sysrq_char ( tty , port , * ch ) )
2009-07-09 16:35:52 +04:00
tty_insert_flip_char ( tty , * ch , TTY_NORMAL ) ;
}
2007-05-07 14:09:33 +04:00
}
2009-05-12 00:24:09 +04:00
tty_flip_buffer_push ( tty ) ;
2008-10-13 13:39:46 +04:00
tty_kref_put ( tty ) ;
2009-05-12 00:24:09 +04:00
done :
usb_serial_generic_resubmit_read_urb ( port , GFP_ATOMIC ) ;
2007-05-07 14:09:33 +04:00
}
2008-07-22 14:09:07 +04:00
void usb_serial_generic_read_bulk_callback ( struct urb * urb )
2007-02-01 22:08:18 +03:00
{
2008-02-24 13:41:47 +03:00
struct usb_serial_port * port = urb - > context ;
2007-02-01 22:08:18 +03:00
unsigned char * data = urb - > transfer_buffer ;
2007-06-16 02:44:13 +04:00
int status = urb - > status ;
2007-10-28 15:24:16 +03:00
unsigned long flags ;
2007-02-01 22:08:18 +03:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 22:08:18 +03:00
2007-06-16 02:44:13 +04:00
if ( unlikely ( status ! = 0 ) ) {
dbg ( " %s - nonzero read bulk status received: %d " ,
2008-03-04 03:08:34 +03:00
__func__ , status ) ;
2007-02-01 22:08:18 +03:00
return ;
}
2008-07-22 14:11:55 +04:00
usb_serial_debug_data ( debug , & port - > dev , __func__ ,
urb - > actual_length , data ) ;
2007-02-01 22:08:18 +03:00
/* Throttle the device if requested by tty */
2007-10-28 15:24:16 +03:00
spin_lock_irqsave ( & port - > lock , flags ) ;
2008-07-22 14:11:55 +04:00
port - > throttled = port - > throttle_req ;
if ( ! port - > throttled ) {
2008-03-05 10:28:42 +03:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2007-05-07 14:09:33 +04:00
flush_and_resubmit_read_urb ( port ) ;
2008-07-22 14:11:55 +04:00
} else
2008-03-05 10:28:42 +03:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2007-02-01 22:08:18 +03:00
}
2006-07-11 21:19:25 +04:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_read_bulk_callback ) ;
2005-04-17 02:20:36 +04:00
2008-07-22 14:09:07 +04:00
void usb_serial_generic_write_bulk_callback ( struct urb * urb )
2005-04-17 02:20:36 +04:00
{
2009-05-12 00:24:07 +04:00
unsigned long flags ;
2008-02-24 13:41:47 +03:00
struct usb_serial_port * port = urb - > context ;
2007-06-16 02:44:13 +04:00
int status = urb - > status ;
2005-04-17 02:20:36 +04:00
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2005-04-17 02:20:36 +04:00
2009-05-12 00:24:07 +04:00
if ( port - > serial - > type - > max_in_flight_urbs ) {
2010-01-07 02:48:42 +03:00
kfree ( urb - > transfer_buffer ) ;
2009-05-12 00:24:07 +04:00
spin_lock_irqsave ( & port - > lock , flags ) ;
- - port - > urbs_in_flight ;
port - > tx_bytes_flight - = urb - > transfer_buffer_length ;
if ( port - > urbs_in_flight < 0 )
port - > urbs_in_flight = 0 ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
} else {
2010-03-18 01:00:42 +03:00
spin_lock_irqsave ( & port - > lock , flags ) ;
port - > tx_bytes_flight - = urb - > transfer_buffer_length ;
2009-05-12 00:24:07 +04:00
port - > write_urb_busy = 0 ;
2010-03-18 01:00:42 +03:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
2009-05-12 00:24:07 +04:00
2010-03-18 01:00:43 +03:00
if ( status ) {
spin_lock_irqsave ( & port - > lock , flags ) ;
2009-12-23 11:10:48 +03:00
kfifo_reset_out ( & port - > write_fifo ) ;
2010-03-18 01:00:43 +03:00
spin_unlock_irqrestore ( & port - > lock , flags ) ;
} else {
2009-08-28 23:54:27 +04:00
usb_serial_generic_write_start ( port ) ;
2010-03-18 01:00:43 +03:00
}
2005-04-17 02:20:36 +04:00
}
2009-08-28 23:54:27 +04:00
2010-02-27 16:06:07 +03:00
if ( status )
dbg ( " %s - non-zero urb status: %d " , __func__ , status ) ;
2006-05-23 08:58:49 +04:00
usb_serial_port_softint ( port ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 20:48:18 +03:00
EXPORT_SYMBOL_GPL ( usb_serial_generic_write_bulk_callback ) ;
2005-04-17 02:20:36 +04:00
2008-07-22 14:09:07 +04:00
void usb_serial_generic_throttle ( struct tty_struct * tty )
2007-02-01 22:08:18 +03:00
{
2008-07-22 14:09:07 +04:00
struct usb_serial_port * port = tty - > driver_data ;
2007-02-01 22:08:18 +03:00
unsigned long flags ;
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 22:08:18 +03: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 ) ;
}
2008-07-22 14:09:07 +04:00
void usb_serial_generic_unthrottle ( struct tty_struct * tty )
2007-02-01 22:08:18 +03:00
{
2008-07-22 14:09:07 +04:00
struct usb_serial_port * port = tty - > driver_data ;
2007-02-01 22:08:18 +03:00
int was_throttled ;
unsigned long flags ;
2008-03-04 03:08:34 +03:00
dbg ( " %s - port %d " , __func__ , port - > number ) ;
2007-02-01 22:08:18 +03:00
/* Clear the throttle flags */
spin_lock_irqsave ( & port - > lock , flags ) ;
was_throttled = port - > throttled ;
port - > throttled = port - > throttle_req = 0 ;
spin_unlock_irqrestore ( & port - > lock , flags ) ;
if ( was_throttled ) {
2007-05-07 14:09:33 +04:00
/* Resume reading from device */
2009-09-24 22:20:20 +04:00
flush_and_resubmit_read_urb ( port ) ;
2007-02-01 22:08:18 +03:00
}
}
2010-03-25 21:29:16 +03:00
# ifdef CONFIG_MAGIC_SYSRQ
2009-07-09 16:36:22 +04:00
int usb_serial_handle_sysrq_char ( struct tty_struct * tty ,
struct usb_serial_port * port , unsigned int ch )
2009-05-12 00:24:09 +04:00
{
2010-03-09 06:50:12 +03:00
if ( port - > sysrq & & port - > port . console ) {
2009-05-12 00:24:09 +04:00
if ( ch & & time_before ( jiffies , port - > sysrq ) ) {
2009-07-09 16:36:22 +04:00
handle_sysrq ( ch , tty ) ;
2009-05-12 00:24:09 +04:00
port - > sysrq = 0 ;
return 1 ;
}
port - > sysrq = 0 ;
}
return 0 ;
}
2010-03-25 21:29:16 +03: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-12 00:24:09 +04: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 23:54:27 +04: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 18:05:47 +03:00
if ( ! test_bit ( ASYNCB_INITIALIZED , & port - > port . flags ) )
2009-08-28 23:54:27 +04:00
continue ;
if ( port - > read_urb ) {
r = usb_submit_urb ( port - > read_urb , GFP_NOIO ) ;
if ( r < 0 )
c + + ;
}
if ( port - > write_urb ) {
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 19:53:55 +04:00
void usb_serial_generic_disconnect ( struct usb_serial * serial )
2005-04-17 02:20:36 +04:00
{
int i ;
2008-03-04 03:08:34 +03:00
dbg ( " %s " , __func__ ) ;
2005-04-17 02:20:36 +04:00
/* stop reads and writes on all ports */
2008-07-22 14:11:55 +04:00
for ( i = 0 ; i < serial - > num_ports ; + + i )
2005-04-17 02:20:36 +04:00
generic_cleanup ( serial - > port [ i ] ) ;
}
2009-06-02 19:53:55 +04:00
void usb_serial_generic_release ( struct usb_serial * serial )
{
dbg ( " %s " , __func__ ) ;
}