/* * Create an image file for the MTCDP ID EEPROM * * Copyright (C) 2013 by Multi-Tech Systems * * Author: James Maki * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 2012-07-30 JSR - Added wifi and bluetooth capa flags */ #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "eeprom.h" static int eeprom_size = 512; static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom); static void mts_dc_eeprom_inspect(struct mts_dc_eeprom_layout *dc_eeprom); static int hwaddr_aton(const char *str, uint8_t *buf, size_t len) { size_t count = 0; for (;;) { unsigned acc; char ch; acc = 0; while ((ch = *str) != ':' && ch != 0) { if (ch >= '0' && ch <= '9') { ch -= '0'; } else if (ch >= 'a' && ch <= 'f') { ch -= 'a' - 10; } else if (ch >= 'A' && ch <= 'F') { ch -= 'A' - 10; } else { return 0; } acc = (acc << 4) + ch; str++; } if (acc > 255) { return 0; } if (count >= len) { return 0; } buf[count] = acc; count++; if (ch == 0) { break; } str++; } if (count < len) { return 0; } return 1; } static int id_yaml_out(const char *name, struct mts_id_eeprom_layout *id_eeprom) { FILE *file; if (!strcmp(name, "-")) { file = stdout; } else { file = fopen(name, "w+"); if (!file) { log_error("could not open %s: %m", name); return -1; } } fprintf(file, "---\n"); fprintf(file, "\n"); fprintf(file, "vendor-id: \"%.32s\"\n", id_eeprom->vendor_id); fprintf(file, "product-id: \"%.32s\"\n", id_eeprom->product_id); fprintf(file, "device-id: \"%.32s\"\n", id_eeprom->device_id); fprintf(file, "hw-version: \"%.32s\"\n", id_eeprom->hw_version); fprintf(file, "mac-addr: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n", id_eeprom->mac_addr[0], id_eeprom->mac_addr[1], id_eeprom->mac_addr[2], id_eeprom->mac_addr[3], id_eeprom->mac_addr[4], id_eeprom->mac_addr[5]); fprintf(file, "imei: \"%.32s\"\n", id_eeprom->imei); fprintf(file, "capa-gps: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_GPS) ? "true" : "false"); fprintf(file, "capa-din: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_DIN) ? "true" : "false"); fprintf(file, "capa-dout: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_DOUT) ? "true" : "false"); fprintf(file, "capa-adc: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_ADC) ? "true" : "false"); fprintf(file, "capa-wifi: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_WIFI) ? "true" : "false"); fprintf(file, "capa-bluetooth: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_BLUETOOTH) ? "true" : "false"); fprintf(file, "capa: \""); int i; for (i = 0; i < sizeof(id_eeprom->capa); i++) { fprintf(file, "\\x%02X", id_eeprom->capa[i]); } fprintf(file, "\"\n"); fprintf(file, "mac-bluetooth: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n", id_eeprom->mac_bluetooth[0], id_eeprom->mac_bluetooth[1], id_eeprom->mac_bluetooth[2], id_eeprom->mac_bluetooth[3], id_eeprom->mac_bluetooth[4], id_eeprom->mac_bluetooth[5]); fprintf(file, "mac-wifi: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n", id_eeprom->mac_wifi[0], id_eeprom->mac_wifi[1], id_eeprom->mac_wifi[2], id_eeprom->mac_wifi[3], id_eeprom->mac_wifi[4], id_eeprom->mac_wifi[5]); fprintf(file, "...\n"); fclose(file); return 0; } static int dc_yaml_out(const char *name, struct mts_dc_eeprom_layout *dc_eeprom) { FILE *file; if (!strcmp(name, "-")) { file = stdout; } else { file = fopen(name, "w+"); if (!file) { log_error("could not open %s: %m", name); return -1; } } fprintf(file, "---\n"); fprintf(file, "\n"); fprintf(file, "vendor-id: \"%.32s\"\n", dc_eeprom->vendor_id); fprintf(file, "product-id: \"%.32s\"\n", dc_eeprom->product_id); fprintf(file, "device-id: \"%.32s\"\n", dc_eeprom->device_id); fprintf(file, "hw-version: \"%.32s\"\n", dc_eeprom->hw_version); fprintf(file, "mac-addr: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n", dc_eeprom->mac_addr[0], dc_eeprom->mac_addr[1], dc_eeprom->mac_addr[2], dc_eeprom->mac_addr[3], dc_eeprom->mac_addr[4], dc_eeprom->mac_addr[5]); fprintf(file, "...\n"); fclose(file); return 0; } static int bin_out(const char *name, char *eeprom) { int fd; int tmp; if (!strcmp(name, "-")) { fd = fileno(stdout); } else { fd = open(name, O_CREAT | O_WRONLY, 0644); if (fd < 0) { log_error("could not open %s: %m", name); return fd; } } tmp = write(fd, eeprom, eeprom_size); if (tmp < 0) { log_error("writing %s failed: %m", name); return fd; } else if (tmp != eeprom_size) { log_error("only wrote %d bytes to %s", tmp, name); return -1; } close(fd); return tmp; } static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom) { log_info("sizeof: %u", sizeof(struct mts_id_eeprom_layout)); log_info("vendor-id: %.32s", id_eeprom->vendor_id); log_info("product-id: %.32s", id_eeprom->product_id); log_info("device-id: %.32s", id_eeprom->device_id); log_info("hw-version: %.32s", id_eeprom->hw_version); log_info("mac-addr: %02X:%02X:%02X:%02X:%02X:%02X", id_eeprom->mac_addr[0], id_eeprom->mac_addr[1], id_eeprom->mac_addr[2], id_eeprom->mac_addr[3], id_eeprom->mac_addr[4], id_eeprom->mac_addr[5]); log_info("imei: %.32s", id_eeprom->imei); log_info("capa-gps: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_GPS) ? "yes" : "no"); log_info("capa-din: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_DIN) ? "yes" : "no"); log_info("capa-dout: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_DOUT) ? "yes" : "no"); log_info("capa-adc: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_ADC) ? "yes" : "no"); log_info("capa-wifi: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_WIFI) ? "yes" : "no"); log_info("capa-bluetooth: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_BLUETOOTH) ? "yes" : "no"); log_info("mac-bluetooth: %02X:%02X:%02X:%02X:%02X:%02X", id_eeprom->mac_bluetooth[0], id_eeprom->mac_bluetooth[1], id_eeprom->mac_bluetooth[2], id_eeprom->mac_bluetooth[3], id_eeprom->mac_bluetooth[4], id_eeprom->mac_bluetooth[5]); log_info("mac-wifi: %02X:%02X:%02X:%02X:%02X:%02X", id_eeprom->mac_wifi[0], id_eeprom->mac_wifi[1], id_eeprom->mac_wifi[2], id_eeprom->mac_wifi[3], id_eeprom->mac_wifi[4], id_eeprom->mac_wifi[5]); } static void mts_dc_eeprom_inspect(struct mts_dc_eeprom_layout *dc_eeprom) { log_info("sizeof: %u", sizeof(struct mts_dc_eeprom_layout)); log_info("vendor-id: %.32s", dc_eeprom->vendor_id); log_info("product-id: %.32s", dc_eeprom->product_id); log_info("device-id: %.32s", dc_eeprom->device_id); log_info("hw-version: %.32s", dc_eeprom->hw_version); log_info("mac-addr: %02X:%02X:%02X:%02X:%02X:%02X", dc_eeprom->mac_addr[0], dc_eeprom->mac_addr[1], dc_eeprom->mac_addr[2], dc_eeprom->mac_addr[3], dc_eeprom->mac_addr[4], dc_eeprom->mac_addr[5]); } static void print_version(const char *name) { printf("%s (" PACKAGE ") " VERSION " (" __DATE__ " " __TIME__ ")\n", name); printf("Copyright (C) 2010 by Multi-Tech Systems\n"); printf( "This program is free software; you may redistribute it under the terms of\n" "the GNU General Public License version 2 or (at your option) any later version.\n" "This program has absolutely no warranty.\n"); } static void usage(FILE *out) { fprintf(out, "usage: mts-id-eeprom [ OPTIONS ... ]\n"); fprintf(out, "where OPTIONS := { \n"); fprintf(out, " --in-file |\n"); fprintf(out, " --out-file |\n"); fprintf(out, " --vendor-id |\n"); fprintf(out, " --product-id |\n"); fprintf(out, " --device-id |\n"); fprintf(out, " --hw-version |\n"); fprintf(out, " --mac-addr |\n"); fprintf(out, " --mac-bluetooth |\n"); fprintf(out, " --mac-wifi |\n"); fprintf(out, " --imei |\n"); fprintf(out, " --capa-gps |\n"); fprintf(out, " --capa-din |\n"); fprintf(out, " --capa-dout |\n"); fprintf(out, " --capa-adc |\n"); fprintf(out, " --capa-wifi |\n"); fprintf(out, " --capa-bluetooth |\n"); fprintf(out, " --capa-clear (clears all flags) |\n"); fprintf(out, " --out-format { bin | yaml (default) } |\n"); fprintf(out, " --update |\n"); fprintf(out, " --daughter-card\n"); fprintf(out, " }\n"); fprintf(out, "\n"); } enum { CMD_OPT_IN_FILE = 128, CMD_OPT_OUT_FILE, CMD_OPT_VENDOR_ID, CMD_OPT_PRODUCT_ID, CMD_OPT_DEVICE_ID, CMD_OPT_HW_VERSION, CMD_OPT_MAC_ADDR, CMD_OPT_MAC_BLUETOOTH, CMD_OPT_MAC_WIFI, CMD_OPT_IMEI, CMD_OPT_CAPA_GPS, CMD_OPT_CAPA_DIN, CMD_OPT_CAPA_DOUT, CMD_OPT_CAPA_ADC, CMD_OPT_CAPA_WIFI, CMD_OPT_CAPA_BLUETOOTH, CMD_OPT_CAPA_CLEAR, CMD_OPT_OUT_FORMAT, CMD_OPT_UPDATE, CMD_OPT_DAUGHTER_CARD, CMD_OPT_VERSION, CMD_OPT_HELP, }; static char *short_options = "f:"; static struct option long_options[] = { {"in-file", 1, NULL, CMD_OPT_IN_FILE}, {"out-file", 1, NULL, CMD_OPT_OUT_FILE}, {"vendor-id", 1, NULL, CMD_OPT_VENDOR_ID}, {"product-id", 1, NULL, CMD_OPT_PRODUCT_ID}, {"device-id", 1, NULL, CMD_OPT_DEVICE_ID}, {"hw-version", 1, NULL, CMD_OPT_HW_VERSION}, {"mac-addr", 1, NULL, CMD_OPT_MAC_ADDR}, {"mac-bluetooth", 1, NULL, CMD_OPT_MAC_BLUETOOTH}, {"mac-wifi", 1, NULL, CMD_OPT_MAC_WIFI}, {"imei", 1, NULL, CMD_OPT_IMEI}, {"capa-gps", 0, NULL, CMD_OPT_CAPA_GPS}, {"capa-din", 0, NULL, CMD_OPT_CAPA_DIN}, {"capa-dout", 0, NULL, CMD_OPT_CAPA_DOUT}, {"capa-adc", 0, NULL, CMD_OPT_CAPA_ADC}, {"capa-wifi", 0, NULL, CMD_OPT_CAPA_WIFI}, {"capa-bluetooth", 0, NULL, CMD_OPT_CAPA_BLUETOOTH}, {"capa-clear", 0, NULL, CMD_OPT_CAPA_CLEAR}, {"out-format", 1, NULL, CMD_OPT_OUT_FORMAT}, {"update", 0, NULL, CMD_OPT_UPDATE}, {"daughter-card", 0, NULL, CMD_OPT_DAUGHTER_CARD}, {"version", 0, NULL, CMD_OPT_VERSION}, {"help", 0, NULL, CMD_OPT_HELP}, {0, 0, 0, 0}, }; int main(int argc, char *argv[]) { int i; int option_index; int tmp; int fd; char *in_file = NULL; char *out_file = "-"; char *out_format = "yaml"; int update = 0; int daughter_card = 0; char *vendor_id = NULL; char *product_id = NULL; char *device_id = NULL; char *hw_version = NULL; char *mac_addr = NULL; struct mts_id_eeprom_layout id_eeprom; struct mts_dc_eeprom_layout dc_eeprom; memset(&id_eeprom, 0, eeprom_size); memset(&dc_eeprom, 0, eeprom_size); #if 0 strncpy(id_eeprom.vendor_id, VENDOR_ID_MULTITECH, sizeof(id_eeprom.vendor_id) - 1); strncpy(id_eeprom.product_id, PRODUCT_ID_MTCDP_E1_DK, sizeof(id_eeprom.product_id) - 1); strncpy(id_eeprom.device_id, "12345678", sizeof(id_eeprom.device_id) - 1); strncpy(id_eeprom.hw_version, HW_VERSION_MTCDP_1_0, sizeof(id_eeprom.hw_version) - 1); hwaddr_aton("00:d0:a0:02:0d:e1", id_eeprom.mac_addr, sizeof(id_eeprom.mac_addr)); strncpy(id_eeprom.imei, "353626020834450", sizeof(id_eeprom.imei) - 1); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_GPS); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_DIN); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_DOUT); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_ADC); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_WIFI); DEVICE_CAPA_SET(id_eeprom.capa, CAPA_BLUETOOTH); hwaddr_aton("00:d0:a0:02:0d:e2", id_eeprom.mac_bluetooth, sizeof(id_eeprom.mac_bluetooth)); hwaddr_aton("00:d0:a0:02:0d:e3", id_eeprom.mac_wifi, sizeof(id_eeprom.mac_wifi)); #endif // parse options once to get input file and daughter_card flag only while((i = getopt_long(argc, argv, short_options, long_options, &option_index)) >= 0) { switch(i) { case 0: break; case CMD_OPT_IN_FILE: in_file = optarg; break; case CMD_OPT_DAUGHTER_CARD: daughter_card = 1; break; case CMD_OPT_VERSION: print_version("mts-id-eeprom"); exit(0); break; case CMD_OPT_HELP: usage(stdout); exit(0); break; } } // read eeprom before parsing other options and modifying fields // this is needed if --update is specified if (in_file) { fd = open(in_file, O_RDONLY); if (fd < 0) { log_error("could not open in-file %s: %m", in_file); exit(1); } if (daughter_card) { tmp = read(fd, (char *) &dc_eeprom, eeprom_size); } else { tmp = read(fd, (char *) &id_eeprom, eeprom_size); } if (tmp < 0) { log_error("reading %s failed: %m", in_file); exit(1); } else if (tmp != eeprom_size) { log_error("only read %d bytes from %s", tmp, in_file); exit(1); } if (daughter_card) { log_info("loaded dc eeprom from %s successfully", in_file); mts_dc_eeprom_inspect(&dc_eeprom); } else { log_info("loaded id eeprom from %s successfully", in_file); mts_id_eeprom_inspect(&id_eeprom); } close(fd); } // reset getopt index and parse again optind = 0; while((i = getopt_long(argc, argv, short_options, long_options, &option_index)) >= 0) { switch(i) { case 0: break; case CMD_OPT_IN_FILE: // handled above break; case CMD_OPT_UPDATE: update = 1; break; case CMD_OPT_DAUGHTER_CARD: // handled above break; case CMD_OPT_OUT_FILE: out_file = optarg; break; case CMD_OPT_VENDOR_ID: vendor_id = optarg; break; case CMD_OPT_PRODUCT_ID: product_id = optarg; break; case CMD_OPT_DEVICE_ID: device_id = optarg; break; case CMD_OPT_HW_VERSION: hw_version = optarg; break; case CMD_OPT_MAC_ADDR: mac_addr = optarg; break; case CMD_OPT_MAC_BLUETOOTH: tmp = hwaddr_aton(optarg, id_eeprom.mac_bluetooth, sizeof(id_eeprom.mac_bluetooth)); if (!tmp) { log_error("invalid mac-bluetooth %s", optarg); usage(stderr); exit(1); } break; case CMD_OPT_MAC_WIFI: tmp = hwaddr_aton(optarg, id_eeprom.mac_wifi, sizeof(id_eeprom.mac_wifi)); if (!tmp) { log_error("invalid mac-wifi %s", optarg); usage(stderr); exit(1); } break; case CMD_OPT_IMEI: strncpy(id_eeprom.imei, optarg, sizeof(id_eeprom.imei) - 1); break; case CMD_OPT_CAPA_GPS: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_GPS); break; case CMD_OPT_CAPA_DIN: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_DIN); break; case CMD_OPT_CAPA_DOUT: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_DOUT); break; case CMD_OPT_CAPA_ADC: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_ADC); break; case CMD_OPT_CAPA_WIFI: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_WIFI); break; case CMD_OPT_CAPA_BLUETOOTH: DEVICE_CAPA_SET(id_eeprom.capa, CAPA_BLUETOOTH); break; case CMD_OPT_CAPA_CLEAR: memset(id_eeprom.capa, 0, sizeof(id_eeprom.capa)); break; case CMD_OPT_OUT_FORMAT: if (strcmp(optarg, "bin") && strcmp(optarg, "yaml")) { log_error("invalid out-format %s", optarg); usage(stderr); exit(1); } out_format = optarg; break; default: usage(stderr); exit(1); } } /* these fields can apply to the on board EEPROM or the daughter card EEPROM */ if (vendor_id) { if (! daughter_card) { strncpy(id_eeprom.vendor_id, vendor_id, sizeof(id_eeprom.vendor_id) - 1); } else { strncpy(dc_eeprom.vendor_id, vendor_id, sizeof(dc_eeprom.vendor_id) - 1); } } if (product_id) { if (! daughter_card) { strncpy(id_eeprom.product_id, product_id, sizeof(id_eeprom.product_id) - 1); } else { strncpy(dc_eeprom.product_id, product_id, sizeof(dc_eeprom.product_id) - 1); } } if (device_id) { if (! daughter_card) { strncpy(id_eeprom.device_id, device_id, sizeof(id_eeprom.device_id) - 1); } else { strncpy(dc_eeprom.device_id, device_id, sizeof(dc_eeprom.device_id) - 1); } } if (hw_version) { if (! daughter_card) { strncpy(id_eeprom.hw_version, hw_version, sizeof(id_eeprom.hw_version) - 1); } else { strncpy(dc_eeprom.hw_version, hw_version, sizeof(dc_eeprom.hw_version) - 1); } } if (mac_addr) { if (! daughter_card) { tmp = hwaddr_aton(mac_addr, id_eeprom.mac_addr, sizeof(id_eeprom.mac_addr)); } else { tmp = hwaddr_aton(mac_addr, dc_eeprom.mac_addr, sizeof(dc_eeprom.mac_addr)); } if (!tmp) { log_error("invalid mac-addr %s", optarg); usage(stderr); exit(1); } } // updating eeprom in place, force bin format if (update && in_file) { out_file = in_file; out_format = "bin"; } if (out_file) { if (!strcmp(out_format, "bin")) { if (! daughter_card) { bin_out(out_file, (char*) &id_eeprom); } else { bin_out(out_file, (char*) &dc_eeprom); } } else if (!strcmp(out_format, "yaml")) { if (! daughter_card) { id_yaml_out(out_file, &id_eeprom); } else { dc_yaml_out(out_file, &dc_eeprom); } } else { log_error("un-handled out-format"); exit(1); } /* print out what we wrote to the eeprom, unless stdout */ if (strcmp(out_file, "-")) { log_info("Data written to %s", out_file); if (daughter_card) { mts_dc_eeprom_inspect(&dc_eeprom); } else { mts_id_eeprom_inspect(&id_eeprom); } } } return 0; }