Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |