-/* 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;
-}
-