Bug Summary

File:libs/spandsp/src/v42.c
Location:line 318, column 21
Description:Value stored to 'param_val' is never read

Annotated Source Code

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, 2011 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
26/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
27
28/*! \file */
29
30#if defined(HAVE_CONFIG_H1)
31#include "config.h"
32#endif
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <inttypes.h>
37#include <string.h>
38#include <errno(*__errno_location ()).h>
39#include <fcntl.h>
40#include <ctype.h>
41#if defined(HAVE_STDBOOL_H1)
42#include <stdbool.h>
43#else
44#include "spandsp/stdbool.h"
45#endif
46#include <assert.h>
47
48#include "spandsp/telephony.h"
49#include "spandsp/alloc.h"
50#include "spandsp/logging.h"
51#include "spandsp/bit_operations.h"
52#include "spandsp/async.h"
53#include "spandsp/hdlc.h"
54#include "spandsp/v42.h"
55
56#include "spandsp/private/logging.h"
57#include "spandsp/private/hdlc.h"
58#include "spandsp/private/v42.h"
59
60/* Detection phase timer */
61#define T_400750 750
62/* Acknowledgement timer - 1 second between SABME's */
63#define T_4011000 1000
64/* Replay delay timer (optional) */
65#define T_4021000 1000
66/* Inactivity timer (optional). No default - use 10 seconds with no packets */
67#define T_40310000 10000
68
69#define LAPM_DLCI_DTE_TO_DTE0 0
70#define LAPM_DLCI_LAYER2_MANAGEMENT63 63
71
72#define elements(a)(sizeof(a)/sizeof((a)[0])) (sizeof(a)/sizeof((a)[0]))
73
74/* LAPM definitions */
75
76#define LAPM_FRAMETYPE_MASK0x03 0x03
77
78enum
79{
80 LAPM_FRAMETYPE_I = 0x00,
81 LAPM_FRAMETYPE_I_ALT = 0x02,
82 LAPM_FRAMETYPE_S = 0x01,
83 LAPM_FRAMETYPE_U = 0x03
84};
85
86/* Supervisory headers */
87enum
88{
89 LAPM_S_RR = 0x00, /* cr */
90 LAPM_S_RNR = 0x04, /* cr */
91 LAPM_S_REJ = 0x08, /* cr */
92 LAPM_S_SREJ = 0x0C /* cr */
93};
94
95#define LAPM_S_PF0x01 0x01
96
97/* Unnumbered headers */
98enum
99{
100 LAPM_U_UI = 0x00, /* cr */
101 LAPM_U_DM = 0x0C, /* r */
102 LAPM_U_DISC = 0x40, /* c */
103 LAPM_U_UA = 0x60, /* r */
104 LAPM_U_SABME = 0x6C, /* c */
105 LAPM_U_FRMR = 0x84, /* r */
106 LAPM_U_XID = 0xAC, /* cr */
107 LAPM_U_TEST = 0xE0 /* c */
108};
109
110#define LAPM_U_PF0x10 0x10
111
112/* XID sub-field definitions */
113#define FI_GENERAL0x82 0x82
114#define GI_PARAM_NEGOTIATION0x80 0x80
115#define GI_PRIVATE_NEGOTIATION0xF0 0xF0
116#define GI_USER_DATA0xFF 0xFF
117
118/* Param negotiation (Table 11a/V.42) */
119enum
120{
121 PI_HDLC_OPTIONAL_FUNCTIONS = 0x03,
122 PI_TX_INFO_MAXSIZE = 0x05,
123 PI_RX_INFO_MAXSIZE = 0x06,
124 PI_TX_WINDOW_SIZE = 0x07,
125 PI_RX_WINDOW_SIZE = 0x08
126};
127
128/* Private param negotiation (Table 11b/V.42) */
129enum
130{
131 PI_PARAMETER_SET_ID = 0x00,
132 PI_V42BIS_COMPRESSION_REQUEST = 0x01,
133 PI_V42BIS_NUM_CODEWORDS = 0x02,
134 PI_V42BIS_MAX_STRING_LENGTH = 0x03
135};
136
137#define LAPM_DLCI_DTE_TO_DTE0 0
138#define LAPM_DLCI_LAYER2_MANAGEMENT63 63
139
140/* Type definitions */
141enum
142{
143 LAPM_DETECT = 0,
144 LAPM_IDLE = 1,
145 LAPM_ESTABLISH = 2,
146 LAPM_DATA = 3,
147 LAPM_RELEASE = 4,
148 LAPM_SIGNAL = 5,
149 LAPM_SETPARM = 6,
150 LAPM_TEST = 7,
151 LAPM_V42_UNSUPPORTED = 8
152};
153
154/* Prototypes */
155static int lapm_connect(v42_state_t *ss);
156static int lapm_disconnect(v42_state_t *s);
157static void reset_lapm(v42_state_t *s);
158static void lapm_hdlc_underflow(void *user_data);
159
160static int lapm_config(v42_state_t *ss);
161
162SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * lapm_status_to_str(int status)
163{
164 switch (status)
165 {
166 case LAPM_DETECT:
167 return "LAPM_DETECT";
168 case LAPM_IDLE:
169 return "LAPM_IDLE";
170 case LAPM_ESTABLISH:
171 return "LAPM_ESTABLISH";
172 case LAPM_DATA:
173 return "LAPM_DATA";
174 case LAPM_RELEASE:
175 return "LAPM_RELEASE";
176 case LAPM_SIGNAL:
177 return "LAPM_SIGNAL";
178 case LAPM_SETPARM:
179 return "LAPM_SETPARM";
180 case LAPM_TEST:
181 return "LAPM_TEST";
182 case LAPM_V42_UNSUPPORTED:
183 return "LAPM_V42_UNSUPPORTED";
184 }
185 /*endswitch*/
186 return "???";
187}
188/*- End of function --------------------------------------------------------*/
189
190static void report_rx_status_change(v42_state_t *s, int status)
191{
192 if (s->lapm.status_handler)
193 s->lapm.status_handler(s->lapm.status_user_data, status);
194 else if (s->lapm.iframe_put)
195 s->lapm.iframe_put(s->lapm.iframe_put_user_data, NULL((void*)0), status);
196}
197/*- End of function --------------------------------------------------------*/
198
199static inline uint32_t pack_value(const uint8_t *buf, int len)
200{
201 uint32_t val;
202
203 val = 0;
204 while (len--)
205 {
206 val <<= 8;
207 val |= *buf++;
208 }
209 return val;
210}
211/*- End of function --------------------------------------------------------*/
212
213static inline v42_frame_t *get_next_free_ctrl_frame(lapm_state_t *s)
214{
215 v42_frame_t *f;
216 int ctrl_put_next;
217
218 if ((ctrl_put_next = s->ctrl_put + 1) >= V42_CTRL_FRAMES8)
219 ctrl_put_next = 0;
220 if (ctrl_put_next == s->ctrl_get)
221 return NULL((void*)0);
222 f = &s->ctrl_buf[s->ctrl_put];
223 s->ctrl_put = ctrl_put_next;
224 return f;
225}
226/*- End of function --------------------------------------------------------*/
227
228static int tx_unnumbered_frame(lapm_state_t *s, uint8_t addr, uint8_t ctrl, uint8_t *info, int len)
229{
230 v42_frame_t *f;
231 uint8_t *buf;
232
233 if ((f = get_next_free_ctrl_frame(s)) == NULL((void*)0))
234 return -1;
235 buf = f->buf;
236 buf[0] = addr;
237 buf[1] = LAPM_FRAMETYPE_U | ctrl;
238 f->len = 2;
239 if (info && len)
240 {
241 memcpy(&buf[f->len], info, len);
242 f->len += len;
243 }
244 return 0;
245}
246/*- End of function --------------------------------------------------------*/
247
248static int tx_supervisory_frame(lapm_state_t *s, uint8_t addr, uint8_t ctrl, uint8_t pf_mask)
249{
250 v42_frame_t *f;
251 uint8_t *buf;
252
253 if ((f = get_next_free_ctrl_frame(s)) == NULL((void*)0))
254 return -1;
255 buf = f->buf;
256 buf[0] = addr;
257 buf[1] = LAPM_FRAMETYPE_S | ctrl;
258 buf[2] = (s->vr << 1) | pf_mask;
259 f->len = 3;
260 return 0;
261}
262/*- End of function --------------------------------------------------------*/
263
264static __inline__ int set_param(int param, int value, int def)
265{
266 if ((value < def && param >= def) || (value >= def && param < def))
267 return def;
268 if ((value < def && param < value) || (value >= def && param > value))
269 return value;
270 return param;
271}
272/*- End of function --------------------------------------------------------*/
273
274static int receive_xid(v42_state_t *ss, const uint8_t *frame, int len)
275{
276 lapm_state_t *s;
277 v42_config_parameters_t config;
278 const uint8_t *buf;
279 uint8_t group_id;
280 uint16_t group_len;
281 uint32_t param_val;
282 uint8_t param_id;
283 uint8_t param_len;
284
285 s = &ss->lapm;
286 if (frame[2] != FI_GENERAL0x82)
287 return -1;
288 memset(&config, 0, sizeof(config));
289 /* Skip the header octets */
290 frame += 3;
291 len -= 3;
292 while (len > 0)
293 {
294 group_id = frame[0];
295 group_len = frame[1];
296 group_len = (group_len << 8) | frame[2];
297 frame += 3;
298 len -= (3 + group_len);
299 if (len < 0)
300 break;
301 buf = frame;
302 frame += group_len;
303 switch (group_id)
304 {
305 case GI_PARAM_NEGOTIATION0x80:
306 while (group_len > 0)
307 {
308 param_id = buf[0];
309 param_len = buf[1];
310 buf += 2;
311 if (group_len < (2 + param_len))
312 break;
313 group_len -= (2 + param_len);
314 switch (param_id)
315 {
316 case PI_HDLC_OPTIONAL_FUNCTIONS:
317 /* TODO: param_val is never used right now. */
318 param_val = pack_value(buf, param_len);
Value stored to 'param_val' is never read
319 break;
320 case PI_TX_INFO_MAXSIZE:
321 param_val = pack_value(buf, param_len);
322 param_val >>= 3;
323 config.v42_tx_n401 =
324 s->tx_n401 = set_param(s->tx_n401, param_val, ss->config.v42_tx_n401);
325 break;
326 case PI_RX_INFO_MAXSIZE:
327 param_val = pack_value(buf, param_len);
328 param_val >>= 3;
329 config.v42_rx_n401 =
330 s->rx_n401 = set_param(s->rx_n401, param_val, ss->config.v42_rx_n401);
331 break;
332 case PI_TX_WINDOW_SIZE:
333 param_val = pack_value(buf, param_len);
334 config.v42_tx_window_size_k =
335 s->tx_window_size_k = set_param(s->tx_window_size_k, param_val, ss->config.v42_tx_window_size_k);
336 break;
337 case PI_RX_WINDOW_SIZE:
338 param_val = pack_value(buf, param_len);
339 config.v42_rx_window_size_k =
340 s->rx_window_size_k = set_param(s->rx_window_size_k, param_val, ss->config.v42_rx_window_size_k);
341 break;
342 default:
343 break;
344 }
345 buf += param_len;
346 }
347 break;
348 case GI_PRIVATE_NEGOTIATION0xF0:
349 while (group_len > 0)
350 {
351 param_id = buf[0];
352 param_len = buf[1];
353 buf += 2;
354 if (group_len < 2 + param_len)
355 break;
356 group_len -= (2 + param_len);
357 switch (param_id)
358 {
359 case PI_PARAMETER_SET_ID:
360 /* This might be worth monitoring, but it doesn't serve mnuch other purpose */
361 break;
362 case PI_V42BIS_COMPRESSION_REQUEST:
363 config.comp = pack_value(buf, param_len);
364 break;
365 case PI_V42BIS_NUM_CODEWORDS:
366 config.comp_dict_size = pack_value(buf, param_len);
367 break;
368 case PI_V42BIS_MAX_STRING_LENGTH:
369 config.comp_max_string = pack_value(buf, param_len);
370 break;
371 default:
372 break;
373 }
374 buf += param_len;
375 }
376 break;
377 default:
378 break;
379 }
380 }
381 //v42_update_config(ss, &config);
382 return 0;
383}
384/*- End of function --------------------------------------------------------*/
385
386static void transmit_xid(v42_state_t *ss, uint8_t addr)
387{
388 lapm_state_t *s;
389 uint8_t *buf;
390 int len;
391 int group_len;
392 uint32_t param_val;
393 v42_frame_t *f;
394
395 s = &ss->lapm;
396 if ((f = get_next_free_ctrl_frame(s)) == NULL((void*)0))
397 return;
398
399 buf = f->buf;
400 len = 0;
401
402 /* Figure 11/V.42 */
403 *buf++ = addr;
404 *buf++ = LAPM_U_XID | LAPM_FRAMETYPE_U;
405 /* Format identifier subfield */
406 *buf++ = FI_GENERAL0x82;
407 len += 3;
408
409 /* Parameter negotiation group */
410 group_len = 20;
411 *buf++ = GI_PARAM_NEGOTIATION0x80;
412 *buf++ = (group_len >> 8) & 0xFF;
413 *buf++ = group_len & 0xFF;
414 len += 3;
415
416 /* For conformance with the encoding rules in ISO/IEC 8885, the transmitter of an XID command frame shall
417 set bit positions 2, 4, 8, 9, 12 and 16 to 1. (Table 11a/V.42)
418 Optional bits are:
419 3 Selective retransmission procedure (SREJ frame) single I frame request
420 14 Loop-back test procedure (TEST frame)
421 17
422 Extended FCS procedure (32-bit FCS)
423 24 Selective retransmission procedure (SREJ frame) multiple I frame request with span list
424 capability. */
425 *buf++ = PI_HDLC_OPTIONAL_FUNCTIONS;
426 *buf++ = 4;
427 *buf++ = 0x8A; /* Bits 2, 4, and 8 set */
428 *buf++ = 0x89; /* Bits 9, 12, and 16 set */
429 *buf++ = 0x00;
430 *buf++ = 0x00;
431
432 /* Send the maximum as a number of bits, rather than octets */
433 param_val = ss->config.v42_tx_n401 << 3;
434 *buf++ = PI_TX_INFO_MAXSIZE;
435 *buf++ = 2;
436 *buf++ = (param_val >> 8) & 0xFF;
437 *buf++ = (param_val & 0xFF);
438
439 /* Send the maximum as a number of bits, rather than octets */
440 param_val = ss->config.v42_rx_n401 << 3;
441 *buf++ = PI_RX_INFO_MAXSIZE;
442 *buf++ = 2;
443 *buf++ = (param_val >> 8) & 0xFF;
444 *buf++ = (param_val & 0xFF);
445
446 *buf++ = PI_TX_WINDOW_SIZE;
447 *buf++ = 1;
448 *buf++ = ss->config.v42_tx_window_size_k;
449
450 *buf++ = PI_RX_WINDOW_SIZE;
451 *buf++ = 1;
452 *buf++ = ss->config.v42_rx_window_size_k;
453
454 len += group_len;
455
456 if (ss->config.comp)
457 {
458 /* Private parameter negotiation group */
459 group_len = 15;
460 *buf++ = GI_PRIVATE_NEGOTIATION0xF0;
461 *buf++ = (group_len >> 8) & 0xFF;
462 *buf++ = group_len & 0xFF;
463 len += 3;
464
465 /* Private parameter for V.42 (ASCII for V42). V.42 says ".42", but V.42bis says "V42",
466 and that seems to be what should be used. */
467 *buf++ = PI_PARAMETER_SET_ID;
468 *buf++ = 3;
469 *buf++ = 'V';
470 *buf++ = '4';
471 *buf++ = '2';
472
473 /* V.42bis P0
474 00 Compression in neither direction (default);
475 01 Negotiation initiator-responder direction only;
476 10 Negotiation responder-initiator direction only;
477 11 Both directions. */
478 *buf++ = PI_V42BIS_COMPRESSION_REQUEST;
479 *buf++ = 1;
480 *buf++ = ss->config.comp;
481
482 /* V.42bis P1 */
483 param_val = ss->config.comp_dict_size;
484 *buf++ = PI_V42BIS_NUM_CODEWORDS;
485 *buf++ = 2;
486 *buf++ = (param_val >> 8) & 0xFF;
487 *buf++ = param_val & 0xFF;
488
489 /* V.42bis P2 */
490 *buf++ = PI_V42BIS_MAX_STRING_LENGTH;
491 *buf++ = 1;
492 *buf++ = ss->config.comp_max_string;
493
494 len += group_len;
495 }
496
497 f->len = len;
498}
499/*- End of function --------------------------------------------------------*/
500
501static int ms_to_bits(v42_state_t *s, int time)
502{
503 return ((time*s->tx_bit_rate)/1000);
504}
505/*- End of function --------------------------------------------------------*/
506
507static void t400_expired(v42_state_t *ss)
508{
509 /* Give up trying to detect a V.42 capable peer. */
510 ss->bit_timer = 0;
511 ss->lapm.state = LAPM_V42_UNSUPPORTED;
512 report_rx_status_change(ss, ss->lapm.state);
513}
514/*- End of function --------------------------------------------------------*/
515
516static __inline__ void t400_start(v42_state_t *s)
517{
518 s->bit_timer = ms_to_bits(s, T_400750);
519 s->bit_timer_func = t400_expired;
520}
521/*- End of function --------------------------------------------------------*/
522
523static __inline__ void t400_stop(v42_state_t *s)
524{
525 s->bit_timer = 0;
526}
527/*- End of function --------------------------------------------------------*/
528
529static void t401_expired(v42_state_t *ss)
530{
531 lapm_state_t *s;
532
533 span_log(&ss->logging, SPAN_LOG_FLOW, "T.401 expired\n");
534 s = &ss->lapm;
535 if (s->retry_count > V42_DEFAULT_N_4005)
536 {
537 s->retry_count = 0;
538 switch (s->state)
539 {
540 case LAPM_ESTABLISH:
541 case LAPM_RELEASE:
542 s->state = LAPM_IDLE;
543 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
544 break;
545 case LAPM_DATA:
546 lapm_disconnect(ss);
547 break;
548 }
549 return ;
550 }
551 s->retry_count++;
552 if (s->configuring)
553 {
554 transmit_xid(ss, s->cmd_addr);
555 }
556 else
557 {
558 switch (s->state)
559 {
560 case LAPM_ESTABLISH:
561 tx_unnumbered_frame(s, s->cmd_addr, LAPM_U_SABME | LAPM_U_PF0x10, NULL((void*)0), 0);
562 break;
563 case LAPM_RELEASE:
564 tx_unnumbered_frame(s, s->cmd_addr, LAPM_U_DISC | LAPM_U_PF0x10, NULL((void*)0), 0);
565 break;
566 case LAPM_DATA:
567 tx_supervisory_frame(s, s->cmd_addr, (s->local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1);
568 break;
569 }
570 }
571 ss->bit_timer = ms_to_bits(ss, T_4011000);
572 ss->bit_timer_func = t401_expired;
573}
574/*- End of function --------------------------------------------------------*/
575
576static __inline__ void t401_start(v42_state_t *s)
577{
578 s->bit_timer = ms_to_bits(s, T_4011000);
579 s->bit_timer_func = t401_expired;
580 s->lapm.retry_count = 0;
581}
582/*- End of function --------------------------------------------------------*/
583
584static __inline__ void t401_stop(v42_state_t *s)
585{
586 s->bit_timer = 0;
587 s->lapm.retry_count = 0;
588}
589/*- End of function --------------------------------------------------------*/
590
591static void t403_expired(v42_state_t *ss)
592{
593 lapm_state_t *s;
594
595 span_log(&ss->logging, SPAN_LOG_FLOW, "T.403 expired\n");
596 if (ss->lapm.state != LAPM_DATA)
597 return;
598 s = &ss->lapm;
599 tx_supervisory_frame(s, s->cmd_addr, (ss->lapm.local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1);
600 t401_start(ss);
601 ss->lapm.retry_count = 1;
602}
603/*- End of function --------------------------------------------------------*/
604
605static __inline__ void t401_stop_t403_start(v42_state_t *s)
606{
607 s->bit_timer = ms_to_bits(s, T_40310000);
608 s->bit_timer_func = t403_expired;
609 s->lapm.retry_count = 0;
610}
611/*- End of function --------------------------------------------------------*/
612
613static void initiate_negotiation_expired(v42_state_t *s)
614{
615 /* Timer service routine */
616 span_log(&s->logging, SPAN_LOG_FLOW, "Start negotiation\n");
617 lapm_config(s);
618 lapm_hdlc_underflow(s);
619}
620/*- End of function --------------------------------------------------------*/
621
622static int tx_information_frame(v42_state_t *ss)
623{
624 lapm_state_t *s;
625 v42_frame_t *f;
626 uint8_t *buf;
627 int n;
628 int info_put_next;
629
630 s = &ss->lapm;
631 if (s->far_busy || ((s->vs - s->va) & 0x7F) >= s->tx_window_size_k)
632 return false0;
633 if (s->info_get != s->info_put)
634 return true1;
635 if ((info_put_next = s->info_put + 1) >= V42_INFO_FRAMES(15 + 1))
636 info_put_next = 0;
637 if (info_put_next == s->info_get || info_put_next == s->info_acked)
638 return false0;
639 f = &s->info_buf[s->info_put];
640 buf = f->buf;
641 if (s->iframe_get == NULL((void*)0))
642 return false0;
643 n = s->iframe_get(s->iframe_get_user_data, buf + 3, s->tx_n401);
644 if (n < 0)
645 {
646 /* Error */
647 report_rx_status_change(ss, SIG_STATUS_LINK_ERROR);
648 return false0;
649 }
650 if (n == 0)
651 return false0;
652
653 f->len = n + 3;
654 s->info_put = info_put_next;
655 return true1;
656}
657/*- End of function --------------------------------------------------------*/
658
659static void tx_information_rr_rnr_response(v42_state_t *ss, const uint8_t *frame, int len)
660{
661 lapm_state_t *s;
662
663 s = &ss->lapm;
664 /* Respond with information frame, RR, or RNR, as appropriate */
665 /* p = 1 may be used for status checking */
666 if ((frame[2] & 0x1) || !tx_information_frame(ss))
667 tx_supervisory_frame(s, frame[0], (s->local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1);
668}
669/*- End of function --------------------------------------------------------*/
670
671static int reject_info(lapm_state_t *s)
672{
673 uint8_t n;
674
675 /* Reject all non-acked frames */
676 if (s->state != LAPM_DATA)
677 return 0;
678 n = (s->vs - s->va) & 0x7F;
679 s->vs = s->va;
680 s->info_get = s->info_acked;
681 return n;
682}
683/*- End of function --------------------------------------------------------*/
684
685static int ack_info(v42_state_t *ss, uint8_t nr)
686{
687 lapm_state_t *s;
688 int n;
689
690 s = &ss->lapm;
691 /* Check that NR is valid - i.e. VA <= NR <= VS && VS-VA <= k */
692 if (!((((nr - s->va) & 0x7F) + ((s->vs - nr) & 0x7F)) <= s->tx_window_size_k
693 &&
694 ((s->vs - s->va) & 0x7F) <= s->tx_window_size_k))
695 {
696 lapm_disconnect(ss);
697 return -1;
698 }
699 n = 0;
700 while (s->va != nr && s->info_acked != s->info_get)
701 {
702 if (++s->info_acked >= V42_INFO_FRAMES(15 + 1))
703 s->info_acked = 0;
704 s->va = (s->va + 1) & 0x7F;
705 n++;
706 }
707 if (n > 0 && s->retry_count == 0)
708 {
709 t401_stop_t403_start(ss);
710 /* 8.4.8 */
711 if (((s->vs - s->va) & 0x7F))
712 t401_start(ss);
713 }
714 return n;
715}
716/*- End of function --------------------------------------------------------*/
717
718static int valid_data_state(v42_state_t *ss)
719{
720 lapm_state_t *s;
721
722 s = &ss->lapm;
723 switch (s->state)
724 {
725 case LAPM_DETECT:
726 case LAPM_IDLE:
727 break;
728 case LAPM_ESTABLISH:
729 reset_lapm(ss);
730 s->state = LAPM_DATA;
731 report_rx_status_change(ss, SIG_STATUS_LINK_CONNECTED);
732 return 1;
733 case LAPM_DATA:
734 return 1;
735 case LAPM_RELEASE:
736 reset_lapm(ss);
737 s->state = LAPM_IDLE;
738 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
739 break;
740 case LAPM_SIGNAL:
741 case LAPM_SETPARM:
742 case LAPM_TEST:
743 case LAPM_V42_UNSUPPORTED:
744 break;
745 }
746 return 0;
747}
748/*- End of function --------------------------------------------------------*/
749
750static void receive_information_frame(v42_state_t *ss, const uint8_t *frame, int len)
751{
752 lapm_state_t *s;
753
754 s = &ss->lapm;
755 if (!valid_data_state(ss))
756 return;
757 if (len > s->rx_n401 + 3)
758 return;
759 /* Ack I frames: NR - 1 */
760 ack_info(ss, frame[2] >> 1);
761 if (s->local_busy)
762 {
763 /* 8.4.7 */
764 if ((frame[2] & 0x1))
765 tx_supervisory_frame(s, s->rsp_addr, LAPM_S_RNR, 1);
766 return;
767 }
768 /* NS sequence error */
769 if ((frame[1] >> 1) != s->vr)
770 {
771 if (!s->rejected)
772 {
773 tx_supervisory_frame(s, s->rsp_addr, LAPM_S_REJ, (frame[2] & 0x1));
774 s->rejected = true1;
775 }
776 return;
777 }
778 s->rejected = false0;
779
780 s->iframe_put(s->iframe_put_user_data, frame + 3, len - 3);
781 /* Increment vr */
782 s->vr = (s->vr + 1) & 0x7F;
783 tx_information_rr_rnr_response(ss, frame, len);
784}
785/*- End of function --------------------------------------------------------*/
786
787static void rx_supervisory_cmd_frame(v42_state_t *ss, const uint8_t *frame, int len)
788{
789 lapm_state_t *s;
790
791 s = &ss->lapm;
792 /* If l->local_busy each RR,RNR,REJ with p=1 should be replied by RNR with f=1 (8.4.7) */
793 switch (frame[1] & 0x0C)
794 {
795 case LAPM_S_RR:
796 s->far_busy = false0;
797 ack_info(ss, frame[2] >> 1);
798 /* If p = 1 may be used for status checking? */
799 tx_information_rr_rnr_response(ss, frame, len);
800 break;
801 case LAPM_S_RNR:
802 s->far_busy = true1;
803 ack_info(ss, frame[2] >> 1);
804 /* If p = 1 may be used for status checking? */
805 if ((frame[2] & 0x1))
806 tx_supervisory_frame(s, s->rsp_addr, (s->local_busy) ? LAPM_S_RNR : LAPM_S_RR, 1);
807 break;
808 case LAPM_S_REJ:
809 s->far_busy = false0;
810 ack_info(ss, frame[2] >> 1);
811 if (s->retry_count == 0)
812 {
813 t401_stop_t403_start(ss);
814 reject_info(s);
815 }
816 tx_information_rr_rnr_response(ss, frame, len);
817 break;
818 case LAPM_S_SREJ:
819 /* TODO: */
820 return;
821 default:
822 return;
823 }
824}
825/*- End of function --------------------------------------------------------*/
826
827static void rx_supervisory_rsp_frame(v42_state_t *ss, const uint8_t *frame, int len)
828{
829 lapm_state_t *s;
830
831 s = &ss->lapm;
832 if (s->retry_count == 0 && (frame[2] & 0x1))
833 return;
834 /* Ack I frames <= NR - 1 */
835 switch (frame[1] & 0x0C)
836 {
837 case LAPM_S_RR:
838 s->far_busy = false0;
839 ack_info(ss, frame[2] >> 1);
840 if (s->retry_count && (frame[2] & 0x1))
841 {
842 reject_info(s);
843 t401_stop_t403_start(ss);
844 }
845 break;
846 case LAPM_S_RNR:
847 s->far_busy = true1;
848 ack_info(ss, frame[2] >> 1);
849 if (s->retry_count && (frame[2] & 0x1))
850 {
851 reject_info(s);
852 t401_stop_t403_start(ss);
853 }
854 if (s->retry_count == 0)
855 t401_start(ss);
856 break;
857 case LAPM_S_REJ:
858 s->far_busy = false0;
859 ack_info(ss, frame[2] >> 1);
860 if (s->retry_count == 0 || (frame[2] & 0x1))
861 {
862 reject_info(s);
863 t401_stop_t403_start(ss);
864 }
865 break;
866 case LAPM_S_SREJ:
867 /* TODO: */
868 return;
869 default:
870 return;
871 }
872}
873/*- End of function --------------------------------------------------------*/
874
875static int rx_unnumbered_cmd_frame(v42_state_t *ss, const uint8_t *frame, int len)
876{
877 lapm_state_t *s;
878
879 s = &ss->lapm;
880 switch (frame[1] & 0xEC)
881 {
882 case LAPM_U_SABME:
883 /* Discard un-acked I frames. Reset vs, vr, and va. Clear exceptions */
884 reset_lapm(ss);
885 /* Going to connected state */
886 s->state = LAPM_DATA;
887 /* Respond UA (or DM on error) */
888 // fixme: why may be error and LAPM_U_DM ??
889 tx_unnumbered_frame(s, s->rsp_addr, LAPM_U_UA | (frame[1] & 0x10), NULL((void*)0), 0);
890 t401_stop_t403_start(ss);
891 report_rx_status_change(ss, SIG_STATUS_LINK_CONNECTED);
892 break;
893 case LAPM_U_UI:
894 /* Break signal */
895 /* TODO: */
896 break;
897 case LAPM_U_DISC:
898 /* Respond UA (or DM) */
899 if (s->state == LAPM_IDLE)
900 {
901 tx_unnumbered_frame(s, s->rsp_addr, LAPM_U_DM | LAPM_U_PF0x10, NULL((void*)0), 0);
902 }
903 else
904 {
905 /* Going to disconnected state, discard unacked I frames, reset all. */
906 s->state = LAPM_IDLE;
907 reset_lapm(ss);
908 tx_unnumbered_frame(s, s->rsp_addr, LAPM_U_UA | (frame[1] & 0x10), NULL((void*)0), 0);
909 t401_stop(ss);
910 /* TODO: notify CF */
911 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
912 }
913 break;
914 case LAPM_U_XID:
915 /* Exchange general ID info */
916 receive_xid(ss, frame, len);
917 transmit_xid(ss, s->rsp_addr);
918 break;
919 case LAPM_U_TEST:
920 /* TODO: */
921 break;
922 default:
923 return -1;
924 }
925 return 0;
926}
927/*- End of function --------------------------------------------------------*/
928
929static int rx_unnumbered_rsp_frame(v42_state_t *ss, const uint8_t *frame, int len)
930{
931 lapm_state_t *s;
932
933 s = &ss->lapm;
934 switch (frame[1] & 0xEC)
935 {
936 case LAPM_U_DM:
937 switch (s->state)
938 {
939 case LAPM_IDLE:
940 if (!(frame[1] & 0x10))
941 {
942 /* TODO: notify CF */
943 report_rx_status_change(ss, SIG_STATUS_LINK_CONNECTED);
944 }
945 break;
946 case LAPM_ESTABLISH:
947 case LAPM_RELEASE:
948 if ((frame[1] & 0x10))
949 {
950 s->state = LAPM_IDLE;
951 reset_lapm(ss);
952 t401_stop(ss);
953 /* TODO: notify CF */
954 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
955 }
956 break;
957 case LAPM_DATA:
958 if (s->retry_count || !(frame[1] & 0x10))
959 {
960 s->state = LAPM_IDLE;
961 reset_lapm(ss);
962 /* TODO: notify CF */
963 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
964 }
965 break;
966 default:
967 break;
968 }
969 break;
970 case LAPM_U_UI:
971 /* TODO: */
972 break;
973 case LAPM_U_UA:
974 switch (s->state)
975 {
976 case LAPM_ESTABLISH:
977 s->state = LAPM_DATA;
978 reset_lapm(ss);
979 t401_stop_t403_start(ss);
980 report_rx_status_change(ss, SIG_STATUS_LINK_CONNECTED);
981 break;
982 case LAPM_RELEASE:
983 s->state = LAPM_IDLE;
984 reset_lapm(ss);
985 t401_stop(ss);
986 report_rx_status_change(ss, SIG_STATUS_LINK_DISCONNECTED);
987 break;
988 default:
989 /* Unsolicited UA */
990 /* TODO: */
991 break;
992 }
993 /* Clear all exceptions, busy states (self and peer) */
994 /* Reset vars */
995 break;
996 case LAPM_U_FRMR:
997 /* Non-recoverable error */
998 /* TODO: */
999 break;
1000 case LAPM_U_XID:
1001 if (s->configuring)
1002 {
1003 receive_xid(ss, frame, len);
1004 s->configuring = false0;
1005 t401_stop(ss);
1006 switch (s->state)
1007 {
1008 case LAPM_IDLE:
1009 lapm_connect(ss);
1010 break;
1011 case LAPM_DATA:
1012 s->local_busy = false0;
1013 tx_supervisory_frame(s, s->cmd_addr, LAPM_S_RR, 0);
1014 break;
1015 }
1016 }
1017 break;
1018 default:
1019 break;
1020 }
1021 return 0;
1022}
1023/*- End of function --------------------------------------------------------*/
1024
1025static void lapm_hdlc_underflow(void *user_data)
1026{
1027 lapm_state_t *s;
1028 v42_state_t *ss;
1029 v42_frame_t *f;
1030
1031 ss = (v42_state_t *) user_data;
1032 s = &ss->lapm;
1033 if (s->ctrl_get != s->ctrl_put)
1034 {
1035 /* Send control frame */
1036 f = &s->ctrl_buf[s->ctrl_get];
1037 if (++s->ctrl_get >= V42_CTRL_FRAMES8)
1038 s->ctrl_get = 0;
1039 }
1040 else
1041 {
1042 if (s->far_busy || s->configuring || s->state != LAPM_DATA)
1043 {
1044 hdlc_tx_flags(&s->hdlc_tx, 10);
1045 return;
1046 }
1047 if (s->info_get == s->info_put && !tx_information_frame(ss))
1048 {
1049 hdlc_tx_flags(&s->hdlc_tx, 10);
1050 return;
1051 }
1052 /* Send info frame */
1053 f = &s->info_buf[s->info_get];
1054 if (++s->info_get >= V42_INFO_FRAMES(15 + 1))
1055 s->info_get = 0;
1056
1057 f->buf[0] = s->cmd_addr;
1058 f->buf[1] = s->vs << 1;
1059 f->buf[2] = s->vr << 1;
1060 s->vs = (s->vs + 1) & 0x7F;
1061 if (ss->bit_timer == 0)
1062 t401_start(ss);
1063 }
1064 hdlc_tx_frame(&s->hdlc_tx, f->buf, f->len);
1065}
1066/*- End of function --------------------------------------------------------*/
1067
1068SPAN_DECLARE_NONSTD(void)__attribute__((visibility("default"))) void lapm_receive(void *user_data, const uint8_t *frame, int len, int ok)
1069{
1070 lapm_state_t *s;
1071 v42_state_t *ss;
1072
1073 ss = (v42_state_t *) user_data;
1074 s = &ss->lapm;
1075 if (len < 0)
1076 {
1077 span_log(&ss->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(len), len);
1078 return;
1079 }
1080 if (!ok)
1081 return;
1082
1083 switch ((frame[1] & LAPM_FRAMETYPE_MASK0x03))
1084 {
1085 case LAPM_FRAMETYPE_I:
1086 case LAPM_FRAMETYPE_I_ALT:
1087 receive_information_frame(ss, frame, len);
1088 break;
1089 case LAPM_FRAMETYPE_S:
1090 if (!valid_data_state(ss))
1091 return;
1092 if (frame[0] == s->rsp_addr)
1093 rx_supervisory_cmd_frame(ss, frame, len);
1094 else
1095 rx_supervisory_rsp_frame(ss, frame, len);
1096 break;
1097 case LAPM_FRAMETYPE_U:
1098 if (frame[0] == s->rsp_addr)
1099 rx_unnumbered_cmd_frame(ss, frame, len);
1100 else
1101 rx_unnumbered_rsp_frame(ss, frame, len);
1102 break;
1103 }
1104}
1105/*- End of function --------------------------------------------------------*/
1106
1107static int lapm_connect(v42_state_t *ss)
1108{
1109 lapm_state_t *s;
1110
1111 s = &ss->lapm;
1112 if (s->state != LAPM_IDLE)
1113 return -1;
1114
1115 /* Negotiate params */
1116 //transmit_xid(s, s->cmd_addr);
1117
1118 reset_lapm(ss);
1119 /* Connect */
1120 s->state = LAPM_ESTABLISH;
1121 tx_unnumbered_frame(s, s->cmd_addr, LAPM_U_SABME | LAPM_U_PF0x10, NULL((void*)0), 0);
1122 /* Start T401 (and not T403) */
1123 t401_start(ss);
1124 return 0;
1125}
1126/*- End of function --------------------------------------------------------*/
1127
1128static int lapm_disconnect(v42_state_t *ss)
1129{
1130 lapm_state_t *s;
1131
1132 s = &ss->lapm;
1133 s->state = LAPM_RELEASE;
1134 tx_unnumbered_frame(s, s->cmd_addr, LAPM_U_DISC | LAPM_U_PF0x10, NULL((void*)0), 0);
1135 t401_start(ss);
1136 return 0;
1137}
1138/*- End of function --------------------------------------------------------*/
1139
1140static int lapm_config(v42_state_t *ss)
1141{
1142 lapm_state_t *s;
1143
1144 s = &ss->lapm;
1145 s->configuring = true1;
1146 if (s->state == LAPM_DATA)
1147 {
1148 s->local_busy = true1;
1149 tx_supervisory_frame(s, s->cmd_addr, LAPM_S_RNR, 1);
1150 }
1151 transmit_xid(ss, s->cmd_addr);
1152 t401_start(ss);
1153 return 0;
1154}
1155/*- End of function --------------------------------------------------------*/
1156
1157static void reset_lapm(v42_state_t *ss)
1158{
1159 lapm_state_t *s;
1160
1161 s = &ss->lapm;
1162 /* Reset the LAP.M state */
1163 s->local_busy = false0;
1164 s->far_busy = false0;
1165 s->vs = 0;
1166 s->va = 0;
1167 s->vr = 0;
1168 /* Discard any info frames still queued for transmission */
1169 s->info_put = 0;
1170 s->info_acked = 0;
1171 s->info_get = 0;
1172 /* Discard any control frames */
1173 s->ctrl_put = 0;
1174 s->ctrl_get = 0;
1175
1176 s->tx_window_size_k = ss->config.v42_tx_window_size_k;
1177 s->rx_window_size_k = ss->config.v42_rx_window_size_k;
1178 s->tx_n401 = ss->config.v42_tx_n401;
1179 s->rx_n401 = ss->config.v42_rx_n401;
1180}
1181/*- End of function --------------------------------------------------------*/
1182
1183SPAN_DECLARE(void)__attribute__((visibility("default"))) void v42_stop(v42_state_t *ss)
1184{
1185 lapm_state_t *s;
1186
1187 s = &ss->lapm;
1188 ss->bit_timer = 0;
1189 s->packer_process = NULL((void*)0);
1190 lapm_disconnect(ss);
1191}
1192/*- End of function --------------------------------------------------------*/
1193
1194static void restart_lapm(v42_state_t *s)
1195{
1196 if (s->calling_party)
1197 {
1198 s->bit_timer = 48*8;
1199 s->bit_timer_func = initiate_negotiation_expired;
1200 }
1201 else
1202 {
1203 lapm_hdlc_underflow(s);
1204 }
1205 s->lapm.packer_process = NULL((void*)0);
1206 s->lapm.state = LAPM_IDLE;
1207}
1208/*- End of function --------------------------------------------------------*/
1209
1210static void negotiation_rx_bit(v42_state_t *s, int new_bit)
1211{
1212 /* DC1 with even parity, 8-16 ones, DC1 with odd parity, 8-16 ones */
1213 /* uint8_t odp = "0100010001 11111111 0100010011 11111111"; */
1214 /* V.42 OK E , 8-16 ones, C, 8-16 ones */
1215 /* uint8_t adp_v42 = "0101000101 11111111 0110000101 11111111"; */
1216 /* V.42 disabled E, 8-16 ones, NULL, 8-16 ones */
1217 /* uint8_t adp_nov42 = "0101000101 11111111 0000000001 11111111"; */
1218
1219 /* There may be no negotiation, so we need to process this data through the
1220 HDLC receiver as well */
1221 if (new_bit < 0)
1222 {
1223 /* Special conditions */
1224 span_log(&s->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(new_bit), new_bit);
1225 return;
1226 }
1227 /*endif*/
1228 new_bit &= 1;
1229 s->neg.rxstream = (s->neg.rxstream << 1) | new_bit;
1230 switch (s->neg.rx_negotiation_step)
1231 {
1232 case 0:
1233 /* Look for some ones */
1234 if (new_bit)
1235 break;
1236 /*endif*/
1237 s->neg.rx_negotiation_step = 1;
1238 s->neg.rxbits = 0;
1239 s->neg.rxstream = ~1;
1240 s->neg.rxoks = 0;
1241 break;
1242 case 1:
1243 /* Look for the first character */
1244 if (++s->neg.rxbits < 9)
1245 break;
1246 /*endif*/
1247 s->neg.rxstream &= 0x3FF;
1248 if (s->calling_party && s->neg.rxstream == 0x145)
1249 {
1250 s->neg.rx_negotiation_step++;
1251 }
1252 else if (!s->calling_party && s->neg.rxstream == 0x111)
1253 {
1254 s->neg.rx_negotiation_step++;
1255 }
1256 else
1257 {
1258 s->neg.rx_negotiation_step = 0;
1259 }
1260 /*endif*/
1261 s->neg.rxbits = 0;
1262 s->neg.rxstream = ~0;
1263 break;
1264 case 2:
1265 /* Look for 8 to 16 ones */
1266 s->neg.rxbits++;
1267 if (new_bit)
1268 break;
1269 /*endif*/
1270 if (s->neg.rxbits >= 8 && s->neg.rxbits <= 16)
1271 s->neg.rx_negotiation_step++;
1272 else
1273 s->neg.rx_negotiation_step = 0;
1274 /*endif*/
1275 s->neg.rxbits = 0;
1276 s->neg.rxstream = ~1;
1277 break;
1278 case 3:
1279 /* Look for the second character */
1280 if (++s->neg.rxbits < 9)
1281 break;
1282 /*endif*/
1283 s->neg.rxstream &= 0x3FF;
1284 if (s->calling_party && s->neg.rxstream == 0x185)
1285 {
1286 s->neg.rx_negotiation_step++;
1287 }
1288 else if (s->calling_party && s->neg.rxstream == 0x001)
1289 {
1290 s->neg.rx_negotiation_step++;
1291 }
1292 else if (!s->calling_party && s->neg.rxstream == 0x113)
1293 {
1294 s->neg.rx_negotiation_step++;
1295 }
1296 else
1297 {
1298 s->neg.rx_negotiation_step = 0;
1299 }
1300 /*endif*/
1301 s->neg.rxbits = 0;
1302 s->neg.rxstream = ~0;
1303 break;
1304 case 4:
1305 /* Look for 8 to 16 ones */
1306 s->neg.rxbits++;
1307 if (new_bit)
1308 break;
1309 /*endif*/
1310 if (s->neg.rxbits >= 8 && s->neg.rxbits <= 16)
1311 {
1312 if (++s->neg.rxoks >= 2)
1313 {
1314 /* HIT - we have found the "V.42 supported" pattern. */
1315 s->neg.rx_negotiation_step++;
1316 if (s->calling_party)
1317 {
1318 t400_stop(s);
1319 s->lapm.state = LAPM_IDLE;
1320 report_rx_status_change(s, s->lapm.state);
1321 restart_lapm(s);
1322 }
1323 else
1324 {
1325 s->neg.odp_seen = true1;
1326 }
1327 /*endif*/
1328 break;
1329 }
1330 /*endif*/
1331 s->neg.rx_negotiation_step = 1;
1332 s->neg.rxbits = 0;
1333 s->neg.rxstream = ~1;
1334 }
1335 else
1336 {
1337 s->neg.rx_negotiation_step = 0;
1338 s->neg.rxbits = 0;
1339 s->neg.rxstream = ~0;
1340 }
1341 /*endif*/
1342 break;
1343 case 5:
1344 /* Parked */
1345 break;
1346 }
1347 /*endswitch*/
1348}
1349/*- End of function --------------------------------------------------------*/
1350
1351static int v42_support_negotiation_tx_bit(v42_state_t *s)
1352{
1353 int bit;
1354
1355 if (s->calling_party)
1356 {
1357 if (s->neg.txbits <= 0)
1358 {
1359 s->neg.txstream = 0x3FE22;
1360 s->neg.txbits = 36;
1361 }
1362 else if (s->neg.txbits == 18)
1363 {
1364 s->neg.txstream = 0x3FF22;
1365 }
1366 /*endif*/
1367 bit = s->neg.txstream & 1;
1368 s->neg.txstream >>= 1;
1369 s->neg.txbits--;
1370 }
1371 else
1372 {
1373 if (s->neg.odp_seen && s->neg.txadps < 10)
1374 {
1375 if (s->neg.txbits <= 0)
1376 {
1377 if (++s->neg.txadps >= 10)
1378 {
1379 t400_stop(s);
1380 s->lapm.state = LAPM_IDLE;
1381 report_rx_status_change(s, s->lapm.state);
1382 s->neg.txstream = 1;
1383 restart_lapm(s);
1384 }
1385 else
1386 {
1387 s->neg.txstream = 0x3FE8A;
1388 s->neg.txbits = 36;
1389 }
1390 /*endif*/
1391 }
1392 else if (s->neg.txbits == 18)
1393 {
1394 s->neg.txstream = 0x3FE86;
1395 }
1396 /*endif*/
1397 bit = s->neg.txstream & 1;
1398 s->neg.txstream >>= 1;
1399 s->neg.txbits--;
1400 }
1401 else
1402 {
1403 bit = 1;
1404 }
1405 /*endif*/
1406 }
1407 /*endif*/
1408 return bit;
1409}
1410/*- End of function --------------------------------------------------------*/
1411
1412SPAN_DECLARE(void)__attribute__((visibility("default"))) void v42_rx_bit(void *user_data, int bit)
1413{
1414 v42_state_t *s;
1415
1416 s = (v42_state_t *) user_data;
1417 if (s->lapm.state == LAPM_DETECT)
1418 negotiation_rx_bit(s, bit);
1419 else
1420 hdlc_rx_put_bit(&s->lapm.hdlc_rx, bit);
1421 /*endif*/
1422}
1423/*- End of function --------------------------------------------------------*/
1424
1425SPAN_DECLARE(int)__attribute__((visibility("default"))) int v42_tx_bit(void *user_data)
1426{
1427 v42_state_t *s;
1428 int bit;
1429
1430 s = (v42_state_t *) user_data;
1431 if (s->bit_timer && (--s->bit_timer) <= 0)
1432 {
1433 s->bit_timer = 0;
1434 s->bit_timer_func(s);
1435 }
1436 if (s->lapm.state == LAPM_DETECT)
1437 bit = v42_support_negotiation_tx_bit(s);
1438 else
1439 bit = hdlc_tx_get_bit(&s->lapm.hdlc_tx);
1440 /*endif*/
1441 return bit;
1442}
1443/*- End of function --------------------------------------------------------*/
1444
1445SPAN_DECLARE(int)__attribute__((visibility("default"))) int v42_set_local_busy_status(v42_state_t *s, int busy)
1446{
1447 int previous_busy;
1448
1449 previous_busy = s->lapm.local_busy;
1450 s->lapm.local_busy = busy;
1451 return previous_busy;
1452}
1453/*- End of function --------------------------------------------------------*/
1454
1455SPAN_DECLARE(int)__attribute__((visibility("default"))) int v42_get_far_busy_status(v42_state_t *s)
1456{
1457 return s->lapm.far_busy;
1458}
1459/*- End of function --------------------------------------------------------*/
1460
1461SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * v42_get_logging_state(v42_state_t *s)
1462{
1463 return &s->logging;
1464}
1465/*- End of function --------------------------------------------------------*/
1466
1467SPAN_DECLARE(void)__attribute__((visibility("default"))) void v42_set_status_callback(v42_state_t *s, modem_status_func_t status_handler, void *user_data)
1468{
1469 s->lapm.status_handler = status_handler;
1470 s->lapm.status_user_data = user_data;
1471}
1472/*- End of function --------------------------------------------------------*/
1473
1474SPAN_DECLARE(void)__attribute__((visibility("default"))) void v42_restart(v42_state_t *s)
1475{
1476 hdlc_tx_init(&s->lapm.hdlc_tx, false0, 1, true1, lapm_hdlc_underflow, s);
1477 hdlc_rx_init(&s->lapm.hdlc_rx, false0, false0, 1, lapm_receive, s);
1478
1479 if (s->detect)
1480 {
1481 /* We need to do the V.42 support detection sequence */
1482 s->neg.txstream = ~0;
1483 s->neg.txbits = 0;
1484 s->neg.rxstream = ~0;
1485 s->neg.rxbits = 0;
1486 s->neg.rxoks = 0;
1487 s->neg.txadps = 0;
1488 s->neg.rx_negotiation_step = 0;
1489 s->neg.odp_seen = false0;
1490 t400_start(s);
1491 s->lapm.state = LAPM_DETECT;
1492 }
1493 else
1494 {
1495 /* Go directly to LAP.M mode */
1496 s->lapm.state = LAPM_IDLE;
1497 restart_lapm(s);
1498 }
1499 /*endif*/
1500}
1501/*- End of function --------------------------------------------------------*/
1502
1503SPAN_DECLARE(v42_state_t *)__attribute__((visibility("default"))) v42_state_t * v42_init(v42_state_t *ss,
1504 bool_Bool calling_party,
1505 bool_Bool detect,
1506 get_msg_func_t iframe_get,
1507 put_msg_func_t iframe_put,
1508 void *user_data)
1509{
1510 lapm_state_t *s;
1511
1512 if (ss == NULL((void*)0))
1513 {
1514 if ((ss = (v42_state_t *) span_alloc(sizeof(*ss))) == NULL((void*)0))
1515 return NULL((void*)0);
1516 }
1517 memset(ss, 0, sizeof(*ss));
1518
1519 s = &ss->lapm;
1520 ss->calling_party = calling_party;
1521 ss->detect = detect;
1522 s->iframe_get = iframe_get;
1523 s->iframe_get_user_data = user_data;
1524 s->iframe_put = iframe_put;
1525 s->iframe_put_user_data = user_data;
1526
1527 s->state = (ss->detect) ? LAPM_DETECT : LAPM_IDLE;
1528 s->local_busy = false0;
1529 s->far_busy = false0;
1530
1531 /* The address octet is:
1532 Data link connection identifier (0)
1533 Command/response (0 if answerer, 1 if originator)
1534 Extended address (1) */
1535 s->cmd_addr = (LAPM_DLCI_DTE_TO_DTE0 << 2) | ((ss->calling_party) ? 0x02 : 0x00) | 0x01;
1536 s->rsp_addr = (LAPM_DLCI_DTE_TO_DTE0 << 2) | ((ss->calling_party) ? 0x00 : 0x02) | 0x01;
1537
1538 /* Set default values for the LAP.M parameters. These can be modified later. */
1539 ss->config.v42_tx_window_size_k = V42_DEFAULT_WINDOW_SIZE_K15;
1540 ss->config.v42_rx_window_size_k = V42_DEFAULT_WINDOW_SIZE_K15;
1541 ss->config.v42_tx_n401 = V42_DEFAULT_N_401128;
1542 ss->config.v42_rx_n401 = V42_DEFAULT_N_401128;
1543
1544 /* TODO: This should be part of the V.42bis startup */
1545 ss->config.comp = 1;
1546 ss->config.comp_dict_size = 512;
1547 ss->config.comp_max_string = 6;
1548
1549 ss->tx_bit_rate = 28800;
1550
1551 reset_lapm(ss);
1552
1553 span_log_init(&ss->logging, SPAN_LOG_NONE, NULL((void*)0));
1554 span_log_set_protocol(&ss->logging, "V.42");
1555 return ss;
1556}
1557/*- End of function --------------------------------------------------------*/
1558
1559SPAN_DECLARE(int)__attribute__((visibility("default"))) int v42_release(v42_state_t *s)
1560{
1561 reset_lapm(s);
1562 return 0;
1563}
1564/*- End of function --------------------------------------------------------*/
1565
1566SPAN_DECLARE(int)__attribute__((visibility("default"))) int v42_free(v42_state_t *s)
1567{
1568 v42_release(s);
1569 span_free(s);
1570 return 0;
1571}
1572/*- End of function --------------------------------------------------------*/
1573/*- End of file ------------------------------------------------------------*/