mirror of
https://github.com/torvalds/linux.git
synced 2024-12-15 23:51:46 +00:00
USB: serial: opticon: add serial line ioctls
This lets userspace determine what the state of the RTS line is, which is what is needed to properly handle data flow for this device (it raises RTS when there is data to be sent from it.) Cc: Kees Stoop <kees.stoop@opticon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
648d4e1656
commit
faac64ad9c
@ -14,6 +14,7 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
@ -110,7 +111,6 @@ static void opticon_bulk_callback(struct urb *urb)
|
||||
priv->rts = false;
|
||||
else
|
||||
priv->rts = true;
|
||||
/* FIXME change the RTS level */
|
||||
} else {
|
||||
dev_dbg(&priv->udev->dev,
|
||||
"Unknown data packet received from the device:"
|
||||
@ -341,6 +341,67 @@ static void opticon_unthrottle(struct tty_struct *tty)
|
||||
__func__, result);
|
||||
}
|
||||
|
||||
static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct opticon_private *priv = usb_get_serial_data(port->serial);
|
||||
unsigned long flags;
|
||||
int result = 0;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (priv->rts)
|
||||
result = TIOCM_RTS;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
dbg("%s - %x", __func__, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int get_serial_info(struct opticon_private *priv,
|
||||
struct serial_struct __user *serial)
|
||||
{
|
||||
struct serial_struct tmp;
|
||||
|
||||
if (!serial)
|
||||
return -EFAULT;
|
||||
|
||||
memset(&tmp, 0x00, sizeof(tmp));
|
||||
|
||||
/* fake emulate a 16550 uart to make userspace code happy */
|
||||
tmp.type = PORT_16550A;
|
||||
tmp.line = priv->serial->minor;
|
||||
tmp.port = 0;
|
||||
tmp.irq = 0;
|
||||
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
|
||||
tmp.xmit_fifo_size = 1024;
|
||||
tmp.baud_base = 9600;
|
||||
tmp.close_delay = 5*HZ;
|
||||
tmp.closing_wait = 30*HZ;
|
||||
|
||||
if (copy_to_user(serial, &tmp, sizeof(*serial)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opticon_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct opticon_private *priv = usb_get_serial_data(port->serial);
|
||||
|
||||
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
return get_serial_info(priv,
|
||||
(struct serial_struct __user *)arg);
|
||||
}
|
||||
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static int opticon_startup(struct usb_serial *serial)
|
||||
{
|
||||
struct opticon_private *priv;
|
||||
@ -475,6 +536,8 @@ static struct usb_serial_driver opticon_device = {
|
||||
.shutdown = opticon_shutdown,
|
||||
.throttle = opticon_throttle,
|
||||
.unthrottle = opticon_unthrottle,
|
||||
.ioctl = opticon_ioctl,
|
||||
.tiocmget = opticon_tiocmget,
|
||||
};
|
||||
|
||||
static int __init opticon_init(void)
|
||||
|
Loading…
Reference in New Issue
Block a user