void serial_api_rx_helloresponse(INT8U* payload, INT8U payloadLen) { serial_helloresponse_ht* msg; // drop packet if wrong length if (payloadLen!=sizeof(serial_helloresponse_ht)) { // print dnm_ucli_printf("ERROR: helloresponse wrong length (%d bytes)\r\n",payloadLen); // disconnect OSSemPost(bridge_app_v.disconnectedSem); return; } // cast message msg = (serial_helloresponse_ht*)payload; // store seqNoRx bridge_app_v.seqNoRx = msg->mgrSeqNo; #ifdef PRINT_TRACE dnm_ucli_printf(" seqNoRx %d\r\n",bridge_app_v.seqNoRx); #endif // I'm now connected bridge_app_v.connected = 0x01; }
//=========================== CLI handlers ==================================== // Open the LPTimer device dn_error_t cli_openHandler(const char* arg, INT32U len) { dn_error_t dnErr; int length; lptimer_app_v.overflow = 0; length = sscanf(arg, "%hhu %hhx %hhu %hhu %hu %hhu %hhu %hhu", &lptimer_app_v.openArgs.mode, &lptimer_app_v.openArgs.enabledEvents, &lptimer_app_v.openArgs.oneshot, &lptimer_app_v.openArgs.polarity, &lptimer_app_v.openArgs.compare, &lptimer_app_v.openArgs.clearOnCompare, &lptimer_app_v.openArgs.captureOnGate, &lptimer_app_v.openArgs.clearOnGate); if (length != 8) { dnm_ucli_printf("Usage: open <mode> <events> <single> <pol> <cmp> <clrCmp> <capGate> <clrGate>\r\n"); return DN_ERR_NONE; } dnm_ucli_printf("Opening lptimer"); dnErr = dn_open(DN_LPTIMER_DEV_ID, &lptimer_app_v.openArgs, sizeof(dn_lptimer_open_args_t)); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf(" failed with RC=%d\r\n", dnErr); return DN_ERR_NONE; } else{ dnm_ucli_printf("\r\n"); } return DN_ERR_NONE; }
// Search task static void searchTask(void* unused) { dn_error_t dnErr; INT8U rc; dn_netid_t netId; INT8U state; // Wait for stack to print start messages OSTimeDly(1 * SECOND); //initialize RSSI app_vars.bestRSSI = -127; //initialize netId (in network order) - set to an invalid ID to catch if we don't hear any ADV app_vars.network.netId = INVALID_NET; // Go into search - advNotifCb will collect networks dnm_ucli_printf("Searching for preferred network %d for 30 s...\r\n", PREFERRED_NET); dnErr = dnm_loc_searchCmd(&rc); ASSERT(dnErr == DN_ERR_NONE); ASSERT(rc == DN_API_RC_OK); // Wait SEARCH_TIME seconds OSTimeDly(SEARCH_TIME); // set the network ID to the best advertisement heard netId = app_vars.network.netId; if(netId != INVALID_NET){ dnErr = dnm_loc_setParameterCmd(DN_API_PARAM_NETID, (INT8U*)&netId, sizeof(dn_netid_t), &rc); ASSERT(dnErr == DN_ERR_NONE); ASSERT(rc == DN_API_RC_OK); // join the network dnm_ucli_printf("Joining network %d...\r\n", htons(app_vars.network.netId)); dnErr = dnm_loc_joinCmd(&rc); ASSERT(dnErr == DN_ERR_NONE); ASSERT(rc == DN_API_RC_OK); } while (1) { // this is a task, it executes forever // wait a bit OSTimeDly(5000); state = operationalCheck(); switch (state){ case DN_API_ST_OPERATIONAL: dnm_ucli_printf("I'm so happy in network %d!\r\n", htons(app_vars.network.netId)); break; case DN_API_ST_SEARCHING: case DN_API_ST_NEGO: case DN_API_ST_CONNECTED: dnm_ucli_printf("I'm trying to join network %d...\r\n", htons(app_vars.network.netId)); break; default: dnm_ucli_printf("I couldn't find a network to join\r\n"); break; } } }
dn_error_t advNotifCb(dn_api_loc_notif_adv_t* advNotif, INT8U length){ dn_netid_t netId; if(length == sizeof(dn_api_loc_notif_adv_t)){ netId = ntohs(advNotif->netId); if(netId == PREFERRED_NET){ dnm_ucli_printf("Heard the preferred network %d at %d dBm\r\n", netId, advNotif->rssi); memcpy(&app_vars.network, advNotif, sizeof(dn_api_loc_notif_adv_t)); app_vars.bestRSSI = MAX_RSSI; } else if(advNotif->rssi > app_vars.bestRSSI){ app_vars.bestRSSI = advNotif->rssi; dnm_ucli_printf("Heard network %d at %d dBm (louder than previous best)\r\n", netId, advNotif->rssi); memcpy(&app_vars.network, advNotif, sizeof(dn_api_loc_notif_adv_t)); } else{ dnm_ucli_printf("Heard network %d at %d dBm\r\n", netId, advNotif->rssi); } return (DN_ERR_NONE); } return (DN_ERR_SIZE); }
// set the value of the comparison register // device must already be open dn_error_t cli_setCompareHandler(const char* arg, INT32U len) { dn_error_t dnErr; int length; INT32U compare; //--- param 0: len length = sscanf(arg, "%u", &compare); if (length != 1) { dnm_ucli_printf("Usage: set <cmp>\r\n"); return DN_ERR_NONE; } // Registers are 32-bits wide but only 16 bits are useable here // for the compare. Setting to >65535 in the dn_ioctl call will // result in an error in future versions of the stack dnErr = dn_ioctl(DN_LPTIMER_DEV_ID, DN_IOCTL_LPTIMER_SET_COMPARE, &compare, sizeof(compare)); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf("Failed RC=%d\r\n", dnErr); return dnErr; } dnm_ucli_printf("Compare: %u\r\n", compare); return DN_ERR_NONE; }
void printBuf(INT8U* buf, INT8U len) { INT8U i; for (i=0;i<len;i++) { dnm_ucli_printf(" %02x",buf[i]); } dnm_ucli_printf("\r\n"); }
static void uartTxTask(void* unused) { INT8U osErr; dn_error_t dnErr; INT8U reply; INT32U replyLen; // create a semaphore uart_app_v.uartTxSem = OSSemCreate(0); ASSERT (uart_app_v.uartTxSem!=NULL); // prepare TX buffer memset(uart_app_v.uartTxBuffer,TX_BUFFER_PATTERN,sizeof(uart_app_v.uartTxBuffer)); while(1) { // this is a task, it executes forever // wait for the semaphore to be posted OSSemPend( uart_app_v.uartTxSem, // pevent 0, // timeout &osErr // perr ); ASSERT (osErr == OS_ERR_NONE); // print dnm_ucli_printf("Sending %d UART packets, %d bytes, delay %d ms\r\n", uart_app_v.uartTxNumLeft, uart_app_v.uartTxLen, uart_app_v.uartTxDelay ); while(uart_app_v.uartTxNumLeft>0) { // send packet dnErr = dn_sendSyncMsgByType( uart_app_v.uartTxBuffer, uart_app_v.uartTxLen, DN_MSG_TYPE_UART_TX_CTRL, (void*)&reply, sizeof(reply), &replyLen ); ASSERT(dnErr==DN_ERR_NONE); ASSERT(replyLen==sizeof(INT8U)); ASSERT(reply==DN_ERR_NONE); // decrement uart_app_v.uartTxNumLeft--; // wait a bit if (uart_app_v.uartTxDelay) { OSTimeDly(uart_app_v.uartTxDelay); } } // print dnm_ucli_printf("done.\r\n"); } }
// internal function void dnm_ucli_dump_v(const INT8U *data, INT32S len, const char * format, va_list arg) { int i; dnm_ucli_printfTimestamp_v(format, arg); for (i = 0; i < len; i++) { if (i % 20 == 0) dnm_ucli_printf("\r\n %03d : ", i); dnm_ucli_printf("%02x ", *data++); } dnm_ucli_printf("\r\n"); }
dn_error_t eventNotifCb(dn_api_loc_notif_events_t* eventNotif, INT8U *rsp) { // copy notification to local variables for simpler debugging memcpy(&app_vars.eventNotif, eventNotif, sizeof(dn_api_loc_notif_events_t)); dnm_ucli_printf("Event received - "); dnm_ucli_printf("events: 0x%04x, state: 0x%02x, alarms: 0x%04x\r\n", htonl(app_vars.eventNotif.events), app_vars.eventNotif.state, htonl(app_vars.eventNotif.alarms)); *rsp = DN_API_RC_OK; return DN_ERR_NONE; }
// internal function void dnm_ucli_printfTimestamp_v(const char *format, va_list arg) { #ifdef WIN32 // Print Windows time struct _timeb t; struct tm locTime; _ftime_s(&t); localtime_s(&locTime, &(t.time)); dnm_ucli_printf("(%02d:%02d:%02d.%03d) ", locTime.tm_hour, locTime.tm_min, locTime.tm_sec, t.millitm); #endif dnm_ucli_printf("%6u : ", OSTimeGet()); // TODO change to print sec.msec dnm_ucli_printf_v(format, arg); }
dn_error_t cli_ctrCmdHandler(const char* arg, INT32U len) { dn_error_t dnErr; // prepare paramaters memcpy(security_app_vars.inBuf, &security_inBuf, 16); memcpy(security_app_vars.key, &security_key, 16); memset(security_app_vars.iv, 0, 16); // print dnm_ucli_printf("params:\r\n"); dnm_ucli_printf(" - key: "); printBuf(security_app_vars.key, sizeof(security_app_vars.key)); dnm_ucli_printf(" - iv: "); printBuf(security_app_vars.iv, sizeof(security_app_vars.iv)); // print dnm_ucli_printf("input:\r\n"); dnm_ucli_printf(" - plaintext: "); printBuf(security_app_vars.inBuf, sizeof(security_app_vars.inBuf)); // encrypt dnErr = dn_sec_aesCtr( security_app_vars.inBuf, // inBuf security_app_vars.outBuf, // outBuf sizeof(security_app_vars.inBuf), // len security_app_vars.key, // key security_app_vars.iv // iv ); ASSERT(dnErr==DN_ERR_NONE); // print dnm_ucli_printf("output:\r\n"); dnm_ucli_printf(" - ciphertext: "); printBuf(security_app_vars.outBuf, sizeof(security_app_vars.outBuf)); security_app_vars.outBuf[5] ^= 0x01; // decrypt (same operation as encrypt, inBuf and outBuf inverted) dnErr = dn_sec_aesCtr( security_app_vars.outBuf, // inBuf security_app_vars.inBuf, // outBuf sizeof(security_app_vars.inBuf), // len security_app_vars.key, // key security_app_vars.iv // iv ); ASSERT(dnErr==DN_ERR_NONE); // print dnm_ucli_printf("output:\r\n"); dnm_ucli_printf(" - decrypted: "); printBuf(security_app_vars.inBuf, sizeof(security_app_vars.inBuf)); return DN_ERR_NONE; }
// get the current value of the counter register dn_error_t cli_getCounterHandler(const char* arg, INT32U len) { dn_error_t dnErr; INT32U counter; dnErr = dn_ioctl(DN_LPTIMER_DEV_ID, DN_IOCTL_LPTIMER_GET_COUNTER, &counter, sizeof(counter)); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf("Failed RC=%d\r\n", dnErr); return dnErr; } dnm_ucli_printf("Counter: %u\r\n", counter); return DN_ERR_NONE; }
// get the current value of the capture register // device must be open dn_error_t cli_getCaptureHandler(const char* arg, INT32U len) { dn_error_t dnErr; INT32U capture; dnErr = dn_ioctl(DN_LPTIMER_DEV_ID, DN_IOCTL_LPTIMER_GET_CAPTURE, &capture, sizeof(capture)); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf("Failed RC=%d\r\n", dnErr); return dnErr; } dnm_ucli_printf("Capture: %u\r\n", capture); return DN_ERR_NONE; }
/** \brief Print data in hext format. \param[in] buf Pointer to the start of the data to be printed. \param[in] len Number of bytes to print. */ void dnm_ucli_printBuf(INT8U* buf, INT8U len) { INT8U i; for (i=0; i<len; i++) { dnm_ucli_printf("%02X ",buf[i]); } }
void serial_api_tx_subscribe() { serial_subscribe_ht request; serial_subscribe_ack_ht response; INT8U responseLen; INT8U rc; // create request.filter = 0xffffffff; request.unackFilter = 0xffffffff; // send rc = serial_tx( PKT_TYPE_SUBSCRIBE, // packetType (INT8U*)&request, // txPayload sizeof(serial_subscribe_ht), // txPayloadLen &response, // rxPayload sizeof(serial_subscribe_ack_ht), // rxPayloadMaxLen &responseLen // rxPayloadLen ); if ( rc!=RC_OK || responseLen<sizeof(serial_subscribe_ack_ht) || response.rc!=RC_OK ) { // print dnm_ucli_printf("ERROR: subscription error\r\n"); // disconnect OSSemPost(bridge_app_v.disconnectedSem); } }
static void lptimerTask(void* unused) { dn_error_t dnErr; INT8U osErr; INT32U msg; INT32U rxLen; INT32U msgType; // give time for stack banner to print OSTimeDly(1 * SECOND); // create the memory block for the UART channel lptimer_app_v.eventChIdMem = OSMemCreate( lptimer_app_v.eventChIdMemBuf, EVENT_CHANNEL_SIZE, EVENT_CHANNEL_MSG_SIZE, &osErr); ASSERT(osErr==OS_ERR_NONE); // create an asynchronous notification channel dnErr = dn_createAsyncChannel(lptimer_app_v.eventChIdMem, &lptimer_app_v.eventChId); ASSERT(dnErr==DN_ERR_NONE); // associate the channel descriptor with UART notifications dnErr = dn_registerChannel(lptimer_app_v.eventChId, DN_MSG_TYPE_LPTIMER_NOTIF); ASSERT(dnErr==DN_ERR_NONE); while(1) { // this is a task, it executes forever // wait for event message dnErr = dn_readAsyncMsg(lptimer_app_v.eventChId, &msg, &rxLen, &msgType, sizeof(msg), 0 ); ASSERT(dnErr==DN_ERR_NONE); ASSERT(msgType==DN_MSG_TYPE_LPTIMER_NOTIF); if(msg & DN_LPTIMER_COMPARE_EVENT) { // print message received - the count will have increased slightly since the capture dnm_ucli_printf("COMP Event %d\r\n", msg); } if(msg & DN_LPTIMER_CAPTURE_EVENT) { // print message received dnm_ucli_printf("CAPT Event %d\r\n", msg); } if(msg & DN_LPTIMER_OVERFLOW_EVENT) { lptimer_app_v.overflow++; } } }
// close the LPTimer device // device must already be open dn_error_t cli_closeHandler(const char* arg, INT32U len) { dn_error_t dnErr; dnErr = dn_close(DN_LPTIMER_DEV_ID); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf("Close failed with RC=%d\r\n", dnErr); return dnErr; } return DN_ERR_NONE; }
// Reset command - returns an error if device fails to reset dn_error_t cli_reset(const char* arg, INT32U len){ INT8U rc; dnm_ucli_printf("Resetting...\r\n\n"); // send reset to stack dnm_loc_resetCmd(&rc); // mote will reset in 5s if rc=DN_ERR_NONE return(DN_ERR_NONE); }
// disable capture in the current mode dn_error_t cli_disableHandler(const char* arg, INT32U len) { dn_error_t dnErr; dnErr = dn_ioctl(DN_LPTIMER_DEV_ID, DN_IOCTL_LPTIMER_DISABLE, NULL, 0); if (dnErr != DN_ERR_NONE) { dnm_ucli_printf("Disable failed with RC=%d\r\n", dnErr); return dnErr; } return DN_ERR_NONE; }
void serial_rx_dispatch(INT8U packetType, INT8U* payload, INT8U payloadLen) { switch (packetType) { case PKT_TYPE_HELLORESPONSE: serial_api_rx_helloresponse(payload,payloadLen); break; case PKT_TYPE_NOTIFICATION: serial_api_rx_notification(payload,payloadLen); break; default: dnm_ucli_printf("WARNING: unknown DATA packetType=%d\r\n",packetType); break; } }
static void eventTask(void* unused) { dn_error_t dnErr; INT8U rc; // Give stack time to print banner OSTimeDly(1*SECOND); dnm_ucli_printf("Listening for advertisements...\r\n"); dnErr = dnm_loc_joinCmd(&rc); ASSERT(dnErr == DN_ERR_NONE); ASSERT(rc == DN_API_RC_OK); while (1) { // this is a task, it executes forever // wait a bit OSTimeDly(5000); } }
static void managerConnectionTask(void* unused) { dn_error_t dnErr; INT8U osErr; // wait for the loc_task to finish joining the network OSSemPend(bridge_app_v.joinedSem, 0, &osErr); ASSERT(osErr==OS_ERR_NONE); // start discoverTask task osErr = OSTaskCreateExt( discoverTask, (void *)0, (OS_STK*)(&bridge_app_v.discoverTaskStack[TASK_APP_DISCO_STK_SIZE-1]), TASK_APP_DISCO_PRIORITY, TASK_APP_DISCO_PRIORITY, (OS_STK*)bridge_app_v.discoverTaskStack, TASK_APP_DISCO_STK_SIZE, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR ); ASSERT(osErr == OS_ERR_NONE); OSTaskNameSet(TASK_APP_DISCO_PRIORITY, (INT8U*)TASK_APP_DISCO_NAME, &osErr); ASSERT(osErr == OS_ERR_NONE); while(1) { // this is a task, it executes forever // connect serial_api_tx_hello(); OSTimeDly(1000); if (bridge_app_v.connected!=0x01) { // try to reconnect continue; } // subscribe to all notifications serial_api_tx_subscribe(); // wait for disconnection OSSemPend(bridge_app_v.disconnectedSem, 0, &osErr); ASSERT(osErr==OS_ERR_NONE); dnm_ucli_printf("WARNING: disconnected from manager API\r\n"); } }
INT8U sendDiscoveredMotes(INT8U* pkBuf, INT8U payloadLen) { dn_error_t dnErr; INT8U rc; INT8U retries; loc_sendtoNW_t* pkToSend; INT8U returnVal; // fill in packet header pkToSend = (loc_sendtoNW_t*)pkBuf; pkToSend->locSendTo.socketId = loc_getSocketId(); pkToSend->locSendTo.destAddr = DN_MGR_IPV6_MULTICAST_ADDR; pkToSend->locSendTo.destPort = MOM_UDP_PORT; pkToSend->locSendTo.serviceType = DN_API_SERVICE_TYPE_BW; pkToSend->locSendTo.priority = DN_API_PRIORITY_MED; pkToSend->locSendTo.packetId = 0xFFFF; returnVal = RC_NO_RESOURCES; retries = 0; while (retries<MAX_RETRIES) { dnErr = dnm_loc_sendtoCmd( pkToSend, payloadLen, &rc ); if (dnErr==DN_ERR_NONE) { dnm_ucli_printf("INFO: motes sent\r\n"); break; } else { // increment number of retries retries++; // wait before trying again OSTimeDly(RETRY_PERIOD); } } return returnVal; }
dn_error_t cli_sumCmdHandler(const char* arg, INT32U len) { int a; int b; int l; //--- param 0: a l = sscanf(arg, "%d", &a); if (l < 1) { return DN_ERR_INVALID; } //--- param 1: b l = sscanf(arg+l, "%d", &b); if (l < 1) { return DN_ERR_INVALID; } //---- print sum dnm_ucli_printf("sum: %d",a+b); return DN_ERR_NONE; }
dn_error_t cli_cbcCmdHandler(const char* arg, INT32U len) { dn_error_t dnErr; // prepare paramaters memcpy(security_app_vars.inBuf, &security_inBuf, 16); memcpy(security_app_vars.key, &security_key, 16); memset(security_app_vars.iv, 0, 16); // print dnm_ucli_printf("params:\r\n"); dnm_ucli_printf(" - key: "); printBuf(security_app_vars.key, sizeof(security_app_vars.key)); dnm_ucli_printf(" - iv: "); printBuf(security_app_vars.iv, sizeof(security_app_vars.iv)); // print dnm_ucli_printf("input:\r\n"); dnm_ucli_printf(" - inBuf: "); printBuf(security_app_vars.inBuf, sizeof(security_app_vars.inBuf)); // create MIC dnErr = dn_sec_aesCbcMac( security_app_vars.inBuf, // inBuf sizeof(security_app_vars.inBuf), // len security_app_vars.key, // key security_app_vars.iv, // iv security_app_vars.mic // mic ); ASSERT(dnErr==DN_ERR_NONE); // print dnm_ucli_printf("output:\r\n"); dnm_ucli_printf(" - mic: "); printBuf(security_app_vars.mic, sizeof(security_app_vars.mic)); return DN_ERR_NONE; }
void serial_api_rx_notification(INT8U* payload, INT8U payloadLen) { dn_error_t dnErr; serial_notif_ht* serial_notif; serial_notif_data_ht* serial_notif_data; INT8U dataLen; loc_sendtoNW_t* pkToSend; INT8U rc; // drop packet if wrong length if (payloadLen<=sizeof(serial_notif_ht)) { // print dnm_ucli_printf("ERROR: notification wrong length (%d bytes)\r\n",payloadLen); // disconnect OSSemPost(bridge_app_v.disconnectedSem); return; } // cast message serial_notif = (serial_notif_ht*)payload; // handle notification switch(serial_notif->notifType) { case PKT_NOTIF_TYPE_DATA: // cast serial message serial_notif_data = (serial_notif_data_ht*)serial_notif->payload; dataLen = payloadLen-sizeof(serial_notif_ht)-sizeof(serial_notif_data); if (dataLen+8>MAX_PAYLOAD_LENGTH) { dnm_ucli_printf("WARNING: data packet too long (%d bytes)\r\n",dataLen); } else { // prepare wireless packet pkToSend = (loc_sendtoNW_t*)bridge_app_v.pkBuf; pkToSend->locSendTo.socketId = loc_getSocketId(); pkToSend->locSendTo.destAddr = DN_MGR_IPV6_MULTICAST_ADDR; pkToSend->locSendTo.destPort = htons(serial_notif_data->dstPort); pkToSend->locSendTo.serviceType = DN_API_SERVICE_TYPE_BW; pkToSend->locSendTo.priority = DN_API_PRIORITY_MED; pkToSend->locSendTo.packetId = 0xFFFF; memcpy(&pkToSend->locSendTo.payload[0],serial_notif_data->macAddress,8); memcpy(&pkToSend->locSendTo.payload[8],serial_notif_data->data,dataLen); // send wireless packet dnErr = dnm_loc_sendtoCmd( pkToSend, 8+dataLen, &rc ); if (dnErr==DN_ERR_NONE) { dnm_ucli_printf("INFO: DATA tunneled\r\n"); } else { dnm_ucli_printf("ERROR: DATA tunneling dnErr=%d\r\n",dnErr); } } break; case PKT_NOTIF_TYPE_EVENT: case PKT_NOTIF_TYPE_HR: if (payloadLen+1>MAX_PAYLOAD_LENGTH) { dnm_ucli_printf("WARNING: notification too long (%d bytes)\r\n",dataLen); } else { // prepare wireless packet pkToSend = (loc_sendtoNW_t*)bridge_app_v.pkBuf; pkToSend->locSendTo.socketId = loc_getSocketId(); pkToSend->locSendTo.destAddr = DN_MGR_IPV6_MULTICAST_ADDR; pkToSend->locSendTo.destPort = MOM_UDP_PORT; pkToSend->locSendTo.serviceType = DN_API_SERVICE_TYPE_BW; pkToSend->locSendTo.priority = DN_API_PRIORITY_MED; pkToSend->locSendTo.packetId = 0xFFFF; pkToSend->locSendTo.payload[0] = MOM_RESP_DISPATCH_SERIALNOTIF; memcpy(&pkToSend->locSendTo.payload[1],payload,payloadLen); // send wireless packet dnErr = dnm_loc_sendtoCmd( pkToSend, 1+payloadLen, &rc ); if (dnErr==DN_ERR_NONE) { dnm_ucli_printf("INFO: NOTIF tunneled\r\n"); } else { dnm_ucli_printf("ERROR: NOTIF tunneling dnErr=%d\r\n",dnErr); } } break; case PKT_NOTIF_TYPE_IPDATA: case PKT_NOTIF_TYPE_LOG: dnm_ucli_printf("WARNING notifType %d not handled\r\n",serial_notif->notifType); break; default: // print dnm_ucli_printf("ERROR: unexpected notifType %d\r\n",serial_notif->notifType); // disconnect OSSemPost(bridge_app_v.disconnectedSem); return; } }
dn_error_t cli_ccm3CmdHandler(const char* arg, INT32U len) { dn_error_t dnErr; dn_sec_ccmopt_t dn_sec_ccmopt; INT8U aBuf[sizeof(ccm3_a)]; INT8U mBuf[sizeof(ccm3_m)]; dnm_ucli_printf("Test vector from \"C.2.3 MAC command frame\"\r\n"); // Size of CCM authentication field (MIC); range: 4-16. dn_sec_ccmopt.M = 8; // Size of CCM length field; range: 2-8. dn_sec_ccmopt.L = 2; // buffer to authenticate only memcpy(aBuf, &ccm3_a, sizeof(ccm3_a)); // buffer to authenticate and encrypt memcpy(mBuf, &ccm3_m, sizeof(ccm3_m)); // key memcpy(security_app_vars.key, &security_key, sizeof(security_key)); // nonce/initialization vector memcpy(security_app_vars.iv, &ccm3_nonce, sizeof(ccm3_nonce)); // print dnm_ucli_printf("params:\r\n"); dnm_ucli_printf(" - M: %d\r\n",dn_sec_ccmopt.M); dnm_ucli_printf(" - L: %d\r\n",dn_sec_ccmopt.L); dnm_ucli_printf(" - key: "); printBuf(security_app_vars.key, sizeof(security_app_vars.key)); dnm_ucli_printf(" - nonce: "); printBuf(security_app_vars.iv, sizeof(security_app_vars.iv)); // print dnm_ucli_printf("input:\r\n"); dnm_ucli_printf(" - aBuf: "); printBuf(aBuf, sizeof(aBuf)); dnm_ucli_printf(" - mBuf: "); printBuf(mBuf, sizeof(mBuf)); // encrypt and authenticate dnErr = dn_sec_aesCcmEncrypt( &dn_sec_ccmopt, // opt aBuf, // aBuf sizeof(aBuf), // aLen mBuf, // mBuf sizeof(mBuf), // mLen security_app_vars.key, // key security_app_vars.iv, // nonce security_app_vars.mic // mic ); ASSERT(dnErr==DN_ERR_NONE); // print dnm_ucli_printf("output:\r\n"); dnm_ucli_printf(" - aBuf: "); printBuf(aBuf, sizeof(aBuf)); dnm_ucli_printf(" - mBuf: "); printBuf(mBuf, sizeof(mBuf)); dnm_ucli_printf(" - mic: "); printBuf(security_app_vars.mic, 8); return DN_ERR_NONE; }
INT8U discoverMotes(INT8U numMotesIn, INT8U* numMotesOut, INT8U* pkBuf, INT8U maxPayloadLen) { INT8U lastWrittenMac[8]; INT8U firstMACwritten; INT8U currentMac[8]; serial_getMoteConfig_ht request; serial_getMoteConfig_ack_ht response; INT8U responseLen; INT8U rc; INT8U lastMAC[8]; mom_response_ht* mom_response_h; mom_response_rpc_ht* mom_response_rpc_h; mom_motes_ht* mom_motes_h; INT8U* payload; INT8U payloadIdx; INT8U moteidx; INT8U i; INT8U lenMAC; // start with empty MAC address memset(currentMac,0,8); firstMACwritten = 1; payload = ((loc_sendtoNW_t*)pkBuf)->locSendTo.payload; payloadIdx = 0; moteidx = 0; while (1) { // prepare next request memcpy(request.macAddress,currentMac,8); request.next = 0x01; // send rc = serial_tx( PKT_TYPE_GETMOTECONFIG, // packetType (INT8U*)&request, // txPayload sizeof(serial_getMoteConfig_ht), // txPayloadLen &response, // rxPayload sizeof(serial_getMoteConfig_ack_ht), // rxPayloadMaxLen &responseLen // rxPayloadLen ); if (rc!=RC_OK || responseLen<1) { // there was a problem communicating with the manager // print dnm_ucli_printf("ERROR: problem communicating with manager\r\n"); // disconnect OSSemPost(bridge_app_v.disconnectedSem); // abort, abort return RC_WRITE_FAIL; } else if (response.rc!=RC_OK) { // end of list of motes if (numMotesOut==NULL) { // send remainder of buffer if (payloadIdx>0) { rc = sendDiscoveredMotes(pkBuf,payloadIdx); if (rc!=RC_OK) { return rc; } } } else { // write number of motes *numMotesOut = moteidx; } // stop return RC_OK; } else { // not the end of the list of motes if (response.isAP==0x00 && response.state==MOTE_STATE_OPERATIONAL) { // I have found a new mote if (numMotesOut==NULL) { // write motes //===== start of packet if (payloadIdx==0) { // mom_response_ht mom_response_h = (mom_response_ht*)&payload[payloadIdx]; mom_response_h->dispatch = MOM_RESP_DISPATCH_RPC; payloadIdx += sizeof(mom_response_ht); // mom_response_rpc_ht mom_response_rpc_h = (mom_response_rpc_ht*)&payload[payloadIdx]; mom_response_rpc_h->procID= MOM_PROC_GETOPERATIONALMOTES; payloadIdx += sizeof(mom_response_rpc_ht); // motes header mom_motes_h = (mom_motes_ht*)&payload[payloadIdx]; mom_motes_h->number = numMotesIn; mom_motes_h->index = moteidx; payloadIdx += sizeof(mom_motes_ht); } //===== body of packet // determine how many bytes are different with previous MAC (delta encoding) lenMAC=8; if (firstMACwritten==1) { firstMACwritten=0; } else { for (i=0;i<8;i++) { if (response.macAddress[i]==lastWrittenMac[i]) { lenMAC--; } else { break; } } } // write header payload[payloadIdx] = lenMAC; payloadIdx++; // write lenMAC last address of MAC address memcpy(&payload[payloadIdx],&response.macAddress[8-lenMAC],lenMAC); payloadIdx += lenMAC; // remember last written MAC address memcpy(lastWrittenMac,response.macAddress,8); //===== end of packet if (payloadIdx+8>=maxPayloadLen) { // not enough space to write another MAC address // send buffer rc = sendDiscoveredMotes(pkBuf,payloadIdx); if (rc!=RC_OK) { return rc; } // reset buffer firstMACwritten = 1; payloadIdx = 0; } } // increment number of motes moteidx++; } // store MAC address for next iteration memcpy(currentMac,response.macAddress,8); } } }
/** \brief Send a frame to the serial API of the SmartMesh IP manager. A response is expected from the manager if rxPayload!=NULL. In this case, this function retries transmitting if no response is received after SERIAL_ACK_TIMEOUT ms. If no response is received after SERIAL_MAX_RETRIES retries, the function returns RC_WRITE_FAIL. \param[in] packetType The payload type. \param[in] txPayload Payload to transmit to the manager. \param[in] txPayloadLen Number of bytes into the payload to transmit to the manager. \param[out] rxPayload Pointer to a buffer to write the received payload into. manager. \param[in] rxPayloadMaxLen Maximum number of bytes which fit in the rxPayload buffer. If the manager responds with more bytes, this function returns RC_NO_RESOURCES, and no bytes are written to the rxPayload buffer. \param[out] rxPayloadLen Expected number of bytes returned by the manager. \return RC_OK if the operation succeeded successfully. \return RC_NO_RESOURCES if the manager returned a number of bytes different from rxPayloadLen. \return RC_WRITE_FAIL if no answer from the manager is received after SERIAL_MAX_RETRIES retries. */ INT8U serial_tx( INT8U packetType, INT8U* txPayload, INT8U txPayloadLen, INT8U* rxPayload, INT8U rxPayloadMaxLen, INT8U* rxPayloadLen ) { INT8U osErr; dn_error_t dnErr; INT8U i; INT8U len; INT8U functionReply; INT8U retryCounter; INT32U functionReplyLen; serial_ht* tx_frame; INT8U returnVal; // I'm busy sending a DATA packet over serial OSSemPend(bridge_app_v.serialTxDataAvailable,0,&osErr); ASSERT(osErr==RC_OK); // create packet tx_frame = (serial_ht*)bridge_app_v.uartTxBuffer; tx_frame->control = 0x00; tx_frame->packetType = packetType; tx_frame->seqNum = bridge_app_v.seqNoTx++; tx_frame->payloadLen = txPayloadLen; if (txPayload!=NULL) { memcpy(tx_frame->payload,txPayload,txPayloadLen); } len = sizeof(serial_ht)+txPayloadLen; // store packet details bridge_app_v.requestPacketType = packetType; bridge_app_v.responsePayload = rxPayload; bridge_app_v.responsePayloadMaxLen = rxPayloadMaxLen; retryCounter = SERIAL_MAX_RETRIES; while (retryCounter>0) { #ifdef PRINT_TRACE dnm_ucli_printf("---TX--> (%d bytes)",len); for (i=0;i<len;i++) { dnm_ucli_printf(" %02x",bridge_app_v.uartTxBuffer[i]); } dnm_ucli_printf("\r\n"); dnm_ucli_printf(" packetType %d\r\n",tx_frame->packetType); dnm_ucli_printf(" seqNum %d\r\n",tx_frame->seqNum); #endif // send packet dnErr = dn_sendSyncMsgByType( bridge_app_v.uartTxBuffer, len, DN_MSG_TYPE_UART_TX_CTRL, (void*)&functionReply, sizeof(functionReply), &functionReplyLen ); ASSERT(functionReplyLen==sizeof(INT8U)); ASSERT(functionReply==DN_ERR_NONE); // wait for response, if appropriate if (rxPayload!=NULL) { // wait for response OSSemPend( bridge_app_v.waitForResponseSem, SERIAL_ACK_TIMEOUT, &osErr ); // return appropriate value switch (osErr) { case OS_ERR_NONE: *rxPayloadLen = bridge_app_v.responsePayloadLen; if (bridge_app_v.responsePayloadLen<=bridge_app_v.responsePayloadMaxLen) { returnVal = RC_OK; } else { returnVal = RC_NO_RESOURCES; } retryCounter = 0; break; case OS_ERR_TIMEOUT: dnm_ucli_printf("WARNING: serial API timeout.\r\n"); retryCounter--; break; default: ASSERT(0); } } else { retryCounter = 0; } } // reset packet details bridge_app_v.requestPacketType = 0x00; // I'm NOT busy sending a DATA packet over serial OSSemPost(bridge_app_v.serialTxDataAvailable); return returnVal; }
static void uartRxTask(void* unused) { dn_error_t dnErr; INT8U osErr; dn_uart_open_args_t uartOpenArgs; INT32U rxLen; INT32U msgType; INT8U i; INT32S err; // create the memory block for the UART channel uart_app_v.uartRxChannelMem = OSMemCreate( uart_app_v.uartRxChannelMemBuf, 1, sizeof(uart_app_v.uartRxChannelMemBuf), &osErr ); ASSERT(osErr==OS_ERR_NONE); // create an asynchronous notification channel dnErr = dn_createAsyncChannel(uart_app_v.uartRxChannelMem, &uart_app_v.uartRxChannel); ASSERT(dnErr==DN_ERR_NONE); // associate the channel descriptor with UART notifications dnErr = dn_registerChannel(uart_app_v.uartRxChannel, DN_MSG_TYPE_UART_NOTIF); ASSERT(dnErr==DN_ERR_NONE); // open the UART device uartOpenArgs.rxChId = uart_app_v.uartRxChannel; uartOpenArgs.eventChId = 0; uartOpenArgs.rate = 115200u; uartOpenArgs.mode = DN_UART_MODE_M4; uartOpenArgs.ctsOutVal = 0; uartOpenArgs.fNoSleep = 0; err = dn_open( DN_UART_DEV_ID, &uartOpenArgs, sizeof(uartOpenArgs) ); ASSERT(err>=0); while(1) { // this is a task, it executes forever // wait for UART messages dnErr = dn_readAsyncMsg( uart_app_v.uartRxChannel, // chDesc uart_app_v.uartRxBuffer, // msg &rxLen, // rxLen &msgType, // msgType MAX_UART_PACKET_SIZE, // maxLen 0 // timeout (0==never) ); ASSERT(dnErr==DN_ERR_NONE); ASSERT(msgType==DN_MSG_TYPE_UART_NOTIF); // print message received dnm_ucli_printf("uart RX (%d bytes)",rxLen); for (i=0;i<rxLen;i++) { dnm_ucli_printf(" %02x",uart_app_v.uartRxBuffer[i]); } dnm_ucli_printf("\r\n"); } }