serial_core: Handle TIOC[GS]RS485 ioctls.
The following drivers: 8250_core, atmel_serial, max310x, mcf, omap-serial and sci16is7xx implement code to handle RS485 ioctls. In order to avoid code duplication, we implement a simple ioctl handler on the serial_core layer. This handler can be used by all the other drivers instead of duplicating code. Until this is the only RS485 ioctl handler, it will try first the rs485_config callback and if it is not present it will call the driver specific ioctl. Reviewed-by: Alan Cox <alan@linux.intel.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7f1dc2f384
commit
a5f276f10f
|
@ -1152,6 +1152,39 @@ static int uart_get_icount(struct tty_struct *tty,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uart_get_rs485_config(struct uart_port *port,
|
||||||
|
struct serial_rs485 __user *rs485)
|
||||||
|
{
|
||||||
|
if (!port->rs485_config)
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
if (copy_to_user(rs485, &port->rs485, sizeof(port->rs485)))
|
||||||
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int uart_set_rs485_config(struct uart_port *port,
|
||||||
|
struct serial_rs485 __user *rs485_user)
|
||||||
|
{
|
||||||
|
struct serial_rs485 rs485;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!port->rs485_config)
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
ret = port->rs485_config(port, &rs485);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (copy_to_user(rs485_user, &port->rs485, sizeof(port->rs485)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called via sys_ioctl. We can use spin_lock_irq() here.
|
* Called via sys_ioctl. We can use spin_lock_irq() here.
|
||||||
*/
|
*/
|
||||||
|
@ -1223,6 +1256,18 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||||
* protected against the tty being hung up.
|
* protected against the tty being hung up.
|
||||||
*/
|
*/
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
case TIOCGRS485:
|
||||||
|
ret = uart_get_rs485_config(state->uart_port, uarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TIOCSRS485:
|
||||||
|
ret = uart_set_rs485_config(state->uart_port, uarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret != -ENOIOCTLCMD)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
case TIOCSERGETLSR: /* Get line status register */
|
case TIOCSERGETLSR: /* Get line status register */
|
||||||
ret = uart_get_lsr_info(tty, state, uarg);
|
ret = uart_get_lsr_info(tty, state, uarg);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -131,6 +131,8 @@ struct uart_port {
|
||||||
void (*pm)(struct uart_port *, unsigned int state,
|
void (*pm)(struct uart_port *, unsigned int state,
|
||||||
unsigned int old);
|
unsigned int old);
|
||||||
void (*handle_break)(struct uart_port *);
|
void (*handle_break)(struct uart_port *);
|
||||||
|
int (*rs485_config)(struct uart_port *,
|
||||||
|
struct serial_rs485 *rs485);
|
||||||
unsigned int irq; /* irq number */
|
unsigned int irq; /* irq number */
|
||||||
unsigned long irqflags; /* irq flags */
|
unsigned long irqflags; /* irq flags */
|
||||||
unsigned int uartclk; /* base uart clock */
|
unsigned int uartclk; /* base uart clock */
|
||||||
|
@ -231,6 +233,7 @@ struct uart_port {
|
||||||
unsigned char unused[2];
|
unsigned char unused[2];
|
||||||
struct attribute_group *attr_group; /* port specific attributes */
|
struct attribute_group *attr_group; /* port specific attributes */
|
||||||
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
|
const struct attribute_group **tty_groups; /* all attributes (serial core use only) */
|
||||||
|
struct serial_rs485 rs485;
|
||||||
void *private_data; /* generic platform data pointer */
|
void *private_data; /* generic platform data pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user