1ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/* 2ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * interface to user space for the gigaset driver 3ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * 4ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Copyright (c) 2004 by Hansjoerg Lipp <hjlipp@web.de> 5ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * 6ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * ===================================================================== 7ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * This program is free software; you can redistribute it and/or 8ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * modify it under the terms of the GNU General Public License as 9ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * published by the Free Software Foundation; either version 2 of 10ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * the License, or (at your option) any later version. 11ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * ===================================================================== 12ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp */ 13ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 14ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp#include "gigaset.h" 15ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp#include <linux/gigaset_dev.h> 16ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp#include <linux/tty_flip.h> 1707a97fe8864a38cedd24a2c8c89cce8c3efd6095Paul Gortmaker#include <linux/module.h> 18ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 19ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/*** our ioctls ***/ 20ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 21ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_lock(struct cardstate *cs, int *arg) 22ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 23ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int cmd = *arg; 24ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 25784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); 26ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 27ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (cmd > 1) 28ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -EINVAL; 29ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 30ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (cmd < 0) { 319d4bee2b9de9e30057a860d2d6794f874caffc5eTilman Schmidt *arg = cs->mstate == MS_LOCKED; 32ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 33ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 34ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 359d4bee2b9de9e30057a860d2d6794f874caffc5eTilman Schmidt if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { 36475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); 37ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->baud_rate(cs, B115200); 38ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->set_line_ctrl(cs, CS8); 39475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->control_state = TIOCM_DTR | TIOCM_RTS; 40ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 41ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 42ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->waiting = 1; 43ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, 44784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt NULL, cmd, NULL)) { 45ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->waiting = 0; 46ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -ENOMEM; 47ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 48ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp gigaset_schedule_event(cs); 49ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 50ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp wait_event(cs->waitqueue, !cs->waiting); 51ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 52ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (cs->cmd_result >= 0) { 53ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp *arg = cs->cmd_result; 54ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 55ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 56ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 57ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return cs->cmd_result; 58ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 59ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 60ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_version(struct cardstate *cs, unsigned arg[4]) 61ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 62ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp static const unsigned version[4] = GIG_VERSION; 63ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp static const unsigned compat[4] = GIG_COMPAT; 64ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned cmd = arg[0]; 65ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 66784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); 67ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 68ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp switch (cmd) { 69ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGVER_DRIVER: 70ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp memcpy(arg, version, sizeof version); 71ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 72ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGVER_COMPAT: 73ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp memcpy(arg, compat, sizeof compat); 74ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 75ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGVER_FWBASE: 76ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->waiting = 1; 77ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, 78784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt NULL, 0, arg)) { 79ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->waiting = 0; 80ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -ENOMEM; 81ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 82ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp gigaset_schedule_event(cs); 83ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 84ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp wait_event(cs->waitqueue, !cs->waiting); 85ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 86ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (cs->cmd_result >= 0) 87ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 88ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 89ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return cs->cmd_result; 90ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp default: 91ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -EINVAL; 92ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 93ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 94ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 95ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_config(struct cardstate *cs, int *arg) 96ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 97784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); 98ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 99ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (*arg != 1) 100ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -EINVAL; 101ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 1029d4bee2b9de9e30057a860d2d6794f874caffc5eTilman Schmidt if (cs->mstate != MS_LOCKED) 103ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -EBUSY; 104ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 10569049cc87dccb1e6fb54aa25c63033efac805dbdTilman Schmidt if (!cs->connected) { 106c8770dcabd6a615b155c25dc4d57251d3e7f151cTilman Schmidt pr_err("%s: not connected\n", __func__); 10769049cc87dccb1e6fb54aa25c63033efac805dbdTilman Schmidt return -ENODEV; 10869049cc87dccb1e6fb54aa25c63033efac805dbdTilman Schmidt } 10969049cc87dccb1e6fb54aa25c63033efac805dbdTilman Schmidt 110ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp *arg = 0; 111ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return gigaset_enterconfigmode(cs); 112ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 113ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 114ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/*** the terminal driver ***/ 115ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/* stolen from usbserial and some other tty drivers */ 116ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 117ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_open(struct tty_struct *tty, struct file *filp); 118ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_close(struct tty_struct *tty, struct file *filp); 1196caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxstatic int if_ioctl(struct tty_struct *tty, 120784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt unsigned int cmd, unsigned long arg); 121ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_write_room(struct tty_struct *tty); 122ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_chars_in_buffer(struct tty_struct *tty); 123ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_throttle(struct tty_struct *tty); 124ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_unthrottle(struct tty_struct *tty); 125606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic void if_set_termios(struct tty_struct *tty, struct ktermios *old); 12660b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int if_tiocmget(struct tty_struct *tty); 12720b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int if_tiocmset(struct tty_struct *tty, 128784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt unsigned int set, unsigned int clear); 129ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_write(struct tty_struct *tty, 130784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt const unsigned char *buf, int count); 131ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 132b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dikestatic const struct tty_operations if_ops = { 133ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .open = if_open, 134ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .close = if_close, 135ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .ioctl = if_ioctl, 136ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .write = if_write, 137ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .write_room = if_write_room, 138ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .chars_in_buffer = if_chars_in_buffer, 139ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .set_termios = if_set_termios, 140ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .throttle = if_throttle, 141ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .unthrottle = if_unthrottle, 142ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .tiocmget = if_tiocmget, 143ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp .tiocmset = if_tiocmset, 144ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp}; 145ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 146ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_open(struct tty_struct *tty, struct file *filp) 147ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 148ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp struct cardstate *cs; 149ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 150784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%d+%d: %s()", 151784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt tty->driver->minor_start, tty->index, __func__); 152ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 153ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs = gigaset_get_cs_by_tty(tty); 154e468c04894f36045cf93d1384183a461014b6840Tilman Schmidt if (!cs || !try_module_get(cs->driver->owner)) 155ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return -ENODEV; 156ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 1572f9381e98471837b631743270de988e78aad1f96Pavel Shved if (mutex_lock_interruptible(&cs->mutex)) { 1582f9381e98471837b631743270de988e78aad1f96Pavel Shved module_put(cs->driver->owner); 159d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 1602f9381e98471837b631743270de988e78aad1f96Pavel Shved } 161ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty->driver_data = cs; 162ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 16348a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby ++cs->port.count; 164ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 16548a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby if (cs->port.count == 1) { 16648a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_port_tty_set(&cs->port, tty); 167d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt tty->low_latency = 1; 168ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 169ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 170abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 171ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return 0; 172ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 173ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 174ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_close(struct tty_struct *tty, struct file *filp) 175ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 176fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 177ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 178fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby if (!cs) { /* happens if we didn't find cs in open */ 179ef37ea34cac19ef46173b26ee47a102f3b987d1eTilman Schmidt gig_dbg(DEBUG_IF, "%s: no cardstate", __func__); 180ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return; 181ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 182ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 183784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 184ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 185abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_lock(&cs->mutex); 186ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 18751370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) 18851370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ 18948a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby else if (!cs->port.count) 1905002779d37b261271da9883e06c14b097d4781c4Tilman Schmidt dev_warn(cs->dev, "%s: device not opened\n", __func__); 19148a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby else if (!--cs->port.count) 19248a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_port_tty_set(&cs->port, NULL); 193ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 194abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 195e468c04894f36045cf93d1384183a461014b6840Tilman Schmidt 196e468c04894f36045cf93d1384183a461014b6840Tilman Schmidt module_put(cs->driver->owner); 197ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 198ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 1996caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxstatic int if_ioctl(struct tty_struct *tty, 200784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt unsigned int cmd, unsigned long arg) 201ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 202fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 203ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int retval = -ENODEV; 204ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int int_arg; 205ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned char buf[6]; 206ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned version[4]; 207ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 208784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); 209ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 210abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt if (mutex_lock_interruptible(&cs->mutex)) 211d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 212ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 21351370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) { 21451370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 21551370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt retval = -ENODEV; 216fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby } else { 217ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = 0; 218ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp switch (cmd) { 219ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGASET_REDIR: 220ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = get_user(int_arg, (int __user *) arg); 221ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 222ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = if_lock(cs, &int_arg); 223ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 224ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = put_user(int_arg, (int __user *) arg); 225ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp break; 226ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGASET_CONFIG: 227ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = get_user(int_arg, (int __user *) arg); 228ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 229ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = if_config(cs, &int_arg); 230ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 231ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = put_user(int_arg, (int __user *) arg); 232ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp break; 233ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGASET_BRKCHARS: 234ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = copy_from_user(&buf, 235475be4d85a274d0961593db41cf85689db1d583cJoe Perches (const unsigned char __user *) arg, 6) 236784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt ? -EFAULT : 0; 23701371500b245ae63f542d74140a3d8ccb74d0318Tilman Schmidt if (retval >= 0) { 23801371500b245ae63f542d74140a3d8ccb74d0318Tilman Schmidt gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", 239475be4d85a274d0961593db41cf85689db1d583cJoe Perches 6, (const unsigned char *) arg); 240ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = cs->ops->brkchars(cs, buf); 24101371500b245ae63f542d74140a3d8ccb74d0318Tilman Schmidt } 242ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp break; 243ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp case GIGASET_VERSION: 244917f5085ddb3498033551e711fb22f48ddeb8378Tilman Schmidt retval = copy_from_user(version, 245475be4d85a274d0961593db41cf85689db1d583cJoe Perches (unsigned __user *) arg, sizeof version) 246784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt ? -EFAULT : 0; 247ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 248ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = if_version(cs, version); 249ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (retval >= 0) 250917f5085ddb3498033551e711fb22f48ddeb8378Tilman Schmidt retval = copy_to_user((unsigned __user *) arg, 251784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt version, sizeof version) 252784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt ? -EFAULT : 0; 253ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp break; 254784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt default: 2551528b18f7ec2b907711f37667c68e10d9296c882Tilman Schmidt gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", 256784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt __func__, cmd); 257ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = -ENOIOCTLCMD; 258ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 259ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 260ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 261abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 262ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 263ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 264ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 265ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 26660b33c133ca0b7c0b6072c87234b63fee6e80558Alan Coxstatic int if_tiocmget(struct tty_struct *tty) 267ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 268fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 269ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int retval; 270ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 271784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 272ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 273abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt if (mutex_lock_interruptible(&cs->mutex)) 274d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 275ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 276475be4d85a274d0961593db41cf85689db1d583cJoe Perches retval = cs->control_state & (TIOCM_RTS | TIOCM_DTR); 277ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 278abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 279ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 280ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 281ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 282ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 28320b9d17715017ae4dd4ec87fabc36d33b9de708eAlan Coxstatic int if_tiocmset(struct tty_struct *tty, 284784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt unsigned int set, unsigned int clear) 285ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 286fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 287ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int retval; 288ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned mc; 289ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 290784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", 291784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt cs->minor_index, __func__, set, clear); 292ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 293abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt if (mutex_lock_interruptible(&cs->mutex)) 294d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 295ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 29669049cc87dccb1e6fb54aa25c63033efac805dbdTilman Schmidt if (!cs->connected) { 29751370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 298ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = -ENODEV; 299ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } else { 300475be4d85a274d0961593db41cf85689db1d583cJoe Perches mc = (cs->control_state | set) & ~clear & (TIOCM_RTS | TIOCM_DTR); 301ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc); 302ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->control_state = mc; 303ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 304ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 305abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 306ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 307ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 308ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 309ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 310ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_write(struct tty_struct *tty, const unsigned char *buf, int count) 311ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 312fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 313e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt struct cmdbuf_t *cb; 314e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt int retval; 315ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 316784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 317ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 318abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt if (mutex_lock_interruptible(&cs->mutex)) 319d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 320ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 32151370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) { 32251370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 32351370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt retval = -ENODEV; 324e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt goto done; 325e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt } 326e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt if (cs->mstate != MS_LOCKED) { 3275002779d37b261271da9883e06c14b097d4781c4Tilman Schmidt dev_warn(cs->dev, "can't write to unlocked device\n"); 328ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = -EBUSY; 329e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt goto done; 330e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt } 331e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt if (count <= 0) { 332e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt /* nothing to do */ 333e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt retval = 0; 334e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt goto done; 335ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 336ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 337e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL); 338e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt if (!cb) { 339e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt dev_err(cs->dev, "%s: out of memory\n", __func__); 340e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt retval = -ENOMEM; 341e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt goto done; 342e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt } 343ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 344e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt memcpy(cb->buf, buf, count); 345e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt cb->len = count; 346e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt cb->offset = 0; 347e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt cb->next = NULL; 348e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt cb->wake_tasklet = &cs->if_wake_tasklet; 349e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt retval = cs->ops->write_cmd(cs, cb); 350e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidtdone: 351e3628dd176ba3ed329991ef042c29aae60617630Tilman Schmidt mutex_unlock(&cs->mutex); 352ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 353ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 354ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 355ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_write_room(struct tty_struct *tty) 356ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 357fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 358ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int retval = -ENODEV; 359ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 360784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 361ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 362abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt if (mutex_lock_interruptible(&cs->mutex)) 363d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt return -ERESTARTSYS; 364ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 36551370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) { 36651370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 36751370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt retval = -ENODEV; 368fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby } else if (cs->mstate != MS_LOCKED) { 3695002779d37b261271da9883e06c14b097d4781c4Tilman Schmidt dev_warn(cs->dev, "can't write to unlocked device\n"); 3709d4bee2b9de9e30057a860d2d6794f874caffc5eTilman Schmidt retval = -EBUSY; 371ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } else 372ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = cs->ops->write_room(cs); 373ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 374abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 375ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 376ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 377ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 378ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 379ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic int if_chars_in_buffer(struct tty_struct *tty) 380ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 381fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 382a4304f2d5a3823deea894026ec95e43b33912357Tilman Schmidt int retval = 0; 383ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 384784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 385ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 386a4304f2d5a3823deea894026ec95e43b33912357Tilman Schmidt mutex_lock(&cs->mutex); 387ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 388a4304f2d5a3823deea894026ec95e43b33912357Tilman Schmidt if (!cs->connected) 38951370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 390a4304f2d5a3823deea894026ec95e43b33912357Tilman Schmidt else if (cs->mstate != MS_LOCKED) 3915002779d37b261271da9883e06c14b097d4781c4Tilman Schmidt dev_warn(cs->dev, "can't write to unlocked device\n"); 392a4304f2d5a3823deea894026ec95e43b33912357Tilman Schmidt else 393ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp retval = cs->ops->chars_in_buffer(cs); 394ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 395abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 396ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 397ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return retval; 398ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 399ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 400ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_throttle(struct tty_struct *tty) 401ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 402fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 403ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 404784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 405ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 406abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_lock(&cs->mutex); 407ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 40851370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) 40951370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ 410d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt else 4111528b18f7ec2b907711f37667c68e10d9296c882Tilman Schmidt gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); 412ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 413abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 414ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 415ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 416ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_unthrottle(struct tty_struct *tty) 417ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 418fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 419ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 420784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 421ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 422abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_lock(&cs->mutex); 423ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 42451370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) 42551370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ 426d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt else 4271528b18f7ec2b907711f37667c68e10d9296c882Tilman Schmidt gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); 428ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 429abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 430ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 431ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 432606d099cdd1080bbb50ea50dc52d98252f8f10a1Alan Coxstatic void if_set_termios(struct tty_struct *tty, struct ktermios *old) 433ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 434fc258f89405f63b379324d1f8388ae4810297997Jiri Slaby struct cardstate *cs = tty->driver_data; 435ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned int iflag; 436ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned int cflag; 437ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned int old_cflag; 438ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp unsigned int control_state, new_state; 439ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 440784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); 441ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 442abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_lock(&cs->mutex); 443ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 44451370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt if (!cs->connected) { 44551370e5b21c5825cff7482e1c38f4e7c5dab3e2bTilman Schmidt gig_dbg(DEBUG_IF, "not connected"); 446ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp goto out; 447ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 448ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 449ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp iflag = tty->termios->c_iflag; 450ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cflag = tty->termios->c_cflag; 451d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt old_cflag = old ? old->c_cflag : cflag; 452784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", 453784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt cs->minor_index, iflag, cflag, old_cflag); 454ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 455ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* get a local copy of the current port settings */ 456ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp control_state = cs->control_state; 457ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 458ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* 459ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Update baud rate. 460ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Do not attempt to cache old rates and skip settings, 461ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * disconnects screw such tricks up completely. 462ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Premature optimization is the root of all evil. 463ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp */ 464ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 465784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt /* reassert DTR and (maybe) RTS on transition from B0 */ 466ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if ((old_cflag & CBAUD) == B0) { 467ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp new_state = control_state | TIOCM_DTR; 468ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* don't set RTS if using hardware flow control */ 469ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!(old_cflag & CRTSCTS)) 470ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp new_state |= TIOCM_RTS; 471784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s", 472784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt cs->minor_index, 473784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt (new_state & TIOCM_RTS) ? " only" : "/RTS"); 474ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->set_modem_ctrl(cs, control_state, new_state); 475ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp control_state = new_state; 476ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 477ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 478ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->baud_rate(cs, cflag & CBAUD); 479ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 480ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if ((cflag & CBAUD) == B0) { 481ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* Drop RTS and DTR */ 482784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); 483ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); 484ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->set_modem_ctrl(cs, control_state, new_state); 485ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp control_state = new_state; 486ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 487ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 488ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* 489ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Update line control register (LCR) 490ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp */ 491ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 492ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->ops->set_line_ctrl(cs, cflag); 493ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 494ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp /* save off the modified port settings */ 495ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp cs->control_state = control_state; 496ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 497ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippout: 498abfd1dc7c18e4be89715071a524324c7b2515565Tilman Schmidt mutex_unlock(&cs->mutex); 499ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 500ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 501ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 502ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/* wakeup tasklet for the write operation */ 503ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippstatic void if_wake(unsigned long data) 504ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 50548a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby struct cardstate *cs = (struct cardstate *)data; 50648a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby struct tty_struct *tty = tty_port_tty_get(&cs->port); 507ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 50848a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby if (tty) { 50948a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_wakeup(tty); 51048a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_kref_put(tty); 51148a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby } 512ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 513ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 514ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/*** interface to common ***/ 515ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 516ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippvoid gigaset_if_init(struct cardstate *cs) 517ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 518ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp struct gigaset_driver *drv; 519ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 520ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp drv = cs->driver; 521ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!drv->have_tty) 522ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return; 523ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 5245452fee23eddb5ebb46f13aba50c8930c160e1daJoe Perches tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); 5257435f50e1261f569c660efb4ae52e8bc21a92cbdTilman Schmidt 5267435f50e1261f569c660efb4ae52e8bc21a92cbdTilman Schmidt mutex_lock(&cs->mutex); 52701107d343076c34b9e1ce5d073292bd7f3097fdaGreg Kroah-Hartman cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); 5283dda4e373c7474cfe280f4270b70c1563f92a2a7Hansjoerg Lipp 52901107d343076c34b9e1ce5d073292bd7f3097fdaGreg Kroah-Hartman if (!IS_ERR(cs->tty_dev)) 53001107d343076c34b9e1ce5d073292bd7f3097fdaGreg Kroah-Hartman dev_set_drvdata(cs->tty_dev, cs); 5313dda4e373c7474cfe280f4270b70c1563f92a2a7Hansjoerg Lipp else { 53242e3d611158faa2d372ccfb1e17bfde13935de68Tilman Schmidt pr_warning("could not register device to the tty subsystem\n"); 53301107d343076c34b9e1ce5d073292bd7f3097fdaGreg Kroah-Hartman cs->tty_dev = NULL; 5343dda4e373c7474cfe280f4270b70c1563f92a2a7Hansjoerg Lipp } 5357435f50e1261f569c660efb4ae52e8bc21a92cbdTilman Schmidt mutex_unlock(&cs->mutex); 536ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 537ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 538ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippvoid gigaset_if_free(struct cardstate *cs) 539ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 540ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp struct gigaset_driver *drv; 541ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 542ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp drv = cs->driver; 543ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!drv->have_tty) 544ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return; 545ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 546ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tasklet_disable(&cs->if_wake_tasklet); 547ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tasklet_kill(&cs->if_wake_tasklet); 54801107d343076c34b9e1ce5d073292bd7f3097fdaGreg Kroah-Hartman cs->tty_dev = NULL; 549ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty_unregister_device(drv->tty, cs->minor_index); 550ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 551ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 5521cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt/** 5531cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * gigaset_if_receive() - pass a received block of data to the tty device 5541cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * @cs: device descriptor structure. 5551cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * @buffer: received data. 5561cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * @len: number of bytes received. 5571cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * 5581cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * Called by asyncdata/isocdata if a block of data received from the 5591cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt * device must be sent to userspace through the ttyG* device. 5601cec9727fbfd7baff2034796154be1a0297bceddTilman Schmidt */ 561ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippvoid gigaset_if_receive(struct cardstate *cs, 562784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt unsigned char *buffer, size_t len) 563ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 56448a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby struct tty_struct *tty = tty_port_tty_get(&cs->port); 565ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 56648a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby if (tty == NULL) { 5671528b18f7ec2b907711f37667c68e10d9296c882Tilman Schmidt gig_dbg(DEBUG_IF, "receive on closed device"); 56848a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby return; 569ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 57048a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby 57148a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_insert_flip_string(tty, buffer, len); 57248a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_flip_buffer_push(tty); 57348a7466f4dd0104d87a6d8dd0f25027be89c8453Jiri Slaby tty_kref_put(tty); 574ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 575ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg LippEXPORT_SYMBOL_GPL(gigaset_if_receive); 576ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 577ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp/* gigaset_if_initdriver 578ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * Initialize tty interface. 579ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp * parameters: 580784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt * drv Driver 581784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt * procname Name of the driver (e.g. for /proc/tty/drivers) 582784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt * devname Name of the device files (prefix without minor number) 583ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp */ 584ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippvoid gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, 585f4eaa37017a5a68f67ef86729508022c13fb8e6dGreg Kroah-Hartman const char *devname) 586ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 587ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp int ret; 588ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp struct tty_driver *tty; 589ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 590ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp drv->have_tty = 0; 591ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 5922f16669d322e05171c9e1cfd94f402f7399bd2a3Jiri Slaby drv->tty = tty = alloc_tty_driver(drv->minors); 593d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt if (tty == NULL) 594ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp goto enomem; 595ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 5965bd49735db39c1c1360cb91b1f1e1c999d90eb94Joe Perches tty->type = TTY_DRIVER_TYPE_SERIAL; 5975bd49735db39c1c1360cb91b1f1e1c999d90eb94Joe Perches tty->subtype = SERIAL_TYPE_NORMAL; 598331b831983f9d706f4a40d08a996d5c2c7a6ea7bGreg Kroah-Hartman tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 599ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 600ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty->driver_name = procname; 601ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty->name = devname; 602ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty->minor_start = drv->minor; 603ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 604d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt tty->init_termios = tty_std_termios; 605d9ba9c9125d89e246dc0a0702446528acceb6ddbTilman Schmidt tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; 606ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty_set_operations(tty, &if_ops); 607ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 608ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp ret = tty_register_driver(tty); 609ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (ret < 0) { 610c8770dcabd6a615b155c25dc4d57251d3e7f151cTilman Schmidt pr_err("error %d registering tty driver\n", ret); 611ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp goto error; 612ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp } 613784d5858aac58c06608def862d73ae9a32f5ee23Tilman Schmidt gig_dbg(DEBUG_IF, "tty driver initialized"); 614ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp drv->have_tty = 1; 615ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return; 616ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 617ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippenomem: 618c8770dcabd6a615b155c25dc4d57251d3e7f151cTilman Schmidt pr_err("out of memory\n"); 619ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipperror: 620ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (drv->tty) 621ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp put_tty_driver(drv->tty); 622ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 623ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 624ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lippvoid gigaset_if_freedriver(struct gigaset_driver *drv) 625ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp{ 626ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp if (!drv->have_tty) 627ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp return; 628ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp 629ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp drv->have_tty = 0; 630ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp tty_unregister_driver(drv->tty); 631ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp put_tty_driver(drv->tty); 632ee8a4b7f857fe7ba243e65c8925798cf8eda5ab0Hansjoerg Lipp} 633