diff options
Diffstat (limited to 'drivers/isdn/gigaset/interface.c')
| -rw-r--r-- | drivers/isdn/gigaset/interface.c | 404 |
1 files changed, 142 insertions, 262 deletions
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index af195b07c19..600c79b030c 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -13,8 +13,8 @@ #include "gigaset.h" #include <linux/gigaset_dev.h> -#include <linux/tty.h> #include <linux/tty_flip.h> +#include <linux/module.h> /*** our ioctls ***/ @@ -33,10 +33,10 @@ static int if_lock(struct cardstate *cs, int *arg) } if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { - cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); + cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); - cs->control_state = TIOCM_DTR|TIOCM_RTS; + cs->control_state = TIOCM_DTR | TIOCM_RTS; } cs->waiting = 1; @@ -45,8 +45,6 @@ static int if_lock(struct cardstate *cs, int *arg) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -81,8 +79,6 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_VER"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -107,7 +103,7 @@ static int if_config(struct cardstate *cs, int *arg) return -EBUSY; if (!cs->connected) { - err("not connected!"); + pr_err("%s: not connected\n", __func__); return -ENODEV; } @@ -116,65 +112,29 @@ static int if_config(struct cardstate *cs, int *arg) } /*** the terminal driver ***/ -/* stolen from usbserial and some other tty drivers */ - -static int if_open(struct tty_struct *tty, struct file *filp); -static void if_close(struct tty_struct *tty, struct file *filp); -static int if_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); -static int if_write_room(struct tty_struct *tty); -static int if_chars_in_buffer(struct tty_struct *tty); -static void if_throttle(struct tty_struct *tty); -static void if_unthrottle(struct tty_struct *tty); -static void if_set_termios(struct tty_struct *tty, struct ktermios *old); -static int if_tiocmget(struct tty_struct *tty, struct file *file); -static int if_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); -static int if_write(struct tty_struct *tty, - const unsigned char *buf, int count); - -static const struct tty_operations if_ops = { - .open = if_open, - .close = if_close, - .ioctl = if_ioctl, - .write = if_write, - .write_room = if_write_room, - .chars_in_buffer = if_chars_in_buffer, - .set_termios = if_set_termios, - .throttle = if_throttle, - .unthrottle = if_unthrottle, -#if 0 - .break_ctl = serial_break, -#endif - .tiocmget = if_tiocmget, - .tiocmset = if_tiocmset, -}; static int if_open(struct tty_struct *tty, struct file *filp) { struct cardstate *cs; - unsigned long flags; gig_dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index, __func__); - tty->driver_data = NULL; - cs = gigaset_get_cs_by_tty(tty); if (!cs || !try_module_get(cs->driver->owner)) return -ENODEV; - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + if (mutex_lock_interruptible(&cs->mutex)) { + module_put(cs->driver->owner); + return -ERESTARTSYS; + } tty->driver_data = cs; - ++cs->open_count; + ++cs->port.count; - if (cs->open_count == 1) { - spin_lock_irqsave(&cs->lock, flags); - cs->tty = tty; - spin_unlock_irqrestore(&cs->lock, flags); - tty->low_latency = 1; //FIXME test + if (cs->port.count == 1) { + tty_port_tty_set(&cs->port, tty); + cs->port.low_latency = 1; } mutex_unlock(&cs->mutex); @@ -183,12 +143,10 @@ static int if_open(struct tty_struct *tty, struct file *filp) static void if_close(struct tty_struct *tty, struct file *filp) { - struct cardstate *cs; - unsigned long flags; + struct cardstate *cs = tty->driver_data; - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); + if (!cs) { /* happens if we didn't find cs in open */ + gig_dbg(DEBUG_IF, "%s: no cardstate", __func__); return; } @@ -196,44 +154,36 @@ static void if_close(struct tty_struct *tty, struct file *filp) mutex_lock(&cs->mutex); - if (!cs->open_count) - warn("%s: device not opened", __func__); - else { - if (!--cs->open_count) { - spin_lock_irqsave(&cs->lock, flags); - cs->tty = NULL; - spin_unlock_irqrestore(&cs->lock, flags); - } - } + if (!cs->connected) + gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ + else if (!cs->port.count) + dev_warn(cs->dev, "%s: device not opened\n", __func__); + else if (!--cs->port.count) + tty_port_tty_set(&cs->port, NULL); mutex_unlock(&cs->mutex); module_put(cs->driver->owner); } -static int if_ioctl(struct tty_struct *tty, struct file *file, +static int if_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - struct cardstate *cs; + struct cardstate *cs = tty->driver_data; int retval = -ENODEV; int int_arg; unsigned char buf[6]; unsigned version[4]; - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } - gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - if (!cs->open_count) - warn("%s: device not opened", __func__); - else { + if (!cs->connected) { + gig_dbg(DEBUG_IF, "not connected"); + retval = -ENODEV; + } else { retval = 0; switch (cmd) { case GIGASET_REDIR: @@ -251,25 +201,18 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, retval = put_user(int_arg, (int __user *) arg); break; case GIGASET_BRKCHARS: - //FIXME test if MS_LOCKED - if (!cs->connected) { - gig_dbg(DEBUG_ANY, - "can't communicate with unplugged device"); - retval = -ENODEV; - break; - } retval = copy_from_user(&buf, - (const unsigned char __user *) arg, 6) + (const unsigned char __user *) arg, 6) ? -EFAULT : 0; if (retval >= 0) { gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", - 6, (const unsigned char *) arg); + 6, (const unsigned char *) arg); retval = cs->ops->brkchars(cs, buf); } break; case GIGASET_VERSION: retval = copy_from_user(version, - (unsigned __user *) arg, sizeof version) + (unsigned __user *) arg, sizeof version) ? -EFAULT : 0; if (retval >= 0) retval = if_version(cs, version); @@ -279,7 +222,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, ? -EFAULT : 0; break; default: - gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", __func__, cmd); retval = -ENOIOCTLCMD; } @@ -290,54 +233,41 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, return retval; } -static int if_tiocmget(struct tty_struct *tty, struct file *file) +static int if_tiocmget(struct tty_struct *tty) { - struct cardstate *cs; + struct cardstate *cs = tty->driver_data; int retval; - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - // FIXME read from device? - retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); + retval = cs->control_state & (TIOCM_RTS | TIOCM_DTR); mutex_unlock(&cs->mutex); return retval; } -static int if_tiocmset(struct tty_struct *tty, struct file *file, +static int if_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { - struct cardstate *cs; + struct cardstate *cs = tty->driver_data; int retval; unsigned mc; - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } - gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", cs->minor_index, __func__, set, clear); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { - gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); + gig_dbg(DEBUG_IF, "not connected"); retval = -ENODEV; } else { - mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR); + mc = (cs->control_state | set) & ~clear & (TIOCM_RTS | TIOCM_DTR); retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc); cs->control_state = mc; } @@ -349,62 +279,65 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct cardstate *cs; - int retval = -ENODEV; - - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } + struct cardstate *cs = tty->driver_data; + struct cmdbuf_t *cb; + int retval; gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - if (!cs->open_count) - warn("%s: device not opened", __func__); - else if (cs->mstate != MS_LOCKED) { - warn("can't write to unlocked device"); + if (!cs->connected) { + gig_dbg(DEBUG_IF, "not connected"); + retval = -ENODEV; + goto done; + } + if (cs->mstate != MS_LOCKED) { + dev_warn(cs->dev, "can't write to unlocked device\n"); retval = -EBUSY; - } else if (!cs->connected) { - gig_dbg(DEBUG_ANY, "can't write to unplugged device"); - retval = -EBUSY; //FIXME - } else { - retval = cs->ops->write_cmd(cs, buf, count, - &cs->if_wake_tasklet); + goto done; + } + if (count <= 0) { + /* nothing to do */ + retval = 0; + goto done; } - mutex_unlock(&cs->mutex); + cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL); + if (!cb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + retval = -ENOMEM; + goto done; + } + memcpy(cb->buf, buf, count); + cb->len = count; + cb->offset = 0; + cb->next = NULL; + cb->wake_tasklet = &cs->if_wake_tasklet; + retval = cs->ops->write_cmd(cs, cb); +done: + mutex_unlock(&cs->mutex); return retval; } static int if_write_room(struct tty_struct *tty) { - struct cardstate *cs; - int retval = -ENODEV; - - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } + struct cardstate *cs = tty->driver_data; + int retval; gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - if (!cs->open_count) - warn("%s: device not opened", __func__); - else if (cs->mstate != MS_LOCKED) { - warn("can't write to unlocked device"); + if (!cs->connected) { + gig_dbg(DEBUG_IF, "not connected"); + retval = -ENODEV; + } else if (cs->mstate != MS_LOCKED) { + dev_warn(cs->dev, "can't write to unlocked device\n"); retval = -EBUSY; - } else if (!cs->connected) { - gig_dbg(DEBUG_ANY, "can't write to unplugged device"); - retval = -EBUSY; //FIXME } else retval = cs->ops->write_room(cs); @@ -415,29 +348,18 @@ static int if_write_room(struct tty_struct *tty) static int if_chars_in_buffer(struct tty_struct *tty) { - struct cardstate *cs; - int retval = -ENODEV; - - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return -ENODEV; - } + struct cardstate *cs = tty->driver_data; + int retval = 0; gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + mutex_lock(&cs->mutex); - if (!cs->open_count) - warn("%s: device not opened", __func__); - else if (cs->mstate != MS_LOCKED) { - warn("can't write to unlocked device"); - retval = -EBUSY; - } else if (!cs->connected) { - gig_dbg(DEBUG_ANY, "can't write to unplugged device"); - retval = -EBUSY; //FIXME - } else + if (!cs->connected) + gig_dbg(DEBUG_IF, "not connected"); + else if (cs->mstate != MS_LOCKED) + dev_warn(cs->dev, "can't write to unlocked device\n"); + else retval = cs->ops->chars_in_buffer(cs); mutex_unlock(&cs->mutex); @@ -447,82 +369,56 @@ static int if_chars_in_buffer(struct tty_struct *tty) static void if_throttle(struct tty_struct *tty) { - struct cardstate *cs; - - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return; - } + struct cardstate *cs = tty->driver_data; gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); mutex_lock(&cs->mutex); - if (!cs->open_count) - warn("%s: device not opened", __func__); - else { - //FIXME - } + if (!cs->connected) + gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ + else + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } static void if_unthrottle(struct tty_struct *tty) { - struct cardstate *cs; - - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return; - } + struct cardstate *cs = tty->driver_data; gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); mutex_lock(&cs->mutex); - if (!cs->open_count) - warn("%s: device not opened", __func__); - else { - //FIXME - } + if (!cs->connected) + gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ + else + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } static void if_set_termios(struct tty_struct *tty, struct ktermios *old) { - struct cardstate *cs; + struct cardstate *cs = tty->driver_data; unsigned int iflag; unsigned int cflag; unsigned int old_cflag; unsigned int control_state, new_state; - cs = (struct cardstate *) tty->driver_data; - if (!cs) { - err("cs==NULL in %s", __func__); - return; - } - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); mutex_lock(&cs->mutex); - if (!cs->open_count) { - warn("%s: device not opened", __func__); - goto out; - } - if (!cs->connected) { - gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); + gig_dbg(DEBUG_IF, "not connected"); goto out; } - // stolen from mct_u232.c - iflag = tty->termios->c_iflag; - cflag = tty->termios->c_cflag; - old_cflag = old ? old->c_cflag : cflag; //FIXME? + iflag = tty->termios.c_iflag; + cflag = tty->termios.c_cflag; + old_cflag = old ? old->c_cflag : cflag; gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, iflag, cflag, old_cflag); @@ -565,29 +461,6 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) cs->ops->set_line_ctrl(cs, cflag); -#if 0 - //FIXME this hangs M101 [ts 2005-03-09] - //FIXME do we need this? - /* - * Set flow control: well, I do not really now how to handle DTR/RTS. - * Just do what we have seen with SniffUSB on Win98. - */ - /* Drop DTR/RTS if no flow control otherwise assert */ - gig_dbg(DEBUG_IF, "%u: control_state %x", - cs->minor_index, control_state); - new_state = control_state; - if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) - new_state |= TIOCM_DTR | TIOCM_RTS; - else - new_state &= ~(TIOCM_DTR | TIOCM_RTS); - if (new_state != control_state) { - gig_dbg(DEBUG_IF, "%u: new_state %x", - cs->minor_index, new_state); - gigaset_set_modem_ctrl(cs, control_state, new_state); - control_state = new_state; - } -#endif - /* save off the modified port settings */ cs->control_state = control_state; @@ -595,14 +468,27 @@ out: mutex_unlock(&cs->mutex); } +static const struct tty_operations if_ops = { + .open = if_open, + .close = if_close, + .ioctl = if_ioctl, + .write = if_write, + .write_room = if_write_room, + .chars_in_buffer = if_chars_in_buffer, + .set_termios = if_set_termios, + .throttle = if_throttle, + .unthrottle = if_unthrottle, + .tiocmget = if_tiocmget, + .tiocmset = if_tiocmset, +}; + /* wakeup tasklet for the write operation */ static void if_wake(unsigned long data) { - struct cardstate *cs = (struct cardstate *) data; + struct cardstate *cs = (struct cardstate *)data; - if (cs->tty) - tty_wakeup(cs->tty); + tty_port_tty_wakeup(&cs->port); } /*** interface to common ***/ @@ -615,15 +501,16 @@ void gigaset_if_init(struct cardstate *cs) if (!drv->have_tty) return; - tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); + tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); mutex_lock(&cs->mutex); - cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); + cs->tty_dev = tty_port_register_device(&cs->port, drv->tty, + cs->minor_index, NULL); if (!IS_ERR(cs->tty_dev)) dev_set_drvdata(cs->tty_dev, cs); else { - warn("could not register device to the tty subsystem"); + pr_warning("could not register device to the tty subsystem\n"); cs->tty_dev = NULL; } mutex_unlock(&cs->mutex); @@ -643,21 +530,20 @@ void gigaset_if_free(struct cardstate *cs) tty_unregister_device(drv->tty, cs->minor_index); } +/** + * gigaset_if_receive() - pass a received block of data to the tty device + * @cs: device descriptor structure. + * @buffer: received data. + * @len: number of bytes received. + * + * Called by asyncdata/isocdata if a block of data received from the + * device must be sent to userspace through the ttyG* device. + */ void gigaset_if_receive(struct cardstate *cs, unsigned char *buffer, size_t len) { - unsigned long flags; - struct tty_struct *tty; - - spin_lock_irqsave(&cs->lock, flags); - if ((tty = cs->tty) == NULL) - gig_dbg(DEBUG_ANY, "receive on closed device"); - else { - tty_buffer_request_room(tty, len); - tty_insert_flip_string(tty, buffer, len); - tty_flip_buffer_push(tty); - } - spin_unlock_irqrestore(&cs->lock, flags); + tty_insert_flip_string(&cs->port, buffer, len); + tty_flip_buffer_push(&cs->port); } EXPORT_SYMBOL_GPL(gigaset_if_receive); @@ -671,36 +557,30 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive); void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, const char *devname) { - unsigned minors = drv->minors; int ret; struct tty_driver *tty; drv->have_tty = 0; - if ((drv->tty = alloc_tty_driver(minors)) == NULL) + drv->tty = tty = alloc_tty_driver(drv->minors); + if (tty == NULL) goto enomem; - tty = drv->tty; - tty->magic = TTY_DRIVER_MAGIC, - tty->major = GIG_MAJOR, - tty->type = TTY_DRIVER_TYPE_SERIAL, - tty->subtype = SERIAL_TYPE_NORMAL, + tty->type = TTY_DRIVER_TYPE_SERIAL; + tty->subtype = SERIAL_TYPE_NORMAL; tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty->driver_name = procname; tty->name = devname; tty->minor_start = drv->minor; - tty->num = drv->minors; - - tty->owner = THIS_MODULE; - tty->init_termios = tty_std_termios; //FIXME - tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME + tty->init_termios = tty_std_termios; + tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(tty, &if_ops); ret = tty_register_driver(tty); if (ret < 0) { - warn("failed to register tty driver (error %d)", ret); + pr_err("error %d registering tty driver\n", ret); goto error; } gig_dbg(DEBUG_IF, "tty driver initialized"); @@ -708,7 +588,7 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, return; enomem: - warn("could not allocate tty structures"); + pr_err("out of memory\n"); error: if (drv->tty) put_tty_driver(drv->tty); |
