FreeCalypso > hg > fc-usbser-tools
view cp2102/intel_hex_in.c @ 71:0b37be8b23ca
doc/FTDI-EEPROM-format: document string descriptors
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 24 Sep 2023 22:27:38 +0000 |
parents | 842cff427588 |
children |
line wrap: on
line source
/* * This module implements a function for reading CP2102 EEPROM images * in the Intel HEX format which we've copied from cp210x-program-1.0, * the Python-language tool from 2014. */ #include <sys/types.h> #include <ctype.h> #include <string.h> #include <strings.h> #include <stdio.h> #include <stdlib.h> #include "cp210x_defs.h" extern u_char eeprom[SIZE_EEPROM]; static int decode_hex_digit(c) { if (c >= '0' && c <= '9') return(c - '0'); if (c >= 'A' && c <= 'F') return(c - 'A' + 10); if (c >= 'a' && c <= 'f') return(c - 'a' + 10); return(-1); } static int decode_hex_byte(str) char *str; { int u, l; u = decode_hex_digit(str[0]); l = decode_hex_digit(str[1]); return (u << 4) | l; } void read_intel_hex(filename) char *filename; { FILE *inf; char linebuf[1024], *cp; int lineno; unsigned eeprom_offset; unsigned payload_len, record_len, n; u_char record[21], csum; unsigned record_addr, expect_addr; inf = fopen(filename, "r"); if (!inf) { perror(filename); exit(1); } eeprom_offset = 0; for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { if (!index(linebuf, '\n')) { fprintf(stderr, "%s line %d: too long or missing newline\n", filename, lineno); exit(1); } if (linebuf[0] != ':') continue; if (!isxdigit(linebuf[1]) || !isxdigit(linebuf[2])) { inv_record: fprintf(stderr, "%s line %d: invalid Intex HEX record\n", filename, lineno); exit(1); } payload_len = decode_hex_byte(linebuf + 1); if (payload_len > 16) { bad_payload_len: fprintf(stderr, "%s line %d: unsupported payload length\n", filename, lineno); exit(1); } record_len = payload_len + 5; cp = linebuf + 1; csum = 0; for (n = 0; n < record_len; n++) { if (!isxdigit(cp[0]) || !isxdigit(cp[1])) goto inv_record; record[n] = decode_hex_byte(cp); cp += 2; csum += record[n]; } if (csum) { fprintf(stderr, "%s line %d: bad Intel HEX record checksum\n", filename, lineno); exit(1); } if (record[3] == 0x00) { if (payload_len != 16) goto bad_payload_len; if (eeprom_offset >= SIZE_EEPROM) { fprintf(stderr, "%s line %d: data continues past valid EEPROM size\n", filename, lineno); exit(1); } record_addr = (record[1] << 8) | record[2]; expect_addr = EEPROM_START_ADDR + eeprom_offset; if (record_addr != expect_addr) { fprintf(stderr, "%s line %d: record addr is %04X, but we expect %04X\n", filename, lineno, record_addr, expect_addr); exit(1); } bcopy(record + 4, eeprom + eeprom_offset, 16); eeprom_offset += 16; } else if (record[3] == 0x01) { if (payload_len) { fprintf(stderr, "%s line %d: nonzero payload length in end-marker record\n", filename, lineno); exit(1); } if (eeprom_offset < SIZE_EEPROM) { fprintf(stderr, "%s line %d: end-marker without full data\n", filename, lineno); exit(1); } break; } else { fprintf(stderr, "%s line %d: unsupported Intel HEX record type\n", filename, lineno); exit(1); } } fclose(inf); if (!eeprom_offset) { fprintf(stderr, "error: no Intel HEX EEPROM data found in %s\n", filename); exit(1); } if (eeprom_offset < SIZE_EEPROM) { fprintf(stderr, "error: %s contains truncated data\n", filename); exit(1); } }