ao-tools: Change ao-eeprom into eeprom analysis tool
[fw/altos] / ao-tools / lib / ao-eeprom-read.c
1 /*
2  * Copyright © 2017 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include "ao-eeprom-read.h"
16 #include <json-c/json.h>
17 #include <string.h>
18 #include <errno.h>
19
20 static struct json_object *
21 ao_eeprom_read_config(FILE *file)
22 {
23         char                    line[1024];
24         struct json_tokener     *tok;
25         struct json_object      *obj = NULL;
26         enum json_tokener_error err;
27
28         tok = json_tokener_new();
29         if (!tok)
30                 goto fail_tok;
31
32         for (;;) {
33                 if (fgets(line, sizeof(line), file) == NULL)
34                         goto fail_read;
35                 obj = json_tokener_parse_ex(tok, line, strlen(line));
36                 err = json_tokener_get_error(tok);
37                 if (err == json_tokener_success)
38                         break;
39                 if (err != json_tokener_continue)
40                         goto fail_read;
41         }
42         json_tokener_free(tok);
43         return obj;
44 fail_read:
45         json_tokener_free(tok);
46 fail_tok:
47         return NULL;
48 }
49
50 static int
51 ao_eeprom_read_byte(FILE *file)
52 {
53         int     byte;
54         if (fscanf(file, "%x", &byte) != 1)
55                 return EOF;
56         return byte;
57 }
58
59 static int
60 ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom)
61 {
62         uint8_t *data = NULL, *ndata;
63         int     len = 0;
64         int     size = 0;
65         int     byte;
66
67         data = malloc(size = 64);
68         if (!data)
69                 goto fail_alloc;
70         while ((byte = ao_eeprom_read_byte(file)) != EOF) {
71                 if (len == size) {
72                         ndata = realloc(data, size *= 2);
73                         if (!ndata)
74                                 goto fail_realloc;
75                         data = ndata;
76                 }
77                 data[len++] = (uint8_t) byte;
78         }
79         eeprom->data = data;
80         eeprom->len = len;
81         return 1;
82 fail_realloc:
83         free(data);
84 fail_alloc:
85         return 0;
86 }
87
88 static int
89 ao_json_get_int(struct json_object *obj, const char *key, int def)
90 {
91         struct json_object *value;
92         int i;
93
94         if (!json_object_object_get_ex(obj, key, &value))
95                 return def;
96         errno = 0;
97         i = (int) json_object_get_int(value);
98         if (errno != 0)
99                 return def;
100         return i;
101 }
102
103 static const char *
104 ao_json_get_string(struct json_object *obj, const char *key, const char *def)
105 {
106         struct json_object *value;
107         const char *str;
108
109         if (!json_object_object_get_ex(obj, key, &value))
110                 return def;
111         errno = 0;
112         str = json_object_get_string(value);
113         if (errno)
114                 return def;
115         if (!str)
116                 return def;
117         return str;
118 }
119
120 static int
121 ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj)
122 {
123         struct json_object      *pyros;
124         struct json_object      *pyro;
125         int                     i, p;
126
127         if (!json_object_object_get_ex(obj, "pyros", &pyros))
128                 return 1;
129
130         if (json_object_get_type(pyros) != json_type_array)
131                 return 0;
132
133         for (i = 0; i < json_object_array_length(pyros); i++) {
134                 pyro = json_object_array_get_idx(pyros, i);
135                 if (pyro) {
136                         p = ao_json_get_int(pyro, "channel", -1);
137                         if (0 <= p && p < AO_PYRO_NUM) {
138                                 config->pyro[p].flags           = ao_json_get_int(pyro, "flags", 0);
139                                 config->pyro[p].accel_less      = ao_json_get_int(pyro, "accel_less", 0);
140                                 config->pyro[p].accel_greater   = ao_json_get_int(pyro, "accel_greater", 0);
141                                 config->pyro[p].speed_less      = ao_json_get_int(pyro, "speed_less", 0);
142                                 config->pyro[p].speed_greater   = ao_json_get_int(pyro, "speed_greater", 0);
143                                 config->pyro[p].height_less     = ao_json_get_int(pyro, "height_less", 0);
144                                 config->pyro[p].height_greater  = ao_json_get_int(pyro, "height_greater", 0);
145                                 config->pyro[p].orient_less     = ao_json_get_int(pyro, "orient_less", 0);
146                                 config->pyro[p].orient_greater  = ao_json_get_int(pyro, "orient_greater", 0);
147                                 config->pyro[p].time_less       = ao_json_get_int(pyro, "time_less", 0);
148                                 config->pyro[p].time_greater    = ao_json_get_int(pyro, "time_greater", 0);
149                                 config->pyro[p].delay           = ao_json_get_int(pyro, "delay", 0);
150                                 config->pyro[p].state_less      = ao_json_get_int(pyro, "state_less", 0);
151                                 config->pyro[p].state_greater_or_equal  = ao_json_get_int(pyro, "state_greater_or_equal", 0);
152                                 config->pyro[p].motor           = ao_json_get_int(pyro, "motor", 0);
153                         }
154                 }
155         }
156         return 1;
157 }
158
159 static int
160 ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj)
161 {
162         struct json_object      *ms5607;
163
164         if (!json_object_object_get_ex(obj, "ms5607", &ms5607))
165                 return 1;
166
167         if (json_object_get_type(ms5607) != json_type_object)
168                 return 0;
169
170         ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0);
171         ms5607_prom->sens =     ao_json_get_int(ms5607, "sens", 0);
172         ms5607_prom->off =      ao_json_get_int(ms5607, "off", 0);
173         ms5607_prom->tcs =      ao_json_get_int(ms5607, "tcs", 0);
174         ms5607_prom->tco =      ao_json_get_int(ms5607, "tco", 0);
175         ms5607_prom->tref =     ao_json_get_int(ms5607, "tref", 0);
176         ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0);
177         ms5607_prom->crc =      ao_json_get_int(ms5607, "crc", 0);
178         return 1;
179 }
180
181 static int
182 ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj)
183 {
184         struct ao_config        *config = &ao_eeprom->config;
185         const char              *s;
186
187         if (json_object_get_type(obj) != json_type_object)
188                 return 0;
189
190         ao_eeprom->log_format =         ao_json_get_int(obj, "log_format", 0);
191         ao_eeprom->serial_number =      ao_json_get_int(obj, "serial", 0);
192
193         config->major =                 ao_json_get_int(obj, "config_major", 0);
194         config->minor =                 ao_json_get_int(obj, "config_minor", 0);
195         if (config->major == 0 || config->minor == 0)
196                 return 0;
197
198         config->main_deploy =           ao_json_get_int(obj, "main_deploy", 250);
199         config->accel_plus_g =          ao_json_get_int(obj, "accel_cal_plus", 0);
200
201         s = ao_json_get_string(obj, "callsign", "N0CALL");
202         strncpy(config->callsign, s, sizeof(config->callsign)-1);
203
204         config->apogee_delay =          ao_json_get_int(obj, "apogee_delay", 0);
205         config->accel_minus_g =         ao_json_get_int(obj, "accel_cal_minus", 0);
206         config->radio_cal =             ao_json_get_int(obj, "radio_calibration", 0);
207         config->flight_log_max =        ao_json_get_int(obj, "flight_log_max", 0);
208         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
209         config->pad_orientation =       ao_json_get_int(obj, "pad_orientation", 0);
210         config->radio_setting =         ao_json_get_int(obj, "radio_setting", 0);
211         config->radio_enable =          ao_json_get_int(obj, "radio_enable", 1);
212         config->frequency =             ao_json_get_int(obj, "frequency", 434550);
213         config->apogee_lockout =        ao_json_get_int(obj, "apogee_lockout", 0);
214         if (!ao_eeprom_get_pyro(config, obj))
215                 return 0;
216         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
217         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
218         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
219         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
220         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
221         config->ignite_mode =           ao_json_get_int(obj, "ignite_mode", 0);
222
223         if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj))
224                 return 0;
225
226         return 1;
227 }
228
229 struct ao_eeprom *
230 ao_eeprom_read(FILE *file)
231 {
232         struct ao_eeprom        *ao_eeprom;
233         struct json_object      *obj;
234         int                     ret;
235
236         ao_eeprom = calloc(1, sizeof (struct ao_eeprom));
237         if (!ao_eeprom)
238                 goto fail_ao_eeprom;
239
240         obj = ao_eeprom_read_config(file);
241         if (!obj)
242                 goto fail_config;
243
244         ret = ao_eeprom_get_config(ao_eeprom, obj);
245         json_object_put(obj);
246         if (!ret)
247                 goto fail_config;
248
249         if (!ao_eeprom_read_data(file, ao_eeprom))
250                 goto fail_data;
251
252         return ao_eeprom;
253 fail_data:
254 fail_config:
255         free(ao_eeprom);
256 fail_ao_eeprom:
257         return NULL;
258 }