Commit 91267c94 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: New timer handling for "+++" escape sequence

Instead of having one common timer and walking the list of
all ISDN channels, which might be possibly associated with a
ttyI and even more possibly so waiting for the silence period
after "+++", just use a per ttyI timer, which only gets activated
when necessary.
parent b6b5803f
......@@ -1163,8 +1163,6 @@ isdn_timer_funct(ulong dummy)
if (tf & ISDN_TIMER_FAST) {
if (tf & ISDN_TIMER_MODEMREAD)
isdn_tty_readmodem();
if (tf & ISDN_TIMER_MODEMPLUS)
isdn_tty_modem_escape();
if (tf & ISDN_TIMER_MODEMXMIT)
isdn_tty_modem_xmit();
}
......@@ -1983,7 +1981,7 @@ isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
slot = &slots[i];
if (drivers[slot->di]->fi.state != ST_DRV_RUNNING)
if (!slot->drv || slot->drv->fi.state != ST_DRV_RUNNING)
continue;
if (!USG_NONE(slots[i].usage))
......
......@@ -26,7 +26,9 @@
/* Prototypes */
static int isdn_tty_edit_at(const char *, int, modem_info *, int);
static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
static void isdn_tty_escape_timer(unsigned long data);
static void isdn_tty_check_esc(struct modem_info *info,
const unsigned char *p, int count);
static void isdn_tty_modem_reset_regs(modem_info *, int);
static void isdn_tty_cmd_ATA(modem_info *);
static void isdn_tty_flush_buffer(struct tty_struct *);
......@@ -1228,13 +1230,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
|| (info->vonline & 3)
#endif
) {
#ifdef CONFIG_ISDN_AUDIO
if (!info->vonline)
#endif
isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
&(m->pluscount),
&(m->lastplus),
from_user);
if (from_user) {
if (copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c)) {
total = -EFAULT;
......@@ -1242,6 +1237,10 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
}
} else
memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
#ifdef CONFIG_ISDN_AUDIO
if (!info->vonline)
#endif
isdn_tty_check_esc(info, &info->xmit_buf[info->xmit_count], c);
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline) {
int cc = isdn_tty_handleDLEdown(info, m, c);
......@@ -2131,6 +2130,9 @@ isdn_tty_init(void)
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->isdn_slot = NULL;
init_timer(&info->escape_timer);
info->escape_timer.data = (unsigned long) info;
info->escape_timer.function = isdn_tty_escape_timer;
skb_queue_head_init(&info->rpqueue);
info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
skb_queue_head_init(&info->xmit_queue);
......@@ -2595,55 +2597,56 @@ isdn_tty_off_hook(void)
#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
#define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */
static void
isdn_tty_escape_timer(unsigned long data)
{
struct modem_info *info = (struct modem_info *) data;
if (!info->online)
return;
info->emu.pluscount = 0;
info->online = 0;
isdn_tty_modem_result(RESULT_OK, info);
}
/*
* Check Buffer for Modem-escape-sequence, activate timer-callback to
* isdn_tty_modem_escape() if sequence found.
*
* Parameters:
* p pointer to databuffer
* plus escape-character
* count length of buffer
* pluscount count of valid escape-characters so far
* lastplus timestamp of last character
*/
static void
isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
int *lastplus, int from_user)
static void isdn_tty_check_esc(struct modem_info *info,
const unsigned char *p, int count)
{
char cbuf[3];
unsigned char plus = info->emu.mdmreg[REG_ESC];
if (plus > 127)
return;
if (count > 3) {
p += count - 3;
count = 3;
*pluscount = 0;
info->emu.pluscount = 0;
info->emu.lastplus = jiffies;
}
if (from_user) {
if (copy_from_user(cbuf, p, count))
return;
p = cbuf;
}
while (count > 0) {
if (*(p++) == plus) {
if ((*pluscount)++) {
/* Time since last '+' > 0.5 sec. ? */
if (time_after(jiffies, *lastplus + PLUSWAIT1))
*pluscount = 1;
for (; count > 0; info->emu.lastplus = jiffies, count--) {
if (*(p++) != plus) {
info->emu.pluscount = 0;
continue;
}
if (info->emu.pluscount == 0) {
if (time_after(jiffies, info->emu.lastplus + PLUSWAIT2))
info->emu.pluscount = 1;
} else {
/* Time since last non-'+' < 1.5 sec. ? */
if (time_before(jiffies, *lastplus + PLUSWAIT2))
*pluscount = 0;
}
if ((*pluscount == 3) && (count == 1))
isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
if (*pluscount > 3)
*pluscount = 1;
} else
*pluscount = 0;
*lastplus = jiffies;
count--;
if (time_after(jiffies, info->emu.lastplus + PLUSWAIT1))
info->emu.pluscount = 1;
else
info->emu.pluscount++;
}
}
if (info->emu.pluscount == 3)
mod_timer(&info->escape_timer, jiffies + PLUSWAIT2);
else
del_timer(&info->escape_timer);
}
/*
......@@ -3977,36 +3980,6 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
return total;
}
/*
* Switch all modem-channels who are online and got a valid
* escape-sequence 1.5 seconds ago, to command-mode.
* This function is called every second via timer-interrupt from within
* timer-dispatcher isdn_timer_function()
*/
void
isdn_tty_modem_escape(void)
{
int ton = 0;
int i;
int midx;
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (USG_MODEM(isdn_slot_usage(i)))
if ((midx = isdn_slot_m_idx(i)) >= 0) {
modem_info *info = &isdn_mdm.info[midx];
if (info->online) {
ton = 1;
if ((info->emu.pluscount == 3) &&
time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) {
info->emu.pluscount = 0;
info->online = 0;
isdn_tty_modem_result(RESULT_OK, info);
}
}
}
isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
}
/*
* Put a RING-message to all modem-channels who have the RI-bit set.
* This function is called every second via timer-interrupt from within
......
......@@ -98,7 +98,6 @@
((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
(info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void);
......
......@@ -242,12 +242,10 @@ typedef struct {
#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */
#define ISDN_TIMER_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
#define ISDN_TIMER_MODEMREAD 1
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_CARRIER)
/* GLOBAL_FLAGS */
......@@ -363,6 +361,7 @@ typedef struct modem_info {
#endif
struct tty_struct *tty; /* Pointer to corresponding tty */
atemu emu; /* AT-emulator data */
struct timer_list escape_timer; /* to recognize +++ escape */
struct termios normal_termios; /* For saving termios structs */
struct termios callout_termios;
wait_queue_head_t open_wait, close_wait;
......
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