diff --git a/.travis.yml b/.travis.yml index 03559d8a5..95c670a89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_script: - sudo apt-get -qq install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 - ## Install old APCS ARM toolchain for mc1233x, cc2538 and mbxxx + ## Install old APCS ARM toolchain for mc1233x and mbxxx - if [ ${BUILD_ARCH:-0} = arm-apcs ] ; then $WGET https://raw.githubusercontent.com/wiki/malvira/libmc1322x/files/arm-2008q3-66-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 && tar xjf arm-2008q3*.tar.bz2 -C /tmp/ && @@ -41,15 +41,16 @@ before_script: ## Install mainline ARM toolchain. gcc-arm-none-eabi is available ## in Ubuntu >= 14.04, but this external PPA is needed for 12.04. - - if [ ${BUILD_ARCH:-0} = arm ] ; then + ## Install srecord + - if [ ${BUILD_ARCH:-0} = arm-aapcs ] ; then sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded && sudo apt-get -qq update && - sudo apt-get -qq install gcc-arm-none-eabi && + sudo apt-get -qq install gcc-arm-none-eabi srecord && arm-none-eabi-gcc --version ; fi ## Download and extract cc26xxware - - if [ ${BUILD_ARCH:-0} = arm ] ; then + - if [ ${BUILD_ARCH:-0} = arm-aapcs ] ; then wget http://www.ti.com/lit/sw/swrc296/swrc296.zip && unzip swrc296.zip && export TI_CC26XXWARE=cc26xxware_2_20_06_14829 ; @@ -110,6 +111,7 @@ env: - BUILD_TYPE='rpl' - BUILD_TYPE='rime' - BUILD_TYPE='ipv6' + - BUILD_TYPE='ip64' MAKE_TARGETS='cooja' - BUILD_TYPE='hello-world' - BUILD_TYPE='base' # XXX: netperf disabled b/c it's flaky @@ -122,6 +124,6 @@ env: - BUILD_TYPE='compile-8051-ports' BUILD_CATEGORY='compile' BUILD_ARCH='8051' - BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs' - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' + - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/apps/dhcp/dhcp.c b/apps/dhcp/dhcp.c index 9ac20b102..2c9d35003 100644 --- a/apps/dhcp/dhcp.c +++ b/apps/dhcp/dhcp.c @@ -88,7 +88,7 @@ makestrings(void) uip_getdraddr(&addr); makeaddr(&addr, gateway); - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -147,7 +147,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_sethostaddr(&s->ipaddr); uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); set_statustext("Configured."); process_post(PROCESS_CURRENT(), SHOWCONFIG, NULL); } diff --git a/apps/netconf/netconf.c b/apps/netconf/netconf.c index 8249d35ec..b7a81fb99 100644 --- a/apps/netconf/netconf.c +++ b/apps/netconf/netconf.c @@ -113,7 +113,7 @@ makestrings(void) makeaddr(&addr, gateway); #if UIP_UDP - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -152,7 +152,7 @@ apply_tcpipconfig(void) #if UIP_UDP nullterminate(dnsserver); if(uiplib_ipaddrconv(dnsserver, &addr)) { - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); } #endif /* UIP_UDP */ } diff --git a/apps/rest-coap/Makefile.rest-coap b/apps/rest-coap/Makefile.rest-coap deleted file mode 100644 index cd6e332cd..000000000 --- a/apps/rest-coap/Makefile.rest-coap +++ /dev/null @@ -1,4 +0,0 @@ -rest-coap_src = coap-common.c coap-server.c - -APPS += rest-common -include $(CONTIKI)/apps/rest-common/Makefile.rest-common diff --git a/apps/rest-coap/coap-common.c b/apps/rest-coap/coap-common.c deleted file mode 100644 index 0ddff495d..000000000 --- a/apps/rest-coap/coap-common.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * coap-common.c - * - * Created on: Aug 30, 2010 - * Author: dogan - */ - -#ifdef CONTIKI_TARGET_NETSIM - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -#else - #include "contiki.h" - #include "contiki-net.h" - #include -#endif - -#include "coap-common.h" - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -void init_packet(coap_packet_t* packet) -{ - packet->ver = 1; - packet->type = 0; - packet->option_count = 0; - packet->code = 0; - packet->tid = 0; - packet->options = NULL; - packet->url = NULL; - packet->url_len = 0; - packet->query = NULL; - packet->query_len = 0; - packet->payload = NULL; - packet->payload_len = 0; -} - -int serialize_packet(coap_packet_t* packet, uint8_t* buffer) -{ - int index = 0; - header_option_t* option = NULL; - uint16_t option_delta = 0; - - buffer[0] = (packet->ver) << COAP_HEADER_VERSION_POSITION; - buffer[0] |= (packet->type) << COAP_HEADER_TYPE_POSITION; - buffer[0] |= packet->option_count; - buffer[1] = packet->code; - uint16_t temp = uip_htons(packet->tid); - memcpy( - (void*)&buffer[2], - (void*)(&temp), - sizeof(packet->tid)); - - index += 4; - - PRINTF("serialize option_count %u\n", packet->option_count); - - /*Options should be sorted beforehand*/ - for (option = packet->options ; option ; option = option->next){ - uint16_t delta = option->option - option_delta; - if ( !delta ){ - PRINTF("WARNING: Delta==Zero\n"); - } - buffer[index] = (delta) << COAP_HEADER_OPTION_DELTA_POSITION; - - PRINTF("option %u len %u option diff %u option_value addr %x option addr %x next option addr %x", option->option, option->len, option->option - option_delta, (unsigned int) option->value, (unsigned int)option, (unsigned int)option->next); - - int i = 0; - for ( ; i < option->len ; i++ ){ - PRINTF(" (%u)", option->value[i]); - } - PRINTF("\n"); - - if (option->len < 0xF){ - buffer[index] |= option->len; - index++; - } else{ - buffer[index] |= (0xF); //1111 - buffer[index + 1] = option->len - (0xF); - index += 2; - } - - memcpy((char*)&buffer[index], option->value, option->len); - index += option->len; - option_delta = option->option; - } - - if(packet->payload){ - memcpy(&buffer[index], packet->payload, packet->payload_len); - index += packet->payload_len; - } - - return index; -} diff --git a/apps/rest-coap/coap-common.h b/apps/rest-coap/coap-common.h deleted file mode 100644 index 835d123f3..000000000 --- a/apps/rest-coap/coap-common.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * coap.h - * - * Created on: Aug 25, 2010 - * Author: dogan - */ - -#ifndef COAP_COMMON_H_ -#define COAP_COMMON_H_ - -#include "contiki-net.h" - -/*COAP method types*/ -typedef enum { - COAP_GET = 1, - COAP_POST, - COAP_PUT, - COAP_DELETE -} coap_method_t; - -typedef enum { - MESSAGE_TYPE_CON, - MESSAGE_TYPE_NON, - MESSAGE_TYPE_ACK, - MESSAGE_TYPE_RST -} message_type; - -typedef enum { - OK_200 = 80, - CREATED_201 = 81, - NOT_MODIFIED_304 = 124, - BAD_REQUEST_400 = 160, - NOT_FOUND_404 = 164, - METHOD_NOT_ALLOWED_405 = 165, - UNSUPPORTED_MADIA_TYPE_415 = 175, - INTERNAL_SERVER_ERROR_500 = 200, - BAD_GATEWAY_502 = 202, - GATEWAY_TIMEOUT_504 = 204 -} status_code_t; - -typedef enum { - Option_Type_Content_Type = 1, - Option_Type_Max_Age = 2, - Option_Type_Etag = 4, - Option_Type_Uri_Authority = 5, - Option_Type_Location = 6, - Option_Type_Uri_Path = 9, - Option_Type_Subscription_Lifetime = 10, - Option_Type_Token = 11, - Option_Type_Block = 13, - Option_Type_Uri_Query = 15 -} option_type; - -typedef enum { - TEXT_PLAIN = 0, - TEXT_XML = 1, - TEXT_CSV = 2, - TEXT_HTML = 3, - IMAGE_GIF = 21, - IMAGE_JPEG = 22, - IMAGE_PNG = 23, - IMAGE_TIFF = 24, - AUDIO_RAW = 25, - VIDEO_RAW = 26, - APPLICATION_LINK_FORMAT = 40, - APPLICATION_XML = 41, - APPLICATION_OCTET_STREAM = 42, - APPLICATION_RDF_XML = 43, - APPLICATION_SOAP_XML = 44, - APPLICATION_ATOM_XML = 45, - APPLICATION_XMPP_XML = 46, - APPLICATION_EXI = 47, - APPLICATION_X_BXML = 48, - APPLICATION_FASTINFOSET = 49, - APPLICATION_SOAP_FASTINFOSET = 50, - APPLICATION_JSON = 51 -} content_type_t; - -#define COAP_HEADER_VERSION_MASK 0xC0 -#define COAP_HEADER_TYPE_MASK 0x30 -#define COAP_HEADER_OPTION_COUNT_MASK 0x0F -#define COAP_HEADER_OPTION_DELTA_MASK 0xF0 -#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F - -#define COAP_HEADER_VERSION_POSITION 6 -#define COAP_HEADER_TYPE_POSITION 4 -#define COAP_HEADER_OPTION_DELTA_POSITION 4 - -#define REQUEST_BUFFER_SIZE 200 - -#define DEFAULT_CONTENT_TYPE 0 -#define DEFAULT_MAX_AGE 60 -#define DEFAULT_URI_AUTHORITY "" -#define DEFAULT_URI_PATH "" - -//keep open requests and their xactid - -struct header_option_t -{ - struct header_option_t* next; - uint16_t option; - uint16_t len; - uint8_t* value; -}; -typedef struct header_option_t header_option_t; - -struct block_option_t { - uint32_t number; - uint8_t more; - uint8_t size; -}; -typedef struct block_option_t block_option_t; - -typedef struct -{ - uint8_t ver; //2-bits currently set to 1. - uint8_t type; //2-bits Confirmable (0), Non-Confirmable (1), Acknowledgment (2) or Reset (3) - uint8_t option_count; //4-bits - uint8_t code; //8-bits Method or response code - uint16_t tid; //16-bit unsigned integer - header_option_t* options; - char* url; //put it just as a shortcut or else need to parse options everytime to access it. - uint16_t url_len; - char* query; - uint16_t query_len; - uint16_t payload_len; - uint8_t* payload; - uip_ipaddr_t addr; -} coap_packet_t; - -/*error definitions*/ -typedef enum -{ - NO_ERROR, - - /*Memory errors*/ - MEMORY_ALLOC_ERR, - MEMORY_BOUNDARY_EXCEEDED -} error_t; - -int serialize_packet(coap_packet_t* request, uint8_t* buffer); -void init_packet(coap_packet_t* packet); - -#endif /* COAP_COMMON_H_ */ diff --git a/apps/rest-coap/coap-server.c b/apps/rest-coap/coap-server.c deleted file mode 100644 index 6f20e364c..000000000 --- a/apps/rest-coap/coap-server.c +++ /dev/null @@ -1,545 +0,0 @@ -#include -#include -#include -#include /*for isxdigit*/ -#include "contiki.h" -#include "contiki-net.h" - -#include "buffer.h" -#include "coap-server.h" -#include "rest-util.h" -#include "rest.h" /*added for periodic_resource*/ - -#include "dev/leds.h" - -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) -#include "static-routing.h" -#endif - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -#define MAX_PAYLOAD_LEN 120 -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -static struct uip_udp_conn *server_conn; - -static uint16_t current_tid; - -static service_callback service_cbk = NULL; - -void -coap_set_service_callback(service_callback callback) -{ - service_cbk = callback; -} - -void -parse_message(coap_packet_t* packet, uint8_t* buf, uint16_t size) -{ - int processed = 0; - int i = 0; - PRINTF("parse_message size %d-->\n",size); - - init_packet(packet); - - packet->ver = (buf[0] & COAP_HEADER_VERSION_MASK) >> COAP_HEADER_VERSION_POSITION; - packet->type = (buf[0] & COAP_HEADER_TYPE_MASK) >> COAP_HEADER_TYPE_POSITION; - packet->option_count = buf[0] & COAP_HEADER_OPTION_COUNT_MASK; - packet->code = buf[1]; - packet->tid = (buf[2] << 8) + buf[3]; - - processed += 4; - - if (packet->option_count) { - int option_index = 0; - uint8_t option_delta; - uint16_t option_len; - uint8_t* option_buf = buf + processed; - packet->options = (header_option_t*)allocate_buffer(sizeof(header_option_t) * packet->option_count); - - if (packet->options) { - header_option_t* current_option = packet->options; - header_option_t* prev_option = NULL; - while(option_index < packet->option_count) { - /*FIXME : put boundary controls*/ - option_delta = (option_buf[i] & COAP_HEADER_OPTION_DELTA_MASK) >> COAP_HEADER_OPTION_DELTA_POSITION; - option_len = (option_buf[i] & COAP_HEADER_OPTION_SHORT_LENGTH_MASK); - i++; - if (option_len == 0xf) { - option_len += option_buf[i]; - i++; - } - - current_option->option = option_delta; - current_option->len = option_len; - current_option->value = option_buf + i; - if (option_index) { - prev_option->next = current_option; - /*This field defines the difference between the option Type of - * this option and the previous option (or zero for the first option)*/ - current_option->option += prev_option->option; - } - - if (current_option->option == Option_Type_Uri_Path) { - packet->url = (char*)current_option->value; - packet->url_len = current_option->len; - } else if (current_option->option == Option_Type_Uri_Query){ - packet->query = (char*)current_option->value; - packet->query_len = current_option->len; - } - - PRINTF("OPTION %d %u %s \n", current_option->option, current_option->len, current_option->value); - - i += option_len; - option_index++; - prev_option = current_option++; - } - current_option->next = NULL; - } else { - PRINTF("MEMORY ERROR\n"); /*FIXME : add control here*/ - return; - } - } - processed += i; - - /**/ - if (processed < size) { - packet->payload = &buf[processed]; - packet->payload_len = size - processed; - } - - /*FIXME url is not decoded - is necessary?*/ - - /*If query is not already provided via Uri_Query option then check URL*/ - if (packet->url && !packet->query) { - if ((packet->query = strchr(packet->url, '?'))) { - uint16_t total_url_len = packet->url_len; - /*set query len and update url len so that it does not include query part now*/ - packet->url_len = packet->query - packet->url; - packet->query++; - packet->query_len = packet->url + total_url_len - packet->query; - - PRINTF("url %s, url_len %u, query %s, query_len %u\n", packet->url, packet->url_len, packet->query, packet->query_len); - } - } - - PRINTF("PACKET ver:%d type:%d oc:%d \ncode:%d tid:%u url:%s len:%u payload:%s pay_len %u\n", (int)packet->ver, (int)packet->type, (int)packet->option_count, (int)packet->code, packet->tid, packet->url, packet->url_len, packet->payload, packet->payload_len); -} - -int -coap_get_query_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size) -{ - if (packet->query) { - return get_variable(name, packet->query, packet->query_len, output, output_size, 0); - } - - return 0; -} - -int -coap_get_post_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size) -{ - if (packet->payload) { - return get_variable(name, packet->payload, packet->payload_len, output, output_size, 1); - } - - return 0; -} - -static header_option_t* -allocate_header_option(uint16_t variable_len) -{ - PRINTF("sizeof header_option_t %u variable size %u\n", sizeof(header_option_t), variable_len); - uint8_t* buffer = allocate_buffer(sizeof(header_option_t) + variable_len); - if (buffer){ - header_option_t* option = (header_option_t*) buffer; - option->next = NULL; - option->len = 0; - option->value = buffer + sizeof(header_option_t); - return option; - } - - return NULL; -} - -/*FIXME : does not overwrite the same option yet.*/ -int -coap_set_option(coap_packet_t* packet, option_type option_type, uint16_t len, uint8_t* value) -{ - PRINTF("coap_set_option len %u\n", len); - header_option_t* option = allocate_header_option(len); - if (option){ - option->next = NULL; - option->len = len; - option->option = option_type; - memcpy(option->value, value, len); - header_option_t* option_current = packet->options; - header_option_t* prev = NULL; - while (option_current){ - if (option_current->option > option->option){ - break; - } - prev = option_current; - option_current = option_current->next; - } - - if (!prev){ - if (option_current){ - option->next = option_current; - } - packet->options = option; - } else{ - option->next = option_current; - prev->next = option; - } - - packet->option_count++; - - PRINTF("option->len %u option->option %u option->value %x next %x\n", option->len, option->option, (unsigned int) option->value, (unsigned int)option->next); - - int i = 0; - for ( ; i < option->len ; i++ ){ - PRINTF(" (%u)", option->value[i]); - } - PRINTF("\n"); - - return 1; - } - - return 0; -} - -header_option_t* -coap_get_option(coap_packet_t* packet, option_type option_type) -{ - PRINTF("coap_get_option count: %u--> \n", packet->option_count); - int i = 0; - - header_option_t* current_option = packet->options; - for (; i < packet->option_count; current_option = current_option->next, i++) { - PRINTF("Current option: %u\n", current_option->option); - if (current_option->option == option_type){ - return current_option; - } - } - - return NULL; -} - -static void -fill_error_packet(coap_packet_t* packet, int error, uint16_t tid) -{ - packet->ver=1; - packet->option_count=0; - packet->url=NULL; - packet->options=NULL; - switch (error){ - case MEMORY_ALLOC_ERR: - packet->code=INTERNAL_SERVER_ERROR_500; - packet->tid=tid; - packet->type=MESSAGE_TYPE_ACK; - break; - default: - break; - } -} - -static void -init_response(coap_packet_t* request, coap_packet_t* response) -{ - init_packet(response); - if(request->type == MESSAGE_TYPE_CON) { - response->code = OK_200; - response->tid = request->tid; - response->type = MESSAGE_TYPE_ACK; - } -} - -uint16_t -coap_get_payload(coap_packet_t* packet, uint8_t** payload) -{ - if (packet->payload) { - *payload = packet->payload; - return packet->payload_len; - } else { - *payload = NULL; - return 0; - } -} - -int -coap_set_payload(coap_packet_t* packet, uint8_t* payload, uint16_t size) -{ - packet->payload = copy_to_buffer(payload, size); - if (packet->payload) { - packet->payload_len = size; - return 1; - } - - return 0; -} - -int -coap_set_header_content_type(coap_packet_t* packet, content_type_t content_type) -{ - uint16_t len = 1; - - return coap_set_option(packet, Option_Type_Content_Type, len, (uint8_t*) &content_type); -} - -content_type_t -coap_get_header_content_type(coap_packet_t* packet) -{ - header_option_t* option = coap_get_option(packet, Option_Type_Content_Type); - if (option){ - return (uint8_t)(*(option->value)); - } - - return DEFAULT_CONTENT_TYPE; -} - -int -coap_get_header_subscription_lifetime(coap_packet_t* packet, uint32_t* lifetime) -{ - PRINTF("coap_get_header_subscription_lifetime --> \n"); - header_option_t* option = coap_get_option(packet, Option_Type_Subscription_Lifetime); - if (option){ - PRINTF("Subs Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]); - - *lifetime = read_int(option->value, option->len); - return 1; - } - - return 0; -} - -int -coap_set_header_subscription_lifetime(coap_packet_t* packet, uint32_t lifetime) -{ - uint8_t temp[4]; - uint16_t len = write_variable_int(temp, lifetime); - - return coap_set_option(packet, Option_Type_Subscription_Lifetime, len, temp); -} - -int -coap_get_header_block(coap_packet_t* packet, block_option_t* block) -{ - uint32_t all_block; - PRINTF("coap_get_header_block --> \n"); - header_option_t* option = coap_get_option(packet, Option_Type_Block); - if (option){ - PRINTF("Block Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]); - - all_block = read_int(option->value, option->len); - block->number = all_block >> 4; - block->more = (all_block & 0x8) >> 3; - block->size = (all_block & 0x7); - return 1; - } - - return 0; -} - -int -coap_set_header_block(coap_packet_t* packet, uint32_t number, uint8_t more, uint8_t size) -{ - uint8_t temp[4]; - size = log_2(size/16); - number = number << 4; - number |= (more << 3) & 0x8; - number |= size & 0x7; - - uint16_t len = write_variable_int(temp, number); - PRINTF("number %lu, more %u, size %u block[0] %u block[1] %u block[2] %u block[3] %u\n", - number, (uint16_t)more, (uint16_t)size, (uint16_t)temp[0], (uint16_t)temp[1], (uint16_t)temp[2], (uint16_t)temp[3]); - return coap_set_option(packet, Option_Type_Block, len, temp); -} - - -int -coap_set_header_uri(coap_packet_t* packet, char* uri) -{ - return coap_set_option(packet, Option_Type_Uri_Path, strlen(uri), (uint8_t*) uri); -} - -int -coap_set_header_etag(coap_packet_t* packet, uint8_t* etag, uint8_t size) -{ - return coap_set_option(packet, Option_Type_Etag, size, etag); -} - -void -coap_set_code(coap_packet_t* packet, status_code_t code) -{ - packet->code = (uint8_t)code; -} - -coap_method_t -coap_get_method(coap_packet_t* packet) -{ - return (coap_method_t)packet->code; -} - -void -coap_set_method(coap_packet_t* packet, coap_method_t method) -{ - packet->code = (uint8_t)method; -} - -static void send_request(coap_packet_t* request, struct uip_udp_conn *client_conn) -{ - char buf[MAX_PAYLOAD_LEN]; - int data_size = 0; - - data_size = serialize_packet(request, buf); - - PRINTF("Created a connection with the server "); - PRINT6ADDR(&client_conn->ripaddr); - PRINTF(" local/remote port %u/%u\n", - uip_htons(client_conn->lport), uip_htons(client_conn->rport)); - - PRINTF("Sending to: "); - PRINT6ADDR(&client_conn->ripaddr); - uip_udp_packet_send(client_conn, buf, data_size); -} - -static int -handle_incoming_data(void) -{ - int error=NO_ERROR; - char buf[MAX_PAYLOAD_LEN]; - - PRINTF("uip_datalen received %u \n",(uint16_t)uip_datalen()); - - char* data = (char *)uip_appdata + uip_ext_len; - uint16_t datalen = uip_datalen() - uip_ext_len; - - int data_size = 0; - - if (uip_newdata()) { - ((char *)data)[datalen] = 0; - PRINTF("Server received: '%s' (port:%u) from ", (char *)data, uip_htons(UIP_UDP_BUF->srcport)); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("\n"); - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - parse_message(request, (uint8_t*)data, datalen); - - uip_ipaddr_copy(&request->addr, &UIP_IP_BUF->srcipaddr); - - if (request->type != MESSAGE_TYPE_ACK) { - coap_packet_t* response = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_response(request, response); - - if (service_cbk) { - service_cbk(request, response); - } - - data_size = serialize_packet(response, buf); - - } - delete_buffer(); - } else { - PRINTF("Memory Alloc Error\n"); - error = MEMORY_ALLOC_ERR; - /*FIXME : Crappy way of accessing TID of the incoming packet, fix it!*/ - coap_packet_t error_packet; - fill_error_packet(&error_packet,error, (data[2] << 8) + data[3]); - data_size = serialize_packet(&error_packet, buf); - } - - uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); - server_conn->rport = UIP_UDP_BUF->srcport; - - PRINTF("Responding with message size: %d\n",data_size); - uip_udp_packet_send(server_conn, buf, data_size); - /* Restore server connection to allow data from any node */ - memset(&server_conn->ripaddr, 0, sizeof(server_conn->ripaddr)); - server_conn->rport = 0; - } - - return error; -} - -process_event_t resource_changed_event; - -void -resource_changed(struct periodic_resource_t* resource) -{ - process_post(&coap_server, resource_changed_event, (process_data_t)resource); -} - - -/*---------------------------------------------------------------------------*/ - -PROCESS(coap_server, "Coap Server"); -PROCESS_THREAD(coap_server, ev, data) -{ - PROCESS_BEGIN(); - PRINTF("COAP SERVER\n"); - -/* if static routes are used rather than RPL */ -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) - set_global_address(); - configure_routing(); -#endif - - current_tid = random_rand(); - - resource_changed_event = process_alloc_event(); - - /* new connection with remote host */ - server_conn = udp_new(NULL, uip_htons(0), NULL); - udp_bind(server_conn, uip_htons(MOTE_SERVER_LISTEN_PORT)); - PRINTF("Local/remote port %u/%u\n", uip_htons(server_conn->lport), uip_htons(server_conn->rport)); - - while(1) { - PROCESS_YIELD(); - - if(ev == tcpip_event) { - handle_incoming_data(); - } else if (ev == resource_changed_event) { - periodic_resource_t* resource = (periodic_resource_t*)data; - PRINTF("resource_changed_event \n"); - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_packet(request); - coap_set_code(request, COAP_GET); - request->tid = current_tid++; - coap_set_header_subscription_lifetime(request, resource->lifetime); - coap_set_header_uri(request, (char *)resource->resource->url); - if (resource->periodic_request_generator) { - resource->periodic_request_generator(request); - } - - if (!resource->client_conn) { - /*FIXME send port is fixed for now to 61616*/ - resource->client_conn = udp_new(&resource->addr, uip_htons(61616), NULL); - udp_bind(resource->client_conn, uip_htons(MOTE_CLIENT_LISTEN_PORT)); - } - - if (resource->client_conn) { - send_request(request, resource->client_conn); - } - - delete_buffer(); - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/apps/rest-coap/coap-server.h b/apps/rest-coap/coap-server.h deleted file mode 100644 index 888d08721..000000000 --- a/apps/rest-coap/coap-server.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef COAPSERVER_H_ -#define COAPSERVER_H_ - -#define COAP_DATA_BUFF_SIZE 300 - -#include "contiki.h" -#include "coap-common.h" - -/*Declare process*/ -PROCESS_NAME(coap_server); - -#define MOTE_SERVER_LISTEN_PORT 61616 -#define MOTE_CLIENT_LISTEN_PORT 61617 - -void parse_message(coap_packet_t* packet, uint8_t* buf, uint16_t size); - -uint16_t coap_get_payload(coap_packet_t* packet, uint8_t** payload); -int coap_set_payload(coap_packet_t* packet, uint8_t* payload, uint16_t size); - -content_type_t coap_get_header_content_type(coap_packet_t* packet); -int coap_set_header_content_type(coap_packet_t* packet, content_type_t content_type); - -int coap_get_header_subscription_lifetime(coap_packet_t* packet, uint32_t* lifetime); -int coap_set_header_subscription_lifetime(coap_packet_t* packet, uint32_t lifetime); - -int coap_get_header_block(coap_packet_t* packet, block_option_t* block); -int coap_set_header_block(coap_packet_t* packet, uint32_t number, uint8_t more, uint8_t size); - -int coap_set_header_uri(coap_packet_t* packet, char* uri); -int coap_set_header_etag(coap_packet_t* packet, uint8_t* etag, uint8_t size); - -void coap_set_code(coap_packet_t* packet, status_code_t code); - -coap_method_t coap_get_method(coap_packet_t* packet); -void coap_set_method(coap_packet_t* packet, coap_method_t method); - -int coap_get_query_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size); -int coap_get_post_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size); - -header_option_t* coap_get_option(coap_packet_t* packet, option_type option_type); -int coap_set_option(coap_packet_t* packet, option_type option_type, uint16_t len, uint8_t* value); - -/*Type definition of the service callback*/ -typedef int (*service_callback) (coap_packet_t* request, coap_packet_t* response); - -/* - *Setter of the service callback, this callback will be called in case of HTTP request. - */ -void coap_set_service_callback(service_callback callback); - -struct periodic_resource_t; -void resource_changed(struct periodic_resource_t* resource); - -#endif /* COAPSERVER_H_ */ diff --git a/apps/rest-common/Makefile.rest-common b/apps/rest-common/Makefile.rest-common deleted file mode 100644 index 4ce0e5ac3..000000000 --- a/apps/rest-common/Makefile.rest-common +++ /dev/null @@ -1 +0,0 @@ -rest-common_src = rest.c rest-util.c buffer.c static-routing.c diff --git a/apps/rest-common/buffer.c b/apps/rest-common/buffer.c deleted file mode 100644 index df5f616a1..000000000 --- a/apps/rest-common/buffer.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * buffer.c - * - * Created on: Oct 19, 2010 - * Author: dogan - */ - -#include -#include -#include -#include "buffer.h" - -uint8_t* data_buffer; -uint16_t buffer_size; -uint16_t buffer_index; - -void -delete_buffer(void) -{ - if (data_buffer) { - free(data_buffer); - data_buffer = NULL; - buffer_index = 0; - buffer_size = 0; - } -} - -uint8_t* -init_buffer(uint16_t size) -{ - delete_buffer(); - data_buffer = (uint8_t*)malloc(size); - if (data_buffer) { - buffer_size = size; - } - buffer_index = 0; - - return data_buffer; -} - -uint8_t* -allocate_buffer(uint16_t size) -{ - uint8_t* buffer = NULL; - int rem = 0; - /*To get rid of alignment problems, always allocate even size*/ - rem = size % 4; - if (rem) { - size+=(4-rem); - } - if (buffer_index + size < buffer_size) { - buffer = data_buffer + buffer_index; - buffer_index += size; - } - - return buffer; -} - -uint8_t* -copy_to_buffer(void* data, uint16_t len) -{ - uint8_t* buffer = allocate_buffer(len); - if (buffer) { - memcpy(buffer, data, len); - } - - return buffer; -} - -uint8_t* -copy_text_to_buffer(char* text) -{ - uint8_t* buffer = allocate_buffer(strlen(text) + 1); - if (buffer) { - strcpy(buffer, text); - } - - return buffer; -} diff --git a/apps/rest-common/buffer.h b/apps/rest-common/buffer.h deleted file mode 100644 index dd72ac2cf..000000000 --- a/apps/rest-common/buffer.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * buffer.h - * - * Created on: Oct 19, 2010 - * Author: dogan - */ - -#ifndef BUFFER_H_ -#define BUFFER_H_ - -void delete_buffer(void); -uint8_t* init_buffer(uint16_t size); -uint8_t* allocate_buffer(uint16_t size); -uint8_t* copy_to_buffer(void* data, uint16_t len); -uint8_t* copy_text_to_buffer(char* text); - -#endif /* BUFFER_H_ */ diff --git a/apps/rest-common/rest-util.c b/apps/rest-common/rest-util.c deleted file mode 100644 index b7e7f118e..000000000 --- a/apps/rest-common/rest-util.c +++ /dev/null @@ -1,118 +0,0 @@ -#include /*for size_t*/ -#include /*for isxdigit*/ -#include - -#include "contiki-net.h" - -/*Copied from mangoose http server*/ -size_t -decode(const char *src, size_t srclen, char *dst, size_t dstlen, int is_form) -{ - size_t i, j; - int a, b; -#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') - - for (i = j = 0; i < srclen && j < dstlen - 1; i++, j++) { - if (src[i] == '%' && - isxdigit(* (unsigned char *) (src + i + 1)) && - isxdigit(* (unsigned char *) (src + i + 2))) { - a = tolower(* (unsigned char *) (src + i + 1)); - b = tolower(* (unsigned char *) (src + i + 2)); - dst[j] = ((HEXTOI(a) << 4) | HEXTOI(b)) & 0xff; - i += 2; - } else if (is_form && src[i] == '+') { - dst[j] = ' '; - } else { - dst[j] = src[i]; - } - } - - dst[j] = '\0'; /* Null-terminate the destination */ - - return ( i == srclen ); -} - -/*Copied from mangoose http server*/ -int -get_variable(const char *name, const char *buffer, size_t buflen, char* output, size_t output_len, int decode_type) -{ - const char *start = NULL, *end = NULL, *end_of_value; - size_t var_len = 0; - - /*initialize the output buffer first*/ - *output = 0; - - var_len = strlen(name); - end = buffer + buflen; - - for (start = buffer; start + var_len < end; start++){ - if ((start == buffer || start[-1] == '&') && start[var_len] == '=' && - ! strncmp(name, start, var_len)) { - /* Point p to variable value */ - start += var_len + 1; - - /* Point s to the end of the value */ - end_of_value = (const char *) memchr(start, '&', end - start); - if (end_of_value == NULL) { - end_of_value = end; - } - - return decode(start, end_of_value - start, output, output_len, decode_type); - } - } - - return 0; -} - -uint32_t -read_int(uint8_t *buf, uint8_t size) -{ - uint32_t data = 0; - - if (size >= 1 && size <= 4) { - uint8_t *p = (uint8_t *)&data; - memcpy(p + 4 - size, buf, size); - } - - return uip_ntohl(data); -} - - -int -write_int(uint8_t *buf, uint32_t data, uint8_t size) -{ - int success = 0; - - if (size >= 1 && size <= 4) { - data = uip_htonl(data); - memcpy(buf, ((char*)(&data)) + 4 - size, size); - success = size; - } - - return success; -} - -int -write_variable_int(uint8_t *buf, uint32_t data) -{ - uint8_t size = 4; - if (data <= 0xFF) { - size = 1; - } else if (data <= 0xFFFF) { - size = 2; - } else if (data <= 0xFFFFFF) { - size = 3; - } - return write_int(buf, data, size); -} - -uint16_t log_2(uint16_t value) -{ - uint16_t result = 0; - do { - value = value >> 1; - result++; - } while (value); - - return result ? result - 1 : result; -} diff --git a/apps/rest-common/rest-util.h b/apps/rest-common/rest-util.h deleted file mode 100644 index 421c8b3ea..000000000 --- a/apps/rest-common/rest-util.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * rest-util.h - * - * Created on: Oct 26, 2010 - * Author: dogan - */ - -#ifndef RESTUTIL_H_ -#define RESTUTIL_H_ - -size_t decode(const char *src, size_t srclen, char *dst, size_t dstlen, int is_form); -int get_variable(const char *name, const char *buffer, size_t buflen, char* output, size_t output_len, int decode_type); - -uint32_t read_int(uint8_t *buf, uint8_t size); -int write_int(uint8_t *buf, uint32_t data, uint8_t size); -int write_variable_int(uint8_t *buf, uint32_t data); - -uint16_t log_2(uint16_t value); - -#endif /* RESTUTIL_H_ */ diff --git a/apps/rest-common/rest.c b/apps/rest-common/rest.c deleted file mode 100644 index b28ae1bd5..000000000 --- a/apps/rest-common/rest.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "contiki.h" -#include /*for string operations in match_addresses*/ -#include "rest.h" -#include "buffer.h" - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -/*FIXME it is possible to define some of the rest functions as MACROs rather than functions full of ifdefs.*/ - -PROCESS_NAME(rest_manager_process); - -LIST(restful_services); -LIST(restful_periodic_services); - -void -rest_init(void) -{ - list_init(restful_services); - -#ifdef WITH_COAP - coap_set_service_callback(rest_invoke_restful_service); -#else /*WITH_COAP*/ - http_set_service_callback(rest_invoke_restful_service); -#endif /*WITH_COAP*/ - - /*Start rest framework process*/ - process_start(&rest_manager_process, NULL); -} - -void -rest_activate_resource(resource_t* resource) -{ - /*add it to the restful web service link list*/ - list_add(restful_services, resource); -} - -void -rest_activate_periodic_resource(periodic_resource_t* periodic_resource) -{ - list_add(restful_periodic_services, periodic_resource); - rest_activate_resource(periodic_resource->resource); -} - -void -rest_set_user_data(resource_t* resource, void* user_data) -{ - resource->user_data = user_data; -} - -void* -rest_get_user_data(resource_t* resource) -{ - return resource->user_data; -} - -void -rest_set_pre_handler(resource_t* resource, restful_pre_handler pre_handler) -{ - resource->pre_handler = pre_handler; -} - -void -rest_set_post_handler(resource_t* resource, restful_post_handler post_handler) -{ - resource->post_handler = post_handler; -} - -list_t -rest_get_resources(void) -{ - return restful_services; -} - -void -rest_set_response_status(RESPONSE* response, status_code_t status) -{ -#ifdef WITH_COAP - coap_set_code(response, status); -#else /*WITH_COAP*/ - http_set_status(response, status); -#endif /*WITH_COAP*/ -} - -#ifdef WITH_COAP -static method_t coap_to_rest_method(coap_method_t method) -{ - return (method_t)(1 << (method - 1)); -} - -static coap_method_t rest_to_coap_method(method_t method) -{ - coap_method_t coap_method = COAP_GET; - switch (method) { - case METHOD_GET: - coap_method = COAP_GET; - break; - case METHOD_POST: - coap_method = COAP_POST; - break; - case METHOD_PUT: - coap_method = COAP_PUT; - break; - case METHOD_DELETE: - coap_method = COAP_DELETE; - break; - default: - break; - } - return coap_method; -} -#endif /*WITH_COAP*/ - -method_t -rest_get_method_type(REQUEST* request) -{ -#ifdef WITH_COAP - return coap_to_rest_method(coap_get_method(request)); -#else - return (method_t)(request->request_type); -#endif -} - -/*Only defined for COAP for now.*/ -#ifdef WITH_COAP -void -rest_set_method_type(REQUEST* request, method_t method) -{ - coap_set_method(request, rest_to_coap_method(method)); -} -#endif /*WITH_COAP*/ - -void -rest_set_response_payload(RESPONSE* response, uint8_t* payload, uint16_t size) -{ -#ifdef WITH_COAP - coap_set_payload(response, payload, size); -#else - http_set_res_payload(response, payload, size); -#endif /*WITH_COAP*/ -} - -/*Only defined for COAP for now.*/ -#ifdef WITH_COAP -void -rest_set_request_payload(REQUEST* request, uint8_t* payload, uint16_t size) -{ - coap_set_payload(request, payload, size); -} -#endif /*WITH_COAP*/ - -int -rest_get_query_variable(REQUEST* request, const char *name, char* output, uint16_t output_size) -{ -#ifdef WITH_COAP - return coap_get_query_variable(request, name, output, output_size); -#else - return http_get_query_variable(request, name, output, output_size); -#endif /*WITH_COAP*/ -} - -int -rest_get_post_variable(REQUEST* request, const char *name, char* output, uint16_t output_size) -{ -#ifdef WITH_COAP - return coap_get_post_variable(request, name, output, output_size); -#else - return http_get_post_variable(request, name, output, output_size); -#endif /*WITH_COAP*/ -} - -content_type_t -rest_get_header_content_type(REQUEST* request) -{ -#ifdef WITH_COAP - return coap_get_header_content_type(request); -#else - return http_get_header_content_type(request); -#endif /*WITH_COAP*/ -} - -int -rest_set_header_content_type(RESPONSE* response, content_type_t content_type) -{ -#ifdef WITH_COAP - return coap_set_header_content_type(response, content_type); -#else - return http_set_res_header(response, HTTP_HEADER_NAME_CONTENT_TYPE, http_get_content_type_string(content_type), 1); -#endif /*WITH_COAP*/ - -} - -int -rest_set_header_etag(RESPONSE* response, uint8_t* etag, uint8_t size) -{ -#ifdef WITH_COAP - return coap_set_header_etag(response, etag, size); -#else - /*FIXME for now etag should be a "/0" ending string for http part*/ - char temp_etag[10]; - memcpy(temp_etag, etag, size); - temp_etag[size] = 0; - return http_set_res_header(response, HTTP_HEADER_NAME_ETAG, temp_etag, 1); -#endif /*WITH_COAP*/ -} - -int -rest_invoke_restful_service(REQUEST* request, RESPONSE* response) -{ - int found = 0; - const char* url = request->url; - uint16_t url_len = request->url_len; - - PRINTF("rest_invoke_restful_service url %s url_len %d -->\n", url, url_len); - - resource_t* resource = NULL; - - for (resource = (resource_t*)list_head(restful_services); resource; resource = resource->next) { - /*if the web service handles that kind of requests and urls matches*/ - if (url && strlen(resource->url) == url_len && strncmp(resource->url, url, url_len) == 0){ - found = 1; - method_t method = rest_get_method_type(request); - - PRINTF("method %u, resource->methods_to_handle %u\n", (uint16_t)method, resource->methods_to_handle); - - if (resource->methods_to_handle & method) { - - /*FIXME Need to move somewhere else*/ - #ifdef WITH_COAP - uint32_t lifetime = 0; - if (coap_get_header_subscription_lifetime(request, &lifetime)) { - PRINTF("Lifetime %lu\n", lifetime); - - periodic_resource_t* periodic_resource = NULL; - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services); - periodic_resource; - periodic_resource = periodic_resource->next) { - if (periodic_resource->resource == resource) { - PRINTF("Periodic Resource Found\n"); - PRINT6ADDR(&request->addr); - periodic_resource->lifetime = lifetime; - stimer_set(periodic_resource->lifetime_timer, lifetime); - uip_ipaddr_copy(&periodic_resource->addr, &request->addr); - } - } - } - #endif /*WITH_COAP*/ - - /*call pre handler if it exists*/ - if (!resource->pre_handler || resource->pre_handler(request, response)) { - /* call handler function*/ - resource->handler(request, response); - - /*call post handler if it exists*/ - if (resource->post_handler) { - resource->post_handler(request, response); - } - } - } else { - rest_set_response_status(response, METHOD_NOT_ALLOWED_405); - } - break; - } - } - - if (!found) { - rest_set_response_status(response, NOT_FOUND_404); - } - - return found; -} - -PROCESS(rest_manager_process, "Rest Process"); - -PROCESS_THREAD(rest_manager_process, ev, data) -{ - PROCESS_BEGIN(); - - /*start the coap or http server*/ - process_start(SERVER_PROCESS, NULL); - - PROCESS_PAUSE(); - - /*Periodic resources are only available to COAP implementation*/ -#if 0 -#ifdef WITH_COAP - periodic_resource_t* periodic_resource = NULL; - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services); periodic_resource; periodic_resource = periodic_resource->next) { - if (periodic_resource->period) { - PRINTF("Set timer for Res: %s to %lu\n", periodic_resource->resource->url, periodic_resource->period); - etimer_set(periodic_resource->handler_cb_timer, periodic_resource->period); - } - } - - while(1) { - PROCESS_WAIT_EVENT(); - if (ev == PROCESS_EVENT_TIMER) { - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services);periodic_resource;periodic_resource = periodic_resource->next) { - if (periodic_resource->period && etimer_expired(periodic_resource->handler_cb_timer)) { - PRINTF("Etimer expired for %s (period:%lu life:%lu)\n", periodic_resource->resource->url, periodic_resource->period, periodic_resource->lifetime); - /*call the periodic handler function if exists*/ - if (periodic_resource->periodic_handler) { - if ((periodic_resource->periodic_handler)(periodic_resource->resource)) { - PRINTF("RES CHANGE\n"); - if (!stimer_expired(periodic_resource->lifetime_timer)) { - PRINTF("TIMER NOT EXPIRED\n"); - resource_changed(periodic_resource); - periodic_resource->lifetime = stimer_remaining(periodic_resource->lifetime_timer); - } else { - periodic_resource->lifetime = 0; - } - } - - PRINTF("%s lifetime %lu (%lu) expired %d\n", periodic_resource->resource->url, stimer_remaining(periodic_resource->lifetime_timer), periodic_resource->lifetime, stimer_expired(periodic_resource->lifetime_timer)); - } - etimer_reset(periodic_resource->handler_cb_timer); - } - } - } - } -#endif /*WITH_COAP*/ -#endif - PROCESS_END(); -} diff --git a/apps/rest-common/rest.h b/apps/rest-common/rest.h deleted file mode 100644 index 2cf2ca7f1..000000000 --- a/apps/rest-common/rest.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef REST_H_ -#define REST_H_ - -/*includes*/ -#include "contiki.h" -#include "contiki-lib.h" - -#ifdef WITH_COAP - #include "coap-common.h" -#include "coap-server.h" - #define REQUEST coap_packet_t - #define RESPONSE coap_packet_t - #define SERVER_PROCESS (&coap_server) -#else /*WITH_COAP*/ - /*WITH_HTTP*/ - #include "http-common.h" - #include "http-server.h" - #define REQUEST http_request_t - #define RESPONSE http_response_t - #define SERVER_PROCESS (&http_server) -#endif /*WITH_COAP*/ - -struct resource_t; - -/*REST method types*/ -typedef enum { - METHOD_GET = (1 << 0), - METHOD_POST = (1 << 1), - METHOD_PUT = (1 << 2), - METHOD_DELETE = (1 << 3) -} method_t; - -/*Signature of handler functions*/ -typedef void (*restful_handler) (REQUEST* request, RESPONSE* response); -typedef int (*restful_pre_handler) (REQUEST* request, RESPONSE* response); -typedef void (*restful_post_handler) (REQUEST* request, RESPONSE* response); - -typedef int (*restful_periodic_handler) (struct resource_t* resource); -typedef void (*restful_periodic_request_generator) (REQUEST* request); - -/* - * Data structure representing a resource in REST. - */ -struct resource_t { - struct resource_t *next; /*points to next resource defined*/ - method_t methods_to_handle; /*handled HTTP methods*/ - const char* url; /*handled URL*/ - restful_handler handler; /*handler function*/ - restful_pre_handler pre_handler; /*to be called before handler, may perform initializations*/ - restful_post_handler post_handler; /*to be called after handler, may perform finalizations (cleanup, etc)*/ - void* user_data; /*pointer to user specific data*/ -}; -typedef struct resource_t resource_t; - -struct periodic_resource_t { - struct periodic_resource_t *next; - resource_t *resource; - uint32_t period; - struct etimer* handler_cb_timer; - struct stimer* lifetime_timer; - restful_periodic_handler periodic_handler; - restful_periodic_request_generator periodic_request_generator; - uint32_t lifetime; - uip_ipaddr_t addr; - struct uip_udp_conn *client_conn; -}; -typedef struct periodic_resource_t periodic_resource_t; - -/* - * Macro to define a Resource - * Resources are statically defined for the sake of efficiency and better memory management. - */ -#define RESOURCE(name, methods_to_handle, url) \ -void name##_handler(REQUEST*, RESPONSE*); \ -resource_t resource_##name = {NULL, methods_to_handle, url, name##_handler, NULL, NULL, NULL} - -/* - * Macro to define a Periodic Resource - */ -#define PERIODIC_RESOURCE(name, methods_to_handle, url, period) \ -RESOURCE(name, methods_to_handle, url); \ -int name##_periodic_handler(resource_t*); \ -void name##_periodic_request_generator(REQUEST*); \ -struct etimer handler_cb_timer_##name; \ -struct stimer lifetime_timer_##name; \ -periodic_resource_t periodic_resource_##name = {NULL, &resource_##name, period, &handler_cb_timer_##name, &lifetime_timer_##name, name##_periodic_handler, name##_periodic_request_generator, 0} - - -/* - * Initializes REST framework and starts HTTP or COAP process - */ -void rest_init(void); - -/* - * Resources wanted to be accessible should be activated with the following code. - */ -void rest_activate_resource(resource_t* resource); - -void rest_activate_periodic_resource(periodic_resource_t* periodic_resource); - -/* - * To be called by HTTP/COAP server as a callback function when a new service request appears. - * This function dispatches the corresponding RESTful service. - */ -int rest_invoke_restful_service(REQUEST* request, RESPONSE* response); - -/* - * Returns the resource list - */ -list_t rest_get_resources(void); - -/* - * Returns query variable in the URL. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int rest_get_query_variable(REQUEST* request, const char *name, char* output, uint16_t output_size); - -/* - * Returns variable in the Post Data/Payload. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int rest_get_post_variable(REQUEST* request, const char *name, char* output, uint16_t output_size); - -method_t rest_get_method_type(REQUEST* request); -void rest_set_method_type(REQUEST* request, method_t method); - -/* - * Getter for the request content type - */ -content_type_t rest_get_header_content_type(REQUEST* request); - -/* - * Setter for the response content type - */ -int rest_set_header_content_type(RESPONSE* response, content_type_t content_type); - -/* - * Setter for the response etag header - */ -int rest_set_header_etag(RESPONSE* response, uint8_t* etag, uint8_t size); - -/* - * Setter for the status code (200, 201, etc) of the response. - */ -void rest_set_response_status(RESPONSE* response, status_code_t status); - -/* - * Setter for the payload of the request and response - */ -void rest_set_request_payload(RESPONSE* response, uint8_t* payload, uint16_t size); -void rest_set_response_payload(RESPONSE* response, uint8_t* payload, uint16_t size); - -/* - * Getter method for user specific data. - */ -void* rest_get_user_data(resource_t* resource); - -/* - * Setter method for user specific data. - */ -void rest_set_user_data(resource_t* resource, void* user_data); - -/* - * Sets the pre handler function of the Resource. - * If set, this function will be called just before the original handler function. - * Can be used to setup work before resource handling. - */ -void rest_set_pre_handler(resource_t* resource, restful_pre_handler pre_handler); - -/* - * Sets the post handler function of the Resource. - * If set, this function will be called just after the original handler function. - * Can be used to do cleanup (deallocate memory, etc) after resource handling. - */ -void rest_set_post_handler(resource_t* resource, restful_post_handler post_handler); - -#endif /*REST_H_*/ diff --git a/apps/rest-common/static-routing.c b/apps/rest-common/static-routing.c deleted file mode 100644 index 1d297b2db..000000000 --- a/apps/rest-common/static-routing.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * static-routing.c - * - * Created on: Oct 12, 2010 - * Author: dogan - */ - -#include "static-routing.h" - -#if !defined (CONTIKI_TARGET_MINIMAL_NET) /* Any other targets will be added here (&& ! defined (OTHER))*/ - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - - -#if !UIP_CONF_IPV6_RPL -#include "contiki-net.h" -#include "sys/node-id.h" - -void set_global_address(void) -{ - uip_ipaddr_t ipaddr; - - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); - uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); - uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); -} - -void configure_routing(void) -{ - PRINTF("configure_routing\n"); - - if (node_id < 10) { /*COOJA*/ - /*Go to desktop machine over border router*/ - ADD_ROUTE(DESKTOP_MACHINE_ID, COOJA_BORDER_ROUTER_ID); - } else { /*SKY*/ - if (node_id < 20) { /*First hops (ids between 10-20)*/ - /*Go to desktop machine over border router*/ - ADD_ROUTE(DESKTOP_MACHINE_ID, BORDER_ROUTER_ID); - } - - switch(node_id) { - case 12: - ADD_ROUTE(22, 22); /*Go to next hop over the local address of next hop*/ - break; - case 13: - ADD_ROUTE(23, 23); /*Go to next hop over the local address of next hop*/ - break; - - case 22: - ADD_ROUTE(0, 12); /*Go to desktop machine over the corresponding first hop*/ - break; - case 23: - ADD_ROUTE(0, 13); /*Go to desktop machine over the corresponding first hop*/ - break; - default: - break; - } - } -} -#endif /*!UIP_CONF_IPV6_RPL*/ -#endif /*CONTIKI_TARGET_MINIMAL_NET*/ diff --git a/apps/rest-common/static-routing.h b/apps/rest-common/static-routing.h deleted file mode 100644 index c4b757893..000000000 --- a/apps/rest-common/static-routing.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * static-routing.h - * - * Created on: Oct 12, 2010 - * Author: dogan - */ - -#ifndef STATICROUTING_H_ -#define STATICROUTING_H_ - -#if !defined (CONTIKI_TARGET_MINIMAL_NET) -#define NODE_IP(nodeid,type,ipaddr) NODE_##nodeid##_##type(ipaddr) - -/*desktop machine*/ -#define DESKTOP_MACHINE_ID 0 -#define NODE_0_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0x0001) - -/*Cooja Nodes*/ -#define COOJA_BORDER_ROUTER_ID 1 -#define NODE_1_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) -#define NODE_1_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) - -#define NODE_2_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) -#define NODE_2_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) - -#define NODE_3_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7403, 0x0003, 0x0303) -#define NODE_3_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7403, 0x0003, 0x0303) - -#define NODE_6_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7406, 0x0006, 0x0606) -#define NODE_6_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7406, 0x0006, 0x0606) - -/*real nodes*/ -#define BORDER_ROUTER_ID 11 -#define NODE_11_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xd5f1) -#define NODE_11_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xd5f1) - -#define NODE_12_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x1160, 0xf95a) -#define NODE_12_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x1160, 0xf95a) - -#define NODE_13_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x3575) -#define NODE_13_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x3575) - -#define NODE_22_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xc0f6) -#define NODE_22_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xc0f6) - -#define NODE_23_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x0d5a) -#define NODE_23_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x0d5a) - -#define ADD_ROUTE(node_global,node_local)\ -do{\ - uip_ipaddr_t ipaddr_local, ipaddr_global;\ - NODE_IP(node_global, GLOBAL, &ipaddr_global);\ - NODE_IP(node_local, LOCAL, &ipaddr_local);\ - uip_ds6_route_add(&ipaddr_global, 128, &ipaddr_local);\ -}while(0) - -void set_global_address(void); -void configure_routing(void); - -#endif /*CONTIKI_TARGET_MINIMAL_NET*/ -#endif /* STATICROUTING_H_ */ diff --git a/apps/rest-http/Makefile.rest-http b/apps/rest-http/Makefile.rest-http deleted file mode 100644 index 3d946d2d9..000000000 --- a/apps/rest-http/Makefile.rest-http +++ /dev/null @@ -1,4 +0,0 @@ -rest-http_src = http-common.c http-server.c - -APPS += rest-common -include $(CONTIKI)/apps/rest-common/Makefile.rest-common diff --git a/apps/rest-http/http-common.c b/apps/rest-http/http-common.c deleted file mode 100644 index 0d3deefa3..000000000 --- a/apps/rest-http/http-common.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "http-common.h" - -/*needed for web services giving all path (http://172.16.79.0/services/light1) - * instead relative (/services/light1) in HTTP request. Ex: Restlet lib.*/ -const char* http_string = "http"; - -/*HTTP method strings*/ -const char* http_get_string = "GET"; -const char* http_head_string = "HEAD"; -const char* http_post_string = "POST"; -const char* http_put_string = "PUT"; -const char* http_delete_string = "DELETE"; - -const char* httpv1_1 = "HTTP/1.1"; -const char* line_end = "\r\n"; -const char* contiki = "Contiki"; -const char* close = "close"; - -/*header names*/ -const char* HTTP_HEADER_NAME_CONTENT_TYPE = "Content-Type"; -const char* HTTP_HEADER_NAME_CONTENT_LENGTH = "Content-Length"; -const char* HTTP_HEADER_NAME_LOCATION = "Location"; -const char* HTTP_HEADER_NAME_CONNECTION = "Connection"; -const char* HTTP_HEADER_NAME_SERVER = "Server"; -const char* HTTP_HEADER_NAME_HOST = "Host"; -const char* HTTP_HEADER_NAME_IF_NONE_MATCH = "If-None-Match"; -const char* HTTP_HEADER_NAME_ETAG = "ETag"; - -const char* header_delimiter = ": "; diff --git a/apps/rest-http/http-common.h b/apps/rest-http/http-common.h deleted file mode 100644 index e70115c2b..000000000 --- a/apps/rest-http/http-common.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef HTTPCOMMON_H_ -#define HTTPCOMMON_H_ - -/*includes*/ -#include "contiki.h" -#include "contiki-net.h" - -/*current state of the request, waiting: handling request, output: sending response*/ -#define STATE_WAITING 0 -#define STATE_OUTPUT 1 - -/*definitions of the line ending characters*/ -#define LINE_FEED_CHAR '\n' -#define CARRIAGE_RETURN_CHAR '\r' - -/*needed for web services giving all path (http://172.16.79.0/services/light1) - * instead relative (/services/light1) in HTTP request. Ex: Restlet lib. does it*/ -extern const char* http_string; - -/*HTTP method strings*/ -extern const char* http_get_string; -extern const char* http_head_string; -extern const char* http_post_string; -extern const char* http_put_string; -extern const char* http_delete_string; - -extern const char* httpv1_1; -extern const char* line_end; -extern const char* contiki; -extern const char* close; - -/*header names*/ -extern const char* HTTP_HEADER_NAME_CONTENT_TYPE; -extern const char* HTTP_HEADER_NAME_CONTENT_LENGTH; -extern const char* HTTP_HEADER_NAME_LOCATION; -extern const char* HTTP_HEADER_NAME_CONNECTION; -extern const char* HTTP_HEADER_NAME_SERVER; -extern const char* HTTP_HEADER_NAME_HOST; -extern const char* HTTP_HEADER_NAME_IF_NONE_MATCH; -extern const char* HTTP_HEADER_NAME_ETAG; - -extern const char* header_delimiter; - - -/*Configuration parameters*/ -#define HTTP_PORT 8080 -#define HTTP_DATA_BUFF_SIZE 600 -#define INCOMING_DATA_BUFF_SIZE 102 /*100+2, 100 = max url len, 2 = space char+'\0'*/ - -/*HTTP method types*/ -typedef enum { - HTTP_METHOD_GET = (1 << 0), - HTTP_METHOD_POST = (1 << 1), - HTTP_METHOD_PUT = (1 << 2), - HTTP_METHOD_DELETE = (1 << 3) -} http_method_t; - -//DY : FIXME right now same enum names with COAP with different values. Will this work fine? -typedef enum { - OK_200 = 200, - CREATED_201 = 201, - NOT_MODIFIED_304 = 304, - BAD_REQUEST_400 = 400, - NOT_FOUND_404 = 404, - METHOD_NOT_ALLOWED_405 = 405, - REQUEST_URI_TOO_LONG_414 = 414, - UNSUPPORTED_MADIA_TYPE_415 = 415, - INTERNAL_SERVER_ERROR_500 = 500, - BAD_GATEWAY_502 = 502, - SERVICE_UNAVAILABLE_503 = 503, - GATEWAY_TIMEOUT_504 = 504 -} status_code_t; - -typedef enum { - TEXT_PLAIN, - TEXT_XML, - TEXT_CSV, - TEXT_HTML, - APPLICATION_XML, - APPLICATION_EXI, - APPLICATION_JSON, - APPLICATION_LINK_FORMAT, - APPLICATION_WWW_FORM, - UNKNOWN_CONTENT_TYPE -} content_type_t; - -/*Header type*/ -struct http_header_t { - struct http_header_t* next; - char* name; - char* value; -}; -typedef struct http_header_t http_header_t; - -/*This structure contains information about the HTTP request.*/ -struct http_request_t { - char* url; - uint16_t url_len; - http_method_t request_type; /* GET, POST, etc */ - char* query; - uint16_t query_len; - http_header_t* headers; - uint16_t payload_len; - uint8_t* payload; -}; -typedef struct http_request_t http_request_t; - -/*This structure contains information about the HTTP response.*/ -struct http_response_t { - status_code_t status_code; - char* status_string; - http_header_t* headers; - uint16_t payload_len; - uint8_t* payload; -}; -typedef struct http_response_t http_response_t; - -/*This structure contains information about the TCP Connection.*/ -typedef struct { - struct psock sin, sout; /*Protosockets for incoming and outgoing communication*/ - struct pt outputpt; - char inputbuf[INCOMING_DATA_BUFF_SIZE]; /*to put incoming data in*/ - uint8_t state; - http_request_t request; - http_response_t response; -} connection_state_t; - -/*error definitions*/ -typedef enum { - HTTP_NO_ERROR, - - /*Memory errors*/ - HTTP_MEMORY_ALLOC_ERR, - HTTP_MEMORY_BOUNDARY_EXCEEDED, - - /*specific errors*/ - HTTP_XML_NOT_VALID, - HTTP_SOAP_MESSAGE_NOT_VALID, - HTTP_URL_TOO_LONG, - HTTP_URL_INVALID -} http_error_t; - -#endif /*HTTPCOMMON_H_*/ diff --git a/apps/rest-http/http-server.c b/apps/rest-http/http-server.c deleted file mode 100644 index 256e37904..000000000 --- a/apps/rest-http/http-server.c +++ /dev/null @@ -1,653 +0,0 @@ -#include -#include /*for atoi*/ -#include -#include "contiki.h" - -#include "http-server.h" -#include "buffer.h" -#include "rest-util.h" - -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) -#include "static-routing.h" -#endif - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -static void -init_response(http_response_t* response) -{ - response->status_code = OK_200; - response->status_string = NULL; - response->headers = NULL; - response->payload = NULL; - response->payload_len = 0; -} - -static void -init_request(http_request_t* request) -{ - request->request_type = 0; - request->url = NULL; - request->url_len = 0; - request->query = NULL; - request->query_len = 0; - request->headers = NULL; - request->payload = NULL; - request->payload_len = 0; -} - -/** - * Initializes the connection state by clearing out the data structures - */ -static void -init_connection(connection_state_t* conn_state) -{ - conn_state->state = STATE_WAITING; - - init_request(&conn_state->request); - init_response(&conn_state->response); -} - -void -http_set_status(http_response_t* response, status_code_t status) -{ - response->status_code = status; -} - -static http_header_t* -allocate_header(uint16_t variable_len) -{ - PRINTF("sizeof http_header_t %u variable size %u\n", sizeof(http_header_t), variable_len); - uint8_t* buffer = allocate_buffer(sizeof(http_header_t) + variable_len); - if (buffer) { - http_header_t* option = (http_header_t*) buffer; - option->next = NULL; - option->name = NULL; - option->value = buffer + sizeof(http_header_t); - return option; - } - - return NULL; -} - -int -http_set_res_header(http_response_t* response, const char* name, const char* value, int copy) -{ - PRINTF("http_set_res_header (copy:%d) %s:%s\n", copy, name, value); - uint16_t size = 0; - http_header_t* current_header = NULL; - http_header_t* head = NULL; - - if (copy) { - size += strlen(value) + 1; - } - - current_header = allocate_header(size); - - if (current_header) { - current_header->name = (char*)name; - if (copy) { - strcpy(current_header->value, value); - } else { - current_header->value = (char*)value; - } - - head = response->headers; - response->headers = current_header; - if (head) { - current_header->next = head; - } - - return 1; - } - - return 0; -} - -static const char* is_request_hdr_needed(const char* header_name) -{ - const char* header = NULL; - /*FIXME add needed headers here*/ - if (strcmp(header_name, HTTP_HEADER_NAME_CONTENT_LENGTH) == 0) { - header = HTTP_HEADER_NAME_CONTENT_LENGTH; - } else if (strcmp(header_name, HTTP_HEADER_NAME_CONTENT_TYPE) == 0) { - header = HTTP_HEADER_NAME_CONTENT_TYPE; - } - - return header; -} - -static service_callback service_cbk = NULL; - -void -http_set_service_callback(service_callback callback) -{ - service_cbk = callback; -} - -const char* content_types[] = { - "text/plain", - "text/xml", - "text/csv", - "text/html", - "application/xml", - "application/exi", - "application/json", - "application/link-format", - "application/x-www-form-urlencoded", -}; - -const char* -http_get_content_type_string(content_type_t content_type) -{ - return content_types[content_type]; -} - -char* -get_default_status_string(status_code_t status_code) -{ - char* value = NULL; - switch(status_code) { - case 200: - value = "OK"; - break; - case 201: - value = "Created"; - break; - case 202: - value = "Accepted"; - break; - case 204: - value = "No Content"; - break; - case 304: - value = "Not Modified"; - break; - case 400: - value = "Bad Request" ; - break; - case 404: - value = "Not Found" ; - break; - case 405: - value = "Method Not Allowed" ; - break; - case 406: - value = "Not Acceptable" ; - break; - case 414: - value = "Request-URI Too Long" ; - break; - case 415: - value = "Unsupported Media Type" ; - break; - case 500: - value = "Internal Server Error" ; - break; - case 501: - value = "Not Implemented" ; - break; - case 503: - value = "Service Unavailable" ; - break; - /*FIXME : will be removed later, put to catch the unhandled statuses.*/ - default: - value = "$$BUG$$"; - break; - } - - return value; -} - -int -http_get_query_variable(http_request_t* request, const char *name, char* output, uint16_t output_size) -{ - if (request->query) { - return get_variable(name, request->query, request->query_len, output, output_size, 0); - } - - return 0; -} - -int -http_get_post_variable(http_request_t* request, const char *name, char* output, uint16_t output_size) -{ - if (request->payload) { - return get_variable(name, request->payload, request->payload_len, output, output_size, 1); - } - - return 0; -} - -static int -is_method_handled(connection_state_t* conn_state, const char* method) -{ - /*other method types can be added here if needed*/ - if(strncmp(method, http_get_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_GET; - } else if (strncmp(method, http_post_string, 4) == 0) { - conn_state->request.request_type = HTTP_METHOD_POST; - } else if (strncmp(method, http_put_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_PUT; - } else if (strncmp(method, http_delete_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_DELETE; - } else { - PRINTF("No Method supported : %s\nstate : %d\n", conn_state->inputbuf, conn_state->state); - return 0; - } - - return 1; -} - -static int -parse_url(connection_state_t* conn_state, char* url) -{ - int error = HTTP_NO_ERROR; - int full_url_path = 0; - /*even for default index.html there is / Ex: GET / HTTP/1.1*/ - if (url[0] != '/') { - /*if url is complete (http://...) rather than relative*/ - if (strncmp(url, http_string, 4) != 0 ) { - PRINTF("Url not valid : %s \n",url); - error = HTTP_URL_INVALID; - } else { - full_url_path = 1; - } - } - - if (error == HTTP_NO_ERROR) { - char* url_buffer = url; - if (full_url_path) { - unsigned char num_of_slash = 0; - do { - url_buffer = strchr( ++url_buffer, '/' ); - - PRINTF("Buffer : %s %d\n", url_buffer, num_of_slash); - - } while (url_buffer && ++num_of_slash < 3); - } - - PRINTF("Url found :%s\n", url_buffer); - - /*Get rid of the first slash*/ - if (url_buffer && ++url_buffer) { - conn_state->request.url = (char*) copy_text_to_buffer(url_buffer); - conn_state->request.url_len = strlen(url_buffer); - - if ((conn_state->request.query = strchr(conn_state->request.url, '?'))) { - *(conn_state->request.query++) = 0; - /*update url len - decrease the size of query*/ - conn_state->request.url_len = strlen(conn_state->request.url); - conn_state->request.query_len = strlen(conn_state->request.query); - } - - PRINTF("url %s, url_len %u, query %s, query_len %u\n", conn_state->request.url, conn_state->request.url_len, conn_state->request.query, conn_state->request.query_len); - - /*FIXME url is not decoded - should be done here*/ - } else { - error = HTTP_URL_INVALID; - } - } - - return error; -} - -static int -parse_header(connection_state_t* conn_state, char* inputbuf) -{ - PRINTF("parse_header --->\n"); - const char* header_name = NULL; - - char* delimiter = strchr(inputbuf, ':'); - if (delimiter) { - *delimiter++ = 0; /*after increment delimiter will point space char*/ - - header_name = is_request_hdr_needed(inputbuf); - if (header_name && delimiter) { - char* buffer = delimiter; - - if (buffer[0] == ' ') { - buffer++; - } - - http_header_t* current_header = NULL; - http_header_t* head = NULL; - - current_header = allocate_header(strlen(buffer)); - - if (current_header) { - current_header->name = (char*)header_name; - strcpy(current_header->value, buffer); - } - - head = conn_state->request.headers; - conn_state->request.headers = current_header; - if (head) { - current_header->next = head; - } - - return 1; - } - } - - return 0; -} - -int -http_set_res_payload(http_response_t* response, uint8_t* payload, uint16_t size) -{ - response->payload = copy_to_buffer(payload, size); - if (response->payload) { - response->payload_len = size; - return 1; - } - - return 0; -} - -static const char* -get_header(http_header_t* headers, const char* hdr_name) -{ - for (;headers; headers = headers->next) { - if (strcmp(headers->name, hdr_name) == 0) { - return headers->value; - } - } - - return NULL; -} - -const char* http_get_req_header(http_request_t* request, const char* name) -{ - return get_header(request->headers, name); -} - -content_type_t http_get_header_content_type(http_request_t* request) -{ - const char* content_type_string = http_get_req_header(request, HTTP_HEADER_NAME_CONTENT_TYPE); - if (content_type_string) { - int i = 0; - for(; i < sizeof(content_types)/sizeof(const char*) ; i++) { - if (strcmp(content_types[i], content_type_string)) { - return (content_type_t)i; - } - } - } - - return UNKNOWN_CONTENT_TYPE; -} - -static -PT_THREAD(handle_request(connection_state_t* conn_state)) -{ - static int error; - const char* content_len; - - PSOCK_BEGIN(&(conn_state->sin)); - - content_len = NULL; - - error = HTTP_NO_ERROR; /*always reinit static variables due to protothreads*/ - - PRINTF("Request--->\n"); - - //read method - PSOCK_READTO(&(conn_state->sin), ' '); - - if (!is_method_handled(conn_state, conn_state->inputbuf)) { - /*method not handled*/ - http_set_status(&conn_state->response, SERVICE_UNAVAILABLE_503); - conn_state->state = STATE_OUTPUT; - } else { - /*read until the end of url*/ - PSOCK_READTO(&(conn_state->sin), ' '); - - /*-1 is needed since it also includes space char*/ - if (conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] != ' ' ) { - error = HTTP_URL_TOO_LONG; - } - - conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; - - PRINTF("Read URL:%s\n", conn_state->inputbuf); - - if (error == HTTP_NO_ERROR) { - error = parse_url(conn_state, conn_state->inputbuf); - } - - if (error != HTTP_NO_ERROR) { - if (error == HTTP_URL_TOO_LONG) { - http_set_status(&conn_state->response, REQUEST_URI_TOO_LONG_414); - } else { - http_set_status(&conn_state->response, BAD_REQUEST_400); - } - - conn_state->state = STATE_OUTPUT; - } else { - /*read until the end of HTTP version - not used yet*/ - PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); - - PRINTF("After URL:%s\n", conn_state->inputbuf); - - /*FIXME : PSOCK_READTO takes just a single delimiter so I read till the end of line - but now it may not fit in the buffer. If PSOCK_READTO would take two delimiters, - we would have read until : and so it would not be blocked.*/ - - /*Read the headers and store the necessary ones*/ - do { - /*read the next line*/ - PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); - conn_state->inputbuf[ PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; - - /*if headers finished then stop the infinite loop*/ - if (conn_state->inputbuf[0] == CARRIAGE_RETURN_CHAR || conn_state->inputbuf[0] == 0) { - PRINTF("Finished Headers!\n\n"); - break; - } - - parse_header(conn_state, conn_state->inputbuf); - } - while(1); - - content_len = get_header(conn_state->request.headers, HTTP_HEADER_NAME_CONTENT_LENGTH); - if (content_len) { - conn_state->request.payload_len = atoi(content_len); - - PRINTF("Post Data Size string: %s int: %d\n", content_len, conn_state->request.payload_len); - } - - if (conn_state->request.payload_len) { - static uint16_t read_bytes = 0; - /*init the static variable again*/ - read_bytes = 0; - - conn_state->request.payload = allocate_buffer(conn_state->request.payload_len + 1); - - if (conn_state->request.payload) { - do { - PSOCK_READBUF(&(conn_state->sin)); - /*null terminate the buffer in case it is a string.*/ - conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin))] = 0; - - memcpy(conn_state->request.payload + read_bytes, conn_state->inputbuf, PSOCK_DATALEN(&(conn_state->sin))); - - read_bytes += PSOCK_DATALEN(&(conn_state->sin)); - - } while (read_bytes < conn_state->request.payload_len); - - conn_state->request.payload[read_bytes++] = 0; - - PRINTF("PostData => %s \n", conn_state->request.payload); - } else { - error = HTTP_MEMORY_ALLOC_ERR; - } - } - - if (error == HTTP_NO_ERROR) { - if (service_cbk) { - service_cbk(&conn_state->request, &conn_state->response); - } - } else { - PRINTF("Error:%d\n",error); - http_set_status(&conn_state->response, INTERNAL_SERVER_ERROR_500); - } - - conn_state->state = STATE_OUTPUT; - } - } - - PSOCK_END(&(conn_state->sin)); -} - -static -PT_THREAD(send_data(connection_state_t* conn_state)) -{ - uint16_t index; - http_response_t* response; - http_header_t* header; - uint8_t* buffer; - - PSOCK_BEGIN(&(conn_state->sout)); - - PRINTF("send_data -> \n"); - - index = 0; - response = &conn_state->response; - header = response->headers; - buffer = allocate_buffer(200); - - /*FIXME: what is the best solution here to send the data. Right now, if buffer is not allocated, no data is sent!*/ - if (buffer) { - index += sprintf(buffer + index, "%s %d %s%s", httpv1_1, response->status_code, response->status_string, line_end); - for (;header;header = header->next) { - PRINTF("header %u \n", (uint16_t)header); - index += sprintf(buffer + index, "%s%s%s%s", header->name, header_delimiter, header->value, line_end); - } - index += sprintf(buffer + index, "%s", line_end); - - memcpy(buffer + index, response->payload, response->payload_len); - index += response->payload_len; - - PRINTF("Sending Data(size %d): %s \n", index, buffer); - - PSOCK_SEND(&(conn_state->sout), buffer, index); - } else { - PRINTF("BUFF ERROR: send_data!\n"); - } - - PSOCK_END(&(conn_state->sout)); -} - -static -PT_THREAD(handle_response(connection_state_t* conn_state)) -{ - PT_BEGIN(&(conn_state->outputpt)); - - PRINTF("handle_response ->\n"); - - http_set_res_header(&conn_state->response, HTTP_HEADER_NAME_CONNECTION, close, 0); - http_set_res_header(&conn_state->response, HTTP_HEADER_NAME_SERVER, contiki, 0); - - if (!(conn_state->response.status_string)) { - conn_state->response.status_string = - get_default_status_string(conn_state->response.status_code); - } - - PT_WAIT_THREAD(&(conn_state->outputpt), send_data(conn_state)); - - PRINTF("<-- handle_response\n\n\n"); - - PSOCK_CLOSE(&(conn_state->sout)); - - PT_END(&(conn_state->outputpt)); -} - -static void -handle_connection(connection_state_t* conn_state) -{ - if (conn_state->state == STATE_WAITING) { - handle_request(conn_state); - } - - if (conn_state->state == STATE_OUTPUT) { - handle_response(conn_state); - } -} - -PROCESS(http_server, "Httpd Process"); - -PROCESS_THREAD(http_server, ev, data) -{ - connection_state_t *conn_state; - - PROCESS_BEGIN(); - - /* if static routes are used rather than RPL */ -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) - set_global_address(); - configure_routing(); -#endif /*!UIP_CONF_IPV6_RPL*/ - - #ifdef CONTIKI_TARGET_SKY - PRINTF("##RF CHANNEL : %d##\n",RF_CHANNEL); - #endif //CONTIKI_TARGET_SKY - - tcp_listen(uip_htons(HTTP_PORT)); - - /* - * We loop for ever, accepting new connections. - */ - while(1) { - PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); - - conn_state = (connection_state_t *)data; - - if(uip_connected()) { - PRINTF("##Connected##\n"); - - if(init_buffer(HTTP_DATA_BUFF_SIZE)) { - conn_state = (connection_state_t*)allocate_buffer(sizeof(connection_state_t)); - - if (conn_state) { - tcp_markconn(uip_conn, conn_state); - - /*initialize connection state*/ - init_connection(conn_state); - - /*-1 is needed to be able to null terminate the strings in the buffer, especially good for debugging (to have null terminated strings)*/ - PSOCK_INIT(&(conn_state->sin), (uint8_t*)conn_state->inputbuf, sizeof(conn_state->inputbuf) - 1); - PSOCK_INIT(&(conn_state->sout), (uint8_t*)conn_state->inputbuf, sizeof(conn_state->inputbuf) - 1); - PT_INIT(&(conn_state->outputpt)); - - handle_connection(conn_state); - } else { - PRINTF("Memory Alloc Error. Aborting!\n"); - uip_abort(); - } - } - } else if (uip_aborted() || uip_closed() || uip_timedout()) { - if (conn_state) { - delete_buffer(); - - /*Following 2 lines are needed since this part of code is somehow executed twice so it tries to free the same region twice. - Potential bug in uip*/ - conn_state = NULL; - tcp_markconn(uip_conn, conn_state); - } - } else { - handle_connection(conn_state); - } - } - - PROCESS_END(); -} diff --git a/apps/rest-http/http-server.h b/apps/rest-http/http-server.h deleted file mode 100644 index f28fee0ea..000000000 --- a/apps/rest-http/http-server.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef HTTPSERVER_H_ -#define HTTPSERVER_H_ - -#include "http-common.h" -#include "rest.h" - -/*Declare process*/ -PROCESS_NAME(http_server); - -/*Type definition of the service callback*/ -typedef int (*service_callback) (http_request_t* request, http_response_t* response); - -/* - *Setter of the service callback, this callback will be called in case of HTTP request. - */ -void http_set_service_callback(service_callback callback); - -/* - * Setter for the status code (200, 201, etc) of the response. - */ -void http_set_status(http_response_t* response, status_code_t status); - -/* - * Adds the header name and value provided to the response. - * Name of the header should be hardcoded since it is accessed from code segment - * (not copied to buffer) whereas value of the header can be copied - * depending on the relevant parameter. This is needed since some values may be - * generated dynamically (ex: e-tag value) - */ -int http_set_res_header(http_response_t* response, const char* name, const char* value, int copy); - -/* - * Returns the value of the header name provided. Return NULL if header does not exist. - */ -const char* http_get_req_header(http_request_t* request, const char* name); - -int http_set_res_payload(http_response_t* response, uint8_t* payload, uint16_t size); - -/* - * Returns query variable in the URL. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int http_get_query_variable(http_request_t* request, const char *name, char* output, uint16_t output_size); - -/* - * Returns variable in the Post Data. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int http_get_post_variable(http_request_t* request, const char *name, char* output, uint16_t output_size); - -/* - * Get the header "Content-Type". - */ -const char* http_get_content_type_string(content_type_t content_type); -content_type_t http_get_header_content_type(http_request_t* request); - -#endif /*HTTPSERVER_H_*/ diff --git a/apps/shell/Makefile.shell b/apps/shell/Makefile.shell index 39d444781..db1de4d6a 100644 --- a/apps/shell/Makefile.shell +++ b/apps/shell/Makefile.shell @@ -9,7 +9,7 @@ shell_src = shell.c shell-reboot.c shell-vars.c shell-ps.c \ shell_dsc = shell-dsc.c ifeq ($(CONTIKI_WITH_RIME),1) -shell_src += shell-rime.c shell-sendtest.c shell-netfile.c \ +shell_src += shell-rime.c shell-sendtest.c \ shell-rime-ping.c shell-rime-sniff.c shell-rime-netcmd.c \ shell-rime-debug.c shell-rime-debug-runicast.c \ shell-rime-sendcmd.c shell-download.c shell-rime-neighbors.c \ diff --git a/apps/shell/shell-netfile.c b/apps/shell/shell-netfile.c deleted file mode 100644 index 45c303974..000000000 --- a/apps/shell/shell-netfile.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * A brief description of what this file is. - * \author - * Adam Dunkels - */ - -#include "contiki.h" -#include "shell-netfile.h" -#include "net/rime/rime.h" -#include "net/rime/rudolph0.h" -#include "dev/leds.h" - -#include "cfs/cfs.h" - -#include -#include - -#define FILENAME_LEN 20 - -static struct rudolph0_conn rudolph0_conn; -static char filename[FILENAME_LEN]; -static int receiving_file; -static struct pt recvnetfilept; -/*---------------------------------------------------------------------------*/ -PROCESS(shell_netfile_process, "netfile"); -SHELL_COMMAND(netfile_command, - "netfile", - "netfile: send file to entire network", - &shell_netfile_process); -PROCESS(shell_recvnetfile_process, "recvnetfile"); -SHELL_COMMAND(recvnetfile_command, - "recvnetfile", - "recvnetfile: receive file from network and print to output", - &shell_recvnetfile_process); -/*---------------------------------------------------------------------------*/ -static int -write_chunk_pt(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - PT_BEGIN(&recvnetfilept); - - PT_WAIT_UNTIL(&recvnetfilept, receiving_file); - leds_on(LEDS_YELLOW); - leds_on(LEDS_RED); - PT_WAIT_UNTIL(&recvnetfilept, flag == RUDOLPH0_FLAG_NEWFILE); - leds_off(LEDS_RED); - - do { - if(datalen > 0) { - shell_output(&recvnetfile_command, data, datalen, "", 0); - /* printf("write_chunk wrote %d bytes at %d\n", datalen, offset);*/ - } - PT_YIELD(&recvnetfilept); - } while(flag != RUDOLPH0_FLAG_LASTCHUNK); - - shell_output(&recvnetfile_command, data, datalen, "", 0); - /* printf("write_chunk wrote %d bytes at %d\n", datalen, offset);*/ - shell_output(&recvnetfile_command, "", 0, "", 0); - leds_off(LEDS_YELLOW); - receiving_file = 0; - process_post(&shell_recvnetfile_process, PROCESS_EVENT_CONTINUE, NULL); - - PT_END(&recvnetfilept); -} -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - write_chunk_pt(c, offset, flag, data, datalen); -} - -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int ret; - int fd; - - fd = cfs_open(filename, CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - cfs_close(fd); - return ret; -} -CC_CONST_FUNCTION static struct rudolph0_callbacks rudolph0_callbacks = - {/*(void (*)(struct rudolph0_conn *, int, int, uint8_t *, int))*/ - write_chunk, - read_chunk}; -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(shell_netfile_process, ev, data) -{ - int fd; - - PROCESS_BEGIN(); - - if(data != NULL) { - rudolph0_send(&rudolph0_conn, CLOCK_SECOND); - - strncpy(filename, data, FILENAME_LEN); - fd = cfs_open(filename, CFS_READ); - if(fd < 0) { - shell_output_str(&netfile_command, "netfile: could not open file ", filename); - } else { - cfs_close(fd); - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(shell_recvnetfile_process, ev, data) -{ - PROCESS_BEGIN(); - - PT_INIT(&recvnetfilept); - receiving_file = 1; - while(1) { - struct shell_input *input; - - PROCESS_WAIT_EVENT(); - - if(ev == shell_event_input) { - input = data; - if(input->len1 + input->len2 == 0) { - receiving_file = 0; - PROCESS_EXIT(); - } - } else if(receiving_file == 0) { - PROCESS_EXIT(); - } - } - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ -void -shell_netfile_init(void) -{ - receiving_file = 0; - shell_register_command(&netfile_command); - shell_register_command(&recvnetfile_command); - - rudolph0_open(&rudolph0_conn, SHELL_RIME_CHANNEL_NETFILE, - &rudolph0_callbacks); -} -/*---------------------------------------------------------------------------*/ diff --git a/apps/shell/shell.h b/apps/shell/shell.h index ea383deb8..f6e4e1b8d 100644 --- a/apps/shell/shell.h +++ b/apps/shell/shell.h @@ -382,7 +382,6 @@ struct shell_input { #include "shell-httpd.h" #include "shell-irc.h" #include "shell-memdebug.h" -#include "shell-netfile.h" #include "shell-netperf.h" #include "shell-netstat.h" #include "shell-ping.h" diff --git a/core/contiki-net.h b/core/contiki-net.h index d38d89344..087be23cb 100644 --- a/core/contiki-net.h +++ b/core/contiki-net.h @@ -44,6 +44,7 @@ #include "net/ip/uiplib.h" #include "net/ip/uip-udp-packet.h" #include "net/ip/simple-udp.h" +#include "net/ip/uip-nameserver.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-icmp6.h" diff --git a/core/lib/petsciiconv.c b/core/lib/petsciiconv.c index 873c7c2c7..a6eda5979 100644 --- a/core/lib/petsciiconv.c +++ b/core/lib/petsciiconv.c @@ -72,14 +72,13 @@ static unsigned char ascii2petscii[128] = { 0x58,0x59,0x5a,0xdb,0xdd,0xdd,0x5e,0xdf, }; -static unsigned int i; -static unsigned char *ptr; - /*-----------------------------------------------------------------------------------*/ void petsciiconv_toascii(char *buf, unsigned int len) { - static char c; + unsigned int i; + char *ptr; + char c; ptr = buf; for(i = len; i > 0; --i) { @@ -108,6 +107,9 @@ petsciiconv_toascii(char *buf, unsigned int len) void petsciiconv_topetscii(char *buf, unsigned int len) { + unsigned int i; + char *ptr; + ptr = buf; for(i = len; i > 0; --i) { *ptr = ascii2petscii[*ptr & 0x7f]; diff --git a/core/net/http-socket/http-socket.c b/core/net/http-socket/http-socket.c new file mode 100644 index 000000000..758c1473e --- /dev/null +++ b/core/net/http-socket/http-socket.c @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "contiki-net.h" +#include "ip64-addr.h" +#include "http-socket.h" + +#include +#include + +#define MAX_PATHLEN 80 +#define MAX_HOSTLEN 40 +PROCESS(http_socket_process, "HTTP socket process"); +LIST(socketlist); + +static void removesocket(struct http_socket *s); +/*---------------------------------------------------------------------------*/ +static void +call_callback(struct http_socket *s, http_socket_event_t e, + const uint8_t *data, uint16_t datalen) +{ + if(s->callback != NULL) { + s->callback(s, s->callbackptr, e, + data, datalen); + } +} +/*---------------------------------------------------------------------------*/ +static void +parse_header_init(struct http_socket *s) +{ + PT_INIT(&s->headerpt); +} +/*---------------------------------------------------------------------------*/ +static int +parse_header_byte(struct http_socket *s, char c) +{ + PT_BEGIN(&s->headerpt); + + memset(&s->header, -1, sizeof(s->header)); + + /* Skip the HTTP response */ + while(c != ' ') { + PT_YIELD(&s->headerpt); + } + + /* Skip the space */ + PT_YIELD(&s->headerpt); + /* Read three characters of HTTP status and convert to BCD */ + s->header.status_code = 0; + for(s->header_chars = 0; s->header_chars < 3; s->header_chars++) { + s->header.status_code = s->header.status_code << 4 | (c - '0'); + PT_YIELD(&s->headerpt); + } + + if(s->header.status_code == 0x200 || s->header.status_code == 0x206) { + /* Read headers until data */ + + while(1) { + /* Skip characters until end of line */ + do { + while(c != '\r') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header_chars++; + PT_YIELD(&s->headerpt); + } while(c != '\n'); + s->header_chars--; + PT_YIELD(&s->headerpt); + + if(s->header_chars == 0) { + /* This was an empty line, i.e. the end of headers */ + break; + } + + /* Start of line */ + s->header_chars = 0; + + /* Read header field */ + while(c != ' ' && c != '\t' && c != ':' && c != '\r' && + s->header_chars < sizeof(s->header_field) - 1) { + s->header_field[s->header_chars++] = c; + PT_YIELD(&s->headerpt); + } + s->header_field[s->header_chars] = '\0'; + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == ':') { + /* Skip the colon */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(!strcmp(s->header_field, "Content-Length")) { + s->header.content_length = 0; + while(isdigit((int)c)) { + s->header.content_length = s->header.content_length * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + } else if(!strcmp(s->header_field, "Content-Range")) { + /* Skip the bytes-unit token */ + while(c != ' ' && c != '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header.content_range.first_byte_pos = 0; + while(isdigit((int)c)) { + s->header.content_range.first_byte_pos = + s->header.content_range.first_byte_pos * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == '-') { + /* Skip the dash */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header.content_range.last_byte_pos = 0; + while(isdigit((int)c)) { + s->header.content_range.last_byte_pos = + s->header.content_range.last_byte_pos * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == '/') { + /* Skip the slash */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c != '*') { + s->header.content_range.instance_length = 0; + while(isdigit((int)c)) { + s->header.content_range.instance_length = + s->header.content_range.instance_length * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + } + } + } + } + } + } + + /* All headers read, now read data */ + call_callback(s, HTTP_SOCKET_HEADER, (void *)&s->header, sizeof(s->header)); + + /* Should exit the pt here to indicate that all headers have been + read */ + PT_EXIT(&s->headerpt); + } else { + if(s->header.status_code == 0x404) { + printf("File not found\n"); + } else if(s->header.status_code == 0x301 || s->header.status_code == 0x302) { + printf("File moved (not handled)\n"); + } + + call_callback(s, HTTP_SOCKET_ERR, (void *)&s->header, sizeof(s->header)); + tcp_socket_close(&s->s); + removesocket(s); + PT_EXIT(&s->headerpt); + } + + + PT_END(&s->headerpt); +} +/*---------------------------------------------------------------------------*/ +static int +input_pt(struct http_socket *s, + const uint8_t *inputptr, int inputdatalen) +{ + int i; + PT_BEGIN(&s->pt); + + /* Parse the header */ + s->header_received = 0; + do { + for(i = 0; i < inputdatalen; i++) { + if(!PT_SCHEDULE(parse_header_byte(s, inputptr[i]))) { + s->header_received = 1; + break; + } + } + inputdatalen -= i; + inputptr += i; + + if(s->header_received == 0) { + /* If we have not yet received the full header, we wait for the + next packet to arrive. */ + PT_YIELD(&s->pt); + } + } while(s->header_received == 0); + + s->bodylen = 0; + do { + /* Receive the data */ + call_callback(s, HTTP_SOCKET_DATA, inputptr, inputdatalen); + + /* Close the connection if the expected content length has been received */ + if(s->header.content_length >= 0 && s->bodylen < s->header.content_length) { + s->bodylen += inputdatalen; + if(s->bodylen >= s->header.content_length) { + tcp_socket_close(&s->s); + } + } + + PT_YIELD(&s->pt); + } while(inputdatalen > 0); + + PT_END(&s->pt); +} +/*---------------------------------------------------------------------------*/ +static void +start_timeout_timer(struct http_socket *s) +{ + PROCESS_CONTEXT_BEGIN(&http_socket_process); + etimer_set(&s->timeout_timer, HTTP_SOCKET_TIMEOUT); + PROCESS_CONTEXT_END(&http_socket_process); + s->timeout_timer_started = 1; +} +/*---------------------------------------------------------------------------*/ +static int +input(struct tcp_socket *tcps, void *ptr, + const uint8_t *inputptr, int inputdatalen) +{ + struct http_socket *s = ptr; + + input_pt(s, inputptr, inputdatalen); + start_timeout_timer(s); + + return 0; /* all data consumed */ +} +/*---------------------------------------------------------------------------*/ +static int +parse_url(const char *url, char *host, uint16_t *portptr, char *path) +{ + const char *urlptr; + int i; + const char *file; + uint16_t port; + + if(url == NULL) { + printf("null url\n"); + return 0; + } + + /* Don't even try to go further if the URL is empty. */ + if(strlen(url) == 0) { + printf("empty url\n"); + return 0; + } + + /* See if the URL starts with http:// and remove it. Otherwise, we + assume it is an implicit http://. */ + if(strncmp(url, "http://", strlen("http://")) == 0) { + urlptr = url + strlen("http://"); + } else { + urlptr = url; + } + + /* Find host part of the URL. */ + if(*urlptr == '[') { + /* Handle IPv6 addresses - scan for matching ']' */ + urlptr++; + for(i = 0; i < MAX_HOSTLEN; ++i) { + if(*urlptr == ']') { + if(host != NULL) { + host[i] = 0; + } + break; + } + if(host != NULL) { + host[i] = *urlptr; + } + ++urlptr; + } + } else { + for(i = 0; i < MAX_HOSTLEN; ++i) { + if(*urlptr == 0 || + *urlptr == '/' || + *urlptr == ' ' || + *urlptr == ':') { + if(host != NULL) { + host[i] = 0; + } + break; + } + if(host != NULL) { + host[i] = *urlptr; + } + ++urlptr; + } + } + + /* Find the port. Default is 80. */ + port = 80; + if(*urlptr == ':') { + port = 0; + do { + ++urlptr; + if(*urlptr >= '0' && *urlptr <= '9') { + port = (10 * port) + (*urlptr - '0'); + } + } while(*urlptr >= '0' && + *urlptr <= '9'); + } + if(portptr != NULL) { + *portptr = port; + } + /* Find file part of the URL. */ + while(*urlptr != '/' && *urlptr != 0) { + ++urlptr; + } + if(*urlptr == '/') { + file = urlptr; + } else { + file = "/"; + } + if(path != NULL) { + strncpy(path, file, MAX_PATHLEN); + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +removesocket(struct http_socket *s) +{ + etimer_stop(&s->timeout_timer); + s->timeout_timer_started = 0; + list_remove(socketlist, s); +} +/*---------------------------------------------------------------------------*/ +static void +event(struct tcp_socket *tcps, void *ptr, + tcp_socket_event_t e) +{ + struct http_socket *s = ptr; + char host[MAX_HOSTLEN]; + char path[MAX_PATHLEN]; + uint16_t port; + char str[42]; + int len; + + if(e == TCP_SOCKET_CONNECTED) { + printf("Connected\n"); + if(parse_url(s->url, host, &port, path)) { + tcp_socket_send_str(tcps, s->postdata != NULL ? "POST " : "GET "); + if(s->proxy_port != 0) { + /* If we are configured to route through a proxy, we should + provide the full URL as the path. */ + tcp_socket_send_str(tcps, s->url); + } else { + tcp_socket_send_str(tcps, path); + } + tcp_socket_send_str(tcps, " HTTP/1.1\r\n"); + tcp_socket_send_str(tcps, "Connection: close\r\n"); + tcp_socket_send_str(tcps, "Host: "); + tcp_socket_send_str(tcps, host); + tcp_socket_send_str(tcps, "\r\n"); + if(s->postdata != NULL) { + if(s->content_type) { + tcp_socket_send_str(tcps, "Content-Type: "); + tcp_socket_send_str(tcps, s->content_type); + tcp_socket_send_str(tcps, "\r\n"); + } + tcp_socket_send_str(tcps, "Content-Length: "); + sprintf(str, "%u", s->postdatalen); + tcp_socket_send_str(tcps, str); + tcp_socket_send_str(tcps, "\r\n"); + } else if(s->length || s->pos > 0) { + tcp_socket_send_str(tcps, "Range: bytes="); + if(s->length) { + if(s->pos >= 0) { + sprintf(str, "%llu-%llu", s->pos, s->pos + s->length - 1); + } else { + sprintf(str, "-%llu", s->length); + } + } else { + sprintf(str, "%llu-", s->pos); + } + tcp_socket_send_str(tcps, str); + tcp_socket_send_str(tcps, "\r\n"); + } + tcp_socket_send_str(tcps, "\r\n"); + if(s->postdata != NULL && s->postdatalen) { + len = tcp_socket_send(tcps, s->postdata, s->postdatalen); + s->postdata += len; + s->postdatalen -= len; + } + } + parse_header_init(s); + } else if(e == TCP_SOCKET_CLOSED) { + call_callback(s, HTTP_SOCKET_CLOSED, NULL, 0); + removesocket(s); + printf("Closed\n"); + } else if(e == TCP_SOCKET_TIMEDOUT) { + call_callback(s, HTTP_SOCKET_TIMEDOUT, NULL, 0); + removesocket(s); + printf("Timedout\n"); + } else if(e == TCP_SOCKET_ABORTED) { + call_callback(s, HTTP_SOCKET_ABORTED, NULL, 0); + removesocket(s); + printf("Aborted\n"); + } else if(e == TCP_SOCKET_DATA_SENT) { + if(s->postdata != NULL && s->postdatalen) { + len = tcp_socket_send(tcps, s->postdata, s->postdatalen); + s->postdata += len; + s->postdatalen -= len; + } else { + start_timeout_timer(s); + } + } +} +/*---------------------------------------------------------------------------*/ +static int +start_request(struct http_socket *s) +{ + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + uip_ip6addr_t *addr; + char host[MAX_HOSTLEN]; + char path[MAX_PATHLEN]; + uint16_t port; + int ret; + + if(parse_url(s->url, host, &port, path)) { + + printf("url %s host %s port %d path %s\n", + s->url, host, port, path); + + /* Check if we are to route the request through a proxy. */ + if(s->proxy_port != 0) { + /* The proxy address should be an IPv6 address. */ + uip_ip6addr_copy(&ip6addr, &s->proxy_addr); + port = s->proxy_port; + } else if(uiplib_ip6addrconv(host, &ip6addr) == 0) { + /* First check if the host is an IP address. */ + if(uiplib_ip4addrconv(host, &ip4addr) != 0) { + ip64_addr_4to6(&ip4addr, &ip6addr); + } else { + /* Try to lookup the hostname. If it fails, we initiate a hostname + lookup. */ + ret = resolv_lookup(host, &addr); + if(ret == RESOLV_STATUS_UNCACHED || + ret == RESOLV_STATUS_EXPIRED) { + resolv_query(host); + puts("Resolving host..."); + return HTTP_SOCKET_OK; + } + if(addr != NULL) { + s->did_tcp_connect = 1; + tcp_socket_connect(&s->s, addr, port); + return HTTP_SOCKET_OK; + } else { + return HTTP_SOCKET_ERR; + } + } + } + tcp_socket_connect(&s->s, &ip6addr, port); + return HTTP_SOCKET_OK; + } else { + return HTTP_SOCKET_ERR; + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(http_socket_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + + PROCESS_WAIT_EVENT(); + + if(ev == resolv_event_found && data != NULL) { + struct http_socket *s; + const char *name = data; + /* Either found a hostname, or not. We need to go through the + list of http sockets and figure out to which connection this + reply corresponds, then either restart the HTTP get, or kill + it (if no hostname was found). */ + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + char host[MAX_HOSTLEN]; + if(s->did_tcp_connect) { + /* We already connected, ignored */ + } else if(parse_url(s->url, host, NULL, NULL) && + strcmp(name, host) == 0) { + if(resolv_lookup(name, NULL) == RESOLV_STATUS_CACHED) { + /* Hostname found, restart get. */ + start_request(s); + } else { + /* Hostname not found, kill connection. */ + call_callback(s, HTTP_SOCKET_HOSTNAME_NOT_FOUND, NULL, 0); + removesocket(s); + } + } + } + } else if(ev == PROCESS_EVENT_TIMER) { + struct http_socket *s; + struct etimer *timeout_timer = data; + /* + * A socket time-out has occurred. We need to go through the list of HTTP + * sockets and figure out to which socket this timer event corresponds, + * then close this socket. + */ + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + if(timeout_timer == &s->timeout_timer && s->timeout_timer_started) { + tcp_socket_close(&s->s); + break; + } + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + static uint8_t inited = 0; + if(inited == 0) { + process_start(&http_socket_process, NULL); + list_init(socketlist); + inited = 1; + } +} +/*---------------------------------------------------------------------------*/ +void +http_socket_init(struct http_socket *s) +{ + init(); + uip_create_unspecified(&s->proxy_addr); + s->proxy_port = 0; +} +/*---------------------------------------------------------------------------*/ +static void +initialize_socket(struct http_socket *s) +{ + s->pos = 0; + s->length = 0; + s->postdata = NULL; + s->postdatalen = 0; + s->timeout_timer_started = 0; + PT_INIT(&s->pt); + tcp_socket_register(&s->s, s, + s->inputbuf, sizeof(s->inputbuf), + s->outputbuf, sizeof(s->outputbuf), + input, event); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_get(struct http_socket *s, + const char *url, + int64_t pos, + uint64_t length, + http_socket_callback_t callback, + void *callbackptr) +{ + initialize_socket(s); + strncpy(s->url, url, sizeof(s->url)); + s->pos = pos; + s->length = length; + s->callback = callback; + s->callbackptr = callbackptr; + + s->did_tcp_connect = 0; + + list_add(socketlist, s); + + return start_request(s); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_post(struct http_socket *s, + const char *url, + const void *postdata, + uint16_t postdatalen, + const char *content_type, + http_socket_callback_t callback, + void *callbackptr) +{ + initialize_socket(s); + strncpy(s->url, url, sizeof(s->url)); + s->postdata = postdata; + s->postdatalen = postdatalen; + s->content_type = content_type; + + s->callback = callback; + s->callbackptr = callbackptr; + + s->did_tcp_connect = 0; + + list_add(socketlist, s); + + return start_request(s); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_close(struct http_socket *socket) +{ + struct http_socket *s; + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + if(s == socket) { + tcp_socket_close(&s->s); + removesocket(s); + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +http_socket_set_proxy(struct http_socket *s, + const uip_ipaddr_t *addr, uint16_t port) +{ + uip_ipaddr_copy(&s->proxy_addr, addr); + s->proxy_port = port; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/http-socket/http-socket.h b/core/net/http-socket/http-socket.h new file mode 100644 index 000000000..5b683e10b --- /dev/null +++ b/core/net/http-socket/http-socket.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef HTTP_SOCKET_H +#define HTTP_SOCKET_H + +#include "tcp-socket.h" + +struct http_socket; + +typedef enum { + HTTP_SOCKET_ERR, + HTTP_SOCKET_OK, + HTTP_SOCKET_HEADER, + HTTP_SOCKET_DATA, + HTTP_SOCKET_CLOSED, + HTTP_SOCKET_TIMEDOUT, + HTTP_SOCKET_ABORTED, + HTTP_SOCKET_HOSTNAME_NOT_FOUND, +} http_socket_event_t; + +struct http_socket_header { + uint16_t status_code; + int64_t content_length; + struct { + int64_t first_byte_pos; + int64_t last_byte_pos; + int64_t instance_length; + } content_range; +}; + +typedef void (* http_socket_callback_t)(struct http_socket *s, + void *ptr, + http_socket_event_t ev, + const uint8_t *data, + uint16_t datalen); + +#define MAX(n, m) (((n) < (m)) ? (m) : (n)) + +#define HTTP_SOCKET_INPUTBUFSIZE UIP_TCP_MSS +#define HTTP_SOCKET_OUTPUTBUFSIZE MAX(UIP_TCP_MSS, 128) + +#define HTTP_SOCKET_URLLEN 128 + +#define HTTP_SOCKET_TIMEOUT ((2 * 60 + 30) * CLOCK_SECOND) + +struct http_socket { + struct http_socket *next; + struct tcp_socket s; + uip_ipaddr_t proxy_addr; + uint16_t proxy_port; + int64_t pos; + uint64_t length; + const uint8_t *postdata; + uint16_t postdatalen; + http_socket_callback_t callback; + void *callbackptr; + int did_tcp_connect; + char url[HTTP_SOCKET_URLLEN]; + uint8_t inputbuf[HTTP_SOCKET_INPUTBUFSIZE]; + uint8_t outputbuf[HTTP_SOCKET_OUTPUTBUFSIZE]; + + struct etimer timeout_timer; + uint8_t timeout_timer_started; + struct pt pt, headerpt; + int header_chars; + char header_field[15]; + struct http_socket_header header; + uint8_t header_received; + uint64_t bodylen; + const char *content_type; +}; + +void http_socket_init(struct http_socket *s); + +int http_socket_get(struct http_socket *s, const char *url, + int64_t pos, uint64_t length, + http_socket_callback_t callback, + void *callbackptr); + +int http_socket_post(struct http_socket *s, const char *url, + const void *postdata, + uint16_t postdatalen, + const char *content_type, + http_socket_callback_t callback, + void *callbackptr); + +int http_socket_close(struct http_socket *socket); + +void http_socket_set_proxy(struct http_socket *s, + const uip_ipaddr_t *addr, uint16_t port); + + +#endif /* HTTP_SOCKET_H */ diff --git a/core/net/ip64-addr/ip64-addr.c b/core/net/ip/ip64-addr.c similarity index 100% rename from core/net/ip64-addr/ip64-addr.c rename to core/net/ip/ip64-addr.c diff --git a/core/net/ip64-addr/ip64-addr.h b/core/net/ip/ip64-addr.h similarity index 100% rename from core/net/ip64-addr/ip64-addr.h rename to core/net/ip/ip64-addr.h diff --git a/core/net/ip/resolv.c b/core/net/ip/resolv.c index 5df53ecac..58bda004d 100644 --- a/core/net/ip/resolv.c +++ b/core/net/ip/resolv.c @@ -65,6 +65,7 @@ #include "net/ip/tcpip.h" #include "net/ip/resolv.h" #include "net/ip/uip-udp-packet.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" #ifndef DEBUG @@ -227,17 +228,6 @@ struct dns_hdr { uint16_t numextrarr; }; -/** These default values for the DNS server are Google's public DNS: - * - */ -static uip_ipaddr_t resolv_default_dns_server = -#if NETSTACK_CONF_WITH_IPV6 - { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } }; -#else /* NETSTACK_CONF_WITH_IPV6 */ - { { 8, 8, 8, 8 } }; -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /** \internal The DNS answer message structure. */ struct dns_answer { /* DNS answer record starts with either a domain name or a pointer @@ -269,6 +259,7 @@ struct namemap { #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ uip_ipaddr_t ipaddr; uint8_t err; + uint8_t server; #if RESOLV_CONF_SUPPORTS_MDNS int is_mdns:1, is_probe:1; #endif @@ -637,6 +628,21 @@ mdns_prep_host_announce_packet(void) } #endif /* RESOLV_CONF_SUPPORTS_MDNS */ /*---------------------------------------------------------------------------*/ +static char +try_next_server(struct namemap *namemapptr) +{ +#if VERBOSE_DEBUG + printf("server %d\n", namemapptr->server); +#endif + namemapptr->server++; + if(uip_nameserver_get(namemapptr->server) != NULL) { + namemapptr->retries = 0; + return 1; + } + namemapptr->server = 0; + return 0; +} +/*---------------------------------------------------------------------------*/ /** \internal * Runs through the list of names to see if there are any that have * not yet been queried and, if so, sends out a query. @@ -666,16 +672,20 @@ check_entries(void) if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES) #endif /* RESOLV_CONF_SUPPORTS_MDNS */ { - /* STATE_ERROR basically means "not found". */ - namemapptr->state = STATE_ERROR; + /* Try the next server (if possible) before failing. Otherwise + simply mark the entry as failed. */ + if(try_next_server(namemapptr) == 0) { + /* STATE_ERROR basically means "not found". */ + namemapptr->state = STATE_ERROR; #if RESOLV_SUPPORTS_RECORD_EXPIRATION - /* Keep the "not found" error valid for 30 seconds */ - namemapptr->expiration = clock_seconds() + 30; + /* Keep the "not found" error valid for 30 seconds */ + namemapptr->expiration = clock_seconds() + 30; #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ - resolv_found(namemapptr->name, NULL); - continue; + resolv_found(namemapptr->name, NULL); + continue; + } } namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3; @@ -747,7 +757,9 @@ check_entries(void) } else { uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + (const uip_ipaddr_t *) + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); @@ -755,7 +767,8 @@ check_entries(void) #else /* RESOLV_CONF_SUPPORTS_MDNS */ uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); #endif /* RESOLV_CONF_SUPPORTS_MDNS */ @@ -774,7 +787,7 @@ newdata(void) static int8_t i; - register struct namemap *namemapptr; + register struct namemap *namemapptr = NULL; struct dns_answer *ans; @@ -1041,11 +1054,28 @@ newdata(void) uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr); resolv_found(namemapptr->name, &namemapptr->ipaddr); + break; skip_to_next_answer: queryptr = (unsigned char *)skip_name(queryptr) + 10 + uip_htons(ans->len); --nanswers; } + + /* Got to this point there's no answer, try next nameserver if available + since this one doesn't know the answer */ +#if RESOLV_CONF_SUPPORTS_MDNS + if(nanswers == 0 && UIP_UDP_BUF->srcport != UIP_HTONS(MDNS_PORT) + && hdr->id != 0) +#else + if(nanswers == 0) +#endif + { + if(try_next_server(namemapptr)) { + namemapptr->state = STATE_ASKING; + process_post(&resolv_process, PROCESS_EVENT_TIMER, NULL); + } + } + } /*---------------------------------------------------------------------------*/ #if RESOLV_CONF_SUPPORTS_MDNS @@ -1405,31 +1435,6 @@ resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr) return ret; } /*---------------------------------------------------------------------------*/ -/** - * Obtain the currently configured DNS server. - * - * \return A pointer to a 4-byte representation of the IP address of - * the currently configured DNS server or NULL if no DNS server has - * been configured. - */ -uip_ipaddr_t * -resolv_getserver(void) -{ - return &resolv_default_dns_server; -} -/*---------------------------------------------------------------------------*/ -/** - * Configure a DNS server. - * - * \param dnsserver A pointer to a 4-byte representation of the IP - * address of the DNS server to be configured. - */ -void -resolv_conf(const uip_ipaddr_t * dnsserver) -{ - uip_ipaddr_copy(&resolv_default_dns_server, dnsserver); -} -/*---------------------------------------------------------------------------*/ /** \internal * Callback function which is called when a hostname is found. * diff --git a/core/net/ip/resolv.h b/core/net/ip/resolv.h index cf1fef7e0..ed24d5bce 100644 --- a/core/net/ip/resolv.h +++ b/core/net/ip/resolv.h @@ -57,11 +57,6 @@ */ CCIF extern process_event_t resolv_event_found; -/* Functions. */ -CCIF void resolv_conf(const uip_ipaddr_t * dnsserver); - -CCIF uip_ipaddr_t *resolv_getserver(void); - enum { /** Hostname is fresh and usable. This response is cached and will eventually * expire to RESOLV_STATUS_EXPIRED.*/ @@ -95,6 +90,7 @@ enum { typedef uint8_t resolv_status_t; +/* Functions. */ CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); CCIF void resolv_query(const char *name); diff --git a/core/net/ip/slipdev.c b/core/net/ip/slipdev.c index caab454ac..8bc688557 100644 --- a/core/net/ip/slipdev.c +++ b/core/net/ip/slipdev.c @@ -103,7 +103,7 @@ slipdev_send(void) ptr = &uip_buf[UIP_LLH_LEN]; for(i = 0; i < uip_len; ++i) { if(i == UIP_TCPIP_HLEN) { - ptr = (char *)uip_appdata; + ptr = (uint8_t *)uip_appdata; } c = *ptr++; switch(c) { diff --git a/core/net/ip/tcp-socket.c b/core/net/ip/tcp-socket.c index 44010ce1c..285be2768 100644 --- a/core/net/ip/tcp-socket.c +++ b/core/net/ip/tcp-socket.c @@ -41,6 +41,8 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) +static void relisten(struct tcp_socket *s); + LIST(socketlist); /*---------------------------------------------------------------------------*/ PROCESS(tcp_socket_process, "TCP socket process"); @@ -58,8 +60,8 @@ senddata(struct tcp_socket *s) { int len = MIN(s->output_data_max_seg, uip_mss()); - if(s->output_data_len > 0) { - len = MIN(s->output_data_len, len); + if(s->output_senddata_len > 0) { + len = MIN(s->output_senddata_len, len); s->output_data_send_nxt = len; uip_send(s->output_data_ptr, len); } @@ -68,21 +70,27 @@ senddata(struct tcp_socket *s) static void acked(struct tcp_socket *s) { - if(s->output_data_len > 0) { + if(s->output_senddata_len > 0) { /* Copy the data in the outputbuf down and update outputbufptr and outputbuf_lastsent */ if(s->output_data_send_nxt > 0) { memcpy(&s->output_data_ptr[0], - &s->output_data_ptr[s->output_data_send_nxt], - s->output_data_maxlen - s->output_data_send_nxt); + &s->output_data_ptr[s->output_data_send_nxt], + s->output_data_maxlen - s->output_data_send_nxt); } if(s->output_data_len < s->output_data_send_nxt) { printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n", - s->output_data_len, - s->output_data_send_nxt); + s->output_data_len, + s->output_data_send_nxt); + tcp_markconn(uip_conn, NULL); + uip_abort(); + call_event(s, TCP_SOCKET_ABORTED); + relisten(s); + return; } s->output_data_len -= s->output_data_send_nxt; + s->output_senddata_len = s->output_data_len; s->output_data_send_nxt = 0; call_event(s, TCP_SOCKET_DATA_SENT); @@ -134,6 +142,11 @@ appcall(void *state) { struct tcp_socket *s = state; + if(s != NULL && s->c != NULL && s->c != uip_conn) { + /* Safe-guard: this should not happen, as the incoming event relates to + * a previous connection */ + return; + } if(uip_connected()) { /* Check if this connection originated in a local listen socket. We do this by checking the state pointer - if NULL, @@ -176,8 +189,10 @@ appcall(void *state) } if(uip_aborted()) { + tcp_markconn(uip_conn, NULL); call_event(s, TCP_SOCKET_ABORTED); relisten(s); + } if(s == NULL) { @@ -203,13 +218,16 @@ appcall(void *state) if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) { s->flags &= ~TCP_SOCKET_FLAGS_CLOSING; uip_close(); + s->c = NULL; tcp_markconn(uip_conn, NULL); - call_event(s, TCP_SOCKET_CLOSED); + s->c = NULL; + /*call_event(s, TCP_SOCKET_CLOSED);*/ relisten(s); } if(uip_closed()) { tcp_markconn(uip_conn, NULL); + s->c = NULL; call_event(s, TCP_SOCKET_CLOSED); relisten(s); } @@ -255,6 +273,7 @@ tcp_socket_register(struct tcp_socket *s, void *ptr, s->ptr = ptr; s->input_data_ptr = input_databuf; s->input_data_maxlen = input_databuf_len; + s->output_data_len = 0; s->output_data_ptr = output_databuf; s->output_data_maxlen = output_databuf_len; s->input_callback = input_callback; @@ -268,12 +287,15 @@ tcp_socket_register(struct tcp_socket *s, void *ptr, /*---------------------------------------------------------------------------*/ int tcp_socket_connect(struct tcp_socket *s, - uip_ipaddr_t *ipaddr, - uint16_t port) + const uip_ipaddr_t *ipaddr, + uint16_t port) { if(s == NULL) { return -1; } + if(s->c != NULL) { + tcp_markconn(s->c, NULL); + } PROCESS_CONTEXT_BEGIN(&tcp_socket_process); s->c = tcp_connect(ipaddr, uip_htons(port), s); PROCESS_CONTEXT_END(); @@ -317,7 +339,7 @@ tcp_socket_unlisten(struct tcp_socket *s) /*---------------------------------------------------------------------------*/ int tcp_socket_send(struct tcp_socket *s, - const uint8_t *data, int datalen) + const uint8_t *data, int datalen) { int len; @@ -329,6 +351,11 @@ tcp_socket_send(struct tcp_socket *s, memcpy(&s->output_data_ptr[s->output_data_len], data, len); s->output_data_len += len; + + if(s->output_senddata_len == 0) { + s->output_senddata_len = s->output_data_len; + } + return len; } /*---------------------------------------------------------------------------*/ @@ -365,3 +392,9 @@ tcp_socket_unregister(struct tcp_socket *s) return 1; } /*---------------------------------------------------------------------------*/ +int +tcp_socket_max_sendlen(struct tcp_socket *s) +{ + return s->output_data_maxlen - s->output_data_len; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip/tcp-socket.h b/core/net/ip/tcp-socket.h index 208bc8288..34cb0d6b7 100644 --- a/core/net/ip/tcp-socket.h +++ b/core/net/ip/tcp-socket.h @@ -32,6 +32,8 @@ #ifndef TCP_SOCKET_H #define TCP_SOCKET_H +#include "uip.h" + struct tcp_socket; typedef enum { @@ -95,6 +97,7 @@ struct tcp_socket { uint16_t output_data_maxlen; uint16_t output_data_len; uint16_t output_data_send_nxt; + uint16_t output_senddata_len; uint16_t output_data_max_seg; uint8_t flags; @@ -170,7 +173,7 @@ int tcp_socket_register(struct tcp_socket *s, void *ptr, * */ int tcp_socket_connect(struct tcp_socket *s, - uip_ipaddr_t *ipaddr, + const uip_ipaddr_t *ipaddr, uint16_t port); /** @@ -266,4 +269,19 @@ int tcp_socket_close(struct tcp_socket *s); * */ int tcp_socket_unregister(struct tcp_socket *s); + +/** + * \brief The maximum amount of data that could currently be sent + * \param s A pointer to a TCP socket + * \return The number of bytes available in the output buffer + * + * This function queries the TCP socket and returns the + * number of bytes available in the output buffer. This + * function is used before calling tcp_socket_send() to + * ensure that one application level message can be held + * in the output buffer. + * + */ +int tcp_socket_max_sendlen(struct tcp_socket *s); + #endif /* TCP_SOCKET_H */ diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index 6f2744785..1c75d1bc9 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -228,7 +228,7 @@ packet_input(void) #if UIP_TCP #if UIP_ACTIVE_OPEN struct uip_conn * -tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) +tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) { struct uip_conn *c; diff --git a/core/net/ip/tcpip.h b/core/net/ip/tcpip.h index 3fd64bce8..8fb2ff526 100644 --- a/core/net/ip/tcpip.h +++ b/core/net/ip/tcpip.h @@ -165,7 +165,7 @@ CCIF void tcp_unlisten(uint16_t port); * memory could not be allocated for the connection. * */ -CCIF struct uip_conn *tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, +CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate); /** diff --git a/core/net/ip/uip-nameserver.c b/core/net/ip/uip-nameserver.c new file mode 100644 index 000000000..367fe421d --- /dev/null +++ b/core/net/ip/uip-nameserver.c @@ -0,0 +1,236 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-net.h" + +#include "lib/list.h" +#include "lib/memb.h" + +#include +/** \brief Nameserver record */ +typedef struct uip_nameserver_record { + struct uip_nameserver_record *next; + uip_ipaddr_t ip; + uint32_t added; + uint32_t lifetime; +} uip_nameserver_record; + +#if UIP_NAMESERVER_POOL_SIZE > 1 +/** \brief Initialization flag */ +static uint8_t initialized = 0; +#endif + +/** \name List and memory block + * @{ + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +LIST(dns); +MEMB(dnsmemb, uip_nameserver_record, UIP_NAMESERVER_POOL_SIZE); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +static uip_ipaddr_t serveraddr; +static uint32_t serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/** @} */ + +/** \brief Expiration time in seconds */ +#define DNS_EXPIRATION(r) \ + (((UIP_NAMESERVER_INFINITE_LIFETIME - r->added) <= r->lifetime) ? \ + UIP_NAMESERVER_INFINITE_LIFETIME : r->added + r->lifetime) +/*----------------------------------------------------------------------------*/ +/** + * Initialize the module variables + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +static CC_INLINE void +init(void) +{ + list_init(dns); + memb_init(&dnsmemb); + initialized = 1; +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +void +uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e; + + if(initialized == 0) { + init(); + } + + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(uip_ipaddr_cmp(&e->ip, nameserver)) { + break; + /* RFC6106: In case there's no more space, the new servers should replace + * the the eldest ones */ + } + } + + if(e == NULL) { + if((e = memb_alloc(&dnsmemb)) != NULL) { + list_add(dns, e); + } else { + uip_nameserver_record *p; + for(e = list_head(dns), p = list_head(dns); p != NULL; + p = list_item_next(p)) { + if(DNS_EXPIRATION(p) < DNS_EXPIRATION(e)) { + e = p; + } + } + } + } + + /* RFC6106: In case the entry is existing the expiration time must be + * updated. Otherwise, new entries are added. */ + if(e != NULL) { + if(lifetime == 0) { + memb_free(&dnsmemb, e); + list_remove(dns, e); + } else { + e->added = clock_seconds(); + e->lifetime = lifetime; + uip_ipaddr_copy(&e->ip, nameserver); + } + } +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + uip_ipaddr_copy(&serveraddr, nameserver); + serverlifetime = lifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +#if UIP_NAMESERVER_POOL_SIZE > 1 +/** + * Purge expired records + */ +static void +purge(void) +{ + register uip_nameserver_record *e = NULL; + uint32_t time = clock_seconds(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(DNS_EXPIRATION(e) < time) { + list_remove(dns, e); + memb_free(&dnsmemb, e); + e = list_head(dns); + } + } +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_nameserver_get(uint8_t num) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + uint8_t i; + uip_nameserver_record *e = NULL; + + if(initialized == 0) { + return NULL; + } + purge(); + for(i = 1, e = list_head(dns); e != NULL && i <= num; + i++, e = list_item_next(e)) { + } + + if(e != NULL) { + return &e->ip; + } + return NULL; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + if(num > 0) { + return NULL; + } + return &serveraddr; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint32_t +uip_nameserver_next_expiration(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e = NULL; + uint32_t exp = UIP_NAMESERVER_INFINITE_LIFETIME; + uint32_t t; + + if(initialized == 0 || list_length(dns) == 0) { + return 0; + } + purge(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + t = DNS_EXPIRATION(e); + if(t < exp) { + exp = t; + } + } + + return exp; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + return serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint16_t +uip_nameserver_count(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + if(initialized == 0) { + return 0; + } + return list_length(dns); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +#if NETSTACK_CONF_WITH_IPV6 + if(uip_is_addr_unspecified(&serveraddr)) { +#else /* NETSTACK_CONF_WITH_IPV6 */ + if(uip_ipaddr_cmp(&serveraddr, &uip_all_zeroes_addr)) { +#endif /* NETSTACK_CONF_WITH_IPV6 */ + return 0; + } else { + return 1; + } +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ip/uip-nameserver.h b/core/net/ip/uip-nameserver.h new file mode 100644 index 000000000..41dcf58c8 --- /dev/null +++ b/core/net/ip/uip-nameserver.h @@ -0,0 +1,101 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#ifndef UIP_NAMESERVER_H_ +#define UIP_NAMESERVER_H_ + +/** + * \name General + * @{ + */ +/** \brief Number of Nameservers to keep */ +#ifndef UIP_CONF_NAMESERVER_POOL_SIZE +#define UIP_NAMESERVER_POOL_SIZE 1 +#else /* UIP_CONF_NAMESERVER_POOL_SIZE */ +#define UIP_NAMESERVER_POOL_SIZE UIP_CONF_NAMESERVER_POOL_SIZE +#endif /* UIP_CONF_NAMESERVER_POOL_SIZE */ +/** \brief Infinite Lifetime indicator */ +#define UIP_NAMESERVER_INFINITE_LIFETIME 0xFFFFFFFF +/** @} */ + +/** + * \name Nameserver maintenance + * @{ + */ +/** + * \brief Insert or update a nameserver into/from the pool + * + * The list is kept according to the RFC6106, which indicates that new entries + * will replace old ones (with lower lifetime) and existing entries will update + * their lifetimes. + * + * \param nameserver Pointer to the nameserver ip address + * \param lifetime Life time of the given address. Minimum is 0, which is + * considered to remove an entry. Maximum is 0xFFFFFFFF which + * is considered infinite. + */ +void uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime); + +/** + * \brief Get a Nameserver ip address given in RA + * + * \param num The number of the nameserver to obtain, starting at 0 and going + * up to the pool size. + */ +uip_ipaddr_t *uip_nameserver_get(uint8_t num); + +/** + * \brief Get next expiration time + * + * The least expiration time is returned + */ +uint32_t uip_nameserver_next_expiration(void); + +/** + * \brief Get the number of recorded name servers + */ +uint16_t uip_nameserver_count(void); +/** @} */ + +#endif /* UIP_NAMESERVER_H_ */ +/** @} */ diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index 78ebfef59..cb12f52ab 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -600,7 +600,7 @@ void uip_unlisten(uint16_t port); * or NULL if no connection could be allocated. * */ -struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16_t port); +struct uip_conn *uip_connect(const uip_ipaddr_t *ripaddr, uint16_t port); @@ -1030,10 +1030,10 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); #define uip_ipaddr_copy(dest, src) (*(dest) = *(src)) #endif #ifndef uip_ip4addr_copy -#define uip_ip4addr_copy(dest, src) (*(dest) = *(src)) +#define uip_ip4addr_copy(dest, src) (*((uip_ip4addr_t *)dest) = *((uip_ip4addr_t *)src)) #endif #ifndef uip_ip6addr_copy -#define uip_ip6addr_copy(dest, src) (*(dest) = *(src)) +#define uip_ip6addr_copy(dest, src) (*((uip_ip6addr_t *)dest) = *((uip_ip6addr_t *)src)) #endif /** diff --git a/core/net/ip64-addr/README.md b/core/net/ip64-addr/README.md deleted file mode 100644 index 258fb7905..000000000 --- a/core/net/ip64-addr/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The `ip64-addr` module converts between IPv4 addresses and -IPv4-encoded IPv6 addresses. It is used in IPv6 networks that are -attached to the IPv4 world through an `ip64` router. With such a -router, IPv6 nodes in the network can reach IPv4 nodes by using their -IPv6-encoded address. diff --git a/core/net/ip64/ip64-addrmap.c b/core/net/ip64/ip64-addrmap.c index d7cfcb74f..3a36b2344 100644 --- a/core/net/ip64/ip64-addrmap.c +++ b/core/net/ip64/ip64-addrmap.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -148,6 +149,7 @@ ip64_addrmap_lookup(const uip_ip6addr_t *ip6addr, m->ip6port == ip6port && uip_ip4addr_cmp(&m->ip4addr, ip4addr) && uip_ip6addr_cmp(&m->ip6addr, ip6addr)) { + m->ip6to4++; return m; } } @@ -166,6 +168,7 @@ ip64_addrmap_lookup_port(uint16_t mapped_port, uint8_t protocol) m->protocol, protocol); if(m->mapped_port == mapped_port && m->protocol == protocol) { + m->ip4to6++; return m; } } @@ -204,6 +207,8 @@ ip64_addrmap_create(const uip_ip6addr_t *ip6addr, m->ip6port = ip6port; m->protocol = protocol; m->flags = FLAGS_NONE; + m->ip6to4 = 1; + m->ip4to6 = 0; timer_set(&m->timer, 0); /* Pick a new, unused local port. First make sure that the diff --git a/core/net/ip64/ip64-addrmap.h b/core/net/ip64/ip64-addrmap.h index a055efdd0..c4a31efcc 100644 --- a/core/net/ip64/ip64-addrmap.h +++ b/core/net/ip64/ip64-addrmap.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -40,6 +41,7 @@ struct ip64_addrmap_entry { struct timer timer; uip_ip6addr_t ip6addr; uip_ip4addr_t ip4addr; + uint32_t ip6to4, ip4to6; uint16_t mapped_port; uint16_t ip6port; uint16_t ip4port; diff --git a/core/net/ip64/ip64-conf-example.h b/core/net/ip64/ip64-conf-example.h index 33c1ff285..66102d5c8 100644 --- a/core/net/ip64/ip64-conf-example.h +++ b/core/net/ip64/ip64-conf-example.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-dns64.c b/core/net/ip64/ip64-dns64.c new file mode 100644 index 000000000..d9527629a --- /dev/null +++ b/core/net/ip64/ip64-dns64.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ip64.h" +#include "ip64-addr.h" +#include "ip64-dns64.h" + +#include + +#define DEBUG 0 + +#if DEBUG +#undef PRINTF +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + +struct dns_hdr { + uint8_t id[2]; + uint8_t flags1, flags2; +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + uint8_t numquestions[2]; + uint8_t numanswers[2]; + uint8_t numauthrr[2]; + uint8_t numextrarr[2]; +}; + +#define DNS_QUESTION_TYPE0 0 +#define DNS_QUESTION_TYPE1 1 +#define DNS_QUESTION_CLASS0 2 +#define DNS_QUESTION_CLASS1 3 +#define DNS_QUESTION_SIZE 4 + +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + * to a name already present somewhere in the packet. */ + uint8_t type[2]; + uint8_t class[2]; + uint8_t ttl[4]; + uint8_t len[2]; + union { + uint8_t ip6[16]; + uint8_t ip4[4]; + } addr; +}; + +#define DNS_TYPE_A 1 +#define DNS_TYPE_AAAA 28 + +#define DNS_CLASS_IN 1 +#define DNS_CLASS_ANY 255 + +/*---------------------------------------------------------------------------*/ +void +ip64_dns64_6to4(const uint8_t *ipv6data, int ipv6datalen, + uint8_t *ipv4data, int ipv4datalen) +{ + int i, j; + int qlen; + uint8_t *qdata; + uint8_t *q; + struct dns_hdr *hdr; + + hdr = (struct dns_hdr *)ipv4data; + PRINTF("ip64_dns64_6to4 id: %02x%02x\n", hdr->id[0], hdr->id[1]); + PRINTF("ip64_dns64_6to4 flags1: 0x%02x\n", hdr->flags1); + PRINTF("ip64_dns64_6to4 flags2: 0x%02x\n", hdr->flags2); + PRINTF("ip64_dns64_6to4 numquestions: 0x%02x\n", ((hdr->numquestions[0] << 8) + hdr->numquestions[1])); + PRINTF("ip64_dns64_6to4 numanswers: 0x%02x\n", ((hdr->numanswers[0] << 8) + hdr->numanswers[1])); + PRINTF("ip64_dns64_6to4 numauthrr: 0x%02x\n", ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1])); + PRINTF("ip64_dns64_6to4 numextrarr: 0x%02x\n", ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1])); + + /* Find the DNS question header by scanning through the question + labels. */ + qdata = ipv4data + sizeof(struct dns_hdr); + for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) { + do { + qlen = *qdata; + qdata++; + for(j = 0; j < qlen; j++) { + qdata++; + if(qdata > ipv4data + ipv4datalen) { + PRINTF("ip64_dns64_6to4: packet ended while parsing\n"); + return; + } + } + } while(qlen != 0); + q = qdata; + if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN && + q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) { + q[DNS_QUESTION_TYPE1] = DNS_TYPE_A; + } + + qdata += DNS_QUESTION_SIZE; + } +} +/*---------------------------------------------------------------------------*/ +int +ip64_dns64_4to6(const uint8_t *ipv4data, int ipv4datalen, + uint8_t *ipv6data, int ipv6datalen) +{ + uint8_t n; + int i, j; + int qlen, len; + const uint8_t *qdata, *adata; + uint8_t *qcopy, *acopy, *lenptr; + uint8_t *q; + struct dns_hdr *hdr; + + hdr = (struct dns_hdr *)ipv4data; + PRINTF("ip64_dns64_4to6 id: %02x%02x\n", hdr->id[0], hdr->id[1]); + PRINTF("ip64_dns64_4to6 flags1: 0x%02x\n", hdr->flags1); + PRINTF("ip64_dns64_4to6 flags2: 0x%02x\n", hdr->flags2); + PRINTF("ip64_dns64_4to6 numquestions: 0x%02x\n", ((hdr->numquestions[0] << 8) + hdr->numquestions[1])); + PRINTF("ip64_dns64_4to6 numanswers: 0x%02x\n", ((hdr->numanswers[0] << 8) + hdr->numanswers[1])); + PRINTF("ip64_dns64_4to6 numauthrr: 0x%02x\n", ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1])); + PRINTF("ip64_dns64_4to6 numextrarr: 0x%02x\n", ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1])); + + /* Find the DNS answer header by scanning through the question + labels. */ + qdata = ipv4data + sizeof(struct dns_hdr); + qcopy = ipv6data + sizeof(struct dns_hdr); + for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) { + do { + qlen = *qdata; + qdata++; + qcopy++; + for(j = 0; j < qlen; j++) { + qdata++; + qcopy++; + if(qdata > ipv4data + ipv4datalen) { + PRINTF("ip64_dns64_4to6: packet ended while parsing\n"); + return ipv6datalen; + } + } + } while(qlen != 0); + q = qcopy; + if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN && + q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) { + q[DNS_QUESTION_TYPE1] = DNS_TYPE_AAAA; + } + + qdata += DNS_QUESTION_SIZE; + qcopy += DNS_QUESTION_SIZE; + } + + adata = qdata; + acopy = qcopy; + + /* Go through the answers section and update the answers. */ + for(i = 0; i < ((hdr->numanswers[0] << 8) + hdr->numanswers[1]); i++) { + + n = *adata; + if(n & 0xc0) { + /* Short-hand name format: 2 bytes */ + *acopy++ = *adata++; + *acopy++ = *adata++; + } else { + /* Name spelled out */ + do { + n = *adata; + adata++; + acopy++; + for(j = 0; j < n; j++) { + *acopy++ = *adata++; + } + } while(n != 0); + } + + if(adata[0] == 0 && adata[1] == DNS_TYPE_A) { + /* Update the type field from A to AAAA */ + *acopy = *adata; + acopy++; + adata++; + *acopy = DNS_TYPE_AAAA; + acopy++; + adata++; + + /* Get the length of the address record. Should be 4. */ + lenptr = &acopy[6]; + len = (adata[6] << 8) + adata[7]; + + /* Copy the class, the TTL, and the data length */ + memcpy(acopy, adata, 2 + 4 + 2); + acopy += 8; + adata += 8; + + if(len == 4) { + uip_ip4addr_t addr; + uip_ipaddr(&addr, adata[0], adata[1], adata[2], adata[3]); + ip64_addr_4to6(&addr, (uip_ip6addr_t *)acopy); + + adata += len; + acopy += 16; + lenptr[0] = 0; + lenptr[1] = 16; + ipv6datalen += 12; + + } else { + memcpy(acopy, adata, len); + acopy += len; + adata += len; + } + } else { + len = (adata[8] << 8) + adata[9]; + + /* Copy the type, class, the TTL, and the data length */ + memcpy(acopy, adata, 2 + 2 + 4 + 2); + acopy += 10; + adata += 10; + + /* Copy the data */ + memcpy(acopy, adata, len); + acopy += len; + adata += len; + } + } + return ipv6datalen; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip64/ip64-dns64.h b/core/net/ip64/ip64-dns64.h new file mode 100644 index 000000000..27eb73127 --- /dev/null +++ b/core/net/ip64/ip64-dns64.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef IP64_DNS64_H_ +#define IP64_DNS64_H_ + +void ip64_dns64_6to4(const uint8_t *ipv6data, int ipv6datalen, + uint8_t *ipv4data, int ipv4datalen); +int ip64_dns64_4to6(const uint8_t *ipv4data, int ipv4datalen, + uint8_t *ipv6data, int ipv6datalen); + +#endif /* IP64_DNS64_H_ */ diff --git a/core/net/ip64/ip64-driver.h b/core/net/ip64/ip64-driver.h index 9de5d44a3..50b00cfd9 100644 --- a/core/net/ip64/ip64-driver.h +++ b/core/net/ip64/ip64-driver.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-eth-interface.c b/core/net/ip64/ip64-eth-interface.c index d2d941e2a..42f6234cc 100644 --- a/core/net/ip64/ip64-eth-interface.c +++ b/core/net/ip64/ip64-eth-interface.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-eth-interface.h b/core/net/ip64/ip64-eth-interface.h index 83dc6ab53..21bbd947f 100644 --- a/core/net/ip64/ip64-eth-interface.h +++ b/core/net/ip64/ip64-eth-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-eth.c b/core/net/ip64/ip64-eth.c index 1f6c67525..0a717c625 100644 --- a/core/net/ip64/ip64-eth.c +++ b/core/net/ip64/ip64-eth.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-eth.h b/core/net/ip64/ip64-eth.h index 3f5982df3..aa9448a86 100644 --- a/core/net/ip64/ip64-eth.h +++ b/core/net/ip64/ip64-eth.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-interface.h b/core/net/ip64/ip64-interface.h index 0e304ed37..574ae1c7f 100644 --- a/core/net/ip64/ip64-interface.h +++ b/core/net/ip64/ip64-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-ipv4-dhcp.c b/core/net/ip64/ip64-ipv4-dhcp.c index 6381fa179..ab8c6a517 100644 --- a/core/net/ip64/ip64-ipv4-dhcp.c +++ b/core/net/ip64/ip64-ipv4-dhcp.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-ipv4-dhcp.h b/core/net/ip64/ip64-ipv4-dhcp.h index c0ebdf52f..295af6854 100644 --- a/core/net/ip64/ip64-ipv4-dhcp.h +++ b/core/net/ip64/ip64-ipv4-dhcp.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-null-driver.c b/core/net/ip64/ip64-null-driver.c index 95f2b1f72..dafef5ea5 100644 --- a/core/net/ip64/ip64-null-driver.c +++ b/core/net/ip64/ip64-null-driver.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-null-driver.h b/core/net/ip64/ip64-null-driver.h index 2a9ad0711..f77691154 100644 --- a/core/net/ip64/ip64-null-driver.h +++ b/core/net/ip64/ip64-null-driver.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-slip-interface.c b/core/net/ip64/ip64-slip-interface.c index dab563f51..05fe704c7 100644 --- a/core/net/ip64/ip64-slip-interface.c +++ b/core/net/ip64/ip64-slip-interface.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64-slip-interface.h b/core/net/ip64/ip64-slip-interface.h index eecb14395..c3cf26a2f 100644 --- a/core/net/ip64/ip64-slip-interface.h +++ b/core/net/ip64/ip64-slip-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ip64/ip64.c b/core/net/ip64/ip64.c index f058f1d22..e00e1e443 100644 --- a/core/net/ip64/ip64.c +++ b/core/net/ip64/ip64.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -58,7 +59,8 @@ #include "ip64-special-ports.h" #include "ip64-eth-interface.h" #include "ip64-slip-interface.h" - +#include "ip64-dns64.h" +#include "net/ipv6/uip-ds6.h" #include "ip64-ipv4-dhcp.h" #include "contiki-net.h" @@ -172,6 +174,8 @@ static uip_ip4addr_t ipv4_broadcast_addr; #define TCP_SYN 0x02 #define TCP_RST 0x04 +#define DNS_PORT 53 + /*---------------------------------------------------------------------------*/ void ip64_init(void) @@ -366,7 +370,7 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, struct icmpv6_hdr *icmpv6hdr; uint16_t ipv6len, ipv4len; struct ip64_addrmap_entry *m; - + v6hdr = (struct ipv6_hdr *)ipv6packet; v4hdr = (struct ipv4_hdr *)resultpacket; @@ -434,6 +438,15 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, case IP_PROTO_UDP: PRINTF("ip64_6to4: UDP header\n"); v4hdr->proto = IP_PROTO_UDP; + + /* Check if this is a DNS request. If so, we should rewrite it + with the DNS64 module. */ + if(udphdr->destport == UIP_HTONS(DNS_PORT)) { + ip64_dns64_6to4((uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr), + ipv6len - IPV6_HDRLEN - sizeof(struct udp_hdr), + (uint8_t *)udphdr + sizeof(struct udp_hdr), + BUFSIZE - IPV4_HDRLEN - sizeof(struct udp_hdr)); + } /* Compute and check the UDP checksum - since we're going to recompute it ourselves, we must ensure that it was correct in the first place. */ @@ -572,9 +585,18 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, } else { ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME); - /* Treat DNS requests specially: since the are one-shot, we + /* Treat UDP packets from the IPv6 network to a multicast + address on the IPv4 network differently: since there is + no way for packets from the IPv4 network to go back to + the IPv6 network on these mappings, we'll mark them as + recyclable. */ + if(v4hdr->destipaddr.u8[0] == 224) { + ip64_addrmap_set_recycleble(m); + } + + /* Treat DNS requests differently: since the are one-shot, we mark them as recyclable. */ - if(udphdr->destport == UIP_HTONS(53)) { + if(udphdr->destport == UIP_HTONS(DNS_PORT)) { ip64_addrmap_set_recycleble(m); } } @@ -706,6 +728,21 @@ ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4packet_len, switch(v4hdr->proto) { case IP_PROTO_UDP: v6hdr->nxthdr = IP_PROTO_UDP; + /* Check if this is a DNS request. If so, we should rewrite it + with the DNS64 module. */ + if(udphdr->srcport == UIP_HTONS(DNS_PORT)) { + int len; + + len = ip64_dns64_4to6((uint8_t *)v4hdr + IPV4_HDRLEN + sizeof(struct udp_hdr), + ipv4len - IPV4_HDRLEN - sizeof(struct udp_hdr), + (uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr), + ipv6_packet_len - sizeof(struct udp_hdr)); + ipv6_packet_len = len + sizeof(struct udp_hdr); + v6hdr->len[0] = ipv6_packet_len >> 8; + v6hdr->len[1] = ipv6_packet_len & 0xff; + ipv6len = ipv6_packet_len + IPV6_HDRLEN; + + } break; case IP_PROTO_TCP: diff --git a/core/net/ip64/ip64.h b/core/net/ip64/ip64.h index 58cda4511..50d37d691 100644 --- a/core/net/ip64/ip64.h +++ b/core/net/ip64/ip64.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. diff --git a/core/net/ipv4/uip-over-mesh.c b/core/net/ipv4/uip-over-mesh.c index 92c5dbfd4..e6709f1d4 100644 --- a/core/net/ipv4/uip-over-mesh.c +++ b/core/net/ipv4/uip-over-mesh.c @@ -262,8 +262,8 @@ uip_over_mesh_send(void) if(BUF->proto == UIP_PROTO_TCP) { #if NETSTACK_CONF_WITH_RIME packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1); -#endif /* NETSTACK_CONF_WITH_RIME */ packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); +#endif /* NETSTACK_CONF_WITH_RIME */ /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/ } diff --git a/core/net/ipv4/uip.c b/core/net/ipv4/uip.c index 174b0a3fa..9668d1f2b 100644 --- a/core/net/ipv4/uip.c +++ b/core/net/ipv4/uip.c @@ -75,18 +75,9 @@ #include "net/ipv4/uip_arp.h" #include "net/ip/uip_arch.h" -#if !NETSTACK_CONF_WITH_IPV6 /* If NETSTACK_CONF_WITH_IPV6 is defined, we compile the - uip6.c file instead of this one. Therefore - this #ifndef removes the entire compilation - output of the uip.c file */ - - -#if NETSTACK_CONF_WITH_IPV6 #include "net/ipv4/uip-neighbor.h" -#endif /* NETSTACK_CONF_WITH_IPV6 */ #include - /*---------------------------------------------------------------------------*/ /* Variable definitions. */ @@ -395,7 +386,7 @@ uip_init(void) /*---------------------------------------------------------------------------*/ #if UIP_ACTIVE_OPEN struct uip_conn * -uip_connect(uip_ipaddr_t *ripaddr, uint16_t rport) +uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) { register struct uip_conn *conn, *cconn; @@ -1973,6 +1964,4 @@ uip_send(const void *data, int len) } } /*---------------------------------------------------------------------------*/ -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /** @}*/ diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index 3be5a0f2a..62b9014c5 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -1336,11 +1336,6 @@ send_packet(linkaddr_t *dest) packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr); #endif - /* Force acknowledge from sender (test hardware autoacks) */ -#if SICSLOWPAN_CONF_ACK_ALL - packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); -#endif - /* Provide a callback function to receive the result of a packet transmission. */ NETSTACK_LLSEC.send(&packet_sent, NULL); @@ -1388,6 +1383,7 @@ output(const uip_lladdr_t *localdest) set_packet_attrs(); } +#if PACKETBUF_WITH_PACKET_TYPE #define TCP_FIN 0x01 #define TCP_ACK 0x10 #define TCP_CTL 0x3f @@ -1402,6 +1398,7 @@ output(const uip_lladdr_t *localdest) packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM_END); } +#endif /* * The destination address will be tagged to each outbound diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3931319a0..49e3d3588 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -280,7 +280,7 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, if(r != NULL) { uip_ipaddr_t *current_nexthop; current_nexthop = uip_ds6_route_nexthop(r); - if(uip_ipaddr_cmp(nexthop, current_nexthop)) { + if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) { /* no need to update route - already correct! */ return r; } diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index accaf8271..72b1badfa 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -72,6 +72,7 @@ #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" /*------------------------------------------------------------------*/ @@ -112,19 +113,23 @@ void uip_log(char *msg); #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) +#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) /** @} */ +#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */ +static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ +static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ +static uip_ds6_addr_t *addr; /** Pointer to an interface address */ +#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */ static uip_ipaddr_t ipaddr; static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ #endif -static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ -static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ -static uip_ds6_addr_t *addr; /** Pointer to an interface address */ + /*------------------------------------------------------------------*/ /* create a llao */ static void @@ -139,7 +144,7 @@ create_llao(uint8_t *llao, uint8_t type) { /*------------------------------------------------------------------*/ - +#if UIP_ND6_SEND_NA static void ns_input(void) { @@ -319,7 +324,7 @@ discard: uip_len = 0; return; } - +#endif /* UIP_ND6_SEND_NA */ /*------------------------------------------------------------------*/ @@ -385,6 +390,7 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) PRINTF("\n"); return; } +#if UIP_ND6_SEND_NA /*------------------------------------------------------------------*/ /** * Neighbor Advertisement Processing @@ -554,7 +560,7 @@ discard: uip_len = 0; return; } - +#endif /* UIP_ND6_SEND_NA */ #if UIP_CONF_ROUTER #if UIP_ND6_SEND_RA @@ -715,6 +721,29 @@ uip_nd6_ra_output(uip_ipaddr_t * dest) uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; + +#if UIP_ND6_RA_RDNSS + if(uip_nameserver_count() > 0) { + uint8_t i = 0; + uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip; + uip_ipaddr_t *dns = NULL; + UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS; + UIP_ND6_OPT_RDNSS_BUF->reserved = 0; + UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration(); + if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) { + UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds(); + } + while((dns = uip_nameserver_get(i)) != NULL) { + uip_ipaddr_copy(ip++, dns); + i++; + } + UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1); + PRINTF("%d nameservers reported\n", i); + uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3; + nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3; + } +#endif /* UIP_ND6_RA_RDNSS */ + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); @@ -834,7 +863,7 @@ ra_input(void) (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 1, NBR_STALE); } else { - uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } @@ -938,6 +967,23 @@ ra_input(void) /* End of autonomous flag related processing */ } break; +#if UIP_ND6_RA_RDNSS + case UIP_ND6_OPT_RDNSS: + if(UIP_ND6_RA_BUF->flags_reserved & (UIP_ND6_O_FLAG << 6)) { + PRINTF("Processing RDNSS option\n"); + uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2; + uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip); + PRINTF("got %d nameservers\n", naddr); + while(naddr-- > 0) { + PRINTF(" nameserver: "); + PRINT6ADDR(ip); + PRINTF(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + ip++; + } + } + break; +#endif /* UIP_ND6_RA_RDNSS */ default: PRINTF("ND option not supported in RA"); break; diff --git a/core/net/ipv6/uip-nd6.h b/core/net/ipv6/uip-nd6.h index 6c88de614..8b5893328 100644 --- a/core/net/ipv6/uip-nd6.h +++ b/core/net/ipv6/uip-nd6.h @@ -87,7 +87,7 @@ #define UIP_ND6_MIN_RA_INTERVAL UIP_CONF_ND6_MIN_RA_INTERVAL #endif #define UIP_ND6_M_FLAG 0 -#define UIP_ND6_O_FLAG 0 +#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL) #define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL #define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/ @@ -139,6 +139,23 @@ /** @} */ +/** \name RFC 6106 RA DNS Options Constants */ +/** @{ */ +#ifndef UIP_CONF_ND6_RA_RDNSS +#define UIP_ND6_RA_RDNSS 0 +#else +#define UIP_ND6_RA_RDNSS UIP_CONF_ND6_RA_RDNSS +#endif + +#ifndef UIP_CONF_ND6_RA_DNSSL +#define UIP_ND6_RA_DNSSL 0 +#else +#error Not implemented +#define UIP_ND6_RA_DNSSL UIP_CONF_ND6_RA_DNSSL +#endif +/** @} */ + + /** \name ND6 option types */ /** @{ */ #define UIP_ND6_OPT_SLLAO 1 @@ -146,6 +163,8 @@ #define UIP_ND6_OPT_PREFIX_INFO 3 #define UIP_ND6_OPT_REDIRECTED_HDR 4 #define UIP_ND6_OPT_MTU 5 +#define UIP_ND6_OPT_RDNSS 25 +#define UIP_ND6_OPT_DNSSL 31 /** @} */ /** \name ND6 option types */ @@ -168,6 +187,8 @@ #define UIP_ND6_OPT_HDR_LEN 2 #define UIP_ND6_OPT_PREFIX_INFO_LEN 32 #define UIP_ND6_OPT_MTU_LEN 8 +#define UIP_ND6_OPT_RDNSS_LEN 1 +#define UIP_ND6_OPT_DNSSL_LEN 1 /* Length of TLLAO and SLLAO options, it is L2 dependant */ @@ -290,6 +311,15 @@ typedef struct uip_nd6_opt_mtu { uint32_t mtu; } uip_nd6_opt_mtu; +/** \brief ND option RDNSS */ +typedef struct uip_nd6_opt_dns { + uint8_t type; + uint8_t len; + uint16_t reserved; + uint32_t lifetime; + uip_ipaddr_t ip; +} uip_nd6_opt_dns; + /** \struct Redirected header option */ typedef struct uip_nd6_opt_redirected_hdr { uint8_t type; diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index a5d1db13c..c88822fbf 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -459,7 +459,7 @@ uip_init(void) /*---------------------------------------------------------------------------*/ #if UIP_TCP && UIP_ACTIVE_OPEN struct uip_conn * -uip_connect(uip_ipaddr_t *ripaddr, uint16_t rport) +uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) { register struct uip_conn *conn, *cconn; diff --git a/core/net/mac/contikimac/contikimac.c b/core/net/mac/contikimac/contikimac.c index ef0587b41..a168ae6ab 100644 --- a/core/net/mac/contikimac/contikimac.c +++ b/core/net/mac/contikimac/contikimac.c @@ -341,7 +341,6 @@ powercycle(struct rtimer *t, void *ptr) while(1) { static uint8_t packet_seen; - static rtimer_clock_t t0; static uint8_t count; #if SYNC_CYCLE_STARTS @@ -365,7 +364,6 @@ powercycle(struct rtimer *t, void *ptr) packet_seen = 0; for(count = 0; count < CCA_COUNT_MAX; ++count) { - t0 = RTIMER_NOW(); if(we_are_sending == 0 && we_are_receiving_burst == 0) { powercycle_turn_radio_on(); /* Check if a packet is seen in the air. If so, we keep the @@ -501,7 +499,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, uint8_t got_strobe_ack = 0; int len; uint8_t is_broadcast = 0; - uint8_t is_reliable = 0; uint8_t is_known_receiver = 0; uint8_t collisions; int transmit_len; @@ -548,11 +545,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]); #endif /* NETSTACK_CONF_WITH_IPV6 */ } - is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) -#if NETSTACK_CONF_WITH_RIME - || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) -#endif /* NETSTACK_CONF_WITH_RIME */ - ; if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) { packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); @@ -676,11 +668,12 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, { rtimer_clock_t wt; - rtimer_clock_t txtime; - int ret; - - txtime = RTIMER_NOW(); - ret = NETSTACK_RADIO.transmit(transmit_len); + rtimer_clock_t txtime = RTIMER_NOW(); +#if RDC_CONF_HARDWARE_ACK + int ret = NETSTACK_RADIO.transmit(transmit_len); +#else + NETSTACK_RADIO.transmit(transmit_len); +#endif #if RDC_CONF_HARDWARE_ACK /* For radios that block in the transmit routine and detect the diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 6ede3ec8d..ab6fec726 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -373,11 +373,13 @@ send_packet(mac_callback_t sent, void *ptr) } metadata->sent = sent; metadata->cptr = ptr; - +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); - } else { + } else +#endif + { list_add(n->queued_packet_list, q); } diff --git a/core/net/mac/cxmac/cxmac.c b/core/net/mac/cxmac/cxmac.c index ebf7651dd..770a5c19d 100644 --- a/core/net/mac/cxmac/cxmac.c +++ b/core/net/mac/cxmac/cxmac.c @@ -453,8 +453,6 @@ send_packet(void) packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]); #endif /* NETSTACK_CONF_WITH_IPV6 */ } -/* is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || - packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);*/ len = NETSTACK_FRAMER.create(); strobe_len = len + sizeof(struct cxmac_hdr); if(len < 0 || strobe_len > (int)sizeof(strobe)) { @@ -475,7 +473,7 @@ send_packet(void) return MAC_TX_ERR; } -#if WITH_STREAMING +#if WITH_STREAMING && PACKETBUF_WITH_PACKET_TYPE if(is_streaming == 1 && (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &is_streaming_to) || @@ -519,7 +517,7 @@ send_packet(void) wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD); expected = now + wait - 2 * DEFAULT_ON_TIME; -#if WITH_ACK_OPTIMIZATION +#if WITH_ACK_OPTIMIZATION && PACKETBUF_WITH_PACKET_TYPE /* Wait until the receiver is expected to be awake */ if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) != PACKETBUF_ATTR_PACKET_TYPE_ACK && @@ -624,12 +622,16 @@ send_packet(void) /* If we have received the strobe ACK, and we are sending a packet that will need an upper layer ACK (as signified by the PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */ - if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || + if(got_strobe_ack && ( #if NETSTACK_CONF_WITH_RIME + packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) || #endif /* NETSTACK_CONF_WITH_RIME */ +#if PACKETBUF_WITH_PACKET_TYPE packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == - PACKETBUF_ATTR_PACKET_TYPE_STREAM)) { + PACKETBUF_ATTR_PACKET_TYPE_STREAM || +#endif + 0)) { on(); /* Wait for ACK packet */ waiting_for_packet = 1; } else { diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index 03b091feb..987d142ba 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -242,8 +242,10 @@ parse(void) } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); - /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); +#if NETSTACK_CONF_WITH_RIME packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); +#endif #if LLSEC802154_SECURITY_LEVEL if(frame.fcf.security_enabled) { diff --git a/core/net/mac/mac-sequence.c b/core/net/mac/mac-sequence.c index 638dece13..40ac3c28a 100644 --- a/core/net/mac/mac-sequence.c +++ b/core/net/mac/mac-sequence.c @@ -74,7 +74,7 @@ mac_sequence_is_duplicate(void) for(i = 0; i < MAX_SEQNOS; ++i) { if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno) { + if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) == received_seqnos[i].seqno) { /* Duplicate packet. */ return 1; } @@ -102,7 +102,7 @@ mac_sequence_register_seqno(void) for(j = i - 1; j > 0; --j) { memcpy(&received_seqnos[j], &received_seqnos[j - 1], sizeof(struct seqno)); } - received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); + received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); linkaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c index 3403b764e..111211a2b 100644 --- a/core/net/mac/nullrdc.c +++ b/core/net/mac/nullrdc.c @@ -264,11 +264,13 @@ send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) static void packet_input(void) { +#if NULLRDC_SEND_802154_ACK int original_datalen; uint8_t *original_dataptr; original_datalen = packetbuf_datalen(); original_dataptr = packetbuf_dataptr(); +#endif #if NULLRDC_802154_AUTOACK if(packetbuf_datalen() == ACK_LEN) { @@ -294,7 +296,7 @@ packet_input(void) if(duplicate) { /* Drop the packet. */ PRINTF("nullrdc: drop duplicate link layer packet %u\n", - packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); } else { mac_sequence_register_seqno(); } diff --git a/core/net/mac/sicslowmac/sicslowmac.c b/core/net/mac/sicslowmac/sicslowmac.c index 9d88a6b78..09d77ae17 100644 --- a/core/net/mac/sicslowmac/sicslowmac.c +++ b/core/net/mac/sicslowmac/sicslowmac.c @@ -106,7 +106,9 @@ send_packet(mac_callback_t sent, void *ptr) params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; +#if NETSTACK_CONF_WITH_RIME params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); +#endif params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ diff --git a/core/net/packetbuf.c b/core/net/packetbuf.c index 6e4c3e720..217f40bc2 100644 --- a/core/net/packetbuf.c +++ b/core/net/packetbuf.c @@ -106,10 +106,7 @@ packetbuf_compact(void) { int i, len; - if(packetbuf_is_reference()) { - memcpy(&packetbuf[PACKETBUF_HDR_SIZE], packetbuf_reference_ptr(), - packetbuf_datalen()); - } else if(bufptr > 0) { + if(bufptr > 0) { len = packetbuf_datalen() + PACKETBUF_HDR_SIZE; for(i = PACKETBUF_HDR_SIZE; i < len; i++) { packetbuf[i] = packetbuf[bufptr + i]; @@ -215,26 +212,6 @@ packetbuf_hdrptr(void) return (void *)(&packetbuf[hdrptr]); } /*---------------------------------------------------------------------------*/ -void -packetbuf_reference(void *ptr, uint16_t len) -{ - packetbuf_clear(); - packetbufptr = ptr; - buflen = len; -} -/*---------------------------------------------------------------------------*/ -int -packetbuf_is_reference(void) -{ - return packetbufptr != &packetbuf[PACKETBUF_HDR_SIZE]; -} -/*---------------------------------------------------------------------------*/ -void * -packetbuf_reference_ptr(void) -{ - return packetbufptr; -} -/*---------------------------------------------------------------------------*/ uint16_t packetbuf_datalen(void) { diff --git a/core/net/packetbuf.h b/core/net/packetbuf.h index 048493897..3c1839bf1 100644 --- a/core/net/packetbuf.h +++ b/core/net/packetbuf.h @@ -74,6 +74,12 @@ #define PACKETBUF_HDR_SIZE 48 #endif +#ifdef PACKETBUF_CONF_WITH_PACKET_TYPE +#define PACKETBUF_WITH_PACKET_TYPE PACKETBUF_CONF_WITH_PACKET_TYPE +#else +#define PACKETBUF_WITH_PACKET_TYPE NETSTACK_CONF_WITH_RIME +#endif + /** * \brief Clear and reset the packetbuf * @@ -181,52 +187,12 @@ uint16_t packetbuf_totlen(void); */ void packetbuf_set_datalen(uint16_t len); -/** - * \brief Point the packetbuf to external data - * \param ptr A pointer to the external data - * \param len The length of the external data - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to make - * the packetbuf point to external data. The function also - * specifies the length of the external data that the - * packetbuf references. - */ -void packetbuf_reference(void *ptr, uint16_t len); - -/** - * \brief Check if the packetbuf references external data - * \retval Non-zero if the packetbuf references external data, zero otherwise. - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to check - * if the packetbuf points to external data that has - * previously been referenced with packetbuf_reference(). - * - */ -int packetbuf_is_reference(void); - -/** - * \brief Get a pointer to external data referenced by the packetbuf - * \retval A pointer to the external data - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. The data may point to external - * data that has previously been referenced with - * packetbuf_reference(). This function is used to get a - * pointer to the external data. - * - */ -void *packetbuf_reference_ptr(void); - /** * \brief Compact the packetbuf * * This function compacts the packetbuf by copying the data * portion of the packetbuf so that becomes consecutive to - * the header. It also copies external data that has - * previously been referenced with packetbuf_reference() - * into the packetbuf. + * the header. * * This function is called by the Rime code before a * packet is to be sent by a device driver. This assures @@ -257,9 +223,7 @@ int packetbuf_copyfrom(const void *from, uint16_t len); * * This function copies the packetbuf to an external * buffer. Both the data portion and the header portion of - * the packetbuf is copied. If the packetbuf referenced - * external data (referenced with packetbuf_reference()) the - * external data is copied. + * the packetbuf is copied. * * The external buffer to which the packetbuf is to be * copied must be able to accomodate at least @@ -351,10 +315,12 @@ enum { PACKETBUF_ATTR_IS_CREATED_AND_SECURED, /* Scope 1 attributes: used between two neighbors only. */ - PACKETBUF_ATTR_RELIABLE, - PACKETBUF_ATTR_PACKET_ID, +#if PACKETBUF_WITH_PACKET_TYPE PACKETBUF_ATTR_PACKET_TYPE, +#endif #if NETSTACK_CONF_WITH_RIME + PACKETBUF_ATTR_PACKET_ID, + PACKETBUF_ATTR_RELIABLE, PACKETBUF_ATTR_REXMIT, PACKETBUF_ATTR_MAX_REXMIT, PACKETBUF_ATTR_NUM_REXMIT, diff --git a/core/net/queuebuf.c b/core/net/queuebuf.c index 72c35c3c6..8a9ebfe8a 100644 --- a/core/net/queuebuf.c +++ b/core/net/queuebuf.c @@ -43,18 +43,13 @@ */ #include "contiki-net.h" + #if WITH_SWAP #include "cfs/cfs.h" #endif #include /* for memcpy() */ -#ifdef QUEUEBUF_CONF_REF_NUM -#define QUEUEBUF_REF_NUM QUEUEBUF_CONF_REF_NUM -#else -#define QUEUEBUF_REF_NUM 2 -#endif - /* Structure pointing to a buffer either stored in RAM or swapped in CFS */ struct queuebuf { @@ -83,15 +78,7 @@ struct queuebuf_data { struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS]; }; -struct queuebuf_ref { - uint16_t len; - uint8_t *ref; - uint8_t hdr[PACKETBUF_HDR_SIZE]; - uint8_t hdrlen; -}; - MEMB(bufmem, struct queuebuf, QUEUEBUF_NUM); -MEMB(refbufmem, struct queuebuf_ref, QUEUEBUF_REF_NUM); MEMB(buframmem, struct queuebuf_data, QUEUEBUFRAM_NUM); #if WITH_SWAP @@ -144,7 +131,7 @@ LIST(queuebuf_list); #endif /* QUEUEBUF_CONF_STATS */ #if QUEUEBUF_STATS -uint8_t queuebuf_len, queuebuf_ref_len, queuebuf_max_len; +uint8_t queuebuf_len, queuebuf_max_len; #endif /* QUEUEBUF_STATS */ #if WITH_SWAP @@ -301,20 +288,15 @@ queuebuf_init(void) #endif memb_init(&buframmem); memb_init(&bufmem); - memb_init(&refbufmem); #if QUEUEBUF_STATS - queuebuf_max_len = QUEUEBUF_NUM; + queuebuf_max_len = 0; #endif /* QUEUEBUF_STATS */ } /*---------------------------------------------------------------------------*/ int queuebuf_numfree(void) { - if(packetbuf_is_reference()) { - return memb_numfree(&refbufmem); - } else { - return memb_numfree(&bufmem); - } + return memb_numfree(&bufmem); } /*---------------------------------------------------------------------------*/ #if QUEUEBUF_DEBUG @@ -326,81 +308,62 @@ queuebuf_new_from_packetbuf(void) #endif /* QUEUEBUF_DEBUG */ { struct queuebuf *buf; - struct queuebuf_ref *rbuf; - if(packetbuf_is_reference()) { - rbuf = memb_alloc(&refbufmem); - if(rbuf != NULL) { -#if QUEUEBUF_STATS - ++queuebuf_ref_len; -#endif /* QUEUEBUF_STATS */ - rbuf->len = packetbuf_datalen(); - rbuf->ref = packetbuf_reference_ptr(); - rbuf->hdrlen = packetbuf_copyto_hdr(rbuf->hdr); - } else { - PRINTF("queuebuf_new_from_packetbuf: could not allocate a reference queuebuf\n"); - } - return (struct queuebuf *)rbuf; - } else { - struct queuebuf_data *buframptr; - buf = memb_alloc(&bufmem); - if(buf != NULL) { + struct queuebuf_data *buframptr; + buf = memb_alloc(&bufmem); + if(buf != NULL) { #if QUEUEBUF_DEBUG - list_add(queuebuf_list, buf); - buf->file = file; - buf->line = line; - buf->time = clock_time(); + list_add(queuebuf_list, buf); + buf->file = file; + buf->line = line; + buf->time = clock_time(); #endif /* QUEUEBUF_DEBUG */ - buf->ram_ptr = memb_alloc(&buframmem); + buf->ram_ptr = memb_alloc(&buframmem); #if WITH_SWAP - /* If the allocation failed, store the qbuf in swap files */ - if(buf->ram_ptr != NULL) { - buf->location = IN_RAM; - buframptr = buf->ram_ptr; - } else { - buf->location = IN_CFS; - buf->swap_id = -1; - tmpdata_qbuf = buf; - buframptr = &tmpdata; - } + /* If the allocation failed, store the qbuf in swap files */ + if(buf->ram_ptr != NULL) { + buf->location = IN_RAM; + buframptr = buf->ram_ptr; + } else { + buf->location = IN_CFS; + buf->swap_id = -1; + tmpdata_qbuf = buf; + buframptr = &tmpdata; + } #else - if(buf->ram_ptr == NULL) { - PRINTF("queuebuf_new_from_packetbuf: could not queuebuf data\n"); + if(buf->ram_ptr == NULL) { + PRINTF("queuebuf_new_from_packetbuf: could not queuebuf data\n"); + memb_free(&bufmem, buf); + return NULL; + } + buframptr = buf->ram_ptr; +#endif + + buframptr->len = packetbuf_copyto(buframptr->data); + packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs); + +#if WITH_SWAP + if(buf->location == IN_CFS) { + if(queuebuf_flush_tmpdata() == -1) { + /* We were unable to write the data in the swap */ memb_free(&bufmem, buf); return NULL; } - buframptr = buf->ram_ptr; -#endif - - buframptr->len = packetbuf_copyto(buframptr->data); - packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs); - -#if WITH_SWAP - if(buf->location == IN_CFS) { - if(queuebuf_flush_tmpdata() == -1) { - /* We were unable to write the data in the swap */ - memb_free(&bufmem, buf); - return NULL; - } - } + } #endif #if QUEUEBUF_STATS - ++queuebuf_len; - PRINTF("queuebuf len %d\n", queuebuf_len); - printf("#A q=%d\n", queuebuf_len); - if(queuebuf_len == queuebuf_max_len + 1) { - queuebuf_free(buf); - queuebuf_len--; - return NULL; - } + ++queuebuf_len; + PRINTF("#A q=%d\n", queuebuf_len); + if(queuebuf_len > queuebuf_max_len) { + queuebuf_max_len = queuebuf_len; + } #endif /* QUEUEBUF_STATS */ - } else { - PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n"); - } - return buf; + } else { + PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n"); } + return buf; } /*---------------------------------------------------------------------------*/ void @@ -444,47 +407,30 @@ queuebuf_free(struct queuebuf *buf) memb_free(&bufmem, buf); #if QUEUEBUF_STATS --queuebuf_len; - printf("#A q=%d\n", queuebuf_len); + PRINTF("#A q=%d\n", queuebuf_len); #endif /* QUEUEBUF_STATS */ #if QUEUEBUF_DEBUG list_remove(queuebuf_list, buf); #endif /* QUEUEBUF_DEBUG */ - } else if(memb_inmemb(&refbufmem, buf)) { - memb_free(&refbufmem, buf); -#if QUEUEBUF_STATS - --queuebuf_ref_len; -#endif /* QUEUEBUF_STATS */ } } /*---------------------------------------------------------------------------*/ void queuebuf_to_packetbuf(struct queuebuf *b) { - struct queuebuf_ref *r; if(memb_inmemb(&bufmem, b)) { struct queuebuf_data *buframptr = queuebuf_load_to_ram(b); packetbuf_copyfrom(buframptr->data, buframptr->len); packetbuf_attr_copyfrom(buframptr->attrs, buframptr->addrs); - } else if(memb_inmemb(&refbufmem, b)) { - r = (struct queuebuf_ref *)b; - packetbuf_clear(); - packetbuf_copyfrom(r->ref, r->len); - packetbuf_hdralloc(r->hdrlen); - memcpy(packetbuf_hdrptr(), r->hdr, r->hdrlen); } } /*---------------------------------------------------------------------------*/ void * queuebuf_dataptr(struct queuebuf *b) { - struct queuebuf_ref *r; - if(memb_inmemb(&bufmem, b)) { struct queuebuf_data *buframptr = queuebuf_load_to_ram(b); return buframptr->data; - } else if(memb_inmemb(&refbufmem, b)) { - r = (struct queuebuf_ref *)b; - return r->ref; } return NULL; } diff --git a/core/net/rime/rudolph0.c b/core/net/rime/rudolph0.c deleted file mode 100644 index 9582430b4..000000000 --- a/core/net/rime/rudolph0.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * Rudolph0: a simple block data flooding protocol - * \author - * Adam Dunkels - */ - -/** - * \addtogroup rudolph0 - * @{ - */ - -#include /* for offsetof */ - -#include "net/rime/rime.h" -#include "net/rime/rudolph0.h" - -#define STEADY_TIME CLOCK_SECOND * 2 - -#define DEFAULT_SEND_INTERVAL CLOCK_SECOND / 2 -enum { - TYPE_DATA, - TYPE_NACK, -}; - -enum { - STATE_RECEIVER, - STATE_SENDER, -}; - -#define VERSION_LT(a, b) ((signed char)((a) - (b)) < 0) - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -/*---------------------------------------------------------------------------*/ -static void -read_new_datapacket(struct rudolph0_conn *c) -{ - int len = 0; - - if(c->cb->read_chunk) { - len = c->cb->read_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - c->current.data, RUDOLPH0_DATASIZE); - } - c->current.datalen = len; - - PRINTF("read_new_datapacket len %d\n", len); -} -/*---------------------------------------------------------------------------*/ -static void -send_nack(struct rudolph0_conn *c) -{ - struct rudolph0_hdr *hdr; - packetbuf_clear(); - packetbuf_hdralloc(sizeof(struct rudolph0_hdr)); - hdr = packetbuf_hdrptr(); - - hdr->type = TYPE_NACK; - hdr->version = c->current.h.version; - hdr->chunk = c->current.h.chunk; - - PRINTF("Sending nack for %d:%d\n", hdr->version, hdr->chunk); - polite_send(&c->nackc, c->send_interval / 2, sizeof(struct rudolph0_hdr)); -} -/*---------------------------------------------------------------------------*/ -static void -sent(struct stbroadcast_conn *stbroadcast) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; - - if(c->current.datalen == RUDOLPH0_DATASIZE) { - c->current.h.chunk++; - PRINTF("Sending data chunk %d next time\n", c->current.h.chunk); - read_new_datapacket(c); - } else { - stbroadcast_set_timer(&c->c, STEADY_TIME); - PRINTF("Steady: Sending the same data chunk next time datalen %d, %d\n", - c->current.datalen, RUDOLPH0_DATASIZE); - } -} -/*---------------------------------------------------------------------------*/ -static void -recv(struct stbroadcast_conn *stbroadcast) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; - struct rudolph0_datapacket *p = packetbuf_dataptr(); - - if(p->h.type == TYPE_DATA) { - if(c->current.h.version != p->h.version) { - PRINTF("rudolph0 new version %d\n", p->h.version); - c->current.h.version = p->h.version; - c->current.h.chunk = 0; - c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NEWFILE, p->data, 0); - if(p->h.chunk != 0) { - send_nack(c); - } else { - c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NONE, p->data, p->datalen); - c->current.h.chunk++; - } - } else if(p->h.version == c->current.h.version) { - if(p->h.chunk == c->current.h.chunk) { - PRINTF("received chunk %d\n", p->h.chunk); - if(p->datalen < RUDOLPH0_DATASIZE) { - c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - RUDOLPH0_FLAG_LASTCHUNK, p->data, p->datalen); - } else { - c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - RUDOLPH0_FLAG_NONE, p->data, p->datalen); - } - c->current.h.chunk++; - - } else if(p->h.chunk > c->current.h.chunk) { - PRINTF("received chunk %d > %d, sending NACK\n", p->h.chunk, c->current.h.chunk); - send_nack(c); - } - } else { /* p->h.version < c->current.h.version */ - /* Ignore packets with old version */ - } - } -} -/*---------------------------------------------------------------------------*/ -static void -recv_nack(struct polite_conn *polite) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *) - ((char *)polite - offsetof(struct rudolph0_conn, - nackc)); - struct rudolph0_datapacket *p = packetbuf_dataptr(); - - if(p->h.type == TYPE_NACK && c->state == STATE_SENDER) { - if(p->h.version == c->current.h.version) { - PRINTF("Reseting chunk to %d\n", p->h.chunk); - c->current.h.chunk = p->h.chunk; - } else { - PRINTF("Wrong version, reseting chunk to 0\n"); - c->current.h.chunk = 0; - } - read_new_datapacket(c); - stbroadcast_set_timer(&c->c, c->send_interval); - } -} -/*---------------------------------------------------------------------------*/ -static const struct polite_callbacks polite = { recv_nack, 0, 0 }; -static const struct stbroadcast_callbacks stbroadcast = { recv, sent }; -/*---------------------------------------------------------------------------*/ -void -rudolph0_open(struct rudolph0_conn *c, uint16_t channel, - const struct rudolph0_callbacks *cb) -{ - stbroadcast_open(&c->c, channel, &stbroadcast); - polite_open(&c->nackc, channel + 1, &polite); - c->cb = cb; - c->current.h.version = 0; - c->state = STATE_RECEIVER; - c->send_interval = DEFAULT_SEND_INTERVAL; -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_close(struct rudolph0_conn *c) -{ - stbroadcast_close(&c->c); - polite_close(&c->nackc); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_send(struct rudolph0_conn *c, clock_time_t send_interval) -{ - c->state = STATE_SENDER; - c->current.h.version++; - c->current.h.version++; - c->current.h.chunk = 0; - c->current.h.type = TYPE_DATA; - read_new_datapacket(c); - packetbuf_reference(&c->current, sizeof(struct rudolph0_datapacket)); - c->send_interval = send_interval; - stbroadcast_send_stubborn(&c->c, c->send_interval); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_force_restart(struct rudolph0_conn *c) -{ - c->current.h.chunk = 0; - send_nack(c); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_stop(struct rudolph0_conn *c) -{ - stbroadcast_cancel(&c->c); -} -/*---------------------------------------------------------------------------*/ -int -rudolph0_version(struct rudolph0_conn *c) -{ - return c->current.h.version; -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_set_version(struct rudolph0_conn *c, int version) -{ - c->current.h.version = version; -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/core/net/rime/rudolph0.h b/core/net/rime/rudolph0.h deleted file mode 100644 index 695d97950..000000000 --- a/core/net/rime/rudolph0.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * Header file for the single-hop reliable bulk data transfer module - * \author - * Adam Dunkels - */ - -/** - * \addtogroup rime - * @{ - */ - -/** - * \defgroup rudolph0 Single-hop reliable bulk data transfer (rudolph0) - * @{ - * - * The rudolph0 module implements a single-hop reliable bulk data - * transfer mechanism. - * - * \section rudolph0-channels Channels - * - * The rudolph0 module uses 2 channels; one for data packets and one - * for NACK and repair packets. - * - */ - -#ifndef RUDOLPH0_H_ -#define RUDOLPH0_H_ - -#include "net/rime/stbroadcast.h" -#include "net/rime/polite.h" - -struct rudolph0_conn; - -enum { - RUDOLPH0_FLAG_NONE, - RUDOLPH0_FLAG_NEWFILE, - RUDOLPH0_FLAG_LASTCHUNK, -}; - -struct rudolph0_callbacks { - void (* write_chunk)(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int len); - int (* read_chunk)(struct rudolph0_conn *c, int offset, uint8_t *to, - int maxsize); -}; - -#ifdef RUDOLPH0_CONF_DATASIZE -#define RUDOLPH0_DATASIZE RUDOLPH0_CONF_DATASIZE -#else -#define RUDOLPH0_DATASIZE 64 -#endif - -struct rudolph0_hdr { - uint8_t type; - uint8_t version; - uint16_t chunk; -}; - -struct rudolph0_datapacket { - struct rudolph0_hdr h; - uint8_t datalen; - uint8_t data[RUDOLPH0_DATASIZE]; -}; - -struct rudolph0_conn { - struct stbroadcast_conn c; - struct polite_conn nackc; - const struct rudolph0_callbacks *cb; - clock_time_t send_interval; - uint8_t state; - struct rudolph0_datapacket current; -}; - -void rudolph0_open(struct rudolph0_conn *c, uint16_t channel, - const struct rudolph0_callbacks *cb); -void rudolph0_close(struct rudolph0_conn *c); -void rudolph0_send(struct rudolph0_conn *c, clock_time_t interval); -void rudolph0_stop(struct rudolph0_conn *c); - -/* Force the sender to restart sending the file from the start. */ -void rudolph0_force_restart(struct rudolph0_conn *c); - -void rudolph0_set_version(struct rudolph0_conn *c, int version); -int rudolph0_version(struct rudolph0_conn *c); - -#endif /* RUDOLPH0_H_ */ -/** @} */ -/** @} */ - diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 3d6aa8b36..a2c0e6dd2 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -195,4 +195,77 @@ #define RPL_PREFERENCE 0 #endif +/* + * Hop-by-hop option + * This option control the insertion of the RPL Hop-by-Hop extension header + * into packets originating from this node. Incoming Hop-by-hop extension + * header are still processed and forwarded. + */ +#ifdef RPL_CONF_INSERT_HBH_OPTION +#define RPL_INSERT_HBH_OPTION RPL_CONF_INSERT_HBH_OPTION +#else +#define RPL_INSERT_HBH_OPTION 1 +#endif + +/* + * RPL probing. When enabled, probes will be sent periodically to keep + * parent link estimates up to date. + * */ +#ifdef RPL_CONF_WITH_PROBING +#define RPL_WITH_PROBING RPL_CONF_WITH_PROBING +#else +#define RPL_WITH_PROBING 1 +#endif + +/* + * RPL probing interval. + * */ +#ifdef RPL_CONF_PROBING_INTERVAL +#define RPL_PROBING_INTERVAL RPL_CONF_PROBING_INTERVAL +#else +#define RPL_PROBING_INTERVAL (120 * CLOCK_SECOND) +#endif + +/* + * RPL probing expiration time. + * */ +#ifdef RPL_CONF_PROBING_EXPIRATION_TIME +#define RPL_PROBING_EXPIRATION_TIME RPL_CONF_PROBING_EXPIRATION_TIME +#else +#define RPL_PROBING_EXPIRATION_TIME (10 * 60 * CLOCK_SECOND) +#endif + +/* + * Function used to select the next parent to be probed. + * */ +#ifdef RPL_CONF_PROBING_SELECT_FUNC +#define RPL_PROBING_SELECT_FUNC RPL_CONF_PROBING_SELECT_FUNC +#else +#define RPL_PROBING_SELECT_FUNC(dag) get_probing_target((dag)) +#endif + +/* + * Function used to send RPL probes. + * To probe with DIO, use: + * #define RPL_CONF_PROBING_SEND_FUNC(instance, addr) dio_output((instance), (addr)) + * To probe with DIS, use: + * #define RPL_CONF_PROBING_SEND_FUNC(instance, addr) dis_output((addr)) + * Any other custom probing function is also acceptable. + * */ +#ifdef RPL_CONF_PROBING_SEND_FUNC +#define RPL_PROBING_SEND_FUNC RPL_CONF_PROBING_SEND_FUNC +#else +#define RPL_PROBING_SEND_FUNC(instance, addr) dio_output((instance), (addr)) +#endif + +/* + * Function used to calculate next RPL probing interval + * */ +#ifdef RPL_CONF_PROBING_DELAY_FUNC +#define RPL_PROBING_DELAY_FUNC RPL_CONF_PROBING_DELAY_FUNC +#else +#define RPL_PROBING_DELAY_FUNC() ((RPL_PROBING_INTERVAL / 2) \ + + random_rand() % (RPL_PROBING_INTERVAL)) +#endif + #endif /* RPL_CONF_H */ diff --git a/core/net/rpl/rpl-dag-root.c b/core/net/rpl/rpl-dag-root.c new file mode 100644 index 000000000..44519bcd4 --- /dev/null +++ b/core/net/rpl/rpl-dag-root.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "contiki.h" +#include "contiki-net.h" + +#include "net/rpl/rpl.h" +#include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-dag-root.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) + +static struct uip_ds6_notification n; +static uint8_t to_become_root; +static struct ctimer c; +/*---------------------------------------------------------------------------*/ +static const uip_ipaddr_t * +dag_root(void) +{ + rpl_dag_t *dag; + + dag = rpl_get_any_dag(); + if(dag != NULL) { + return &dag->dag_id; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static const uip_ipaddr_t * +get_global_address(void) +{ + int i; + uint8_t state; + uip_ipaddr_t *ipaddr = NULL; + + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + state == ADDR_PREFERRED && + !uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)) { + ipaddr = &uip_ds6_if.addr_list[i].ipaddr; + } + } + return ipaddr; +} +/*---------------------------------------------------------------------------*/ +static void +create_dag_callback(void *ptr) +{ + const uip_ipaddr_t *root, *ipaddr; + + root = dag_root(); + ipaddr = get_global_address(); + + if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { + /* The RPL network we are joining is one that we created, so we + become root. */ + if(to_become_root) { + rpl_dag_root_init_dag_immediately(); + to_become_root = 0; + } + } else { + rpl_dag_t *dag; + + dag = rpl_get_any_dag(); +#if DEBUG + printf("Found a network we did not create\n"); + printf("version %d grounded %d preference %d used %d joined %d rank %d\n", + dag->version, dag->grounded, + dag->preference, dag->used, + dag->joined, dag->rank); +#endif /* DEBUG */ + + /* We found a RPL network that we did not create so we just join + it without becoming root. But if the network has an infinite + rank, we assume the network has broken, and we become the new + root of the network. */ + + if(dag->rank == INFINITE_RANK) { + if(to_become_root) { + rpl_dag_root_init_dag_immediately(); + to_become_root = 0; + } + } + + /* Try again after the grace period */ + ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, + int numroutes) +{ + if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD) { + if(route != NULL && ipaddr != NULL && + !uip_is_addr_unspecified(route) && + !uip_is_addr_unspecified(ipaddr)) { + if(to_become_root) { + ctimer_set(&c, 0, create_dag_callback, NULL); + } + } + } +} +/*---------------------------------------------------------------------------*/ +static uip_ipaddr_t * +set_global_address(void) +{ + static uip_ipaddr_t ipaddr; + int i; + uint8_t state; + + /* Assign a unique local address (RFC4193, + http://tools.ietf.org/html/rfc4193). */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + printf("IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); + printf("\n"); + } + } + + return &ipaddr; +} +/*---------------------------------------------------------------------------*/ +void +rpl_dag_root_init(void) +{ + static uint8_t initialized = 0; + + if(!initialized) { + to_become_root = 0; + set_global_address(); + uip_ds6_notification_add(&n, route_callback); + initialized = 1; + } +} +/*---------------------------------------------------------------------------*/ +int +rpl_dag_root_init_dag_immediately(void) +{ + struct uip_ds6_addr *root_if; + int i; + uint8_t state; + uip_ipaddr_t *ipaddr = NULL; + + rpl_dag_root_init(); + + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + state == ADDR_PREFERRED && + !uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)) { + ipaddr = &uip_ds6_if.addr_list[i].ipaddr; + } + } + + if(ipaddr != NULL) { + root_if = uip_ds6_addr_lookup(ipaddr); + if(root_if != NULL) { + rpl_dag_t *dag; + uip_ipaddr_t prefix; + + rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr); + dag = rpl_get_any_dag(); + + /* If there are routes in this dag, we remove them all as we are + from now on the new dag root and the old routes are wrong */ + rpl_remove_routes(dag); + if(dag->instance != NULL && + dag->instance->def_route != NULL) { + uip_ds6_defrt_rm(dag->instance->def_route); + dag->instance->def_route = NULL; + } + + uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + rpl_set_prefix(dag, &prefix, 64); + PRINTF("rpl_dag_root_init_dag: created a new RPL dag\n"); + return 0; + } else { + PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG\n"); + return -1; + } + } else { + PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG, no preferred IP address found\n"); + return -2; + } +} +/*---------------------------------------------------------------------------*/ +void +rpl_dag_root_init_dag(void) +{ + rpl_dag_root_init(); + + ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); + to_become_root = 1; + + /* Send a DIS packet to request RPL info from neighbors. */ + dis_output(NULL); +} +/*---------------------------------------------------------------------------*/ +int +rpl_dag_root_is_root(void) +{ + rpl_instance_t *instance; + + instance = rpl_get_default_instance(); + + if(instance == NULL) { + return 0; + } + + if(instance->current_dag && + instance->current_dag->rank == ROOT_RANK(instance)) { + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl-dag-root.h b/core/net/rpl/rpl-dag-root.h new file mode 100644 index 000000000..b421841b7 --- /dev/null +++ b/core/net/rpl/rpl-dag-root.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef RPL_DAG_ROOT_H_ +#define RPL_DAG_ROOT_H_ + +void rpl_dag_root_init(void); +void rpl_dag_root_init_dag(void); +int rpl_dag_root_init_dag_immediately(void); + +int rpl_dag_root_is_root(void); + +#endif /* RPL_DAG_ROOT_H_ */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 7b1908cfe..6c9b75b8f 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -75,12 +75,37 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF}; /*---------------------------------------------------------------------------*/ /* Per-parent RPL information */ -NBR_TABLE(rpl_parent_t, rpl_parents); +NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents); /*---------------------------------------------------------------------------*/ /* Allocate instance table. */ rpl_instance_t instance_table[RPL_MAX_INSTANCES]; rpl_instance_t *default_instance; +/*---------------------------------------------------------------------------*/ +void +rpl_print_neighbor_list() +{ + if(default_instance != NULL && default_instance->current_dag != NULL && + default_instance->of != NULL && default_instance->of->calculate_rank != NULL) { + int curr_dio_interval = default_instance->dio_intcurrent; + int curr_rank = default_instance->current_dag->rank; + rpl_parent_t *p = nbr_table_head(rpl_parents); + clock_time_t now = clock_time(); + + printf("RPL: rank %u dioint %u, %u nbr(s)\n", curr_rank, curr_dio_interval, uip_ds6_nbr_num()); + while(p != NULL) { + uip_ds6_nbr_t *nbr = rpl_get_nbr(p); + printf("RPL: nbr %3u %5u, %5u => %5u %c (last tx %u min ago)\n", + nbr_table_get_lladdr(rpl_parents, p)->u8[7], + p->rank, nbr ? nbr->link_metric : 0, + default_instance->of->calculate_rank(p, 0), + p == default_instance->current_dag->preferred_parent ? '*' : ' ', + (unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND))); + p = nbr_table_next(rpl_parents, p); + } + printf("RPL: end of list\n"); + } +} /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) @@ -269,17 +294,27 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) rpl_dag_t *dag; rpl_instance_t *instance; uint8_t version; + int i; version = RPL_LOLLIPOP_INIT; - dag = get_dag(instance_id, dag_id); - if(dag != NULL) { - version = dag->version; - RPL_LOLLIPOP_INCREMENT(version); - PRINTF("RPL: Dropping a joined DAG when setting this node as root"); - if(dag == dag->instance->current_dag) { - dag->instance->current_dag = NULL; + instance = rpl_get_instance(instance_id); + if(instance != NULL) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) { + dag = &instance->dag_table[i]; + if(dag->used) { + if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) { + version = dag->version; + RPL_LOLLIPOP_INCREMENT(version); + } + if(dag == dag->instance->current_dag) { + PRINTF("RPL: Dropping a joined DAG when setting this node as root"); + dag->instance->current_dag = NULL; + } else { + PRINTF("RPL: Dropping a DAG when setting this node as root"); + } + rpl_free_dag(dag); + } } - rpl_free_dag(dag); } dag = rpl_alloc_dag(instance_id, dag_id); @@ -474,6 +509,9 @@ rpl_alloc_instance(uint8_t instance_id) instance->instance_id = instance_id; instance->def_route = NULL; instance->used = 1; +#if RPL_WITH_PROBING + rpl_schedule_probing(instance); +#endif /* RPL_WITH_PROBING */ return instance; } } @@ -507,7 +545,6 @@ rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id) } RPL_STAT(rpl_stats.mem_overflows++); - rpl_free_instance(instance); return NULL; } /*---------------------------------------------------------------------------*/ @@ -517,6 +554,12 @@ rpl_set_default_instance(rpl_instance_t *instance) default_instance = instance; } /*---------------------------------------------------------------------------*/ +rpl_instance_t * +rpl_get_default_instance(void) +{ + return default_instance; +} +/*---------------------------------------------------------------------------*/ void rpl_free_instance(rpl_instance_t *instance) { @@ -534,6 +577,9 @@ rpl_free_instance(rpl_instance_t *instance) rpl_set_default_route(instance, NULL); +#if RPL_WITH_PROBING + ctimer_stop(&instance->probing_timer); +#endif /* RPL_WITH_PROBING */ ctimer_stop(&instance->dio_timer); ctimer_stop(&instance->dao_timer); ctimer_stop(&instance->dao_lifetime_timer); @@ -729,6 +775,9 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) rpl_schedule_dao(instance); } rpl_reset_dio_timer(instance); +#if DEBUG + rpl_print_neighbor_list(); +#endif } else if(best_dag->rank != old_rank) { PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n", (unsigned)old_rank, best_dag->rank); @@ -1329,7 +1378,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF(", rank %u, min_rank %u, ", instance->current_dag->rank, instance->current_dag->min_rank); PRINTF("parent rank %u, parent etx %u, link metric %u, instance etx %u\n", - p->rank, -1/*p->mc.obj.etx*/, p->link_metric, instance->mc.obj.etx); + p->rank, -1/*p->mc.obj.etx*/, rpl_get_nbr(p)->link_metric, instance->mc.obj.etx); /* We have allocated a candidate parent; process the DIO further. */ diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 1b41d05e1..1e3250e20 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -215,6 +215,7 @@ rpl_update_header_empty(void) } break; default: +#if RPL_INSERT_HBH_OPTION PRINTF("RPL: No hop-by-hop option found, creating it\n"); if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); @@ -223,6 +224,7 @@ rpl_update_header_empty(void) } set_rpl_opt(uip_ext_opt_offset); uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; +#endif return 0; } @@ -374,9 +376,11 @@ rpl_invert_header(void) void rpl_insert_header(void) { +#if RPL_INSERT_HBH_OPTION if(default_instance != NULL && !uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { rpl_update_header_empty(); } +#endif } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index c9890b706..66e311d51 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -466,8 +466,12 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - /* always request new DAO to refresh route */ - RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + if(uc_addr == NULL) { + /* Request new DAO to refresh route. We do not do this for unicast DIO + * in order to avoid DAO messages after a DIS-DIO update, + * or upon unicast DIO probing. */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + } /* reserved 2 bytes */ buffer[pos++] = 0; /* flags */ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index a9ca3f375..b49d71089 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -313,6 +313,7 @@ rpl_of_t *rpl_find_of(rpl_ocp_t); void rpl_schedule_dao(rpl_instance_t *); void rpl_schedule_dao_immediately(rpl_instance_t *); void rpl_cancel_dao(rpl_instance_t *instance); +void rpl_schedule_probing(rpl_instance_t *instance); void rpl_reset_dio_timer(rpl_instance_t *); void rpl_reset_periodic_timer(void); @@ -320,4 +321,7 @@ void rpl_reset_periodic_timer(void); /* Route poisoning. */ void rpl_poison_routes(rpl_dag_t *, rpl_parent_t *); + +rpl_instance_t *rpl_get_default_instance(void); + #endif /* RPL_PRIVATE_H */ diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index ea7bfe7f2..27fff0ddf 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -166,6 +166,10 @@ handle_dio_timer(void *ptr) } new_dio_interval(instance); } + +#if DEBUG + rpl_print_neighbor_list(); +#endif } /*---------------------------------------------------------------------------*/ void @@ -323,5 +327,97 @@ rpl_cancel_dao(rpl_instance_t *instance) ctimer_stop(&instance->dao_lifetime_timer); } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_PROBING +static rpl_parent_t * +get_probing_target(rpl_dag_t *dag) +{ + /* Returns the next probing target. The current implementation probes the current + * preferred parent if we have not updated its link for RPL_PROBING_EXPIRATION_TIME. + * Otherwise, it picks at random between: + * (1) selecting the best parent not updated for RPL_PROBING_EXPIRATION_TIME + * (2) selecting the least recently updated parent + */ + rpl_parent_t *p; + rpl_parent_t *probing_target = NULL; + rpl_rank_t probing_target_rank = INFINITE_RANK; + /* min_last_tx is the clock time RPL_PROBING_EXPIRATION_TIME in the past */ + clock_time_t min_last_tx = clock_time(); + min_last_tx = min_last_tx > 2 * RPL_PROBING_EXPIRATION_TIME + ? min_last_tx - RPL_PROBING_EXPIRATION_TIME : 1; + + if(dag == NULL || + dag->instance == NULL || + dag->preferred_parent == NULL) { + return NULL; + } + + /* Our preferred parent needs probing */ + if(dag->preferred_parent->last_tx_time < min_last_tx) { + probing_target = dag->preferred_parent; + } + + /* With 50% probability: probe best parent not updated for RPL_PROBING_EXPIRATION_TIME */ + if(probing_target == NULL && (random_rand() % 2) == 0) { + p = nbr_table_head(rpl_parents); + while(p != NULL) { + if(p->dag == dag && p->last_tx_time < min_last_tx) { + /* p is in our dag and needs probing */ + rpl_rank_t p_rank = dag->instance->of->calculate_rank(p, 0); + if(probing_target == NULL + || p_rank < probing_target_rank) { + probing_target = p; + probing_target_rank = p_rank; + } + } + p = nbr_table_next(rpl_parents, p); + } + } + + /* The default probing target is the least recently updated parent */ + if(probing_target == NULL) { + p = nbr_table_head(rpl_parents); + while(p != NULL) { + if(p->dag == dag) { + if(probing_target == NULL + || p->last_tx_time < probing_target->last_tx_time) { + probing_target = p; + } + } + p = nbr_table_next(rpl_parents, p); + } + } + + return probing_target; +} +/*---------------------------------------------------------------------------*/ +static void +handle_probing_timer(void *ptr) +{ + rpl_instance_t *instance = (rpl_instance_t *)ptr; + rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); + + /* Perform probing */ + if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) { + PRINTF("RPL: probing %3u\n", + nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]); + /* Send probe, e.g. unicast DIO or DIS */ + RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target)); + } + + /* Schedule next probing */ + rpl_schedule_probing(instance); + +#if DEBUG + rpl_print_neighbor_list(); +#endif +} +/*---------------------------------------------------------------------------*/ +void +rpl_schedule_probing(rpl_instance_t *instance) +{ + ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(), + handle_probing_timer, instance); +} +#endif /* RPL_WITH_PROBING */ /** @}*/ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index f92d5f5f8..db5230611 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -263,6 +263,7 @@ rpl_link_neighbor_callback(const linkaddr_t *addr, int status, int numtx) parent->flags |= RPL_PARENT_FLAG_UPDATED; if(instance->of->neighbor_link_callback != NULL) { instance->of->neighbor_link_callback(parent, status, numtx); + parent->last_tx_time = clock_time(); } } } diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 512c1a8f0..e6e385375 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -114,6 +114,7 @@ struct rpl_parent { rpl_metric_container_t mc; #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ rpl_rank_t rank; + clock_time_t last_tx_time; uint8_t dtsn; uint8_t flags; }; @@ -224,6 +225,9 @@ struct rpl_instance { uint16_t dio_totrecv; #endif /* RPL_CONF_STATS */ clock_time_t dio_next_delay; /* delay for completion of dio interval */ +#if RPL_WITH_PROBING + struct ctimer probing_timer; +#endif /* RPL_WITH_PROBING */ struct ctimer dio_timer; struct ctimer dao_timer; struct ctimer dao_lifetime_timer; @@ -251,6 +255,10 @@ rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr); uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr); void rpl_dag_init(void); uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent); +void rpl_print_neighbor_list(); + +/* Per-parent RPL information */ +NBR_TABLE_DECLARE(rpl_parents); /** * RPL modes diff --git a/core/sys/timer.c b/core/sys/timer.c index ea0710911..6fe64119b 100644 --- a/core/sys/timer.c +++ b/core/sys/timer.c @@ -76,8 +76,9 @@ timer_set(struct timer *t, clock_time_t interval) * function will cause the timer to be stable over time, unlike the * timer_restart() function. * - * \param t A pointer to the timer. + * \note Must not be executed before timer expired * + * \param t A pointer to the timer. * \sa timer_restart() */ void diff --git a/cpu/6502/ipconfig/ipconfig.c b/cpu/6502/ipconfig/ipconfig.c index d21994032..5452b735a 100644 --- a/cpu/6502/ipconfig/ipconfig.c +++ b/cpu/6502/ipconfig/ipconfig.c @@ -117,7 +117,7 @@ makestrings(void) makeaddr(&addr, gateway); #if WITH_DNS - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -245,7 +245,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); #if WITH_DNS - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Configured."); @@ -261,7 +261,7 @@ dhcpc_unconfigured(const struct dhcpc_state *s) uip_setnetmask(&nulladdr); uip_setdraddr(&nulladdr); #if WITH_DNS - resolv_conf(&nulladdr); + uip_nameserver_update(&nulladdr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Unconfigured."); diff --git a/cpu/6502/lib/config.c b/cpu/6502/lib/config.c index 08677a682..545c47116 100644 --- a/cpu/6502/lib/config.c +++ b/cpu/6502/lib/config.c @@ -105,7 +105,7 @@ config_read(char *filename) uip_setnetmask(&config.netmask); uip_setdraddr(&config.draddr); #if WITH_DNS - resolv_conf(&config.resolvaddr); + uip_nameserver_update(&config.resolvaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ return &config.ethernetcfg; diff --git a/cpu/6502/net/lan91c96.S b/cpu/6502/net/lan91c96.S index 0bfb4e35b..e94fdda7c 100644 --- a/cpu/6502/net/lan91c96.S +++ b/cpu/6502/net/lan91c96.S @@ -89,7 +89,7 @@ fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03 .byte fixup29-fixup28, fixup30-fixup29, fixup31-fixup30 .byte fixup32-fixup31, fixup33-fixup32, fixup34-fixup33 .byte fixup35-fixup34, fixup36-fixup35, fixup37-fixup36 - .byte fixup38-fixup37, fixup39-fixup38, fixup40-fixup39 + .byte fixup38-fixup37, fixup39-fixup38 fixups = * - fixup @@ -272,9 +272,7 @@ fixup22:lda ethdata bcs :++ ; Yes, skip packet - ; Remove and release RX packet from the FIFO - lda #%10000000 -fixup23:sta ethmmucr + jsr releasepacket ; No packet available lda #$00 @@ -285,7 +283,7 @@ fixup23:sta ethmmucr ; Read bytes into buffer : jsr adjustptr : -fixup24:lda ethdata +fixup23:lda ethdata sta (ptr),y iny bne :- @@ -294,8 +292,7 @@ fixup24:lda ethdata bpl :- ; Remove and release RX packet from the FIFO - lda #%10000000 -fixup25:sta ethmmucr + jsr releasepacket ; Return packet length lda len @@ -313,19 +310,19 @@ send: ; Allocate memory for TX txa ora #%00100000 -fixup26:sta ethmmucr +fixup24:sta ethmmucr ; 8 retries ldy #$08 ; Wait for allocation ready : -fixup27:lda ethist +fixup25:lda ethist and #%00001000 ; ALLOC INT bne :+ - ; Shouldn't we do something here to actively free memory, - ; maybe removing and releasing an RX packet from the FIFO ??? + ; No space avaliable, skip a received frame + jsr releasepacket ; And try again dey @@ -335,21 +332,21 @@ fixup27:lda ethist ; Acknowledge interrupt, is it necessary ??? : lda #%00001000 -fixup28:sta ethack +fixup26:sta ethack ; Set packet address -fixup29:lda etharr -fixup30:sta ethpnr +fixup27:lda etharr +fixup28:sta ethpnr lda #$00 ldx #%01000000 ; AUTO INCR. -fixup31:sta ethptr -fixup32:stx ethptr+1 +fixup29:sta ethptr +fixup30:stx ethptr+1 ; Status written by CSMA lda #$00 -fixup33:sta ethdata -fixup34:sta ethdata +fixup31:sta ethdata +fixup32:sta ethdata ; Check packet length parity: ; - Even packet length -> carry set -> add 6 bytes @@ -361,10 +358,10 @@ fixup34:sta ethdata ; The packet contains 3 extra words lda len adc #$05 ; Actually 5 or 6 depending on carry -fixup35:sta ethdata +fixup33:sta ethdata lda len+1 adc #$00 -fixup36:sta ethdata +fixup34:sta ethdata ; Send the packet ; --------------- @@ -372,7 +369,7 @@ fixup36:sta ethdata ; Write bytes from buffer jsr adjustptr : lda (ptr),y -fixup37:sta ethdata +fixup35:sta ethdata iny bne :- inc ptr+1 @@ -390,13 +387,13 @@ fixup37:sta ethdata ; No : lda #$00 -fixup38:sta ethdata ; Fill byte +fixup36:sta ethdata ; Fill byte : -fixup39:sta ethdata ; Control byte +fixup37:sta ethdata ; Control byte ; Add packet to FIFO lda #%11000000 ; ENQUEUE PACKET - transmit packet -fixup40:sta ethmmucr +fixup38:sta ethmmucr clc rts @@ -407,6 +404,14 @@ exit: ;--------------------------------------------------------------------- +releasepacket: + ; Remove and release RX packet from the FIFO + lda #%10000000 +fixup39:sta ethmmucr + rts + +;--------------------------------------------------------------------- + adjustptr: lda len ldx len+1 diff --git a/cpu/avr/radio/mac/sicslowmac.c b/cpu/avr/radio/mac/sicslowmac.c index 9a176277a..b836bcd3a 100644 --- a/cpu/avr/radio/mac/sicslowmac.c +++ b/cpu/avr/radio/mac/sicslowmac.c @@ -402,14 +402,18 @@ sicslowmac_dataRequest(void) frame_create_params_t params; frame_result_t result; +#if NETSTACK_CONF_WITH_RIME /* Save the msduHandle in a global variable. */ msduHandle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); +#endif /* Build the FCF. */ params.fcf.frameType = DATAFRAME; params.fcf.securityEnabled = false; params.fcf.framePending = false; +#if NETSTACK_CONF_WITH_RIME params.fcf.ackRequired = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); +#endif params.fcf.panIdCompression = false; /* Insert IEEE 802.15.4 (2003) version bit. */ diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index e4181868c..aee2f6d29 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -1073,8 +1073,10 @@ rf230_transmit(unsigned short payload_len) if (tx_result==RADIO_TX_OK) { RIMESTATS_ADD(lltx); +#if NETSTACK_CONF_WITH_RIME if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE)) RIMESTATS_ADD(ackrx); //ack was requested and received +#endif #if RF230_INSERTACK /* Not PAN broadcast to FFFF, and ACK was requested and received */ if (!((buffer[5]==0xff) && (buffer[6]==0xff)) && (buffer[0]&(1<<6))) diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h index 020c3250f..30de9a1e5 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.h +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -49,8 +49,8 @@ * */ -#ifndef RADIO_H -#define RADIO_H +#ifndef RF230BB_H_ +#define RF230BB_H_ /*============================ INCLUDE =======================================*/ #include #include @@ -225,6 +225,6 @@ uint8_t rf230_get_raw_rssi(void); #define rf230_rssi rf230_get_raw_rssi -#endif +#endif /* RF230BB_H_ */ /** @} */ /*EOF*/ diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index b172101d1..d4eafc93a 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -52,12 +52,20 @@ CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c +CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c USB_CORE_SOURCEFILES += usb-core.c cdc-acm.c USB_ARCH_SOURCEFILES += usb-arch.c usb-serial.c cdc-acm-descriptors.c +ifneq ($(TARGET_START_SOURCEFILES),) + CPU_START_SOURCEFILES = TARGET_START_SOURCEFILES +else + CPU_START_SOURCEFILES = startup-gcc.c +endif +CPU_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CPU_START_SOURCEFILES)}} + CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) CONTIKI_SOURCEFILES += $(USB_CORE_SOURCEFILES) $(USB_ARCH_SOURCEFILES) @@ -74,7 +82,7 @@ $(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) ### Compilation rules CUSTOM_RULE_LINK=1 -%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) +%.elf: $(CPU_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index b453f2aa3..c0abed38b 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -96,17 +96,17 @@ clock_init(void) REG(SYS_CTRL_RCGCGPT) |= SYS_CTRL_RCGCGPT_GPT0; /* Make sure GPT0 is off */ - REG(GPT_0_BASE | GPTIMER_CTL) = 0; + REG(GPT_0_BASE + GPTIMER_CTL) = 0; /* 16-bit */ - REG(GPT_0_BASE | GPTIMER_CFG) = 0x04; + REG(GPT_0_BASE + GPTIMER_CFG) = 0x04; /* One-Shot, Count Down, No Interrupts */ - REG(GPT_0_BASE | GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT; + REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT; /* Prescale by 16 (thus, value 15 in TAPR) */ - REG(GPT_0_BASE | GPTIMER_TAPR) = 0x0F; + REG(GPT_0_BASE + GPTIMER_TAPR) = 0x0F; } /*---------------------------------------------------------------------------*/ CCIF clock_time_t @@ -144,11 +144,11 @@ clock_wait(clock_time_t i) void clock_delay_usec(uint16_t dt) { - REG(GPT_0_BASE | GPTIMER_TAILR) = dt; - REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN; + REG(GPT_0_BASE + GPTIMER_TAILR) = dt; + REG(GPT_0_BASE + GPTIMER_CTL) |= GPTIMER_CTL_TAEN; /* One-Shot mode: TAEN will be cleared when the timer reaches 0 */ - while(REG(GPT_0_BASE | GPTIMER_CTL) & GPTIMER_CTL_TAEN); + while(REG(GPT_0_BASE + GPTIMER_CTL) & GPTIMER_CTL_TAEN); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index e8ec81309..58b464fc5 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -80,7 +80,6 @@ /* Local RF Flags */ #define RX_ACTIVE 0x80 #define RF_MUST_RESET 0x40 -#define WAS_OFF 0x10 #define RF_ON 0x01 /* Bit Masks for the last byte in the RX FIFO */ @@ -180,6 +179,8 @@ get_channel() static int8_t set_channel(uint8_t channel) { + uint8_t was_on = 0; + PRINTF("RF: Set Channel\n"); if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) { @@ -189,16 +190,14 @@ set_channel(uint8_t channel) /* Changes to FREQCTRL take effect after the next recalibration */ /* If we are off, save state, otherwise switch off and save state */ - if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; - } else { - rf_flags &= ~WAS_OFF; + if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) != 0) { + was_on = 1; off(); } REG(RFCORE_XREG_FREQCTRL) = (CC2538_RF_CHANNEL_MIN + (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING); /* switch radio back on only if radio was on before - otherwise will turn on radio foor sleepy nodes */ - if((rf_flags & WAS_OFF) != WAS_OFF) { + if(was_on) { on(); } @@ -244,10 +243,11 @@ static radio_value_t get_rssi(void) { int8_t rssi; + uint8_t was_off = 0; /* If we are off, turn on first */ if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; + was_off = 1; on(); } @@ -257,8 +257,7 @@ get_rssi(void) rssi = (int8_t)(REG(RFCORE_XREG_RSSI) & RFCORE_XREG_RSSI_RSSI_VAL) - RSSI_OFFSET; /* If we were off, turn back off */ - if((rf_flags & WAS_OFF) == WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } @@ -345,12 +344,13 @@ static int channel_clear(void) { int cca; + uint8_t was_off = 0; PRINTF("RF: CCA\n"); /* If we are off, turn on first */ if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; + was_off = 1; on(); } @@ -364,8 +364,7 @@ channel_clear(void) } /* If we were off, turn back off */ - if((rf_flags & WAS_OFF) == WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } @@ -561,13 +560,14 @@ transmit(unsigned short transmit_len) uint8_t counter; int ret = RADIO_TX_ERR; rtimer_clock_t t0; + uint8_t was_off = 0; PRINTF("RF: Transmit\n"); if(!(rf_flags & RX_ACTIVE)) { t0 = RTIMER_NOW(); on(); - rf_flags |= WAS_OFF; + was_off = 1; while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); } @@ -609,8 +609,7 @@ transmit(unsigned short transmit_len) ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - if(rf_flags & WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } diff --git a/cpu/cc2538/dev/cc2538-sensors.h b/cpu/cc2538/dev/cc2538-sensors.h new file mode 100644 index 000000000..b4d3ada91 --- /dev/null +++ b/cpu/cc2538/dev/cc2538-sensors.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-sensors CC2538 Built-In Sensors + * + * Module controlling sensors on the CC2538 SoC (Tmp and VDD3) + * @{ + * + * \file + * Generic header usable by all CC2538 sensor drivers + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC2538_SENSORS_H_ +#define CC2538_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +#include "dev/cc2538-temp-sensor.h" +#include "dev/vdd3-sensor.h" +/*---------------------------------------------------------------------------*/ +/** + * \name CC2538 sensor constants + * + * These constants are used by various sensors on the CC2538. They can be used + * to differentiate between raw and converted readings, to configure ADC + * decimation rate (where applicable). + * @{ + */ +#define CC2538_SENSORS_VALUE_TYPE_RAW 0 /**< Request the raw reading */ +#define CC2538_SENSORS_VALUE_TYPE_CONVERTED 1 /**< Request the converted reading */ + +#define CC2538_SENSORS_ERROR 0x80000000 /**< Generic Error */ +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC2538_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/cc2538-temp-sensor.c b/cpu/cc2538/dev/cc2538-temp-sensor.c new file mode 100644 index 000000000..dd5dcba6c --- /dev/null +++ b/cpu/cc2538/dev/cc2538-temp-sensor.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-temp-sensor + * @{ + * + * \file + * Driver for the CC2538 On-Chip temperature sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/adc.h" +#include "dev/cc2538-sensors.h" + +#include +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int raw = adc_get(SOC_ADC_ADCCON_CH_TEMP, SOC_ADC_ADCCON_REF_INT, + SOC_ADC_ADCCON_DIV_512); + + if(type == CC2538_SENSORS_VALUE_TYPE_RAW) { + return raw; + } else if(type == CC2538_SENSORS_VALUE_TYPE_CONVERTED) { + return 25000 + ((raw >> 4) - 1422) * 10000 / 42; + } + + return CC2538_SENSORS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(cc2538_temp_sensor, TEMP_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.h b/cpu/cc2538/dev/cc2538-temp-sensor.h similarity index 54% rename from platform/srf06-cc26xx/sensortag/sht-21-sensor.h rename to cpu/cc2538/dev/cc2538-temp-sensor.h index af2f5d401..b515c5042 100644 --- a/platform/srf06-cc26xx/sensortag/sht-21-sensor.h +++ b/cpu/cc2538/dev/cc2538-temp-sensor.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,6 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. @@ -29,55 +31,39 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup cc2538-sensors * @{ * - * \defgroup sensortag-cc26xx-sht-sensor SensorTag 2.0 Humidity Sensor + * \defgroup cc2538-temp-sensor CC2538 on-chip temperature Sensor * - * Due to the time required between triggering a reading and the reading - * becoming available, this driver is meant to be used in an asynchronous - * fashion. The caller must first activate the sensor by calling - * SENSORS_ACTIVATE(). This will trigger a cycle which will read both - * temperature and humidity, but the call will not wait for the cycle to - * complete so that the CPU can perform other tasks or drop to a low power - * mode. + * Driver for the CC2538 on-chip temperature sensor * - * Once readings are available, the driver will generate a sensors_changed - * event. - * - * Calls to .status() will return the driver's state which could indicate that - * a measurement is in progress (different return values for each) or that - * readings are ready. - * - * Multiple calls to value() will simply return the reading that was latched - * after the last cycle. In order to obtain fresh readings, a new cycle must be - * started by a new call to SENSORS_ACTIVATE. + * This driver can return the raw as well as the converted value of the sensor + * reading. This is controlled by the type argument of the sensor driver's + * value() function. The choices for the type argument are: + * - CC2538_SENSORS_VALUE_TYPE_RAW (value() returns the raw reading) + * - CC2538_SENSORS_VALUE_TYPE_CONVERTED (value() returns degrees mC) * @{ * * \file - * Header file for the Sensortag-CC26ss Sensirion SHT21 Humidity sensor + * Header file for the CC2538 on-chip temperature Sensor Driver */ /*---------------------------------------------------------------------------*/ -#ifndef SHT_21_SENSOR_H_ -#define SHT_21_SENSOR_H_ +#ifndef CC2538_TEMP_SENSOR_H_ +#define CC2538_TEMP_SENSOR_H_ /*---------------------------------------------------------------------------*/ -#define SHT_21_SENSOR_TYPE_TEMP 1 -#define SHT_21_SENSOR_TYPE_HUMIDITY 2 +#include "lib/sensors.h" /*---------------------------------------------------------------------------*/ /** - * \name SHT21 driver states + * \name temperature sensor * @{ */ -#define SHT_21_SENSOR_STATUS_DISABLED 0 /**< Not initialised */ -#define SHT_21_SENSOR_STATUS_INITIALISED 1 /**< Initialised but idle */ -#define SHT_21_SENSOR_STATUS_READING_TEMP 2 /**< Temp reading in progress */ -#define SHT_21_SENSOR_STATUS_READING_HUMIDITY 3 /**< Humidity reading in progress */ -#define SHT_21_SENSOR_STATUS_READINGS_READY 4 /**< Both readings ready */ +#define TEMP_SENSOR "On-Chip Temperature" /** @} */ /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor sht_21_sensor; +extern const struct sensors_sensor cc2538_temp_sensor; /*---------------------------------------------------------------------------*/ -#endif /* SHT_21_SENSOR_H_ */ +#endif /* CC2538_TEMP_SENSOR_H_ */ /*---------------------------------------------------------------------------*/ /** * @} diff --git a/cpu/cc2538/dev/gpio.c b/cpu/cc2538/dev/gpio.c index 2961a2eb0..eb561c757 100644 --- a/cpu/cc2538/dev/gpio.c +++ b/cpu/cc2538/dev/gpio.c @@ -79,69 +79,41 @@ notify(uint8_t mask, uint8_t port) } } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port A */ -void -gpio_port_a_isr() +/** \brief Interrupt service routine for Port \a port + * \param port Number between 0 and 3. Port A: 0, Port B: 1, etc. + */ +static void +gpio_port_isr(uint8_t port) { + uint32_t base; + uint8_t int_status, power_up_int_status; + lpm_exit(); ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_A_BASE | GPIO_MIS), GPIO_A_NUM); + base = GPIO_PORT_TO_BASE(port); + int_status = GPIO_GET_MASKED_INT_STATUS(base); + power_up_int_status = GPIO_GET_POWER_UP_INT_STATUS(port); - GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_A_NUM, 0xFF); + notify(int_status | power_up_int_status, port); + + GPIO_CLEAR_INTERRUPT(base, int_status); + GPIO_CLEAR_POWER_UP_INTERRUPT(port, power_up_int_status); ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port B */ -void -gpio_port_b_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_B_BASE | GPIO_MIS), GPIO_B_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_B_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port C */ -void -gpio_port_c_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_C_BASE | GPIO_MIS), GPIO_C_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_C_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port D */ -void -gpio_port_d_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_D_BASE | GPIO_MIS), GPIO_D_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_D_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); +#define GPIO_PORT_ISR(lowercase_port, uppercase_port) \ +void \ +gpio_port_##lowercase_port##_isr(void) \ +{ \ + gpio_port_isr(GPIO_##uppercase_port##_NUM); \ } +GPIO_PORT_ISR(a, A) +GPIO_PORT_ISR(b, B) +GPIO_PORT_ISR(c, C) +GPIO_PORT_ISR(d, D) /*---------------------------------------------------------------------------*/ void gpio_init() diff --git a/cpu/cc2538/dev/gpio.h b/cpu/cc2538/dev/gpio.h index 3f93633a1..e97ba2825 100644 --- a/cpu/cc2538/dev/gpio.h +++ b/cpu/cc2538/dev/gpio.h @@ -91,28 +91,28 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_INPUT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_DIR) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_DIR) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to output. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_DIR) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE high. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_PIN(PORT_BASE, PIN_MASK) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = 0xFF; } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = 0xFF; } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE low. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLR_PIN(PORT_BASE, PIN_MASK) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = 0x00; } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = 0x00; } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to value. * \param PORT_BASE GPIO Port register offset @@ -133,7 +133,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * and then use 0x0A as the value ((1 << 3) | (1 << 1) for pins 3 and 1) */ #define GPIO_WRITE_PIN(PORT_BASE, PIN_MASK, value) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = (value); } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = (value); } while(0) /** \brief Read pins with PIN_MASK of port with PORT_BASE. * \param PORT_BASE GPIO Port register offset @@ -146,21 +146,21 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * the macro will return 0x81. */ #define GPIO_READ_PIN(PORT_BASE, PIN_MASK) \ - REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) + REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) /** \brief Set pins with PIN_MASK of port with PORT_BASE to detect edge. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IS) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IS) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to detect level. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_LEVEL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IS) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IS) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on both edges. @@ -168,7 +168,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_TRIGGER_BOTH_EDGES(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IBE) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IBE) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on single edge (controlled by GPIO_IEV). @@ -176,7 +176,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IBE) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IBE) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on rising edge. @@ -184,7 +184,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IEV) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IEV) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on falling edge. @@ -192,7 +192,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_FALLING(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IEV) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IEV) &= ~(PIN_MASK); } while(0) /** \brief Enable interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -200,7 +200,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IE) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IE) |= (PIN_MASK); } while(0) /** \brief Disable interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -208,7 +208,32 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IE) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IE) &= ~(PIN_MASK); } while(0) + +/** \brief Get raw interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the raw interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of the interrupts + * trigger conditions detected (raw, before interrupt masking), indicating that + * all the requirements are met, before they are finally allowed to trigger by + * the interrupt mask. The bits cleared indicate that corresponding input pins + * have not initiated an interrupt. + */ +#define GPIO_GET_RAW_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_RIS) + +/** \brief Get masked interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the masked interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of input lines + * triggering an interrupt. The bits cleared indicate that either no interrupt + * has been generated, or the interrupt is masked. This is the state of the + * interrupt after interrupt masking. + */ +#define GPIO_GET_MASKED_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_MIS) /** \brief Clear interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -216,7 +241,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLEAR_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IC) = (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IC) = (PIN_MASK); } while(0) /** \brief Configure the pin to be under peripheral control with PIN_MASK of * port with PORT_BASE. @@ -224,7 +249,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_PERIPHERAL_CONTROL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_AFSEL) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_AFSEL) |= (PIN_MASK); } while(0) /** \brief Configure the pin to be software controlled with PIN_MASK of port * with PORT_BASE. @@ -232,7 +257,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_AFSEL) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_AFSEL) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port PORT to trigger a power-up interrupt * on rising edge. @@ -240,7 +265,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_POWER_UP_ON_RISING(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_P_EDGE_CTRL) &= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_P_EDGE_CTRL) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) /** \brief Set pins with PIN_MASK of port PORT to trigger a power-up interrupt @@ -249,7 +274,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_POWER_UP_ON_FALLING(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_P_EDGE_CTRL) |= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_P_EDGE_CTRL) |= \ (PIN_MASK) << ((PORT) << 3); } while(0) /** \brief Enable power-up interrupt triggering for pins with PIN_MASK of port @@ -258,7 +283,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_ENABLE_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_PI_IEN) |= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) |= \ (PIN_MASK) << ((PORT) << 3); } while(0) /** \brief Disable power-up interrupt triggering for pins with PIN_MASK of port @@ -267,16 +292,24 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DISABLE_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_PI_IEN) &= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) +/** \brief Get power-up interrupt status of port PORT. + * \param PORT GPIO Port (not port base address) + * \return Bit-mask reflecting the power-up interrupt status of all the port + * pins + */ +#define GPIO_GET_POWER_UP_INT_STATUS(PORT) \ + ((REG(GPIO_PORT_TO_BASE(PORT) + GPIO_IRQ_DETECT_ACK) >> ((PORT) << 3)) & 0xFF) + /** \brief Clear power-up interrupt triggering for pins with PIN_MASK of port * PORT. * \param PORT GPIO Port (not port base address) * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLEAR_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_IRQ_DETECT_ACK) = \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_IRQ_DETECT_ACK) = \ (PIN_MASK) << ((PORT) << 3); } while(0) /** diff --git a/cpu/cc2538/dev/i2c.c b/cpu/cc2538/dev/i2c.c new file mode 100644 index 000000000..a4683bdc5 --- /dev/null +++ b/cpu/cc2538/dev/i2c.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2015, Mehdi Migault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-i2c cc2538 I2C Control + * @{ + * + * \file + * Implementation file of the I2C Control module + * + * \author + * Mehdi Migault + */ + +#include "i2c.h" + +#include +#include "clock.h" +/*---------------------------------------------------------------------------*/ +/* Additional functions */ +static uint32_t +get_sys_clock(void) +{ + /* Get the clock status diviser */ + return SYS_CTRL_32MHZ / + (1 << (REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYS_DIV)); +} +/*---------------------------------------------------------------------------*/ +void +i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, + uint32_t bus_speed) +{ + /* Enable I2C clock in different modes */ + REG(SYS_CTRL_RCGCI2C) |= 1; /* Run mode */ + + /* Reset I2C peripheral */ + REG(SYS_CTRL_SRI2C) |= 1; /* Reset position */ + + /* Delay for a little bit */ + clock_delay_usec(50); + + REG(SYS_CTRL_SRI2C) &= ~1; /* Normal position */ + + /* Set pins in input */ + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_sda), GPIO_PIN_MASK(pin_sda)); + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_scl), GPIO_PIN_MASK(pin_scl)); + + /* Set peripheral control for the pins */ + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(port_sda), GPIO_PIN_MASK(pin_sda)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(port_scl), GPIO_PIN_MASK(pin_scl)); + + /* Set the pad to no drive type */ + ioc_set_over(port_sda, pin_sda, IOC_OVERRIDE_DIS); + ioc_set_over(port_scl, pin_scl, IOC_OVERRIDE_DIS); + + /* Set pins as peripheral inputs */ + REG(IOC_I2CMSSDA) = ioc_input_sel(port_sda, pin_sda); + REG(IOC_I2CMSSCL) = ioc_input_sel(port_scl, pin_scl); + + /* Set pins as peripheral outputs */ + ioc_set_sel(port_sda, pin_sda, IOC_PXX_SEL_I2C_CMSSDA); + ioc_set_sel(port_scl, pin_scl, IOC_PXX_SEL_I2C_CMSSCL); + + /* Enable the I2C master module */ + i2c_master_enable(); + + /* t the master clock frequency */ + i2c_set_frequency(bus_speed); +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_enable(void) +{ + REG(I2CM_CR) |= 0x10; /* Set MFE bit */ +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_disable(void) +{ + REG(I2CM_CR) &= ~0x10; /* Reset MFE bit */ +} +/*---------------------------------------------------------------------------*/ +void +i2c_set_frequency(uint32_t freq) +{ + /* Peripheral clock setting, using the system clock */ + REG(I2CM_TPR) = ((get_sys_clock() + (2 * 10 * freq) - 1) / + (2 * 10 * freq)) - 1; +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode) +{ + if(access_mode) { + REG(I2CM_SA) = ((slave_addr << 1) | 1); + } else { + REG(I2CM_SA) = (slave_addr << 1); + } +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_data_put(uint8_t data) +{ + REG(I2CM_DR) = data; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_data_get(void) +{ + return REG(I2CM_DR); +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_command(uint8_t cmd) +{ + REG(I2CM_CTRL) = cmd; + /* Here we need a delay, otherwise the I2C module keep the receiver mode */ + clock_delay_usec(1); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_busy(void) +{ + return REG(I2CM_STAT) & I2CM_STAT_BUSY; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_error(void) +{ + uint8_t temp = REG(I2CM_STAT); /* Get all status */ + if(temp & I2CM_STAT_BUSY) { /* No valid if BUSY bit is set */ + return I2C_MASTER_ERR_NONE; + } else if(temp & (I2CM_STAT_ERROR | I2CM_STAT_ARBLST)) { + return temp; /* Compare later */ + } + return I2C_MASTER_ERR_NONE; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_single_send(uint8_t slave_addr, uint8_t data) +{ + i2c_master_set_slave_address(slave_addr, I2C_SEND); + i2c_master_data_put(data); + i2c_master_command(I2C_MASTER_CMD_SINGLE_SEND); + + while(i2c_master_busy()); + + /* Return the STAT register of I2C module if error occured, I2C_MASTER_ERR_NONE otherwise */ + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_single_receive(uint8_t slave_addr, uint8_t *data) +{ + uint32_t temp; + + i2c_master_set_slave_address(slave_addr, I2C_RECEIVE); + i2c_master_command(I2C_MASTER_CMD_SINGLE_RECEIVE); + + while(i2c_master_busy()); + temp = i2c_master_error(); + if(temp == I2C_MASTER_ERR_NONE) { + *data = i2c_master_data_get(); + } + return temp; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len) +{ + uint8_t sent; + if((len == 0) || (data == NULL)) { + return I2CM_STAT_INVALID; + } + if(len == 1) { + return i2c_single_send(slave_addr, data[0]); + } + i2c_master_set_slave_address(slave_addr, I2C_SEND); + i2c_master_data_put(data[0]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_START); + while(i2c_master_busy()); + if(i2c_master_error() == I2C_MASTER_ERR_NONE) { + for(sent = 1; sent <= (len - 2); sent++) { + i2c_master_data_put(data[sent]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_CONT); + while(i2c_master_busy()); + } + /* This should be the last byte, stop sending */ + i2c_master_data_put(data[len - 1]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_FINISH); + while(i2c_master_busy()); + } + + /* Return the STAT register of I2C module if error occurred, I2C_MASTER_ERR_NONE otherwise */ + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len) +{ + uint8_t recv = 0; + if((len == 0) || data == NULL) { + return I2CM_STAT_INVALID; + } + if(len == 1) { + return i2c_single_receive(slave_addr, &data[0]); + } + i2c_master_set_slave_address(slave_addr, I2C_RECEIVE); + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_START); + while(i2c_master_busy()); + if(i2c_master_error() == I2C_MASTER_ERR_NONE) { + data[0] = i2c_master_data_get(); + /* If we got 2 or more bytes pending to be received, keep going*/ + for(recv = 1; recv <= (len - 2); recv++) { + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_CONT); + while(i2c_master_busy()); + data[recv] = i2c_master_data_get(); + } + /* This should be the last byte, stop receiving */ + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + while(i2c_master_busy()); + data[len - 1] = i2c_master_data_get(); + } + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc2538/dev/i2c.h b/cpu/cc2538/dev/i2c.h new file mode 100644 index 000000000..6ec606167 --- /dev/null +++ b/cpu/cc2538/dev/i2c.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, Mehdi Migault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-i2c cc2538 I2C Control + * + * cc2538 I2C Control Module + * @{ + * + * \file + * Header file with declarations for the I2C Control module + * + * \author + * Mehdi Migault + */ +#ifndef I2C_H_ +#define I2C_H_ + +#include "reg.h" +#include "sys-ctrl.h" +#include "gpio.h" +#include "ioc.h" +#include /* For debug */ +#include "clock.h" /* For temporisation */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Master commands + * @{ + */ +#define I2C_MASTER_CMD_SINGLE_SEND 0x00000007 +#define I2C_MASTER_CMD_SINGLE_RECEIVE 0x00000007 +#define I2C_MASTER_CMD_BURST_SEND_START 0x00000003 +#define I2C_MASTER_CMD_BURST_SEND_CONT 0x00000001 +#define I2C_MASTER_CMD_BURST_SEND_FINISH 0x00000005 +#define I2C_MASTER_CMD_BURST_SEND_ERROR_STOP 0x00000004 +#define I2C_MASTER_CMD_BURST_RECEIVE_START 0x0000000b +#define I2C_MASTER_CMD_BURST_RECEIVE_CONT 0x00000009 +#define I2C_MASTER_CMD_BURST_RECEIVE_FINISH 0x00000005 +#define I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP 0x00000004 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Master status flags + * @{ + */ +#define I2C_MASTER_ERR_NONE 0 +#define I2CM_STAT_BUSY 0x00000001 +#define I2CM_STAT_ERROR 0x00000002 +#define I2CM_STAT_ADRACK 0x00000004 +#define I2CM_STAT_DATACK 0x00000008 +#define I2CM_STAT_ARBLST 0x00000010 +#define I2CM_STAT_IDLE 0x00000020 +#define I2CM_STAT_BUSBSY 0x00000040 +#define I2CM_STAT_INVALID 0x00000080 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C registers + * @{ + */ +#define I2CM_CR 0x40020020 /* I2C master config */ +#define I2CM_TPR 0x4002000C /* I2C master timer period */ +#define I2CM_SA 0x40020000 /* I2C master slave address */ +#define I2CM_DR 0x40020008 /* I2C master data */ +#define I2CM_CTRL 0x40020004 /* Master control in write */ +#define I2CM_STAT I2CM_CTRL /* Master status in read */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Miscellaneous + * @{ + */ +#define I2C_SCL_NORMAL_BUS_SPEED 100000 /* 100KHz I2C */ +#define I2C_SCL_FAST_BUS_SPEED 400000 /* 400KHz I2C */ +#define I2C_RECEIVE 0x01 /* Master receive */ +#define I2C_SEND 0x00 /* Master send */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name I2C Functions + * @{ + */ + +/** + * \brief Initialize the I2C peripheral and pins + * \param port_sda The GPIO number of the pin used fort SDA + * \param pin_sda The pin number used for SDA + * \param port_scl The GPIO number of the pin used fort SCL + * \param pin_scl The pin number used for SCL + * \param bus_speed The clock frequency used by I2C module + * + * \e bus_speed can take the following values: + * + * - I2C_SCL_NORMAL_BUS_SPEED : 100KHz + * - I2C_SCL_FAST_BUS_SPEED : 400KHz + */ +void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, + uint8_t pin_scl, uint32_t bus_speed); + +/** \brief Enable master I2C module */ +void i2c_master_enable(void); + +/** \brief Disable master I2C module */ +void i2c_master_disable(void); + +/** + * \brief Initialize I2C peripheral clock with given frequency + * \param freq The desired frequency + * + * \e freq can take the following values: + * + * - I2C_SCL_NORMAL_BUS_SPEED : 100KHz + * - I2C_SCL_FAST_BUS_SPEED : 400KHz + */ +void i2c_set_frequency(uint32_t freq); + +/** + * \brief Set the address of slave and access mode for the next I2C communication + * \param slave_addr The receiver slave address on 7 bits + * \param access_mode The I2C access mode (send/receive) + * + * \e access_mode can take the following values: + * + * - I2C_RECEIVE : 1 + * - I2C_SEND : 0 + */ +void i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode); + +/** + * \brief Prepare data to be transmitted + * \param data The byte of data to be transmitted from the I2C master + */ +void i2c_master_data_put(uint8_t data); + +/** + * \brief Return received data from I2C + * \return The byte received by I2C after à receive command + */ +uint8_t i2c_master_data_get(void); + +/** + * \brief Control the state of the master module for send and receive operations + * \param cmd The operation to perform + * + * \e cmd can take the following values: + * + * - I2C_MASTER_CMD_SINGLE_SEND + * - I2C_MASTER_CMD_SINGLE_RECEIVE + * - I2C_MASTER_CMD_BURST_SEND_START + * - I2C_MASTER_CMD_BURST_SEND_CONT + * - I2C_MASTER_CMD_BURST_SEND_FINISH + * - I2C_MASTER_CMD_BURST_SEND_ERROR_STOP + * - I2C_MASTER_CMD_BURST_RECEIVE_START + * - I2C_MASTER_CMD_BURST_RECEIVE_CONT + * - I2C_MASTER_CMD_BURST_RECEIVE_FINISH + * - I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP + */ +void i2c_master_command(uint8_t cmd); + +/** + * \brief Return the busy state of I2C module + * \retval 0 The I2C module is not busy + * \retval 1 The I2C module is busy + */ +uint8_t i2c_master_busy(void); + +/** + * \brief Return the status register if error occurred during last communication + * \retval I2C_MASTER_ERR_NONE Return 0 if no error occurred + * + * If an error occurred, return the status register of the I2C module. + * Use the result with the I2CM_STAT_* flags to custom your processing + */ +uint8_t i2c_master_error(void); +/** + * \brief Perform all operations to send a byte to a slave + * \param slave_addr The adress of the slave to which data are sent + * \param data The data to send to the slave + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data); + +/** + * \brief Perform all operations to receive a byte from a slave + * \param slave_addr The address of the slave from which data are received + * \param data A pointer to store the received data + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data); +/** + * \brief Perform all operations to send multiple bytes to a slave + * \param slave_addr The address of the slave to which data are sent + * \param data A pointer to the data to send to the slave + * \param len Number of bytes to send + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len); + +/** + * \brief Perform all operations to receive multiple bytes from a slave + * \param slave_addr The address of the slave from which data are received + * \param data A pointer to store the received data + * \param len Number of bytes to receive + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len); +/** @} */ + +#endif /* I2C_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/nvic.c b/cpu/cc2538/dev/nvic.c index 8e2e991ab..86e97c093 100644 --- a/cpu/cc2538/dev/nvic.c +++ b/cpu/cc2538/dev/nvic.c @@ -57,7 +57,7 @@ nvic_init() interrupt_unpend = (uint32_t *)NVIC_UNPEND0; /* Provide our interrupt table to the NVIC */ - REG(SCB_VTABLE) = (NVIC_CONF_VTABLE_BASE | NVIC_CONF_VTABLE_OFFSET); + REG(SCB_VTABLE) = (NVIC_CONF_VTABLE_BASE + NVIC_CONF_VTABLE_OFFSET); } /*---------------------------------------------------------------------------*/ void diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index bf5e16b8c..ea6a6a57a 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -206,22 +206,22 @@ reset(uint32_t uart_base) uint32_t lchr; /* Make sure the UART is disabled before trying to configure it */ - REG(uart_base | UART_CTL) = UART_CTL_VALUE; + REG(uart_base + UART_CTL) = UART_CTL_VALUE; /* Clear error status */ - REG(uart_base | UART_ECR) = 0xFF; + REG(uart_base + UART_ECR) = 0xFF; /* Store LCHR configuration */ - lchr = REG(uart_base | UART_LCRH); + lchr = REG(uart_base + UART_LCRH); /* Flush FIFOs by clearing LCHR.FEN */ - REG(uart_base | UART_LCRH) = 0; + REG(uart_base + UART_LCRH) = 0; /* Restore LCHR configuration */ - REG(uart_base | UART_LCRH) = lchr; + REG(uart_base + UART_LCRH) = lchr; /* UART Enable */ - REG(uart_base | UART_CTL) |= UART_CTL_UARTEN; + REG(uart_base + UART_CTL) |= UART_CTL_UARTEN; } /*---------------------------------------------------------------------------*/ static bool @@ -232,7 +232,7 @@ permit_pm1(void) for(regs = &uart_regs[0]; regs < &uart_regs[UART_INSTANCE_COUNT]; regs++) { /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ if((REG(SYS_CTRL_RCGCUART) & regs->sys_ctrl_rcgcuart_uart) != 0 && - (REG(regs->base | UART_FR) & UART_FR_TXFE) == 0) { + (REG(regs->base + UART_FR) & UART_FR_TXFE) == 0) { return false; } } @@ -261,7 +261,7 @@ uart_init(uint8_t uart) REG(SYS_CTRL_DCGCUART) |= regs->sys_ctrl_dcgcuart_uart; /* Run on SYS_DIV */ - REG(regs->base | UART_CC) = 0; + REG(regs->base + UART_CC) = 0; /* * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register @@ -292,21 +292,21 @@ uart_init(uint8_t uart) * Acknowledge RX and RX Timeout * Acknowledge Framing, Overrun and Break Errors */ - REG(regs->base | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; - REG(regs->base | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; + REG(regs->base + UART_IM) = UART_IM_RXIM | UART_IM_RTIM; + REG(regs->base + UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; - REG(regs->base | UART_IFLS) = + REG(regs->base + UART_IFLS) = UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2; /* Make sure the UART is disabled before trying to configure it */ - REG(regs->base | UART_CTL) = UART_CTL_VALUE; + REG(regs->base + UART_CTL) = UART_CTL_VALUE; /* Baud Rate Generation */ - REG(regs->base | UART_IBRD) = regs->ibrd; - REG(regs->base | UART_FBRD) = regs->fbrd; + REG(regs->base + UART_IBRD) = regs->ibrd; + REG(regs->base + UART_FBRD) = regs->fbrd; /* UART Control: 8N1 with FIFOs */ - REG(regs->base | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; + REG(regs->base + UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; /* * Enable hardware flow control (RTS/CTS) if requested. @@ -316,18 +316,18 @@ uart_init(uint8_t uart) REG(IOC_UARTCTS_UART1) = ioc_input_sel(regs->cts.port, regs->cts.pin); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->cts.port), GPIO_PIN_MASK(regs->cts.pin)); ioc_set_over(regs->cts.port, regs->cts.pin, IOC_OVERRIDE_DIS); - REG(UART_1_BASE | UART_CTL) |= UART_CTL_CTSEN; + REG(UART_1_BASE + UART_CTL) |= UART_CTL_CTSEN; } if(regs->rts.port >= 0) { ioc_set_sel(regs->rts.port, regs->rts.pin, IOC_PXX_SEL_UART1_RTS); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rts.port), GPIO_PIN_MASK(regs->rts.pin)); ioc_set_over(regs->rts.port, regs->rts.pin, IOC_OVERRIDE_OE); - REG(UART_1_BASE | UART_CTL) |= UART_CTL_RTSEN; + REG(UART_1_BASE + UART_CTL) |= UART_CTL_RTSEN; } /* UART Enable */ - REG(regs->base | UART_CTL) |= UART_CTL_UARTEN; + REG(regs->base + UART_CTL) |= UART_CTL_UARTEN; /* Enable UART0 Interrupts */ nvic_interrupt_enable(regs->nvic_int); @@ -354,9 +354,9 @@ uart_write_byte(uint8_t uart, uint8_t b) uart_base = uart_regs[uart].base; /* Block if the TX FIFO is full */ - while(REG(uart_base | UART_FR) & UART_FR_TXFF); + while(REG(uart_base + UART_FR) & UART_FR_TXFF); - REG(uart_base | UART_DR) = b; + REG(uart_base + UART_DR) = b; } /*---------------------------------------------------------------------------*/ void @@ -371,18 +371,18 @@ uart_isr(uint8_t uart) /* Store the current MIS and clear all flags early, except the RTM flag. * This will clear itself when we read out the entire FIFO contents */ - mis = REG(uart_base | UART_MIS) & 0x0000FFFF; + mis = REG(uart_base + UART_MIS) & 0x0000FFFF; - REG(uart_base | UART_ICR) = 0x0000FFBF; + REG(uart_base + UART_ICR) = 0x0000FFBF; if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) { - while(!(REG(uart_base | UART_FR) & UART_FR_RXFE)) { + while(!(REG(uart_base + UART_FR) & UART_FR_RXFE)) { if(input_handler[uart] != NULL) { - input_handler[uart]((unsigned char)(REG(uart_base | UART_DR) & 0xFF)); + input_handler[uart]((unsigned char)(REG(uart_base + UART_DR) & 0xFF)); } else { /* To prevent an Overrun Error, we need to flush the FIFO even if we * don't have an input_handler. Use mis as a data trash can */ - mis = REG(uart_base | UART_DR); + mis = REG(uart_base + UART_DR); } } } else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) { diff --git a/cpu/cc2538/dev/vdd3-sensor.c b/cpu/cc2538/dev/vdd3-sensor.c new file mode 100644 index 000000000..678c25b8e --- /dev/null +++ b/cpu/cc2538/dev/vdd3-sensor.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-vdd3-sensor + * @{ + * + * \file + * Driver for the CC2538 VDD3 sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/vdd3-sensor.h" +#include "dev/adc.h" +#include "dev/cc2538-sensors.h" + +#include +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int raw = adc_get(SOC_ADC_ADCCON_CH_VDD_3, SOC_ADC_ADCCON_REF_INT, + SOC_ADC_ADCCON_DIV_512); + + if(type == CC2538_SENSORS_VALUE_TYPE_RAW) { + return raw; + } else if(type == CC2538_SENSORS_VALUE_TYPE_CONVERTED) { + return raw * (3 * 1190) / (2047 << 4); + } + + return CC2538_SENSORS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(vdd3_sensor, VDD3_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc2538/dev/vdd3-sensor.h b/cpu/cc2538/dev/vdd3-sensor.h new file mode 100644 index 000000000..aa0fcf94c --- /dev/null +++ b/cpu/cc2538/dev/vdd3-sensor.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-sensors + * @{ + * + * \defgroup cc2538-vdd3-sensor CC2538 VDD3 Sensor + * + * Driver for the CC2538 VDD3 sensor + * + * This driver can return the raw as well as the converted value of the sensor + * reading. This is controlled by the type argument of the sensor driver's + * value() function. The choices for the type argument are: + * - REMOTE_SENSORS_VALUE_TYPE_RAW (value() returns the raw reading) + * - REMOTE_SENSORS_VALUE_TYPE_CONVERTED (value() returns mV) + * @{ + * + * \file + * Header file for the CC2538 VDD3 Sensor Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef VDD3_SENSOR_H_ +#define VDD3_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +/** + * \name VDD3 sensors + * @{ + */ +#define VDD3_SENSOR "VDD3" +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor vdd3_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* VDD3_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/cc2538dk/startup-gcc.c b/cpu/cc2538/startup-gcc.c similarity index 94% rename from platform/cc2538dk/startup-gcc.c rename to cpu/cc2538/startup-gcc.c index ce3db6dde..99a624a7d 100644 --- a/platform/cc2538dk/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -30,22 +30,23 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538dk + * \addtogroup cc2538 * @{ * * \file - * Startup code for the cc2538dk platform, to be used when building with gcc + * Startup code for the cc2538 chip, to be used when building with gcc */ #include "contiki.h" #include "reg.h" #include "flash-cca.h" #include "sys-ctrl.h" -#include "uart.h" #include /*---------------------------------------------------------------------------*/ extern int main(void); /*---------------------------------------------------------------------------*/ +#define WEAK_ALIAS(x) __attribute__ ((weak, alias(#x))) +/*---------------------------------------------------------------------------*/ /* System handlers provided here */ void reset_handler(void); void nmi_handler(void); @@ -62,6 +63,9 @@ void cc2538_rf_rx_tx_isr(void); void cc2538_rf_err_isr(void); void udma_isr(void); void udma_err_isr(void); +void usb_isr(void) WEAK_ALIAS(default_handler); +void uart0_isr(void) WEAK_ALIAS(default_handler); +void uart1_isr(void) WEAK_ALIAS(default_handler); /* Boot Loader Backdoor selection */ #if FLASH_CCA_CONF_BOOTLDR_BACKDOOR @@ -73,32 +77,16 @@ void udma_err_isr(void); #define FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL 0 #endif -#if ( (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN < 0) || (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN > 7) ) +#if ((FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN < 0) || (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN > 7)) #error Invalid boot loader backdoor pin. Please set FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN between 0 and 7 (indicating PA0 - PA7). #endif -#define FLASH_CCA_BOOTLDR_CFG ( FLASH_CCA_BOOTLDR_CFG_ENABLE \ +#define FLASH_CCA_BOOTLDR_CFG (FLASH_CCA_BOOTLDR_CFG_ENABLE \ | FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL \ - | (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S) ) + | (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S)) #else #define FLASH_CCA_BOOTLDR_CFG FLASH_CCA_BOOTLDR_CFG_DISABLE #endif - -/* Link in the USB ISR only if USB is enabled */ -#if USB_SERIAL_CONF_ENABLE -void usb_isr(void); -#else -#define usb_isr default_handler -#endif - -/* Likewise for the UART[01] ISRs */ -#if UART_CONF_ENABLE -void uart0_isr(void); -void uart1_isr(void); -#else /* UART_CONF_ENABLE */ -#define uart0_isr default_handler -#define uart1_isr default_handler -#endif /* UART_CONF_ENABLE */ /*---------------------------------------------------------------------------*/ /* Allocate stack space */ static unsigned long stack[512]; diff --git a/cpu/cc26xx/Makefile.cc26xx b/cpu/cc26xx/Makefile.cc26xx index a339bd9f1..f8bf8de9f 100644 --- a/cpu/cc26xx/Makefile.cc26xx +++ b/cpu/cc26xx/Makefile.cc26xx @@ -6,6 +6,7 @@ OBJCOPY = arm-none-eabi-objcopy OBJDUMP = arm-none-eabi-objdump NM = arm-none-eabi-nm SIZE = arm-none-eabi-size +SREC_CAT = srec_cat ### TI CC26xxware out-of-tree ### TI_CC26XXWARE is the home directory of the cc26xxware @@ -106,9 +107,12 @@ CUSTOM_RULE_LINK=1 $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ -%.hex: %.elf +%.i16hex: %.elf $(OBJCOPY) -O ihex $< $@ +%.hex: %.i16hex + $(SREC_CAT) $< -intel -o $@ -intel + %.bin: %.elf $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ diff --git a/cpu/cc26xx/clock.c b/cpu/cc26xx/clock.c index fdf3b9405..c96158b48 100644 --- a/cpu/cc26xx/clock.c +++ b/cpu/cc26xx/clock.c @@ -167,7 +167,7 @@ clock_delay_usec(uint16_t len) * Wait for TBEN to clear. CC26xxware does not provide us with a convenient * function, hence the direct register access here */ - while(HWREG(GPT0_BASE | GPT_O_CTL) & GPT_CTL_TBEN); + while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc26xx/dev/cc26xx-rf.c b/cpu/cc26xx/dev/cc26xx-rf.c index c791969e5..f7b28b4e1 100644 --- a/cpu/cc26xx/dev/cc26xx-rf.c +++ b/cpu/cc26xx/dev/cc26xx-rf.c @@ -267,15 +267,17 @@ const output_config_t *tx_power_current = &output_power[0]; /*---------------------------------------------------------------------------*/ /* RF interrupts */ #define RX_IRQ IRQ_IEEE_RX_ENTRY_DONE -#define TX_IRQ IRQ_IEEE_TX_FRAME #define TX_ACK_IRQ IRQ_IEEE_TX_ACK #define ERROR_IRQ IRQ_INTERNAL_ERROR +/* Those IRQs are enabled all the time */ +#define ENABLED_IRQS (RX_IRQ + ERROR_IRQ) + /* - * We don't really care about TX ISR, we just use it to bring the CM3 out - * of sleep, which it enters while the RF is TXing + * We only enable this right before starting frame TX, so we can sleep while + * the TX is ongoing */ -#define ENABLED_IRQS (RX_IRQ + TX_IRQ + ERROR_IRQ) +#define LAST_FG_CMD_DONE IRQ_LAST_FG_COMMAND_DONE #define cc26xx_rf_cpe0_isr RFCCPE0IntHandler #define cc26xx_rf_cpe1_isr RFCCPE1IntHandler @@ -464,7 +466,7 @@ rf_is_accessible(void) { if(ti_lib_prcm_rf_ready() && ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) == - PRCM_DOMAIN_POWER_ON) { + PRCM_DOMAIN_POWER_ON) { return 1; } return 0; @@ -937,6 +939,7 @@ init_rf_params(void) BITVALUE(CMD_IEEE_RX, frameFiltOpt, defaultPend, 0) | BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPendDataReqOnly, 0) | BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPanCoord, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, maxFrameVersion, 1) | BITVALUE(CMD_IEEE_RX, frameFiltOpt, bStrictLenFilter, 0); /* Receive all frame types */ GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameTypes) = @@ -1294,6 +1297,10 @@ transmit(unsigned short transmit_len) GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, payloadLen) = transmit_len; GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, pPayload) = tx_buf; + /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS + + LAST_FG_CMD_DONE; + ret = rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status); if(ret) { @@ -1334,9 +1341,11 @@ transmit(unsigned short transmit_len) ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - if(was_off) { - off(); - } + /* + * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it + * except when we are transmitting + */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; return ret; } diff --git a/cpu/cc26xx/dev/cc26xx-rf.h b/cpu/cc26xx/dev/cc26xx-rf.h index 4087a037d..a278e085d 100644 --- a/cpu/cc26xx/dev/cc26xx-rf.h +++ b/cpu/cc26xx/dev/cc26xx-rf.h @@ -66,7 +66,7 @@ #define CC26XX_RF_AUTOACK 1 #endif /* CC26XX_RF_CONF_AUTOACK */ -#if defined (CC26XX_RF_CONF_BLE_SUPPORT) && (CC26XX_MODEL_CPU_VARIANT == 2650) +#if (CC26XX_RF_CONF_BLE_SUPPORT) && (CC26XX_MODEL_CPU_VARIANT == 2650) #define CC26XX_RF_BLE_SUPPORT CC26XX_RF_CONF_BLE_SUPPORT #else #define CC26XX_RF_BLE_SUPPORT 0 diff --git a/cpu/cc26xx/dev/cc26xx-rtc.c b/cpu/cc26xx/dev/cc26xx-rtc.c index b06aebd22..b1b01ea6e 100644 --- a/cpu/cc26xx/dev/cc26xx-rtc.c +++ b/cpu/cc26xx/dev/cc26xx-rtc.c @@ -91,7 +91,7 @@ cc26xx_rtc_get_next_trigger() if(HWREG(AON_RTC_BASE + AON_RTC_O_CHCTL) & AON_RTC_CHCTL_CH0_EN) { rtimer_clock_t ch0 = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH2); - return RTIMER_CLOCK_LT(ch0 ,ch2) ? ch0 : ch2; + return RTIMER_CLOCK_LT(ch0, ch2) ? ch0 : ch2; } return ch2; diff --git a/cpu/cc26xx/dev/contiki-watchdog.c b/cpu/cc26xx/dev/contiki-watchdog.c index 8241b5045..2c833c9d4 100644 --- a/cpu/cc26xx/dev/contiki-watchdog.c +++ b/cpu/cc26xx/dev/contiki-watchdog.c @@ -54,7 +54,7 @@ void watchdog_init(void) { - ti_lib_wathdog_reload_set(0xFFFFF); + ti_lib_watchdog_reload_set(0xFFFFF); } /*---------------------------------------------------------------------------*/ /** @@ -63,7 +63,7 @@ watchdog_init(void) void watchdog_start(void) { - ti_lib_wathdog_reset_enable(); + ti_lib_watchdog_reset_enable(); } /*---------------------------------------------------------------------------*/ /** @@ -72,7 +72,7 @@ watchdog_start(void) void watchdog_periodic(void) { - ti_lib_wathdog_int_clear(); + ti_lib_watchdog_int_clear(); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc26xx/ti-lib.h b/cpu/cc26xx/ti-lib.h index df5e2cf39..e545ac501 100644 --- a/cpu/cc26xx/ti-lib.h +++ b/cpu/cc26xx/ti-lib.h @@ -640,24 +640,24 @@ /* watchdog.h */ #include "driverlib/watchdog.h" -#define ti_lib_wathdog_running(...) WatchdogRunning(__VA_ARGS__) -#define ti_lib_wathdog_enable(...) WatchdogEnable(__VA_ARGS__) -#define ti_lib_wathdog_reset_enable(...) WatchdogResetEnable(__VA_ARGS__) -#define ti_lib_wathdog_reset_disable(...) WatchdogResetDisable(__VA_ARGS__) -#define ti_lib_wathdog_lock(...) WatchdogLock(__VA_ARGS__) -#define ti_lib_wathdog_unlock(...) WatchdogUnlock(__VA_ARGS__) -#define ti_lib_wathdog_lock_state(...) WatchdogLockState(__VA_ARGS__) -#define ti_lib_wathdog_reload_set(...) WatchdogReloadSet(__VA_ARGS__) -#define ti_lib_wathdog_reload_get(...) WatchdogReloadGet(__VA_ARGS__) -#define ti_lib_wathdog_value_get(...) WatchdogValueGet(__VA_ARGS__) -#define ti_lib_wathdog_int_register(...) WatchdogIntRegister(__VA_ARGS__) -#define ti_lib_wathdog_int_unregister(...) WatchdogIntUnregister(__VA_ARGS__) -#define ti_lib_wathdog_int_enable(...) WatchdogIntEnable(__VA_ARGS__) -#define ti_lib_wathdog_int_status(...) WatchdogIntStatus(__VA_ARGS__) -#define ti_lib_wathdog_int_clear(...) WatchdogIntClear(__VA_ARGS__) -#define ti_lib_wathdog_int_type_set(...) WatchdogIntTypeSet(__VA_ARGS__) -#define ti_lib_wathdog_stall_enable(...) WatchdogStallEnable(__VA_ARGS__) -#define ti_lib_wathdog_stall_disable(...) WatchdogStallDisable(__VA_ARGS__) +#define ti_lib_watchdog_running(...) WatchdogRunning(__VA_ARGS__) +#define ti_lib_watchdog_enable(...) WatchdogEnable(__VA_ARGS__) +#define ti_lib_watchdog_reset_enable(...) WatchdogResetEnable(__VA_ARGS__) +#define ti_lib_watchdog_reset_disable(...) WatchdogResetDisable(__VA_ARGS__) +#define ti_lib_watchdog_lock(...) WatchdogLock(__VA_ARGS__) +#define ti_lib_watchdog_unlock(...) WatchdogUnlock(__VA_ARGS__) +#define ti_lib_watchdog_lock_state(...) WatchdogLockState(__VA_ARGS__) +#define ti_lib_watchdog_reload_set(...) WatchdogReloadSet(__VA_ARGS__) +#define ti_lib_watchdog_reload_get(...) WatchdogReloadGet(__VA_ARGS__) +#define ti_lib_watchdog_value_get(...) WatchdogValueGet(__VA_ARGS__) +#define ti_lib_watchdog_int_register(...) WatchdogIntRegister(__VA_ARGS__) +#define ti_lib_watchdog_int_unregister(...) WatchdogIntUnregister(__VA_ARGS__) +#define ti_lib_watchdog_int_enable(...) WatchdogIntEnable(__VA_ARGS__) +#define ti_lib_watchdog_int_status(...) WatchdogIntStatus(__VA_ARGS__) +#define ti_lib_watchdog_int_clear(...) WatchdogIntClear(__VA_ARGS__) +#define ti_lib_watchdog_int_type_set(...) WatchdogIntTypeSet(__VA_ARGS__) +#define ti_lib_watchdog_stall_enable(...) WatchdogStallEnable(__VA_ARGS__) +#define ti_lib_watchdog_stall_disable(...) WatchdogStallDisable(__VA_ARGS__) /*---------------------------------------------------------------------------*/ #endif /* TI_LIB_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/cpu/mc1322x/doc/rest-tutorial.md b/cpu/mc1322x/doc/rest-tutorial.md deleted file mode 100644 index c3c3e05f9..000000000 --- a/cpu/mc1322x/doc/rest-tutorial.md +++ /dev/null @@ -1,172 +0,0 @@ -Contiki REST/CoAP Quickstart using Econotags -====================================== - -Contiki has an implementation of the IETF CORE (Constrained RESTful -Environments) working group's CoAP layer (Constrained Application -Protocol). CoAP is a RESTful application layer that uses HTTP-like -methods (GET, POST, PUT, DELETE) to interact with constrained -networks. CoAP operates over UDP and supports reliable transmission. - -This tutorial will show you how to run Contiki's CoAP demo on Redwire -Econotags using an RPL border-router. - -1) Run a RPL border-router and tunnel ---------------------------------------------------------------- - -See [the RPL -HOWTO](http://mc1322x.devl.org/repos/contiki-mc1322x/cpu/mc1322x/doc/rpl-tutorial.md) -for details about running a RPL border-router. - -2) Build and run the `rest-server-example` on a second Econotag ----------------------------------------- - -__The following must be done on the contiki-mc1322x.git tree__ - - git clone git://git.devl.org/git/malvira/contiki-mc1322x.git - -__Contiki CVS is currently down and the new SCM system hasn't been set -up yet. The necessary changes will be pushed as soon as the new SCM is -available. - 6 Februrary 2011__ - -To build the rest-server-example: - - cd contiki-mc1322x/examples/rest-example - make TARGET=redbee-econotag - -This will produce the binary image -`rest-server-example_redbee-econotag.bin`, which you can load directly -on to an mc1322x and execute. - - mc1322x-load.pl -f rest-server-example_redbee-econotag.bin -t /dev/ttyUSB3 - -Then press the reset button to connect to the bootloader. - -In this example, we are loading the CoAP server on to the econotag on `/dev/ttyUSB3` - -You should see boot up messages similar to this: - - CONNECT - Size: 62096 bytes - Sending rest-server-example_redbee-econotag.bin - done sending files. - performing ring osc cal - crm_status: 0xc0000 - sys_cntl: 0x18 - ring osc cal complete - cal_count: 0x17e17e0 - cal factor: 100 - hib_wake_secs: 2000 - loading rime address from flash. - Rime started with address 00:50:C2:AB:C0:00:00:23 - nullmac nullrdc, channel check rate 100 Hz, radio channel 26 - Tentative link-local IPv6 address - fe80:0000:0000:0000:0250:c2ab:c000:0023 - Tentative global IPv6 address aaaa:0000:0000:0000:0250:c2ab:c000:0023 - Starting 'Rest Server Example' - COAP Server - -The last line indicates that the server will be using -COAP. As an alternative, you can build the server to use HTTP instead with: - - make TARGET=redbee-econotag WITH_COAP=0 - -3) Download and install the `Copper` Firefox Plugin ------------------------------------------------------ - -The `Copper` Plugin for Firefox provides the `coap:` URL access method -as well as an interface to easily send `coap` requests. - -Download and install the plugin from here: - -+ [Copper plugin homepage](http://people.inf.ethz.ch/~mkovatsc/) -+ Install link:[copper-0.3.0pre2.xpi](http://people.inf.ethz.ch/~mkovatsc/resources/copper/copper-0.3.0pre2.xpi) - -4) Open Copper --------------- - -Open a new Firefox tab and click on the orange CU button in the lower -right. - -[![Open CU](http://mc1322x.devl.org/files/coap-blanktab-t.png)](http://mc1322x.devl.org/files/coap-blanktab.png) - -The initial CU screen will look like this: - -[![CU startup](http://mc1322x.devl.org/files/coap-opencu-t.png)](http://mc1322x.devl.org/files/coap-opencu.png) - -Type in the the URL of the coap node with the default port number of -"61616": - -[![CU startup](http://mc1322x.devl.org/files/coap-url-t.png)](http://mc1322x.devl.org/files/coap-url.png) - -+ Don't forget the brackets ( [ ] ) in the URL - -+ Make sure to use the IPv6 address of your coap server. You can get - this from the boot up messages or from the webpage served by your - border-router. - -+ You must always press Enter after changing the URL. - -5) GET `.well-known/core` resources ------------------------------------- - -Now click on the red "./well-known/core" button: this changes the URL -to the `.well-known/core` resource. - -Then click GET to perform a get. You should see an acknowledgement -that the GET was successful (returns 200 OK). The payload should -return: - - ;n="HelloWorld",;n="LedControl",;n="Light - -Which is are the well-known resources that this node advertises; see -the [COAP -specification](https://datatracker.ietf.org/doc/draft-ietf-core-coap/) -for details. - -[![Open CU](http://mc1322x.devl.org/files/coap-wellknown-t.png)](http://mc1322x.devl.org/files/coap-wellknown.png) - -6) PUT,POST the `led` resource state ------------------------------------- - -You can PUT or POST to change the state of the LED. - -Type in the following URL and press enter: - - coap://[aaaa::250:c2ff:fea8:c48e]:61616/led?color=green - -Be sure to use the proper IP address. For this URL: we will perform -actions on the `led` resource with a query string of `color=green`. - -In the payload, type: - - mode=on - -That is the payload that will be PUT or POSTed. The COAP server -detects the mode string and activates the LED accordingly (with the -color chosen by the query string). - -Then click PUT or POST to perform the request. - -[![CU startup](http://mc1322x.devl.org/files/coap-led-t.png)](http://mc1322x.devl.org/files/coap-led.png) - -You should get a successful return code (200 OK) and the green LED -should turn on. If you PUT/POST `mode=off` the led will turn off. - -The econotag only has two LEDs: a green and a red. The red LED is used -to indicate radio transmission by default and so cannot be used in -this demo. The Coniki blue LED is connected to GPIO 43. You can toggle -it, but you won't see anything unless you hook something up to this -pin. - -7) Other resources ------------------- - -The `rest-server-example` also provides `helloworld` and `light` as -GETtable resources. - - coap://[aaaa::250:c2ff:fea8:c48e]:61616/helloworld - coap://[aaaa::250:c2ff:fea8:c48e]:61616/light - -The econotag does not have a light sensor. The light resource will -always return 0. At a latter date, this sensor will be connected to -one of the ADC pins. diff --git a/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c b/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c index c6c0b532c..14d143bc7 100644 --- a/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c +++ b/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c @@ -50,10 +50,10 @@ void halInternalGetMfgTokenData(void *data, uint16_t ID, uint8_t index, uint8_t MEMCOPY(ram, eui64, 8 /*EUI64_SIZE*/); } else { //read from the Information Blocks. The token ID is only the - //bottom 16bits of the token's actual address. Since the info blocks - //exist in the range DATA_BIG_INFO_BASE-DATA_BIG_INFO_END, we need - //to OR the ID with DATA_BIG_INFO_BASE to get the real address. - uint32_t realAddress = (DATA_BIG_INFO_BASE|ID) + (len*index); + //DATA_BIG_INFO_BASE-relative 16-bit offset of the token. Since the + //info blocks exist in the range DATA_BIG_INFO_BASE-DATA_BIG_INFO_END, + //we need to add the ID to DATA_BIG_INFO_BASE to get the real address. + uint32_t realAddress = (DATA_BIG_INFO_BASE+ID) + (len*index); uint8_t *flash = (uint8_t *)realAddress; @@ -77,7 +77,7 @@ void halInternalGetMfgTokenData(void *data, uint16_t ID, uint8_t index, uint8_t void halInternalSetMfgTokenData(uint16_t token, void *data, uint8_t len) { StStatus flashStatus; - uint32_t realAddress = (DATA_BIG_INFO_BASE|token); + uint32_t realAddress = (DATA_BIG_INFO_BASE+token); uint8_t * flash = (uint8_t *)realAddress; uint32_t i; diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 970f9dca7..d455e02df 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -658,11 +658,13 @@ cc2420_transmit(unsigned short payload_len) { rtimer_clock_t sfd_timestamp; sfd_timestamp = cc2420_sfd_start_time; +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ write_ram((uint8_t *) &sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2, WRITE_RAM_IN_ORDER); } +#endif } if(!(get_status() & BV(CC2420_TX_ACTIVE))) { diff --git a/dev/cc2520/cc2520.c b/dev/cc2520/cc2520.c index 249bc6ad6..b6c0e43fa 100644 --- a/dev/cc2520/cc2520.c +++ b/dev/cc2520/cc2520.c @@ -438,11 +438,13 @@ cc2520_transmit(unsigned short payload_len) { rtimer_clock_t sfd_timestamp; sfd_timestamp = cc2520_sfd_start_time; +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ CC2520_WRITE_RAM(&sfd_timestamp, CC2520RAM_TXFIFO + payload_len - 1, 2); } +#endif } if(!(status() & BV(CC2520_TX_ACTIVE))) { diff --git a/dev/enc28j60/enc28j60-ip64-driver.c b/dev/enc28j60/enc28j60-ip64-driver.c new file mode 100644 index 000000000..f1804d998 --- /dev/null +++ b/dev/enc28j60/enc28j60-ip64-driver.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "contiki.h" +#include "enc28j60.h" +#include "enc28j60-ip64-driver.h" + +#include "ip64.h" +#include "ip64-eth.h" + +#include +#include + +PROCESS(enc28j60_ip64_driver_process, "ENC28J60 IP64 driver"); + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + uint8_t eui64[8]; + uint8_t macaddr[6]; + + /* Assume that linkaddr_node_addr holds the EUI64 of this device. */ + memcpy(eui64, &linkaddr_node_addr, sizeof(eui64)); + + /* Mangle the EUI64 into a 48-bit Ethernet address. */ + memcpy(&macaddr[0], &eui64[0], 3); + memcpy(&macaddr[3], &eui64[5], 3); + + /* In case the OUI happens to contain a broadcast bit, we mask that + out here. */ + macaddr[0] = (macaddr[0] & 0xfe); + + /* Set the U/L bit, in order to create a locally administered MAC address */ + macaddr[0] = (macaddr[0] | 0x02); + + memcpy(ip64_eth_addr.addr, macaddr, sizeof(macaddr)); + + printf("MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + enc28j60_init(macaddr); + process_start(&enc28j60_ip64_driver_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static int +output(uint8_t *packet, uint16_t len) +{ + enc28j60_send(packet, len); + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(enc28j60_ip64_driver_process, ev, data) +{ + static int len; + static struct etimer e; + PROCESS_BEGIN(); + + while(1) { + etimer_set(&e, 1); + PROCESS_WAIT_EVENT(); + len = enc28j60_read(ip64_packet_buffer, ip64_packet_buffer_maxlen); + if(len > 0) { + IP64_INPUT(ip64_packet_buffer, len); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +const struct ip64_driver enc28j60_ip64_driver = { + init, + output +}; +/*---------------------------------------------------------------------------*/ diff --git a/dev/enc28j60/enc28j60-ip64-driver.h b/dev/enc28j60/enc28j60-ip64-driver.h new file mode 100644 index 000000000..29d3ed5a4 --- /dev/null +++ b/dev/enc28j60/enc28j60-ip64-driver.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ENC28J60_IP64_DRIVER_H +#define ENC28J60_IP64_DRIVER_H + +#include "ip64-driver.h" +extern const struct ip64_driver enc28j60_ip64_driver; + +#endif /* ENC28J60_IP64_DRIVER_H */ diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c new file mode 100644 index 000000000..dd00dddeb --- /dev/null +++ b/dev/enc28j60/enc28j60.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "contiki.h" +#include "enc28j60.h" +#include +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define EIE 0x1b +#define EIR 0x1c +#define ESTAT 0x1d +#define ECON2 0x1e +#define ECON1 0x1f + +#define ESTAT_CLKRDY 0x01 +#define ESTAT_TXABRT 0x02 + +#define ECON1_RXEN 0x04 +#define ECON1_TXRTS 0x08 + +#define ECON2_AUTOINC 0x80 +#define ECON2_PKTDEC 0x40 + +#define EIR_TXIF 0x08 + +#define ERXTX_BANK 0x00 + +#define ERDPTL 0x00 +#define ERDPTH 0x01 +#define EWRPTL 0x02 +#define EWRPTH 0x03 +#define ETXSTL 0x04 +#define ETXSTH 0x05 +#define ETXNDL 0x06 +#define ETXNDH 0x07 +#define ERXSTL 0x08 +#define ERXSTH 0x09 +#define ERXNDL 0x0a +#define ERXNDH 0x0b +#define ERXRDPTL 0x0c +#define ERXRDPTH 0x0d + +#define RX_BUF_START 0x0000 +#define RX_BUF_END 0x0fff + +#define TX_BUF_START 0x1200 + +/* MACONx registers are in bank 2 */ +#define MACONX_BANK 0x02 + +#define MACON1 0x00 +#define MACON2 0x01 +#define MACON3 0x02 +#define MACON4 0x03 +#define MABBIPG 0x04 +#define MAIPGL 0x06 +#define MAIPGH 0x07 +#define MAMXFLL 0x0a +#define MAMXFLH 0x0b + +#define MACON1_TXPAUS 0x08 +#define MACON1_RXPAUS 0x04 +#define MACON1_MARXEN 0x01 + +#define MACON2_MARST 0x80 + +#define MACON3_PADCFG_FULL 0xe0 +#define MACON3_TXCRCEN 0x10 +#define MACON3_FRMLNEN 0x02 +#define MACON3_FULDPX 0x01 + +#define MAX_MAC_LENGTH 1518 + +#define MAADRX_BANK 0x03 +#define MAADR1 0x04 /* MAADR<47:40> */ +#define MAADR2 0x05 /* MAADR<39:32> */ +#define MAADR3 0x02 /* MAADR<31:24> */ +#define MAADR4 0x03 /* MAADR<23:16> */ +#define MAADR5 0x00 /* MAADR<15:8> */ +#define MAADR6 0x01 /* MAADR<7:0> */ + +#define EPKTCNT_BANK 0x01 +#define ERXFCON 0x18 +#define EPKTCNT 0x19 + +#define ERXFCON_UCEN 0x80 +#define ERXFCON_ANDOR 0x40 +#define ERXFCON_CRCEN 0x20 +#define ERXFCON_MCEN 0x02 +#define ERXFCON_BCEN 0x01 + + +PROCESS(enc_watchdog_process, "Enc28j60 watchdog"); + +static uint8_t initialized = 0; +static uint8_t enc_mac_addr[6]; +static int received_packets = 0; +static int sent_packets = 0; + +/*---------------------------------------------------------------------------*/ +static uint8_t +readreg(uint8_t reg) +{ + uint8_t r; + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0x00 | (reg & 0x1f)); + r = enc28j60_arch_spi_read(); + enc28j60_arch_spi_deselect(); + return r; +} +/*---------------------------------------------------------------------------*/ +static void +writereg(uint8_t reg, uint8_t data) +{ + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0x40 | (reg & 0x1f)); + enc28j60_arch_spi_write(data); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +setregbank(uint8_t bank) +{ + writereg(ECON1, (readreg(ECON1) & 0xfc) | (bank & 0x03)); +} +/*---------------------------------------------------------------------------*/ +static void +writedatabyte(uint8_t byte) +{ + enc28j60_arch_spi_select(); + /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x7a); + enc28j60_arch_spi_write(byte); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +writedata(uint8_t *data, int datalen) +{ + int i; + enc28j60_arch_spi_select(); + /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x7a); + for(i = 0; i < datalen; i++) { + enc28j60_arch_spi_write(data[i]); + } + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +readdatabyte(void) +{ + uint8_t r; + enc28j60_arch_spi_select(); + /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x3a); + r = enc28j60_arch_spi_read(); + enc28j60_arch_spi_deselect(); + return r; +} +/*---------------------------------------------------------------------------*/ +static int +readdata(uint8_t *buf, int len) +{ + int i; + enc28j60_arch_spi_select(); + /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x3a); + for(i = 0; i < len; i++) { + buf[i] = enc28j60_arch_spi_read(); + } + enc28j60_arch_spi_deselect(); + return i; +} +/*---------------------------------------------------------------------------*/ +static void +softreset(void) +{ + enc28j60_arch_spi_select(); + /* The System Command (soft reset) is 1 1 1 1 1 1 1 1 */ + enc28j60_arch_spi_write(0xff); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +reset(void) +{ + PRINTF("enc28j60: resetting chip\n"); + + enc28j60_arch_spi_init(); + + /* + 6.0 INITIALIZATION + + Before the ENC28J60 can be used to transmit and receive packets, + certain device settings must be initialized. Depending on the + application, some configuration options may need to be + changed. Normally, these tasks may be accomplished once after + Reset and do not need to be changed thereafter. + + 6.1 Receive Buffer + + Before receiving any packets, the receive buffer must be + initialized by programming the ERXST and ERXND pointers. All + memory between and including the ERXST and ERXND addresses will be + dedicated to the receive hardware. It is recommended that the + ERXST pointer be programmed with an even address. + + Applications expecting large amounts of data and frequent packet + delivery may wish to allocate most of the memory as the receive + buffer. Applications that may need to save older packets or have + several packets ready for transmission should allocate less + memory. + + When programming the ERXST pointer, the ERXWRPT registers will + automatically be updated with the same values. The address in + ERXWRPT will be used as the starting location when the receive + hardware begins writing received data. For tracking purposes, the + ERXRDPT registers should additionally be programmed with the same + value. To program ERXRDPT, the host controller must write to + ERXRDPTL first, followed by ERXRDPTH. See Section 7.2.4 “Freeing + Receive Buffer Space for more information + + 6.2 Transmission Buffer + + All memory which is not used by the receive buffer is considered + the transmission buffer. Data which is to be transmitted should be + written into any unused space. After a packet is transmitted, + however, the hardware will write a seven-byte status vector into + memory after the last byte in the packet. Therefore, the host + controller should leave at least seven bytes between each packet + and the beginning of the receive buffer. No explicit action is + required to initialize the transmission buffer. + + 6.3 Receive Filters + + The appropriate receive filters should be enabled or disabled by + writing to the ERXFCON register. See Section 8.0 “Receive Filters + for information on how to configure it. + + 6.4 Waiting For OST + + If the initialization procedure is being executed immediately + following a Power-on Reset, the ESTAT.CLKRDY bit should be polled + to make certain that enough time has elapsed before proceeding to + modify the MAC and PHY registers. For more information on the OST, + see Section 2.2 “Oscillator Start-up Timer. + */ + + /* Wait for OST */ + while((readreg(ESTAT) & ESTAT_CLKRDY) == 0); + + softreset(); + + setregbank(ERXTX_BANK); + /* Set up receive buffer */ + writereg(ERXSTL, RX_BUF_START & 0xff); + writereg(ERXSTH, RX_BUF_START >> 8); + writereg(ERXNDL, RX_BUF_END & 0xff); + writereg(ERXNDH, RX_BUF_END >> 8); + writereg(ERDPTL, RX_BUF_START & 0xff); + writereg(ERDPTH, RX_BUF_START >> 8); + writereg(ERXRDPTL, RX_BUF_START & 0xff); + writereg(ERXRDPTH, RX_BUF_START >> 8); + + /* Receive filters */ + setregbank(EPKTCNT_BANK); + /* writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | + ERXFCON_MCEN | ERXFCON_BCEN);*/ + /* XXX: can't seem to get the unicast filter to work right now, + using promiscous mode for now. */ + writereg(ERXFCON, 0); + + /* + 6.5 MAC Initialization Settings + + Several of the MAC registers require configuration during + initialization. This only needs to be done once; the order of + programming is unimportant. + + 1. Clear the MARST bit in MACON2 to pull the MAC out of Reset. + + 2. Set the MARXEN bit in MACON1 to enable the MAC to receive + frames. If using full duplex, most applications should also set + TXPAUS and RXPAUS to allow IEEE defined flow control to function. + + 3. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most + applications should enable automatic padding to at least 60 bytes + and always append a valid CRC. For convenience, many applications + may wish to set the FRMLNEN bit as well to enable frame length + status reporting. The FULDPX bit should be set if the application + will be connected to a full-duplex configured remote node; + otherwise, it should be left clear. + + 4. Configure the bits in MACON4. Many applications may not need to + modify the Reset default. + + 5. Program the MAMXFL registers with the maximum frame length to + be permitted to be received or transmitted. Normal network nodes + are designed to handle packets that are 1518 bytes or less. + + 6. Configure the Back-to-Back Inter-Packet Gap register, + MABBIPG. Most applications will program this register with 15h + when Full-Duplex mode is used and 12h when Half-Duplex mode is + used. + + 7. Configure the Non-Back-to-Back Inter-Packet Gap register low + byte, MAIPGL. Most applications will program this register with + 12h. + + 8. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap + register high byte, MAIPGH, should be programmed. Most + applications will program this register to 0Ch. + + 9. If Half-Duplex mode is used, program the Retransmission and + Collision Window registers, MACLCON1 and MACLCON2. Most + applications will not need to change the default Reset values. If + the network is spread over exceptionally long cables, the default + value of MACLCON2 may need to be increased. + + 10. Program the local MAC address into the + MAADR0:MAADR5 registers. + */ + + setregbank(MACONX_BANK); + + /* Pull MAC out of reset */ + writereg(MACON2, 0);//readreg(MACON2) & (~MACON2_MARST)); + + /* Turn on reception and IEEE-defined flow control */ + writereg(MACON1, readreg(MACON1) | (MACON1_MARXEN + MACON1_TXPAUS + + MACON1_RXPAUS)); + + /* Set padding, crc, full duplex */ + writereg(MACON3, readreg(MACON3) | (MACON3_PADCFG_FULL + MACON3_TXCRCEN + + MACON3_FULDPX + MACON3_FRMLNEN)); + + /* Don't modify MACON4 */ + + /* Set maximum frame length in MAMXFL */ + writereg(MAMXFLL, MAX_MAC_LENGTH & 0xff); + writereg(MAMXFLH, MAX_MAC_LENGTH >> 8); + + /* Set back-to-back inter packet gap */ + writereg(MABBIPG, 0x15); + + /* Set non-back-to-back packet gap */ + writereg(MAIPGL, 0x12); + writereg(MAIPGH, 0x0c); + + /* Set MAC address */ + setregbank(MAADRX_BANK); + writereg(MAADR6, enc_mac_addr[5]); + writereg(MAADR5, enc_mac_addr[4]); + writereg(MAADR4, enc_mac_addr[3]); + writereg(MAADR3, enc_mac_addr[2]); + writereg(MAADR2, enc_mac_addr[1]); + writereg(MAADR1, enc_mac_addr[0]); + + /* Receive filters */ + setregbank(EPKTCNT_BANK); + writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); + + /* + 6.6 PHY Initialization Settings + + Depending on the application, bits in three of the PHY module’s + registers may also require configuration. The PHCON1.PDPXMD bit + partially controls the device’s half/full-duplex + configuration. Normally, this bit is initialized correctly by the + external circuitry (see Section 2.6 “LED Configuration). If the + external circuitry is not present or incorrect, however, the host + controller must program the bit properly. Alternatively, for an + externally configurable system, the PDPXMD bit may be read and the + FULDPX bit be programmed to match. + + For proper duplex operation, the PHCON1.PDPXMD bit must also match + the value of the MACON3.FULDPX bit. + + If using half duplex, the host controller may wish to set the + PHCON2.HDLDIS bit to prevent automatic loopback of the data which + is transmitted. The PHY register, PHLCON, controls the outputs of + LEDA and LEDB. If an application requires a LED configuration + other than the default, PHLCON must be altered to match the new + requirements. The settings for LED operation are discussed in + Section 2.6 “LED Configuration. The PHLCON register is shown in + Register 2-2 (page 9). + */ + + /* Don't worry about PHY configuration for now */ + + /* Turn on autoincrement for buffer access */ + writereg(ECON2, readreg(ECON2) | ECON2_AUTOINC); + + /* Turn on reception */ + writereg(ECON1, ECON1_RXEN); +} +/*---------------------------------------------------------------------------*/ +void +enc28j60_init(uint8_t *mac_addr) +{ + if(initialized) { + return; + } + + memcpy(enc_mac_addr, mac_addr, 6); + + /* Start watchdog process */ + process_start(&enc_watchdog_process, NULL); + + reset(); + + initialized = 1; +} +/*---------------------------------------------------------------------------*/ +int +enc28j60_send(uint8_t *data, uint16_t datalen) +{ + int padding = 0; + + if(!initialized) { + return -1; + } + + /* + 1. Appropriately program the ETXST pointer to point to an unused + location in memory. It will point to the per packet control + byte. In the example, it would be programmed to 0120h. It is + recommended that an even address be used for ETXST. + + 2. Use the WBM SPI command to write the per packet control byte, + the destination address, the source MAC address, the + type/length and the data payload. + + 3. Appropriately program the ETXND pointer. It should point to the + last byte in the data payload. In the example, it would be + programmed to 0156h. + + 4. Clear EIR.TXIF, set EIE.TXIE and set EIE.INTIE to enable an + interrupt when done (if desired). + + 5. Start the transmission process by setting + ECON1.TXRTS. + */ + + setregbank(ERXTX_BANK); + /* Set up the transmit buffer pointer */ + writereg(ETXSTL, TX_BUF_START & 0xff); + writereg(ETXSTH, TX_BUF_START >> 8); + writereg(EWRPTL, TX_BUF_START & 0xff); + writereg(EWRPTH, TX_BUF_START >> 8); + + /* Write the transmission control register as the first byte of the + output packet. We write 0x00 to indicate that the default + configuration (the values in MACON3) will be used. */ +#define WITH_MANUAL_PADDING 1 +#if WITH_MANUAL_PADDING +#define PADDING_MIN_SIZE 60 + writedatabyte(0x0B); /* POVERRIDE, PCRCEN, PHUGEEN. Not PPADEN */ + if(datalen < PADDING_MIN_SIZE) { + padding = PADDING_MIN_SIZE - datalen; + } else { + padding = 0; + } +#else /* WITH_MANUAL_PADDING */ + writedatabyte(0x00); /* MACON3 */ + padding = 0; +#endif /* WITH_MANUAL_PADDING */ + + /* Write a pointer to the last data byte. */ + writereg(ETXNDL, (TX_BUF_START + datalen + 0 + padding) & 0xff); + writereg(ETXNDH, (TX_BUF_START + datalen + 0 + padding) >> 8); + + writedata(data, datalen); + if(padding > 0) { + uint8_t padding_buf[60]; + memset(padding_buf, 0, padding); + writedata(padding_buf, padding); + } + + /* Clear EIR.TXIF */ + writereg(EIR, readreg(EIR) & (~EIR_TXIF)); + + /* Don't care about interrupts for now */ + + /* Send the packet */ + writereg(ECON1, readreg(ECON1) | ECON1_TXRTS); + while((readreg(ECON1) & ECON1_TXRTS) > 0); + + if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { + PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, + 0xff & data[0], 0xff & data[1], 0xff & data[2], + 0xff & data[3], 0xff & data[4], 0xff & data[5]); + } else { + PRINTF("enc28j60: tx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, + 0xff & data[0], 0xff & data[1], 0xff & data[2], + 0xff & data[3], 0xff & data[4], 0xff & data[5]); + } + sent_packets++; + PRINTF("enc28j60: sent_packets %d\n", sent_packets); + return datalen; +} +/*---------------------------------------------------------------------------*/ +int +enc28j60_read(uint8_t *buffer, uint16_t bufsize) +{ + int n, len, next, err; + + uint8_t nxtpkt[2]; + uint8_t status[2]; + uint8_t length[2]; + + err = 0; + + setregbank(EPKTCNT_BANK); + n = readreg(EPKTCNT); + + if(n == 0) { + return 0; + } + + PRINTF("enc28j60: EPKTCNT 0x%02x\n", n); + + setregbank(ERXTX_BANK); + /* Read the next packet pointer */ + nxtpkt[0] = readdatabyte(); + nxtpkt[1] = readdatabyte(); + + PRINTF("enc28j60: nxtpkt 0x%02x%02x\n", nxtpkt[1], nxtpkt[0]); + + length[0] = readdatabyte(); + length[1] = readdatabyte(); + + PRINTF("enc28j60: length 0x%02x%02x\n", length[1], length[0]); + + status[0] = readdatabyte(); + status[1] = readdatabyte(); + + /* This statement is just to avoid a compiler warning: */ + status[0] = status[0]; + PRINTF("enc28j60: status 0x%02x%02x\n", status[1], status[0]); + + len = (length[1] << 8) + length[0]; + if(bufsize >= len) { + readdata(buffer, len); + } else { + uint16_t i; + + err = 1; + + /* flush rx fifo */ + for(i = 0; i < len; i++) { + readdatabyte(); + } + } + + /* Read an additional byte at odd lengths, to avoid FIFO corruption */ + if((len % 2) != 0) { + readdatabyte(); + } + + /* Errata #14 */ + next = (nxtpkt[1] << 8) + nxtpkt[0]; + if(next == RX_BUF_START) { + next = RX_BUF_END; + } else { + next = next - 1; + } + writereg(ERXRDPTL, next & 0xff); + writereg(ERXRDPTH, next >> 8); + + writereg(ECON2, readreg(ECON2) | ECON2_PKTDEC); + + if(err) { + PRINTF("enc28j60: rx err: flushed %d\n", len); + return 0; + } + PRINTF("enc28j60: rx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", len, + 0xff & buffer[0], 0xff & buffer[1], 0xff & buffer[2], + 0xff & buffer[3], 0xff & buffer[4], 0xff & buffer[5]); + + received_packets++; + PRINTF("enc28j60: received_packets %d\n", received_packets); + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(enc_watchdog_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + + while(1) { +#define RESET_PERIOD (30 * CLOCK_SECOND) + etimer_set(&et, RESET_PERIOD); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + PRINTF("enc28j60: test received_packet %d > sent_packets %d\n", received_packets, sent_packets); + if(received_packets <= sent_packets) { + PRINTF("enc28j60: resetting chip\n"); + reset(); + } + received_packets = 0; + sent_packets = 0; + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/dev/enc28j60/enc28j60.h b/dev/enc28j60/enc28j60.h new file mode 100644 index 000000000..059528816 --- /dev/null +++ b/dev/enc28j60/enc28j60.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ENC28J60_H +#define ENC28J60_H + +void enc28j60_init(uint8_t *mac_addr); + +int enc28j60_send(uint8_t *data, uint16_t datalen); + +int enc28j60_read(uint8_t *buffer, uint16_t bufsize); + +/* ENC28J60 architecture-specific SPI functions that are called by the + enc28j60 driver and must be implemented by the platform code */ + +void enc28j60_arch_spi_init(void); +uint8_t enc28j60_arch_spi_write(uint8_t data); +uint8_t enc28j60_arch_spi_read(void); +void enc28j60_arch_spi_select(void); +void enc28j60_arch_spi_deselect(void); + + +#endif /* ENC28J60_H */ diff --git a/doc/examples.txt b/doc/examples.txt index 5b2789278..10c175034 100644 --- a/doc/examples.txt +++ b/doc/examples.txt @@ -11,7 +11,6 @@ /** \example example-mesh.c */ /** \example example-multihop.c */ /** \example example-rucb.c */ -/** \example example-rudolph0.c */ /** \example example-rudolph1.c */ /** \example example-rudolph2.c */ /** \example example-runicast.c */ diff --git a/doc/tutorial-raven.txt b/doc/tutorial-raven.txt index 57e696cf3..1cc4bfe9d 100644 --- a/doc/tutorial-raven.txt +++ b/doc/tutorial-raven.txt @@ -454,24 +454,24 @@ See the \ref usbstick documentation for more details about using Wireshark. One can use avrdude to load the binaries in Linux. -\subsection advanced_hc01 Using HC01 Header Compression Scheme -IETF Internet Draft draft-hui-6lowpan-hc-01 defines a stateful -header compression mechanism (called HC01) which will soon +\subsection advanced_hc06 Using HC06 Header Compression Scheme +IETF Internet Draft draft-hui-6lowpan-hc-06 defines a stateful +header compression mechanism (called HC06) which will soon deprecate the stateless header compression mechanism (called -HC1) defined in RFC4944. HC01 is much more powerfull and flexible, +HC1) defined in RFC4944. HC06 is much more powerfull and flexible, in particular it allows compression of some multicast addresses and of all global unicast addresses. -Contiki is compiled by default with HC1 support. To use HC01 +Contiki is compiled by default with HC1 support. To use HC06 instead, edit platform/xxx/contiki-conf.h (replace xxx with avr-raven, then avr-ravenusb.) and replace the line
\code -#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC1 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC1 \endcode with \code -#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC01 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 \endcode Recompile and load Contiki for both the RAVEN ATmega1284P and RZ USB diff --git a/doc/uip6-doc.txt b/doc/uip6-doc.txt index a2f95b91e..1aec7b493 100644 --- a/doc/uip6-doc.txt +++ b/doc/uip6-doc.txt @@ -242,8 +242,6 @@ UIP_CONF_IPV6_QUEUE_PKT UIP_CONF_IPV6_REASSEMBLY /*Integer flags*/ UIP_CONF_NETIF_MAX_ADDRESSES -UIP_CONF_ND6_MAX_PREFIXES -UIP_CONF_ND6_MAX_DEFROUTERS NBR_TABLE_CONF_MAX_NEIGHBORS \endcode diff --git a/examples/cc2538dk/cc2538-demo.c b/examples/cc2538dk/cc2538-demo.c index 9210968c2..e50dd3937 100644 --- a/examples/cc2538dk/cc2538-demo.c +++ b/examples/cc2538dk/cc2538-demo.c @@ -69,8 +69,9 @@ #include "sys/rtimer.h" #include "dev/leds.h" #include "dev/uart.h" +#include "dev/cc2538-sensors.h" #include "dev/button-sensor.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" #include "dev/watchdog.h" #include "dev/serial-line.h" #include "dev/sys-ctrl.h" @@ -114,8 +115,6 @@ rt_callback(struct rtimer *t, void *ptr) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc2538_demo_process, ev, data) { - int16_t value; - PROCESS_EXITHANDLER(broadcast_close(&bc)) PROCESS_BEGIN(); @@ -134,15 +133,13 @@ PROCESS_THREAD(cc2538_demo_process, ev, data) printf("-----------------------------------------\n" "Counter = 0x%08x\n", counter); - value = adc_sensor.value(ADC_SENSOR_VDD_3); - printf("VDD = %d mV\n", value * (3 * 1190) / (2047 << 4)); + printf("VDD = %d mV\n", + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); - value = adc_sensor.value(ADC_SENSOR_TEMP); printf("Temperature = %d mC\n", - 25000 + ((value >> 4) - 1422) * 10000 / 42); + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); - value = adc_sensor.value(ADC_SENSOR_ALS); - printf("Ambient light sensor = %d raw\n", value); + printf("Ambient light sensor = %d raw\n", als_sensor.value(0)); etimer_set(&et, CLOCK_SECOND); rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1, diff --git a/examples/cc2538dk/mqtt-demo/mqtt-demo.c b/examples/cc2538dk/mqtt-demo/mqtt-demo.c index 398feec68..691d4deed 100644 --- a/examples/cc2538dk/mqtt-demo/mqtt-demo.c +++ b/examples/cc2538dk/mqtt-demo/mqtt-demo.c @@ -53,7 +53,7 @@ #include "lib/sensors.h" #include "dev/button-sensor.h" #include "dev/leds.h" -#include "dev/adc-sensor.h" +#include "dev/cc2538-sensors.h" #include /*---------------------------------------------------------------------------*/ @@ -450,7 +450,6 @@ publish(void) /* Publish MQTT topic in IBM quickstart format */ int len; int remaining = APP_BUFFER_SIZE; - int16_t value; seq_nr_value++; @@ -487,9 +486,8 @@ publish(void) remaining -= len; buf_ptr += len; - value = adc_sensor.value(ADC_SENSOR_TEMP); len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (mC)\":%d", - 25000 + ((value >> 4) - 1422) * 10000 / 42); + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); @@ -498,9 +496,8 @@ publish(void) remaining -= len; buf_ptr += len; - value = adc_sensor.value(ADC_SENSOR_VDD_3); len = snprintf(buf_ptr, remaining, ",\"VDD3 (mV)\":%d", - value * (3 * 1190) / (2047 << 4)); + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); diff --git a/examples/cc2538dk/sniffer/netstack.c b/examples/cc2538dk/sniffer/netstack.c index 0945be888..3aeb6968e 100644 --- a/examples/cc2538dk/sniffer/netstack.c +++ b/examples/cc2538dk/sniffer/netstack.c @@ -41,5 +41,6 @@ void netstack_init(void) { NETSTACK_RADIO.init(); + NETSTACK_RADIO.on(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-demo.c b/examples/cc26xx/cc26xx-demo.c index 83f78e869..903af6631 100644 --- a/examples/cc26xx/cc26xx-demo.c +++ b/examples/cc26xx/cc26xx-demo.c @@ -143,11 +143,11 @@ AUTOSTART_PROCESSES(&cc26xx_demo_process); #define SENSOR_READING_PERIOD (CLOCK_SECOND * 20) #define SENSOR_READING_RANDOM (CLOCK_SECOND << 4) -static struct ctimer bmp_timer, opt_timer, sht_timer, tmp_timer, mpu_timer; +static struct ctimer bmp_timer, opt_timer, hdc_timer, tmp_timer, mpu_timer; /*---------------------------------------------------------------------------*/ static void init_bmp_reading(void *not_used); static void init_opt_reading(void *not_used); -static void init_sht_reading(void *not_used); +static void init_hdc_reading(void *not_used); static void init_tmp_reading(void *not_used); static void init_mpu_reading(void *not_used); /*---------------------------------------------------------------------------*/ @@ -214,27 +214,27 @@ get_tmp_reading() } /*---------------------------------------------------------------------------*/ static void -get_sht_reading() +get_hdc_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { - printf("SHT: Temp=%d.%02d C\n", value / 100, value % 100); + printf("HDC: Temp=%d.%02d C\n", value / 100, value % 100); } else { - printf("SHT: Temp Read Error\n"); + printf("HDC: Temp Read Error\n"); } - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); if(value != CC26XX_SENSOR_READING_ERROR) { - printf("SHT: Humidity=%d.%02d %%RH\n", value / 100, value % 100); + printf("HDC: Humidity=%d.%02d %%RH\n", value / 100, value % 100); } else { - printf("SHT: Humidity Read Error\n"); + printf("HDC: Humidity Read Error\n"); } - ctimer_set(&sht_timer, next, init_sht_reading, NULL); + ctimer_set(&hdc_timer, next, init_hdc_reading, NULL); } /*---------------------------------------------------------------------------*/ static void @@ -311,9 +311,9 @@ init_opt_reading(void *not_used) } /*---------------------------------------------------------------------------*/ static void -init_sht_reading(void *not_used) +init_hdc_reading(void *not_used) { - SENSORS_ACTIVATE(sht_21_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); } /*---------------------------------------------------------------------------*/ static void @@ -360,7 +360,7 @@ static void init_sensor_readings(void) { #if BOARD_SENSORTAG - SENSORS_ACTIVATE(sht_21_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); SENSORS_ACTIVATE(tmp_007_sensor); SENSORS_ACTIVATE(opt_3001_sensor); SENSORS_ACTIVATE(bmp_280_sensor); @@ -450,8 +450,8 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) get_bmp_reading(); } else if(ev == sensors_event && data == &opt_3001_sensor) { get_light_reading(); - } else if(ev == sensors_event && data == &sht_21_sensor) { - get_sht_reading(); + } else if(ev == sensors_event && data == &hdc_1000_sensor) { + get_hdc_reading(); } else if(ev == sensors_event && data == &tmp_007_sensor) { get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index 91f921b9d..6cae9611d 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -68,7 +68,7 @@ PROCESS(cc26xx_web_demo_process, "CC26XX Web Demo"); struct ctimer batmon_timer; #if BOARD_SENSORTAG -struct ctimer bmp_timer, sht_timer, tmp_timer, opt_timer, mpu_timer; +struct ctimer bmp_timer, hdc_timer, tmp_timer, opt_timer, mpu_timer; #endif /*---------------------------------------------------------------------------*/ /* Provide visible feedback via LEDS while searching for a network */ @@ -111,11 +111,11 @@ DEMO_SENSOR(bmp_pres, CC26XX_WEB_DEMO_SENSOR_BMP_PRES, DEMO_SENSOR(bmp_temp, CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, "Air Temp", "air-temp", "bmp_temp", CC26XX_WEB_DEMO_UNIT_TEMP); -DEMO_SENSOR(sht_temp, CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, - "SHT Temp", "sht-temp", "sht_temp", +DEMO_SENSOR(hdc_temp, CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, + "HDC Temp", "hdc-temp", "hdc_temp", CC26XX_WEB_DEMO_UNIT_TEMP); -DEMO_SENSOR(sht_hum, CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, - "SHT Humidity", "sht-humidity", "sht_hum", +DEMO_SENSOR(hdc_hum, CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, + "HDC Humidity", "hdc-humidity", "hdc_hum", CC26XX_WEB_DEMO_UNIT_HUMIDITY); DEMO_SENSOR(tmp_amb, CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, "Ambient Temp", "ambient-temp", "tmp_amb", @@ -152,7 +152,7 @@ DEMO_SENSOR(mpu_gyro_z, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, #if BOARD_SENSORTAG static void init_bmp_reading(void *data); static void init_light_reading(void *data); -static void init_sht_reading(void *data); +static void init_hdc_reading(void *data); static void init_tmp_reading(void *data); static void init_mpu_reading(void *data); #endif @@ -526,42 +526,42 @@ get_tmp_reading() } /*---------------------------------------------------------------------------*/ static void -get_sht_reading() +get_hdc_reading() { int value; char *buf; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); - if(sht_temp_reading.publish) { - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + if(hdc_temp_reading.publish) { + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { - sht_temp_reading.raw = value; + hdc_temp_reading.raw = value; - compare_and_update(&sht_temp_reading); + compare_and_update(&hdc_temp_reading); - buf = sht_temp_reading.converted; + buf = hdc_temp_reading.converted; memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, value % 100); } } - if(sht_hum_reading.publish) { - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + if(hdc_hum_reading.publish) { + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); if(value != CC26XX_SENSOR_READING_ERROR) { - sht_hum_reading.raw = value; + hdc_hum_reading.raw = value; - compare_and_update(&sht_hum_reading); + compare_and_update(&hdc_hum_reading); - buf = sht_hum_reading.converted; + buf = hdc_hum_reading.converted; memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, value % 100); } } - ctimer_set(&sht_timer, next, init_sht_reading, NULL); + ctimer_set(&hdc_timer, next, init_hdc_reading, NULL); } /*---------------------------------------------------------------------------*/ static void @@ -702,12 +702,12 @@ init_bmp_reading(void *data) } /*---------------------------------------------------------------------------*/ static void -init_sht_reading(void *data) +init_hdc_reading(void *data) { - if(sht_hum_reading.publish || sht_temp_reading.publish) { - SENSORS_ACTIVATE(sht_21_sensor); + if(hdc_hum_reading.publish || hdc_temp_reading.publish) { + SENSORS_ACTIVATE(hdc_1000_sensor); } else { - ctimer_set(&sht_timer, CLOCK_SECOND, init_sht_reading, NULL); + ctimer_set(&hdc_timer, CLOCK_SECOND, init_hdc_reading, NULL); } } /*---------------------------------------------------------------------------*/ @@ -756,7 +756,7 @@ init_sensor_readings(void) #if BOARD_SENSORTAG init_bmp_reading(NULL); init_light_reading(NULL); - init_sht_reading(NULL); + init_hdc_reading(NULL); init_tmp_reading(NULL); init_mpu_reading(NULL); #endif /* BOARD_SENSORTAG */ @@ -781,8 +781,8 @@ init_sensors(void) list_add(sensor_list, &opt_reading); - list_add(sensor_list, &sht_hum_reading); - list_add(sensor_list, &sht_temp_reading); + list_add(sensor_list, &hdc_hum_reading); + list_add(sensor_list, &hdc_temp_reading); list_add(sensor_list, &mpu_acc_x_reading); list_add(sensor_list, &mpu_acc_y_reading); @@ -852,7 +852,7 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data) while(1) { if(ev == sensors_event && data == CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { if((CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER)->value( - BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { + BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { printf("Restoring defaults!\n"); cc26xx_web_demo_restore_defaults(); } else { @@ -873,8 +873,8 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data) get_bmp_reading(); } else if(ev == sensors_event && data == &opt_3001_sensor) { get_light_reading(); - } else if(ev == sensors_event && data == &sht_21_sensor) { - get_sht_reading(); + } else if(ev == sensors_event && data == &hdc_1000_sensor) { + get_hdc_reading(); } else if(ev == sensors_event && data == &tmp_007_sensor) { get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h index 89bf91d2b..a501925e8 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h @@ -121,8 +121,8 @@ #define CC26XX_WEB_DEMO_SENSOR_BMP_TEMP 3 #define CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT 4 #define CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT 5 -#define CC26XX_WEB_DEMO_SENSOR_SHT_TEMP 6 -#define CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY 7 +#define CC26XX_WEB_DEMO_SENSOR_HDC_TEMP 6 +#define CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY 7 #define CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT 8 #define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X 9 #define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y 10 diff --git a/examples/cc26xx/cc26xx-web-demo/coap-server.c b/examples/cc26xx/cc26xx-web-demo/coap-server.c index 65d748707..0b434d170 100644 --- a/examples/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/cc26xx/cc26xx-web-demo/coap-server.c @@ -66,8 +66,8 @@ extern resource_t res_bmp280_temp; extern resource_t res_bmp280_press; extern resource_t res_tmp007_amb; extern resource_t res_tmp007_obj; -extern resource_t res_sht21_temp; -extern resource_t res_sht21_hum; +extern resource_t res_hdc1000_temp; +extern resource_t res_hdc1000_hum; extern resource_t res_opt3001_light; extern resource_t res_mpu_acc_x; extern resource_t res_mpu_acc_y; @@ -98,8 +98,8 @@ start_board_resources(void) rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); - rest_activate_resource(&res_sht21_temp, "sen/sht/t"); - rest_activate_resource(&res_sht21_hum, "sen/sht/h"); + rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); + rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); rest_activate_resource(&res_opt3001_light, "sen/opt/light"); rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); diff --git a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c index 281567acf..29c22d22b 100644 --- a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c +++ b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c @@ -163,11 +163,6 @@ static const char *http_header_srv_str[] = { NULL }; -static const char *http_header_redir_location[] = { - "Location: /config.html\r\n", - NULL -}; - static const char *http_header_con_close[] = { CONN_CLOSE, NULL @@ -197,37 +192,49 @@ static const char config_div_left[] = "
"; static const char config_div_right[] = "
"; static const char config_div_close[] = "
"; /*---------------------------------------------------------------------------*/ +static char generate_index(struct httpd_state *s); +static char generate_config(struct httpd_state *s); +/*---------------------------------------------------------------------------*/ typedef struct page { struct page *next; char *filename; char *title; + char (*script)(struct httpd_state *s); } page_t; static page_t http_index_page = { NULL, "index.html", "Index", + generate_index, }; static page_t http_dev_cfg_page = { NULL, "config.html", "Device Config", + generate_config, }; #if CC26XX_WEB_DEMO_NET_UART +static char generate_net_uart_config(struct httpd_state *s); + static page_t http_net_cfg_page = { NULL, - "net.html", + "netu.html", "Net-UART Config", + generate_net_uart_config, }; #endif #if CC26XX_WEB_DEMO_MQTT_CLIENT +static char generate_mqtt_config(struct httpd_state *s); + static page_t http_mqtt_cfg_page = { NULL, "mqtt.html", "MQTT/IBM Cloud Config", + generate_mqtt_config, }; #endif /*---------------------------------------------------------------------------*/ @@ -395,12 +402,12 @@ PT_THREAD(generate_top_matter(struct httpd_state *s, const char *title, s->page = list_head(pages_list); PT_WAIT_THREAD(&s->top_matter_pt, - enqueue_chunk(s, 0, "[ %s ]", + enqueue_chunk(s, 0, "[ %s ]", s->page->filename, s->page->title)); for(s->page = s->page->next; s->page != NULL; s->page = s->page->next) { PT_WAIT_THREAD(&s->top_matter_pt, - enqueue_chunk(s, 0, " | [ %s ]", + enqueue_chunk(s, 0, " | [ %s ]", s->page->filename, s->page->title)); } @@ -531,7 +538,8 @@ PT_THREAD(generate_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "
generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -570,7 +578,8 @@ PT_THREAD(generate_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "

Actions

")); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -607,7 +616,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -747,7 +757,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) enqueue_chunk(s, 0, "
")); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "
generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -786,7 +797,8 @@ PT_THREAD(generate_net_uart_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -974,18 +986,13 @@ parse_post_request_chunk(char *buf, int buf_len, int last_chunk) static httpd_simple_script_t get_script(const char *name) { - if(strlen(name) == 10 && strncmp(name, "index.html", 10) == 0) { - return generate_index; - } else if(strlen(name) == 11 && strncmp(name, "config.html", 11) == 0) { - return generate_config; -#if CC26XX_WEB_DEMO_MQTT_CLIENT - } else if(strlen(name) == 9 && strncmp(name, "mqtt.html", 9) == 0) { - return generate_mqtt_config; -#endif -#if CC26XX_WEB_DEMO_NET_UART - } else if(strlen(name) == 8 && strncmp(name, "net.html", 8) == 0) { - return generate_net_uart_config; -#endif + page_t *page; + + for(page = list_head(pages_list); page != NULL; + page = list_item_next(page)) { + if(strncmp(name, page->filename, strlen(page->filename)) == 0) { + return page->script; + } } return NULL; @@ -1003,7 +1010,8 @@ PT_THREAD(send_string(struct httpd_state *s, const char *str)) /*---------------------------------------------------------------------------*/ static PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr, - const char *content_type, const char **additional)) + const char *content_type, const char *redir, + const char **additional)) { PT_BEGIN(&s->generate_pt); @@ -1013,6 +1021,11 @@ PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr, PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); } + if(redir) { + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "Location: %s\r\n", redir)); + } + if(additional) { for(s->ptr = additional; *(s->ptr) != NULL; s->ptr++) { PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); @@ -1041,25 +1054,30 @@ PT_THREAD(handle_output(struct httpd_state *s)) if(s->return_code == RETURN_CODE_OK) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_302, http_content_type_plain, - http_header_redir_location)); + s->filename, + NULL)); } else if(s->return_code == RETURN_CODE_LR) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_411, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length Required\n")); } else if(s->return_code == RETURN_CODE_TL) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_413, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length too Large\n")); } else if(s->return_code == RETURN_CODE_SU) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_503, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Service Unavailable\n")); } else { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_400, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Bad Request\n")); } @@ -1069,6 +1087,7 @@ PT_THREAD(handle_output(struct httpd_state *s)) strncpy(s->filename, "/notfound.html", sizeof(s->filename)); PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404, http_content_type_html, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, NOT_FOUND)); @@ -1077,6 +1096,7 @@ PT_THREAD(handle_output(struct httpd_state *s)) } else { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200, http_content_type_html, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, s->script(s)); } @@ -1109,6 +1129,15 @@ PT_THREAD(handle_input(struct httpd_state *s)) } } else if(strncasecmp(s->inputbuf, http_post, 5) == 0) { s->request_type = REQUEST_TYPE_POST; + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, s->inputbuf, sizeof(s->filename)); + /* POST: Read out the rest of the line and ignore it */ PSOCK_READTO(&s->sin, ISO_nl); @@ -1279,8 +1308,8 @@ PROCESS_THREAD(httpd_simple_process, ev, data) init(); snprintf(http_mqtt_a, IBM_QUICKSTART_LINK_LEN, - "[ IBM Quickstart ]", + "[ IBM Quickstart ]", linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5], linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); diff --git a/examples/cc26xx/cc26xx-web-demo/project-conf.h b/examples/cc26xx/cc26xx-web-demo/project-conf.h index d49a7b3e9..b7baac119 100644 --- a/examples/cc26xx/cc26xx-web-demo/project-conf.h +++ b/examples/cc26xx/cc26xx-web-demo/project-conf.h @@ -44,10 +44,14 @@ #define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1 #define CC26XX_WEB_DEMO_CONF_NET_UART 1 /*---------------------------------------------------------------------------*/ -/* Shrink the size of the uIP buffer, routing table and ND cache */ +/* + * Shrink the size of the uIP buffer, routing table and ND cache. + * Set the TCP MSS + */ #define UIP_CONF_BUFFER_SIZE 900 #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 #define UIP_CONF_MAX_ROUTES 8 +#define UIP_CONF_TCP_MSS 128 /*---------------------------------------------------------------------------*/ #endif /* PROJECT_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c index fecfca994..277c29c05 100644 --- a/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -229,28 +229,28 @@ RESOURCE(res_bmp280_press, "title=\"Barometer (Pressure)\";rt=\"hPa (hectopascal / millibar)\"", res_get_handler_bmp_press, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ -/* SHT21 sensor resources and handler: Temperature, Pressure */ +/* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_sht_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, request, response, + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response, buffer, preferred_size, offset); } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sht_humidity(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, request, response, + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response, buffer, preferred_size, offset); } /*---------------------------------------------------------------------------*/ -RESOURCE(res_sht21_temp, "title=\"Temperature\";rt=\"C\"", - res_get_handler_sht_temp, NULL, NULL, NULL); +RESOURCE(res_hdc1000_temp, "title=\"Temperature\";rt=\"C\"", + res_get_handler_hdc_temp, NULL, NULL, NULL); -RESOURCE(res_sht21_hum, "title=\"Humidity\";rt=\"%RH\"", - res_get_handler_sht_humidity, NULL, NULL, NULL); +RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", + res_get_handler_hdc_humidity, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void diff --git a/examples/example-shell/example-shell.c b/examples/example-shell/example-shell.c index 24b7c2a05..a8c7c74b6 100644 --- a/examples/example-shell/example-shell.c +++ b/examples/example-shell/example-shell.c @@ -66,7 +66,6 @@ PROCESS_THREAD(example_shell_process, ev, data) shell_file_init(); shell_httpd_init(); shell_irc_init(); - shell_netfile_init(); /*shell_ping_init();*/ /* uIP ping */ shell_power_init(); /*shell_profile_init();*/ diff --git a/examples/http-socket/Makefile b/examples/http-socket/Makefile new file mode 100644 index 000000000..b1d95efe0 --- /dev/null +++ b/examples/http-socket/Makefile @@ -0,0 +1,7 @@ +all: http-example +CONTIKI=../.. +MODULES += core/net/http-socket + +include $(CONTIKI)/Makefile.include + + diff --git a/examples/http-socket/http-example.c b/examples/http-socket/http-example.c new file mode 100644 index 000000000..21aff094d --- /dev/null +++ b/examples/http-socket/http-example.c @@ -0,0 +1,62 @@ +#include "contiki-net.h" +#include "http-socket.h" +#include "ip64-addr.h" + +#include + +static struct http_socket s; +static int bytes_received = 0; + +/*---------------------------------------------------------------------------*/ +PROCESS(http_example_process, "HTTP Example"); +AUTOSTART_PROCESSES(&http_example_process); +/*---------------------------------------------------------------------------*/ +static void +callback(struct http_socket *s, void *ptr, + http_socket_event_t e, + const uint8_t *data, uint16_t datalen) +{ + if(e == HTTP_SOCKET_ERR) { + printf("HTTP socket error\n"); + } else if(e == HTTP_SOCKET_TIMEDOUT) { + printf("HTTP socket error: timed out\n"); + } else if(e == HTTP_SOCKET_ABORTED) { + printf("HTTP socket error: aborted\n"); + } else if(e == HTTP_SOCKET_HOSTNAME_NOT_FOUND) { + printf("HTTP socket error: hostname not found\n"); + } else if(e == HTTP_SOCKET_CLOSED) { + printf("HTTP socket closed, %d bytes received\n", bytes_received); + } else if(e == HTTP_SOCKET_DATA) { + bytes_received += datalen; + printf("HTTP socket received %d bytes of data\n", datalen); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(http_example_process, ev, data) +{ + static struct etimer et; + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + + PROCESS_BEGIN(); + + uip_ipaddr(&ip4addr, 8,8,8,8); + ip64_addr_4to6(&ip4addr, &ip6addr); + uip_nameserver_update(&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME); + + etimer_set(&et, CLOCK_SECOND * 60); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + http_socket_init(&s); + http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, + callback, NULL); + + etimer_set(&et, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ip64-router/Makefile b/examples/ip64-router/Makefile new file mode 100644 index 000000000..c44c677ad --- /dev/null +++ b/examples/ip64-router/Makefile @@ -0,0 +1,5 @@ +all: ip64-router +CONTIKI=../.. + +include $(CONTIKI)/Makefile.include + diff --git a/examples/ip64-router/ip64-router.c b/examples/ip64-router/ip64-router.c new file mode 100644 index 000000000..391b5038b --- /dev/null +++ b/examples/ip64-router/ip64-router.c @@ -0,0 +1,27 @@ +#include "contiki.h" +#include "contiki-net.h" +#include "ip64.h" +#include "net/netstack.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(router_node_process, "Router node"); +AUTOSTART_PROCESSES(&router_node_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(router_node_process, ev, data) +{ + PROCESS_BEGIN(); + + /* Set us up as a RPL root node. */ + rpl_dag_root_init_dag(); + + /* Initialize the IP64 module so we'll start translating packets */ + ip64_init(); + + /* ... and do nothing more. */ + while(1) { + PROCESS_WAIT_EVENT(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ip64-router/project-conf.h b/examples/ip64-router/project-conf.h new file mode 100644 index 000000000..e69de29bb diff --git a/examples/ipv6/rpl-collect/udp-sender.c b/examples/ipv6/rpl-collect/udp-sender.c index f216cbdcc..dd279cc7f 100644 --- a/examples/ipv6/rpl-collect/udp-sender.c +++ b/examples/ipv6/rpl-collect/udp-sender.c @@ -137,7 +137,7 @@ collect_common_send(void) /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ parent.u8[LINKADDR_SIZE - 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; parent.u8[LINKADDR_SIZE - 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; - parent_etx = rpl_get_parent_rank((linkaddr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; + parent_etx = rpl_get_parent_rank((uip_lladdr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; } } rtmetric = dag->rank; diff --git a/examples/ipv6/slip-radio/no-framer.c b/examples/ipv6/slip-radio/no-framer.c index e3aed93b7..7f3447e97 100644 --- a/examples/ipv6/slip-radio/no-framer.c +++ b/examples/ipv6/slip-radio/no-framer.c @@ -109,8 +109,7 @@ parse(void) } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); - /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); diff --git a/examples/rest-example/Makefile b/examples/rest-example/Makefile deleted file mode 100644 index 745091636..000000000 --- a/examples/rest-example/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -all: rest-server-example coap-client-example - -ifndef TARGET -TARGET=sky -endif - -CONTIKI=../.. - -WITH_COAP = 1 - -CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" - -ifeq ($(WITH_COAP), 1) -CFLAGS += -DWITH_COAP -APPS += rest-coap -else -CFLAGS += -DWITH_HTTP -APPS += rest-http -endif - -CONTIKI_WITH_IPV6 = 1 -include $(CONTIKI)/Makefile.include - -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c - (cd $(CONTIKI)/tools && $(MAKE) tunslip6) - -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 diff --git a/examples/rest-example/README.md b/examples/rest-example/README.md deleted file mode 100644 index 1fd391653..000000000 --- a/examples/rest-example/README.md +++ /dev/null @@ -1,137 +0,0 @@ -REST example -============ - -Open a terminal and go to "/examples/rest-example/" directory. - -MAIN EXAMPLE: rest-server-example.c : A RESTful server example showing how to -use the REST layer to develop server-side applications (possible to run it over -either COAP or HTTP) To use COAP as the underlying application protocol, one -should define WITH_COAP = 1 in rest-example/Makefile. Otherwise, HTTP is used. -Look at the source code to see which resources are available. (check the -RESOURCE macros in the code). Each resource has a handler function which is -called by the REST layer to serve the request. (i.e. "helloworld" resource has -a handler function named "helloworld_handler" which is called when a web -service request is received for "helloworld" resource.) - - -To run REST examples in COOJA on Linux --------------------------------------------- - -Accessing the server from outside: - -1. Start COOJA and load the simulation "rest-server-example.csc" by the following command. - - make TARGET=cooja rest-server-example.csc - -2. After loading the COOJA file, open another another terminal pointing to the - same directory and connect to the COOJA simulation using tunslip6: - - make connect-router-cooja - -3. You need to use a COAP or HTTP client to interact with the COOJA nodes - running REST code. In this setting, two servers are available: IP addresses - are aaaa::0212:7402:0002:0202 and aaaa::0212:7403:0003:0303. COAP uses - 61616, whereas HTTP uses 8080 port in default configuration. First, ping - the COOJA nodes to test the connectivity. - - ping6 aaaa::0212:7402:0002:0202 - ping6 aaaa::0212:7403:0003:0303 - -HTTP Examples -------------- - -You can use curl as an http client to interact with the COOJA motes running -REST code. - - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #get helloworld plain text - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/led?color=green -d mode=off -i #turn off the green led - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/.well-known/core -i - curl -X POST -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #method not allowed - -COAP Examples -------------- - -You should run a COAP client on your computer. You can use the URLs and methods -provided above in HTTP examples to test the COAP Server. For example, Matthias -Kovatsch has developed a CoAP Firefox plug-in which is accessible via -[http://people.inf.ethz.ch/mkovatsc/#pro](http://people.inf.ethz.ch/mkovatsc/#pro) - -Accessing the server inside the sensor network: (Note: Provided only for COAP -implementation) Start COOJA and load the simulation -"coap-client-server-example.csc" by the following command. - - make TARGET=cooja coap-client-server-example.csc - -coap-client-server-example.csc : Runs rest-server-example.c as the server (over -COAP) (IP:aaaa::0212:7401:0001:0101) in one node and coap-client-example.c as -the client (IP: aaaa::0212:7402:0002:0202) in another node. Client -periodically accesses resources of server and prints the payload. - -Note: If the generated binary is bigger than the MOTE code size, then you will -get a "region text is full" error. Right now, REST+HTTP example uses (Contiki -& ContikiMAC & uIPv6 & RPL & HTTP Server & REST Layer) which does not fit in -Tmote Sky memory. To save same code space and make the example fit, you can -define static routes rather than using RPL or use nullrdc rather than -ContikiMAC. If border router does not fit, then first try to update the -Makefile of border router in /examples/ipv6/rpl-border-router by -setting WITH_WEBSERVER=0. - -To run REST server on real nodes (i.e. tmote sky) --------------------------------------------- - -1. Program the nodes with the rest-server-example - - make TARGET=sky rest-server-example.upload - -2. Disconnect the nodes and program one node with the RPL border router - - cd ../ipv6/rpl-border-router && make TARGET=sky border-router.upload - -3. Connect to the border router using tunslip6: - - make connect-router - -4. Reconnect the motes, open new terminal for each mote and run the following - command to note their IP addresses (after running the command reset the - corresponding mote to get IP address printed) - - make login TARGET=sky MOTE=2 #Shows the prints for first mote - make login TARGET=sky MOTE=3 #For second mote and so on. - -5. Test the connectivity by pinging them. - - ping6 - -6. Remaining parts are the same with the COOJA example. (i.e. if it is a COAP - Server, it's available at :61616) - - -To run REST server with minimal-net on Linux --------------------------------------------- -1. Compile with minimal-net setting. - - make rest-server-example TARGET=minimal-net - -2. Run the generated executable with sudo and note the IP address of the server - which will be printed right after. - - sudo ./rest-server-example.minimal-net - -3. How to access and test the server is same with the other settings. (i.e. if - it is a COAP Server, it's available at :61616 and if - it's a HTTP Server it is available at :8080) - -TODO ----- - -- Better option handling needed - ex: critical options are not differentiated - for now. Need to add support for some such as Tokens. Also, C/E difference - should be added. -- Reilable message sending is missing. i.e. client example should resend - request in case ACK does not arrive. Same for server pushing (in case of - subscriptions) -- Add Block transfer example -- Add Subscription example -- Add an Android/Java COAP Client to Contikiprojects to be able to interact - with Contiki. -- COAP-specific Method Codes diff --git a/examples/rest-example/coap-client-example.c b/examples/rest-example/coap-client-example.c deleted file mode 100644 index e5772f103..000000000 --- a/examples/rest-example/coap-client-example.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include "contiki.h" -#include "contiki-net.h" -#include "rest.h" -#include "buffer.h" - -#define DEBUG 1 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) -#define LOCAL_PORT 61617 -#define REMOTE_PORT 61616 - -char temp[100]; -int xact_id; -static uip_ipaddr_t server_ipaddr; -static struct uip_udp_conn *client_conn; -static struct etimer et; -#define MAX_PAYLOAD_LEN 100 - -#define NUMBER_OF_URLS 3 -char* service_urls[NUMBER_OF_URLS] = {"light", ".well-known/core", "helloworld"}; - -static void -response_handler(coap_packet_t* response) -{ - uint16_t payload_len = 0; - uint8_t* payload = NULL; - payload_len = coap_get_payload(response, &payload); - - PRINTF("Response transaction id: %u", response->tid); - if (payload) { - memcpy(temp, payload, payload_len); - temp[payload_len] = 0; - PRINTF(" payload: %s\n", temp); - } -} - -static void -send_data(void) -{ - char buf[MAX_PAYLOAD_LEN]; - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - int data_size = 0; - int service_id = random_rand() % NUMBER_OF_URLS; - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_packet(request); - - coap_set_method(request, COAP_GET); - request->tid = xact_id++; - request->type = MESSAGE_TYPE_CON; - coap_set_header_uri(request, service_urls[service_id]); - - data_size = serialize_packet(request, buf); - - PRINTF("Client sending request to:["); - PRINT6ADDR(&client_conn->ripaddr); - PRINTF("]:%u/%s\n", (uint16_t)REMOTE_PORT, service_urls[service_id]); - uip_udp_packet_send(client_conn, buf, data_size); - - delete_buffer(); - } -} - -static void -handle_incoming_data() -{ - PRINTF("Incoming packet size: %u \n", (uint16_t)uip_datalen()); - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - if (uip_newdata()) { - coap_packet_t* response = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - if (response) { - parse_message(response, uip_appdata, uip_datalen()); - response_handler(response); - } - } - delete_buffer(); - } -} - -PROCESS(coap_client_example, "COAP Client Example"); -AUTOSTART_PROCESSES(&coap_client_example); - -PROCESS_THREAD(coap_client_example, ev, data) -{ - PROCESS_BEGIN(); - - SERVER_NODE(&server_ipaddr); - - /* new connection with server */ - client_conn = udp_new(&server_ipaddr, UIP_HTONS(REMOTE_PORT), NULL); - udp_bind(client_conn, UIP_HTONS(LOCAL_PORT)); - - PRINTF("Created a connection with the server "); - PRINT6ADDR(&client_conn->ripaddr); - PRINTF(" local/remote port %u/%u\n", - UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); - - etimer_set(&et, 5 * CLOCK_SECOND); - while(1) { - PROCESS_YIELD(); - if (etimer_expired(&et)) { - send_data(); - etimer_reset(&et); - } else if (ev == tcpip_event) { - handle_incoming_data(); - } - } - - PROCESS_END(); -} diff --git a/examples/rest-example/coap-client-server-example.csc b/examples/rest-example/coap-client-server-example.csc deleted file mode 100644 index bee90493b..000000000 --- a/examples/rest-example/coap-client-server-example.csc +++ /dev/null @@ -1,147 +0,0 @@ - - - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/serial_socket - - coap-client-server-example - -2147483648 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - sky1 - CoapServer - [CONTIKI_DIR]/examples/rest-example/rest-server-example.c - make rest-server-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/rest-server-example.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - sky2 - CoapClient - [CONTIKI_DIR]/examples/rest-example/coap-client-example.c - make coap-client-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/coap-client-example.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 54.5338749671737 - 36.41934631024719 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 49.41583327244326 - 52.00647916206431 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - sky2 - - - - org.contikios.cooja.plugins.SimControl - 318 - 2 - 172 - 0 - 0 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 3.686023978928717 0.0 0.0 3.686023978928717 -20.14794638096936 -127.69712925102564 - - 271 - 0 - 211 - 666 - 41 - - - org.contikios.cooja.plugins.LogListener - - - - 1263 - 1 - 199 - 0 - 339 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - 125 - 500.0 - - 1263 - 3 - 150 - 0 - 538 - - - diff --git a/examples/rest-example/rest-server-example.c b/examples/rest-example/rest-server-example.c deleted file mode 100644 index 24b33ff15..000000000 --- a/examples/rest-example/rest-server-example.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include "contiki.h" -#include "contiki-net.h" -#include "rest.h" - -#if defined (PLATFORM_HAS_LIGHT) -#include "dev/light-sensor.h" -#endif -#if defined (PLATFORM_HAS_BATT) -#include "dev/battery-sensor.h" -#endif -#if defined (PLATFORM_HAS_SHT11) -#include "dev/sht11/sht11-sensor.h" -#endif -#if defined (PLATFORM_HAS_LEDS) -#include "dev/leds.h" -#endif - -#define DEBUG 1 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -char temp[100]; - -/* Resources are defined by RESOURCE macro, signature: resource name, the http methods it handles and its url*/ -RESOURCE(helloworld, METHOD_GET, "helloworld"); - -/* For each resource defined, there corresponds an handler method which should be defined too. - * Name of the handler method should be [resource name]_handler - * */ -void -helloworld_handler(REQUEST* request, RESPONSE* response) -{ - sprintf(temp,"Hello World!\n"); - - rest_set_header_content_type(response, TEXT_PLAIN); - rest_set_response_payload(response, (uint8_t*)temp, strlen(temp)); -} - -RESOURCE(discover, METHOD_GET, ".well-known/core"); -void -discover_handler(REQUEST* request, RESPONSE* response) -{ - char temp[100]; - int index = 0; - index += sprintf(temp + index, "%s,", ";n=\"HelloWorld\""); -#if defined (PLATFORM_HAS_LEDS) - index += sprintf(temp + index, "%s,", ";n=\"LedControl\""); -#endif -#if defined (PLATFORM_HAS_LIGHT) - index += sprintf(temp + index, "%s", ";n=\"Light\""); -#endif - - rest_set_response_payload(response, (uint8_t*)temp, strlen(temp)); - rest_set_header_content_type(response, APPLICATION_LINK_FORMAT); -} - -#if defined (PLATFORM_HAS_LIGHT) -uint16_t light_photosynthetic; -uint16_t light_solar; - -void -read_light_sensor(uint16_t* light_1, uint16_t* light_2) -{ - *light_1 = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); - *light_2 = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); -} - -/*A simple getter example. Returns the reading from light sensor with a simple etag*/ -RESOURCE(light, METHOD_GET, "light"); -void -light_handler(REQUEST* request, RESPONSE* response) -{ - read_light_sensor(&light_photosynthetic, &light_solar); - sprintf(temp,"%u;%u", light_photosynthetic, light_solar); - - char etag[4] = "ABCD"; - rest_set_header_content_type(response, TEXT_PLAIN); - rest_set_header_etag(response, etag, sizeof(etag)); - rest_set_response_payload(response, temp, strlen(temp)); -} -#endif /*PLATFORM_HAS_LIGHT*/ - -#if defined (PLATFORM_HAS_LEDS) -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ -RESOURCE(led, METHOD_POST | METHOD_PUT , "led"); - -void -led_handler(REQUEST* request, RESPONSE* response) -{ - char color[10]; - char mode[10]; - uint8_t led = 0; - int success = 1; - - if (rest_get_query_variable(request, "color", color, 10)) { - PRINTF("color %s\n", color); - - if (!strcmp(color,"red")) { - led = LEDS_RED; - } else if(!strcmp(color,"green")) { - led = LEDS_GREEN; - } else if ( !strcmp(color,"blue") ) { - led = LEDS_BLUE; - } else { - success = 0; - } - } else { - success = 0; - } - - if (success && rest_get_post_variable(request, "mode", mode, 10)) { - PRINTF("mode %s\n", mode); - - if (!strcmp(mode, "on")) { - leds_on(led); - } else if (!strcmp(mode, "off")) { - leds_off(led); - } else { - success = 0; - } - } else { - success = 0; - } - - if (!success) { - rest_set_response_status(response, BAD_REQUEST_400); - } -} - - -/*A simple actuator example. Toggles the red led*/ -RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "toggle"); -void -toggle_handler(REQUEST* request, RESPONSE* response) -{ - leds_toggle(LEDS_RED); -} -#endif /*defined (CONTIKI_HAS_LEDS)*/ - - -PROCESS(rest_server_example, "Rest Server Example"); -AUTOSTART_PROCESSES(&rest_server_example); - -PROCESS_THREAD(rest_server_example, ev, data) -{ - PROCESS_BEGIN(); - -#ifdef WITH_COAP - PRINTF("COAP Server\n"); -#else - PRINTF("HTTP Server\n"); -#endif - - rest_init(); - -#if defined (PLATFORM_HAS_LIGHT) - SENSORS_ACTIVATE(light_sensor); - rest_activate_resource(&resource_light); -#endif -#if defined (PLATFORM_HAS_LEDS) - rest_activate_resource(&resource_led); - rest_activate_resource(&resource_toggle); -#endif /*defined (PLATFORM_HAS_LEDS)*/ - - rest_activate_resource(&resource_helloworld); - rest_activate_resource(&resource_discover); - - PROCESS_END(); -} diff --git a/examples/rest-example/rest-server-example.csc b/examples/rest-example/rest-server-example.csc deleted file mode 100644 index 3b598c66a..000000000 --- a/examples/rest-example/rest-server-example.csc +++ /dev/null @@ -1,185 +0,0 @@ - - - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/serial_socket - - REST with RPL router - -2147483648 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - org.contikios.cooja.mspmote.SkyMoteType - skyweb - Rest - [CONTIKI_DIR]/examples/rest-example/rest-server-example.c - make rest-server-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/rest-server-example.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 62.239287566073514 - 34.43810269527116 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - skyweb - - - - - org.contikios.cooja.interfaces.Position - 47.68359039801751 - 47.26544238238854 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - skyweb - - - - org.contikios.cooja.plugins.SimControl - 259 - 1 - 179 - 0 - 0 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - 10.505309204322225 0.0 0.0 10.505309204322225 -249.89475921566975 -141.01191150973983 - - 819 - 5 - 563 - 35 - 306 - - - org.contikios.cooja.plugins.LogListener - - - - 762 - 0 - 326 - 36 - 296 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - - 815 - 4 - 385 - 255 - 8 - - - SerialSocketServer - 0 - 422 - 3 - 74 - 1234 - 93 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - - 125 - 25.49079397896416 - - 1624 - 2 - 252 - 166 - 699 - - - diff --git a/examples/rime/Makefile b/examples/rime/Makefile index e35d8f1e9..f46fc2fbf 100644 --- a/examples/rime/Makefile +++ b/examples/rime/Makefile @@ -1,7 +1,7 @@ CONTIKI = ../.. all: example-abc example-mesh example-collect example-trickle example-polite \ - example-rudolph0 example-rudolph1 example-rudolph2 example-rucb \ + example-rudolph1 example-rudolph2 example-rucb \ example-runicast example-unicast example-neighbors CONTIKI_WITH_RIME = 1 diff --git a/examples/rime/example-rudolph0.c b/examples/rime/example-rudolph0.c deleted file mode 100644 index 196340f1c..000000000 --- a/examples/rime/example-rudolph0.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * Testing the rudolph0 code in Rime - * \author - * Adam Dunkels - */ - -#include "contiki.h" -#include "cfs/cfs.h" -#include "net/rime/rudolph0.h" - -#include "dev/button-sensor.h" - -#include "dev/leds.h" - -#include - -#define FILESIZE 200 - -/*---------------------------------------------------------------------------*/ -PROCESS(example_rudolph0_process, "Rudolph0 example"); -AUTOSTART_PROCESSES(&example_rudolph0_process); -/*---------------------------------------------------------------------------*/ -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - int fd; - - if(flag == RUDOLPH0_FLAG_NEWFILE) { - /* printf("+++ rudolph0 new file incoming at %lu\n", clock_time());*/ - leds_on(LEDS_RED); - fd = cfs_open("codeprop.out", CFS_WRITE); - } else { - fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - } - - if(datalen > 0) { - int ret; - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_write(fd, data, datalen); - /* printf("write_chunk wrote %d bytes at %d, %d\n", ret, offset, (unsigned char)data[0]);*/ - } - - cfs_close(fd); - - if(flag == RUDOLPH0_FLAG_LASTCHUNK) { - int i; - /* printf("+++ rudolph0 entire file received at %lu\n", clock_time());*/ - leds_off(LEDS_RED); - leds_on(LEDS_YELLOW); - fd = cfs_open("hej", CFS_READ); - for(i = 0; i < FILESIZE; ++i) { - unsigned char buf; - cfs_read(fd, &buf, 1); - if(buf != (unsigned char)i) { - printf("error: diff at %d, %d != %d\n", i, i, buf); - break; - } - } - cfs_close(fd); - } -} -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int fd; - int ret; - - fd = cfs_open("hej", CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - cfs_close(fd); - return ret; -} -const static struct rudolph0_callbacks rudolph0_call = {write_chunk, - read_chunk}; -static struct rudolph0_conn rudolph0; -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(example_rudolph0_process, ev, data) -{ - static int fd; - - PROCESS_EXITHANDLER(rudolph0_close(&rudolph0);) - - PROCESS_BEGIN(); - - PROCESS_PAUSE(); - - - rudolph0_open(&rudolph0, 138, &rudolph0_call); - SENSORS_ACTIVATE(button_sensor); - - while(1) { - PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event && - data == &button_sensor); - { - int i; - - fd = cfs_open("hej", CFS_WRITE); - for(i = 0; i < FILESIZE; i++) { - unsigned char buf = i; - cfs_write(fd, &buf, 1); - } - cfs_close(fd); - } - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); - - PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event && - data == &button_sensor); - rudolph0_stop(&rudolph0); - - } - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/seedeye/powerswitch/Makefile b/examples/seedeye/powerswitch/Makefile index 6e12ccc81..683da4226 100644 --- a/examples/seedeye/powerswitch/Makefile +++ b/examples/seedeye/powerswitch/Makefile @@ -7,42 +7,8 @@ all: remotepowerswitch CONTIKI=../../../ CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" -WITH_COAP=13 - -# REST framework, requires WITH_COAP -ifeq ($(WITH_COAP), 13) -${info INFO: compiling with CoAP-13} -CFLAGS += -DWITH_COAP=13 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-13 -else ifeq ($(WITH_COAP), 12) -${info INFO: compiling with CoAP-12} -CFLAGS += -DWITH_COAP=12 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-12 -else ifeq ($(WITH_COAP), 7) -${info INFO: compiling with CoAP-08} -CFLAGS += -DWITH_COAP=7 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-07 -else ifeq ($(WITH_COAP), 3) -${info INFO: compiling with CoAP-03} -CFLAGS += -DWITH_COAP=3 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-03 -else -${info INFO: compiling with HTTP} -CFLAGS += -DWITH_HTTP -CFLAGS += -DREST=http_rest_implementation -CFLAGS += -DUIP_CONF_TCP=1 -APPS += er-http-engine -endif - -APPS += erbium +APPS += er-coap +APPS += rest-engine CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include diff --git a/examples/seedeye/powerswitch/remotepowerswitch.c b/examples/seedeye/powerswitch/remotepowerswitch.c index 3bcfb10f3..04d3ea3c5 100644 --- a/examples/seedeye/powerswitch/remotepowerswitch.c +++ b/examples/seedeye/powerswitch/remotepowerswitch.c @@ -1,13 +1,13 @@ /* * Remote Power Switch Example for the Seed-Eye Board * Copyright (c) 2013, Giovanni Pellerano - * + * * Ownership: Scuola Superiore Sant'Anna (http://www.sssup.it) and * Consorzio Nazionale Interuniversitario per le Telecomunicazioni * (http://www.cnit.it). * * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,7 +33,7 @@ * SUCH DAMAGE. * */ - + /** * \addtogroup Remote Power Switch Example for the Seed-Eye Board * @@ -55,20 +55,21 @@ #include "contiki.h" #include "contiki-net.h" -#include "erbium.h" +#include "rest-engine.h" #include "dev/leds.h" #include -RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "actuators/powerswitch", "title=\"Red LED\";rt=\"Control\""); void toggle_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); - + PORTEbits.RE0 = !PORTEbits.RE0; } +RESOURCE(resource_toggle, "title=\"Red LED\";rt=\"Control\"", toggle_handler, toggle_handler, toggle_handler, NULL); + PROCESS(remote_power_switch, "Remote Power Switch"); @@ -79,11 +80,11 @@ PROCESS_THREAD(remote_power_switch, ev, data) PROCESS_BEGIN(); rest_init_engine(); - + TRISEbits.TRISE0 = 0; PORTEbits.RE0 = 0; - rest_activate_resource(&resource_toggle); + rest_activate_resource(&resource_toggle, "actuators/powerswitch"); while(1) { PROCESS_WAIT_EVENT(); diff --git a/examples/sky-shell/sky-upload.c b/examples/sky-shell/sky-upload.c index 703b450bc..7d4b221ac 100644 --- a/examples/sky-shell/sky-upload.c +++ b/examples/sky-shell/sky-upload.c @@ -58,7 +58,6 @@ PROCESS_THREAD(test_shell_process, ev, data) shell_coffee_init(); shell_exec_init(); shell_file_init(); - shell_netfile_init(); shell_ps_init(); shell_rime_init(); shell_rime_netcmd_init(); diff --git a/examples/sky/tcprudolph0.c b/examples/sky/tcprudolph0.c deleted file mode 100644 index 1dfea085f..000000000 --- a/examples/sky/tcprudolph0.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2005, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -#include -#include - -#include "contiki.h" -#include "sys/etimer.h" -#include "loader/elfloader.h" - -#include "net/ip/uip.h" - -#include "dev/leds.h" - -#include "cfs/cfs.h" - -#include "codeprop.h" - -#include "net/rime/rudolph0.h" - -#include - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -PROCESS(tcp_loader_process, "TCP loader"); -AUTOSTART_PROCESSES(&tcp_loader_process); - -static -struct codeprop_state { - uint16_t addr; - uint16_t len; - struct pt tcpthread_pt; - int fd; -} s; - -static char msg[30 + 10]; - -static struct rudolph0_conn rudolph0; - -/*---------------------------------------------------------------------*/ -static int -start_program(void) -{ - /* Link, load, and start new program. */ - int ret; - s.fd = cfs_open("codeprop.out", CFS_READ); - ret = elfloader_load(s.fd); - - /* XXX: Interrupts seems to be turned off a little too long during the - ELF loading process, so we need to "manually" trigger a timer - interrupt here. */ - TACCR1 = TAR + 1000; - - if(ret == ELFLOADER_OK) { - sprintf(msg, "ok\n"); - PRINTF("Ok, starting new program.\n"); - /* Start processes. */ - autostart_start(elfloader_autostart_processes); - } else { - sprintf(msg, "err %d %s", ret, elfloader_unknown); - PRINTF("Error: '%s'.\n", msg); - } - cfs_close(s.fd); - return ret; -} -/*---------------------------------------------------------------------*/ -static -PT_THREAD(recv_tcpthread(struct pt *pt)) -{ - PT_BEGIN(pt); - - /* Read the header. */ - PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0); - - if(uip_datalen() < sizeof(struct codeprop_tcphdr)) { - PRINTF(("codeprop: header not found in first tcp segment\n")); - uip_abort(); - goto thread_done; - } - - /* Kill old program. */ - rudolph0_stop(&rudolph0); - /* elfloader_unload();*/ - - s.len = uip_htons(((struct codeprop_tcphdr *)uip_appdata)->len); - s.addr = 0; - uip_appdata += sizeof(struct codeprop_tcphdr); - uip_len -= sizeof(struct codeprop_tcphdr); - - s.fd = cfs_open("codeprop.out", CFS_WRITE); - cfs_close(s.fd); - /* xmem_erase(XMEM_ERASE_UNIT_SIZE, EEPROMFS_ADDR_CODEPROP);*/ - - /* Read the rest of the data. */ - do { - leds_toggle(LEDS_RED); - if(uip_len > 0) { - s.fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - cfs_seek(s.fd, s.addr, CFS_SEEK_SET); - /* xmem_pwrite(uip_appdata, uip_len, EEPROMFS_ADDR_CODEPROP + s.addr);*/ - cfs_write(s.fd, uip_appdata, uip_len); - cfs_close(s.fd); - - PRINTF("Wrote %d bytes to file\n", uip_len); - s.addr += uip_len; - } - if(s.addr < s.len) { - PT_YIELD_UNTIL(pt, uip_newdata()); - } - } while(s.addr < s.len); - leds_off(LEDS_RED); - -#if DEBUG - { - int i, fd, j; - printf("Contents of file:\n"); - fd = cfs_open("codeprop.out", CFS_READ); - j = 0; - printf("\n0x%04x: ", 0); - for(i = 0; i < s.len; ++i) { - unsigned char byte; - cfs_read(fd, &byte, 1); - printf("0x%02x, ", byte); - ++j; - if(j == 8) { - printf("\n0x%04x: ", i + 1); - j = 0; - } - clock_delay(400); - } - cfs_close(fd); - } -#endif - - int ret; - - ret = start_program(); - -#if CONTIKI_TARGET_NETSIM - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); -#else /* CONTIKI_TARGET_NETSIM */ - if(ret == ELFLOADER_OK) { - /* Propagate program. */ - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); - } -#endif /* CONTIKI_TARGET_NETSIM */ - - /* Return "ok" message. */ - do { - ret = strlen(msg); - uip_send(msg, ret); - PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed()); - } while(uip_rexmit()); - - /* Close the connection. */ - uip_close(); - - - thread_done:; - PT_END(pt); -} -/*---------------------------------------------------------------------*/ -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - int fd; - - leds_toggle(LEDS_YELLOW); - - if(flag == RUDOLPH0_FLAG_NEWFILE) { - printf("+++ rudolph0 new file incoming at %u\n", clock_time()); - fd = cfs_open("codeprop.out", CFS_WRITE); - - if(elfloader_autostart_processes != NULL) { - PRINTF("Stopping old programs.\n"); - autostart_exit(elfloader_autostart_processes); - elfloader_autostart_processes = NULL; - } - - } else { - fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - } - - if(datalen > 0) { - int ret; - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_write(fd, data, datalen); - /* printf("write_chunk wrote %d bytes at %d, %d\n", ret, offset, (unsigned char)data[0]);*/ - } - - cfs_close(fd); - - if(flag == RUDOLPH0_FLAG_LASTCHUNK) { - printf("+++ rudolph0 entire file received at %u\n", clock_time()); - start_program(); - leds_off(LEDS_YELLOW); - } -} -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int fd; - int ret; - - leds_toggle(LEDS_GREEN); - - fd = cfs_open("codeprop.out", CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - if(ret < maxsize) { - leds_off(LEDS_GREEN); - } - cfs_close(fd); - return ret; -} -const static struct rudolph0_callbacks rudolph0_call = {write_chunk, - read_chunk}; -/*---------------------------------------------------------------------*/ -PROCESS_THREAD(tcp_loader_process, ev, data) -{ - PROCESS_BEGIN(); - - rudolph0_open(&rudolph0, 20, &rudolph0_call); - - tcp_listen(UIP_HTONS(CODEPROP_DATA_PORT)); - - while(1) { - PROCESS_YIELD(); - if(ev == tcpip_event && uip_conn->lport == UIP_HTONS(CODEPROP_DATA_PORT)) { - if(uip_connected()) { /* Really uip_connecting()!!! */ - if(data == NULL) { - PT_INIT(&s.tcpthread_pt); - process_poll(&tcp_loader_process); - tcp_markconn(uip_conn, &s); - - if(elfloader_autostart_processes != NULL) { - PRINTF("Stopping old programs.\n"); - autostart_exit(elfloader_autostart_processes); - elfloader_autostart_processes = NULL; - } - } else { - PRINTF(("codeprop: uip_connected() and data != NULL\n")); - uip_abort(); - } - } - recv_tcpthread(&s.tcpthread_pt); /* Run thread */ - - if(uip_closed() || uip_aborted() || uip_timedout()) { - PRINTF(("codeprop: connection down\n")); - tcp_markconn(uip_conn, NULL); - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------*/ -#include "net/rime/collect.h" -#include "net/rime/mesh.h" -#include "net/rime/rudolph0.h" -#include "net/rime/rudolph1.h" -void -dummy(void) -{ - /* Make sure that all Rime modules are present in the core */ - collect_close(NULL); - mesh_close(NULL); - ipolite_close(NULL); - polite_close(NULL); - ruc_close(NULL); - sibc_close(NULL); - rudolph0_close(NULL); - rudolph1_close(NULL); - - /* Make sure psock is included */ - psock_datalen(NULL); -} -/*---------------------------------------------------------------------*/ diff --git a/examples/z1/Makefile b/examples/z1/Makefile index 4273b9687..220f1f274 100644 --- a/examples/z1/Makefile +++ b/examples/z1/Makefile @@ -7,7 +7,7 @@ ZOLERTIA_Z1SP=0 CONTIKI_PROJECT = test-phidgets blink test-adxl345 test-tmp102 test-light-ziglet CONTIKI_PROJECT += test-battery test-relay-phidget test-tlc59116 test-sht25 -CONTIKI_SOURCEFILES += sht11.c +CONTIKI_SOURCEFILES += sht11.c reed-sensor.c APPS=serial-shell ifeq ($(ZOLERTIA_Z1SP),1) diff --git a/examples/rest-example/project-conf.h b/examples/z1/test-reed-sensor.c similarity index 54% rename from examples/rest-example/project-conf.h rename to examples/z1/test-reed-sensor.c index 7019c021a..799f913cf 100644 --- a/examples/rest-example/project-conf.h +++ b/examples/z1/test-reed-sensor.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2015, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,35 +26,48 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * This file is part of the Contiki operating system. * */ +/** + * \file + * A quick program for testing a reed sensor. + * \author + * Antonio Lignan + */ -#ifndef PROJECT_RPL_WEB_CONF_H_ -#define PROJECT_RPL_WEB_CONF_H_ +#include +#include "contiki.h" +#include "reed-sensor.h" +#define REED_READ_INTERVAL (CLOCK_SECOND / 4) +#define REED_EXAMPLE_EVENT 1 +/*---------------------------------------------------------------------------*/ +PROCESS(test_process, "Reed test process"); +AUTOSTART_PROCESSES(&test_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(test_process, ev, data) +{ + PROCESS_BEGIN(); -/* Disabling RDC and CSMA for demo purposes. Core updates often - require more memory. */ -/* For projects, optimize memory and enable RDC and CSMA again. */ -#undef NETSTACK_CONF_RDC -#define NETSTACK_CONF_RDC nullrdc_driver - -#undef NETSTACK_CONF_MAC -#define NETSTACK_CONF_MAC nullmac_driver - -#ifndef QUEUEBUF_CONF_NUM -#define QUEUEBUF_CONF_NUM 6 + SENSORS_ACTIVATE(reed_sensor); +#if REED_EXAMPLE_EVENT + reed_sensor.configure(REED_SENSOR_MODE, REED_SENSOR_EVENT_MODE); +#else + etimer_set(&et, REED_READ_INTERVAL); #endif -#ifndef UIP_CONF_BUFFER_SIZE -#define UIP_CONF_BUFFER_SIZE 140 -#endif + while(1) { -#ifndef UIP_CONF_RECEIVE_WINDOW -#define UIP_CONF_RECEIVE_WINDOW 60 -#endif + PROCESS_YIELD(); -#ifndef WEBSERVER_CONF_CFS_CONNS -#define WEBSERVER_CONF_CFS_CONNS 2 -#endif - -#endif /* PROJECT_RPL_WEB_CONF_H_ */ + if(ev == PROCESS_EVENT_TIMER) { + printf("Reed poll status [%d]\n", reed_sensor.value(REED_SENSOR_VAL)); + etimer_restart(&et); + } else if(ev == reed_sensor_event_changed) { + printf("Reed sensor event --> %d\n", (*((int *)data))); + } + } + PROCESS_END(); +} diff --git a/platform/apple2enh/Makefile.apple2enh b/platform/apple2enh/Makefile.apple2enh index ca1d45970..2bc8c4626 100644 --- a/platform/apple2enh/Makefile.apple2enh +++ b/platform/apple2enh/Makefile.apple2enh @@ -55,7 +55,7 @@ endif disk: all cp $(CONTIKI)/tools/$(TARGET)/prodos.dsk contiki.dsk - java -jar $(AC) -p contiki.dsk contiki.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p contiki.dsk contiki.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 contiki.dsk contiki bin < $(CONTIKI_PROJECT).$(TARGET) java -jar $(AC) -p contiki.dsk contiki.cfg bin 0 < $(CONTIKI)/tools/$(TARGET)/sample.cfg java -jar $(AC) -p contiki.dsk cs8900a.eth rel 0 < cs8900a.eth diff --git a/platform/apple2enh/contiki-conf.h b/platform/apple2enh/contiki-conf.h index 3f96da1aa..4326efe2d 100644 --- a/platform/apple2enh/contiki-conf.h +++ b/platform/apple2enh/contiki-conf.h @@ -64,5 +64,6 @@ #define WWW_CONF_MAX_FORMACTIONLEN 20 #define WWW_CONF_MAX_INPUTNAMELEN 20 #define WWW_CONF_MAX_INPUTVALUELEN 20 +#define WWW_CONF_WGET_EXEC(url) exec("wget", url) #endif /* CONTIKI_CONF_H_ */ diff --git a/platform/apple2enh/contiki-main.c b/platform/apple2enh/contiki-main.c index 0d0751c1a..8a42a53da 100644 --- a/platform/apple2enh/contiki-main.c +++ b/platform/apple2enh/contiki-main.c @@ -104,7 +104,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/apple2enh/lib/pfs.S b/platform/apple2enh/lib/pfs.S index 00101d329..ed44dfc1e 100644 --- a/platform/apple2enh/lib/pfs.S +++ b/platform/apple2enh/lib/pfs.S @@ -32,13 +32,14 @@ ; ;--------------------------------------------------------------------- .constructor init_pfs - .destructor done_pfs + .destructor done_pfs .importzp ptr1 - .import popax, _uip_aligned_buf - .export _pfs_open, _pfs_read, _pfs_close + .import popax, _uip_aligned_buf + .export _pfs_open, _pfs_read, _pfs_close ;--------------------------------------------------------------------- pathname := $0280 mli := $BF00 +level := $BF94 OPEN_CALL = $C8 READ_CALL = $CA @@ -68,8 +69,11 @@ close_fd: .byte $00 ;REF_NUM .segment "INIT" init_pfs: - ; Get prefix len of path used to load binary - ldx pathname + ; Allow exec() to keep file open + inc level + + ; Get prefix len of path used to load binary + ldx pathname : lda pathname,x cmp #'/' beq :+ @@ -80,6 +84,15 @@ init_pfs: ;--------------------------------------------------------------------- .code +done_pfs: + ; Close all file + lda #$00 + jsr _pfs_close + + ; Allow exec() to keep file open + dec level + rts + _pfs_open: ; Pop and store name jsr popax @@ -131,11 +144,8 @@ _pfs_read: ldx read_count_out+1 rts -done_pfs: - lda #$00 - _pfs_close: - ; Store fd + ; Store fd sta close_fd jsr mli @@ -147,6 +157,6 @@ _pfs_close: error: ; Return -1 lda #$FF - tax - rts + tax + rts ;--------------------------------------------------------------------- diff --git a/platform/atarixl/contiki-main.c b/platform/atarixl/contiki-main.c index 61cd4c7bb..91cb35367 100644 --- a/platform/atarixl/contiki-main.c +++ b/platform/atarixl/contiki-main.c @@ -100,7 +100,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/avr-atmega128rfa1/contiki-conf.h b/platform/avr-atmega128rfa1/contiki-conf.h index 47f5c6584..545f6a253 100644 --- a/platform/avr-atmega128rfa1/contiki-conf.h +++ b/platform/avr-atmega128rfa1/contiki-conf.h @@ -191,8 +191,6 @@ typedef unsigned short uip_stats_t; #define CHANNEL_802_15_4 26 /* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ #define RF230_CONF_AUTOACK 1 -/* Request 802.15.4 ACK on all packets sent (else autoretry). This is primarily for testing. */ -#define SICSLOWPAN_CONF_ACK_ALL 0 /* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode) */ #define RF230_CONF_FRAME_RETRIES 2 /* Number of csma retry attempts 0-5 in extended tx mode (7 does immediate tx with no csma) */ diff --git a/platform/avr-raven/contiki-conf.h b/platform/avr-raven/contiki-conf.h index 40469aa21..2fe0d6099 100644 --- a/platform/avr-raven/contiki-conf.h +++ b/platform/avr-raven/contiki-conf.h @@ -206,8 +206,6 @@ typedef unsigned short uip_stats_t; #define RADIO_CONF_CALIBRATE_INTERVAL 256 /* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ #define RF230_CONF_AUTOACK 1 -/* Request 802.15.4 ACK on all packets sent (else autoretry). This is primarily for testing. */ -#define SICSLOWPAN_CONF_ACK_ALL 0 /* Number of auto retry attempts+1, 1-16. Set zero to disable extended TX_ARET_ON mode with CCA) */ #define RF230_CONF_FRAME_RETRIES 3 /* Number of CSMA attempts 0-7. 802.15.4 2003 standard max is 5. */ diff --git a/platform/avr-ravenusb/contiki-conf.h b/platform/avr-ravenusb/contiki-conf.h index 03001d02a..1ebe6d718 100644 --- a/platform/avr-ravenusb/contiki-conf.h +++ b/platform/avr-ravenusb/contiki-conf.h @@ -284,9 +284,6 @@ typedef unsigned short uip_stats_t; #define RADIO_CONF_CALIBRATE_INTERVAL 256 /* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ #define RF230_CONF_AUTOACK 1 -/* Request 802.15.4 ACK on all packets sent by sicslowpan.c (else autoretry) */ -/* Broadcasts will be duplicated by the retry count, since no one will ACK them! */ -#define SICSLOWPAN_CONF_ACK_ALL 0 /* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode with CCA) */ #define RF230_CONF_FRAME_RETRIES 2 /* CCA theshold energy -91 to -61 dBm (default -77). Set this smaller than the expected minimum rssi to avoid packet collisions */ diff --git a/platform/avr-rcb/contiki-conf.h b/platform/avr-rcb/contiki-conf.h index 3ecb788db..df67fbc81 100644 --- a/platform/avr-rcb/contiki-conf.h +++ b/platform/avr-rcb/contiki-conf.h @@ -110,12 +110,8 @@ void clock_adjust_ticks(clock_time_t howmany); #define QUEUEBUF_CONF_NUM 15 /* 54 bytes per queue ref buffer */ #define QUEUEBUF_CONF_REF_NUM 2 -/* 0 for IPv6, or 1 for HC1, 2 for HC01 */ -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 -#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC01 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #define SICSLOWPAN_CONF_FRAG 1 @@ -135,8 +131,6 @@ void clock_adjust_ticks(clock_time_t howmany); #define UIP_CONF_IPV6_QUEUE_PKT 0 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #if NETSTACK_CONF_WITH_IPV6 //tcpip.c error on ipv4 build if UIP_CONF_ICMP6 defined #define UIP_CONF_ICMP6 1 #endif diff --git a/platform/avr-zigbit/contiki-conf.h b/platform/avr-zigbit/contiki-conf.h index 57178721d..56ffff826 100644 --- a/platform/avr-zigbit/contiki-conf.h +++ b/platform/avr-zigbit/contiki-conf.h @@ -108,7 +108,6 @@ void clock_adjust_ticks(clock_time_t howmany); /* The new NETSTACK interface requires RF230BB */ #if RF230BB #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 //for barebones driver, sicslowpan calls radio->read function #undef PACKETBUF_CONF_HDR_SIZE //RF230BB takes the packetbuf default for header size #define UIP_CONF_LLH_LEN 0 @@ -136,20 +135,16 @@ void clock_adjust_ticks(clock_time_t howmany); #else /* Original combined RF230/mac code will not compile with current contiki stack */ //#define PACKETBUF_CONF_HDR_SIZE 0 //RF230 handles headers internally -/* 0 for IPv6, or 1 for HC1, 2 for HC01 */ -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 //NB '2' is now HC06 in the core mac! //FTH081105 -#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_CONF_COMPRESSION_HC01 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #define SICSLOWPAN_CONF_MAXAGE 5 #define UIP_CONF_LLH_LEN 14 #endif /*RF230BB */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_FRAG 1 -#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LL_802154 1 #define UIP_CONF_MAX_CONNECTIONS 2 #define UIP_CONF_MAX_LISTENPORTS 2 @@ -159,11 +154,9 @@ void clock_adjust_ticks(clock_time_t howmany); #define UIP_CONF_FWCACHE_SIZE 0 #define UIP_CONF_IPV6_CHECKS 1 -#define UIP_CONF_IPV6_QUEUE_PKT 0 +#define UIP_CONF_IPV6_QUEUE_PKT 0 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_UDP_CHECKSUMS 1 #define UIP_CONF_TCP_SPLIT 1 diff --git a/platform/c128/contiki-main.c b/platform/c128/contiki-main.c index c3d15f478..d28f24f75 100644 --- a/platform/c128/contiki-main.c +++ b/platform/c128/contiki-main.c @@ -100,7 +100,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/c64/contiki-main.c b/platform/c64/contiki-main.c index 57a333f0b..b5cc59a9c 100644 --- a/platform/c64/contiki-main.c +++ b/platform/c64/contiki-main.c @@ -98,7 +98,7 @@ main(void) uip_setdraddr(&addr); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); ethernet_config = &config; } diff --git a/platform/cc2538dk/Makefile.cc2538dk b/platform/cc2538dk/Makefile.cc2538dk index a760ee5a1..5c3fd77ec 100644 --- a/platform/cc2538dk/Makefile.cc2538dk +++ b/platform/cc2538dk/Makefile.cc2538dk @@ -9,10 +9,7 @@ CONTIKI_TARGET_DIRS = . dev CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += contiki-main.c CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c -CONTIKI_TARGET_SOURCEFILES += button-sensor.c adc-sensor.c - -TARGET_START_SOURCEFILES += startup-gcc.c -TARGET_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(TARGET_START_SOURCEFILES)}} +CONTIKI_TARGET_SOURCEFILES += button-sensor.c als-sensor.c CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 4cb83fdd2..91e8b7e7c 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -74,10 +74,9 @@ The toolchain used to build contiki is arm-gcc, also used by other arm-based Con Thread model: single gcc version 4.3.2 (Sourcery G++ Lite 2008q3-66) -The platform is currently being used/tested with the following toolchains: +The platform is currently being used/tested with "GNU Tools for ARM Embedded Processors". This is the recommended version and the one being used by Contiki's regression tests on Travis. -* GNU Tools for ARM Embedded Processors. This is the recommended version. Works nicely on OS X. -* Alternatively, you can use this older version for Linux. At the time of writing, this is the version used by Contiki's regression tests. +The older version (Sourcery G++ Lite 2008q3-66) shown above should still work, but the port is no longer being tested with it. Drivers ------- diff --git a/platform/cc2538dk/contiki-main.c b/platform/cc2538dk/contiki-main.c index 4487a07f2..71de03a10 100644 --- a/platform/cc2538dk/contiki-main.c +++ b/platform/cc2538dk/contiki-main.c @@ -43,6 +43,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" +#include "dev/adc.h" #include "dev/leds.h" #include "dev/sys-ctrl.h" #include "dev/scb.h" @@ -208,6 +209,8 @@ main(void) process_start(&tcpip_process, NULL); #endif /* NETSTACK_CONF_WITH_IPV6 */ + adc_init(); + process_start(&sensors_process, NULL); energest_init(); diff --git a/platform/cc2538dk/dev/adc-sensor.c b/platform/cc2538dk/dev/als-sensor.c similarity index 82% rename from platform/cc2538dk/dev/adc-sensor.c rename to platform/cc2538dk/dev/als-sensor.c index 4c2f1f853..2ecc857ea 100644 --- a/platform/cc2538dk/dev/adc-sensor.c +++ b/platform/cc2538dk/dev/als-sensor.c @@ -30,18 +30,18 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538dk-adc-sensor + * \addtogroup cc2538dk-als-sensor * @{ * * \file - * Driver for the SmartRF06EB ADC + * Driver for the SmartRF06EB ALS */ #include "contiki.h" #include "sys/clock.h" #include "dev/ioc.h" #include "dev/gpio.h" #include "dev/adc.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" #include @@ -52,30 +52,15 @@ static int value(int type) { - uint8_t channel; + uint8_t channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN; int16_t res; - switch(type) { - case ADC_SENSOR_VDD_3: - channel = SOC_ADC_ADCCON_CH_VDD_3; - break; - case ADC_SENSOR_TEMP: - channel = SOC_ADC_ADCCON_CH_TEMP; - break; - case ADC_SENSOR_ALS: - channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN; - GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); - clock_delay_usec(2000); - break; - default: - return 0; - } + GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + clock_delay_usec(2000); res = adc_get(channel, SOC_ADC_ADCCON_REF_INT, SOC_ADC_ADCCON_DIV_512); - if(type == ADC_SENSOR_ALS) { - GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); - } + GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); return res; } @@ -94,7 +79,6 @@ configure(int type, int value) GPIO_SET_INPUT(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK); ioc_set_over(GPIO_A_NUM, ADC_ALS_OUT_PIN, IOC_OVERRIDE_ANA); - adc_init(); break; } return 0; @@ -106,6 +90,6 @@ status(int type) return 1; } /*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status); +SENSORS_SENSOR(als_sensor, ALS_SENSOR, value, configure, status); /** @} */ diff --git a/platform/cc2538dk/dev/adc-sensor.h b/platform/cc2538dk/dev/als-sensor.h similarity index 79% rename from platform/cc2538dk/dev/adc-sensor.h rename to platform/cc2538dk/dev/als-sensor.h index b6d0efbdf..abed92e13 100644 --- a/platform/cc2538dk/dev/adc-sensor.h +++ b/platform/cc2538dk/dev/als-sensor.h @@ -33,33 +33,29 @@ * \addtogroup cc2538-smartrf-sensors * @{ * - * \defgroup cc2538dk-adc-sensor cc2538dk ADC Driver + * \defgroup cc2538dk-als-sensor cc2538dk ALS Driver * - * Driver for the SmartRF06EB ADC sensors + * Driver for the SmartRF06EB ALS sensor * @{ * * \file - * Header file for the cc2538dk ADC Driver + * Header file for the cc2538dk ALS Driver */ -#ifndef ADC_SENSOR_H_ -#define ADC_SENSOR_H_ +#ifndef ALS_SENSOR_H_ +#define ALS_SENSOR_H_ #include "lib/sensors.h" /*---------------------------------------------------------------------------*/ -/** \name ADC sensors +/** \name ALS sensor * @{ */ -#define ADC_SENSOR "ADC" - -#define ADC_SENSOR_VDD_3 0 /**< On-chip VDD / 3 */ -#define ADC_SENSOR_TEMP 1 /**< On-chip temperature */ -#define ADC_SENSOR_ALS 2 /**< Ambient light sensor */ +#define ALS_SENSOR "ALS" /** @} */ -extern const struct sensors_sensor adc_sensor; +extern const struct sensors_sensor als_sensor; -#endif /* ADC_SENSOR_H_ */ +#endif /* ALS_SENSOR_H_ */ /** * @} diff --git a/platform/cc2538dk/dev/smartrf-sensors.c b/platform/cc2538dk/dev/smartrf-sensors.c index 41d977783..76841af3b 100644 --- a/platform/cc2538dk/dev/smartrf-sensors.c +++ b/platform/cc2538dk/dev/smartrf-sensors.c @@ -42,13 +42,15 @@ */ #include "contiki.h" #include "dev/button-sensor.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" +#include "dev/cc2538-sensors.h" #include /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor, &adc_sensor); + &button_up_sensor, &button_down_sensor, &als_sensor, + &cc2538_temp_sensor, &vdd3_sensor); /** * @} diff --git a/platform/cooja-ip64/Makefile.cooja-ip64 b/platform/cooja-ip64/Makefile.cooja-ip64 new file mode 100644 index 000000000..d86077c57 --- /dev/null +++ b/platform/cooja-ip64/Makefile.cooja-ip64 @@ -0,0 +1,15 @@ +COOJAPLATFORMDIR=$(CONTIKI)/platform/cooja + +MODULES += core/net/ip64 +include $(COOJAPLATFORMDIR)/Makefile.cooja + +vpath %.c $(COOJAPLATFORMDIR) $(COOJAPLATFORMDIR)/dev \ + $(COOJAPLATFORMDIR)/net $(COOJAPLATFORMDIR)/lib \ + $(COOJAPLATFORMDIR)/sys $(COOJAPLATFORMDIR)/cfs +CFLAGS += -I $(COOJAPLATFORMDIR) + +CFLAGS += -DWITH_IP64=1 -DWITH_LARGE_BUFFER_SIZE=1 +CFLAGS += -DINCLUDE_SUBPLATFORM_CONF=1 + +%.cooja: %.cooja-ip64 + cp $< $@ diff --git a/platform/cooja-ip64/Makefile.customrules-cooja-ip64 b/platform/cooja-ip64/Makefile.customrules-cooja-ip64 new file mode 100644 index 000000000..3de3bc7c5 --- /dev/null +++ b/platform/cooja-ip64/Makefile.customrules-cooja-ip64 @@ -0,0 +1,50 @@ +### Define custom targets + +REDEF_PRINTF=1 # Redefine functions to enable printf()s inside Cooja + +# NB: Assumes ARCHIVE was not overridden and is in $(OBJECTDIR) +$(ARCHIVE): $(CONTIKI_OBJECTFILES) | $(OBJECTDIR) + ${subst obj_cooja/,$(OBJECTDIR)/,$(AR_COMMAND_1)} $^ $(AR_COMMAND_2) + +# NB: Assumes JNILIB was not overridden and is in $(OBJECTDIR) +$(JNILIB): $(CONTIKI_APP_OBJ) $(MAIN_OBJ) $(PROJECT_OBJECTFILES) $(ARCHIVE) | $(OBJECTDIR) +ifdef SYMBOLS + @echo Generating symbols + # Recreate symbols file and relink with final memory layout (twice) + ${CONTIKI}/tools/make-symbols-nm $(JNILIB) + $(CC) $(CFLAGS) -c symbols.c -o $(OBJECTDIR)/symbols.o + $(LINK_COMMAND_1) $^ $(LINK_COMMAND_2) + ${CONTIKI}/tools/make-symbols-nm $(JNILIB) + $(CC) $(CFLAGS) -c symbols.c -o $(OBJECTDIR)/symbols.o +endif ## SYMBOLS +ifdef REDEF_PRINTF + @echo Redefining printf + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym printf=log_printf $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym puts=log_puts $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym putchar=log_putchar $(OBJ); ) +endif ## REDEF_PRINTF + ${subst .cooja,.$(TARGET),${subst obj_cooja/,$(OBJECTDIR)/,$(LINK_COMMAND_1)}} $^ $(LINK_COMMAND_2) + +.PHONY: $(CONTIKI_APP).$(TARGET) +$(CONTIKI_APP).$(TARGET): $(JNILIB) + cp $(JNILIB) $@ + rm $(CONTIKI_APP_OBJ) + + mkdir -p obj_cooja + @-cp obj_cooja-ip64/$(LIBNAME).map obj_cooja/$(LIBNAME).map && echo Placed a copy of the map file at obj_cooja/$(LIBNAME).map + + cp obj_cooja-ip64/$(LIBNAME).cooja-ip64 obj_cooja/$(LIBNAME).cooja + @echo Placed a copy of the shared library at obj_cooja/$(LIBNAME).cooja + + cp $@ $(CONTIKI_APP).cooja + @echo Placed a copy of the shared library at $(CONTIKI_APP).cooja + +# Trickiness: GNU make matches this against the file base name. +# Assume that the directory part is the standard location. +mtype%.o: contiki-cooja-ip64-main.o | $(OBJECTDIR) + mv contiki-cooja-ip64-main.o $@ + +symbols.c: + # Create initial symbol files if not existing + cp ${CONTIKI}/tools/empty-symbols.c symbols.c + cp ${CONTIKI}/tools/empty-symbols.h symbols.h diff --git a/platform/cooja-ip64/contiki-cooja-ip64-main.c b/platform/cooja-ip64/contiki-cooja-ip64-main.c new file mode 100644 index 000000000..1077162a7 --- /dev/null +++ b/platform/cooja-ip64/contiki-cooja-ip64-main.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * COOJA Contiki mote main file. + * \author + * Fredrik Osterlind + */ + +#include +#include +#include + +#include "contiki.h" + +#include "sys/clock.h" +#include "sys/etimer.h" +#include "sys/cooja_mt.h" +#include "sys/autostart.h" + +#include "lib/random.h" +#include "lib/simEnvChange.h" + +#include "net/rime/rime.h" +#include "net/netstack.h" +#include "net/ip/uip-nameserver.h" + +#include "dev/serial-line.h" +#include "dev/cooja-radio.h" +#include "dev/button-sensor.h" +#include "dev/pir-sensor.h" +#include "dev/vib-sensor.h" + +#include "sys/node-id.h" + +#include "ip64.h" +#include "dev/slip.h" + +/* JNI-defined functions, depends on the environment variable CLASSNAME */ +#ifndef CLASSNAME +#error CLASSNAME is undefined, required by contiki-cooja-main.c +#endif /* CLASSNAME */ +#define COOJA__QUOTEME(a,b,c) COOJA_QUOTEME(a,b,c) +#define COOJA_QUOTEME(a,b,c) a##b##c +#define COOJA_JNI_PATH Java_org_contikios_cooja_corecomm_ +#define Java_org_contikios_cooja_corecomm_CLASSNAME_init COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_init) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_getMemory) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setMemory) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_tick COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_tick) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setReferenceAddress) + +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#define PRINT6ADDR(addr) printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) + +/* Simulation mote interfaces */ +SIM_INTERFACE_NAME(moteid_interface); +SIM_INTERFACE_NAME(vib_interface); +SIM_INTERFACE_NAME(rs232_interface); +SIM_INTERFACE_NAME(simlog_interface); +SIM_INTERFACE_NAME(beep_interface); +SIM_INTERFACE_NAME(radio_interface); +SIM_INTERFACE_NAME(button_interface); +SIM_INTERFACE_NAME(pir_interface); +SIM_INTERFACE_NAME(clock_interface); +SIM_INTERFACE_NAME(leds_interface); +SIM_INTERFACE_NAME(cfs_interface); +SIM_INTERFACES(&vib_interface, &moteid_interface, &rs232_interface, &simlog_interface, &beep_interface, &radio_interface, &button_interface, &pir_interface, &clock_interface, &leds_interface, &cfs_interface); +/* Example: manually add mote interfaces */ +//SIM_INTERFACE_NAME(dummy_interface); +//SIM_INTERFACES(..., &dummy_interface); + +/* Sensors */ +SENSORS(&button_sensor, &pir_sensor, &vib_sensor); + +/* + * referenceVar is used for comparing absolute and process relative memory. + * (this must not be static due to memory locations) + */ +long referenceVar; + +/* + * Contiki and rtimer threads. + */ +static struct cooja_mt_thread rtimer_thread; +static struct cooja_mt_thread process_run_thread; + +#define MIN(a, b) ( (a)<(b) ? (a) : (b) ) + +/*---------------------------------------------------------------------------*/ +static void +print_processes(struct process * const processes[]) +{ + /* const struct process * const * p = processes;*/ + printf("Starting"); + while(*processes != NULL) { + printf(" '%s'", (*processes)->name); + processes++; + } + putchar('\n'); +} +/*---------------------------------------------------------------------------*/ +static void +rtimer_thread_loop(void *data) +{ + while(1) + { + rtimer_arch_check(); + + /* Return to COOJA */ + cooja_mt_yield(); + } +} +/*---------------------------------------------------------------------------*/ +static void +set_mac_addr(void) +{ + linkaddr_t addr; + int i; + + memset(&addr, 0, sizeof(linkaddr_t)); + for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { + addr.u8[i + 1] = node_id & 0xff; + addr.u8[i + 0] = node_id >> 8; + } + linkaddr_set_node_addr(&addr); + printf("MAC address "); + for(i = 0; i < sizeof(addr.u8) - 1; i++) { + printf("%d.", addr.u8[i]); + } + printf("%d\n", addr.u8[i]); +} +/*---------------------------------------------------------------------------*/ +void +contiki_init(void) +{ + int i; + uint8_t addr[sizeof(uip_lladdr.addr)]; + uip_ipaddr_t ipaddr; + uip_ds6_addr_t *lladdr; + uip_ip4addr_t ipv4addr, netmask; + + /* Start process handler */ + process_init(); + + /* Start Contiki processes */ + process_start(&etimer_process, NULL); + process_start(&sensors_process, NULL); + ctimer_init(); + + /* Print startup information */ + printf(CONTIKI_VERSION_STRING " started. "); + if(node_id > 0) { + printf("Node id is set to %u.\n", node_id); + } else { + printf("Node id is not set.\n"); + } + + set_mac_addr(); + + queuebuf_init(); + + /* Initialize communication stack */ + netstack_init(); + printf("%s/%s/%s, channel check rate %lu Hz\n", + NETSTACK_NETWORK.name, NETSTACK_MAC.name, NETSTACK_RDC.name, + CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: + NETSTACK_RDC.channel_check_interval())); + + /* IPv6 CONFIGURATION */ + + + for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { + addr[i + 1] = node_id & 0xff; + addr[i + 0] = node_id >> 8; + } + linkaddr_copy(addr, &linkaddr_node_addr); + memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr)); + + process_start(&tcpip_process, NULL); + + printf("Tentative link-local IPv6 address "); + + lladdr = uip_ds6_get_link_local(-1); + for(i = 0; i < 7; ++i) { + printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], + lladdr->ipaddr.u8[i * 2 + 1]); + } + printf("%02x%02x\n", lladdr->ipaddr.u8[14], + lladdr->ipaddr.u8[15]); + + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); + printf("Tentative global IPv6 address "); + for(i = 0; i < 7; ++i) { + printf("%02x%02x:", + ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); + } + printf("%02x%02x\n", + ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); + + /* Start serial process */ + serial_line_init(); + + /* Start autostart processes (defined in Contiki application) */ + print_processes(autostart_processes); + autostart_start(autostart_processes); + + /* Start the SLIP */ + printf("Initiating SLIP with IP address is 172.16.0.2.\n"); + + uip_ipaddr(&ipv4addr, 172, 16, 0, 2); + uip_ipaddr(&netmask, 255, 255, 255, 0); + ip64_set_ipv4_address(&ipv4addr, &netmask); + + rs232_set_input(slip_input_byte); + log_set_putchar_with_slip(1); + + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + + uip_ipaddr(&ip4addr, 8,8,8,8); + ip64_addr_4to6(&ip4addr, &ip6addr); + + uip_nameserver_update((uip_ipaddr_t *)&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME); +} +/*---------------------------------------------------------------------------*/ +static void +process_run_thread_loop(void *data) +{ + /* Yield once during bootup */ + simProcessRunValue = 1; + cooja_mt_yield(); + + contiki_init(); + + while(1) { + simProcessRunValue = process_run(); + while(simProcessRunValue-- > 0) { + process_run(); + } + simProcessRunValue = process_nevents(); + + /* Check if we must stay awake */ + if(simDontFallAsleep) { + simDontFallAsleep = 0; + simProcessRunValue = 1; + } + + /* Return to COOJA */ + cooja_mt_yield(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize a mote by starting processes etc. + * + * This function initializes a mote by starting certain + * processes and setting up the environment. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_init(JNIEnv *env, jobject obj) +{ + /* Create rtimers and Contiki threads */ + cooja_mt_start(&rtimer_thread, &rtimer_thread_loop, NULL); + cooja_mt_start(&process_run_thread, &process_run_thread_loop, NULL); + } +/*---------------------------------------------------------------------------*/ +/** + * \brief Get a segment from the process memory. + * \param start Start address of segment + * \param length Size of memory segment + * \return Java byte array containing a copy of memory segment. + * + * Fetches a memory segment from the process memory starting at + * (start), with size (length). This function does not perform + * ANY error checking, and the process may crash if addresses are + * not available/readable. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) +{ + (*env)->SetByteArrayRegion( + env, + mem_arr, + 0, + (size_t) length, + (jbyte *) (((long)rel_addr) + referenceVar) + ); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Replace a segment of the process memory with given byte array. + * \param start Start address of segment + * \param length Size of memory segment + * \param mem_arr Byte array contaning new memory + * + * Replaces a process memory segment with given byte array. + * This function does not perform ANY error checking, and the + * process may crash if addresses are not available/writable. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) +{ + jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0); + memcpy((char *)(((long)rel_addr) + referenceVar), + mem, + length); + (*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Let mote execute one "block" of code (tick mote). + * + * Let mote defined by the active contiki processes and current + * process memory execute some program code. This code must not block + * or else this function will never return. A typical contiki + * process will return when it executes PROCESS_WAIT..() statements. + * + * Before the control is left to contiki processes, any messages + * from the Java part are handled. These may for example be + * incoming network data. After the contiki processes return control, + * messages to the Java part are also handled (those which may need + * special attention). + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) +{ + clock_time_t nextEtimer; + rtimer_clock_t nextRtimer; + + simProcessRunValue = 0; + + /* Let all simulation interfaces act first */ + doActionsBeforeTick(); + + /* Poll etimer process */ + if(etimer_pending()) { + etimer_request_poll(); + } + + /* Let rtimers run. + * Sets simProcessRunValue */ + cooja_mt_exec(&rtimer_thread); + + if(simProcessRunValue == 0) { + /* Rtimers done: Let Contiki handle a few events. + * Sets simProcessRunValue */ + cooja_mt_exec(&process_run_thread); + } + + /* Let all simulation interfaces act before returning to java */ + doActionsAfterTick(); + + /* Do we have any pending timers */ + simEtimerPending = etimer_pending() || rtimer_arch_pending(); + if(!simEtimerPending) { + return; + } + + /* Save nearest expiration time */ + nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; + nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime; + if(etimer_pending() && rtimer_arch_pending()) { + simNextExpirationTime = MIN(nextEtimer, nextRtimer); + } else if(etimer_pending()) { + simNextExpirationTime = nextEtimer; + } else if(rtimer_arch_pending()) { + simNextExpirationTime = nextRtimer; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the relative memory address of the reference variable. + * \return Relative memory address. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress(JNIEnv *env, jobject obj, jint addr) +{ + referenceVar = (((long)&referenceVar) - ((long)addr)); +} diff --git a/platform/cooja-ip64/ip64-conf.h b/platform/cooja-ip64/ip64-conf.h new file mode 100644 index 000000000..376614abe --- /dev/null +++ b/platform/cooja-ip64/ip64-conf.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef IP64_CONF_H +#define IP64_CONF_H + +#undef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface + +#include "ip64-slip-interface.h" +#include "ip64-null-driver.h" + +#define IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP 1 +#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_slip_interface +#define IP64_CONF_INPUT ip64_slip_interface_input +#define IP64_CONF_ETH_DRIVER ip64_null_driver + +#endif /* IP64_CONF_H */ diff --git a/platform/cooja-ip64/subplatform-conf.h b/platform/cooja-ip64/subplatform-conf.h new file mode 100644 index 000000000..14afc2ad2 --- /dev/null +++ b/platform/cooja-ip64/subplatform-conf.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __PLATFORM_CONF_H__ +#define __PLATFORM_CONF_H__ + +#if WITH_IP64 +#define WITH_SLIP 1 +#ifndef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface +#endif +#endif /* WITH_IP64 */ + +#ifndef UIP_CONF_ND6_RA_RDNSS +#define UIP_CONF_ND6_RA_RDNSS 1 +#endif + +#ifndef UIP_CONF_ND6_SEND_RA +#define UIP_CONF_ND6_SEND_RA 1 +#endif + +#ifndef UIP_CONF_ROUTER +#define UIP_CONF_ROUTER 1 +#endif + +#endif /* __PLATFORM_CONF_H__ */ diff --git a/platform/cooja/Makefile.cooja b/platform/cooja/Makefile.cooja index 574def7c7..c28dac608 100644 --- a/platform/cooja/Makefile.cooja +++ b/platform/cooja/Makefile.cooja @@ -37,7 +37,7 @@ endif ## QUICKSTART #MAIN_SRC = $(OBJECTDIR)/$(LIBNAME).c MAIN_OBJ = $(OBJECTDIR)/$(LIBNAME).o ARCHIVE = $(OBJECTDIR)/$(LIBNAME).a -JNILIB = $(OBJECTDIR)/$(LIBNAME).cooja +JNILIB = $(OBJECTDIR)/$(LIBNAME).$(TARGET) CONTIKI_APP_OBJ = $(CONTIKI_APP).co ### COOJA platform sources @@ -75,7 +75,7 @@ CFLAGSNO = $(EXTRA_CC_ARGS) -Wall -g -I/usr/local/include -DCLASSNAME=$(CLASSNAM CFLAGS += $(CFLAGSNO) MODULES += core/net core/net/mac \ - core/net/llsec + core/net/llsec core/net/ip64-addr ## Copied from Makefile.include, since Cooja overrides CFLAGS et al HAS_STACK = 0 diff --git a/platform/cooja/contiki-conf.h b/platform/cooja/contiki-conf.h index d6601bdca..d4f3979e9 100644 --- a/platform/cooja/contiki-conf.h +++ b/platform/cooja/contiki-conf.h @@ -33,6 +33,10 @@ #ifndef CONTIKI_CONF_H_ #define CONTIKI_CONF_H_ +#ifdef INCLUDE_SUBPLATFORM_CONF +#include "subplatform-conf.h" +#endif /* INCLUDE_SUBPLATFORM_CONF */ + #define PROFILE_CONF_ON 0 #define ENERGEST_CONF_ON 0 #define LOG_CONF_ENABLED 1 @@ -135,14 +139,20 @@ #define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 +#ifndef UIP_CONF_ND6_SEND_RA #define UIP_CONF_ND6_SEND_RA 0 +#endif + +#ifndef UIP_CONF_ND6_REACHABLE_TIME #define UIP_CONF_ND6_REACHABLE_TIME 600000 +#endif + +#ifndef UIP_CONF_ND6_RETRANS_TIMER #define UIP_CONF_ND6_RETRANS_TIMER 10000 +#endif #define LINKADDR_CONF_SIZE 8 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #ifndef UIP_CONF_IPV6_QUEUE_PKT #define UIP_CONF_IPV6_QUEUE_PKT 1 @@ -150,22 +160,13 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 -#ifndef UIP_CONF_BUFFER_SIZE -#define UIP_CONF_BUFFER_SIZE 240 -#endif -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS #define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 8 @@ -176,7 +177,9 @@ #define PACKETBUF_CONF_ATTRS_INLINE 1 +#ifndef QUEUEBUF_CONF_NUM #define QUEUEBUF_CONF_NUM 16 +#endif #define CC_CONF_REGISTER_ARGS 1 #define CC_CONF_FUNCTION_POINTER_ARGS 1 @@ -210,12 +213,6 @@ typedef unsigned long rtimer_clock_t; #define UIP_CONF_DHCP_LIGHT #define UIP_CONF_LLH_LEN 0 -#ifndef UIP_CONF_RECEIVE_WINDOW -#define UIP_CONF_RECEIVE_WINDOW 48 -#endif -#ifndef UIP_CONF_TCP_MSS -#define UIP_CONF_TCP_MSS 48 -#endif #define UIP_CONF_MAX_CONNECTIONS 4 #define UIP_CONF_MAX_LISTENPORTS 8 #define UIP_CONF_UDP_CONNS 12 @@ -238,10 +235,27 @@ typedef unsigned long rtimer_clock_t; #define CFS_CONF_OFFSET_TYPE long +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1600 +#endif + +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS (UIP_CONF_BUFFER_SIZE - 70) +#endif + +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_CONF_RECEIVE_WINDOW (UIP_CONF_BUFFER_SIZE - 70) +#endif + +#define RF_CHANNEL 26 +#define IEEE802154_CONF_PANID 0xABCD +#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 + /* include the project config */ /* PROJECT_CONF_H might be defined in the project Makefile */ #ifdef PROJECT_CONF_H #include PROJECT_CONF_H #endif /* PROJECT_CONF_H */ + #endif /* CONTIKI_CONF_H_ */ diff --git a/platform/econotag/contiki-conf.h b/platform/econotag/contiki-conf.h index 871145f20..2b29867ef 100644 --- a/platform/econotag/contiki-conf.h +++ b/platform/econotag/contiki-conf.h @@ -192,22 +192,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 1300 #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 diff --git a/platform/ev-aducrf101mkxz/contiki-conf.h b/platform/ev-aducrf101mkxz/contiki-conf.h index c0df15b8a..673a358ab 100644 --- a/platform/ev-aducrf101mkxz/contiki-conf.h +++ b/platform/ev-aducrf101mkxz/contiki-conf.h @@ -139,22 +139,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 240 #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 diff --git a/platform/eval-adf7xxxmb4z/contiki-conf.h b/platform/eval-adf7xxxmb4z/contiki-conf.h index e983d7eba..965bb16cd 100644 --- a/platform/eval-adf7xxxmb4z/contiki-conf.h +++ b/platform/eval-adf7xxxmb4z/contiki-conf.h @@ -142,22 +142,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 1300 #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 diff --git a/platform/exp5438/contiki-conf.h b/platform/exp5438/contiki-conf.h index ff23e07a6..bb7a5fcdd 100644 --- a/platform/exp5438/contiki-conf.h +++ b/platform/exp5438/contiki-conf.h @@ -163,22 +163,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #ifndef UIP_CONF_BUFFER_SIZE #define UIP_CONF_BUFFER_SIZE 240 #endif -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS #define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 diff --git a/platform/mbxxx/contiki-conf.h b/platform/mbxxx/contiki-conf.h index 5ad8a505e..1d2b17322 100644 --- a/platform/mbxxx/contiki-conf.h +++ b/platform/mbxxx/contiki-conf.h @@ -128,12 +128,6 @@ #define UIP_CONF_UDP 1 -#if (WITH_COAP==7) || (WITH_COAP==6) || (WITH_COAP==3) -#define UIP_CONF_TCP 0 -#else -#define UIP_CONF_TCP 1 -#endif /* WITH_COAP */ - #define UIP_CONF_ROUTER 1 #define UIP_CONF_ND6_SEND_RA 0 @@ -141,8 +135,6 @@ #define UIP_CONF_IPV6_QUEUE_PKT 0 #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 -#define UIP_CONF_ND6_MAX_PREFIXES 2 -#define UIP_CONF_ND6_MAX_DEFROUTERS 1 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 140 #define UIP_CONF_MAX_CONNECTIONS 4 diff --git a/platform/micaz/contiki-conf.h b/platform/micaz/contiki-conf.h index 25d191540..099941d85 100644 --- a/platform/micaz/contiki-conf.h +++ b/platform/micaz/contiki-conf.h @@ -139,20 +139,14 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 240 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 diff --git a/platform/minimal-net/contiki-conf.h b/platform/minimal-net/contiki-conf.h index 1501b1384..e736b363d 100644 --- a/platform/minimal-net/contiki-conf.h +++ b/platform/minimal-net/contiki-conf.h @@ -159,8 +159,6 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 1 //#define UIP_CONF_NETIF_MAX_ADDRESSES 5 -//#define UIP_CONF_ND6_MAX_PREFIXES 3 -//#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define NBR_TABLE_CONF_MAX_NEIGHBORS 100 #define UIP_CONF_DS6_DEFRT_NBU 2 #define UIP_CONF_DS6_PREFIX_NBU 5 diff --git a/platform/native/Makefile.native b/platform/native/Makefile.native index 460610a6a..198dbabee 100644 --- a/platform/native/Makefile.native +++ b/platform/native/Makefile.native @@ -42,4 +42,4 @@ CURSES_LIBS ?= -lncurses TARGET_LIBFILES += $(CURSES_LIBS) -MODULES+=core/net core/net/mac core/ctk core/net/llsec +MODULES+=core/net core/net/mac core/ctk core/net/llsec core/net/ip64-addr/ diff --git a/platform/native/contiki-conf.h b/platform/native/contiki-conf.h index 48e623266..5ce72c09e 100644 --- a/platform/native/contiki-conf.h +++ b/platform/native/contiki-conf.h @@ -103,15 +103,11 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_ROUTER 1 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS #define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 @@ -121,8 +117,6 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_IPV6_QUEUE_PKT 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_ICMP6 1 /* configure number of neighbors and routes */ diff --git a/platform/sky/contiki-conf.h b/platform/sky/contiki-conf.h index 0340a993b..53f22f87f 100644 --- a/platform/sky/contiki-conf.h +++ b/platform/sky/contiki-conf.h @@ -164,22 +164,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #ifndef UIP_CONF_BUFFER_SIZE #define UIP_CONF_BUFFER_SIZE 240 #endif -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS #define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 diff --git a/platform/srf06-cc26xx/README.md b/platform/srf06-cc26xx/README.md index 4cfb9945d..811fc473f 100644 --- a/platform/srf06-cc26xx/README.md +++ b/platform/srf06-cc26xx/README.md @@ -39,7 +39,7 @@ In terms of hardware support, the following drivers have been implemented: * Motion Processing Unit (MPU9250 - Accelerometer, Gyro) * BMP280 sensor * TMP007 sensor - * SHT21 sensor + * HDC1000 sensor * OPT3001 sensor * Buzzer * External SPI flash @@ -69,15 +69,19 @@ To use the port you need: [...] gcc version 4.9.3 20141119 (release) [ARM/embedded-4_9-branch revision 218278] (GNU Tools for ARM Embedded Processors) +* srecord (http://srecord.sourceforge.net/) * You may also need other drivers so that the SmartRF can communicate with your operating system and so that you can use the chip's UART for I/O. Please read the section ["Drivers" in the CC2538DK readme](https://github.com/contiki-os/contiki/tree/master/platform/cc2538dk#drivers). Environment =========== -To use this port, you will need to download and extract CC26xxware sources, -provided by TI here http://www.ti.com/tool/cc26xxware. Once you have done this, you will need to configure the Contiki -build system so that it can locate and compile them as part of the build process. +To use this port, you will need to download and extract CC26xxware sources. We +currently use CC26xxware version 2.20.06.14829. The download link can be found +here: http://processors.wiki.ti.com/index.php/CC26xxware + +Once you have done this, you will need to configure the Contiki build system so +that it can locate and compile them as part of the build process. To do this, you will need to set the following environment variable: diff --git a/platform/srf06-cc26xx/contiki-conf.h b/platform/srf06-cc26xx/contiki-conf.h index 6a99c29b3..359c922df 100644 --- a/platform/srf06-cc26xx/contiki-conf.h +++ b/platform/srf06-cc26xx/contiki-conf.h @@ -220,7 +220,7 @@ #define UIP_CONF_TCP 1 #endif #ifndef UIP_CONF_TCP_MSS -#define UIP_CONF_TCP_MSS 128 +#define UIP_CONF_TCP_MSS 64 #endif #define UIP_CONF_UDP 1 @@ -244,10 +244,6 @@ #ifndef ENERGEST_CONF_ON #define ENERGEST_CONF_ON 0 /**< Energest Module */ #endif - -#ifndef STARTUP_CONF_VERBOSE -#define STARTUP_CONF_VERBOSE 1 /**< Set to 0 to decrease startup verbosity */ -#endif /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -273,29 +269,10 @@ * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT * keep using SLIP */ -#if defined (UIP_FALLBACK_INTERFACE) || defined (CMD_CONF_OUTPUT) +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) #define SLIP_ARCH_CONF_ENABLED 1 #endif #endif - -/** - * \brief Define this as 1 to build a headless node. - * - * The UART will not be initialised its clock will be gated, offering some - * energy savings. The USB will not be initialised either - */ -#ifndef CC26XX_CONF_QUIET -#define CC26XX_CONF_QUIET 0 -#endif - -/* CC26XX_CONF_QUIET is hard and overrides all other related defines */ -#if CC26XX_CONF_QUIET -#undef CC26XX_UART_CONF_ENABLE -#define CC26XX_UART_CONF_ENABLE 0 - -#undef STARTUP_CONF_VERBOSE -#define STARTUP_CONF_VERBOSE 0 -#endif /* CC26XX_CONF_QUIET */ /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -310,6 +287,13 @@ /* Notify various examples that we have Buttons */ #define PLATFORM_HAS_BUTTON 1 + +/* + * Override button symbols from dev/button-sensor.h, for the examples that + * include it + */ +#define button_sensor button_left_sensor +#define button_sensor2 button_right_sensor /** @} */ /*---------------------------------------------------------------------------*/ /* Platform-specific define to signify sensor reading failure */ @@ -332,14 +316,14 @@ typedef uint32_t clock_time_t; typedef uint32_t uip_stats_t; /* Clock (time) comparison macro */ -#define CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define * RTIMER_CLOCK_LT to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) /** @} */ /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ diff --git a/platform/srf06-cc26xx/contiki-main.c b/platform/srf06-cc26xx/contiki-main.c index d28643531..f2f6bbe21 100644 --- a/platform/srf06-cc26xx/contiki-main.c +++ b/platform/srf06-cc26xx/contiki-main.c @@ -193,7 +193,7 @@ main(void) serial_line_init(); printf("Starting " CONTIKI_VERSION_STRING "\n"); - printf("With CC26xxware v%u.%02u.%02u.%u\n", DRIVERLIB_MAJOR_VER, + printf("With DriverLib v%u.%02u.%02u.%u\n", DRIVERLIB_MAJOR_VER, DRIVERLIB_MINOR_VER, DRIVERLIB_PATCH_VER, DRIVERLIB_BUILD_ID); printf(BOARD_STRING " using CC%u\n", CC26XX_MODEL_CPU_VARIANT); diff --git a/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/platform/srf06-cc26xx/sensortag/Makefile.sensortag index 98fad7a68..94de7711f 100644 --- a/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -1,8 +1,8 @@ -CFLAGS += -DBOARD_SENSORTAG=1 -DTI_BSP_BOARD_HDR=\"ti-bsp-st.h\" +CFLAGS += -DBOARD_SENSORTAG=1 CFLAGS += -DBACKDOOR_IOID=0x00000000 BOARD_SOURCEFILES += leds-arch.c sensortag-sensors.c sensor-common.c BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c -BOARD_SOURCEFILES += sht-21-sensor.c mpu-9250-sensor.c button-sensor.c +BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c diff --git a/platform/srf06-cc26xx/sensortag/board-peripherals.h b/platform/srf06-cc26xx/sensortag/board-peripherals.h index aa61ab333..9c994d9e6 100644 --- a/platform/srf06-cc26xx/sensortag/board-peripherals.h +++ b/platform/srf06-cc26xx/sensortag/board-peripherals.h @@ -43,7 +43,7 @@ #include "bmp-280-sensor.h" #include "tmp-007-sensor.h" #include "opt-3001-sensor.h" -#include "sht-21-sensor.h" +#include "hdc-1000-sensor.h" #include "mpu-9250-sensor.h" #include "reed-relay.h" #include "buzzer.h" diff --git a/platform/srf06-cc26xx/sensortag/board.c b/platform/srf06-cc26xx/sensortag/board.c index 5246a85ef..e397f1266 100644 --- a/platform/srf06-cc26xx/sensortag/board.c +++ b/platform/srf06-cc26xx/sensortag/board.c @@ -76,7 +76,7 @@ shutdown_handler(uint8_t mode) SENSORS_DEACTIVATE(bmp_280_sensor); SENSORS_DEACTIVATE(opt_3001_sensor); SENSORS_DEACTIVATE(tmp_007_sensor); - SENSORS_DEACTIVATE(sht_21_sensor); + SENSORS_DEACTIVATE(hdc_1000_sensor); mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0); } } diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.c b/platform/srf06-cc26xx/sensortag/button-sensor.c index 089ea7332..e6a9114ea 100644 --- a/platform/srf06-cc26xx/sensortag/button-sensor.c +++ b/platform/srf06-cc26xx/sensortag/button-sensor.c @@ -227,7 +227,7 @@ value_left(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)left_timer.duration; } @@ -239,7 +239,7 @@ value_right(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)right_timer.duration; } diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.h b/platform/srf06-cc26xx/sensortag/button-sensor.h index 6e15b4d4c..25acb104f 100644 --- a/platform/srf06-cc26xx/sensortag/button-sensor.h +++ b/platform/srf06-cc26xx/sensortag/button-sensor.h @@ -54,7 +54,6 @@ #define BUTTON_SENSOR_VALUE_RELEASED 0 #define BUTTON_SENSOR_VALUE_PRESSED 1 /*---------------------------------------------------------------------------*/ -#define button_sensor button_left_sensor extern const struct sensors_sensor button_left_sensor; extern const struct sensors_sensor button_right_sensor; /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c new file mode 100644 index 000000000..8fdd6d847 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sensortag-cc26xx-hdc-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx HDC sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "hdc-1000-sensor.h" +#include "sensor-common.h" +#include "board-i2c.h" + +#include "ti-lib.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Sensor I2C address */ +#define SENSOR_I2C_ADDRESS 0x43 + +/* Registers */ +#define HDC1000_REG_TEMP 0x00 /* Temperature */ +#define HDC1000_REG_HUM 0x01 /* Humidity */ +#define HDC1000_REG_CONFIG 0x02 /* Configuration */ +#define HDC1000_REG_SERID_H 0xFB /* Serial ID high */ +#define HDC1000_REG_SERID_M 0xFC /* Serial ID middle */ +#define HDC1000_REG_SERID_L 0xFD /* Serial ID low */ +#define HDC1000_REG_MANF_ID 0xFE /* Manufacturer ID */ +#define HDC1000_REG_DEV_ID 0xFF /* Device ID */ + +/* Fixed values */ +#define HDC1000_VAL_MANF_ID 0x5449 +#define HDC1000_VAL_DEV_ID 0x1000 +#define HDC1000_VAL_CONFIG 0x1000 /* 14 bit, acquired in sequence */ + +/* Sensor selection/deselection */ +#define SENSOR_SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS) +#define SENSOR_DESELECT() board_i2c_deselect() +/*---------------------------------------------------------------------------*/ +/* Byte swap of 16-bit register value */ +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) + +#define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v)) +/*---------------------------------------------------------------------------*/ +/* Raw data as returned from the sensor (Big Endian) */ +typedef struct sensor_data { + uint16_t temp; + uint16_t hum; +} sensor_data_t; + +/* Raw data, little endian */ +static uint16_t raw_temp; +static uint16_t raw_hum; +/*---------------------------------------------------------------------------*/ +static bool success; +static sensor_data_t data; +/*---------------------------------------------------------------------------*/ +static int enabled = HDC_1000_SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* + * Maximum measurement durations in clock ticks. We use 14bit resolution, thus: + * - Tmp: 6.35ms + * - RH: 6.5ms + */ +#define MEASUREMENT_DURATION 2 + +/* + * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a + * reading (max 15ms) + */ +#define SENSOR_STARTUP_DELAY 3 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the humidity sensor driver + * \return True if I2C operation successful + */ +static bool +sensor_init(void) +{ + uint16_t val; + + SENSOR_SELECT(); + + /* Enable reading data in one operation */ + val = SWAP(HDC1000_VAL_CONFIG); + success = sensor_common_write_reg(HDC1000_REG_CONFIG, (uint8_t *)&val, 2); + + SENSOR_DESELECT(); + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start measurement + */ +static void +start(void) +{ + if(success) { + SENSOR_SELECT(); + + success = board_i2c_write_single(HDC1000_REG_TEMP); + SENSOR_DESELECT(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Take readings from the sensor + * \return true of I2C operations successful + */ +static bool +read_data() +{ + bool valid; + + if(success) { + SENSOR_SELECT(); + + success = board_i2c_read((uint8_t *)&data, sizeof(data)); + SENSOR_DESELECT(); + + /* Store temperature */ + raw_temp = SWAP(data.temp); + + /* Store humidity */ + raw_hum = SWAP(data.hum); + } + + valid = success; + success = true; + + return valid; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to temperature and humidity + * \param temp - converted temperature + * \param hum - converted humidity + */ +static void +convert(float *temp, float *hum) +{ + /* Convert temperature to degrees C */ + *temp = ((double)(int16_t)raw_temp / 65536) * 165 - 40; + + /* Convert relative humidity to a %RH value */ + *hum = ((double)raw_hum / 65536) * 100; +} +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = HDC_1000_SENSOR_STATUS_READINGS_READY; + + /* Latch readings */ + read_data(); + + sensors_changed(&hdc_1000_sensor); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMIDITY + * \return Temperature (centi degrees C) or Humidity (centi %RH) + */ +static int +value(int type) +{ + int rv; + float temp; + float hum; + + if(enabled != HDC_1000_SENSOR_STATUS_READINGS_READY) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + if((type != HDC_1000_SENSOR_TYPE_TEMP) && + type != HDC_1000_SENSOR_TYPE_HUMIDITY) { + PRINTF("Invalid type\n"); + return CC26XX_SENSOR_READING_ERROR; + } else { + convert(&temp, &hum); + PRINTF("HDC: %04X %04X t=%d h=%d\n", raw_temp, raw_hum, + (int)(temp * 100), (int)(hum * 100)); + + if(type == HDC_1000_SENSOR_TYPE_TEMP) { + rv = (int)(temp * 100); + } else if(type == HDC_1000_SENSOR_TYPE_HUMIDITY) { + rv = (int)(hum * 100); + } + } + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the HDC1000 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + raw_temp = 0; + raw_hum = 0; + memset(&data, 0, sizeof(data)); + + sensor_init(); + enabled = HDC_1000_SENSOR_STATUS_INITIALISED; + break; + case SENSORS_ACTIVE: + /* Must be initialised first */ + if(enabled == HDC_1000_SENSOR_STATUS_DISABLED) { + return HDC_1000_SENSOR_STATUS_DISABLED; + } + if(enable) { + start(); + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + enabled = HDC_1000_SENSOR_STATUS_TAKING_READINGS; + } else { + ctimer_stop(&startup_timer); + enabled = HDC_1000_SENSOR_STATUS_INITIALISED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return One of the SENSOR_STATUS_xyz defines + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return HDC_1000_SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(hdc_1000_sensor, "HDC1000", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h new file mode 100755 index 000000000..990b1ab69 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-hdc-sensor SensorTag 2.0 TI HDC1000 Sensor + * + * Due to the time required for the sensor to startup, this driver is meant to + * be used in an asynchronous fashion. The caller must first activate the + * sensor by calling SENSORS_ACTIVATE(). This will trigger the sensor's startup + * sequence, but the call will not wait for it to complete so that the CPU can + * perform other tasks or drop to a low power mode. Once the sensor has taken + * readings, it will automatically go back to low power mode. + * + * Once the sensor is stable, the driver will retrieve readings from the sensor + * and latch them. It will then generate a sensors_changed event. + * + * The user can then retrieve readings by calling .value() and by passing + * either HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMIDITY as the + * argument. Multiple calls to value() will not trigger new readings, they will + * simply return the most recent latched values. + * + * The user can query the sensor's status by calling .status() + * + * To get a fresh reading, the user must trigger a new reading cycle by calling + * SENSORS_ACTIVATE(). + * @{ + * + * \file + * Header file for the Sensortag-CC26ss TI HDC1000 sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef HDC_1000_SENSOR_H +#define HDC_1000_SENSOR_H +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define HDC_1000_SENSOR_TYPE_TEMP 1 +#define HDC_1000_SENSOR_TYPE_HUMIDITY 2 +/*---------------------------------------------------------------------------*/ +/** + * \name HDC1000 driver states + * @{ + */ +#define HDC_1000_SENSOR_STATUS_DISABLED 0 /**< Not initialised */ +#define HDC_1000_SENSOR_STATUS_INITIALISED 1 /**< Initialised but idle */ +#define HDC_1000_SENSOR_STATUS_TAKING_READINGS 2 /**< Readings in progress */ +#define HDC_1000_SENSOR_STATUS_READINGS_READY 3 /**< Both readings ready */ +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor hdc_1000_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* HDC_1000_SENSOR_H */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/reed-relay.c b/platform/srf06-cc26xx/sensortag/reed-relay.c index b5956f6f8..612163b12 100644 --- a/platform/srf06-cc26xx/sensortag/reed-relay.c +++ b/platform/srf06-cc26xx/sensortag/reed-relay.c @@ -50,7 +50,7 @@ /*---------------------------------------------------------------------------*/ static struct timer debouncetimer; /*---------------------------------------------------------------------------*/ -#define REED_ISR_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ +#define REED_IO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ IOC_IOPULL_DOWN | IOC_SLEW_DISABLE | \ IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ IOC_INT_DISABLE | IOC_IOMODE_NORMAL | \ @@ -94,10 +94,12 @@ configure(int type, int value) ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); ti_lib_gpio_event_clear(1 << BOARD_IOID_REED_RELAY); - /* Enabled the GPIO clock when the CM3 is running */ + /* Enable the GPIO clock when the CM3 is running */ ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + + /* S/W control, input, pull-down */ ti_lib_ioc_port_configure_set(BOARD_IOID_REED_RELAY, IOC_PORT_GPIO, - REED_ISR_CFG); + REED_IO_CFG); gpio_interrupt_register_handler(BOARD_IOID_REED_RELAY, reed_interrupt_handler); diff --git a/platform/srf06-cc26xx/sensortag/sensortag-sensors.c b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c index a8f26aefe..bcd0fe367 100644 --- a/platform/srf06-cc26xx/sensortag/sensortag-sensors.c +++ b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c @@ -41,7 +41,7 @@ #include "sensortag/bmp-280-sensor.h" #include "sensortag/tmp-007-sensor.h" #include "sensortag/opt-3001-sensor.h" -#include "sensortag/sht-21-sensor.h" +#include "sensortag/hdc-1000-sensor.h" #include "sensortag/mpu-9250-sensor.h" #include "sensortag/reed-relay.h" @@ -49,7 +49,7 @@ /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_left_sensor, &button_right_sensor, - &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &sht_21_sensor, + &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &hdc_1000_sensor, &mpu_9250_sensor, &reed_relay_sensor); /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.c b/platform/srf06-cc26xx/sensortag/sht-21-sensor.c deleted file mode 100644 index f90e12f55..000000000 --- a/platform/srf06-cc26xx/sensortag/sht-21-sensor.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-sht-sensor - * @{ - * - * \file - * Driver for the Sensortag-CC26xx Sensirion SHT21 Humidity sensor - */ -/*---------------------------------------------------------------------------*/ -#include "contiki-conf.h" -#include "sys/ctimer.h" -#include "lib/sensors.h" -#include "sht-21-sensor.h" -#include "sensor-common.h" -#include "board-i2c.h" - -#include "ti-lib.h" - -#include -#include -#include -/*---------------------------------------------------------------------------*/ -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif -/*---------------------------------------------------------------------------*/ -/* Sensor I2C address */ -#define HAL_SHT21_I2C_ADDRESS 0x40 -/*---------------------------------------------------------------------------*/ -#define S_REG_LEN 2 -#define DATA_LEN 3 -/*---------------------------------------------------------------------------*/ -/* Internal commands */ -#define SHT21_CMD_TEMP_T_NH 0xF3 /* command trig. temp meas. no hold master */ -#define SHT21_CMD_HUMI_T_NH 0xF5 /* command trig. humidity meas. no hold master */ -#define SHT21_CMD_WRITE_U_R 0xE6 /* command write user register */ -#define SHT21_CMD_READ_U_R 0xE7 /* command read user register */ -#define SHT21_CMD_SOFT_RST 0xFE /* command soft reset */ -/*---------------------------------------------------------------------------*/ -#define HUMIDITY 0x00 -#define TEMPERATURE 0x01 -/*---------------------------------------------------------------------------*/ -#define USR_REG_MASK 0x38 /* Mask off reserved bits (3,4,5) */ -#define USR_REG_DEFAULT 0x02 /* Disable OTP reload */ -#define USR_REG_RES_MASK 0x7E /* Only change bits 0 and 7 (meas. res.) */ -#define USR_REG_11BITRES 0x81 /* 11-bit resolution */ -/*---------------------------------------------------------------------------*/ -#define USR_REG_TEST_VAL 0x83 -/*---------------------------------------------------------------------------*/ -#define DATA_SIZE 6 -/*---------------------------------------------------------------------------*/ -static uint8_t usr; /* User register value */ -static uint8_t buf[DATA_SIZE]; /* Data buffer */ -static bool success; -/*---------------------------------------------------------------------------*/ -static int enabled = SHT_21_SENSOR_STATUS_DISABLED; -/*---------------------------------------------------------------------------*/ -/* - * Maximum measurement durations in clock ticks. We use 11bit resolution, thus: - * - Tmp: 11ms - * - RH: 15ms - */ -#define MEASUREMENT_DURATION 3 - -/* - * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a - * reading - */ -#define SENSOR_STARTUP_DELAY 4 - -static struct ctimer startup_timer; -/*---------------------------------------------------------------------------*/ -/** - * \brief Select the SHT sensor on the I2C-bus - */ -static void -select(void) -{ - /* Select the SHT21 address */ - board_i2c_select(BOARD_I2C_INTERFACE_0, HAL_SHT21_I2C_ADDRESS); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Write a command over I2C - * \param cmd The command to send - * \return TRUE if the command was sent successfully - */ -static bool -write_cmd(uint8_t cmd) -{ - /* Send command */ - return board_i2c_write_single(cmd); -} -/*---------------------------------------------------------------------------*/ -/* - * \brief Read data from the SHT over I2C - * \param buf Pointer to buffer where data will be stored - * \param len Number of bytes to read - * \return TRUE if the required number of bytes were received - */ -static bool -read_data(uint8_t *buf, uint8_t len) -{ - /* Read data */ - return board_i2c_read(buf, len); -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Initialise the SHT21 sensor - */ -static void -sensor_init(void) -{ - select(); - - /* Set 11 bit resolution */ - sensor_common_read_reg(SHT21_CMD_READ_U_R, &usr, 1); - usr &= USR_REG_RES_MASK; - usr |= USR_REG_11BITRES; - sensor_common_write_reg(SHT21_CMD_WRITE_U_R, &usr, 1); - success = true; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Start a temperature measurement - */ -static void -start_temp(void) -{ - if(success) { - select(); - success = write_cmd(SHT21_CMD_TEMP_T_NH); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Latch the last temperature measurement - */ -static void -latch_temp(void) -{ - if(success) { - select(); - success = read_data(buf, DATA_LEN); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Start a humidity measurement - */ -static void -start_humidity(void) -{ - if(success) { - select(); - success = write_cmd(SHT21_CMD_HUMI_T_NH); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Latch the last humidity measurement - */ -static void -latch_humidity(void) -{ - if(success) { - select(); - success = read_data(buf + DATA_LEN, DATA_LEN); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Retrieve latched raw readings from buffer and store in variables - * \param raw_temp Pointer to a buffer where the temperature reading will be - * stored - * \param raw_hum Pointer to a buffer where the humidity reading will be - * stored - * \return TRUE on success - */ -static bool -get_readings(uint16_t *raw_temp, uint16_t *raw_hum) -{ - bool valid; - - valid = success; - if(!success) { - sensor_common_set_error_data(buf, DATA_SIZE); - } - - /* Store temperature */ - *raw_temp = buf[0] << 8 | buf[1]; - - /* [2] We ignore the CRC */ - - /* Store humidity */ - *raw_hum = buf[3] << 8 | buf[4]; - - /* [5] We ignore the CRC */ - - success = true; - - return valid; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Convert raw data to temperature (degrees C) and rel. humidity (%RH) - * \param raw_temp Raw temperature data (little endian) - * \param raw_hum Raw humidity data (little endian) - * \param temp Converted temperature value - * \param hum Converted humidity value - */ -static void -convert(uint16_t raw_temp, uint16_t raw_hum, float *temp, float *hum) -{ - /* Convert temperature to degrees C */ - raw_temp &= ~0x0003; /* clear bits [1..0] (status bits) */ - *temp = -46.85 + 175.72 / 65536 * (double)(int16_t)raw_temp; - - /* Convert relative humidity to a %RH value */ - raw_hum &= ~0x0003; /* clear bits [1..0] (status bits) */ - - /* RH= -6 + 125 * SRH / 2^16 */ - *hum = -6.0 + 125.0 / 65536 * (double)raw_hum; -} -/*---------------------------------------------------------------------------*/ -static void -state_machine(void *not_used) -{ - switch(enabled) { - case SHT_21_SENSOR_STATUS_INITIALISED: - start_temp(); - enabled = SHT_21_SENSOR_STATUS_READING_TEMP; - break; - case SHT_21_SENSOR_STATUS_READING_TEMP: - latch_temp(); - start_humidity(); - enabled = SHT_21_SENSOR_STATUS_READING_HUMIDITY; - break; - case SHT_21_SENSOR_STATUS_READING_HUMIDITY: - latch_humidity(); - enabled = SHT_21_SENSOR_STATUS_READINGS_READY; - sensors_changed(&sht_21_sensor); - return; - case SHT_21_SENSOR_STATUS_READINGS_READY: - case SHT_21_SENSOR_STATUS_DISABLED: - default: - ctimer_stop(&startup_timer); - return; - } - - ctimer_set(&startup_timer, MEASUREMENT_DURATION, state_machine, NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns a reading from the sensor - * \param type SHT_21_SENSOR_TYPE_TEMP or SHT_21_SENSOR_TYPE_HUMIDITY - * \return Temperature (centi degrees C) or Humidity (centi %RH) - */ -static int -value(int type) -{ - int rv; - uint16_t raw_temp; - uint16_t raw_hum; - float temp; - float hum; - - if(enabled != SHT_21_SENSOR_STATUS_READINGS_READY) { - PRINTF("Sensor disabled or starting up (%d)\n", enabled); - return CC26XX_SENSOR_READING_ERROR; - } - - if((type != SHT_21_SENSOR_TYPE_TEMP) && type != SHT_21_SENSOR_TYPE_HUMIDITY) { - PRINTF("Invalid type\n"); - return CC26XX_SENSOR_READING_ERROR; - } else { - rv = get_readings(&raw_temp, &raw_hum); - - if(rv == 0) { - return CC26XX_SENSOR_READING_ERROR; - } - - convert(raw_temp, raw_hum, &temp, &hum); - PRINTF("SHT: %04X %04X t=%d h=%d\n", raw_temp, raw_hum, - (int)(temp * 100), (int)(hum * 100)); - - if(type == SHT_21_SENSOR_TYPE_TEMP) { - rv = (int)(temp * 100); - } else if(type == SHT_21_SENSOR_TYPE_HUMIDITY) { - rv = (int)(hum * 100); - } - } - return rv; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the SHT21 sensor. - * - * \param type Activate, enable or disable the sensor. See below - * \param enable - * - * When type == SENSORS_HW_INIT we turn on the hardware - * When type == SENSORS_ACTIVE and enable==1 we enable the sensor - * When type == SENSORS_ACTIVE and enable==0 we disable the sensor - */ -static int -configure(int type, int enable) -{ - switch(type) { - case SENSORS_HW_INIT: - sensor_init(); - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - break; - case SENSORS_ACTIVE: - /* Must be initialised first */ - if(enabled == SHT_21_SENSOR_STATUS_DISABLED) { - return SHT_21_SENSOR_STATUS_DISABLED; - } - if(enable) { - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, state_machine, NULL); - } else { - ctimer_stop(&startup_timer); - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - } - break; - default: - break; - } - return enabled; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns the status of the sensor - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return One of the SENSOR_STATUS_xyz defines - */ -static int -status(int type) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - return enabled; - break; - default: - break; - } - return SHT_21_SENSOR_STATUS_DISABLED; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(sht_21_sensor, "SHT21", value, configure, status); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 index 7d64aac94..ee64aa519 100644 --- a/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -1,5 +1,3 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c - -CONTIKI_TARGET_DIRS += $(BOARD)/bsp diff --git a/platform/srf06-cc26xx/srf06/button-sensor.c b/platform/srf06-cc26xx/srf06/button-sensor.c index 5c6dae6f1..9638d511e 100644 --- a/platform/srf06-cc26xx/srf06/button-sensor.c +++ b/platform/srf06-cc26xx/srf06/button-sensor.c @@ -329,7 +329,7 @@ value_select(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)sel_timer.duration; } @@ -341,7 +341,7 @@ value_left(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)left_timer.duration; } @@ -353,7 +353,7 @@ value_right(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)right_timer.duration; } @@ -365,7 +365,7 @@ value_up(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)up_timer.duration; } @@ -377,7 +377,7 @@ value_down(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)down_timer.duration; } diff --git a/platform/srf06-cc26xx/srf06/button-sensor.h b/platform/srf06-cc26xx/srf06/button-sensor.h index 1f5752059..2c47f9118 100644 --- a/platform/srf06-cc26xx/srf06/button-sensor.h +++ b/platform/srf06-cc26xx/srf06/button-sensor.h @@ -49,7 +49,6 @@ #define BUTTON_SENSOR_VALUE_RELEASED 0 #define BUTTON_SENSOR_VALUE_PRESSED 1 /*---------------------------------------------------------------------------*/ -#define button_sensor button_select_sensor extern const struct sensors_sensor button_select_sensor; extern const struct sensors_sensor button_left_sensor; extern const struct sensors_sensor button_right_sensor; diff --git a/platform/win32/contiki-main.c b/platform/win32/contiki-main.c index dcadd5385..5ced80992 100644 --- a/platform/win32/contiki-main.c +++ b/platform/win32/contiki-main.c @@ -140,7 +140,7 @@ main(int argc, char **argv) log_message("Def. Router: ", inet_ntoa(*(struct in_addr*)&addr)); uip_ipaddr(&addr, 192,168,0,1); - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); log_message("DNS Server: ", inet_ntoa(*(struct in_addr*)&addr)); } diff --git a/platform/wismote/contiki-conf.h b/platform/wismote/contiki-conf.h index adcb37c1a..761d68f91 100644 --- a/platform/wismote/contiki-conf.h +++ b/platform/wismote/contiki-conf.h @@ -147,22 +147,16 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #ifndef UIP_CONF_BUFFER_SIZE #define UIP_CONF_BUFFER_SIZE 240 #endif -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS #define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 diff --git a/platform/z1/contiki-conf.h b/platform/z1/contiki-conf.h index 34fd48dde..3f223c0c5 100644 --- a/platform/z1/contiki-conf.h +++ b/platform/z1/contiki-conf.h @@ -153,20 +153,14 @@ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 -#define UIP_CONF_ND6_MAX_PREFIXES 3 -#define UIP_CONF_ND6_MAX_DEFROUTERS 2 #define UIP_CONF_IP_FORWARD 0 #define UIP_CONF_BUFFER_SIZE 140 -#define SICSLOWPAN_CONF_COMPRESSION_IPV6 0 -#define SICSLOWPAN_CONF_COMPRESSION_HC1 1 -#define SICSLOWPAN_CONF_COMPRESSION_HC01 2 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ -#define SICSLOWPAN_CONF_CONVENTIONAL_MAC 1 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 diff --git a/platform/z1/dev/reed-sensor.c b/platform/z1/dev/reed-sensor.c new file mode 100644 index 000000000..7e7a0df6d --- /dev/null +++ b/platform/z1/dev/reed-sensor.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015, Zolertia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/** + * \file + * Reed sensor driver file + * \author + * Antonio Lignan + */ + +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/reed-sensor.h" +#include "sys/process.h" +#include "sys/ctimer.h" +/*---------------------------------------------------------------------------*/ +#ifndef REED_CHECK_PERIOD +#define REED_CHECK_PERIOD CLOCK_SECOND +#endif +/*---------------------------------------------------------------------------*/ +static int current_status = -1; +static struct ctimer change_timer; +process_event_t reed_sensor_event_changed; +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return ~(REED_PORT_DIR & REED_READ_PIN); + } + return REED_SENSOR_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if((!status(SENSORS_ACTIVE)) || (type != REED_SENSOR_VAL)) { + return REED_SENSOR_ERROR; + } + return (REED_PORT_READ & REED_READ_PIN) ? REED_CLOSED : REED_OPEN; +} +/*---------------------------------------------------------------------------*/ +static void +check_callback(void *data) +{ + static int new_status; + if(current_status == -1) { + ctimer_stop(&change_timer); + return; + } + + new_status = value(REED_SENSOR_VAL); + if(new_status != current_status) { + current_status = new_status; + process_post(PROCESS_BROADCAST, reed_sensor_event_changed, ¤t_status); + } + ctimer_reset(&change_timer); +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + if(c) { + if(!status(SENSORS_ACTIVE)) { + REED_PORT_SEL |= REED_READ_PIN; + REED_PORT_DIR &= ~REED_READ_PIN; + REED_PORT_REN |= REED_READ_PIN; + REED_PORT_PRES |= REED_READ_PIN; + } + } else { + REED_PORT_DIR |= REED_READ_PIN; + REED_PORT_REN &= ~REED_READ_PIN; + } + return REED_SENSOR_SUCCESS; + case REED_SENSOR_MODE: + if(c == REED_SENSOR_EVENT_MODE) { + current_status = value(REED_SENSOR_VAL); + ctimer_set(&change_timer, REED_CHECK_PERIOD, check_callback, NULL); + } else if(c == REED_SENSOR_EVENT_POLL) { + current_status = -1; + ctimer_stop(&change_timer); + } else { + return REED_SENSOR_ERROR; + } + return REED_SENSOR_SUCCESS; + } + return REED_SENSOR_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(reed_sensor, REED_SENSOR, value, configure, status); diff --git a/platform/z1/dev/reed-sensor.h b/platform/z1/dev/reed-sensor.h new file mode 100644 index 000000000..7e86716f5 --- /dev/null +++ b/platform/z1/dev/reed-sensor.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Zolertia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/** + * Header file for the reed sensor + * + * The Reed sensor allows to be used either by polling the sensor status or by + * setting up a timer on the background ticking every REED_CHECK_PERIOD, posting + * a reed_sensor_event_changed event, informing the application about a change + * in the sensor status (basically open or closed). To enable each mode + * (default is polling) call the configure() function with REED_SENSOR_MODE + * using REED_SENSOR_EVENT_MODE or REED_SENSOR_POLL_MODE, after having + * initialized the device using SENSORS_ACTIVATE(reed_sensor). + * + * \file + * Reed sensor header file + * \author + * Antonio Lignan + */ +#include "lib/sensors.h" + +#ifndef REED_SENSOR_H_ +#define REED_SENSOR_H_ +/* -------------------------------------------------------------------------- */ +#define REED_SENSOR_ERROR -1 +#define REED_SENSOR_SUCCESS 0x00 +#define REED_SENSOR_VAL 0x01 +/* -------------------------------------------------------------------------- */ +#define REED_OPEN 0x00 +#define REED_CLOSED 0x01 +/* -------------------------------------------------------------------------- */ +#define REED_SENSOR_MODE 0x01 +#define REED_SENSOR_EVENT_MODE 0x0A +#define REED_SENSOR_EVENT_POLL 0x0B +/* -------------------------------------------------------------------------- */ +#define REED_PORT_DIR P4DIR +#define REED_PORT_SEL P4SEL +#define REED_PORT_REN P4REN +#define REED_PORT_READ P4IN +#define REED_PORT_PRES P4OUT +#define REED_READ_PIN (1 << 2) +/* -------------------------------------------------------------------------- */ +#define REED_SENSOR "Reed Sensor" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor reed_sensor; +extern process_event_t reed_sensor_event_changed; +/* -------------------------------------------------------------------------- */ +#endif /* ifndef REED_SENSOR_H_ */ diff --git a/platform/z1/dev/sht25.c b/platform/z1/dev/sht25.c index e17d7477b..b8356087b 100644 --- a/platform/z1/dev/sht25.c +++ b/platform/z1/dev/sht25.c @@ -124,11 +124,11 @@ sht25_read(uint8_t variable) return rd; } /*---------------------------------------------------------------------------*/ -static int16_t -value(uint8_t type) +static int +value(int type) { return sht25_read(type); } /*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(sht25, "SHT25", value, configure, status); +SENSORS_SENSOR(sht25, SHT25_SENSOR, value, configure, status); /*---------------------------------------------------------------------------*/ diff --git a/platform/z1/dev/sht25.h b/platform/z1/dev/sht25.h index 1b0bb27bc..65d9399d3 100644 --- a/platform/z1/dev/sht25.h +++ b/platform/z1/dev/sht25.h @@ -64,6 +64,8 @@ #define SHT25_VAL_HUM SHT25_HUM_HOLD #define SHT25_ERROR -1 /* -------------------------------------------------------------------------- */ +#define SHT25_SENSOR "SHT25 Sensor" +/* -------------------------------------------------------------------------- */ extern const struct sensors_sensor sht25; /* -------------------------------------------------------------------------- */ #endif /* ifndef SHT25_H_ */ diff --git a/regression-tests/00-doxygen/doxyerrors.cnt b/regression-tests/00-doxygen/doxyerrors.cnt index 485369e4e..360b9e4ba 100644 --- a/regression-tests/00-doxygen/doxyerrors.cnt +++ b/regression-tests/00-doxygen/doxyerrors.cnt @@ -1 +1,2 @@ -205 +209 + diff --git a/regression-tests/01-compile-base/Makefile b/regression-tests/01-compile-base/Makefile index d6fb60a91..e756bf5a6 100644 --- a/regression-tests/01-compile-base/Makefile +++ b/regression-tests/01-compile-base/Makefile @@ -20,7 +20,6 @@ powertrace/sky \ rime/sky \ rime/z1 \ ravenusbstick/avr-ravenusb \ -rest-example/sky \ servreg-hack/sky \ sky/sky \ sky-ip/sky \ @@ -30,7 +29,6 @@ sky-shell-webserver/sky \ tcp-socket/minimal-net \ telnet-server/minimal-net \ webserver/minimal-net \ -webserver-ipv6/exp5438 \ webserver-ipv6/eval-adf7xxxmb4z \ wget/minimal-net \ z1/z1 \ diff --git a/regression-tests/12-rpl/09-rpl-probing.csc b/regression-tests/12-rpl/09-rpl-probing.csc new file mode 100644 index 000000000..bc29029af --- /dev/null +++ b/regression-tests/12-rpl/09-rpl-probing.csc @@ -0,0 +1,258 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype190 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype481 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype692 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 8.0 + 2.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype481 + + + + org.contikios.cooja.interfaces.Position + -7.19071602882406 + 34.96668248624779 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype190 + + + + org.contikios.cooja.interfaces.Position + -17.870288882812428 + 4.581754854333804 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype692 + + + + org.contikios.cooja.plugins.SimControl + 280 + 2 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.494541140753371 0.0 0.0 2.494541140753371 168.25302383129448 116.2254386098645 + + 400 + 3 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 597 + 0 + 428 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 605 + 1 + 684 + 604 + 14 + + + diff --git a/regression-tests/15-compile-arm-apcs-ports/Makefile b/regression-tests/15-compile-arm-apcs-ports/Makefile index 394c11414..e73a9a39f 100644 --- a/regression-tests/15-compile-arm-apcs-ports/Makefile +++ b/regression-tests/15-compile-arm-apcs-ports/Makefile @@ -4,19 +4,10 @@ TOOLSDIR=../../tools EXAMPLES = \ hello-world/econotag \ hello-world/mbxxx \ -hello-world/cc2538dk \ ipv6/rpl-border-router/econotag \ -ipv6/rpl-border-router/cc2538dk \ er-rest-example/econotag \ -er-rest-example/cc2538dk \ webserver-ipv6/econotag \ -webserver-ipv6/cc2538dk \ -cc2538dk/cc2538dk \ -cc2538dk/udp-ipv6-echo-server/cc2538dk \ -cc2538dk/sniffer/cc2538dk \ -cc2538dk/mqtt-demo/cc2538dk \ ipv6/multicast/econotag \ -ipv6/multicast/cc2538dk \ TOOLS= diff --git a/regression-tests/18-compile-arm-ports/Makefile b/regression-tests/18-compile-arm-ports/Makefile index 4389c6d86..217b5eef9 100644 --- a/regression-tests/18-compile-arm-ports/Makefile +++ b/regression-tests/18-compile-arm-ports/Makefile @@ -8,6 +8,15 @@ webserver-ipv6/ev-aducrf101mkxz \ ipv6/multicast/ev-aducrf101mkxz \ cc2538dk/sniffer/ev-aducrf101mkxz \ cc26xx/cc26xx-web-demo/srf06-cc26xx \ +hello-world/cc2538dk \ +ipv6/rpl-border-router/cc2538dk \ +er-rest-example/cc2538dk \ +webserver-ipv6/cc2538dk \ +cc2538dk/cc2538dk \ +cc2538dk/udp-ipv6-echo-server/cc2538dk \ +cc2538dk/sniffer/cc2538dk \ +cc2538dk/mqtt-demo/cc2538dk \ +ipv6/multicast/cc2538dk \ TOOLS= diff --git a/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc b/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc new file mode 100644 index 000000000..c30af5032 --- /dev/null +++ b/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc @@ -0,0 +1,245 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 1.0 + generated + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype503 + ip64-router/ip64-router.c TARGET=cooja-ip64 + [CONTIKI_DIR]/examples/ip64-router/ip64-router.c + make ip64-router.cooja-ip64 TARGET=cooja-ip64 + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype555 + examples/http-socket/http-example.c + [CONTIKI_DIR]/examples/http-socket/http-example.c + make http-example.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 55.719691912311305 + 37.8697579181178 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype503 + + + + org.contikios.cooja.interfaces.Position + 65.60514720922419 + 33.88871867406431 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype555 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 606 + 15 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.TrafficVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.LEDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + 8.230641272440463 0.0 0.0 8.230641272440463 -395.6087959411366 -239.69239249818943 + + 219 + 3 + 171 + 29 + 27 + + + org.contikios.cooja.plugins.LogListener + + + + + + 888 + 2 + 603 + 34 + 307 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 960 + 0 + 682 + 528 + 192 + + + org.contikios.cooja.serialsocket.SerialSocketServer + 0 + + 60001 + true + + 362 + 4 + 116 + 234 + 101 + + + diff --git a/regression-tests/20-ip64/Makefile b/regression-tests/20-ip64/Makefile new file mode 100644 index 000000000..272bc7da1 --- /dev/null +++ b/regression-tests/20-ip64/Makefile @@ -0,0 +1 @@ +include ../Makefile.simulation-test diff --git a/tools/6502/Makefile b/tools/6502/Makefile index 6e0d6bd50..143393cf0 100644 --- a/tools/6502/Makefile +++ b/tools/6502/Makefile @@ -73,14 +73,14 @@ apple2: contiki-apple2-1.dsk contiki-apple2-2.dsk contiki-apple2-3.dsk contiki-a contiki-apple2-1.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ - java -jar $(AC) -p $@ menu.system sys 0 < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ethconfi bin 0 < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ipconfig bin 0 < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webbrows.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh + java -jar $(AC) -p $@ webbrows.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ webbrows bin < ../../examples/webbrowser/webbrowser.apple2enh - java -jar $(AC) -p $@ wget.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ wget.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ wget bin < ../../examples/wget/wget.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth @@ -90,14 +90,14 @@ contiki-apple2-1.dsk: apple2enh-makes contiki-apple2-2.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ - java -jar $(AC) -p $@ menu.system sys 0 < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ethconfi bin 0 < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ipconfig bin 0 < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ irc.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh + java -jar $(AC) -p $@ irc.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ irc bin < ../../examples/irc/irc-client.apple2enh - java -jar $(AC) -p $@ breadbox.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ breadbox.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ breadbox bin < ../../../contikiprojects/vandenbrande.com/twitter/platform/apple2enh/breadbox64.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth @@ -107,14 +107,14 @@ contiki-apple2-2.dsk: apple2enh-makes contiki-apple2-3.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ - java -jar $(AC) -p $@ menu.system sys 0 < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ethconfi bin 0 < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ipconfig bin 0 < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ email.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh + java -jar $(AC) -p $@ email.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ email bin < ../../examples/email/email-client.apple2enh - java -jar $(AC) -p $@ ftp.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ftp.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ ftp bin < ../../examples/ftp/ftp-client.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth @@ -124,14 +124,14 @@ contiki-apple2-3.dsk: apple2enh-makes contiki-apple2-4.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ - java -jar $(AC) -p $@ menu.system sys 0 < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ethconfi bin 0 < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ipconfig bin 0 < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webserv.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh + java -jar $(AC) -p $@ webserv.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ webserv bin < ../../examples/webserver/webserver-example.apple2enh - java -jar $(AC) -p $@ telnetd.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ telnetd.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ telnetd bin < ../../examples/telnet-server/telnet-server.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth @@ -145,26 +145,26 @@ contiki-apple2-4.dsk: apple2enh-makes contiki-apple2.2mg: apple2enh-makes cp ../apple2enh/prodos.2mg $@ - java -jar $(AC) -p $@ menu.system sys 0 < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ethconfi bin 0 < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys 0 < $(CC65_HOME)/targetutil/loader.system - java -jar $(AC) -cc65 $@ ipconfig bin 0 < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webbrows.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh + java -jar $(AC) -p $@ webbrows.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ webbrows bin < ../../examples/webbrowser/webbrowser.apple2enh - java -jar $(AC) -p $@ wget.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ wget.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ wget bin < ../../examples/wget/wget.apple2enh - java -jar $(AC) -p $@ irc.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ irc.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ irc bin < ../../examples/irc/irc-client.apple2enh - java -jar $(AC) -p $@ breadbox.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ breadbox.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ breadbox bin < ../../../contikiprojects/vandenbrande.com/twitter/platform/apple2enh/breadbox64.apple2enh - java -jar $(AC) -p $@ email.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ email.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ email bin < ../../examples/email/email-client.apple2enh - java -jar $(AC) -p $@ ftp.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ftp.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ ftp bin < ../../examples/ftp/ftp-client.apple2enh - java -jar $(AC) -p $@ webserv.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ webserv.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ webserv bin < ../../examples/webserver/webserver-example.apple2enh - java -jar $(AC) -p $@ telnetd.system sys 0 < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ telnetd.system sys < $(CC65_HOME)/targetutil/loader.system java -jar $(AC) -cc65 $@ telnetd bin < ../../examples/telnet-server/telnet-server.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java index 0819b616e..21ed157ce 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java @@ -44,6 +44,7 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.mote.memory.MemoryInterface; import org.contikios.cooja.motes.AbstractEmulatedMote; + import avrora.arch.avr.AVRProperties; import avrora.core.LoadableProgram; import avrora.sim.AtmelInterpreter; @@ -54,6 +55,8 @@ import avrora.sim.mcu.EEPROM; import avrora.sim.platform.MicaZ; import avrora.sim.platform.PlatformFactory; +import org.contikios.cooja.avrmote.interfaces.MicaClock; + /** * @author Joakim Eriksson, Fredrik Osterlind */ @@ -74,6 +77,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private EEPROM eeprom = null; + private long executed = 0; + private long skipped = 0; + + /* Stack monitoring variables */ private boolean stopNextInstruction = false; @@ -184,6 +191,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private long cyclesExecuted = 0; private long cyclesUntil = 0; public void execute(long t) { + MicaClock clock = ((MicaClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ if (myMoteInterfaceHandler.getClock().getTime() < 0) { scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); @@ -196,13 +207,22 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { } /* TODO Poll mote interfaces? */ - + + /* skip if necessary */ + if (((1-deviation) * executed) > skipped) { + skipped += 1; + scheduleNextWakeup(t + Simulation.MILLISECOND); + } + /* Execute one millisecond */ cyclesUntil += NR_CYCLES_PER_MSEC; while (cyclesExecuted < cyclesUntil) { cyclesExecuted += interpreter.step(); } + /* book keeping */ + executed += 1; + /* TODO Poll mote interfaces? */ /* Schedule wakeup every millisecond */ diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java index 468e07a73..569e08dfd 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java @@ -54,10 +54,12 @@ public class MicaClock extends Clock { private MicaZMote myMote; private long timeDrift; /* Microseconds */ + private double deviation; public MicaClock(Mote mote) { simulation = mote.getSimulation(); myMote = (MicaZMote) mote; + deviation = 1.0; } public void setTime(long newTime) { @@ -68,6 +70,15 @@ public class MicaClock extends Clock { return simulation.getSimulationTime() + timeDrift; } + public double getDeviation() { + return deviation; + } + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; + } + public void setDrift(long drift) { timeDrift = drift; } @@ -75,19 +86,4 @@ public class MicaClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - return null; - } - - public void releaseInterfaceVisualizer(JPanel panel) { - } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java index 403376583..b22fbc145 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java @@ -78,6 +78,8 @@ import se.sics.mspsim.util.MapEntry; import se.sics.mspsim.util.MapTable; import se.sics.mspsim.profiler.SimpleProfiler; +import org.contikios.cooja.mspmote.interfaces.MspClock; + /** * @author Fredrik Osterlind */ @@ -288,13 +290,22 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc private long lastExecute = -1; /* Last time mote executed */ private long nextExecute; + + private long executed = 0; + private long skipped = 0; + public void execute(long time) { execute(time, EXECUTE_DURATION_US); } + public void execute(long t, int duration) { + MspClock clock = ((MspClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ - if (!booted && myMoteInterfaceHandler.getClock().getTime() < 0) { - scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); + if (!booted && clock.getTime() < 0) { + scheduleNextWakeup(t - clock.getTime()); return; } booted = true; @@ -313,12 +324,17 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t); } + if (((1-deviation) * executed) > skipped) { + lastExecute = lastExecute + duration; // (t+duration) - (t-lastExecute); + nextExecute = t+duration; + skipped += duration; + scheduleNextWakeup(nextExecute); + } + /* Execute MSPSim-based mote */ /* TODO Try-catch overhead */ try { - nextExecute = - t + duration + - myCpu.stepMicros(t - lastExecute, duration); + nextExecute = myCpu.stepMicros(Math.max(0, t-lastExecute), duration) + t + duration; lastExecute = t; } catch (EmulationException e) { String trace = e.getMessage() + "\n\n" + getStackTrace(); @@ -330,7 +346,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (nextExecute < t) { throw new RuntimeException(t + ": MSPSim requested early wakeup: " + nextExecute); } + /*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/ + executed += duration; scheduleNextWakeup(nextExecute); if (stopNextInstruction) { diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java index c66352e98..10aacffad 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java @@ -52,9 +52,11 @@ public class MspClock extends Clock { private Simulation simulation; private long timeDrift; /* Microseconds */ + private double deviation; public MspClock(Mote mote) { simulation = mote.getSimulation(); + deviation = 1.0; } public void setTime(long newTime) { @@ -72,20 +74,13 @@ public class MspClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - /* TODO Show current CPU speed */ - return null; + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; } - public void releaseInterfaceVisualizer(JPanel panel) { + public double getDeviation() { + return deviation; } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java index 127a7a3a7..b033ef06d 100644 --- a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java +++ b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java @@ -114,6 +114,14 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public long getTime() { return moteTime; } + + public void setDeviation(double deviation) { + logger.fatal("Can't change deviation");; + } + + public double getDeviation() { + return 1.0; + } public void doActionsBeforeTick() { /* Update time */ @@ -161,5 +169,4 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public void setConfigXML(Collection configXML, boolean visAvailable) { } - } diff --git a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java index faefaddfc..58ec05fa5 100644 --- a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java +++ b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java @@ -30,7 +30,19 @@ package org.contikios.cooja.interfaces; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + import org.contikios.cooja.*; +import org.jdom.Element; /** * Represents a mote's internal clock. Notice that the overall @@ -39,10 +51,10 @@ import org.contikios.cooja.*; * This observable never notifies. * * @author Fredrik Osterlind + * Andreas Löscher */ @ClassDescription("Clock") public abstract class Clock extends MoteInterface { - /** * Set mote's time to given time. * @@ -76,4 +88,88 @@ public abstract class Clock extends MoteInterface { */ public abstract long getDrift(); + + /** + * The clock deviation is a factor that represents with how much speed the + * mote progresses through the simulation in relation to the simulation speed. + * + * A value of 1.0 results in the mote being simulated with the same speed + * as the simulation. A value of 0.5 results in the mote being simulation + * at half of the simulation speed. + * + * @param deviation Deviation factor + */ + public abstract void setDeviation(double deviation); + + /** + * Get deviation factor + */ + public abstract double getDeviation(); + + @Override + public JPanel getInterfaceVisualizer() { + JPanel panel = new JPanel(); + GridLayout layout = new GridLayout(0,2); + + /* elements */ + final JLabel timeLabel = new JLabel("Time (ms)"); + final JTextField timeField = new JTextField(String.valueOf(getTime() / 1000)); + final JLabel deviationLabel = new JLabel("Deviation Factor"); + final JTextField deviationField = new JTextField(String.valueOf(getDeviation())); + final JButton readButton = new JButton("Read Clock Values"); + final JButton updateButton = new JButton("Write Clock Values"); + /* set layout */ + panel.setLayout(layout); + /* add components */ + panel.add(timeLabel); + panel.add(timeField); + panel.add(deviationLabel); + panel.add(deviationField); + panel.add(readButton); + panel.add(updateButton); + + readButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + timeField.setText(String.valueOf(getTime() / 1000)); + deviationField.setText(String.valueOf(getDeviation())); + } + } + }); + + updateButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + setTime(Long.parseLong(timeField.getText()) * 1000); + setDeviation(Double.parseDouble(deviationField.getText())); + } + } + }); + + return panel; + } + + @Override + public void releaseInterfaceVisualizer(JPanel panel) { + } + + @Override + public Collection getConfigXML() { + ArrayList config = new ArrayList(); + Element element = new Element("deviation"); + element.setText(String.valueOf(getDeviation())); + config.add(element); + return config; + } + + @Override + public void setConfigXML(Collection configXML, boolean visAvailable) { + for (Element element : configXML) { + if (element.getName().equals("deviation")) { + setDeviation(Double.parseDouble(element.getText())); + } + } + } } diff --git a/tools/sky/Makefile b/tools/sky/Makefile index 0b1fa08db..be3caa44b 100644 --- a/tools/sky/Makefile +++ b/tools/sky/Makefile @@ -22,4 +22,4 @@ endif all: $(SERIALDUMP) $(SERIALDUMP): serialdump.c - $(CC) -o $@ $< + $(CC) -O2 -o $@ $< diff --git a/tools/sky/serialdump-linux b/tools/sky/serialdump-linux index 8c7af779d..8bb8192c2 100755 Binary files a/tools/sky/serialdump-linux and b/tools/sky/serialdump-linux differ diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index ce6c2ae32..e3e47092b 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -6,35 +7,36 @@ #include #include #include +#include -#define BAUDRATE B57600 -#define BAUDRATE_S "57600" +#define BAUDRATE B115200 +#define BAUDRATE_S "115200" #ifdef linux #define MODEMDEVICE "/dev/ttyS0" #else #define MODEMDEVICE "/dev/com1" #endif /* linux */ -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 -#define CSNA_INIT 0x01 +#define CSNA_INIT 0x01 -#define BUFSIZE 40 -#define HCOLS 20 -#define ICOLS 18 +#define BUFSIZE 40 +#define HCOLS 20 +#define ICOLS 18 -#define MODE_START_DATE 0 -#define MODE_DATE 1 -#define MODE_START_TEXT 2 -#define MODE_TEXT 3 -#define MODE_INT 4 -#define MODE_HEX 5 -#define MODE_SLIP_AUTO 6 -#define MODE_SLIP 7 -#define MODE_SLIP_HIDE 8 +#define MODE_START_DATE 0 +#define MODE_DATE 1 +#define MODE_START_TEXT 2 +#define MODE_TEXT 3 +#define MODE_INT 4 +#define MODE_HEX 5 +#define MODE_SLIP_AUTO 6 +#define MODE_SLIP 7 +#define MODE_SLIP_HIDE 8 static unsigned char rxbuf[2048]; @@ -80,7 +82,8 @@ print_hex_line(unsigned char *prefix, unsigned char *outbuf, int index) } } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct termios options; fd_set mask, smask; @@ -95,100 +98,103 @@ int main(int argc, char **argv) unsigned char lastc = '\0'; int index = 1; - while (index < argc) { - if (argv[index][0] == '-') { + while(index < argc) { + if(argv[index][0] == '-') { switch(argv[index][1]) { - case 'b': - /* set speed */ - if (strcmp(&argv[index][2], "38400") == 0) { - speed = B38400; - speedname = "38400"; - } else if (strcmp(&argv[index][2], "19200") == 0) { - speed = B19200; - speedname = "19200"; - } else if (strcmp(&argv[index][2], "57600") == 0) { - speed = B57600; - speedname = "57600"; - } else if (strcmp(&argv[index][2], "115200") == 0) { - speed = B115200; - speedname = "115200"; - } else { - fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); - return usage(1); - } - break; - case 'x': - mode = MODE_HEX; - break; - case 'i': - mode = MODE_INT; - break; - case 's': - switch(argv[index][2]) { - case 'n': - mode = MODE_SLIP_HIDE; - break; - case 'o': - mode = MODE_SLIP; - break; - default: - mode = MODE_SLIP_AUTO; - break; - } - break; - case 'T': - if(strlen(&argv[index][2]) == 0) { - timeformat = "%Y-%m-%d %H:%M:%S"; - } else { - timeformat = &argv[index][2]; - } - mode = MODE_START_DATE; - break; - case 'h': - return usage(0); - default: - fprintf(stderr, "unknown option '%c'\n", argv[index][1]); - return usage(1); + case 'b': + /* set speed */ + if(strcmp(&argv[index][2], "38400") == 0) { + speed = B38400; + speedname = "38400"; + } else if(strcmp(&argv[index][2], "19200") == 0) { + speed = B19200; + speedname = "19200"; + } else if(strcmp(&argv[index][2], "57600") == 0) { + speed = B57600; + speedname = "57600"; + } else if(strcmp(&argv[index][2], "115200") == 0) { + speed = B115200; + speedname = "115200"; + } else { + fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); + return usage(1); + } + break; + case 'x': + mode = MODE_HEX; + break; + case 'i': + mode = MODE_INT; + break; + case 's': + switch(argv[index][2]) { + case 'n': + mode = MODE_SLIP_HIDE; + break; + case 'o': + mode = MODE_SLIP; + break; + default: + mode = MODE_SLIP_AUTO; + break; + } + break; + case 'T': + if(strlen(&argv[index][2]) == 0) { + timeformat = "%Y-%m-%d %H:%M:%S"; + } else { + timeformat = &argv[index][2]; + } + mode = MODE_START_DATE; + break; + case 'h': + return usage(0); + default: + fprintf(stderr, "unknown option '%c'\n", argv[index][1]); + return usage(1); } index++; } else { device = argv[index++]; - if (index < argc) { - fprintf(stderr, "too many arguments\n"); - return usage(1); + if(index < argc) { + fprintf(stderr, "too many arguments\n"); + return usage(1); } } } fprintf(stderr, "connecting to %s (%s)", device, speedname); -#ifndef __APPLE__ - fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); +#ifdef O_SYNC + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC); + if(fd < 0 && errno == EINVAL){ // O_SYNC not supported (e.g. raspberian) + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT); + } #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif - if (fd <0) { + if(fd < 0) { fprintf(stderr, "\n"); - perror(device); + perror("open"); exit(-1); } fprintf(stderr, " [OK]\n"); - if (fcntl(fd, F_SETFL, 0) < 0) { + if(fcntl(fd, F_SETFL, 0) < 0) { perror("could not set fcntl"); exit(-1); } - if (tcgetattr(fd, &options) < 0) { + if(tcgetattr(fd, &options) < 0) { perror("could not get options"); exit(-1); } -/* fprintf(stderr, "serial options set\n"); */ + /* fprintf(stderr, "serial options set\n"); */ cfsetispeed(&options, speed); cfsetospeed(&options, speed); /* Enable the receiver and set local mode */ options.c_cflag |= (CLOCAL | CREAD); /* Mask the character size bits and turn off (odd) parity */ - options.c_cflag &= ~(CSIZE|PARENB|PARODD); + options.c_cflag &= ~(CSIZE | PARENB | PARODD); /* Select 8 data bits */ options.c_cflag |= CS8; @@ -197,30 +203,29 @@ int main(int argc, char **argv) /* Raw output */ options.c_oflag &= ~OPOST; - if (tcsetattr(fd, TCSANOW, &options) < 0) { + if(tcsetattr(fd, TCSANOW, &options) < 0) { perror("could not set options"); exit(-1); } /* Make read() return immediately */ -/* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ -/* perror("\ncould not set fcntl"); */ -/* exit(-1); */ -/* } */ + /* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ + /* perror("\ncould not set fcntl"); */ + /* exit(-1); */ + /* } */ FD_ZERO(&mask); FD_SET(fd, &mask); FD_SET(fileno(stdin), &mask); index = 0; - for (;;) { + for(;;) { smask = mask; - nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, - (struct timeval *) 0); + nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if(nfound < 0) { - if (errno == EINTR) { - fprintf(stderr, "interrupted system call\n"); - continue; + if(errno == EINTR) { + fprintf(stderr, "interrupted system call\n"); + continue; } /* something is very wrong! */ perror("select"); @@ -230,143 +235,142 @@ int main(int argc, char **argv) if(FD_ISSET(fileno(stdin), &smask)) { /* data from standard in */ int n = read(fileno(stdin), buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); - } else if (n > 0) { - /* because commands might need parameters, lines needs to be - separated which means the terminating LF must be sent */ -/* while(n > 0 && buf[n - 1] < 32) { */ -/* n--; */ -/* } */ - if(n > 0) { - int i; - /* fprintf(stderr, "SEND %d bytes\n", n);*/ - /* write slowly */ - for (i = 0; i < n; i++) { - if (write(fd, &buf[i], 1) <= 0) { - perror("write"); - exit(1); - } else { - fflush(NULL); - usleep(6000); - } - } - } + if(n < 0) { + perror("could not read"); + exit(-1); + } else if(n > 0) { + /* because commands might need parameters, lines needs to be + separated which means the terminating LF must be sent */ + /* while(n > 0 && buf[n - 1] < 32) { */ + /* n--; */ + /* } */ + if(n > 0) { + int i; + /* fprintf(stderr, "SEND %d bytes\n", n);*/ + /* write slowly */ + for(i = 0; i < n; i++) { + if(write(fd, &buf[i], 1) <= 0) { + perror("write"); + exit(1); + } else { + fflush(NULL); + usleep(6000); + } + } + } } else { - /* End of input, exit. */ - exit(0); + /* End of input, exit. */ + exit(0); } } if(FD_ISSET(fd, &smask)) { int i, j, n = read(fd, buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); + if(n < 0) { + perror("could not read"); + exit(-1); } for(i = 0; i < n; i++) { - switch(mode) { - case MODE_START_TEXT: - case MODE_TEXT: - printf("%c", buf[i]); - break; - case MODE_START_DATE: { - time_t t; - t = time(&t); - strftime(outbuf, HCOLS, timeformat, localtime(&t)); - printf("%s|", outbuf); - mode = MODE_DATE; - } - /* continue into the MODE_DATE */ - case MODE_DATE: - printf("%c", buf[i]); - if(buf[i] == '\n') { - mode = MODE_START_DATE; - } - break; - case MODE_INT: - printf("%03d ", buf[i]); - if(++index >= ICOLS) { - index = 0; - printf("\n"); - } - break; - case MODE_HEX: - rxbuf[index++] = buf[i]; - if(index >= HCOLS) { - print_hex_line("", rxbuf, index); - index = 0; - printf("\n"); - } - break; + switch(mode) { + case MODE_START_TEXT: + case MODE_TEXT: + printf("%c", buf[i]); + break; + case MODE_START_DATE: { + time_t t; + t = time(&t); + strftime(outbuf, HCOLS, timeformat, localtime(&t)); + printf("%s|", outbuf); + mode = MODE_DATE; + } + /* continue into the MODE_DATE */ + case MODE_DATE: + printf("%c", buf[i]); + if(buf[i] == '\n') { + mode = MODE_START_DATE; + } + break; + case MODE_INT: + printf("%03d ", buf[i]); + if(++index >= ICOLS) { + index = 0; + printf("\n"); + } + break; + case MODE_HEX: + rxbuf[index++] = buf[i]; + if(index >= HCOLS) { + print_hex_line("", rxbuf, index); + index = 0; + printf("\n"); + } + break; - case MODE_SLIP_AUTO: - case MODE_SLIP_HIDE: - if(!flags && (buf[i] != SLIP_END)) { - /* Not a SLIP packet? */ - printf("%c", buf[i]); - break; - } - /* continue to slip only mode */ - case MODE_SLIP: - switch(buf[i]) { - case SLIP_ESC: - lastc = SLIP_ESC; - break; + case MODE_SLIP_AUTO: + case MODE_SLIP_HIDE: + if(!flags && (buf[i] != SLIP_END)) { + /* Not a SLIP packet? */ + printf("%c", buf[i]); + break; + } + /* continue to slip only mode */ + case MODE_SLIP: + switch(buf[i]) { + case SLIP_ESC: + lastc = SLIP_ESC; + break; - case SLIP_END: - if(index > 0) { - if(flags != 2 && mode != MODE_SLIP_HIDE) { - /* not overflowed: show packet */ - print_hex_line("SLIP: ", rxbuf, - index > HCOLS ? HCOLS : index); - printf("\n"); - } - lastc = '\0'; - index = 0; - flags = 0; - } else { - flags = !flags; - } - break; + case SLIP_END: + if(index > 0) { + if(flags != 2 && mode != MODE_SLIP_HIDE) { + /* not overflowed: show packet */ + print_hex_line("SLIP: ", rxbuf, index > HCOLS ? HCOLS : index); + printf("\n"); + } + lastc = '\0'; + index = 0; + flags = 0; + } else { + flags = !flags; + } + break; - default: - if(lastc == SLIP_ESC) { - lastc = '\0'; + default: + if(lastc == SLIP_ESC) { + lastc = '\0'; - /* Previous read byte was an escape byte, so this byte will be - interpreted differently from others. */ - switch(buf[i]) { - case SLIP_ESC_END: - buf[i] = SLIP_END; - break; - case SLIP_ESC_ESC: - buf[i] = SLIP_ESC; - break; - } - } + /* Previous read byte was an escape byte, so this byte will be + interpreted differently from others. */ + switch(buf[i]) { + case SLIP_ESC_END: + buf[i] = SLIP_END; + break; + case SLIP_ESC_ESC: + buf[i] = SLIP_ESC; + break; + } + } - rxbuf[index++] = buf[i]; - if(index >= sizeof(rxbuf)) { - fprintf(stderr, "**** slip overflow\n"); - index = 0; - flags = 2; - } - break; - } - break; - } + rxbuf[index++] = buf[i]; + if(index >= sizeof(rxbuf)) { + fprintf(stderr, "**** slip overflow\n"); + index = 0; + flags = 2; + } + break; + } + break; + } } /* after processing for some output modes */ if(index > 0) { - switch(mode) { - case MODE_HEX: - print_hex_line("", rxbuf, index); - break; - } + switch(mode) { + case MODE_HEX: + print_hex_line("", rxbuf, index); + break; + } } fflush(stdout); } diff --git a/tools/wpcapslip/Connect.java b/tools/wpcapslip/Connect.java new file mode 100644 index 000000000..7ec6a0699 --- /dev/null +++ b/tools/wpcapslip/Connect.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +public class Connect { + private static Process cmd1Process; + private static Process cmd2Process; + private static BufferedOutputStream cmd1Out = null; + private static BufferedOutputStream cmd2Out = null; + + private static final int BUFSIZE = 512; + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("Usage: " + Connect.class.getName() + " [cmd1] [cmd2]"); + System.exit(1); + } + + /* Command 1 */ + String cmd1 = args[0]; + System.out.println("> " + cmd1); + cmd1Process = Runtime.getRuntime().exec(cmd1, null, new File(".")); + final DataInputStream cmd1Input = new DataInputStream( + cmd1Process.getInputStream()); + final BufferedReader cmd1Err = new BufferedReader( + new InputStreamReader(cmd1Process.getErrorStream())); + cmd1Out = new BufferedOutputStream(cmd1Process.getOutputStream()); + Thread readInput = new Thread(new Runnable() { + + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = cmd1Input.read(buf, 0, BUFSIZE); + if (numRead > 0 && cmd2Out != null) { + /* System.err.println("1>2 " + numRead); */ + cmd2Out.write(buf, 0, numRead); + cmd2Out.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + String exitVal = "?"; + try { + if (cmd1Process != null) { + exitVal = "" + cmd1Process.exitValue(); + } + } catch (IllegalStateException e) { + e.printStackTrace(); + exitVal = "!"; + } + System.out.println("cmd1 terminated: " + exitVal); + exit(); + } + }, "read stdout cmd1"); + Thread readError = new Thread(new Runnable() { + public void run() { + String line; + try { + while ((line = cmd1Err.readLine()) != null) { + System.err.println("cmd1 err: " + line); + } + cmd1Err.close(); + } catch (IOException e) { + } + System.err.println("cmd1 terminated."); + exit(); + } + }, "read error cmd1"); + readInput.start(); + readError.start(); + + /* Command 2 */ + String cmd2 = args[1]; + System.err.println("> " + cmd2); + cmd2Process = Runtime.getRuntime().exec(cmd2, null, new File(".")); + final DataInputStream cmd2Input = new DataInputStream( + cmd2Process.getInputStream()); + final BufferedReader cmd2Err = new BufferedReader( + new InputStreamReader(cmd2Process.getErrorStream())); + cmd2Out = new BufferedOutputStream(cmd2Process.getOutputStream()); + readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = cmd2Input.read(buf, 0, BUFSIZE); + if (numRead > 0 && cmd1Out != null) { + /* System.err.println("2>1 " + numRead); */ + cmd1Out.write(buf, 0, numRead); + cmd1Out.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + String exitVal = "?"; + try { + if (cmd2Process != null) { + exitVal = "" + cmd2Process.exitValue(); + } + } catch (IllegalStateException e) { + e.printStackTrace(); + exitVal = "!"; + } + System.out.println("cmd2 terminated: " + exitVal); + exit(); + } + }, "read stdout cmd2"); + readError = new Thread(new Runnable() { + public void run() { + String line; + try { + while ((line = cmd2Err.readLine()) != null) { + System.err.println("cmd2 err: " + line); + } + cmd2Err.close(); + } catch (IOException e) { + } + System.err.println("cmd2 terminated."); + exit(); + } + }, "read error cmd2"); + readInput.start(); + readError.start(); + + while (true) { + Thread.sleep(100); + } + } + + private static void exit() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + try { + if (cmd1Process != null) { + cmd1Process.destroy(); + } + } catch (Exception e) { + } + try { + if (cmd2Process != null) { + cmd2Process.destroy(); + } + } catch (Exception e) { + } + System.err.flush(); + System.exit(1); + } + +} diff --git a/tools/wpcapslip/ConnectSocket.java b/tools/wpcapslip/ConnectSocket.java new file mode 100644 index 000000000..417ebac1d --- /dev/null +++ b/tools/wpcapslip/ConnectSocket.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.net.Socket; + +public class ConnectSocket { + private static BufferedOutputStream stdoutOutput = null; + private static BufferedOutputStream networkServerOutput = null; + + private static final int BUFSIZE = 512; + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("Usage: " + ConnectSocket.class.getName() + " [server ip] [server port]"); + System.exit(1); + } + + /* Stdin */ + final BufferedInputStream stdinInput = new BufferedInputStream(new DataInputStream(System.in)); + stdoutOutput = new BufferedOutputStream(System.out); + Thread readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = stdinInput.read(buf, 0, BUFSIZE); + if (numRead > 0 && networkServerOutput != null) { + /* System.err.println("1>2 " + numRead); */ + + networkServerOutput.write(buf, 0, numRead); + networkServerOutput.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + exit(); + } + }, "read stdin"); + readInput.start(); + + /* Network server */ + Socket networkServer = new Socket(args[0], Integer.parseInt(args[1])); + final BufferedInputStream networkServerInput = new BufferedInputStream(new DataInputStream(networkServer.getInputStream())); + networkServerOutput = new BufferedOutputStream(networkServer.getOutputStream()); + readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = networkServerInput.read(buf, 0, BUFSIZE); + if (numRead > 0 && stdoutOutput != null) { + /* System.err.println("2>1 " + numRead); */ + stdoutOutput.write(buf, 0, numRead); + stdoutOutput.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + exit(); + } + }, "read network server"); + readInput.start(); + + while (true) { + Thread.sleep(100); + } + } + + private static void exit() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + System.err.flush(); + System.exit(1); + } +} diff --git a/tools/wpcapslip/Makefile b/tools/wpcapslip/Makefile index 1ab2caff2..fb11826eb 100644 --- a/tools/wpcapslip/Makefile +++ b/tools/wpcapslip/Makefile @@ -1,12 +1,21 @@ CONTIKI=../.. -CFLAGS=-Wall -Werror -I$(CONTIKI)/core -I. +CC=gcc +CFLAGS=-Wall -I$(CONTIKI)/core -I. -all: wpcapslip +all: wpcapslip wpcapstdio Connect.class ConnectSocket.class +%.class: %.java + javac $*.java + vpath %.c $(CONTIKI)/core/net wpcapslip: wpcapslip.o wpcap.o tcpdump.o +wpcapstdio: wpcapstdio.o wpcap.o tcpdump.o + %: %.o $(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@ + +clean: + rm -f *.class *.exe *.o \ No newline at end of file diff --git a/apps/shell/shell-netfile.h b/tools/wpcapslip/net/tcpdump.h similarity index 83% rename from apps/shell/shell-netfile.h rename to tools/wpcapslip/net/tcpdump.h index 2cbe362f0..bfa9fdd3e 100644 --- a/apps/shell/shell-netfile.h +++ b/tools/wpcapslip/net/tcpdump.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2005, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,19 +29,12 @@ * This file is part of the Contiki operating system. * */ +#ifndef __TCPDUMP_H__ +#define __TCPDUMP_H__ -/** - * \file - * A brief description of what this file is. - * \author - * Adam Dunkels - */ +#include "net/ip/uip.h" -#ifndef SHELL_NETFILE_H_ -#define SHELL_NETFILE_H_ +int tcpdump_format(uint8_t *packet, uint16_t packetlen, + char *printbuf, uint16_t printbuflen); -#include "shell.h" - -void shell_netfile_init(void); - -#endif /* SHELL_NETFILE_H_ */ +#endif /* __TCPDUMP_H__ */ diff --git a/tools/wpcapslip/tcpdump.c b/tools/wpcapslip/tcpdump.c new file mode 100644 index 000000000..6883cfec3 --- /dev/null +++ b/tools/wpcapslip/tcpdump.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki-net.h" + +#include +#include + + struct ip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + }; + +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +struct tcpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + /* TCP header. */ + uint16_t srcport, + destport; + uint8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + uint16_t tcpchksum; + uint8_t urgp[2]; + uint8_t optdata[4]; +}; + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +struct icmpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + /* The ICMP and IP headers. */ + /* ICMP (echo) header. */ + uint8_t type, icode; + uint16_t icmpchksum; + uint16_t id, seqno; +}; + + +/* The UDP and IP headers. */ +struct udpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + + /* UDP header. */ + uint16_t srcport, + destport; + uint16_t udplen; + uint16_t udpchksum; +}; + +#define ETHBUF ((struct eth_hdr *)&packet[0]) +#define IPBUF ((struct ip_hdr *)&packet[0]) +#define UDPBUF ((struct udpip_hdr *)&packet[0]) +#define ICMPBUF ((struct icmpip_hdr *)&packet[0]) +#define TCPBUF ((struct tcpip_hdr *)&packet[0]) + + +/*---------------------------------------------------------------------------*/ +static void +tcpflags(unsigned char flags, char *flagsstr) +{ + if(flags & TCP_FIN) { + *flagsstr++ = 'F'; + } + if(flags & TCP_SYN) { + *flagsstr++ = 'S'; + } + if(flags & TCP_RST) { + *flagsstr++ = 'R'; + } + if(flags & TCP_ACK) { + *flagsstr++ = 'A'; + } + if(flags & TCP_URG) { + *flagsstr++ = 'U'; + } + + *flagsstr = 0; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +n(uint16_t num, char *ptr) +{ + uint16_t d; + uint8_t a, f; + + if(num == 0) { + *ptr = '0'; + return ptr + 1; + } else { + f = 0; + for(d = 10000; d >= 1; d /= 10) { + a = (num / d) % 10; + if(f == 1 || a > 0) { + *ptr = a + '0'; + ++ptr; + f = 1; + } + } + } + return ptr; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +d(char *ptr) +{ + *ptr = '.'; + return ptr + 1; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +s(char *str, char *ptr) +{ + strcpy(ptr, str); + return ptr + strlen(str); +} +/*---------------------------------------------------------------------------*/ +int +tcpdump_format(uint8_t *packet, uint16_t packetlen, + char *buf, uint16_t buflen) +{ + char flags[8]; + if(IPBUF->proto == UIP_PROTO_ICMP) { + if(ICMPBUF->type == ICMP_ECHO) { + return s(" ping", + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))) - buf; + + /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d ping", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ + } else if(ICMPBUF->type == ICMP_ECHO_REPLY) { + return s(" pong", + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d pong", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ + } + } else if(IPBUF->proto == UIP_PROTO_UDP) { + return s(" UDP", + n(uip_htons(UDPBUF->destport), d( + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(uip_htons(UDPBUF->srcport), d( + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d UDP", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + uip_htons(UDPBUF->srcport), + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3], + uip_htons(UDPBUF->destport));*/ + } else if(IPBUF->proto == UIP_PROTO_TCP) { + tcpflags(TCPBUF->flags, flags); + return s(flags, + s(" ", + n(uip_htons(TCPBUF->destport), d( + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(uip_htons(TCPBUF->srcport), d( + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf))))))))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d %s", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + uip_htons(TCPBUF->srcport), + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3], + uip_htons(TCPBUF->destport), + flags); */ + } else { + strcpy(buf, "Unrecognized protocol"); + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/wpcapslip/wpcap.c b/tools/wpcapslip/wpcap.c index 5584557a9..b8127d47c 100644 --- a/tools/wpcapslip/wpcap.c +++ b/tools/wpcapslip/wpcap.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include @@ -69,7 +68,7 @@ #define PROGRESS(x) -static void raw_send(void *buf, int len); +void raw_send(void *buf, int len); struct pcap; @@ -150,7 +149,7 @@ struct arp_entry { struct uip_eth_addr ethaddr; uint8_t time; }; -static struct uip_eth_addr uip_lladdr = {{0,0,0,0,0,0}}; +struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; static const uip_ipaddr_t all_zeroes_addr = { { 0x0, /* rest is 0 */ } }; static const struct uip_eth_addr broadcast_ethaddr = {{0xff,0xff,0xff,0xff,0xff,0xff}}; @@ -164,18 +163,20 @@ static int arptime; static int logging; +uip_lladdr_t uip_lladdr; + static void log_message(char *msg1, char *msg2) { if(logging) { - printf("Log: %s %s\n", msg1, msg2); + fprintf(stderr, "Log: %s %s\n", msg1, msg2); } } /*---------------------------------------------------------------------------*/ static void error_exit(char *msg1) { - printf("error_exit: %s", msg1); + fprintf(stderr, "error_exit: %s", msg1); exit(EXIT_FAILURE); } /*---------------------------------------------------------------------------*/ @@ -198,11 +199,11 @@ init_pcap(struct in_addr addr) paddr != NULL; paddr = paddr->next) { if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) { - + struct in_addr interface_addr; interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr; log_message("init_pcap: with address: ", inet_ntoa(interface_addr)); - + if(interface_addr.s_addr == addr.s_addr) { pcap = pcap_open_live(interfaces->name, BUFSIZE, 0, -1, error); if(pcap == NULL) { @@ -263,7 +264,7 @@ set_ethaddr(struct in_addr addr) log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr)); if(adapter_addr.s_addr == addr.s_addr) { - printf("Using local network interface with address %s\n", + fprintf(stderr, "Using local network interface with address %s\n", inet_ntoa(adapter_addr)); if(adapters->PhysicalAddressLength != 6) { error_exit("ip addr specified on cmdline does not belong to an ethernet card\n"); @@ -292,12 +293,12 @@ print_packet(unsigned char *buf, int len) int i; for(i = 0; i < len; ++i) { - printf("0x%02x, ", buf[i]); + fprintf(stderr, "0x%02x, ", buf[i]); if(i % 8 == 7) { - printf("\n"); + fprintf(stderr, "\n"); } } - printf("\n\n"); + fprintf(stderr, "\n\n"); } /*---------------------------------------------------------------------------*/ static void @@ -305,7 +306,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr) { struct arp_entry *tabptr; int i, tmpage, c; - + /* Walk through the ARP mapping table and try to find an entry to update. If none is found, the IP -> MAC address mapping is inserted in the ARP table. */ @@ -318,7 +319,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr) /* Check if the source IP address of the incoming packet matches the IP address in this ARP table entry. */ if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) { - + /* An old entry found, update this and return. */ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); tabptr->time = arptime; @@ -399,7 +400,7 @@ arp_out(struct ethip_hdr *iphdr, int len) int i; #endif -#if 1 +#if 0 /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. @@ -425,7 +426,7 @@ arp_out(struct ethip_hdr *iphdr, int len) /* Else, we use the destination IP address. */ uip_ipaddr_copy(&ipaddr, &iphdr->destipaddr); } - + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) { @@ -439,9 +440,9 @@ arp_out(struct ethip_hdr *iphdr, int len) memset(arphdr->ethhdr.dest.addr, 0xff, 6); memset(arphdr->dhwaddr.addr, 0x00, 6); - memcpy(arphdr->ethhdr.src.addr, uip_lladdr.addr, 6); - memcpy(arphdr->shwaddr.addr, uip_lladdr.addr, 6); - + memcpy(arphdr->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(arphdr->shwaddr.addr, uip_ethaddr.addr, 6); + uip_ipaddr_copy(&arphdr->dipaddr, &ipaddr); uip_ipaddr_copy(&arphdr->sipaddr, &netaddr); arphdr->opcode = UIP_HTONS(ARP_REQUEST); /* ARP request. */ @@ -476,27 +477,27 @@ do_arp(void *buf, int len) if(hdr->ethhdr.type == UIP_HTONS(UIP_ETHTYPE_ARP)) { if(hdr->opcode == UIP_HTONS(ARP_REQUEST)) { /* Check if the ARP is for our network */ - /* printf("ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n", + /* fprintf(stderr, "ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n", uip_ipaddr_to_quad(&hdr->dipaddr), uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask));*/ if(uip_ipaddr_maskcmp(&hdr->dipaddr, &netaddr, &netmask)) { uip_ipaddr_t tmpaddr; - - /* printf("ARP for us.\n");*/ + + /* fprintf(stderr, "ARP for us.\n");*/ uip_arp_update(&hdr->sipaddr, &hdr->shwaddr); - + hdr->opcode = UIP_HTONS(ARP_REPLY); - + memcpy(&hdr->dhwaddr.addr, &hdr->shwaddr.addr, 6); memcpy(&hdr->shwaddr.addr, &uip_lladdr.addr, 6); memcpy(&hdr->ethhdr.src.addr, &uip_lladdr.addr, 6); memcpy(&hdr->ethhdr.dest.addr, &hdr->dhwaddr.addr, 6); - + uip_ipaddr_copy(&tmpaddr, &hdr->dipaddr); uip_ipaddr_copy(&hdr->dipaddr, &hdr->sipaddr); uip_ipaddr_copy(&hdr->sipaddr, &tmpaddr); - + hdr->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP); raw_send(hdr, sizeof(struct arp_hdr)); return NULL; @@ -521,8 +522,8 @@ cleanup(void) char buf[1024]; snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d", - uip_ipaddr_to_quad(&ifaddr)); - printf("%s\n", buf); + uip_ipaddr_to_quad(&netaddr)); + fprintf(stderr, "%s\n", buf); system(buf); } @@ -540,9 +541,9 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) struct in_addr addr; char buf[4000]; uint32_t tmpaddr; - + logging = log; - + addr.s_addr = inet_addr(ethcardaddr); tmpaddr = inet_addr(ethcardaddr); memcpy(&ifaddr.u16[0], &tmpaddr, sizeof(tmpaddr)); @@ -551,21 +552,21 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) tmpaddr = inet_addr(slipnetmask); memcpy(&netmask.u16[0], &tmpaddr, sizeof(tmpaddr)); - printf("Network address %d.%d.%d.%d/%d.%d.%d.%d\n", + fprintf(stderr, "Network address %d.%d.%d.%d/%d.%d.%d.%d\n", uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask)); - + snprintf(buf, sizeof(buf), "route add %d.%d.%d.%d mask %d.%d.%d.%d %d.%d.%d.%d", uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask), uip_ipaddr_to_quad(&ifaddr)); - printf("%s\n", buf); + fprintf(stderr, "%s\n", buf); system(buf); signal(SIGTERM, remove_route); log_message("wpcap_init: cmdline address: ", inet_ntoa(addr)); - + wpcap = LoadLibrary("wpcap.dll"); pcap_findalldevs = (int (*)(struct pcap_if **, char *)) GetProcAddress(wpcap, "pcap_findalldevs"); @@ -588,12 +589,12 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) #if 0 while(1) { int ret; - + ret = wpcap_poll(buf); if(ret > 0) { /* print_packet(buf, ret);*/ if(do_arp(buf, ret)) { - printf("IP packet\n"); + fprintf(stderr, "IP packet\n"); } } sleep(1); @@ -602,17 +603,16 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) } /*---------------------------------------------------------------------------*/ uint16_t -wpcap_poll(char **buf) +wpcap_poll(char **buf, int eth) { struct pcap_pkthdr *packet_header; unsigned char *packet; int len; + int ret; char *buf2; - switch(pcap_next_ex(pcap, &packet_header, &packet)) { - case -1: - error_exit("error on poll\n"); - case 0: + ret = pcap_next_ex(pcap, &packet_header, &packet); + if (ret != 1) { return 0; } @@ -622,13 +622,20 @@ wpcap_poll(char **buf) CopyMemory(*buf, packet, packet_header->caplen); len = packet_header->caplen; - /* printf("len %d\n", len);*/ + + if(eth) { + /* poll requested us to return the raw ethernet packet */ + return len; + } + + buf2 = do_arp(*buf, len); if(buf2 == NULL) { return 0; } else { len = len - (buf2 - *buf); *buf = buf2; + /*fprintf(stderr, "wpcap_poll() %d\n", len);*/ return len; } } @@ -644,7 +651,7 @@ wpcap_send(void *buf, int len) raw_send(buf2, len); } /*---------------------------------------------------------------------------*/ -static void +void raw_send(void *buf, int len) { /* printf("sending len %d\n", len);*/ diff --git a/tools/wpcapslip/wpcapslip.c b/tools/wpcapslip/wpcapslip.c index e6e193f90..b60af7f6a 100644 --- a/tools/wpcapslip/wpcapslip.c +++ b/tools/wpcapslip/wpcapslip.c @@ -47,8 +47,6 @@ #include #include #include -#include -#include #include #include @@ -75,6 +73,18 @@ static int should_print = 0; #define IP_HLEN 20 +/*---------------------------------------------------------------------------*/ +uint16_t +uip_htons(uint16_t val) +{ + return UIP_HTONS(val); +} +/*---------------------------------------------------------------------------*/ +uint32_t +uip_htonl(uint32_t val) +{ + return UIP_HTONL(val); +} /*---------------------------------------------------------------------------*/ static void print_packet(uint8_t *packet, int len) @@ -289,8 +299,9 @@ serial_to_wpcap(FILE *inslip) */ #define DEBUG_LINE_MARKER '\r' int ecode; + ecode = check_ip(&uip.iphdr, inbufptr); - if(ecode < 0 && inbufptr == 8 && strncmp(uip.inbuf, "=IPA", 4) == 0) { + if(ecode < 0 && inbufptr == 8 && strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) { static struct in_addr ipa; inbufptr = 0; @@ -902,7 +913,7 @@ main(int argc, char **argv) if(iphdr->ip_id != last_id) { last_id = iphdr->ip_id; /* printf("------ wpcap_poll ret %d\n", ret);*/ - print_packet(pbuf, ret); + print_packet((uint8_t*)pbuf, ret); write_to_serial(slipfd, pbuf, ret); slip_flushbuf(slipfd); sigalarm_reset(); diff --git a/tools/wpcapslip/wpcapstdio.c b/tools/wpcapslip/wpcapstdio.c new file mode 100644 index 000000000..88f1eace4 --- /dev/null +++ b/tools/wpcapslip/wpcapstdio.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2012, Thingsquare, www.thingsquare.com. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Fredrik Osterlind + * Based on wpcapslip.c by : Oliver Schmidt + */ + +/* This is a stripped-down version of wpcapslip: Instead of reading from and writing + * to a serial port, this program just reads and writes to stdin/stdout. To + * achieve the same functionality as wpcapslip, this program can hence be connected + * to serialdump. But, in contrast to wpcapslip, this program can easily be connected + * to networked or simulated serial ports. -- Fredrik, 2012 */ + +#include +#include +#include +#ifdef __CYGWIN__ +#include +#else /* __CYGWIN__ */ +#include +#endif /* __CYGWIN__ */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define PROGRESS(x) + +void wpcap_start(char *ethifaddr, char *netaddr, char *netmask, int logging); + +void wpcap_send(void *buf, int len); +void raw_send(void *buf, int len); + +uint16_t wpcap_poll(char **buf, int eth); + +#include "net/tcpdump.h" +static int should_print = 0; + +static int send_eth = 0; /* Sends ethernet frames or IP packets */ + +#define IP_HLEN 20 + +/*---------------------------------------------------------------------------*/ +uint16_t +uip_htons(uint16_t val) +{ + return UIP_HTONS(val); +} +/*---------------------------------------------------------------------------*/ +uint32_t +uip_htonl(uint32_t val) +{ + return UIP_HTONL(val); +} +/*---------------------------------------------------------------------------*/ +static void +print_packet(char* prefix, uint8_t *packet, int len) +{ + char buf[2000]; + if(should_print) { + tcpdump_format(packet, len, buf, sizeof(buf)); + fprintf(stderr, "%s: %s\n", prefix, buf); + } +} +/*---------------------------------------------------------------------------*/ +void cleanup(void); +/*---------------------------------------------------------------------------*/ +void +sigcleanup(int signo) +{ + fprintf(stderr, "signal %d\n", signo); + exit(0); /* exit(0) will call cleanup() */ +} +/*---------------------------------------------------------------------------*/ +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +struct ip { + u_int8_t ip_vhl; /* version and header length */ +#define IP_V4 0x40 +#define IP_V 0xf0 +#define IP_HL 0x0f + u_int8_t ip_tos; /* type of service */ + u_int16_t ip_len; /* total length */ + u_int16_t ip_id; /* identification */ + u_int16_t ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_int16_t ip_sum; /* checksum */ + u_int32_t ip_src, ip_dst; /* source and dest address */ + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +}; + +static int ip_id, last_id; + +int +ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); + +int +ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + fprintf(stderr, "%s\n", cmd); + fflush(stderr); + return system(cmd); +} +/*---------------------------------------------------------------------------*/ +int +is_sensible_string(const unsigned char *s, int len) +{ + int i; + for(i = 1; i < len; i++) { + if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { + continue; + } else if(s[i] < ' ' || '~' < s[i]) { + return 0; + } + } + return 1; +} +/*---------------------------------------------------------------------------*/ +u_int16_t +ip4sum(u_int16_t sum, const void *_p, u_int16_t len) +{ + u_int16_t t; + const u_int8_t *p = _p; + const u_int8_t *end = p + len; + + while(p < (end - 1)) { + t = (p[0] << 8) + p[1]; + sum += t; + if(sum < t) + sum++; + p += 2; + } + if(p < end) { + t = (p[0] << 8) + 0; + sum += t; + if(sum < t) + sum++; + } + return sum; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +chksum(const void *p, uint16_t len) +{ + uint16_t sum = ip4sum(0, p, len); + return (sum == 0) ? 0xffff : uip_htons(sum); +} +/*---------------------------------------------------------------------------*/ +int +check_ip(const struct ip *ip, unsigned ip_len) +{ + u_int16_t sum, ip_hl; + + if(send_eth) { + return 0; + } + + /* Check IP version and length. */ + if((ip->ip_vhl & IP_V) != IP_V4) { + return -1; + } + + if(uip_ntohs(ip->ip_len) > ip_len) { + return -2; + } + + if(uip_ntohs(ip->ip_len) < ip_len) { + return -3; + } + + /* Check IP header. */ + ip_hl = 4 * (ip->ip_vhl & IP_HL); + sum = ip4sum(0, ip, ip_hl); + if(sum != 0xffff && sum != 0x0) { + return -4; + } + + if(ip->ip_p == 6 || ip->ip_p == 17) { /* Check TCP or UDP header. */ + u_int16_t tcp_len = ip_len - ip_hl; + + /* Sum pseudoheader. */ + sum = ip->ip_p + tcp_len; /* proto and len, no carry */ + sum = ip4sum(sum, &ip->ip_src, 8); /* src and dst */ + + /* Sum TCP/UDP header and data. */ + sum = ip4sum(sum, (u_int8_t*)ip + ip_hl, tcp_len); + + /* Failed checksum test? */ + if(sum != 0xffff && sum != 0x0) { + if(ip->ip_p == 6) { /* TCP == 6 */ + return -5; + } else { /* UDP */ + /* Deal with disabled UDP checksums. */ + if(ip->uh_sum != 0) { + return -6; + } + } + } + } else if(ip->ip_p == 1) { /* ICMP */ + u_int16_t icmp_len = ip_len - ip_hl; + + sum = ip4sum(0, (u_int8_t*)ip + ip_hl, icmp_len); + if(sum != 0xffff && sum != 0x0) { + return -7; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Read a single character from stdin. When we have a full packet, write it to + * the network interface. + */ +void +serial_to_wpcap(void) +{ + static union { + unsigned char inbuf[2000]; + struct ip iphdr; + } uip; + static int inbufptr = 0; + + int ret; + unsigned char c; + + if(inbufptr >= sizeof(uip.inbuf)) { + inbufptr = 0; + return; + } + ret = read(STDIN_FILENO, &c, 1); + + if(ret <= 0) { + err(1, "serial_to_wpcap: read"); + inbufptr = 0; + return; + } + + switch (c) { + case SLIP_END: + if(inbufptr > 0) { + /* + * Sanity checks. + */ +#define DEBUG_LINE_MARKER '\r' + int ecode; + + ecode = check_ip(&uip.iphdr, inbufptr); + if(ecode < 0 && inbufptr == 8 + && strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) { + static struct in_addr ipa; + + inbufptr = 0; + if(memcmp(&ipa, &uip.inbuf[4], sizeof(ipa)) == 0) { + break; + } + + memcpy(&ipa, &uip.inbuf[4], sizeof(ipa)); + break; + } else if(ecode < 0) { + /* + * If sensible ASCII string, print it as debug info! + */ + /* printf("----------------------------------\n");*/ + if(uip.inbuf[0] == DEBUG_LINE_MARKER) { + fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr); + } else if(is_sensible_string(uip.inbuf, inbufptr)) { + fwrite(uip.inbuf, inbufptr, 1, stderr); + } else { + fprintf(stderr, "serial_to_wpcap: drop packet len=%d ecode=%d\n", + inbufptr, ecode); + } + inbufptr = 0; + break; + } + PROGRESS("s"); + + if(send_eth) { + raw_send(uip.inbuf, inbufptr); + } else { + /* printf("Sending to wpcap\n");*/ + if(uip.iphdr.ip_id != last_id) { + last_id = uip.iphdr.ip_id; + print_packet("to wpcap: ", uip.inbuf, inbufptr); + wpcap_send(uip.inbuf, inbufptr); + } else { + /*print_packet("IGNORED to wpcap: ", uip.inbuf, inbufptr);*/ + } + } + /* printf("After sending to wpcap\n");*/ + inbufptr = 0; + } + break; + + case SLIP_ESC: + /* TODO We do not actually check that we have another byte incoming, so + * we may block here */ + read(STDIN_FILENO, &c, 1); + + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + + /* FALLTHROUGH */ + default: + uip.inbuf[inbufptr++] = c; + break; + } +} +/*---------------------------------------------------------------------------*/ +unsigned char stdout_buf[2000]; +int stdout_buf_cnt; +/*---------------------------------------------------------------------------*/ +void +stdout_write(unsigned char c) +{ + if(stdout_buf_cnt >= sizeof(stdout_buf)) { + err(1, "stdout_write overflow"); + } + stdout_buf[stdout_buf_cnt] = c; + stdout_buf_cnt++; +} +/*---------------------------------------------------------------------------*/ +int +stdout_buf_empty(void) +{ + return stdout_buf_cnt == 0; +} +/*---------------------------------------------------------------------------*/ +void +stdout_flushbuf(void) +{ + if(stdout_buf_empty()) { + return; + } + + fwrite(stdout_buf, stdout_buf_cnt, 1, stdout); + stdout_buf_cnt = 0; + fflush(stdout); +} +/*---------------------------------------------------------------------------*/ +void +write_slip_stdout(void *inbuf, int len) +{ + u_int8_t *p = inbuf; + int i, ecode; + struct ip *iphdr = inbuf; + + if(!send_eth) { + /* + * Sanity checks. + */ + /*fprintf(stderr, "write_slip_stdout: %d\n", len);*/ + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + + if(iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) { + uint16_t nid = uip_htons(ip_id++); + iphdr->ip_id = nid; + nid = ~nid; /* negate */ + iphdr->ip_sum += nid; /* add */ + if(iphdr->ip_sum < nid) { /* 1-complement overflow? */ + iphdr->ip_sum++; + } + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + } + + iphdr->ip_ttl = uip_htons(uip_htons(iphdr->ip_ttl) + 1); + if(iphdr->ip_ttl == 0) { + fprintf(stderr, "Packet with ttl %d dropped\n", iphdr->ip_ttl); + return; + } + iphdr->ip_sum = 0; + iphdr->ip_sum = ~chksum(iphdr, 4 * (iphdr->ip_vhl & IP_HL)); + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + } + + for(i = 0; i < len; i++) { + switch (p[i]) { + case SLIP_END: + stdout_write(SLIP_ESC); + stdout_write(SLIP_ESC_END); + break; + case SLIP_ESC: + stdout_write(SLIP_ESC); + stdout_write(SLIP_ESC_ESC); + break; + default: + stdout_write(p[i]); + break; + } + } + stdout_write(SLIP_END); + /* printf("slip end\n");*/ + PROGRESS("t"); +} +/*---------------------------------------------------------------------------*/ +/*const char *ipaddr;*/ +/*const char *netmask;*/ +static int got_sigalarm; +void +sigalarm(int signo) +{ + got_sigalarm = 1; + return; +} +/*---------------------------------------------------------------------------*/ +void +sigalarm_reset(void) +{ +#ifdef linux +#define TIMEOUT (997*1000) +#else +#define TIMEOUT (2451*1000) +#endif + ualarm(TIMEOUT, TIMEOUT); + got_sigalarm = 0; +} +/*---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int c; + int ret; + char buf[4000]; + int logging = 0; + + ip_id = getpid() * time(NULL); + + while((c = getopt(argc, argv, "E:D:hl:t:T")) != -1) { + switch (c) { + case 'E': + send_eth = 1; + break; + + case 'T': + should_print = 1; + break; + + case 'l': + logging = 1; + break; + + case '?': + case 'h': + default: + err(1, + "usage: wpcapstdio [-E] [-l] [-T] "); + break; + } + } + argc -= (optind - 1); + argv += (optind - 1); + + if(argc != 4) { + err(1, "usage: wpcapstdio [-E] [-T] "); + } + + wpcap_start(argv[1], argv[2], argv[3], logging); + stdout_write(SLIP_END); + + atexit(cleanup); + signal(SIGHUP, sigcleanup); + signal(SIGTERM, sigcleanup); + signal(SIGINT, sigcleanup); + signal(SIGALRM, sigalarm); + + while(1) { + if(got_sigalarm) { + /* Send "?IPA". */ + stdout_write('?'); + stdout_write('I'); + stdout_write('P'); + stdout_write('A'); + stdout_write(SLIP_END); + got_sigalarm = 0; + } + + if(stdout_buf_empty()) { + char *pbuf = buf; + + ret = wpcap_poll(&pbuf, send_eth); + if(ret > 0) { + if(send_eth) { + write_slip_stdout(pbuf, ret); + stdout_flushbuf(); + } else { + struct ip *iphdr = (struct ip *)pbuf; + if(iphdr->ip_id != last_id) { + /*last_id = iphdr->ip_id;*/ + print_packet("to stdout: ", (uint8_t*)pbuf, ret); + write_slip_stdout(pbuf, ret); + stdout_flushbuf(); + } else { + /*print_packet("IGNORED to stdout: ", (uint8_t*)pbuf, ret);*/ + } + } + } + } + + if(!stdout_buf_empty()) { + stdout_flushbuf(); + } + + { + fd_set s_rd; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 100; + + do { + FD_ZERO(&s_rd); + FD_SET(fileno(stdin), &s_rd); + select(fileno(stdin) + 1, &s_rd, NULL, NULL, &tv); + if(FD_ISSET(fileno(stdin), &s_rd)) { + serial_to_wpcap(); + } + } while(FD_ISSET(fileno(stdin), &s_rd)); + } + } +} +/*---------------------------------------------------------------------------*/