From: smckown Date: Wed, 15 Apr 2009 16:40:39 +0000 (+0000) Subject: Reorganize code in cp2101.c X-Git-Tag: debian/0.11.2-5.2tmi~25 X-Git-Url: https://oss.titaniummirror.com/gitweb?p=cp210x.git;a=commitdiff_plain;h=275f797d5c0bb83007f20360b759fce979d25cf7 Reorganize code in cp2101.c Now cp2101.c looks like it would if the minimal patch were applied to cp2101.c from the plain vanilla linux 2.6.24 code. We did also add some newer usb device id's from 2.6.30's cp2101.c. --- diff --git a/src/cp2101.c b/src/cp2101.c index f9433a1..7ad61da 100644 --- a/src/cp2101.c +++ b/src/cp2101.c @@ -11,8 +11,10 @@ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow * control thanks to Munir Nassar nassarmu@real-time.com * + * Silicon Labs RJM: updated to 0.11 for 2.6.15 and later kernels + * * Port configuration, usb descriptor and gpio management by R. Steve McKown - * (smckown@titaniummirror.com). + * rsmckown@gmail.com. * * Outstanding Issues: * Buffers are not flushed when the port is opened. @@ -26,48 +28,13 @@ #include #include #include +#include #include -#include #include -#include - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) ((a)*65536 + (b)*256 + (c)) -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -#ifdef LINUX26 -#undef LINUX26 -#endif -#define LINUX26 -#endif - -#ifdef LINUX26 - -#include #include -#define DEV_ERR(dev,format,arg...) dev_err(dev,format, ## arg) -#define USB_KILL_URB usb_kill_urb - -#else /* !LINUX26 */ - -#include -#include "usb-serial.h" - -#ifdef CONFIG_USB_SERIAL_DEBUG - static int debug = 1; -#else - static int debug; -#endif - -#define DEV_ERR(dev,format,arg...) err(format, ## arg) -#define USB_KILL_URB usb_unlink_urb - -#endif /* LINUX26 */ /* * Version Information - * RJM: updated to 0.11 for 2.6.15 and later kernels */ #define DRIVER_VERSION "v0.11rsm" #define DRIVER_DESC "Silicon Labs CP2101/CP2102/CP2103 RS232 serial adaptor driver" @@ -75,100 +42,103 @@ /* * Function Prototypes */ -static int cp2101_open(struct usb_serial_port*, struct file*); +static int cp2101_open(struct usb_serial_port*, struct file*); static void cp2101_cleanup(struct usb_serial_port*); static void cp2101_close(struct usb_serial_port*, struct file*); static void cp2101_get_termios(struct usb_serial_port*); -static void cp2101_set_termios(struct usb_serial_port*, struct termios*); +static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*); +static int cp2101_tiocmget (struct usb_serial_port *, struct file *); +static int cp2101_tiocmset (struct usb_serial_port *, struct file *, + unsigned int, unsigned int); static void cp2101_break_ctl(struct usb_serial_port*, int); -static int cp2101_startup (struct usb_serial *); +static int cp2101_startup (struct usb_serial *); static void cp2101_shutdown(struct usb_serial*); -static int cp2101_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); -static int cp2101_tiocmget (struct usb_serial_port *, struct file *); -static int cp2101_tiocmset (struct usb_serial_port *, struct file *, unsigned int, unsigned int); +static int cp2101_ioctl(struct usb_serial_port *, struct file *, + unsigned int, unsigned long); static int debug; static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ + { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ + { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ + { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ + { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ + { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ + { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ + { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ + { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ + { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ + { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE (usb, id_table); -#ifdef LINUX26 static struct usb_driver cp2101_driver = { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - .owner = THIS_MODULE, -#endif - .name = "CP2101", + .name = "cp2101", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, + .no_dynamic_id = 1, }; -#define USB_SUBMIT_URB_ATOMIC(_x_) usb_submit_urb(_x_ , GFP_ATOMIC) -#define USB_SUBMIT_URB_KERNEL(_x_) usb_submit_urb(_x_ , GFP_KERNEL) - -#else /* LINUX26 */ - -#define USB_SUBMIT_URB_ATOMIC(_x_) usb_submit_urb(_x_) -#define USB_SUBMIT_URB_KERNEL(_x_) usb_submit_urb(_x_) -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) static struct usb_serial_driver cp2101_device = { .driver = { .owner = THIS_MODULE, .name = "cp2101", }, -#else -static struct usb_serial_device_type cp2101_device = { - .owner = THIS_MODULE, - .name = "CP2101/CP2102/CP2103 USB to UART Bridge", -#endif - .id_table = id_table, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + .usb_driver = &cp2101_driver, + .id_table = id_table, .num_interrupt_in = 0, - .num_bulk_in = 0, - .num_bulk_out = 0, -#else - .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = NUM_DONT_CARE, .num_bulk_out = NUM_DONT_CARE, -#endif - .num_ports = 1, - .open = cp2101_open, - .close = cp2101_close, - .ioctl = cp2101_ioctl, /* GLA, Added backport */ - .break_ctl = cp2101_break_ctl, - .set_termios = cp2101_set_termios, -#ifdef LINUX26 - .tiocmget = cp2101_tiocmget, - .tiocmset = cp2101_tiocmset, - .attach = cp2101_startup, -#else - .startup = cp2101_startup, -#endif - .shutdown = cp2101_shutdown + .num_ports = 1, + .open = cp2101_open, + .close = cp2101_close, + .ioctl = cp2101_ioctl, + .break_ctl = cp2101_break_ctl, + .set_termios = cp2101_set_termios, + .tiocmget = cp2101_tiocmget, + .tiocmset = cp2101_tiocmset, + .attach = cp2101_startup, + .shutdown = cp2101_shutdown, }; /* Config request types */ @@ -176,54 +146,54 @@ static struct usb_serial_device_type cp2101_device = { #define REQTYPE_DEVICE_TO_HOST 0xc1 /* Config SET requests. To GET, add 1 to the request number */ -#define CP2101_UART 0x00 /* Enable / Disable */ -#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ -#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ -#define CP2101_BREAK 0x05 /* On / Off */ -#define CP2101_CONTROL 0x07 /* Flow control line states */ -#define CP2101_MODEMCTL 0x13 /* Modem controls */ -#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ +#define CP2101_UART 0x00 /* Enable / Disable */ +#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ +#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ +#define CP2101_BREAK 0x05 /* On / Off */ +#define CP2101_CONTROL 0x07 /* Flow control line states */ +#define CP2101_MODEMCTL 0x13 /* Modem controls */ +#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ /* CP2101_UART */ -#define UART_ENABLE 0x0001 -#define UART_DISABLE 0x0000 +#define UART_ENABLE 0x0001 +#define UART_DISABLE 0x0000 /* CP2101_BAUDRATE */ -#define BAUD_RATE_GEN_FREQ 0x384000 +#define BAUD_RATE_GEN_FREQ 0x384000 /* CP2101_BITS */ -#define BITS_DATA_MASK 0x0f00 -#define BITS_DATA_5 0x0500 -#define BITS_DATA_6 0x0600 -#define BITS_DATA_7 0x0700 -#define BITS_DATA_8 0x0800 -#define BITS_DATA_9 0x0900 - -#define BITS_PARITY_MASK 0x00f0 -#define BITS_PARITY_NONE 0x0000 -#define BITS_PARITY_ODD 0x0010 -#define BITS_PARITY_EVEN 0x0020 -#define BITS_PARITY_MARK 0x0030 -#define BITS_PARITY_SPACE 0x0040 - -#define BITS_STOP_MASK 0x000f -#define BITS_STOP_1 0x0000 -#define BITS_STOP_1_5 0x0001 -#define BITS_STOP_2 0x0002 +#define BITS_DATA_MASK 0X0f00 +#define BITS_DATA_5 0X0500 +#define BITS_DATA_6 0X0600 +#define BITS_DATA_7 0X0700 +#define BITS_DATA_8 0X0800 +#define BITS_DATA_9 0X0900 + +#define BITS_PARITY_MASK 0x00f0 +#define BITS_PARITY_NONE 0x0000 +#define BITS_PARITY_ODD 0x0010 +#define BITS_PARITY_EVEN 0x0020 +#define BITS_PARITY_MARK 0x0030 +#define BITS_PARITY_SPACE 0x0040 + +#define BITS_STOP_MASK 0x000f +#define BITS_STOP_1 0x0000 +#define BITS_STOP_1_5 0x0001 +#define BITS_STOP_2 0x0002 /* CP2101_BREAK */ -#define BREAK_ON 0x0000 -#define BREAK_OFF 0x0001 +#define BREAK_ON 0x0000 +#define BREAK_OFF 0x0001 /* CP2101_CONTROL */ -#define CONTROL_DTR 0x0001 -#define CONTROL_RTS 0x0002 -#define CONTROL_CTS 0x0010 -#define CONTROL_DSR 0x0020 -#define CONTROL_RING 0x0040 -#define CONTROL_DCD 0x0080 -#define CONTROL_WRITE_DTR 0x0100 -#define CONTROL_WRITE_RTS 0x0200 +#define CONTROL_DTR 0x0001 +#define CONTROL_RTS 0x0002 +#define CONTROL_CTS 0x0010 +#define CONTROL_DSR 0x0020 +#define CONTROL_RING 0x0040 +#define CONTROL_DCD 0x0080 +#define CONTROL_WRITE_DTR 0x0100 +#define CONTROL_WRITE_RTS 0x0200 /* CP2103 ioctls */ #define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ @@ -244,34 +214,34 @@ static struct usb_serial_device_type cp2101_device = { /* FIXME: where is IOCTL_SETMFG? */ /* CP2103 GPIO */ -#define GPIO_0 0x01 -#define GPIO_1 0x02 -#define GPIO_2 0x04 -#define GPIO_3 0x08 -#define GPIO_MASK (GPIO_0|GPIO_1|GPIO_2|GPIO_3) +#define GPIO_0 0x01 +#define GPIO_1 0x02 +#define GPIO_2 0x04 +#define GPIO_3 0x08 +#define GPIO_MASK (GPIO_0|GPIO_1|GPIO_2|GPIO_3) /* GetDeviceVersion() return codes */ -#define CP210x_CP2101_VERSION 0x01 -#define CP210x_CP2102_VERSION 0x02 -#define CP210x_CP2103_VERSION 0x03 - +#define CP210x_CP2101_VERSION 0x01 +#define CP210x_CP2102_VERSION 0x02 +#define CP210x_CP2103_VERSION 0x03 + /* Return codes */ -#define CP210x_SUCCESS 0x00 -#define CP210x_DEVICE_NOT_FOUND 0xFF -#define CP210x_INVALID_HANDLE 0x01 -#define CP210x_INVALID_PARAMETER 0x02 -#define CP210x_DEVICE_IO_FAILED 0x03 -#define CP210x_FUNCTION_NOT_SUPPORTED 0x04 -#define CP210x_GLOBAL_DATA_ERROR 0x05 -#define CP210x_FILE_ERROR 0x06 -#define CP210x_COMMAND_FAILED 0x08 -#define CP210x_INVALID_ACCESS_TYPE 0x09 +#define CP210x_SUCCESS 0x00 +#define CP210x_DEVICE_NOT_FOUND 0xFF +#define CP210x_INVALID_HANDLE 0x01 +#define CP210x_INVALID_PARAMETER 0x02 +#define CP210x_DEVICE_IO_FAILED 0x03 +#define CP210x_FUNCTION_NOT_SUPPORTED 0x04 +#define CP210x_GLOBAL_DATA_ERROR 0x05 +#define CP210x_FILE_ERROR 0x06 +#define CP210x_COMMAND_FAILED 0x08 +#define CP210x_INVALID_ACCESS_TYPE 0x09 /* USB descriptor sizes */ -#define CP210x_MAX_DEVICE_STRLEN 256 -#define CP210x_MAX_PRODUCT_STRLEN 126 -#define CP210x_MAX_SERIAL_STRLEN 63 -#define CP210x_MAX_MAXPOWER 250 +#define CP210x_MAX_DEVICE_STRLEN 256 +#define CP210x_MAX_PRODUCT_STRLEN 126 +#define CP210x_MAX_SERIAL_STRLEN 63 +#define CP210x_MAX_MAXPOWER 250 /* Used to pass variable sized buffers between user and kernel space (ioctls) */ typedef struct { @@ -281,31 +251,30 @@ typedef struct { /* Port config definitions */ typedef struct { - uint16_t mode; /* Push-pull = 1, Open-drain = 0 */ - uint16_t lowPower; - uint16_t latch; /* Logic high = 1, Logic low = 0 */ + uint16_t mode; /* Push-pull = 1, Open-drain = 0 */ + uint16_t lowPower; + uint16_t latch; /* Logic high = 1, Logic low = 0 */ } cp2101_port_state_t; typedef struct { - cp2101_port_state_t reset; - cp2101_port_state_t suspend; - uint8_t enhancedFxn; + cp2101_port_state_t reset; + cp2101_port_state_t suspend; + uint8_t enhancedFxn; } cp2101_port_config_t; #define PORT_CONFIG_LEN 13 /* Because sizeof() will pad to full words */ - /* * cp2101_buf_from_user * Copy a buffer from user space, returning the number of bytes copied * from ubuf.buf into kbuf. klen is the size of the buffer at kbuf. */ -size_t copy_buf_from_user(char* kbuf, unsigned long ubuf, size_t klen) +size_t copy_buf_from_user(char *kbuf, unsigned long ubuf, size_t klen) { - cp2101_buffer_t t; + cp2101_buffer_t t; - if (!kbuf || !ubuf || !klen || copy_from_user(&t, (cp2101_buffer_t *)ubuf, - sizeof(t))) + if (!kbuf || !ubuf || !klen || + copy_from_user(&t, (cp2101_buffer_t *)ubuf, sizeof(t))) return 0; if (t.len < klen) klen = t.len; @@ -314,145 +283,6 @@ size_t copy_buf_from_user(char* kbuf, unsigned long ubuf, size_t klen) return klen; } -/* - * cp2101_get_config - * Reads from the CP2101 configuration registers - * 'size' is specified in bytes. - * 'data' is a pointer to a pre-allocated array of integers large - * enough to hold 'size' bytes (with 4 bytes to each integer) - */ -static int cp2101_get_config(struct usb_serial_port* port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - u32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kmalloc (length * sizeof(u32), GFP_KERNEL); - memset(buf, 0, length * sizeof(u32)); - - if (!buf) { - DEV_ERR(&port->dev,"%s - out of memory.\n", __FUNCTION__); - return -ENOMEM; - } - - /* For get requests, the request number must be incremented */ - request++; - - /* Issue the request, attempting to read 'size' bytes */ - result = usb_control_msg ( - serial->dev, - usb_rcvctrlpipe (serial->dev, 0), - request, - REQTYPE_DEVICE_TO_HOST, - 0x0000, - 0, - buf, - size, - 300); - - /* Convert data into an array of integers */ - for (i=0; idev,"%s - Unable to send config request, " - "request=0x%x size=%d result=%d\n", - __FUNCTION__, request, size, result); - return -EPROTO; - } - - return 0; -} - -/* - * cp2101_set_config - * Writes to the CP2101 configuration registers - * Values less than 16 bits wide are sent directly - * 'size' is specified in bytes. - */ -static int cp2101_set_config(struct usb_serial_port* port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - u32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kmalloc(length * sizeof(u32), GFP_KERNEL); - if (!buf) { - DEV_ERR(&port->dev,"%s - out of memory.\n", - __FUNCTION__); - return -ENOMEM; - } - - /* Array of integers into bytes */ - for (i = 0; i < length; i++) buf[i] = cpu_to_le32(data[i]); - - if (size > 2) { - result = usb_control_msg ( - serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, - REQTYPE_HOST_TO_DEVICE, - 0x0000, - 0, - buf, - size, - 300); - } else { - result = usb_control_msg ( - serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, - REQTYPE_HOST_TO_DEVICE, - data[0], - 0, - NULL, - 0, - 300); - } - - kfree(buf); - - if ((size > 2 && result != size) || result < 0) { - DEV_ERR(&port->dev,"%s - Unable to send request, " - "request=0x%x size=%d result=%d\n", - __FUNCTION__, request, size, result); - return -EPROTO; - } - - /* Single data value */ - result = usb_control_msg ( - serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, - REQTYPE_HOST_TO_DEVICE, - data[0], - 0, - NULL, - 0, - 300); - return 0; -} - -/* - * cp2101_set_config_single - * Convenience function for calling cp2101_set_config on single data values - * without requiring an integer pointer - */ -static inline int cp2101_set_config_single(struct usb_serial_port* port, - u8 request, unsigned int data) -{ - return cp2101_set_config(port, request, &data, 2); -} - /* * cp2101_ctlmsg * A generic usb control message interface. @@ -494,8 +324,8 @@ static int cp2101_reset(struct usb_serial_port *port) #if 1 /* Is this better than usb_device_reset? It may be. Once a client issues * the reset ioctl, it must disconnect and reconnect, since the USB - * connections are torn down. We also ignore the error return, since the - * part resets and doesn't send one... + * connections are torn down. We also ignore the error return, since + * the part resets and doesn't send one... */ cp2101_ctlmsg(port, 0xff, 0x40, 0x0008, 0x00, 0, 0); #else @@ -509,15 +339,18 @@ static int cp2101_get_partnum(struct usb_serial_port *port) static u8 _partnum = 0; int ret = CP210x_SUCCESS; if (!_partnum) { - u8 addr = port->serial->dev->actconfig->interface[0]->cur_altsetting-> - endpoint[0].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + u8 addr = port->serial->dev->actconfig->interface[0]-> + cur_altsetting->endpoint[0].desc.bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; if (addr == 0x03 || addr == 0x02) /* The part is a cp2101 */ _partnum = 0x01; - else if (addr == 0x01) /* Must query part to determine part number */ - ret = (cp2101_ctlmsg(port, 0xff, 0xc0, 0x370b, 0x00, &_partnum, 1) - == 1) ? CP210x_SUCCESS : CP210x_DEVICE_IO_FAILED; - else + else if (addr == 0x01) { + /* Must query part to determine part number */ + if (cp2101_ctlmsg(port, 0xff, 0xc0, 0x370b, 0x00, + &_partnum, 1) != 1) + ret = CP210x_DEVICE_IO_FAILED; + } else ret = CP210x_DEVICE_IO_FAILED; } dbg("%s - partnum %u err %d", __FUNCTION__, _partnum, ret); @@ -547,7 +380,7 @@ static int make_usb_string(char* usbstr, size_t usblen, char* src, if (usbstr && usblen >= 2 && src && *src && srclen) { char* p; - /* The usb string format uses a single byte to represent length */ + /* The usb string format uses first byte as length */ if (usblen > 256) usblen = 256; @@ -574,12 +407,241 @@ static int make_usb_string(char* usbstr, size_t usblen, char* src, inline int cp2101_setstr(struct usb_serial_port *port, int cmd, char *usbstr) { unsigned len = usbstr[0]; - int ret = cp2101_ctlmsg(port, 0xff, 0x40, 0x3700 | (cmd & 0xff), 0, usbstr, - len); + int ret = cp2101_ctlmsg(port, 0xff, 0x40, 0x3700 | (cmd & 0xff), 0, + usbstr, len); dbg("%s - cmd 0x%02x len %d ret %d", __FUNCTION__, cmd, len, ret); return ret; } +/* Set all gpio simultaneously */ +static int cp2101_gpioset(struct usb_serial_port *port, u8 gpio) +{ + dbg("%s - port %d, gpio = 0x%.2x", __FUNCTION__, port->number, gpio); + + return cp2101_ctlmsg(port, 0xff, 0x40, 0x37e1, + ((uint16_t)gpio << 8) | GPIO_MASK, 0, 0); +} + +/* Set select gpio bits */ +static int cp2101_gpiosetb(struct usb_serial_port *port, u8 set, u8 clear) +{ + u16 gpio = 0; + + /* The bitmask is in the LSB, the values in the MSB */ + if (set & GPIO_0) + gpio |= (GPIO_0 << 8)|GPIO_0; + if (set & GPIO_1) + gpio |= (GPIO_1 << 8)|GPIO_1; + if (set & GPIO_2) + gpio |= (GPIO_2 << 8)|GPIO_2; + if (set & GPIO_3) + gpio |= (GPIO_3 << 8)|GPIO_3; + if (clear & GPIO_0) + gpio = (gpio & ~(GPIO_0 << 8))|GPIO_0; + if (clear & GPIO_1) + gpio = (gpio & ~(GPIO_1 << 8))|GPIO_1; + if (clear & GPIO_2) + gpio = (gpio & ~(GPIO_2 << 8))|GPIO_2; + if (clear & GPIO_3) + gpio = (gpio & ~(GPIO_3 << 8))|GPIO_3; + + dbg("%s - port %d, gpiob = 0x%.4x", __FUNCTION__, port->number, gpio); + + /* FIXME: how about REQTYPE_HOST_TO_DEVICE instead of 0x40? */ + return cp2101_ctlmsg(port, 0xff, 0x40, 0x37e1, gpio, 0, 0); +} + +static int cp2101_gpioget(struct usb_serial_port *port, u8* gpio) +{ + int ret; + + dbg("%s - port %d", __FUNCTION__, port->number); + + /* FIXME: how about REQTYPE_DEVICE_TO_HOST instead of 0xc0? */ + ret = cp2101_ctlmsg(port, 0xff, 0xc0, 0x00c2, 0, gpio, 1); + + dbg("%s - gpio = 0x%.2x (%d)", __FUNCTION__, *gpio, ret); + + return (ret == 1) ? 0 : -1; +} + +static int cp2101_portconfset(struct usb_serial_port *port, + cp2101_port_config_t* config) +{ + cp2101_port_config_t lconfig; + int ret; + + dbg("%s", __FUNCTION__); + + memcpy(&lconfig, config, sizeof(lconfig)); + + /* apparently not implemented yet */ + lconfig.suspend.lowPower = 0; + lconfig.reset.lowPower = 0; + + /* Words from cp2103 are MSB */ + lconfig.reset.mode = cpu_to_be16(config->reset.mode); + /* lconfig.reset.lowPower = cpu_to_be16(config->reset.lowPower); */ + lconfig.reset.latch = cpu_to_be16(config->reset.latch); + lconfig.suspend.mode = cpu_to_be16(config->suspend.mode); + /* lconfig.suspend.lowPower = cpu_to_be16(config->suspend.lowPower); */ + lconfig.suspend.latch = cpu_to_be16(config->suspend.latch); + + ret = cp2101_ctlmsg(port, 0xff, 0x40, 0x370c, 0, &lconfig, + PORT_CONFIG_LEN); + if (ret == PORT_CONFIG_LEN) + return 0; + else if (ret >= 0) + return -1; + else + return ret; +} + +static int cp2101_portconfget(struct usb_serial_port *port, + cp2101_port_config_t* config) +{ + int ret; + + dbg("%s", __FUNCTION__); + + ret = cp2101_ctlmsg(port, 0xff, 0xc0, 0x370c, 0, config, + PORT_CONFIG_LEN); + if (ret == PORT_CONFIG_LEN) { + /* Words from cp2103 are MSB */ + config->reset.mode = be16_to_cpu(config->reset.mode); + config->reset.lowPower = be16_to_cpu(config->reset.lowPower); + config->reset.latch = be16_to_cpu(config->reset.latch); + config->suspend.mode = be16_to_cpu(config->suspend.mode); + config->suspend.lowPower = + be16_to_cpu(config->suspend.lowPower); + config->suspend.latch = be16_to_cpu(config->suspend.latch); + + /* apparently not implemented yet */ + config->reset.lowPower = 0; + config->suspend.lowPower = 0; + + return 0; + } else if (ret >= 0) + return -1; + else + return ret; + +} + +/* + * cp2101_get_config + * Reads from the CP2101 configuration registers + * 'size' is specified in bytes. + * 'data' is a pointer to a pre-allocated array of integers large + * enough to hold 'size' bytes (with 4 bytes to each integer) + */ +static int cp2101_get_config(struct usb_serial_port* port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); + return -ENOMEM; + } + + /* For get requests, the request number must be incremented */ + request++; + + /* Issue the request, attempting to read 'size' bytes */ + result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0), + request, REQTYPE_DEVICE_TO_HOST, 0x0000, + 0, buf, size, 300); + + /* Convert data into an array of integers */ + for (i=0; idev, "%s - Unable to send config request, " + "request=0x%x size=%d result=%d\n", + __FUNCTION__, request, size, result); + return -EPROTO; + } + + return 0; +} + +/* + * cp2101_set_config + * Writes to the CP2101 configuration registers + * Values less than 16 bits wide are sent directly + * 'size' is specified in bytes. + */ +static int cp2101_set_config(struct usb_serial_port* port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", + __FUNCTION__); + return -ENOMEM; + } + + /* Array of integers into bytes */ + for (i = 0; i < length; i++) + buf[i] = cpu_to_le32(data[i]); + + if (size > 2) { + result = usb_control_msg (serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, 0x0000, + 0, buf, size, 300); + } else { + result = usb_control_msg (serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + } + + kfree(buf); + + if ((size > 2 && result != size) || result < 0) { + dev_err(&port->dev, "%s - Unable to send request, " + "request=0x%x size=%d result=%d\n", + __FUNCTION__, request, size, result); + return -EPROTO; + } + + /* Single data value */ + result = usb_control_msg (serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + return 0; +} + +/* + * cp2101_set_config_single + * Convenience function for calling cp2101_set_config on single data values + * without requiring an integer pointer + */ +static inline int cp2101_set_config_single(struct usb_serial_port* port, + u8 request, unsigned int data) +{ + return cp2101_set_config(port, request, &data, 2); +} + static int cp2101_open (struct usb_serial_port *port, struct file *filp) { struct usb_serial *serial = port->serial; @@ -588,7 +650,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp) dbg("%s - port %d", __FUNCTION__, port->number); if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { - DEV_ERR(&port->dev, "%s - Unable to enable UART\n", + dev_err(&port->dev, "%s - Unable to enable UART\n", __FUNCTION__); return -EPROTO; } @@ -601,9 +663,9 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp) port->read_urb->transfer_buffer_length, serial->type->read_bulk_callback, port); - result = USB_SUBMIT_URB_KERNEL(port->read_urb); + result = usb_submit_urb(port->read_urb, GFP_KERNEL); if (result) { - DEV_ERR(&port->dev, "%s - failed resubmitting read urb, " + dev_err(&port->dev, "%s - failed resubmitting read urb, " "error %d\n", __FUNCTION__, result); return result; } @@ -623,22 +685,13 @@ static void cp2101_cleanup (struct usb_serial_port *port) dbg("%s - port %d", __FUNCTION__, port->number); - if (serial != NULL && serial->dev) { + if (serial->dev) { /* shutdown any bulk reads that might be going on */ if (serial->num_bulk_out) - USB_KILL_URB(port->write_urb); + usb_kill_urb(port->write_urb); if (serial->num_bulk_in) - USB_KILL_URB(port->read_urb); + usb_kill_urb(port->read_urb); } - -#ifdef LINUX26 - kfree (usb_get_serial_port_data(port)); - usb_set_serial_port_data(port, NULL); -#else - /*TODOGLA: port.private maybe? - Nobody is using that at the moement in this driver*/ -#endif - } static void cp2101_close (struct usb_serial_port *port, struct file * filp) @@ -647,12 +700,180 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp) /* shutdown our urbs */ dbg("%s - shutting down urbs", __FUNCTION__); - USB_KILL_URB(port->write_urb); - USB_KILL_URB(port->read_urb); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); } +static int cp2101_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); + + switch (cmd) { + + case TIOCMGET: + { + int result = cp2101_tiocmget(port, file); + if (copy_to_user(&arg, &result, sizeof(int))) + return -EFAULT; + return 0; + } + break; + + case TIOCMSET: + case TIOCMBIS: + + case TIOCMBIC: + { + int val = 0; + + if (copy_from_user(&val, &arg, sizeof(int))) + return -EFAULT; + + /* this looks wrong: TIOCMSET isn't going to work right */ + if (cp2101_tiocmset(port, file, cmd==TIOCMBIC ? 0 : val, + cmd==TIOCMBIC ? val : 0)) + return -EFAULT; + return 0; + } + break; + + case IOCTL_GPIOGET: + if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION) { + u8 gpio = 0; + if (!cp2101_gpioget(port, &gpio) && !copy_to_user((u8*)arg, + &gpio, sizeof(gpio))) + return 0; + } + return -EFAULT; + break; + + case IOCTL_GPIOSET: + if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION && + !cp2101_gpioset(port, arg)) + return 0; + return -EFAULT; + break; + + case IOCTL_GPIOBIC: + case IOCTL_GPIOBIS: + if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION && + !cp2101_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, + (cmd==IOCTL_GPIOBIC) ? arg : 0)) + return 0; + return -EFAULT; + break; + + case IOCTL_DEVICERESET: + return cp2101_reset(port); + break; + + case IOCTL_PORTCONFGET: + { + cp2101_port_config_t config; + if (!cp2101_portconfget(port, &config) && !copy_to_user( + (cp2101_port_config_t*)arg, &config, + sizeof(config))) + return 0; + } + return -EFAULT; + break; + + case IOCTL_PORTCONFSET: + { + cp2101_port_config_t config; + if (!copy_from_user(&config, (cp2101_port_config_t*)arg, + sizeof(config)) && + !cp2101_portconfset(port, &config)) + return 0; + return -EFAULT; + } + break; + + case IOCTL_SETVID: + { + unsigned int vid; + if (!copy_from_user(&vid, (unsigned int *)arg, + sizeof(unsigned int)) && + !cp2101_setu16(port, 0x01, vid)) + return 0; + return -EFAULT; + } + break; + + case IOCTL_SETPID: + { + unsigned int pid; + if (!copy_from_user(&pid, (unsigned int *)arg, + sizeof(unsigned int)) && + !cp2101_setu16(port, 0x02, pid)) + return 0; + return -EFAULT; + } + break; + + case IOCTL_SETMFG: +#if 0 /* Silicon Labs apparently doesn't provide for setting of mfg desc */ + { + char usbstr[CP210x_MAX_MFG_STRLEN * 2 + 2]; + size_t len = copy_buf_from_user(usbstr + sizeof(usbstr) - + CP210x_MAX_MFG_STRLEN, arg, + CP210x_MAX_MFG_STRLEN); + len = make_usb_string(usbstr, sizeof(usbstr), str, len); + if (len && cp2101_setstr(port, 0x00, usbstr) == len) + return 0; + return -EFAULT; + } +#endif + break; + + case IOCTL_SETPRODUCT: + { + char usbstr[CP210x_MAX_PRODUCT_STRLEN * 2 + 2]; + char* str = usbstr + sizeof(usbstr) - CP210x_MAX_PRODUCT_STRLEN; + size_t len = copy_buf_from_user(str, arg, + CP210x_MAX_PRODUCT_STRLEN); + len = make_usb_string(usbstr, sizeof(usbstr), str, len); + if (len && cp2101_setstr(port, 0x03, usbstr) == len) + return 0; + return -EFAULT; + } + break; + + case IOCTL_SETSERIAL: + { + char usbstr[CP210x_MAX_SERIAL_STRLEN * 2 + 2]; + char* str = usbstr + sizeof(usbstr) - CP210x_MAX_SERIAL_STRLEN; + size_t len = copy_buf_from_user(str, arg, + CP210x_MAX_SERIAL_STRLEN); + len = make_usb_string(usbstr, sizeof(usbstr), str, len); + if (len && cp2101_setstr(port, 0x04, usbstr) == len) + return 0; + return -EFAULT; + } + break; + + case IOCTL_SETDEVVER: + { + unsigned int ver; + if (!copy_from_user(&ver, (unsigned int *)arg, + sizeof(unsigned int)) && + !cp2101_setu16(port, 0x07, ver)) + return 0; + return -EFAULT; + } + break; + + default: + dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); + break; + } + + return -ENOIOCTLCMD; +} + /* * cp2101_get_termios * Reads the baud rate, data bits, parity, stop bits and flow control mode @@ -667,11 +888,10 @@ static void cp2101_get_termios (struct usb_serial_port *port) dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { + if (!port->tty || !port->tty->termios) { dbg("%s - no tty structures", __FUNCTION__); return; } - cflag = port->tty->termios->c_cflag; cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ @@ -679,40 +899,9 @@ static void cp2101_get_termios (struct usb_serial_port *port) baud = BAUD_RATE_GEN_FREQ / baud; dbg("%s - baud rate = %d", __FUNCTION__, baud); - cflag &= ~CBAUD; - switch (baud) { - /* - * The baud rates which are commented out below - * appear to be supported by the device - * but are non-standard - */ - case 600: cflag |= B600; break; - case 1200: cflag |= B1200; break; - case 1800: cflag |= B1800; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - /*case 7200: cflag |= B7200; break;*/ - case 9600: cflag |= B9600; break; - /*case 14400: cflag |= B14400; break;*/ - case 19200: cflag |= B19200; break; - /*case 28800: cflag |= B28800; break;*/ - case 38400: cflag |= B38400; break; - /*case 55854: cflag |= B55054; break;*/ - case 57600: cflag |= B57600; break; - case 115200: cflag |= B115200; break; - /*case 127117: cflag |= B127117; break;*/ - case 230400: cflag |= B230400; break; - case 460800: cflag |= B460800; break; - case 921600: cflag |= B921600; break; - /*case 3686400: cflag |= B3686400; break;*/ - default: - dbg("%s - Baud rate is not supported, " - "using 9600 baud", __FUNCTION__); - cflag |= B9600; - cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ/9600)); - break; - } + + tty_encode_baud_rate(port->tty, baud, baud); + cflag = port->tty->termios->c_cflag; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; @@ -824,63 +1013,50 @@ static void cp2101_get_termios (struct usb_serial_port *port) } static void cp2101_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { - unsigned int cflag, old_cflag=0; + unsigned int cflag, old_cflag; int baud=0, bits; unsigned int modem_ctl[4]; dbg("%s - port %d", __FUNCTION__, port->number); - if ((!port->tty) || (!port->tty->termios)) { + if (!port->tty || !port->tty->termios) { dbg("%s - no tty structures", __FUNCTION__); return; } - cflag = port->tty->termios->c_cflag; - - /* Check that they really want us to change something */ - if (old_termios) { - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(port->tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) { - dbg("%s - nothing to change...", __FUNCTION__); - return; - } + port->tty->termios->c_cflag &= ~CMSPAR; - old_cflag = old_termios->c_cflag; - } + cflag = port->tty->termios->c_cflag; + old_cflag = old_termios->c_cflag; + baud = tty_get_baud_rate(port->tty); /* If the baud rate is to be updated*/ - if ((cflag & CBAUD) != (old_cflag & CBAUD)) { - switch (cflag & CBAUD) { - /* - * The baud rates which are commented out below - * appear to be supported by the device - * but are non-standard - */ - case B0: baud = 0; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - /*case B7200: baud = 7200; break;*/ - case B9600: baud = 9600; break; - /*ase B14400: baud = 14400; break;*/ - case B19200: baud = 19200; break; - /*case B28800: baud = 28800; break;*/ - case B38400: baud = 38400; break; - /*case B55854: baud = 55054; break;*/ - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - /*case B127117: baud = 127117; break;*/ - case B230400: baud = 230400; break; - case B460800: baud = 460800; break; - case B921600: baud = 921600; break; - /*case B3686400: baud = 3686400; break;*/ + if (baud != tty_termios_baud_rate(old_termios)) { + switch (baud) { + case 0: + case 600: + case 1200: + case 1800: + case 2400: + case 4800: + case 7200: + case 9600: + case 14400: + case 19200: + case 28800: + case 38400: + case 55854: + case 57600: + case 115200: + case 127117: + case 230400: + case 460800: + case 921600: + case 3686400: + break; default: - DEV_ERR(&port->dev, "cp2101 driver does not " - "support the baudrate requested\n"); + baud = 9600; break; } @@ -888,11 +1064,15 @@ static void cp2101_set_termios (struct usb_serial_port *port, dbg("%s - Setting baud rate to %d baud", __FUNCTION__, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ / baud))) - DEV_ERR(&port->dev, "Baud rate requested not " + (BAUD_RATE_GEN_FREQ / baud))) { + dev_err(&port->dev, "Baud rate requested not " "supported by device\n"); + baud = tty_termios_baud_rate(old_termios); + } } } + /* Report back the resulting baud rate */ + tty_encode_baud_rate(port->tty, baud, baud); /* If the number of data bits is to be updated */ if ((cflag & CSIZE) != (old_cflag & CSIZE)) { @@ -920,14 +1100,14 @@ static void cp2101_set_termios (struct usb_serial_port *port, dbg("%s - data bits = 9", __FUNCTION__); break;*/ default: - DEV_ERR(&port->dev, "cp2101 driver does not " + dev_err(&port->dev, "cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - DEV_ERR(&port->dev,"Number of data bits requested " + dev_err(&port->dev, "Number of data bits requested " "not supported by device\n"); } @@ -944,7 +1124,7 @@ static void cp2101_set_termios (struct usb_serial_port *port, } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - DEV_ERR(&port->dev,"Parity mode not supported " + dev_err(&port->dev, "Parity mode not supported " "by device\n"); } @@ -959,7 +1139,7 @@ static void cp2101_set_termios (struct usb_serial_port *port, dbg("%s - stop bits = 1", __FUNCTION__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - DEV_ERR(&port->dev,"Number of stop bits requested " + dev_err(&port->dev, "Number of stop bits requested " "not supported by device\n"); } @@ -1053,287 +1233,6 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state) cp2101_set_config(port, CP2101_BREAK, &state, 2); } -/* Set all gpio simultaneously */ -static int cp2101_gpioset(struct usb_serial_port *port, u8 gpio) -{ - dbg("%s - port %d, gpio = 0x%.2x", __FUNCTION__, port->number, gpio); - - return cp2101_ctlmsg(port, 0xff, 0x40, 0x37e1, - ((uint16_t)gpio << 8) | GPIO_MASK, 0, 0); -} - -/* Set select gpio bits */ -static int cp2101_gpiosetb(struct usb_serial_port *port, u8 set, u8 clear) -{ - u16 gpio = 0; - - /* The bitmask is in the LSB, the values in the MSB */ - if (set & GPIO_0) - gpio |= (GPIO_0 << 8)|GPIO_0; - if (set & GPIO_1) - gpio |= (GPIO_1 << 8)|GPIO_1; - if (set & GPIO_2) - gpio |= (GPIO_2 << 8)|GPIO_2; - if (set & GPIO_3) - gpio |= (GPIO_3 << 8)|GPIO_3; - if (clear & GPIO_0) - gpio = (gpio & ~(GPIO_0 << 8))|GPIO_0; - if (clear & GPIO_1) - gpio = (gpio & ~(GPIO_1 << 8))|GPIO_1; - if (clear & GPIO_2) - gpio = (gpio & ~(GPIO_2 << 8))|GPIO_2; - if (clear & GPIO_3) - gpio = (gpio & ~(GPIO_3 << 8))|GPIO_3; - - dbg("%s - port %d, gpiob = 0x%.4x", __FUNCTION__, port->number, gpio); - - /* FIXME: how about REQTYPE_HOST_TO_DEVICE instead of 0x40? */ - return cp2101_ctlmsg(port, 0xff, 0x40, 0x37e1, gpio, 0, 0); -} - -static int cp2101_gpioget(struct usb_serial_port *port, u8* gpio) -{ - int ret; - - dbg("%s - port %d", __FUNCTION__, port->number); - - /* FIXME: how about REQTYPE_DEVICE_TO_HOST instead of 0xc0? */ - ret = cp2101_ctlmsg(port, 0xff, 0xc0, 0x00c2, 0, gpio, 1); - - dbg("%s - gpio = 0x%.2x (%d)", __FUNCTION__, *gpio, ret); - - return (ret == 1) ? 0 : -1; -} - -static int cp2101_portconfset(struct usb_serial_port *port, - cp2101_port_config_t* config) -{ - cp2101_port_config_t lconfig; - int ret; - - dbg("%s", __FUNCTION__); - - memcpy(&lconfig, config, sizeof(lconfig)); - - /* apparently not implemented yet */ - lconfig.suspend.lowPower = 0; - lconfig.reset.lowPower = 0; - - /* Words from cp2103 are MSB */ - lconfig.reset.mode = cpu_to_be16(config->reset.mode); - /* lconfig.reset.lowPower = cpu_to_be16(config->reset.lowPower); */ - lconfig.reset.latch = cpu_to_be16(config->reset.latch); - lconfig.suspend.mode = cpu_to_be16(config->suspend.mode); - /* lconfig.suspend.lowPower = cpu_to_be16(config->suspend.lowPower); */ - lconfig.suspend.latch = cpu_to_be16(config->suspend.latch); - - ret = cp2101_ctlmsg(port, 0xff, 0x40, 0x370c, 0, &lconfig, PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) - return 0; - else if (ret >= 0) - return -1; - else - return ret; -} - -static int cp2101_portconfget(struct usb_serial_port *port, - cp2101_port_config_t* config) -{ - int ret; - - dbg("%s", __FUNCTION__); - - ret = cp2101_ctlmsg(port, 0xff, 0xc0, 0x370c, 0, config, PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) { - /* Words from cp2103 are MSB */ - config->reset.mode = be16_to_cpu(config->reset.mode); - config->reset.lowPower = be16_to_cpu(config->reset.lowPower); - config->reset.latch = be16_to_cpu(config->reset.latch); - config->suspend.mode = be16_to_cpu(config->suspend.mode); - config->suspend.lowPower = be16_to_cpu(config->suspend.lowPower); - config->suspend.latch = be16_to_cpu(config->suspend.latch); - - /* apparently not implemented yet */ - config->reset.lowPower = 0; - config->suspend.lowPower = 0; - - return 0; - } else if (ret >= 0) - return -1; - else - return ret; - -} - -static int cp2101_ioctl (struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg) -{ - dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); - - switch (cmd) { - -#ifndef LINUX26 - case TIOCMGET: - { - int result = cp2101_tiocmget(port, file); - if (copy_to_user(&arg, &result, sizeof(int))) - return -EFAULT; - return 0; - } - break; - - case TIOCMSET: - case TIOCMBIS: - - case TIOCMBIC: - { - int val = 0; - - if (copy_from_user(&val, &arg, sizeof(int))) - return -EFAULT; - -/* this looks wrong: TIOCMSET isn't going to work right */ - if(cp2101_tiocmset(port, file, cmd==TIOCMBIC?0:val, cmd==TIOCMBIC?val:0)) - return -EFAULT; - return 0; - } - break; -#endif - - case IOCTL_GPIOGET: - if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION) { - u8 gpio = 0; - if (!cp2101_gpioget(port, &gpio) && - !copy_to_user((u8*)arg, &gpio, sizeof(gpio))) - return 0; - } - return -EFAULT; - break; - - case IOCTL_GPIOSET: - if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION && - !cp2101_gpioset(port, arg)) - return 0; - return -EFAULT; - break; - - case IOCTL_GPIOBIC: - case IOCTL_GPIOBIS: - if (cp2101_get_partnum(port) == CP210x_CP2103_VERSION && - !cp2101_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, - (cmd==IOCTL_GPIOBIC) ? arg : 0)) - return 0; - return -EFAULT; - break; - - case IOCTL_DEVICERESET: - return cp2101_reset(port); - break; - - case IOCTL_PORTCONFGET: - { - cp2101_port_config_t config; - if (!cp2101_portconfget(port, &config) && - !copy_to_user((cp2101_port_config_t*)arg, &config, - sizeof(config))) - return 0; - } - return -EFAULT; - break; - - case IOCTL_PORTCONFSET: - { - cp2101_port_config_t config; - if (!copy_from_user(&config, (cp2101_port_config_t*)arg, - sizeof(config)) && - !cp2101_portconfset(port, &config)) - return 0; - return -EFAULT; - } - break; - - case IOCTL_SETVID: - { - unsigned int vid; - if (!copy_from_user(&vid, (unsigned int *)arg, - sizeof(unsigned int)) && - !cp2101_setu16(port, 0x01, vid)) - return 0; - return -EFAULT; - } - break; - - case IOCTL_SETPID: - { - unsigned int pid; - if (!copy_from_user(&pid, (unsigned int *)arg, - sizeof(unsigned int)) && - !cp2101_setu16(port, 0x02, pid)) - return 0; - return -EFAULT; - } - break; - - case IOCTL_SETMFG: -#if 0 /* Don't know how to set manufacturer desc yet */ - { - char usbstr[CP210x_MAX_MFG_STRLEN * 2 + 2]; - size_t len = copy_buf_from_user( - usbstr + sizeof(usbstr) - CP210x_MAX_MFG_STRLEN, arg, - CP210x_MAX_MFG_STRLEN); - len = make_usb_string(usbstr, sizeof(usbstr), str, len); - if (len && cp2101_setstr(port, 0x00, usbstr) == len) - return 0; - return -EFAULT; - } -#endif - break; - - case IOCTL_SETPRODUCT: - { - char usbstr[CP210x_MAX_PRODUCT_STRLEN * 2 + 2]; - char* str = usbstr + sizeof(usbstr) - CP210x_MAX_PRODUCT_STRLEN; - size_t len = copy_buf_from_user(str, arg, - CP210x_MAX_PRODUCT_STRLEN); - len = make_usb_string(usbstr, sizeof(usbstr), str, len); - if (len && cp2101_setstr(port, 0x03, usbstr) == len) - return 0; - return -EFAULT; - } - break; - - case IOCTL_SETSERIAL: - { - char usbstr[CP210x_MAX_SERIAL_STRLEN * 2 + 2]; - char* str = usbstr + sizeof(usbstr) - CP210x_MAX_SERIAL_STRLEN; - size_t len = copy_buf_from_user(str, arg, - CP210x_MAX_SERIAL_STRLEN); - len = make_usb_string(usbstr, sizeof(usbstr), str, len); - if (len && cp2101_setstr(port, 0x04, usbstr) == len) - return 0; - return -EFAULT; - } - break; - - case IOCTL_SETDEVVER: - { - unsigned int ver; - if (!copy_from_user(&ver, (unsigned int *)arg, - sizeof(unsigned int)) && - !cp2101_setu16(port, 0x07, ver)) - return 0; - return -EFAULT; - } - break; - - default: - dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); - break; - } - - return -ENOIOCTLCMD; -} - static int cp2101_startup (struct usb_serial *serial) { /* CP2101 buffers behave strangely unless device is reset */ @@ -1349,11 +1248,7 @@ static void cp2101_shutdown (struct usb_serial *serial) /* Stop reads and writes on all ports */ for (i=0; i < serial->num_ports; ++i) { -#ifdef LINUX26 cp2101_cleanup(serial->port[i]); -#else - cp2101_cleanup(&serial->port[i]); -#endif } } @@ -1365,14 +1260,13 @@ static int __init cp2101_init (void) if (retval) return retval; /* Failed to register */ -#ifdef LINUX26 - retval = usb_register(&cp2101_driver); + retval = usb_register(&cp2101_driver); if (retval) { /* Failed to register */ usb_serial_deregister(&cp2101_device); return retval; } -#endif + /* Success */ info(DRIVER_DESC " " DRIVER_VERSION); return 0; @@ -1380,9 +1274,7 @@ static int __init cp2101_init (void) static void __exit cp2101_exit (void) { -#ifdef LINUX26 usb_deregister (&cp2101_driver); -#endif usb_serial_deregister (&cp2101_device); } @@ -1390,17 +1282,8 @@ module_init(cp2101_init); module_exit(cp2101_exit); MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); -#ifdef LINUX26 -MODULE_VERSION(DRIVER_VERSION); module_param(debug, bool, S_IRUGO | S_IWUSR); -#else -MODULE_PARM(debug, "i"); -#endif MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); - -/* -vi:ts=4 -*/ -