Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94d0f7ea authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman
Browse files

USB: kobil_sct: Rework driver



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: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c4e41562
Loading
Loading
Loading
Loading
+55 −89
Original line number Diff line number Diff line
@@ -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 [] = {
@@ -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,
@@ -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;
};


@@ -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;
@@ -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) {
@@ -607,70 +598,39 @@ 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;

		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 ");
	settings = kzalloc(50, GFP_KERNEL);
	if (! settings)
		return;

	sprintf(settings, "%d ", speed);

		if (priv->internal_termios.c_cflag & PARENB) {
			if  (priv->internal_termios.c_cflag & PARODD) {
	if (c_cflag & PARENB) {
		if  (c_cflag & PARODD) {
			urb_val |= SUSBCR_SPASB_OddParity;
			strcat(settings, "Odd Parity");
		} else {
@@ -681,7 +641,6 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
		urb_val |= SUSBCR_SPASB_NoParity;
		strcat(settings, "No Parity");
	}
		dbg("%s - port %d setting port to: %s", __FUNCTION__, port->number, settings );

	result = usb_control_msg( port->serial->dev,
				  usb_rcvctrlpipe(port->serial->dev, 0 ),
@@ -693,16 +652,25 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
				  0,
				  KOBIL_TIMEOUT
		);

		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 ), 
@@ -716,14 +684,12 @@ 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;
	}

}

static int __init kobil_init (void)
{