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) ...@@ -432,43 +432,47 @@ static void acm_tty_break_ctl(struct tty_struct *tty, int state)
dbg("send break failed"); 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; struct acm *acm = tty->driver_data;
unsigned int mask, newctrl;
if (!ACM_READY(acm)) return -EINVAL;
switch (cmd) { if (!ACM_READY(acm))
return -EINVAL;
case TIOCMGET:
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->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
(acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | (acm->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
(acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | (acm->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) |
(acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | (acm->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) |
TIOCM_CTS, (unsigned long *) arg); TIOCM_CTS;
}
case TIOCMSET: static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
case TIOCMBIS: unsigned int set, unsigned int clear)
case TIOCMBIC: {
struct acm *acm = tty->driver_data;
unsigned int newctrl;
if (get_user(mask, (unsigned long *) arg)) if (!ACM_READY(acm))
return -EFAULT; return -EINVAL;
newctrl = acm->ctrlout; 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) { newctrl = (newctrl & ~clear) | set;
case TIOCMSET: newctrl = mask; break;
case TIOCMBIS: newctrl |= mask; break;
case TIOCMBIC: newctrl &= ~mask; break;
}
if (acm->ctrlout == newctrl) return 0; if (acm->ctrlout == newctrl)
return 0;
return acm_set_control(acm, acm->ctrlout = newctrl); 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; return -ENOIOCTLCMD;
} }
...@@ -750,7 +754,9 @@ static struct tty_driver acm_tty_driver = { ...@@ -750,7 +754,9 @@ static struct tty_driver acm_tty_driver = {
.unthrottle = acm_tty_unthrottle, .unthrottle = acm_tty_unthrottle,
.chars_in_buffer = acm_tty_chars_in_buffer, .chars_in_buffer = acm_tty_chars_in_buffer,
.break_ctl = acm_tty_break_ctl, .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) ...@@ -820,7 +820,7 @@ static int usb_midi_open(struct inode *inode, struct file *file)
struct list_head *devs, *mdevs; struct list_head *devs, *mdevs;
struct usb_midi_state *s; struct usb_midi_state *s;
struct usb_mididev *m; struct usb_mididev *m;
int flags; unsigned long flags;
int succeed = 0; int succeed = 0;
#if 0 #if 0
......
...@@ -17,11 +17,6 @@ ...@@ -17,11 +17,6 @@
*/ */
#include <linux/config.h> #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 #ifdef CONFIG_USB_DEBUG
#define DEBUG #define DEBUG
...@@ -29,6 +24,11 @@ ...@@ -29,6 +24,11 @@
#undef DEBUG #undef DEBUG
#endif #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 <linux/usb.h>
#include "hcd.h" #include "hcd.h"
...@@ -214,7 +214,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev) ...@@ -214,7 +214,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hub = hcd->self.root_hub; hub = hcd->self.root_hub;
hcd->state = USB_STATE_QUIESCING; hcd->state = USB_STATE_QUIESCING;
dev_dbg (*hcd->controller, "roothub graceful disconnect\n"); dev_dbg (hcd->controller, "roothub graceful disconnect\n");
usb_disconnect (&hub); usb_disconnect (&hub);
hcd->driver->stop (hcd); hcd->driver->stop (hcd);
...@@ -326,7 +326,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) ...@@ -326,7 +326,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = -EBUSY; retval = -EBUSY;
if (hcd->state != USB_STATE_SUSPENDED) { 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; goto done;
} }
hcd->state = USB_STATE_RESUMING; hcd->state = USB_STATE_RESUMING;
...@@ -336,7 +336,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) ...@@ -336,7 +336,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval = hcd->driver->resume (hcd); retval = hcd->driver->resume (hcd);
if (!HCD_IS_RUNNING (hcd->state)) { 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); usb_hc_died (hcd);
// FIXME: recover, reset etc. // FIXME: recover, reset etc.
} else { } else {
......
...@@ -961,8 +961,8 @@ static void urb_unlink (struct urb *urb) ...@@ -961,8 +961,8 @@ static void urb_unlink (struct urb *urb)
spin_lock_irqsave (&hcd_data_lock, flags); spin_lock_irqsave (&hcd_data_lock, flags);
list_del_init (&urb->urb_list); list_del_init (&urb->urb_list);
dev = urb->dev; dev = urb->dev;
usb_put_dev (dev);
spin_unlock_irqrestore (&hcd_data_lock, flags); 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, ...@@ -791,14 +791,22 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type,
void usb_disconnect(struct usb_device **pdev) void usb_disconnect(struct usb_device **pdev)
{ {
struct usb_device *dev = *pdev; struct usb_device *dev = *pdev;
struct usb_bus *bus = dev->bus; struct usb_bus *bus;
struct usb_operations *ops = bus->op; struct usb_operations *ops;
int i; int i;
might_sleep (); might_sleep ();
if (!dev) if (!dev) {
pr_debug ("%s nodev\n", __FUNCTION__);
return; return;
}
bus = dev->bus;
if (!bus) {
pr_debug ("%s nobus\n", __FUNCTION__);
return;
}
ops = bus->op;
*pdev = NULL; *pdev = NULL;
......
...@@ -20,7 +20,19 @@ ...@@ -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 * 1.5A: - Version for inclusion in 2.5 series kernel
* - Modifications by Richard Purdie (rpurdie@rpsys.net) * - Modifications by Richard Purdie (rpurdie@rpsys.net)
...@@ -28,6 +40,7 @@ ...@@ -28,6 +40,7 @@
* udsl_usb_send_data_context->urb to a pointer and adding code * udsl_usb_send_data_context->urb to a pointer and adding code
* to alloc and free it * to alloc and free it
* - remove_wait_queue() added to udsl_atm_processqueue_thread() * - 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. * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
* (reported by stephen.robinson@zen.co.uk) * (reported by stephen.robinson@zen.co.uk)
...@@ -77,9 +90,9 @@ static int udsl_print_packet (const unsigned char *data, int len); ...@@ -77,9 +90,9 @@ static int udsl_print_packet (const unsigned char *data, int len);
#define PACKETDEBUG(arg...) #define PACKETDEBUG(arg...)
#endif #endif
#define DRIVER_AUTHOR "Johan Verrept, Johan.Verrept@advalvas.be" #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@wanadoo.fr>"
#define DRIVER_DESC "Driver for the Alcatel SpeedTouch USB ADSL modem" #define DRIVER_DESC "Alcatel SpeedTouch USB driver"
#define DRIVER_VERSION "1.5A" #define DRIVER_VERSION "1.6"
#define SPEEDTOUCH_VENDORID 0x06b9 #define SPEEDTOUCH_VENDORID 0x06b9
#define SPEEDTOUCH_PRODUCTID 0x4061 #define SPEEDTOUCH_PRODUCTID 0x4061
...@@ -393,11 +406,12 @@ static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_bu ...@@ -393,11 +406,12 @@ static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_bu
** encode ** ** encode **
*************/ *************/
static const unsigned char zeros[ATM_CELL_PAYLOAD];
static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
{ {
struct udsl_control *ctrl = UDSL_SKB (skb); struct udsl_control *ctrl = UDSL_SKB (skb);
unsigned int i, zero_padding; unsigned int zero_padding;
unsigned char zero = 0;
u32 crc; u32 crc;
ctrl->atm_data.vcc = vcc; ctrl->atm_data.vcc = vcc;
...@@ -423,8 +437,7 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) ...@@ -423,8 +437,7 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
ctrl->aal5_trailer [3] = skb->len; ctrl->aal5_trailer [3] = skb->len;
crc = crc32_be (~0, skb->data, skb->len); crc = crc32_be (~0, skb->data, skb->len);
for (i = 0; i < zero_padding; i++) crc = crc32_be (crc, zeros, zero_padding);
crc = crc32_be (crc, &zero, 1);
crc = crc32_be (crc, ctrl->aal5_trailer, 4); crc = crc32_be (crc, ctrl->aal5_trailer, 4);
crc = ~crc; crc = ~crc;
...@@ -566,8 +579,7 @@ static void udsl_process_receive (unsigned long data) ...@@ -566,8 +579,7 @@ static void udsl_process_receive (unsigned long data)
atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); atmsar_vcc->vcc->push (atmsar_vcc->vcc, new);
} else { } else {
dbg dbg
("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", ("dropping incoming packet : vcc->sk->rcvbuf = %d, skb->true_size = %d",
atomic_read (&atmsar_vcc->vcc->rx_inuse),
atmsar_vcc->vcc->sk->rcvbuf, new->truesize); atmsar_vcc->vcc->sk->rcvbuf, new->truesize);
dev_kfree_skb (new); dev_kfree_skb (new);
} }
......
...@@ -744,7 +744,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) ...@@ -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); *private_header = cpu_to_le16(skb->len-2);
kaweth->tx_skb = skb; kaweth->tx_skb = skb;
......
...@@ -315,7 +315,11 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)"); ...@@ -315,7 +315,11 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
#ifdef DEBUG #ifdef DEBUG
#define devdbg(usbnet, fmt, arg...) \ #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 #else
#define devdbg(usbnet, fmt, arg...) do {} while(0) #define devdbg(usbnet, fmt, arg...) do {} while(0)
#endif #endif
......
...@@ -101,6 +101,8 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs); ...@@ -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 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 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 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 [] = { static struct usb_device_id id_table_combined [] = {
...@@ -138,6 +140,8 @@ static struct usb_serial_device_type belkin_device = { ...@@ -138,6 +140,8 @@ static struct usb_serial_device_type belkin_device = {
.ioctl = belkin_sa_ioctl, .ioctl = belkin_sa_ioctl,
.set_termios = belkin_sa_set_termios, .set_termios = belkin_sa_set_termios,
.break_ctl = belkin_sa_break_ctl, .break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
.tiocmset = belkin_sa_tiocmset,
.attach = belkin_sa_startup, .attach = belkin_sa_startup,
.shutdown = belkin_sa_shutdown, .shutdown = belkin_sa_shutdown,
}; };
...@@ -502,65 +506,77 @@ static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state ) ...@@ -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); struct belkin_sa_private *priv = usb_get_serial_port_data(port);
int ret = 0;
int mask;
unsigned long control_state; unsigned long control_state;
unsigned long flags; unsigned long flags;
dbg("%s", __FUNCTION__);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state; control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */ return control_state;
switch (cmd) { }
case TIOCMGET:
return put_user(control_state, (unsigned long *) arg);
break;
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)) { static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
/* RTS needs set */ unsigned int set, unsigned int clear)
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0; {
if (urb_value) struct usb_serial *serial = port->serial;
control_state |= TIOCM_RTS; struct belkin_sa_private *priv = usb_get_serial_port_data(port);
else unsigned long control_state;
control_state &= ~TIOCM_RTS; unsigned long flags;
int retval;
int rts = 0;
int dtr = 0;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) { dbg("%s", __FUNCTION__);
err("Set RTS error %d", ret);
goto cmerror;
}
}
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { spin_lock_irqsave(&priv->lock, flags);
/* DTR needs set */ control_state = priv->control_state;
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value) if (set & TIOCM_RTS) {
control_state |= TIOCM_RTS;
rts = 1;
}
if (set & TIOCM_DTR) {
control_state |= TIOCM_DTR; control_state |= TIOCM_DTR;
else dtr = 1;
control_state &= ~TIOCM_DTR; }
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) { if (clear & TIOCM_RTS) {
err("Set DTR error %d", ret); control_state &= ~TIOCM_RTS;
goto cmerror; rts = 0;
} }
if (clear & TIOCM_DTR) {
control_state &= ~TIOCM_DTR;
dtr = 0;
} }
cmerror:
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state; priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags); 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: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */ /* TODO */
......
...@@ -460,6 +460,9 @@ static void digi_set_termios( struct usb_serial_port *port, ...@@ -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 void digi_break_ctl( struct usb_serial_port *port, int break_state );
static int digi_ioctl( struct usb_serial_port *port, struct file *file, static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg ); 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, static int digi_write( struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count ); const unsigned char *buf, int count );
static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs ); 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 = { ...@@ -526,6 +529,8 @@ static struct usb_serial_device_type digi_acceleport_2_device = {
.ioctl = digi_ioctl, .ioctl = digi_ioctl,
.set_termios = digi_set_termios, .set_termios = digi_set_termios,
.break_ctl = digi_break_ctl, .break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup, .attach = digi_startup,
.shutdown = digi_shutdown, .shutdown = digi_shutdown,
}; };
...@@ -551,6 +556,8 @@ static struct usb_serial_device_type digi_acceleport_4_device = { ...@@ -551,6 +556,8 @@ static struct usb_serial_device_type digi_acceleport_4_device = {
.ioctl = digi_ioctl, .ioctl = digi_ioctl,
.set_termios = digi_set_termios, .set_termios = digi_set_termios,
.break_ctl = digi_break_ctl, .break_ctl = digi_break_ctl,
.tiocmget = digi_tiocmget,
.tiocmset = digi_tiocmset,
.attach = digi_startup, .attach = digi_startup,
.shutdown = digi_shutdown, .shutdown = digi_shutdown,
}; };
...@@ -1211,39 +1218,46 @@ static void digi_break_ctl( struct usb_serial_port *port, int break_state ) ...@@ -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, static int digi_tiocmget( struct usb_serial_port *port, struct file *file )
unsigned int cmd, unsigned long arg )
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val; unsigned int val;
unsigned long flags = 0; unsigned long flags;
dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd );
switch (cmd) { dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
case TIOCMGET:
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave( &priv->dp_port_lock, flags );
val = priv->dp_modem_signals; val = priv->dp_modem_signals;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore( &priv->dp_port_lock, flags );
if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) ) return val;
return( -EFAULT ); }
return( 0 );
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 ); spin_lock_irqsave( &priv->dp_port_lock, flags );
if( cmd == TIOCMBIS ) val = (priv->dp_modem_signals & ~clear) | set;
val = priv->dp_modem_signals | val;
else if( cmd == TIOCMBIC )
val = priv->dp_modem_signals & ~val;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); 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: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* 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); ...@@ -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_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_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 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 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 ); 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 = { ...@@ -198,6 +200,8 @@ static struct usb_serial_device_type ftdi_sio_device = {
.ioctl = ftdi_sio_ioctl, .ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios, .set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl, .break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_sio_startup, .attach = ftdi_sio_startup,
.shutdown = ftdi_sio_shutdown, .shutdown = ftdi_sio_shutdown,
}; };
...@@ -219,6 +223,8 @@ static struct usb_serial_device_type ftdi_8U232AM_device = { ...@@ -219,6 +223,8 @@ static struct usb_serial_device_type ftdi_8U232AM_device = {
.ioctl = ftdi_sio_ioctl, .ioctl = ftdi_sio_ioctl,
.set_termios = ftdi_sio_set_termios, .set_termios = ftdi_sio_set_termios,
.break_ctl = ftdi_sio_break_ctl, .break_ctl = ftdi_sio_break_ctl,
.tiocmget = ftdi_sio_tiocmget,
.tiocmset = ftdi_sio_tiocmset,
.attach = ftdi_8U232AM_startup, .attach = ftdi_8U232AM_startup,
.shutdown = ftdi_sio_shutdown, .shutdown = ftdi_sio_shutdown,
}; };
...@@ -823,125 +829,100 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * ...@@ -823,125 +829,100 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
return; return;
} /* ftdi_sio_set_termios */ } /* 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 usb_serial *serial = port->serial;
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value=0; /* Will hold the new flags */ char *buf = NULL;
char buf[2]; int ret = -EINVAL;
int ret, mask; int size;
dbg("%s cmd 0x%04x", __FUNCTION__, cmd); dbg("%s", __FUNCTION__);
/* Based on code from acm.c and others */ buf = kmalloc(2, GFP_KERNEL);
switch (cmd) { if (!buf)
goto exit;
case TIOCMGET: if (priv->ftdi_type == sio) {
dbg("%s TIOCMGET", __FUNCTION__); size = 1;
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);
}
} else { } else {
/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same /* 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 */ 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), usb_rcvctrlpipe(serial->dev, 0),
FTDI_SIO_GET_MODEM_STATUS_REQUEST, FTDI_SIO_GET_MODEM_STATUS_REQUEST,
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, 0, 0, 0, buf, size, WDR_TIMEOUT);
buf, 2, WDR_TIMEOUT)) < 0 ) { if (ret < 0) {
err("%s Could not get modem status of device - err: %d", __FUNCTION__, err("%s Could not get modem status of device - err: %d",
ret); __FUNCTION__, ret);
return(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_CTS_MASK ? TIOCM_CTS : 0) |
(buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) |
(buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0);
(unsigned long *) arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ exit:
dbg("%s TIOCMSET", __FUNCTION__); kfree(buf);
if (get_user(mask, (unsigned long *) arg)) return ret;
return -EFAULT; }
urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file,
err("Error from DTR set urb (TIOCMSET)"); unsigned int set, unsigned int clear)
} {
urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW); struct usb_serial *serial = port->serial;
if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ int ret = 0;
err("Error from RTS set urb (TIOCMSET)");
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 */ if (set & TIOCM_DTR)
dbg("%s TIOCMBIS", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev, if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0) { HIGH)) < 0) {
err("Urb to set DTR failed"); err("Urb to set DTR failed");
return(ret); goto exit;
}
} }
if (mask & TIOCM_RTS) {
if (clear & TIOCM_RTS)
if ((ret = set_rts(serial->dev, if ((ret = set_rts(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
HIGH)) < 0){ LOW)) < 0) {
err("Urb to set RTS failed"); err("Urb to unset RTS failed");
return(ret); goto exit;
}
} }
break;
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ if (clear & TIOCM_DTR)
dbg("%s TIOCMBIC", __FUNCTION__);
if (get_user(mask, (unsigned long *) arg))
return -EFAULT;
if (mask & TIOCM_DTR){
if ((ret = set_dtr(serial->dev, if ((ret = set_dtr(serial->dev,
usb_sndctrlpipe(serial->dev, 0), usb_sndctrlpipe(serial->dev, 0),
LOW)) < 0){ LOW)) < 0) {
err("Urb to unset DTR failed"); 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;
/* exit:
* I had originally implemented TCSET{A,S}{,F,W} and return ret;
* 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 static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
* ftdi_sio_set_termios. {
* dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
*/
switch (cmd) {
default: default:
/* This is not an error - turns out the higher layers will do /* 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); dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd);
return(-ENOIOCTLCMD); return(-ENOIOCTLCMD);
......
...@@ -455,6 +455,8 @@ static void edge_unthrottle (struct usb_serial_port *port); ...@@ -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 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 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 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 int edge_startup (struct usb_serial *serial);
static void edge_shutdown (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 ...@@ -1762,42 +1764,27 @@ static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int
return -ENOIOCTLCMD; 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; struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int arg; unsigned int mcr;
if (copy_from_user(&arg, value, sizeof(int))) dbg("%s - port %d", __FUNCTION__, port->number);
return -EFAULT;
switch (cmd) { mcr = edge_port->shadowMCR;
case TIOCMBIS: if (set & TIOCM_RTS)
if (arg & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_DTR)
mcr |= MCR_RTS; mcr |= MCR_RTS;
if (arg & TIOCM_LOOP) if (set & TIOCM_DTR)
mcr |= MCR_DTR;
if (set & TIOCM_LOOP)
mcr |= MCR_LOOPBACK; mcr |= MCR_LOOPBACK;
break;
case TIOCMBIC: if (clear & TIOCM_RTS)
if (arg & TIOCM_RTS)
mcr &= ~MCR_RTS; mcr &= ~MCR_RTS;
if (arg & TIOCM_DTR) if (clear & TIOCM_DTR)
mcr &= ~MCR_RTS; mcr &= ~MCR_DTR;
if (arg & TIOCM_LOOP) if (clear & TIOCM_LOOP)
mcr &= ~MCR_LOOPBACK; 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; edge_port->shadowMCR = mcr;
...@@ -1806,12 +1793,17 @@ static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, uns ...@@ -1806,12 +1793,17 @@ static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, uns
return 0; 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 result = 0;
unsigned int msr = edge_port->shadowMSR; unsigned int msr;
unsigned int mcr = edge_port->shadowMCR; 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 */ result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
| ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
| ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */
...@@ -1822,13 +1814,9 @@ static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value) ...@@ -1822,13 +1814,9 @@ static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value)
dbg("%s -- %x", __FUNCTION__, result); dbg("%s -- %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int))) return result;
return -EFAULT;
return 0;
} }
static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo) static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo)
{ {
struct serial_struct tmp; struct serial_struct tmp;
...@@ -1885,16 +1873,6 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned ...@@ -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 get_lsr_info(edge_port, (unsigned int *) arg);
return 0; 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: case TIOCGSERIAL:
dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number); dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
return get_serial_info(edge_port, (struct serial_struct *) arg); return get_serial_info(edge_port, (struct serial_struct *) arg);
......
...@@ -114,6 +114,8 @@ static struct usb_serial_device_type edgeport_1port_device = { ...@@ -114,6 +114,8 @@ static struct usb_serial_device_type edgeport_1port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
...@@ -137,6 +139,8 @@ static struct usb_serial_device_type edgeport_2port_device = { ...@@ -137,6 +139,8 @@ static struct usb_serial_device_type edgeport_2port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
...@@ -160,6 +164,8 @@ static struct usb_serial_device_type edgeport_4port_device = { ...@@ -160,6 +164,8 @@ static struct usb_serial_device_type edgeport_4port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
...@@ -183,6 +189,8 @@ static struct usb_serial_device_type edgeport_8port_device = { ...@@ -183,6 +189,8 @@ static struct usb_serial_device_type edgeport_8port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
......
...@@ -2403,42 +2403,27 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_ ...@@ -2403,42 +2403,27 @@ static void edge_set_termios (struct usb_serial_port *port, struct termios *old_
return; 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; struct edgeport_port *edge_port = usb_get_serial_port_data(port);
unsigned int arg; unsigned int mcr;
if (copy_from_user(&arg, value, sizeof(int))) dbg("%s - port %d", __FUNCTION__, port->number);
return -EFAULT;
switch (cmd) { mcr = edge_port->shadow_mcr;
case TIOCMBIS: if (set & TIOCM_RTS)
if (arg & TIOCM_RTS)
mcr |= MCR_RTS;
if (arg & TIOCM_DTR)
mcr |= MCR_RTS; mcr |= MCR_RTS;
if (arg & TIOCM_LOOP) if (set & TIOCM_DTR)
mcr |= MCR_DTR;
if (set & TIOCM_LOOP)
mcr |= MCR_LOOPBACK; mcr |= MCR_LOOPBACK;
break;
case TIOCMBIC: if (clear & TIOCM_RTS)
if (arg & TIOCM_RTS)
mcr &= ~MCR_RTS; mcr &= ~MCR_RTS;
if (arg & TIOCM_DTR) if (clear & TIOCM_DTR)
mcr &= ~MCR_RTS; mcr &= ~MCR_DTR;
if (arg & TIOCM_LOOP) if (clear & TIOCM_LOOP)
mcr &= ~MCR_LOOPBACK; 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; edge_port->shadow_mcr = mcr;
...@@ -2447,12 +2432,17 @@ static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, un ...@@ -2447,12 +2432,17 @@ static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, un
return 0; 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 result = 0;
unsigned int msr = edge_port->shadow_msr; unsigned int msr;
unsigned int mcr = edge_port->shadow_mcr; 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 */ result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */
| ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */
| ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */
...@@ -2463,9 +2453,7 @@ static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value) ...@@ -2463,9 +2453,7 @@ static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value)
dbg("%s -- %x", __FUNCTION__, result); dbg("%s -- %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int))) return result;
return -EFAULT;
return 0;
} }
static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo) 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 ...@@ -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); // return get_lsr_info(edge_port, (unsigned int *) arg);
break; 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: case TIOCGSERIAL:
dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number); dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
return get_serial_info(edge_port, (struct serial_struct *) arg); return get_serial_info(edge_port, (struct serial_struct *) arg);
...@@ -2665,6 +2641,8 @@ static struct usb_serial_device_type edgeport_1port_device = { ...@@ -2665,6 +2641,8 @@ static struct usb_serial_device_type edgeport_1port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
...@@ -2688,6 +2666,8 @@ static struct usb_serial_device_type edgeport_2port_device = { ...@@ -2688,6 +2666,8 @@ static struct usb_serial_device_type edgeport_2port_device = {
.shutdown = edge_shutdown, .shutdown = edge_shutdown,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
.tiocmset = edge_tiocmset,
.write = edge_write, .write = edge_write,
.write_room = edge_write_room, .write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer, .chars_in_buffer = edge_chars_in_buffer,
......
...@@ -282,16 +282,13 @@ static void keyspan_set_termios (struct usb_serial_port *port, ...@@ -282,16 +282,13 @@ static void keyspan_set_termios (struct usb_serial_port *port,
keyspan_send_setup(port, 0); keyspan_send_setup(port, 0);
} }
static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
unsigned int cmd, unsigned long arg)
{ {
unsigned int value, set; unsigned int value;
struct keyspan_port_private *p_priv; struct keyspan_port_private *p_priv;
p_priv = usb_get_serial_port_data(port); p_priv = usb_get_serial_port_data(port);
switch (cmd) {
case TIOCMGET:
value = ((p_priv->rts_state) ? TIOCM_RTS : 0) | value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
((p_priv->dtr_state) ? TIOCM_DTR : 0) | ((p_priv->dtr_state) ? TIOCM_DTR : 0) |
((p_priv->cts_state) ? TIOCM_CTS : 0) | ((p_priv->cts_state) ? TIOCM_CTS : 0) |
...@@ -299,31 +296,32 @@ static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -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->dcd_state) ? TIOCM_CAR : 0) |
((p_priv->ri_state) ? TIOCM_RNG : 0); ((p_priv->ri_state) ? TIOCM_RNG : 0);
if (put_user(value, (unsigned int *) arg)) return value;
return -EFAULT; }
return 0;
case TIOCMSET: static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
if (get_user(value, (unsigned int *) arg)) unsigned int set, unsigned int clear)
return -EFAULT; {
p_priv->rts_state = ((value & TIOCM_RTS) ? 1 : 0); struct keyspan_port_private *p_priv;
p_priv->dtr_state = ((value & TIOCM_DTR) ? 1 : 0);
keyspan_send_setup(port, 0);
return 0;
case TIOCMBIS: p_priv = usb_get_serial_port_data(port);
case TIOCMBIC:
if (get_user(value, (unsigned int *) arg)) if (set & TIOCM_RTS)
return -EFAULT; p_priv->rts_state = 1;
set = (cmd == TIOCMBIS); if (set & TIOCM_DTR)
if (value & TIOCM_RTS) p_priv->dtr_state = 1;
p_priv->rts_state = set;
if (value & TIOCM_DTR) if (clear & TIOCM_RTS)
p_priv->dtr_state = set; p_priv->rts_state = 0;
if (clear & TIOCM_DTR)
p_priv->dtr_state = 0;
keyspan_send_setup(port, 0); keyspan_send_setup(port, 0);
return 0; return 0;
} }
static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
......
...@@ -63,6 +63,11 @@ static void keyspan_set_termios (struct usb_serial_port *port, ...@@ -63,6 +63,11 @@ static void keyspan_set_termios (struct usb_serial_port *port,
struct termios *old); struct termios *old);
static void keyspan_break_ctl (struct usb_serial_port *port, static void keyspan_break_ctl (struct usb_serial_port *port,
int break_state); 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_fake_startup (struct usb_serial *serial);
static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk, static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk,
...@@ -551,6 +556,8 @@ static struct usb_serial_device_type keyspan_1port_device = { ...@@ -551,6 +556,8 @@ static struct usb_serial_device_type keyspan_1port_device = {
.ioctl = keyspan_ioctl, .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios, .set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl, .break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup, .attach = keyspan_startup,
.shutdown = keyspan_shutdown, .shutdown = keyspan_shutdown,
}; };
...@@ -574,6 +581,8 @@ static struct usb_serial_device_type keyspan_2port_device = { ...@@ -574,6 +581,8 @@ static struct usb_serial_device_type keyspan_2port_device = {
.ioctl = keyspan_ioctl, .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios, .set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl, .break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup, .attach = keyspan_startup,
.shutdown = keyspan_shutdown, .shutdown = keyspan_shutdown,
}; };
...@@ -597,6 +606,8 @@ static struct usb_serial_device_type keyspan_4port_device = { ...@@ -597,6 +606,8 @@ static struct usb_serial_device_type keyspan_4port_device = {
.ioctl = keyspan_ioctl, .ioctl = keyspan_ioctl,
.set_termios = keyspan_set_termios, .set_termios = keyspan_set_termios,
.break_ctl = keyspan_break_ctl, .break_ctl = keyspan_break_ctl,
.tiocmget = keyspan_tiocmget,
.tiocmset = keyspan_tiocmset,
.attach = keyspan_startup, .attach = keyspan_startup,
.shutdown = keyspan_shutdown, .shutdown = keyspan_shutdown,
}; };
......
...@@ -457,17 +457,13 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial, ...@@ -457,17 +457,13 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
return rc; return rc;
} }
static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
int rc; int rc;
unsigned int value; unsigned char status;
unsigned char status, mask; int value;
switch (cmd) {
case TIOCMGET: /* get modem pins state */
rc = keyspan_pda_get_modem_info(serial, &status); rc = keyspan_pda_get_modem_info(serial, &status);
if (rc < 0) if (rc < 0)
return rc; return rc;
...@@ -478,41 +474,37 @@ static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -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<<4)) ? TIOCM_DSR : 0) |
((status & (1<<3)) ? TIOCM_CTS : 0) | ((status & (1<<3)) ? TIOCM_CTS : 0) |
((status & (1<<2)) ? TIOCM_RTS : 0); ((status & (1<<2)) ? TIOCM_RTS : 0);
if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) return value;
return -EFAULT; }
return 0;
case TIOCMSET: /* set a state as returned by MGET */ static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) unsigned int set, unsigned int clear)
return -EFAULT; {
status = struct usb_serial *serial = port->serial;
((value & TIOCM_DTR) ? (1<<7) : 0) | int rc;
((value & TIOCM_CAR) ? (1<<6) : 0) | unsigned char status;
((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;
rc = keyspan_pda_get_modem_info(serial, &status); rc = keyspan_pda_get_modem_info(serial, &status);
if (rc < 0) if (rc < 0)
return rc; return rc;
mask =
((value & TIOCM_RTS) ? (1<<2) : 0) | if (set & TIOCM_RTS)
((value & TIOCM_DTR) ? (1<<7) : 0); status |= (1<<2);
if (cmd == TIOCMBIS) if (set & TIOCM_DTR)
status |= mask; status |= (1<<7);
else
status &= ~mask; if (clear & TIOCM_RTS)
status &= ~(1<<2);
if (clear & TIOCM_DTR)
status &= ~(1<<7);
rc = keyspan_pda_set_modem_info(serial, status); rc = keyspan_pda_set_modem_info(serial, status);
if (rc < 0)
return rc; 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: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */ /* TODO */
...@@ -874,6 +866,8 @@ static struct usb_serial_device_type keyspan_pda_device = { ...@@ -874,6 +866,8 @@ static struct usb_serial_device_type keyspan_pda_device = {
.ioctl = keyspan_pda_ioctl, .ioctl = keyspan_pda_ioctl,
.set_termios = keyspan_pda_set_termios, .set_termios = keyspan_pda_set_termios,
.break_ctl = keyspan_pda_break_ctl, .break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset,
.attach = keyspan_pda_startup, .attach = keyspan_pda_startup,
.shutdown = keyspan_pda_shutdown, .shutdown = keyspan_pda_shutdown,
}; };
......
...@@ -105,6 +105,11 @@ static void klsi_105_unthrottle (struct usb_serial_port *port); ...@@ -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, static void klsi_105_break_ctl (struct usb_serial_port *port,
int break_state ); 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. * All of the device info needed for the KLSI converters.
...@@ -143,6 +148,8 @@ static struct usb_serial_device_type kl5kusb105d_device = { ...@@ -143,6 +148,8 @@ static struct usb_serial_device_type kl5kusb105d_device = {
.ioctl = klsi_105_ioctl, .ioctl = klsi_105_ioctl,
.set_termios = klsi_105_set_termios, .set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/ /*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
.tiocmset = klsi_105_tiocmset,
.attach = klsi_105_startup, .attach = klsi_105_startup,
.shutdown = klsi_105_shutdown, .shutdown = klsi_105_shutdown,
.throttle = klsi_105_throttle, .throttle = klsi_105_throttle,
...@@ -879,68 +886,67 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) ...@@ -879,68 +886,67 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */ } /* mct_u232_break_ctl */
#endif #endif
static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
unsigned int cmd, unsigned long arg)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port); struct klsi_105_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long flags; unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET: {
int rc; int rc;
unsigned long line_state; 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); rc = klsi_105_get_line_state(serial, &line_state);
if (rc < 0) { if (rc < 0) {
err("Reading line control failed (error = %d)", rc); err("Reading line control failed (error = %d)", rc);
/* better return value? EAGAIN? */ /* better return value? EAGAIN? */
return -ENOIOCTLCMD; return rc;
} }
spin_lock_irqsave (&priv->lock, flags); spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state; priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state); 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 */ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ unsigned int set, unsigned int clear)
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ {
if (get_user(mask, (unsigned long *) arg)) int retval = -EINVAL;
return -EFAULT;
if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { dbg("%s", __FUNCTION__);
/* 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; */
}
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { /* if this ever gets implemented, it should be done something like this:
/* DTR needs set */ struct usb_serial *serial = port->serial;
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || struct klsi_105_private *priv = usb_get_serial_port_data(port);
(cmd == TIOCMBIS) ) unsigned long flags;
dbg("%s - set DTR not handled", __FUNCTION__); int control;
/* 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;
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: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */ /* TODO */
......
...@@ -81,6 +81,9 @@ static int kobil_write (struct usb_serial_port *port, int from_user, ...@@ -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_write_room(struct usb_serial_port *port);
static int kobil_ioctl(struct usb_serial_port *port, struct file *file, static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg); 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_read_int_callback( struct urb *urb, struct pt_regs *regs );
static void kobil_write_callback( struct urb *purb, 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 = { ...@@ -106,6 +109,8 @@ struct usb_serial_device_type kobil_device = {
.attach = kobil_startup, .attach = kobil_startup,
.shutdown = kobil_shutdown, .shutdown = kobil_shutdown,
.ioctl = kobil_ioctl, .ioctl = kobil_ioctl,
.tiocmget = kobil_tiocmget,
.tiocmset = kobil_tiocmset,
.open = kobil_open, .open = kobil_open,
.close = kobil_close, .close = kobil_close,
.write = kobil_write, .write = kobil_write,
...@@ -490,11 +495,120 @@ static int kobil_write_room (struct usb_serial_port *port) ...@@ -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, static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct kobil_private * priv; struct kobil_private * priv;
int mask;
int result; int result;
unsigned short urb_val = 0; unsigned short urb_val = 0;
unsigned char *transfer_buffer; unsigned char *transfer_buffer;
...@@ -605,90 +719,8 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -605,90 +719,8 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
kfree(transfer_buffer); kfree(transfer_buffer);
return ((result < 0) ? -EFAULT : 0); 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);
} }
return -ENOIOCTLCMD;
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;
} }
......
...@@ -125,7 +125,11 @@ static int mct_u232_ioctl (struct usb_serial_port *port, ...@@ -125,7 +125,11 @@ static int mct_u232_ioctl (struct usb_serial_port *port,
unsigned long arg); unsigned long arg);
static void mct_u232_break_ctl (struct usb_serial_port *port, static void mct_u232_break_ctl (struct usb_serial_port *port,
int break_state ); 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. * 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 = { ...@@ -165,6 +169,8 @@ static struct usb_serial_device_type mct_u232_device = {
.ioctl = mct_u232_ioctl, .ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios, .set_termios = mct_u232_set_termios,
.break_ctl = mct_u232_break_ctl, .break_ctl = mct_u232_break_ctl,
.tiocmget = mct_u232_tiocmget,
.tiocmset = mct_u232_tiocmset,
.attach = mct_u232_startup, .attach = mct_u232_startup,
.shutdown = mct_u232_shutdown, .shutdown = mct_u232_shutdown,
}; };
...@@ -773,57 +779,55 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) ...@@ -773,57 +779,55 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
} /* mct_u232_break_ctl */ } /* mct_u232_break_ctl */
static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
unsigned int cmd, unsigned long arg)
{ {
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port); struct mct_u232_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long control_state; unsigned long control_state;
unsigned long flags; unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd); dbg("%s", __FUNCTION__);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state; control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */ return control_state;
switch (cmd) { }
case TIOCMGET:
return put_user(control_state, (unsigned long *) arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ unsigned int set, unsigned int clear)
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ {
if (get_user(mask, (unsigned long *) arg)) struct usb_serial *serial = port->serial;
return -EFAULT; struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { dbg("%s", __FUNCTION__);
/* RTS needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
(cmd == TIOCMBIS) )
control_state |= TIOCM_RTS;
else
control_state &= ~TIOCM_RTS;
}
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { spin_lock_irqsave(&priv->lock, flags);
/* DTR needs set */ control_state = priv->control_state;
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
(cmd == TIOCMBIS) ) if (set & TIOCM_RTS)
control_state |= TIOCM_RTS;
if (set & TIOCM_DTR)
control_state |= TIOCM_DTR; control_state |= TIOCM_DTR;
else if (clear & TIOCM_RTS)
control_state &= ~TIOCM_RTS;
if (clear & TIOCM_DTR)
control_state &= ~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; priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags); 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: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */ /* TODO */
......
/* /*
* Prolific PL2303 USB to serial adaptor driver * 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 * Original driver for 2.2.x by anonymous
* *
...@@ -111,6 +112,16 @@ static struct usb_driver pl2303_driver = { ...@@ -111,6 +112,16 @@ static struct usb_driver pl2303_driver = {
#define VENDOR_READ_REQUEST_TYPE 0xc0 #define VENDOR_READ_REQUEST_TYPE 0xc0
#define VENDOR_READ_REQUEST 0x01 #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 */ /* function prototypes for a PL2303 serial converter */
static int pl2303_open (struct usb_serial_port *port, struct file *filp); static int pl2303_open (struct usb_serial_port *port, struct file *filp);
static void pl2303_close (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); ...@@ -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, static int pl2303_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count); const unsigned char *buf, int count);
static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); 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 int pl2303_startup (struct usb_serial *serial);
static void pl2303_shutdown (struct usb_serial *serial); static void pl2303_shutdown (struct usb_serial *serial);
...@@ -143,6 +157,8 @@ static struct usb_serial_device_type pl2303_device = { ...@@ -143,6 +157,8 @@ static struct usb_serial_device_type pl2303_device = {
.ioctl = pl2303_ioctl, .ioctl = pl2303_ioctl,
.break_ctl = pl2303_break_ctl, .break_ctl = pl2303_break_ctl,
.set_termios = pl2303_set_termios, .set_termios = pl2303_set_termios,
.tiocmget = pl2303_tiocmget,
.tiocmset = pl2303_tiocmset,
.read_bulk_callback = pl2303_read_bulk_callback, .read_bulk_callback = pl2303_read_bulk_callback,
.read_int_callback = pl2303_read_int_callback, .read_int_callback = pl2303_read_int_callback,
.write_bulk_callback = pl2303_write_bulk_callback, .write_bulk_callback = pl2303_write_bulk_callback,
...@@ -153,6 +169,7 @@ static struct usb_serial_device_type pl2303_device = { ...@@ -153,6 +169,7 @@ static struct usb_serial_device_type pl2303_device = {
struct pl2303_private { struct pl2303_private {
spinlock_t lock; spinlock_t lock;
u8 line_control; u8 line_control;
u8 line_status;
u8 termios_initialized; u8 termios_initialized;
}; };
...@@ -222,6 +239,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -222,6 +239,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int cflag; unsigned int cflag;
unsigned char *buf; unsigned char *buf;
int baud; int baud;
...@@ -234,13 +252,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -234,13 +252,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
return; return;
} }
spin_lock(&priv->lock); spin_lock_irqsave(&priv->lock, flags);
if (!priv->termios_initialized) { if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios; *(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
priv->termios_initialized = 1; priv->termios_initialized = 1;
} }
spin_unlock(&priv->lock); spin_unlock_irqrestore(&priv->lock, flags);
cflag = port->tty->termios->c_cflag; cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */ /* 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 ...@@ -350,13 +368,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
if (cflag && CBAUD) { if (cflag && CBAUD) {
u8 control; u8 control;
spin_lock (&priv->lock); spin_lock_irqsave(&priv->lock, flags);
if ((cflag && CBAUD) == B0) if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else else
priv->line_control |= (CONTROL_DTR | CONTROL_RTS); priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
control = priv->line_control; control = priv->line_control;
spin_unlock (&priv->lock); spin_unlock_irqrestore(&priv->lock, flags);
set_control_lines (serial->dev, control); set_control_lines (serial->dev, control);
} }
...@@ -445,6 +463,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) ...@@ -445,6 +463,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
{ {
struct usb_serial *serial; struct usb_serial *serial;
struct pl2303_private *priv; struct pl2303_private *priv;
unsigned long flags;
unsigned int c_cflag; unsigned int c_cflag;
int result; int result;
...@@ -481,72 +500,56 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) ...@@ -481,72 +500,56 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
if (c_cflag & HUPCL) { if (c_cflag & HUPCL) {
/* drop DTR and RTS */ /* drop DTR and RTS */
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
spin_lock (&priv->lock); spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0; priv->line_control = 0;
spin_unlock (&priv->lock); spin_unlock_irqrestore (&priv->lock, flags);
set_control_lines (port->serial->dev, 0); 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); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg; unsigned long flags;
u8 control; u8 control;
if (copy_from_user(&arg, value, sizeof(int))) spin_lock_irqsave (&priv->lock, flags);
return -EFAULT; if (set & TIOCM_RTS)
spin_lock (&priv->lock);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
priv->line_control |= CONTROL_RTS; priv->line_control |= CONTROL_RTS;
if (arg & TIOCM_DTR) if (set & TIOCM_DTR)
priv->line_control |= CONTROL_DTR; priv->line_control |= CONTROL_DTR;
break; if (clear & TIOCM_RTS)
case TIOCMBIC:
if (arg & TIOCM_RTS)
priv->line_control &= ~CONTROL_RTS; priv->line_control &= ~CONTROL_RTS;
if (arg & TIOCM_DTR) if (clear & TIOCM_DTR)
priv->line_control &= ~CONTROL_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; control = priv->line_control;
spin_unlock (&priv->lock); spin_unlock_irqrestore (&priv->lock, flags);
return set_control_lines (port->serial->dev, control); 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); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int mcr; unsigned int mcr;
unsigned int result; unsigned int result;
spin_lock (&priv->lock); dbg("%s (%d)", __FUNCTION__, port->number);
spin_lock_irqsave (&priv->lock, flags);
mcr = priv->line_control; mcr = priv->line_control;
spin_unlock (&priv->lock); spin_unlock_irqrestore (&priv->lock, flags);
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0); | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);
dbg("%s - result = %x", __FUNCTION__, result); dbg("%s - result = %x", __FUNCTION__, result);
if (copy_to_user(value, &result, sizeof(int))) return result;
return -EFAULT;
return 0;
} }
static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) 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 ...@@ -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); dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
switch (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: default:
dbg("%s not supported = 0x%04x", __FUNCTION__, cmd); dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
break; break;
...@@ -573,7 +565,6 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign ...@@ -573,7 +565,6 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
static void pl2303_break_ctl (struct usb_serial_port *port, int break_state) static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
...@@ -613,9 +604,13 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -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_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); 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; int status;
dbg("%s (%d)", __FUNCTION__, port->number);
switch (urb->status) { switch (urb->status) {
case 0: case 0:
/* success */ /* success */
...@@ -637,7 +632,13 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -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); 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: exit:
status = usb_submit_urb (urb, GFP_ATOMIC); status = usb_submit_urb (urb, GFP_ATOMIC);
...@@ -651,10 +652,14 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) ...@@ -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_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct pl2303_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty; struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer; unsigned char *data = urb->transfer_buffer;
unsigned long flags;
int i; int i;
int result; int result;
u8 status;
char tty_flag;
if (port_paranoia_check (port, __FUNCTION__)) if (port_paranoia_check (port, __FUNCTION__))
return; return;
...@@ -688,13 +693,34 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) ...@@ -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); 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; tty = port->tty;
if (tty && urb->actual_length) { 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) { for (i = 0; i < urb->actual_length; ++i) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) { if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty); 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); tty_flip_buffer_push (tty);
} }
......
...@@ -785,6 +785,51 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int ...@@ -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); 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) void usb_serial_port_softint(void *private)
{ {
struct usb_serial_port *port = (struct usb_serial_port *)private; struct usb_serial_port *port = (struct usb_serial_port *)private;
...@@ -1286,6 +1331,8 @@ struct tty_driver usb_serial_tty_driver = { ...@@ -1286,6 +1331,8 @@ struct tty_driver usb_serial_tty_driver = {
.break_ctl = serial_break, .break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer, .chars_in_buffer = serial_chars_in_buffer,
.read_proc = serial_read_proc, .read_proc = serial_read_proc,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
}; };
......
...@@ -251,6 +251,8 @@ struct usb_serial_device_type { ...@@ -251,6 +251,8 @@ struct usb_serial_device_type {
int (*chars_in_buffer) (struct usb_serial_port *port); int (*chars_in_buffer) (struct usb_serial_port *port);
void (*throttle) (struct usb_serial_port *port); void (*throttle) (struct usb_serial_port *port);
void (*unthrottle) (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_int_callback)(struct urb *urb, struct pt_regs *regs);
void (*read_bulk_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 ...@@ -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_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_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 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 void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
static int whiteheat_chars_in_buffer (struct usb_serial_port *port); static int whiteheat_chars_in_buffer (struct usb_serial_port *port);
static void whiteheat_throttle (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 = { ...@@ -184,6 +186,8 @@ static struct usb_serial_device_type whiteheat_device = {
.ioctl = whiteheat_ioctl, .ioctl = whiteheat_ioctl,
.set_termios = whiteheat_set_termios, .set_termios = whiteheat_set_termios,
.break_ctl = whiteheat_break_ctl, .break_ctl = whiteheat_break_ctl,
.tiocmget = whiteheat_tiocmget,
.tiocmset = whiteheat_tiocmset,
.chars_in_buffer = whiteheat_chars_in_buffer, .chars_in_buffer = whiteheat_chars_in_buffer,
.throttle = whiteheat_throttle, .throttle = whiteheat_throttle,
.unthrottle = whiteheat_unthrottle, .unthrottle = whiteheat_unthrottle,
...@@ -767,73 +771,53 @@ static int whiteheat_write_room(struct usb_serial_port *port) ...@@ -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); struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0; 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); firm_get_dtr_rts(port);
if (info->mcr & UART_MCR_DTR) if (info->mcr & UART_MCR_DTR)
modem_signals |= TIOCM_DTR; modem_signals |= TIOCM_DTR;
if (info->mcr & UART_MCR_RTS) if (info->mcr & UART_MCR_RTS)
modem_signals |= TIOCM_RTS; modem_signals |= TIOCM_RTS;
if (copy_to_user((unsigned int *)arg, &modem_signals, sizeof(unsigned int))) return modem_signals;
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;
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: dbg("%s - port %d", __FUNCTION__, port->number);
if (copy_from_user(&modem_signals, (unsigned int *)arg, sizeof(unsigned int)))
return -EFAULT;
if (modem_signals & TIOCM_DTR) if (set & TIOCM_RTS)
info->mcr |= UART_MCR_DTR;
if (modem_signals & TIOCM_RTS)
info->mcr |= UART_MCR_RTS; info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR)
info->mcr |= UART_MCR_DTR;
firm_set_dtr(port, info->mcr & UART_MCR_DTR); if (clear & TIOCM_RTS)
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)
info->mcr &= ~UART_MCR_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_dtr(port, info->mcr & UART_MCR_DTR);
firm_set_rts(port, info->mcr & UART_MCR_RTS); 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: case TIOCGSERIAL:
memset(&serstruct, 0, sizeof(serstruct)); memset(&serstruct, 0, sizeof(serstruct));
serstruct.type = PORT_16654; serstruct.type = PORT_16654;
...@@ -864,10 +848,10 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un ...@@ -864,10 +848,10 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
break; break;
default: 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