/* * Copyright © 2017 Keith Packard * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include "ao-eeprom-read.h" #include #include #include static struct json_object * ao_eeprom_read_config(FILE *file) { char line[1024]; struct json_tokener *tok; struct json_object *obj = NULL; enum json_tokener_error err; tok = json_tokener_new(); if (!tok) goto fail_tok; for (;;) { if (fgets(line, sizeof(line), file) == NULL) goto fail_read; obj = json_tokener_parse_ex(tok, line, strlen(line)); err = json_tokener_get_error(tok); if (err == json_tokener_success) break; if (err != json_tokener_continue) goto fail_read; } json_tokener_free(tok); return obj; fail_read: json_tokener_free(tok); fail_tok: return NULL; } static int ao_eeprom_read_byte(FILE *file) { int byte; if (fscanf(file, "%x", &byte) != 1) return EOF; return byte; } static int ao_eeprom_read_data(FILE *file, struct ao_eeprom *eeprom) { uint8_t *data = NULL, *ndata; int len = 0; int size = 0; int byte; data = malloc(size = 64); if (!data) goto fail_alloc; while ((byte = ao_eeprom_read_byte(file)) != EOF) { if (len == size) { ndata = realloc(data, size *= 2); if (!ndata) goto fail_realloc; data = ndata; } data[len++] = (uint8_t) byte; } eeprom->data = data; eeprom->len = len; return 1; fail_realloc: free(data); fail_alloc: return 0; } static int ao_json_get_int(struct json_object *obj, const char *key, int def) { struct json_object *value; int i; if (!json_object_object_get_ex(obj, key, &value)) return def; errno = 0; i = (int) json_object_get_int(value); if (errno != 0) return def; return i; } static const char * ao_json_get_string(struct json_object *obj, const char *key, const char *def) { struct json_object *value; const char *str; if (!json_object_object_get_ex(obj, key, &value)) return def; errno = 0; str = json_object_get_string(value); if (errno) return def; if (!str) return def; return str; } static int ao_eeprom_get_pyro(struct ao_config *config, struct json_object *obj) { struct json_object *pyros; struct json_object *pyro; int i, p; if (!json_object_object_get_ex(obj, "pyros", &pyros)) return 1; if (json_object_get_type(pyros) != json_type_array) return 0; for (i = 0; i < json_object_array_length(pyros); i++) { pyro = json_object_array_get_idx(pyros, i); if (pyro) { p = ao_json_get_int(pyro, "channel", -1); if (0 <= p && p < AO_PYRO_NUM) { config->pyro[p].flags = ao_json_get_int(pyro, "flags", 0); config->pyro[p].accel_less = ao_json_get_int(pyro, "accel_less", 0); config->pyro[p].accel_greater = ao_json_get_int(pyro, "accel_greater", 0); config->pyro[p].speed_less = ao_json_get_int(pyro, "speed_less", 0); config->pyro[p].speed_greater = ao_json_get_int(pyro, "speed_greater", 0); config->pyro[p].height_less = ao_json_get_int(pyro, "height_less", 0); config->pyro[p].height_greater = ao_json_get_int(pyro, "height_greater", 0); config->pyro[p].orient_less = ao_json_get_int(pyro, "orient_less", 0); config->pyro[p].orient_greater = ao_json_get_int(pyro, "orient_greater", 0); config->pyro[p].time_less = ao_json_get_int(pyro, "time_less", 0); config->pyro[p].time_greater = ao_json_get_int(pyro, "time_greater", 0); config->pyro[p].delay = ao_json_get_int(pyro, "delay", 0); config->pyro[p].state_less = ao_json_get_int(pyro, "state_less", 0); config->pyro[p].state_greater_or_equal = ao_json_get_int(pyro, "state_greater_or_equal", 0); config->pyro[p].motor = ao_json_get_int(pyro, "motor", 0); } } } return 1; } static int ao_eeprom_get_ms5607(struct ao_ms5607_prom *ms5607_prom, struct json_object *obj) { struct json_object *ms5607; if (!json_object_object_get_ex(obj, "ms5607", &ms5607)) return 1; if (json_object_get_type(ms5607) != json_type_object) return 0; ms5607_prom->reserved = ao_json_get_int(ms5607, "reserved", 0); ms5607_prom->sens = ao_json_get_int(ms5607, "sens", 0); ms5607_prom->off = ao_json_get_int(ms5607, "off", 0); ms5607_prom->tcs = ao_json_get_int(ms5607, "tcs", 0); ms5607_prom->tco = ao_json_get_int(ms5607, "tco", 0); ms5607_prom->tref = ao_json_get_int(ms5607, "tref", 0); ms5607_prom->tempsens = ao_json_get_int(ms5607, "tempsens", 0); ms5607_prom->crc = ao_json_get_int(ms5607, "crc", 0); return 1; } static int ao_eeprom_get_config(struct ao_eeprom *ao_eeprom, struct json_object *obj) { struct ao_config *config = &ao_eeprom->config; const char *s; if (json_object_get_type(obj) != json_type_object) return 0; ao_eeprom->log_format = ao_json_get_int(obj, "log_format", 0); ao_eeprom->serial_number = ao_json_get_int(obj, "serial", 0); config->major = ao_json_get_int(obj, "config_major", 0); config->minor = ao_json_get_int(obj, "config_minor", 0); if (config->major == 0 || config->minor == 0) return 0; config->main_deploy = ao_json_get_int(obj, "main_deploy", 250); config->accel_plus_g = ao_json_get_int(obj, "accel_cal_plus", 0); s = ao_json_get_string(obj, "callsign", "N0CALL"); strncpy(config->callsign, s, sizeof(config->callsign)-1); config->apogee_delay = ao_json_get_int(obj, "apogee_delay", 0); config->accel_minus_g = ao_json_get_int(obj, "accel_cal_minus", 0); config->radio_cal = ao_json_get_int(obj, "radio_calibration", 0); config->flight_log_max = ao_json_get_int(obj, "flight_log_max", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->pad_orientation = ao_json_get_int(obj, "pad_orientation", 0); config->radio_setting = ao_json_get_int(obj, "radio_setting", 0); config->radio_enable = ao_json_get_int(obj, "radio_enable", 1); config->frequency = ao_json_get_int(obj, "frequency", 434550); config->apogee_lockout = ao_json_get_int(obj, "apogee_lockout", 0); if (!ao_eeprom_get_pyro(config, obj)) return 0; config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); config->ignite_mode = ao_json_get_int(obj, "ignite_mode", 0); if (!ao_eeprom_get_ms5607(&ao_eeprom->ms5607_prom, obj)) return 0; return 1; } struct ao_eeprom * ao_eeprom_read(FILE *file) { struct ao_eeprom *ao_eeprom; struct json_object *obj; int ret; ao_eeprom = calloc(1, sizeof (struct ao_eeprom)); if (!ao_eeprom) goto fail_ao_eeprom; obj = ao_eeprom_read_config(file); if (!obj) goto fail_config; ret = ao_eeprom_get_config(ao_eeprom, obj); json_object_put(obj); if (!ret) goto fail_config; if (!ao_eeprom_read_data(file, ao_eeprom)) goto fail_data; return ao_eeprom; fail_data: fail_config: free(ao_eeprom); fail_ao_eeprom: return NULL; }