· 4 years ago · Jul 20, 2021, 03:04 PM
1/******************************************************************************
2 @file api_mac.c
3
4 @brief TIMAC 2.0 API
5
6 Group: WCS LPC
7 Target Device: linux_gateway
8
9 ******************************************************************************
10
11 Copyright (c) 2016-2021, Texas Instruments Incorporated
12 All rights reserved.
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
16 are met:
17
18 * Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20
21 * Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24
25 * Neither the name of Texas Instruments Incorporated nor the names of
26 its contributors may be used to endorse or promote products derived
27 from this software without specific prior written permission.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
31 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
33 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
36 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
38 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 ******************************************************************************
42
43
44 *****************************************************************************/
45
46/******************************************************************************
47 Includes
48*****************************************************************************/
49
50#include "ti_semaphore.h"
51#include "mutex.h"
52#include "log.h"
53#include "fatal.h"
54#include "rand_data.h"
55#include "mutex.h"
56#include "timer.h"
57#include "stream.h"
58#include "stream_uart.h"
59#include "stream_socket.h"
60
61#include "mt_msg.h"
62#include "api_mac.h"
63#include "api_mac_linux.h"
64
65#include <stdio.h>
66#include <stdarg.h>
67#include <stdint.h>
68#include <malloc.h>
69#include <string.h>
70
71/******************************************************************************
72 Structures
73*****************************************************************************/
74
75/*!
76 @struct secPibStruct
77 Used to dispatch pib set/get requests from a dispatch table.
78*/
79struct secPibStruct
80{
81 /*! the active message */
82 struct mt_msg *pMsg;
83 /*! result of the get/set */
84 ApiMac_status_t result;
85 /*! How many messages where transfered, ie: 2=success */
86 int n_msgs;
87 /*! Is this get/set an error */
88 bool is_error;
89 /*! True if setting */
90 bool is_set;
91 /*! Attribute id as an integer */
92 int attr;
93 /*! data location */
94 void *pValue;
95};
96
97/*!
98 @struct secPibHandler
99 Entry in a pib sec pib get/set dispatch table.
100*/
101struct secPibHandler
102{
103 /*! The corrisponding attribute as an integer */
104 int attr;
105 /*! Handler for this attribute */
106 void (*handler)(struct secPibStruct *pInfo);
107};
108
109/******************************************************************************
110 Global Vars see: api_mac.h or api_mac_linux.h for details.
111******************************************************************************/
112
113/*!
114
115 @brief When waiting for the next AREQ, how long to block.
116
117 When the application calls ApiMac_processIncoming()
118 the code processes all pending async requests then blocks
119 on a semaphore waiting for the next Areq, this is the timeout
120 period to wait before giving up, 0 means do not wait, return
121 immediately.
122*/
123int ApiMacLinux_areq_timeout_mSecs = DEFAULT_ApiMacLinux_areq_timeout_mSecs;
124
125/*!
126 Debug log flags for the API MAC module.
127 these flags are used by the "main" app when parsing the
128 application INI file to set/clear/enable/disable log flags.
129
130 See the file: "log.h" for more details.
131*/
132const struct ini_flag_name api_mac_log_flags[] =
133{
134 { .name = "api-mac-wait", .value = LOG_DBG_API_MAC_wait },
135 { .name = "api-mac-stats", .value = LOG_DBG_API_MAC_datastats },
136 /* terminate */
137 { .name = NULL, .value = 0 }
138};
139
140struct mt_version_info MT_DEVICE_version_info;
141
142/******************************************************************************
143 Constants, definitions, and Local Defines
144*****************************************************************************/
145
146/* These values come from the API_MAC embedded implimentation */
147
148/*! Capability Information - Device is capable of becoming a PAN coordinator */
149#define CAPABLE_PAN_COORD 0x01
150/*! Capability Information - Device is an FFD */
151#define CAPABLE_FFD 0x02
152/*!
153 Capability Information - Device is mains powered rather than battery powered
154*/
155#define CAPABLE_MAINS_POWER 0x04
156/*! Capability Information - Device has its receiver on when idle */
157#define CAPABLE_RX_ON_IDLE 0x08
158/*!
159 Capability Information - Device is capable of sending
160 and receiving secured frames
161*/
162#define CAPABLE_SECURITY 0x40
163/*!
164 Capability Information - Request allocation of a short address in the
165 associate procedure
166*/
167#define CAPABLE_ALLOC_ADDR 0x80
168
169/*! Msgs processed while awaiting a reset rsp */
170#define MAX_MSGS_PROCESSED_POST_RESET 20
171
172/*! Offset into the payload for the payload IEs */
173#define PAYLOAD_IE_OFFSET 0
174/*! Offset into the IE for the subIE */
175#define PAYLOAD_IE_SUBIE_OFFSET 0
176
177/*! Macro to get the IE Type */
178#define PAYLOAD_IE_TYPE(p) (((p)[PAYLOAD_IE_OFFSET+1] >> 7) & 0x01)
179
180/*! Macro to get the IE Group ID */
181#define PAYLOAD_IE_GROUP_ID(p) \
182 ((((uint8_t *)p)[PAYLOAD_IE_OFFSET+1] >> 3) & 0x0f)
183
184/*! Macro to get the IE Content Length */
185#define PAYLOAD_IE_CONTENT_LEN(p) \
186 ((((uint8_t *)p)[PAYLOAD_IE_OFFSET+0] & 0x00ff) + \
187 ((((uint8_t *)p)[PAYLOAD_IE_OFFSET+1] & 0x0007) << 8))
188
189/*! Type value for payload IE */
190#define PAYLOAD_IE_TYPE_VAL 1
191/*! Type value for payload IE */
192#define PAYLOAD_IE_HEADER_LEN 2
193
194/*! Macro to get the short subIE length */
195#define PAYLOAD_IE_SHORT_SUBIE_LEN(p) ((p)[PAYLOAD_IE_SUBIE_OFFSET+0])
196
197/*! Macro to get the long subIE length */
198#define PAYLOAD_IE_LONG_SUBIE_LEN(p) \
199 (((p)[PAYLOAD_IE_OFFSET+0] & 0x00ff) + \
200 (((p)[PAYLOAD_IE_OFFSET+1] & 0x0007) << 8))
201
202/*! Macro to get the subIE type */
203#define PAYLOAD_IE_SUBIE_TYPE(p) (((p)[PAYLOAD_IE_SUBIE_OFFSET+1] >> 7) & 0x01)
204
205/*! Macro to get the subIE ID */
206#define PAYLOAD_IE_SUBIE_ID(p) ((p)[PAYLOAD_IE_SUBIE_OFFSET+1] & 0x7f)
207
208/*! subIE header length */
209#define PAYLOAD_SUB_IE_HEADER_LEN 2
210
211/*! Short subIE type */
212#define PAYLOAD_SUB_ID_IE_TYPE_SHORT 0
213/*! Long subIE type */
214#define PAYLOAD_SUB_ID_IE_TYPE_LONG 1
215
216/*! Short subIE header length */
217#define PAYLOAD_SUB_ID_IE_SHORT_HEADER_LEN 2
218
219/*! Payload IE SubIE Type Size */
220#define PAYLOAD_IE_SUB_IE_TYPE_SIZE 1
221/*! Payload IE SubIE Type Position */
222#define PAYLOAD_IE_SUB_IE_TYPE_POSITION 15
223/*! Payload IE SubIE ID Short Size */
224#define PAYLOAD_IE_SUB_IE_ID_SHORT_SIZE 7
225/*! Payload IE SubIE ID Short Position */
226#define PAYLOAD_IE_SUB_IE_ID_SHORT_POSITION 8
227/*! Payload IE SubIE Short Length Size */
228#define PAYLOAD_IE_SUB_IE_LEN_SHORT_SIZE 8
229/*! Payload IE SubIE Short Length Position */
230#define PAYLOAD_IE_SUB_IE_LEN_SHORT_POSITION 0
231/*! Payload IE SubIE ID Long Size */
232#define PAYLOAD_IE_SUB_IE_ID_LONG_SIZE 4
233/*! Payload IE SubIE ID Long Position */
234#define PAYLOAD_IE_SUB_IE_SUB_ID_LONG_POSITION 11
235/*! Payload IE SubIE ID Long Length Size */
236#define PAYLOAD_IE_SUB_IE_LEN_LONG_SIZE 11
237/*! Payload IE SubIE Long Length Position */
238#define PAYLOAD_IE_SUB_IE_LEN_LONG_POSITION 0
239
240/*! Unpack a field from a uint16_t */
241#define IE_UNPACKING(var,size,position) (((uint16_t)(var)>>(position))\
242 &(((uint16_t)1<<(size))-1))
243
244/*! Make a uint16_t from 2 uint8_t */
245#define MAKE_UINT16(low, high) (((low)&0x00FF)|(((high)&0x00FF)<<8))
246
247/*! Get the SubIE type field (bool) */
248#define GET_SUBIE_TYPE(ctl) \
249 (bool)(IE_UNPACKING(ctl, \
250 PAYLOAD_IE_SUB_IE_TYPE_SIZE, \
251 PAYLOAD_IE_SUB_IE_TYPE_POSITION))
252
253/*! Get the SubIE Long ID */
254#define GET_SUBIE_ID_LONG(ctl) \
255 (uint8_t)(IE_UNPACKING(ctl, \
256 PAYLOAD_IE_SUB_IE_ID_LONG_SIZE, \
257 PAYLOAD_IE_SUB_IE_SUB_ID_LONG_POSITION))
258
259/*! Get the SubIE Long Length */
260#define GET_SUBIE_LEN_LONG(ctl) \
261 (uint16_t)(IE_UNPACKING(ctl, \
262 PAYLOAD_IE_SUB_IE_LEN_LONG_SIZE, \
263 PAYLOAD_IE_SUB_IE_LEN_LONG_POSITION))
264
265/*! Get the SubIE Short ID */
266#define GET_SUBIE_ID_SHORT(ctl) \
267 (uint8_t)(IE_UNPACKING(ctl, \
268 PAYLOAD_IE_SUB_IE_ID_SHORT_SIZE, \
269 PAYLOAD_IE_SUB_IE_ID_SHORT_POSITION))
270
271/*! Get the SubIE Short Length */
272#define GET_SUBIE_LEN_SHORT(ctl) \
273 (uint16_t)(IE_UNPACKING(ctl, \
274 PAYLOAD_IE_SUB_IE_LEN_SHORT_SIZE, \
275 PAYLOAD_IE_SUB_IE_LEN_SHORT_POSITION))
276
277/******************************************************************************
278 Local Structs
279******************************************************************************/
280
281/* forward */
282struct mt_msg_dispatch;
283
284/*
285 @typedef msg_dispatch_handler
286
287 @brief Function prototype for an AREQ handler.
288
289 When an async message comes in, the handler for that message is
290 found in a dispatch table, this is the prototype of a handler
291 in that table.
292*/
293typedef void msg_dispatch_handler(const struct mt_msg_dispatch *pDTE,
294 struct mt_msg *pMsg);
295
296/*!
297 * @struct mt_msg_dispatch
298 * @brief Dispatch table entry for a message handler/parser.
299 */
300struct mt_msg_dispatch
301{
302 /*! cmd0 to match against */
303 int cmd0;
304 /*! cmd1 to match against */
305 int cmd1;
306 /*! for use by the handler */
307 intptr_t cookie;
308 /*! for log purposes */
309 const char *dbg_prefix;
310 /*! handler for this command */
311 msg_dispatch_handler *pHandler;
312};
313
314/******************************************************************************
315 * Local Variables
316 ******************************************************************************/
317
318/*! When specific ASYNC messages arrive, we call these functions. */
319static ApiMac_callbacks_t *pApiMac_callbacks;
320
321/*! used as random source for ApiMac_randomByte() */
322static struct rand_data_one rand_data_source;
323
324/******************************************************************************
325 Local Function Prototypes
326 *****************************************************************************/
327static void *api_mac_callocMem(struct mt_msg *pMsg, const char *pWhy, int cnt,
328 int siz);
329static void api_mac_freeMem(void *pMem);
330static void decode_Sec(struct mt_msg *pMsg, ApiMac_sec_t *pSec);
331static void encode_Sec(struct mt_msg *pMsg, ApiMac_sec_t *pSec);
332static void decode_Addr(struct mt_msg *pMsg, ApiMac_sAddr_t *pAddr);
333static void encode_Addr(struct mt_msg *pMsg, const ApiMac_sAddr_t *pAddr);
334static void api_rd_panDesc(struct mt_msg *pMsg, ApiMac_panDesc_t *pD);
335static void process_areq_associate_ind(const struct mt_msg_dispatch *p,
336 struct mt_msg *pMsg);
337static void process_areq_sync_loss_ind(const struct mt_msg_dispatch *p,
338 struct mt_msg *pMsg);
339static void process_areq_data_cnf(const struct mt_msg_dispatch *p,
340 struct mt_msg *pMsg);
341static void process_areq_data_ind(const struct mt_msg_dispatch *p,
342 struct mt_msg *pMsg);
343static void process_areq_purge_cnf(const struct mt_msg_dispatch *p,
344 struct mt_msg *pMsg);
345static void process_areq_orphan_ind(const struct mt_msg_dispatch *p,
346 struct mt_msg *pMsg);
347static void process_areq_associate_cnf(const struct mt_msg_dispatch *p,
348 struct mt_msg *pMsg);
349static void process_areq_beacon_notify(const struct mt_msg_dispatch *p,
350 struct mt_msg *pMsg);
351static void process_areq_disassociate_ind(const struct mt_msg_dispatch *p,
352 struct mt_msg *pMsg);
353static void process_areq_disassociate_cnf(const struct mt_msg_dispatch *p,
354 struct mt_msg *pMsg);
355static void process_areq_poll_cnf(const struct mt_msg_dispatch *p,
356 struct mt_msg *pMsg);
357static void process_areq_scan_cnf(const struct mt_msg_dispatch *p,
358 struct mt_msg *pMsg);
359static void process_areq_comm_status_ind(const struct mt_msg_dispatch *p,
360 struct mt_msg *pMsg);
361static void process_areq_start_cnf(const struct mt_msg_dispatch *p,
362 struct mt_msg *pMsg);
363static void process_areq_ws_async_cnf(const struct mt_msg_dispatch *p,
364 struct mt_msg *pMsg);
365static void process_areq_ws_async_ind(const struct mt_msg_dispatch *p,
366 struct mt_msg *pMsg);
367static void process_areq_poll_ind(const struct mt_msg_dispatch *p,
368 struct mt_msg *pMsg);
369static void process_areq_reset_ind(const struct mt_msg_dispatch *p,
370 struct mt_msg *pMsg);
371static void process_areq(struct mt_msg *pMsg);
372static void resetCoPDevice(void);
373static void *createInterface(void);
374static uint16_t convertTxOptions(ApiMac_txOptions_t *txOptions);
375static int API_MAC_TxRx_Status(struct mt_msg *pMsg);
376static struct mt_msg *api_new_msg(int len, int cmd0, int cmd1,
377 const char *dbg_prefix);
378static int API_MAC_Get_Common(int cmd0, int cmd1, int att_id, int wiresize,
379 int datasize, void *pValue);
380static int API_MAC_Set_Common(int cmd0, int cmd1, int att_id, int wiresize,
381 uint64_t v);
382static ApiMac_status_t API_MAC_SetGetArray_Common(bool is_set, int cmd0,
383 int cmd1, int pib_attribute,
384 uint8_t *pValue);
385static void sec_pib_ApiMac_securityAttribute_keyTable(struct secPibStruct *p);
386static void sec_pib_ApiMac_securityAttribute_keyIdLookupEntry(struct secPibStruct *p);
387static void sec_pib_ApiMac_securityAttribute_keyDeviceEntry(struct secPibStruct *p);
388static void sec_pib_ApiMac_securityAttribute_keyUsageEntry(struct secPibStruct *p);
389static void sec_pib_ApiMac_securityAttribute_keyEntry(struct secPibStruct *p);
390static void sec_pib_ApiMac_securityAttribute_deviceEntry(struct secPibStruct *p);
391static void sec_pib_ApiMac_securityAttribute_securityLevelEntry(struct secPibStruct *p);
392static ApiMac_status_t common_ApiMac_mlmeGetSetSecurityReqStruct(int is_set,
393 ApiMac_securityAttribute_struct_t pibAttribute, void *pValue);
394
395/******************************************************************************
396 Functions.
397******************************************************************************/
398
399/*!
400 * @brief Allocate memory associated with this message.
401 * @param pMsg - associated message
402 * @param why - message for error logging
403 * @param cnt - number of items to allocate
404 * @param siz - size of each item to allocate
405 *
406 * If required, logs error messages
407 */
408static void *api_mac_callocMem(struct mt_msg *pMsg,
409 const char *pWhy,
410 int cnt,
411 int siz)
412{
413 void *vp;
414
415 vp = calloc(cnt, siz);
416 if(vp == NULL)
417 {
418 MT_MSG_log(LOG_ERROR, pMsg, "no memory for: %s\n", pWhy);
419 }
420 return (vp);
421}
422
423/*!
424 * @brief Compliment of api_mac_callocMem()
425 * @param pMem - data to free
426 */
427static void api_mac_freeMem(void *pMem)
428{
429 if(pMem)
430 {
431 free(pMem);
432 }
433}
434
435/*!
436 * @brief common routine to decode a security component of a message
437 * @param pMsg - the message to read from
438 * @param pSec - the security item to fill in
439 */
440static void decode_Sec(struct mt_msg *pMsg, ApiMac_sec_t *pSec)
441{
442 MT_MSG_rdBuf_DBG(pMsg,
443 (void *)(&pSec->keySource[0]),
444 APIMAC_KEY_SOURCE_MAX_LEN, "keySource");
445 pSec->securityLevel = MT_MSG_rdU8_DBG(pMsg, "securityLevel");
446 pSec->keyIdMode = MT_MSG_rdU8_DBG(pMsg, "keyIdMode");
447 pSec->keyIndex = MT_MSG_rdU8_DBG(pMsg, "keyIndex");
448}
449
450/*!
451 * @brief Common routine to handle a "security" component of a message.
452 * @param wrPtr - where to encode the security information
453 * @param pSec - the security information to encode
454 * @return updated wrPtr
455 *
456 * An example use of this can be found in ApiMac_mlmeAssociateReq()
457 */
458static void encode_Sec(struct mt_msg *pMsg, ApiMac_sec_t *pSec)
459{
460 MT_MSG_wrBuf_DBG(pMsg,
461 (void *)(&(pSec->keySource[0])),
462 APIMAC_KEY_SOURCE_MAX_LEN, "keySource");
463 MT_MSG_wrU8_DBG(pMsg, pSec->securityLevel, "securityLevel");
464 MT_MSG_wrU8_DBG(pMsg, pSec->keyIdMode, "keyIdMode");
465 MT_MSG_wrU8_DBG(pMsg, pSec->keyIndex, "keyIndex");
466}
467
468/*!
469 * @brief Decode an address from a message
470 * @return void
471 */
472static void decode_Addr(struct mt_msg *pMsg, ApiMac_sAddr_t *pAddr)
473{
474 int x;
475 pAddr->addrMode = MT_MSG_rdU8_DBG(pMsg, "addrMode");
476 switch(pAddr->addrMode)
477 {
478 default:
479 case ApiMac_addrType_none:
480 /* read something.. */
481 for(x = 0 ; x < 8 ; x++)
482 {
483 pAddr->addr.extAddr[x] = MT_MSG_rdU8_DBG(pMsg, "filler");
484 }
485 break;
486 case ApiMac_addrType_short:
487 pAddr->addr.shortAddr = MT_MSG_rdU16_DBG(pMsg, "shortAddr");
488 for(x = 2 ; x < 8 ; x++)
489 {
490 /* read & toss */
491 MT_MSG_rdU8_DBG(pMsg, "filler");
492 }
493 break;
494 case ApiMac_addrType_extended:
495 for(x = 0 ; x < 8 ; x++)
496 {
497 pAddr->addr.extAddr[x] = MT_MSG_rdU8_DBG(pMsg, "extaddr");
498 }
499 }
500}
501
502/*!
503 * @brief internal helper function to encode an address
504 * @param pMsg - the message to write to
505 * @param pAddr - the address to write/encode
506 */
507static void encode_Addr(struct mt_msg *pMsg, const ApiMac_sAddr_t *pAddr)
508{
509 int x;
510 MT_MSG_wrU8_DBG(pMsg, pAddr->addrMode, "addrMode");
511 switch(pAddr->addrMode)
512 {
513 case ApiMac_addrType_none:
514 /* zero fill */
515 for(x = 0 ; x < 8 ; x++)
516 {
517 MT_MSG_wrU8_DBG(pMsg, 0, "addr-fill");
518 }
519 break;
520 case ApiMac_addrType_short:
521 MT_MSG_wrU16_DBG(pMsg, pAddr->addr.shortAddr, "shortAddr");
522 for(x = 2 ; x < 8 ; x++)
523 {
524 MT_MSG_wrU8_DBG(pMsg, 0,"addr-fill");
525 }
526 break;
527 case ApiMac_addrType_extended:
528 for(x = 0 ; x < 8 ; x++)
529 {
530 MT_MSG_wrU8_DBG(pMsg, pAddr->addr.extAddr[x], "ext-addr");
531 }
532 break;
533 default:
534 BUG_HERE("API error bad address type\n");
535 /* insert fill bytes */
536 MT_MSG_wrU32_DBG(pMsg, 0, "dbg-fill");
537 MT_MSG_wrU32_DBG(pMsg, 0, "dbg-fill");
538 break;
539 }
540}
541
542/*!
543 * @brief common code to parse a pan descriptor from an MT message
544 *
545 * @param pMsg - message to parse
546 * @param pD - where to put the message
547 * @param flavor - 0 if a beacon, !0 if a scan response type
548 */
549static void api_rd_panDesc(struct mt_msg *pMsg,
550 ApiMac_panDesc_t *pD)
551{
552 decode_Addr(pMsg, &(pD->coordAddress));
553 pD->coordPanId = MT_MSG_rdU16_DBG(pMsg, "coordPanId");
554 pD->superframeSpec = MT_MSG_rdU16_DBG(pMsg, "superFrameSpec");
555 pD->logicalChannel = MT_MSG_rdU8_DBG(pMsg, "logicalChannel");
556 pD->channelPage = MT_MSG_rdU8_DBG(pMsg, "channelPage");
557 pD->gtsPermit = MT_MSG_rdU8_DBG(pMsg, "gtsPermit");
558 pD->linkQuality = MT_MSG_rdU8_DBG(pMsg, "linkQuality");
559 pD->timestamp = MT_MSG_rdU32_DBG(pMsg, "timestamp");
560 pD->securityFailure = MT_MSG_rdU8_DBG(pMsg, "securityFailure");
561 decode_Sec(pMsg, &(pD->sec));
562}
563
564static bool is_bad_addr( ApiMac_sAddrExt_t p )
565{
566 int x;
567 /* A bad MAC address is defined as all 1s */
568 for( x = 0 ; x < APIMAC_SADDR_EXT_LEN ; x++ ){
569 if( p[x] != 0x0ff ){
570 return false;
571 }
572 }
573 return true;
574}
575
576
577/*!
578 Initialize this module.
579
580 Public function defined in api_mac.h
581*/
582void *ApiMac_init(bool enableFH)
583{
584 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
585
586
587 int r;
588 bool b;
589 void *sem;
590 static bool initialMacInit = true;
591
592 if (initialMacInit)
593 {
594 sem = createInterface();
595 initialMacInit = false;
596 }
597
598 memset( (void *)(&MT_DEVICE_version_info), 0, sizeof(MT_DEVICE_version_info) );
599 r = MT_MSG_getVersion( API_MAC_msg_interface, &MT_DEVICE_version_info );
600 if( r != 2 )
601 {
602 FATAL_printf("Cannot get VERSION info from CoProcessor\n");
603 }
604
605
606 if(enableFH)
607 {
608 ApiMac_enableFH();
609 }
610
611 ApiMac_mlmeResetReq(true);
612
613 /* get mac address from the co-processor */
614 {
615 ApiMac_sAddrExt_t cfg, prim;
616 /* First: the one from the CCFG */
617 r = MT_MSG_getExtAddress( API_MAC_msg_interface, NULL, prim, cfg );
618 if( r != 4 ){
619 FATAL_printf("Cannot get MAC addresses from CoProcessor\n");
620 }
621 /* if not programed, use the factory one */
622 b = is_bad_addr( cfg );
623 if( b ){
624 memcpy( cfg, prim, APIMAC_SADDR_EXT_LEN);
625 }
626
627 /* Oh no things are horrible bad! */
628 if( is_bad_addr( cfg )){
629 /* we must invent a random one */
630 RAND_DATA_initOne( &(rand_data_source), ((uint32_t)( TIMER_getAbsNow() ) ));
631 int x;
632 for( x = 0 ; x < APIMAC_SADDR_EXT_LEN ; x++ ){
633 cfg[x] = ApiMac_randomByte();
634 }
635 /* Set the Local admin bit */
636 cfg[0] |= 2;
637 /* unicast bit */
638 cfg[0] &= (~1);
639 }
640
641 ApiMac_mlmeSetReqArray( ApiMac_attribute_extendedAddress, cfg );
642 }
643
644 return sem;
645}
646
647/*!
648 Register for MAC callbacks.
649
650 Public function defined in api_mac.h
651*/
652void ApiMac_registerCallbacks(ApiMac_callbacks_t *pCallbacks)
653{
654 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
655 pApiMac_callbacks = pCallbacks;
656}
657
658/*!
659 * @brief Process an associate indication
660 *
661 * @param p - dispatch table entry
662 * @param pMsg - the message to process.
663 */
664static void process_areq_associate_ind(const struct mt_msg_dispatch *p,
665 struct mt_msg *pMsg)
666{
667 int r;
668 ApiMac_mlmeAssociateInd_t indication;
669
670 (void)p;
671
672 memset((void *)(&indication), 0, sizeof(indication));
673
674 MT_MSG_rdBuf_DBG(pMsg,
675 (void *)(&indication.deviceAddress[0]),
676 APIMAC_SADDR_EXT_LEN, "extaddr");
677
678 r = MT_MSG_rdU8_DBG(pMsg, "capInfo");
679 ApiMac_buildMsgCapInfo((uint8_t)(r),
680 &(indication.capabilityInformation));
681
682 decode_Sec(pMsg, &indication.sec);
683
684 MT_MSG_parseComplete(pMsg);
685 if(pMsg->is_error)
686 {
687 return;
688 }
689
690 if(pApiMac_callbacks->pAssocIndCb)
691 {
692 (*(pApiMac_callbacks->pAssocIndCb))(&indication);
693 }
694}
695
696/*!
697 * @brief Process a sync loss indication
698 *
699 * @param p - dispatch table entry
700 * @param pMsg - the message to process.
701 */
702static void process_areq_sync_loss_ind(const struct mt_msg_dispatch *p,
703 struct mt_msg *pMsg)
704{
705 ApiMac_mlmeSyncLossInd_t indication;
706
707 (void)p;
708
709 memset((void *)(&indication), 0, sizeof(indication));
710
711 indication.reason = MT_MSG_rdU8_DBG(pMsg, "reason");
712 indication.panId = MT_MSG_rdU16_DBG(pMsg, "panID");
713 indication.logicalChannel = MT_MSG_rdU8_DBG(pMsg, "logicalChannel");
714 indication.channelPage = MT_MSG_rdU8_DBG(pMsg, "channelPage");
715 indication.phyID = MT_MSG_rdU8_DBG(pMsg, "phyID");
716 decode_Sec(pMsg, &indication.sec);
717
718 MT_MSG_parseComplete(pMsg);
719 if(pMsg->is_error)
720 {
721 return;
722 }
723
724 if(pApiMac_callbacks->pSyncLossIndCb)
725 {
726 (*(pApiMac_callbacks->pSyncLossIndCb))(&indication);
727 }
728}
729
730/*!
731 * @brief Process a data conformation
732 *
733 * @param p - dispatch table entry
734 * @param pMsg - the message to process.
735 */
736static void process_areq_data_cnf(const struct mt_msg_dispatch *p,
737 struct mt_msg *pMsg)
738{
739 ApiMac_mcpsDataCnf_t indication;
740
741 (void)p;
742
743 memset((void *)(&indication), 0, sizeof(indication));
744
745 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
746 indication.msduHandle = MT_MSG_rdU8_DBG(pMsg, "msdu-handle");
747 indication.timestamp = MT_MSG_rdU32_DBG(pMsg, "timestamp");
748 indication.timestamp2 = MT_MSG_rdU16_DBG(pMsg, "timestamp2");
749 indication.retries = MT_MSG_rdU8_DBG(pMsg, "retries" );
750 indication.mpduLinkQuality = MT_MSG_rdU8_DBG(pMsg, "mpduLinkQuality");
751 indication.correlation = MT_MSG_rdU8_DBG(pMsg, "correlation");
752 indication.rssi = MT_MSG_rdU8_DBG(pMsg, "rssi" );
753 indication.frameCntr = MT_MSG_rdU32_DBG(pMsg, "frameCntr");
754
755 MT_MSG_parseComplete(pMsg);
756 if(pMsg->is_error)
757 {
758 return;
759 }
760
761 if(pApiMac_callbacks->pDataCnfCb)
762 {
763 (*(pApiMac_callbacks->pDataCnfCb))(&indication);
764 }
765}
766
767/*!
768 * @brief Process a data indication
769 *
770 * @param p - dispatch table entry
771 * @param pMsg - the message to process.
772 */
773static void process_areq_data_ind(const struct mt_msg_dispatch *p,
774 struct mt_msg *pMsg)
775{
776 ApiMac_mcpsDataInd_t indication;
777
778 memset((void *)(&indication), 0, sizeof(indication));
779
780 (void)p;
781
782 decode_Addr(pMsg, (&indication.srcAddr));
783 decode_Addr(pMsg, (&indication.dstAddr));
784 indication.timestamp = MT_MSG_rdU32_DBG(pMsg, "timestamp");
785 indication.timestamp2 = MT_MSG_rdU16_DBG(pMsg, "timestamp2");
786 indication.srcPanId = MT_MSG_rdU16_DBG(pMsg, "srcPanId");
787 indication.dstPanId = MT_MSG_rdU16_DBG(pMsg, "dstPanId");
788 indication.mpduLinkQuality = MT_MSG_rdU8_DBG(pMsg, "mdpuLinkQuality");
789 indication.correlation = MT_MSG_rdU8_DBG(pMsg, "correlation");
790 indication.rssi = MT_MSG_rdU8_DBG(pMsg, "rssi");
791 indication.dsn = MT_MSG_rdU8_DBG(pMsg, "dsn");
792 decode_Sec(pMsg, &indication.sec);
793 indication.frameCntr = MT_MSG_rdU32_DBG(pMsg, "frameCntr");
794
795 indication.msdu.len = MT_MSG_rdU16_DBG(pMsg, "msdu.len");
796 indication.payloadIeLen = MT_MSG_rdU16_DBG(pMsg, "payloadIeLen");
797
798 indication.msdu.p = &(pMsg->iobuf[ pMsg->iobuf_idx ]);
799 MT_MSG_rdBuf_DBG(pMsg, NULL, indication.msdu.len, "msdu.data");
800
801 indication.pPayloadIE = &(pMsg->iobuf[ pMsg->iobuf_idx ]);
802 MT_MSG_rdBuf_DBG(pMsg, NULL, indication.payloadIeLen, "payloadData");
803
804 MT_MSG_parseComplete(pMsg);
805 if(pMsg->is_error)
806 {
807 return;
808 }
809
810
811 LOG_printf( LOG_DBG_API_MAC_datastats,
812 "data-ind: len=%2d addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
813 pMsg->expected_len,
814 indication.srcAddr.addr.extAddr[0],
815 indication.srcAddr.addr.extAddr[1],
816 indication.srcAddr.addr.extAddr[2],
817 indication.srcAddr.addr.extAddr[3],
818 indication.srcAddr.addr.extAddr[4],
819 indication.srcAddr.addr.extAddr[5],
820 indication.srcAddr.addr.extAddr[6],
821 indication.srcAddr.addr.extAddr[7]);
822
823 if(pApiMac_callbacks->pDataIndCb)
824 {
825 (*(pApiMac_callbacks->pDataIndCb))(&indication);
826 }
827}
828
829/*!
830 * @brief Process a purge confirmation
831 *
832 * @param p - dispatch table entry
833 * @param pMsg - the message to process.
834 */
835static void process_areq_purge_cnf(const struct mt_msg_dispatch *p,
836 struct mt_msg *pMsg)
837{
838 ApiMac_mcpsPurgeCnf_t indication;
839
840 (void)p;
841
842 memset((void *)(&indication), 0, sizeof(indication));
843
844 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
845 indication.msduHandle = MT_MSG_rdU8_DBG(pMsg, "handle");
846
847 MT_MSG_parseComplete(pMsg);
848 if(pMsg->is_error)
849 {
850 return;
851 }
852
853 if(pApiMac_callbacks->pPurgeCnfCb)
854 {
855 (*(pApiMac_callbacks->pPurgeCnfCb))(&indication);
856 }
857}
858
859/*!
860 * @brief Process an orphan indication
861 *
862 * @param p - dispatch table entry
863 * @param pMsg - the message to process.
864 */
865static void process_areq_orphan_ind(const struct mt_msg_dispatch *p,
866 struct mt_msg *pMsg)
867{
868 ApiMac_mlmeOrphanInd_t indication;
869
870 (void)p;
871
872 memset((void *)(&indication), 0, sizeof(indication));
873
874 MT_MSG_rdBuf_DBG(pMsg,
875 (void *)(&indication.orphanAddress[0]),
876 APIMAC_SADDR_EXT_LEN, "ext-addr");
877 LOG_printf( LOG_DBG_API_MAC_datastats,
878 "orphan: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
879 indication.orphanAddress[0],
880 indication.orphanAddress[1],
881 indication.orphanAddress[2],
882 indication.orphanAddress[3],
883 indication.orphanAddress[4],
884 indication.orphanAddress[5],
885 indication.orphanAddress[6],
886 indication.orphanAddress[7]);
887
888 decode_Sec(pMsg, &(indication.sec));
889
890 MT_MSG_parseComplete(pMsg);
891 if(pMsg->is_error)
892 {
893 return;
894 }
895
896 if(pApiMac_callbacks->pOrphanIndCb)
897 {
898 (*(pApiMac_callbacks->pOrphanIndCb))(&indication);
899 }
900}
901
902/*!
903 * @brief Process an associate confirmation
904 *
905 * @param p - dispatch table entry
906 * @param pMsg - the message to process.
907 */
908static void process_areq_associate_cnf(const struct mt_msg_dispatch *p,
909 struct mt_msg *pMsg)
910{
911 ApiMac_mlmeAssociateCnf_t indication;
912
913 (void)(p);
914
915 memset((void *)(&indication), 0, sizeof(indication));
916
917 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
918 indication.assocShortAddress = MT_MSG_rdU16_DBG(pMsg, "shorAddress");
919 decode_Sec(pMsg, &indication.sec);
920
921 MT_MSG_parseComplete(pMsg);
922 if(pMsg->is_error)
923 {
924 return;
925 }
926
927 if(pApiMac_callbacks->pAssocCnfCb)
928 {
929 (*(pApiMac_callbacks->pAssocCnfCb))(&indication);
930 }
931}
932
933/*!
934 * @brief Process a beacon notify message
935 *
936 * @param p - dispatch table entry
937 * @param pMsg - the message to process.
938 */
939static void process_areq_beacon_notify(const struct mt_msg_dispatch *p,
940 struct mt_msg *pMsg)
941{
942 int x;
943 int idx_save;
944 ApiMac_mlmeBeaconNotifyInd_t indication;
945
946 (void)(p);
947
948 /* simplify, do this check at the top. */
949 if(pApiMac_callbacks->pBeaconNotifyIndCb == NULL)
950 {
951 return;
952 }
953
954 memset((void *)(&indication), 0, sizeof(indication));
955
956 indication.beaconType = MT_MSG_rdU8_DBG(pMsg, "beacontype");
957 indication.bsn = MT_MSG_rdU8_DBG(pMsg, "bsn");
958 switch(indication.beaconType)
959 {
960 default:
961 MT_MSG_log(LOG_ERROR, pMsg,
962 "unknown beacon type: %d\n",
963 indication.beaconType);
964 break;
965 case ApiMac_beaconType_normal:
966 /* standard beacon */
967 indication.panDesc.timestamp = MT_MSG_rdU32_DBG(pMsg, "timestamp");
968 decode_Addr(pMsg, &(indication.panDesc.coordAddress));
969 indication.panDesc.coordPanId = MT_MSG_rdU16_DBG(pMsg, "pan-PandID");
970 indication.panDesc.superframeSpec = MT_MSG_rdU16_DBG(pMsg, "pan-super-frame");
971 indication.panDesc.logicalChannel = MT_MSG_rdU8_DBG(pMsg, "pan-logical-channel");
972 indication.panDesc.channelPage = MT_MSG_rdU8_DBG(pMsg, "pan-channel-page");
973 indication.panDesc.gtsPermit = MT_MSG_rdU8_DBG(pMsg, "pan-gts-permit");
974 indication.panDesc.linkQuality = MT_MSG_rdU8_DBG(pMsg, "pan-link-quality");
975 indication.panDesc.securityFailure = MT_MSG_rdU8_DBG(pMsg, "pan-security-failure");
976 decode_Sec(pMsg, &(indication.panDesc.sec));
977 indication.beaconData.beacon.numPendShortAddr = MT_MSG_rdU8_DBG(pMsg, "num-pend-short-addr");
978 indication.beaconData.beacon.numPendExtAddr = MT_MSG_rdU8_DBG(pMsg, "num-pend-ext-addr");
979 indication.beaconData.beacon.sduLength = MT_MSG_rdU8_DBG(pMsg, "sdu-length");
980
981 /* remember where we are now. */
982 idx_save = pMsg->iobuf_idx;
983 /* fake parse these ... */
984 MT_MSG_rdBuf_DBG(pMsg, NULL,
985 2 * indication.beaconData.beacon.numPendShortAddr,
986 "pend-short-addr");
987 MT_MSG_rdBuf_DBG(pMsg, NULL,
988 8 * indication.beaconData.beacon.numPendExtAddr,
989 "pend-ext-addr");
990 MT_MSG_rdBuf_DBG(pMsg, NULL,
991 indication.beaconData.beacon.sduLength, "sdu.data");
992 MT_MSG_parseComplete(pMsg);
993
994 if(pMsg->is_error)
995 {
996 goto fail_1;
997 }
998
999 /* allocate space for these */
1000 indication.beaconData.beacon.pShortAddrList =
1001 (uint16_t *)api_mac_callocMem(pMsg,
1002 "beacon",
1003 indication.beaconData.beacon.numPendShortAddr+1,
1004 sizeof(uint16_t));
1005 indication.beaconData.beacon.pExtAddrList =
1006 (uint8_t *)api_mac_callocMem(pMsg,
1007 "beacon",
1008 indication.beaconData.beacon.numPendExtAddr+1,
1009 8);
1010 indication.beaconData.beacon.pSdu =
1011 (uint8_t *)api_mac_callocMem(pMsg,
1012 "beacon",
1013 indication.beaconData.beacon.sduLength+1,
1014 1);
1015
1016 if(pMsg->is_error)
1017 {
1018 goto fail_1;
1019 }
1020 /* reset to the starting point */
1021 pMsg->iobuf_idx = idx_save;
1022
1023 /* and read properly to do byte swap if required */
1024 for(x = 0 ; x < indication.beaconData.beacon.numPendShortAddr ; x++)
1025 {
1026 indication.beaconData.beacon.pShortAddrList[x] =
1027 MT_MSG_rdU16_DBG(pMsg, "short-addr");
1028 }
1029
1030 /* read properly to deal with alignment */
1031 for(x = 0 ; x < indication.beaconData.beacon.numPendExtAddr ; x++)
1032 {
1033 MT_MSG_rdBuf_DBG(pMsg,
1034 indication.beaconData.beacon.pExtAddrList + (x *8),
1035 8, "dummy");
1036 }
1037
1038 /* these are just bytes.. */
1039 MT_MSG_rdBuf_DBG(pMsg,
1040 indication.beaconData.beacon.pSdu,
1041 indication.beaconData.beacon.sduLength, "sdu-data");
1042
1043 MT_MSG_parseComplete(pMsg);
1044 if(!(pMsg->is_error))
1045 {
1046 (*(pApiMac_callbacks->pBeaconNotifyIndCb))(&indication);
1047 }
1048 fail_1:
1049 if(indication.beaconData.beacon.pShortAddrList)
1050 {
1051 api_mac_freeMem((void *)(indication.beaconData.beacon.pShortAddrList));
1052 indication.beaconData.beacon.pShortAddrList = NULL;
1053 }
1054 if(indication.beaconData.beacon.pExtAddrList)
1055 {
1056 api_mac_freeMem((void *)(indication.beaconData.beacon.pExtAddrList));
1057 indication.beaconData.beacon.pExtAddrList = NULL;
1058 }
1059 if(indication.beaconData.beacon.pSdu)
1060 {
1061 api_mac_freeMem((void *)(indication.beaconData.beacon.pSdu));
1062 indication.beaconData.beacon.pSdu = NULL;
1063 }
1064
1065 break;
1066 case ApiMac_beaconType_enhanced:
1067 indication.beaconData.eBeacon.coexist.beaconOrder = MT_MSG_rdU8_DBG(pMsg, "beaconOrder");
1068 indication.beaconData.eBeacon.coexist.superFrameOrder = MT_MSG_rdU8_DBG(pMsg, "superFrameOrder");
1069 indication.beaconData.eBeacon.coexist.finalCapSlot = MT_MSG_rdU8_DBG(pMsg, "finalCapSlot");
1070 indication.beaconData.eBeacon.coexist.eBeaconOrder = MT_MSG_rdU8_DBG(pMsg, "eBeaconOrder");
1071 indication.beaconData.eBeacon.coexist.offsetTimeSlot = MT_MSG_rdU8_DBG(pMsg, "offsetTimeSlot");
1072 indication.beaconData.eBeacon.coexist.capBackOff = MT_MSG_rdU8_DBG(pMsg, "capBackOff");
1073 indication.beaconData.eBeacon.coexist.eBeaconOrderNBPAN = MT_MSG_rdU16_DBG(pMsg, "beaconordernpan");
1074 MT_MSG_parseComplete(pMsg);
1075 if(pMsg->is_error)
1076 {
1077 break;
1078 }
1079 if(pApiMac_callbacks->pBeaconNotifyIndCb)
1080 {
1081 (*(pApiMac_callbacks->pBeaconNotifyIndCb))(&indication);
1082 }
1083 break;
1084 }
1085}
1086
1087/*!
1088 * @brief Process a disassociate indication
1089 *
1090 * @param p - dispatch table entry
1091 * @param pMsg - the message to process.
1092 */
1093static void process_areq_disassociate_ind(const struct mt_msg_dispatch *p,
1094 struct mt_msg *pMsg)
1095{
1096 ApiMac_mlmeDisassociateInd_t indication;
1097
1098 (void)(p);
1099
1100 memset((void *)(&indication), 0, sizeof(indication));
1101
1102 MT_MSG_rdBuf_DBG(pMsg,
1103 (void *)(&indication.deviceAddress[0]),
1104 APIMAC_SADDR_EXT_LEN, "ext-addr");
1105 indication.disassociateReason = MT_MSG_rdU8_DBG(pMsg, "reason");
1106 decode_Sec(pMsg, &(indication.sec));
1107
1108 MT_MSG_parseComplete(pMsg);
1109 if(pMsg->is_error)
1110 {
1111 return;
1112 }
1113
1114 if(pApiMac_callbacks->pDisassociateIndCb)
1115 {
1116 (*(pApiMac_callbacks->pDisassociateIndCb))(&indication);
1117 }
1118}
1119
1120/*!
1121 * @brief Process a disassociate confirmation
1122 *
1123 * @param p - dispatch table entry
1124 * @param pMsg - the message to process.
1125 */
1126static void process_areq_disassociate_cnf(const struct mt_msg_dispatch *p,
1127 struct mt_msg *pMsg)
1128{
1129 ApiMac_mlmeDisassociateCnf_t indication;
1130
1131 (void)(p);
1132
1133 memset((void *)(&indication), 0, sizeof(indication));
1134
1135 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
1136 decode_Addr(pMsg, &indication.deviceAddress);
1137 indication.panId = MT_MSG_rdU16_DBG(pMsg, "pan-id");
1138
1139 MT_MSG_parseComplete(pMsg);
1140 if(pMsg->is_error)
1141 {
1142 return;
1143 }
1144
1145 if(pApiMac_callbacks->pDisassociateCnfCb)
1146 {
1147 (*(pApiMac_callbacks->pDisassociateCnfCb))(&indication);
1148 }
1149}
1150
1151/*!
1152 * @brief Process a poll confirmation
1153 *
1154 * @param p - dispatch table entry
1155 * @param pMsg - the message to process.
1156 */
1157static void process_areq_poll_cnf(const struct mt_msg_dispatch *p,
1158 struct mt_msg *pMsg)
1159{
1160 ApiMac_mlmePollCnf_t indication;
1161
1162 (void)(p);
1163
1164 memset((void *)(&indication), 0, sizeof(indication));
1165
1166 indication.status = MT_MSG_rdU8_DBG(pMsg ,"status");
1167 indication.framePending = MT_MSG_rdU8_DBG(pMsg, "framePending");
1168
1169 MT_MSG_parseComplete(pMsg);
1170 if(pMsg->is_error)
1171 {
1172 return;
1173 }
1174
1175 if(pApiMac_callbacks->pPollCnfCb)
1176 {
1177 (*(pApiMac_callbacks->pPollCnfCb))(&indication);
1178 }
1179}
1180
1181/*!
1182 * @brief Process a scan confirmation
1183 *
1184 * @param p - dispatch table entry
1185 * @param pMsg - the message to process.
1186 */
1187static void process_areq_scan_cnf(const struct mt_msg_dispatch *p,
1188 struct mt_msg *pMsg)
1189{
1190 int x;
1191 ApiMac_panDesc_t *pPD;
1192 ApiMac_mlmeScanCnf_t indication;
1193 uint8_t *pU8;
1194
1195 (void)(p);
1196
1197 pU8 = NULL;
1198 pPD = NULL;
1199
1200 memset((void *)(&indication), 0, sizeof(indication));
1201
1202 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
1203
1204 indication.scanType = MT_MSG_rdU8_DBG(pMsg, "scanType");
1205 indication.channelPage = MT_MSG_rdU8_DBG(pMsg, "channelPage");
1206 indication.phyId = MT_MSG_rdU8_DBG(pMsg, "phyId");
1207 MT_MSG_rdBuf_DBG(pMsg, (void *)(indication.unscannedChannels), 17, "unscannedchannels");
1208 indication.resultListSize = MT_MSG_rdU8_DBG(pMsg, "resultListSize");
1209
1210 switch(indication.scanType)
1211 {
1212 default:
1213 LOG_printf(LOG_ERROR,
1214 "areq-scan-cnf unknown type: %d\n",
1215 indication.scanType);
1216 pMsg->is_error = true;
1217 break;
1218 case ApiMac_scantype_orphan:
1219 if(indication.resultListSize)
1220 {
1221 MT_MSG_log(LOG_ERROR, pMsg, "orphan scan size not zero?\n");
1222 }
1223 break;
1224 case ApiMac_scantype_energyDetect:
1225 pU8 = (uint8_t *)api_mac_callocMem(pMsg,
1226 "scan result",
1227 indication.resultListSize + 1,
1228 sizeof(uint8_t));
1229 indication.result.pEnergyDetect = pU8;
1230 if(pMsg->is_error)
1231 {
1232 break;
1233 }
1234 MT_MSG_rdBuf_DBG(pMsg,
1235 (void *)(pU8),
1236 indication.resultListSize,
1237 "energydata");
1238 break;
1239 case ApiMac_scantype_activeEnhanced:
1240 case ApiMac_scantype_active:
1241 case ApiMac_scantype_passive:
1242 pPD = (ApiMac_panDesc_t *)api_mac_callocMem(
1243 pMsg,
1244 "scan result",
1245 indication.resultListSize + 1,
1246 sizeof(*indication.result.pPanDescriptor));
1247
1248 indication.result.pPanDescriptor = pPD;
1249 if(pMsg->is_error)
1250 {
1251 break;
1252 }
1253 for(x = 0; x < indication.resultListSize; x++)
1254 {
1255 api_rd_panDesc(pMsg, pPD + x);
1256 }
1257 break;
1258 }
1259
1260 /* did we properly parse this? */
1261 MT_MSG_parseComplete(pMsg);
1262
1263 if(!pMsg->is_error)
1264 {
1265 if(pApiMac_callbacks->pScanCnfCb)
1266 {
1267 (*(pApiMac_callbacks->pScanCnfCb))(&indication);
1268 }
1269 }
1270 if(pPD)
1271 {
1272 api_mac_freeMem((void *)(pPD));
1273 pPD = NULL;
1274 }
1275
1276 if(pU8)
1277 {
1278 api_mac_freeMem((void *)(pU8));
1279 }
1280}
1281
1282/*!
1283 * @brief Process a communications status indication
1284 *
1285 * @param p - dispatch table entry
1286 * @param pMsg - the message to process.
1287 */
1288static void process_areq_comm_status_ind(const struct mt_msg_dispatch *p,
1289 struct mt_msg *pMsg)
1290{
1291 ApiMac_mlmeCommStatusInd_t indication;
1292
1293 (void)(p);
1294
1295 memset((void *)(&indication), 0, sizeof(indication));
1296
1297 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
1298 decode_Addr(pMsg, &indication.srcAddr);
1299 decode_Addr(pMsg, &indication.dstAddr);
1300 indication.panId = MT_MSG_rdU16_DBG(pMsg, "panID");
1301 indication.reason = MT_MSG_rdU8_DBG(pMsg, "reason");
1302 decode_Sec(pMsg, &indication.sec);
1303
1304 MT_MSG_parseComplete(pMsg);
1305 if(pMsg->is_error)
1306 {
1307 return;
1308 }
1309
1310 if(pApiMac_callbacks->pCommStatusCb)
1311 {
1312 (*(pApiMac_callbacks->pCommStatusCb))(&indication);
1313 }
1314}
1315
1316/*!
1317 * @brief Process a start confirmation
1318 *
1319 * @param p - dispatch table entry
1320 * @param pMsg - the message to process.
1321 */
1322static void process_areq_start_cnf(const struct mt_msg_dispatch *p,
1323 struct mt_msg *pMsg)
1324{
1325 ApiMac_mlmeStartCnf_t indication;
1326
1327 (void)(p);
1328
1329 memset((void *)(&indication), 0, sizeof(indication));
1330
1331 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
1332
1333 MT_MSG_parseComplete(pMsg);
1334 if(pMsg->is_error)
1335 {
1336 return;
1337 }
1338
1339 if(pApiMac_callbacks->pStartCnfCb)
1340 {
1341 (*(pApiMac_callbacks->pStartCnfCb))(&indication);
1342 }
1343}
1344
1345/*!
1346 * @brief Process a WiSun async confirm
1347 *
1348 * @param p - dispatch table entry
1349 * @param pMsg - the message to process.
1350 */
1351static void process_areq_ws_async_cnf(const struct mt_msg_dispatch *p,
1352 struct mt_msg *pMsg)
1353{
1354 ApiMac_mlmeWsAsyncCnf_t indication;
1355
1356 (void)(p);
1357
1358 memset((void *)(&indication), 0, sizeof(indication));
1359
1360 indication.status = MT_MSG_rdU8_DBG(pMsg, "status");
1361
1362 MT_MSG_parseComplete(pMsg);
1363 if(pMsg->is_error)
1364 {
1365 return;
1366 }
1367
1368 if(pApiMac_callbacks->pWsAsyncCnfCb)
1369 {
1370 (*(pApiMac_callbacks->pWsAsyncCnfCb))(&indication);
1371 }
1372}
1373
1374/*!
1375 * @brief Process a WiSun async indication.
1376 *
1377 * @param p - dispatch table entry
1378 * @param pMsg - the message to process.
1379 */
1380static void process_areq_ws_async_ind(const struct mt_msg_dispatch *p,
1381 struct mt_msg *pMsg)
1382{
1383 ApiMac_mlmeWsAsyncInd_t indication;
1384
1385 (void)(p);
1386
1387 memset((void *)(&indication), 0, sizeof(indication));
1388
1389 decode_Addr(pMsg, &indication.srcAddr);
1390 decode_Addr(pMsg, &indication.dstAddr);
1391 indication.timestamp = MT_MSG_rdU32_DBG(pMsg, "timestamp");
1392 indication.timestamp2 = MT_MSG_rdU16_DBG(pMsg, "timestamp2");
1393 indication.srcPanId = MT_MSG_rdU16_DBG(pMsg, "src-pan-id");
1394 indication.dstPanId = MT_MSG_rdU16_DBG(pMsg, "dst-pan-id");
1395 indication.mpduLinkQuality = MT_MSG_rdU8_DBG(pMsg, "mdpu-link-quality");
1396 indication.correlation = MT_MSG_rdU8_DBG(pMsg, "correlation");
1397 indication.rssi = MT_MSG_rdU8_DBG(pMsg, "rssi");
1398 indication.dsn = MT_MSG_rdU8_DBG(pMsg, "dsn");
1399 decode_Sec(pMsg, &(indication.sec));
1400 indication.frameCntr = MT_MSG_rdU32_DBG(pMsg, "framecntr");
1401 indication.fhFrameType = MT_MSG_rdU8_DBG(pMsg,"frameType" );
1402 // indication.fhProtoDispatch = MT_MSG_rdU8_DBG(pMsg, "fh-protodisptch");
1403 indication.msdu.len = MT_MSG_rdU16_DBG(pMsg, "msdu-len");
1404 indication.payloadIeLen = MT_MSG_rdU16_DBG(pMsg, "payload-ie-len" );
1405
1406 if(indication.msdu.len)
1407 {
1408 indication.msdu.p = api_mac_callocMem(pMsg,
1409 "ws_async_ind",
1410 indication.msdu.len,
1411 sizeof(uint8_t));
1412 MT_MSG_rdBuf_DBG(pMsg, (void *)(indication.msdu.p),
1413 indication.msdu.len,
1414 "msdu.data");
1415 }
1416 if(indication.payloadIeLen)
1417 {
1418 indication.pPayloadIE = api_mac_callocMem(pMsg,
1419 "ws_async_ind",
1420 indication.payloadIeLen,
1421 sizeof(uint8_t));
1422 MT_MSG_rdBuf_DBG(pMsg,
1423 (void *)(indication.pPayloadIE),
1424 indication.payloadIeLen, "payload");
1425
1426 }
1427
1428 MT_MSG_parseComplete(pMsg);
1429 if(!pMsg->is_error)
1430 {
1431 if(pApiMac_callbacks->pWsAsyncIndCb)
1432 {
1433 (*(pApiMac_callbacks->pWsAsyncIndCb))(&indication);
1434 }
1435 }
1436 if(indication.msdu.p)
1437 {
1438 api_mac_freeMem((void *)indication.msdu.p);
1439 indication.msdu.p = NULL;
1440 }
1441 if(indication.pPayloadIE)
1442 {
1443 api_mac_freeMem((void *)(indication.pPayloadIE));
1444 indication.pPayloadIE = NULL;
1445 }
1446}
1447
1448/*!
1449 * @brief process a poll indication.
1450 * @param pMsg - the message
1451 */
1452static void process_areq_poll_ind(const struct mt_msg_dispatch *p,
1453 struct mt_msg *pMsg)
1454{
1455 ApiMac_mlmePollInd_t indication;
1456
1457 (void)(p);
1458
1459 decode_Addr(pMsg, &indication.srcAddr);
1460 indication.srcPanId = MT_MSG_rdU16_DBG(pMsg, "srcPanId");
1461 indication.noRsp = MT_MSG_rdU8_DBG(pMsg, "noRsp") ? true : false;
1462
1463 MT_MSG_parseComplete(pMsg);
1464 if(pMsg->is_error)
1465 {
1466 return;
1467 }
1468 if(pApiMac_callbacks->pPollIndCb)
1469 {
1470 (*(pApiMac_callbacks->pPollIndCb))(&indication);
1471 }
1472}
1473
1474/*!
1475 * @brief process a reset indication
1476 * @param pMsg - the message
1477 */
1478static void process_areq_reset_ind(const struct mt_msg_dispatch *p,
1479 struct mt_msg *pMsg)
1480{
1481 ApiMac_mcpsResetInd_t indication;
1482 const char *r_str;
1483 int transport;
1484 int product;
1485 int major;
1486 int minor;
1487 int maint;
1488
1489 (void)(p);
1490
1491 memset((void *)(&indication), 0, sizeof(indication));
1492
1493 indication.reason = MT_MSG_rdU8_DBG(pMsg, "reason");
1494
1495 /* Log reset reason */
1496 switch( indication.reason )
1497 {
1498 default: r_str = "unknown"; break;
1499 case ApiMac_resetReason_hardware: r_str = "hardware"; break;
1500 case ApiMac_resetReason_hostReq: r_str = "host-req"; break;
1501 case ApiMac_resetReason_halAssert: r_str = "hal-assert"; break;
1502 case ApiMac_resetReason_macAssert: r_str = "mac-assert"; break;
1503 case ApiMac_resetReason_rtosAssert: r_str = "rtos-assert"; break;
1504 }
1505
1506 transport = MT_MSG_rdU8_DBG( pMsg, "transport" );
1507 product = MT_MSG_rdU8_DBG( pMsg, "product" );
1508 major = MT_MSG_rdU8_DBG( pMsg, "major" );
1509 minor = MT_MSG_rdU8_DBG( pMsg, "minor" );
1510 maint = MT_MSG_rdU8_DBG( pMsg, "maint" );
1511
1512 MT_MSG_log( LOG_ALWAYS, pMsg,
1513 "Reset Indication: reason: %d (%s) version: %d/%d/%d/%d/%d\n",
1514 indication.reason,
1515 r_str,
1516 transport,
1517 product,
1518 major,
1519 minor,
1520 maint );
1521
1522 /* Verify entire message has been parsed */
1523 MT_MSG_parseComplete(pMsg);
1524 if(pMsg->is_error)
1525 {
1526 return;
1527 }
1528
1529 if(pApiMac_callbacks->pResetIndCb)
1530 {
1531 (*(pApiMac_callbacks->pResetIndCb))(&indication);
1532 }
1533}
1534
1535/*!
1536 * @brief Internal function to process/handle messages.
1537 *
1538 * @param pMsg - the message to process
1539 */
1540static void process_areq(struct mt_msg *pMsg)
1541{
1542 const struct mt_msg_dispatch *p;
1543
1544 /* Lookup table to dispatch messages */
1545 static const struct mt_msg_dispatch lut[] = {
1546 {
1547 .cmd0 = MAC_SYNC_LOSS_IND_cmd0,
1548 .cmd1 = MAC_SYNC_LOSS_IND_cmd1,
1549 .dbg_prefix = "sync-loss-ind" ,
1550 .pHandler = process_areq_sync_loss_ind
1551 },
1552 {
1553 .cmd0 = MAC_ASSOCIATE_IND_cmd0,
1554 .cmd1 = MAC_ASSOCIATE_IND_cmd1,
1555 .dbg_prefix = "associate-ind" ,
1556 .pHandler = process_areq_associate_ind
1557 },
1558 {
1559 .cmd0 = MAC_ASSOCIATE_CNF_cmd0,
1560 .cmd1 = MAC_ASSOCIATE_CNF_cmd1,
1561 .dbg_prefix = "associate-cnf" ,
1562 .pHandler = process_areq_associate_cnf
1563 },
1564 {
1565 .cmd0 = MAC_BEACON_NOTIFY_IND_cmd0,
1566 .cmd1 = MAC_BEACON_NOTIFY_IND_cmd1,
1567 .dbg_prefix = "beacon-notify" ,
1568 .pHandler = process_areq_beacon_notify },
1569 {
1570 .cmd0 = MAC_DATA_CNF_cmd0,
1571 .cmd1 = MAC_DATA_CNF_cmd1,
1572 .dbg_prefix = "data-cnf" ,
1573 .pHandler = process_areq_data_cnf },
1574 {
1575 .cmd0 = MAC_DATA_IND_cmd0,
1576 .cmd1 = MAC_DATA_IND_cmd1,
1577 .dbg_prefix = "data-ind" ,
1578 .pHandler = process_areq_data_ind
1579 },
1580 {
1581 .cmd0 = MAC_DISASSOCIATE_IND_cmd0,
1582 .cmd1 = MAC_DISASSOCIATE_IND_cmd1,
1583 .dbg_prefix = "disassociate-ind" ,
1584 .pHandler = process_areq_disassociate_ind
1585 },
1586 {
1587 .cmd0 = MAC_DISASSOCIATE_CNF_cmd0,
1588 .cmd1 = MAC_DISASSOCIATE_CNF_cmd1,
1589 .dbg_prefix = "disassociate-cnf" ,
1590 .pHandler = process_areq_disassociate_cnf
1591 },
1592
1593 /* 0x88- not used */
1594 /* 0x89- not used */
1595
1596 {
1597 .cmd0 = MAC_ORPHAN_IND_cmd0,
1598 .cmd1 = MAC_ORPHAN_IND_cmd1,
1599 .dbg_prefix = "orphan-ind" ,
1600 .pHandler = process_areq_orphan_ind
1601 },
1602 {
1603 .cmd0 = MAC_POLL_CNF_cmd0,
1604 .cmd1 = MAC_POLL_CNF_cmd1,
1605 .dbg_prefix = "poll-cnf" ,
1606 .pHandler = process_areq_poll_cnf
1607 },
1608 {
1609 .cmd0 = MAC_SCAN_CNF_cmd0,
1610 .cmd1 = MAC_SCAN_CNF_cmd1,
1611 .dbg_prefix = "scan-cnf" ,
1612 .pHandler = process_areq_scan_cnf
1613 },
1614 {
1615 .cmd0 = MAC_COMM_STATUS_IND_cmd0,
1616 .cmd1 = MAC_COMM_STATUS_IND_cmd1,
1617 .dbg_prefix = "status-ind" ,
1618 .pHandler = process_areq_comm_status_ind
1619 },
1620 {
1621 .cmd0 = MAC_START_CNF_cmd0,
1622 .cmd1 = MAC_START_CNF_cmd1,
1623 .dbg_prefix = "start-cnf" ,
1624 .pHandler = process_areq_start_cnf
1625 },
1626 /* 0x8f - not used */
1627 {
1628 .cmd0 = MAC_PURGE_CNF_cmd0,
1629 .cmd1 = MAC_PURGE_CNF_cmd1,
1630 .dbg_prefix = "purge-cnf" ,
1631 .pHandler = process_areq_purge_cnf
1632 },
1633 {
1634 .cmd0 = MAC_POLL_IND_cmd0,
1635 .cmd1 = MAC_POLL_IND_cmd1,
1636 .dbg_prefix = "poll-ind" ,
1637 .pHandler = process_areq_poll_ind
1638 },
1639 {
1640 .cmd0 = MAC_WS_ASYNC_CNF_cmd0,
1641 .cmd1 = MAC_WS_ASYNC_CNF_cmd1,
1642 .dbg_prefix = "ws-async-cnf" ,
1643 .pHandler = process_areq_ws_async_cnf
1644 },
1645 {
1646 .cmd0 = MAC_WS_ASYNC_IND_cmd0,
1647 .cmd1 = MAC_WS_ASYNC_IND_cmd1,
1648 .dbg_prefix = "ws-async-ind" ,
1649 .pHandler = process_areq_ws_async_ind
1650 },
1651 {
1652 .cmd0 = SYS_RESET_IND_cmd0,
1653 .cmd1 = SYS_RESET_IND_cmd1,
1654 .dbg_prefix = "reset-indication" ,
1655 .pHandler = process_areq_reset_ind
1656 },
1657 /* terminate */
1658 { .pHandler = NULL }
1659 };
1660
1661 if(pApiMac_callbacks == NULL)
1662 {
1663 MT_MSG_log(LOG_ERROR, pMsg, "no-callbacks\n");
1664 return;
1665 }
1666
1667 p = lut;
1668
1669 while(p->pHandler)
1670 {
1671 if((p->cmd0 == (pMsg->cmd0 & 0x7F)) && (p->cmd1 == pMsg->cmd1))
1672 {
1673 break;
1674 }
1675 p++;
1676 }
1677 if(p->pHandler)
1678 {
1679 pMsg->pLogPrefix = p->dbg_prefix;
1680 LOG_printf(LOG_DBG_MT_MSG_traffic,
1681 "%s: rx: %s\n",
1682 pMsg->pSrcIface->dbg_name,
1683 pMsg->pLogPrefix);
1684 MT_MSG_log(LOG_DBG_MT_MSG_areq, pMsg, "process-areq\n");
1685 (*(p->pHandler))(p, pMsg);
1686 }
1687 else
1688 {
1689 pMsg->pLogPrefix = "unknown-areq";
1690
1691 MT_MSG_log(LOG_DBG_MT_MSG_areq, pMsg, "***UNKNOWN AREQ***\n");
1692 LOG_hexdump(LOG_DBG_MT_MSG_areq, 0, pMsg->iobuf, pMsg->iobuf_nvalid);
1693
1694 /* an AREQ we do not know/understand. */
1695 if(pApiMac_callbacks)
1696 {
1697 if(pApiMac_callbacks->pUnprocessedCb)
1698 {
1699 pApiMac_callbacks->pUnprocessedCb(0, 0, (void *)(pMsg));
1700 }
1701 }
1702 }
1703}
1704
1705/*!
1706 Process at most one incoming messages
1707 Public function defined in api_mac.h
1708*/
1709void ApiMac_processIncoming(void)
1710{
1711 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
1712
1713 struct mt_msg *pMsg;
1714
1715 pMsg = MT_MSG_LIST_remove(API_MAC_msg_interface,
1716 &(API_MAC_msg_interface->rx_list),
1717 ApiMacLinux_areq_timeout_mSecs);
1718
1719 if(pMsg == NULL)
1720 {
1721 LOG_printf(LOG_DBG_API_MAC_wait, "no-msg\n");
1722 return;
1723 }
1724
1725 /* process the message */
1726 if(pMsg->m_type == MT_MSG_TYPE_areq|| pMsg->m_type == MT_MSG_TYPE_areq_frag_data)
1727 {
1728 process_areq(pMsg);
1729 }
1730 else
1731 {
1732 /* embedded code passes:
1733 src
1734 0
1735 pointer to message.
1736
1737 We have no specific source, so we set src=0
1738 */
1739 MT_MSG_log(LOG_ERROR, pMsg, "unprocessed-msg\n");
1740 if(pApiMac_callbacks)
1741 {
1742 if(pApiMac_callbacks->pUnprocessedCb)
1743 {
1744 pApiMac_callbacks->pUnprocessedCb(0, 0, (void *)(pMsg));
1745 }
1746 }
1747 }
1748 MT_MSG_free(pMsg);
1749}
1750
1751/*!
1752 * @brief send reset command and await response from CoProcessor
1753 */
1754static void resetCoPDevice(void)
1755{
1756 struct mt_msg *pMsg;
1757 uint8_t resetAttempt = 0;
1758
1759 /* Send reset request */
1760 MT_MSG_reset(API_MAC_msg_interface, 1);
1761
1762 while (resetAttempt < MAX_MSGS_PROCESSED_POST_RESET)
1763 {
1764 /* Wait for incoming message */
1765 pMsg = MT_MSG_LIST_remove(API_MAC_msg_interface,
1766 &(API_MAC_msg_interface->rx_list),
1767 ApiMacLinux_areq_timeout_mSecs);
1768
1769 /* Attempt again if reset response not received */
1770 if((NULL == pMsg) ||
1771 (0x41 != (pMsg->cmd0 & 0x7F)) || (0x80 != pMsg->cmd1))
1772 {
1773 resetAttempt++;
1774 MT_MSG_free(pMsg);
1775 }
1776 else
1777 {
1778 MT_MSG_log( LOG_DBG_MT_MSG_traffic, pMsg, "Reset Indication: CoP init\n");
1779 MT_MSG_free(pMsg);
1780 break;
1781 }
1782 }
1783
1784 if(MAX_MSGS_PROCESSED_POST_RESET == resetAttempt)
1785 {
1786 FATAL_printf("No reset response received after device reset\n");
1787 }
1788}
1789
1790/*!
1791 Initialize this MT MSG interface.
1792*/
1793static void *createInterface(void)
1794{
1795 int r;
1796
1797 MT_MSG_init();
1798
1799 if( API_MAC_msg_interface == NULL )
1800 {
1801 BUG_HERE("msg interface not specified(NULL)\n");
1802 }
1803
1804 r = MT_MSG_interfaceCreate(API_MAC_msg_interface);
1805 if(r != 0)
1806 {
1807 FATAL_printf("Cannot init interface (%d)\n", r);
1808 }
1809
1810 /* Reset device for initialization */
1811 resetCoPDevice();
1812
1813 /* We return "other" list semaphore.
1814 When we get an AREQ, we post here
1815 If some external event occurs
1816 We let the caller post here also
1817 */
1818 return ((void *)(API_MAC_msg_interface->rx_list.sem));
1819}
1820
1821/*!
1822 * @brief Convert API txOptions to bitmasked txOptions.
1823 *
1824 * @param txOptions - tx options structure
1825 * @return bitmasked txoptions
1826 */
1827static uint16_t convertTxOptions(ApiMac_txOptions_t *txOptions)
1828{
1829 uint16_t retVal = 0;
1830
1831 if(txOptions->ack == true)
1832 {
1833 retVal |= MAC_TXOPTION_ACK;
1834 }
1835 if(txOptions->indirect == true)
1836 {
1837 retVal |= MAC_TXOPTION_INDIRECT;
1838 }
1839 if(txOptions->pendingBit == true)
1840 {
1841 retVal |= MAC_TXOPTION_PEND_BIT;
1842 }
1843 if(txOptions->noRetransmits == true)
1844 {
1845 retVal |= MAC_TXOPTION_NO_RETRANS;
1846 }
1847 if(txOptions->noConfirm == true)
1848 {
1849 retVal |= MAC_TXOPTION_NO_CNF;
1850 }
1851 if(txOptions->useAltBE == true)
1852 {
1853 retVal |= MAC_TXOPTION_ALT_BE;
1854 }
1855 if(txOptions->usePowerAndChannel == true)
1856 {
1857 retVal |= MAC_TXOPTION_PWR_CHAN;
1858 }
1859
1860 return (retVal);
1861}
1862
1863/*!
1864 * @brief Internal function to send a synchronous request expecting a status
1865 *
1866 * @param pMsg - the message to send.
1867 * @return the status byte code returned from the remote end.
1868 *
1869 * Note: This routine also frees both messsages (tx and response)
1870 */
1871static int API_MAC_TxRx_Status(struct mt_msg *pMsg)
1872{
1873 int r;
1874
1875 r = MT_MSG_txrx(pMsg);
1876
1877 /* We should get 2 back.
1878 1 = we transmitted a message
1879 1 = we rx'ed a message
1880 =====
1881 1+1 = 2 = success
1882 */
1883 if(r != 2)
1884 {
1885 /* Something is wrong... */
1886 r = ApiMac_status_badState;
1887 goto fail;
1888 }
1889
1890 /* Got response */
1891 /* status is a single byte. */
1892 r = MT_MSG_rdU8_DBG(pMsg->pSrsp, "status");
1893 /* we should be done now */
1894 MT_MSG_parseComplete(pMsg->pSrsp);
1895
1896 /* anything wrong? */
1897 if(pMsg->is_error || pMsg->pSrsp->is_error)
1898 {
1899 r = ApiMac_status_invalidParameter;
1900 }
1901 LOG_printf(LOG_DBG_MT_MSG_traffic,
1902 "SREQ: (%s) SRSP: Result: %d (0x%02x)\n",
1903 pMsg->pLogPrefix, r, r);
1904fail:
1905 MT_MSG_free(pMsg);
1906 return (r);
1907}
1908
1909/*!
1910 * @brief Allocate a new message
1911 * @param len - expected payload length, or -1 if unknown
1912 * @param cmd0 - cmd0 value
1913 * @param cmd1 - cmd1 value
1914 * @return pointer to an allocated message, or NULL if no memory
1915 */
1916static struct mt_msg *api_new_msg(int len, int cmd0,
1917 int cmd1,
1918 const char *dbg_prefix)
1919{
1920 struct mt_msg *pMsg;
1921
1922 pMsg = MT_MSG_alloc(len, cmd0, cmd1);
1923 if(pMsg)
1924 {
1925 pMsg->pLogPrefix = dbg_prefix;
1926 MT_MSG_setSrcIface(pMsg, NULL);
1927 MT_MSG_setDestIface(pMsg, API_MAC_msg_interface);
1928 }
1929 return (pMsg);
1930}
1931
1932/*!
1933 This function sends application data to the MAC for
1934 transmission in a MAC data frame.
1935
1936 Public function defined in api_mac.h
1937*/
1938ApiMac_status_t ApiMac_mcpsDataReq(ApiMac_mcpsDataReq_t *pData)
1939{
1940
1941 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
1942
1943 struct mt_msg *pMsg;
1944 int n;
1945 n = 0x23;
1946 n = n + pData->msdu.len;
1947 n = n + pData->payloadIELen;
1948
1949 pMsg = api_new_msg(n, 0x22, 0x05, "mcpsDataReq");
1950 if(!pMsg)
1951 {
1952 return (ApiMac_status_noResources);
1953 }
1954 encode_Addr(pMsg, &(pData->dstAddr));
1955 MT_MSG_wrU16_DBG(pMsg, pData->dstPanId, "dstPanId");
1956 MT_MSG_wrU8_DBG(pMsg, pData->srcAddrMode , "srcAddrMode");
1957 MT_MSG_wrU8_DBG(pMsg, pData->msduHandle, "msduHandle");
1958 MT_MSG_wrU8_DBG(pMsg, convertTxOptions(&(pData->txOptions)), "txOptions");
1959 MT_MSG_wrU8_DBG(pMsg, pData->channel, "channel");
1960 MT_MSG_wrU8_DBG(pMsg, pData->power, "power");
1961 encode_Sec(pMsg, &(pData->sec));
1962 MT_MSG_wrU32_DBG(pMsg, pData->includeFhIEs, "includeFhIEs");
1963
1964 MT_MSG_wrU16_DBG(pMsg, pData->msdu.len, "msdu.len");
1965 MT_MSG_wrU16_DBG(pMsg, pData->payloadIELen, "payloadIELen");
1966
1967 MT_MSG_wrBuf_DBG(pMsg, pData->msdu.p, pData->msdu.len, "msdu-data");
1968 MT_MSG_wrBuf_DBG(pMsg, pData->pIEList, pData->payloadIELen, "payload-IE");
1969
1970 return (API_MAC_TxRx_Status(pMsg));
1971}
1972
1973/*!
1974 This function purges and discards a data request from the MAC
1975 data queue.
1976
1977 Public function defined in api_mac.h
1978*/
1979ApiMac_status_t ApiMac_mcpsPurgeReq(uint8_t msduHandle)
1980{
1981 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
1982
1983 struct mt_msg *pMsg;
1984
1985 pMsg = api_new_msg(1, 0x22, 0x0e, "mcpsPurgeReq");
1986 if(!pMsg)
1987 {
1988 return (ApiMac_status_noResources);
1989 }
1990
1991 MT_MSG_wrU8_DBG(pMsg, msduHandle, "handle");
1992
1993 return (API_MAC_TxRx_Status(pMsg));
1994}
1995
1996/*!
1997 This function sends an associate request to a coordinator
1998 device.
1999
2000 Public function defined in api_mac.h
2001*/
2002ApiMac_status_t ApiMac_mlmeAssociateReq(ApiMac_mlmeAssociateReq_t *pData)
2003{
2004 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2005
2006 struct mt_msg *pMsg;
2007
2008 pMsg = api_new_msg(0x1a, 0x22, 0x06, "mlmeAssociateReq");
2009 if(pMsg == NULL)
2010 {
2011 return (ApiMac_status_noResources);
2012 }
2013
2014 MT_MSG_wrU8_DBG(pMsg, pData->logicalChannel, "logicalChannel");
2015 MT_MSG_wrU8_DBG(pMsg, pData->channelPage, "channelPage");
2016 MT_MSG_wrU8_DBG(pMsg, pData->phyID, "phyID");
2017 encode_Addr(pMsg, &(pData->coordAddress));
2018 MT_MSG_wrU16_DBG(pMsg, pData->coordPanId, "coordPanId");
2019 MT_MSG_wrU8_DBG(pMsg,
2020 ApiMac_convertCapabilityInfo(
2021 &(pData->capabilityInformation)),
2022 "capabilityInfo");
2023 encode_Sec(pMsg, &(pData->sec));
2024
2025 return (API_MAC_TxRx_Status(pMsg));
2026}
2027
2028/*!
2029 This function is used by an associated device to notify the
2030 coordinator of its intent to leave the PAN.
2031
2032 Public function defined in api_mac.h
2033*/
2034ApiMac_status_t ApiMac_mlmeDisassociateReq(ApiMac_mlmeDisassociateReq_t *pData)
2035{
2036 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2037
2038 struct mt_msg *pMsg;
2039
2040 pMsg = api_new_msg(0x18, 0x22, 0x07, "mlmeDisassociateReq");
2041 if(pMsg == NULL)
2042 {
2043 return (ApiMac_status_noResources);
2044 }
2045
2046 encode_Addr(pMsg, &(pData->deviceAddress));
2047 MT_MSG_wrU16_DBG(pMsg, pData->devicePanId, "panId");
2048 MT_MSG_wrU8_DBG(pMsg, pData->disassociateReason, "reason");
2049 MT_MSG_wrU8_DBG(pMsg, pData->txIndirect , "txIndirect");
2050 encode_Sec(pMsg, &(pData->sec));
2051
2052 return (API_MAC_TxRx_Status(pMsg));
2053}
2054
2055/*!
2056 * @brief Internal common routine to handle all PIB get requests.
2057 *
2058 * @param cmd0 - command 0 value to use
2059 * @param cmd1 - command 1 value to use
2060 * @param att_id - the attribute id
2061 * @param wiresize - transmission size of the item
2062 * @param datasize - variable size of the item
2063 * @param pValue - pointer to the value
2064 *
2065 *
2066 * If the wiresize & data size is positive
2067 * The value is a numeric (byte swap applies)
2068 * else
2069 * (negative) the value is an array of bytes
2070 *
2071 * Also see: API_MAC_Set_Common()
2072 */
2073static int API_MAC_Get_Common(int cmd0,
2074 int cmd1,
2075 int att_id,
2076 int wiresize,
2077 int datasize,
2078 void *pValue)
2079{
2080 int r;
2081 uint64_t v;
2082 struct mt_msg *pMsg;
2083 struct mt_msg *pSrsp;
2084 int l;
2085
2086 v = 0;
2087
2088 /* some attributes are 16bit numbers */
2089 if(att_id > 0x100)
2090 {
2091 l = 2;
2092 }
2093 else
2094 {
2095 l = 1;
2096 }
2097 pMsg = api_new_msg(l, cmd0, cmd1, "pib-get-common");
2098 if(!pMsg)
2099 {
2100 return (ApiMac_status_noResources);
2101 }
2102
2103 if(l == 1)
2104 {
2105 MT_MSG_wrU8_DBG(pMsg, att_id, "pib-id8");
2106 }
2107 else
2108 {
2109 MT_MSG_wrU16_DBG(pMsg, att_id, "pib-id16");
2110 }
2111
2112 // security requests require two index dummy bytes
2113 switch (att_id)
2114 {
2115 /* NOTE: "security" structures are not handled in this function. */
2116 /* Hence they are not listed here */
2117
2118 /* security array of bytes */
2119 case ApiMac_securityAttribute_autoRequestKeySource:
2120 case ApiMac_securityAttribute_defaultKeySource:
2121 case ApiMac_securityAttribute_panCoordExtendedAddress:
2122 /* uint8s */
2123 case ApiMac_securityAttribute_securityLevelTableEntries:
2124 case ApiMac_securityAttribute_autoRequestSecurityLevel:
2125 case ApiMac_securityAttribute_autoRequestKeyIdMode:
2126 case ApiMac_securityAttribute_autoRequestKeyIndex:
2127 /* uint16s */
2128 case ApiMac_securityAttribute_keyTableEntries:
2129 case ApiMac_securityAttribute_deviceTableEntries:
2130 case ApiMac_securityAttribute_panCoordShortAddress:
2131 /* uint32s - there are none */
2132 /* uint64s - there are none */
2133
2134 MT_MSG_wrU16_DBG(pMsg, 0, "idx1-not-used");
2135 MT_MSG_wrU16_DBG(pMsg, 0, "idx2-not-used");
2136 break;
2137 default:
2138 // these do not apply.
2139 break;
2140 }
2141
2142 /* do the transfer */
2143 r = MT_MSG_txrx(pMsg);
2144
2145 if(r != 2)
2146 {
2147 r = ApiMac_status_badState;
2148 goto fail;
2149 }
2150
2151 pSrsp = pMsg->pSrsp;
2152
2153 /* read the status byte */
2154 r = MT_MSG_rdU8_DBG(pSrsp, "status");
2155 if(r != ApiMac_status_success)
2156 {
2157 goto fail;
2158 }
2159
2160 if(wiresize < 0)
2161 {
2162 /* Negative is an array of bytes */
2163 /* so negate the size and call rdBuf */
2164 MT_MSG_rdBuf_DBG(pSrsp, pValue, -wiresize, "data-bytes");
2165 }
2166 else
2167 {
2168 switch(wiresize)
2169 {
2170 default:
2171 BUG_HERE("invalid wiresize: %d\n", wiresize);
2172 break;
2173 case 1:
2174 v = MT_MSG_rdU8_DBG(pSrsp, "pib-value8");
2175 break;
2176 case 2:
2177 v = MT_MSG_rdU16_DBG(pSrsp, "pib-value16");
2178 break;
2179 case 4:
2180 v = MT_MSG_rdU32_DBG(pSrsp, "pib-value32");
2181 break;
2182 case 8:
2183 v = MT_MSG_rdU64_DBG(pSrsp, "pib-value64");
2184 break;
2185 }
2186 }
2187 MT_MSG_parseComplete(pSrsp);
2188
2189 if(pSrsp->is_error)
2190 {
2191 /* something is wrong */
2192 r = ApiMac_status_unsupportedAttribute;
2193 goto fail;
2194 }
2195
2196 if(datasize < 0)
2197 {
2198 /* negative case was handled above, both wire & data size
2199 are either both positive, or both negative */
2200 }
2201 else
2202 {
2203 switch(datasize)
2204 {
2205 default:
2206 BUG_HERE("invalid data: %d\n", wiresize);
2207 break;
2208 case 1:
2209 (*(uint8_t *)(pValue)) = (uint8_t)(v);
2210 break;
2211 case 2:
2212 (*(uint16_t *)(pValue)) = (uint16_t)(v);
2213 break;
2214 case 4:
2215 (*(uint32_t *)(pValue)) = (uint32_t)(v);
2216 break;
2217 case 8:
2218 (*(uint64_t *)(pValue)) = (uint64_t)(v);
2219 break;
2220 }
2221 }
2222 r = ApiMac_status_success;
2223fail:
2224 if(pMsg)
2225 {
2226 MT_MSG_free(pMsg);
2227 }
2228 if( r != ApiMac_status_success )
2229 {
2230 LOG_printf(LOG_ERROR, "*** ERROR ** Set/Get operation failed with status code: 0x%02x\n", r);
2231 }
2232 return (r);
2233}
2234
2235/*!
2236 * @brief Internal common routine to handle all PIB set requests.
2237 *
2238 * @param cmd0 - the command 0 value to use
2239 * @param cmd1 - the command 1 value to use
2240 * @param att_id - the attribute id
2241 * @param wiresize - size of the value on the wire
2242 * @param datasize - size of the value in memory
2243 * @param pValue - pointer to the value
2244 *
2245 * Also see: API_MAC_Get_Common()
2246 */
2247static int API_MAC_Set_Common(int cmd0,
2248 int cmd1,
2249 int att_id,
2250 int wiresize,
2251 uint64_t v)
2252{
2253
2254
2255 struct mt_msg *pMsg;
2256 ApiMac_status_t r;
2257 int n_wrote;
2258 int len;
2259
2260 if(wiresize < 0)
2261 {
2262 BUG_HERE("wrong api use\n");
2263 }
2264 /* +1 for the attribute number */
2265 /* +N for the wiressize */
2266 len = 1;
2267 if( att_id < 0x0100 )
2268 {
2269 /* non-frequency hopping gets filler bytes */
2270 len += 16;
2271 }
2272 else
2273 {
2274 /* frequency hopping *DOES*NOT* get filler bytes */
2275 len += 1; /* All FH attribute ids are 16bit not 8bit */
2276 len += wiresize;
2277 }
2278 pMsg = api_new_msg(len, cmd0, cmd1, "pib-set-common");
2279
2280 if(!pMsg)
2281 {
2282 return (ApiMac_status_noResources);
2283 }
2284
2285 n_wrote = 0;
2286 if(att_id > 0x100)
2287 {
2288 MT_MSG_wrU16_DBG(pMsg, att_id, "pib-id16");
2289 n_wrote += 2;
2290 }
2291 else
2292 {
2293 MT_MSG_wrU8_DBG(pMsg, att_id, "pib-id8");
2294 n_wrote += 1;
2295 }
2296
2297 switch(wiresize)
2298 {
2299 default:
2300 BUG_HERE("invalid wiresize: %d\n", wiresize);
2301 break;
2302 case 1:
2303 MT_MSG_wrU8_DBG(pMsg , (uint8_t)(v), "pib-value8");
2304 n_wrote += 1;
2305 break;
2306 case 2:
2307 MT_MSG_wrU16_DBG(pMsg , (uint16_t)(v), "pib-value16");
2308 n_wrote += 2;
2309 break;
2310 case 4:
2311 MT_MSG_wrU32_DBG(pMsg , (uint32_t)(v), "pib-value32");
2312 n_wrote += 4;
2313 break;
2314 case 8:
2315 MT_MSG_wrU64_DBG(pMsg , (uint64_t)(v), "pib-value64");
2316 n_wrote += 8;
2317 break;
2318 }
2319
2320 // insert filler as required.
2321 while( n_wrote < len ){
2322 MT_MSG_wrU8_DBG(pMsg, 0, "filler");
2323 n_wrote++;
2324 }
2325
2326 r = (API_MAC_TxRx_Status(pMsg));
2327 if( r != ApiMac_status_success )
2328 {
2329 LOG_printf(LOG_ERROR, "**ERROR** Set/Operation failed with status code: 0x%02x\n", r);
2330 }
2331 return (r);
2332}
2333
2334/*!
2335 * @brief Common code to handle a PIB item Get/Set array type.
2336 * @param is_set - true if set operation
2337 * @param cmd0 - the command value
2338 * @param cmd1 - the command value
2339 * @param pib_attribute - the attribute id.
2340 * @param pValue - pointer to the data being transfered.
2341 */
2342static ApiMac_status_t API_MAC_SetGetArray_Common(bool is_set,
2343 int cmd0,
2344 int cmd1,
2345 int pib_attribute,
2346 uint8_t *pValue)
2347{
2348 int n;
2349 struct mt_msg *pMsg;
2350 int wiresize;
2351 int datasize;
2352 bool is_secure;
2353 ApiMac_status_t r;
2354
2355 wiresize = 0;
2356 datasize = 0;
2357
2358 /* Assume it is not a security releated request */
2359 is_secure = false;
2360 switch( pib_attribute )
2361 {
2362 case ApiMac_securityAttribute_autoRequestKeySource:
2363 case ApiMac_securityAttribute_defaultKeySource:
2364 case ApiMac_securityAttribute_panCoordExtendedAddress:
2365 is_secure = true;
2366 break;
2367 default:
2368 is_secure = false;
2369 break;
2370 }
2371
2372 switch (pib_attribute)
2373 {
2374 default:
2375 break;
2376 case ApiMac_attribute_beaconPayload:
2377 wiresize = 16;
2378 datasize = 16;
2379 break;
2380 case ApiMac_securityAttribute_autoRequestKeySource:
2381 case ApiMac_securityAttribute_defaultKeySource:
2382 case ApiMac_securityAttribute_panCoordExtendedAddress:
2383 case ApiMac_attribute_coordExtendedAddress:
2384 case ApiMac_attribute_extendedAddress:
2385 case ApiMac_FHAttribute_trackParentEUI:
2386 wiresize = 8;
2387 datasize = 8;
2388 break;
2389 case ApiMac_FHAttribute_gtk0Hash:
2390 case ApiMac_FHAttribute_gtk1Hash:
2391 case ApiMac_FHAttribute_gtk2Hash:
2392 case ApiMac_FHAttribute_gtk3Hash:
2393 wiresize = APIMAC_FH_GTK_HASH_SIZE;
2394 datasize = APIMAC_FH_GTK_HASH_SIZE;
2395 break;
2396
2397 case ApiMac_FHAttribute_unicastExcludedChannels:
2398 case ApiMac_FHAttribute_broadcastExcludedChannels:
2399 wiresize = APIMAC_FH_MAX_BIT_MAP_SIZE;
2400 break;
2401 case ApiMac_FHAttribute_netName:
2402 wiresize = APIMAC_FH_NET_NAME_SIZE_MAX;
2403 break;
2404 }
2405
2406 if(wiresize == 0)
2407 {
2408 BUG_HERE("unknown attribute id: %d (0x%x)\n", pib_attribute, pib_attribute);
2409 return (ApiMac_status_unsupportedAttribute);
2410 }
2411
2412 if(!is_set)
2413 {
2414 return (API_MAC_Get_Common(cmd0,
2415 cmd1,
2416 pib_attribute,
2417 -wiresize,
2418 -datasize,
2419 pValue));
2420 }
2421 /* sets are different */
2422
2423 /* determine msg length */
2424 n = 0;
2425 if( pib_attribute < 0x100 )
2426 {
2427 n += 1;
2428 }
2429 else
2430 {
2431 n += 2;
2432 }
2433 if( is_secure )
2434 {
2435 n = n + 4;
2436 }
2437 n = n + wiresize;
2438
2439 pMsg = api_new_msg(n, cmd0, cmd1, "pib-getset-array-common");
2440 if(pMsg == NULL)
2441 {
2442 return (ApiMac_status_noResources);
2443 }
2444 if(pib_attribute < 0x100)
2445 {
2446 MT_MSG_wrU8_DBG(pMsg, pib_attribute, "pib-id8");
2447 }
2448 else
2449 {
2450 MT_MSG_wrU16_DBG(pMsg, pib_attribute, "pib-id16");
2451 }
2452 if(is_secure)
2453 {
2454 MT_MSG_wrU16_DBG(pMsg, 0, "idx1-not-used");
2455 MT_MSG_wrU16_DBG(pMsg, 0, "idx2-not-used");
2456 }
2457 MT_MSG_wrBuf_DBG(pMsg, pValue, wiresize, "data-bytes");
2458
2459 r = (API_MAC_TxRx_Status(pMsg));
2460 if( r != ApiMac_status_success )
2461 {
2462 LOG_printf(LOG_ERROR, "**ERROR** Set/Operation failed with status code: 0x%02x\n", r);
2463 }
2464 return (r);
2465}
2466
2467/*!
2468 This function gets an attribute value
2469 in the MAC PIB.
2470
2471 Public function defined in api_mac.h
2472*/
2473ApiMac_status_t ApiMac_mlmeGetReqBool(ApiMac_attribute_bool_t pibAttribute,
2474 bool *pValue)
2475{
2476 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2477
2478 return (API_MAC_Get_Common(0x022,
2479 0x08,
2480 pibAttribute,
2481 1, sizeof(bool),
2482 (void *)(pValue)));
2483}
2484
2485/*!
2486 This function gets an attribute value
2487 in the MAC PIB.
2488
2489 Public function defined in api_mac.h
2490*/
2491ApiMac_status_t ApiMac_mlmeGetReqUint8(ApiMac_attribute_uint8_t pibAttribute,
2492 uint8_t *pValue)
2493{
2494 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2495
2496 return (API_MAC_Get_Common(0x022,
2497 0x08,
2498 pibAttribute,
2499 1,
2500 sizeof(uint8_t),
2501 (void *)(pValue)));
2502}
2503
2504/*!
2505 This function gets an attribute value
2506 in the MAC PIB.
2507
2508 Public function defined in api_mac.h
2509*/
2510ApiMac_status_t ApiMac_mlmeGetReqUint16(ApiMac_attribute_uint16_t pibAttribute,
2511 uint16_t *pValue)
2512{
2513 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2514
2515 return (API_MAC_Get_Common(0x022,
2516 0x08,
2517 pibAttribute,
2518 2,
2519 sizeof(uint16_t),
2520 (void *)(pValue)));
2521}
2522
2523/*!
2524 This function gets an attribute value
2525 in the MAC PIB.
2526
2527 Public function defined in api_mac.h
2528*/
2529ApiMac_status_t ApiMac_mlmeGetReqUint32(ApiMac_attribute_uint32_t pibAttribute,
2530 uint32_t *pValue)
2531{
2532 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2533
2534 return (API_MAC_Get_Common(0x022,
2535 0x08,
2536 pibAttribute,
2537 4,
2538 sizeof(uint32_t),
2539 (void *)(pValue)));
2540}
2541
2542/*!
2543 This function gets an attribute value
2544 in the MAC PIB.
2545
2546 Public function defined in api_mac.h
2547*/
2548ApiMac_status_t ApiMac_mlmeGetReqArray(ApiMac_attribute_array_t pibAttribute,
2549 uint8_t *pValue)
2550{
2551 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2552
2553 return (API_MAC_SetGetArray_Common(false,
2554 0x22,
2555 0x08,
2556 pibAttribute,
2557 (void *)(pValue)));
2558}
2559
2560/*!
2561 This function sets an attribute value
2562 in the MAC PIB.
2563
2564 Public function defined in api_mac.h
2565*/
2566ApiMac_status_t ApiMac_mlmeSetReqArray(ApiMac_attribute_array_t pibAttribute,
2567 uint8_t *pValue)
2568{
2569 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2570
2571 return (API_MAC_SetGetArray_Common(true,
2572 0x22,
2573 0x09,
2574 pibAttribute,
2575 (void *)(pValue)));
2576}
2577
2578/*!
2579 This function gets an attribute value
2580 in the MAC PIB.
2581
2582 Public function defined in api_mac.h
2583*/
2584ApiMac_status_t ApiMac_mlmeGetFhReqUint16(
2585 ApiMac_FHAttribute_uint16_t pibAttribute,
2586 uint16_t *pValue)
2587{
2588 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2589
2590 return (API_MAC_Get_Common(0x22,
2591 0x42,
2592 pibAttribute,
2593 2,
2594 sizeof(uint16_t),
2595 pValue));
2596}
2597
2598/*!
2599 This function gets an attribute value
2600 in the MAC PIB.
2601
2602 Public function defined in api_mac.h
2603*/
2604ApiMac_status_t ApiMac_mlmeGetFhReqUint32(
2605 ApiMac_FHAttribute_uint32_t pibAttribute,
2606 uint32_t *pValue)
2607{
2608 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2609
2610 return (API_MAC_Get_Common(0x22,
2611 0x42,
2612 pibAttribute,
2613 2,
2614 sizeof(uint32_t),
2615 pValue));
2616}
2617
2618ApiMac_status_t ApiMac_mlmeSetFhReqArray(
2619 ApiMac_FHAttribute_array_t pibAttribute, uint8_t *pValue)
2620{
2621 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2622
2623 return (API_MAC_SetGetArray_Common(true, 0x22, 0x43, pibAttribute, pValue));
2624}
2625
2626/*!
2627 This function gets an FH attribute value
2628 in the MAC PIB.
2629
2630 Public function defined in api_mac.h
2631*/
2632ApiMac_status_t ApiMac_mlmeGetFhReqArray(
2633 ApiMac_FHAttribute_array_t pibAttribute, uint8_t *pValue)
2634{
2635 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2636
2637 return (API_MAC_SetGetArray_Common(false,
2638 0x22,
2639 0x42,
2640 pibAttribute,
2641 pValue));
2642}
2643
2644/*!
2645 This function gets an attribute value
2646 in the MAC Security PIB.
2647
2648 Public function defined in api_mac.h
2649*/
2650ApiMac_status_t ApiMac_mlmeGetSecurityReqUint8(
2651 ApiMac_securityAttribute_uint8_t pibAttribute, uint8_t *pValue)
2652{
2653 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2654
2655 return (API_MAC_Get_Common(0x22,
2656 0x30,
2657 pibAttribute,
2658 1,
2659 1,
2660 (void *)(pValue)));
2661}
2662
2663/*!
2664 This function gets an attribute value
2665 in the MAC Security PIB.
2666
2667 Public function defined in api_mac.h
2668*/
2669ApiMac_status_t ApiMac_mlmeGetSecurityReqUint16(
2670 ApiMac_securityAttribute_uint16_t pibAttribute, uint16_t *pValue)
2671{
2672 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2673
2674 return (API_MAC_Get_Common(0x22,
2675 0x30,
2676 pibAttribute,
2677 2,
2678 2,
2679 (void *)(pValue)));
2680}
2681
2682/*!
2683 This function gets an attribute value
2684 in the MAC Security PIB.
2685
2686 Public function defined in api_mac.h
2687*/
2688ApiMac_status_t ApiMac_mlmeGetSecurityReqArray(
2689 ApiMac_securityAttribute_array_t pibAttribute, uint8_t *pValue)
2690{
2691 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
2692
2693 return (API_MAC_SetGetArray_Common(false,
2694 0x22,
2695 0x30,
2696 pibAttribute,
2697 (void *)(pValue)));
2698}
2699
2700/*!
2701 * @brief Handle a pib security attribute key table request
2702 * @param p - security get/set operational details.
2703 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2704 */
2705static void sec_pib_ApiMac_securityAttribute_keyTable(struct secPibStruct *p)
2706{
2707 if(!(p->is_set) || (p->pValue))
2708 {
2709 /* Linux code only supports a NULL here */
2710 LOG_printf(LOG_ERROR, "%s: pib: %d SET and only NULL supported\n",
2711 __FUNCTION__, p->attr);
2712 p->is_error = true;
2713 return;
2714 }
2715 MT_MSG_wrU8_DBG(p->pMsg, p->attr, "addr");
2716 MT_MSG_wrU16_DBG(p->pMsg, 0, "idx1"); /* index1 */
2717 MT_MSG_wrU16_DBG(p->pMsg, 0, "idx2"); /* index2 */
2718
2719 p->n_msgs = MT_MSG_txrx(p->pMsg);
2720 if(p->n_msgs == 2)
2721 {
2722 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
2723 }
2724}
2725
2726
2727/*!
2728 * @brief Handle a pib security attribute key id lookup entry request request
2729 * @param p - security get/set operational details.
2730 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2731 */
2732static void
2733sec_pib_ApiMac_securityAttribute_keyIdLookupEntry(struct secPibStruct *p)
2734{
2735 ApiMac_securityPibKeyIdLookupEntry_t *pSecPibKeyIdLookupEntry;
2736
2737 pSecPibKeyIdLookupEntry =
2738 (ApiMac_securityPibKeyIdLookupEntry_t *)(p->pValue);
2739
2740 MT_MSG_wrU8_DBG(p->pMsg,
2741 p->attr, "attr");
2742 MT_MSG_wrU16_DBG(p->pMsg,
2743 pSecPibKeyIdLookupEntry->keyIndex, "keyIndex"); /* index1 */
2744 MT_MSG_wrU8_DBG(p->pMsg,
2745 pSecPibKeyIdLookupEntry->keyIdLookupIndex, "lookupIndex");
2746
2747 if(p->is_set)
2748 {
2749 MT_MSG_wrBuf_DBG(p->pMsg,
2750 pSecPibKeyIdLookupEntry->lookupEntry.lookupData,
2751 sizeof(pSecPibKeyIdLookupEntry->lookupEntry.lookupData),
2752 "lookupData");
2753 MT_MSG_wrU8_DBG(p->pMsg,
2754 pSecPibKeyIdLookupEntry->lookupEntry.lookupDataSize,
2755 "lookupSize");
2756 }
2757
2758 p->n_msgs = MT_MSG_txrx(p->pMsg);
2759 if(p->n_msgs != 2)
2760 {
2761 return;
2762 }
2763 /* read status byte */
2764 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
2765 if(p->is_set)
2766 {
2767 return;
2768 }
2769
2770 pSecPibKeyIdLookupEntry->keyIndex =
2771 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "keyIndex");
2772 pSecPibKeyIdLookupEntry->keyIdLookupIndex =
2773 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "keyIdLookupIndex");
2774
2775 MT_MSG_rdBuf_DBG(p->pMsg->pSrsp,
2776 pSecPibKeyIdLookupEntry->lookupEntry.lookupData,
2777 sizeof(pSecPibKeyIdLookupEntry->lookupEntry.lookupData),
2778 "lookupData");
2779 pSecPibKeyIdLookupEntry->lookupEntry.lookupDataSize =
2780 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "lookupDataSize");
2781}
2782
2783/*!
2784 * @brief Handle a pib security attribute key device entry request
2785 * @param p - security get/set operational details.
2786 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2787 */
2788static void
2789sec_pib_ApiMac_securityAttribute_keyDeviceEntry(struct secPibStruct *p)
2790{
2791 ApiMac_securityPibKeyDeviceEntry_t *pSecPibKeyDeviceEntry;
2792
2793 pSecPibKeyDeviceEntry = (ApiMac_securityPibKeyDeviceEntry_t *)(p->pValue);
2794
2795 MT_MSG_wrU8_DBG(p->pMsg,
2796 p->attr,
2797 "attr");
2798 MT_MSG_wrU16_DBG(p->pMsg,
2799 pSecPibKeyDeviceEntry->keyIndex,
2800 "keyIndex"); /* index1 */
2801 MT_MSG_wrU16_DBG(p->pMsg,
2802 pSecPibKeyDeviceEntry->keyDeviceIndex,
2803 "keyDeviceIndex"); /* index2 */
2804
2805 if(p->is_set)
2806 {
2807 MT_MSG_wrU16_DBG(p->pMsg,
2808 pSecPibKeyDeviceEntry->deviceEntry.deviceDescriptorHandle,
2809 "descriptorHandle");
2810 MT_MSG_wrU8_DBG(p->pMsg,
2811 pSecPibKeyDeviceEntry->deviceEntry.uniqueDevice,
2812 "uniqueDevice");
2813 MT_MSG_wrU8_DBG(p->pMsg,
2814 pSecPibKeyDeviceEntry->deviceEntry.blackListed,
2815 "blackListed");
2816 }
2817 p->n_msgs = MT_MSG_txrx(p->pMsg);
2818 if(p->n_msgs != 2)
2819 {
2820 return;
2821 }
2822
2823 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
2824 if(p->is_set)
2825 {
2826 return;
2827 }
2828
2829 pSecPibKeyDeviceEntry->keyIndex =
2830 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "idx1"); /* index1 */
2831 pSecPibKeyDeviceEntry->keyDeviceIndex =
2832 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "idx2"); /* index2 */
2833
2834 pSecPibKeyDeviceEntry->deviceEntry.deviceDescriptorHandle =
2835 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "descriptorHandle");
2836 pSecPibKeyDeviceEntry->deviceEntry.uniqueDevice =
2837 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "uniqueDevice");
2838 pSecPibKeyDeviceEntry->deviceEntry.blackListed =
2839 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "blacklisted");
2840}
2841
2842/*!
2843 * @brief handle a pib security key usage entry
2844 * @param p - security get/set operational details.
2845 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2846 */
2847static void
2848sec_pib_ApiMac_securityAttribute_keyUsageEntry(struct secPibStruct *p)
2849{
2850 ApiMac_securityPibKeyUsageEntry_t *pSecPibKeyUsageEntry;
2851
2852 pSecPibKeyUsageEntry = (ApiMac_securityPibKeyUsageEntry_t *)(p->pValue);
2853
2854 MT_MSG_wrU8_DBG(p->pMsg,
2855 p->attr,
2856 "attr");
2857 MT_MSG_wrU16_DBG(p->pMsg,
2858 pSecPibKeyUsageEntry->keyIndex,
2859 "keyIndex"); /* index1 */
2860 MT_MSG_wrU8_DBG(p->pMsg,
2861 pSecPibKeyUsageEntry->keyUsageIndex,
2862 "keyUsageIndex"); /* index2 */
2863
2864 if(p->is_set)
2865 {
2866 MT_MSG_wrU8_DBG(p->pMsg,
2867 pSecPibKeyUsageEntry->usageEntry.frameType,
2868 "frameType");
2869 MT_MSG_wrU8_DBG(p->pMsg,
2870 pSecPibKeyUsageEntry->usageEntry.cmdFrameId,
2871 "cmdframeId");
2872 }
2873
2874 p->n_msgs = MT_MSG_txrx(p->pMsg);
2875 if(p->n_msgs != 2)
2876 {
2877 return;
2878 }
2879
2880 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
2881 if(p->is_set)
2882 {
2883 return;
2884 }
2885
2886 pSecPibKeyUsageEntry->keyIndex =
2887 MT_MSG_rdU16_DBG(p->pMsg->pSrsp,
2888 "keyIndex");
2889 pSecPibKeyUsageEntry->keyUsageIndex =
2890 MT_MSG_rdU8_DBG(p->pMsg->pSrsp,
2891 "keyUsageIndex");
2892
2893 pSecPibKeyUsageEntry->usageEntry.frameType =
2894 MT_MSG_rdU8_DBG(p->pMsg->pSrsp,
2895 "frameType");
2896 pSecPibKeyUsageEntry->usageEntry.cmdFrameId =
2897 MT_MSG_rdU8_DBG(p->pMsg->pSrsp,
2898 "cmdframeId");
2899}
2900
2901/*
2902 * @brief handle a pib key entry request.
2903 * @param p - security get/set operational details.
2904 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2905 */
2906static void sec_pib_ApiMac_securityAttribute_keyEntry(struct secPibStruct *p)
2907{
2908 ApiMac_securityPibKeyEntry_t *pSecPibKeyEntry;
2909
2910 pSecPibKeyEntry = (ApiMac_securityPibKeyEntry_t *)(p->pValue);
2911
2912 MT_MSG_wrU8_DBG(p->pMsg, p->attr, "attr");
2913 /* index1 */
2914 MT_MSG_wrU16_DBG(p->pMsg, pSecPibKeyEntry->keyIndex, "keyIndex");
2915 MT_MSG_wrU8_DBG(p->pMsg, 0, "notused"); /* not used */
2916
2917 if(p->is_set)
2918 {
2919 MT_MSG_wrBuf_DBG(p->pMsg,
2920 pSecPibKeyEntry->keyEntry,
2921 sizeof(pSecPibKeyEntry->keyEntry),
2922 "keyEntry");
2923 MT_MSG_wrU32_DBG(p->pMsg,
2924 pSecPibKeyEntry->frameCounter,
2925 "frameCounter");
2926 }
2927
2928 p->n_msgs = MT_MSG_txrx(p->pMsg);
2929 if(p->n_msgs != 2)
2930 {
2931 return;
2932 }
2933
2934 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
2935 if(p->is_set)
2936 {
2937 return;
2938 }
2939
2940 pSecPibKeyEntry->keyIndex =
2941 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "keyIndex"); /* index1 */
2942 /* toss unused byte */
2943 (void)MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "unused");
2944
2945 MT_MSG_rdBuf_DBG(p->pMsg->pSrsp,
2946 pSecPibKeyEntry->keyEntry,
2947 sizeof(pSecPibKeyEntry->keyEntry),
2948 "keyEntry");
2949 pSecPibKeyEntry->frameCounter =
2950 MT_MSG_rdU32_DBG(p->pMsg->pSrsp,
2951 "frameCounter");
2952}
2953
2954/*!
2955 * @brief handle a pib security key device entry
2956 * @param p - security get/set operational details.
2957 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
2958 */
2959static void sec_pib_ApiMac_securityAttribute_deviceEntry(struct secPibStruct *p)
2960{
2961 int x;
2962
2963 ApiMac_securityPibDeviceEntry_t *pSecPibDeviceEntry;
2964
2965 pSecPibDeviceEntry = (ApiMac_securityPibDeviceEntry_t *)(p->pValue);
2966
2967 MT_MSG_wrU8_DBG(p->pMsg,
2968 p->attr,
2969 "attr");
2970 MT_MSG_wrU8_DBG(p->pMsg,
2971 pSecPibDeviceEntry->deviceIndex,
2972 "deviceIndex"); /* index1 */
2973 MT_MSG_wrU8_DBG(p->pMsg,
2974 0,
2975 "not-used"); /* not used */
2976
2977 if(p->is_set)
2978 {
2979 MT_MSG_wrU16_DBG(p->pMsg,
2980 pSecPibDeviceEntry->deviceEntry.devInfo.panID,
2981 "panID");
2982 MT_MSG_wrU16_DBG(p->pMsg,
2983 pSecPibDeviceEntry->deviceEntry.devInfo.shortAddress,
2984 "shortAddr");
2985 MT_MSG_wrBuf_DBG(p->pMsg,
2986 pSecPibDeviceEntry->deviceEntry.devInfo.extAddress,
2987 sizeof(pSecPibDeviceEntry->deviceEntry.devInfo.extAddress),
2988 "extAddr");
2989 MT_MSG_wrU8_DBG(p->pMsg,
2990 pSecPibDeviceEntry->deviceEntry.exempt,
2991 "exempt");
2992 for(x = 0; x < API_MAX_NODE_KEY_ENTRIES; x++)
2993 {
2994 MT_MSG_wrU32_DBG(p->pMsg,
2995 pSecPibDeviceEntry->deviceEntry.frameCntr[x].frameCounter,
2996 "frameCounter");
2997 MT_MSG_wrU16_DBG(p->pMsg,
2998 pSecPibDeviceEntry->deviceEntry.frameCntr[x].keyIdx,
2999 "keyIdx");
3000 }
3001 }
3002
3003 p->n_msgs = MT_MSG_txrx(p->pMsg);
3004 if(p->n_msgs != 2)
3005 {
3006 return;
3007 }
3008
3009 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
3010 if(p->is_set)
3011 {
3012 return;
3013 }
3014
3015 pSecPibDeviceEntry->deviceIndex =
3016 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "deviceIndex"); /* index1 */
3017 /* toss */
3018 (void)MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "notused"); /* not used */
3019
3020 pSecPibDeviceEntry->deviceEntry.devInfo.panID =
3021 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "panID");
3022 pSecPibDeviceEntry->deviceEntry.devInfo.shortAddress =
3023 MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "shortAddr");
3024 MT_MSG_rdBuf_DBG(p->pMsg->pSrsp,
3025 pSecPibDeviceEntry->deviceEntry.devInfo.extAddress,
3026 sizeof(pSecPibDeviceEntry->deviceEntry.devInfo.extAddress),
3027 "extAddr");
3028
3029 pSecPibDeviceEntry->deviceEntry.exempt =
3030 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "exempt");
3031 for(x = 0; x < API_MAX_NODE_KEY_ENTRIES; x++)
3032 {
3033 pSecPibDeviceEntry->deviceEntry.frameCntr[x].frameCounter =
3034 MT_MSG_rdU32_DBG(p->pMsg->pSrsp,
3035 "frameCounter");
3036 pSecPibDeviceEntry->deviceEntry.frameCntr[x].keyIdx =
3037 MT_MSG_rdU16_DBG(p->pMsg->pSrsp,
3038 "keyIdx");
3039 }
3040}
3041
3042/*!
3043 * @brief handle a pib security level entry
3044 * See common_ApiMac_mlmeGetSetSecurityReqStruct() for details
3045 * @param p - security get/set structure with operational details.
3046 */
3047static void sec_pib_ApiMac_securityAttribute_securityLevelEntry(
3048 struct secPibStruct *p)
3049{
3050 ApiMac_securityPibSecurityLevelEntry_t *pSecLevelEntry;
3051
3052 pSecLevelEntry = (ApiMac_securityPibSecurityLevelEntry_t *)(p->pValue);
3053
3054 MT_MSG_wrU8_DBG(p->pMsg,
3055 p->attr, "attr");
3056 MT_MSG_wrU8_DBG(p->pMsg,
3057 pSecLevelEntry->levelIndex,
3058 "levelIndex");
3059 MT_MSG_wrU8_DBG(p->pMsg,
3060 0,
3061 "notused");
3062 MT_MSG_wrU16_DBG(p->pMsg,
3063 0,
3064 "notused");
3065 if(p->is_set)
3066 {
3067 MT_MSG_wrU8_DBG(p->pMsg,
3068 pSecLevelEntry->levelEntry.frameType,
3069 "frameType");
3070 MT_MSG_wrU8_DBG(p->pMsg,
3071 pSecLevelEntry->levelEntry.commandFrameIdentifier,
3072 "frameIdentifier");
3073 MT_MSG_wrU8_DBG(p->pMsg,
3074 pSecLevelEntry->levelEntry.securityMinimum,
3075 "securityMinimum");
3076 MT_MSG_wrU8_DBG(p->pMsg,
3077 pSecLevelEntry->levelEntry.securityOverrideSecurityMinimum,
3078 "override-security");
3079 }
3080
3081 p->n_msgs = MT_MSG_txrx(p->pMsg);
3082 if(p->n_msgs != 2)
3083 {
3084 return;
3085 }
3086
3087 p->result = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "status");
3088
3089 if(p->is_set)
3090 {
3091 return;
3092 }
3093
3094 pSecLevelEntry->levelIndex = MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "level-index");
3095 /* toss */
3096 (void)MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "ignore");
3097 (void)MT_MSG_rdU16_DBG(p->pMsg->pSrsp, "ignore");
3098
3099 pSecLevelEntry->levelEntry.frameType =
3100 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "frameType");
3101 pSecLevelEntry->levelEntry.commandFrameIdentifier =
3102 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "frameIdentifier");
3103 pSecLevelEntry->levelEntry.securityMinimum =
3104 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "securityMinimum");
3105 pSecLevelEntry->levelEntry.securityOverrideSecurityMinimum =
3106 MT_MSG_rdU8_DBG(p->pMsg->pSrsp, "override-security");
3107}
3108
3109/*!
3110 * @brief Common code to handle security pib get/set for structures.
3111 * specific items are handled via the lookup table [above]
3112 * @param is_set - true if set operation
3113 * @param pibAttribute - the attribute id
3114 * @param pValue - pointer to the value (to save or get)
3115 * @returns status of the get/set request from the device.
3116 */
3117static ApiMac_status_t common_ApiMac_mlmeGetSetSecurityReqStruct(
3118 int is_set,
3119 ApiMac_securityAttribute_struct_t pibAttribute, void *pValue)
3120{
3121 int x;
3122 struct secPibStruct pdata;
3123
3124 /* dispatch table */
3125 static const struct secPibHandler sec_pib_handlers[] =
3126 {
3127 { .attr = ApiMac_securityAttribute_keyTable,
3128 .handler = sec_pib_ApiMac_securityAttribute_keyTable
3129 },
3130 { .attr = ApiMac_securityAttribute_keyIdLookupEntry,
3131 .handler = sec_pib_ApiMac_securityAttribute_keyIdLookupEntry
3132 },
3133 { .attr = ApiMac_securityAttribute_keyDeviceEntry,
3134 .handler = sec_pib_ApiMac_securityAttribute_keyDeviceEntry
3135 },
3136 { .attr = ApiMac_securityAttribute_keyUsageEntry,
3137 .handler = sec_pib_ApiMac_securityAttribute_keyUsageEntry
3138 },
3139 { .attr = ApiMac_securityAttribute_keyEntry,
3140 .handler = sec_pib_ApiMac_securityAttribute_keyEntry
3141 },
3142 { .attr = ApiMac_securityAttribute_deviceEntry,
3143 .handler = sec_pib_ApiMac_securityAttribute_deviceEntry
3144 },
3145 { .attr = ApiMac_securityAttribute_securityLevelEntry,
3146 .handler = sec_pib_ApiMac_securityAttribute_securityLevelEntry
3147 },
3148
3149 /* terminate */
3150 {.attr = 0,.handler = NULL }
3151 };
3152
3153 memset((void *)(&pdata), 0, sizeof(pdata));
3154 pdata.attr = (int)(pibAttribute);
3155 pdata.pValue = pValue;
3156 pdata.is_set = is_set;
3157 pdata.pMsg = api_new_msg(-1,
3158 0x22,
3159 is_set ? 0x31 : 0x30,
3160 "mlmeGetSetSecurityReqStruct");
3161
3162 if(pdata.pMsg == NULL)
3163 {
3164 pdata.result = ApiMac_status_noResources;
3165 goto err;
3166 }
3167
3168 /* look up in the table. */
3169 for(x = 0; sec_pib_handlers[x].handler; x++)
3170 {
3171 if(pdata.attr == sec_pib_handlers[x].attr)
3172 {
3173 break;
3174 }
3175 }
3176
3177 /* do we have a handler? */
3178 if(sec_pib_handlers[x].handler == NULL)
3179 {
3180 pdata.result = ApiMac_status_unsupportedAttribute;
3181 BUG_HERE("unknown atribute: 0x%02x", pdata.attr);
3182 goto err;
3183 }
3184
3185 /* Assume something is wrong.. */
3186 pdata.result = ApiMac_status_invalidParameter;
3187 /* call the handler */
3188 (*(sec_pib_handlers[x].handler))(&pdata);
3189
3190 /* in all get/set cases we should have had 2 transfers. */
3191 if(pdata.n_msgs != 2)
3192 {
3193 /* we had a transfer error */
3194 pdata.is_error = true;
3195 pdata.result = ApiMac_status_badState;
3196 goto err;
3197 }
3198 /* we should have parsed the entire srsp message */
3199 MT_MSG_parseComplete(pdata.pMsg->pSrsp);
3200
3201 /* if we had a tx error or a rx or r-xparse error */
3202 /* we are done.. */
3203 if(pdata.pMsg->is_error || pdata.pMsg->pSrsp->is_error)
3204 {
3205 /* some message had an error */
3206 pdata.is_error = true;
3207 pdata.result = ApiMac_status_badState;
3208 }
3209
3210err:
3211 if(pdata.pMsg)
3212 {
3213 MT_MSG_free(pdata.pMsg);
3214 pdata.pMsg = NULL;
3215 }
3216 /* otherwise we return the status */
3217 if( pdata.result != ApiMac_status_success )
3218 {
3219 LOG_printf(LOG_ERROR, "**ERROR** Set request failed code: 0x%02x\n", pdata.result);
3220 }
3221 return (pdata.result);
3222}
3223
3224/*!
3225 This function gets an attribute value
3226 in the MAC Security PIB.
3227
3228 Public function defined in api_mac.h
3229*/
3230ApiMac_status_t ApiMac_mlmeGetSecurityReqStruct(
3231 ApiMac_securityAttribute_struct_t pibAttribute, void *pValue)
3232{
3233
3234 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3235
3236 return (common_ApiMac_mlmeGetSetSecurityReqStruct(false,
3237 pibAttribute,
3238 pValue));
3239}
3240
3241/*!
3242 This function gets an attribute value
3243 in the MAC PIB.
3244
3245 Public function defined in api_mac.h
3246*/
3247ApiMac_status_t ApiMac_mlmeSetReqBool(ApiMac_attribute_bool_t pibAttribute,
3248 bool value)
3249{
3250 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3251
3252 return (API_MAC_Set_Common(0x22, 0x09, pibAttribute, 1, value));
3253}
3254
3255/*!
3256 This function gets an attribute value
3257 in the MAC PIB.
3258
3259 Public function defined in api_mac.h
3260*/
3261ApiMac_status_t ApiMac_mlmeSetReqUint8(ApiMac_attribute_uint8_t pibAttribute,
3262 uint8_t value)
3263{
3264 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3265
3266 return (API_MAC_Set_Common(0x22, 0x09, pibAttribute, 1, value));
3267}
3268
3269/*!
3270 This function gets an attribute value
3271 in the MAC PIB.
3272
3273 Public function defined in api_mac.h
3274*/
3275ApiMac_status_t ApiMac_mlmeSetReqUint16(
3276 ApiMac_attribute_uint16_t pibAttribute,
3277 uint16_t value)
3278{
3279 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3280
3281 return (API_MAC_Set_Common(0x22, 0x09, pibAttribute, 2, value));
3282}
3283
3284/*!
3285 This function gets an attribute value
3286 in the MAC PIB.
3287
3288 Public function defined in api_mac.h
3289*/
3290ApiMac_status_t ApiMac_mlmeSetReqUint32(
3291 ApiMac_attribute_uint32_t pibAttribute,
3292 uint32_t value)
3293{
3294 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3295
3296 return (API_MAC_Set_Common(0x22, 0x09, pibAttribute, 4, value));
3297}
3298
3299static ApiMac_status_t API_MAC_SetSecurity_Common( int cmd0,
3300 int cmd1,
3301 int att_id,
3302 int wiresize,
3303 uint64_t value )
3304{
3305 struct mt_msg *pMsg;
3306 struct mt_msg *pSrsp;
3307 int l;
3308 int r;
3309
3310 pMsg = api_new_msg(-1, cmd0, cmd1, "pib-getset-secure");
3311 if(!pMsg)
3312 {
3313 return (ApiMac_status_noResources);
3314 }
3315
3316 /* some attributes are 16bit numbers */
3317 if(att_id > 0x100)
3318 {
3319 l = 2;
3320 }
3321 else
3322 {
3323 l = 1;
3324 }
3325
3326 if(l == 1)
3327 {
3328 MT_MSG_wrU8_DBG(pMsg, att_id, "pib-id8");
3329 }
3330 else
3331 {
3332 MT_MSG_wrU16_DBG(pMsg, att_id, "pib-id16");
3333 }
3334 MT_MSG_wrU16_DBG(pMsg, 0, "idx1-not-used");
3335 MT_MSG_wrU16_DBG(pMsg, 0, "idx2-not-used");
3336 switch (wiresize) {
3337 case 1:
3338 MT_MSG_wrU8_DBG(pMsg, (uint8_t)value, "value8");
3339 break;
3340 case 2:
3341 MT_MSG_wrU16_DBG(pMsg, (uint16_t)value, "value16");
3342 break;
3343 case 4:
3344 MT_MSG_wrU32_DBG(pMsg, (uint32_t)value, "value32");
3345 break;
3346 case 8:
3347 MT_MSG_wrU64_DBG(pMsg, value, "value64");
3348 break;
3349 }
3350 /* do the transfer */
3351 r = MT_MSG_txrx(pMsg);
3352
3353 /* Did we transfer 2 messages? */
3354 if(r != 2)
3355 {
3356 r = ApiMac_status_badState;
3357 goto fail;
3358 }
3359
3360 pSrsp = pMsg->pSrsp;
3361
3362 /* read the status byte */
3363 r = MT_MSG_rdU8_DBG(pSrsp, "status");
3364 MT_MSG_parseComplete(pSrsp);
3365 if(pMsg->is_error || pSrsp->is_error)
3366 {
3367 r = ApiMac_status_badState;
3368 }
3369 else
3370 {
3371 r = ApiMac_status_success;
3372 }
3373fail:
3374 if(pMsg)
3375 {
3376 MT_MSG_free(pMsg);
3377 }
3378 if( r != ApiMac_status_success )
3379 {
3380 LOG_printf(LOG_ERROR, "**ERROR** Set/Operation failed with status code: 0x%02x\n", r);
3381 }
3382 return (r);
3383}
3384
3385/*!
3386 This function sets an attribute value
3387 in the MAC Security PIB.
3388
3389 Public function defined in api_mac.h
3390*/
3391ApiMac_status_t ApiMac_mlmeSetSecurityReqUint8(
3392 ApiMac_securityAttribute_uint8_t pibAttribute,
3393 uint8_t value)
3394{
3395 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3396
3397 return (API_MAC_SetSecurity_Common(0x22, 0x31, pibAttribute, 1, value));
3398}
3399
3400/*!
3401 This function sets an attribute value
3402 in the MAC Security PIB.
3403
3404 Public function defined in api_mac.h
3405*/
3406ApiMac_status_t ApiMac_mlmeSetSecurityReqUint16(
3407 ApiMac_securityAttribute_uint16_t pibAttribute,
3408 uint16_t value)
3409{
3410 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3411
3412 return (API_MAC_SetSecurity_Common(0x22, 0x31, pibAttribute, 2, value));
3413}
3414
3415
3416/*!
3417 This function sets an attribute value
3418 in the MAC Security PIB.
3419
3420 Public function defined in api_mac.h
3421*/
3422ApiMac_status_t ApiMac_mlmeSetSecurityReqArray(
3423 ApiMac_securityAttribute_array_t pibAttribute, uint8_t *pValue)
3424{
3425 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3426
3427 return (API_MAC_SetGetArray_Common(true,
3428 0x22,
3429 0x31,
3430 pibAttribute,
3431 (void *)(pValue)));
3432}
3433
3434/*!
3435 This function sets an attribute value
3436 in the MAC Security PIB.
3437
3438 Public function defined in api_mac.h
3439*/
3440ApiMac_status_t ApiMac_mlmeSetSecurityReqStruct(
3441 ApiMac_securityAttribute_struct_t pibAttribute, void *pValue)
3442{
3443 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3444
3445 return (common_ApiMac_mlmeGetSetSecurityReqStruct(true,
3446 pibAttribute,
3447 pValue));
3448}
3449
3450/*!
3451 @brief Sets a parameter in the FH PIB
3452
3453 Public function defined in api_mac.h
3454*/
3455ApiMac_status_t ApiMac_mlmeSetFhReqUint8(
3456 ApiMac_FHAttribute_uint8_t pibAttribute, uint8_t value)
3457{
3458 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3459
3460 return (API_MAC_Set_Common(0x22, 0x43, pibAttribute, 1, value));
3461}
3462
3463/*!
3464 Sets a parameter in the FH PIB
3465
3466 Public function defined in api_mac.h
3467*/
3468ApiMac_status_t ApiMac_mlmeGetFhReqUint8(
3469 ApiMac_FHAttribute_uint8_t pibAttribute, uint8_t *pValue)
3470{
3471 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3472
3473 return (API_MAC_Get_Common(0x22,
3474 0x42,
3475 pibAttribute,
3476 1,
3477 sizeof(uint8_t),
3478 (void *)pValue));
3479}
3480
3481/*!
3482 Sets a parameter in the FH PIB
3483
3484 Public function defined in api_mac.h
3485*/
3486ApiMac_status_t ApiMac_mlmeSetFhReqUint16(
3487 ApiMac_FHAttribute_uint16_t pibAttribute,
3488 uint16_t value)
3489{
3490 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3491
3492 return (API_MAC_Set_Common(0x22, 0x43, pibAttribute, 2, value));
3493}
3494
3495/*!
3496 Sets a parameter in the FH PIB
3497
3498 Public function defined in api_mac.h
3499*/
3500ApiMac_status_t ApiMac_mlmeSetFhReqUint32(
3501 ApiMac_FHAttribute_uint32_t pibAttribute,
3502 uint32_t value)
3503{
3504 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3505
3506 return (API_MAC_Set_Common(0x22, 0x43, pibAttribute, 4, value));
3507}
3508
3509/*!
3510 This function is called in response to an orphan notification
3511 from a peer device.
3512
3513 Public function defined in api_mac.h
3514*/
3515ApiMac_status_t ApiMac_mlmeOrphanRsp(ApiMac_mlmeOrphanRsp_t *pData)
3516{
3517 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3518
3519 struct mt_msg *pMsg;
3520
3521 pMsg = api_new_msg(0x16, 0x22, 0x51, "mlmeOrphanRsp");
3522 if(!pMsg)
3523 {
3524 return (ApiMac_status_noResources);
3525 }
3526
3527 MT_MSG_wrBuf_DBG(pMsg,
3528 (void *)(&pData->orphanAddress[0]),
3529 APIMAC_SADDR_EXT_LEN, "ext-addr");
3530 MT_MSG_wrU16_DBG(pMsg, pData->shortAddress, "shortAddr");
3531 MT_MSG_wrU8_DBG(pMsg, pData->associatedMember, "assocatedMember");
3532 encode_Sec(pMsg, &(pData->sec));
3533
3534 return (API_MAC_TxRx_Status(pMsg));
3535}
3536
3537/*!
3538 This function is used to request pending data from the coordinator.
3539
3540 Public function defined in api_mac.h
3541*/
3542ApiMac_status_t ApiMac_mlmePollReq(ApiMac_mlmePollReq_t *pData)
3543{
3544 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3545
3546 struct mt_msg *pMsg;
3547
3548 pMsg = api_new_msg(0x16, 0x22, 0x0d, "mlmePollReq");
3549 if(pMsg == NULL)
3550 {
3551 return (ApiMac_status_noResources);
3552 }
3553 encode_Addr(pMsg, &(pData->coordAddress));
3554 MT_MSG_wrU16_DBG(pMsg, pData->coordPanId, "panID");
3555 encode_Sec(pMsg, &(pData->sec));
3556
3557 return (API_MAC_TxRx_Status(pMsg));
3558}
3559
3560/*!
3561 This function must be called once at system startup before any other
3562 function in the management API is called.
3563
3564 Public function defined in api_mac.h
3565*/
3566ApiMac_status_t ApiMac_mlmeResetReq(bool setDefaultPib)
3567{
3568 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3569
3570 struct mt_msg *pMsg;
3571
3572 pMsg = api_new_msg(0x01, 0x22, 0x01, "mlmeResetReq");
3573 if(pMsg == NULL)
3574 {
3575 return (ApiMac_status_noResources);
3576 }
3577 MT_MSG_wrU8_DBG(pMsg, setDefaultPib, "resetParam");
3578
3579 return (API_MAC_TxRx_Status(pMsg));
3580}
3581
3582/*!
3583 This function initiates an energy detect, active, passive, or
3584 orphan scan on one or more channels.
3585
3586 Public function defined in api_mac.h
3587*/
3588ApiMac_status_t ApiMac_mlmeScanReq(ApiMac_mlmeScanReq_t *pData)
3589{
3590 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3591
3592 struct mt_msg *pMsg;
3593
3594 pMsg = api_new_msg(23+17, 0x22, 0x0c, "mlmeScanReq");
3595 if(!pMsg)
3596 {
3597 return (ApiMac_status_noResources);
3598 }
3599
3600 MT_MSG_wrU8_DBG(pMsg, pData->scanType , "scanType");
3601 MT_MSG_wrU8_DBG(pMsg, pData->scanDuration , "scanDuration");
3602 MT_MSG_wrU8_DBG(pMsg, pData->channelPage , "channelPage");
3603 MT_MSG_wrU8_DBG(pMsg, pData->phyID , "phyID");
3604 MT_MSG_wrU8_DBG(pMsg, pData->maxResults , "maxResults");
3605 MT_MSG_wrU8_DBG(pMsg, pData->permitJoining, "permitJoining");
3606 MT_MSG_wrU8_DBG(pMsg, pData->linkQuality , "linkQuality");
3607 MT_MSG_wrU8_DBG(pMsg, pData->percentFilter, "percentFilter");
3608 MT_MSG_wrU8_DBG(pMsg, pData->MPMScan , "MPMScan");
3609 MT_MSG_wrU8_DBG(pMsg, pData->MPMScanType , "MPMScantype");
3610 MT_MSG_wrU16_DBG(pMsg, pData->MPMScanDuration, "MPMScanDuration");
3611 encode_Sec(pMsg, &(pData->sec));
3612
3613 MT_MSG_wrBuf_DBG(pMsg, pData->scanChannels, sizeof(pData->scanChannels), "scanChannels");
3614
3615 return (API_MAC_TxRx_Status(pMsg));
3616}
3617
3618/*!
3619 This function is called by a coordinator or PAN coordinator
3620 to start or reconfigure a network.
3621
3622 Public function defined in api_mac.h
3623*/
3624ApiMac_status_t ApiMac_mlmeStartReq(ApiMac_mlmeStartReq_t *pData)
3625{
3626 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3627
3628 struct mt_msg *pMsg;
3629
3630 pMsg = api_new_msg(0x2a + pData->mpmParams.numIEs, 0x22, 0x03, "mlmeStartReq");
3631 if(pMsg == NULL)
3632 {
3633 return (ApiMac_status_noResources);
3634 }
3635
3636 MT_MSG_wrU32_DBG(pMsg, pData->startTime, "startTime");
3637 MT_MSG_wrU16_DBG(pMsg, pData->panId, "panId");
3638 MT_MSG_wrU8_DBG(pMsg, pData->logicalChannel, "logicalChannel");
3639 MT_MSG_wrU8_DBG(pMsg, pData->channelPage, "channelPage");
3640 MT_MSG_wrU8_DBG(pMsg, pData->phyID, "phyID");
3641 MT_MSG_wrU8_DBG(pMsg, pData->beaconOrder, "beaconOrder");
3642 MT_MSG_wrU8_DBG(pMsg, pData->superframeOrder, "superframeOrder");
3643 MT_MSG_wrU8_DBG(pMsg, pData->panCoordinator, "panCoordinator");
3644 MT_MSG_wrU8_DBG(pMsg, pData->batteryLifeExt, "batteryLifeExt");
3645 MT_MSG_wrU8_DBG(pMsg, pData->coordRealignment , "coordRealignment");
3646 encode_Sec(pMsg, &(pData->realignSec));
3647 encode_Sec(pMsg, &(pData->beaconSec));
3648 MT_MSG_wrU8_DBG(pMsg, pData->startFH, "startFH");
3649 MT_MSG_wrU8_DBG(pMsg, pData->mpmParams.eBeaconOrder, "eBeaconOrder");
3650 MT_MSG_wrU8_DBG(pMsg, pData->mpmParams.offsetTimeSlot, "offsetTimeSlot");
3651 MT_MSG_wrU16_DBG(pMsg, pData->mpmParams.NBPANEBeaconOrder, "NBPANEBeaconOrder");
3652 MT_MSG_wrU8_DBG(pMsg, pData->mpmParams.numIEs, "numIEs");
3653 MT_MSG_wrBuf_DBG(pMsg, pData->mpmParams.pIEIDs, pData->mpmParams.numIEs, "ieids");
3654
3655 return (API_MAC_TxRx_Status(pMsg));
3656}
3657
3658/*!
3659 This function requests the MAC to synchronize with the
3660 coordinator by acquiring and optionally tracking its beacons.
3661
3662 Public function defined in api_mac.h
3663*/
3664ApiMac_status_t ApiMac_mlmeSyncReq(ApiMac_mlmeSyncReq_t *pData)
3665{
3666 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3667
3668 struct mt_msg *pMsg;
3669
3670 pMsg = api_new_msg(0x04, 0x22, 0x04, "mlmeSyncReq");
3671 if(pMsg == NULL)
3672 {
3673 return (ApiMac_status_noResources);
3674 }
3675
3676 MT_MSG_wrU8_DBG(pMsg, pData->logicalChannel, "logicalChannel");
3677 MT_MSG_wrU8_DBG(pMsg, pData->channelPage, "channelPage");
3678 MT_MSG_wrU8_DBG(pMsg, pData->trackBeacon, "trackBeacon");
3679 MT_MSG_wrU8_DBG(pMsg, pData->phyID, "phyID");
3680
3681 return (API_MAC_TxRx_Status(pMsg));
3682}
3683
3684/*!
3685 This function returns a random byte from the (internal) random number
3686 generator.
3687
3688 Public function defined in api_mac.h
3689*/
3690uint8_t ApiMac_randomByte(void)
3691{
3692 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3693
3694 return (RAND_DATA_nextByte(&rand_data_source));
3695}
3696
3697/*!
3698 Update Device Table entry and PIB with new Pan Id.
3699
3700 Public function defined in api_mac.h
3701*/
3702ApiMac_status_t ApiMac_updatePanId(uint16_t panId)
3703{
3704 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3705
3706 struct mt_msg *pMsg;
3707
3708 pMsg = api_new_msg(0x02, 0x22, 0x32, "updatePanId");
3709 if(pMsg == NULL)
3710 {
3711 return (ApiMac_status_noResources);
3712 }
3713
3714 MT_MSG_wrU16_DBG(pMsg, panId, "panID");
3715
3716 return (API_MAC_TxRx_Status(pMsg));
3717}
3718
3719/*!
3720 Enable source match for auto ack and pending.
3721
3722 Public function defined in api_mac.h
3723 */
3724ApiMac_status_t ApiMac_srcMatchEnable(void)
3725{
3726 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3727
3728 struct mt_msg *pMsg;
3729
3730 pMsg = api_new_msg(0, 0x22, 0x39, "srcMatchEnable");
3731 if(pMsg == NULL)
3732 {
3733 return (ApiMac_status_noResources);
3734 }
3735 return (API_MAC_TxRx_Status(pMsg));
3736}
3737
3738/*!
3739 This functions handles the WiSUN async request.
3740
3741 Public function defined in api_mac.h
3742*/
3743ApiMac_status_t ApiMac_mlmeWSAsyncReq(ApiMac_mlmeWSAsyncReq_t* pData)
3744{
3745 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3746
3747 struct mt_msg *pMsg;
3748
3749 pMsg = api_new_msg(13+17, 0x22, 0x44, "mlmeWSAsyncReq");
3750 if(pMsg == NULL)
3751 {
3752 return (ApiMac_status_noResources);
3753 }
3754
3755 MT_MSG_wrU8_DBG(pMsg, pData->operation, "operation" );
3756 MT_MSG_wrU8_DBG(pMsg, pData->frameType, "frame-type");
3757 encode_Sec(pMsg, &(pData->sec));
3758 MT_MSG_wrBuf_DBG(pMsg,
3759 (void *)(&(pData->channels[0])),
3760 APIMAC_154G_CHANNEL_BITMAP_SIZ, "chnl-bitmap");
3761
3762 return (API_MAC_TxRx_Status(pMsg));
3763}
3764
3765/*!
3766 This function starts frequency hopping.
3767
3768 Public function defined in api_mac.h
3769*/
3770ApiMac_status_t ApiMac_startFH(void)
3771{
3772 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3773
3774 struct mt_msg *pMsg;
3775
3776 pMsg = api_new_msg(0, 0x22, 0x41, "startFH");
3777 if(pMsg == NULL)
3778 {
3779 return (ApiMac_status_noResources);
3780 }
3781 return (API_MAC_TxRx_Status(pMsg));
3782}
3783
3784/*!
3785 * @brief Common function to parse the payload information element.
3786 *
3787 * @param pPayload - pointer to the buffer with the payload IEs.
3788 * @param payloadLen - length of the buffer with the payload IEs.
3789 * @param pList - pointer to point of place to allocated the link list.
3790 * @param group - true to check for termination IE.
3791 *
3792 * @return ApiMac_status_t
3793 */
3794static ApiMac_status_t parsePayloadIEs(uint8_t *pContent, uint16_t contentLen,
3795 ApiMac_payloadIeRec_t **pList,
3796 bool group)
3797{
3798 ApiMac_payloadIeRec_t* pIe = (ApiMac_payloadIeRec_t*) NULL;
3799 ApiMac_payloadIeRec_t* pTempIe;
3800 uint16_t lenContent = 0;
3801 ApiMac_status_t status = ApiMac_status_success;
3802
3803 if((pContent == NULL) || (contentLen == 0))
3804 {
3805 return (ApiMac_status_noData);
3806 }
3807
3808 /* Initialize the list pointer */
3809 *pList = (ApiMac_payloadIeRec_t*) NULL;
3810
3811 while(lenContent < contentLen)
3812 {
3813 uint16_t hdr;
3814 bool typeLong;
3815 uint8_t ieId;
3816
3817 hdr = MAKE_UINT16(pContent[0], pContent[1]);
3818 pContent += PAYLOAD_IE_HEADER_LEN; /* Move past the header */
3819
3820 typeLong = GET_SUBIE_TYPE(hdr);
3821 if(typeLong)
3822 {
3823 ieId = GET_SUBIE_ID_LONG(hdr);
3824 }
3825 else
3826 {
3827 ieId = GET_SUBIE_ID_SHORT(hdr);
3828 }
3829
3830 if(group)
3831 {
3832 if(!typeLong)
3833 {
3834 /* Only long IE types when parsing Group IEs */
3835 status = ApiMac_status_unsupported;
3836 break;
3837 }
3838
3839 if(ApiMac_payloadIEGroup_term == ieId)
3840 {
3841 /* Termination IE found */
3842 break;
3843 }
3844 }
3845
3846 pTempIe = (ApiMac_payloadIeRec_t *)malloc(
3847 sizeof(ApiMac_payloadIeRec_t));
3848
3849 if(pTempIe)
3850 {
3851 memset(pTempIe, 0, sizeof(ApiMac_payloadIeRec_t));
3852
3853 /* If nothing in the list, add the node first otherwise
3854 add it to the end of the list */
3855 if(*pList == NULL)
3856 {
3857 *pList = pTempIe;
3858 }
3859 else
3860 {
3861 /* pIe should point to the previous node,
3862 since it was allocated in the previous iteration */
3863 pIe->pNext = pTempIe;
3864 }
3865
3866 pIe = pTempIe;
3867 pTempIe = NULL;
3868
3869 /* Fill in the IE information */
3870 pIe->item.ieTypeLong = typeLong;
3871 pIe->item.ieId = ieId;
3872
3873 if(pIe->item.ieTypeLong)
3874 {
3875 pIe->item.ieContentLen = GET_SUBIE_LEN_LONG(hdr);
3876 }
3877 else
3878 {
3879 pIe->item.ieContentLen = GET_SUBIE_LEN_SHORT(hdr);
3880 }
3881 pIe->item.pIEContent = pContent;
3882
3883 /* Update length and pointer */
3884 lenContent += PAYLOAD_IE_HEADER_LEN + pIe->item.ieContentLen;
3885 pContent += pIe->item.ieContentLen;
3886 }
3887 else
3888 {
3889 status = ApiMac_status_noResources;
3890 break;
3891 }
3892 }
3893
3894 if((status != ApiMac_status_success) && (NULL != *pList))
3895 {
3896 /* not successful in parsing all header ie's, free the linked list */
3897 pIe = *pList;
3898 while(NULL != pIe)
3899 {
3900 pTempIe = pIe->pNext;
3901 api_mac_freeMem((void *)pIe);
3902 pIe = pTempIe;
3903 }
3904 *pList = NULL;
3905 }
3906
3907 return (status);
3908}
3909
3910/*!
3911 Parses the payload information elements.
3912
3913 Public function defined in api_mac.h
3914*/
3915ApiMac_status_t ApiMac_parsePayloadGroupIEs(
3916 uint8_t *pPayload, uint16_t payloadLen,
3917 ApiMac_payloadIeRec_t **pList)
3918{
3919 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3920
3921 return (parsePayloadIEs(pPayload, payloadLen, pList, true));
3922}
3923
3924/*!
3925 Parses the payload Sub Information Elements.
3926
3927 Public function defined in api_mac.h
3928*/
3929extern ApiMac_status_t ApiMac_parsePayloadSubIEs(
3930 uint8_t *pContent,
3931 uint16_t contentLen,
3932 ApiMac_payloadIeRec_t **pList)
3933{
3934 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3935
3936 return (parsePayloadIEs(pContent, contentLen, pList, false));
3937}
3938
3939/*!
3940 Free memory allocated by ApiMac.
3941
3942 Public function defined in api_mac.h
3943*/
3944void ApiMac_freeIEList(ApiMac_payloadIeRec_t *pList)
3945{
3946 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3947
3948 /* Loop through the list */
3949 while(pList)
3950 {
3951 ApiMac_payloadIeRec_t *pTmp = pList;
3952
3953 /* Move to the next item in the list */
3954 pList = pTmp->pNext;
3955
3956 /* free the current item */
3957 api_mac_freeMem((void *)pTmp);
3958 }
3959}
3960
3961/*!
3962 Enables the Frequency hopping operation.
3963
3964 Public function defined in api_mac.h
3965*/
3966ApiMac_status_t ApiMac_enableFH(void)
3967{
3968 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3969
3970 struct mt_msg *pMsg;
3971
3972 pMsg = api_new_msg(0, 0x22, 0x40, "enableFH");
3973 if(pMsg == NULL)
3974 {
3975 return (ApiMac_status_noResources);
3976 }
3977 return (API_MAC_TxRx_Status(pMsg));
3978}
3979
3980/*!
3981 Sends the association response to the device
3982
3983 Public function defined in api_mac.h
3984*/
3985ApiMac_status_t ApiMac_mlmeAssociateRsp(ApiMac_mlmeAssociateRsp_t *pData)
3986{
3987 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
3988
3989 struct mt_msg *pMsg;
3990
3991 pMsg = api_new_msg(0x16, 0x22, 0x50, "mlmeAssociateRsp");
3992 if(pMsg == NULL)
3993 {
3994 return (ApiMac_status_noResources);
3995 }
3996
3997 MT_MSG_wrBuf_DBG(pMsg, &(pData->deviceAddress[0]),
3998 APIMAC_SADDR_EXT_LEN,
3999 "deviceAddr");
4000 MT_MSG_wrU16_DBG(pMsg,
4001 pData->assocShortAddress,
4002 "shortAddr");
4003 MT_MSG_wrU8_DBG(pMsg,
4004 pData->status,
4005 "status");
4006
4007 encode_Sec(pMsg, &(pData->sec));
4008
4009 return (API_MAC_TxRx_Status(pMsg));
4010}
4011
4012/*!
4013 Convert ApiMac_capabilityInfo_t data type to uint8_t capInfo
4014
4015 Public function defined in api_mac.h
4016*/
4017uint8_t ApiMac_convertCapabilityInfo(ApiMac_capabilityInfo_t *pMsgcapInfo)
4018{
4019 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4020
4021 uint8_t capInfo = 0;
4022
4023 if(pMsgcapInfo->panCoord)
4024 {
4025 capInfo |= CAPABLE_PAN_COORD;
4026 }
4027
4028 if(pMsgcapInfo->ffd)
4029 {
4030 capInfo |= CAPABLE_FFD;
4031 }
4032
4033 if(pMsgcapInfo->mainsPower)
4034 {
4035 capInfo |= CAPABLE_MAINS_POWER;
4036 }
4037
4038 if(pMsgcapInfo->rxOnWhenIdle)
4039 {
4040 capInfo |= CAPABLE_RX_ON_IDLE;
4041 }
4042
4043 if(pMsgcapInfo->security)
4044 {
4045 capInfo |= CAPABLE_SECURITY;
4046 }
4047
4048 if(pMsgcapInfo->allocAddr)
4049 {
4050 capInfo |= CAPABLE_ALLOC_ADDR;
4051 }
4052
4053 return (capInfo);
4054}
4055
4056/*!
4057 Convert from bitmask byte to API MAC capInfo
4058
4059 Public function defined in api_mac.h
4060*/
4061void ApiMac_buildMsgCapInfo(uint8_t cInfo, ApiMac_capabilityInfo_t *pPBcapInfo)
4062{
4063 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4064
4065 if(cInfo & CAPABLE_PAN_COORD)
4066 {
4067 pPBcapInfo->panCoord = 1;
4068 }
4069
4070 if(cInfo & CAPABLE_FFD)
4071 {
4072 pPBcapInfo->ffd = 1;
4073 }
4074
4075 if(cInfo & CAPABLE_MAINS_POWER)
4076 {
4077 pPBcapInfo->mainsPower = 1;
4078 }
4079
4080 if(cInfo & CAPABLE_RX_ON_IDLE)
4081 {
4082 pPBcapInfo->rxOnWhenIdle = 1;
4083 }
4084
4085 if(cInfo & CAPABLE_SECURITY)
4086 {
4087 pPBcapInfo->security = 1;
4088 }
4089
4090 if(cInfo & CAPABLE_ALLOC_ADDR)
4091 {
4092 pPBcapInfo->allocAddr = 1;
4093 }
4094}
4095
4096/*!
4097 Adds a new MAC device table entry.
4098
4099 Public function defined in api_mac.h
4100*/
4101ApiMac_status_t ApiMac_secAddDevice(ApiMac_secAddDevice_t *pAddDev)
4102{
4103 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4104
4105 struct mt_msg *pMsg;
4106
4107 pMsg = api_new_msg(0x1d, 0x22, 0x33, "secAddDevice");
4108 if(pMsg == NULL)
4109 {
4110 return (ApiMac_status_noResources);
4111 }
4112
4113 MT_MSG_wrU16_DBG(pMsg,
4114 pAddDev->panID ,
4115 "panId");
4116 MT_MSG_wrU16_DBG(pMsg,
4117 pAddDev->shortAddr ,
4118 "shortAddr");
4119 MT_MSG_wrBuf_DBG(pMsg,
4120 pAddDev->extAddr, APIMAC_SADDR_EXT_LEN,
4121 "extAddr");
4122 MT_MSG_wrU32_DBG(pMsg,
4123 pAddDev->frameCounter,
4124 "frameCounter");
4125 MT_MSG_wrU8_DBG(pMsg,
4126 pAddDev->exempt,
4127 "exempt");
4128 MT_MSG_wrU8_DBG(pMsg,
4129 pAddDev->uniqueDevice,
4130 "uniqueDevice");
4131 MT_MSG_wrU8_DBG(pMsg,
4132 pAddDev->duplicateDevFlag,
4133 "duplicateDevFlag");
4134 MT_MSG_wrU8_DBG(pMsg,
4135 pAddDev->keyIdLookupDataSize,
4136 "lookupSize");
4137 MT_MSG_wrBuf_DBG(pMsg,
4138 pAddDev->keyIdLookupData, APIMAC_MAX_KEY_LOOKUP_LEN,
4139 "lookupData");
4140
4141 return (API_MAC_TxRx_Status(pMsg));
4142}
4143
4144/*!
4145 Removes MAC device table entries.
4146
4147 Public function defined in api_mac.h
4148*/
4149ApiMac_status_t ApiMac_secDeleteDevice(ApiMac_sAddrExt_t *pExtAddr)
4150{
4151 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4152
4153 struct mt_msg *pMsg;
4154
4155 pMsg = api_new_msg(0x08, 0x22, 0x34, "secDeleteDevice");
4156 if(pMsg == NULL)
4157 {
4158 return (ApiMac_status_noResources);
4159 }
4160
4161 MT_MSG_wrBuf_DBG(pMsg, pExtAddr, APIMAC_SADDR_EXT_LEN, "extAddr");
4162
4163 return (API_MAC_TxRx_Status(pMsg));
4164}
4165
4166/*!
4167 Removes the key at the specified key Index and removes all MAC device table
4168 enteries associated with this key.
4169
4170 Public function defined in api_mac.h
4171*/
4172ApiMac_status_t ApiMac_secDeleteKeyAndAssocDevices(uint8_t keyIndex)
4173{
4174 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4175
4176 struct mt_msg *pMsg;
4177
4178 pMsg = api_new_msg(0x01, 0x022, 0x36, "secDeleteKeyAndAssocDevices");
4179 if(pMsg == NULL)
4180 {
4181 return (ApiMac_status_noResources);
4182 }
4183
4184 MT_MSG_wrU8_DBG(pMsg, keyIndex, "keyIndex");
4185
4186 return (API_MAC_TxRx_Status(pMsg));
4187}
4188
4189/*!
4190 Removes all MAC device table entries
4191
4192 Public function defined in api_mac.h
4193*/
4194ApiMac_status_t ApiMac_secDeleteAllDevices(void)
4195{
4196 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4197
4198 struct mt_msg *pMsg;
4199
4200 pMsg = api_new_msg(0, 0x22, 0x35, "secDeleteAllDevices");
4201 if(pMsg == NULL)
4202 {
4203 return (ApiMac_status_noResources);
4204 }
4205
4206 return (API_MAC_TxRx_Status(pMsg));
4207}
4208
4209/*!
4210 Reads the frame counter value associated with a MAC security key indexed
4211 by the designated key identifier and the default key source
4212
4213 Public function defined in api_mac.h
4214*/
4215ApiMac_status_t ApiMac_secGetDefaultSourceKey(uint8_t keyId,
4216 uint32_t *pFrameCounter)
4217{
4218 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4219
4220 struct mt_msg *pMsg;
4221 int r;
4222
4223 pMsg = api_new_msg(1, 0x22, 0x37, "secGetDefaultSourceKey");
4224 if(pMsg == NULL)
4225 {
4226 return (ApiMac_status_noResources);
4227 }
4228
4229 MT_MSG_wrU8_DBG(pMsg, keyId, "key-id");
4230
4231 r = MT_MSG_txrx(pMsg);
4232 if(r != 2)
4233 {
4234 r = ApiMac_status_badState;
4235 goto fail;
4236 }
4237 /* read the response */
4238 r = MT_MSG_rdU8_DBG(pMsg->pSrsp, "response");
4239 *pFrameCounter = MT_MSG_rdU32_DBG(pMsg->pSrsp, "framecounter");
4240 MT_MSG_parseComplete(pMsg->pSrsp);
4241 if(pMsg->is_error || pMsg->pSrsp->is_error)
4242 {
4243 r = ApiMac_status_invalidParameter;
4244 }
4245fail:
4246 MT_MSG_free(pMsg);
4247 return (r);
4248}
4249
4250/*!
4251 Adds the MAC security key, adds the associated lookup list for the key,
4252 initializes the frame counter to the value provided
4253
4254 Public function defined in api_mac.h
4255*/
4256ApiMac_status_t ApiMac_secAddKeyInitFrameCounter(
4257 ApiMac_secAddKeyInitFrameCounter_t *pInfo)
4258{
4259 LOG_printf(LOG_ALWAYS, "[API_MAC] %s\n", __PRETTY_FUNCTION__ );
4260
4261 struct mt_msg *pMsg;
4262
4263 pMsg = api_new_msg(0x21, 0x22, 0x38, "secAddKeyInitFrameCounter");
4264 if(pMsg == NULL)
4265 {
4266 return (ApiMac_status_noResources);
4267 }
4268
4269 MT_MSG_wrU8_DBG(pMsg,
4270 pInfo->newKeyFlag ,
4271 "newKeyFlag");
4272 MT_MSG_wrU16_DBG(pMsg,
4273 pInfo->replaceKeyIndex,
4274 "replaceKeyIndex");
4275 MT_MSG_wrBuf_DBG(pMsg,
4276 pInfo->key,
4277 sizeof(pInfo->key),
4278 "key");
4279 MT_MSG_wrU32_DBG(pMsg,
4280 pInfo->frameCounter,
4281 "frameCounter");
4282 MT_MSG_wrU8_DBG(pMsg,
4283 pInfo->lookupDataSize,
4284 "lookupSize");
4285 MT_MSG_wrBuf_DBG(pMsg,
4286 pInfo->lookupData,
4287 sizeof(pInfo->lookupData) ,
4288 "lookupData");
4289
4290 return (API_MAC_TxRx_Status(pMsg));
4291}
4292
4293/*
4294 * ========================================
4295 * Texas Instruments Micro Controller Style
4296 * ========================================
4297 * Local Variables:
4298 * mode: c
4299 * c-file-style: "bsd"
4300 * tab-width: 4
4301 * c-basic-offset: 4
4302 * indent-tabs-mode: nil
4303 * End:
4304 * vim:set filetype=c tabstop=4 shiftwidth=4 expandtab=true
4305 */
4306