Skip to content

Commit

Permalink
USB: kobil_sct: Rework driver
Browse files Browse the repository at this point in the history
No hardware but this driver is currently totally broken so we can't make
it much worse. Remove all tbe broken invalid termios handling and replace
it with a proper set_termios method.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Alan Cox authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent c4e4156 commit 94d0f7e
Showing 1 changed file with 55 additions and 89 deletions.
144 changes: 55 additions & 89 deletions drivers/usb/serial/kobil_sct.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear);
static void kobil_read_int_callback( struct urb *urb );
static void kobil_write_callback( struct urb *purb );
static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old);


static struct usb_device_id id_table [] = {
Expand Down Expand Up @@ -119,6 +120,7 @@ static struct usb_serial_driver kobil_device = {
.attach = kobil_startup,
.shutdown = kobil_shutdown,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open,
Expand All @@ -137,7 +139,6 @@ struct kobil_private {
int cur_pos; // index of the next char to send in buf
__u16 device_type;
int line_state;
struct ktermios internal_termios;
};


Expand Down Expand Up @@ -216,7 +217,7 @@ static void kobil_shutdown (struct usb_serial *serial)

static int kobil_open (struct usb_serial_port *port, struct file *filp)
{
int i, result = 0;
int result = 0;
struct kobil_private *priv;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
Expand All @@ -242,16 +243,6 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)

// set up internal termios structure
priv->internal_termios.c_iflag = port->tty->termios->c_iflag;
priv->internal_termios.c_oflag = port->tty->termios->c_oflag;
priv->internal_termios.c_cflag = port->tty->termios->c_cflag;
priv->internal_termios.c_lflag = port->tty->termios->c_lflag;

for (i=0; i<NCCS; i++) {
priv->internal_termios.c_cc[i] = port->tty->termios->c_cc[i];
}

// allocate memory for transfer buffer
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
Expand Down Expand Up @@ -607,102 +598,79 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
return (result < 0) ? result : 0;
}


static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old)
{
struct kobil_private * priv;
int result;
unsigned short urb_val = 0;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
char *settings;
void __user *user_arg = (void __user *)arg;
int c_cflag = port->tty->termios->c_cflag;
speed_t speed;
void * settings;

priv = usb_get_serial_port_data(port);
if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
// This device doesn't support ioctl calls
return 0;
}

switch (cmd) {
case TCGETS: // 0x5401
if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) {
dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
return -EFAULT;
}
if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
&priv->internal_termios))
return -EFAULT;
return 0;

case TCSETS: // 0x5402
if (!(port->tty->termios)) {
dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
return -ENOTTY;
}
if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) {
dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
return -EFAULT;
}
if (user_termios_to_kernel_termios(&priv->internal_termios,
(struct ktermios __user *)arg))
return -EFAULT;

settings = kzalloc(50, GFP_KERNEL);
if (! settings) {
return -ENOBUFS;
}
return;

switch (priv->internal_termios.c_cflag & CBAUD) {
case B1200:
switch (speed = tty_get_baud_rate(port->tty)) {
case 1200:
urb_val = SUSBCR_SBR_1200;
strcat(settings, "1200 ");
break;
case B9600:
case 9600:
default:
urb_val = SUSBCR_SBR_9600;
strcat(settings, "9600 ");
break;
}
}
urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;

settings = kzalloc(50, GFP_KERNEL);
if (! settings)
return;

urb_val |= (priv->internal_termios.c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
strcat(settings, (priv->internal_termios.c_cflag & CSTOPB) ? "2 StopBits " : "1 StopBit ");
sprintf(settings, "%d ", speed);

if (priv->internal_termios.c_cflag & PARENB) {
if (priv->internal_termios.c_cflag & PARODD) {
urb_val |= SUSBCR_SPASB_OddParity;
strcat(settings, "Odd Parity");
} else {
urb_val |= SUSBCR_SPASB_EvenParity;
strcat(settings, "Even Parity");
}
if (c_cflag & PARENB) {
if (c_cflag & PARODD) {
urb_val |= SUSBCR_SPASB_OddParity;
strcat(settings, "Odd Parity");
} else {
urb_val |= SUSBCR_SPASB_NoParity;
strcat(settings, "No Parity");
urb_val |= SUSBCR_SPASB_EvenParity;
strcat(settings, "Even Parity");
}
dbg("%s - port %d setting port to: %s", __FUNCTION__, port->number, settings );
} else {
urb_val |= SUSBCR_SPASB_NoParity;
strcat(settings, "No Parity");
}

result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetBaudRateParityAndStopBits,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
urb_val,
0,
settings,
0,
KOBIL_TIMEOUT
);
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetBaudRateParityAndStopBits,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
urb_val,
0,
settings,
0,
KOBIL_TIMEOUT
);
kfree(settings);
}

dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
kfree(settings);
static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct kobil_private * priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
int result;

if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
// This device doesn't support ioctl calls
return 0;

switch (cmd) {
case TCFLSH: // 0x540B
transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
if (! transfer_buffer)
return -ENOBUFS;
}

result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
Expand All @@ -716,15 +684,13 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
);

dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);

kfree(transfer_buffer);
return ((result < 0) ? -EFAULT : 0);

return (result < 0) ? -EFAULT : 0;
default:
return -ENOIOCTLCMD;
}
return -ENOIOCTLCMD;
}


static int __init kobil_init (void)
{
int retval;
Expand Down

0 comments on commit 94d0f7e

Please sign in to comment.