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) ...@@ -1163,8 +1163,6 @@ isdn_timer_funct(ulong dummy)
if (tf & ISDN_TIMER_FAST) { if (tf & ISDN_TIMER_FAST) {
if (tf & ISDN_TIMER_MODEMREAD) if (tf & ISDN_TIMER_MODEMREAD)
isdn_tty_readmodem(); isdn_tty_readmodem();
if (tf & ISDN_TIMER_MODEMPLUS)
isdn_tty_modem_escape();
if (tf & ISDN_TIMER_MODEMXMIT) if (tf & ISDN_TIMER_MODEMXMIT)
isdn_tty_modem_xmit(); isdn_tty_modem_xmit();
} }
...@@ -1983,7 +1981,7 @@ isdn_get_free_slot(int usage, int l2_proto, int l3_proto, ...@@ -1983,7 +1981,7 @@ isdn_get_free_slot(int usage, int l2_proto, int l3_proto,
for (i = 0; i < ISDN_MAX_CHANNELS; i++) { for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
slot = &slots[i]; slot = &slots[i];
if (drivers[slot->di]->fi.state != ST_DRV_RUNNING) if (!slot->drv || slot->drv->fi.state != ST_DRV_RUNNING)
continue; continue;
if (!USG_NONE(slots[i].usage)) if (!USG_NONE(slots[i].usage))
......
...@@ -26,7 +26,9 @@ ...@@ -26,7 +26,9 @@
/* Prototypes */ /* Prototypes */
static int isdn_tty_edit_at(const char *, int, modem_info *, int); 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_modem_reset_regs(modem_info *, int);
static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_cmd_ATA(modem_info *);
static void isdn_tty_flush_buffer(struct tty_struct *); 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 ...@@ -1228,13 +1230,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
|| (info->vonline & 3) || (info->vonline & 3)
#endif #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 (from_user) {
if (copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c)) { if (copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c)) {
total = -EFAULT; total = -EFAULT;
...@@ -1242,6 +1237,10 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co ...@@ -1242,6 +1237,10 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
} }
} else } else
memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); 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 #ifdef CONFIG_ISDN_AUDIO
if (info->vonline) { if (info->vonline) {
int cc = isdn_tty_handleDLEdown(info, m, c); int cc = isdn_tty_handleDLEdown(info, m, c);
...@@ -2131,6 +2130,9 @@ isdn_tty_init(void) ...@@ -2131,6 +2130,9 @@ isdn_tty_init(void)
init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->close_wait);
info->isdn_slot = NULL; 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); skb_queue_head_init(&info->rpqueue);
info->xmit_size = ISDN_SERIAL_XMIT_SIZE; info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
skb_queue_head_init(&info->xmit_queue); skb_queue_head_init(&info->xmit_queue);
...@@ -2595,55 +2597,56 @@ isdn_tty_off_hook(void) ...@@ -2595,55 +2597,56 @@ isdn_tty_off_hook(void)
#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */ #define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
#define PLUSWAIT2 (HZ*3/2) /* 1.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 * Check Buffer for Modem-escape-sequence, activate timer-callback to
* isdn_tty_modem_escape() if sequence found. * 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 static void isdn_tty_check_esc(struct modem_info *info,
isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, const unsigned char *p, int count)
int *lastplus, int from_user)
{ {
char cbuf[3]; unsigned char plus = info->emu.mdmreg[REG_ESC];
if (plus > 127) if (plus > 127)
return; return;
if (count > 3) { if (count > 3) {
p += count - 3; p += count - 3;
count = 3; count = 3;
*pluscount = 0; info->emu.pluscount = 0;
info->emu.lastplus = jiffies;
} }
if (from_user) { for (; count > 0; info->emu.lastplus = jiffies, count--) {
if (copy_from_user(cbuf, p, count)) if (*(p++) != plus) {
return; info->emu.pluscount = 0;
p = cbuf; continue;
} }
while (count > 0) { if (info->emu.pluscount == 0) {
if (*(p++) == plus) { if (time_after(jiffies, info->emu.lastplus + PLUSWAIT2))
if ((*pluscount)++) { info->emu.pluscount = 1;
/* Time since last '+' > 0.5 sec. ? */
if (time_after(jiffies, *lastplus + PLUSWAIT1))
*pluscount = 1;
} else { } else {
/* Time since last non-'+' < 1.5 sec. ? */ if (time_after(jiffies, info->emu.lastplus + PLUSWAIT1))
if (time_before(jiffies, *lastplus + PLUSWAIT2)) info->emu.pluscount = 1;
*pluscount = 0; else
} info->emu.pluscount++;
if ((*pluscount == 3) && (count == 1)) }
isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
if (*pluscount > 3)
*pluscount = 1;
} else
*pluscount = 0;
*lastplus = jiffies;
count--;
} }
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) ...@@ -3977,36 +3980,6 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
return total; 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. * 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 * This function is called every second via timer-interrupt from within
......
...@@ -98,7 +98,6 @@ ...@@ -98,7 +98,6 @@
((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
(info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2)) (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_modem_ring(void);
extern void isdn_tty_carrier_timeout(void); extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void); extern void isdn_tty_modem_xmit(void);
......
...@@ -242,12 +242,10 @@ typedef struct { ...@@ -242,12 +242,10 @@ typedef struct {
#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */ #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_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
#define ISDN_TIMER_MODEMREAD 1 #define ISDN_TIMER_MODEMREAD 1
#define ISDN_TIMER_MODEMPLUS 2
#define ISDN_TIMER_MODEMRING 4 #define ISDN_TIMER_MODEMRING 4
#define ISDN_TIMER_MODEMXMIT 8 #define ISDN_TIMER_MODEMXMIT 8
#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ #define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ #define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMXMIT)
ISDN_TIMER_MODEMXMIT)
#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_CARRIER) #define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_CARRIER)
/* GLOBAL_FLAGS */ /* GLOBAL_FLAGS */
...@@ -363,6 +361,7 @@ typedef struct modem_info { ...@@ -363,6 +361,7 @@ typedef struct modem_info {
#endif #endif
struct tty_struct *tty; /* Pointer to corresponding tty */ struct tty_struct *tty; /* Pointer to corresponding tty */
atemu emu; /* AT-emulator data */ atemu emu; /* AT-emulator data */
struct timer_list escape_timer; /* to recognize +++ escape */
struct termios normal_termios; /* For saving termios structs */ struct termios normal_termios; /* For saving termios structs */
struct termios callout_termios; struct termios callout_termios;
wait_queue_head_t open_wait, close_wait; 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