This source file includes following definitions.
- isdn_tty_try_read
- isdn_tty_readmodem
- isdn_tty_dial
- isdn_tty_modem_hup
- isdn_tty_paranoia_check
- isdn_tty_change_speed
- isdn_tty_startup
- isdn_tty_shutdown
- isdn_tty_write
- isdn_tty_write_room
- isdn_tty_chars_in_buffer
- isdn_tty_flush_buffer
- isdn_tty_flush_chars
- isdn_tty_throttle
- isdn_tty_unthrottle
- isdn_tty_get_lsr_info
- isdn_tty_get_modem_info
- isdn_tty_set_modem_info
- isdn_tty_ioctl
- isdn_tty_set_termios
- isdn_tty_block_til_ready
- isdn_tty_open
- isdn_tty_close
- isdn_tty_hangup
- isdn_tty_reset_profile
- isdn_tty_modem_reset_regs
- modem_write_profile
- isdn_tty_modem_init
- isdn_tty_find_icall
- isdn_tty_at_cout
- isdn_tty_on_hook
- isdn_tty_off_hook
- isdn_tty_check_esc
- isdn_tty_modem_result
- isdn_tty_show_profile
- isdn_tty_get_msnstr
- isdn_tty_getdial
- isdn_tty_parse_at
- isdn_tty_edit_at
- isdn_tty_modem_escape
- isdn_tty_modem_ring
- isdn_tty_modem_xmit
- isdn_tty_bsent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #define __NO_VERSION__
35 #include <linux/module.h>
36 #include <linux/isdn.h>
37 #include "isdn_common.h"
38 #include "isdn_tty.h"
39
40
41
42 static int isdn_tty_edit_at(const char *, int, modem_info *, int);
43 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
44 static void isdn_tty_modem_reset_regs(atemu *, int);
45
46
47 #define MODEM_PARANOIA_CHECK
48 #define MODEM_DO_RESTART
49
50 static char *isdn_ttyname_ttyI = "ttyI";
51 static char *isdn_ttyname_cui = "cui";
52 char *isdn_tty_revision = "$Revision: 1.3 $";
53
54 int isdn_tty_try_read(int i, u_char * buf, int len)
55 {
56 int c;
57 struct tty_struct *tty;
58
59 if (i < 0)
60 return 0;
61 if (dev->mdm.online[i]) {
62 if ((tty = dev->mdm.info[i].tty)) {
63 if (dev->mdm.info[i].MCR & UART_MCR_RTS) {
64 c = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
65 if (c >= len) {
66 if (len > 1) {
67 memcpy(tty->flip.char_buf_ptr, buf, len);
68 tty->flip.count += len;
69 memset(tty->flip.flag_buf_ptr, 0, len);
70 if (dev->mdm.atmodem[i].mdmreg[12] & 128)
71 tty->flip.flag_buf_ptr[len - 1] = 0xff;
72 tty->flip.flag_buf_ptr += len;
73 tty->flip.char_buf_ptr += len;
74 } else
75 tty_insert_flip_char(tty, buf[0], 0);
76 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
77 return 1;
78 }
79 }
80 }
81 }
82 return 0;
83 }
84
85 void isdn_tty_readmodem(void)
86 {
87 int resched = 0;
88 int midx;
89 int i;
90 int c;
91 int r;
92 ulong flags;
93 struct tty_struct *tty;
94 modem_info *info;
95
96 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
97 if ((midx = dev->m_idx[i]) >= 0)
98 if (dev->mdm.online[midx]) {
99 save_flags(flags);
100 cli();
101 r = 0;
102 info = &dev->mdm.info[midx];
103 if ((tty = info->tty)) {
104 if (info->MCR & UART_MCR_RTS) {
105 c = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
106 if (c > 0) {
107 r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
108 tty->flip.char_buf_ptr,
109 tty->flip.flag_buf_ptr, c, 0);
110 if (!(dev->mdm.atmodem[midx].mdmreg[12] & 128))
111 memset(tty->flip.flag_buf_ptr, 0, r);
112 tty->flip.count += r;
113 tty->flip.flag_buf_ptr += r;
114 tty->flip.char_buf_ptr += r;
115 if (r)
116 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
117 }
118 } else
119 r = 1;
120 } else
121 r = 1;
122 restore_flags(flags);
123 if (r) {
124 dev->mdm.rcvsched[midx] = 0;
125 resched = 1;
126 } else
127 dev->mdm.rcvsched[midx] = 1;
128 }
129 }
130 if (!resched)
131 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
132 }
133
134
135
136
137
138
139
140
141
142 static void isdn_tty_dial(char *n, modem_info * info, atemu * m)
143 {
144 isdn_ctrl cmd;
145 ulong flags;
146 int i;
147
148 save_flags(flags);
149 cli();
150 i = isdn_get_free_channel(ISDN_USAGE_MODEM, m->mdmreg[14], m->mdmreg[15], -1, -1);
151 if (i < 0) {
152 restore_flags(flags);
153 isdn_tty_modem_result(6, info);
154 } else {
155 if (strlen(m->msn)) {
156 info->isdn_driver = dev->drvmap[i];
157 info->isdn_channel = dev->chanmap[i];
158 info->drv_index = i;
159 dev->m_idx[i] = info->line;
160 dev->usage[i] |= ISDN_USAGE_OUTGOING;
161 isdn_info_update();
162 restore_flags(flags);
163 cmd.driver = info->isdn_driver;
164 cmd.arg = info->isdn_channel;
165 cmd.command = ISDN_CMD_CLREAZ;
166 dev->drv[info->isdn_driver]->interface->command(&cmd);
167 strcpy(cmd.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
168 cmd.driver = info->isdn_driver;
169 cmd.command = ISDN_CMD_SETEAZ;
170 dev->drv[info->isdn_driver]->interface->command(&cmd);
171 cmd.driver = info->isdn_driver;
172 cmd.command = ISDN_CMD_SETL2;
173 cmd.arg = info->isdn_channel + (m->mdmreg[14] << 8);
174 dev->drv[info->isdn_driver]->interface->command(&cmd);
175 cmd.driver = info->isdn_driver;
176 cmd.command = ISDN_CMD_SETL3;
177 cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
178 dev->drv[info->isdn_driver]->interface->command(&cmd);
179 cmd.driver = info->isdn_driver;
180 cmd.arg = info->isdn_channel;
181 sprintf(cmd.num, "%s,%s,%d,%d", n, isdn_map_eaz2msn(m->msn, info->isdn_driver),
182 m->mdmreg[18], m->mdmreg[19]);
183 cmd.command = ISDN_CMD_DIAL;
184 dev->mdm.dialing[info->line] = 1;
185 strcpy(dev->num[i], n);
186 isdn_info_update();
187 dev->drv[info->isdn_driver]->interface->command(&cmd);
188 } else
189 restore_flags(flags);
190 }
191 }
192
193 void isdn_tty_modem_hup(modem_info * info)
194 {
195 isdn_ctrl cmd;
196
197 dev->mdm.rcvsched[info->line] = 0;
198 dev->mdm.online[info->line] = 0;
199 if (info->isdn_driver >= 0) {
200 cmd.driver = info->isdn_driver;
201 cmd.command = ISDN_CMD_HANGUP;
202 cmd.arg = info->isdn_channel;
203 dev->drv[info->isdn_driver]->interface->command(&cmd);
204 isdn_all_eaz(info->isdn_driver, info->isdn_channel);
205 isdn_free_channel(info->isdn_driver, info->isdn_channel, ISDN_USAGE_MODEM);
206 }
207 dev->m_idx[info->drv_index] = -1;
208 info->isdn_driver = -1;
209 info->isdn_channel = -1;
210 info->drv_index = -1;
211 }
212
213 static inline int isdn_tty_paranoia_check(modem_info * info, dev_t device, const char *routine)
214 {
215 #ifdef MODEM_PARANOIA_CHECK
216 if (!info) {
217 printk(KERN_WARNING "isdn: null info_struct for (%d, %d) in %s\n",
218 MAJOR(device), MINOR(device), routine);
219 return 1;
220 }
221 if (info->magic != ISDN_ASYNC_MAGIC) {
222 printk(KERN_WARNING "isdn: bad magic for modem struct (%d, %d) in %s\n",
223 MAJOR(device), MINOR(device), routine);
224 return 1;
225 }
226 #endif
227 return 0;
228 }
229
230
231
232
233
234 static void isdn_tty_change_speed(modem_info * info)
235 {
236 uint cflag, cval, fcr, quot;
237 int i;
238
239 if (!info->tty || !info->tty->termios)
240 return;
241 cflag = info->tty->termios->c_cflag;
242
243 quot = i = cflag & CBAUD;
244 if (i & CBAUDEX) {
245 i &= ~CBAUDEX;
246 if (i < 1 || i > 2)
247 info->tty->termios->c_cflag &= ~CBAUDEX;
248 else
249 i += 15;
250 }
251 if (quot) {
252 info->MCR |= UART_MCR_DTR;
253 } else {
254 info->MCR &= ~UART_MCR_DTR;
255 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
256 if (dev->mdm.online[info->line]) {
257 #ifdef ISDN_DEBUG_MODEM_HUP
258 printk(KERN_DEBUG "Mhup in changespeed\n");
259 #endif
260 isdn_tty_modem_hup(info);
261 isdn_tty_modem_result(3, info);
262 }
263 return;
264 }
265
266 cval = cflag & (CSIZE | CSTOPB);
267 cval >>= 4;
268 if (cflag & PARENB)
269 cval |= UART_LCR_PARITY;
270 if (!(cflag & PARODD))
271 cval |= UART_LCR_EPAR;
272 fcr = 0;
273
274
275 if (cflag & CRTSCTS) {
276 info->flags |= ISDN_ASYNC_CTS_FLOW;
277 } else
278 info->flags &= ~ISDN_ASYNC_CTS_FLOW;
279 if (cflag & CLOCAL)
280 info->flags &= ~ISDN_ASYNC_CHECK_CD;
281 else {
282 info->flags |= ISDN_ASYNC_CHECK_CD;
283 }
284 }
285
286 static int isdn_tty_startup(modem_info * info)
287 {
288 ulong flags;
289
290 if (info->flags & ISDN_ASYNC_INITIALIZED)
291 return 0;
292 if (!info->type) {
293 if (info->tty)
294 set_bit(TTY_IO_ERROR, &info->tty->flags);
295 return 0;
296 }
297 save_flags(flags);
298 cli();
299
300 #ifdef ISDN_DEBUG_MODEM_OPEN
301 printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
302 #endif
303
304
305
306 info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
307 if (info->tty)
308 clear_bit(TTY_IO_ERROR, &info->tty->flags);
309
310
311
312 isdn_tty_change_speed(info);
313
314 info->flags |= ISDN_ASYNC_INITIALIZED;
315 dev->mdm.msr[info->line] |= UART_MSR_DSR;
316 #if FUTURE
317 info->send_outstanding = 0;
318 #endif
319 restore_flags(flags);
320 return 0;
321 }
322
323
324
325
326
327 static void isdn_tty_shutdown(modem_info * info)
328 {
329 ulong flags;
330
331 if (!(info->flags & ISDN_ASYNC_INITIALIZED))
332 return;
333 #ifdef ISDN_DEBUG_MODEM_OPEN
334 printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
335 #endif
336 save_flags(flags);
337 cli();
338 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
339 info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
340 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
341 if (dev->mdm.online[info->line]) {
342 #ifdef ISDN_DEBUG_MODEM_HUP
343 printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
344 #endif
345 isdn_tty_modem_hup(info);
346 }
347 }
348 if (info->tty)
349 set_bit(TTY_IO_ERROR, &info->tty->flags);
350
351 info->flags &= ~ISDN_ASYNC_INITIALIZED;
352 restore_flags(flags);
353 }
354
355 static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
356 {
357 int c, total = 0;
358 modem_info *info = (modem_info *) tty->driver_data;
359 ulong flags;
360 int i;
361
362 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
363 return 0;
364 if (!tty)
365 return 0;
366 save_flags(flags);
367 cli();
368 while (1) {
369 c = MIN(count, info->xmit_size - info->xmit_count - 1);
370 if (info->isdn_driver >= 0) {
371 #if 0
372 if (info->isdn_driver != 0) {
373 printk(KERN_DEBUG "FIDO: Zwei HW-Treiber geladen? Ansonsten ist was faul.\n");
374 break;
375 }
376 int drvidx = info->isdn_driver;
377 driver *driv = dev->drv[drvidx];
378 i = driv->maxbufsize;
379 #else
380 i = dev->drv[info->isdn_driver]->maxbufsize;
381 #endif
382 c = MIN(c, i);
383 }
384 if (c <= 0)
385 break;
386 i = info->line;
387 if (dev->mdm.online[i]) {
388 isdn_tty_check_esc(buf, dev->mdm.atmodem[i].mdmreg[2], c,
389 &(dev->mdm.atmodem[i].pluscount),
390 &(dev->mdm.atmodem[i].lastplus), from_user);
391 if (from_user)
392 memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c);
393 else
394 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
395 info->xmit_count += c;
396 if (dev->mdm.atmodem[i].mdmreg[13] & 1) {
397 char *bufptr;
398 int buflen;
399 #if 0
400 printk(KERN_DEBUG "WB1: %d\n", info->xmit_count);
401 #endif
402 bufptr = info->xmit_buf;
403 buflen = info->xmit_count;
404 if (dev->mdm.atmodem[i].mdmreg[13] & 2) {
405
406
407 #ifdef ISDN_DEBUG_MODEM_DUMP
408 isdn_dumppkt("T70pack1:", bufptr, buflen, 40);
409 #endif
410 bufptr -= 4;
411 buflen += 4;
412 memcpy(bufptr, "\1\0\1\0", 4);
413 #ifdef ISDN_DEBUG_MODEM_DUMP
414 isdn_dumppkt("T70pack2:", bufptr, buflen, 40);
415 #endif
416 }
417 if (dev->drv[info->isdn_driver]->interface->
418 writebuf(info->isdn_driver, info->isdn_channel, bufptr, buflen, 0) > 0) {
419 info->xmit_count = 0;
420 info->xmit_size = dev->mdm.atmodem[i].mdmreg[16] * 16;
421 #if FUTURE
422 info->send_outstanding++;
423 dev->mdm.msr[i] &= ~UART_MSR_CTS;
424 #endif
425 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
426 tty->ldisc.write_wakeup)
427 (tty->ldisc.write_wakeup) (tty);
428 wake_up_interruptible(&tty->write_wait);
429 }
430 }
431 } else {
432 if (dev->mdm.dialing[i]) {
433 dev->mdm.dialing[i] = 0;
434 #ifdef ISDN_DEBUG_MODEM_HUP
435 printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
436 #endif
437 isdn_tty_modem_hup(info);
438 isdn_tty_modem_result(3, info);
439 } else
440 c = isdn_tty_edit_at(buf, c, info, from_user);
441 }
442 buf += c;
443 count -= c;
444 total += c;
445 }
446 if (info->xmit_count)
447 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
448 restore_flags(flags);
449 return total;
450 }
451
452 static int isdn_tty_write_room(struct tty_struct *tty)
453 {
454 modem_info *info = (modem_info *) tty->driver_data;
455 int ret;
456
457 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write_room"))
458 return 0;
459 if (!dev->mdm.online[info->line])
460 return info->xmit_size - 1;
461 ret = info->xmit_size - info->xmit_count - 1;
462 return (ret < 0) ? 0 : ret;
463 }
464
465 static int isdn_tty_chars_in_buffer(struct tty_struct *tty)
466 {
467 modem_info *info = (modem_info *) tty->driver_data;
468
469 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_chars_in_buffer"))
470 return 0;
471 if (!dev->mdm.online[info->line])
472 return 0;
473 return (info->xmit_count);
474 }
475
476 static void isdn_tty_flush_buffer(struct tty_struct *tty)
477 {
478 modem_info *info = (modem_info *) tty->driver_data;
479 uint flags;
480
481 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer"))
482 return;
483 save_flags(flags);
484 cli();
485 info->xmit_count = 0;
486 restore_flags(flags);
487 wake_up_interruptible(&tty->write_wait);
488 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
489 tty->ldisc.write_wakeup)
490 (tty->ldisc.write_wakeup) (tty);
491 }
492
493 static void isdn_tty_flush_chars(struct tty_struct *tty)
494 {
495 modem_info *info = (modem_info *) tty->driver_data;
496
497 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars"))
498 return;
499 if (info->xmit_count > 0)
500 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
501 }
502
503
504
505
506
507
508
509
510
511 static void isdn_tty_throttle(struct tty_struct *tty)
512 {
513 modem_info *info = (modem_info *) tty->driver_data;
514
515 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_throttle"))
516 return;
517 if (I_IXOFF(tty))
518 info->x_char = STOP_CHAR(tty);
519 info->MCR &= ~UART_MCR_RTS;
520 }
521
522 static void isdn_tty_unthrottle(struct tty_struct *tty)
523 {
524 modem_info *info = (modem_info *) tty->driver_data;
525
526 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_unthrottle"))
527 return;
528 if (I_IXOFF(tty)) {
529 if (info->x_char)
530 info->x_char = 0;
531 else
532 info->x_char = START_CHAR(tty);
533 }
534 info->MCR |= UART_MCR_RTS;
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553 static int isdn_tty_get_lsr_info(modem_info * info, uint * value)
554 {
555 u_char status;
556 uint result;
557 ulong flags;
558
559 save_flags(flags);
560 cli();
561 status = dev->mdm.msr[info->line];
562 restore_flags(flags);
563 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
564 put_fs_long(result, (ulong *) value);
565 return 0;
566 }
567
568
569 static int isdn_tty_get_modem_info(modem_info * info, uint * value)
570 {
571 u_char control, status;
572 uint result;
573 ulong flags;
574
575 control = info->MCR;
576 save_flags(flags);
577 cli();
578 status = dev->mdm.msr[info->line];
579 restore_flags(flags);
580 result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
581 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
582 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
583 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
584 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
585 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
586 put_fs_long(result, (ulong *) value);
587 return 0;
588 }
589
590 static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
591 {
592 uint arg = get_fs_long((ulong *) value);
593
594 switch (cmd) {
595 case TIOCMBIS:
596 if (arg & TIOCM_RTS) {
597 info->MCR |= UART_MCR_RTS;
598 }
599 if (arg & TIOCM_DTR) {
600 info->MCR |= UART_MCR_DTR;
601 }
602 break;
603 case TIOCMBIC:
604 if (arg & TIOCM_RTS) {
605 info->MCR &= ~UART_MCR_RTS;
606 }
607 if (arg & TIOCM_DTR) {
608 info->MCR &= ~UART_MCR_DTR;
609 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
610 if (dev->mdm.online[info->line]) {
611 #ifdef ISDN_DEBUG_MODEM_HUP
612 printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
613 #endif
614 isdn_tty_modem_hup(info);
615 isdn_tty_modem_result(3, info);
616 }
617 }
618 break;
619 case TIOCMSET:
620 info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR))
621 | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
622 | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
623 if (!(info->MCR & UART_MCR_DTR)) {
624 isdn_tty_modem_reset_regs(&dev->mdm.atmodem[info->line], 0);
625 if (dev->mdm.online[info->line]) {
626 #ifdef ISDN_DEBUG_MODEM_HUP
627 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
628 #endif
629 isdn_tty_modem_hup(info);
630 isdn_tty_modem_result(3, info);
631 }
632 }
633 break;
634 default:
635 return -EINVAL;
636 }
637 return 0;
638 }
639
640 static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
641 uint cmd, ulong arg)
642 {
643 modem_info *info = (modem_info *) tty->driver_data;
644 int error;
645 int retval;
646
647 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl"))
648 return -ENODEV;
649 switch (cmd) {
650 case TCSBRK:
651 retval = tty_check_change(tty);
652 if (retval)
653 return retval;
654 tty_wait_until_sent(tty, 0);
655 return 0;
656 case TCSBRKP:
657 retval = tty_check_change(tty);
658 if (retval)
659 return retval;
660 tty_wait_until_sent(tty, 0);
661 return 0;
662 case TIOCGSOFTCAR:
663 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
664 if (error)
665 return error;
666 put_fs_long(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
667 return 0;
668 case TIOCSSOFTCAR:
669 arg = get_fs_long((ulong *) arg);
670 tty->termios->c_cflag =
671 ((tty->termios->c_cflag & ~CLOCAL) |
672 (arg ? CLOCAL : 0));
673 return 0;
674 case TIOCMGET:
675 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
676 if (error)
677 return error;
678 return isdn_tty_get_modem_info(info, (uint *) arg);
679 case TIOCMBIS:
680 case TIOCMBIC:
681 case TIOCMSET:
682 return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
683 case TIOCSERGETLSR:
684 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
685 if (error)
686 return error;
687 else
688 return isdn_tty_get_lsr_info(info, (uint *) arg);
689
690 case TIOCGSERIAL:
691 return -ENOIOCTLCMD;
692 #if 0
693 error = verify_area(VERIFY_WRITE, (void *) arg,
694 sizeof(struct serial_struct));
695 if (error)
696 return error;
697 return get_serial_info(info,
698 (struct serial_struct *) arg);
699 #endif
700 case TIOCSSERIAL:
701 return -ENOIOCTLCMD;
702 #if 0
703 return set_serial_info(info,
704 (struct serial_struct *) arg);
705 #endif
706 case TIOCSERCONFIG:
707 return -ENOIOCTLCMD;
708 #if 0
709 return do_autoconfig(info);
710 #endif
711
712 case TIOCSERGWILD:
713 return -ENOIOCTLCMD;
714 #if 0
715 error = verify_area(VERIFY_WRITE, (void *) arg,
716 sizeof(int));
717 if (error)
718 return error;
719 put_fs_long(modem_wild_int_mask, (ulong *) arg);
720 return 0;
721 #endif
722 case TIOCSERSWILD:
723 return -ENOIOCTLCMD;
724 #if 0
725 if (!suser())
726 return -EPERM;
727 modem_wild_int_mask = get_fs_long((ulong *) arg);
728 if (modem_wild_int_mask < 0)
729 modem_wild_int_mask = check_wild_interrupts(0);
730 return 0;
731 #endif
732 case TIOCSERGSTRUCT:
733 return -ENOIOCTLCMD;
734 #if 0
735 error = verify_area(VERIFY_WRITE, (void *) arg,
736 sizeof(modem_info));
737 if (error)
738 return error;
739 memcpy_tofs((modem_info *) arg,
740 info, sizeof(modem_info));
741 return 0;
742 #endif
743 default:
744 #ifdef ISDN_DEBUG_MODEM_IOCTL
745 printk(KERN_DEBUG "unsupp. ioctl 0x%08x on ttyi%d\n", cmd, info->line);
746 #endif
747 return -ENOIOCTLCMD;
748 }
749 return 0;
750 }
751
752 static void isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
753 {
754 modem_info *info = (modem_info *) tty->driver_data;
755
756 if (tty->termios->c_cflag == old_termios->c_cflag)
757 return;
758 isdn_tty_change_speed(info);
759 if ((old_termios->c_cflag & CRTSCTS) &&
760 !(tty->termios->c_cflag & CRTSCTS)) {
761 tty->hw_stopped = 0;
762 }
763 }
764
765
766
767
768
769
770 static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
771 {
772 struct wait_queue wait = {current, NULL};
773 int do_clocal = 0;
774 unsigned long flags;
775 int retval;
776
777
778
779
780
781 if (tty_hung_up_p(filp) ||
782 (info->flags & ISDN_ASYNC_CLOSING)) {
783 if (info->flags & ISDN_ASYNC_CLOSING)
784 interruptible_sleep_on(&info->close_wait);
785 #ifdef MODEM_DO_RESTART
786 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
787 return -EAGAIN;
788 else
789 return -ERESTARTSYS;
790 #else
791 return -EAGAIN;
792 #endif
793 }
794
795
796
797
798 if (tty->driver.subtype == ISDN_SERIAL_TYPE_CALLOUT) {
799 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
800 return -EBUSY;
801 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
802 (info->flags & ISDN_ASYNC_SESSION_LOCKOUT) &&
803 (info->session != current->session))
804 return -EBUSY;
805 if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
806 (info->flags & ISDN_ASYNC_PGRP_LOCKOUT) &&
807 (info->pgrp != current->pgrp))
808 return -EBUSY;
809 info->flags |= ISDN_ASYNC_CALLOUT_ACTIVE;
810 return 0;
811 }
812
813
814
815
816 if (filp->f_flags & O_NONBLOCK) {
817 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
818 return -EBUSY;
819 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
820 return 0;
821 }
822 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
823 if (info->normal_termios.c_cflag & CLOCAL)
824 do_clocal = 1;
825 } else {
826 if (tty->termios->c_cflag & CLOCAL)
827 do_clocal = 1;
828 }
829
830
831
832
833
834
835
836 retval = 0;
837 add_wait_queue(&info->open_wait, &wait);
838 #ifdef ISDN_DEBUG_MODEM_OPEN
839 printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
840 info->line, info->count);
841 #endif
842 save_flags(flags);
843 cli();
844 if (!(tty_hung_up_p(filp)))
845 info->count--;
846 restore_flags(flags);
847 info->blocked_open++;
848 while (1) {
849 current->state = TASK_INTERRUPTIBLE;
850 if (tty_hung_up_p(filp) ||
851 !(info->flags & ISDN_ASYNC_INITIALIZED)) {
852 #ifdef MODEM_DO_RESTART
853 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
854 retval = -EAGAIN;
855 else
856 retval = -ERESTARTSYS;
857 #else
858 retval = -EAGAIN;
859 #endif
860 break;
861 }
862 if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
863 !(info->flags & ISDN_ASYNC_CLOSING) &&
864 (do_clocal || (
865 dev->mdm.msr[info->line] &
866 UART_MSR_DCD))) {
867 break;
868 }
869 if (current->signal & ~current->blocked) {
870 retval = -ERESTARTSYS;
871 break;
872 }
873 #ifdef ISDN_DEBUG_MODEM_OPEN
874 printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n",
875 info->line, info->count);
876 #endif
877 schedule();
878 }
879 current->state = TASK_RUNNING;
880 remove_wait_queue(&info->open_wait, &wait);
881 if (!tty_hung_up_p(filp))
882 info->count++;
883 info->blocked_open--;
884 #ifdef ISDN_DEBUG_MODEM_OPEN
885 printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n",
886 info->line, info->count);
887 #endif
888 if (retval)
889 return retval;
890 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
891 return 0;
892 }
893
894
895
896
897
898
899
900 static int isdn_tty_open(struct tty_struct *tty, struct file *filp)
901 {
902 modem_info *info;
903 int retval, line;
904
905 line = MINOR(tty->device) - tty->driver.minor_start;
906 if (line < 0 || line > ISDN_MAX_CHANNELS)
907 return -ENODEV;
908 info = &dev->mdm.info[line];
909 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_open"))
910 return -ENODEV;
911 #ifdef ISDN_DEBUG_MODEM_OPEN
912 printk(KERN_DEBUG "isdn_tty_open %s%d, count = %d\n", tty->driver.name,
913 info->line, info->count);
914 #endif
915 info->count++;
916 tty->driver_data = info;
917 info->tty = tty;
918
919
920
921 retval = isdn_tty_startup(info);
922 if (retval) {
923 #ifdef ISDN_DEBUG_MODEM_OPEN
924 printk(KERN_DEBUG "isdn_tty_open return after startup\n");
925 #endif
926 return retval;
927 }
928 retval = isdn_tty_block_til_ready(tty, filp, info);
929 if (retval) {
930 #ifdef ISDN_DEBUG_MODEM_OPEN
931 printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
932 #endif
933 return retval;
934 }
935 if ((info->count == 1) && (info->flags & ISDN_ASYNC_SPLIT_TERMIOS)) {
936 if (tty->driver.subtype == ISDN_SERIAL_TYPE_NORMAL)
937 *tty->termios = info->normal_termios;
938 else
939 *tty->termios = info->callout_termios;
940 isdn_tty_change_speed(info);
941 }
942 info->session = current->session;
943 info->pgrp = current->pgrp;
944 #ifdef ISDN_DEBUG_MODEM_OPEN
945 printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
946 #endif
947 dev->modempoll++;
948 #ifdef ISDN_DEBUG_MODEM_OPEN
949 printk(KERN_DEBUG "isdn_tty_open normal exit\n");
950 #endif
951 return 0;
952 }
953
954 static void isdn_tty_close(struct tty_struct *tty, struct file *filp)
955 {
956 modem_info *info = (modem_info *) tty->driver_data;
957 ulong flags;
958 ulong timeout;
959
960 if (!info || isdn_tty_paranoia_check(info, tty->device, "isdn_tty_close"))
961 return;
962 save_flags(flags);
963 cli();
964 if (tty_hung_up_p(filp)) {
965 restore_flags(flags);
966 #ifdef ISDN_DEBUG_MODEM_OPEN
967 printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
968 #endif
969 return;
970 }
971 dev->modempoll--;
972 if ((tty->count == 1) && (info->count != 1)) {
973
974
975
976
977
978
979
980 printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
981 "info->count is %d\n", info->count);
982 info->count = 1;
983 }
984 if (--info->count < 0) {
985 printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
986 info->line, info->count);
987 info->count = 0;
988 }
989 if (info->count) {
990 restore_flags(flags);
991 #ifdef ISDN_DEBUG_MODEM_OPEN
992 printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
993 #endif
994 return;
995 }
996 info->flags |= ISDN_ASYNC_CLOSING;
997
998
999
1000
1001 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
1002 info->normal_termios = *tty->termios;
1003 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1004 info->callout_termios = *tty->termios;
1005
1006 tty->closing = 1;
1007
1008
1009
1010
1011
1012
1013
1014 if (info->flags & ISDN_ASYNC_INITIALIZED) {
1015 tty_wait_until_sent(tty, 3000);
1016
1017
1018
1019
1020
1021 timeout = jiffies + HZ;
1022 while (!(dev->mdm.mlr[info->line]
1023 & UART_LSR_TEMT)) {
1024 current->state = TASK_INTERRUPTIBLE;
1025 current->timeout = jiffies + 20;
1026 schedule();
1027 if (jiffies > timeout)
1028 break;
1029 }
1030 }
1031 isdn_tty_shutdown(info);
1032 if (tty->driver.flush_buffer)
1033 tty->driver.flush_buffer(tty);
1034 if (tty->ldisc.flush_buffer)
1035 tty->ldisc.flush_buffer(tty);
1036 info->tty = 0;
1037 tty->closing = 0;
1038 #if 00
1039 if (tty->ldisc.num != ldiscs[N_TTY].num) {
1040 if (tty->ldisc.close)
1041 (tty->ldisc.close) (tty);
1042 tty->ldisc = ldiscs[N_TTY];
1043 tty->termios->c_line = N_TTY;
1044 if (tty->ldisc.open)
1045 (tty->ldisc.open) (tty);
1046 }
1047 #endif
1048 if (info->blocked_open) {
1049 if (info->close_delay) {
1050 current->state = TASK_INTERRUPTIBLE;
1051 current->timeout = jiffies + info->close_delay;
1052 schedule();
1053 }
1054 wake_up_interruptible(&info->open_wait);
1055 }
1056 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE |
1057 ISDN_ASYNC_CLOSING);
1058 wake_up_interruptible(&info->close_wait);
1059 restore_flags(flags);
1060 #ifdef ISDN_DEBUG_MODEM_OPEN
1061 printk(KERN_DEBUG "isdn_tty_close normal exit\n");
1062 #endif
1063 }
1064
1065
1066
1067
1068 static void isdn_tty_hangup(struct tty_struct *tty)
1069 {
1070 modem_info *info = (modem_info *) tty->driver_data;
1071
1072 if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_hangup"))
1073 return;
1074 isdn_tty_shutdown(info);
1075 info->count = 0;
1076 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
1077 info->tty = 0;
1078 wake_up_interruptible(&info->open_wait);
1079 }
1080
1081 static void isdn_tty_reset_profile(atemu * m)
1082 {
1083 m->profile[0] = 0;
1084 m->profile[1] = 0;
1085 m->profile[2] = 43;
1086 m->profile[3] = 13;
1087 m->profile[4] = 10;
1088 m->profile[5] = 8;
1089 m->profile[6] = 3;
1090 m->profile[7] = 60;
1091 m->profile[8] = 2;
1092 m->profile[9] = 6;
1093 m->profile[10] = 7;
1094 m->profile[11] = 70;
1095 m->profile[12] = 0x45;
1096 m->profile[13] = 0;
1097 m->profile[14] = ISDN_PROTO_L2_X75I;
1098 m->profile[15] = ISDN_PROTO_L3_TRANS;
1099 m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
1100 m->profile[17] = ISDN_MODEM_WINSIZE;
1101 m->profile[18] = 7;
1102 m->profile[19] = 0;
1103 m->pmsn[0] = '\0';
1104 }
1105
1106 static void isdn_tty_modem_reset_regs(atemu * m, int force)
1107 {
1108 if ((m->mdmreg[12] & 32) || force) {
1109 memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
1110 memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
1111 }
1112 m->mdmcmdl = 0;
1113 }
1114
1115 static void modem_write_profile(atemu * m)
1116 {
1117 memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
1118 memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
1119 if (dev->profd)
1120 send_sig(SIGIO, dev->profd, 1);
1121 }
1122
1123 int isdn_tty_modem_init(void)
1124 {
1125 modem *m;
1126 int i;
1127 modem_info *info;
1128
1129 m = &dev->mdm;
1130 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1131 isdn_tty_reset_profile(&(m->atmodem[i]));
1132 isdn_tty_modem_reset_regs(&(m->atmodem[i]), 1);
1133 }
1134 memset(&m->tty_modem, 0, sizeof(struct tty_driver));
1135 m->tty_modem.magic = TTY_DRIVER_MAGIC;
1136 m->tty_modem.name = isdn_ttyname_ttyI;
1137 m->tty_modem.major = ISDN_TTY_MAJOR;
1138 m->tty_modem.minor_start = 0;
1139 m->tty_modem.num = ISDN_MAX_CHANNELS;
1140 m->tty_modem.type = TTY_DRIVER_TYPE_SERIAL;
1141 m->tty_modem.subtype = ISDN_SERIAL_TYPE_NORMAL;
1142 m->tty_modem.init_termios = tty_std_termios;
1143 m->tty_modem.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1144 m->tty_modem.flags = TTY_DRIVER_REAL_RAW;
1145 m->tty_modem.refcount = &m->refcount;
1146 m->tty_modem.table = m->modem_table;
1147 m->tty_modem.termios = m->modem_termios;
1148 m->tty_modem.termios_locked = m->modem_termios_locked;
1149 m->tty_modem.open = isdn_tty_open;
1150 m->tty_modem.close = isdn_tty_close;
1151 m->tty_modem.write = isdn_tty_write;
1152 m->tty_modem.put_char = NULL;
1153 m->tty_modem.flush_chars = isdn_tty_flush_chars;
1154 m->tty_modem.write_room = isdn_tty_write_room;
1155 m->tty_modem.chars_in_buffer = isdn_tty_chars_in_buffer;
1156 m->tty_modem.flush_buffer = isdn_tty_flush_buffer;
1157 m->tty_modem.ioctl = isdn_tty_ioctl;
1158 m->tty_modem.throttle = isdn_tty_throttle;
1159 m->tty_modem.unthrottle = isdn_tty_unthrottle;
1160 m->tty_modem.set_termios = isdn_tty_set_termios;
1161 m->tty_modem.stop = NULL;
1162 m->tty_modem.start = NULL;
1163 m->tty_modem.hangup = isdn_tty_hangup;
1164
1165
1166
1167
1168 m->cua_modem = m->tty_modem;
1169 m->cua_modem.name = isdn_ttyname_cui;
1170 m->cua_modem.major = ISDN_TTYAUX_MAJOR;
1171 m->tty_modem.minor_start = 0;
1172 m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT;
1173
1174 if (tty_register_driver(&m->tty_modem)) {
1175 printk(KERN_WARNING "isdn: Unable to register modem-device\n");
1176 return -1;
1177 }
1178 if (tty_register_driver(&m->cua_modem)) {
1179 printk(KERN_WARNING "Couldn't register modem-callout-device\n");
1180 return -2;
1181 }
1182 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1183 info = &(m->info[i]);
1184 info->magic = ISDN_ASYNC_MAGIC;
1185 info->line = i;
1186 info->tty = 0;
1187 info->close_delay = 50;
1188 info->x_char = 0;
1189 info->count = 0;
1190 info->blocked_open = 0;
1191 info->callout_termios = m->cua_modem.init_termios;
1192 info->normal_termios = m->tty_modem.init_termios;
1193 info->open_wait = 0;
1194 info->close_wait = 0;
1195 info->type = ISDN_PORT_16550A;
1196 info->isdn_driver = -1;
1197 info->isdn_channel = -1;
1198 info->drv_index = -1;
1199 info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
1200 if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_SIZE + 5, GFP_KERNEL))) {
1201 printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
1202 return -3;
1203 }
1204 info->xmit_buf += 4;
1205 }
1206 return 0;
1207 }
1208
1209
1210
1211
1212
1213
1214
1215 int isdn_tty_find_icall(int di, int ch, char *num)
1216 {
1217 char *eaz;
1218 int i;
1219 int idx;
1220 int si1;
1221 int si2;
1222 char *s;
1223 char nr[31];
1224 ulong flags;
1225
1226 save_flags(flags);
1227 cli();
1228 if (num[0] == ',') {
1229 nr[0] = '0';
1230 strncpy(&nr[1], num, 29);
1231 printk(KERN_WARNING "isdn: Incoming call without OAD, assuming '0'\n");
1232 } else
1233 strncpy(nr, num, 30);
1234 s = strtok(nr, ",");
1235 s = strtok(NULL, ",");
1236 if (!s) {
1237 printk(KERN_WARNING "isdn: Incoming callinfo garbled, ignored: %s\n",
1238 num);
1239 restore_flags(flags);
1240 return -1;
1241 }
1242 si1 = (int)simple_strtoul(s,NULL,10);
1243 s = strtok(NULL, ",");
1244 if (!s) {
1245 printk(KERN_WARNING "isdn: Incoming callinfo garbled, ignored: %s\n",
1246 num);
1247 restore_flags(flags);
1248 return -1;
1249 }
1250 si2 = (int)simple_strtoul(s,NULL,10);
1251 eaz = strtok(NULL, ",");
1252 if (!eaz) {
1253 printk(KERN_WARNING "isdn: Incoming call without CPN, assuming '0'\n");
1254 eaz = "0";
1255 }
1256 #ifdef ISDN_DEBUG_MODEM_ICALL
1257 printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
1258 #endif
1259 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1260 #ifdef ISDN_DEBUG_MODEM_ICALL
1261 printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
1262 dev->mdm.atmodem[i].msn, isdn_map_eaz2msn(dev->mdm.atmodem[i].msn, di),
1263 dev->mdm.atmodem[i].mdmreg[18], dev->mdm.atmodem[i].mdmreg[19]);
1264 #endif
1265 if ((!strcmp(isdn_map_eaz2msn(dev->mdm.atmodem[i].msn, di)
1266 ,eaz)) &&
1267 (dev->mdm.atmodem[i].mdmreg[18] == si1) &&
1268 (dev->mdm.atmodem[i].mdmreg[19] == si2)) {
1269 modem_info *info = &dev->mdm.info[i];
1270 idx = isdn_dc2minor(di, ch);
1271 #ifdef ISDN_DEBUG_MODEM_ICALL
1272 printk(KERN_DEBUG "m_fi: match1\n");
1273 printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
1274 info->flags, info->isdn_driver, info->isdn_channel,
1275 dev->usage[idx]);
1276 #endif
1277 if ((info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
1278 (info->isdn_driver == -1) &&
1279 (info->isdn_channel == -1) &&
1280 (USG_NONE(dev->usage[idx]))) {
1281 info->isdn_driver = di;
1282 info->isdn_channel = ch;
1283 info->drv_index = idx;
1284 dev->m_idx[idx] = info->line;
1285 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
1286 dev->usage[idx] |= ISDN_USAGE_MODEM;
1287 strcpy(dev->num[idx], nr);
1288 isdn_info_update();
1289 restore_flags(flags);
1290 printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
1291 info->line);
1292 return info->line;
1293 }
1294 }
1295 }
1296 printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
1297 dev->drv[di]->reject_bus ? "rejected" : "ignored");
1298 restore_flags(flags);
1299 return -1;
1300 }
1301
1302
1303
1304
1305
1306 #define cmdchar(c) ((c>' ')&&(c<=0x7f))
1307
1308
1309
1310
1311
1312 static void isdn_tty_at_cout(char *msg, modem_info * info)
1313 {
1314 struct tty_struct *tty;
1315 atemu *m = &(dev->mdm.atmodem[info->line]);
1316 char *p;
1317 char c;
1318 ulong flags;
1319
1320 if (!msg) {
1321 printk(KERN_WARNING "isdn: Null-Message in isdn_tty_at_cout\n");
1322 return;
1323 }
1324 save_flags(flags);
1325 cli();
1326 tty = info->tty;
1327 for (p = msg; *p; p++) {
1328 switch (*p) {
1329 case '\r':
1330 c = m->mdmreg[3];
1331 break;
1332 case '\n':
1333 c = m->mdmreg[4];
1334 break;
1335 case '\b':
1336 c = m->mdmreg[5];
1337 break;
1338 default:
1339 c = *p;
1340 }
1341 if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
1342 restore_flags(flags);
1343 return;
1344 }
1345 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
1346 break;
1347 tty_insert_flip_char(tty, c, 0);
1348 }
1349 restore_flags(flags);
1350 queue_task(&tty->flip.tqueue, &tq_timer);
1351 }
1352
1353
1354
1355
1356 static void isdn_tty_on_hook(modem_info * info)
1357 {
1358 if (info->isdn_channel >= 0) {
1359 #ifdef ISDN_DEBUG_MODEM_HUP
1360 printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
1361 #endif
1362 isdn_tty_modem_hup(info);
1363 isdn_tty_modem_result(3, info);
1364 }
1365 }
1366
1367 static void isdn_tty_off_hook(void)
1368 {
1369 printk(KERN_DEBUG "isdn_tty_off_hook\n");
1370 }
1371
1372 #define PLUSWAIT1 (HZ/2)
1373 #define PLUSWAIT2 (HZ*3/2)
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
1387 int *lastplus, int from_user)
1388 {
1389 char cbuf[3];
1390
1391 if (plus > 127)
1392 return;
1393 if (count > 3) {
1394 p += count - 3;
1395 count = 3;
1396 *pluscount = 0;
1397 }
1398 if (from_user) {
1399 memcpy_fromfs(cbuf, p, count);
1400 p = cbuf;
1401 }
1402 while (count > 0) {
1403 if (*(p++) == plus) {
1404 if ((*pluscount)++) {
1405
1406 if ((jiffies - *lastplus) > PLUSWAIT1)
1407 *pluscount = 1;
1408 } else {
1409
1410 if ((jiffies - *lastplus) < PLUSWAIT2)
1411 *pluscount = 0;
1412 }
1413 if ((*pluscount == 3) && (count = 1))
1414 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
1415 if (*pluscount > 3)
1416 *pluscount = 1;
1417 } else
1418 *pluscount = 0;
1419 *lastplus = jiffies;
1420 count--;
1421 }
1422 }
1423
1424
1425
1426
1427
1428
1429
1430 void isdn_tty_modem_result(int code, modem_info * info)
1431 {
1432 atemu *m = &dev->mdm.atmodem[info->line];
1433 static char *msg[] =
1434 {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
1435 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
1436 "RINGING", "NO MSN/EAZ"};
1437 ulong flags;
1438 char s[4];
1439
1440 switch (code) {
1441 case 2:
1442 m->mdmreg[1]++;
1443 if (m->mdmreg[1] == m->mdmreg[0]) {
1444
1445 isdn_ctrl cmd;
1446 m->mdmreg[1] = 0;
1447 dev->mdm.msr[info->line] &= ~UART_MSR_RI;
1448 cmd.driver = info->isdn_driver;
1449 cmd.arg = info->isdn_channel;
1450 cmd.command = ISDN_CMD_ACCEPTD;
1451 dev->drv[info->isdn_driver]->interface->command(&cmd);
1452 }
1453 break;
1454 case 3:
1455
1456 save_flags(flags);
1457 cli();
1458 dev->mdm.msr[info->line] &= ~(UART_MSR_DCD | UART_MSR_RI);
1459 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
1460 restore_flags(flags);
1461 return;
1462 }
1463 restore_flags(flags);
1464 break;
1465 case 1:
1466 case 5:
1467 dev->mdm.online[info->line] = 1;
1468 break;
1469 }
1470 if (m->mdmreg[12] & 1) {
1471
1472 isdn_tty_at_cout("\r\n", info);
1473 if (m->mdmreg[12] & 2) {
1474
1475 sprintf(s, "%d", code);
1476 isdn_tty_at_cout(s, info);
1477 } else {
1478 if (code == 2) {
1479 isdn_tty_at_cout("CALLER NUMBER: ", info);
1480 isdn_tty_at_cout(dev->num[info->drv_index], info);
1481 isdn_tty_at_cout("\r\n", info);
1482 }
1483 isdn_tty_at_cout(msg[code], info);
1484 if (code == 5) {
1485
1486 isdn_tty_at_cout((m->mdmreg[14] != 3) ? "/X.75" : "/HDLC", info);
1487 if (m->mdmreg[13] & 2)
1488 isdn_tty_at_cout("/T.70", info);
1489 }
1490 }
1491 isdn_tty_at_cout("\r\n", info);
1492 }
1493 if (code == 3) {
1494 save_flags(flags);
1495 cli();
1496 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
1497 restore_flags(flags);
1498 return;
1499 }
1500 if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
1501 (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1502 (info->flags & ISDN_ASYNC_CALLOUT_NOHUP))))
1503 tty_hangup(info->tty);
1504 restore_flags(flags);
1505 }
1506 }
1507
1508
1509
1510
1511 static void isdn_tty_show_profile(int ridx, modem_info * info)
1512 {
1513 char v[6];
1514
1515 sprintf(v, "%d\r\n", dev->mdm.atmodem[info->line].mdmreg[ridx]);
1516 isdn_tty_at_cout(v, info);
1517 }
1518
1519
1520
1521
1522 static void isdn_tty_get_msnstr(char *n, char **p)
1523 {
1524 while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
1525 *n++ = *p[0]++;
1526 *n = '\0';
1527 }
1528
1529
1530
1531
1532 static void isdn_tty_getdial(char *p, char *q)
1533 {
1534 int first = 1;
1535
1536 while (strchr("0123456789,#.*WPTS-", *p) && *p) {
1537 if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first))
1538 *q++ = *p;
1539 p++;
1540 first = 0;
1541 }
1542 *q = 0;
1543 }
1544
1545
1546
1547
1548
1549
1550
1551 static void isdn_tty_parse_at(modem_info * info)
1552 {
1553 atemu *m = &dev->mdm.atmodem[info->line];
1554 char *p;
1555 int mreg;
1556 int mval;
1557 int i;
1558 char rb[100];
1559 char ds[40];
1560 isdn_ctrl cmd;
1561
1562 #ifdef ISDN_DEBUG_AT
1563 printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
1564 #endif
1565 for (p = &m->mdmcmd[2]; *p;) {
1566 switch (*p) {
1567 case 'A':
1568
1569 p++;
1570 if (m->mdmreg[1]) {
1571 #define FIDOBUG
1572 #ifdef FIDOBUG
1573
1574 driver *fido_drv;
1575 isdn_if *fido_if;
1576 int fido_isdn_driver;
1577 modem_info *fido_modem_info;
1578 int (*fido_command) (isdn_ctrl *);
1579 #endif
1580
1581 m->mdmreg[1] = 0;
1582 dev->mdm.msr[info->line] &= ~UART_MSR_RI;
1583 cmd.driver = info->isdn_driver;
1584 cmd.command = ISDN_CMD_SETL2;
1585 cmd.arg = info->isdn_channel + (m->mdmreg[14] << 8);
1586 dev->drv[info->isdn_driver]->interface->command(&cmd);
1587 cmd.driver = info->isdn_driver;
1588 cmd.command = ISDN_CMD_SETL3;
1589 cmd.arg = info->isdn_channel + (m->mdmreg[15] << 8);
1590 dev->drv[info->isdn_driver]->interface->command(&cmd);
1591 cmd.driver = info->isdn_driver;
1592 cmd.arg = info->isdn_channel;
1593 cmd.command = ISDN_CMD_ACCEPTD;
1594 #ifdef FIDOBUG
1595 fido_modem_info = info;
1596 fido_isdn_driver = fido_modem_info->isdn_driver;
1597 fido_drv = dev->drv[fido_isdn_driver];
1598 fido_if = fido_drv->interface;
1599 fido_command = fido_if->command;
1600 fido_command(&cmd);
1601 #else
1602 dev->drv[info->isdn_driver]->interface->command(&cmd);
1603 #endif
1604 } else {
1605 isdn_tty_modem_result(8, info);
1606 return;
1607 }
1608 break;
1609 case 'D':
1610
1611 isdn_tty_getdial(++p, ds);
1612 p += strlen(p);
1613 if (!strlen(m->msn))
1614 isdn_tty_modem_result(10, info);
1615 else if (strlen(ds))
1616 isdn_tty_dial(ds, info, m);
1617 else
1618 isdn_tty_modem_result(4, info);
1619 return;
1620 case 'E':
1621
1622 p++;
1623 switch (*p) {
1624 case '0':
1625 p++;
1626 m->mdmreg[12] &= ~4;
1627 break;
1628 case '1':
1629 p++;
1630 m->mdmreg[12] |= 4;
1631 break;
1632 default:
1633 isdn_tty_modem_result(4, info);
1634 return;
1635 }
1636 break;
1637 case 'H':
1638
1639 p++;
1640 switch (*p) {
1641 case '0':
1642 p++;
1643 isdn_tty_on_hook(info);
1644 break;
1645 case '1':
1646 p++;
1647 isdn_tty_off_hook();
1648 break;
1649 default:
1650 isdn_tty_on_hook(info);
1651 break;
1652 }
1653 break;
1654 case 'I':
1655
1656 p++;
1657 isdn_tty_at_cout("ISDN for Linux (c) by Fritz Elfert\r\n", info);
1658 switch (*p) {
1659 case '0':
1660 case '1':
1661 p++;
1662 break;
1663 default:
1664 }
1665 break;
1666 case 'O':
1667
1668 p++;
1669 if (dev->mdm.msr[info->line] & UART_MSR_DCD)
1670 isdn_tty_modem_result(5, info);
1671 else
1672 isdn_tty_modem_result(3, info);
1673 return;
1674 case 'Q':
1675
1676 p++;
1677 switch (*p) {
1678 case '0':
1679 p++;
1680 m->mdmreg[12] |= 1;
1681 break;
1682 case '1':
1683 p++;
1684 m->mdmreg[12] &= ~1;
1685 break;
1686 default:
1687 isdn_tty_modem_result(4, info);
1688 return;
1689 }
1690 break;
1691 case 'S':
1692
1693 p++;
1694 mreg = isdn_getnum(&p);
1695 if (mreg < 0 || mreg > ISDN_MODEM_ANZREG) {
1696 isdn_tty_modem_result(4, info);
1697 return;
1698 }
1699 switch (*p) {
1700 case '=':
1701 p++;
1702 mval = isdn_getnum(&p);
1703 if (mval >= 0 && mval <= 255) {
1704 if ((mreg == 16) && ((mval * 16) > ISDN_SERIAL_XMIT_SIZE)) {
1705 isdn_tty_modem_result(4, info);
1706 return;
1707 }
1708 m->mdmreg[mreg] = mval;
1709 } else {
1710 isdn_tty_modem_result(4, info);
1711 return;
1712 }
1713 break;
1714 case '?':
1715 p++;
1716 isdn_tty_show_profile(mreg, info);
1717 return;
1718 break;
1719 default:
1720 isdn_tty_modem_result(4, info);
1721 return;
1722 }
1723 break;
1724 case 'V':
1725
1726 p++;
1727 switch (*p) {
1728 case '0':
1729 p++;
1730 m->mdmreg[12] |= 2;
1731 break;
1732 case '1':
1733 p++;
1734 m->mdmreg[12] &= ~2;
1735 break;
1736 default:
1737 isdn_tty_modem_result(4, info);
1738 return;
1739 }
1740 break;
1741 case 'Z':
1742
1743 p++;
1744 isdn_tty_modem_reset_regs(m, 1);
1745 break;
1746 case '+':
1747 p++;
1748 switch (*p) {
1749 case 'F':
1750 break;
1751 }
1752 break;
1753 case '&':
1754 p++;
1755 switch (*p) {
1756 case 'B':
1757
1758 p++;
1759 i = isdn_getnum(&p);
1760 if ((i < 0) || (i > ISDN_SERIAL_XMIT_SIZE)) {
1761 isdn_tty_modem_result(4, info);
1762 return;
1763 }
1764 m->mdmreg[16] = i / 16;
1765 break;
1766 case 'D':
1767
1768 p++;
1769 switch (isdn_getnum(&p)) {
1770 case 2:
1771 m->mdmreg[12] &= ~32;
1772 break;
1773 case 3:
1774 m->mdmreg[12] |= 32;
1775 break;
1776 default:
1777 isdn_tty_modem_result(4, info);
1778 return;
1779 }
1780 break;
1781 case 'E':
1782
1783 p++;
1784 isdn_tty_get_msnstr(m->msn, &p);
1785 break;
1786 case 'F':
1787
1788 p++;
1789 isdn_tty_reset_profile(m);
1790 isdn_tty_modem_reset_regs(m, 1);
1791 break;
1792 case 'S':
1793
1794 p++;
1795 i = isdn_getnum(&p);
1796 if ((i > 0) && (i < 9))
1797 m->mdmreg[17] = i;
1798 else {
1799 isdn_tty_modem_result(4, info);
1800 return;
1801 }
1802 break;
1803 case 'V':
1804
1805 p++;
1806 for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
1807 sprintf(rb, "S%d=%d%s", i, m->mdmreg[i], (i == 6) ? "\r\n" : " ");
1808 isdn_tty_at_cout(rb, info);
1809 }
1810 sprintf(rb, "\r\nEAZ/MSN: %s\r\n", strlen(m->msn) ? m->msn : "None");
1811 isdn_tty_at_cout(rb, info);
1812 break;
1813 case 'W':
1814
1815 p++;
1816 switch (*p) {
1817 case '0':
1818 p++;
1819 modem_write_profile(m);
1820 break;
1821 default:
1822 isdn_tty_modem_result(4, info);
1823 return;
1824 }
1825 break;
1826 case 'X':
1827
1828 p++;
1829 switch (*p) {
1830 case '0':
1831 p++;
1832 m->mdmreg[13] &= ~2;
1833 break;
1834 case '1':
1835 p++;
1836 m->mdmreg[13] |= 2;
1837 m->mdmreg[14] = 0;
1838 m->mdmreg[16] = 7;
1839 m->mdmreg[18] = 7;
1840 m->mdmreg[19] = 0;
1841 break;
1842 default:
1843 isdn_tty_modem_result(4, info);
1844 return;
1845 }
1846 break;
1847 default:
1848 isdn_tty_modem_result(4, info);
1849 return;
1850 }
1851 break;
1852 default:
1853 isdn_tty_modem_result(4, info);
1854 return;
1855 }
1856 }
1857 isdn_tty_modem_result(0, info);
1858 }
1859
1860
1861
1862
1863 #define my_toupper(c) (((c>='a')&&(c<='z'))?(c&0xdf):c)
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874 static int isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
1875 {
1876 atemu *m = &dev->mdm.atmodem[info->line];
1877 int total = 0;
1878 u_char c;
1879 char eb[2];
1880 int cnt;
1881
1882 for (cnt = count; cnt > 0; p++, cnt--) {
1883 if (user)
1884 c = get_fs_byte(p);
1885 else
1886 c = *p;
1887 total++;
1888 if (c == m->mdmreg[3] || c == m->mdmreg[4]) {
1889
1890 m->mdmcmd[m->mdmcmdl] = 0;
1891 if (m->mdmreg[12] & 4) {
1892 eb[0] = c;
1893 eb[1] = 0;
1894 isdn_tty_at_cout(eb, info);
1895 }
1896 if (m->mdmcmdl >= 2)
1897 isdn_tty_parse_at(info);
1898 m->mdmcmdl = 0;
1899 continue;
1900 }
1901 if (c == m->mdmreg[5] && m->mdmreg[5] < 128) {
1902
1903 if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
1904 if (m->mdmcmdl)
1905 m->mdmcmdl--;
1906 if (m->mdmreg[12] & 4)
1907 isdn_tty_at_cout("\b", info);
1908 }
1909 continue;
1910 }
1911 if (cmdchar(c)) {
1912 if (m->mdmreg[12] & 4) {
1913 eb[0] = c;
1914 eb[1] = 0;
1915 isdn_tty_at_cout(eb, info);
1916 }
1917 if (m->mdmcmdl < 255) {
1918 c = my_toupper(c);
1919 switch (m->mdmcmdl) {
1920 case 0:
1921 if (c == 'A')
1922 m->mdmcmd[m->mdmcmdl++] = c;
1923 break;
1924 case 1:
1925 if (c == 'T')
1926 m->mdmcmd[m->mdmcmdl++] = c;
1927 break;
1928 default:
1929 m->mdmcmd[m->mdmcmdl++] = c;
1930 }
1931 }
1932 }
1933 }
1934 return total;
1935 }
1936
1937
1938
1939
1940
1941
1942
1943 void isdn_tty_modem_escape(void)
1944 {
1945 int ton = 0;
1946 int i;
1947 int midx;
1948
1949 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1950 if (USG_MODEM(dev->usage[i]))
1951 if ((midx = dev->m_idx[i]) >= 0)
1952 if (dev->mdm.online[midx]) {
1953 ton = 1;
1954 if ((dev->mdm.atmodem[midx].pluscount == 3) &&
1955 ((jiffies - dev->mdm.atmodem[midx].lastplus) > PLUSWAIT2)) {
1956 dev->mdm.atmodem[midx].pluscount = 0;
1957 dev->mdm.online[midx] = 0;
1958 isdn_tty_modem_result(0, &dev->mdm.info[midx]);
1959 }
1960 }
1961 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
1962 }
1963
1964
1965
1966
1967
1968
1969 void isdn_tty_modem_ring(void)
1970 {
1971 int ton = 0;
1972 int i;
1973 int midx;
1974
1975 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1976 if (USG_MODEM(dev->usage[i]))
1977 if ((midx = dev->m_idx[i]) >= 0)
1978 if (dev->mdm.msr[midx] & UART_MSR_RI) {
1979 ton = 1;
1980 isdn_tty_modem_result(2, &dev->mdm.info[midx]);
1981 }
1982 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
1983 }
1984
1985 void isdn_tty_modem_xmit(void)
1986 {
1987 int ton = 0;
1988 int i;
1989 int midx;
1990 char *bufptr;
1991 int buflen;
1992
1993 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1994 if (USG_MODEM(dev->usage[i]))
1995 if ((midx = dev->m_idx[i]) >= 0)
1996 if (dev->mdm.online[midx]) {
1997 modem_info *info = &(dev->mdm.info[midx]);
1998 ulong flags;
1999
2000 save_flags(flags);
2001 cli();
2002 if (info->xmit_count > 0) {
2003 struct tty_struct *tty = info->tty;
2004 ton = 1;
2005 #if 0
2006 printk(KERN_DEBUG "WB2: %d\n", info->xmit_count);
2007 #endif
2008 bufptr = info->xmit_buf;
2009 buflen = info->xmit_count;
2010 if (dev->mdm.atmodem[midx].mdmreg[13] & 2) {
2011
2012 #ifdef ISDN_DEBUG_MODEM_DUMP
2013 isdn_dumppkt("T70pack3:", bufptr, buflen, 40);
2014 #endif
2015 bufptr -= 4;
2016 buflen += 4;
2017 memcpy(bufptr, "\1\0\1\0", 4);
2018 #ifdef ISDN_DEBUG_MODEM_DUMP
2019 isdn_dumppkt("T70pack4:", bufptr, buflen, 40);
2020 #endif
2021 }
2022 if (dev->drv[info->isdn_driver]->interface->
2023 writebuf(info->isdn_driver, info->isdn_channel, bufptr, buflen, 0) > 0) {
2024 info->xmit_count = 0;
2025 info->xmit_size = dev->mdm.atmodem[midx].mdmreg[16] * 16;
2026 #if FUTURE
2027 info->send_outstanding++;
2028 dev->mdm.msr[midx] &= ~UART_MSR_CTS;
2029 #endif
2030 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
2031 tty->ldisc.write_wakeup)
2032 (tty->ldisc.write_wakeup) (tty);
2033 wake_up_interruptible(&tty->write_wait);
2034 }
2035 }
2036 restore_flags(flags);
2037 }
2038 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
2039 }
2040
2041 #if FUTURE
2042
2043
2044
2045
2046
2047 void isdn_tty_bsent(int drv, int chan)
2048 {
2049 int i;
2050 ulong flags;
2051
2052 save_flags(flags);
2053 cli();
2054 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2055 modem_info *info = &dev->mdm.info[i];
2056 if ((info->isdn_driver == drv) &&
2057 (info->isdn_channel == chan) &&
2058 (info->send_outstanding)) {
2059 if (!(--info->send_outstanding))
2060 dev->mdm.msr[i] |= UART_MSR_CTS;
2061 restore_flags(flags);
2062 return;
2063 }
2064 }
2065 restore_flags(flags);
2066 return;
2067 }
2068 #endif