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