in meta-facebook/meta-fby3/recipes-kernel/exar1420/files/xr_usb_serial_common.c [901:1071]
static int xr_usb_serial_tty_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct xr_usb_serial *xr_usb_serial = tty->driver_data;
int rv = -ENOIOCTLCMD;
unsigned int channel, reg, val,preciseflags;
int baud_rate = 0;
struct usb_cdc_line_coding newline;
short *data;
switch (cmd) {
case TIOCGSERIAL: /* gets serial port data */
rv = get_serial_info(xr_usb_serial, (struct serial_struct __user *) arg);
break;
case TIOCSSERIAL:
rv = set_serial_info(xr_usb_serial, (struct serial_struct __user *) arg);
break;
case XR_USB_SERIAL_GET_REG:
if (get_user(channel, (int __user *)arg))
return -EFAULT;
if (get_user(reg, (int __user *)(arg + sizeof(int))))
return -EFAULT;
data = kmalloc(2, GFP_KERNEL);
if (data == NULL) {
dev_err(&xr_usb_serial->control->dev, "%s - Cannot allocate USB buffer.\n", __func__);
return -ENOMEM;
}
if (channel == -1)
{
rv = xr_usb_serial_get_reg(xr_usb_serial,reg, data);
}
else
{
rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,reg, data);
}
if (rv < 0)
{
dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d)\n", rv);
kfree(data);
return -EFAULT;
}
if (put_user(le16_to_cpu(*data), (int __user *)(arg + 2 * sizeof(int))))
{
dev_err(&xr_usb_serial->control->dev, "Cannot put user result\n");
kfree(data);
return -EFAULT;
}
rv = 0;
kfree(data);
break;
case XR_USB_SERIAL_SET_REG:
if (get_user(channel, (int __user *)arg))
return -EFAULT;
if (get_user(reg, (int __user *)(arg + sizeof(int))))
return -EFAULT;
if (get_user(val, (int __user *)(arg + 2 * sizeof(int))))
return -EFAULT;
if (channel == -1)
{
rv = xr_usb_serial_set_reg(xr_usb_serial,reg, val);
}
else
{
rv = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,reg, val);
}
if (rv < 0)
return -EFAULT;
rv = 0;
break;
case XR_USB_SERIAL_LOOPBACK:
if (get_user(channel, (int __user *)arg))
return -EFAULT;
if (channel == -1)
channel = xr_usb_serial->channel;
rv = xr_usb_serial_set_loopback(xr_usb_serial,channel);
if (rv < 0)
return -EFAULT;
rv = 0;
break;
case XR_USB_SERIAL_SET_GPIO_MODE_REG:
xr_usb_serial_disable(xr_usb_serial);
if (get_user(channel, (int __user *)arg))
return -EFAULT;
if (get_user(val, (int __user *)(arg + sizeof(int))))
return -EFAULT;
if (channel == -1)
{
//block = portdata->block;
rv = xr_usb_serial_set_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, val);
}
else
{
rv = xr_usb_serial_set_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr, val);
}
dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_SET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,val);
xr_usb_serial_enable(xr_usb_serial);
if (rv < 0)
return -EFAULT;
break;
case XR_USB_SERIAL_GET_GPIO_MODE_REG:
xr_usb_serial_disable(xr_usb_serial);
if (get_user(channel, (int __user *)arg))
return -EFAULT;
data = kmalloc(2, GFP_KERNEL);
if (data == NULL) {
dev_err(&xr_usb_serial->control->dev, "%s - Cannot allocate USB buffer.\n", __func__);
return -ENOMEM;
}
if (channel == -1)
{
rv = xr_usb_serial_get_reg(xr_usb_serial,xr_usb_serial->reg_map.uart_gpio_mode_addr, data);
}
else
{
rv = xr_usb_serial_get_reg_ext(xr_usb_serial,channel,xr_usb_serial->reg_map.uart_gpio_mode_addr,data);
}
xr_usb_serial_enable(xr_usb_serial);
dev_dbg(&xr_usb_serial->control->dev, "XR_USB_SERIAL_GET_GPIO_MODE_REG 0x%x val:0x%x \n", xr_usb_serial->reg_map.uart_gpio_mode_addr,*data);
if (rv < 0 ) {
dev_err(&xr_usb_serial->control->dev, "Cannot get register (%d) channel=%d \n", rv,channel);
kfree(data);
return -EFAULT;
}
if (put_user(data[0], (int __user *)(arg + sizeof(int)))) {
dev_err(&xr_usb_serial->control->dev, "Cannot put user result\n");
kfree(data);
return -EFAULT;
}
kfree(data);
break;
case XRIOC_SET_ANY_BAUD_RATE:
if (get_user(baud_rate, (int __user *)arg)) {
dev_dbg(&xr_usb_serial->control->dev, "get_user errot \n");
return -EFAULT;
}
xr_usb_serial->line.dwDTERate = baud_rate;
memcpy(&newline,&(xr_usb_serial->line),sizeof(struct usb_cdc_line_coding));
xr_usb_serial_disable(xr_usb_serial);
rv = xr_usb_serial_set_line(xr_usb_serial,&newline);
xr_usb_serial_enable(xr_usb_serial);
dev_dbg(&xr_usb_serial->control->dev, "XRIOC_SET_ANY_BAUD_RATE set baud_rate:%d ret=%d\n", baud_rate,rv);
break;
case XRIOC_SET_PRECISE_FLAGS:
preciseflags = arg;
dev_dbg(&xr_usb_serial->control->dev, "%s VIOC_SET_PRECISE_FLAGS %d\n", __func__, preciseflags);
xr_usb_serial_disable(xr_usb_serial);
if (preciseflags)
{
xr_usb_serial->preciseflags = 1;
}
else
{
xr_usb_serial->preciseflags = 0;
}
xr_usb_serial_set_wide_mode(xr_usb_serial,xr_usb_serial->preciseflags);
xr_usb_serial_enable(xr_usb_serial);
break;
}
return rv;
}