1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * -------------------------------------------------------------------
30 *
31 * ## Unit Test ##
32 *
33 * This file includes its own unit test. To compile the unit test,
34 * simply compile this file with the macro SPINEL_SELF_TEST set to 1.
35 * For example:
36 *
37 * cc spinel.c -Wall -DSPINEL_SELF_TEST=1 -o spinel
38 *
39 * -------------------------------------------------------------------
40 */
41
42 // ----------------------------------------------------------------------------
43 // MARK: -
44 // MARK: Headers
45
46 #include "spinel.h"
47
48 #include <errno.h>
49 #include <limits.h>
50
51 #ifndef SPINEL_PLATFORM_HEADER
52 /* These are all already included in the spinel platform header
53 * if SPINEL_PLATFORM_HEADER was defined.
54 */
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #endif // #ifndef SPINEL_PLATFORM_HEADER
59
60 // ----------------------------------------------------------------------------
61 // MARK: -
62
63 // IAR's errno.h apparently doesn't define EOVERFLOW.
64 #ifndef EOVERFLOW
65 // There is no real good choice for what to set
66 // errno to in this case, so we just pick the
67 // value '1' somewhat arbitrarily.
68 #define EOVERFLOW 1
69 #endif
70
71 // IAR's errno.h apparently doesn't define EINVAL.
72 #ifndef EINVAL
73 // There is no real good choice for what to set
74 // errno to in this case, so we just pick the
75 // value '1' somewhat arbitrarily.
76 #define EINVAL 1
77 #endif
78
79 // IAR's errno.h apparently doesn't define ENOMEM.
80 #ifndef ENOMEM
81 // There is no real good choice for what to set
82 // errno to in this case, so we just pick the
83 // value '1' somewhat arbitrarily.
84 #define ENOMEM 1
85 #endif
86
87 #ifndef SPINEL_PLATFORM_SHOULD_LOG_ASSERTS
88 #define SPINEL_PLATFORM_SHOULD_LOG_ASSERTS 0
89 #endif
90
91 #ifndef SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
92 #define SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR 0
93 #endif
94
95 #ifndef SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
96 #define SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF 0
97 #endif
98
99 #ifndef SPINEL_SELF_TEST
100 #define SPINEL_SELF_TEST 0
101 #endif
102
103 #if defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
104 #error "SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR is set but errno is already defined."
105 #endif
106
107 // Work-around for platforms that don't implement the `errno` variable.
108 #if !defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
109 static int spinel_errno_workaround_;
110 #define errno spinel_errno_workaround_
111 #endif // SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
112
113 #ifndef assert_printf
114 #if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
115 #define assert_printf(fmt, ...) printf(__FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
116 #else // if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
117 #define assert_printf(fmt, ...) fprintf(stderr, __FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
118 #endif // else SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
119 #endif
120
121
122 #ifndef require_action
123 #if SPINEL_PLATFORM_SHOULD_LOG_ASSERTS
124 #define require_action(c, l, a) \
125 do \
126 { \
127 if (!(c)) \
128 { \
129 assert_printf("Requirement Failed (%s)", #c); \
130 a; \
131 goto l; \
132 } \
133 } while (0)
134 #else // if DEBUG
135 #define require_action(c, l, a) \
136 do \
137 { \
138 if (!(c)) \
139 { \
140 a; \
141 goto l; \
142 } \
143 } while (0)
144 #endif // else DEBUG
145 #endif // ifndef require_action
146
147 #ifndef require
148 #define require(c, l) require_action(c, l, {})
149 #endif
150
151 #ifndef strnlen
spinel_strnlen(const char * s,size_t maxlen)152 static size_t spinel_strnlen(const char *s, size_t maxlen)
153 {
154 size_t ret;
155
156 for (ret = 0; (ret < maxlen) && (s[ret] != 0); ret++)
157 {
158 // Empty loop.
159 }
160
161 return ret;
162 }
163 #else
164 #define spinel_strnlen strnlen
165 #endif
166
167 typedef struct
168 {
169 va_list obj;
170 } va_list_obj;
171
172 #define SPINEL_MAX_PACK_LENGTH 32767
173
174 // ----------------------------------------------------------------------------
175
176 // This function validates whether a given byte sequence (string) follows UTF8 encoding.
spinel_validate_utf8(const uint8_t * string)177 static bool spinel_validate_utf8(const uint8_t *string)
178 {
179 bool ret = true;
180 uint8_t byte;
181 uint8_t continuation_bytes = 0;
182
183 while ((byte = *string++) != 0)
184 {
185 if ((byte & 0x80) == 0)
186 {
187 continue;
188 }
189
190 // This is a leading byte 1xxx-xxxx.
191
192 if ((byte & 0x40) == 0) // 10xx-xxxx
193 {
194 // We got a continuation byte pattern without seeing a leading byte earlier.
195 ret = false;
196 goto bail;
197 }
198 else if ((byte & 0x20) == 0) // 110x-xxxx
199 {
200 continuation_bytes = 1;
201 }
202 else if ((byte & 0x10) == 0) // 1110-xxxx
203 {
204 continuation_bytes = 2;
205 }
206 else if ((byte & 0x08) == 0) // 1111-0xxx
207 {
208 continuation_bytes = 3;
209 }
210 else // 1111-1xxx (invalid pattern).
211 {
212 ret = false;
213 goto bail;
214 }
215
216 while (continuation_bytes-- != 0)
217 {
218 byte = *string++;
219
220 // Verify the continuation byte pattern 10xx-xxxx
221 if ((byte & 0xc0) != 0x80)
222 {
223 ret = false;
224 goto bail;
225 }
226 }
227 }
228
229 bail:
230 return ret;
231 }
232
233 // ----------------------------------------------------------------------------
234 // MARK: -
235
spinel_packed_uint_decode(const uint8_t * bytes,spinel_size_t len,unsigned int * value_ptr)236 spinel_ssize_t spinel_packed_uint_decode(const uint8_t *bytes, spinel_size_t len, unsigned int *value_ptr)
237 {
238 spinel_ssize_t ret = 0;
239 unsigned int value = 0;
240
241 unsigned int i = 0;
242
243 do
244 {
245 if ((len < sizeof(uint8_t)) || (i >= sizeof(unsigned int) * CHAR_BIT))
246 {
247 ret = -1;
248 break;
249 }
250
251 value |= (unsigned int)(bytes[0] & 0x7F) << i;
252 i += 7;
253 ret += sizeof(uint8_t);
254 bytes += sizeof(uint8_t);
255 len -= sizeof(uint8_t);
256 } while ((bytes[-1] & 0x80) == 0x80);
257
258 if ((ret > 0) && (value_ptr != NULL))
259 {
260 *value_ptr = value;
261 }
262
263 return ret;
264 }
265
spinel_packed_uint_size(unsigned int value)266 spinel_ssize_t spinel_packed_uint_size(unsigned int value)
267 {
268 spinel_ssize_t ret;
269
270 if (value < (1 << 7))
271 {
272 ret = 1;
273 }
274 else if (value < (1 << 14))
275 {
276 ret = 2;
277 }
278 else if (value < (1 << 21))
279 {
280 ret = 3;
281 }
282 else if (value < (1 << 28))
283 {
284 ret = 4;
285 }
286 else
287 {
288 ret = 5;
289 }
290
291 return ret;
292 }
293
spinel_packed_uint_encode(uint8_t * bytes,spinel_size_t len,unsigned int value)294 spinel_ssize_t spinel_packed_uint_encode(uint8_t *bytes, spinel_size_t len, unsigned int value)
295 {
296 const spinel_ssize_t encoded_size = spinel_packed_uint_size(value);
297
298 if ((spinel_ssize_t)len >= encoded_size)
299 {
300 spinel_ssize_t i;
301
302 for (i = 0; i != encoded_size - 1; ++i)
303 {
304 *bytes++ = (value & 0x7F) | 0x80;
305 value = (value >> 7);
306 }
307
308 *bytes++ = (value & 0x7F);
309 }
310
311 return encoded_size;
312 }
313
spinel_next_packed_datatype(const char * pack_format)314 const char *spinel_next_packed_datatype(const char *pack_format)
315 {
316 int depth = 0;
317
318 do
319 {
320 switch (*++pack_format)
321 {
322 case '(':
323 depth++;
324 break;
325
326 case ')':
327 depth--;
328
329 if (depth == 0)
330 {
331 pack_format++;
332 }
333
334 break;
335 }
336 } while ((depth > 0) && *pack_format != 0);
337
338 return pack_format;
339 }
340
spinel_datatype_vunpack_(bool in_place,const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list_obj * args)341 static spinel_ssize_t spinel_datatype_vunpack_(bool in_place,
342 const uint8_t *data_in,
343 spinel_size_t data_len,
344 const char * pack_format,
345 va_list_obj * args)
346 {
347 spinel_ssize_t ret = 0;
348
349 // Buffer length sanity check
350 require_action(data_len <= SPINEL_MAX_PACK_LENGTH, bail, (ret = -1, errno = EINVAL));
351
352 for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
353 {
354 if (*pack_format == ')')
355 {
356 // Don't go past the end of a struct.
357 break;
358 }
359
360 switch ((spinel_datatype_t)pack_format[0])
361 {
362 case SPINEL_DATATYPE_BOOL_C:
363 {
364 bool *arg_ptr = va_arg(args->obj, bool *);
365 require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
366
367 if (arg_ptr)
368 {
369 *arg_ptr = data_in[0] != 0;
370 }
371
372 ret += sizeof(uint8_t);
373 data_in += sizeof(uint8_t);
374 data_len -= sizeof(uint8_t);
375 break;
376 }
377
378 case SPINEL_DATATYPE_INT8_C:
379 case SPINEL_DATATYPE_UINT8_C:
380 {
381 uint8_t *arg_ptr = va_arg(args->obj, uint8_t *);
382 require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
383
384 if (arg_ptr)
385 {
386 *arg_ptr = data_in[0];
387 }
388
389 ret += sizeof(uint8_t);
390 data_in += sizeof(uint8_t);
391 data_len -= sizeof(uint8_t);
392 break;
393 }
394
395 case SPINEL_DATATYPE_INT16_C:
396 case SPINEL_DATATYPE_UINT16_C:
397 {
398 uint16_t *arg_ptr = va_arg(args->obj, uint16_t *);
399 require_action(data_len >= sizeof(uint16_t), bail, (ret = -1, errno = EOVERFLOW));
400
401 if (arg_ptr)
402 {
403 *arg_ptr = (uint16_t)((data_in[1] << 8) | data_in[0]);
404 }
405
406 ret += sizeof(uint16_t);
407 data_in += sizeof(uint16_t);
408 data_len -= sizeof(uint16_t);
409 break;
410 }
411
412 case SPINEL_DATATYPE_INT32_C:
413 case SPINEL_DATATYPE_UINT32_C:
414 {
415 uint32_t *arg_ptr = va_arg(args->obj, uint32_t *);
416 require_action(data_len >= sizeof(uint32_t), bail, (ret = -1, errno = EOVERFLOW));
417
418 if (arg_ptr)
419 {
420 *arg_ptr = (uint32_t)((data_in[3] << 24) | (data_in[2] << 16) | (data_in[1] << 8) | data_in[0]);
421 }
422
423 ret += sizeof(uint32_t);
424 data_in += sizeof(uint32_t);
425 data_len -= sizeof(uint32_t);
426 break;
427 }
428
429 case SPINEL_DATATYPE_INT64_C:
430 case SPINEL_DATATYPE_UINT64_C:
431 {
432 uint64_t *arg_ptr = va_arg(args->obj, uint64_t *);
433 require_action(data_len >= sizeof(uint64_t), bail, (ret = -1, errno = EOVERFLOW));
434
435 if (arg_ptr)
436 {
437 uint32_t l32 = (uint32_t)((data_in[3] << 24) | (data_in[2] << 16) | (data_in[1] << 8) | data_in[0]);
438 uint32_t h32 = (uint32_t)((data_in[7] << 24) | (data_in[6] << 16) | (data_in[5] << 8) | data_in[4]);
439
440 *arg_ptr = ((uint64_t)l32) | (((uint64_t)h32) << 32);
441 }
442
443 ret += sizeof(uint64_t);
444 data_in += sizeof(uint64_t);
445 data_len -= sizeof(uint64_t);
446 break;
447 }
448
449 case SPINEL_DATATYPE_IPv6ADDR_C:
450 {
451 require_action(data_len >= sizeof(spinel_ipv6addr_t), bail, (ret = -1, errno = EOVERFLOW));
452
453 if (in_place)
454 {
455 spinel_ipv6addr_t *arg = va_arg(args->obj, spinel_ipv6addr_t *);
456 if (arg)
457 {
458 memcpy(arg, data_in, sizeof(spinel_ipv6addr_t));
459 }
460 }
461 else
462 {
463 const spinel_ipv6addr_t **arg_ptr = va_arg(args->obj, const spinel_ipv6addr_t **);
464 if (arg_ptr)
465 {
466 *arg_ptr = (const spinel_ipv6addr_t *)data_in;
467 }
468 }
469
470 ret += sizeof(spinel_ipv6addr_t);
471 data_in += sizeof(spinel_ipv6addr_t);
472 data_len -= sizeof(spinel_ipv6addr_t);
473 break;
474 }
475
476 case SPINEL_DATATYPE_EUI64_C:
477 {
478 require_action(data_len >= sizeof(spinel_eui64_t), bail, (ret = -1, errno = EOVERFLOW));
479
480 if (in_place)
481 {
482 spinel_eui64_t *arg = va_arg(args->obj, spinel_eui64_t *);
483 if (arg)
484 {
485 memcpy(arg, data_in, sizeof(spinel_eui64_t));
486 }
487 }
488 else
489 {
490 const spinel_eui64_t **arg_ptr = va_arg(args->obj, const spinel_eui64_t **);
491 if (arg_ptr)
492 {
493 *arg_ptr = (const spinel_eui64_t *)data_in;
494 }
495 }
496
497 ret += sizeof(spinel_eui64_t);
498 data_in += sizeof(spinel_eui64_t);
499 data_len -= sizeof(spinel_eui64_t);
500 break;
501 }
502
503 case SPINEL_DATATYPE_EUI48_C:
504 {
505 require_action(data_len >= sizeof(spinel_eui48_t), bail, (ret = -1, errno = EOVERFLOW));
506
507 if (in_place)
508 {
509 spinel_eui48_t *arg = va_arg(args->obj, spinel_eui48_t *);
510 if (arg)
511 {
512 memcpy(arg, data_in, sizeof(spinel_eui48_t));
513 }
514 }
515 else
516 {
517 const spinel_eui48_t **arg_ptr = va_arg(args->obj, const spinel_eui48_t **);
518 if (arg_ptr)
519 {
520 *arg_ptr = (const spinel_eui48_t *)data_in;
521 }
522 }
523
524 ret += sizeof(spinel_eui48_t);
525 data_in += sizeof(spinel_eui48_t);
526 data_len -= sizeof(spinel_eui48_t);
527 break;
528 }
529
530 case SPINEL_DATATYPE_UINT_PACKED_C:
531 {
532 unsigned int * arg_ptr = va_arg(args->obj, unsigned int *);
533 spinel_ssize_t pui_len = spinel_packed_uint_decode(data_in, data_len, arg_ptr);
534
535 // Range check
536 require_action(NULL == arg_ptr || (*arg_ptr < SPINEL_MAX_UINT_PACKED), bail, (ret = -1, errno = ERANGE));
537
538 require(pui_len > 0, bail);
539
540 require(pui_len <= (spinel_ssize_t)data_len, bail);
541
542 ret += pui_len;
543 data_in += pui_len;
544 data_len -= (spinel_size_t)pui_len;
545 break;
546 }
547
548 case SPINEL_DATATYPE_UTF8_C:
549 {
550 size_t len;
551
552 // Make sure we have at least one byte.
553 require_action(data_len > 0, bail, (ret = -1, errno = EOVERFLOW));
554
555 // Add 1 for zero termination. If not zero terminated,
556 // len will then be data_len+1, which we will detect
557 // in the next check.
558 len = spinel_strnlen((const char *)data_in, data_len) + 1;
559
560 // Verify that the string is zero terminated.
561 require_action(len <= data_len, bail, (ret = -1, errno = EOVERFLOW));
562
563 // Verify the string follows valid UTF8 encoding.
564 require_action(spinel_validate_utf8(data_in), bail, (ret = -1, errno = EINVAL));
565
566 if (in_place)
567 {
568 char * arg = va_arg(args->obj, char *);
569 size_t len_arg = va_arg(args->obj, size_t);
570 if (arg)
571 {
572 require_action(len_arg >= len, bail, (ret = -1, errno = ENOMEM));
573 memcpy(arg, data_in, len);
574 }
575 }
576 else
577 {
578 const char **arg_ptr = va_arg(args->obj, const char **);
579 if (arg_ptr)
580 {
581 *arg_ptr = (const char *)data_in;
582 }
583 }
584
585 ret += (spinel_size_t)len;
586 data_in += len;
587 data_len -= (spinel_size_t)len;
588 break;
589 }
590
591 case SPINEL_DATATYPE_DATA_C:
592 case SPINEL_DATATYPE_DATA_WLEN_C:
593 {
594 spinel_ssize_t pui_len = 0;
595 uint16_t block_len = 0;
596 const uint8_t *block_ptr = data_in;
597 void * arg_ptr = va_arg(args->obj, void *);
598 unsigned int * block_len_ptr = va_arg(args->obj, unsigned int *);
599 char nextformat = *spinel_next_packed_datatype(pack_format);
600
601 if ((pack_format[0] == SPINEL_DATATYPE_DATA_WLEN_C) || ((nextformat != 0) && (nextformat != ')')))
602 {
603 pui_len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
604 block_ptr += pui_len;
605
606 require(pui_len > 0, bail);
607 require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
608 }
609 else
610 {
611 block_len = (uint16_t)data_len;
612 pui_len = 0;
613 }
614
615 require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
616
617 if (in_place)
618 {
619 require_action(NULL != block_len_ptr && *block_len_ptr >= block_len, bail, (ret = -1, errno = EINVAL));
620 memcpy(arg_ptr, block_ptr, block_len);
621 }
622 else
623 {
624 const uint8_t **block_ptr_ptr = (const uint8_t **)arg_ptr;
625 if (NULL != block_ptr_ptr)
626 {
627 *block_ptr_ptr = block_ptr;
628 }
629 }
630
631 if (NULL != block_len_ptr)
632 {
633 *block_len_ptr = block_len;
634 }
635
636 block_len += (uint16_t)pui_len;
637 ret += block_len;
638 data_in += block_len;
639 data_len -= block_len;
640 break;
641 }
642
643 case 'T':
644 case SPINEL_DATATYPE_STRUCT_C:
645 {
646 spinel_ssize_t pui_len = 0;
647 uint16_t block_len = 0;
648 spinel_ssize_t actual_len = 0;
649 const uint8_t *block_ptr = data_in;
650 char nextformat = *spinel_next_packed_datatype(pack_format);
651
652 if ((pack_format[0] == SPINEL_DATATYPE_STRUCT_C) || ((nextformat != 0) && (nextformat != ')')))
653 {
654 pui_len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
655 block_ptr += pui_len;
656
657 require(pui_len > 0, bail);
658 require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
659 }
660 else
661 {
662 block_len = (uint16_t)data_len;
663 pui_len = 0;
664 }
665
666 require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
667
668 actual_len = spinel_datatype_vunpack_(false, block_ptr, block_len, pack_format + 2, args);
669
670 require_action(actual_len > -1, bail, (ret = -1, errno = EOVERFLOW));
671
672 if (pui_len)
673 {
674 block_len += (uint16_t)pui_len;
675 }
676 else
677 {
678 block_len = (uint16_t)actual_len;
679 }
680
681 ret += block_len;
682 data_in += block_len;
683 data_len -= block_len;
684 break;
685 }
686
687 case '.':
688 // Skip.
689 break;
690
691 case SPINEL_DATATYPE_ARRAY_C:
692 default:
693 // Unsupported Type!
694 ret = -1;
695 errno = EINVAL;
696 goto bail;
697 }
698 }
699
700 return ret;
701
702 bail:
703 return ret;
704 }
705
spinel_datatype_unpack_in_place(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,...)706 spinel_ssize_t spinel_datatype_unpack_in_place(const uint8_t *data_in,
707 spinel_size_t data_len,
708 const char * pack_format,
709 ...)
710 {
711 spinel_ssize_t ret;
712 va_list_obj args;
713 va_start(args.obj, pack_format);
714
715 ret = spinel_datatype_vunpack_(true, data_in, data_len, pack_format, &args);
716
717 va_end(args.obj);
718 return ret;
719 }
720
spinel_datatype_unpack(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,...)721 spinel_ssize_t spinel_datatype_unpack(const uint8_t *data_in, spinel_size_t data_len, const char *pack_format, ...)
722 {
723 spinel_ssize_t ret;
724 va_list_obj args;
725 va_start(args.obj, pack_format);
726
727 ret = spinel_datatype_vunpack_(false, data_in, data_len, pack_format, &args);
728
729 va_end(args.obj);
730 return ret;
731 }
732
spinel_datatype_vunpack_in_place(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list args)733 spinel_ssize_t spinel_datatype_vunpack_in_place(const uint8_t *data_in,
734 spinel_size_t data_len,
735 const char * pack_format,
736 va_list args)
737 {
738 spinel_ssize_t ret;
739 va_list_obj args_obj;
740 va_copy(args_obj.obj, args);
741
742 ret = spinel_datatype_vunpack_(true, data_in, data_len, pack_format, &args_obj);
743
744 va_end(args_obj.obj);
745 return ret;
746 }
747
spinel_datatype_vunpack(const uint8_t * data_in,spinel_size_t data_len,const char * pack_format,va_list args)748 spinel_ssize_t spinel_datatype_vunpack(const uint8_t *data_in,
749 spinel_size_t data_len,
750 const char * pack_format,
751 va_list args)
752 {
753 spinel_ssize_t ret;
754 va_list_obj args_obj;
755 va_copy(args_obj.obj, args);
756
757 ret = spinel_datatype_vunpack_(false, data_in, data_len, pack_format, &args_obj);
758
759 va_end(args_obj.obj);
760 return ret;
761 }
762
spinel_datatype_vpack_(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,va_list_obj * args)763 static spinel_ssize_t spinel_datatype_vpack_(uint8_t * data_out,
764 spinel_size_t data_len_max,
765 const char * pack_format,
766 va_list_obj * args)
767 {
768 spinel_ssize_t ret = 0;
769
770 // Buffer length sanity check
771 require_action(data_len_max <= SPINEL_MAX_PACK_LENGTH, bail, (ret = -1, errno = EINVAL));
772
773 if (data_out == NULL)
774 {
775 data_len_max = 0;
776 }
777
778 for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
779 {
780 if (*pack_format == ')')
781 {
782 // Don't go past the end of a struct.
783 break;
784 }
785
786 switch ((spinel_datatype_t)*pack_format)
787 {
788 case SPINEL_DATATYPE_BOOL_C:
789 {
790 bool arg = (bool)va_arg(args->obj, int);
791 ret += sizeof(uint8_t);
792
793 if (data_len_max >= sizeof(uint8_t))
794 {
795 data_out[0] = (arg != false);
796 data_out += sizeof(uint8_t);
797 data_len_max -= sizeof(uint8_t);
798 }
799 else
800 {
801 data_len_max = 0;
802 }
803
804 break;
805 }
806
807 case SPINEL_DATATYPE_INT8_C:
808 case SPINEL_DATATYPE_UINT8_C:
809 {
810 uint8_t arg = (uint8_t)va_arg(args->obj, int);
811 ret += sizeof(uint8_t);
812
813 if (data_len_max >= sizeof(uint8_t))
814 {
815 data_out[0] = arg;
816 data_out += sizeof(uint8_t);
817 data_len_max -= sizeof(uint8_t);
818 }
819 else
820 {
821 data_len_max = 0;
822 }
823
824 break;
825 }
826
827 case SPINEL_DATATYPE_INT16_C:
828 case SPINEL_DATATYPE_UINT16_C:
829 {
830 uint16_t arg = (uint16_t)va_arg(args->obj, int);
831 ret += sizeof(uint16_t);
832
833 if (data_len_max >= sizeof(uint16_t))
834 {
835 data_out[1] = (arg >> 8) & 0xff;
836 data_out[0] = (arg >> 0) & 0xff;
837 data_out += sizeof(uint16_t);
838 data_len_max -= sizeof(uint16_t);
839 }
840 else
841 {
842 data_len_max = 0;
843 }
844
845 break;
846 }
847
848 case SPINEL_DATATYPE_INT32_C:
849 case SPINEL_DATATYPE_UINT32_C:
850 {
851 uint32_t arg = (uint32_t)va_arg(args->obj, int);
852 ret += sizeof(uint32_t);
853
854 if (data_len_max >= sizeof(uint32_t))
855 {
856 data_out[3] = (arg >> 24) & 0xff;
857 data_out[2] = (arg >> 16) & 0xff;
858 data_out[1] = (arg >> 8) & 0xff;
859 data_out[0] = (arg >> 0) & 0xff;
860 data_out += sizeof(uint32_t);
861 data_len_max -= sizeof(uint32_t);
862 }
863 else
864 {
865 data_len_max = 0;
866 }
867
868 break;
869 }
870
871 case SPINEL_DATATYPE_INT64_C:
872 case SPINEL_DATATYPE_UINT64_C:
873 {
874 uint64_t arg = va_arg(args->obj, uint64_t);
875
876 ret += sizeof(uint64_t);
877
878 if (data_len_max >= sizeof(uint64_t))
879 {
880 data_out[7] = (arg >> 56) & 0xff;
881 data_out[6] = (arg >> 48) & 0xff;
882 data_out[5] = (arg >> 40) & 0xff;
883 data_out[4] = (arg >> 32) & 0xff;
884 data_out[3] = (arg >> 24) & 0xff;
885 data_out[2] = (arg >> 16) & 0xff;
886 data_out[1] = (arg >> 8) & 0xff;
887 data_out[0] = (arg >> 0) & 0xff;
888 data_out += sizeof(uint64_t);
889 data_len_max -= sizeof(uint64_t);
890 }
891 else
892 {
893 data_len_max = 0;
894 }
895
896 break;
897 }
898
899 case SPINEL_DATATYPE_IPv6ADDR_C:
900 {
901 spinel_ipv6addr_t *arg = va_arg(args->obj, spinel_ipv6addr_t *);
902 ret += sizeof(spinel_ipv6addr_t);
903
904 if (data_len_max >= sizeof(spinel_ipv6addr_t))
905 {
906 *(spinel_ipv6addr_t *)data_out = *arg;
907 data_out += sizeof(spinel_ipv6addr_t);
908 data_len_max -= sizeof(spinel_ipv6addr_t);
909 }
910 else
911 {
912 data_len_max = 0;
913 }
914
915 break;
916 }
917
918 case SPINEL_DATATYPE_EUI48_C:
919 {
920 spinel_eui48_t *arg = va_arg(args->obj, spinel_eui48_t *);
921 ret += sizeof(spinel_eui48_t);
922
923 if (data_len_max >= sizeof(spinel_eui48_t))
924 {
925 *(spinel_eui48_t *)data_out = *arg;
926 data_out += sizeof(spinel_eui48_t);
927 data_len_max -= sizeof(spinel_eui48_t);
928 }
929 else
930 {
931 data_len_max = 0;
932 }
933
934 break;
935 }
936
937 case SPINEL_DATATYPE_EUI64_C:
938 {
939 spinel_eui64_t *arg = va_arg(args->obj, spinel_eui64_t *);
940 ret += sizeof(spinel_eui64_t);
941
942 if (data_len_max >= sizeof(spinel_eui64_t))
943 {
944 *(spinel_eui64_t *)data_out = *arg;
945 data_out += sizeof(spinel_eui64_t);
946 data_len_max -= sizeof(spinel_eui64_t);
947 }
948 else
949 {
950 data_len_max = 0;
951 }
952
953 break;
954 }
955
956 case SPINEL_DATATYPE_UINT_PACKED_C:
957 {
958 uint32_t arg = va_arg(args->obj, uint32_t);
959 spinel_ssize_t encoded_size;
960
961 // Range Check
962 require_action(arg < SPINEL_MAX_UINT_PACKED, bail, {
963 ret = -1;
964 errno = EINVAL;
965 });
966
967 encoded_size = spinel_packed_uint_encode(data_out, data_len_max, arg);
968 ret += encoded_size;
969
970 if ((spinel_ssize_t)data_len_max >= encoded_size)
971 {
972 data_out += encoded_size;
973 data_len_max -= (spinel_size_t)encoded_size;
974 }
975 else
976 {
977 data_len_max = 0;
978 }
979
980 break;
981 }
982
983 case SPINEL_DATATYPE_UTF8_C:
984 {
985 const char *string_arg = va_arg(args->obj, const char *);
986 size_t string_arg_len = 0;
987
988 if (string_arg)
989 {
990 string_arg_len = strlen(string_arg) + 1;
991 }
992 else
993 {
994 string_arg = "";
995 string_arg_len = 1;
996 }
997
998 ret += (spinel_size_t)string_arg_len;
999
1000 if (data_len_max >= string_arg_len)
1001 {
1002 memcpy(data_out, string_arg, string_arg_len);
1003
1004 data_out += string_arg_len;
1005 data_len_max -= (spinel_size_t)string_arg_len;
1006 }
1007 else
1008 {
1009 data_len_max = 0;
1010 }
1011
1012 break;
1013 }
1014
1015 case SPINEL_DATATYPE_DATA_WLEN_C:
1016 case SPINEL_DATATYPE_DATA_C:
1017 {
1018 const uint8_t *arg = va_arg(args->obj, const uint8_t *);
1019 uint32_t data_size_arg = va_arg(args->obj, uint32_t);
1020 spinel_ssize_t size_len = 0;
1021 char nextformat = *spinel_next_packed_datatype(pack_format);
1022
1023 if ((pack_format[0] == SPINEL_DATATYPE_DATA_WLEN_C) || ((nextformat != 0) && (nextformat != ')')))
1024 {
1025 size_len = spinel_datatype_pack(data_out, data_len_max, SPINEL_DATATYPE_UINT16_S, data_size_arg);
1026 require_action(size_len > 0, bail, {
1027 ret = -1;
1028 errno = EINVAL;
1029 });
1030 }
1031
1032 ret += (spinel_size_t)size_len + data_size_arg;
1033
1034 if (data_len_max >= (spinel_size_t)size_len + data_size_arg)
1035 {
1036 data_out += size_len;
1037 data_len_max -= (spinel_size_t)size_len;
1038
1039 if (data_out && arg)
1040 {
1041 memcpy(data_out, arg, data_size_arg);
1042 }
1043
1044 data_out += data_size_arg;
1045 data_len_max -= data_size_arg;
1046 }
1047 else
1048 {
1049 data_len_max = 0;
1050 }
1051
1052 break;
1053 }
1054
1055 case 'T':
1056 case SPINEL_DATATYPE_STRUCT_C:
1057 {
1058 spinel_ssize_t struct_len = 0;
1059 spinel_ssize_t size_len = 0;
1060 char nextformat = *spinel_next_packed_datatype(pack_format);
1061
1062 require_action(pack_format[1] == '(', bail, {
1063 ret = -1;
1064 errno = EINVAL;
1065 });
1066
1067 // First we figure out the size of the struct
1068 {
1069 va_list_obj subargs;
1070 va_copy(subargs.obj, args->obj);
1071 struct_len = spinel_datatype_vpack_(NULL, 0, pack_format + 2, &subargs);
1072 va_end(subargs.obj);
1073 }
1074
1075 if ((pack_format[0] == SPINEL_DATATYPE_STRUCT_C) || ((nextformat != 0) && (nextformat != ')')))
1076 {
1077 size_len = spinel_datatype_pack(data_out, data_len_max, SPINEL_DATATYPE_UINT16_S, struct_len);
1078 require_action(size_len > 0, bail, {
1079 ret = -1;
1080 errno = EINVAL;
1081 });
1082 }
1083
1084 ret += size_len + struct_len;
1085
1086 if (struct_len + size_len <= (spinel_ssize_t)data_len_max)
1087 {
1088 data_out += size_len;
1089 data_len_max -= (spinel_size_t)size_len;
1090
1091 struct_len = spinel_datatype_vpack_(data_out, data_len_max, pack_format + 2, args);
1092
1093 data_out += struct_len;
1094 data_len_max -= (spinel_size_t)struct_len;
1095 }
1096 else
1097 {
1098 data_len_max = 0;
1099 }
1100
1101 break;
1102 }
1103
1104 case '.':
1105 // Skip.
1106 break;
1107
1108 default:
1109 // Unsupported Type!
1110 ret = -1;
1111 errno = EINVAL;
1112 goto bail;
1113 }
1114 }
1115
1116 bail:
1117 return ret;
1118 }
1119
spinel_datatype_pack(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,...)1120 spinel_ssize_t spinel_datatype_pack(uint8_t *data_out, spinel_size_t data_len_max, const char *pack_format, ...)
1121 {
1122 int ret;
1123 va_list_obj args;
1124 va_start(args.obj, pack_format);
1125
1126 ret = spinel_datatype_vpack_(data_out, data_len_max, pack_format, &args);
1127
1128 va_end(args.obj);
1129 return ret;
1130 }
1131
spinel_datatype_vpack(uint8_t * data_out,spinel_size_t data_len_max,const char * pack_format,va_list args)1132 spinel_ssize_t spinel_datatype_vpack(uint8_t * data_out,
1133 spinel_size_t data_len_max,
1134 const char * pack_format,
1135 va_list args)
1136 {
1137 int ret;
1138 va_list_obj args_obj;
1139 va_copy(args_obj.obj, args);
1140
1141 ret = spinel_datatype_vpack_(data_out, data_len_max, pack_format, &args_obj);
1142
1143 va_end(args_obj.obj);
1144 return ret;
1145 }
1146
1147 // ----------------------------------------------------------------------------
1148 // MARK: -
1149
1150 // LCOV_EXCL_START
1151
spinel_command_to_cstr(spinel_command_t command)1152 const char *spinel_command_to_cstr(spinel_command_t command)
1153 {
1154 const char *ret = "UNKNOWN";
1155
1156 switch (command)
1157 {
1158 case SPINEL_CMD_NOOP:
1159 ret = "NOOP";
1160 break;
1161
1162 case SPINEL_CMD_RESET:
1163 ret = "RESET";
1164 break;
1165
1166 case SPINEL_CMD_PROP_VALUE_GET:
1167 ret = "PROP_VALUE_GET";
1168 break;
1169
1170 case SPINEL_CMD_PROP_VALUE_SET:
1171 ret = "PROP_VALUE_SET";
1172 break;
1173
1174 case SPINEL_CMD_PROP_VALUE_INSERT:
1175 ret = "PROP_VALUE_INSERT";
1176 break;
1177
1178 case SPINEL_CMD_PROP_VALUE_REMOVE:
1179 ret = "PROP_VALUE_REMOVE";
1180 break;
1181
1182 case SPINEL_CMD_PROP_VALUE_IS:
1183 ret = "PROP_VALUE_IS";
1184 break;
1185
1186 case SPINEL_CMD_PROP_VALUE_INSERTED:
1187 ret = "PROP_VALUE_INSERTED";
1188 break;
1189
1190 case SPINEL_CMD_PROP_VALUE_REMOVED:
1191 ret = "PROP_VALUE_REMOVED";
1192 break;
1193
1194 case SPINEL_CMD_NET_SAVE:
1195 ret = "NET_SAVE";
1196 break;
1197
1198 case SPINEL_CMD_NET_CLEAR:
1199 ret = "NET_CLEAR";
1200 break;
1201
1202 case SPINEL_CMD_NET_RECALL:
1203 ret = "NET_RECALL";
1204 break;
1205
1206 case SPINEL_CMD_HBO_OFFLOAD:
1207 ret = "HBO_OFFLOAD";
1208 break;
1209
1210 case SPINEL_CMD_HBO_RECLAIM:
1211 ret = "HBO_RECLAIM";
1212 break;
1213
1214 case SPINEL_CMD_HBO_DROP:
1215 ret = "HBO_DROP";
1216 break;
1217
1218 case SPINEL_CMD_HBO_OFFLOADED:
1219 ret = "HBO_OFFLOADED";
1220 break;
1221
1222 case SPINEL_CMD_HBO_RECLAIMED:
1223 ret = "HBO_RECLAIMED";
1224 break;
1225
1226 case SPINEL_CMD_HBO_DROPPED:
1227 ret = "HBO_DROPPED";
1228 break;
1229
1230 case SPINEL_CMD_PEEK:
1231 ret = "PEEK";
1232 break;
1233
1234 case SPINEL_CMD_PEEK_RET:
1235 ret = "PEEK_RET";
1236 break;
1237
1238 case SPINEL_CMD_POKE:
1239 ret = "POKE";
1240 break;
1241
1242 case SPINEL_CMD_PROP_VALUE_MULTI_GET:
1243 ret = "PROP_VALUE_MULTI_GET";
1244 break;
1245
1246 case SPINEL_CMD_PROP_VALUE_MULTI_SET:
1247 ret = "PROP_VALUE_MULTI_SET";
1248 break;
1249
1250 case SPINEL_CMD_PROP_VALUES_ARE:
1251 ret = "PROP_VALUES_ARE";
1252 break;
1253
1254 default:
1255 break;
1256 }
1257
1258 return ret;
1259 }
1260
spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)1261 const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
1262 {
1263 const char *ret = "UNKNOWN";
1264
1265 switch (prop_key)
1266 {
1267 case SPINEL_PROP_LAST_STATUS:
1268 ret = "LAST_STATUS";
1269 break;
1270
1271 case SPINEL_PROP_PROTOCOL_VERSION:
1272 ret = "PROTOCOL_VERSION";
1273 break;
1274
1275 case SPINEL_PROP_NCP_VERSION:
1276 ret = "NCP_VERSION";
1277 break;
1278
1279 case SPINEL_PROP_INTERFACE_TYPE:
1280 ret = "INTERFACE_TYPE";
1281 break;
1282
1283 case SPINEL_PROP_VENDOR_ID:
1284 ret = "VENDOR_ID";
1285 break;
1286
1287 case SPINEL_PROP_CAPS:
1288 ret = "CAPS";
1289 break;
1290
1291 case SPINEL_PROP_INTERFACE_COUNT:
1292 ret = "INTERFACE_COUNT";
1293 break;
1294
1295 case SPINEL_PROP_POWER_STATE:
1296 ret = "POWER_STATE";
1297 break;
1298
1299 case SPINEL_PROP_HWADDR:
1300 ret = "HWADDR";
1301 break;
1302
1303 case SPINEL_PROP_LOCK:
1304 ret = "LOCK";
1305 break;
1306
1307 case SPINEL_PROP_HBO_MEM_MAX:
1308 ret = "HBO_MEM_MAX";
1309 break;
1310
1311 case SPINEL_PROP_HBO_BLOCK_MAX:
1312 ret = "HBO_BLOCK_MAX";
1313 break;
1314
1315 case SPINEL_PROP_HOST_POWER_STATE:
1316 ret = "HOST_POWER_STATE";
1317 break;
1318
1319 case SPINEL_PROP_MCU_POWER_STATE:
1320 ret = "MCU_POWER_STATE";
1321 break;
1322
1323 case SPINEL_PROP_GPIO_CONFIG:
1324 ret = "GPIO_CONFIG";
1325 break;
1326
1327 case SPINEL_PROP_GPIO_STATE:
1328 ret = "GPIO_STATE";
1329 break;
1330
1331 case SPINEL_PROP_GPIO_STATE_SET:
1332 ret = "GPIO_STATE_SET";
1333 break;
1334
1335 case SPINEL_PROP_GPIO_STATE_CLEAR:
1336 ret = "GPIO_STATE_CLEAR";
1337 break;
1338
1339 case SPINEL_PROP_TRNG_32:
1340 ret = "TRNG_32";
1341 break;
1342
1343 case SPINEL_PROP_TRNG_128:
1344 ret = "TRNG_128";
1345 break;
1346
1347 case SPINEL_PROP_TRNG_RAW_32:
1348 ret = "TRNG_RAW_32";
1349 break;
1350
1351 case SPINEL_PROP_UNSOL_UPDATE_FILTER:
1352 ret = "UNSOL_UPDATE_FILTER";
1353 break;
1354
1355 case SPINEL_PROP_UNSOL_UPDATE_LIST:
1356 ret = "UNSOL_UPDATE_LIST";
1357 break;
1358
1359 case SPINEL_PROP_PHY_ENABLED:
1360 ret = "PHY_ENABLED";
1361 break;
1362
1363 case SPINEL_PROP_PHY_CHAN:
1364 ret = "PHY_CHAN";
1365 break;
1366
1367 case SPINEL_PROP_PHY_CHAN_SUPPORTED:
1368 ret = "PHY_CHAN_SUPPORTED";
1369 break;
1370
1371 case SPINEL_PROP_PHY_FREQ:
1372 ret = "PHY_FREQ";
1373 break;
1374
1375 case SPINEL_PROP_PHY_CCA_THRESHOLD:
1376 ret = "PHY_CCA_THRESHOLD";
1377 break;
1378
1379 case SPINEL_PROP_PHY_TX_POWER:
1380 ret = "PHY_TX_POWER";
1381 break;
1382
1383 case SPINEL_PROP_PHY_RSSI:
1384 ret = "PHY_RSSI";
1385 break;
1386
1387 case SPINEL_PROP_PHY_RX_SENSITIVITY:
1388 ret = "PHY_RX_SENSITIVITY";
1389 break;
1390
1391 case SPINEL_PROP_PHY_PCAP_ENABLED:
1392 ret = "PHY_PCAP_ENABLED";
1393 break;
1394
1395 case SPINEL_PROP_PHY_CHAN_PREFERRED:
1396 ret = "PHY_CHAN_PREFERRED";
1397 break;
1398
1399 case SPINEL_PROP_JAM_DETECT_ENABLE:
1400 ret = "JAM_DETECT_ENABLE";
1401 break;
1402
1403 case SPINEL_PROP_JAM_DETECTED:
1404 ret = "JAM_DETECTED";
1405 break;
1406
1407 case SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD:
1408 ret = "JAM_DETECT_RSSI_THRESHOLD";
1409 break;
1410
1411 case SPINEL_PROP_JAM_DETECT_WINDOW:
1412 ret = "JAM_DETECT_WINDOW";
1413 break;
1414
1415 case SPINEL_PROP_JAM_DETECT_BUSY:
1416 ret = "JAM_DETECT_BUSY";
1417 break;
1418
1419 case SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP:
1420 ret = "JAM_DETECT_HISTORY_BITMAP";
1421 break;
1422
1423 case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL:
1424 ret = "CHANNEL_MONITOR_SAMPLE_INTERVAL";
1425 break;
1426
1427 case SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD:
1428 ret = "CHANNEL_MONITOR_RSSI_THRESHOLD";
1429 break;
1430
1431 case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW:
1432 ret = "CHANNEL_MONITOR_SAMPLE_WINDOW";
1433 break;
1434
1435 case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT:
1436 ret = "CHANNEL_MONITOR_SAMPLE_COUNT";
1437 break;
1438
1439 case SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY:
1440 ret = "CHANNEL_MONITOR_CHANNEL_OCCUPANCY";
1441 break;
1442
1443 case SPINEL_PROP_RADIO_CAPS:
1444 ret = "RADIO_CAPS";
1445 break;
1446
1447 case SPINEL_PROP_RADIO_COEX_METRICS:
1448 ret = "RADIO_COEX_METRICS";
1449 break;
1450
1451 case SPINEL_PROP_RADIO_COEX_ENABLE:
1452 ret = "RADIO_COEX_ENABLE";
1453 break;
1454
1455 case SPINEL_PROP_MAC_SCAN_STATE:
1456 ret = "MAC_SCAN_STATE";
1457 break;
1458
1459 case SPINEL_PROP_MAC_SCAN_MASK:
1460 ret = "MAC_SCAN_MASK";
1461 break;
1462
1463 case SPINEL_PROP_MAC_SCAN_PERIOD:
1464 ret = "MAC_SCAN_PERIOD";
1465 break;
1466
1467 case SPINEL_PROP_MAC_SCAN_BEACON:
1468 ret = "MAC_SCAN_BEACON";
1469 break;
1470
1471 case SPINEL_PROP_MAC_15_4_LADDR:
1472 ret = "MAC_15_4_LADDR";
1473 break;
1474
1475 case SPINEL_PROP_MAC_15_4_SADDR:
1476 ret = "MAC_15_4_SADDR";
1477 break;
1478
1479 case SPINEL_PROP_MAC_15_4_PANID:
1480 ret = "MAC_15_4_PANID";
1481 break;
1482
1483 case SPINEL_PROP_MAC_RAW_STREAM_ENABLED:
1484 ret = "MAC_RAW_STREAM_ENABLED";
1485 break;
1486
1487 case SPINEL_PROP_MAC_PROMISCUOUS_MODE:
1488 ret = "MAC_PROMISCUOUS_MODE";
1489 break;
1490
1491 case SPINEL_PROP_MAC_ENERGY_SCAN_RESULT:
1492 ret = "MAC_ENERGY_SCAN_RESULT";
1493 break;
1494
1495 case SPINEL_PROP_MAC_DATA_POLL_PERIOD:
1496 ret = "MAC_DATA_POLL_PERIOD";
1497 break;
1498
1499 case SPINEL_PROP_MAC_WHITELIST:
1500 ret = "MAC_WHITELIST";
1501 break;
1502
1503 case SPINEL_PROP_MAC_WHITELIST_ENABLED:
1504 ret = "MAC_WHITELIST_ENABLED";
1505 break;
1506
1507 case SPINEL_PROP_MAC_EXTENDED_ADDR:
1508 ret = "MAC_EXTENDED_ADDR";
1509 break;
1510
1511 case SPINEL_PROP_MAC_SRC_MATCH_ENABLED:
1512 ret = "MAC_SRC_MATCH_ENABLED";
1513 break;
1514
1515 case SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES:
1516 ret = "MAC_SRC_MATCH_SHORT_ADDRESSES";
1517 break;
1518
1519 case SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES:
1520 ret = "MAC_SRC_MATCH_EXTENDED_ADDRESSES";
1521 break;
1522
1523 case SPINEL_PROP_MAC_BLACKLIST:
1524 ret = "MAC_BLACKLIST";
1525 break;
1526
1527 case SPINEL_PROP_MAC_BLACKLIST_ENABLED:
1528 ret = "MAC_BLACKLIST_ENABLED";
1529 break;
1530
1531 case SPINEL_PROP_MAC_FIXED_RSS:
1532 ret = "MAC_FIXED_RSS";
1533 break;
1534
1535 case SPINEL_PROP_MAC_CCA_FAILURE_RATE:
1536 ret = "MAC_CCA_FAILURE_RATE";
1537 break;
1538
1539 case SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT:
1540 ret = "MAC_MAX_RETRY_NUMBER_DIRECT";
1541 break;
1542
1543 case SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT:
1544 ret = "MAC_MAX_RETRY_NUMBER_INDIRECT";
1545 break;
1546
1547 case SPINEL_PROP_NET_SAVED:
1548 ret = "NET_SAVED";
1549 break;
1550
1551 case SPINEL_PROP_NET_IF_UP:
1552 ret = "NET_IF_UP";
1553 break;
1554
1555 case SPINEL_PROP_NET_STACK_UP:
1556 ret = "NET_STACK_UP";
1557 break;
1558
1559 case SPINEL_PROP_NET_ROLE:
1560 ret = "NET_ROLE";
1561 break;
1562
1563 case SPINEL_PROP_NET_NETWORK_NAME:
1564 ret = "NET_NETWORK_NAME";
1565 break;
1566
1567 case SPINEL_PROP_NET_XPANID:
1568 ret = "NET_XPANID";
1569 break;
1570
1571 case SPINEL_PROP_NET_MASTER_KEY:
1572 ret = "NET_MASTER_KEY";
1573 break;
1574
1575 case SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER:
1576 ret = "NET_KEY_SEQUENCE_COUNTER";
1577 break;
1578
1579 case SPINEL_PROP_NET_PARTITION_ID:
1580 ret = "NET_PARTITION_ID";
1581 break;
1582
1583 case SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING:
1584 ret = "NET_REQUIRE_JOIN_EXISTING";
1585 break;
1586
1587 case SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME:
1588 ret = "NET_KEY_SWITCH_GUARDTIME";
1589 break;
1590
1591 case SPINEL_PROP_NET_PSKC:
1592 ret = "NET_PSKC";
1593 break;
1594
1595 case SPINEL_PROP_THREAD_LEADER_ADDR:
1596 ret = "THREAD_LEADER_ADDR";
1597 break;
1598
1599 case SPINEL_PROP_THREAD_PARENT:
1600 ret = "THREAD_PARENT";
1601 break;
1602
1603 case SPINEL_PROP_THREAD_CHILD_TABLE:
1604 ret = "THREAD_CHILD_TABLE";
1605 break;
1606
1607 case SPINEL_PROP_THREAD_LEADER_RID:
1608 ret = "THREAD_LEADER_RID";
1609 break;
1610
1611 case SPINEL_PROP_THREAD_LEADER_WEIGHT:
1612 ret = "THREAD_LEADER_WEIGHT";
1613 break;
1614
1615 case SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT:
1616 ret = "THREAD_LOCAL_LEADER_WEIGHT";
1617 break;
1618
1619 case SPINEL_PROP_THREAD_NETWORK_DATA:
1620 ret = "THREAD_NETWORK_DATA";
1621 break;
1622
1623 case SPINEL_PROP_THREAD_NETWORK_DATA_VERSION:
1624 ret = "THREAD_NETWORK_DATA_VERSION";
1625 break;
1626
1627 case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA:
1628 ret = "THREAD_STABLE_NETWORK_DATA";
1629 break;
1630
1631 case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION:
1632 ret = "THREAD_STABLE_NETWORK_DATA_VERSION";
1633 break;
1634
1635 case SPINEL_PROP_THREAD_ON_MESH_NETS:
1636 ret = "THREAD_ON_MESH_NETS";
1637 break;
1638
1639 case SPINEL_PROP_THREAD_OFF_MESH_ROUTES:
1640 ret = "THREAD_OFF_MESH_ROUTES";
1641 break;
1642
1643 case SPINEL_PROP_THREAD_ASSISTING_PORTS:
1644 ret = "THREAD_ASSISTING_PORTS";
1645 break;
1646
1647 case SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE:
1648 ret = "THREAD_ALLOW_LOCAL_NET_DATA_CHANGE";
1649 break;
1650
1651 case SPINEL_PROP_THREAD_MODE:
1652 ret = "THREAD_MODE";
1653 break;
1654
1655 case SPINEL_PROP_THREAD_CHILD_TIMEOUT:
1656 ret = "THREAD_CHILD_TIMEOUT";
1657 break;
1658
1659 case SPINEL_PROP_THREAD_RLOC16:
1660 ret = "THREAD_RLOC16";
1661 break;
1662
1663 case SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD:
1664 ret = "THREAD_ROUTER_UPGRADE_THRESHOLD";
1665 break;
1666
1667 case SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY:
1668 ret = "THREAD_CONTEXT_REUSE_DELAY";
1669 break;
1670
1671 case SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT:
1672 ret = "THREAD_NETWORK_ID_TIMEOUT";
1673 break;
1674
1675 case SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS:
1676 ret = "THREAD_ACTIVE_ROUTER_IDS";
1677 break;
1678
1679 case SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU:
1680 ret = "THREAD_RLOC16_DEBUG_PASSTHRU";
1681 break;
1682
1683 case SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED:
1684 ret = "THREAD_ROUTER_ROLE_ENABLED";
1685 break;
1686
1687 case SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD:
1688 ret = "THREAD_ROUTER_DOWNGRADE_THRESHOLD";
1689 break;
1690
1691 case SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER:
1692 ret = "THREAD_ROUTER_SELECTION_JITTER";
1693 break;
1694
1695 case SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID:
1696 ret = "THREAD_PREFERRED_ROUTER_ID";
1697 break;
1698
1699 case SPINEL_PROP_THREAD_NEIGHBOR_TABLE:
1700 ret = "THREAD_NEIGHBOR_TABLE";
1701 break;
1702
1703 case SPINEL_PROP_THREAD_CHILD_COUNT_MAX:
1704 ret = "THREAD_CHILD_COUNT_MAX";
1705 break;
1706
1707 case SPINEL_PROP_THREAD_LEADER_NETWORK_DATA:
1708 ret = "THREAD_LEADER_NETWORK_DATA";
1709 break;
1710
1711 case SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA:
1712 ret = "THREAD_STABLE_LEADER_NETWORK_DATA";
1713 break;
1714
1715 case SPINEL_PROP_THREAD_JOINERS:
1716 ret = "THREAD_JOINERS";
1717 break;
1718
1719 case SPINEL_PROP_THREAD_COMMISSIONER_ENABLED:
1720 ret = "THREAD_COMMISSIONER_ENABLED";
1721 break;
1722
1723 case SPINEL_PROP_THREAD_TMF_PROXY_ENABLED:
1724 ret = "THREAD_TMF_PROXY_ENABLED";
1725 break;
1726
1727 case SPINEL_PROP_THREAD_TMF_PROXY_STREAM:
1728 ret = "THREAD_TMF_PROXY_STREAM";
1729 break;
1730
1731 case SPINEL_PROP_THREAD_UDP_FORWARD_STREAM:
1732 ret = "THREAD_UDP_FORWARD_STREAM";
1733 break;
1734
1735 case SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG:
1736 ret = "THREAD_DISCOVERY_SCAN_JOINER_FLAG";
1737 break;
1738
1739 case SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING:
1740 ret = "THREAD_DISCOVERY_SCAN_ENABLE_FILTERING";
1741 break;
1742
1743 case SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID:
1744 ret = "THREAD_DISCOVERY_SCAN_PANID";
1745 break;
1746
1747 case SPINEL_PROP_THREAD_STEERING_DATA:
1748 ret = "THREAD_STEERING_DATA";
1749 break;
1750
1751 case SPINEL_PROP_THREAD_ROUTER_TABLE:
1752 ret = "THREAD_ROUTER_TABLE";
1753 break;
1754
1755 case SPINEL_PROP_THREAD_ACTIVE_DATASET:
1756 ret = "THREAD_ACTIVE_DATASET";
1757 break;
1758
1759 case SPINEL_PROP_THREAD_PENDING_DATASET:
1760 ret = "THREAD_PENDING_DATASET";
1761 break;
1762
1763 case SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET:
1764 ret = "THREAD_MGMT_SET_ACTIVE_DATASET";
1765 break;
1766
1767 case SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET:
1768 ret = "THREAD_MGMT_SET_PENDING_DATASET";
1769 break;
1770
1771 case SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP:
1772 ret = "DATASET_ACTIVE_TIMESTAMP";
1773 break;
1774
1775 case SPINEL_PROP_DATASET_PENDING_TIMESTAMP:
1776 ret = "DATASET_PENDING_TIMESTAMP";
1777 break;
1778
1779 case SPINEL_PROP_DATASET_DELAY_TIMER:
1780 ret = "DATASET_DELAY_TIMER";
1781 break;
1782
1783 case SPINEL_PROP_DATASET_SECURITY_POLICY:
1784 ret = "DATASET_SECURITY_POLICY";
1785 break;
1786
1787 case SPINEL_PROP_DATASET_RAW_TLVS:
1788 ret = "DATASET_RAW_TLVS";
1789 break;
1790
1791 case SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES:
1792 ret = "THREAD_CHILD_TABLE_ADDRESSES";
1793 break;
1794
1795 case SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES:
1796 ret = "THREAD_NEIGHBOR_TABLE_ERROR_RATES";
1797 break;
1798
1799 case SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE:
1800 ret = "THREAD_ADDRESS_CACHE_TABLE";
1801 break;
1802
1803 case SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET:
1804 ret = "THREAD_MGMT_GET_ACTIVE_DATASET";
1805 break;
1806
1807 case SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET:
1808 ret = "THREAD_MGMT_GET_PENDING_DATASET";
1809 break;
1810
1811 case SPINEL_PROP_DATASET_DEST_ADDRESS:
1812 ret = "DATASET_DEST_ADDRESS";
1813 break;
1814
1815 case SPINEL_PROP_THREAD_NEW_DATASET:
1816 ret = "THREAD_NEW_DATASET";
1817 break;
1818
1819 case SPINEL_PROP_MESHCOP_JOINER_STATE:
1820 ret = "MESHCOP_JOINER_STATE";
1821 break;
1822
1823 case SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING:
1824 ret = "MESHCOP_JOINER_COMMISSIONING";
1825 break;
1826
1827 case SPINEL_PROP_IPV6_LL_ADDR:
1828 ret = "IPV6_LL_ADDR";
1829 break;
1830
1831 case SPINEL_PROP_IPV6_ML_ADDR:
1832 ret = "IPV6_ML_ADDR";
1833 break;
1834
1835 case SPINEL_PROP_IPV6_ML_PREFIX:
1836 ret = "IPV6_ML_PREFIX";
1837 break;
1838
1839 case SPINEL_PROP_IPV6_ADDRESS_TABLE:
1840 ret = "IPV6_ADDRESS_TABLE";
1841 break;
1842
1843 case SPINEL_PROP_IPV6_ROUTE_TABLE:
1844 ret = "IPV6_ROUTE_TABLE";
1845 break;
1846
1847 case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD:
1848 ret = "IPV6_ICMP_PING_OFFLOAD";
1849 break;
1850
1851 case SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE:
1852 ret = "IPV6_MULTICAST_ADDRESS_TABLE";
1853 break;
1854
1855 case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE:
1856 ret = "IPV6_ICMP_PING_OFFLOAD_MODE";
1857 break;
1858
1859 case SPINEL_PROP_STREAM_DEBUG:
1860 ret = "STREAM_DEBUG";
1861 break;
1862
1863 case SPINEL_PROP_STREAM_RAW:
1864 ret = "STREAM_RAW";
1865 break;
1866
1867 case SPINEL_PROP_STREAM_NET:
1868 ret = "STREAM_NET";
1869 break;
1870
1871 case SPINEL_PROP_STREAM_NET_INSECURE:
1872 ret = "STREAM_NET_INSECURE";
1873 break;
1874
1875 case SPINEL_PROP_STREAM_LOG:
1876 ret = "STREAM_LOG";
1877 break;
1878
1879 case SPINEL_PROP_MESHCOP_COMMISSIONER_STATE:
1880 ret = "MESHCOP_COMMISSIONER_STATE";
1881 break;
1882
1883 case SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS:
1884 ret = "MESHCOP_COMMISSIONER_JOINERS";
1885 break;
1886
1887 case SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL:
1888 ret = "MESHCOP_COMMISSIONER_PROVISIONING_URL";
1889 break;
1890
1891 case SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID:
1892 ret = "MESHCOP_COMMISSIONER_SESSION_ID";
1893 break;
1894
1895 case SPINEL_PROP_MESHCOP_JOINER_DISCERNER:
1896 ret = "MESHCOP_JOINER_DISCERNER";
1897 break;
1898
1899 case SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN:
1900 ret = "MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN";
1901 break;
1902
1903 case SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN:
1904 ret = "MESHCOP_COMMISSIONER_ENERGY_SCAN";
1905 break;
1906
1907 case SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT:
1908 ret = "MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT";
1909 break;
1910
1911 case SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_QUERY:
1912 ret = "MESHCOP_COMMISSIONER_PAN_ID_QUERY";
1913 break;
1914
1915 case SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT:
1916 ret = "MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT";
1917 break;
1918
1919 case SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET:
1920 ret = "MESHCOP_COMMISSIONER_MGMT_GET";
1921 break;
1922
1923 case SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET:
1924 ret = "MESHCOP_COMMISSIONER_MGMT_SET";
1925 break;
1926
1927 case SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC:
1928 ret = "MESHCOP_COMMISSIONER_GENERATE_PSKC";
1929 break;
1930
1931 case SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL:
1932 ret = "CHANNEL_MANAGER_NEW_CHANNEL";
1933 break;
1934
1935 case SPINEL_PROP_CHANNEL_MANAGER_DELAY:
1936 ret = "CHANNEL_MANAGER_DELAY";
1937 break;
1938
1939 case SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS:
1940 ret = "CHANNEL_MANAGER_SUPPORTED_CHANNELS";
1941 break;
1942
1943 case SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS:
1944 ret = "CHANNEL_MANAGER_FAVORED_CHANNELS";
1945 break;
1946
1947 case SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT:
1948 ret = "CHANNEL_MANAGER_CHANNEL_SELECT";
1949 break;
1950
1951 case SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED:
1952 ret = "CHANNEL_MANAGER_AUTO_SELECT_ENABLED";
1953 break;
1954
1955 case SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL:
1956 ret = "CHANNEL_MANAGER_AUTO_SELECT_INTERVAL";
1957 break;
1958
1959 case SPINEL_PROP_THREAD_NETWORK_TIME:
1960 ret = "THREAD_NETWORK_TIME";
1961 break;
1962
1963 case SPINEL_PROP_TIME_SYNC_PERIOD:
1964 ret = "TIME_SYNC_PERIOD";
1965 break;
1966
1967 case SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD:
1968 ret = "TIME_SYNC_XTAL_THRESHOLD";
1969 break;
1970
1971 case SPINEL_PROP_CHILD_SUPERVISION_INTERVAL:
1972 ret = "CHILD_SUPERVISION_INTERVAL";
1973 break;
1974
1975 case SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT:
1976 ret = "CHILD_SUPERVISION_CHECK_TIMEOUT";
1977 break;
1978
1979 case SPINEL_PROP_RCP_VERSION:
1980 ret = "RCP_VERSION";
1981 break;
1982
1983 case SPINEL_PROP_PARENT_RESPONSE_INFO:
1984 ret = "PARENT_RESPONSE_INFO";
1985 break;
1986
1987 case SPINEL_PROP_SLAAC_ENABLED:
1988 ret = "SLAAC_ENABLED";
1989 break;
1990
1991 case SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE:
1992 ret = "SERVER_ALLOW_LOCAL_DATA_CHANGE";
1993 break;
1994
1995 case SPINEL_PROP_SERVER_SERVICES:
1996 ret = "SERVER_SERVICES";
1997 break;
1998
1999 case SPINEL_PROP_SERVER_LEADER_SERVICES:
2000 ret = "SERVER_LEADER_SERVICES";
2001 break;
2002
2003 case SPINEL_PROP_UART_BITRATE:
2004 ret = "UART_BITRATE";
2005 break;
2006
2007 case SPINEL_PROP_UART_XON_XOFF:
2008 ret = "UART_XON_XOFF";
2009 break;
2010
2011 case SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED:
2012 ret = "15_4_PIB_PHY_CHANNELS_SUPPORTED";
2013 break;
2014
2015 case SPINEL_PROP_15_4_PIB_MAC_PROMISCUOUS_MODE:
2016 ret = "15_4_PIB_MAC_PROMISCUOUS_MODE";
2017 break;
2018
2019 case SPINEL_PROP_15_4_PIB_MAC_SECURITY_ENABLED:
2020 ret = "15_4_PIB_MAC_SECURITY_ENABLED";
2021 break;
2022
2023 case SPINEL_PROP_CNTR_RESET:
2024 ret = "CNTR_RESET";
2025 break;
2026
2027 case SPINEL_PROP_CNTR_TX_PKT_TOTAL:
2028 ret = "CNTR_TX_PKT_TOTAL";
2029 break;
2030
2031 case SPINEL_PROP_CNTR_TX_PKT_ACK_REQ:
2032 ret = "CNTR_TX_PKT_ACK_REQ";
2033 break;
2034
2035 case SPINEL_PROP_CNTR_TX_PKT_ACKED:
2036 ret = "CNTR_TX_PKT_ACKED";
2037 break;
2038
2039 case SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ:
2040 ret = "CNTR_TX_PKT_NO_ACK_REQ";
2041 break;
2042
2043 case SPINEL_PROP_CNTR_TX_PKT_DATA:
2044 ret = "CNTR_TX_PKT_DATA";
2045 break;
2046
2047 case SPINEL_PROP_CNTR_TX_PKT_DATA_POLL:
2048 ret = "CNTR_TX_PKT_DATA_POLL";
2049 break;
2050
2051 case SPINEL_PROP_CNTR_TX_PKT_BEACON:
2052 ret = "CNTR_TX_PKT_BEACON";
2053 break;
2054
2055 case SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ:
2056 ret = "CNTR_TX_PKT_BEACON_REQ";
2057 break;
2058
2059 case SPINEL_PROP_CNTR_TX_PKT_OTHER:
2060 ret = "CNTR_TX_PKT_OTHER";
2061 break;
2062
2063 case SPINEL_PROP_CNTR_TX_PKT_RETRY:
2064 ret = "CNTR_TX_PKT_RETRY";
2065 break;
2066
2067 case SPINEL_PROP_CNTR_TX_ERR_CCA:
2068 ret = "CNTR_TX_ERR_CCA";
2069 break;
2070
2071 case SPINEL_PROP_CNTR_TX_PKT_UNICAST:
2072 ret = "CNTR_TX_PKT_UNICAST";
2073 break;
2074
2075 case SPINEL_PROP_CNTR_TX_PKT_BROADCAST:
2076 ret = "CNTR_TX_PKT_BROADCAST";
2077 break;
2078
2079 case SPINEL_PROP_CNTR_TX_ERR_ABORT:
2080 ret = "CNTR_TX_ERR_ABORT";
2081 break;
2082
2083 case SPINEL_PROP_CNTR_RX_PKT_TOTAL:
2084 ret = "CNTR_RX_PKT_TOTAL";
2085 break;
2086
2087 case SPINEL_PROP_CNTR_RX_PKT_DATA:
2088 ret = "CNTR_RX_PKT_DATA";
2089 break;
2090
2091 case SPINEL_PROP_CNTR_RX_PKT_DATA_POLL:
2092 ret = "CNTR_RX_PKT_DATA_POLL";
2093 break;
2094
2095 case SPINEL_PROP_CNTR_RX_PKT_BEACON:
2096 ret = "CNTR_RX_PKT_BEACON";
2097 break;
2098
2099 case SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ:
2100 ret = "CNTR_RX_PKT_BEACON_REQ";
2101 break;
2102
2103 case SPINEL_PROP_CNTR_RX_PKT_OTHER:
2104 ret = "CNTR_RX_PKT_OTHER";
2105 break;
2106
2107 case SPINEL_PROP_CNTR_RX_PKT_FILT_WL:
2108 ret = "CNTR_RX_PKT_FILT_WL";
2109 break;
2110
2111 case SPINEL_PROP_CNTR_RX_PKT_FILT_DA:
2112 ret = "CNTR_RX_PKT_FILT_DA";
2113 break;
2114
2115 case SPINEL_PROP_CNTR_RX_ERR_EMPTY:
2116 ret = "CNTR_RX_ERR_EMPTY";
2117 break;
2118
2119 case SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR:
2120 ret = "CNTR_RX_ERR_UKWN_NBR";
2121 break;
2122
2123 case SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR:
2124 ret = "CNTR_RX_ERR_NVLD_SADDR";
2125 break;
2126
2127 case SPINEL_PROP_CNTR_RX_ERR_SECURITY:
2128 ret = "CNTR_RX_ERR_SECURITY";
2129 break;
2130
2131 case SPINEL_PROP_CNTR_RX_ERR_BAD_FCS:
2132 ret = "CNTR_RX_ERR_BAD_FCS";
2133 break;
2134
2135 case SPINEL_PROP_CNTR_RX_ERR_OTHER:
2136 ret = "CNTR_RX_ERR_OTHER";
2137 break;
2138
2139 case SPINEL_PROP_CNTR_RX_PKT_DUP:
2140 ret = "CNTR_RX_PKT_DUP";
2141 break;
2142
2143 case SPINEL_PROP_CNTR_RX_PKT_UNICAST:
2144 ret = "CNTR_RX_PKT_UNICAST";
2145 break;
2146
2147 case SPINEL_PROP_CNTR_RX_PKT_BROADCAST:
2148 ret = "CNTR_RX_PKT_BROADCAST";
2149 break;
2150
2151 case SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL:
2152 ret = "CNTR_TX_IP_SEC_TOTAL";
2153 break;
2154
2155 case SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL:
2156 ret = "CNTR_TX_IP_INSEC_TOTAL";
2157 break;
2158
2159 case SPINEL_PROP_CNTR_TX_IP_DROPPED:
2160 ret = "CNTR_TX_IP_DROPPED";
2161 break;
2162
2163 case SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL:
2164 ret = "CNTR_RX_IP_SEC_TOTAL";
2165 break;
2166
2167 case SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL:
2168 ret = "CNTR_RX_IP_INSEC_TOTAL";
2169 break;
2170
2171 case SPINEL_PROP_CNTR_RX_IP_DROPPED:
2172 ret = "CNTR_RX_IP_DROPPED";
2173 break;
2174
2175 case SPINEL_PROP_CNTR_TX_SPINEL_TOTAL:
2176 ret = "CNTR_TX_SPINEL_TOTAL";
2177 break;
2178
2179 case SPINEL_PROP_CNTR_RX_SPINEL_TOTAL:
2180 ret = "CNTR_RX_SPINEL_TOTAL";
2181 break;
2182
2183 case SPINEL_PROP_CNTR_RX_SPINEL_ERR:
2184 ret = "CNTR_RX_SPINEL_ERR";
2185 break;
2186
2187 case SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID:
2188 ret = "CNTR_RX_SPINEL_OUT_OF_ORDER_TID";
2189 break;
2190
2191 case SPINEL_PROP_CNTR_IP_TX_SUCCESS:
2192 ret = "CNTR_IP_TX_SUCCESS";
2193 break;
2194
2195 case SPINEL_PROP_CNTR_IP_RX_SUCCESS:
2196 ret = "CNTR_IP_RX_SUCCESS";
2197 break;
2198
2199 case SPINEL_PROP_CNTR_IP_TX_FAILURE:
2200 ret = "CNTR_IP_TX_FAILURE";
2201 break;
2202
2203 case SPINEL_PROP_CNTR_IP_RX_FAILURE:
2204 ret = "CNTR_IP_RX_FAILURE";
2205 break;
2206
2207 case SPINEL_PROP_MSG_BUFFER_COUNTERS:
2208 ret = "MSG_BUFFER_COUNTERS";
2209 break;
2210
2211 case SPINEL_PROP_CNTR_ALL_MAC_COUNTERS:
2212 ret = "CNTR_ALL_MAC_COUNTERS";
2213 break;
2214
2215 case SPINEL_PROP_CNTR_MLE_COUNTERS:
2216 ret = "CNTR_MLE_COUNTERS";
2217 break;
2218
2219 case SPINEL_PROP_CNTR_ALL_IP_COUNTERS:
2220 ret = "CNTR_ALL_IP_COUNTERS";
2221 break;
2222
2223 case SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM:
2224 ret = "CNTR_MAC_RETRY_HISTOGRAM";
2225 break;
2226
2227 case SPINEL_PROP_NEST_STREAM_MFG:
2228 ret = "NEST_STREAM_MFG";
2229 break;
2230
2231 case SPINEL_PROP_NEST_LEGACY_ULA_PREFIX:
2232 ret = "NEST_LEGACY_ULA_PREFIX";
2233 break;
2234
2235 case SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED:
2236 ret = "NEST_LEGACY_LAST_NODE_JOINED";
2237 break;
2238
2239 case SPINEL_PROP_DEBUG_TEST_ASSERT:
2240 ret = "DEBUG_TEST_ASSERT";
2241 break;
2242
2243 case SPINEL_PROP_DEBUG_NCP_LOG_LEVEL:
2244 ret = "DEBUG_NCP_LOG_LEVEL";
2245 break;
2246
2247 case SPINEL_PROP_DEBUG_TEST_WATCHDOG:
2248 ret = "DEBUG_TEST_WATCHDOG";
2249 break;
2250
2251 default:
2252 break;
2253 }
2254
2255 return ret;
2256 }
2257
spinel_net_role_to_cstr(uint8_t net_role)2258 const char *spinel_net_role_to_cstr(uint8_t net_role)
2259 {
2260 const char *ret = "NET_ROLE_UNKNOWN";
2261
2262 switch (net_role)
2263 {
2264 case SPINEL_NET_ROLE_DETACHED:
2265 ret = "NET_ROLE_DETACHED";
2266 break;
2267
2268 case SPINEL_NET_ROLE_CHILD:
2269 ret = "NET_ROLE_CHILD";
2270 break;
2271
2272 case SPINEL_NET_ROLE_ROUTER:
2273 ret = "NET_ROLE_ROUTER";
2274 break;
2275
2276 case SPINEL_NET_ROLE_LEADER:
2277 ret = "NET_ROLE_LEADER";
2278 break;
2279
2280 default:
2281 break;
2282 }
2283
2284 return ret;
2285 }
2286
spinel_mcu_power_state_to_cstr(uint8_t mcu_power_state)2287 const char *spinel_mcu_power_state_to_cstr(uint8_t mcu_power_state)
2288 {
2289 const char *ret = "MCU_POWER_STATE_UNKNOWN";
2290
2291 switch (mcu_power_state)
2292 {
2293 case SPINEL_MCU_POWER_STATE_ON:
2294 ret = "MCU_POWER_STATE_ON";
2295 break;
2296
2297 case SPINEL_MCU_POWER_STATE_LOW_POWER:
2298 ret = "MCU_POWER_STATE_LOW_POWER";
2299 break;
2300
2301 case SPINEL_MCU_POWER_STATE_OFF:
2302 ret = "MCU_POWER_STATE_OFF";
2303 break;
2304
2305 default:
2306 break;
2307 }
2308
2309 return ret;
2310 }
2311
spinel_status_to_cstr(spinel_status_t status)2312 const char *spinel_status_to_cstr(spinel_status_t status)
2313 {
2314 const char *ret = "UNKNOWN";
2315
2316 switch (status)
2317 {
2318 case SPINEL_STATUS_OK:
2319 ret = "OK";
2320 break;
2321
2322 case SPINEL_STATUS_FAILURE:
2323 ret = "FAILURE";
2324 break;
2325
2326 case SPINEL_STATUS_UNIMPLEMENTED:
2327 ret = "UNIMPLEMENTED";
2328 break;
2329
2330 case SPINEL_STATUS_INVALID_ARGUMENT:
2331 ret = "INVALID_ARGUMENT";
2332 break;
2333
2334 case SPINEL_STATUS_INVALID_STATE:
2335 ret = "INVALID_STATE";
2336 break;
2337
2338 case SPINEL_STATUS_INVALID_COMMAND:
2339 ret = "INVALID_COMMAND";
2340 break;
2341
2342 case SPINEL_STATUS_INVALID_INTERFACE:
2343 ret = "INVALID_INTERFACE";
2344 break;
2345
2346 case SPINEL_STATUS_INTERNAL_ERROR:
2347 ret = "INTERNAL_ERROR";
2348 break;
2349
2350 case SPINEL_STATUS_SECURITY_ERROR:
2351 ret = "SECURITY_ERROR";
2352 break;
2353
2354 case SPINEL_STATUS_PARSE_ERROR:
2355 ret = "PARSE_ERROR";
2356 break;
2357
2358 case SPINEL_STATUS_IN_PROGRESS:
2359 ret = "IN_PROGRESS";
2360 break;
2361
2362 case SPINEL_STATUS_NOMEM:
2363 ret = "NOMEM";
2364 break;
2365
2366 case SPINEL_STATUS_BUSY:
2367 ret = "BUSY";
2368 break;
2369
2370 case SPINEL_STATUS_PROP_NOT_FOUND:
2371 ret = "PROP_NOT_FOUND";
2372 break;
2373
2374 case SPINEL_STATUS_DROPPED:
2375 ret = "DROPPED";
2376 break;
2377
2378 case SPINEL_STATUS_EMPTY:
2379 ret = "EMPTY";
2380 break;
2381
2382 case SPINEL_STATUS_CMD_TOO_BIG:
2383 ret = "CMD_TOO_BIG";
2384 break;
2385
2386 case SPINEL_STATUS_NO_ACK:
2387 ret = "NO_ACK";
2388 break;
2389
2390 case SPINEL_STATUS_CCA_FAILURE:
2391 ret = "CCA_FAILURE";
2392 break;
2393
2394 case SPINEL_STATUS_ALREADY:
2395 ret = "ALREADY";
2396 break;
2397
2398 case SPINEL_STATUS_ITEM_NOT_FOUND:
2399 ret = "ITEM_NOT_FOUND";
2400 break;
2401
2402 case SPINEL_STATUS_INVALID_COMMAND_FOR_PROP:
2403 ret = "INVALID_COMMAND_FOR_PROP";
2404 break;
2405
2406 case SPINEL_STATUS_JOIN_FAILURE:
2407 ret = "JOIN_FAILURE";
2408 break;
2409
2410 case SPINEL_STATUS_JOIN_SECURITY:
2411 ret = "JOIN_SECURITY";
2412 break;
2413
2414 case SPINEL_STATUS_JOIN_NO_PEERS:
2415 ret = "JOIN_NO_PEERS";
2416 break;
2417
2418 case SPINEL_STATUS_JOIN_INCOMPATIBLE:
2419 ret = "JOIN_INCOMPATIBLE";
2420 break;
2421
2422 case SPINEL_STATUS_JOIN_RSP_TIMEOUT:
2423 ret = "JOIN_RSP_TIMEOUT";
2424 break;
2425
2426 case SPINEL_STATUS_JOIN_SUCCESS:
2427 ret = "JOIN_SUCCESS";
2428 break;
2429
2430 case SPINEL_STATUS_RESET_POWER_ON:
2431 ret = "RESET_POWER_ON";
2432 break;
2433
2434 case SPINEL_STATUS_RESET_EXTERNAL:
2435 ret = "RESET_EXTERNAL";
2436 break;
2437
2438 case SPINEL_STATUS_RESET_SOFTWARE:
2439 ret = "RESET_SOFTWARE";
2440 break;
2441
2442 case SPINEL_STATUS_RESET_FAULT:
2443 ret = "RESET_FAULT";
2444 break;
2445
2446 case SPINEL_STATUS_RESET_CRASH:
2447 ret = "RESET_CRASH";
2448 break;
2449
2450 case SPINEL_STATUS_RESET_ASSERT:
2451 ret = "RESET_ASSERT";
2452 break;
2453
2454 case SPINEL_STATUS_RESET_OTHER:
2455 ret = "RESET_OTHER";
2456 break;
2457
2458 case SPINEL_STATUS_RESET_UNKNOWN:
2459 ret = "RESET_UNKNOWN";
2460 break;
2461
2462 case SPINEL_STATUS_RESET_WATCHDOG:
2463 ret = "RESET_WATCHDOG";
2464 break;
2465
2466 default:
2467 break;
2468 }
2469
2470 return ret;
2471 }
2472
spinel_capability_to_cstr(spinel_capability_t capability)2473 const char *spinel_capability_to_cstr(spinel_capability_t capability)
2474 {
2475 const char *ret = "UNKNOWN";
2476
2477 switch (capability)
2478 {
2479 case SPINEL_CAP_LOCK:
2480 ret = "LOCK";
2481 break;
2482
2483 case SPINEL_CAP_NET_SAVE:
2484 ret = "NET_SAVE";
2485 break;
2486
2487 case SPINEL_CAP_HBO:
2488 ret = "HBO";
2489 break;
2490
2491 case SPINEL_CAP_POWER_SAVE:
2492 ret = "POWER_SAVE";
2493 break;
2494
2495 case SPINEL_CAP_COUNTERS:
2496 ret = "COUNTERS";
2497 break;
2498
2499 case SPINEL_CAP_JAM_DETECT:
2500 ret = "JAM_DETECT";
2501 break;
2502
2503 case SPINEL_CAP_PEEK_POKE:
2504 ret = "PEEK_POKE";
2505 break;
2506
2507 case SPINEL_CAP_WRITABLE_RAW_STREAM:
2508 ret = "WRITABLE_RAW_STREAM";
2509 break;
2510
2511 case SPINEL_CAP_GPIO:
2512 ret = "GPIO";
2513 break;
2514
2515 case SPINEL_CAP_TRNG:
2516 ret = "TRNG";
2517 break;
2518
2519 case SPINEL_CAP_CMD_MULTI:
2520 ret = "CMD_MULTI";
2521 break;
2522
2523 case SPINEL_CAP_UNSOL_UPDATE_FILTER:
2524 ret = "UNSOL_UPDATE_FILTER";
2525 break;
2526
2527 case SPINEL_CAP_MCU_POWER_STATE:
2528 ret = "MCU_POWER_STATE";
2529 break;
2530
2531 case SPINEL_CAP_PCAP:
2532 ret = "PCAP";
2533 break;
2534
2535 case SPINEL_CAP_802_15_4_2003:
2536 ret = "802_15_4_2003";
2537 break;
2538
2539 case SPINEL_CAP_802_15_4_2006:
2540 ret = "802_15_4_2006";
2541 break;
2542
2543 case SPINEL_CAP_802_15_4_2011:
2544 ret = "802_15_4_2011";
2545 break;
2546
2547 case SPINEL_CAP_802_15_4_PIB:
2548 ret = "802_15_4_PIB";
2549 break;
2550
2551 case SPINEL_CAP_802_15_4_2450MHZ_OQPSK:
2552 ret = "802_15_4_2450MHZ_OQPSK";
2553 break;
2554
2555 case SPINEL_CAP_802_15_4_915MHZ_OQPSK:
2556 ret = "802_15_4_915MHZ_OQPSK";
2557 break;
2558
2559 case SPINEL_CAP_802_15_4_868MHZ_OQPSK:
2560 ret = "802_15_4_868MHZ_OQPSK";
2561 break;
2562
2563 case SPINEL_CAP_802_15_4_915MHZ_BPSK:
2564 ret = "802_15_4_915MHZ_BPSK";
2565 break;
2566
2567 case SPINEL_CAP_802_15_4_868MHZ_BPSK:
2568 ret = "802_15_4_868MHZ_BPSK";
2569 break;
2570
2571 case SPINEL_CAP_802_15_4_915MHZ_ASK:
2572 ret = "802_15_4_915MHZ_ASK";
2573 break;
2574
2575 case SPINEL_CAP_802_15_4_868MHZ_ASK:
2576 ret = "802_15_4_868MHZ_ASK";
2577 break;
2578
2579 case SPINEL_CAP_CONFIG_FTD:
2580 ret = "CONFIG_FTD";
2581 break;
2582
2583 case SPINEL_CAP_CONFIG_MTD:
2584 ret = "CONFIG_MTD";
2585 break;
2586
2587 case SPINEL_CAP_CONFIG_RADIO:
2588 ret = "CONFIG_RADIO";
2589 break;
2590
2591 case SPINEL_CAP_ROLE_ROUTER:
2592 ret = "ROLE_ROUTER";
2593 break;
2594
2595 case SPINEL_CAP_ROLE_SLEEPY:
2596 ret = "ROLE_SLEEPY";
2597 break;
2598
2599 case SPINEL_CAP_NET_THREAD_1_0:
2600 ret = "NET_THREAD_1_0";
2601 break;
2602
2603 case SPINEL_CAP_NET_THREAD_1_1:
2604 ret = "NET_THREAD_1_1";
2605 break;
2606
2607 case SPINEL_CAP_MAC_WHITELIST:
2608 ret = "MAC_WHITELIST";
2609 break;
2610
2611 case SPINEL_CAP_MAC_RAW:
2612 ret = "MAC_RAW";
2613 break;
2614
2615 case SPINEL_CAP_OOB_STEERING_DATA:
2616 ret = "OOB_STEERING_DATA";
2617 break;
2618
2619 case SPINEL_CAP_CHANNEL_MONITOR:
2620 ret = "CHANNEL_MONITOR";
2621 break;
2622
2623 case SPINEL_CAP_CHANNEL_MANAGER:
2624 ret = "CHANNEL_MANAGER";
2625 break;
2626
2627 case SPINEL_CAP_OPENTHREAD_LOG_METADATA:
2628 ret = "OPENTHREAD_LOG_METADATA";
2629 break;
2630
2631 case SPINEL_CAP_TIME_SYNC:
2632 ret = "TIME_SYNC";
2633 break;
2634
2635 case SPINEL_CAP_CHILD_SUPERVISION:
2636 ret = "CHILD_SUPERVISION";
2637 break;
2638
2639 case SPINEL_CAP_POSIX:
2640 ret = "POSIX";
2641 break;
2642
2643 case SPINEL_CAP_SLAAC:
2644 ret = "SLAAC";
2645 break;
2646
2647 case SPINEL_CAP_RADIO_COEX:
2648 ret = "RADIO_COEX";
2649 break;
2650
2651 case SPINEL_CAP_MAC_RETRY_HISTOGRAM:
2652 ret = "MAC_RETRY_HISTOGRAM";
2653 break;
2654
2655 case SPINEL_CAP_ERROR_RATE_TRACKING:
2656 ret = "ERROR_RATE_TRACKING";
2657 break;
2658
2659 case SPINEL_CAP_THREAD_COMMISSIONER:
2660 ret = "THREAD_COMMISSIONER";
2661 break;
2662
2663 case SPINEL_CAP_THREAD_TMF_PROXY:
2664 ret = "THREAD_TMF_PROXY";
2665 break;
2666
2667 case SPINEL_CAP_THREAD_UDP_FORWARD:
2668 ret = "THREAD_UDP_FORWARD";
2669 break;
2670
2671 case SPINEL_CAP_THREAD_JOINER:
2672 ret = "THREAD_JOINER";
2673 break;
2674
2675 case SPINEL_CAP_THREAD_BORDER_ROUTER:
2676 ret = "THREAD_BORDER_ROUTER";
2677 break;
2678
2679 case SPINEL_CAP_THREAD_SERVICE:
2680 ret = "THREAD_SERVICE";
2681 break;
2682
2683 case SPINEL_CAP_NEST_LEGACY_INTERFACE:
2684 ret = "NEST_LEGACY_INTERFACE";
2685 break;
2686
2687 case SPINEL_CAP_NEST_LEGACY_NET_WAKE:
2688 ret = "NEST_LEGACY_NET_WAKE";
2689 break;
2690
2691 case SPINEL_CAP_NEST_TRANSMIT_HOOK:
2692 ret = "NEST_TRANSMIT_HOOK";
2693 break;
2694
2695 default:
2696 break;
2697 }
2698
2699 return ret;
2700 }
2701
2702 // LCOV_EXCL_STOP
2703
2704 /* -------------------------------------------------------------------------- */
2705
2706 #if SPINEL_SELF_TEST
2707
main(void)2708 int main(void)
2709 {
2710 int ret = -1;
2711 const spinel_eui64_t static_eui64 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}};
2712 const char static_string[] = "static_string";
2713 uint8_t buffer[1024];
2714 ssize_t len;
2715
2716 len =
2717 spinel_datatype_pack(buffer, sizeof(buffer), "CiiLUE", 0x88, 9, 0xA3, 0xDEADBEEF, static_string, &static_eui64);
2718
2719 if (len != 30)
2720 {
2721 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
2722 goto bail;
2723 }
2724
2725 {
2726 const char *str = NULL;
2727
2728 // Length ends right before the string.
2729 len = spinel_datatype_unpack(buffer, 8, "CiiLU", NULL, NULL, NULL, NULL, &str);
2730
2731 if (len != -1)
2732 {
2733 printf("error:%d: len != -1; (%d)\n", __LINE__, (int)len);
2734 goto bail;
2735 }
2736
2737 if (str != NULL)
2738 {
2739 printf("error:%d: str != NULL\n", __LINE__);
2740 goto bail;
2741 }
2742 }
2743
2744 len = 30;
2745
2746 {
2747 uint8_t c = 0;
2748 unsigned int i1 = 0;
2749 unsigned int i2 = 0;
2750 uint32_t l = 0;
2751 const char * str = NULL;
2752 const spinel_eui64_t *eui64 = NULL;
2753
2754 len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "CiiLUE", &c, &i1, &i2, &l, &str, &eui64);
2755
2756 if (len != 30)
2757 {
2758 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
2759 goto bail;
2760 }
2761
2762 if (c != 0x88)
2763 {
2764 printf("error: x != 0x88; (%d)\n", c);
2765 goto bail;
2766 }
2767
2768 if (i1 != 9)
2769 {
2770 printf("error: i1 != 9; (%d)\n", i1);
2771 goto bail;
2772 }
2773
2774 if (i2 != 0xA3)
2775 {
2776 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
2777 goto bail;
2778 }
2779
2780 if (l != 0xDEADBEEF)
2781 {
2782 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
2783 goto bail;
2784 }
2785
2786 if (strcmp(str, static_string) != 0)
2787 {
2788 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
2789 goto bail;
2790 }
2791
2792 if (memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
2793 {
2794 printf("error:%d: memcmp(eui64, &eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
2795 goto bail;
2796 }
2797 }
2798
2799 {
2800 uint8_t c = 0;
2801 unsigned int i1 = 0;
2802 unsigned int i2 = 0;
2803 uint32_t l = 0;
2804 char str[sizeof(static_string)];
2805 spinel_eui64_t eui64 = {{0}};
2806
2807 len = spinel_datatype_unpack_in_place(buffer, (spinel_size_t)len, "CiiLUE", &c, &i1, &i2, &l, &str, sizeof(str),
2808 &eui64);
2809
2810 if (len != 30)
2811 {
2812 printf("error:%d: len != 30; (%d)\n", __LINE__, (int)len);
2813 goto bail;
2814 }
2815
2816 if (c != 0x88)
2817 {
2818 printf("error: x != 0x88; (%d)\n", c);
2819 goto bail;
2820 }
2821
2822 if (i1 != 9)
2823 {
2824 printf("error: i1 != 9; (%d)\n", i1);
2825 goto bail;
2826 }
2827
2828 if (i2 != 0xA3)
2829 {
2830 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
2831 goto bail;
2832 }
2833
2834 if (l != 0xDEADBEEF)
2835 {
2836 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
2837 goto bail;
2838 }
2839
2840 if (strcmp(str, static_string) != 0)
2841 {
2842 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
2843 goto bail;
2844 }
2845
2846 if (memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
2847 {
2848 printf("error:%d: memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
2849 goto bail;
2850 }
2851 }
2852
2853 // -----------------------------------
2854
2855 memset(buffer, 0xAA, sizeof(buffer));
2856
2857 len = spinel_datatype_pack(buffer, sizeof(buffer), "Cit(iL)UE", 0x88, 9, 0xA3, 0xDEADBEEF, static_string,
2858 &static_eui64);
2859
2860 if (len != 32)
2861 {
2862 printf("error:%d: len != 32; (%d)\n", __LINE__, (int)len);
2863 goto bail;
2864 }
2865
2866 {
2867 uint8_t c = 0;
2868 unsigned int i1 = 0;
2869 unsigned int i2 = 0;
2870 uint32_t l = 0;
2871 const char * str = NULL;
2872 spinel_eui64_t *eui64 = NULL;
2873
2874 len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "Cit(iL)UE", &c, &i1, &i2, &l, &str, &eui64);
2875
2876 if (len != 32)
2877 {
2878 printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
2879 goto bail;
2880 }
2881
2882 if (c != 0x88)
2883 {
2884 printf("error: x != 0x88; (%d)\n", c);
2885 goto bail;
2886 }
2887
2888 if (i1 != 9)
2889 {
2890 printf("error: i1 != 9; (%d)\n", i1);
2891 goto bail;
2892 }
2893
2894 if (i2 != 0xA3)
2895 {
2896 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
2897 goto bail;
2898 }
2899
2900 if (l != 0xDEADBEEF)
2901 {
2902 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
2903 goto bail;
2904 }
2905
2906 if (strcmp(str, static_string) != 0)
2907 {
2908 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
2909 goto bail;
2910 }
2911
2912 if (memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
2913 {
2914 printf("error:%d: memcmp(eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
2915 goto bail;
2916 }
2917 }
2918
2919 {
2920 uint8_t c = 0;
2921 unsigned int i1 = 0;
2922 unsigned int i2 = 0;
2923 uint32_t l = 0;
2924 char str[sizeof(static_string)];
2925 spinel_eui64_t eui64 = {{0}};
2926
2927 len = spinel_datatype_unpack_in_place(buffer, (spinel_size_t)len, "Cit(iL)UE", &c, &i1, &i2, &l, &str,
2928 sizeof(str), &eui64);
2929
2930 if (len != 32)
2931 {
2932 printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
2933 goto bail;
2934 }
2935
2936 if (c != 0x88)
2937 {
2938 printf("error: x != 0x88; (%d)\n", c);
2939 goto bail;
2940 }
2941
2942 if (i1 != 9)
2943 {
2944 printf("error: i1 != 9; (%d)\n", i1);
2945 goto bail;
2946 }
2947
2948 if (i2 != 0xA3)
2949 {
2950 printf("error: i2 != 0xA3; (0x%02X)\n", i2);
2951 goto bail;
2952 }
2953
2954 if (l != 0xDEADBEEF)
2955 {
2956 printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
2957 goto bail;
2958 }
2959
2960 if (strcmp(str, static_string) != 0)
2961 {
2962 printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
2963 goto bail;
2964 }
2965
2966 if (memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0)
2967 {
2968 printf("error:%d: memcmp(&eui64, &static_eui64, sizeof(spinel_eui64_t)) != 0\n", __LINE__);
2969 goto bail;
2970 }
2971 }
2972
2973 {
2974 // Test UTF8 validation - Good/Valid strings
2975
2976 // Single symbols
2977 const uint8_t single1[] = {0}; // 0000
2978 const uint8_t single2[] = {0x7F, 0x00}; // 007F
2979 const uint8_t single3[] = {0xC2, 0x80, 0x00}; // 080
2980 const uint8_t single4[] = {0xDF, 0xBF, 0x00}; // 07FF
2981 const uint8_t single5[] = {0xE0, 0xA0, 0x80, 0x00}; // 0800
2982 const uint8_t single6[] = {0xEF, 0xBF, 0xBF, 0x00}; // FFFF
2983 const uint8_t single7[] = {0xF0, 0x90, 0x80, 0x80, 0x00}; // 010000
2984 const uint8_t single8[] = {0xF4, 0x8F, 0xBF, 0xBF, 0x00}; // 10FFFF
2985
2986 // Strings
2987 const uint8_t str1[] = "spinel";
2988 const uint8_t str2[] = "OpenThread";
2989 const uint8_t str3[] = {0x41, 0x7F, 0xEF, 0xBF, 0xBF, 0xC2, 0x80, 0x21, 0x33, 0x00};
2990 const uint8_t str4[] = {0xCE, 0xBA, 0xE1, 0xBD, 0xB9, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0xB5, 0x00}; // κόσμε
2991 const uint8_t str5[] = {0x3D, 0xF4, 0x8F, 0xBF, 0xBF, 0x01, 0xE0, 0xA0, 0x83, 0x22, 0xEF, 0xBF, 0xBF, 0x00};
2992 const uint8_t str6[] = {0xE5, 0xA2, 0x82, 0xE0, 0xA0, 0x80, 0xC2, 0x83, 0xC2, 0x80, 0xF4,
2993 0x8F, 0xBF, 0xBF, 0xF4, 0x8F, 0xBF, 0xBF, 0xDF, 0xBF, 0x21, 0x00};
2994
2995 const uint8_t * good_strings[] = {single1, single2, single3, single4, single5, single6, single7, single8,
2996 str1, str2, str3, str4, str5, str6, NULL};
2997 const uint8_t **str_ptr;
2998
2999 for (str_ptr = &good_strings[0]; *str_ptr != NULL; str_ptr++)
3000 {
3001 if (!spinel_validate_utf8(*str_ptr))
3002 {
3003 printf("error: spinel_validate_utf8() did not correctly detect a valid UTF8 sequence!\n");
3004 goto bail;
3005 }
3006 }
3007 }
3008
3009 {
3010 // Test UTF8 validation - Bad/Invalid strings
3011
3012 // Single symbols (invalid)
3013 const uint8_t single1[] = {0xF8, 0x00};
3014 const uint8_t single2[] = {0xF9, 0x00};
3015 const uint8_t single3[] = {0xFA, 0x00};
3016 const uint8_t single4[] = {0xFF, 0x00};
3017
3018 // Bad continuations
3019 const uint8_t bad1[] = {0xDF, 0x0F, 0x00};
3020 const uint8_t bad2[] = {0xE0, 0xA0, 0x10, 0x00};
3021 const uint8_t bad3[] = {0xF0, 0x90, 0x80, 0x60, 0x00};
3022 const uint8_t bad4[] = {0xF4, 0x8F, 0xBF, 0x0F, 0x00};
3023 const uint8_t bad5[] = {0x21, 0xA0, 0x00};
3024 const uint8_t bad6[] = {0xCE, 0xBA, 0xE1, 0xBD, 0xB9, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0x00};
3025
3026 const uint8_t * bad_strings[] = {single1, single2, single3, single4, bad1, bad2, bad3, bad4, bad5, bad6, NULL};
3027 const uint8_t **str_ptr;
3028
3029 for (str_ptr = &bad_strings[0]; *str_ptr != NULL; str_ptr++)
3030 {
3031 if (spinel_validate_utf8(*str_ptr))
3032 {
3033 printf("error: spinel_validate_utf8() did not correctly detect an invalid UTF8 sequence\n");
3034 goto bail;
3035 }
3036 }
3037 }
3038
3039 printf("OK\n");
3040 ret = 0;
3041 return ret;
3042
3043 bail:
3044 printf("FAILURE\n");
3045 return ret;
3046 }
3047
3048 #endif // #if SPINEL_SELF_TEST
3049