From: R. Steve McKown Date: Mon, 17 May 2010 15:55:48 +0000 (-0600) Subject: Move userspace/kernel shared defs to cp210x.h; no new typedefs; other cleanups. X-Git-Tag: debian/0.11.3-3tmi~13 X-Git-Url: https://oss.titaniummirror.com/gitweb?p=cp210x.git;a=commitdiff_plain;h=a50a97ae61aefa7a7795e46c71c1eee09ac951b6 Move userspace/kernel shared defs to cp210x.h; no new typedefs; other cleanups. --- diff --git a/src/cp210x.c b/src/cp210x.c index e89ed3c..af0302c 100644 --- a/src/cp210x.c +++ b/src/cp210x.c @@ -23,6 +23,7 @@ #include #include #include +#include "cp210x.h" /* * Version Information @@ -200,96 +201,44 @@ static struct usb_serial_driver cp210x_device = { #define CONTROL_WRITE_DTR 0x0100 #define CONTROL_WRITE_RTS 0x0200 -/* CP2103 ioctls */ -#define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ -#define IOCTL_GPIOSET 0x8001 /* Set gpio bits */ -#define IOCTL_GPIOBIC 0x8002 /* Clear specific gpio bit(s) */ -#define IOCTL_GPIOBIS 0x8003 /* Set specific gpio bit(s) */ - -/* CP210x ioctls principally used during initial device configuration */ -#define IOCTL_DEVICERESET 0x8004 /* Reset the cp210x */ -#define IOCTL_PORTCONFGET 0x8005 /* Get port configuration */ -#define IOCTL_PORTCONFSET 0x8006 /* Set port configuration */ -#define IOCTL_SETVID 0x8007 /* Set vendor id */ -#define IOCTL_SETPID 0x8008 /* Set product id */ -#define IOCTL_SETMFG 0x8009 /* Set manufacturer string */ -#define IOCTL_SETPRODUCT 0x800a /* Set product string */ -#define IOCTL_SETSERIAL 0x800b /* Set serial number string */ -#define IOCTL_SETDEVVER 0x800c /* set device version id */ -/* 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) - -/* GetDeviceVersion() return codes */ -#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 - -/* 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 - -/* Used to pass variable sized buffers between user and kernel space (ioctls) */ -typedef struct { - char *buf; - size_t len; -} cp210x_buffer_t; - -/* 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 */ -} cp210x_port_state_t; - -typedef struct { - cp210x_port_state_t reset; - cp210x_port_state_t suspend; - uint8_t enhancedFxn; -} cp210x_port_config_t; - -#define PORT_CONFIG_LEN 13 /* Because sizeof() will pad to full words */ +/* cp210x_get_partnum() return codes */ +#define CP210x_PART_UNKNOWN 0x00 +#define CP210x_PART_CP2101 0x01 +#define CP210x_PART_CP2102 0x02 +#define CP210x_PART_CP2103 0x03 /* * cp210x_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. */ -static size_t copy_buf_from_user(char *kbuf, unsigned long ubuf, size_t klen) +static size_t cp210x_buf_from_user(char *kbuf, unsigned long ubuf, size_t klen) { - cp210x_buffer_t t; + struct cp210x_buffer t; if (!kbuf || !ubuf || !klen || - copy_from_user(&t, (cp210x_buffer_t __user *)ubuf, + copy_from_user(&t, (struct cp210x_buffer __user *)ubuf, sizeof(t))) return 0; if (t.len < klen) klen = t.len; if (!t.buf || !t.len || - copy_from_user(kbuf, (char __user *)t.buf, klen)) + copy_from_user(kbuf, (u8 __user *)t.buf, klen)) return 0; return klen; } +/* cp210x_has_setmfg + * Returns 1 if the CP210X part includes firmware that allows setting the + * USB MFG descriptor, else 0. As of this writing, no CP210X firmware allows + * this. SiLabs has suggested this may change in future firmware versions or + * parts. + */ +static inline int cp210x_has_setmfg(void) +{ + return 0; +} + /* * cp210x_ctlmsg * A generic usb control message interface. @@ -329,7 +278,7 @@ static int cp210x_reset(struct usb_serial_port *port) dbg("%s", __FUNCTION__); #if 1 - /* Is this better than usb_device_reset? It may be. Once a client issues + /* 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... @@ -343,25 +292,24 @@ static int cp210x_reset(struct usb_serial_port *port) static int cp210x_get_partnum(struct usb_serial_port *port) { - static u8 _partnum = 0; - int ret = CP210x_SUCCESS; - if (!_partnum) { + static u8 _partnum = CP210x_PART_UNKNOWN; + + if (_partnum == CP210x_PART_UNKNOWN) { 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; + if (addr == 0x03 || addr == 0x02) + _partnum = CP210x_PART_CP2101; else if (addr == 0x01) { /* Must query part to determine part number */ if (cp210x_ctlmsg(port, 0xff, 0xc0, 0x370b, 0x00, &_partnum, 1) != 1) - ret = CP210x_DEVICE_IO_FAILED; - } else - ret = CP210x_DEVICE_IO_FAILED; + _partnum = CP210x_PART_UNKNOWN; + } } - dbg("%s - partnum %u err %d", __FUNCTION__, _partnum, ret); - return (ret == CP210x_SUCCESS) ? _partnum : 0; + dbg("%s - partnum %u", __FUNCTION__, _partnum); + return _partnum; } static inline int cp210x_setu16(struct usb_serial_port *port, int cmd, @@ -387,9 +335,8 @@ 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 first byte as length */ - if (usblen > 256) - usblen = 256; + if (usblen > 255) + usblen = 255; p = usbstr + 1; *p++ = 0x03; @@ -473,30 +420,31 @@ static int cp210x_gpioget(struct usb_serial_port *port, u8 *gpio) } static int cp210x_portconfset(struct usb_serial_port *port, - cp210x_port_config_t *config) + struct cp210x_port_config *config) { - cp210x_port_config_t lconfig; + struct cp210x_port_config 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); +#if 0 /* apparently not implemented by CP210X firmware */ + lconfig.reset.lowPower = cpu_to_be16(config->reset.lowPower); + lconfig.suspend.lowPower = cpu_to_be16(config->suspend.lowPower); +#else + lconfig.suspend.lowPower = 0; + lconfig.reset.lowPower = 0; +#endif ret = cp210x_ctlmsg(port, 0xff, 0x40, 0x370c, 0, &lconfig, - PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) + sizeof(struct cp210x_port_config)); + if (ret == sizeof(struct cp210x_port_config)) return 0; else if (ret >= 0) return -1; @@ -505,15 +453,15 @@ static int cp210x_portconfset(struct usb_serial_port *port, } static int cp210x_portconfget(struct usb_serial_port *port, - cp210x_port_config_t *config) + struct cp210x_port_config *config) { int ret; dbg("%s", __FUNCTION__); ret = cp210x_ctlmsg(port, 0xff, 0xc0, 0x370c, 0, config, - PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) { + sizeof(struct cp210x_port_config)); + if (ret == sizeof(struct cp210x_port_config)) { /* Words from cp2103 are MSB */ config->reset.mode = be16_to_cpu(config->reset.mode); config->reset.lowPower = be16_to_cpu(config->reset.lowPower); @@ -742,7 +690,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, break; case IOCTL_GPIOGET: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION) { + if (cp210x_get_partnum(port) == CP210x_PART_CP2103) { u8 gpio = 0; if (!cp210x_gpioget(port, &gpio) && !copy_to_user( (u8 __user *)arg, &gpio, sizeof(gpio))) @@ -752,7 +700,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, break; case IOCTL_GPIOSET: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION && + if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpioset(port, arg)) return 0; return -EFAULT; @@ -760,7 +708,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, case IOCTL_GPIOBIC: case IOCTL_GPIOBIS: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION && + if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, (cmd==IOCTL_GPIOBIC) ? arg : 0)) return 0; @@ -773,9 +721,9 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, case IOCTL_PORTCONFGET: { - cp210x_port_config_t config; + struct cp210x_port_config config; if (!cp210x_portconfget(port, &config) && !copy_to_user( - (cp210x_port_config_t __user *)arg, + (struct cp210x_port_config __user *)arg, &config, sizeof(config))) return 0; } @@ -784,8 +732,8 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, case IOCTL_PORTCONFSET: { - cp210x_port_config_t config; - if (!copy_from_user(&config, (cp210x_port_config_t __user *)arg, + struct cp210x_port_config config; + if (!copy_from_user(&config, (struct cp210x_port_config __user *)arg, sizeof(config)) && !cp210x_portconfset(port, &config)) return 0; @@ -816,25 +764,23 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, break; case IOCTL_SETMFG: -#if 0 /* Silicon Labs apparently doesn't provide for setting of mfg desc */ - { + if (cp210x_has_setmfg()) { char usbstr[CP210x_MAX_MFG_STRLEN * 2 + 2]; - size_t len = copy_buf_from_user(usbstr + sizeof(usbstr) - - CP210x_MAX_MFG_STRLEN, arg, + char *str = usbstr + sizeof(usbstr) - CP210x_MAX_MFG_STRLEN; + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_MFG_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x00, usbstr) == len) return 0; - return -EFAULT; } -#endif + return -EFAULT; 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, + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_PRODUCT_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x03, usbstr) == len) @@ -847,7 +793,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, { 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, + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_SERIAL_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x04, usbstr) == len) diff --git a/src/cp210x.c.karmic b/src/cp210x.c.karmic index 831a0f4..78d6b62 100644 --- a/src/cp210x.c.karmic +++ b/src/cp210x.c.karmic @@ -23,6 +23,7 @@ #include #include #include +#include "cp210x.h" /* * Version Information @@ -221,96 +222,44 @@ static struct usb_serial_driver cp210x_device = { #define CONTROL_WRITE_DTR 0x0100 #define CONTROL_WRITE_RTS 0x0200 -/* CP2103 ioctls */ -#define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ -#define IOCTL_GPIOSET 0x8001 /* Set gpio bits */ -#define IOCTL_GPIOBIC 0x8002 /* Clear specific gpio bit(s) */ -#define IOCTL_GPIOBIS 0x8003 /* Set specific gpio bit(s) */ - -/* CP210x ioctls principally used during initial device configuration */ -#define IOCTL_DEVICERESET 0x8004 /* Reset the cp210x */ -#define IOCTL_PORTCONFGET 0x8005 /* Get port configuration */ -#define IOCTL_PORTCONFSET 0x8006 /* Set port configuration */ -#define IOCTL_SETVID 0x8007 /* Set vendor id */ -#define IOCTL_SETPID 0x8008 /* Set product id */ -#define IOCTL_SETMFG 0x8009 /* Set manufacturer string */ -#define IOCTL_SETPRODUCT 0x800a /* Set product string */ -#define IOCTL_SETSERIAL 0x800b /* Set serial number string */ -#define IOCTL_SETDEVVER 0x800c /* set device version id */ -/* 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) - -/* GetDeviceVersion() return codes */ -#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 - -/* 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 - -/* Used to pass variable sized buffers between user and kernel space (ioctls) */ -typedef struct { - char *buf; - size_t len; -} cp210x_buffer_t; - -/* 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 */ -} cp210x_port_state_t; - -typedef struct { - cp210x_port_state_t reset; - cp210x_port_state_t suspend; - uint8_t enhancedFxn; -} cp210x_port_config_t; - -#define PORT_CONFIG_LEN 13 /* Because sizeof() will pad to full words */ +/* cp210x_get_partnum() return codes */ +#define CP210x_PART_UNKNOWN 0x00 +#define CP210x_PART_CP2101 0x01 +#define CP210x_PART_CP2102 0x02 +#define CP210x_PART_CP2103 0x03 /* * cp210x_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. */ -static size_t copy_buf_from_user(char *kbuf, unsigned long ubuf, size_t klen) +static size_t cp210x_buf_from_user(char *kbuf, unsigned long ubuf, size_t klen) { - cp210x_buffer_t t; + struct cp210x_buffer t; if (!kbuf || !ubuf || !klen || - copy_from_user(&t, (cp210x_buffer_t __user *)ubuf, + copy_from_user(&t, (struct cp210x_buffer __user *)ubuf, sizeof(t))) return 0; if (t.len < klen) klen = t.len; if (!t.buf || !t.len || - copy_from_user(kbuf, (char __user *)t.buf, klen)) + copy_from_user(kbuf, (u8 __user *)t.buf, klen)) return 0; return klen; } +/* cp210x_has_setmfg + * Returns 1 if the CP210X part includes firmware that allows setting the + * USB MFG descriptor, else 0. As of this writing, no CP210X firmware allows + * this. SiLabs has suggested this may change in future firmware versions or + * parts. + */ +static inline int cp210x_has_setmfg(void) +{ + return 0; +} + /* * cp210x_ctlmsg * A generic usb control message interface. @@ -347,10 +296,10 @@ static int cp210x_ctlmsg(struct usb_serial_port *port, u8 request, static int cp210x_reset(struct usb_serial_port *port) { - dbg("%s", __FUNCTION__); + dbg("%s", __func__); #if 1 - /* Is this better than usb_device_reset? It may be. Once a client issues + /* 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... @@ -364,25 +313,24 @@ static int cp210x_reset(struct usb_serial_port *port) static int cp210x_get_partnum(struct usb_serial_port *port) { - static u8 _partnum = 0; - int ret = CP210x_SUCCESS; - if (!_partnum) { + static u8 _partnum = CP210x_PART_UNKNOWN; + + if (_partnum == CP210x_PART_UNKNOWN) { 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; + if (addr == 0x03 || addr == 0x02) + _partnum = CP210x_PART_CP2101; else if (addr == 0x01) { /* Must query part to determine part number */ if (cp210x_ctlmsg(port, 0xff, 0xc0, 0x370b, 0x00, &_partnum, 1) != 1) - ret = CP210x_DEVICE_IO_FAILED; - } else - ret = CP210x_DEVICE_IO_FAILED; + _partnum = CP210x_PART_UNKNOWN; + } } - dbg("%s - partnum %u err %d", __FUNCTION__, _partnum, ret); - return (ret == CP210x_SUCCESS) ? _partnum : 0; + dbg("%s - partnum %u", __func__, _partnum); + return _partnum; } static inline int cp210x_setu16(struct usb_serial_port *port, int cmd, @@ -408,9 +356,8 @@ 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 first byte as length */ - if (usblen > 256) - usblen = 256; + if (usblen > 255) + usblen = 255; p = usbstr + 1; *p++ = 0x03; @@ -437,14 +384,14 @@ static int cp210x_setstr(struct usb_serial_port *port, int cmd, char *usbstr) unsigned len = usbstr[0]; int ret = cp210x_ctlmsg(port, 0xff, 0x40, 0x3700 | (cmd & 0xff), 0, usbstr, len); - dbg("%s - cmd 0x%02x len %d ret %d", __FUNCTION__, cmd, len, ret); + dbg("%s - cmd 0x%02x len %d ret %d", __func__, cmd, len, ret); return ret; } /* Set all gpio simultaneously */ static int cp210x_gpioset(struct usb_serial_port *port, u8 gpio) { - dbg("%s - port %d, gpio = 0x%.2x", __FUNCTION__, port->number, gpio); + dbg("%s - port %d, gpio = 0x%.2x", __func__, port->number, gpio); return cp210x_ctlmsg(port, 0xff, 0x40, 0x37e1, ((uint16_t)gpio << 8) | GPIO_MASK, NULL, 0); @@ -473,7 +420,7 @@ static int cp210x_gpiosetb(struct usb_serial_port *port, u8 set, u8 clear) if (clear & GPIO_3) gpio = (gpio & ~(GPIO_3 << 8))|GPIO_3; - dbg("%s - port %d, gpiob = 0x%.4x", __FUNCTION__, port->number, gpio); + dbg("%s - port %d, gpiob = 0x%.4x", __func__, port->number, gpio); /* FIXME: how about REQTYPE_HOST_TO_DEVICE instead of 0x40? */ return cp210x_ctlmsg(port, 0xff, 0x40, 0x37e1, gpio, NULL, 0); @@ -483,41 +430,42 @@ static int cp210x_gpioget(struct usb_serial_port *port, u8 *gpio) { int ret; - dbg("%s - port %d", __FUNCTION__, port->number); + dbg("%s - port %d", __func__, port->number); /* FIXME: how about REQTYPE_DEVICE_TO_HOST instead of 0xc0? */ ret = cp210x_ctlmsg(port, 0xff, 0xc0, 0x00c2, 0, gpio, 1); - dbg("%s - gpio = 0x%.2x (%d)", __FUNCTION__, *gpio, ret); + dbg("%s - gpio = 0x%.2x (%d)", __func__, *gpio, ret); return (ret == 1) ? 0 : -1; } static int cp210x_portconfset(struct usb_serial_port *port, - cp210x_port_config_t *config) + struct cp210x_port_config *config) { - cp210x_port_config_t lconfig; + struct cp210x_port_config lconfig; int ret; - dbg("%s", __FUNCTION__); + dbg("%s", __func__); 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); +#if 0 /* apparently not implemented by CP210X firmware */ + lconfig.reset.lowPower = cpu_to_be16(config->reset.lowPower); + lconfig.suspend.lowPower = cpu_to_be16(config->suspend.lowPower); +#else + lconfig.suspend.lowPower = 0; + lconfig.reset.lowPower = 0; +#endif ret = cp210x_ctlmsg(port, 0xff, 0x40, 0x370c, 0, &lconfig, - PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) + sizeof(struct cp210x_port_config)); + if (ret == sizeof(struct cp210x_port_config)) return 0; else if (ret >= 0) return -1; @@ -526,15 +474,15 @@ static int cp210x_portconfset(struct usb_serial_port *port, } static int cp210x_portconfget(struct usb_serial_port *port, - cp210x_port_config_t *config) + struct cp210x_port_config *config) { int ret; - dbg("%s", __FUNCTION__); + dbg("%s", __func__); ret = cp210x_ctlmsg(port, 0xff, 0xc0, 0x370c, 0, config, - PORT_CONFIG_LEN); - if (ret == PORT_CONFIG_LEN) { + sizeof(struct cp210x_port_config)); + if (ret == sizeof(struct cp210x_port_config)) { /* Words from cp2103 are MSB */ config->reset.mode = be16_to_cpu(config->reset.mode); config->reset.lowPower = be16_to_cpu(config->reset.lowPower); @@ -778,7 +726,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, { struct usb_serial_port *port = tty->driver_data; - dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd); + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); switch (cmd) { @@ -809,7 +757,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, break; case IOCTL_GPIOGET: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION) { + if (cp210x_get_partnum(port) == CP210x_PART_CP2103) { u8 gpio = 0; if (!cp210x_gpioget(port, &gpio) && !copy_to_user( (u8 __user *)arg, &gpio, sizeof(gpio))) @@ -819,7 +767,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, break; case IOCTL_GPIOSET: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION && + if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpioset(port, arg)) return 0; return -EFAULT; @@ -827,7 +775,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, case IOCTL_GPIOBIC: case IOCTL_GPIOBIS: - if (cp210x_get_partnum(port) == CP210x_CP2103_VERSION && + if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, (cmd==IOCTL_GPIOBIC) ? arg : 0)) return 0; @@ -840,9 +788,9 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, case IOCTL_PORTCONFGET: { - cp210x_port_config_t config; + struct cp210x_port_config config; if (!cp210x_portconfget(port, &config) && !copy_to_user( - (cp210x_port_config_t __user *)arg, + (struct cp210x_port_config __user *)arg, &config, sizeof(config))) return 0; } @@ -851,8 +799,8 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, case IOCTL_PORTCONFSET: { - cp210x_port_config_t config; - if (!copy_from_user(&config, (cp210x_port_config_t __user *)arg, + struct cp210x_port_config config; + if (!copy_from_user(&config, (struct cp210x_port_config __user *)arg, sizeof(config)) && !cp210x_portconfset(port, &config)) return 0; @@ -883,25 +831,23 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, break; case IOCTL_SETMFG: -#if 0 /* Silicon Labs apparently doesn't provide for setting of mfg desc */ - { + if (cp210x_has_setmfg()) { char usbstr[CP210x_MAX_MFG_STRLEN * 2 + 2]; - size_t len = copy_buf_from_user(usbstr + sizeof(usbstr) - - CP210x_MAX_MFG_STRLEN, arg, + char *str = usbstr + sizeof(usbstr) - CP210x_MAX_MFG_STRLEN; + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_MFG_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x00, usbstr) == len) return 0; - return -EFAULT; } -#endif + return -EFAULT; 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, + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_PRODUCT_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x03, usbstr) == len) @@ -914,7 +860,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, { 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, + size_t len = cp210x_buf_from_user(str, arg, CP210x_MAX_SERIAL_STRLEN); len = make_usb_string(usbstr, sizeof(usbstr), str, len); if (len && cp210x_setstr(port, 0x04, usbstr) == len) @@ -935,7 +881,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, break; default: - dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); + dbg("%s not supported = 0x%04x", __func__, cmd); break; } diff --git a/src/cp210x.h b/src/cp210x.h new file mode 100644 index 0000000..9892464 --- /dev/null +++ b/src/cp210x.h @@ -0,0 +1,65 @@ +/* + * Silicon Laboratories CP210x USB to RS232 serial adaptor driver + * + * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * Definitions usable by both the cp210x kernel module and userspace. + * + */ + +#if !defined(CP210X_H) +#define CP210X_H + +/* CP2103 GPIO ioctls */ +#define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ +#define IOCTL_GPIOSET 0x8001 /* Set gpio bits */ +#define IOCTL_GPIOBIC 0x8002 /* Clear specific gpio bit(s) */ +#define IOCTL_GPIOBIS 0x8003 /* Set specific gpio bit(s) */ + +/* CP210x ioctls principally used during initial device configuration */ +#define IOCTL_DEVICERESET 0x8004 /* Reset the cp210x */ +#define IOCTL_PORTCONFGET 0x8005 /* Get port configuration */ +#define IOCTL_PORTCONFSET 0x8006 /* Set port configuration */ +#define IOCTL_SETVID 0x8007 /* Set vendor id */ +#define IOCTL_SETPID 0x8008 /* Set product id */ +#define IOCTL_SETMFG 0x8009 /* Set manufacturer string */ +#define IOCTL_SETPRODUCT 0x800a /* Set product string */ +#define IOCTL_SETSERIAL 0x800b /* Set serial number string */ +#define IOCTL_SETDEVVER 0x800c /* Set device version id */ + +/* CP2103 GPIO bit positions */ +#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) + +/* USB descriptor sizes */ +#define CP210x_MAX_MFG_STRLEN 255 +#define CP210x_MAX_PRODUCT_STRLEN 126 +#define CP210x_MAX_SERIAL_STRLEN 63 + +/* Used to pass variable sized buffers between user and kernel space (ioctls) */ +struct cp210x_buffer { + __u8 *buf; + __s32 len; +} __attribute__((packed)); + +/* Port config definitions */ +struct cp210x_port_state { + __u16 mode; /* Push-pull = 1, Open-drain = 0 */ + __u16 lowPower; + __u16 latch; /* Logic high = 1, Logic low = 0 */ +} __attribute__((packed)); + +struct cp210x_port_config { + struct cp210x_port_state reset; + struct cp210x_port_state suspend; + __u8 enhancedFxn; +} __attribute__((packed)); + +#endif /* CP210X_H */