From: Greg KH To: Alan Cox Cc: linux-usb-devel@lists.sourceforge.net Subject: [PATCH 11 of 15] USB Serial mct_u232 driver updated This patch updates the mctu232 driver. diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c --- a/drivers/usb/serial/mct_u232.c Thu Jan 3 21:41:53 2002 +++ b/drivers/usb/serial/mct_u232.c Thu Jan 3 21:41:53 2002 @@ -24,6 +24,15 @@ * Basic tests have been performed with minicom/zmodem transfers and * modem dialing under Linux 2.4.0-test10 (for me it works fine). * + * 10-Nov-2001 Wolfgang Grandegger + * - Fixed an endianess problem with the baudrate selection for PowerPC. + * + * 06-Dec-2001 Martin Hamilton + * Added support for the Belkin F5U109 DB9 adaptor + * + * 30-May-2001 Greg Kroah-Hartman + * switched from using spinlock to a semaphore, which fixes lots of problems. + * * 04-May-2001 Stelian Pop * - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes * instead of the device reported 32 (using 32 bytes causes many data @@ -79,7 +88,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.0.0" +#define DRIVER_VERSION "v1.1" #define DRIVER_AUTHOR "Wolfgang Grandegger " #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" @@ -91,7 +100,7 @@ */ #undef FIX_WRITE_RETURN_CODE_PROBLEM #ifdef FIX_WRITE_RETURN_CODE_PROBLEM -static int write_blocking = 0; /* disabled by default */ +static int write_blocking; /* disabled by default */ #endif /* @@ -127,8 +136,10 @@ static __u16 mct_u232_product_id = MCT_U232_PID; static __u16 mct_u232_sitecom_id = MCT_U232_SITECOM_PID; static __u16 mct_u232_du_h3sp_id = MCT_U232_DU_H3SP_PID; +static __u16 mct_u232_belkin_vendor_id = MCT_U232_BELKIN_F5U109_VID; +static __u16 mct_u232_belkin_product_id = MCT_U232_BELKIN_F5U109_PID; -struct usb_serial_device_type mct_u232_device = { +static struct usb_serial_device_type mct_u232_device = { name: "Magic Control Technology USB-RS232", idVendor: &mct_u232_vendor_id, idProduct: &mct_u232_product_id, @@ -153,7 +164,7 @@ shutdown: mct_u232_shutdown, }; -struct usb_serial_device_type mct_u232_sitecom_device = { +static struct usb_serial_device_type mct_u232_sitecom_device = { name: "MCT/Sitecom USB-RS232", idVendor: &mct_u232_vendor_id, idProduct: &mct_u232_sitecom_id, @@ -178,7 +189,7 @@ shutdown: mct_u232_shutdown, }; -struct usb_serial_device_type mct_u232_du_h3sp_device = { +static struct usb_serial_device_type mct_u232_du_h3sp_device = { name: "MCT/D-Link DU-H3SP USB BAY", idVendor: &mct_u232_vendor_id, idProduct: &mct_u232_du_h3sp_id, @@ -203,6 +214,31 @@ shutdown: mct_u232_shutdown, }; +static struct usb_serial_device_type mct_u232_belkin_device = { + name: "Belkin F5U109", + idVendor: &mct_u232_belkin_vendor_id, + idProduct: &mct_u232_belkin_product_id, + needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */ + needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */ + needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */ + num_interrupt_in: 2, + num_bulk_in: 0, + num_bulk_out: 1, + num_ports: 1, + open: mct_u232_open, + close: mct_u232_close, +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM + write: mct_u232_write, + write_bulk_callback: mct_u232_write_bulk_callback, +#endif + read_int_callback: mct_u232_read_int_callback, + ioctl: mct_u232_ioctl, + set_termios: mct_u232_set_termios, + break_ctl: mct_u232_break_ctl, + startup: mct_u232_startup, + shutdown: mct_u232_shutdown, +}; + @@ -220,7 +256,8 @@ #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) { - if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID) { + if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID + || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) { switch (value) { case 300: return 0x01; case 600: return 0x02; /* this one not tested */ @@ -243,7 +280,7 @@ { unsigned int divisor; int rc; - divisor = mct_u232_calculate_baud_rate(serial, value); + divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value)); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_BAUD_RATE_REQUEST, MCT_U232_SET_REQUEST_TYPE, @@ -374,13 +411,13 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + int retval = 0; dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); ++port->open_count; MOD_INC_USE_COUNT; @@ -426,16 +463,21 @@ } port->read_urb->dev = port->serial->dev; - if (usb_submit_urb(port->read_urb)) + retval = usb_submit_urb(port->read_urb); + if (retval) { err("usb_submit_urb(read bulk) failed"); + goto exit; + } port->interrupt_in_urb->dev = port->serial->dev; - if (usb_submit_urb(port->interrupt_in_urb)) + retval = usb_submit_urb(port->interrupt_in_urb); + if (retval) err(" usb_submit_urb(read int) failed"); } - spin_unlock_irqrestore (&port->port_lock, flags); +exit: + up (&port->sem); return 0; } /* mct_u232_open */ @@ -443,26 +485,24 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp) { - unsigned long flags; - dbg(__FUNCTION__" port %d", port->number); - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); --port->open_count; - MOD_DEC_USE_COUNT; if (port->open_count <= 0) { - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - /* wgg - do I need this? I think so. */ - usb_unlink_urb (port->interrupt_in_urb); + if (port->serial->dev) { + /* shutdown our urbs */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + usb_unlink_urb (port->interrupt_in_urb); + } port->active = 0; } - spin_unlock_irqrestore (&port->port_lock, flags); - + up (&port->sem); + MOD_DEC_USE_COUNT; } /* mct_u232_close */ @@ -473,7 +513,6 @@ const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; - unsigned long flags; int result, bytes_sent, size; dbg(__FUNCTION__ " - port %d", port->number); @@ -496,14 +535,17 @@ bytes_sent = 0; while (count > 0) { - spin_lock_irqsave (&port->port_lock, flags); + down (&port->sem); size = (count > port->bulk_out_size) ? port->bulk_out_size : count; usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); if (from_user) { - copy_from_user(port->write_urb->transfer_buffer, buf, size); + if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { + up (&port->sem); + return -EFAULT; + } } else { memcpy (port->write_urb->transfer_buffer, buf, size); @@ -524,11 +566,11 @@ if (result) { err(__FUNCTION__ " - failed submitting write urb, error %d", result); - spin_unlock_irqrestore (&port->port_lock, flags); - return bytes_sent; + up (&port->sem); + return result; } - spin_unlock_irqrestore (&port->port_lock, flags); + up (&port->sem); bytes_sent += size; if (write_blocking) @@ -794,7 +836,7 @@ { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; - int ret, mask; + int mask; dbg (__FUNCTION__ "cmd=0x%x", cmd); @@ -807,7 +849,8 @@ case TIOCMSET: /* Turns on and off the lines as specified by the mask */ case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (get_user(mask, (unsigned long *) arg)) + return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ @@ -853,6 +896,7 @@ usb_serial_register (&mct_u232_device); usb_serial_register (&mct_u232_sitecom_device); usb_serial_register (&mct_u232_du_h3sp_device); + usb_serial_register (&mct_u232_belkin_device); info(DRIVER_VERSION ":" DRIVER_DESC); return 0; } @@ -863,6 +907,7 @@ usb_serial_deregister (&mct_u232_device); usb_serial_deregister (&mct_u232_sitecom_device); usb_serial_deregister (&mct_u232_du_h3sp_device); + usb_serial_deregister (&mct_u232_belkin_device); } diff -Nru a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h --- a/drivers/usb/serial/mct_u232.h Thu Jan 3 21:41:53 2002 +++ b/drivers/usb/serial/mct_u232.h Thu Jan 3 21:41:53 2002 @@ -30,9 +30,12 @@ #define MCT_U232_SITECOM_PID 0x0230 /* Sitecom Product Id */ /* DU-H3SP USB BAY hub */ - #define MCT_U232_DU_H3SP_PID 0x0200 /* D-Link DU-H3SP USB BAY */ +/* Belkin badge the MCT U232-P9 as the F5U109 */ +#define MCT_U232_BELKIN_F5U109_VID 0x050d /* Vendor Id */ +#define MCT_U232_BELKIN_F5U109_PID 0x0109 /* Product Id */ + /* * Vendor Request Interface */ @@ -363,6 +366,25 @@ * bmAttributes = 03 (Interrupt) * wMaxPacketSize = 0002 * bInterval = 02 + * + * + * Hardware details (added by Martin Hamilton, 2001/12/06) + * ----------------------------------------------------------------- + * + * This info was gleaned from opening a Belkin F5U109 DB9 USB serial + * adaptor, which turns out to simply be a re-badged U232-P9. We + * know this because there is a sticky label on the circuit board + * which says "U232-P9" ;-) + * + * The circuit board inside the adaptor contains a Philips PDIUSBD12 + * USB endpoint chip and a Phillips P87C52UBAA microcontroller with + * embedded UART. Exhaustive documentation for these is available at: + * + * http://www.semiconductors.philips.com/pip/p87c52ubaa + * http://www.semiconductors.philips.com/pip/pdiusbd12 + * + * Thanks to Julian Highfield for the pointer to the Philips database. + * */ #endif /* __LINUX_USB_SERIAL_MCT_U232_H */