Commit 2c0bec02 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 00ed39d3 9e033bb9
......@@ -432,43 +432,47 @@ static void acm_tty_break_ctl(struct tty_struct *tty, int state)
dbg("send break failed");
}
static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
{
struct acm *acm = tty->driver_data;
unsigned int mask, newctrl;
if (!ACM_READY(acm)) return -EINVAL;
switch (cmd) {
case TIOCMGET:
if (!ACM_READY(acm))
return -EINVAL;
return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
return (acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
(acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
(acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
(acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
(acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
TIOCM_CTS, (unsigned long *) arg);
TIOCM_CTS;
}
case TIOCMSET:
case TIOCMBIS:
case TIOCMBIC:
static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct acm *acm = tty->driver_data;
unsigned int newctrl;
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (!ACM_READY(acm))
return -EINVAL;
newctrl = acm->ctrlout;
mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0);
clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0);
switch (cmd) {
case TIOCMSET: newctrl = mask; break;
case TIOCMBIS: newctrl |= mask; break;
case TIOCMBIC: newctrl &= ~mask; break;
}
newctrl = (newctrl & ~clear) | set;
if (acm->ctrlout == newctrl) return 0;
if (acm->ctrlout == newctrl)
return 0;
return acm_set_control(acm, acm->ctrlout = newctrl);
}
}
static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct acm *acm = tty->driver_data;
if (!ACM_READY(acm))
return -EINVAL;
return -ENOIOCTLCMD;
}
......@@ -750,7 +754,9 @@ static struct tty_driver acm_tty_driver = {
.unthrottle = acm_tty_unthrottle,
.chars_in_buffer = acm_tty_chars_in_buffer,
.break_ctl = acm_tty_break_ctl,
.set_termios = acm_tty_set_termios
.set_termios = acm_tty_set_termios,
.tiocmget = acm_tty_tiocmget,
.tiocmset = acm_tty_tiocmset,
};
/*
......
......@@ -820,7 +820,7 @@ static int usb_midi_open(struct inode *inode, struct file *file)
struct list_head *devs, *mdevs;
struct usb_midi_state *s;
struct usb_mididev *m;
int flags;
unsigned long flags;
int succeed = 0;
#if 0
......
......@@ -17,11 +17,6 @@
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/irq.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
......@@ -29,6 +24,11 @@
#undef DEBUG
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/usb.h>
#include "hcd.h"
......@@ -214,7 +214,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING;
dev_dbg (*hcd->controller, "roothub graceful disconnect\n");
dev_dbg (hcd->controller, "roothub graceful disconnect\n");
usb_disconnect (&hub);
hcd->driver->stop (hcd);
......@@ -326,7 +326,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = -EBUSY;
if (hcd->state != USB_STATE_SUSPENDED) {
dev_dbg (*hcd->controller, "can't resume, not suspended!\n");
dev_dbg (hcd->controller, "can't resume, not suspended!\n");
goto done;
}
hcd->state = USB_STATE_RESUMING;
......@@ -336,7 +336,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = hcd->driver->resume (hcd);
if (!HCD_IS_RUNNING (hcd->state)) {
dev_dbg (*hcd->controller, "resume fail, retval %d\n", retval);
dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
usb_hc_died (hcd);
// FIXME: recover, reset etc.
} else {
......
......@@ -961,8 +961,8 @@ static void urb_unlink (struct urb *urb)
spin_lock_irqsave (&hcd_data_lock, flags);
list_del_init (&urb->urb_list);
dev = urb->dev;
usb_put_dev (dev);
spin_unlock_irqrestore (&hcd_data_lock, flags);
usb_put_dev (dev);
}
......
......@@ -791,14 +791,22 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type,
void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *dev = *pdev;
struct usb_bus *bus = dev->bus;
struct usb_operations *ops = bus->op;
struct usb_bus *bus;
struct usb_operations *ops;
int i;
might_sleep ();
if (!dev)
if (!dev) {
pr_debug ("%s nodev\n", __FUNCTION__);
return;
}
bus = dev->bus;
if (!bus) {
pr_debug ("%s nobus\n", __FUNCTION__);
return;
}
ops = bus->op;
*pdev = NULL;
......
......@@ -20,7 +20,19 @@
******************************************************************************/
/*
* Written by Johan Verrept (Johan.Verrept@advalvas.be)
* Written by Johan Verrept, maintained by Duncan Sands (duncan.sands@wanadoo.fr)
*
* 1.6: - No longer opens a connection if the firmware is not loaded
* - Added support for the speedtouch 330
* - Removed the limit on the number of devices
* - Module now autoloads on device plugin
* - Merged relevant parts of sarlib
* - Replaced the kernel thread with a tasklet
* - New packet transmission code
* - Changed proc file contents
* - Fixed all known SMP races
* - Many fixes and cleanups
* - Various fixes by Oliver Neukum (oliver@neukum.name)
*
* 1.5A: - Version for inclusion in 2.5 series kernel
* - Modifications by Richard Purdie (rpurdie@rpsys.net)
......@@ -28,6 +40,7 @@
* udsl_usb_send_data_context->urb to a pointer and adding code
* to alloc and free it
* - remove_wait_queue() added to udsl_atm_processqueue_thread()
* - Duncan Sands (duncan.sands@wanadoo.fr) is the new maintainer
*
* 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
* (reported by stephen.robinson@zen.co.uk)
......@@ -77,9 +90,9 @@ static int udsl_print_packet (const unsigned char *data, int len);
#define PACKETDEBUG(arg...)
#endif
#define DRIVER_AUTHOR "Johan Verrept, Johan.Verrept@advalvas.be"
#define DRIVER_DESC "Driver for the Alcatel SpeedTouch USB ADSL modem"
#define DRIVER_VERSION "1.5A"
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@wanadoo.fr>"
#define DRIVER_DESC "Alcatel SpeedTouch USB driver"
#define DRIVER_VERSION "1.6"
#define SPEEDTOUCH_VENDORID 0x06b9
#define SPEEDTOUCH_PRODUCTID 0x4061
......@@ -393,11 +406,12 @@ static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_bu
** encode **
*************/
static const unsigned char zeros[ATM_CELL_PAYLOAD];
static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
{
struct udsl_control *ctrl = UDSL_SKB (skb);
unsigned int i, zero_padding;
unsigned char zero = 0;
unsigned int zero_padding;
u32 crc;
ctrl->atm_data.vcc = vcc;
......@@ -423,8 +437,7 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
ctrl->aal5_trailer [3] = skb->len;
crc = crc32_be (~0, skb->data, skb->len);
for (i = 0; i < zero_padding; i++)
crc = crc32_be (crc, &zero, 1);
crc = crc32_be (crc, zeros, zero_padding);
crc = crc32_be (crc, ctrl->aal5_trailer, 4);
crc = ~crc;
......@@ -566,8 +579,7 @@ static void udsl_process_receive (unsigned long data)
atmsar_vcc->vcc->push (atmsar_vcc->vcc, new);
} else {
dbg
("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d",
atomic_read (&atmsar_vcc->vcc->rx_inuse),
("dropping incoming packet : vcc->sk->rcvbuf = %d, skb->true_size = %d",
atmsar_vcc->vcc->sk->rcvbuf, new->truesize);
dev_kfree_skb (new);
}
......
......@@ -744,7 +744,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
}
}
private_header = __skb_push(skb, 2);
private_header = (u16 *)__skb_push(skb, 2);
*private_header = cpu_to_le16(skb->len-2);
kaweth->tx_skb = skb;
......
......@@ -315,7 +315,11 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
#ifdef DEBUG
#define devdbg(usbnet, fmt, arg...) \
printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
do { \
printk(KERN_DEBUG "%s:", (usbnet)->net.name); \
printk(fmt, ## arg); \
printk("\n"); \
} while (0)
#else
#define devdbg(usbnet, fmt, arg...) do {} while(0)
#endif
......
......@@ -101,6 +101,8 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs);
static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old);
static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file);
static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static struct usb_device_id id_table_combined [] = {
......@@ -138,6 +140,8 @@ static struct usb_serial_device_type belkin_device = {
.ioctl = belkin_sa_ioctl,
.set_termios = belkin_sa_set_termios,
.break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
.tiocmset = belkin_sa_tiocmset,
.attach = belkin_sa_startup,
.shutdown = belkin_sa_shutdown,
};
......@@ -502,65 +506,77 @@ static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
}
static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct usb_serial *serial = port->serial;
__u16 urb_value; /* Will hold the new flags */
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
int ret = 0;
int mask;
unsigned long control_state;
unsigned long flags;
dbg("%s", __FUNCTION__);
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET:
return put_user(control_state, (unsigned long *) arg);
break;
return control_state;
}
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
/* RTS needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value)
control_state |= TIOCM_RTS;
else
control_state &= ~TIOCM_RTS;
static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
int retval;
int rts = 0;
int dtr = 0;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) {
err("Set RTS error %d", ret);
goto cmerror;
}
}
dbg("%s", __FUNCTION__);
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value)
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
if (set & TIOCM_RTS) {
control_state |= TIOCM_RTS;
rts = 1;
}
if (set & TIOCM_DTR) {
control_state |= TIOCM_DTR;
else
control_state &= ~TIOCM_DTR;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) {
err("Set DTR error %d", ret);
goto cmerror;
dtr = 1;
}
if (clear & TIOCM_RTS) {
control_state &= ~TIOCM_RTS;
rts = 0;
}
if (clear & TIOCM_DTR) {
control_state &= ~TIOCM_DTR;
dtr = 0;
}
cmerror:
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
break;
retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts);
if (retval < 0) {
err("Set RTS error %d", retval);
goto exit;
}
retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
if (retval < 0) {
err("Set DTR error %d", retval);
goto exit;
}
exit:
return retval;
}
static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
......
......@@ -460,6 +460,9 @@ static void digi_set_termios( struct usb_serial_port *port,
static void digi_break_ctl( struct usb_serial_port *port, int break_state );
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg );
static int digi_tiocmget( struct usb_serial_port *port, struct file *file );
static int digi_tiocmset( struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear );
static int digi_write( struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count );
static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs );
......@@ -526,6 +529,8 @@ static struct usb_serial_device_type digi_acceleport_2_device = {
.ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
.shutdown = digi_shutdown,
};
......@@ -551,6 +556,8 @@ static struct usb_serial_device_type digi_acceleport_4_device = {
.ioctl = digi_ioctl,
.set_termios = digi_set_termios,
.break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup,
.shutdown = digi_shutdown,
};
......@@ -1211,39 +1218,46 @@ static void digi_break_ctl( struct usb_serial_port *port, int break_state )
}
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg )
static int digi_tiocmget( struct usb_serial_port *port, struct file *file )
{
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags = 0;
dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd );
unsigned long flags;
switch (cmd) {
dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
case TIOCMGET:
spin_lock_irqsave( &priv->dp_port_lock, flags );
val = priv->dp_modem_signals;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) )
return( -EFAULT );
return( 0 );
return val;
}
static int digi_tiocmset( struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear )
{
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags;
dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
case TIOCMSET:
case TIOCMBIS:
case TIOCMBIC:
if( copy_from_user(&val, (unsigned int *)arg, sizeof(int)) )
return( -EFAULT );
spin_lock_irqsave( &priv->dp_port_lock, flags );
if( cmd == TIOCMBIS )
val = priv->dp_modem_signals | val;
else if( cmd == TIOCMBIC )
val = priv->dp_modem_signals & ~val;
val = (priv->dp_modem_signals & ~clear) | set;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( digi_set_modem_signals( port, val, 1 ) );
return digi_set_modem_signals( port, val, 1 );
}
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg )
{
struct digi_port *priv = usb_get_serial_port_data(port);
dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd );
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
......
......@@ -175,6 +175,8 @@ static int ftdi_sio_write_room (struct usb_serial_port *port);
static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void ftdi_sio_break_ctl (struct usb_serial_port *port, int break_state );
......@@ -198,6 +200,8 @@ static struct usb_serial_device_type ftdi_sio_device = {
.ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_sio_startup,
.shutdown = ftdi_sio_shutdown,
};
......@@ -219,6 +223,8 @@ static struct usb_serial_device_type ftdi_8U232AM_device = {
.ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_8U232AM_startup,
.shutdown = ftdi_sio_shutdown,
};
......@@ -823,125 +829,100 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
return;
} /* ftdi_sio_set_termios */
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value=0; /* Will hold the new flags */
char buf[2];
int ret, mask;
char *buf = NULL;
int ret = -EINVAL;
int size;
dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
dbg("%s", __FUNCTION__);
/* Based on code from acm.c and others */
switch (cmd) {
buf = kmalloc(2, GFP_KERNEL);
if (!buf)
goto exit;
case TIOCMGET:
dbg("%s TIOCMGET", __FUNCTION__);
if (priv->ftdi_type == sio){
/* Request the status from the device */
if ((ret = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
FTDI_SIO_GET_MODEM_STATUS_REQUEST,
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, 0,
buf, 1, WDR_TIMEOUT)) < 0 ) {
err("%s Could not get modem status of device - err: %d", __FUNCTION__,
ret);
return(ret);
}
if (priv->ftdi_type == sio) {
size = 1;
} else {
/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
format as the data returned from the in point */
if ((ret = usb_control_msg(serial->dev,
size = 2;
}
ret = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
FTDI_SIO_GET_MODEM_STATUS_REQUEST,
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, 0,
buf, 2, WDR_TIMEOUT)) < 0 ) {
err("%s Could not get modem status of device - err: %d", __FUNCTION__,
ret);
return(ret);
}
0, 0, buf, size, WDR_TIMEOUT);
if (ret < 0) {
err("%s Could not get modem status of device - err: %d",
__FUNCTION__, ret);
goto exit;
}
return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
(buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0),
(unsigned long *) arg);
break;
(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0);
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
dbg("%s TIOCMSET", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
err("Error from DTR set urb (TIOCMSET)");
}
urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){
err("Error from RTS set urb (TIOCMSET)");
exit:
kfree(buf);
return ret;
}
static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial *serial = port->serial;
int ret = 0;
dbg("%s", __FUNCTION__);
if (set & TIOCM_RTS)
if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0) {
err("Urb to set RTS failed");
goto exit;
}
break;
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
dbg("%s TIOCMBIS", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if (set & TIOCM_DTR)
if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0) {
err("Urb to set DTR failed");
return(ret);
}
goto exit;
}
if (mask & TIOCM_RTS) {
if (clear & TIOCM_RTS)
if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0){
err("Urb to set RTS failed");
return(ret);
}
LOW)) < 0) {
err("Urb to unset RTS failed");
goto exit;
}
break;
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
dbg("%s TIOCMBIC", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if (clear & TIOCM_DTR)
if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
LOW)) < 0){
LOW)) < 0) {
err("Urb to unset DTR failed");
return(ret);
goto exit;
}
}
if (mask & TIOCM_RTS) {
if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
LOW)) < 0){
err("Urb to unset RTS failed");
return(ret);
}
}
break;
/*
* I had originally implemented TCSET{A,S}{,F,W} and
* TCGET{A,S} here separately, however when testing I
* found that the higher layers actually do the termios
* conversions themselves and pass the call onto
* ftdi_sio_set_termios.
*
*/
exit:
return ret;
}
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
switch (cmd) {
default:
/* This is not an error - turns out the higher layers will do
* some ioctls itself (see comment above)
* some ioctls itself
*/
dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd);
return(-ENOIOCTLCMD);
......
......@@ -455,6 +455,8 @@ static void edge_unthrottle (struct usb_serial_port *port);
static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
static void edge_break (struct usb_serial_port *port, int break_state);
static int edge_tiocmget (struct usb_serial_port *port, struct file *file);
static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static int edge_startup (struct usb_serial *serial);
static void edge_shutdown (struct usb_serial *serial);
......@@ -1762,42 +1764,27 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int
return -ENOIOCTLCMD;
}
static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value)
static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
{
unsigned int mcr = edge_port->shadowMCR;
unsigned int arg;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT;
dbg("%s - port %d", __FUNCTION__, port->number);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_DTR)
mcr = edge_port->shadowMCR;
if (set & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_LOOP)
if (set & TIOCM_DTR)
mcr |= MCR_DTR;
if (set & TIOCM_LOOP)
mcr |= MCR_LOOPBACK;
break;
case TIOCMBIC:
if (arg & TIOCM_RTS)
if (clear & TIOCM_RTS)
mcr &= ~MCR_RTS;
if (arg & TIOCM_DTR)
mcr &= ~MCR_RTS;
if (arg & TIOCM_LOOP)
if (clear & TIOCM_DTR)
mcr &= ~MCR_DTR;
if (clear & TIOCM_LOOP)
mcr &= ~MCR_LOOPBACK;
break;
case TIOCMSET:
/* turn off the RTS and DTR and LOOPBACK
* and then only turn on what was asked to */
mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
break;
}
edge_port->shadowMCR = mcr;
......@@ -1806,12 +1793,17 @@ static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, uns
return 0;
}
static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value)
static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr = edge_port->shadowMSR;
unsigned int mcr = edge_port->shadowMCR;
unsigned int msr;
unsigned int mcr;
dbg("%s - port %d", __FUNCTION__, port->number);
msr = edge_port->shadowMSR;
mcr = edge_port->shadowMCR;
result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
| ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
| ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */
......@@ -1822,13 +1814,9 @@ static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value)
dbg("%s -- %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
return 0;
return result;
}
static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo)
{
struct serial_struct tmp;
......@@ -1885,16 +1873,6 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
return get_lsr_info(edge_port, (unsigned int *) arg);
return 0;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, port->number);
return set_modem_info(edge_port, cmd, (unsigned int *) arg);
case TIOCMGET:
dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
return get_modem_info(edge_port, (unsigned int *) arg);
case TIOCGSERIAL:
dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
return get_serial_info(edge_port, (struct serial_struct *) arg);
......
......@@ -114,6 +114,8 @@ static struct usb_serial_device_type edgeport_1port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......@@ -137,6 +139,8 @@ static struct usb_serial_device_type edgeport_2port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......@@ -160,6 +164,8 @@ static struct usb_serial_device_type edgeport_4port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......@@ -183,6 +189,8 @@ static struct usb_serial_device_type edgeport_8port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......
......@@ -2403,42 +2403,27 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_
return;
}
static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value)
static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
{
unsigned int mcr = edge_port->shadow_mcr;
unsigned int arg;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int mcr;
if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT;
dbg("%s - port %d", __FUNCTION__, port->number);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_DTR)
mcr = edge_port->shadow_mcr;
if (set & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_LOOP)
if (set & TIOCM_DTR)
mcr |= MCR_DTR;
if (set & TIOCM_LOOP)
mcr |= MCR_LOOPBACK;
break;
case TIOCMBIC:
if (arg & TIOCM_RTS)
if (clear & TIOCM_RTS)
mcr &= ~MCR_RTS;
if (arg & TIOCM_DTR)
mcr &= ~MCR_RTS;
if (arg & TIOCM_LOOP)
if (clear & TIOCM_DTR)
mcr &= ~MCR_DTR;
if (clear & TIOCM_LOOP)
mcr &= ~MCR_LOOPBACK;
break;
case TIOCMSET:
/* turn off the RTS and DTR and LOOPBACK
* and then only turn on what was asked to */
mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
break;
}
edge_port->shadow_mcr = mcr;
......@@ -2447,12 +2432,17 @@ static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, un
return 0;
}
static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value)
static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int result = 0;
unsigned int msr = edge_port->shadow_msr;
unsigned int mcr = edge_port->shadow_mcr;
unsigned int msr;
unsigned int mcr;
dbg("%s - port %d", __FUNCTION__, port->number);
msr = edge_port->shadow_msr;
mcr = edge_port->shadow_mcr;
result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
| ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
| ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */
......@@ -2463,9 +2453,7 @@ static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value)
dbg("%s -- %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
return 0;
return result;
}
static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo)
......@@ -2515,18 +2503,6 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
// return get_lsr_info(edge_port, (unsigned int *) arg);
break;
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
dbg("%s - (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, port->number);
return set_modem_info(edge_port, cmd, (unsigned int *) arg);
break;
case TIOCMGET:
dbg("%s - (%d) TIOCMGET", __FUNCTION__, port->number);
return get_modem_info(edge_port, (unsigned int *) arg);
break;
case TIOCGSERIAL:
dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
return get_serial_info(edge_port, (struct serial_struct *) arg);
......@@ -2665,6 +2641,8 @@ static struct usb_serial_device_type edgeport_1port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......@@ -2688,6 +2666,8 @@ static struct usb_serial_device_type edgeport_2port_device = {
.shutdown = edge_shutdown,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write,
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
......
......@@ -282,16 +282,13 @@ static void keyspan_set_termios (struct usb_serial_port *port,
keyspan_send_setup(port, 0);
}
static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
{
unsigned int value, set;
unsigned int value;
struct keyspan_port_private *p_priv;
p_priv = usb_get_serial_port_data(port);
switch (cmd) {
case TIOCMGET:
value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
((p_priv->dtr_state) ? TIOCM_DTR : 0) |
((p_priv->cts_state) ? TIOCM_CTS : 0) |
......@@ -299,31 +296,32 @@ static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
((p_priv->dcd_state) ? TIOCM_CAR : 0) |
((p_priv->ri_state) ? TIOCM_RNG : 0);
if (put_user(value, (unsigned int *) arg))
return -EFAULT;
return 0;
return value;
}
case TIOCMSET:
if (get_user(value, (unsigned int *) arg))
return -EFAULT;
p_priv->rts_state = ((value & TIOCM_RTS) ? 1 : 0);
p_priv->dtr_state = ((value & TIOCM_DTR) ? 1 : 0);
keyspan_send_setup(port, 0);
return 0;
static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct keyspan_port_private *p_priv;
case TIOCMBIS:
case TIOCMBIC:
if (get_user(value, (unsigned int *) arg))
return -EFAULT;
set = (cmd == TIOCMBIS);
if (value & TIOCM_RTS)
p_priv->rts_state = set;
if (value & TIOCM_DTR)
p_priv->dtr_state = set;
p_priv = usb_get_serial_port_data(port);
if (set & TIOCM_RTS)
p_priv->rts_state = 1;
if (set & TIOCM_DTR)
p_priv->dtr_state = 1;
if (clear & TIOCM_RTS)
p_priv->rts_state = 0;
if (clear & TIOCM_DTR)
p_priv->dtr_state = 0;
keyspan_send_setup(port, 0);
return 0;
}
}
static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
}
......
......@@ -63,6 +63,11 @@ static void keyspan_set_termios (struct usb_serial_port *port,
struct termios *old);
static void keyspan_break_ctl (struct usb_serial_port *port,
int break_state);
static int keyspan_tiocmget (struct usb_serial_port *port,
struct file *file);
static int keyspan_tiocmset (struct usb_serial_port *port,
struct file *file, unsigned int set,
unsigned int clear);
static int keyspan_fake_startup (struct usb_serial *serial);
static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk,
......@@ -551,6 +556,8 @@ static struct usb_serial_device_type keyspan_1port_device = {
.ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup,
.shutdown = keyspan_shutdown,
};
......@@ -574,6 +581,8 @@ static struct usb_serial_device_type keyspan_2port_device = {
.ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup,
.shutdown = keyspan_shutdown,
};
......@@ -597,6 +606,8 @@ static struct usb_serial_device_type keyspan_4port_device = {
.ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup,
.shutdown = keyspan_shutdown,
};
......
......@@ -457,17 +457,13 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
return rc;
}
static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
{
struct usb_serial *serial = port->serial;
int rc;
unsigned int value;
unsigned char status, mask;
unsigned char status;
int value;
switch (cmd) {
case TIOCMGET: /* get modem pins state */
rc = keyspan_pda_get_modem_info(serial, &status);
if (rc < 0)
return rc;
......@@ -478,41 +474,37 @@ static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
((status & (1<<4)) ? TIOCM_DSR : 0) |
((status & (1<<3)) ? TIOCM_CTS : 0) |
((status & (1<<2)) ? TIOCM_RTS : 0);
if (copy_to_user((unsigned int *)arg, &value, sizeof(int)))
return -EFAULT;
return 0;
case TIOCMSET: /* set a state as returned by MGET */
if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
return -EFAULT;
status =
((value & TIOCM_DTR) ? (1<<7) : 0) |
((value & TIOCM_CAR) ? (1<<6) : 0) |
((value & TIOCM_RNG) ? (1<<5) : 0) |
((value & TIOCM_DSR) ? (1<<4) : 0) |
((value & TIOCM_CTS) ? (1<<3) : 0) |
((value & TIOCM_RTS) ? (1<<2) : 0);
rc = keyspan_pda_set_modem_info(serial, status);
if (rc < 0)
return rc;
return 0;
case TIOCMBIS: /* set bits in bitmask <arg> */
case TIOCMBIC: /* clear bits from bitmask <arg> */
if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
return -EFAULT;
return value;
}
static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial *serial = port->serial;
int rc;
unsigned char status;
rc = keyspan_pda_get_modem_info(serial, &status);
if (rc < 0)
return rc;
mask =
((value & TIOCM_RTS) ? (1<<2) : 0) |
((value & TIOCM_DTR) ? (1<<7) : 0);
if (cmd == TIOCMBIS)
status |= mask;
else
status &= ~mask;
if (set & TIOCM_RTS)
status |= (1<<2);
if (set & TIOCM_DTR)
status |= (1<<7);
if (clear & TIOCM_RTS)
status &= ~(1<<2);
if (clear & TIOCM_DTR)
status &= ~(1<<7);
rc = keyspan_pda_set_modem_info(serial, status);
if (rc < 0)
return rc;
return 0;
}
static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
......@@ -874,6 +866,8 @@ static struct usb_serial_device_type keyspan_pda_device = {
.ioctl = keyspan_pda_ioctl,
.set_termios = keyspan_pda_set_termios,
.break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset,
.attach = keyspan_pda_startup,
.shutdown = keyspan_pda_shutdown,
};
......
......@@ -105,6 +105,11 @@ static void klsi_105_unthrottle (struct usb_serial_port *port);
static void klsi_105_break_ctl (struct usb_serial_port *port,
int break_state );
*/
static int klsi_105_tiocmget (struct usb_serial_port *port,
struct file *file);
static int klsi_105_tiocmset (struct usb_serial_port *port,
struct file *file, unsigned int set,
unsigned int clear);
/*
* All of the device info needed for the KLSI converters.
......@@ -143,6 +148,8 @@ static struct usb_serial_device_type kl5kusb105d_device = {
.ioctl = klsi_105_ioctl,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
.tiocmset = klsi_105_tiocmset,
.attach = klsi_105_startup,
.shutdown = klsi_105_shutdown,
.throttle = klsi_105_throttle,
......@@ -879,68 +886,67 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
#endif
static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET: {
int rc;
unsigned long line_state;
dbg("%s - TIOCMGET request, just guessing", __FUNCTION__);
dbg("%s - request, just guessing", __FUNCTION__);
rc = klsi_105_get_line_state(serial, &line_state);
if (rc < 0) {
err("Reading line control failed (error = %d)", rc);
/* better return value? EAGAIN? */
return -ENOIOCTLCMD;
return rc;
}
spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
return put_user(line_state, (unsigned long *) arg);
};
return (int)line_state;
}
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
int retval = -EINVAL;
if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
/* RTS needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
(cmd == TIOCMBIS) )
dbg("%s - set RTS not handled", __FUNCTION__);
/* priv->control_state |= TIOCM_RTS; */
else
dbg("%s - clear RTS not handled", __FUNCTION__);
/* priv->control_state &= ~TIOCM_RTS; */
}
dbg("%s", __FUNCTION__);
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
(cmd == TIOCMBIS) )
dbg("%s - set DTR not handled", __FUNCTION__);
/* priv->control_state |= TIOCM_DTR; */
else
dbg("%s - clear DTR not handled", __FUNCTION__);
/* priv->control_state &= ~TIOCM_DTR; */
}
/*
mct_u232_set_modem_ctrl(serial, priv->control_state);
*/
break;
/* if this ever gets implemented, it should be done something like this:
struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int control;
spin_lock_irqsave (&priv->lock, flags);
if (set & TIOCM_RTS)
priv->control_state |= TIOCM_RTS;
if (set & TIOCM_DTR)
priv->control_state |= TIOCM_DTR;
if (clear & TIOCM_RTS)
priv->control_state &= ~TIOCM_RTS;
if (clear & TIOCM_DTR)
priv->control_state &= ~TIOCM_DTR;
control = priv->control_state;
spin_unlock_irqrestore (&priv->lock, flags);
retval = mct_u232_set_modem_ctrl(serial, control);
*/
return retval;
}
static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
dbg("%scmd=0x%x", __FUNCTION__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
......
......@@ -81,6 +81,9 @@ static int kobil_write (struct usb_serial_port *port, int from_user,
static int kobil_write_room(struct usb_serial_port *port);
static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg);
static int kobil_tiocmget(struct usb_serial_port *port, struct file *file);
static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear);
static void kobil_read_int_callback( struct urb *urb, struct pt_regs *regs );
static void kobil_write_callback( struct urb *purb, struct pt_regs *regs );
......@@ -106,6 +109,8 @@ struct usb_serial_device_type kobil_device = {
.attach = kobil_startup,
.shutdown = kobil_shutdown,
.ioctl = kobil_ioctl,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open,
.close = kobil_close,
.write = kobil_write,
......@@ -490,11 +495,120 @@ static int kobil_write_room (struct usb_serial_port *port)
}
static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
{
struct kobil_private * priv;
int result;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) {
// This device doesn't support ioctl calls
return -EINVAL;
}
// allocate memory for transfer buffer
transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer) {
return -ENOMEM;
}
memset(transfer_buffer, 0, transfer_buffer_length);
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_GetStatusLineState,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
0,
0,
transfer_buffer,
transfer_buffer_length,
KOBIL_TIMEOUT);
dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
__FUNCTION__, port->number, result, transfer_buffer[0]);
if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
priv->line_state |= TIOCM_DSR;
} else {
priv->line_state &= ~TIOCM_DSR;
}
kfree(transfer_buffer);
return priv->line_state;
}
static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct kobil_private * priv;
int result;
int dtr = 0;
int rts = 0;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) {
// This device doesn't support ioctl calls
return -EINVAL;
}
// allocate memory for transfer buffer
transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOMEM;
}
memset(transfer_buffer, 0, transfer_buffer_length);
if (set & TIOCM_RTS)
rts = 1;
if (set & TIOCM_DTR)
dtr = 1;
if (clear & TIOCM_RTS)
rts = 0;
if (clear & TIOCM_DTR)
dtr = 0;
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
if (dtr != 0)
dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
else
dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
0,
transfer_buffer,
0,
KOBIL_TIMEOUT);
} else {
if (rts != 0)
dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
else
dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
0,
transfer_buffer,
0,
KOBIL_TIMEOUT);
}
dbg("%s - port %d Send set_status_line URB returns: %i", __FUNCTION__, port->number, result);
kfree(transfer_buffer);
return (result < 0) ? result : 0;
}
static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct kobil_private * priv;
int mask;
int result;
unsigned short urb_val = 0;
unsigned char *transfer_buffer;
......@@ -605,90 +719,8 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
kfree(transfer_buffer);
return ((result < 0) ? -EFAULT : 0);
case TIOCMGET: // 0x5415
// allocate memory for transfer buffer
transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOBUFS;
} else {
memset(transfer_buffer, 0, transfer_buffer_length);
}
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_GetStatusLineState,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
0,
0,
transfer_buffer,
transfer_buffer_length,
KOBIL_TIMEOUT
);
dbg("%s - port %d Send get_status_line_state (TIOCMGET) URB returns: %i. Statusline: %02x",
__FUNCTION__, port->number, result, transfer_buffer[0]);
if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
priv->line_state |= TIOCM_DSR;
} else {
priv->line_state &= ~TIOCM_DSR;
}
kfree(transfer_buffer);
return put_user(priv->line_state, (unsigned long *) arg);
case TIOCMSET: // 0x5418
if (get_user(mask, (unsigned long *) arg)){
return -EFAULT;
}
// allocate memory for transfer buffer
transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOBUFS;
} else {
memset(transfer_buffer, 0, transfer_buffer_length);
}
if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
if ((mask & TIOCM_DTR) != 0){
dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
} else {
dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
}
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
( ((mask & TIOCM_DTR) != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
0,
transfer_buffer,
0,
KOBIL_TIMEOUT
);
} else {
if ((mask & TIOCM_RTS) != 0){
dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
} else {
dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
}
result = usb_control_msg( port->serial->dev,
usb_rcvctrlpipe(port->serial->dev, 0 ),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
(((mask & TIOCM_RTS) != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
0,
transfer_buffer,
0,
KOBIL_TIMEOUT
);
}
dbg("%s - port %d Send set_status_line (TIOCMSET) URB returns: %i", __FUNCTION__, port->number, result);
kfree(transfer_buffer);
return ((result < 0) ? -EFAULT : 0);
}
return 0;
return -ENOIOCTLCMD;
}
......
......@@ -125,7 +125,11 @@ static int mct_u232_ioctl (struct usb_serial_port *port,
unsigned long arg);
static void mct_u232_break_ctl (struct usb_serial_port *port,
int break_state );
static int mct_u232_tiocmget (struct usb_serial_port *port,
struct file *file);
static int mct_u232_tiocmset (struct usb_serial_port *port,
struct file *file, unsigned int set,
unsigned int clear);
/*
* All of the device info needed for the MCT USB-RS232 converter.
*/
......@@ -165,6 +169,8 @@ static struct usb_serial_device_type mct_u232_device = {
.ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios,
.break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
.tiocmset = mct_u232_tiocmset,
.attach = mct_u232_startup,
.shutdown = mct_u232_shutdown,
};
......@@ -773,57 +779,55 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */
static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long control_state;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
dbg("%s", __FUNCTION__);
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET:
return put_user(control_state, (unsigned long *) arg);
break;
return control_state;
}
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
/* RTS needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
(cmd == TIOCMBIS) )
control_state |= TIOCM_RTS;
else
control_state &= ~TIOCM_RTS;
}
dbg("%s", __FUNCTION__);
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
(cmd == TIOCMBIS) )
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
if (set & TIOCM_RTS)
control_state |= TIOCM_RTS;
if (set & TIOCM_DTR)
control_state |= TIOCM_DTR;
else
if (clear & TIOCM_RTS)
control_state &= ~TIOCM_RTS;
if (clear & TIOCM_DTR)
control_state &= ~TIOCM_DTR;
}
mct_u232_set_modem_ctrl(serial, control_state);
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
break;
return mct_u232_set_modem_ctrl(serial, control_state);
}
static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
{
dbg("%scmd=0x%x", __FUNCTION__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
......
/*
* Prolific PL2303 USB to serial adaptor driver
*
* Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2003 IBM Corp.
*
* Original driver for 2.2.x by anonymous
*
......@@ -111,6 +112,16 @@ static struct usb_driver pl2303_driver = {
#define VENDOR_READ_REQUEST_TYPE 0xc0
#define VENDOR_READ_REQUEST 0x01
#define UART_STATE 0x08
#define UART_DCD 0x01
#define UART_DSR 0x02
#define UART_BREAK_ERROR 0x04
#define UART_RING 0x08
#define UART_FRAME_ERROR 0x10
#define UART_PARITY_ERROR 0x20
#define UART_OVERRUN_ERROR 0x40
#define UART_CTS 0x80
/* function prototypes for a PL2303 serial converter */
static int pl2303_open (struct usb_serial_port *port, struct file *filp);
static void pl2303_close (struct usb_serial_port *port, struct file *filp);
......@@ -124,6 +135,9 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
static int pl2303_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count);
static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear);
static int pl2303_startup (struct usb_serial *serial);
static void pl2303_shutdown (struct usb_serial *serial);
......@@ -143,6 +157,8 @@ static struct usb_serial_device_type pl2303_device = {
.ioctl = pl2303_ioctl,
.break_ctl = pl2303_break_ctl,
.set_termios = pl2303_set_termios,
.tiocmget = pl2303_tiocmget,
.tiocmset = pl2303_tiocmset,
.read_bulk_callback = pl2303_read_bulk_callback,
.read_int_callback = pl2303_read_int_callback,
.write_bulk_callback = pl2303_write_bulk_callback,
......@@ -153,6 +169,7 @@ static struct usb_serial_device_type pl2303_device = {
struct pl2303_private {
spinlock_t lock;
u8 line_control;
u8 line_status;
u8 termios_initialized;
};
......@@ -222,6 +239,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int cflag;
unsigned char *buf;
int baud;
......@@ -234,13 +252,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
return;
}
spin_lock(&priv->lock);
spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
priv->termios_initialized = 1;
}
spin_unlock(&priv->lock);
spin_unlock_irqrestore(&priv->lock, flags);
cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */
......@@ -350,13 +368,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
if (cflag && CBAUD) {
u8 control;
spin_lock (&priv->lock);
spin_lock_irqsave(&priv->lock, flags);
if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
control = priv->line_control;
spin_unlock (&priv->lock);
spin_unlock_irqrestore(&priv->lock, flags);
set_control_lines (serial->dev, control);
}
......@@ -445,6 +463,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
struct pl2303_private *priv;
unsigned long flags;
unsigned int c_cflag;
int result;
......@@ -481,72 +500,56 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
priv = usb_get_serial_port_data(port);
spin_lock (&priv->lock);
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
spin_unlock (&priv->lock);
spin_unlock_irqrestore (&priv->lock, flags);
set_control_lines (port->serial->dev, 0);
}
}
}
static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg;
unsigned long flags;
u8 control;
if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT;
spin_lock (&priv->lock);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
spin_lock_irqsave (&priv->lock, flags);
if (set & TIOCM_RTS)
priv->line_control |= CONTROL_RTS;
if (arg & TIOCM_DTR)
if (set & TIOCM_DTR)
priv->line_control |= CONTROL_DTR;
break;
case TIOCMBIC:
if (arg & TIOCM_RTS)
if (clear & TIOCM_RTS)
priv->line_control &= ~CONTROL_RTS;
if (arg & TIOCM_DTR)
if (clear & TIOCM_DTR)
priv->line_control &= ~CONTROL_DTR;
break;
case TIOCMSET:
/* turn off RTS and DTR and then only turn
on what was asked to */
priv->line_control &= ~(CONTROL_RTS | CONTROL_DTR);
priv->line_control |= ((arg & TIOCM_RTS) ? CONTROL_RTS : 0);
priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
break;
}
control = priv->line_control;
spin_unlock (&priv->lock);
spin_unlock_irqrestore (&priv->lock, flags);
return set_control_lines (port->serial->dev, control);
}
static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr;
unsigned int result;
spin_lock (&priv->lock);
dbg("%s (%d)", __FUNCTION__, port->number);
spin_lock_irqsave (&priv->lock, flags);
mcr = priv->line_control;
spin_unlock (&priv->lock);
spin_unlock_irqrestore (&priv->lock, flags);
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);
dbg("%s - result = %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
return 0;
return result;
}
static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
......@@ -554,17 +557,6 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign
dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
switch (cmd) {
case TIOCMGET:
dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
return get_modem_info (port, (unsigned int *)arg);
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, port->number);
return set_modem_info(port, cmd, (unsigned int *) arg);
default:
dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
break;
......@@ -573,7 +565,6 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign
return -ENOIOCTLCMD;
}
static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
{
struct usb_serial *serial = port->serial;
......@@ -613,9 +604,13 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
//unsigned char *data = urb->transfer_buffer;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
int status;
dbg("%s (%d)", __FUNCTION__, port->number);
switch (urb->status) {
case 0:
/* success */
......@@ -637,7 +632,13 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
//FIXME need to update state of terminal lines variable
if (urb->actual_length > UART_STATE)
goto exit;
/* Save off the uart status for others to look at */
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = data[UART_STATE];
spin_unlock_irqrestore(&priv->lock, flags);
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
......@@ -651,10 +652,14 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct pl2303_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
int i;
int result;
u8 status;
char tty_flag;
if (port_paranoia_check (port, __FUNCTION__))
return;
......@@ -688,13 +693,34 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
/* get tty_flag from status */
tty_flag = TTY_NORMAL;
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
if (status & UART_BREAK_ERROR )
tty_flag = TTY_BREAK;
else if (status & UART_PARITY_ERROR)
tty_flag = TTY_PARITY;
else if (status & UART_FRAME_ERROR)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
tty = port->tty;
if (tty && urb->actual_length) {
/* overrun is special, not associated with a char */
if (status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
for (i = 0; i < urb->actual_length; ++i) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
tty_insert_flip_char (tty, data[i], 0);
tty_insert_flip_char (tty, data[i], tty_flag);
}
tty_flip_buffer_push (tty);
}
......
......@@ -785,6 +785,51 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
return ((count < begin+length-off) ? count : begin+length-off);
}
static int serial_tiocmget (struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial)
goto exit;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
dbg("%s - port not open", __FUNCTION__);
goto exit;
}
if (serial->type->tiocmget)
return serial->type->tiocmget(port, file);
exit:
return -EINVAL;
}
static int serial_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
if (!serial)
goto exit;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
dbg("%s - port not open", __FUNCTION__);
goto exit;
}
if (serial->type->tiocmset)
return serial->type->tiocmset(port, file, set, clear);
exit:
return -EINVAL;
}
void usb_serial_port_softint(void *private)
{
struct usb_serial_port *port = (struct usb_serial_port *)private;
......@@ -1286,6 +1331,8 @@ struct tty_driver usb_serial_tty_driver = {
.break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer,
.read_proc = serial_read_proc,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
};
......
......@@ -251,6 +251,8 @@ struct usb_serial_device_type {
int (*chars_in_buffer) (struct usb_serial_port *port);
void (*throttle) (struct usb_serial_port *port);
void (*unthrottle) (struct usb_serial_port *port);
int (*tiocmget) (struct usb_serial_port *port, struct file *file);
int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
......
......@@ -146,6 +146,8 @@ static int whiteheat_write (struct usb_serial_port *port, int from_user, const
static int whiteheat_write_room (struct usb_serial_port *port);
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
static int whiteheat_chars_in_buffer (struct usb_serial_port *port);
static void whiteheat_throttle (struct usb_serial_port *port);
......@@ -184,6 +186,8 @@ static struct usb_serial_device_type whiteheat_device = {
.ioctl = whiteheat_ioctl,
.set_termios = whiteheat_set_termios,
.break_ctl = whiteheat_break_ctl,
.tiocmget = whiteheat_tiocmget,
.tiocmset = whiteheat_tiocmset,
.chars_in_buffer = whiteheat_chars_in_buffer,
.throttle = whiteheat_throttle,
.unthrottle = whiteheat_unthrottle,
......@@ -767,73 +771,53 @@ static int whiteheat_write_room(struct usb_serial_port *port)
}
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
{
struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
struct serial_struct serstruct;
dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
dbg("%s - port %d", __FUNCTION__, port->number);
switch (cmd) {
case TIOCMGET:
firm_get_dtr_rts(port);
if (info->mcr & UART_MCR_DTR)
modem_signals |= TIOCM_DTR;
if (info->mcr & UART_MCR_RTS)
modem_signals |= TIOCM_RTS;
if (copy_to_user((unsigned int *)arg, &modem_signals, sizeof(unsigned int)))
return -EFAULT;
break;
case TIOCMSET:
if (copy_from_user(&modem_signals, (unsigned int *)arg, sizeof(unsigned int)))
return -EFAULT;
if (modem_signals & TIOCM_DTR)
info->mcr |= UART_MCR_DTR;
else
info->mcr &= ~UART_MCR_DTR;
if (modem_signals & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
else
info->mcr &= ~UART_MCR_RTS;
return modem_signals;
}
firm_set_dtr(port, info->mcr & UART_MCR_DTR);
firm_set_rts(port, info->mcr & UART_MCR_RTS);
break;
static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct whiteheat_private *info = usb_get_serial_port_data(port);
case TIOCMBIS:
if (copy_from_user(&modem_signals, (unsigned int *)arg, sizeof(unsigned int)))
return -EFAULT;
dbg("%s - port %d", __FUNCTION__, port->number);
if (modem_signals & TIOCM_DTR)
info->mcr |= UART_MCR_DTR;
if (modem_signals & TIOCM_RTS)
if (set & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR)
info->mcr |= UART_MCR_DTR;
firm_set_dtr(port, info->mcr & UART_MCR_DTR);
firm_set_rts(port, info->mcr & UART_MCR_RTS);
break;
case TIOCMBIC:
if (copy_from_user(&modem_signals, (unsigned int *)arg, sizeof(unsigned int)))
return -EFAULT;
if (modem_signals & TIOCM_DTR)
info->mcr &= ~UART_MCR_DTR;
if (modem_signals & TIOCM_RTS)
if (clear & TIOCM_RTS)
info->mcr &= ~UART_MCR_RTS;
if (clear & TIOCM_DTR)
info->mcr &= ~UART_MCR_DTR;
firm_set_dtr(port, info->mcr & UART_MCR_DTR);
firm_set_rts(port, info->mcr & UART_MCR_RTS);
return 0;
}
break;
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct serial_struct serstruct;
dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
switch (cmd) {
case TIOCGSERIAL:
memset(&serstruct, 0, sizeof(serstruct));
serstruct.type = PORT_16654;
......@@ -864,10 +848,10 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
break;
default:
return -ENOIOCTLCMD;
break;
}
return 0;
return -ENOIOCTLCMD;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment