SingingCat 0
application
userconfig.c
1#include "main-header.h"
2#include "userconfig.h"
3
4struct user_config userconfiginram;
5static uint32_t curpid;
6static uint8_t max;
7static uint8_t lastpos;
8static uint32_t userconfig_calc_checksum(struct user_config *cfg) {
9 return crc32(&cfg->userdata, cfg->validbytes);
10}
11
12static struct user_config *get_cfg() {
13 struct user_config *cfg = get_flash_user_config_addr();
14
15 if (cfg == NULL) {
16 printf("[userconfig] warning - NO USERCONFIG FLASH SECTION (struct too big? %i bytes)!!!\r\n", sizeof(_user_config));
17 }
18 return cfg;
19}
20uint32_t userconfig_size() {
21 struct user_config *cfg = get_cfg();
22
23 if (cfg == NULL) {
24 return 0;
25 }
26 uint32_t c = userconfig_calc_checksum(cfg);
27
28 if (c != cfg->checksum) {
29 printf("[userconfig] Invalid checksum\r\n");
30 return 0;
31 }
32 return cfg->validbytes;
33}
34uint32_t userconfig_version() {
35 struct user_config *cfg = get_cfg();
36
37 if (cfg == NULL) {
38 return 0;
39 }
40 return cfg->data_version;
41}
42
43int userconfig_copy(uint8_t *buf, uint16_t bufsize, uint16_t *actual_size) {
44 struct user_config *cfg = get_cfg();
45
46 if (cfg == NULL) {
47 return 1;
48 }
49 if (cfg->validbytes > bufsize) {
50 return 2;
51 }
52 int i;
53
54 printf("[userconfig] copying userdata from userconfig at %p\r\n",cfg);
55 for (i = 0; i < cfg->validbytes; i++) {
56 buf[i] = cfg->userdata[i];
57 }
58 *actual_size = cfg->validbytes;
59 return 0;
60}
61
62/*****************************************************************************
63* flash update stuff
64*****************************************************************************/
65static int userconfig_receive_init(struct command *com) {
66 lastpos = 0;
67 userconfiginram.validbytes = 0;
68 uint16_t r16;
69 int r;
70
71 if ((r = namedarg_uint16(com, "max", &r16)) != 0) {
72 return 2;
73 }
74 max = (uint8_t)r16;
75 if ((r = namedarg_uint32(com, "pid", &curpid)) != 0) {
76 return 2;
77 }
78 return 1;
79}
80
81// receive a data update
82static int userconfig_receive_data(struct command *com) {
83 uint32_t pid;
84 int r;
85
86 if ((r = namedarg_uint32(com, "pid", &pid)) != 0) {
87 return 2;
88 }
89 if (pid != curpid) {
90 printf("[userconfig]: pid mismatch\r\n");
91 return 2;
92 }
93 if ((r = namedarg_uint32(com, "pos", &pid)) != 0) {
94 return 2;
95 }
96 if ((lastpos + 1) != ((uint8_t)pid)) {
97 printf("[userconfig]: Pos out of sequence: %i vs %i\r\n", (uint32_t)lastpos, pid);
98 return 2;
99 }
100 lastpos = pid;
101 if ((r = namedarg_uint32(com, "size", &pid)) != 0) {
102 printf("[userconfig]: missing size\r\n");
103 return 2;
104 }
105 const char *data = namedarg(com, "data");
106
107 if (data == NULL) {
108 printf("[userconfig]: missing data\r\n");
109 return 2;
110 }
111 const uint8_t *bytes = (const uint8_t *)data;
112 uint32_t i;
113 uint32_t j = userconfiginram.validbytes;
114
115 if ((j + pid) > sizeof(userconfiginram.userdata)) {
116 printf("[userconfig: too big (%i bytes does not fit into %i bytes buffer\r\n", (j + pid), sizeof(userconfiginram.userdata));
117 return 2;
118 }
119 for (i = 0; i < pid; i++) {
120 userconfiginram.userdata[j] = bytes[i];
121 j++;
122 }
123 userconfiginram.validbytes = j;
124 if (lastpos < max) {
125 // not last packet just yet..
126 return 1;
127 }
128
129 // close it up and flash it
130 r = write_user_config_to_flash();
131 if (r != 0) {
132 return 2;
133 }
134 return 1;
135}
136// return (00==ok)
137int userconfig_write(uint8_t *buf, uint32_t size) {
138 if (size > sizeof(userconfiginram.userdata)) {
139 printf("[userconfig]: buf too big (%i > %i)\r\n", size, sizeof(userconfiginram.userdata));
140 return 5;
141 }
142 uint32_t i;
143
144 for (i = 0; i < size; i++) {
145 userconfiginram.userdata[i] = buf[i];
146 }
147 userconfiginram.validbytes = size;
148 return write_user_config_to_flash();
149}
150
151// do crc and write to flash (return 0==ok)
152int write_user_config_to_flash() {
153 int r;
154 struct user_config *cfg = get_cfg();
155
156 if (cfg == NULL) {
157 return 2;
158 }
159 if (userconfiginram.validbytes == cfg->validbytes) {
160 int i;
161 int found = 0;
162 for (i = 0; i < cfg->validbytes; i++) {
163 if ((userconfiginram.userdata[i] != cfg->userdata[i])) {
164 found = 1;
165 break;
166 }
167 }
168 if (found == 0) {
169 printf("[userconfig] no change, not flashing\r\n");
170 return 0;
171 }
172 }
173 uint32_t size = sizeof(struct user_config);
174
175 userconfiginram.checksum = userconfig_calc_checksum(&userconfiginram);
176 userconfiginram.data_version = cfg->data_version + 1;
177 if ((r = mculib_flash_unlock(MAIN_MCULIBHANDLE))) {
178 printf("[userconfig]: Unlock flash failed: %i\r\n", r);
179 mculib_flash_lock(MAIN_MCULIBHANDLE);
180 return 2;
181 }
182 if ((r = mculib_flash_erase(MAIN_MCULIBHANDLE, (void *)cfg, size + 4))) { // must erase 4 byte aligned. address calculatin in hw.c takes this into account
183 printf("[userconfig]: Erase config failed: %i\r\n", r);
184 mculib_flash_lock(MAIN_MCULIBHANDLE);
185 return 2;
186 }
187 printf("[userconfig]: writing in-ram copy to flash @ 0x%p (%i bytes)\r\n", (void *)cfg, size);
188 if ((r = mculib_flash_write(MAIN_MCULIBHANDLE, (void *)&userconfiginram, (void *)cfg, size)) != 0) {
189 printf("[userconfig]: Write config failed: %i\r\n", r);
190 mculib_flash_lock(MAIN_MCULIBHANDLE);
191 return 2;
192 }
193
194 mculib_flash_lock(MAIN_MCULIBHANDLE);
195 printf("[userconfig]: Saved %i bytes to flash. Flash result: %i\r\n", size, r);
196
197 return 0;
198}
199
200// send a section of the buf to server (0=ok, otherwise err)
201static int send_userconfig_data(struct command *com, struct user_config *cfg, int cur, int offset, int size) {
202 struct command *reply = alloc_command();
203
204 if (reply == NULL) {
205 return 1;
206 }
207 const uint8_t *base;
208
209 base = (const uint8_t *)&cfg->userdata;
210 base = base + offset;
211 reply->target = com->sender;
212 reply->index = com->index;
213 reply->connid = com->connid;
214 reply->com = com->com;
215 reply->flags = COMFLAGS_DATA;
216 command_add_arg(reply, "dseq=%i", cur);
217 command_add_binary_arg(reply, size, base);
218 send_command(reply);
219 free_command(reply);
220 return 0;
221}
222
223// send data to server
224static int userconfig_send_data(struct command *com) {
225 struct user_config *cfg = get_cfg();
226
227 if (cfg == NULL) {
228 return 2;
229 }
230
231 struct command *reply = alloc_command();
232
233 if (reply == NULL) {
234 return 2;
235 }
236 int tblen = userconfig_size();
237 int tvers = userconfig_version();
238
239 printf("[userconfig] sending %i bytes (version %i)\r\n", tblen, tvers);
240 int tcoms = 0;
241 int cur = 0;
242 int offset = 0;
243
244 for (;;) {
245 if (offset >= tblen) {
246 break;
247 }
248 int size = 128;
249 if (offset + size > tblen) {
250 size = tblen - offset;
251 }
252 send_userconfig_data(com, cfg, cur, offset, size);
253 tcoms++;
254 offset = offset + size;
255 }
256 reply->target = com->sender;
257 reply->index = com->index;
258 reply->connid = com->connid;
259 reply->com = com->com;
260 reply->flags = COMFLAGS_ACK;
261 command_add_arg(reply, "total_bytes=%i", tblen);
262 command_add_arg(reply, "total_coms=%i", tcoms);
263 command_add_arg(reply, "version=%i", tvers);
264 command_add_arg(reply, "chk=%p", cfg->checksum);
265 deliver_command(reply, NULL);
266 printf("[userconfig] sent %i bytes in %i commands\r\n", tblen, tcoms);
267 return 0;
268}
269
270/*
271 * brief receive a partial update
272 * return 1 for successfull ack, 2 for unsuccessful
273 */
274int userconfig_receive(struct command *com) {
275 uint32_t t;
276 int r = namedarg_uint32(com, "ucr", &t);
277
278 if (r != 0) {
279 return 2;
280 }
281 if (t == 1) {
282 return userconfig_receive_init(com);
283 } else if (t == 2) {
284 return userconfig_receive_data(com);
285 } else if (t == 3) {
286 return userconfig_send_data(com); //send data to server
287 }
288 return 2;
289}
int namedarg_uint16(struct command *com, const char *name, uint16_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
int send_command(struct command *com)
send a command to another module (or broadcast)
Definition: queue.c:374
void free_command(struct command *com)
free a command
Definition: queue.c:200
int deliver_command(struct command *com, pkt_callback)
deliver a command to a module
Definition: queue.c:651
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
const char * namedarg(struct command *com, const char *name)
get a named arg (key-value pair) or NULL
int namedarg_uint32(struct command *com, const char *name, uint32_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
struct command * alloc_command()
allocate a free command
Definition: queue.c:173
int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf)
adds a binary parameter to command returns 0 if ok otherwise errorcode
int com
Definition: command.h:22
long target
Definition: command.h:16
uint8_t connid
Definition: command.h:18
int index
Definition: command.h:13
uint8_t flags
Definition: command.h:23