Bug Summary

File:src/v150_1.c
Warning:line 2425, column 5
Value stored to 'res' is never read

Annotated Source Code

1/*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v150_1.c - An implementation of V.150.1.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2022, 2023 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 General Public License version 2, as
14 * 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 General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26#if defined(HAVE_CONFIG_H1)
27#include "config.h"
28#endif
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <sys/types.h>
33#include <inttypes.h>
34#include <memory.h>
35#if defined(HAVE_STDBOOL_H1)
36#include <stdbool.h>
37#else
38#include <spandsp/stdbool.h>
39#endif
40
41#define SPANDSP_FULLY_DEFINE_SPRT_STATE_T
42
43#include "spandsp/telephony.h"
44#include "spandsp/alloc.h"
45#include "spandsp/unaligned.h"
46#include "spandsp/logging.h"
47#include "spandsp/async.h"
48#include "spandsp/sprt.h"
49#include "spandsp/v150_1.h"
50#include "spandsp/v150_1_sse.h"
51
52#include "spandsp/private/logging.h"
53#include "spandsp/private/sprt.h"
54#include "spandsp/private/v150_1_sse.h"
55#include "spandsp/private/v150_1.h"
56
57#include "v150_1_local.h"
58
59/* Terminology
60
61 V.150.1 has several components. The terms used for these are:
62
63 Signalling state events (SSE)
64 An RTP payload type which encodes indications of changes between audio, FoIP, MoIP, and ToIP modes.
65 In SDP this is referred to as v150fw.
66 Simple packet relay transport (SPRT)
67 A hybrid unreliable plus reliable packet over UDP protocol, compatible with sending RTP to and from the
68 same UDP port. You can also find the term IP-TLP associated wtih this protocol. In SDP this is referred
69 to udpsprt.
70 The actual V.150.1 modem relay protocol.
71 These are are messages which typically pass across an SPRT transport. In SDP this is referred to as v150mr.
72*/
73
74/* A Cisco box in V.150.1 mode is quite fussy about what it receives to trigger it into a V.8 exchange with an attached
75 modem.
76
77 Simply sending a bunch of /ANSam RFC3733/RFC4734 packets gets you nowhere, but this does contradict what RFC4734
78 says.
79
80 Waiting 200ms after answer, sending 450ms of ANSam, then switching to sending /ANSam until a v150fw packet
81 arrives, then sending /ANSam-end, sounds compliant, but a Cisco doesn't like that. It would never happen connected
82 to a real modem, as it takes a while to detect ANSam, and be sure the AM part if really there. A real modem
83 connected to a Cisco causes the Cisco to send something like 200ms of ANSam, before the switch to /ANSam. Trying
84 to mimic that gets you farther.
85
86 When I failed to send /ANSam-end at the end of my tone the Cisco behaved quirkily. However, when I call into the
87 Cisco, it just stops sending /ANSam, and never seems to send any /ANSam-end packets.
88
89 Cisco seems to consistently accept the following as a valid ANSamPR, resulting in a v150fw CM packet being received
90 from the Cisco:
91 ANSWER
92 Send 40ms to several seconds of silence
93 Send 11 to 20 ANSam packets at 20ms per packet
94 22 fails, and you get an v150fw AA message, instead of a CM message. This is reasonable, as the phase
95 reversal is almost late, and if you consider the sending end would need some time to detect the
96 initial tone, its really quite late.
97 21 acts really quirky, and you may get nothing back. The Cisco seems to get really messed up. No RTP or
98 SPRT comes from it until the calling hangs up.
99 Values between 1 and 10 seem quirky. 10 fails, and you get an v150fw AA message, instead of a CM message.
100 Some values between 1 and 10 often work OK, while others give an AA.
101 Send sustained /ANSam at 20ms per packet, until...
102 ..... v150fw packet received
103 Send 4 /ANSam end packets at 20ms intervals
104*/
105
106/* A Cisco box has the following parameters:
107
108modem relay latency <milliseconds>
109 Specifies the estimated one-way delay across the IP network.
110 Range is 100 to 1000. Default is 200.
111
112modem relay sse redundancy interval <milliseconds>
113 Specifies the timer value for redundant transmission of SSEs.
114 Range is 5ms to 50ms. Default is 20ms.
115
116modem relay sse redundancy packet <number>
117 Specifies the SSE packet transmission count before disconnecting.
118 Range is 1 to 5 packets. Default is 3.
119
120modem relay sse t1 <milliseconds>
121 Specifies the repeat interval, in milliseconds (ms), for initial audio SSEs used for resetting the SSE protocol state machine (clearing the call) following error recovery.
122 Range is 500ms to 3000ms. Default is 1000ms.
123
124modem relay sse retries <value>
125 Specifies the number of SSE packet retries, repeated every t1 interval, before disconnecting.
126 Range is 0 to 5. Default is 5.
127
128modem relay sprt retries <value>
129 Specifies the number of SPRT packet retries, repeated every t1 interval, before disconnecting.
130 Range is 0 to 10. Default is 10.
131
132modem relay sprt v14 receive playback hold-time <milliseconds>
133 Configures the time, in ms, to hold incoming data in the V.14 receive queue.
134 Range is 20ms to 250ms. Default is 50ms.
135
136modem relay sprt v14 transmit hold-time <milliseconds>
137 Configures the time to wait, in ms, after the first character is ready before sending
138 the SPRT packet.
139 Range is 10ms to 30ms. Default is 20ms.
140
141modem relay sprt v14 transmit maximum hold-count <characters>
142 Configures the number of V.14 characters to be received on the modem interface that will
143 trigger sending an SPRT packet.
144 Range is 8 to 128. Default is 16.
145*/
146
147/*
148
149There are two defined versions of a modem relay gateway:
150
151U-MR: A Universal Modem Relay
152
153 A U-MR needs to support V.92 digital, V.90 digital, V.34, V.32bis, V.32, V.22bis, V.22, V.23 and V.21
154
155V-MR: A V.8 Modem Relay
156 A V-MR doesn't have to support any specific set of modulations. Instead, V.8 is used to negotiate a
157 common one. Inter-gateway messages exchanged during call setup can be used for each end to inform the
158 other which modulations are supported.
159
160
161The SPRT related SDP needs a entry like:
162
163 a=fmtp:120 mr=1;mg=0;CDSCselect=1;jmdelay=no;versn=1.1
164
165mr=0 for V-MR
166 =1 for U-MR
167
168mg=0 for no transcompression
169 =1 for single transcompression
170 =2 for double transcompression
171
172CDSCselect=1 for audio RFC4733
173 =2 for VBD preferred
174 =3 for Mixed
175
176mrmods=1-4,10-12,14,17
177 where 1 = V.34 duplex
178 2 = V.34 half-duplex
179 3 = V.32bis/V.32
180 4 = V.22bis/V.22
181 5 = V.17
182 6 = V.29
183 7 = V.27ter
184 8 = V.26ter
185 9 = V.26bis
186 10 = V.23 duplex
187 11 = V.23 half-duplex
188 12 = V.21
189 13 = V.90 analogue
190 14 = V.90 digital
191 15 = V/91
192 16 = V.92 analogue
193 17 = V.92 digital
194
195jmdelay=no JM delay not supported
196 =yes JM delay supported
197
198versn=1.1 This is optional. The current version is 1.1
199
200txalgs=1 V.44 (V.42bis is always required, so is not listed in this tag)
201 =2 MNP5
202
203v42bNumCodeWords=1024
204
205v42bMaxStringLength=32
206
207v44NumTxCodewords=1024
208
209v44NumRxCodewords=1024
210
211v44MaxTxStringLength=64
212
213v44MaxRxStringLength=64
214
215V44LenTxHistory=3072
216
217V44LenRxHistory=3072
218
219TCXpreference=1
220 =2
221
222
223
224 a=sprtparm: 140 132 132 140 32 8
225
226 These are the maximum payload sizes for the 4 channels, and the maximum window sizes for
227 the two reliable channels. A '$' may be used for unspecified values.
228
229
230 a=vndpar: <vendorIDformat> <vendorID> <vendorSpecificDataTag> <vendorSpecificData>
231
232<vendorIDformat>=1 for T.35
233 =2 for IANA private enterprise number
234
235<vendorID>
236<vendorSpecificDataTag>
237<vendorSpecificData>
238
239Voice band data (VBD) mode:
240
241 |<----------------------------------- Data compression ------------------------------------->|
242 |<----------------------------------- Error correction ------------------------------------->|
243 |<-------------------------------------- Modulation ---------------------------------------->|
244 | |<---- Encapsulated G.711 ---->| |
245 | | | |
246 |<---------- PSTN ----------->|<-------Packet network ------>|<----------- PSTN ------------>|
247
248
249The various modem relay error correction and compression scenarios:
250
251MR1
252
253 |<----------------------------------- Data compression --- --------------------------------->|
254 |<---- Error correction ----->| |<----- Error correction ------>|
255 |<------- Modulation -------->| |<-------- Modulation --------->|
256 | |<---- Reliable transport ---->| |
257 | | | |
258 |<---------- PSTN ----------->|<-------Packet network ------>|<----------- PSTN ------------>|
259
260
261MR2
262
263 |<---- Data compression ----->| |<----- Data compression ------>|
264 |<---- Error correction ----->| |<----- Error correction ------>|
265 |<------- Modulation -------->| |<-------- Modulation --------->|
266 | |<------- MR2a or MR2b ------->| |
267 | | | |
268 |<---------- PSTN ----------->|<-------Packet network ------>|<----------- PSTN ------------>|
269
270MR2a: Reliable transport without data compression
271MR2b: Reliable transport with data compression
272
273
274
275MR3
276
277 |<---- Data compression ----->|<-------------------- Data compression ---------------------->|
278 |<------------------- Data compression --------------------->|<----- Data compression ------>|
279 |<---- Error correction -0--->| |<----- Error correction ------>|
280 |<------- Modulation -------->| |<-------- Modulation --------->|
281 | |<---- Reliable transport ---->| |
282 | | | |
283 |<--------- PSTN ------------>|<------ Packet network ------>|<----------- PSTN ------------>|
284
285
286
287MR4
288
289 |<------------------- Data compression --------------------->|<----- Data compression ------>|
290 |<---- Error correction ----->| |<----- Error correction ------>|
291 |<------- Modulation -------->| |<-------- Modulation --------->|
292 | |<---- Reliable transport ---->| |
293 | | | |
294 |<---------- PSTN ----------->|<-------Packet network ------>|<----------- PSTN ------------>|
295
296*/
297
298/* Example call flows
299
300Establishing Modem Relay with V.32 Modem
301
302 M1 G1 G2 M2
303 | | | |
304 | | |<-------------ANS--------------|
305 | |<--------RFC4733 ANS----------| |
306 |<------------ANS-------------| | |
307 | | |<------------/ANS--------------|
308 | |<--------RFC4733 /ANS---------| |
309 |<-----------/ANS-------------| | |
310 | | | |
311 | | | |
312 |<<----- V.32 signals ------>>| | |
313 | |-------SSE MR(m,a) AA-------->| |
314 | | |<<------ V.32 signals ------->>|
315 | |<------SSE MR(m,m) p'---------| |
316 |<<----- V.32 signals ------>>| | |
317 | |-----------SPRT:INIT--------->|<<------ V.32 signals ------->>|
318 | | | |
319 | |<----------SPRT:INIT----------| |
320 |<<----- V.32 signals ------>>| |<<------ V.32 signals ------->>|
321 | |<--SPRT:MR_EVENT(PHYSUPv32)---| |
322 | | | |
323 | |---SPRT:MR_EVENT(PHYSUPv32)-->| |
324 | | | |
325 | |<------SPRT:CONNECT(v32)------| |
326 | | | |
327 | |-------SPRT:CONNECT(v32)----->| |
328 | | | |
329 |<<------ V.32 data -------->>|<<-------- SPRT:data ------->>|<<-------- V.32 data -------->>|
330 | | | |
331 | | | |
332
333
334
335Establishing Modem Relay with V.34 Modem
336
337 M1 G1 G2 M2
338 | | | |
339 | | |<-------------ANS--------------|
340 | |<--------RFC4733 ANS----------| |
341 |<-----------ANS--------------| | |
342 | | |<------------/ANS--------------|
343 | |<--------RFC4733 /ANS---------| |
344 |<----------/ANS--------------| | |
345 | | | |
346 |------------CM-------------->| | |
347 | |-----SSE MR(m,a) CM(v34)----->| |
348 | | |--------------CM-------------->|
349 | |<------SSE MR(m,m) p'---------| |
350 | | | |
351 | |-----------SPRT:INIT--------->| |
352 | | | |
353 | |<----------SPRT:INIT----------| |
354 | | |<-------------JM---------------|
355 | |<-----SPRT:JM_INFO(v34)-------| |
356 |<-----------JM---------------| | |
357 | | | |
358 |<<----- V.34 signals ------>>| |<<------ V.34 signals ------->>|
359 | |<--SPRT:MR_EVENT(PHYSUPv34)---| |
360 | | | |
361 | |---SPRT:MR_EVENT(PHYSUPv34)-->| |
362 | | | |
363 | |<------SPRT:CONNECT(v34)------| |
364 | | | |
365 | |-------SPRT:CONNECT(v34)----->| |
366 | | | |
367 |<<------ V.34 data -------->>|<<-------- SPRT:data ------->>|<<-------- V.34 data -------->>|
368 | | | |
369 | | | |
370
371
372
373Establishing Modem Relay with ITU V.34 Modem with no JM_INFO Message Sent from G2 Gateway
374
375 M1 G1 G2 M2
376 | | | |
377 | | |<-------------ANS--------------|
378 | |<--------RFC4733 ANS----------| |
379 |<-----------ANS--------------| | |
380 | | |<------------/ANS--------------|
381 | |<--------RFC4733 /ANS---------| |
382 |<----------/ANS--------------| | |
383 | | | |
384 |------------CM-------------->| | |
385 | |-----SSE MR(m,a) CM(v34)----->| |
386 |<-----------JM---------------| |--------------CM-------------->|
387 | |<------SSE MR(m,m) p'---------| |
388 | | | |
389 | |-----------SPRT:INIT--------->| |
390 | | | |
391 | |<----------SPRT:INIT----------| |
392 | | |<-------------JM---------------|
393 | | | |
394 |<<----- V.34 signals ------>>| |<<------ V.34 signals ------->>|
395 | |<--SPRT:MR_EVENT(PHYSUPv34)---| |
396 | | | |
397 | |---SPRT:MR_EVENT(PHYSUPv34)-->| |
398 | | | |
399 | |<------SPRT:CONNECT(v34)------| |
400 | | | |
401 | |-------SPRT:CONNECT(v34)----->| |
402 | | | |
403 |<<------- V.34 data ------->>|<<-------- SPRT:data ------->>|<<-------- V.34 data -------->>|
404 | | | |
405 | | | |
406
407
408
409
410Establishing Modem Relay with ITU V.90 Modem
411
412 M1 G1 G2 M2
413 | | | |
414 | | |<-------------ANS--------------|
415 | |<--------RFC4733 ANS----------| |
416 |<------------ANS-------------| | |
417 | | |<------------/ANS--------------|
418 | |<--------RFC4733 /ANS---------| |
419 |<-----------/ANS-------------| | |
420 | | | |
421 |-------------CM------------->| | |
422 | |--SSE MR(m,a) CM(v90 or v92)->| |
423 | ` | |--------------CM-------------->|
424 | |<------SSE MR(m,m) p'---------| |
425 | | | |
426 | |-----------SPRT:INIT--------->| |
427 | | | |
428 | |<----------SPRT:INIT----------| |
429 | | |<-------------JM---------------|
430 | |<--SPRT:JM_INFO (v90 or v92)--| |
431 |<------------JM--------------| | |
432 | | | |
433 |<<----- V.90 signals ------>>| |<<------ V.90 signals ------->>|
434 | |<--SPRT:MR_EVENT(PHYSUPv90)---| |
435 | | | |
436 | |<------SPRT:CONNECT(v90)------| |
437 | | | |
438 | |---SPRT:MR_EVENT(PHYSUPv90)-->| |
439 | | | |
440 | |-------SPRT:CONNECT(v90)----->| |
441 | | | |
442 |<<------- V.90 data ------->>|<<-------- SPRT:data ------->>|<<-------- V.90 data -------->>|
443 | | | |
444 | | | |
445
446
447
448
449Establishing Modem Relay with ITU V.92 Modem
450
451 M1 G1 G2 M2
452 | | | |
453 | | |<--------------ANS-------------|
454 | |<--------RFC4733 ANS----------| |
455 |<------------ANS-------------| | |
456 | | |<-------------/ANS-------------|
457 | |<--------RFC4733 /ANS---------| |
458 |<-----------/ANS-------------| | |
459 | | | |
460 |-------------CM------------->| | |
461 | |--SSE MR(m,a) CM(v90 or v92)->| |
462 | | |---------------CM------------->|
463 | |<------SSE MR(m,m) p'---------| |
464 | | | |
465 | |-----------SPRT:INIT--------->| |
466 | | | |
467 | |<----------SPRT:INIT----------| |
468 | | |<--------------JM--------------|
469 | |<--SPRT:JM_INFO (v90 or v92)--| |
470 |<------------JM--------------| | |
471 | | | |
472 |<<----- V.92 signals ------>>| |<<------- V.92 signals ------>>|
473 | |<--SPRT:MR_EVENT(PHYSUPv92)---| |
474 | | | |
475 | |<------SPRT:CONNECT(v92)------| |
476 | | | |
477 | |---SPRT:MR_EVENT(PHYSUPv92)-->| |
478 | | | |
479 | |-------SPRT:CONNECT(v90)----->| |
480 | | | |
481 |<<------- V.92 data ------->>|<<-------- SPRT:data ------->>|<<-------- V.92 data -------->>|
482 | | | |
483 | | | |
484*/
485
486/*
487 telephone network
488 ^
489 |
490 |
491 v
492 +-----------------------------------+
493 | |
494 | Signal processing entity (SPE) |
495 | |
496 +-----------------------------------+
497 | ^
498 | |
499 Signal list 1 | | Signal list 2
500 | |
501 v |
502 +-----------------------------------+ Signal list 5 +-----------------------------------+
503 | | ----------------->| |
504 | SSE protocol state machine (P) | | Gateway state machine (s,s') |
505 | |<------------------| |
506 +-----------------------------------+ Signal list 6 +-----------------------------------+
507 | ^
508 | |
509 Signal list 3 | | Signal list 4
510 | |
511 v |
512 +-----------------------------------+
513 | |
514 | IP network processor |
515 | |
516 +-----------------------------------+
517 ^
518 |
519 |
520 v
521 IP network
522*/
523
524/*
525 Table 31/V.150.1 - MoIP initial modes.
526
527 <<<<<<<< Additional modes supported >>>>>>>> Starting mode
528 FoIP (T.38) and/or ToIP (V.151) VoIP
529 -----------------------------------------------------------------------------
530 No No MoIP
531 No Yes VoIP
532 Yes No MoIP
533 Yes Yes VoIP
534 */
535
536/* Used to verify if a message type is compatible with the transmission
537 control channel it arrives on */
538static uint8_t channel_check[25] =
539{
540 0x0F, /* V150_1_MSGID_NULL */
541 0x04, /* V150_1_MSGID_INIT */
542 0x04, /* V150_1_MSGID_XID_XCHG */
543 0x04, /* V150_1_MSGID_JM_INFO */
544 0x04, /* V150_1_MSGID_START_JM */
545 0x04, /* V150_1_MSGID_CONNECT */
546 0x0F, /* V150_1_MSGID_BREAK */
547 0x0F, /* V150_1_MSGID_BREAKACK */
548 0x04, /* V150_1_MSGID_MR_EVENT */
549 0x04, /* V150_1_MSGID_CLEARDOWN */
550 0x04, /* V150_1_MSGID_PROF_XCHG */
551 0x00, /* Reserved (11) */
552 0x00, /* Reserved (12) */
553 0x00, /* Reserved (13) */
554 0x00, /* Reserved (14) */
555 0x00, /* Reserved (15) */
556 0x0A, /* V150_1_MSGID_I_RAW_OCTET */
557 0x0A, /* V150_1_MSGID_I_RAW_BIT (optional) */
558 0x0A, /* V150_1_MSGID_I_OCTET */
559 0x0A, /* V150_1_MSGID_I_CHAR_STAT (optional) */
560 0x0A, /* V150_1_MSGID_I_CHAR_DYN (optional) */
561 0x0A, /* V150_1_MSGID_I_FRAME (optional) */
562 0x0A, /* V150_1_MSGID_I_OCTET_CS (optional) (this only makes sense for the SPRT_TCID_UNRELIABLE_SEQUENCED channel) */
563 0x0A, /* V150_1_MSGID_I_CHAR_STAT_CS (optional) (this only makes sense for the SPRT_TCID_UNRELIABLE_SEQUENCED channel) */
564 0x0A /* V150_1_MSGID_I_CHAR_DYN_CS (optional) (this only makes sense for the SPRT_TCID_UNRELIABLE_SEQUENCED channel) */
565};
566
567static struct
568{
569 uint16_t min_payload_bytes;
570 uint16_t max_payload_bytes;
571} channel_parm_limits[SPRT_CHANNELS4] =
572{
573 {
574 SPRT_MIN_TC0_PAYLOAD_BYTES140,
575 SPRT_MAX_TC0_PAYLOAD_BYTES256
576 },
577 {
578 SPRT_MIN_TC1_PAYLOAD_BYTES132,
579 SPRT_MAX_TC1_PAYLOAD_BYTES256
580 },
581 {
582 SPRT_MIN_TC2_PAYLOAD_BYTES132,
583 SPRT_MAX_TC2_PAYLOAD_BYTES256
584 },
585 {
586 SPRT_MIN_TC3_PAYLOAD_BYTES140,
587 SPRT_MAX_TC3_PAYLOAD_BYTES256
588 }
589};
590
591static span_timestamp_t update_call_discrimination_timer(v150_1_state_t *s, span_timestamp_t timeout);
592
593SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_msg_id_to_str(int msg_id)
594{
595 const char *res;
596
597 res = "unknown";
598 switch (msg_id)
599 {
600 case V150_1_MSGID_NULL:
601 res = "NULL";
602 break;
603 case V150_1_MSGID_INIT:
604 res = "INIT";
605 break;
606 case V150_1_MSGID_XID_XCHG:
607 res = "XID xchg";
608 break;
609 case V150_1_MSGID_JM_INFO:
610 res = "JM info";
611 break;
612 case V150_1_MSGID_START_JM:
613 res = "Start JM";
614 break;
615 case V150_1_MSGID_CONNECT:
616 res = "Connect";
617 break;
618 case V150_1_MSGID_BREAK:
619 res = "Break";
620 break;
621 case V150_1_MSGID_BREAKACK:
622 res = "Break ack";
623 break;
624 case V150_1_MSGID_MR_EVENT:
625 res = "MR event";
626 break;
627 case V150_1_MSGID_CLEARDOWN:
628 res = "Cleardown";
629 break;
630 case V150_1_MSGID_PROF_XCHG:
631 res = "Prof xchg";
632 break;
633 case V150_1_MSGID_I_RAW_OCTET:
634 res = "I raw octet";
635 break;
636 case V150_1_MSGID_I_RAW_BIT:
637 res = "I raw bit";
638 break;
639 case V150_1_MSGID_I_OCTET:
640 res = "I octet";
641 break;
642 case V150_1_MSGID_I_CHAR_STAT:
643 res = "I char stat";
644 break;
645 case V150_1_MSGID_I_CHAR_DYN:
646 res = "I char dyn";
647 break;
648 case V150_1_MSGID_I_FRAME:
649 res = "I frame";
650 break;
651 case V150_1_MSGID_I_OCTET_CS:
652 res = "I octet cs";
653 break;
654 case V150_1_MSGID_I_CHAR_STAT_CS:
655 res = "I char stat cs";
656 break;
657 case V150_1_MSGID_I_CHAR_DYN_CS:
658 res = "I char dyn cs";
659 break;
660 }
661 /*endswitch*/
662 return res;
663}
664/*- End of function --------------------------------------------------------*/
665
666SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_data_bits_to_str(int code)
667{
668 const char *res;
669
670 res = "unknown";
671 switch (code)
672 {
673 case V150_1_DATA_BITS_5:
674 res = "5 bits";
675 break;
676 case V150_1_DATA_BITS_6:
677 res = "6 bits";
678 break;
679 case V150_1_DATA_BITS_7:
680 res = "7 bits";
681 break;
682 case V150_1_DATA_BITS_8:
683 res = "8 bits";
684 break;
685 }
686 /*endswitch*/
687 return res;
688}
689/*- End of function --------------------------------------------------------*/
690
691SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_parity_to_str(int code)
692{
693 const char *res;
694
695 res = "unknown";
696 switch (code)
697 {
698 case V150_1_PARITY_UNKNOWN:
699 res = "unknown";
700 break;
701 case V150_1_PARITY_NONE:
702 res = "none";
703 break;
704 break;
705 case V150_1_PARITY_EVEN:
706 res = "even";
707 break;
708 case V150_1_PARITY_ODD:
709 res = "odd";
710 break;
711 case V150_1_PARITY_SPACE:
712 res = "space";
713 break;
714 case V150_1_PARITY_MARK:
715 res = "mark";
716 break;
717 }
718 /*endswitch*/
719 return res;
720}
721/*- End of function --------------------------------------------------------*/
722
723SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_stop_bits_to_str(int code)
724{
725 const char *res;
726
727 res = "unknown";
728 switch (code)
729 {
730 case V150_1_STOP_BITS_1:
731 res = "1 bit";
732 break;
733 case V150_1_STOP_BITS_2:
734 res = "2 bits";
735 break;
736 }
737 /*endswitch*/
738 return res;
739}
740/*- End of function --------------------------------------------------------*/
741
742SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_mr_event_type_to_str(int type)
743{
744 const char *res;
745
746 res = "unknown";
747 switch (type)
748 {
749 case V150_1_MR_EVENT_ID_NULL:
750 res = "NULL";
751 break;
752 case V150_1_MR_EVENT_ID_RATE_RENEGOTIATION:
753 res = "Renegotiation";
754 break;
755 case V150_1_MR_EVENT_ID_RETRAIN:
756 res = "Retrain";
757 break;
758 case V150_1_MR_EVENT_ID_PHYSUP:
759 res = "Physically up";
760 break;
761 }
762 /*endswitch*/
763 return res;
764}
765/*- End of function --------------------------------------------------------*/
766
767SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_cleardown_reason_to_str(int type)
768{
769 const char *res;
770
771 res = "unknown";
772 switch (type)
773 {
774 case V150_1_CLEARDOWN_REASON_UNKNOWN:
775 res = "Unknown";
776 break;
777 case V150_1_CLEARDOWN_REASON_PHYSICAL_LAYER_RELEASE:
778 res = "Physical layer release";
779 break;
780 case V150_1_CLEARDOWN_REASON_LINK_LAYER_DISCONNECT:
781 res = "Link layer disconnect";
782 break;
783 case V150_1_CLEARDOWN_REASON_DATA_COMPRESSION_DISCONNECT:
784 res = "Data compression disconnect";
785 break;
786 case V150_1_CLEARDOWN_REASON_ABORT:
787 res = "Abort";
788 break;
789 case V150_1_CLEARDOWN_REASON_ON_HOOK:
790 res = "On hook";
791 break;
792 case V150_1_CLEARDOWN_REASON_NETWORK_LAYER_TERMINATION:
793 res = "Network layer termination";
794 break;
795 case V150_1_CLEARDOWN_REASON_ADMINISTRATIVE:
796 res = "Administrative";
797 break;
798 }
799 /*endswitch*/
800 return res;
801}
802/*- End of function --------------------------------------------------------*/
803
804SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_symbol_rate_to_str(int code)
805{
806 const char *res;
807
808 res = "unknown";
809 switch (code)
810 {
811 case V150_1_SYMBOL_RATE_NULL:
812 res = "NULL";
813 break;
814 case V150_1_SYMBOL_RATE_600:
815 res = "600 baud";
816 break;
817 case V150_1_SYMBOL_RATE_1200:
818 res = "1200 baud";
819 break;
820 case V150_1_SYMBOL_RATE_1600:
821 res = "1600 baud";
822 break;
823 case V150_1_SYMBOL_RATE_2400:
824 res = "2400 baud";
825 break;
826 case V150_1_SYMBOL_RATE_2743:
827 res = "2743 baud";
828 break;
829 case V150_1_SYMBOL_RATE_3000:
830 res = "3000 baud";
831 break;
832 case V150_1_SYMBOL_RATE_3200:
833 res = "3200 baud";
834 break;
835 case V150_1_SYMBOL_RATE_3429:
836 res = "3429 baud";
837 break;
838 case V150_1_SYMBOL_RATE_8000:
839 res = "8000 baud";
840 break;
841 }
842 /*endswitch*/
843 return res;
844}
845/*- End of function --------------------------------------------------------*/
846
847SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_modulation_to_str(int modulation)
848{
849 const char *res;
850
851 res = "unknown";
852 switch (modulation)
853 {
854 case V150_1_SELMOD_NULL:
855 res = "NULL";
856 break;
857 case V150_1_SELMOD_V92:
858 res = "V.92";
859 break;
860 case V150_1_SELMOD_V91:
861 res = "V.91";
862 break;
863 case V150_1_SELMOD_V90:
864 res = "V90";
865 break;
866 case V150_1_SELMOD_V34:
867 res = "V.34";
868 break;
869 case V150_1_SELMOD_V32bis:
870 res = "V.32bis";
871 break;
872 case V150_1_SELMOD_V32:
873 res = "V.32";
874 break;
875 case V150_1_SELMOD_V22bis:
876 res = "V.22bis";
877 break;
878 case V150_1_SELMOD_V22:
879 res = "V.22";
880 break;
881 case V150_1_SELMOD_V17:
882 res = "V.17";
883 break;
884 case V150_1_SELMOD_V29:
885 res = "V.29";
886 break;
887 case V150_1_SELMOD_V27ter:
888 res = "V.27ter";
889 break;
890 case V150_1_SELMOD_V26ter:
891 res = "V.26ter";
892 break;
893 case V150_1_SELMOD_V26bis:
894 res = "V.26bis";
895 break;
896 case V150_1_SELMOD_V23:
897 res = "V.23";
898 break;
899 case V150_1_SELMOD_V21:
900 res = "V.21";
901 break;
902 case V150_1_SELMOD_BELL212:
903 res = "Bell 212";
904 break;
905 case V150_1_SELMOD_BELL103:
906 res = "Bell 103";
907 break;
908 }
909 /*endswitch*/
910 return res;
911}
912/*- End of function --------------------------------------------------------*/
913
914SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_compression_to_str(int compression)
915{
916 const char *res;
917
918 res = "unknown";
919 switch (compression)
920 {
921 case V150_1_COMPRESSION_NONE:
922 res = "None";
923 break;
924 case V150_1_COMPRESSION_V42BIS:
925 res = "V.42bis";
926 break;
927 case V150_1_COMPRESSION_V44:
928 res = "V.44";
929 break;
930 case V150_1_COMPRESSION_MNP5:
931 res = "MNP5";
932 break;
933 }
934 /*endswitch*/
935 return res;
936}
937/*- End of function --------------------------------------------------------*/
938
939SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_compression_direction_to_str(int direction)
940{
941 const char *res;
942
943 res = "unknown";
944 switch (direction)
945 {
946 case V150_1_COMPRESS_NEITHER_WAY:
947 res = "Neither way";
948 break;
949 case V150_1_COMPRESS_TX_ONLY:
950 res = "Tx only";
951 break;
952 case V150_1_COMPRESS_RX_ONLY:
953 res = "Rx only";
954 break;
955 case V150_1_COMPRESS_BIDIRECTIONAL:
956 res = "Bidirectional";
957 break;
958 }
959 /*endswitch*/
960 return res;
961}
962/*- End of function --------------------------------------------------------*/
963
964SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_error_correction_to_str(int correction)
965{
966 const char *res;
967
968 res = "unknown";
969 switch (correction)
970 {
971 case V150_1_ERROR_CORRECTION_NONE:
972 res = "None";
973 break;
974 case V150_1_ERROR_CORRECTION_V42_LAPM:
975 res = "V.42 LAPM";
976 break;
977 case V150_1_ERROR_CORRECTION_V42_ANNEX_A:
978 res = "V.42 annex A";
979 break;
980 }
981 /*endswitch*/
982 return res;
983}
984/*- End of function --------------------------------------------------------*/
985
986SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_break_source_to_str(int source)
987{
988 const char *res;
989
990 res = "unknown";
991 switch (source)
992 {
993 case V150_1_BREAK_SOURCE_V42_LAPM:
994 res = "V.42 LAPM";
995 break;
996 case V150_1_BREAK_SOURCE_V42_ANNEX_A:
997 res = "V.42 annex A";
998 break;
999 case V150_1_BREAK_SOURCE_V14:
1000 res = "V.14";
1001 break;
1002 }
1003 /*endswitch*/
1004 return res;
1005}
1006/*- End of function --------------------------------------------------------*/
1007
1008SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_break_type_to_str(int type)
1009{
1010 const char *res;
1011
1012 res = "unknown";
1013 switch (type)
1014 {
1015 case V150_1_BREAK_TYPE_NOT_APPLICABLE:
1016 res = "Non applicable";
1017 break;
1018 case V150_1_BREAK_TYPE_DESTRUCTIVE_EXPEDITED:
1019 res = "Destructive, expedited";
1020 break;
1021 case V150_1_BREAK_TYPE_NON_DESTRUCTIVE_EXPEDITED:
1022 res = "Non-destructive, expedited";
1023 break;
1024 case V150_1_BREAK_TYPE_NON_DESTRUCTIVE_NON_EXPEDITED:
1025 res = "Non-destructive, non-expedited";
1026 break;
1027 }
1028 /*endswitch*/
1029 return res;
1030}
1031/*- End of function --------------------------------------------------------*/
1032
1033SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_state_to_str(int state)
1034{
1035 const char *res;
1036
1037 res = "unknown";
1038 switch (state)
1039 {
1040 case V150_1_STATE_IDLE:
1041 res = "Idle";
1042 break;
1043 case V150_1_STATE_INITED:
1044 res = "Inited";
1045 break;
1046 case V150_1_STATE_PHYSUP:
1047 res = "Physically up";
1048 break;
1049 case V150_1_STATE_CONNECTED:
1050 res = "Connected";
1051 break;
1052 }
1053 /*endswitch*/
1054 return res;
1055}
1056/*- End of function --------------------------------------------------------*/
1057
1058SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_status_reason_to_str(int status)
1059{
1060 const char *res;
1061
1062 res = "unknown";
1063 switch (status)
1064 {
1065 case V150_1_STATUS_REASON_NULL:
1066 res = "NULL";
1067 break;
1068 case V150_1_STATUS_REASON_MEDIA_STATE_CHANGED:
1069 res = "media state changed";
1070 break;
1071 case V150_1_STATUS_REASON_CONNECTION_STATE_CHANGED:
1072 res = "connection state changed";
1073 break;
1074 case V150_1_STATUS_REASON_DATA_FORMAT_CHANGED:
1075 res = "format changed";
1076 break;
1077 case V150_1_STATUS_REASON_BREAK_RECEIVED:
1078 res = "break received";
1079 break;
1080 case V150_1_STATUS_REASON_RATE_RETRAIN_RECEIVED:
1081 res = "retrain request received";
1082 break;
1083 case V150_1_STATUS_REASON_RATE_RENEGOTIATION_RECEIVED:
1084 res = "rate renegotiation received";
1085 break;
1086 case V150_1_STATUS_REASON_BUSY_CHANGED:
1087 res = "busy changed";
1088 break;
1089 case V150_1_STATUS_REASON_CONNECTION_STATE_PHYSUP:
1090 res = "physically up";
1091 break;
1092 case V150_1_STATUS_REASON_CONNECTION_STATE_CONNECTED:
1093 res = "connected";
1094 break;
1095 }
1096 /*endswitch*/
1097 return res;
1098}
1099/*- End of function --------------------------------------------------------*/
1100
1101SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_jm_category_to_str(int category)
1102{
1103 const char *res;
1104
1105 res = "unknown";
1106 switch (category)
1107 {
1108 case V150_1_JM_CATEGORY_ID_PROTOCOLS:
1109 res = "protocols";
1110 break;
1111 case V150_1_JM_CATEGORY_ID_CALL_FUNCTION_1:
1112 res = "call function 1";
1113 break;
1114 case V150_1_JM_CATEGORY_ID_MODULATION_MODES:
1115 res = "modulation modes";
1116 break;
1117 case V150_1_JM_CATEGORY_ID_PSTN_ACCESS:
1118 res = "PSTN access";
1119 break;
1120 case V150_1_JM_CATEGORY_ID_PCM_MODEM_AVAILABILITY:
1121 res = "PCM modem availability";
1122 break;
1123 case V150_1_JM_CATEGORY_ID_EXTENSION:
1124 res = "extension";
1125 break;
1126 }
1127 /*endswitch*/
1128 return res;
1129}
1130/*- End of function --------------------------------------------------------*/
1131
1132SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_jm_info_modulation_to_str(int modulation)
1133{
1134 const char *res;
1135
1136 res = "unknown";
1137 switch (modulation)
1138 {
1139 case V150_1_JM_MODULATION_MODE_V34_AVAILABLE:
1140 res = "V.34";
1141 break;
1142 case V150_1_JM_MODULATION_MODE_V34_HALF_DUPLEX_AVAILABLE:
1143 res = "V.34 half-duplex";
1144 break;
1145 case V150_1_JM_MODULATION_MODE_V32_V32bis_AVAILABLE:
1146 res = "V.32bis/V,32";
1147 break;
1148 case V150_1_JM_MODULATION_MODE_V22_V22bis_AVAILABLE:
1149 res = "V.22bis/V.22";
1150 break;
1151 case V150_1_JM_MODULATION_MODE_V17_AVAILABLE:
1152 res = "V.17";
1153 break;
1154 case V150_1_JM_MODULATION_MODE_V29_AVAILABLE:
1155 res = "V.29";
1156 break;
1157 case V150_1_JM_MODULATION_MODE_V27ter_AVAILABLE:
1158 res = "V.27ter";
1159 break;
1160 case V150_1_JM_MODULATION_MODE_V26ter_AVAILABLE:
1161 res = "V.26ter";
1162 break;
1163 case V150_1_JM_MODULATION_MODE_V26bis_AVAILABLE:
1164 res = "V.26bis";
1165 break;
1166 case V150_1_JM_MODULATION_MODE_V23_AVAILABLE:
1167 res = "V.23";
1168 break;
1169 case V150_1_JM_MODULATION_MODE_V23_HALF_DUPLEX_AVAILABLE:
1170 res = "V.23 half-duplex";
1171 break;
1172 case V150_1_JM_MODULATION_MODE_V21_AVAILABLE:
1173 res = "V.21";
1174 break;
1175 }
1176 /*endswitch*/
1177 return res;
1178}
1179/*- End of function --------------------------------------------------------*/
1180
1181SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_signal_to_str(int modulation)
1182{
1183 const char *res;
1184
1185 res = "unknown";
1186 switch (modulation)
1187 {
1188 case V150_1_SIGNAL_TONE_2100HZ:
1189 res = "2100Hz detected";
1190 break;
1191 case V150_1_SIGNAL_TONE_2225HZ:
1192 res = "2225Hz detected";
1193 break;
1194 case V150_1_SIGNAL_ANS:
1195 res = "V.25 ANS detected";
1196 break;
1197 case V150_1_SIGNAL_ANS_PR:
1198 res = "V.25 ANS reversal detected";
1199 break;
1200 case V150_1_SIGNAL_ANSAM:
1201 res = "V.8 ANSam detected";
1202 break;
1203 case V150_1_SIGNAL_ANSAM_PR:
1204 res = "V.8 ANSam reversal detected";
1205 break;
1206 case V150_1_SIGNAL_CI:
1207 res = "V.8 CI detected";
1208 break;
1209 case V150_1_SIGNAL_CM:
1210 res = "V.8 CM detected";
1211 break;
1212 case V150_1_SIGNAL_JM:
1213 res = "V.8 JM detected";
1214 break;
1215 case V150_1_SIGNAL_V21_LOW:
1216 res = "V.21 low channel detected";
1217 break;
1218 case V150_1_SIGNAL_V21_HIGH:
1219 res = "V.21 high channel detected";
1220 break;
1221 case V150_1_SIGNAL_V23_LOW:
1222 res = "V.23 low channel detected";
1223 break;
1224 case V150_1_SIGNAL_V23_HIGH:
1225 res = "V.23 high channel detected";
1226 break;
1227 case V150_1_SIGNAL_SB1:
1228 res = "V.22bis scrambled ones detected";
1229 break;
1230 case V150_1_SIGNAL_USB1:
1231 res = "V.22bis unscrambled ones detected";
1232 break;
1233 case V150_1_SIGNAL_S1:
1234 res = "V.22bis S1 detected";
1235 break;
1236 case V150_1_SIGNAL_AA:
1237 res = "V.32/V.32bis AA detected";
1238 break;
1239 case V150_1_SIGNAL_AC:
1240 res = "V.32/V.32bis AC detected";
1241 break;
1242 case V150_1_SIGNAL_CALL_DISCRIMINATION_TIMEOUT:
1243 res = "Call discrimination time-out";
1244 break;
1245 case V150_1_SIGNAL_UNKNOWN:
1246 res = "unrecognised signal detected";
1247 break;
1248 case V150_1_SIGNAL_SILENCE:
1249 res = "silence detected";
1250 break;
1251 case V150_1_SIGNAL_ABORT:
1252 res = "SPE has initiated an abort request";
1253 break;
1254
1255 case V150_1_SIGNAL_ANS_GEN:
1256 res = "Generate V.25 ANS";
1257 break;
1258 case V150_1_SIGNAL_ANS_PR_GEN:
1259 res = "Generate V.25 ANS reversal";
1260 break;
1261 case V150_1_SIGNAL_ANSAM_GEN:
1262 res = "Generate V.8 ANSam";
1263 break;
1264 case V150_1_SIGNAL_ANSAM_PR_GEN:
1265 res = "Generate V.8 ANSam reversal";
1266 break;
1267 case V150_1_SIGNAL_2225HZ_GEN:
1268 res = "Generate 2225Hz";
1269 break;
1270 case V150_1_SIGNAL_CONCEAL_MODEM:
1271 res = "Block modem signal";
1272 break;
1273 case V150_1_SIGNAL_BLOCK_2100HZ_TONE:
1274 res = "Block 2100Hz";
1275 break;
1276 case V150_1_SIGNAL_AUTOMODE_ENABLE:
1277 res = "Enable automode";
1278 break;
1279
1280 case V150_1_SIGNAL_AUDIO_GEN:
1281 res = "Send audio state";
1282 break;
1283 case V150_1_SIGNAL_FAX_RELAY_GEN:
1284 res = "Send fax relay state";
1285 break;
1286 case V150_1_SIGNAL_INDETERMINATE_GEN:
1287 res = "Send indeterminate state";
1288 break;
1289 case V150_1_SIGNAL_MODEM_RELAY_GEN:
1290 res = "Send modem relay state";
1291 break;
1292 case V150_1_SIGNAL_TEXT_RELAY_GEN:
1293 res = "Send text relay state";
1294 break;
1295 case V150_1_SIGNAL_VBD_GEN:
1296 res = "Send VBD state";
1297 break;
1298 case V150_1_SIGNAL_RFC4733_ANS_GEN:
1299 res = "Send RFC4733 ANS";
1300 break;
1301 case V150_1_SIGNAL_RFC4733_ANS_PR_GEN:
1302 res = "Send RFC4733 ANS reversal";
1303 break;
1304 case V150_1_SIGNAL_RFC4733_ANSAM_GEN:
1305 res = "Send RFC4733 ANSam";
1306 break;
1307 case V150_1_SIGNAL_RFC4733_ANSAM_PR_GEN:
1308 res = "Send RFC4733 ANSam reversal";
1309 break;
1310 case V150_1_SIGNAL_RFC4733_TONE_GEN:
1311 res = "Send RFC4733 tone";
1312 break;
1313
1314 case V150_1_SIGNAL_AUDIO:
1315 res = "Audio state detected";
1316 break;
1317 case V150_1_SIGNAL_FAX_RELAY:
1318 res = "Facsimile relay state detected";
1319 break;
1320 case V150_1_SIGNAL_INDETERMINATE:
1321 res = "Indeterminate state detected";
1322 break;
1323 case V150_1_SIGNAL_MODEM_RELAY:
1324 res = "Modem relay state detected";
1325 break;
1326 case V150_1_SIGNAL_TEXT_RELAY:
1327 res = "Text relay state detected";
1328 break;
1329 case V150_1_SIGNAL_VBD:
1330 res = "VBD state detected";
1331 break;
1332 case V150_1_SIGNAL_RFC4733_ANS:
1333 res = "RFC4733 ANS event detected";
1334 break;
1335 case V150_1_SIGNAL_RFC4733_ANS_PR:
1336 res = "RFC4733 ANS reversal detected";
1337 break;
1338 case V150_1_SIGNAL_RFC4733_ANSAM:
1339 res = "RFC4733 ANSam detected";
1340 break;
1341 case V150_1_SIGNAL_RFC4733_ANSAM_PR:
1342 res = "RFC4733 ANSam reversal detected";
1343 break;
1344 case V150_1_SIGNAL_RFC4733_TONE:
1345 res = "RFC4733 tone detected";
1346 break;
1347
1348 case V150_1_SIGNAL_AUDIO_STATE:
1349 res = "Audio";
1350 break;
1351 case V150_1_SIGNAL_FAX_RELAY_STATE:
1352 res = "Fax relay";
1353 break;
1354 case V150_1_SIGNAL_INDETERMINATE_STATE:
1355 res = "Indeterminate";
1356 break;
1357 case V150_1_SIGNAL_MODEM_RELAY_STATE:
1358 res = "Modem relay";
1359 break;
1360 case V150_1_SIGNAL_TEXT_RELAY_STATE:
1361 res = "Text relay";
1362 break;
1363 case V150_1_SIGNAL_VBD_STATE:
1364 res = "VBD";
1365 break;
1366
1367 case V150_1_SIGNAL_CALL_DISCRIMINATION_TIMER_EXPIRED:
1368 res = "Call discrimination timer exposed";
1369 break;
1370 }
1371 /*endswitch*/
1372 return res;
1373}
1374/*- End of function --------------------------------------------------------*/
1375
1376SPAN_DECLARE(const char *)__attribute__((visibility("default"))) const char * v150_1_media_state_to_str(int state)
1377{
1378 const char *res;
1379
1380 res = "unknown";
1381 switch (state)
1382 {
1383 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
1384 res = "Initial Audio";
1385 break;
1386 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
1387 res = "Voice Band Data (VBD)";
1388 break;
1389 case V150_1_MEDIA_STATE_MODEM_RELAY:
1390 res = "Modem Relay";
1391 break;
1392 case V150_1_MEDIA_STATE_FAX_RELAY:
1393 res = "Fax Relay";
1394 break;
1395 case V150_1_MEDIA_STATE_TEXT_RELAY:
1396 res = "Text Relay";
1397 break;
1398 case V150_1_MEDIA_STATE_TEXT_PROBE:
1399 res = "Text Probe";
1400 break;
1401 case V150_1_MEDIA_STATE_INDETERMINATE:
1402 res = "Indeterminate";
1403 break;
1404 }
1405 /*endswitch*/
1406 return res;
1407}
1408/*- End of function --------------------------------------------------------*/
1409
1410static int status_report(v150_1_state_t *s, int reason)
1411{
1412 v150_1_status_t report;
1413
1414 report.reason = reason;
1415 switch (reason)
1416 {
1417 case V150_1_STATUS_REASON_MEDIA_STATE_CHANGED:
1418 report.types.media_state_change.local_state = s->local_media_state;
1419 report.types.media_state_change.remote_state = s->remote_media_state;
1420 break;
1421 case V150_1_STATUS_REASON_CONNECTION_STATE_CHANGED:
1422 report.types.connection_state_change.state = s->far.parms.connection_state;
1423 report.types.connection_state_change.cleardown_reason = s->far.parms.cleardown_reason;
1424 break;
1425 case V150_1_STATUS_REASON_CONNECTION_STATE_PHYSUP:
1426 report.types.physup_parameters.selmod = s->far.parms.selmod;
1427 report.types.physup_parameters.tdsr = s->far.parms.tdsr;
1428 report.types.physup_parameters.rdsr = s->far.parms.rdsr;
1429
1430 report.types.physup_parameters.txsen = s->far.parms.txsen;
1431 report.types.physup_parameters.txsr = s->far.parms.txsr;
1432 report.types.physup_parameters.rxsen = s->far.parms.rxsen;
1433 report.types.physup_parameters.rxsr = s->far.parms.rxsr;
1434 break;
1435 case V150_1_STATUS_REASON_CONNECTION_STATE_CONNECTED:
1436 report.types.connect_parameters.selmod = s->far.parms.selmod;
1437 report.types.connect_parameters.tdsr = s->far.parms.tdsr;
1438 report.types.connect_parameters.rdsr = s->far.parms.rdsr;
1439
1440 report.types.connect_parameters.selected_compression_direction = s->far.parms.selected_compression_direction;
1441 report.types.connect_parameters.selected_compression = s->far.parms.selected_compression;
1442 report.types.connect_parameters.selected_error_correction = s->far.parms.selected_error_correction;
1443
1444 report.types.connect_parameters.compression_tx_dictionary_size = s->far.parms.compression_tx_dictionary_size;
1445 report.types.connect_parameters.compression_rx_dictionary_size = s->far.parms.compression_rx_dictionary_size;
1446 report.types.connect_parameters.compression_tx_string_length = s->far.parms.compression_tx_string_length;
1447 report.types.connect_parameters.compression_rx_string_length = s->far.parms.compression_rx_string_length;
1448 report.types.connect_parameters.compression_tx_history_size = s->far.parms.compression_tx_history_size;
1449 report.types.connect_parameters.compression_rx_history_size = s->far.parms.compression_rx_history_size;
1450
1451 /* I_RAW-OCTET is always available. There is no selection flag for it. */
1452 report.types.connect_parameters.i_raw_octet_available = true1;
1453 report.types.connect_parameters.i_raw_bit_available = s->far.parms.i_raw_bit_available;
1454 report.types.connect_parameters.i_frame_available = s->far.parms.i_frame_available;
1455 /* I_OCTET is an oddity, as you need to know in advance whether there will be a DLCI field
1456 present. So, functionally its really like 2 different types of message. */
1457 report.types.connect_parameters.i_octet_with_dlci_available = s->far.parms.i_octet_with_dlci_available;
1458 report.types.connect_parameters.i_octet_without_dlci_available = s->far.parms.i_octet_without_dlci_available;
1459 report.types.connect_parameters.i_char_stat_available = s->far.parms.i_char_stat_available;
1460 report.types.connect_parameters.i_char_dyn_available = s->far.parms.i_char_dyn_available;
1461 /* Unlike I_OCTET, I_OCTET-CS is only defined without a DLCI field. */
1462 report.types.connect_parameters.i_octet_cs_available = s->far.parms.i_octet_cs_available;
1463 report.types.connect_parameters.i_char_stat_cs_available = s->far.parms.i_char_stat_cs_available;
1464 report.types.connect_parameters.i_char_dyn_cs_available = s->far.parms.i_char_dyn_cs_available;
1465 break;
1466 case V150_1_STATUS_REASON_DATA_FORMAT_CHANGED:
1467 report.types.data_format_change.bits = 5 + ((s->far.parms.data_format_code >> 5) & 0x03);
1468 report.types.data_format_change.parity_code = (s->far.parms.data_format_code >> 2) & 0x07;
1469 report.types.data_format_change.stop_bits = 1 + (s->far.parms.data_format_code & 0x03);
1470 break;
1471 case V150_1_STATUS_REASON_BREAK_RECEIVED:
1472 report.types.break_received.source = s->far.break_source;
1473 report.types.break_received.type = s->far.break_type;
1474 report.types.break_received.duration = s->far.break_duration*10;
1475 break;
1476 case V150_1_STATUS_REASON_RATE_RETRAIN_RECEIVED:
1477 break;
1478 case V150_1_STATUS_REASON_RATE_RENEGOTIATION_RECEIVED:
1479 break;
1480 case V150_1_STATUS_REASON_BUSY_CHANGED:
1481 report.types.busy_change.local_busy = s->near.parms.busy;
1482 report.types.busy_change.far_busy = s->far.parms.busy;
1483 break;
1484 }
1485 /*endswitch*/
1486 if (s->rx_status_report_handler)
1487 s->rx_status_report_handler(s->rx_status_report_user_data, &report);
1488 /*endif*/
1489 return 0;
1490}
1491/*- End of function --------------------------------------------------------*/
1492
1493static int send_spe_signal(v150_1_state_t *s, int signal)
1494{
1495 span_log(&s->logging, SPAN_LOG_FLOW, "Signal to SPE %s\n", v150_1_signal_to_str(signal));
1496 return 0;
1497}
1498/*- End of function --------------------------------------------------------*/
1499
1500static int send_ip_signal(v150_1_state_t *s, int signal)
1501{
1502 span_log(&s->logging, SPAN_LOG_FLOW, "Signal to IP %s\n", v150_1_signal_to_str(signal));
1503 return 0;
1504}
1505/*- End of function --------------------------------------------------------*/
1506
1507static int stop_timer(v150_1_state_t *s)
1508{
1509 span_log(&s->logging, SPAN_LOG_FLOW, "Stop timer\n");
1510 return 0;
1511}
1512/*- End of function --------------------------------------------------------*/
1513
1514static int generic_macro(v150_1_state_t *s, int signal, int ric)
1515{
1516 span_timestamp_t now;
1517
1518 /* Figure 25/V.150.1 */
1519 span_log(&s->logging,
1520 SPAN_LOG_FLOW,
1521 "IP signal %s(%s, %s)\n",
1522 v150_1_media_state_to_str(s->local_media_state),
1523 v150_1_signal_to_str(signal),
1524 v150_1_sse_moip_ric_to_str(ric));
1525 if (s->local_media_state == s->remote_media_state)
1526 {
1527 /* Stop the call discrimination timer */
1528 s->call_discrimination_timer = 0;
1529 update_call_discrimination_timer(s, s->call_discrimination_timer);
1530 }
1531 else
1532 {
1533 /* Start the call discrimination timer */
1534 if (s->call_discrimination_timer == 0)
1535 {
1536 now = update_call_discrimination_timer(s, ~0);
1537 s->call_discrimination_timer = now + s->call_discrimination_timeout;
1538 update_call_discrimination_timer(s, s->call_discrimination_timer);
1539 }
1540 /*endif*/
1541 }
1542 /*endif*/
1543 return 0;
1544}
1545/*- End of function --------------------------------------------------------*/
1546
1547static void update_media_states(v150_1_state_t *s, int local, int remote)
1548{
1549 if (local != s->local_media_state || remote != s->remote_media_state)
1550 {
1551 s->remote_media_state = remote;
1552 s->local_media_state = local;
1553 status_report(s, V150_1_STATUS_REASON_MEDIA_STATE_CHANGED);
1554 }
1555 /*endif*/
1556}
1557/*- End of function --------------------------------------------------------*/
1558
1559static int v150_1_figures_26_to_31(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1560{
1561 /* Figure 26/V.150.1 to 31/V.150.1 */
1562 switch (signal)
1563 {
1564 case V150_1_SIGNAL_TONE_2100HZ:
1565 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1566 ||
1567 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1568 {
1569 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, s->remote_media_state);
1570 //send ANS or ANSam
1571 generic_macro(s, V150_1_SIGNAL_ANS, 0);
1572 }
1573 else
1574 {
1575 send_spe_signal(s, V150_1_SIGNAL_BLOCK_2100HZ_TONE);
1576 }
1577 /*endif*/
1578 break;
1579 case V150_1_SIGNAL_ANS:
1580 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1581 ||
1582 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1583 {
1584 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, s->remote_media_state);
1585 generic_macro(s, V150_1_SIGNAL_ANS, 0);
1586 }
1587 else
1588 {
1589 generic_macro(s, V150_1_SIGNAL_RFC4733_ANS_GEN, 0);
1590 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1591 }
1592 /*endif*/
1593 break;
1594 case V150_1_SIGNAL_ANSAM:
1595 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1596 ||
1597 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1598 {
1599 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, s->remote_media_state);
1600 generic_macro(s, V150_1_SIGNAL_ANSAM, 0);
1601 }
1602 else
1603 {
1604 generic_macro(s, V150_1_SIGNAL_RFC4733_ANSAM_GEN, 0);
1605 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1606 }
1607 /*endif*/
1608 break;
1609 case V150_1_SIGNAL_RFC4733_ANS:
1610 send_spe_signal(s, V150_1_SIGNAL_ANS_GEN);
1611 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1612 break;
1613 case V150_1_SIGNAL_RFC4733_ANSAM:
1614 send_spe_signal(s, V150_1_SIGNAL_ANSAM_GEN);
1615 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1616 break;
1617 case V150_1_SIGNAL_RFC4733_ANS_PR:
1618 send_spe_signal(s, V150_1_SIGNAL_ANS_PR_GEN);
1619 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1620 break;
1621 case V150_1_SIGNAL_RFC4733_ANSAM_PR:
1622 send_spe_signal(s, V150_1_SIGNAL_ANSAM_PR_GEN);
1623 send_spe_signal(s, V150_1_SIGNAL_CONCEAL_MODEM);
1624 break;
1625 case V150_1_SIGNAL_ANS_PR:
1626 break;
1627 case V150_1_SIGNAL_ANSAM_PR:
1628 break;
1629 case V150_1_SIGNAL_UNKNOWN:
1630 case V150_1_SIGNAL_CALL_DISCRIMINATION_TIMEOUT:
1631 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1632 ||
1633 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1634 {
1635 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, s->remote_media_state);
1636 generic_macro(s, signal, 0);
1637 }
1638 /*endif*/
1639 break;
1640 case V150_1_SIGNAL_VBD:
1641 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1642 ||
1643 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1644 {
1645 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, V150_1_MEDIA_STATE_VOICE_BAND_DATA);
1646 generic_macro(s, signal, 0);
1647 }
1648 else
1649 {
1650 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, s->remote_media_state);
1651 generic_macro(s, signal, 0);
1652 }
1653 /*endif*/
1654 break;
1655 case V150_1_SIGNAL_MODEM_RELAY:
1656 span_log(&s->logging, SPAN_LOG_FLOW, "Modem relay signal %s\n", v150_1_signal_to_str(signal));
1657 break;
1658 case V150_1_SIGNAL_CM:
1659 span_log(&s->logging, SPAN_LOG_FLOW, "SPE signal %s\n", v150_1_signal_to_str(signal));
1660 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1661 ||
1662 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1663 {
1664 update_media_states(s, V150_1_MEDIA_STATE_VOICE_BAND_DATA, V150_1_MEDIA_STATE_MODEM_RELAY);
1665 generic_macro(s, V150_1_SIGNAL_MODEM_RELAY_GEN, V150_1_SSE_MOIP_RIC_V8_CM);
1666 }
1667 else
1668 {
1669 update_media_states(s, V150_1_MEDIA_STATE_MODEM_RELAY, V150_1_MEDIA_STATE_MODEM_RELAY);
1670 generic_macro(s, V150_1_SIGNAL_MODEM_RELAY_GEN, V150_1_SSE_MOIP_RIC_V8_CM);
1671 }
1672 /*endif*/
1673 break;
1674 /*supported modulations */
1675 default:
1676 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1677 break;
1678 }
1679 /*endswitch*/
1680 return 0;
1681}
1682/*- End of function --------------------------------------------------------*/
1683
1684static int v150_1_figure_32(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1685{
1686 /* Figure 32/V.150.1 */
1687 switch (signal)
1688 {
1689 case V150_1_SIGNAL_AUDIO:
1690 //send SSE p'
1691 generic_macro(s, signal, 0);
1692 break;
1693 default:
1694 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1695 break;
1696 }
1697 /*endswitch*/
1698 return 0;
1699}
1700/*- End of function --------------------------------------------------------*/
1701
1702static int v150_1_figure_33(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1703{
1704 /* Figure 33/V.150.1 */
1705 switch (signal)
1706 {
1707 case V150_1_SIGNAL_AUDIO:
1708 //send SSE p'
1709 generic_macro(s, signal, 0);
1710 break;
1711 default:
1712 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1713 break;
1714 }
1715 /*endswitch*/
1716 return 0;
1717}
1718/*- End of function --------------------------------------------------------*/
1719
1720static int v150_1_figure_34(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1721{
1722 /* Figure 34/V.150.1 */
1723 switch (signal)
1724 {
1725 case V150_1_SIGNAL_AUDIO:
1726 //send SSE p'
1727 generic_macro(s, signal, 0);
1728 break;
1729 case V150_1_SIGNAL_MODEM_RELAY:
1730 stop_timer(s);
1731 break;
1732 case V150_1_SIGNAL_VBD:
1733 //send SSE RC
1734 generic_macro(s, signal, 0);
1735 break;
1736 default:
1737 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1738 break;
1739 }
1740 /*endswitch*/
1741 return 0;
1742}
1743/*- End of function --------------------------------------------------------*/
1744
1745static int v150_1_figure_35(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1746{
1747 /* Figure 35/V.150.1 */
1748 switch (signal)
1749 {
1750 case V150_1_SIGNAL_JM:
1751 if (s->cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
1752 ||
1753 s->cdscselect == V150_1_CDSCSELECT_MIXED)
1754 {
1755 }
1756 else
1757 {
1758 }
1759 /*endif*/
1760 break;
1761 case V150_1_SIGNAL_VBD:
1762 update_media_states(s, s->local_media_state, V150_1_MEDIA_STATE_VOICE_BAND_DATA);
1763 break;
1764 default:
1765 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1766 break;
1767 }
1768 /*endswitch*/
1769 return 0;
1770}
1771/*- End of function --------------------------------------------------------*/
1772
1773static int v150_1_figure_36(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1774{
1775 /* Figure 36/V.150.1 */
1776 switch (signal)
1777 {
1778 case V150_1_SIGNAL_AUDIO:
1779 update_media_states(s, V150_1_MEDIA_STATE_INITIAL_AUDIO, V150_1_MEDIA_STATE_VOICE_BAND_DATA);
1780 break;
1781 case V150_1_SIGNAL_MODEM_RELAY:
1782 stop_timer(s);
1783 break;
1784 case V150_1_SIGNAL_VBD:
1785 stop_timer(s);
1786 update_media_states(s, V150_1_MEDIA_STATE_INITIAL_AUDIO, V150_1_MEDIA_STATE_VOICE_BAND_DATA);
1787 // send sse p'
1788 generic_macro(s, signal, 0);
1789 break;
1790 default:
1791 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1792 break;
1793 }
1794 /*endswitch*/
1795 return 0;
1796}
1797/*- End of function --------------------------------------------------------*/
1798
1799static int v150_1_figure_37(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1800{
1801 /* Figure 37/V.150.1 */
1802 switch (signal)
1803 {
1804 case V150_1_SIGNAL_AUDIO:
1805 update_media_states(s, V150_1_MEDIA_STATE_INITIAL_AUDIO, V150_1_MEDIA_STATE_INITIAL_AUDIO);
1806 break;
1807 case V150_1_SIGNAL_MODEM_RELAY:
1808 stop_timer(s);
1809 break;
1810 case V150_1_SIGNAL_VBD:
1811 stop_timer(s);
1812 break;
1813 default:
1814 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1815 break;
1816 }
1817 /*endswitch*/
1818 return 0;
1819}
1820/*- End of function --------------------------------------------------------*/
1821
1822static int v150_1_figure_38(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1823{
1824 /* Figure 38/V.150.1 */
1825 switch (signal)
1826 {
1827 case V150_1_SIGNAL_AUDIO:
1828 update_media_states(s, V150_1_MEDIA_STATE_INITIAL_AUDIO, V150_1_MEDIA_STATE_INITIAL_AUDIO);
1829 break;
1830 case V150_1_SIGNAL_VBD:
1831 stop_timer(s);
1832 break;
1833 default:
1834 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1835 break;
1836 }
1837 /*endswitch*/
1838 return 0;
1839}
1840/*- End of function --------------------------------------------------------*/
1841
1842static int v150_1_figure_39(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1843{
1844 /* Figure 39/V.150.1 */
1845 switch (signal)
1846 {
1847 case V150_1_SIGNAL_MODEM_RELAY:
1848 break;
1849 case V150_1_SIGNAL_CM:
1850 break;
1851 case V150_1_SIGNAL_RFC4733_ANS:
1852 send_spe_signal(s, V150_1_SIGNAL_ANS_GEN);
1853 break;
1854 case V150_1_SIGNAL_RFC4733_ANSAM:
1855 send_spe_signal(s, V150_1_SIGNAL_ANSAM_GEN);
1856 break;
1857 case V150_1_SIGNAL_RFC4733_ANS_PR:
1858 send_spe_signal(s, V150_1_SIGNAL_ANS_GEN);
1859 break;
1860 case V150_1_SIGNAL_RFC4733_ANSAM_PR:
1861 send_spe_signal(s, V150_1_SIGNAL_ANSAM_GEN);
1862 break;
1863 case V150_1_SIGNAL_ANS:
1864 if (s->rfc4733_preferred)
1865 {
1866 generic_macro(s, V150_1_SIGNAL_RFC4733_ANS_GEN, 0);
1867 }
1868 else
1869 {
1870 /* Pass the audio through */
1871 }
1872 /*endif*/
1873 break;
1874 case V150_1_SIGNAL_ANSAM:
1875 if (s->rfc4733_preferred)
1876 {
1877 generic_macro(s, V150_1_SIGNAL_RFC4733_ANSAM_GEN, 0);
1878 }
1879 else
1880 {
1881 /* Pass the audio through */
1882 }
1883 /*endif*/
1884 break;
1885 case V150_1_SIGNAL_ANS_PR:
1886 if (s->rfc4733_preferred)
1887 {
1888 generic_macro(s, V150_1_SIGNAL_RFC4733_ANS_PR_GEN, 0);
1889 }
1890 else
1891 {
1892 /* Pass the audio through */
1893 }
1894 /*endif*/
1895 break;
1896 case V150_1_SIGNAL_ANSAM_PR:
1897 if (s->rfc4733_preferred)
1898 {
1899 generic_macro(s, V150_1_SIGNAL_RFC4733_ANSAM_PR_GEN, 0);
1900 }
1901 else
1902 {
1903 /* Pass the audio through */
1904 }
1905 /*endif*/
1906 break;
1907 default:
1908 span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected signal %s\n", v150_1_signal_to_str(signal));
1909 break;
1910 }
1911 /*endswitch*/
1912 return 0;
1913}
1914/*- End of function --------------------------------------------------------*/
1915
1916SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_state_machine(v150_1_state_t *s, int signal, const uint8_t *msg, int len)
1917{
1918 span_log(&s->logging,
1919 SPAN_LOG_FLOW,
1920 "State machine - %s %s %s\n",
1921 v150_1_media_state_to_str(s->local_media_state),
1922 v150_1_media_state_to_str(s->remote_media_state),
1923 v150_1_signal_to_str(signal));
1924 /* Figure 40/V.150.1, leading out to the other SDL figures */
1925 switch (signal)
1926 {
1927 case V150_1_SIGNAL_SILENCE:
1928 if (s->local_media_state != V150_1_MEDIA_STATE_INITIAL_AUDIO
1929 ||
1930 s->remote_media_state != V150_1_MEDIA_STATE_INITIAL_AUDIO)
1931 {
1932 s->remote_media_state = V150_1_MEDIA_STATE_INDETERMINATE;
1933 s->local_media_state = V150_1_MEDIA_STATE_INITIAL_AUDIO;
1934 status_report(s, V150_1_STATUS_REASON_MEDIA_STATE_CHANGED);
1935 generic_macro(s, signal, 0);
1936 }
1937 /*endif*/
1938 break;
1939 case V150_1_SIGNAL_ABORT:
1940 s->remote_media_state = V150_1_MEDIA_STATE_INDETERMINATE;
1941 s->local_media_state = V150_1_MEDIA_STATE_INITIAL_AUDIO;
1942 status_report(s, V150_1_STATUS_REASON_MEDIA_STATE_CHANGED);
1943 generic_macro(s, signal, 0);
1944 break;
1945 case V150_1_SIGNAL_CALL_DISCRIMINATION_TIMER_EXPIRED:
1946 /* Time to give up with negotiation, and go with the flow */
1947 s->remote_media_state = V150_1_MEDIA_STATE_INDETERMINATE;
1948 s->local_media_state = V150_1_MEDIA_STATE_INITIAL_AUDIO;
1949 status_report(s, V150_1_STATUS_REASON_MEDIA_STATE_CHANGED);
1950 break;
1951 default:
1952 switch (s->local_media_state)
1953 {
1954 case V150_1_MEDIA_STATE_INDETERMINATE:
1955 switch (s->remote_media_state)
1956 {
1957 case V150_1_MEDIA_STATE_INDETERMINATE:
1958 break;
1959 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
1960 break;
1961 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
1962 break;
1963 case V150_1_MEDIA_STATE_FAX_RELAY:
1964 break;
1965 case V150_1_MEDIA_STATE_MODEM_RELAY:
1966 break;
1967 case V150_1_MEDIA_STATE_TEXT_RELAY:
1968 break;
1969 }
1970 /*endswitch*/
1971 break;
1972 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
1973 switch (s->remote_media_state)
1974 {
1975 case V150_1_MEDIA_STATE_INDETERMINATE:
1976 break;
1977 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
1978 v150_1_figures_26_to_31(s, signal, msg, len);
1979 break;
1980 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
1981 v150_1_figure_33(s, signal, msg, len);
1982 break;
1983 case V150_1_MEDIA_STATE_FAX_RELAY:
1984 break;
1985 case V150_1_MEDIA_STATE_MODEM_RELAY:
1986 v150_1_figure_32(s, signal, msg, len);
1987 break;
1988 case V150_1_MEDIA_STATE_TEXT_RELAY:
1989 break;
1990 }
1991 /*endswitch*/
1992 break;
1993 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
1994 switch (s->remote_media_state)
1995 {
1996 case V150_1_MEDIA_STATE_INDETERMINATE:
1997 break;
1998 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
1999 v150_1_figure_37(s, signal, msg, len);
2000 break;
2001 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
2002 v150_1_figure_39(s, signal, msg, len);
2003 break;
2004 case V150_1_MEDIA_STATE_FAX_RELAY:
2005 break;
2006 case V150_1_MEDIA_STATE_MODEM_RELAY:
2007 v150_1_figure_38(s, signal, msg, len);
2008 break;
2009 case V150_1_MEDIA_STATE_TEXT_RELAY:
2010 break;
2011 }
2012 /*endswitch*/
2013 break;
2014 case V150_1_MEDIA_STATE_FAX_RELAY:
2015 switch (s->remote_media_state)
2016 {
2017 case V150_1_MEDIA_STATE_INDETERMINATE:
2018 break;
2019 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
2020 break;
2021 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
2022 break;
2023 case V150_1_MEDIA_STATE_FAX_RELAY:
2024 break;
2025 case V150_1_MEDIA_STATE_MODEM_RELAY:
2026 break;
2027 case V150_1_MEDIA_STATE_TEXT_RELAY:
2028 break;
2029 }
2030 /*endswitch*/
2031 break;
2032 case V150_1_MEDIA_STATE_MODEM_RELAY:
2033 switch (s->remote_media_state)
2034 {
2035 case V150_1_MEDIA_STATE_INDETERMINATE:
2036 break;
2037 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
2038 v150_1_figure_34(s, signal, msg, len);
2039 break;
2040 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
2041 v150_1_figure_36(s, signal, msg, len);
2042 break;
2043 case V150_1_MEDIA_STATE_FAX_RELAY:
2044 break;
2045 case V150_1_MEDIA_STATE_MODEM_RELAY:
2046 v150_1_figure_35(s, signal, msg, len);
2047 break;
2048 case V150_1_MEDIA_STATE_TEXT_RELAY:
2049 break;
2050 }
2051 /*endswitch*/
2052 break;
2053 case V150_1_MEDIA_STATE_TEXT_RELAY:
2054 switch (s->remote_media_state)
2055 {
2056 case V150_1_MEDIA_STATE_INDETERMINATE:
2057 break;
2058 case V150_1_MEDIA_STATE_INITIAL_AUDIO:
2059 break;
2060 case V150_1_MEDIA_STATE_VOICE_BAND_DATA:
2061 break;
2062 case V150_1_MEDIA_STATE_FAX_RELAY:
2063 break;
2064 case V150_1_MEDIA_STATE_MODEM_RELAY:
2065 break;
2066 case V150_1_MEDIA_STATE_TEXT_RELAY:
2067 break;
2068 }
2069 /*endswitch*/
2070 break;
2071 }
2072 /*endswitch*/
2073 }
2074 /*endswitch*/
2075 return 0;
2076}
2077/*- End of function --------------------------------------------------------*/
2078
2079SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_bits_per_character(v150_1_state_t *s, int bits)
2080{
2081 if (bits < 5 || bits > 8)
2082 return -1;
2083 /*endif*/
2084 bits -= 5;
2085 s->near.parms.data_format_code &= 0x9F;
2086 s->near.parms.data_format_code |= ((bits << 5) & 0x60);
2087 return 0;
2088}
2089/*- End of function --------------------------------------------------------*/
2090
2091SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_parity(v150_1_state_t *s, int mode)
2092{
2093 s->near.parms.data_format_code &= 0xE3;
2094 s->near.parms.data_format_code |= ((mode << 2) & 0x1C);
2095 return 0;
2096}
2097/*- End of function --------------------------------------------------------*/
2098
2099SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_stop_bits(v150_1_state_t *s, int bits)
2100{
2101 if (bits < 1 || bits > 2)
2102 return -1;
2103 /*endif*/
2104 bits -= 1;
2105 s->near.parms.data_format_code &= 0xFC;
2106 s->near.parms.data_format_code |= (bits & 0x03);
2107 return 0;
2108}
2109/*- End of function --------------------------------------------------------*/
2110
2111static int select_info_msg_type(v150_1_state_t *s)
2112{
2113 int i;
2114
2115 /* Select the first available information message type we find in the preferences list */
2116 for (i = 0; i < 10 && s->near.info_msg_preferences[i] >= 0; i++)
2117 {
2118 switch (s->near.info_msg_preferences[i])
2119 {
2120 case V150_1_MSGID_I_RAW_OCTET:
2121 /* This is always supported */
2122 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2123 return 0;
2124 case V150_1_MSGID_I_RAW_BIT:
2125 if (s->near.parms.i_raw_bit_available)
2126 {
2127 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2128 return 0;
2129 }
2130 /*endif*/
2131 break;
2132 case V150_1_MSGID_I_OCTET:
2133 /* This is always supported */
2134 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2135 return 0;
2136 case V150_1_MSGID_I_CHAR_STAT:
2137 if (s->near.parms.i_char_stat_available)
2138 {
2139 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2140 return 0;
2141 }
2142 /*endif*/
2143 break;
2144 case V150_1_MSGID_I_CHAR_DYN:
2145 if (s->near.parms.i_char_dyn_available)
2146 {
2147 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2148 return 0;
2149 }
2150 /*endif*/
2151 break;
2152 case V150_1_MSGID_I_FRAME:
2153 if (s->near.parms.i_frame_available)
2154 {
2155 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2156 return 0;
2157 }
2158 /*endif*/
2159 break;
2160 case V150_1_MSGID_I_OCTET_CS:
2161 if (s->near.parms.i_octet_cs_available)
2162 {
2163 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2164 return 0;
2165 }
2166 /*endif*/
2167 break;
2168 case V150_1_MSGID_I_CHAR_STAT_CS:
2169 if (s->near.parms.i_char_stat_cs_available)
2170 {
2171 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2172 return 0;
2173 }
2174 /*endif*/
2175 break;
2176 case V150_1_MSGID_I_CHAR_DYN_CS:
2177 if (s->near.parms.i_char_dyn_cs_available)
2178 {
2179 s->near.info_stream_msg_id = s->near.info_msg_preferences[i];
2180 return 0;
2181 }
2182 /*endif*/
2183 break;
2184 default:
2185 s->near.info_stream_msg_id = -1;
2186 return -1;
2187 }
2188 /*endswitch*/
2189 }
2190 /*endfor*/
2191 s->near.info_stream_msg_id = -1;
2192 return -1;
2193}
2194/*- End of function --------------------------------------------------------*/
2195
2196static void log_init(v150_1_state_t *s, v150_1_near_far_t *parms)
2197{
2198 span_log(&s->logging, SPAN_LOG_FLOW, " Preferred non-error controlled Rx channel: %s\n", (parms->necrxch_option) ? "RSC" : "USC");
2199 span_log(&s->logging, SPAN_LOG_FLOW, " Preferred error controlled Rx channel: %s\n", (parms->ecrxch_option) ? "USC" : "RSC");
2200 span_log(&s->logging, SPAN_LOG_FLOW, " XID profile exchange %ssupported\n", (parms->xid_profile_exchange_supported) ? "" : "not ");
2201 span_log(&s->logging, SPAN_LOG_FLOW, " Asymmetric data types %ssupported\n", (parms->asymmetric_data_types_supported) ? "" : "not ");
2202 span_log(&s->logging, SPAN_LOG_FLOW, " I_RAW-CHAR supported\n");
2203 span_log(&s->logging, SPAN_LOG_FLOW, " I_RAW-BIT %ssupported\n", (parms->i_raw_bit_supported) ? "" : "not ");
2204 span_log(&s->logging, SPAN_LOG_FLOW, " I_FRAME %ssupported\n", (parms->i_frame_supported) ? "" : "not ");
2205 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET %s supported\n", (parms->dlci_supported) ? "(DLCI) " : "(no DLCI)");
2206 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-STAT %ssupported\n", (parms->i_char_stat_supported) ? "" : "not ");
2207 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-DYN %ssupported\n", (parms->i_char_dyn_supported) ? "" : "not ");
2208 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET-CS %ssupported\n", (parms->i_octet_cs_supported) ? "" : "not ");
2209 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-STAT-CS %ssupported\n", (parms->i_char_stat_cs_supported) ? "" : "not ");
2210 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-DYN-CS %ssupported\n", (parms->i_char_dyn_cs_supported) ? "" : "not ");
2211}
2212/*- End of function --------------------------------------------------------*/
2213
2214SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_null(v150_1_state_t *s)
2215{
2216 int res;
2217 uint8_t pkt[256];
2218
2219 res = -1;
2220 /* This isn't a real message. Its marked as reserved by the ITU-T in V.150.1 */
2221 pkt[0] = V150_1_MSGID_NULL;
2222 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 1);
2223 span_log(&s->logging, SPAN_LOG_FLOW, "NULL sent\n");
2224 return res;
2225}
2226/*- End of function --------------------------------------------------------*/
2227
2228SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_init(v150_1_state_t *s)
2229{
2230 int res;
2231 uint8_t i;
2232 uint8_t pkt[256];
2233
2234 res = -1;
2235 pkt[0] = V150_1_MSGID_INIT;
2236 /* At this stage we just tell the far end the things we support. */
2237 i = 0;
2238 if (s->near.parms.necrxch_option)
2239 i |= 0x80;
2240 /*endif*/
2241 if (s->near.parms.ecrxch_option)
2242 i |= 0x40;
2243 /*endif*/
2244 if (s->near.parms.xid_profile_exchange_supported)
2245 i |= 0x20;
2246 /*endif*/
2247 if (s->near.parms.asymmetric_data_types_supported)
2248 i |= 0x10;
2249 /*endif*/
2250 if (s->near.parms.i_raw_bit_supported)
2251 i |= 0x08;
2252 /*endif*/
2253 if (s->near.parms.i_frame_supported)
2254 i |= 0x04;
2255 /*endif*/
2256 if (s->near.parms.i_char_stat_supported)
2257 i |= 0x02;
2258 /*endif*/
2259 if (s->near.parms.i_char_dyn_supported)
2260 i |= 0x01;
2261 /*endif*/
2262 pkt[1] = i;
2263 i = 0;
2264 if (s->near.parms.i_octet_cs_supported)
2265 i |= 0x80;
2266 /*endif*/
2267 if (s->near.parms.i_char_stat_cs_supported)
2268 i |= 0x40;
2269 /*endif*/
2270 if (s->near.parms.i_char_dyn_cs_supported)
2271 i |= 0x20;
2272 /*endif*/
2273 pkt[2] = i;
2274 span_log(&s->logging, SPAN_LOG_FLOW, "Sending INIT\n");
2275 log_init(s, &s->near.parms);
2276 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 3);
2277 if (res >= 0)
2278 {
2279 s->near.parms.connection_state = V150_1_STATE_INITED;
2280 if (s->far.parms.connection_state >= V150_1_STATE_INITED)
2281 {
2282 select_info_msg_type(s);
2283 s->joint_connection_state = V150_1_STATE_INITED;
2284 }
2285 /*endif*/
2286 }
2287 /*endif*/
2288 return res;
2289}
2290/*- End of function --------------------------------------------------------*/
2291
2292SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_xid_xchg(v150_1_state_t *s)
2293{
2294 int res;
2295 uint8_t i;
2296 uint8_t pkt[256];
2297
2298 res = -1;
2299 if (!s->far.parms.xid_profile_exchange_supported)
2300 return -1;
2301 /*endif*/
2302 pkt[0] = V150_1_MSGID_XID_XCHG;
2303 pkt[1] = s->near.parms.ecp;
2304 i = 0;
2305 if (s->near.parms.v42bis_supported)
2306 i |= 0x80;
2307 /*endif*/
2308 if (s->near.parms.v44_supported)
2309 i |= 0x40;
2310 /*endif*/
2311 if (s->near.parms.mnp5_supported)
2312 i |= 0x20;
2313 /*endif*/
2314 pkt[2] = i;
2315 if (s->near.parms.v42bis_supported)
2316 {
2317 pkt[3] = s->near.parms.v42bis_p0;
2318 put_net_unaligned_uint16(&pkt[4], s->near.parms.v42bis_p1);
2319 pkt[6] = s->near.parms.v42bis_p2;
2320 }
2321 else
2322 {
2323 memset(&pkt[3], 0, 4);
2324 }
2325 /*endif*/
2326 if (s->near.parms.v44_supported)
2327 {
2328 pkt[7] = s->near.parms.v44_c0;
2329 pkt[8] = s->near.parms.v44_p0;
2330 put_net_unaligned_uint16(&pkt[9], s->near.parms.v44_p1t);
2331 put_net_unaligned_uint16(&pkt[11], s->near.parms.v44_p1r);
2332 pkt[13] = s->near.parms.v44_p2t;
2333 pkt[14] = s->near.parms.v44_p2r;
2334 put_net_unaligned_uint16(&pkt[15], s->near.parms.v44_p3t);
2335 put_net_unaligned_uint16(&pkt[17], s->near.parms.v44_p3r);
2336 }
2337 else
2338 {
2339 memset(&pkt[7], 0, 12);
2340 }
2341 /*endif*/
2342 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 19);
2343 span_log(&s->logging, SPAN_LOG_FLOW, "XID xchg sent\n");
2344 return res;
2345}
2346/*- End of function --------------------------------------------------------*/
2347
2348SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_jm_info(v150_1_state_t *s)
2349{
2350 int res;
2351 int i;
2352 int len;
2353 int bit;
2354 uint8_t pkt[256];
2355
2356 for (i = 0; i < 16; i++)
2357 {
2358 if (s->near.parms.jm_category_id_seen[i])
2359 {
2360 span_log(&s->logging,
2361 SPAN_LOG_FLOW,
2362 " JM %s 0x%x\n",
2363 v150_1_jm_category_to_str(i),
2364 s->near.parms.jm_category_info[i]);
2365 }
2366 /*endif*/
2367 }
2368 /*endfor*/
2369 if (s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_MODULATION_MODES])
2370 {
2371 for (i = 0; i < 16; i++)
2372 {
2373 bit = s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_MODULATION_MODES] & (0x8000 >> i);
2374 if (bit)
2375 {
2376 span_log(&s->logging, SPAN_LOG_FLOW, " JM %s\n", v150_1_jm_info_modulation_to_str(bit));
2377 }
2378 /*endif*/
2379 }
2380 /*endfor*/
2381 }
2382 /*endif*/
2383 res = -1;
2384 pkt[0] = V150_1_MSGID_JM_INFO;
2385 len = 1;
2386 for (i = 0; i < 16; i++)
2387 {
2388 if (s->near.parms.jm_category_id_seen[i])
2389 {
2390 put_net_unaligned_uint16(&pkt[len], (i << 12) | (s->near.parms.jm_category_info[i] & 0x0FFF));
2391 len += 2;
2392 }
2393 /*endif*/
2394 }
2395 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, len);
2396 span_log(&s->logging, SPAN_LOG_FLOW, "JM info sent\n");
2397 return res;
2398}
2399/*- End of function --------------------------------------------------------*/
2400
2401SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_start_jm(v150_1_state_t *s)
2402{
2403 int res;
2404 uint8_t pkt[256];
2405
2406 res = -1;
2407 if (s->near.parms.connection_state != V150_1_STATE_IDLE)
2408 {
2409 pkt[0] = V150_1_MSGID_START_JM;
2410 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 1);
2411 span_log(&s->logging, SPAN_LOG_FLOW, "Start JM sent\n");
2412 }
2413 /*endif*/
2414 return res;
2415}
2416/*- End of function --------------------------------------------------------*/
2417
2418SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_connect(v150_1_state_t *s)
2419{
2420 int res;
2421 int available_data_types;
2422 int len;
2423 uint8_t pkt[256];
2424
2425 res = -1;
Value stored to 'res' is never read
2426 pkt[0] = V150_1_MSGID_CONNECT;
2427 pkt[1] = (s->near.parms.selmod << 2) | s->near.parms.selected_compression_direction;
2428 pkt[2] = (s->near.parms.selected_compression << 4) | s->near.parms.selected_error_correction;
2429 put_net_unaligned_uint16(&pkt[3], s->near.parms.tdsr);
2430 put_net_unaligned_uint16(&pkt[5], s->near.parms.rdsr);
2431
2432 available_data_types = 0;
2433 if (s->near.parms.i_octet_with_dlci_available)
2434 available_data_types |= 0x8000;
2435 /*endif*/
2436 if (s->near.parms.i_octet_without_dlci_available)
2437 available_data_types |= 0x4000;
2438 /*endif*/
2439 if (s->near.parms.i_raw_bit_available)
2440 available_data_types |= 0x2000;
2441 /*endif*/
2442 if (s->near.parms.i_frame_available)
2443 available_data_types |= 0x1000;
2444 /*endif*/
2445 if (s->near.parms.i_char_stat_available)
2446 available_data_types |= 0x0800;
2447 /*endif*/
2448 if (s->near.parms.i_char_dyn_available)
2449 available_data_types |= 0x0400;
2450 /*endif*/
2451 if (s->near.parms.i_octet_cs_available)
2452 available_data_types |= 0x0200;
2453 /*endif*/
2454 if (s->near.parms.i_char_stat_cs_available)
2455 available_data_types |= 0x0100;
2456 /*endif*/
2457 if (s->near.parms.i_char_dyn_cs_available)
2458 available_data_types |= 0x0080;
2459 /*endif*/
2460 put_net_unaligned_uint16(&pkt[7], available_data_types);
2461 len = 9;
2462 if (s->near.parms.selected_compression == V150_1_COMPRESSION_V42BIS || s->near.parms.selected_compression == V150_1_COMPRESSION_V44)
2463 {
2464 /* This is only included if V.42bis or V.44 is selected. For no compression, or MNP5 this is omitted */
2465 put_net_unaligned_uint16(&pkt[9], s->near.parms.compression_tx_dictionary_size);
2466 put_net_unaligned_uint16(&pkt[11], s->near.parms.compression_rx_dictionary_size);
2467 pkt[13] = s->near.parms.compression_tx_string_length;
2468 pkt[14] = s->near.parms.compression_rx_string_length;
2469 len += 6;
2470 }
2471 /*endif*/
2472 if (s->near.parms.selected_compression == V150_1_COMPRESSION_V44)
2473 {
2474 /* This is only included if V.44 is selected. For no compression, MNP5, or V.42bis this is omitted */
2475 put_net_unaligned_uint16(&pkt[15], s->near.parms.compression_tx_history_size);
2476 put_net_unaligned_uint16(&pkt[15], s->near.parms.compression_rx_history_size);
2477 len += 4;
2478 }
2479 /*endif*/
2480 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, len);
2481 if (res >= 0)
2482 {
2483 s->near.parms.connection_state = V150_1_STATE_CONNECTED;
2484 if (s->near.parms.connection_state >= V150_1_STATE_CONNECTED)
2485 s->joint_connection_state = V150_1_STATE_CONNECTED;
2486 /*endif*/
2487 span_log(&s->logging, SPAN_LOG_FLOW, "Connect sent\n");
2488 }
2489 /*endif*/
2490 return res;
2491}
2492/*- End of function --------------------------------------------------------*/
2493
2494SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_break(v150_1_state_t *s, int source, int type, int duration)
2495{
2496 int res;
2497 uint8_t pkt[256];
2498
2499 res = -1;
2500 if (s->near.parms.connection_state != V150_1_STATE_IDLE)
2501 {
2502 pkt[0] = V150_1_MSGID_BREAK;
2503 pkt[1] = (source << 4) | type;
2504 pkt[2] = duration/10;
2505 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 3);
2506 if (res >= 0)
2507 {
2508 span_log(&s->logging, SPAN_LOG_FLOW, "Break sent\n");
2509 }
2510 /*endif*/
2511 }
2512 /*endif*/
2513 return res;
2514}
2515/*- End of function --------------------------------------------------------*/
2516
2517SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_break_ack(v150_1_state_t *s)
2518{
2519 int res;
2520 uint8_t pkt[256];
2521
2522 res = -1;
2523 if (s->near.parms.connection_state != V150_1_STATE_IDLE)
2524 {
2525 pkt[0] = V150_1_MSGID_BREAKACK;
2526 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 1);
2527 if (res >= 0)
2528 {
2529 span_log(&s->logging, SPAN_LOG_FLOW, "Break ACK sent\n");
2530 }
2531 /*endif*/
2532 }
2533 /*endif*/
2534 return res;
2535}
2536/*- End of function --------------------------------------------------------*/
2537
2538SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_mr_event(v150_1_state_t *s, int event_id)
2539{
2540 int res;
2541 int len;
2542 uint8_t i;
2543 uint8_t pkt[256];
2544
2545 res = -1;
2546 pkt[0] = V150_1_MSGID_MR_EVENT;
2547 pkt[1] = event_id;
2548 switch (event_id)
2549 {
2550 case V150_1_MR_EVENT_ID_RETRAIN:
2551 pkt[2] = V150_1_MR_EVENT_REASON_NULL;
2552 len = 3;
2553 s->near.parms.connection_state = V150_1_STATE_RETRAIN;
2554 s->joint_connection_state = V150_1_STATE_RETRAIN;
2555 break;
2556 case V150_1_MR_EVENT_ID_RATE_RENEGOTIATION:
2557 pkt[2] = V150_1_MR_EVENT_REASON_NULL;
2558 len = 3;
2559 s->near.parms.connection_state = V150_1_STATE_RATE_RENEGOTIATION;
2560 s->joint_connection_state = V150_1_STATE_RATE_RENEGOTIATION;
2561 break;
2562 case V150_1_MR_EVENT_ID_PHYSUP:
2563 pkt[2] = 0;
2564 i = (s->near.parms.selmod << 2);
2565 if (s->near.parms.txsen)
2566 i |= 0x02;
2567 /*endif*/
2568 if (s->near.parms.rxsen)
2569 i |= 0x01;
2570 /*endif*/
2571 pkt[3] = i;
2572 put_net_unaligned_uint16(&pkt[4], s->near.parms.tdsr);
2573 put_net_unaligned_uint16(&pkt[4], s->near.parms.rdsr);
2574 pkt[8] = (s->near.parms.txsen) ? s->near.parms.txsr : V150_1_SYMBOL_RATE_NULL;
2575 pkt[9] = (s->near.parms.rxsen) ? s->near.parms.rxsr : V150_1_SYMBOL_RATE_NULL;
2576 len = 10;
2577 s->near.parms.connection_state = V150_1_STATE_PHYSUP;
2578 if (s->far.parms.connection_state >= V150_1_STATE_PHYSUP)
2579 s->joint_connection_state = V150_1_STATE_PHYSUP;
2580 /*endif*/
2581 break;
2582 case V150_1_MR_EVENT_ID_NULL:
2583 default:
2584 pkt[2] = 0;
2585 len = 3;
2586 break;
2587 }
2588 /*endswitch*/
2589 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, len);
2590 if (res >= 0)
2591 {
2592 span_log(&s->logging, SPAN_LOG_FLOW, "MR-event %s (%d) sent\n", v150_1_mr_event_type_to_str(event_id), event_id);
2593 }
2594 /*endif*/
2595 return res;
2596}
2597/*- End of function --------------------------------------------------------*/
2598
2599SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_cleardown(v150_1_state_t *s, int reason)
2600{
2601 int res;
2602 uint8_t pkt[256];
2603
2604 res = -1;
2605
2606 if (s->near.parms.connection_state != V150_1_STATE_IDLE)
2607 {
2608 pkt[0] = V150_1_MSGID_CLEARDOWN;
2609 pkt[1] = reason;
2610 pkt[2] = 0; /* Vendor tag */
2611 pkt[3] = 0; /* Vendor info */
2612 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 4);
2613 if (res >= 0)
2614 {
2615 s->near.parms.connection_state = V150_1_STATE_IDLE;
2616 span_log(&s->logging, SPAN_LOG_FLOW, "Cleardown sent\n");
2617 }
2618 /*endif*/
2619 }
2620 /*endif*/
2621 return res;
2622}
2623/*- End of function --------------------------------------------------------*/
2624
2625SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_prof_xchg(v150_1_state_t *s)
2626{
2627 int res;
2628 uint8_t i;
2629 uint8_t pkt[256];
2630
2631 res = -1;
2632 pkt[0] = V150_1_MSGID_PROF_XCHG;
2633 i = 0;
2634 if (s->near.parms.v42_lapm_supported)
2635 i |= 0x40;
2636 /*endif*/
2637 if (s->near.parms.v42_annex_a_supported)
2638 i |= 0x10;
2639 /*endif*/
2640 if (s->near.parms.v44_supported)
2641 i |= 0x04;
2642 /*endif*/
2643 if (s->near.parms.v42bis_supported)
2644 i |= 0x01;
2645 /*endif*/
2646 pkt[1] = i;
2647 i = 0;
2648 if (s->near.parms.mnp5_supported)
2649 i |= 0x40;
2650 /*endif*/
2651 pkt[2] = i;
2652 if (s->near.parms.v42bis_supported)
2653 {
2654 pkt[3] = s->near.parms.v42bis_p0;
2655 put_net_unaligned_uint16(&pkt[4], s->near.parms.v42bis_p1);
2656 pkt[6] = s->near.parms.v42bis_p2;
2657 }
2658 else
2659 {
2660 memset(&pkt[3], 0, 4);
2661 }
2662 /*endif*/
2663 if (s->near.parms.v44_supported)
2664 {
2665 pkt[7] = s->near.parms.v44_c0;
2666 pkt[8] = s->near.parms.v44_p0;
2667 put_net_unaligned_uint16(&pkt[9], s->near.parms.v44_p1t);
2668 put_net_unaligned_uint16(&pkt[11], s->near.parms.v44_p1r);
2669 pkt[13] = s->near.parms.v44_p2t;
2670 pkt[14] = s->near.parms.v44_p2r;
2671 put_net_unaligned_uint16(&pkt[15], s->near.parms.v44_p3t);
2672 put_net_unaligned_uint16(&pkt[17], s->near.parms.v44_p3r);
2673 }
2674 else
2675 {
2676 memset(&pkt[7], 0, 12);
2677 }
2678 /*endif*/
2679 res = sprt_tx(&s->sprt, SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED, pkt, 19);
2680 span_log(&s->logging, SPAN_LOG_FLOW, "Prof xchg sent\n");
2681 return res;
2682}
2683/*- End of function --------------------------------------------------------*/
2684
2685static int v150_1_build_i_raw_octet(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2686{
2687 if (len > max_len - 3)
2688 return -1;
2689 /*endif*/
2690 pkt[0] = V150_1_MSGID_I_RAW_OCTET;
2691 pkt[1] = 0x80 | 0x02; /* L */
2692 pkt[2] = 0x02; /* N */
2693 memcpy(&pkt[3], buf, len);
2694 len += 3;
2695 return len;
2696}
2697/*- End of function --------------------------------------------------------*/
2698
2699static int v150_1_build_i_raw_bit(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2700{
2701 if (!s->far.parms.i_raw_bit_available)
2702 return -1;
2703 /*endif*/
2704 if (len > max_len - 3)
2705 return -1;
2706 /*endif*/
2707 pkt[0] = V150_1_MSGID_I_RAW_BIT;
2708 pkt[1] = 0x80 | 0x02; /* L */
2709 pkt[2] = 0x02; /* N */
2710 memcpy(&pkt[3], buf, len);
2711 len += 3;
2712 return len;
2713}
2714/*- End of function --------------------------------------------------------*/
2715
2716static int v150_1_build_i_octet(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2717{
2718 int header;
2719
2720 if (!s->far.parms.i_octet_without_dlci_available && !s->far.parms.i_octet_with_dlci_available)
2721 return -1;
2722 /*endif*/
2723 if (len > max_len - 3)
2724 return -1;
2725 /*endif*/
2726 pkt[0] = V150_1_MSGID_I_OCTET;
2727 if (s->far.parms.i_octet_with_dlci_available)
2728 {
2729 /* The DLCI may be one or two octets long. */
2730 if ((s->near.parms.dlci & 0x01) == 0)
2731 {
2732 pkt[1] = s->near.parms.dlci & 0xFF;
2733 header = 2;
2734 }
2735 else
2736 {
2737 put_net_unaligned_uint16(&pkt[1], s->near.parms.dlci);
2738 header = 3;
2739 }
2740 /*endif*/
2741 }
2742 else
2743 {
2744 header = 1;
2745 }
2746 /*endif*/
2747 memcpy(&pkt[header], buf, len);
2748 len += header;
2749 return len;
2750}
2751/*- End of function --------------------------------------------------------*/
2752
2753static int v150_1_build_i_char_stat(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2754{
2755 if (!s->far.parms.i_char_stat_available)
2756 return -1;
2757 /*endif*/
2758 if (len > max_len - 2)
2759 return -1;
2760 /*endif*/
2761 pkt[0] = V150_1_MSGID_I_CHAR_STAT;
2762 pkt[1] = s->near.parms.data_format_code;
2763 memcpy(&pkt[2], buf, len);
2764 len += 2;
2765 return len;
2766}
2767/*- End of function --------------------------------------------------------*/
2768
2769static int v150_1_build_i_char_dyn(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2770{
2771 if (!s->far.parms.i_char_dyn_available)
2772 return -1;
2773 /*endif*/
2774 if (len > max_len - 2)
2775 return -1;
2776 /*endif*/
2777 pkt[0] = V150_1_MSGID_I_CHAR_DYN;
2778 pkt[1] = s->near.parms.data_format_code;
2779 memcpy(&pkt[2], buf, len);
2780 len += 2;
2781 return len;
2782}
2783/*- End of function --------------------------------------------------------*/
2784
2785static int v150_1_build_i_frame(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2786{
2787 int data_frame_state;
2788
2789 data_frame_state = 0;
2790
2791 if (!s->far.parms.i_frame_available)
2792 return -1;
2793 /*endif*/
2794 if (len > max_len - 2)
2795 return -1;
2796 /*endif*/
2797 pkt[0] = V150_1_MSGID_I_FRAME;
2798 pkt[1] = data_frame_state & 0x03;
2799 memcpy(&pkt[2], buf, len);
2800 len += 2;
2801 return len;
2802}
2803/*- End of function --------------------------------------------------------*/
2804
2805static int v150_1_build_i_octet_cs(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2806{
2807 if (!s->far.parms.i_octet_cs_available)
2808 return -1;
2809 /*endif*/
2810 if (len > max_len - 3)
2811 return -1;
2812 /*endif*/
2813 pkt[0] = V150_1_MSGID_I_OCTET_CS;
2814 put_net_unaligned_uint16(&pkt[1], s->near.parms.octet_cs_next_seq_no & 0xFFFF);
2815 memcpy(&pkt[3], buf, len);
2816 s->near.parms.octet_cs_next_seq_no += len;
2817 len += 3;
2818 return len;
2819}
2820/*- End of function --------------------------------------------------------*/
2821
2822static int v150_1_build_i_char_stat_cs(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2823{
2824 if (!s->far.parms.i_char_stat_cs_available)
2825 return -1;
2826 /*endif*/
2827 if (len > max_len - 4)
2828 return -1;
2829 /*endif*/
2830 pkt[0] = V150_1_MSGID_I_CHAR_STAT_CS;
2831 pkt[1] = s->near.parms.data_format_code;
2832 put_net_unaligned_uint16(&pkt[2], s->near.parms.octet_cs_next_seq_no & 0xFFFF);
2833 memcpy(&pkt[4], buf, len);
2834 len += 4;
2835 s->near.parms.octet_cs_next_seq_no += len;
2836 return len;
2837}
2838/*- End of function --------------------------------------------------------*/
2839
2840static int v150_1_build_i_char_dyn_cs(v150_1_state_t *s, uint8_t pkt[], int max_len, const uint8_t buf[], int len)
2841{
2842 if (!s->far.parms.i_char_dyn_cs_available)
2843 return -1;
2844 /*endif*/
2845 if (len > max_len - 4)
2846 return -1;
2847 /*endif*/
2848 pkt[0] = V150_1_MSGID_I_CHAR_DYN_CS;
2849 pkt[1] = s->near.parms.data_format_code;
2850 put_net_unaligned_uint16(&pkt[2], s->near.parms.octet_cs_next_seq_no & 0xFFFF);
2851 memcpy(&pkt[4], buf, len);
2852 s->near.parms.octet_cs_next_seq_no += len;
2853 len += 4;
2854 return len;
2855}
2856/*- End of function --------------------------------------------------------*/
2857
2858SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_tx_info_stream(v150_1_state_t *s, const uint8_t buf[], int len)
2859{
2860 uint8_t pkt[256];
2861 int max_len;
2862 int res;
2863
2864 max_len = s->near.max_payload_bytes[s->near.info_stream_channel];
2865 switch (s->near.info_stream_msg_id)
2866 {
2867 case V150_1_MSGID_I_RAW_OCTET:
2868 res = v150_1_build_i_raw_octet(s, pkt, max_len, buf, len);
2869 break;
2870 case V150_1_MSGID_I_RAW_BIT:
2871 res = v150_1_build_i_raw_bit(s, pkt, max_len, buf, len);
2872 break;
2873 case V150_1_MSGID_I_OCTET:
2874 res = v150_1_build_i_octet(s, pkt, max_len, buf, len);
2875 break;
2876 case V150_1_MSGID_I_CHAR_STAT:
2877 res = v150_1_build_i_char_stat(s, pkt, max_len, buf, len);
2878 break;
2879 case V150_1_MSGID_I_CHAR_DYN:
2880 res = v150_1_build_i_char_dyn(s, pkt, max_len, buf, len);
2881 break;
2882 case V150_1_MSGID_I_FRAME:
2883 res = v150_1_build_i_frame(s, pkt, max_len, buf, len);
2884 break;
2885 case V150_1_MSGID_I_OCTET_CS:
2886 res = v150_1_build_i_octet_cs(s, pkt, max_len, buf, len);
2887 break;
2888 case V150_1_MSGID_I_CHAR_STAT_CS:
2889 res = v150_1_build_i_char_stat_cs(s, pkt, max_len, buf, len);
2890 break;
2891 case V150_1_MSGID_I_CHAR_DYN_CS:
2892 res = v150_1_build_i_char_dyn_cs(s, pkt, max_len, buf, len);
2893 break;
2894 default:
2895 res = -1;
2896 break;
2897 }
2898 /*endswitch*/
2899 if (res >= 0)
2900 {
2901 res = sprt_tx(&s->sprt, s->near.info_stream_channel, pkt, res);
2902 }
2903 else
2904 {
2905 span_log(&s->logging, SPAN_LOG_FLOW, "Bad message\n");
2906 }
2907 /*endif*/
2908 return res;
2909}
2910/*- End of function --------------------------------------------------------*/
2911
2912static int v150_1_process_null(v150_1_state_t *s, const uint8_t buf[], int len)
2913{
2914 if (len != 1)
2915 return -1;
2916 return 0;
2917}
2918/*- End of function --------------------------------------------------------*/
2919
2920static int v150_1_process_init(v150_1_state_t *s, const uint8_t buf[], int len)
2921{
2922 if (len != 3)
2923 {
2924 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid INIT message length %d\n", len);
2925 return -1;
2926 }
2927 /*endif*/
2928 /* Just capture what the far end says about its capabilities */
2929 s->far.parms.necrxch_option = (buf[1] & 0x80) != 0;
2930 s->far.parms.ecrxch_option = (buf[1] & 0x40) != 0;
2931 s->far.parms.xid_profile_exchange_supported = (buf[1] & 0x20) != 0;
2932 s->far.parms.asymmetric_data_types_supported = (buf[1] & 0x10) != 0;
2933 s->far.parms.i_raw_bit_supported = (buf[1] & 0x08) != 0;
2934 s->far.parms.i_frame_supported = (buf[1] & 0x04) != 0;
2935 s->far.parms.i_char_stat_supported = (buf[1] & 0x02) != 0;
2936 s->far.parms.i_char_dyn_supported = (buf[1] & 0x01) != 0;
2937 s->far.parms.i_octet_cs_supported = (buf[2] & 0x80) != 0;
2938 s->far.parms.i_char_stat_cs_supported = (buf[2] & 0x40) != 0;
2939 s->far.parms.i_char_dyn_cs_supported = (buf[2] & 0x20) != 0;
2940
2941 /* Now sift out what will be available, because both ends support the features */
2942 s->near.parms.i_raw_bit_available = s->near.parms.i_raw_bit_supported && s->far.parms.i_raw_bit_supported;
2943 s->near.parms.i_frame_available = s->near.parms.i_frame_supported && s->far.parms.i_frame_supported;
2944 s->near.parms.i_octet_with_dlci_available = s->near.parms.dlci_supported;
2945 s->near.parms.i_octet_without_dlci_available = !s->near.parms.dlci_supported;
2946 s->near.parms.i_char_stat_available = s->near.parms.i_char_stat_supported && s->far.parms.i_char_stat_supported;
2947 s->near.parms.i_char_dyn_available = s->near.parms.i_char_dyn_supported && s->far.parms.i_char_dyn_supported;
2948 s->near.parms.i_octet_cs_available = s->near.parms.i_octet_cs_supported && s->far.parms.i_octet_cs_supported;
2949 s->near.parms.i_char_stat_cs_available = s->near.parms.i_char_stat_cs_supported && s->far.parms.i_char_stat_cs_supported;
2950 s->near.parms.i_char_dyn_cs_available = s->near.parms.i_char_dyn_cs_supported && s->far.parms.i_char_dyn_cs_supported;
2951
2952 if (s->far.parms.connection_state >= V150_1_STATE_INITED)
2953 select_info_msg_type(s);
2954 /*endif*/
2955 span_log(&s->logging, SPAN_LOG_FLOW, "Received INIT\n");
2956 log_init(s, &s->far.parms);
2957
2958 s->far.parms.connection_state = V150_1_STATE_INITED;
2959 if (s->near.parms.connection_state >= V150_1_STATE_INITED)
2960 s->joint_connection_state = V150_1_STATE_INITED;
2961 /*endif*/
2962 status_report(s, V150_1_STATUS_REASON_CONNECTION_STATE_CHANGED);
2963 return 0;
2964}
2965/*- End of function --------------------------------------------------------*/
2966
2967static int v150_1_process_xid_xchg(v150_1_state_t *s, const uint8_t buf[], int len)
2968{
2969 if (s->joint_connection_state < V150_1_STATE_INITED)
2970 {
2971 span_log(&s->logging, SPAN_LOG_WARNING, "XID_XCHG received before INIT. Ignored.\n");
2972 return -1;
2973 }
2974 /*endif*/
2975 if (len != 19)
2976 {
2977 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid XID_XCHG message length %d\n", len);
2978 return -1;
2979 }
2980 /*endif*/
2981 s->far.parms.ecp = buf[1];
2982
2983 s->far.parms.v42bis_supported = (buf[2] & 0x80) != 0;
2984 s->far.parms.v44_supported = (buf[2] & 0x40) != 0;
2985 s->far.parms.mnp5_supported = (buf[2] & 0x20) != 0;
2986
2987 s->far.parms.v42bis_p0 = buf[3];
2988 s->far.parms.v42bis_p1 = get_net_unaligned_uint16(&buf[4]);
2989 s->far.parms.v42bis_p2 = buf[6];
2990 s->far.parms.v44_c0 = buf[7];
2991 s->far.parms.v44_p0 = buf[8];
2992 s->far.parms.v44_p1t = get_net_unaligned_uint16(&buf[9]);
2993 s->far.parms.v44_p1r = get_net_unaligned_uint16(&buf[11]);
2994 s->far.parms.v44_p2t = buf[13];
2995 s->far.parms.v44_p2r = buf[14];
2996 s->far.parms.v44_p3t = get_net_unaligned_uint16(&buf[15]);
2997 s->far.parms.v44_p3r = get_net_unaligned_uint16(&buf[17]);
2998
2999 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis %ssupported\n", (s->far.parms.v42bis_supported) ? "" : "not ");
3000 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 %ssupported\n", (s->far.parms.v44_supported) ? "" : "not ");
3001 span_log(&s->logging, SPAN_LOG_FLOW, " MNP5 %ssupported\n", (s->far.parms.mnp5_supported) ? "" : "not ");
3002 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P0 %d\n", s->far.parms.v42bis_p0);
3003 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P1 %d\n", s->far.parms.v42bis_p1);
3004 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P2 %d\n", s->far.parms.v42bis_p2);
3005 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 C0 %d\n", s->far.parms.v44_c0);
3006 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1 %d\n", s->far.parms.v44_p0);
3007 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1T %d\n", s->far.parms.v44_p1t);
3008 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1R %d\n", s->far.parms.v44_p1r);
3009 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P2T %d\n", s->far.parms.v44_p2t);
3010 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P2R %d\n", s->far.parms.v44_p2r);
3011 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P3T %d\n", s->far.parms.v44_p3t);
3012 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P3R %d\n", s->far.parms.v44_p3r);
3013
3014 /* TODO: */
3015 return 0;
3016}
3017/*- End of function --------------------------------------------------------*/
3018
3019static int v150_1_process_jm_info(v150_1_state_t *s, const uint8_t buf[], int len)
3020{
3021 int i;
3022 int id;
3023 int bit;
3024
3025 if (s->joint_connection_state < V150_1_STATE_INITED)
3026 {
3027 span_log(&s->logging, SPAN_LOG_WARNING, "JM_INFO received before INIT. Ignored.\n");
3028 return -1;
3029 }
3030 /*endif*/
3031 /* The length must be even */
3032 if ((len & 1) != 1)
3033 {
3034 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid JM_INFO message length %d\n", len);
3035 return -1;
3036 }
3037 /*endif*/
3038 for (i = 1; i < len; i += 2)
3039 {
3040 id = (buf[i] >> 4) & 0x0F;
3041 s->far.parms.jm_category_id_seen[id] = true1;
3042 s->far.parms.jm_category_info[id] = get_net_unaligned_uint16(&buf[i]) & 0x0FFF;
3043 }
3044 /*endfor*/
3045 for (i = 0; i < 16; i++)
3046 {
3047 if (s->far.parms.jm_category_id_seen[i])
3048 {
3049 span_log(&s->logging,
3050 SPAN_LOG_WARNING,
3051 " JM %s 0x%x\n",
3052 v150_1_jm_category_to_str(i),
3053 s->far.parms.jm_category_info[i]);
3054 }
3055 /*endif*/
3056 }
3057 /*endfor*/
3058 if (s->far.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_MODULATION_MODES])
3059 {
3060 for (i = 0; i < 16; i++)
3061 {
3062 bit = s->far.parms.jm_category_info[V150_1_JM_CATEGORY_ID_MODULATION_MODES] & (0x8000 >> i);
3063 if (bit)
3064 {
3065 span_log(&s->logging, SPAN_LOG_FLOW, " JM %s\n", v150_1_jm_info_modulation_to_str(bit));
3066 }
3067 /*endif*/
3068 }
3069 /*endfor*/
3070 }
3071 /*endif*/
3072
3073 /* TODO: */
3074 return 0;
3075}
3076/*- End of function --------------------------------------------------------*/
3077
3078static int v150_1_process_start_jm(v150_1_state_t *s, const uint8_t buf[], int len)
3079{
3080 if (s->joint_connection_state < V150_1_STATE_INITED)
3081 {
3082 span_log(&s->logging, SPAN_LOG_WARNING, "START_JM received before INIT. Ignored.\n");
3083 return -1;
3084 }
3085 /*endif*/
3086 if (len > 1)
3087 {
3088 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid START_JM message length %d\n", len);
3089 return -1;
3090 }
3091 /*endif*/
3092
3093 /* TODO: */
3094 return 0;
3095}
3096/*- End of function --------------------------------------------------------*/
3097
3098static int v150_1_process_connect(v150_1_state_t *s, const uint8_t buf[], int len)
3099{
3100 int available_data_types;
3101
3102 if (s->joint_connection_state < V150_1_STATE_INITED)
3103 {
3104 span_log(&s->logging, SPAN_LOG_WARNING, "CONNECT received before INIT. Ignored.\n");
3105 return -1;
3106 }
3107 /*endif*/
3108 if (len < 9 || len > 19)
3109 {
3110 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid CONNECT message length %d\n", len);
3111 return -1;
3112 }
3113 /*endif*/
3114 s->far.parms.selmod = (buf[1] >> 2) & 0x3F;
3115 s->far.parms.selected_compression_direction = buf[1] & 0x03;
3116 s->far.parms.selected_compression = (buf[2] >> 4) & 0x0F;
3117 s->far.parms.selected_error_correction = buf[2] & 0x0F;
3118 s->far.parms.tdsr = get_net_unaligned_uint16(&buf[3]);
3119 s->far.parms.rdsr = get_net_unaligned_uint16(&buf[5]);
3120
3121 available_data_types = get_net_unaligned_uint16(&buf[7]);
3122 s->far.parms.i_octet_with_dlci_available = (available_data_types & 0x8000) != 0;
3123 s->far.parms.i_octet_without_dlci_available = (available_data_types & 0x4000) != 0;
3124 s->far.parms.i_raw_bit_available = (available_data_types & 0x2000) != 0;
3125 s->far.parms.i_frame_available = (available_data_types & 0x1000) != 0;
3126 s->far.parms.i_char_stat_available = (available_data_types & 0x0800) != 0;
3127 s->far.parms.i_char_dyn_available = (available_data_types & 0x0400) != 0;
3128 s->far.parms.i_octet_cs_available = (available_data_types & 0x0200) != 0;
3129 s->far.parms.i_char_stat_cs_available = (available_data_types & 0x0100) != 0;
3130 s->far.parms.i_char_dyn_cs_available = (available_data_types & 0x0080) != 0;
3131
3132 span_log(&s->logging, SPAN_LOG_FLOW, " Modulation %s\n", v150_1_modulation_to_str(s->far.parms.selmod));
3133 span_log(&s->logging, SPAN_LOG_FLOW, " Compression direction %s\n", v150_1_compression_direction_to_str(s->far.parms.selected_compression_direction));
3134 span_log(&s->logging, SPAN_LOG_FLOW, " Compression %s\n", v150_1_compression_to_str(s->far.parms.selected_compression));
3135 span_log(&s->logging, SPAN_LOG_FLOW, " Error correction %s\n", v150_1_error_correction_to_str(s->far.parms.selected_error_correction));
3136 span_log(&s->logging, SPAN_LOG_FLOW, " Tx data rate %d\n", s->far.parms.tdsr);
3137 span_log(&s->logging, SPAN_LOG_FLOW, " Rx data rate %d\n", s->far.parms.rdsr);
3138
3139 span_log(&s->logging, SPAN_LOG_FLOW, " I_RAW-CHAR available\n");
3140 span_log(&s->logging, SPAN_LOG_FLOW, " I_RAW-BIT %savailable\n", (s->far.parms.i_raw_bit_available) ? "" : "not ");
3141 span_log(&s->logging, SPAN_LOG_FLOW, " I_FRAME %savailable\n", (s->far.parms.i_frame_available) ? "" : "not ");
3142 if (s->far.parms.i_octet_without_dlci_available || s->far.parms.i_octet_without_dlci_available)
3143 {
3144 if (s->far.parms.i_octet_without_dlci_available)
3145 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET (no DLCI) available\n");
3146 /*endif*/
3147 if (s->far.parms.i_octet_with_dlci_available)
3148 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET (DLCI) available\n");
3149 /*endif*/
3150 }
3151 else
3152 {
3153 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET not available\n");
3154 }
3155 /*endif*/
3156 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-STAT %savailable\n", (s->far.parms.i_char_stat_available) ? "" : "not ");
3157 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-DYN %savailable\n", (s->far.parms.i_char_dyn_available) ? "" : "not ");
3158 span_log(&s->logging, SPAN_LOG_FLOW, " I_OCTET-CS %savailable\n", (s->far.parms.i_octet_cs_available) ? "" : "not ");
3159 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-STAT-CS %savailable\n", (s->far.parms.i_char_stat_cs_available) ? "" : "not ");
3160 span_log(&s->logging, SPAN_LOG_FLOW, " I_CHAR-DYN-CS %savailable\n", (s->far.parms.i_char_dyn_cs_available) ? "" : "not ");
3161
3162 if (len >= 15
3163 &&
3164 (s->far.parms.selected_compression == V150_1_COMPRESSION_V42BIS || s->far.parms.selected_compression == V150_1_COMPRESSION_V44))
3165 {
3166 /* Selected_compression should be V150_1_COMPRESSION_V42BIS or V150_1_COMPRESSION_V44 */
3167 s->far.parms.compression_tx_dictionary_size = get_net_unaligned_uint16(&buf[9]);
3168 s->far.parms.compression_rx_dictionary_size = get_net_unaligned_uint16(&buf[11]);
3169 s->far.parms.compression_tx_string_length = buf[13];
3170 s->far.parms.compression_rx_string_length = buf[14];
3171
3172 span_log(&s->logging, SPAN_LOG_FLOW, " Tx dictionary size %d\n", s->far.parms.compression_tx_dictionary_size);
3173 span_log(&s->logging, SPAN_LOG_FLOW, " Rx dictionary size %d\n", s->far.parms.compression_rx_dictionary_size);
3174 span_log(&s->logging, SPAN_LOG_FLOW, " Tx string length %d\n", s->far.parms.compression_tx_string_length);
3175 span_log(&s->logging, SPAN_LOG_FLOW, " Rx string length %d\n", s->far.parms.compression_rx_string_length);
3176 }
3177 else
3178 {
3179 s->far.parms.compression_tx_dictionary_size = 0;
3180 s->far.parms.compression_rx_dictionary_size = 0;
3181 s->far.parms.compression_tx_string_length = 0;
3182 s->far.parms.compression_rx_string_length = 0;
3183 }
3184 /*endif*/
3185
3186 if (len >= 19
3187 &&
3188 s->far.parms.selected_compression == V150_1_COMPRESSION_V44)
3189 {
3190 /* Selected_compression should be V150_1_COMPRESSION_V44 */
3191 s->far.parms.compression_tx_history_size = get_net_unaligned_uint16(&buf[15]);
3192 s->far.parms.compression_rx_history_size = get_net_unaligned_uint16(&buf[17]);
3193
3194 span_log(&s->logging, SPAN_LOG_FLOW, " Tx history size %d\n", s->far.parms.compression_tx_history_size);
3195 span_log(&s->logging, SPAN_LOG_FLOW, " Rx history size %d\n", s->far.parms.compression_rx_history_size);
3196 }
3197 else
3198 {
3199 s->far.parms.compression_tx_history_size = 0;
3200 s->far.parms.compression_rx_history_size = 0;
3201 }
3202 /*endif*/
3203
3204 s->far.parms.connection_state = V150_1_STATE_CONNECTED;
3205 if (s->near.parms.connection_state >= V150_1_STATE_CONNECTED)
3206 s->joint_connection_state = V150_1_STATE_CONNECTED;
3207 /*endif*/
3208 status_report(s, V150_1_STATUS_REASON_CONNECTION_STATE_CONNECTED);
3209 return 0;
3210}
3211/*- End of function --------------------------------------------------------*/
3212
3213static int v150_1_process_break(v150_1_state_t *s, const uint8_t buf[], int len)
3214{
3215 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3216 {
3217 span_log(&s->logging, SPAN_LOG_WARNING, "BREAK received before CONNECT. Ignored.\n");
3218 return -1;
3219 }
3220 /*endif*/
3221 if (len != 3)
3222 {
3223 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid BREAK message length %d\n", len);
3224 return -1;
3225 }
3226 /*endif*/
3227
3228 s->far.break_source = (buf[1] >> 4) & 0x0F;
3229 s->far.break_type = buf[1] & 0x0F;
3230 s->far.break_duration = buf[2];
3231 span_log(&s->logging, SPAN_LOG_FLOW, "Break source %s\n", v150_1_break_source_to_str(s->far.break_source));
3232 span_log(&s->logging, SPAN_LOG_FLOW, "Break type %s\n", v150_1_break_type_to_str(s->far.break_type));
3233 span_log(&s->logging, SPAN_LOG_FLOW, "Break len %d ms\n", s->far.break_duration*10);
3234 status_report(s, V150_1_STATUS_REASON_BREAK_RECEIVED);
3235 return 0;
3236}
3237/*- End of function --------------------------------------------------------*/
3238
3239static int v150_1_process_break_ack(v150_1_state_t *s, const uint8_t buf[], int len)
3240{
3241 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3242 {
3243 span_log(&s->logging, SPAN_LOG_WARNING, "BREAKACK received before CONNECT. Ignored.\n");
3244 return -1;
3245 }
3246 /*endif*/
3247 if (len != 1)
3248 {
3249 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid BREAKACK message length %d\n", len);
3250 return -1;
3251 }
3252 /*endif*/
3253
3254 return 0;
3255}
3256/*- End of function --------------------------------------------------------*/
3257
3258static int v150_1_process_mr_event(v150_1_state_t *s, const uint8_t buf[], int len)
3259{
3260 int event;
3261 int reason;
3262
3263 if (s->joint_connection_state < V150_1_STATE_INITED)
3264 {
3265 span_log(&s->logging, SPAN_LOG_WARNING, "MR-EVENT received before INIT. Ignored.\n");
3266 return -1;
3267 }
3268 /*endif*/
3269 if (len < 3)
3270 {
3271 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid MR_EVENT message length %d\n", len);
3272 return -1;
3273 }
3274 /*endif*/
3275
3276 event = buf[1];
3277 span_log(&s->logging, SPAN_LOG_FLOW, "MR-event %s (%d) received\n", v150_1_mr_event_type_to_str(event), event);
3278 switch (event)
3279 {
3280 case V150_1_MR_EVENT_ID_NULL:
3281 if (len != 3)
3282 {
3283 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid MR-event message length %d\n", len);
3284 return -1;
3285 }
3286 /*endif*/
3287 break;
3288 case V150_1_MR_EVENT_ID_RATE_RENEGOTIATION:
3289 case V150_1_MR_EVENT_ID_RETRAIN:
3290 if (len != 3)
3291 {
3292 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid MR-event message length %d\n", len);
3293 return -1;
3294 }
3295 /*endif*/
3296 reason = buf[2];
3297 span_log(&s->logging, SPAN_LOG_FLOW, " Reason %d\n", reason);
3298 if (event == V150_1_MR_EVENT_ID_RETRAIN)
3299 {
3300 s->far.parms.connection_state = V150_1_STATE_RETRAIN;
3301 s->joint_connection_state = V150_1_STATE_RETRAIN;
3302 status_report(s, V150_1_STATUS_REASON_RATE_RETRAIN_RECEIVED);
3303 }
3304 else
3305 {
3306 s->far.parms.connection_state = V150_1_STATE_RATE_RENEGOTIATION;
3307 s->joint_connection_state = V150_1_STATE_RATE_RENEGOTIATION;
3308 status_report(s, V150_1_STATUS_REASON_RATE_RENEGOTIATION_RECEIVED);
3309 }
3310 /*endif*/
3311 break;
3312 case V150_1_MR_EVENT_ID_PHYSUP:
3313 if (len != 10)
3314 {
3315 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid MR-event message length %d\n", len);
3316 return -1;
3317 }
3318 /*endif*/
3319 s->far.parms.selmod = (buf[3] >> 2) & 0x3F;
3320 s->far.parms.txsen = (buf[3] & 0x02) != 0;
3321 s->far.parms.rxsen = (buf[3] & 0x01) != 0;
3322 s->far.parms.tdsr = get_net_unaligned_uint16(&buf[4]);
3323 s->far.parms.rdsr = get_net_unaligned_uint16(&buf[6]);
3324 s->far.parms.txsr = buf[8];
3325 s->far.parms.rxsr = buf[9];
3326
3327 span_log(&s->logging, SPAN_LOG_FLOW, " Selected modulation %s\n", v150_1_modulation_to_str(s->far.parms.selmod));
3328 span_log(&s->logging, SPAN_LOG_FLOW, " Tx data signalling rate %d\n", s->far.parms.tdsr);
3329 span_log(&s->logging, SPAN_LOG_FLOW, " Rx data signalling rate %d\n", s->far.parms.rdsr);
3330 if (s->far.parms.txsen)
3331 span_log(&s->logging, SPAN_LOG_FLOW, " Tx symbol rate %s\n", v150_1_symbol_rate_to_str(s->far.parms.txsr));
3332 /*endif*/
3333 if (s->far.parms.rxsen)
3334 span_log(&s->logging, SPAN_LOG_FLOW, " Rx symbol rate %s\n", v150_1_symbol_rate_to_str(s->far.parms.rxsr));
3335 /*endif*/
3336
3337 /* TODO: report these parameters */
3338
3339 s->far.parms.connection_state = V150_1_STATE_PHYSUP;
3340 if (s->near.parms.connection_state >= V150_1_STATE_PHYSUP)
3341 s->joint_connection_state = V150_1_STATE_PHYSUP;
3342 /*endif*/
3343 status_report(s, V150_1_STATUS_REASON_CONNECTION_STATE_PHYSUP);
3344 break;
3345 default:
3346 span_log(&s->logging, SPAN_LOG_WARNING, "Unknown MR-event type %d received\n", event);
3347 break;
3348 }
3349 /*endif*/
3350 return 0;
3351}
3352/*- End of function --------------------------------------------------------*/
3353
3354static int v150_1_process_cleardown(v150_1_state_t *s, const uint8_t buf[], int len)
3355{
3356 if (s->joint_connection_state < V150_1_STATE_INITED)
3357 {
3358 span_log(&s->logging, SPAN_LOG_WARNING, "CLEARDOWN received before INIT. Ignored.\n");
3359 return -1;
3360 }
3361 /*endif*/
3362 if (len != 4)
3363 {
3364 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid CLEARDOWN message length %d\n", len);
3365 return -1;
3366 }
3367 /*endif*/
3368
3369 s->far.parms.cleardown_reason = buf[1];
3370 span_log(&s->logging,
3371 SPAN_LOG_FLOW,
3372 " Reason %s\n",
3373 v150_1_cleardown_reason_to_str(s->far.parms.cleardown_reason));
3374 // vendor = buf[2];
3375 // vendor_info = buf[3];
3376 /* A cleardown moves everything back to square one. */
3377 s->far.parms.connection_state = V150_1_STATE_IDLE;
3378 status_report(s, V150_1_STATUS_REASON_CONNECTION_STATE_CHANGED);
3379 return 0;
3380}
3381/*- End of function --------------------------------------------------------*/
3382
3383static int v150_1_process_prof_xchg(v150_1_state_t *s, const uint8_t buf[], int len)
3384{
3385 if (s->joint_connection_state < V150_1_STATE_INITED)
3386 {
3387 span_log(&s->logging, SPAN_LOG_WARNING, "PROF_XCHG received before INIT. Ignored.\n");
3388 return -1;
3389 }
3390 /*endif*/
3391 if (len != 19)
3392 {
3393 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid PROF_XCHG message length %d\n", len);
3394 return -1;
3395 }
3396 /*endif*/
3397
3398 /* The following have 3 way options - no, yes and unknown */
3399 s->far.parms.v42_lapm_supported = (buf[1] & 0xC0) == 0x40;
3400 s->far.parms.v42_annex_a_supported = (buf[1] & 0x30) == 0x10;
3401 s->far.parms.v44_supported = (buf[1] & 0x0C) == 0x04;
3402 s->far.parms.v42bis_supported = (buf[1] & 0x03) == 0x01;
3403 s->far.parms.mnp5_supported = (buf[2] & 0xC0) == 0x40;
3404
3405 s->far.parms.v42bis_p0 = buf[3];
3406 s->far.parms.v42bis_p1 = get_net_unaligned_uint16(&buf[4]);
3407 s->far.parms.v42bis_p2 = buf[6];
3408 s->far.parms.v44_c0 = buf[7];
3409 s->far.parms.v44_p0 = buf[8];
3410 s->far.parms.v44_p1t = get_net_unaligned_uint16(&buf[9]);
3411 s->far.parms.v44_p1r = get_net_unaligned_uint16(&buf[11]);
3412 s->far.parms.v44_p2t = buf[13];
3413 s->far.parms.v44_p2r = buf[14];
3414 s->far.parms.v44_p3t = get_net_unaligned_uint16(&buf[15]);
3415 s->far.parms.v44_p3r = get_net_unaligned_uint16(&buf[17]);
3416
3417 span_log(&s->logging, SPAN_LOG_FLOW, " V.42 LAPM %ssupported\n", (s->far.parms.v42_lapm_supported) ? "" : "not ");
3418 span_log(&s->logging, SPAN_LOG_FLOW, " V.42 Annex A %ssupported\n", (s->far.parms.v42_annex_a_supported) ? "" : "not ");
3419 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 %ssupported\n", (s->far.parms.v44_supported) ? "" : "not ");
3420 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis %ssupported\n", (s->far.parms.v42bis_supported) ? "" : "not ");
3421 span_log(&s->logging, SPAN_LOG_FLOW, " MNP5 %ssupported\n", (s->far.parms.mnp5_supported) ? "" : "not ");
3422
3423 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P0 %d\n", s->far.parms.v42bis_p0);
3424 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P1 %d\n", s->far.parms.v42bis_p1);
3425 span_log(&s->logging, SPAN_LOG_FLOW, " V.42bis P2 %d\n", s->far.parms.v42bis_p2);
3426 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 C0 %d\n", s->far.parms.v44_c0);
3427 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1 %d\n", s->far.parms.v44_p0);
3428 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1T %d\n", s->far.parms.v44_p1t);
3429 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P1R %d\n", s->far.parms.v44_p1r);
3430 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P2T %d\n", s->far.parms.v44_p2t);
3431 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P2R %d\n", s->far.parms.v44_p2r);
3432 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P3T %d\n", s->far.parms.v44_p3t);
3433 span_log(&s->logging, SPAN_LOG_FLOW, " V.44 P3R %d\n", s->far.parms.v44_p3r);
3434
3435 /* TODO: */
3436 return 0;
3437}
3438/*- End of function --------------------------------------------------------*/
3439
3440static int v150_1_process_i_raw_octet(v150_1_state_t *s, const uint8_t buf[], int len)
3441{
3442 int i;
3443 int l;
3444 int n;
3445 int header;
3446
3447 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3448 {
3449 span_log(&s->logging, SPAN_LOG_WARNING, "I_RAW-OCTET received before CONNECT. Ignored.\n");
3450 return -1;
3451 }
3452 /*endif*/
3453 if (len < 2)
3454 {
3455 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_RAW-OCTET message length %d\n", len);
3456 return -1;
3457 }
3458 /*endif*/
3459 l = buf[1] & 0x7F;
3460 if ((buf[1] & 0x80) != 0)
3461 {
3462 n = 1;
3463 header = 1;
3464 }
3465 else
3466 {
3467 n = buf[1] + 2;
3468 header = 2;
3469 }
3470 /*endif*/
3471 if (len != l + header)
3472 {
3473 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_RAW-OCTET message length %d\n", len);
3474 return -1;
3475 }
3476 /*endif*/
3477 for (i = 0; i < n; i++)
3478 {
3479 if (s->rx_data_handler)
3480 s->rx_data_handler(s->rx_data_handler_user_data, &buf[header], len - header, -1);
3481 /*endif*/
3482 }
3483 /*endif*/
3484 return 0;
3485}
3486/*- End of function --------------------------------------------------------*/
3487
3488static int v150_1_process_i_raw_bit(v150_1_state_t *s, const uint8_t buf[], int len)
3489{
3490 int i;
3491 int l;
3492 int p;
3493 int n;
3494 int header;
3495
3496 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3497 {
3498 span_log(&s->logging, SPAN_LOG_WARNING, "I_RAW-BIT received before CONNECT. Ignored.\n");
3499 return -1;
3500 }
3501 /*endif*/
3502 if (len < 2)
3503 {
3504 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_RAW-BIT message length %d\n", len);
3505 return -1;
3506 }
3507 /*endif*/
3508 if ((buf[1] & 0x80) == 0)
3509 {
3510 if ((buf[1] & 0x40) == 0)
3511 {
3512 l = buf[1] & 0x3F;
3513 p = 0;
3514 }
3515 else
3516 {
3517 l = (buf[1] >> 3) & 0x07;
3518 p = buf[1] & 0x07;
3519 }
3520 /*endif*/
3521 n = 1;
3522 header = 1;
3523 }
3524 else
3525 {
3526 l = (buf[1] >> 3) & 0x0F;
3527 p = buf[1] & 0x07;
3528 n = buf[2] + 2;
3529 header = 2;
3530 }
3531 /*endif*/
3532 if (len != l + header)
3533 {
3534 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_RAW-BIT message length %d\n", len);
3535 return -1;
3536 }
3537 /*endif*/
3538 for (i = 0; i < n; i++)
3539 {
3540 if (s->rx_data_handler)
3541 s->rx_data_handler(s->rx_data_handler_user_data, &buf[header], len - header, -1);
3542 /*endif*/
3543 }
3544 /*endfor*/
3545 return 0;
3546}
3547/*- End of function --------------------------------------------------------*/
3548
3549static int v150_1_process_i_octet(v150_1_state_t *s, const uint8_t buf[], int len)
3550{
3551 int header;
3552
3553 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3554 {
3555 span_log(&s->logging, SPAN_LOG_WARNING, "I_OCTET received before CONNECT. Ignored.\n");
3556 return -1;
3557 }
3558 /*endif*/
3559 if (len < 2)
3560 {
3561 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_OCTET message length %d\n", len);
3562 return -1;
3563 }
3564 /*endif*/
3565 if (s->far.parms.i_octet_with_dlci_available)
3566 {
3567 /* DLCI is one or two bytes (usually just 1). The low bit of each byte is an extension
3568 bit, allowing for a variable number of bytes. */
3569 if (len < 2)
3570 {
3571 span_log(&s->logging, SPAN_LOG_WARNING, "I_OCTET with DLCI has no DLCI field\n");
3572 header = 1000;
3573 }
3574 else
3575 {
3576 if ((buf[1] & 0x01) == 0)
3577 {
3578 if ((buf[2] & 0x01) == 0)
3579 span_log(&s->logging, SPAN_LOG_WARNING, "I_OCTET with DLCI has bad DLCI field\n");
3580 /*endif*/
3581 header = 3;
3582 s->far.parms.dlci = get_net_unaligned_uint16(&buf[1]);
3583 }
3584 else
3585 {
3586 header = 2;
3587 s->far.parms.dlci = buf[1];
3588 }
3589 /*endif*/
3590 }
3591 /*endif*/
3592 }
3593 else
3594 {
3595 header = 1;
3596 }
3597 /*endif*/
3598 if (len > header)
3599 {
3600 if (s->rx_data_handler)
3601 s->rx_data_handler(s->rx_data_handler_user_data, &buf[header], len - header, -1);
3602 /*endif*/
3603 }
3604 /*endif*/
3605 return 0;
3606}
3607/*- End of function --------------------------------------------------------*/
3608
3609static int v150_1_process_i_char_stat(v150_1_state_t *s, const uint8_t buf[], int len)
3610{
3611 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3612 {
3613 span_log(&s->logging, SPAN_LOG_WARNING, "I_CHAR-STAT received before CONNECT. Ignored.\n");
3614 return -1;
3615 }
3616 /*endif*/
3617 if (len < 2)
3618 {
3619 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_CHAR-STAT message length %d\n", len);
3620 return -1;
3621 }
3622 /*endif*/
3623 if (s->far.parms.data_format_code != buf[1])
3624 {
3625 /* Every packet in a session should have the same data format code */
3626 s->far.parms.data_format_code = buf[1];
3627 status_report(s, V150_1_STATUS_REASON_DATA_FORMAT_CHANGED);
3628 }
3629 /*endif*/
3630 if (len > 2)
3631 {
3632 if (s->rx_data_handler)
3633 s->rx_data_handler(s->rx_data_handler_user_data, &buf[2], len - 2, -1);
3634 /*endif*/
3635 }
3636 /*endif*/
3637 return 0;
3638}
3639/*- End of function --------------------------------------------------------*/
3640
3641static int v150_1_process_i_char_dyn(v150_1_state_t *s, const uint8_t buf[], int len)
3642{
3643 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3644 {
3645 span_log(&s->logging, SPAN_LOG_WARNING, "I_CHAR-DYN received before CONNECT. Ignored.\n");
3646 return -1;
3647 }
3648 /*endif*/
3649 if (len < 2)
3650 {
3651 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_CHAR-DYN message length %d\n", len);
3652 return -1;
3653 }
3654 /*endif*/
3655 if (s->far.parms.data_format_code != buf[1])
3656 {
3657 s->far.parms.data_format_code = buf[1];
3658 status_report(s, V150_1_STATUS_REASON_DATA_FORMAT_CHANGED);
3659 }
3660 /*endif*/
3661 if (len > 2)
3662 {
3663 if (s->rx_data_handler)
3664 s->rx_data_handler(s->rx_data_handler_user_data, &buf[2], len - 2, -1);
3665 /*endif*/
3666 }
3667 /*endif*/
3668 return 0;
3669}
3670/*- End of function --------------------------------------------------------*/
3671
3672static int v150_1_process_i_frame(v150_1_state_t *s, const uint8_t buf[], int len)
3673{
3674 int res;
3675 int data_frame_state;
3676
3677 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3678 {
3679 span_log(&s->logging, SPAN_LOG_WARNING, "I_FRAME received before CONNECT. Ignored.\n");
3680 return -1;
3681 }
3682 /*endif*/
3683 if (len < 2)
3684 {
3685 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_FRAME message length %d\n", len);
3686 return -1;
3687 }
3688 /*endif*/
3689 res = (buf[1] >> 2) & 0x3F;
3690 if (res)
3691 span_log(&s->logging, SPAN_LOG_WARNING, "I_FRAME with non-zero 'res' field\n");
3692 /*endif*/
3693 data_frame_state = buf[1] & 0x03;
3694 if (len > 2)
3695 {
3696 if (s->rx_data_handler)
3697 s->rx_data_handler(s->rx_data_handler_user_data, &buf[2], len - 2, -1);
3698 /*endif*/
3699 }
3700 /*endif*/
3701 return 0;
3702}
3703/*- End of function --------------------------------------------------------*/
3704
3705static int v150_1_process_i_octet_cs(v150_1_state_t *s, const uint8_t buf[], int len)
3706{
3707 int fill;
3708 int character_seq_no;
3709
3710 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3711 {
3712 span_log(&s->logging, SPAN_LOG_WARNING, "I_OCTET-CS received before CONNECT. Ignored.\n");
3713 return -1;
3714 }
3715 /*endif*/
3716 if (len < 3)
3717 {
3718 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_OCTET-CS message length %d\n", len);
3719 return -1;
3720 }
3721 /*endif*/
3722 character_seq_no = get_net_unaligned_uint16(&buf[1]);
3723 /* Check for a gap in the data */
3724 fill = (character_seq_no - s->far.parms.octet_cs_next_seq_no) & 0xFFFF;
3725 if (s->rx_data_handler)
3726 s->rx_data_handler(s->rx_data_handler_user_data, &buf[3], len - 3, fill);
3727 /*endif*/
3728 s->far.parms.octet_cs_next_seq_no = (character_seq_no + len - 3) & 0xFFFF;
3729 return 0;
3730}
3731/*- End of function --------------------------------------------------------*/
3732
3733static int v150_1_process_i_char_stat_cs(v150_1_state_t *s, const uint8_t buf[], int len)
3734{
3735 int fill;
3736 int character_seq_no;
3737
3738 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3739 {
3740 span_log(&s->logging, SPAN_LOG_WARNING, "I_CHAR-STAT-CS received before CONNECT. Ignored.\n");
3741 return -1;
3742 }
3743 /*endif*/
3744 if (len < 4)
3745 {
3746 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_CHAR-STAT-CS message length %d\n", len);
3747 return -1;
3748 }
3749 /*endif*/
3750 if (s->far.parms.data_format_code != buf[1])
3751 {
3752 /* Every packet in a session should have the same data format code */
3753 s->far.parms.data_format_code = buf[1];
3754 status_report(s, V150_1_STATUS_REASON_DATA_FORMAT_CHANGED);
3755 }
3756 /*endif*/
3757 character_seq_no = get_net_unaligned_uint16(&buf[2]);
3758 /* Check for a gap in the data */
3759 fill = (character_seq_no - s->far.parms.octet_cs_next_seq_no) & 0xFFFF;
3760 if (s->rx_data_handler)
3761 s->rx_data_handler(s->rx_data_handler_user_data, &buf[4], len - 4, fill);
3762 /*endif*/
3763 s->far.parms.octet_cs_next_seq_no = (character_seq_no + len - 4) & 0xFFFF;
3764 return 0;
3765}
3766/*- End of function --------------------------------------------------------*/
3767
3768static int v150_1_process_i_char_dyn_cs(v150_1_state_t *s, const uint8_t buf[], int len)
3769{
3770 int fill;
3771 int character_seq_no;
3772
3773 if (s->joint_connection_state != V150_1_STATE_CONNECTED)
3774 {
3775 span_log(&s->logging, SPAN_LOG_WARNING, "I_CHAR-DYN-CS received before CONNECT. Ignored.\n");
3776 return -1;
3777 }
3778 /*endif*/
3779 if (len < 4)
3780 {
3781 span_log(&s->logging, SPAN_LOG_WARNING, "Invalid I_CHAR-DYN-CS message length %d\n", len);
3782 return -1;
3783 }
3784 /*endif*/
3785 if (s->far.parms.data_format_code != buf[1])
3786 {
3787 s->far.parms.data_format_code = buf[1];
3788 status_report(s, V150_1_STATUS_REASON_DATA_FORMAT_CHANGED);
3789 }
3790 /*endif*/
3791 character_seq_no = get_net_unaligned_uint16(&buf[2]);
3792 /* Check for a gap in the data */
3793 fill = (character_seq_no - s->far.parms.octet_cs_next_seq_no) & 0xFFFF;
3794 if (s->rx_data_handler)
3795 s->rx_data_handler(s->rx_data_handler_user_data, &buf[4], len - 4, fill);
3796 /*endif*/
3797 s->far.parms.octet_cs_next_seq_no = (character_seq_no + len - 4) & 0xFFFF;
3798 return 0;
3799}
3800/*- End of function --------------------------------------------------------*/
3801
3802static int process_rx_sprt_msg(void *user_data, int chan, int seq_no, const uint8_t buf[], int len)
3803{
3804 int res;
3805 int msg_id;
3806 v150_1_state_t *s;
3807
3808 s = (v150_1_state_t *) user_data;
3809
3810 span_log(&s->logging, SPAN_LOG_FLOW, "%s (%d) seq %d\n", sprt_transmission_channel_to_str(chan), chan, seq_no);
3811 span_log_buf(&s->logging, SPAN_LOG_FLOW, "", buf, len);
3812
3813 if (chan < SPRT_TCID_MIN || chan > SPRT_TCID_MAX)
3814 {
3815 span_log(&s->logging, SPAN_LOG_ERROR, "Packet arrived on invalid channel %d\n", chan);
3816 return -1;
3817 }
3818 /*endif*/
3819 if ((buf[0] & 0x80))
3820 {
3821 span_log(&s->logging, SPAN_LOG_FLOW, "Don't know how to handle this\n");
3822 return -1;
3823 }
3824 /*endif*/
3825 msg_id = buf[0] & 0x7F;
3826 span_log(&s->logging, SPAN_LOG_FLOW, "Message %s received on channel %d, seq no %d\n", v150_1_msg_id_to_str(msg_id), chan, seq_no);
3827
3828 if (msg_id < sizeof(channel_check))
3829 {
3830 if ((channel_check[msg_id] & (1 << chan)) == 0)
3831 {
3832 span_log(&s->logging, SPAN_LOG_FLOW, "Bad channel for message ID %d\n", msg_id);
3833 return -1;
3834 }
3835 /*endif*/
3836 }
3837 /*endif*/
3838
3839 switch (msg_id)
3840 {
3841 case V150_1_MSGID_NULL:
3842 res = v150_1_process_null(s, buf, len);
3843 break;
3844 case V150_1_MSGID_INIT:
3845 res = v150_1_process_init(s, buf, len);
3846 break;
3847 case V150_1_MSGID_XID_XCHG:
3848 res = v150_1_process_xid_xchg(s, buf, len);
3849 break;
3850 case V150_1_MSGID_JM_INFO:
3851 res = v150_1_process_jm_info(s, buf, len);
3852 break;
3853 case V150_1_MSGID_START_JM:
3854 res = v150_1_process_start_jm(s, buf, len);
3855 break;
3856 case V150_1_MSGID_CONNECT:
3857 res = v150_1_process_connect(s, buf, len);
3858 break;
3859 case V150_1_MSGID_BREAK:
3860 res = v150_1_process_break(s, buf, len);
3861 break;
3862 case V150_1_MSGID_BREAKACK:
3863 res = v150_1_process_break_ack(s, buf, len);
3864 break;
3865 case V150_1_MSGID_MR_EVENT:
3866 res = v150_1_process_mr_event(s, buf, len);
3867 break;
3868 case V150_1_MSGID_CLEARDOWN:
3869 res = v150_1_process_cleardown(s, buf, len);
3870 break;
3871 case V150_1_MSGID_PROF_XCHG:
3872 res = v150_1_process_prof_xchg(s, buf, len);
3873 break;
3874 case V150_1_MSGID_I_RAW_OCTET:
3875 res = v150_1_process_i_raw_octet(s, buf, len);
3876 break;
3877 case V150_1_MSGID_I_RAW_BIT:
3878 res = v150_1_process_i_raw_bit(s, buf, len);
3879 break;
3880 case V150_1_MSGID_I_OCTET:
3881 res = v150_1_process_i_octet(s, buf, len);
3882 break;
3883 case V150_1_MSGID_I_CHAR_STAT:
3884 res = v150_1_process_i_char_stat(s, buf, len);
3885 break;
3886 case V150_1_MSGID_I_CHAR_DYN:
3887 res = v150_1_process_i_char_dyn(s, buf, len);
3888 break;
3889 case V150_1_MSGID_I_FRAME:
3890 res = v150_1_process_i_frame(s, buf, len);
3891 break;
3892 case V150_1_MSGID_I_OCTET_CS:
3893 res = v150_1_process_i_octet_cs(s, buf, len);
3894 break;
3895 case V150_1_MSGID_I_CHAR_STAT_CS:
3896 res = v150_1_process_i_char_stat_cs(s, buf, len);
3897 break;
3898 case V150_1_MSGID_I_CHAR_DYN_CS:
3899 res = v150_1_process_i_char_dyn_cs(s, buf, len);
3900 break;
3901 default:
3902 span_log(&s->logging, SPAN_LOG_FLOW, "Bad msg ID %d\n", msg_id);
3903 res = -1;
3904 break;
3905 }
3906 /*endswitch*/
3907 if (res < 0)
3908 span_log(&s->logging, SPAN_LOG_FLOW, "Bad message\n");
3909 /*endif*/
3910 return res;
3911}
3912/*- End of function --------------------------------------------------------*/
3913
3914SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_test_rx_sprt_msg(v150_1_state_t *s, int chan, int seq_no, const uint8_t buf[], int len)
3915{
3916 process_rx_sprt_msg((void *) s, chan, seq_no, buf, len);
3917 return 0;
3918}
3919/*- End of function --------------------------------------------------------*/
3920
3921SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_local_busy(v150_1_state_t *s, bool_Bool busy)
3922{
3923 bool_Bool previous_busy;
3924
3925 previous_busy = s->near.parms.busy;
3926 s->near.parms.busy = busy;
3927 return previous_busy;
3928}
3929/*- End of function --------------------------------------------------------*/
3930
3931SPAN_DECLARE(bool)__attribute__((visibility("default"))) _Bool v150_1_get_far_busy_status(v150_1_state_t *s)
3932{
3933 return s->far.parms.busy;
3934}
3935/*- End of function --------------------------------------------------------*/
3936
3937SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_local_tc_payload_bytes(v150_1_state_t *s, int channel, int max_len)
3938{
3939 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
3940 return -1;
3941 /*endif*/
3942 if (max_len < channel_parm_limits[channel].min_payload_bytes
3943 ||
3944 max_len > channel_parm_limits[channel].max_payload_bytes)
3945 {
3946 return -1;
3947 }
3948 /*endif*/
3949 s->near.max_payload_bytes[channel] = max_len;
3950 return 0;
3951}
3952/*- End of function --------------------------------------------------------*/
3953
3954SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_get_local_tc_payload_bytes(v150_1_state_t *s, int channel)
3955{
3956 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
3957 return -1;
3958 /*endif*/
3959 return s->near.max_payload_bytes[channel];
3960}
3961/*- End of function --------------------------------------------------------*/
3962
3963SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_info_stream_tx_mode(v150_1_state_t *s, int channel, int msg_id)
3964{
3965 if (channel < SPRT_TCID_MIN || channel > SPRT_TCID_MAX)
3966 return -1;
3967 /*endif*/
3968 switch (msg_id)
3969 {
3970 case V150_1_MSGID_I_RAW_OCTET:
3971 case V150_1_MSGID_I_RAW_BIT:
3972 case V150_1_MSGID_I_OCTET:
3973 case V150_1_MSGID_I_CHAR_STAT:
3974 case V150_1_MSGID_I_CHAR_DYN:
3975 case V150_1_MSGID_I_FRAME:
3976 case V150_1_MSGID_I_OCTET_CS:
3977 case V150_1_MSGID_I_CHAR_STAT_CS:
3978 case V150_1_MSGID_I_CHAR_DYN_CS:
3979 s->near.info_stream_channel = channel;
3980 s->near.info_stream_msg_id = msg_id;
3981 break;
3982 default:
3983 return -1;
3984 }
3985 return 0;
3986}
3987/*- End of function --------------------------------------------------------*/
3988
3989SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_info_stream_msg_priorities(v150_1_state_t *s, int msg_ids[])
3990{
3991 int i;
3992
3993 /* Check the list is valid */
3994 for (i = 0; i < 10 && msg_ids[i] >= 0; i++)
3995 {
3996 switch(msg_ids[i])
3997 {
3998 case V150_1_MSGID_I_RAW_OCTET:
3999 case V150_1_MSGID_I_RAW_BIT:
4000 case V150_1_MSGID_I_OCTET:
4001 case V150_1_MSGID_I_CHAR_STAT:
4002 case V150_1_MSGID_I_CHAR_DYN:
4003 case V150_1_MSGID_I_FRAME:
4004 case V150_1_MSGID_I_OCTET_CS:
4005 case V150_1_MSGID_I_CHAR_STAT_CS:
4006 case V150_1_MSGID_I_CHAR_DYN_CS:
4007 /* OK */
4008 break;
4009 default:
4010 return -1;
4011 }
4012 /*endswitch*/
4013 }
4014 /*endfor*/
4015 for (i = 0; i < 10 && msg_ids[i] >= 0; i++)
4016 {
4017 s->near.info_msg_preferences[i] = msg_ids[i];
4018 }
4019 /*endfor*/
4020 if (i < 10)
4021 s->near.info_msg_preferences[i] = -1;
4022 /*endif*/
4023 return 0;
4024}
4025/*- End of function --------------------------------------------------------*/
4026
4027SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_modulation(v150_1_state_t *s, int modulation)
4028{
4029 s->near.parms.selmod = modulation;
4030 return 0;
4031}
4032/*- End of function --------------------------------------------------------*/
4033
4034SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_compression_direction(v150_1_state_t *s, int compression_direction)
4035{
4036 s->near.parms.selected_compression_direction = compression_direction;
4037 return 0;
4038}
4039/*- End of function --------------------------------------------------------*/
4040
4041SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_compression(v150_1_state_t *s, int compression)
4042{
4043 s->near.parms.selected_compression = compression;
4044 return 0;
4045}
4046/*- End of function --------------------------------------------------------*/
4047
4048SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_compression_parameters(v150_1_state_t *s,
4049 int tx_dictionary_size,
4050 int rx_dictionary_size,
4051 int tx_string_length,
4052 int rx_string_length,
4053 int tx_history_size,
4054 int rx_history_size)
4055{
4056 s->near.parms.compression_tx_dictionary_size = tx_dictionary_size;
4057 s->near.parms.compression_rx_dictionary_size = rx_dictionary_size;
4058 s->near.parms.compression_tx_string_length = tx_string_length;
4059 s->near.parms.compression_rx_string_length = rx_string_length;
4060 /* These are only relevant for V.44 */
4061 s->near.parms.compression_tx_history_size = tx_history_size;
4062 s->near.parms.compression_rx_history_size = rx_history_size;
4063 return 0;
4064}
4065/*- End of function --------------------------------------------------------*/
4066
4067SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_error_correction(v150_1_state_t *s, int error_correction)
4068{
4069 s->near.parms.selected_error_correction = error_correction;
4070 return 0;
4071}
4072/*- End of function --------------------------------------------------------*/
4073
4074SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_tx_symbol_rate(v150_1_state_t *s, bool_Bool enable, int rate)
4075{
4076 s->near.parms.txsen = enable;
4077 s->near.parms.txsr = (enable) ? rate : 0;
4078 return 0;
4079}
4080/*- End of function --------------------------------------------------------*/
4081
4082SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_rx_symbol_rate(v150_1_state_t *s, bool_Bool enable, int rate)
4083{
4084 s->near.parms.rxsen = enable;
4085 s->near.parms.rxsr = (enable) ? rate : 0;
4086 return 0;
4087}
4088/*- End of function --------------------------------------------------------*/
4089
4090SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_tx_data_signalling_rate(v150_1_state_t *s, int rate)
4091{
4092 s->near.parms.tdsr = rate;
4093 return 0;
4094}
4095/*- End of function --------------------------------------------------------*/
4096
4097SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_set_rx_data_signalling_rate(v150_1_state_t *s, int rate)
4098{
4099 s->near.parms.rdsr = rate;
4100 return 0;
4101}
4102/*- End of function --------------------------------------------------------*/
4103
4104static void set_joint_cdscselect(v150_1_state_t *s)
4105{
4106 /* See Table 32/V.150.1 */
4107 if (s->near.parms.cdscselect == V150_1_CDSCSELECT_INDETERMINATE
4108 ||
4109 s->far.parms.cdscselect == V150_1_CDSCSELECT_INDETERMINATE)
4110 {
4111 s->cdscselect = V150_1_CDSCSELECT_INDETERMINATE;
4112 }
4113 else if (s->near.parms.cdscselect == V150_1_CDSCSELECT_AUDIO_RFC4733
4114 ||
4115 s->far.parms.cdscselect == V150_1_CDSCSELECT_AUDIO_RFC4733)
4116 {
4117 s->cdscselect = V150_1_CDSCSELECT_AUDIO_RFC4733;
4118 }
4119 else if (s->near.parms.cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED
4120 ||
4121 s->far.parms.cdscselect == V150_1_CDSCSELECT_VBD_PREFERRED)
4122 {
4123 s->cdscselect = V150_1_CDSCSELECT_VBD_PREFERRED;
4124 }
4125 else
4126 {
4127 s->cdscselect = V150_1_CDSCSELECT_MIXED;
4128 }
4129 /*endif*/
4130}
4131/*- End of function --------------------------------------------------------*/
4132
4133SPAN_DECLARE(void)__attribute__((visibility("default"))) void v150_1_set_near_cdscselect(v150_1_state_t *s, v150_1_cdscselect_t select)
4134{
4135 s->near.parms.cdscselect = select;
4136 set_joint_cdscselect(s);
4137}
4138/*- End of function --------------------------------------------------------*/
4139
4140SPAN_DECLARE(void)__attribute__((visibility("default"))) void v150_1_set_far_cdscselect(v150_1_state_t *s, v150_1_cdscselect_t select)
4141{
4142 s->far.parms.cdscselect = select;
4143 set_joint_cdscselect(s);
4144}
4145/*- End of function --------------------------------------------------------*/
4146
4147SPAN_DECLARE(void)__attribute__((visibility("default"))) void v150_1_set_call_discrimination_timeout(v150_1_state_t *s, int timeout)
4148{
4149 s->call_discrimination_timeout = timeout;
4150}
4151/*- End of function --------------------------------------------------------*/
4152
4153SPAN_DECLARE(logging_state_t *)__attribute__((visibility("default"))) logging_state_t * v150_1_get_logging_state(v150_1_state_t *s)
4154{
4155 return &s->logging;
4156}
4157/*- End of function --------------------------------------------------------*/
4158
4159int sse_status_handler(v150_1_state_t *s, int status)
4160{
4161 span_log(&s->logging, SPAN_LOG_FLOW, "SSE status event %s\n", v150_1_sse_status_to_str(status));
4162 return 0;
4163}
4164/*- End of function --------------------------------------------------------*/
4165
4166static void sprt_status_handler(void *user_data, int status)
4167{
4168 v150_1_state_t *s;
4169
4170 s = (v150_1_state_t *) user_data;
4171 span_log(&s->logging, SPAN_LOG_FLOW, "SPRT status event %d\n", status);
4172}
4173/*- End of function --------------------------------------------------------*/
4174
4175static void call_discrimination_timer_expired(v150_1_state_t *s, span_timestamp_t now)
4176{
4177 v150_1_state_machine(s, V150_1_SIGNAL_CALL_DISCRIMINATION_TIMER_EXPIRED, NULL((void*)0), 0);
4178}
4179/*- End of function --------------------------------------------------------*/
4180
4181SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_timer_expired(v150_1_state_t *s, span_timestamp_t now)
4182{
4183 span_log(&s->logging, SPAN_LOG_FLOW, "V.150.1 timer expired at %lu\n", now);
4184
4185 if (now < s->latest_timer)
4186 {
4187 span_log(&s->logging, SPAN_LOG_FLOW, "V.150.1 timer returned %luus early\n", s->latest_timer - now);
4188 /* Request the same timeout point again. */
4189 if (s->timer_handler)
4190 s->timer_handler(s->timer_user_data, s->latest_timer);
4191 /*endif*/
4192 return 0;
4193 }
4194 /*endif*/
4195
4196 if (s->call_discrimination_timer != 0 && s->call_discrimination_timer <= now)
4197 {
4198 span_log(&s->logging, SPAN_LOG_FLOW, "Call discrimination timer expired\n");
4199 call_discrimination_timer_expired(s, now);
4200 }
4201 /*endif*/
4202 if (s->sse_timer != 0 && s->sse_timer <= now)
4203 {
4204 span_log(&s->logging, SPAN_LOG_FLOW, "SSE timer expired\n");
4205 v150_1_sse_timer_expired(s, now);
4206 }
4207 /*endif*/
4208 if (s->sprt_timer != 0 && s->sprt_timer <= now)
4209 {
4210 span_log(&s->logging, SPAN_LOG_FLOW, "SPRT timer expired\n");
4211 sprt_timer_expired(&s->sprt, now);
4212 }
4213 /*endif*/
4214 return 0;
4215}
4216/*- End of function --------------------------------------------------------*/
4217
4218static span_timestamp_t select_timer(v150_1_state_t *s)
4219{
4220 span_timestamp_t shortest;
4221 int shortest_is;
4222
4223 /* Find the earliest expiring of the active timers, and set the timeout to that. */
4224 shortest = ~0;
4225 shortest_is = 0;
4226 if (s->sprt_timer && s->sprt_timer < shortest)
4227 {
4228 shortest = s->sprt_timer;
4229 shortest_is = 0;
4230 }
4231 /*endif*/
4232 if (s->sse_timer && s->sse_timer < shortest)
4233 {
4234 shortest = s->sse_timer;
4235 shortest_is = 1;
4236 }
4237 /*endif*/
4238 if (s->call_discrimination_timer && s->call_discrimination_timer < shortest)
4239 {
4240 shortest = s->call_discrimination_timer;
4241 shortest_is = 2;
4242 }
4243 /*endif*/
4244
4245 /* If we haven't shrunk shortest from maximum, we have no timer to set, so we stop the timer,
4246 if its set. */
4247 if (shortest == ~0)
4248 shortest = 0;
4249 /*endif*/
4250 span_log(&s->logging, SPAN_LOG_FLOW, "Update timer to %lu (%d)\n", shortest, shortest_is);
4251 s->latest_timer = shortest;
4252 return shortest;
4253}
4254/*- End of function --------------------------------------------------------*/
4255
4256static span_timestamp_t update_call_discrimination_timer(v150_1_state_t *s, span_timestamp_t timeout)
4257{
4258 span_timestamp_t res;
4259
4260 if (timeout != ~0)
4261 {
4262 s->call_discrimination_timer = timeout;
4263 timeout = select_timer(s);
4264 }
4265 /*endif*/
4266 res = 0;
4267 if (s->timer_handler)
4268 res = s->timer_handler(s->timer_user_data, timeout);
4269 /*endif*/
4270 return res;
4271}
4272/*- End of function --------------------------------------------------------*/
4273
4274span_timestamp_t update_sse_timer(void *user_data, span_timestamp_t timeout)
4275{
4276 v150_1_state_t *s;
4277 span_timestamp_t res;
4278
4279 s = (v150_1_state_t *) user_data;
4280 if (timeout != ~0)
4281 {
4282 s->sse_timer = timeout;
4283 timeout = select_timer(s);
4284 }
4285 /*endif*/
4286 res = 0;
4287 if (s->timer_handler)
4288 res = s->timer_handler(s->timer_user_data, timeout);
4289 /*endif*/
4290 return res;
4291}
4292/*- End of function --------------------------------------------------------*/
4293
4294static span_timestamp_t update_sprt_timer(void *user_data, span_timestamp_t timeout)
4295{
4296 v150_1_state_t *s;
4297 span_timestamp_t res;
4298
4299 s = (v150_1_state_t *) user_data;
4300 if (timeout != ~0)
4301 {
4302 s->sprt_timer = timeout;
4303 timeout = select_timer(s);
4304 }
4305 /*endif*/
4306 res = 0;
4307 if (s->timer_handler)
4308 res = s->timer_handler(s->timer_user_data, timeout);
4309 /*endif*/
4310 return res;
4311}
4312/*- End of function --------------------------------------------------------*/
4313
4314SPAN_DECLARE(v150_1_state_t *)__attribute__((visibility("default"))) v150_1_state_t * v150_1_init(v150_1_state_t *s,
4315 sprt_tx_packet_handler_t sprt_tx_packet_handler,
4316 void *sprt_tx_packet_handler_user_data,
4317 uint8_t sprt_tx_payload_type,
4318 uint8_t sprt_rx_payload_type,
4319 v150_1_sse_tx_packet_handler_t sse_tx_packet_handler,
4320 void *sse_tx_packet_user_data,
4321 v150_1_timer_handler_t v150_1_timer_handler,
4322 void *v150_1_timer_user_data,
4323 v150_1_rx_data_handler_t rx_data_handler,
4324 void *rx_data_handler_user_data,
4325 v150_1_rx_status_report_handler_t rx_status_report_handler,
4326 void *rx_status_report_user_data,
4327 v150_1_spe_signal_handler_t spe_signal_handler,
4328 void *spe_signal_handler_user_data)
4329{
4330 if (sprt_tx_packet_handler == NULL((void*)0) || rx_data_handler == NULL((void*)0) || rx_status_report_handler == NULL((void*)0))
4331 return NULL((void*)0);
4332 /*endif*/
4333 if (s == NULL((void*)0))
4334 {
4335 if ((s = (v150_1_state_t *) span_alloc(sizeof(*s))) == NULL((void*)0))
4336 return NULL((void*)0);
4337 /*endif*/
4338 }
4339 /*endif*/
4340 memset(s, 0, sizeof(*s));
4341
4342 span_log_init(&s->logging, SPAN_LOG_NONE, NULL((void*)0));
4343 span_log_set_protocol(&s->logging, "V.150.1");
4344
4345 s->near.max_payload_bytes[SPRT_TCID_UNRELIABLE_UNSEQUENCED] = SPRT_DEFAULT_TC0_PAYLOAD_BYTES140;
4346 s->near.max_payload_bytes[SPRT_TCID_RELIABLE_SEQUENCED] = SPRT_DEFAULT_TC1_PAYLOAD_BYTES132;
4347 s->near.max_payload_bytes[SPRT_TCID_EXPEDITED_RELIABLE_SEQUENCED] = SPRT_DEFAULT_TC2_PAYLOAD_BYTES132;
4348 s->near.max_payload_bytes[SPRT_TCID_UNRELIABLE_SEQUENCED] = SPRT_DEFAULT_TC3_PAYLOAD_BYTES140;
4349
4350 s->near.parms.v42bis_p0 = 3;
4351 s->near.parms.v42bis_p1 = 512;
4352 s->near.parms.v42bis_p2 = 6;
4353 s->near.parms.v44_c0 = 0;
4354 s->near.parms.v44_p0 = 0;
4355 s->near.parms.v44_p1t = 0;
4356 s->near.parms.v44_p1r = 0;
4357 s->near.parms.v44_p2t = 0;
4358 s->near.parms.v44_p2r = 0;
4359 s->near.parms.v44_p3t = 0;
4360 s->near.parms.v44_p3r = 0;
4361
4362 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_CALL_FUNCTION_1] = true1;
4363 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_CALL_FUNCTION_1] = V150_1_JM_CALL_FUNCTION_V_SERIES;
4364 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_MODULATION_MODES] = true1;
4365 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_MODULATION_MODES] =
4366 V150_1_JM_MODULATION_MODE_V34_AVAILABLE
4367 | V150_1_JM_MODULATION_MODE_V32_V32bis_AVAILABLE
4368 | V150_1_JM_MODULATION_MODE_V22_V22bis_AVAILABLE
4369 | V150_1_JM_MODULATION_MODE_V21_AVAILABLE;
4370 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_PROTOCOLS] = true1;
4371 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_PROTOCOLS] = V150_1_JM_PROTOCOL_V42_LAPM;
4372 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_PSTN_ACCESS] = true1;
4373 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_PSTN_ACCESS] = 0;
4374 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_PCM_MODEM_AVAILABILITY] = false0;
4375 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_PCM_MODEM_AVAILABILITY] = 0;
4376 s->near.parms.jm_category_id_seen[V150_1_JM_CATEGORY_ID_EXTENSION] = false0;
4377 s->near.parms.jm_category_info[V150_1_JM_CATEGORY_ID_EXTENSION] = 0;
4378
4379 s->near.parms.selmod = V150_1_SELMOD_NULL;
4380 s->near.parms.selected_compression_direction = V150_1_COMPRESS_NEITHER_WAY;
4381 s->near.parms.selected_compression = V150_1_COMPRESSION_NONE;
4382 s->near.parms.selected_error_correction = V150_1_ERROR_CORRECTION_NONE;
4383 s->near.parms.tdsr = 0;
4384 s->near.parms.rdsr = 0;
4385 s->near.parms.txsen = false0;
4386 s->near.parms.txsr = V150_1_SYMBOL_RATE_NULL;
4387 s->near.parms.rxsen = false0;
4388 s->near.parms.rxsr = V150_1_SYMBOL_RATE_NULL;
4389
4390 /* Set default values that suit V.42bis */
4391 s->near.parms.compression_tx_dictionary_size = 512;
4392 s->near.parms.compression_rx_dictionary_size = 512;
4393 s->near.parms.compression_tx_string_length = 6;
4394 s->near.parms.compression_rx_string_length = 6;
4395 s->near.parms.compression_tx_history_size = 0;
4396 s->near.parms.compression_rx_history_size = 0;
4397
4398 s->near.parms.ecp = V150_1_ERROR_CORRECTION_V42_LAPM;
4399 s->near.parms.v42_lapm_supported = true1;
4400 s->near.parms.v42_annex_a_supported = false0; /* This will never be supported, as it was removed from the V.42 spec in 2002. */
4401 s->near.parms.v42bis_supported = true1;
4402 s->near.parms.v44_supported = false0;
4403 s->near.parms.mnp5_supported = false0;
4404
4405 s->near.parms.necrxch_option = false0;
4406 s->near.parms.ecrxch_option = true1;
4407 s->near.parms.xid_profile_exchange_supported = false0;
4408 s->near.parms.asymmetric_data_types_supported = false0;
4409
4410 s->near.parms.i_raw_bit_supported = false0;
4411 s->near.parms.i_frame_supported = false0;
4412 s->near.parms.i_char_stat_supported = false0;
4413 s->near.parms.i_char_dyn_supported = false0;
4414 s->near.parms.i_octet_cs_supported = true1;
4415 s->near.parms.i_char_stat_cs_supported = false0;
4416 s->near.parms.i_char_dyn_cs_supported = false0;
4417
4418 /* Set a default character format. */
4419 s->near.parms.data_format_code = (V150_1_DATA_BITS_7 << 6)
4420 | (V150_1_PARITY_EVEN << 3)
4421 | V150_1_STOP_BITS_1;
4422 s->far.parms.data_format_code = -1;
4423
4424 s->remote_media_state = V150_1_MEDIA_STATE_INITIAL_AUDIO;
4425 s->local_media_state = V150_1_MEDIA_STATE_INITIAL_AUDIO;
4426
4427 s->call_discrimination_timeout = V150_1_CALL_DISCRIMINATION_DEFAULT_TIMEOUT60000000;
4428
4429 s->near.parms.sprt_subsession_id = 0;
4430 s->near.parms.sprt_payload_type = sprt_tx_payload_type;
4431 s->far.parms.sprt_payload_type = sprt_rx_payload_type;
4432
4433 s->rx_data_handler = rx_data_handler;
4434 s->rx_data_handler_user_data = rx_data_handler_user_data;
4435 s->rx_status_report_handler = rx_status_report_handler;
4436 s->rx_status_report_user_data = rx_status_report_user_data;
4437
4438 s->timer_handler = v150_1_timer_handler;
4439 s->timer_user_data = v150_1_timer_user_data;
4440
4441 v150_1_sse_init(s,
4442 sse_tx_packet_handler,
4443 sse_tx_packet_user_data);
4444
4445 sprt_init(&s->sprt,
4446 s->near.parms.sprt_subsession_id,
4447 s->near.parms.sprt_payload_type,
4448 s->far.parms.sprt_payload_type,
4449 NULL((void*)0) /* Use default params */,
4450 sprt_tx_packet_handler,
4451 sprt_tx_packet_handler_user_data,
4452 process_rx_sprt_msg,
4453 s,
4454 update_sprt_timer,
4455 s,
4456 sprt_status_handler,
4457 s);
4458
4459 return s;
4460}
4461/*- End of function --------------------------------------------------------*/
4462
4463SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_release(v150_1_state_t *s)
4464{
4465 return 0;
4466}
4467/*- End of function --------------------------------------------------------*/
4468
4469SPAN_DECLARE(int)__attribute__((visibility("default"))) int v150_1_free(v150_1_state_t *s)
4470{
4471 int ret;
4472
4473 ret = v150_1_release(s);
4474 span_free(s);
4475 return ret;
4476}
4477/*- End of function --------------------------------------------------------*/
4478/*- End of file ------------------------------------------------------------*/