Hello, Here is the new patch for the cp210x driver. I have made the strcmp in the startup code. I now set the private data and use that to check if it is a cp2104 device. Is this the right way of doing it? Best regards, Andreas Madsen On Thu, 2012-01-12 at 07:59 -0800, Greg KH wrote: > On Thu, Jan 12, 2012 at 01:28:21PM +0100, Andreas wrote: > > Hello Greg Kroah-Hartman. > > > > I have made a patch for the cp210x driver. > > > > I use ubuntu, with kernel version 2.6.38. > > > > It is the first time I have made a patch for a linux driver, so I hope I > > have done it right :) > > > > The reason that I made the patch is because Silicon Labs have a new > > device, cp2104, and there is a problem with setting the baudrate. I have > > seen that there is also other people that have the same problem > > (https://bugs.launchpad.net/ubuntu/+source/linux/+bug/793261). > > > > The change is that I check the iProduct string of the device to see if > > it is a cp2104 device, and then I set the baudrate instead of the > > baudrate divisor. > > Thanks, but do you really want to do this string query on ever baud rate > change? How about determining this when the device is plugged in and > then do this change only if this type of device is present? > > And they don't change the device id, just the string in the device? > That's crazy, and not very nice of them. > > You should run your patch through the scripts/checkpatch.pl script, and > fix the errors that it give you (hint, the coding style is not correct.) > > And finally, you should make this patch against a more modern kernel, > 2.6.38 is quite old, please use 3.2, which can be downloaded from > kernel.org. I can't go and apply patches against older kernels. > > Oh, and also please cc: the linux-usb@xxxxxxxxxxxxxxx mailing list with > any usb patches, so that all developers can see them and review them. > > Care to redo the patch based on this and resend it? > > > > > I have tested it with a cp2104 and a cp2103 device, and both works fine. > > > > Best regards, > > Andreas Madsen > > Seluxit ApS > > > --- linux-source-2.6.38/drivers/usb/serial/cp210x.c 2012-01-03 14:44:25.000000000 +0100 > > +++ linux-source-2.6.38/drivers/usb/serial/cp210x_new.c 2012-01-10 08:24:20.610580474 +0100 > > @@ -201,6 +201,7 @@ > > #define CP210X_EMBED_EVENTS 0x15 > > #define CP210X_GET_EVENTSTATE 0x16 > > #define CP210X_SET_CHARS 0x19 > > +#define CP210X_SET_BAUDRATE 0x1E > > > > /* CP210X_IFC_ENABLE */ > > #define UART_ENABLE 0x0001 > > @@ -583,6 +584,7 @@ > > unsigned int cflag, old_cflag; > > unsigned int baud = 0, bits; > > unsigned int modem_ctl[4]; > > + char prod[128]; > > > > dbg("%s - port %d", __func__, port->number); > > > > @@ -594,8 +596,23 @@ > > old_cflag = old_termios->c_cflag; > > baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); > > > > - /* If the baud rate is to be updated*/ > > - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { > > + > > + /* Read the "iProduct" from the device and check if it is a CP2104, > > + * then use SET_BAUDRATE to change the baudrate. */ > > + usb_string(port->serial->dev,2,prod,sizeof(prod)); > > + if(strcmp(prod,"CP2104 USB to UART Bridge Controller") == 0 && baud != 0) > > + { > > + dbg("%s - Setting baud rate to %d baud", __func__, baud); > > + > > + if(cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, 4)) { > > + dbg("Baud rate requested not supported by device"); > > + baud = tty_termios_baud_rate(old_termios); > > + } > > + } > > + else > > + { > > + /* If the baud rate is to be updated*/ > > + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { > > dbg("%s - Setting baud rate to %d baud", __func__, > > baud); > > if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, > > @@ -603,6 +620,7 @@ > > dbg("Baud rate requested not supported by device"); > > baud = tty_termios_baud_rate(old_termios); > > } > > + } > > } > > /* Report back the resulting baud rate */ > > tty_encode_baud_rate(tty, baud, baud); > > > >
--- linux-3.2/drivers/usb/serial/cp210x.c 2012-01-05 00:55:44.000000000 +0100 +++ linux-3.2.patch/drivers/usb/serial/cp210x.c 2012-01-13 10:16:50.630613034 +0100 @@ -30,6 +30,10 @@ #define DRIVER_VERSION "v0.09" #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver" +struct cp210x_private { + bool cp2104_device; +}; + /* * Function Prototypes */ @@ -47,6 +51,7 @@ unsigned int, unsigned int); static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); +static void cp210x_release(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); static int debug; @@ -168,6 +173,7 @@ .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, + .release = cp210x_release, .dtr_rts = cp210x_dtr_rts }; @@ -200,6 +206,7 @@ #define CP210X_EMBED_EVENTS 0x15 #define CP210X_GET_EVENTSTATE 0x16 #define CP210X_SET_CHARS 0x19 +#define CP210X_SET_BAUDRATE 0x1E /* CP210X_IFC_ENABLE */ #define UART_ENABLE 0x0001 @@ -582,6 +589,7 @@ unsigned int cflag, old_cflag; unsigned int baud = 0, bits; unsigned int modem_ctl[4]; + struct cp210x_private *priv; dbg("%s - port %d", __func__, port->number); @@ -593,8 +601,18 @@ old_cflag = old_termios->c_cflag; baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + priv = usb_get_serial_data(port->serial); + if (priv && priv->cp2104_device && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, baud); + + if (cp210x_set_config(port, CP210X_SET_BAUDRATE, + &baud, 4)) { + dbg("Baud rate requested not supported by device"); + baud = tty_termios_baud_rate(old_termios); + } + } else { + /* If the baud rate is to be updated*/ + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { dbg("%s - Setting baud rate to %d baud", __func__, baud); if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, @@ -602,6 +620,7 @@ dbg("Baud rate requested not supported by device"); baud = tty_termios_baud_rate(old_termios); } + } } /* Report back the resulting baud rate */ tty_encode_baud_rate(tty, baud, baud); @@ -784,11 +803,34 @@ static int cp210x_startup(struct usb_serial *serial) { + char prod[255]; + struct cp210x_private *priv; + /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); + + /* Read the iProduct string to check if the device is a cp2104 */ + usb_string(serial->dev, 2, prod, sizeof(prod)); + if (strcmp(prod, "CP2104 USB to UART Bridge Controller") == 0) { + priv = kzalloc(sizeof(struct cp210x_private), GFP_KERNEL); + if (!priv) { + dev_err(&serial->dev->dev, "%s- kmalloc(%Zd) failed.\n", + __func__, sizeof(struct cp210x_private)); + return -ENOMEM; + } + priv->cp2104_device = 1; + usb_set_serial_data(serial, (void *)priv); + } return 0; } +static void cp210x_release(struct usb_serial *serial) +{ + /* Free private data if pressent */ + struct cp210x_private *priv = usb_get_serial_data(serial); + kfree(priv); +} + static int __init cp210x_init(void) { int retval;
Attachment:
smime.p7s
Description: S/MIME cryptographic signature