void gateway_task () { uint8_t i, len; int8_t rssi, val; uint8_t *local_rx_tx_buf; uint16_t batt; nrk_time_t check_period, wait_time; uint16_t buf; int8_t fd; uint8_t j, cnt, level; nrk_sig_t tx_done_signal; nrk_sig_mask_t ret; nrk_time_t next_transmit_time; nrk_time_t current_time; nrk_time_t prev_time; char tmp[4]; printf ("gateway_task PID=%d\r\n", nrk_get_pid ()); next_transmit_time.secs = 0; next_transmit_time.nano_secs = 0; // init bmac on channel 25 bmac_init (26); // By default the RX check rate is 100ms // below shows how to change that check_period.secs=0; check_period.nano_secs=100*NANOS_PER_MS; val=bmac_set_rx_check_rate(check_period); // The default Clear Channel Assement RSSI threshold is -32 // Setting this value higher means that you will only trigger // receive with a very strong signal. Setting this lower means // bmac will try to receive fainter packets. If the value is set // too high or too low performance will suffer greatly. // bmac_set_cca_thresh(-36); if(val==NRK_ERROR) nrk_kprintf( PSTR("ERROR setting bmac rate\r\n" )); // This sets the next RX buffer. // This can be called at anytime before releaseing the packet // if you wish to do a zero-copy buffer switch bmac_rx_pkt_set_buffer (rx_buf, RF_MAX_PAYLOAD_SIZE); // Get and register the tx_done_signal if you want to // do non-blocking transmits tx_done_signal = bmac_get_tx_done_signal (); nrk_signal_register (tx_done_signal); nrk_time_set(0, 0); cnt = 0; // Initially clear all the data buffers for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { data_pkt.node_specific_data[i][j] = 0; } } while (1) { nrk_time_get(¤t_time); // If it is time to flood the network, send the control packets if(current_time.secs%FLOOD_RATE == 0 && prev_time.secs != current_time.secs || cnt == 0) { prev_time = current_time; cnt ++; SET_PACKET_COUNT(pkt_buf.pkt_type_cnt, cnt); #if MODE==DATA_MODE SET_PACKET_TYPE(pkt_buf.pkt_type_cnt, PKT_TYPE_CONTROL); #else SET_PACKET_TYPE(pkt_buf.pkt_type_cnt, PKT_TYPE_DIAG_CONTROL); #endif pkt_buf.hop_number = 0; pkt_buf.time_to_flood = TIME_TO_FLOOD_IN_SECS; pkt_buf.bmac_check_rate = BMAC_CHECK_RATE_IN_MS; pkt_buf.maximum_depth = MAXIMUM_DEPTH; pkt_buf.delay_at_each_level = DELAY_AT_EACH_LEVEL_IN_SECS; pkt_buf.next_control_time = NEXT_CONTROL_TIME; pkt_buf.data_push_rate = 0; for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { #if MODE==DATA_MODE pkt_buf.node_specific_data[i][j] = SENSOR; #else pkt_buf.node_specific_data[i][j] = 0; #endif } } memcpy(tx_buf, &pkt_buf, sizeof(pkt_buf)); // Non-blocking send nrk_led_set (BLUE_LED); val = bmac_tx_pkt_nonblocking (tx_buf, sizeof(struct message_packet)); nrk_kprintf (PSTR ("Tx packet enqueued\r\n")); ret = nrk_event_wait (SIG(tx_done_signal)); if(ret & SIG(tx_done_signal) == 0 ) nrk_kprintf (PSTR ("TX done signal error\r\n")); nrk_led_clr (BLUE_LED); } // If a new packet has been received, then update the information if(bmac_rx_pkt_ready()) { // Wait until an RX packet is received nrk_led_set (ORANGE_LED); // Get the RX packet local_rx_tx_buf = bmac_rx_pkt_get (&len, &rssi); for (i = 0; i < len; i++) printf ("%d", rx_buf[i]); printf ("\r\n"); memcpy(&pkt_buf, rx_buf, sizeof(pkt_buf)); nrk_led_clr (ORANGE_LED); // Release the RX buffer so future packets can arrive bmac_rx_pkt_release (); // If the received packet is a data packet then update the information, gateway just ignores the control packets if(GET_PACKET_TYPE(pkt_buf.pkt_type_cnt) == PKT_TYPE_DIAG_DATA || GET_PACKET_TYPE(pkt_buf.pkt_type_cnt) == PKT_TYPE_DATA) { printf("Type = %d\n\r", GET_PACKET_TYPE(pkt_buf.pkt_type_cnt)); printf("Count = %d\n\r", GET_PACKET_COUNT(pkt_buf.pkt_type_cnt)); printf("Hop # = %d\n\r", pkt_buf.hop_number); printf("TTF = %d\n\r", pkt_buf.time_to_flood); printf("BCR = %d\n\r", pkt_buf.bmac_check_rate); printf("Nmax = %d\n\r", pkt_buf.maximum_depth); printf("Dlev = %d\n\r", pkt_buf.delay_at_each_level); printf("Nxt = %d\n\r", pkt_buf.next_control_time); printf("Prate = %d\n\r", pkt_buf.data_push_rate); for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { if(pkt_buf.node_specific_data[i][j] != 0) data_pkt.node_specific_data[i][j] = pkt_buf.node_specific_data[i][j]; } } for(i=0; i<(MAX_NODES);i++) { printf("Value @ Node %d is %d (cnt is %d)", i, ((int16_t)data_pkt.node_specific_data[i][1]<<4), (data_pkt.node_specific_data[i][0]&0x3F)); printf("\n\r"); } } } } }
int main(int argc, char **argv) { int sockfd; unsigned char sndbuf[128]; unsigned char *SSI_sensor_discovery; int packet_len = 0; unsigned char SSI_request[128]; unsigned char sndbuf_conf[128]; unsigned char buffer[512]; unsigned char rbuf[512]; int recvbytes; unsigned int bytes; unsigned short int portn; int i = 1; char nRd_address[32] = "127.0.0.1"; unsigned int nRd_port = 21870; unsigned char target[8]; char argbuf[64]; int hits = 0; unsigned char sensor_count = 0; struct sensor_description_t sensor_desc[10]; unsigned char sensor_addr=0; struct pollfd pfds; unsigned int nfds = 1; int timed_out = 0; int full_description=0; int rval = 0; int loop = 1; /* First check the command line parameters and parse them. */ if(argc < 2 || argc > 4 || strncmp(argv[1], "--help", 6) == 0) { usage(); return(-1); } while(i < argc) { sscanf(argv[i], "%s ", argbuf); if(strncmp(argbuf, "-S", 2) == 0) { i++; hits = sscanf(argv[i], "%[^:]:%d", nRd_address, &nRd_port); if(hits == 2) printf("Trying to connect nRouted at %s port %d\n", nRd_address, nRd_port); bzero(argbuf, 64); } else if (strncmp(argbuf, "-l", 2) == 0) { printf("Loop mode.\n"); loop = 10; } else { hits = sscanf(argv[i], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &(target[0]), &(target[1]), &(target[2]), &(target[3]), &(target[4]), &(target[5]), &(target[6]), &(target[7])); printf("Requesting SSI data from: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", target[0], target[1], target[2], target[3], target[4], target[5], target[6], target[7]); } bzero(argbuf, 64); i++; } printf("Trying to connect nRouted at %s port %d\n", nRd_address, nRd_port); /* Copying the Target address to the end of the nRouted Configuration packet, discovery packet and SSI request packet. */ for(i=0;i<8;i++) { sndbuf_conf[i+12] = target[i]; sndbuf[i+18] = target[i]; SSI_request[i+12] = target[i]; } // if((rval=libnrp_create_conf_pkt(sndbuf_conf, PROTO_UNDEFINED, target, NULL, ADDR_UNDEFINED, NULL, PORT_UNDEFINED)) < 0) if((rval=libnrp_create_conf_pkt(sndbuf_conf, PROTO_6LOWPAN, NULL, NULL, ADDR_UNDEFINED, NULL, PORT_UNDEFINED)) < 0) { printf("Failed to create an nRouted configuration packet.\n"); return(-1); } if((sockfd = libnrp_snd_conf(sndbuf_conf, rval, nRd_address, nRd_port)) < 0) { printf("Failed to send the configuration packet to nRouted.\n"); return(-1); } else { printf("nRouted configuration successful.\n"); } /* Create the SSI sensor discovery packet using the wildcard address */ SSI_sensor_discovery = libSSI_sensor_discovery(NULL); printf("SSI_sensor_discovery:0x%hhx 0x%hhx\n", SSI_sensor_discovery[0], SSI_sensor_discovery[1]); /* Create the SSI sensor query packet inside a nRP data packet. */ portn = 122; packet_len = libnrp_create_data_pkt_hdr(sndbuf, SSI_sensor_discovery, 2, PROTO_6LOWPAN, NULL, target, ADDR_IEEE_802_15_4_DEV_LONG, &portn, 40, NULL); /* Here we send the SSI discovery packet to the sensor device. */ write(sockfd, sndbuf, packet_len); pfds.fd = (int)(sockfd); pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; /* We try to read the answer and then process it. */ i=0; timed_out = 0; while(!timed_out && full_description != 1) { if((rval = poll(&pfds, nfds, 1000)) == 0) { printf("Timed out SSI discovery reply.\n"); timed_out = -1; } else { recvbytes = read(sockfd, rbuf, 512); if(recvbytes>0) { printf("Received %d bytes ", recvbytes); libnrp_get_data(rbuf, recvbytes, buffer, &bytes); if(GET_PACKET_TYPE(buffer) == SSI_DISC_REPLY) { printf("Got an SSI sensor discovery reply - good.\n"); libSSI_parse_disc_reply(buffer, &sensor_addr, bytes, &sensor_count, sensor_desc); printf("Got %u sensor descriptions.\n", sensor_count); if(buffer[bytes-2] == 0xff && buffer[bytes-1] == 0xff) { full_description = 1; printf("Got full set of sensor descriptions.\n"); } } else { printf("Wrong type: 0x%hhx\n", (unsigned char)GET_PACKET_TYPE(buffer)); } } } } if(full_description == 0) { printf("Some sensor descriptions were left missing as I timed out.\n"); } usleep(100000); if(sensor_count > 0) { int k; uint16_t sensor_id_list[12]; for(k=0;k<sensor_count;k++) { memcpy(&(sensor_id_list[k]), &(sensor_desc[k].sensor_id), 2); } bytes = libSSI_data_request(SSI_request, &sensor_addr, sensor_id_list, &sensor_count); packet_len = libnrp_create_data_pkt_hdr(sndbuf, SSI_request, bytes, PROTO_6LOWPAN, NULL, target, ADDR_IEEE_802_15_4_DEV_LONG, &portn, 40, NULL); printf("Write %d bytes\n", packet_len); write(sockfd, sndbuf, packet_len); timed_out = 0; while(!timed_out ) { if((rval = poll(&pfds, nfds, 2000)) == 0) { printf("Timed out SSI discovery reply.\n"); timed_out = -1; } else { printf("Read\n"); recvbytes = read(sockfd, buffer, 512); libnrp_get_data(buffer, recvbytes, rbuf, &bytes); if(GET_PACKET_TYPE(rbuf) == SSI_DATA_REPLY) { if(bytes>0) { uint16_t sensor_ids[32]; uint32_t sensor_values[32]; printf("Received SSI_DATA_REPLY (%d bytes).\n", bytes); i=0; i = libSSI_parse_data_response(rbuf, NULL, sensor_ids, sensor_values, bytes); for(k=0;k<i;k++) { int j; for(j=0;j<i;j++) { if(sensor_ids[k] == sensor_desc[j].sensor_id) { if(sensor_desc[j].type == 0x00) printf("%s:%lf %s\n", sensor_desc[j].description, (double)sensor_values[k], sensor_desc[j].unit); else if(sensor_desc[j].type == 0x01) printf("%s:%d %s\n", sensor_desc[j].description, (int)sensor_values[k], sensor_desc[j].unit); } } } } } timed_out = -1; } } } else { printf("No sensors found.\n"); close(sockfd); return(-1); } close(sockfd); return(1); }
static PVRSRV_ERROR DoTLStreamReserve(IMG_HANDLE hStream, IMG_UINT8 **ppui8Data, IMG_UINT32 ui32ReqSize, IMG_UINT32 ui32ReqSizeMin, PVRSRVTL_PACKETTYPE ePacketType, IMG_UINT32* pui32AvSpace) { PTL_STREAM psTmp; IMG_UINT32 *ui32Buf, ui32LRead, ui32LWrite, ui32LPending, lReqSizeAligned, lReqSizeActual; IMG_INT pad, iFreeSpace; PVR_DPF_ENTERED; if (pui32AvSpace) *pui32AvSpace = 0; if (( IMG_NULL == hStream )) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_INVALID_PARAMS); } psTmp = (PTL_STREAM)hStream; /* Assert used as the packet type parameter is currently only provided * by the TL APIs, not the calling client */ PVR_ASSERT((PVRSRVTL_PACKETTYPE_UNDEF < ePacketType) && (PVRSRVTL_PACKETTYPE_LAST >= ePacketType)); /* The buffer is only used in "rounded" (aligned) chunks */ lReqSizeAligned = PVRSRVTL_ALIGN(ui32ReqSize); /* Get a local copy of the stream buffer parameters */ ui32LRead = psTmp->ui32Read ; ui32LWrite = psTmp->ui32Write ; ui32LPending = psTmp->ui32Pending ; /* Multiple pending reserves are not supported. */ if ( NOTHING_PENDING != ui32LPending ) { PVR_DPF_RETURN_RC(PVRSRV_ERROR_NOT_READY); } if ( IMG_UINT16_MAX < lReqSizeAligned ) { psTmp->ui32Pending = NOTHING_PENDING; if (pui32AvSpace) { *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin); } PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL); } /* Prevent other threads from entering this region before we are done. * Not exactly a lock... */ psTmp->ui32Pending = 0; /* If there is enough contiguous space following the current Write * position then no padding is required */ if ( psTmp->ui32Size < ui32LWrite + lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) ) { pad = psTmp->ui32Size - ui32LWrite; } else { pad = 0 ; } lReqSizeActual = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) + pad ; /* If this is a blocking reserve and there is not enough space then wait. */ if( psTmp->bBlock ) { if( psTmp->ui32Size < lReqSizeActual ) { psTmp->ui32Pending = NOTHING_PENDING; PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE); } while ( ( cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size) <(IMG_INT) lReqSizeActual ) ) { OSEventObjectWait(psTmp->hProducerEvent); // update local copies. ui32LRead = psTmp->ui32Read ; ui32LWrite = psTmp->ui32Write ; } } /* The easy case: buffer has enough space to hold the requested packet (data + header) */ iFreeSpace = cbSpaceLeft(ui32LRead, ui32LWrite, psTmp->ui32Size); if ( iFreeSpace >=(IMG_INT) lReqSizeActual ) { if ( pad ) { /* Inserting padding packet. */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_PADDING(pad-sizeof(PVRSRVTL_PACKETHDR)) ; /* CAUTION: the used pad value should always result in a properly * aligned ui32LWrite pointer, which in this case is 0 */ ui32LWrite = (ui32LWrite + pad) % psTmp->ui32Size; /* Detect unaligned pad value */ PVR_ASSERT( ui32LWrite == 0); } /* Insert size-stamped packet header */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_HDR(ui32ReqSize, ePacketType); /* return the next position in the buffer to the user */ *ppui8Data = &psTmp->pbyBuffer[ ui32LWrite+sizeof(PVRSRVTL_PACKETHDR) ] ; /* update pending offset: size stamp + data */ ui32LPending = lReqSizeAligned + sizeof(PVRSRVTL_PACKETHDR) ; } /* The not so easy case: not enough space, decide how to handle data */ else { #if defined(DEBUG) /* Sanity check that the user is not trying to add more data than the * buffer size. Conditionally compile it out to ensure this check has * no impact to release performance */ if ( lReqSizeAligned+sizeof(PVRSRVTL_PACKETHDR) > psTmp->ui32Size ) { psTmp->ui32Pending = NOTHING_PENDING; PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_MISUSE); } #endif /* No data overwriting, insert write_failed flag and return */ if (psTmp->bDrop) { /* Caller should not try to use ppui8Data, * NULLify to give user a chance of avoiding memory corruption */ ppui8Data = IMG_NULL; /* This flag should not be inserted two consecutive times, so * check the last ui32 in case it was a packet drop packet. */ ui32Buf = ui32LWrite ? (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite - sizeof(PVRSRVTL_PACKETHDR)] : // Previous four bytes are not guaranteed to be a packet header... (IMG_UINT32*)&psTmp->pbyBuffer[psTmp->ui32Size - PVRSRVTL_PACKET_ALIGNMENT]; if ( PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED != GET_PACKET_TYPE( (PVRSRVTL_PACKETHDR*)ui32Buf ) ) { /* Insert size-stamped packet header */ ui32Buf = (IMG_UINT32*)&psTmp->pbyBuffer[ui32LWrite]; *ui32Buf = PVRSRVTL_SET_PACKET_WRITE_FAILED ; ui32LWrite += sizeof(PVRSRVTL_PACKETHDR); iFreeSpace -= sizeof(PVRSRVTL_PACKETHDR); } psTmp->ui32Write = ui32LWrite; psTmp->ui32Pending = NOTHING_PENDING; if (pui32AvSpace) { *pui32AvSpace = suggestAllocSize(ui32LRead, ui32LWrite, psTmp->ui32Size, ui32ReqSizeMin); } PVR_DPF_RETURN_RC(PVRSRV_ERROR_STREAM_FULL); } } /* Update stream. */ psTmp->ui32Write = ui32LWrite ; psTmp->ui32Pending = ui32LPending ; PVR_DPF_RETURN_OK; }