00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <ctype.h>
00027
00028 #include "srec.h"
00029
00030
00031
00032 static signed char ctab[256] = {
00033 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00034 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00035 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00036 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
00037 -1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00038 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00039 -1,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00040 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00041 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00042 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00043 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00044 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00045 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00046 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00047 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00048 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00049 };
00050
00051 static int ltab[10] = {4,4,6,8,0,4,0,8,6,4};
00052
00053
00054
00055 #define C1(l,p) (ctab[l[p]])
00056 #define C2(l,p) ((C1(l,p)<<4)|C1(l,p+1))
00057
00058
00059
00060 int
00061 srec_decode(srec_t *srec, char *_line)
00062 {
00063 int len, pos = 0, count, alen, sum = 0;
00064 unsigned char *line = (unsigned char *)_line;
00065
00066 if (!srec || !line)
00067 return SREC_NULL;
00068
00069 for (len = 0; line[len]; len++)
00070 if (line[len] == '\n' || line[len] == '\r')
00071 break;
00072
00073 if (len < 4)
00074 return SREC_INVALID_HDR;
00075
00076 if (line[0] != 'S')
00077 return SREC_INVALID_HDR;
00078
00079 for (pos = 1; pos < len; pos++) {
00080 if (C1(line, pos) < 0)
00081 return SREC_INVALID_CHAR;
00082 }
00083
00084 srec->type = C1(line, 1);
00085 count = C2(line, 2);
00086
00087 if (srec->type > 9)
00088 return SREC_INVALID_TYPE;
00089 alen = ltab[srec->type];
00090 if (alen == 0)
00091 return SREC_INVALID_TYPE;
00092 if (len < alen + 6)
00093 return SREC_TOO_SHORT;
00094 if (count > alen + SREC_DATA_SIZE + 2)
00095 return SREC_TOO_LONG;
00096 if (len != count * 2 + 4)
00097 return SREC_INVALID_LEN;
00098
00099 sum += count;
00100
00101 len -= 4;
00102 line += 4;
00103
00104 srec->addr = 0;
00105 for (pos = 0; pos < alen; pos += 2) {
00106 unsigned char value = C2(line, pos);
00107 srec->addr = (srec->addr << 8) | value;
00108 sum += value;
00109 }
00110
00111 len -= alen;
00112 line += alen;
00113
00114 for (pos = 0; pos < len - 2; pos += 2) {
00115 unsigned char value = C2(line, pos);
00116 srec->data[pos / 2] = value;
00117 sum += value;
00118 }
00119
00120 srec->count = count - (alen / 2) - 1;
00121
00122 sum += C2(line, pos);
00123
00124 if ((sum & 0xff) != 0xff)
00125 return SREC_INVALID_CKSUM;
00126
00127 return SREC_OK;
00128 }
00129
00130 int
00131 srec_encode(srec_t *srec, char *line)
00132 {
00133 int alen, count, sum = 0, pos;
00134
00135 if (srec->type > 9)
00136 return SREC_INVALID_TYPE;
00137 alen = ltab[srec->type];
00138 if (alen == 0)
00139 return SREC_INVALID_TYPE;
00140
00141 line += sprintf(line, "S%d", srec->type);
00142
00143 if (srec->count > 32)
00144 return SREC_TOO_LONG;
00145 count = srec->count + (alen / 2) + 1;
00146 line += sprintf(line, "%02X", count);
00147 sum += count;
00148
00149 while (alen) {
00150 int value;
00151 alen -= 2;
00152 value = (srec->addr >> (alen * 4)) & 0xff;
00153 line += sprintf(line, "%02X", value);
00154 sum += value;
00155 }
00156
00157 for (pos = 0; pos < srec->count; pos++) {
00158 line += sprintf(line, "%02X", srec->data[pos]);
00159 sum += srec->data[pos];
00160 }
00161
00162 sprintf(line, "%02X\n", (~sum) & 0xff);
00163
00164 return SREC_OK;
00165 }
00166
00167 char *
00168 srec_strerror (int error)
00169 {
00170 switch (error) {
00171 case SREC_OK: return "no error";
00172 case SREC_NULL: return "null string error";
00173 case SREC_INVALID_HDR: return "invalid header";
00174 case SREC_INVALID_CHAR: return "invalid character";
00175 case SREC_TOO_SHORT: return "line too short";
00176 case SREC_TOO_LONG: return "line too long";
00177 case SREC_INVALID_LEN: return "length error";
00178 case SREC_INVALID_CKSUM: return "checksum error";
00179 default: return "unknown error";
00180 }
00181 }