Contiki 3.x
params.c
1 /*
2  * Copyright (c) 2011, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 #define PRINTF(FORMAT, args ...) printf_P(PSTR(FORMAT),##args)
33 
34 #define DEBUG 1
35 #if DEBUG
36 #define PRINTD(FORMAT, args ...) printf_P(PSTR(FORMAT),##args)
37 #else
38 #define PRINTD(...)
39 #endif
40 
41 #include "contiki.h"
42 #include <avr/pgmspace.h>
43 #include <avr/eeprom.h>
44 #include <stdio.h>
45 #include <string.h>
46 
47 #if AVR_WEBSERVER
48 /* #include "httpd-fs.h" */
49 /* #include "httpd-cgi.h" */
50 #endif
51 
52 #include "contiki-net.h"
53 #include "params.h"
54 
55 #if CONTIKI_CONF_RANDOM_MAC
56 extern uint8_t rng_get_uint8(void);
57 static void
58 generate_new_eui64(uint8_t eui64[8])
59 {
60  eui64[0] = 0x02;
61  eui64[1] = rng_get_uint8();
62  eui64[2] = rng_get_uint8();
63  eui64[3] = 0xFF;
64  eui64[4] = 0xFE;
65  eui64[5] = rng_get_uint8();
66  eui64[6] = rng_get_uint8();
67  eui64[7] = rng_get_uint8();
68 }
69 #endif
70 
71 #if AVR_WEBSERVER
72 /* Webserver builds can set these in httpd-fsdata.c via makefsdata.h */
73 extern uint8_t default_mac_address[8];
74 extern uint8_t default_server_name[16];
75 extern uint8_t default_domain_name[30];
76 #else
77 const uint8_t default_mac_address[8] PROGMEM = PARAMS_EUI64ADDR;
78 const uint8_t default_server_name[] PROGMEM = PARAMS_SERVERNAME;
79 const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME;
80 #endif
81 
82 #if PARAMETER_STORAGE == 0
83 /* 0 Hard coded, minmal program and eeprom usage. */
84 uint8_t
85 params_get_eui64(uint8_t *eui64)
86 {
87 #if CONTIKI_CONF_RANDOM_MAC
88  PRINTD("Generating random EUI64 MAC\n");
89  generate_new_eui64(eui64);
90  return 1;
91 #else
92  uint8_t i;
93  for(i = 0; i < sizeof(default_mac_address); i++) {
94  eui64[i] = pgm_read_byte_near(default_mac_address + i);
95  }
96  return 0;
97 #endif
98 }
99 #elif PARAMETER_STORAGE == 1
100 /* 1 Stored in fixed eeprom locations, rewritten from flash if corrupt.
101  * They can be manually changed and kept over program reflash.
102  * The channel and bit complement are used to check EEMEM integrity,
103  * If corrupt all values will be rewritten with the default flash values.
104  * To make this work, get the channel before anything else.
105  */
106 #if !AVR_WEBSERVER
107 uint8_t eemem_mac_address[] EEMEM = PARAMS_EUI64ADDR;
108 uint8_t eemem_server_name[] EEMEM = PARAMS_SERVERNAME;
109 uint8_t eemem_domain_name[] EEMEM = PARAMS_DOMAINNAME;
110 #endif /*AVR_WEBSERVER */
111 
112 uint16_t eemem_nodeid EEMEM = PARAMS_NODEID;
113 uint8_t eemem_channel[2] EEMEM = { PARAMS_CHANNEL, ~PARAMS_CHANNEL };
114 uint16_t eemem_panid EEMEM = PARAMS_PANID;
115 uint16_t eemem_panaddr EEMEM = PARAMS_PANADDR;
116 uint8_t eemem_txpower EEMEM = PARAMS_TXPOWER;
117 
118 #if CONTIKI_CONF_RANDOM_MAC
119 static uint8_t randomeui64;
120 #endif
121 
122 uint8_t
123 params_get_channel(void)
124 {
125  uint8_t x[2];
126  *(uint16_t *)x = eeprom_read_word((uint16_t *)&eemem_channel);
127 /* Don't return an invalid channel number */
128  if((x[0] < 11) || (x[0] > 26)) {
129  x[1] = x[0];
130  }
131 /* Do exclusive or test on the two values read */
132  if((uint8_t)x[0] != (uint8_t) ~x[1]) { /* ~x[1] can promote comparison to 16 bit */
133 /* Verification fails, rewrite everything */
134  uint8_t i, buffer[32];
135  PRINTD("EEPROM is corrupt, rewriting with defaults.\n");
136 #if CONTIKI_CONF_RANDOM_MAC
137  PRINTD("Generating random EUI64 MAC\n");
138  generate_new_eui64(&buffer);
139  randomeui64 = 1;
140 #else
141  for(i = 0; i < sizeof(default_mac_address); i++) {
142  buffer[i] = pgm_read_byte_near(default_mac_address + i);
143  }
144 #endif
145 /* eeprom_write_block should not be interrupted */
146  cli();
147  eeprom_write_block(&buffer, &eemem_mac_address, sizeof(eemem_mac_address));
148  for(i = 0; i < sizeof(default_server_name); i++) {
149  buffer[i] = pgm_read_byte_near(default_server_name + i);
150  }
151  eeprom_write_block(&buffer, &eemem_server_name, sizeof(eemem_server_name));
152  for(i = 0; i < sizeof(default_domain_name); i++) {
153  buffer[i] = pgm_read_byte_near(default_domain_name + i);
154  }
155  eeprom_write_block(&buffer, &eemem_domain_name, sizeof(eemem_domain_name));
156  eeprom_write_word(&eemem_panid, PARAMS_PANID);
157  eeprom_write_word(&eemem_panaddr, PARAMS_PANADDR);
158  eeprom_write_byte(&eemem_txpower, PARAMS_TXPOWER);
159  eeprom_write_word(&eemem_nodeid, PARAMS_NODEID);
160  x[0] = PARAMS_CHANNEL;
161  x[1] = ~x[0];
162  eeprom_write_word((uint16_t *)&eemem_channel, *(uint16_t *)x);
163  sei();
164  }
165 /* Always returns a valid channel */
166  return x[0];
167 }
168 uint8_t
169 params_get_eui64(uint8_t *eui64)
170 {
171  cli();
172  eeprom_read_block((void *)eui64, &eemem_mac_address, sizeof(linkaddr_t));
173  sei();
174 #if CONTIKI_CONF_RANDOM_MAC
175  return randomeui64;
176 #else
177  return 0;
178 #endif
179 }
180 uint16_t
181 params_get_panid(void)
182 {
183  return eeprom_read_word(&eemem_panid);
184 }
185 uint16_t
186 params_get_panaddr(void)
187 {
188  return eeprom_read_word(&eemem_panaddr);
189 }
190 uint8_t
191 params_get_txpower(void)
192 {
193  return eeprom_read_byte(&eemem_txpower);
194 }
195 #else /* CONTIKI_CONF_SETTINGS_MANAGER */
196 
197 uint8_t
198 params_get_channel()
199 {
200  uint8_t x;
201  size_t size = 1;
202  if(settings_get(SETTINGS_KEY_CHANNEL, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) {
203  PRINTD("<-Get RF channel %u\n", x);
204  } else {
205  x = PARAMS_CHANNEL;
206  if(settings_add_uint8(SETTINGS_KEY_CHANNEL, x) == SETTINGS_STATUS_OK) {
207  PRINTD("->Set EEPROM RF channel to %d\n", x);
208  }
209  }
210  return x;
211 }
212 uint8_t
213 params_get_eui64(uint8_t *eui64)
214 {
215  size_t size = sizeof(linkaddr_t);
216  if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char *)eui64, &size) == SETTINGS_STATUS_OK) {
217  PRINTD("<-Get EUI64 MAC\n");
218  return 0;
219  }
220 #if CONTIKI_CONF_RANDOM_MAC
221  PRINTD("Generating random EUI64 MAC\n");
222  generate_new_eui64(eui64);
223 #else
224  { uint8_t i;
225  for(i = 0; i < 8; i++) {
226  eui64[i] = pgm_read_byte_near(default_mac_address + i);
227  }
228  } /* test this */
229 #endif
230  if(settings_add(SETTINGS_KEY_EUI64, (unsigned char *)eui64, 8) == SETTINGS_STATUS_OK) {
231  PRINTD("->Set EEPROM MAC address\n");
232  }
233 #if CONTIKI_CONF_RANDOM_MAC
234  return 1;
235 #else
236  return 0;
237 #endif
238 }
239 uint16_t
240 params_get_panid(void)
241 {
242  uint16_t x;
243  size_t size = 2;
244  if(settings_get(SETTINGS_KEY_PAN_ID, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) {
245  PRINTD("<-Get PAN ID of %04x\n", x);
246  } else {
247  x = PARAMS_PANID;
248  if(settings_add_uint16(SETTINGS_KEY_PAN_ID, x) == SETTINGS_STATUS_OK) {
249  PRINTD("->Set EEPROM PAN ID to %04x\n", x);
250  }
251  }
252  return x;
253 }
254 uint16_t
255 params_get_panaddr(void)
256 {
257  uint16_t x;
258  size_t size = 2;
259  if(settings_get(SETTINGS_KEY_PAN_ADDR, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) {
260  PRINTD("<-Get PAN address of %04x\n", x);
261  } else {
262  x = PARAMS_PANADDR;
263  if(settings_add_uint16(SETTINGS_KEY_PAN_ADDR, x) == SETTINGS_STATUS_OK) {
264  PRINTD("->Set EEPROM PAN address to %04x\n", x);
265  }
266  }
267  return x;
268 }
269 uint8_t
270 params_get_txpower(void)
271 {
272  uint8_t x;
273  size_t size = 1;
274  if(settings_get(SETTINGS_KEY_TXPOWER, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) {
275  PRINTD("<-Get tx power of %d (0=max)\n", x);
276  } else {
277  x = PARAMS_TXPOWER;
278  if(settings_add_uint8(SETTINGS_KEY_TXPOWER, x) == SETTINGS_STATUS_OK) {
279  PRINTD("->Set EEPROM tx power of %d (0=max)\n", x);
280  }
281  }
282  return x;
283 }
284 #endif /* CONTIKI_CONF_SETTINGS_MANAGER */
settings_status_t settings_get(settings_key_t key, uint8_t index, uint8_t *value, settings_length_t *value_size)
Fetches the value associated with the given key.
#define SETTINGS_KEY_PAN_ADDR
Definition: settings.h:122
settings_status_t settings_add(settings_key_t key, const uint8_t *value, settings_length_t value_size)
Adds the given key-value pair to the end of the settings store.
#define SETTINGS_KEY_EUI64
EUI64 Address, 8 bytes.
Definition: settings.h:117
#define SETTINGS_KEY_PAN_ID
Definition: settings.h:121
#define SETTINGS_KEY_CHANNEL
Definition: settings.h:119
#define SETTINGS_KEY_TXPOWER
Definition: settings.h:120