2017-11-03 11:28:30 +01:00
// SPDX-License-Identifier: GPL-2.0+
2007-10-26 13:51:49 +02:00
/*
* Infinity Unlimited USB Phoenix driver
*
2010-05-21 11:53:25 +01:00
* Copyright ( C ) 2010 James Courtier - Dutton ( James @ superbug . co . uk )
2007-10-26 13:51:49 +02:00
* Copyright ( C ) 2007 Alain Degreffe ( eczema @ ecze . com )
*
* Original code taken from iuutool ( Copyright ( C ) 2006 Juan Carlos Borrà ¡ s )
*
* And tested with help of WB Electronics
*/
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/slab.h>
# include <linux/tty.h>
# include <linux/tty_driver.h>
# include <linux/tty_flip.h>
# include <linux/serial.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/spinlock.h>
# include <linux/uaccess.h>
# include <linux/usb.h>
# include <linux/usb/serial.h>
# include "iuu_phoenix.h"
# include <linux/random.h>
# define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
2010-01-10 15:34:24 +01:00
static const struct usb_device_id id_table [ ] = {
2007-10-26 13:51:49 +02:00
{ USB_DEVICE ( IUU_USB_VENDOR_ID , IUU_USB_PRODUCT_ID ) } ,
{ } /* Terminating entry */
} ;
MODULE_DEVICE_TABLE ( usb , id_table ) ;
/* turbo parameter */
static int boost = 100 ;
static int clockmode = 1 ;
static int cdmode = 1 ;
static int iuu_cardin ;
static int iuu_cardout ;
2012-01-13 09:32:20 +10:30
static bool xmas ;
2009-08-18 21:05:57 +02:00
static int vcc_default = 5 ;
2007-10-26 13:51:49 +02:00
2012-10-18 10:52:17 +02:00
static int iuu_create_sysfs_attrs ( struct usb_serial_port * port ) ;
static int iuu_remove_sysfs_attrs ( struct usb_serial_port * port ) ;
2007-10-26 13:51:49 +02:00
static void read_rxcmd_callback ( struct urb * urb ) ;
struct iuu_private {
spinlock_t lock ; /* store irq state */
u8 line_status ;
int tiostatus ; /* store IUART SIGNAL for tiocmget call */
u8 reset ; /* if 1 reset is needed */
int poll ; /* number of poll */
u8 * writebuf ; /* buffer for writing to device */
int writelen ; /* num of byte to write to device */
u8 * buf ; /* used for initialize speed */
u8 len ;
2009-08-18 21:05:55 +02:00
int vcc ; /* vcc (either 3 or 5 V) */
2010-05-21 11:53:25 +01:00
u32 boost ;
u32 clk ;
2007-10-26 13:51:49 +02:00
} ;
2012-10-17 13:34:59 +02:00
static int iuu_port_probe ( struct usb_serial_port * port )
2007-10-26 13:51:49 +02:00
{
struct iuu_private * priv ;
2012-10-18 10:52:17 +02:00
int ret ;
2012-09-14 15:08:28 -07:00
2007-10-26 13:51:49 +02:00
priv = kzalloc ( sizeof ( struct iuu_private ) , GFP_KERNEL ) ;
if ( ! priv )
return - ENOMEM ;
2012-10-17 13:34:59 +02:00
priv - > buf = kzalloc ( 256 , GFP_KERNEL ) ;
if ( ! priv - > buf ) {
2007-10-26 13:51:49 +02:00
kfree ( priv ) ;
return - ENOMEM ;
}
2012-10-17 13:34:59 +02:00
priv - > writebuf = kzalloc ( 256 , GFP_KERNEL ) ;
if ( ! priv - > writebuf ) {
kfree ( priv - > buf ) ;
kfree ( priv ) ;
return - ENOMEM ;
}
2009-08-18 21:05:57 +02:00
priv - > vcc = vcc_default ;
2007-10-26 13:51:49 +02:00
spin_lock_init ( & priv - > lock ) ;
2012-10-17 13:34:59 +02:00
usb_set_serial_port_data ( port , priv ) ;
2012-10-18 10:52:17 +02:00
ret = iuu_create_sysfs_attrs ( port ) ;
if ( ret ) {
kfree ( priv - > writebuf ) ;
kfree ( priv - > buf ) ;
kfree ( priv ) ;
return ret ;
}
2007-10-26 13:51:49 +02:00
return 0 ;
}
2012-10-17 13:34:59 +02:00
static int iuu_port_remove ( struct usb_serial_port * port )
2007-10-26 13:51:49 +02:00
{
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2012-10-18 10:52:17 +02:00
iuu_remove_sysfs_attrs ( port ) ;
2012-10-17 13:34:59 +02:00
kfree ( priv - > writebuf ) ;
kfree ( priv - > buf ) ;
kfree ( priv ) ;
2007-10-26 13:51:49 +02:00
2012-10-17 13:34:59 +02:00
return 0 ;
2007-10-26 13:51:49 +02:00
}
2011-02-14 16:26:50 +00:00
static int iuu_tiocmset ( struct tty_struct * tty ,
2007-10-26 13:51:49 +02:00
unsigned int set , unsigned int clear )
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2007-10-26 13:51:49 +02:00
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2008-02-20 21:39:25 +00:00
unsigned long flags ;
2007-10-26 13:51:49 +02:00
2008-02-20 21:39:25 +00:00
/* FIXME: locking on tiomstatus */
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s msg : SET = 0x%04x, CLEAR = 0x%04x \n " ,
__func__ , set , clear ) ;
2008-02-20 21:39:25 +00:00
spin_lock_irqsave ( & priv - > lock , flags ) ;
2007-10-26 13:51:49 +02:00
2010-05-21 11:53:25 +01:00
if ( ( set & TIOCM_RTS ) & & ! ( priv - > tiostatus = = TIOCM_RTS ) ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s TIOCMSET RESET called !!! \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
priv - > reset = 1 ;
}
2010-05-21 11:53:25 +01:00
if ( set & TIOCM_RTS )
priv - > tiostatus = TIOCM_RTS ;
2008-02-20 21:39:25 +00:00
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
2007-10-26 13:51:49 +02:00
return 0 ;
}
/* This is used to provide a carrier detect mechanism
* When a card is present , the response is 0x00
* When no card , the reader respond with TIOCM_CD
* This is known as CD autodetect mechanism
*/
2011-02-14 16:26:14 +00:00
static int iuu_tiocmget ( struct tty_struct * tty )
2007-10-26 13:51:49 +02:00
{
2008-07-22 11:09:07 +01:00
struct usb_serial_port * port = tty - > driver_data ;
2007-10-26 13:51:49 +02:00
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2008-02-20 21:39:25 +00:00
unsigned long flags ;
int rc ;
spin_lock_irqsave ( & priv - > lock , flags ) ;
rc = priv - > tiostatus ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
return rc ;
2007-10-26 13:51:49 +02:00
}
static void iuu_rxcmd ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
int result ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
if ( status ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - status = %d \n " , __func__ , status ) ;
2007-10-26 13:51:49 +02:00
/* error stop all */
return ;
}
memset ( port - > write_urb - > transfer_buffer , IUU_UART_RX , 1 ) ;
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 1 ,
read_rxcmd_callback , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
}
static int iuu_reset ( struct usb_serial_port * port , u8 wt )
{
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
int result ;
char * buf_ptr = port - > write_urb - > transfer_buffer ;
/* Prepare the reset sequence */
* buf_ptr + + = IUU_RST_SET ;
* buf_ptr + + = IUU_DELAY_MS ;
* buf_ptr + + = wt ;
* buf_ptr = IUU_RST_CLEAR ;
/* send the sequence */
usb_fill_bulk_urb ( port - > write_urb ,
port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 4 , iuu_rxcmd , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
priv - > reset = 0 ;
return result ;
}
/* Status Function
* Return value is
* 0x00 = no card
* 0x01 = smartcard
* 0x02 = sim card
*/
static void iuu_update_status_callback ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
u8 * st ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
if ( status ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - status = %d \n " , __func__ , status ) ;
2007-10-26 13:51:49 +02:00
/* error stop all */
return ;
}
st = urb - > transfer_buffer ;
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - enter \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
if ( urb - > actual_length = = 1 ) {
switch ( st [ 0 ] ) {
case 0x1 :
priv - > tiostatus = iuu_cardout ;
break ;
case 0x0 :
priv - > tiostatus = iuu_cardin ;
break ;
default :
priv - > tiostatus = iuu_cardin ;
}
}
iuu_rxcmd ( urb ) ;
}
static void iuu_status_callback ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
int result ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
2007-10-26 13:51:49 +02:00
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - status = %d \n " , __func__ , status ) ;
2007-10-26 13:51:49 +02:00
usb_fill_bulk_urb ( port - > read_urb , port - > serial - > dev ,
usb_rcvbulkpipe ( port - > serial - > dev ,
port - > bulk_in_endpointAddress ) ,
port - > read_urb - > transfer_buffer , 256 ,
iuu_update_status_callback , port ) ;
result = usb_submit_urb ( port - > read_urb , GFP_ATOMIC ) ;
}
static int iuu_status ( struct usb_serial_port * port )
{
int result ;
memset ( port - > write_urb - > transfer_buffer , IUU_GET_STATE_REGISTER , 1 ) ;
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 1 ,
iuu_status_callback , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
return result ;
}
static int bulk_immediate ( struct usb_serial_port * port , u8 * buf , u8 count )
{
int status ;
struct usb_serial * serial = port - > serial ;
int actual = 0 ;
/* send the data out the bulk port */
status =
usb_bulk_msg ( serial - > dev ,
usb_sndbulkpipe ( serial - > dev ,
port - > bulk_out_endpointAddress ) , buf ,
2013-05-27 14:44:42 +02:00
count , & actual , 1000 ) ;
2007-10-26 13:51:49 +02:00
2008-07-22 11:12:59 +01:00
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - error = %2x \n " , __func__ , status ) ;
2008-07-22 11:12:59 +01:00
else
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - write OK ! \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
static int read_immediate ( struct usb_serial_port * port , u8 * buf , u8 count )
{
int status ;
struct usb_serial * serial = port - > serial ;
int actual = 0 ;
/* send the data out the bulk port */
status =
usb_bulk_msg ( serial - > dev ,
usb_rcvbulkpipe ( serial - > dev ,
port - > bulk_in_endpointAddress ) , buf ,
2013-05-27 14:44:42 +02:00
count , & actual , 1000 ) ;
2007-10-26 13:51:49 +02:00
2008-07-22 11:12:59 +01:00
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - error = %2x \n " , __func__ , status ) ;
2008-07-22 11:12:59 +01:00
else
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - read OK ! \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
static int iuu_led ( struct usb_serial_port * port , unsigned int R ,
unsigned int G , unsigned int B , u8 f )
{
int status ;
u8 * buf ;
buf = kmalloc ( 8 , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
buf [ 0 ] = IUU_SET_LED ;
buf [ 1 ] = R & 0xFF ;
buf [ 2 ] = ( R > > 8 ) & 0xFF ;
buf [ 3 ] = G & 0xFF ;
buf [ 4 ] = ( G > > 8 ) & 0xFF ;
buf [ 5 ] = B & 0xFF ;
buf [ 6 ] = ( B > > 8 ) & 0xFF ;
buf [ 7 ] = f ;
status = bulk_immediate ( port , buf , 8 ) ;
kfree ( buf ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - led error status = %2x \n " , __func__ , status ) ;
2007-10-26 13:51:49 +02:00
else
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - led OK ! \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return IUU_OPERATION_OK ;
}
static void iuu_rgbf_fill_buffer ( u8 * buf , u8 r1 , u8 r2 , u8 g1 , u8 g2 , u8 b1 ,
u8 b2 , u8 freq )
{
* buf + + = IUU_SET_LED ;
* buf + + = r1 ;
* buf + + = r2 ;
* buf + + = g1 ;
* buf + + = g2 ;
* buf + + = b1 ;
* buf + + = b2 ;
* buf = freq ;
}
static void iuu_led_activity_on ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
int result ;
char * buf_ptr = port - > write_urb - > transfer_buffer ;
* buf_ptr + + = IUU_SET_LED ;
2016-02-04 19:01:29 +01:00
if ( xmas ) {
2007-10-26 13:51:49 +02:00
get_random_bytes ( buf_ptr , 6 ) ;
* ( buf_ptr + 7 ) = 1 ;
} else {
iuu_rgbf_fill_buffer ( buf_ptr , 255 , 255 , 0 , 0 , 0 , 0 , 255 ) ;
}
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 8 ,
iuu_rxcmd , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
}
static void iuu_led_activity_off ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
int result ;
char * buf_ptr = port - > write_urb - > transfer_buffer ;
2016-02-04 19:01:29 +01:00
if ( xmas ) {
2007-10-26 13:51:49 +02:00
iuu_rxcmd ( urb ) ;
return ;
} else {
* buf_ptr + + = IUU_SET_LED ;
iuu_rgbf_fill_buffer ( buf_ptr , 0 , 0 , 255 , 255 , 0 , 0 , 255 ) ;
}
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 8 ,
iuu_rxcmd , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
}
static int iuu_clk ( struct usb_serial_port * port , int dwFrq )
{
int status ;
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
int Count = 0 ;
u8 FrqGenAdr = 0x69 ;
u8 DIV = 0 ; /* 8bit */
u8 XDRV = 0 ; /* 8bit */
u8 PUMP = 0 ; /* 3bit */
u8 PBmsb = 0 ; /* 2bit */
u8 PBlsb = 0 ; /* 8bit */
u8 PO = 0 ; /* 1bit */
u8 Q = 0 ; /* 7bit */
/* 24bit = 3bytes */
unsigned int P = 0 ;
unsigned int P2 = 0 ;
int frq = ( int ) dwFrq ;
if ( frq = = 0 ) {
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ;
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x09 ;
priv - > buf [ Count + + ] = 0x00 ;
status = bulk_immediate ( port , ( u8 * ) priv - > buf , Count ) ;
if ( status ! = 0 ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - write error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
} else if ( frq = = 3579000 ) {
DIV = 100 ;
P = 1193 ;
Q = 40 ;
XDRV = 0 ;
} else if ( frq = = 3680000 ) {
DIV = 105 ;
P = 161 ;
Q = 5 ;
XDRV = 0 ;
} else if ( frq = = 6000000 ) {
DIV = 66 ;
P = 66 ;
Q = 2 ;
XDRV = 0x28 ;
} else {
unsigned int result = 0 ;
unsigned int tmp = 0 ;
unsigned int check ;
unsigned int check2 ;
char found = 0x00 ;
unsigned int lQ = 2 ;
unsigned int lP = 2055 ;
unsigned int lDiv = 4 ;
for ( lQ = 2 ; lQ < = 47 & & ! found ; lQ + + )
for ( lP = 2055 ; lP > = 8 & & ! found ; lP - - )
for ( lDiv = 4 ; lDiv < = 127 & & ! found ; lDiv + + ) {
tmp = ( 12000000 / lDiv ) * ( lP / lQ ) ;
if ( abs ( ( int ) ( tmp - frq ) ) <
abs ( ( int ) ( frq - result ) ) ) {
check2 = ( 12000000 / lQ ) ;
if ( check2 < 250000 )
continue ;
check = ( 12000000 / lQ ) * lP ;
if ( check > 400000000 )
continue ;
if ( check < 100000000 )
continue ;
if ( lDiv < 4 | | lDiv > 127 )
continue ;
result = tmp ;
P = lP ;
DIV = lDiv ;
Q = lQ ;
if ( result = = frq )
found = 0x01 ;
}
}
}
P2 = ( ( P - PO ) / 2 ) - 4 ;
PUMP = 0x04 ;
PBmsb = ( P2 > > 8 & 0x03 ) ;
PBlsb = P2 & 0xFF ;
PO = ( P > > 10 ) & 0x01 ;
Q = Q - 2 ;
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x09 ;
priv - > buf [ Count + + ] = 0x20 ; /* Adr = 0x09 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x0C ;
priv - > buf [ Count + + ] = DIV ; /* Adr = 0x0C */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x12 ;
priv - > buf [ Count + + ] = XDRV ; /* Adr = 0x12 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x13 ;
priv - > buf [ Count + + ] = 0x6B ; /* Adr = 0x13 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x40 ;
priv - > buf [ Count + + ] = ( 0xC0 | ( ( PUMP & 0x07 ) < < 2 ) ) |
( PBmsb & 0x03 ) ; /* Adr = 0x40 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x41 ;
priv - > buf [ Count + + ] = PBlsb ; /* Adr = 0x41 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x42 ;
priv - > buf [ Count + + ] = Q | ( ( ( PO & 0x01 ) < < 7 ) ) ; /* Adr = 0x42 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x44 ;
priv - > buf [ Count + + ] = ( char ) 0xFF ; /* Adr = 0x44 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x45 ;
priv - > buf [ Count + + ] = ( char ) 0xFE ; /* Adr = 0x45 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x46 ;
priv - > buf [ Count + + ] = 0x7F ; /* Adr = 0x46 */
priv - > buf [ Count + + ] = IUU_UART_WRITE_I2C ; /* 0x4C */
priv - > buf [ Count + + ] = FrqGenAdr < < 1 ;
priv - > buf [ Count + + ] = 0x47 ;
priv - > buf [ Count + + ] = ( char ) 0x84 ; /* Adr = 0x47 */
status = bulk_immediate ( port , ( u8 * ) priv - > buf , Count ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - write error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
static int iuu_uart_flush ( struct usb_serial_port * port )
{
2012-09-14 15:08:28 -07:00
struct device * dev = & port - > dev ;
2007-10-26 13:51:49 +02:00
int i ;
int status ;
u8 rxcmd = IUU_UART_RX ;
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
if ( iuu_led ( port , 0xF000 , 0 , 0 , 0xFF ) < 0 )
return - EIO ;
for ( i = 0 ; i < 2 ; i + + ) {
status = bulk_immediate ( port , & rxcmd , 1 ) ;
if ( status ! = IUU_OPERATION_OK ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - uart_flush_write error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
status = read_immediate ( port , & priv - > len , 1 ) ;
if ( status ! = IUU_OPERATION_OK ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - uart_flush_read error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
if ( priv - > len > 0 ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - uart_flush datalen is : %i \n " , __func__ , priv - > len ) ;
2007-10-26 13:51:49 +02:00
status = read_immediate ( port , priv - > buf , priv - > len ) ;
if ( status ! = IUU_OPERATION_OK ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - uart_flush_read error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
return status ;
}
}
}
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - uart_flush_read OK! \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
iuu_led ( port , 0 , 0xF000 , 0 , 0xFF ) ;
return status ;
}
static void read_buf_callback ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
unsigned char * data = urb - > transfer_buffer ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
2007-10-26 13:51:49 +02:00
2008-12-10 16:00:30 -08:00
if ( status ) {
if ( status = = - EPROTO ) {
2007-10-26 13:51:49 +02:00
/* reschedule needed */
}
return ;
}
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - %i chars to write \n " , __func__ , urb - > actual_length ) ;
2017-04-03 11:57:14 +02:00
if ( urb - > actual_length ) {
2013-01-03 15:53:04 +01:00
tty_insert_flip_string ( & port - > port , data , urb - > actual_length ) ;
2013-01-03 15:53:06 +01:00
tty_flip_buffer_push ( & port - > port ) ;
2007-10-26 13:51:49 +02:00
}
iuu_led_activity_on ( urb ) ;
}
static int iuu_bulk_write ( struct usb_serial_port * port )
{
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2008-05-06 20:42:31 -07:00
unsigned long flags ;
2007-10-26 13:51:49 +02:00
int result ;
2009-06-11 12:52:26 +01:00
int buf_len ;
2007-10-26 13:51:49 +02:00
char * buf_ptr = port - > write_urb - > transfer_buffer ;
2009-06-11 12:52:26 +01:00
spin_lock_irqsave ( & priv - > lock , flags ) ;
2007-10-26 13:51:49 +02:00
* buf_ptr + + = IUU_UART_ESC ;
* buf_ptr + + = IUU_UART_TX ;
* buf_ptr + + = priv - > writelen ;
2009-06-11 12:52:26 +01:00
memcpy ( buf_ptr , priv - > writebuf , priv - > writelen ) ;
buf_len = priv - > writelen ;
priv - > writelen = 0 ;
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - writing %i chars : %*ph \n " , __func__ ,
buf_len , buf_len , buf_ptr ) ;
2007-10-26 13:51:49 +02:00
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
2009-06-11 12:52:26 +01:00
port - > write_urb - > transfer_buffer , buf_len + 3 ,
2007-10-26 13:51:49 +02:00
iuu_rxcmd , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_ATOMIC ) ;
usb_serial_port_softint ( port ) ;
return result ;
}
static int iuu_read_buf ( struct usb_serial_port * port , int len )
{
int result ;
usb_fill_bulk_urb ( port - > read_urb , port - > serial - > dev ,
usb_rcvbulkpipe ( port - > serial - > dev ,
port - > bulk_in_endpointAddress ) ,
port - > read_urb - > transfer_buffer , len ,
read_buf_callback , port ) ;
result = usb_submit_urb ( port - > read_urb , GFP_ATOMIC ) ;
return result ;
}
static void iuu_uart_read_callback ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2008-05-06 20:42:31 -07:00
unsigned long flags ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
2007-10-26 13:51:49 +02:00
int error = 0 ;
int len = 0 ;
unsigned char * data = urb - > transfer_buffer ;
priv - > poll + + ;
2008-12-10 16:00:30 -08:00
if ( status ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - status = %d \n " , __func__ , status ) ;
2007-10-26 13:51:49 +02:00
/* error stop all */
return ;
}
2017-04-03 11:57:14 +02:00
if ( urb - > actual_length = = 1 )
2007-10-26 13:51:49 +02:00
len = ( int ) data [ 0 ] ;
if ( urb - > actual_length > 1 ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - urb->actual_length = %i \n " , __func__ ,
2007-10-26 13:51:49 +02:00
urb - > actual_length ) ;
error = 1 ;
return ;
}
/* if len > 0 call readbuf */
if ( len > 0 & & error = = 0 ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - call read buf - len to read is %i \n " ,
2008-03-03 16:08:34 -08:00
__func__ , len ) ;
2007-10-26 13:51:49 +02:00
status = iuu_read_buf ( port , len ) ;
return ;
}
/* need to update status ? */
if ( priv - > poll > 99 ) {
status = iuu_status ( port ) ;
priv - > poll = 0 ;
return ;
}
/* reset waiting ? */
if ( priv - > reset = = 1 ) {
status = iuu_reset ( port , 0xC ) ;
return ;
}
/* Writebuf is waiting */
spin_lock_irqsave ( & priv - > lock , flags ) ;
if ( priv - > writelen > 0 ) {
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
status = iuu_bulk_write ( port ) ;
return ;
}
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
/* if nothing to write call again rxcmd */
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - rxcmd recall \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
iuu_led_activity_off ( urb ) ;
}
2008-07-22 11:09:07 +01:00
static int iuu_uart_write ( struct tty_struct * tty , struct usb_serial_port * port ,
const u8 * buf , int count )
2007-10-26 13:51:49 +02:00
{
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2008-05-06 20:42:31 -07:00
unsigned long flags ;
2007-10-26 13:51:49 +02:00
if ( count > 256 )
return - ENOMEM ;
spin_lock_irqsave ( & priv - > lock , flags ) ;
2009-06-11 12:52:26 +01:00
2007-10-26 13:51:49 +02:00
/* fill the buffer */
2009-06-11 12:52:26 +01:00
memcpy ( priv - > writebuf + priv - > writelen , buf , count ) ;
priv - > writelen + = count ;
2007-10-26 13:51:49 +02:00
spin_unlock_irqrestore ( & priv - > lock , flags ) ;
2008-07-22 11:12:59 +01:00
return count ;
2007-10-26 13:51:49 +02:00
}
static void read_rxcmd_callback ( struct urb * urb )
{
2008-02-24 18:41:47 +08:00
struct usb_serial_port * port = urb - > context ;
2007-10-26 13:51:49 +02:00
int result ;
2008-12-10 16:00:30 -08:00
int status = urb - > status ;
2007-10-26 13:51:49 +02:00
2008-12-10 16:00:30 -08:00
if ( status ) {
2007-10-26 13:51:49 +02:00
/* error stop all */
return ;
}
usb_fill_bulk_urb ( port - > read_urb , port - > serial - > dev ,
usb_rcvbulkpipe ( port - > serial - > dev ,
port - > bulk_in_endpointAddress ) ,
port - > read_urb - > transfer_buffer , 256 ,
iuu_uart_read_callback , port ) ;
result = usb_submit_urb ( port - > read_urb , GFP_ATOMIC ) ;
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - submit result = %d \n " , __func__ , result ) ;
2007-10-26 13:51:49 +02:00
}
static int iuu_uart_on ( struct usb_serial_port * port )
{
int status ;
u8 * buf ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 13:55:00 -07:00
buf = kmalloc ( 4 , GFP_KERNEL ) ;
2007-10-26 13:51:49 +02:00
if ( ! buf )
return - ENOMEM ;
buf [ 0 ] = IUU_UART_ENABLE ;
buf [ 1 ] = ( u8 ) ( ( IUU_BAUD_9600 > > 8 ) & 0x00FF ) ;
buf [ 2 ] = ( u8 ) ( 0x00FF & IUU_BAUD_9600 ) ;
2009-06-11 12:53:24 +01:00
buf [ 3 ] = ( u8 ) ( 0x0F0 & IUU_ONE_STOP_BIT ) | ( 0x07 & IUU_PARITY_EVEN ) ;
2007-10-26 13:51:49 +02:00
status = bulk_immediate ( port , buf , 4 ) ;
if ( status ! = IUU_OPERATION_OK ) {
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - uart_on error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
goto uart_enable_failed ;
}
/* iuu_reset() the card after iuu_uart_on() */
status = iuu_uart_flush ( port ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - uart_flush error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
uart_enable_failed :
kfree ( buf ) ;
return status ;
}
2014-01-02 19:29:24 +05:30
/* Disables the IUU UART (a.k.a. the Phoenix voiderface) */
2007-10-26 13:51:49 +02:00
static int iuu_uart_off ( struct usb_serial_port * port )
{
int status ;
u8 * buf ;
buf = kmalloc ( 1 , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
buf [ 0 ] = IUU_UART_DISABLE ;
status = bulk_immediate ( port , buf , 1 ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - uart_off error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
kfree ( buf ) ;
return status ;
}
2010-05-21 11:53:25 +01:00
static int iuu_uart_baud ( struct usb_serial_port * port , u32 baud_base ,
2007-10-26 13:51:49 +02:00
u32 * actual , u8 parity )
{
int status ;
2010-05-21 11:53:25 +01:00
u32 baud ;
2007-10-26 13:51:49 +02:00
u8 * dataout ;
u8 DataCount = 0 ;
u8 T1Frekvens = 0 ;
u8 T1reload = 0 ;
unsigned int T1FrekvensHZ = 0 ;
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - enter baud_base=%d \n " , __func__ , baud_base ) ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 13:55:00 -07:00
dataout = kmalloc ( 5 , GFP_KERNEL ) ;
2007-10-26 13:51:49 +02:00
if ( ! dataout )
return - ENOMEM ;
2010-05-21 11:53:25 +01:00
/*baud = (((priv->clk / 35) * baud_base) / 100000); */
baud = baud_base ;
2007-10-26 13:51:49 +02:00
if ( baud < 1200 | | baud > 230400 ) {
kfree ( dataout ) ;
return IUU_INVALID_PARAMETER ;
}
if ( baud > 977 ) {
T1Frekvens = 3 ;
T1FrekvensHZ = 500000 ;
}
if ( baud > 3906 ) {
T1Frekvens = 2 ;
T1FrekvensHZ = 2000000 ;
}
if ( baud > 11718 ) {
T1Frekvens = 1 ;
T1FrekvensHZ = 6000000 ;
}
if ( baud > 46875 ) {
T1Frekvens = 0 ;
T1FrekvensHZ = 24000000 ;
}
T1reload = 256 - ( u8 ) ( T1FrekvensHZ / ( baud * 2 ) ) ;
/* magic number here: ENTER_FIRMWARE_UPDATE; */
dataout [ DataCount + + ] = IUU_UART_ESC ;
/* magic number here: CHANGE_BAUD; */
dataout [ DataCount + + ] = IUU_UART_CHANGE ;
dataout [ DataCount + + ] = T1Frekvens ;
dataout [ DataCount + + ] = T1reload ;
* actual = ( T1FrekvensHZ / ( 256 - T1reload ) ) / 2 ;
switch ( parity & 0x0F ) {
case IUU_PARITY_NONE :
dataout [ DataCount + + ] = 0x00 ;
break ;
case IUU_PARITY_EVEN :
dataout [ DataCount + + ] = 0x01 ;
break ;
case IUU_PARITY_ODD :
dataout [ DataCount + + ] = 0x02 ;
break ;
case IUU_PARITY_MARK :
dataout [ DataCount + + ] = 0x03 ;
break ;
case IUU_PARITY_SPACE :
dataout [ DataCount + + ] = 0x04 ;
break ;
default :
kfree ( dataout ) ;
return IUU_INVALID_PARAMETER ;
break ;
}
switch ( parity & 0xF0 ) {
case IUU_ONE_STOP_BIT :
dataout [ DataCount - 1 ] | = IUU_ONE_STOP_BIT ;
break ;
case IUU_TWO_STOP_BITS :
dataout [ DataCount - 1 ] | = IUU_TWO_STOP_BITS ;
break ;
default :
kfree ( dataout ) ;
return IUU_INVALID_PARAMETER ;
break ;
}
status = bulk_immediate ( port , dataout , DataCount ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - uart_off error \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
kfree ( dataout ) ;
return status ;
}
2009-06-11 12:54:20 +01:00
static void iuu_set_termios ( struct tty_struct * tty ,
struct usb_serial_port * port , struct ktermios * old_termios )
{
const u32 supported_mask = CMSPAR | PARENB | PARODD ;
2010-05-21 11:53:25 +01:00
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2012-07-14 15:31:47 +01:00
unsigned int cflag = tty - > termios . c_cflag ;
2009-06-11 12:54:20 +01:00
int status ;
u32 actual ;
u32 parity ;
int csize = CS7 ;
2010-05-21 11:53:25 +01:00
int baud ;
2009-06-11 12:54:20 +01:00
u32 newval = cflag & supported_mask ;
2010-05-21 11:53:25 +01:00
/* Just use the ospeed. ispeed should be the same. */
2012-07-14 15:31:47 +01:00
baud = tty - > termios . c_ospeed ;
2010-05-21 11:53:25 +01:00
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - enter c_ospeed or baud=%d \n " , __func__ , baud ) ;
2010-05-21 11:53:25 +01:00
2009-06-11 12:54:20 +01:00
/* compute the parity parameter */
parity = 0 ;
if ( cflag & CMSPAR ) { /* Using mark space */
if ( cflag & PARODD )
parity | = IUU_PARITY_SPACE ;
else
parity | = IUU_PARITY_MARK ;
} else if ( ! ( cflag & PARENB ) ) {
parity | = IUU_PARITY_NONE ;
csize = CS8 ;
} else if ( cflag & PARODD )
parity | = IUU_PARITY_ODD ;
else
parity | = IUU_PARITY_EVEN ;
parity | = ( cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT ) ;
/* set it */
status = iuu_uart_baud ( port ,
2010-05-21 11:53:25 +01:00
baud * priv - > boost / 100 ,
2009-06-11 12:54:20 +01:00
& actual , parity ) ;
/* set the termios value to the real one, so the user now what has
* changed . We support few fields so its easies to copy the old hw
* settings back over and then adjust them
*/
2010-05-21 11:53:25 +01:00
if ( old_termios )
2012-07-14 15:31:47 +01:00
tty_termios_copy_hw ( & tty - > termios , old_termios ) ;
2009-06-11 12:54:20 +01:00
if ( status ! = 0 ) /* Set failed - return old bits */
return ;
/* Re-encode speed, parity and csize */
tty_encode_baud_rate ( tty , baud , baud ) ;
2012-07-14 15:31:47 +01:00
tty - > termios . c_cflag & = ~ ( supported_mask | CSIZE ) ;
tty - > termios . c_cflag | = newval | csize ;
2009-06-11 12:54:20 +01:00
}
2009-06-11 12:26:29 +01:00
static void iuu_close ( struct usb_serial_port * port )
2007-10-26 13:51:49 +02:00
{
/* iuu_led (port,255,0,0,0); */
iuu_uart_off ( port ) ;
2013-03-21 12:36:31 +01:00
usb_kill_urb ( port - > write_urb ) ;
usb_kill_urb ( port - > read_urb ) ;
iuu_led ( port , 0 , 0 , 0xF000 , 0xFF ) ;
2007-10-26 13:51:49 +02:00
}
2009-09-19 13:13:33 -07:00
static void iuu_init_termios ( struct tty_struct * tty )
{
2012-07-14 15:31:47 +01:00
tty - > termios = tty_std_termios ;
tty - > termios . c_cflag = CLOCAL | CREAD | CS8 | B9600
2009-09-19 13:13:33 -07:00
| TIOCM_CTS | CSTOPB | PARENB ;
2012-07-14 15:31:47 +01:00
tty - > termios . c_ispeed = 9600 ;
tty - > termios . c_ospeed = 9600 ;
tty - > termios . c_lflag = 0 ;
tty - > termios . c_oflag = 0 ;
tty - > termios . c_iflag = 0 ;
2009-09-19 13:13:33 -07:00
}
2009-09-19 13:13:26 -07:00
static int iuu_open ( struct tty_struct * tty , struct usb_serial_port * port )
2007-10-26 13:51:49 +02:00
{
struct usb_serial * serial = port - > serial ;
2012-09-14 15:08:28 -07:00
struct device * dev = & port - > dev ;
2007-10-26 13:51:49 +02:00
int result ;
2010-05-21 11:53:25 +01:00
int baud ;
2007-10-26 13:51:49 +02:00
u32 actual ;
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
2012-07-14 15:31:47 +01:00
baud = tty - > termios . c_ospeed ;
2010-05-21 11:53:25 +01:00
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - baud %d \n " , __func__ , baud ) ;
2007-10-26 13:51:49 +02:00
usb_clear_halt ( serial - > dev , port - > write_urb - > pipe ) ;
usb_clear_halt ( serial - > dev , port - > read_urb - > pipe ) ;
2009-09-19 13:13:33 -07:00
priv - > poll = 0 ;
2007-10-26 13:51:49 +02:00
# define SOUP(a, b, c, d) do { \
result = usb_control_msg ( port - > serial - > dev , \
usb_sndctrlpipe ( port - > serial - > dev , 0 ) , \
b , a , c , d , NULL , 0 , 1000 ) ; \
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " 0x%x:0x%x:0x%x:0x%x %d \n " , a , b , c , d , result ) ; } while ( 0 )
2007-10-26 13:51:49 +02:00
/* This is not UART related but IUU USB driver related or something */
/* like that. Basically no IUU will accept any commands from the USB */
/* host unless it has received the following message */
/* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
SOUP ( 0x03 , 0x02 , 0x02 , 0x0 ) ;
2017-01-12 14:56:15 +01:00
2007-10-26 13:51:49 +02:00
iuu_led ( port , 0xF000 , 0xF000 , 0 , 0xFF ) ;
iuu_uart_on ( port ) ;
if ( boost < 100 )
boost = 100 ;
2010-05-21 11:53:25 +01:00
priv - > boost = boost ;
2007-10-26 13:51:49 +02:00
switch ( clockmode ) {
case 2 : /* 3.680 Mhz */
2010-05-21 11:53:25 +01:00
priv - > clk = IUU_CLK_3680000 ;
2007-10-26 13:51:49 +02:00
iuu_clk ( port , IUU_CLK_3680000 * boost / 100 ) ;
result =
2010-05-21 11:53:25 +01:00
iuu_uart_baud ( port , baud * boost / 100 , & actual ,
2007-10-26 13:51:49 +02:00
IUU_PARITY_EVEN ) ;
break ;
case 3 : /* 6.00 Mhz */
iuu_clk ( port , IUU_CLK_6000000 * boost / 100 ) ;
2010-05-21 11:53:25 +01:00
priv - > clk = IUU_CLK_6000000 ;
/* Ratio of 6000000 to 3500000 for baud 9600 */
2007-10-26 13:51:49 +02:00
result =
iuu_uart_baud ( port , 16457 * boost / 100 , & actual ,
IUU_PARITY_EVEN ) ;
break ;
default : /* 3.579 Mhz */
iuu_clk ( port , IUU_CLK_3579000 * boost / 100 ) ;
2010-05-21 11:53:25 +01:00
priv - > clk = IUU_CLK_3579000 ;
2007-10-26 13:51:49 +02:00
result =
2010-05-21 11:53:25 +01:00
iuu_uart_baud ( port , baud * boost / 100 , & actual ,
2007-10-26 13:51:49 +02:00
IUU_PARITY_EVEN ) ;
}
/* set the cardin cardout signals */
switch ( cdmode ) {
case 0 :
iuu_cardin = 0 ;
iuu_cardout = 0 ;
break ;
case 1 :
iuu_cardin = TIOCM_CD ;
iuu_cardout = 0 ;
break ;
case 2 :
iuu_cardin = 0 ;
iuu_cardout = TIOCM_CD ;
break ;
case 3 :
iuu_cardin = TIOCM_DSR ;
iuu_cardout = 0 ;
break ;
case 4 :
iuu_cardin = 0 ;
iuu_cardout = TIOCM_DSR ;
break ;
case 5 :
iuu_cardin = TIOCM_CTS ;
iuu_cardout = 0 ;
break ;
case 6 :
iuu_cardin = 0 ;
iuu_cardout = TIOCM_CTS ;
break ;
case 7 :
iuu_cardin = TIOCM_RNG ;
iuu_cardout = 0 ;
break ;
case 8 :
iuu_cardin = 0 ;
iuu_cardout = TIOCM_RNG ;
}
iuu_uart_flush ( port ) ;
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - initialization done \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
memset ( port - > write_urb - > transfer_buffer , IUU_UART_RX , 1 ) ;
usb_fill_bulk_urb ( port - > write_urb , port - > serial - > dev ,
usb_sndbulkpipe ( port - > serial - > dev ,
port - > bulk_out_endpointAddress ) ,
port - > write_urb - > transfer_buffer , 1 ,
read_rxcmd_callback , port ) ;
result = usb_submit_urb ( port - > write_urb , GFP_KERNEL ) ;
if ( result ) {
2012-09-14 15:08:28 -07:00
dev_err ( dev , " %s - failed submitting read urb, error %d \n " , __func__ , result ) ;
2009-06-11 12:26:29 +01:00
iuu_close ( port ) ;
2007-10-26 13:51:49 +02:00
} else {
2012-09-14 15:08:28 -07:00
dev_dbg ( dev , " %s - rxcmd OK \n " , __func__ ) ;
2007-10-26 13:51:49 +02:00
}
2011-11-10 14:58:30 +01:00
2007-10-26 13:51:49 +02:00
return result ;
}
2009-08-18 21:05:55 +02:00
/* how to change VCC */
static int iuu_vcc_set ( struct usb_serial_port * port , unsigned int vcc )
{
int status ;
u8 * buf ;
buf = kmalloc ( 5 , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
buf [ 0 ] = IUU_SET_VCC ;
buf [ 1 ] = vcc & 0xFF ;
buf [ 2 ] = ( vcc > > 8 ) & 0xFF ;
buf [ 3 ] = ( vcc > > 16 ) & 0xFF ;
buf [ 4 ] = ( vcc > > 24 ) & 0xFF ;
status = bulk_immediate ( port , buf , 5 ) ;
kfree ( buf ) ;
if ( status ! = IUU_OPERATION_OK )
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - vcc error status = %2x \n " , __func__ , status ) ;
2009-08-18 21:05:55 +02:00
else
2012-09-14 15:08:28 -07:00
dev_dbg ( & port - > dev , " %s - vcc OK ! \n " , __func__ ) ;
2009-08-18 21:05:55 +02:00
return status ;
}
/*
* Sysfs Attributes
*/
2013-08-23 16:18:34 -07:00
static ssize_t vcc_mode_show ( struct device * dev ,
2009-08-18 21:05:55 +02:00
struct device_attribute * attr , char * buf )
{
struct usb_serial_port * port = to_usb_serial_port ( dev ) ;
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
return sprintf ( buf , " %d \n " , priv - > vcc ) ;
}
2013-08-23 16:18:34 -07:00
static ssize_t vcc_mode_store ( struct device * dev ,
2009-08-18 21:05:55 +02:00
struct device_attribute * attr , const char * buf , size_t count )
{
struct usb_serial_port * port = to_usb_serial_port ( dev ) ;
struct iuu_private * priv = usb_get_serial_port_data ( port ) ;
unsigned long v ;
2012-10-29 18:37:31 +09:00
if ( kstrtoul ( buf , 10 , & v ) ) {
2009-08-18 21:05:55 +02:00
dev_err ( dev , " %s - vcc_mode: %s is not a unsigned long \n " ,
__func__ , buf ) ;
goto fail_store_vcc_mode ;
}
2014-03-12 19:09:42 +01:00
dev_dbg ( dev , " %s: setting vcc_mode = %ld \n " , __func__ , v ) ;
2009-08-18 21:05:55 +02:00
if ( ( v ! = 3 ) & & ( v ! = 5 ) ) {
dev_err ( dev , " %s - vcc_mode %ld is invalid \n " , __func__ , v ) ;
} else {
iuu_vcc_set ( port , v ) ;
priv - > vcc = v ;
}
fail_store_vcc_mode :
return count ;
}
2013-08-23 16:18:34 -07:00
static DEVICE_ATTR_RW ( vcc_mode ) ;
2009-08-18 21:05:55 +02:00
static int iuu_create_sysfs_attrs ( struct usb_serial_port * port )
{
return device_create_file ( & port - > dev , & dev_attr_vcc_mode ) ;
}
static int iuu_remove_sysfs_attrs ( struct usb_serial_port * port )
{
device_remove_file ( & port - > dev , & dev_attr_vcc_mode ) ;
return 0 ;
}
/*
* End Sysfs Attributes
*/
2007-10-26 13:51:49 +02:00
static struct usb_serial_driver iuu_device = {
. driver = {
. owner = THIS_MODULE ,
. name = " iuu_phoenix " ,
} ,
. id_table = id_table ,
. num_ports = 1 ,
2017-03-02 12:51:24 +01:00
. num_bulk_in = 1 ,
. num_bulk_out = 1 ,
2010-03-17 23:00:37 +01:00
. bulk_in_size = 512 ,
. bulk_out_size = 512 ,
2007-10-26 13:51:49 +02:00
. open = iuu_open ,
. close = iuu_close ,
. write = iuu_uart_write ,
. read_bulk_callback = iuu_uart_read_callback ,
. tiocmget = iuu_tiocmget ,
. tiocmset = iuu_tiocmset ,
2009-06-11 12:54:20 +01:00
. set_termios = iuu_set_termios ,
2009-09-19 13:13:33 -07:00
. init_termios = iuu_init_termios ,
2012-10-17 13:34:59 +02:00
. port_probe = iuu_port_probe ,
. port_remove = iuu_port_remove ,
2007-10-26 13:51:49 +02:00
} ;
2012-02-23 14:56:57 -05:00
static struct usb_serial_driver * const serial_drivers [ ] = {
& iuu_device , NULL
} ;
2012-05-08 15:46:14 -07:00
module_usb_serial_driver ( serial_drivers , id_table ) ;
2007-10-26 13:51:49 +02:00
MODULE_AUTHOR ( " Alain Degreffe eczema@ecze.com " ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;
module_param ( xmas , bool , S_IRUGO | S_IWUSR ) ;
2009-08-18 21:05:54 +02:00
MODULE_PARM_DESC ( xmas , " Xmas colors enabled or not " ) ;
2007-10-26 13:51:49 +02:00
module_param ( boost , int , S_IRUGO | S_IWUSR ) ;
2009-08-18 21:05:54 +02:00
MODULE_PARM_DESC ( boost , " Card overclock boost (in percent 100-500) " ) ;
2007-10-26 13:51:49 +02:00
module_param ( clockmode , int , S_IRUGO | S_IWUSR ) ;
2009-08-18 21:05:54 +02:00
MODULE_PARM_DESC ( clockmode , " Card clock mode (1=3.579 MHz, 2=3.680 MHz, "
" 3=6 Mhz) " ) ;
2007-10-26 13:51:49 +02:00
module_param ( cdmode , int , S_IRUGO | S_IWUSR ) ;
2009-08-18 21:05:54 +02:00
MODULE_PARM_DESC ( cdmode , " Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, "
" 4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING) " ) ;
2009-08-18 21:05:57 +02:00
module_param ( vcc_default , int , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( vcc_default , " Set default VCC (either 3 for 3.3V or 5 "
" for 5V). Default to 5. " ) ;