comparison spandsp-0.0.6pre17/src/v42.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v42.c
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: v42.c,v 1.51 2009/11/04 15:52:06 steveu Exp $
26 */
27
28 /* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
29
30 /*! \file */
31
32 #if defined(HAVE_CONFIG_H)
33 #include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #include "spandsp/telephony.h"
43 #include "spandsp/logging.h"
44 #include "spandsp/async.h"
45 #include "spandsp/hdlc.h"
46 #include "spandsp/schedule.h"
47 #include "spandsp/queue.h"
48 #include "spandsp/v42.h"
49
50 #include "spandsp/private/logging.h"
51 #include "spandsp/private/schedule.h"
52 #include "spandsp/private/hdlc.h"
53 #include "spandsp/private/v42.h"
54
55 #if !defined(FALSE)
56 #define FALSE 0
57 #endif
58 #if !defined(TRUE)
59 #define TRUE (!FALSE)
60 #endif
61
62 #define LAPM_FRAMETYPE_MASK 0x03
63
64 #define LAPM_FRAMETYPE_I 0x00
65 #define LAPM_FRAMETYPE_I_ALT 0x02
66 #define LAPM_FRAMETYPE_S 0x01
67 #define LAPM_FRAMETYPE_U 0x03
68
69 /* Timer values */
70
71 #define T_WAIT_MIN 2000
72 #define T_WAIT_MAX 10000
73 /* Detection phase timer */
74 #define T_400 750000
75 /* Acknowledgement timer - 1 second between SABME's */
76 #define T_401 1000000
77 /* Replay delay timer (optional) */
78 #define T_402 1000000
79 /* Inactivity timer (optional). No default - use 10 seconds with no packets */
80 #define T_403 10000000
81 /* Max retries */
82 #define N_400 3
83 /* Max octets in an information field */
84 #define N_401 128
85
86 #define LAPM_DLCI_DTE_TO_DTE 0
87 #define LAPM_DLCI_LAYER2_MANAGEMENT 63
88
89 static void t401_expired(span_sched_state_t *s, void *user_data);
90 static void t403_expired(span_sched_state_t *s, void *user_data);
91
92 SPAN_DECLARE(void) lapm_reset(lapm_state_t *s);
93 SPAN_DECLARE(void) lapm_restart(lapm_state_t *s);
94
95 static void lapm_link_down(lapm_state_t *s);
96
97 static __inline__ void lapm_init_header(uint8_t *frame, int command)
98 {
99 /* Data link connection identifier (0) */
100 /* Command/response (0 if answerer, 1 if originator) */
101 /* Extended address (1) */
102 frame[0] = (LAPM_DLCI_DTE_TO_DTE << 2) | ((command) ? 0x02 : 0x00) | 0x01;
103 }
104 /*- End of function --------------------------------------------------------*/
105
106 static int lapm_tx_frame(lapm_state_t *s, uint8_t *frame, int len)
107 {
108 if ((s->debug & LAPM_DEBUG_LAPM_DUMP))
109 lapm_dump(s, frame, len, s->debug & LAPM_DEBUG_LAPM_RAW, TRUE);
110 /*endif*/
111 hdlc_tx_frame(&s->hdlc_tx, frame, len);
112 return 0;
113 }
114 /*- End of function --------------------------------------------------------*/
115
116 static void t400_expired(span_sched_state_t *ss, void *user_data)
117 {
118 v42_state_t *s;
119
120 /* Give up trying to detect a V.42 capable peer. */
121 s = (v42_state_t *) user_data;
122 s->t400_timer = -1;
123 s->lapm.state = LAPM_UNSUPPORTED;
124 if (s->lapm.status_callback)
125 s->lapm.status_callback(s->lapm.status_callback_user_data, s->lapm.state);
126 /*endif*/
127 }
128 /*- End of function --------------------------------------------------------*/
129
130 static void lapm_send_ua(lapm_state_t *s, int pfbit)
131 {
132 uint8_t frame[3];
133
134 lapm_init_header(frame, !s->we_are_originator);
135 frame[1] = (uint8_t) (0x63 | (pfbit << 4));
136 frame[2] = 0;
137 span_log(&s->logging, SPAN_LOG_FLOW, "Sending unnumbered acknowledgement\n");
138 lapm_tx_frame(s, frame, 3);
139 }
140 /*- End of function --------------------------------------------------------*/
141
142 static void lapm_send_sabme(span_sched_state_t *ss, void *user_data)
143 {
144 lapm_state_t *s;
145 uint8_t frame[3];
146
147 s = (lapm_state_t *) user_data;
148 if (s->t401_timer >= 0)
149 {
150 fprintf(stderr, "Deleting T401 q [%p] %d\n", (void *) s, s->t401_timer);
151 span_schedule_del(&s->sched, s->t401_timer);
152 s->t401_timer = -1;
153 }
154 /*endif*/
155 if (++s->retransmissions > N_400)
156 {
157 /* 8.3.2.2 Too many retries */
158 s->state = LAPM_RELEASE;
159 if (s->status_callback)
160 s->status_callback(s->status_callback_user_data, s->state);
161 /*endif*/
162 return;
163 }
164 /*endif*/
165 fprintf(stderr, "Setting T401 a1 [%p]\n", (void *) s);
166 s->t401_timer = span_schedule_event(&s->sched, T_401, lapm_send_sabme, s);
167 lapm_init_header(frame, s->we_are_originator);
168 frame[1] = 0x7F;
169 frame[2] = 0;
170 span_log(&s->logging, SPAN_LOG_FLOW, "Sending SABME (set asynchronous balanced mode extended)\n");
171 lapm_tx_frame(s, frame, 3);
172 }
173 /*- End of function --------------------------------------------------------*/
174
175 static int lapm_ack_packet(lapm_state_t *s, int num)
176 {
177 lapm_frame_queue_t *f;
178 lapm_frame_queue_t *prev;
179
180 for (prev = NULL, f = s->txqueue; f; prev = f, f = f->next)
181 {
182 if ((f->frame[1] >> 1) == num)
183 {
184 /* Cancel each packet, as necessary */
185 if (prev)
186 prev->next = f->next;
187 else
188 s->txqueue = f->next;
189 /*endif*/
190 span_log(&s->logging,
191 SPAN_LOG_FLOW,
192 "-- ACKing packet %d. New txqueue is %d (-1 means empty)\n",
193 (f->frame[1] >> 1),
194 (s->txqueue) ? (s->txqueue->frame[1] >> 1) : -1);
195 s->last_frame_peer_acknowledged = num;
196 free(f);
197 /* Reset retransmission count if we actually acked something */
198 s->retransmissions = 0;
199 return 1;
200 }
201 /*endif*/
202 }
203 /*endfor*/
204 return 0;
205 }
206 /*- End of function --------------------------------------------------------*/
207
208 static void lapm_ack_rx(lapm_state_t *s, int ack)
209 {
210 int i;
211 int cnt;
212
213 /* This might not be acking anything new */
214 if (s->last_frame_peer_acknowledged == ack)
215 return;
216 /*endif*/
217 /* It should be acking something that is actually outstanding */
218 if ((s->last_frame_peer_acknowledged < s->next_tx_frame && (ack < s->last_frame_peer_acknowledged || ack > s->next_tx_frame))
219 ||
220 (s->last_frame_peer_acknowledged > s->next_tx_frame && (ack > s->last_frame_peer_acknowledged || ack < s->next_tx_frame)))
221 {
222 /* ACK was outside our window --- ignore */
223 span_log(&s->logging, SPAN_LOG_FLOW, "ACK received outside window, ignoring\n");
224 return;
225 }
226 /*endif*/
227
228 /* Cancel each packet, as necessary */
229 span_log(&s->logging,
230 SPAN_LOG_FLOW,
231 "-- ACKing all packets from %d to (but not including) %d\n",
232 s->last_frame_peer_acknowledged,
233 ack);
234 for (cnt = 0, i = s->last_frame_peer_acknowledged; i != ack; i = (i + 1) & 0x7F)
235 cnt += lapm_ack_packet(s, i);
236 /*endfor*/
237 s->last_frame_peer_acknowledged = ack;
238 if (s->txqueue == NULL)
239 {
240 span_log(&s->logging, SPAN_LOG_FLOW, "-- Since there was nothing left, stopping timer T_401\n");
241 /* Something was ACK'd. Stop timer T_401. */
242 fprintf(stderr, "T401 a2 is %d [%p]\n", s->t401_timer, (void *) s);
243 if (s->t401_timer >= 0)
244 {
245 fprintf(stderr, "Deleting T401 a3 [%p] %d\n", (void *) s, s->t401_timer);
246 span_schedule_del(&s->sched, s->t401_timer);
247 s->t401_timer = -1;
248 }
249 /*endif*/
250 }
251 /*endif*/
252 if (s->t403_timer >= 0)
253 {
254 span_log(&s->logging, SPAN_LOG_FLOW, "-- Stopping timer T_403, since we got an ACK\n");
255 if (s->t403_timer >= 0)
256 {
257 fprintf(stderr, "Deleting T403 b %d\n", s->t403_timer);
258 span_schedule_del(&s->sched, s->t403_timer);
259 s->t403_timer = -1;
260 }
261 /*endif*/
262 }
263 /*endif*/
264 if (s->txqueue)
265 {
266 /* Something left to transmit. Start timer T_401 again if it is stopped */
267 span_log(&s->logging,
268 SPAN_LOG_FLOW,
269 "-- Something left to transmit (%d). Restarting timer T_401\n",
270 s->txqueue->frame[1] >> 1);
271 if (s->t401_timer < 0)
272 {
273 fprintf(stderr, "Setting T401 b [%p]\n", (void *) s);
274 s->t401_timer = span_schedule_event(&s->sched, T_401, t401_expired, s);
275 }
276 /*endif*/
277 }
278 else
279 {
280 span_log(&s->logging, SPAN_LOG_FLOW, "-- Nothing left, starting timer T_403\n");
281 /* Nothing to transmit. Start timer T_403. */
282 fprintf(stderr, "Setting T403 c\n");
283 s->t403_timer = span_schedule_event(&s->sched, T_403, t403_expired, s);
284 }
285 /*endif*/
286 }
287 /*- End of function --------------------------------------------------------*/
288
289 static void lapm_reject(lapm_state_t *s)
290 {
291 uint8_t frame[4];
292
293 lapm_init_header(frame, !s->we_are_originator);
294 frame[1] = (uint8_t) (0x00 | 0x08 | LAPM_FRAMETYPE_S);
295 /* Where to start retransmission */
296 frame[2] = (uint8_t) ((s->next_expected_frame << 1) | 0x01);
297 span_log(&s->logging, SPAN_LOG_FLOW, "Sending REJ (reject (%d)\n", s->next_expected_frame);
298 lapm_tx_frame(s, frame, 4);
299 }
300 /*- End of function --------------------------------------------------------*/
301
302 static void lapm_rr(lapm_state_t *s, int pfbit)
303 {
304 uint8_t frame[4];
305
306 lapm_init_header(frame, !s->we_are_originator);
307 frame[1] = (uint8_t) (0x00 | 0x00 | LAPM_FRAMETYPE_S);
308 frame[2] = (uint8_t) ((s->next_expected_frame << 1) | pfbit);
309 /* Note that we have already ACKed this */
310 s->last_frame_we_acknowledged = s->next_expected_frame;
311 span_log(&s->logging, SPAN_LOG_FLOW, "Sending RR (receiver ready) (%d)\n", s->next_expected_frame);
312 lapm_tx_frame(s, frame, 4);
313 }
314 /*- End of function --------------------------------------------------------*/
315
316 static void t401_expired(span_sched_state_t *ss, void *user_data)
317 {
318 lapm_state_t *s;
319
320 s = (lapm_state_t *) user_data;
321 fprintf(stderr, "Expiring T401 a4 [%p]\n", (void *) s);
322 s->t401_timer = -1;
323 if (s->txqueue)
324 {
325 /* Retransmit first packet in the queue, setting the poll bit */
326 span_log(&s->logging, SPAN_LOG_FLOW, "-- Timer T_401 expired, What to do...\n");
327 /* Update N(R), and set the poll bit */
328 s->txqueue->frame[2] = (uint8_t)((s->next_expected_frame << 1) | 0x01);
329 s->last_frame_we_acknowledged = s->next_expected_frame;
330 s->solicit_f_bit = TRUE;
331 if (++s->retransmissions <= N_400)
332 {
333 /* Reschedule timer T401 */
334 span_log(&s->logging, SPAN_LOG_FLOW, "-- Retransmitting %d bytes\n", s->txqueue->len);
335 lapm_tx_frame(s, s->txqueue->frame, s->txqueue->len);
336 span_log(&s->logging, SPAN_LOG_FLOW, "-- Scheduling retransmission (%d)\n", s->retransmissions);
337 fprintf(stderr, "Setting T401 d [%p]\n", (void *) s);
338 s->t401_timer = span_schedule_event(&s->sched, T_401, t401_expired, s);
339 }
340 else
341 {
342 span_log(&s->logging, SPAN_LOG_FLOW, "-- Timeout occured\n");
343 s->state = LAPM_RELEASE;
344 if (s->status_callback)
345 s->status_callback(s->status_callback_user_data, s->state);
346 lapm_link_down(s);
347 lapm_restart(s);
348 }
349 /*endif*/
350 }
351 else
352 {
353 span_log(&s->logging, SPAN_LOG_FLOW, "Timer T_401 expired. Nothing to send...\n");
354 }
355 /*endif*/
356 }
357 /*- End of function --------------------------------------------------------*/
358
359 SPAN_DECLARE(const char *) lapm_status_to_str(int status)
360 {
361 switch (status)
362 {
363 case LAPM_DETECT:
364 return "LAPM_DETECT";
365 case LAPM_ESTABLISH:
366 return "LAPM_ESTABLISH";
367 case LAPM_DATA:
368 return "LAPM_DATA";
369 case LAPM_RELEASE:
370 return "LAPM_RELEASE";
371 case LAPM_SIGNAL:
372 return "LAPM_SIGNAL";
373 case LAPM_SETPARM:
374 return "LAPM_SETPARM";
375 case LAPM_TEST:
376 return "LAPM_TEST";
377 case LAPM_UNSUPPORTED:
378 return "LAPM_UNSUPPORTED";
379 }
380 /*endswitch*/
381 return "???";
382 }
383 /*- End of function --------------------------------------------------------*/
384
385 SPAN_DECLARE(int) lapm_tx(lapm_state_t *s, const void *buf, int len)
386 {
387 return queue_write(s->tx_queue, buf, len);
388 }
389 /*- End of function --------------------------------------------------------*/
390
391 SPAN_DECLARE(int) lapm_release(lapm_state_t *s)
392 {
393 s->state = LAPM_RELEASE;
394 return 0;
395 }
396 /*- End of function --------------------------------------------------------*/
397
398 SPAN_DECLARE(int) lapm_loopback(lapm_state_t *s, int enable)
399 {
400 s->state = LAPM_TEST;
401 return 0;
402 }
403 /*- End of function --------------------------------------------------------*/
404
405 SPAN_DECLARE(int) lapm_break(lapm_state_t *s, int enable)
406 {
407 s->state = LAPM_SIGNAL;
408 return 0;
409 }
410 /*- End of function --------------------------------------------------------*/
411
412 SPAN_DECLARE(int) lapm_tx_iframe(lapm_state_t *s, const void *buf, int len, int cr)
413 {
414 lapm_frame_queue_t *f;
415
416 if ((f = malloc(sizeof(*f) + len + 4)) == NULL)
417 {
418 span_log(&s->logging, SPAN_LOG_FLOW, "Out of memory\n");
419 return -1;
420 }
421 /*endif*/
422
423 lapm_init_header(f->frame, (s->peer_is_originator) ? cr : !cr);
424 f->next = NULL;
425 f->len = len + 4;
426 f->frame[1] = (uint8_t) (s->next_tx_frame << 1);
427 f->frame[2] = (uint8_t) (s->next_expected_frame << 1);
428 memcpy(f->frame + 3, buf, len);
429 s->next_tx_frame = (s->next_tx_frame + 1) & 0x7F;
430 s->last_frame_we_acknowledged = s->next_expected_frame;
431 /* Clear poll bit */
432 f->frame[2] &= ~0x01;
433 if (s->tx_last)
434 s->tx_last->next = f;
435 else
436 s->txqueue = f;
437 /*endif*/
438 s->tx_last = f;
439 /* Immediately transmit unless we're in a recovery state */
440 if (s->retransmissions == 0)
441 lapm_tx_frame(s, f->frame, f->len);
442 /*endif*/
443 if (s->t403_timer >= 0)
444 {
445 span_log(&s->logging, SPAN_LOG_FLOW, "Stopping T_403 timer\n");
446 fprintf(stderr, "Deleting T403 c %d\n", s->t403_timer);
447 span_schedule_del(&s->sched, s->t403_timer);
448 s->t403_timer = -1;
449 }
450 /*endif*/
451 if (s->t401_timer < 0)
452 {
453 span_log(&s->logging, SPAN_LOG_FLOW, "Starting timer T_401\n");
454 s->t401_timer = span_schedule_event(&s->sched, T_401, t401_expired, s);
455 fprintf(stderr, "Setting T401 e %d [%p]\n", s->t401_timer, (void *) s);
456 }
457 else
458 {
459 span_log(&s->logging, SPAN_LOG_FLOW, "Timer T_401 already running (%d)\n", s->t401_timer);
460 }
461 /*endif*/
462 return 0;
463 }
464 /*- End of function --------------------------------------------------------*/
465
466 static void t403_expired(span_sched_state_t *ss, void *user_data)
467 {
468 lapm_state_t *s;
469
470 s = (lapm_state_t *) user_data;
471 span_log(&s->logging, SPAN_LOG_FLOW, "Timer T_403 expired. Sending RR and scheduling T_403 again\n");
472 s->t403_timer = -1;
473 s->retransmissions = 0;
474 /* Solicit an F-bit in the other end's RR */
475 s->solicit_f_bit = TRUE;
476 lapm_rr(s, 1);
477 /* Restart ourselves */
478 fprintf(stderr, "Setting T403 f\n");
479 s->t401_timer = span_schedule_event(&s->sched, T_401, t401_expired, s);
480 }
481 /*- End of function --------------------------------------------------------*/
482
483 SPAN_DECLARE(void) lapm_dump(lapm_state_t *s, const uint8_t *frame, int len, int showraw, int txrx)
484 {
485 const char *type;
486 char direction_tag[2];
487
488 direction_tag[0] = txrx ? '>' : '<';
489 direction_tag[1] = '\0';
490 if (showraw)
491 span_log_buf(&s->logging, SPAN_LOG_FLOW, direction_tag, frame, len);
492 /*endif*/
493
494 switch ((frame[1] & LAPM_FRAMETYPE_MASK))
495 {
496 case LAPM_FRAMETYPE_I:
497 case LAPM_FRAMETYPE_I_ALT:
498 span_log(&s->logging, SPAN_LOG_FLOW, "%c Information frame:\n", direction_tag[0]);
499 break;
500 case LAPM_FRAMETYPE_S:
501 span_log(&s->logging, SPAN_LOG_FLOW, "%c Supervisory frame:\n", direction_tag[0]);
502 break;
503 case LAPM_FRAMETYPE_U:
504 span_log(&s->logging, SPAN_LOG_FLOW, "%c Unnumbered frame:\n", direction_tag[0]);
505 break;
506 }
507 /*endswitch*/
508
509 span_log(&s->logging,
510 SPAN_LOG_FLOW,
511 "%c DLCI: %2d C/R: %d EA: %d\n",
512 direction_tag[0],
513 (frame[0] >> 2),
514 (frame[0] & 0x02) ? 1 : 0,
515 (frame[0] & 0x01),
516 direction_tag[0]);
517 switch ((frame[1] & LAPM_FRAMETYPE_MASK))
518 {
519 case LAPM_FRAMETYPE_I:
520 case LAPM_FRAMETYPE_I_ALT:
521 /* Information frame */
522 span_log(&s->logging,
523 SPAN_LOG_FLOW,
524 "%c N(S): %03d\n",
525 direction_tag[0],
526 (frame[1] >> 1));
527 span_log(&s->logging,
528 SPAN_LOG_FLOW,
529 "%c N(R): %03d P: %d\n",
530 direction_tag[0],
531 (frame[2] >> 1),
532 (frame[2] & 0x01));
533 span_log(&s->logging,
534 SPAN_LOG_FLOW,
535 "%c %d bytes of data\n",
536 direction_tag[0],
537 len - 4);
538 break;
539 case LAPM_FRAMETYPE_S:
540 /* Supervisory frame */
541 switch (frame[1] & 0x0C)
542 {
543 case 0x00:
544 type = "RR (receive ready)";
545 break;
546 case 0x04:
547 type = "RNR (receive not ready)";
548 break;
549 case 0x08:
550 type = "REJ (reject)";
551 break;
552 case 0x0C:
553 type = "SREJ (selective reject)";
554 break;
555 default:
556 type = "???";
557 break;
558 }
559 /*endswitch*/
560 span_log(&s->logging,
561 SPAN_LOG_FLOW,
562 "%c S: %03d [ %s ]\n",
563 direction_tag[0],
564 frame[1],
565 type);
566 span_log(&s->logging,
567 SPAN_LOG_FLOW,
568 "%c N(R): %03d P/F: %d\n",
569 direction_tag[0],
570 frame[2] >> 1,
571 frame[2] & 0x01);
572 span_log(&s->logging,
573 SPAN_LOG_FLOW,
574 "%c %d bytes of data\n",
575 direction_tag[0],
576 len - 4);
577 break;
578 case LAPM_FRAMETYPE_U:
579 /* Unnumbered frame */
580 switch (frame[1] & 0xEC)
581 {
582 case 0x00:
583 type = "UI (unnumbered information)";
584 break;
585 case 0x0C:
586 type = "DM (disconnect mode)";
587 break;
588 case 0x40:
589 type = "DISC (disconnect)";
590 break;
591 case 0x60:
592 type = "UA (unnumbered acknowledgement)";
593 break;
594 case 0x6C:
595 type = "SABME (set asynchronous balanced mode extended)";
596 break;
597 case 0x84:
598 type = "FRMR (frame reject)";
599 break;
600 case 0xAC:
601 type = "XID (exchange identification)";
602 break;
603 case 0xE0:
604 type = "TEST (test)";
605 break;
606 default:
607 type = "???";
608 break;
609 }
610 /*endswitch*/
611 span_log(&s->logging,
612 SPAN_LOG_FLOW,
613 "%c M: %03d [ %s ] P/F: %d\n",
614 direction_tag[0],
615 frame[1],
616 type,
617 (frame[1] >> 4) & 1);
618 span_log(&s->logging,
619 SPAN_LOG_FLOW,
620 "%c %d bytes of data\n",
621 direction_tag[0],
622 len - 3);
623 break;
624 }
625 /*endswitch*/
626 }
627 /*- End of function --------------------------------------------------------*/
628
629 static void lapm_link_up(lapm_state_t *s)
630 {
631 uint8_t buf[1024];
632 int len;
633
634 lapm_reset(s);
635 /* Go into connection established state */
636 s->state = LAPM_DATA;
637 if (s->status_callback)
638 s->status_callback(s->status_callback_user_data, s->state);
639 /*endif*/
640 if (!queue_empty(s->tx_queue))
641 {
642 if ((len = queue_read(s->tx_queue, buf, s->n401)) > 0)
643 lapm_tx_iframe(s, buf, len, TRUE);
644 /*endif*/
645 }
646 /*endif*/
647 if (s->t401_timer >= 0)
648 {
649 fprintf(stderr, "Deleting T401 x [%p] %d\n", (void *) s, s->t401_timer);
650 span_schedule_del(&s->sched, s->t401_timer);
651 s->t401_timer = -1;
652 }
653 /*endif*/
654 /* Start the T403 timer */
655 fprintf(stderr, "Setting T403 g\n");
656 s->t403_timer = span_schedule_event(&s->sched, T_403, t403_expired, s);
657 }
658 /*- End of function --------------------------------------------------------*/
659
660 static void lapm_link_down(lapm_state_t *s)
661 {
662 lapm_reset(s);
663
664 if (s->status_callback)
665 s->status_callback(s->status_callback_user_data, s->state);
666 /*endif*/
667 }
668 /*- End of function --------------------------------------------------------*/
669
670 SPAN_DECLARE(void) lapm_reset(lapm_state_t *s)
671 {
672 lapm_frame_queue_t *f;
673 lapm_frame_queue_t *p;
674
675 /* Having received a SABME, we need to reset our entire state */
676 s->next_tx_frame = 0;
677 s->last_frame_peer_acknowledged = 0;
678 s->next_expected_frame = 0;
679 s->last_frame_we_acknowledged = 0;
680 s->window_size_k = 15;
681 s->n401 = 128;
682 if (s->t401_timer >= 0)
683 {
684 fprintf(stderr, "Deleting T401 d [%p] %d\n", (void *) s, s->t401_timer);
685 span_schedule_del(&s->sched, s->t401_timer);
686 s->t401_timer = -1;
687 }
688 /*endif*/
689 if (s->t403_timer >= 0)
690 {
691 fprintf(stderr, "Deleting T403 e %d\n", s->t403_timer);
692 span_schedule_del(&s->sched, s->t403_timer);
693 s->t403_timer = -1;
694 }
695 /*endif*/
696 s->busy = FALSE;
697 s->solicit_f_bit = FALSE;
698 s->state = LAPM_RELEASE;
699 s->retransmissions = 0;
700 /* Discard anything waiting to go out */
701 for (f = s->txqueue; f; )
702 {
703 p = f;
704 f = f->next;
705 free(p);
706 }
707 /*endfor*/
708 s->txqueue = NULL;
709 }
710 /*- End of function --------------------------------------------------------*/
711
712 SPAN_DECLARE_NONSTD(void) lapm_receive(void *user_data, const uint8_t *frame, int len, int ok)
713 {
714 lapm_state_t *s;
715 lapm_frame_queue_t *f;
716 int sendnow;
717 int octet;
718 int s_field;
719 int m_field;
720
721 fprintf(stderr, "LAPM receive %d %d\n", ok, len);
722 if (!ok || len == 0)
723 return;
724 /*endif*/
725 s = (lapm_state_t *) user_data;
726 if (len < 0)
727 {
728 /* Special conditions */
729 span_log(&s->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(len), len);
730 return;
731 }
732 /*endif*/
733
734 if ((s->debug & LAPM_DEBUG_LAPM_DUMP))
735 lapm_dump(s, frame, len, s->debug & LAPM_DEBUG_LAPM_RAW, FALSE);
736 /*endif*/
737 octet = 0;
738 /* We do not expect extended addresses */
739 if ((frame[octet] & 0x01) == 0)
740 return;
741 /*endif*/
742 /* Check for DLCIs we do not recognise */
743 if ((frame[octet] >> 2) != LAPM_DLCI_DTE_TO_DTE)
744 return;
745 /*endif*/
746 octet++;
747 switch (frame[octet] & LAPM_FRAMETYPE_MASK)
748 {
749 case LAPM_FRAMETYPE_I:
750 case LAPM_FRAMETYPE_I_ALT:
751 if (s->state != LAPM_DATA)
752 {
753 span_log(&s->logging, SPAN_LOG_FLOW, "!! Got an I-frame while link state is %d\n", s->state);
754 break;
755 }
756 /*endif*/
757 /* Information frame */
758 if (len < 4)
759 {
760 span_log(&s->logging, SPAN_LOG_FLOW, "!! Received short I-frame (expected 4, got %d)\n", len);
761 break;
762 }
763 /*endif*/
764 /* Make sure this is a valid packet */
765 if ((frame[1] >> 1) == s->next_expected_frame)
766 {
767 /* Increment next expected I-frame */
768 s->next_expected_frame = (s->next_expected_frame + 1) & 0x7F;
769 /* Handle their ACK */
770 lapm_ack_rx(s, frame[2] >> 1);
771 if ((frame[2] & 0x01))
772 {
773 /* If the Poll/Final bit is set, send the RR immediately */
774 lapm_rr(s, 1);
775 }
776 /*endif*/
777 s->iframe_receive(s->iframe_receive_user_data, frame + 3, len - 4);
778 /* Send an RR if one wasn't sent already */
779 if (s->last_frame_we_acknowledged != s->next_expected_frame)
780 lapm_rr(s, 0);
781 /*endif*/
782 }
783 else
784 {
785 if (((s->next_expected_frame - (frame[1] >> 1)) & 127) < s->window_size_k)
786 {
787 /* It's within our window -- send back an RR */
788 lapm_rr(s, 0);
789 }
790 else
791 {
792 lapm_reject(s);
793 }
794 /*endif*/
795 }
796 /*endif*/
797 break;
798 case LAPM_FRAMETYPE_S:
799 if (s->state != LAPM_DATA)
800 {
801 span_log(&s->logging, SPAN_LOG_FLOW, "!! Got S-frame while link down\n");
802 break;
803 }
804 /*endif*/
805 if (len < 4)
806 {
807 span_log(&s->logging, SPAN_LOG_FLOW, "!! Received short S-frame (expected 4, got %d)\n", len);
808 break;
809 }
810 /*endif*/
811 s_field = frame[octet] & 0xEC;
812 switch (s_field)
813 {
814 case 0x00:
815 /* RR (receive ready) */
816 s->busy = FALSE;
817 /* Acknowledge frames as necessary */
818 lapm_ack_rx(s, frame[2] >> 1);
819 if ((frame[2] & 0x01))
820 {
821 /* If P/F is one, respond with an RR with the P/F bit set */
822 if (s->solicit_f_bit)
823 {
824 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got RR response to our frame\n");
825 }
826 else
827 {
828 span_log(&s->logging, SPAN_LOG_FLOW, "-- Unsolicited RR with P/F bit, responding\n");
829 lapm_rr(s, 1);
830 }
831 /*endif*/
832 s->solicit_f_bit = FALSE;
833 }
834 /*endif*/
835 break;
836 case 0x04:
837 /* RNR (receive not ready) */
838 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got receiver not ready\n");
839 s->busy = TRUE;
840 break;
841 case 0x08:
842 /* REJ (reject) */
843 /* Just retransmit */
844 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got reject requesting packet %d... Retransmitting.\n", frame[2] >> 1);
845 if ((frame[2] & 0x01))
846 {
847 /* If it has the poll bit set, send an appropriate supervisory response */
848 lapm_rr(s, 1);
849 }
850 /*endif*/
851 sendnow = FALSE;
852 /* Resend the appropriate I-frame */
853 for (f = s->txqueue; f; f = f->next)
854 {
855 if (sendnow || (f->frame[1] >> 1) == (frame[2] >> 1))
856 {
857 /* Matches the request, or follows in our window */
858 sendnow = TRUE;
859 span_log(&s->logging,
860 SPAN_LOG_FLOW,
861 "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n",
862 frame[2] >> 1,
863 f->frame[1] >> 1);
864 f->frame[2] = (uint8_t) (s->next_expected_frame << 1);
865 lapm_tx_frame(s, f->frame, f->len);
866 }
867 /*endif*/
868 }
869 /*endfor*/
870 if (!sendnow)
871 {
872 if (s->txqueue)
873 {
874 /* This should never happen */
875 if ((frame[2] & 0x01) == 0 || (frame[2] >> 1))
876 {
877 span_log(&s->logging,
878 SPAN_LOG_FLOW,
879 "!! Got reject for frame %d, but we only have others!\n",
880 frame[2] >> 1);
881 }
882 /*endif*/
883 }
884 else
885 {
886 /* Hrm, we have nothing to send, but have been REJ'd. Reset last_frame_peer_acknowledged, next_tx_frame, etc */
887 span_log(&s->logging, SPAN_LOG_FLOW, "!! Got reject for frame %d, but we have nothing -- resetting!\n", frame[2] >> 1);
888 s->last_frame_peer_acknowledged =
889 s->next_tx_frame = frame[2] >> 1;
890 /* Reset t401 timer if it was somehow going */
891 if (s->t401_timer >= 0)
892 {
893 fprintf(stderr, "Deleting T401 f [%p] %d\n", (void *) s, s->t401_timer);
894 span_schedule_del(&s->sched, s->t401_timer);
895 s->t401_timer = -1;
896 }
897 /*endif*/
898 /* Reset and restart t403 timer */
899 if (s->t403_timer >= 0)
900 {
901 fprintf(stderr, "Deleting T403 g %d\n", s->t403_timer);
902 span_schedule_del(&s->sched, s->t403_timer);
903 s->t403_timer = -1;
904 }
905 /*endif*/
906 fprintf(stderr, "Setting T403 h\n");
907 s->t403_timer = span_schedule_event(&s->sched, T_403, t403_expired, s);
908 }
909 /*endif*/
910 }
911 /*endif*/
912 break;
913 case 0x0C:
914 /* SREJ (selective reject) */
915 break;
916 default:
917 span_log(&s->logging,
918 SPAN_LOG_FLOW,
919 "!! XXX Unknown Supervisory frame sd=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n",
920 s_field,
921 frame[2] & 0x01,
922 frame[2] >> 1,
923 s->next_tx_frame,
924 s->last_frame_peer_acknowledged);
925 break;
926 }
927 /*endswitch*/
928 break;
929 case LAPM_FRAMETYPE_U:
930 if (len < 3)
931 {
932 span_log(&s->logging, SPAN_LOG_FLOW, "!! Received too short unnumbered frame\n");
933 break;
934 }
935 /*endif*/
936 m_field = frame[octet] & 0xEC;
937 switch (m_field)
938 {
939 case 0x00:
940 /* UI (unnumbered information) */
941 switch (frame[++octet] & 0x7F)
942 {
943 case 0x40:
944 /* BRK */
945 span_log(&s->logging, SPAN_LOG_FLOW, "BRK - option %d, length %d\n", (frame[octet] >> 5), frame[octet + 1]);
946 octet += 2;
947 break;
948 case 0x60:
949 /* BRKACK */
950 span_log(&s->logging, SPAN_LOG_FLOW, "BRKACK\n");
951 break;
952 default:
953 /* Unknown */
954 span_log(&s->logging, SPAN_LOG_FLOW, "Unknown UI type\n");
955 break;
956 }
957 /*endswitch*/
958 break;
959 case 0x0C:
960 /* DM (disconnect mode) */
961 if ((frame[octet] & 0x10))
962 {
963 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got Unconnected Mode from peer.\n");
964 /* Disconnected mode, try again */
965 lapm_link_down(s);
966 lapm_restart(s);
967 }
968 else
969 {
970 span_log(&s->logging, SPAN_LOG_FLOW, "-- DM (disconnect mode) requesting SABME, starting.\n");
971 /* Requesting that we start */
972 lapm_restart(s);
973 }
974 /*endif*/
975 break;
976 case 0x40:
977 /* DISC (disconnect) */
978 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got DISC (disconnect) from peer.\n");
979 /* Acknowledge */
980 lapm_send_ua(s, (frame[octet] & 0x10));
981 lapm_link_down(s);
982 break;
983 case 0x60:
984 /* UA (unnumbered acknowledgement) */
985 if (s->state == LAPM_ESTABLISH)
986 {
987 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got UA (unnumbered acknowledgement) from %s peer. Link up.\n", (frame[0] & 0x02) ? "xxx" : "yyy");
988 lapm_link_up(s);
989 }
990 else
991 {
992 span_log(&s->logging, SPAN_LOG_FLOW, "!! Got a UA (unnumbered acknowledgement) in state %d\n", s->state);
993 }
994 /*endif*/
995 break;
996 case 0x6C:
997 /* SABME (set asynchronous balanced mode extended) */
998 span_log(&s->logging, SPAN_LOG_FLOW, "-- Got SABME (set asynchronous balanced mode extended) from %s peer.\n", (frame[0] & 0x02) ? "yyy" : "xxx");
999 if ((frame[0] & 0x02))
1000 {
1001 s->peer_is_originator = TRUE;
1002 if (s->we_are_originator)
1003 {
1004 /* We can't both be originators */
1005 span_log(&s->logging, SPAN_LOG_FLOW, "We think we are the originator, but they think so too.");
1006 break;
1007 }
1008 /*endif*/
1009 }
1010 else
1011 {
1012 s->peer_is_originator = FALSE;
1013 if (!s->we_are_originator)
1014 {
1015 /* We can't both be answerers */
1016 span_log(&s->logging, SPAN_LOG_FLOW, "We think we are the answerer, but they think so too.\n");
1017 break;
1018 }
1019 /*endif*/
1020 }
1021 /*endif*/
1022 /* Send unnumbered acknowledgement */
1023 lapm_send_ua(s, (frame[octet] & 0x10));
1024 lapm_link_up(s);
1025 break;
1026 case 0x84:
1027 /* FRMR (frame reject) */
1028 span_log(&s->logging, SPAN_LOG_FLOW, "!! FRMR (frame reject).\n");
1029 break;
1030 case 0xAC:
1031 /* XID (exchange identification) */
1032 span_log(&s->logging, SPAN_LOG_FLOW, "!! XID (exchange identification) frames not supported\n");
1033 break;
1034 case 0xE0:
1035 /* TEST (test) */
1036 span_log(&s->logging, SPAN_LOG_FLOW, "!! TEST (test) frames not supported\n");
1037 break;
1038 default:
1039 span_log(&s->logging, SPAN_LOG_FLOW, "!! Don't know what to do with M=%X u-frames\n", m_field);
1040 break;
1041 }
1042 /*endswitch*/
1043 break;
1044 }
1045 /*endswitch*/
1046 }
1047 /*- End of function --------------------------------------------------------*/
1048
1049 static void lapm_hdlc_underflow(void *user_data)
1050 {
1051 lapm_state_t *s;
1052 uint8_t buf[1024];
1053 int len;
1054
1055 s = (lapm_state_t *) user_data;
1056 span_log(&s->logging, SPAN_LOG_FLOW, "HDLC underflow\n");
1057 if (s->state == LAPM_DATA)
1058 {
1059 if (!queue_empty(s->tx_queue))
1060 {
1061 if ((len = queue_read(s->tx_queue, buf, s->n401)) > 0)
1062 lapm_tx_iframe(s, buf, len, TRUE);
1063 /*endif*/
1064 }
1065 /*endif*/
1066 }
1067 /*endif*/
1068 }
1069 /*- End of function --------------------------------------------------------*/
1070
1071 SPAN_DECLARE(void) lapm_restart(lapm_state_t *s)
1072 {
1073 #if 0
1074 if (s->state != LAPM_RELEASE)
1075 {
1076 span_log(&s->logging, SPAN_LOG_FLOW, "!! lapm_restart: Not in 'Link Connection Released' state\n");
1077 return;
1078 }
1079 /*endif*/
1080 #endif
1081 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
1082 span_log_set_protocol(&s->logging, "LAP.M");
1083 hdlc_tx_init(&s->hdlc_tx, FALSE, 1, TRUE, lapm_hdlc_underflow, s);
1084 hdlc_rx_init(&s->hdlc_rx, FALSE, FALSE, 1, lapm_receive, s);
1085 /* TODO: This is a bodge! */
1086 s->t401_timer = -1;
1087 s->t402_timer = -1;
1088 s->t403_timer = -1;
1089 lapm_reset(s);
1090 /* TODO: Maybe we should implement T_WAIT? */
1091 lapm_send_sabme(NULL, s);
1092 }
1093 /*- End of function --------------------------------------------------------*/
1094
1095 #if 0
1096 static void lapm_init(lapm_state_t *s)
1097 {
1098 lapm_restart(s);
1099 }
1100 /*- End of function --------------------------------------------------------*/
1101 #endif
1102
1103 static void negotiation_rx_bit(v42_state_t *s, int new_bit)
1104 {
1105 /* DC1 with even parity, 8-16 ones, DC1 with odd parity, 8-16 ones */
1106 //uint8_t odp = "0100010001 11111111 0100010011 11111111";
1107 /* V.42 OK E , 8-16 ones, C, 8-16 ones */
1108 //uint8_t adp_v42 = "0101000101 11111111 0110000101 11111111";
1109 /* V.42 disabled E, 8-16 ones, NULL, 8-16 ones */
1110 //uint8_t adp_nov42 = "0101000101 11111111 0000000001 11111111";
1111
1112 /* There may be no negotiation, so we need to process this data through the
1113 HDLC receiver as well */
1114 if (new_bit < 0)
1115 {
1116 /* Special conditions */
1117 span_log(&s->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(new_bit), new_bit);
1118 return;
1119 }
1120 /*endif*/
1121 new_bit &= 1;
1122 s->rxstream = (s->rxstream << 1) | new_bit;
1123 switch (s->rx_negotiation_step)
1124 {
1125 case 0:
1126 /* Look for some ones */
1127 if (new_bit)
1128 break;
1129 /*endif*/
1130 s->rx_negotiation_step = 1;
1131 s->rxbits = 0;
1132 s->rxstream = ~1;
1133 s->rxoks = 0;
1134 break;
1135 case 1:
1136 /* Look for the first character */
1137 if (++s->rxbits < 9)
1138 break;
1139 /*endif*/
1140 s->rxstream &= 0x3FF;
1141 if (s->calling_party && s->rxstream == 0x145)
1142 {
1143 s->rx_negotiation_step++;
1144 }
1145 else if (!s->calling_party && s->rxstream == 0x111)
1146 {
1147 s->rx_negotiation_step++;
1148 }
1149 else
1150 {
1151 s->rx_negotiation_step = 0;
1152 }
1153 /*endif*/
1154 s->rxbits = 0;
1155 s->rxstream = ~0;
1156 break;
1157 case 2:
1158 /* Look for 8 to 16 ones */
1159 s->rxbits++;
1160 if (new_bit)
1161 break;
1162 /*endif*/
1163 if (s->rxbits >= 8 && s->rxbits <= 16)
1164 s->rx_negotiation_step++;
1165 else
1166 s->rx_negotiation_step = 0;
1167 /*endif*/
1168 s->rxbits = 0;
1169 s->rxstream = ~1;
1170 break;
1171 case 3:
1172 /* Look for the second character */
1173 if (++s->rxbits < 9)
1174 break;
1175 /*endif*/
1176 s->rxstream &= 0x3FF;
1177 if (s->calling_party && s->rxstream == 0x185)
1178 {
1179 s->rx_negotiation_step++;
1180 }
1181 else if (s->calling_party && s->rxstream == 0x001)
1182 {
1183 s->rx_negotiation_step++;
1184 }
1185 else if (!s->calling_party && s->rxstream == 0x113)
1186 {
1187 s->rx_negotiation_step++;
1188 }
1189 else
1190 {
1191 s->rx_negotiation_step = 0;
1192 }
1193 /*endif*/
1194 s->rxbits = 0;
1195 s->rxstream = ~0;
1196 break;
1197 case 4:
1198 /* Look for 8 to 16 ones */
1199 s->rxbits++;
1200 if (new_bit)
1201 break;
1202 /*endif*/
1203 if (s->rxbits >= 8 && s->rxbits <= 16)
1204 {
1205 if (++s->rxoks >= 2)
1206 {
1207 /* HIT */
1208 s->rx_negotiation_step++;
1209 if (s->calling_party)
1210 {
1211 if (s->t400_timer >= 0)
1212 {
1213 fprintf(stderr, "Deleting T400 h %d\n", s->t400_timer);
1214 span_schedule_del(&s->lapm.sched, s->t400_timer);
1215 s->t400_timer = -1;
1216 }
1217 /*endif*/
1218 s->lapm.state = LAPM_ESTABLISH;
1219 if (s->lapm.status_callback)
1220 s->lapm.status_callback(s->lapm.status_callback_user_data, s->lapm.state);
1221 /*endif*/
1222 }
1223 else
1224 {
1225 s->odp_seen = TRUE;
1226 }
1227 /*endif*/
1228 break;
1229 }
1230 /*endif*/
1231 s->rx_negotiation_step = 1;
1232 s->rxbits = 0;
1233 s->rxstream = ~1;
1234 }
1235 else
1236 {
1237 s->rx_negotiation_step = 0;
1238 s->rxbits = 0;
1239 s->rxstream = ~0;
1240 }
1241 /*endif*/
1242 break;
1243 case 5:
1244 /* Parked */
1245 break;
1246 }
1247 /*endswitch*/
1248 }
1249 /*- End of function --------------------------------------------------------*/
1250
1251 static int v42_support_negotiation_tx_bit(v42_state_t *s)
1252 {
1253 int bit;
1254
1255 if (s->calling_party)
1256 {
1257 if (s->txbits <= 0)
1258 {
1259 s->txstream = 0x3FE22;
1260 s->txbits = 36;
1261 }
1262 else if (s->txbits == 18)
1263 {
1264 s->txstream = 0x3FF22;
1265 }
1266 /*endif*/
1267 bit = s->txstream & 1;
1268 s->txstream >>= 1;
1269 s->txbits--;
1270 }
1271 else
1272 {
1273 if (s->odp_seen && s->txadps < 10)
1274 {
1275 if (s->txbits <= 0)
1276 {
1277 if (++s->txadps >= 10)
1278 {
1279 if (s->t400_timer >= 0)
1280 {
1281 fprintf(stderr, "Deleting T400 i %d\n", s->t400_timer);
1282 span_schedule_del(&s->lapm.sched, s->t400_timer);
1283 s->t400_timer = -1;
1284 }
1285 /*endif*/
1286 s->lapm.state = LAPM_ESTABLISH;
1287 if (s->lapm.status_callback)
1288 s->lapm.status_callback(s->lapm.status_callback_user_data, s->lapm.state);
1289 /*endif*/
1290 s->txstream = 1;
1291 }
1292 else
1293 {
1294 s->txstream = 0x3FE8A;
1295 s->txbits = 36;
1296 }
1297 /*endif*/
1298 }
1299 else if (s->txbits == 18)
1300 {
1301 s->txstream = 0x3FE86;
1302 }
1303 /*endif*/
1304 bit = s->txstream & 1;
1305 s->txstream >>= 1;
1306 s->txbits--;
1307 }
1308 else
1309 {
1310 bit = 1;
1311 }
1312 /*endif*/
1313 }
1314 /*endif*/
1315 return bit;
1316 }
1317 /*- End of function --------------------------------------------------------*/
1318
1319 SPAN_DECLARE(void) v42_rx_bit(void *user_data, int bit)
1320 {
1321 v42_state_t *s;
1322
1323 s = (v42_state_t *) user_data;
1324 if (s->lapm.state == LAPM_DETECT)
1325 negotiation_rx_bit(s, bit);
1326 else
1327 hdlc_rx_put_bit(&s->lapm.hdlc_rx, bit);
1328 /*endif*/
1329 }
1330 /*- End of function --------------------------------------------------------*/
1331
1332 SPAN_DECLARE(int) v42_tx_bit(void *user_data)
1333 {
1334 v42_state_t *s;
1335 int bit;
1336
1337 s = (v42_state_t *) user_data;
1338 if (s->lapm.state == LAPM_DETECT)
1339 bit = v42_support_negotiation_tx_bit(s);
1340 else
1341 bit = hdlc_tx_get_bit(&s->lapm.hdlc_tx);
1342 /*endif*/
1343 return bit;
1344 }
1345 /*- End of function --------------------------------------------------------*/
1346
1347 SPAN_DECLARE(void) v42_set_status_callback(v42_state_t *s, v42_status_func_t callback, void *user_data)
1348 {
1349 s->lapm.status_callback = callback;
1350 s->lapm.status_callback_user_data = user_data;
1351 }
1352 /*- End of function --------------------------------------------------------*/
1353
1354 SPAN_DECLARE(void) v42_restart(v42_state_t *s)
1355 {
1356 span_schedule_init(&s->lapm.sched);
1357
1358 s->lapm.we_are_originator = s->calling_party;
1359 lapm_restart(&s->lapm);
1360 if (s->detect)
1361 {
1362 s->txstream = ~0;
1363 s->txbits = 0;
1364 s->rxstream = ~0;
1365 s->rxbits = 0;
1366 s->rxoks = 0;
1367 s->txadps = 0;
1368 s->rx_negotiation_step = 0;
1369 s->odp_seen = FALSE;
1370 fprintf(stderr, "Setting T400 i\n");
1371 s->t400_timer = span_schedule_event(&s->lapm.sched, T_400, t400_expired, s);
1372 s->lapm.state = LAPM_DETECT;
1373 }
1374 else
1375 {
1376 s->lapm.state = LAPM_ESTABLISH;
1377 }
1378 /*endif*/
1379 }
1380 /*- End of function --------------------------------------------------------*/
1381
1382 SPAN_DECLARE(v42_state_t *) v42_init(v42_state_t *s, int calling_party, int detect, v42_frame_handler_t frame_handler, void *user_data)
1383 {
1384 int alloced;
1385
1386 if (frame_handler == NULL)
1387 return NULL;
1388 /*endif*/
1389 alloced = FALSE;
1390 if (s == NULL)
1391 {
1392 if ((s = (v42_state_t *) malloc(sizeof(*s))) == NULL)
1393 return NULL;
1394 alloced = TRUE;
1395 }
1396 memset(s, 0, sizeof(*s));
1397 s->calling_party = calling_party;
1398 s->detect = detect;
1399 s->lapm.iframe_receive = frame_handler;
1400 s->lapm.iframe_receive_user_data = user_data;
1401 s->lapm.debug |= (LAPM_DEBUG_LAPM_RAW | LAPM_DEBUG_LAPM_DUMP | LAPM_DEBUG_LAPM_STATE);
1402 s->lapm.t401_timer =
1403 s->lapm.t402_timer =
1404 s->lapm.t403_timer = -1;
1405
1406 if ((s->lapm.tx_queue = queue_init(NULL, 16384, 0)) == NULL)
1407 {
1408 if (alloced)
1409 free(s);
1410 return NULL;
1411 }
1412 /*endif*/
1413 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
1414 span_log_set_protocol(&s->logging, "V.42");
1415 v42_restart(s);
1416 return s;
1417 }
1418 /*- End of function --------------------------------------------------------*/
1419
1420 SPAN_DECLARE(int) v42_release(v42_state_t *s)
1421 {
1422 return 0;
1423 }
1424 /*- End of function --------------------------------------------------------*/
1425
1426 SPAN_DECLARE(int) v42_free(v42_state_t *s)
1427 {
1428 free(s);
1429 return 0;
1430 }
1431 /*- End of function --------------------------------------------------------*/
1432 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.