// SPDX-License-Identifier: GPL-2.0 /* * IPWireless 3G PCMCIA Network Driver * * Original code * by Stephen Blackheath <stephen@blacksapphire.com>, * Ben Martel <benm@symmetric.co.nz> * * Copyrighted as follows: * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) * * Various driver changes and rewrites, port to new kernels * Copyright (C) 2006-2007 Jiri Kosina * * Misc code cleanups and updates * Copyright (C) 2007 David Sterba
*/
staticstruct ipw_tty *get_tty(int index)
{ /* * The 'ras_raw' channel is only available when 'loopback' mode * is enabled. * Number of minor starts with 16 (_RANGE * _RAS_RAW).
*/ if (!ipwireless_loopback && index >=
IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) return NULL;
/* Take data received from hardware, and send it out the tty */ void ipwireless_tty_received(struct ipw_tty *tty, unsignedchar *data, unsignedint length)
{ int work = 0;
mutex_lock(&tty->ipw_tty_mutex);
if (!tty->port.count) {
mutex_unlock(&tty->ipw_tty_mutex); return;
}
mutex_unlock(&tty->ipw_tty_mutex);
work = tty_insert_flip_string(&tty->port, data, length);
if (work != length)
printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": %d chars not inserted to flip buffer!\n",
length - work);
mutex_lock(&tty->ipw_tty_mutex); if (!tty->port.count) {
mutex_unlock(&tty->ipw_tty_mutex); return -EINVAL;
}
room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; if (room < 0)
room = 0; /* Don't allow caller to write any more than we have room for */ if (count > room)
count = room;
if (count == 0) {
mutex_unlock(&tty->ipw_tty_mutex); return 0;
}
ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
buf, count,
ipw_write_packet_sent_callback, tty); if (ret < 0) {
mutex_unlock(&tty->ipw_tty_mutex); return 0;
}
staticint get_control_lines(struct ipw_tty *tty)
{ unsignedint my = tty->control_lines; unsignedint out = 0;
if (my & IPW_CONTROL_LINE_RTS)
out |= TIOCM_RTS; if (my & IPW_CONTROL_LINE_DTR)
out |= TIOCM_DTR; if (my & IPW_CONTROL_LINE_CTS)
out |= TIOCM_CTS; if (my & IPW_CONTROL_LINE_DSR)
out |= TIOCM_DSR; if (my & IPW_CONTROL_LINE_DCD)
out |= TIOCM_CD;
/* FIXME: Exactly how is the tty object locked here .. */ if (tty->tty_type == TTYTYPE_MODEM) { switch (cmd) { case PPPIOCGCHAN:
{ int chan = ipwireless_ppp_channel_index(
tty->network);
if (chan < 0) return -ENODEV; if (put_user(chan, (int __user *) arg)) return -EFAULT;
} return 0;
case PPPIOCGUNIT:
{ int unit = ipwireless_ppp_unit_number(
tty->network);
if (unit < 0) return -ENODEV; if (put_user(unit, (int __user *) arg)) return -EFAULT;
} return 0;
if (secondary_channel_idx != -1)
ipwireless_associate_network_tty(network,
secondary_channel_idx,
ttys[j]); /* check if we provide raw device (if loopback is enabled) */ if (get_tty(j))
printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": registering %s device ttyIPWp%d\n",
tty_type_name(tty_type), j);
return 0;
}
struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, struct ipw_network *network)
{ int i, j;
for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) { int allfree = 1;
for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
j += IPWIRELESS_PCMCIA_MINOR_RANGE) if (ttys[j] != NULL) {
allfree = 0; break;
}
if (allfree) {
j = i;
if (add_tty(j, hardware, network,
IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
TTYTYPE_MODEM)) return NULL;
/* * Must be called before ipwireless_network_free().
*/ void ipwireless_tty_free(struct ipw_tty *tty)
{ int j; struct ipw_network *network = ttys[tty->index]->network;
if (ttyj) {
mutex_lock(&ttyj->ipw_tty_mutex); if (get_tty(j))
printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": deregistering %s device ttyIPWp%d\n",
tty_type_name(ttyj->tty_type), j); if (ttyj->port.tty != NULL) {
mutex_unlock(&ttyj->ipw_tty_mutex);
tty_vhangup(ttyj->port.tty); /* FIXME: Exactly how is the tty object locked here
against a parallel ioctl etc */ /* FIXME2: hangup does not mean all processes
* are gone */
mutex_lock(&ttyj->ipw_tty_mutex);
} while (ttyj->port.count)
do_ipw_close(ttyj);
ipwireless_disassociate_network_ttys(network,
ttyj->channel_idx);
tty_unregister_device(ipw_tty_driver, j);
tty_port_destroy(&ttyj->port);
ttys[j] = NULL;
mutex_unlock(&ttyj->ipw_tty_mutex);
kfree(ttyj);
}
}
}
/* * If DCD is de-asserted, we close the tty so pppd can tell that we * have gone offline.
*/ if ((old_control_lines & IPW_CONTROL_LINE_DCD)
&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
&& tty->port.tty) {
tty_hangup(tty->port.tty);
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.