00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020
00021 #include "srec.h"
00022
00023 static signed char ctab[256] = {
00024 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00025 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00026 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00027 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
00028 0,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00029 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00030 0,10,11,12,13,14,15,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00031 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00032 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
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 -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00037 -1,-1,-1,-1,-1,-1,-1,-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,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
00040 };
00041
00042 static int ltab[10] = {4,4,6,8,0,4,0,8,6,4};
00043
00044 #define C1(l,p) (ctab[l[p]])
00045 #define C2(l,p) ((C1(l,p)<<4)|C1(l,p+1))
00046
00047 int
00048 srec_decode(srec_t *srec, char *_line)
00049 {
00050 int len, pos = 0, count, alen, sum = 0;
00051 unsigned char *line = (unsigned char *)_line;
00052
00053 if (!srec || !line)
00054 return S_NULL;
00055
00056 for (len = 0; line[len]; len++)
00057 if (line[len] == '\n' || line[len] == '\r')
00058 break;
00059
00060 if (len < 4)
00061 return S_INVALID_HDR;
00062
00063 if (line[0] != 'S')
00064 return S_INVALID_HDR;
00065
00066 for (pos = 1; pos < len; pos++) {
00067 if (C1(line, pos) < 0)
00068 return S_INVALID_CHAR;
00069 }
00070
00071 srec->type = C1(line, 1);
00072 count = C2(line, 2);
00073
00074 if (srec->type > 9)
00075 return S_INVALID_TYPE;
00076 alen = ltab[srec->type];
00077 if (alen == 0)
00078 return S_INVALID_TYPE;
00079 if (len < alen + 6 || len < count * 2 + 4)
00080 return S_TOO_SHORT;
00081 if (count > 37 || len > count * 2 + 4)
00082 return S_TOO_LONG;
00083
00084 sum += count;
00085
00086 len -= 4;
00087 line += 4;
00088
00089 srec->addr = 0;
00090 for (pos = 0; pos < alen; pos += 2) {
00091 unsigned char value = C2(line, pos);
00092 srec->addr = (srec->addr << 8) | value;
00093 sum += value;
00094 }
00095
00096 len -= alen;
00097 line += alen;
00098
00099 for (pos = 0; pos < len - 2; pos += 2) {
00100 unsigned char value = C2(line, pos);
00101 srec->data[pos / 2] = value;
00102 sum += value;
00103 }
00104
00105 srec->count = count - (alen / 2) - 1;
00106
00107 sum += C2(line, pos);
00108
00109 if ((sum & 0xff) != 0xff)
00110 return S_INVALID_CKSUM;
00111
00112 return S_OK;
00113 }
00114
00115 int
00116 srec_encode(srec_t *srec, char *line)
00117 {
00118 int alen, count, sum = 0, pos;
00119
00120 if (srec->type > 9)
00121 return S_INVALID_TYPE;
00122 alen = ltab[srec->type];
00123 if (alen == 0)
00124 return S_INVALID_TYPE;
00125
00126 line += sprintf(line, "S%d", srec->type);
00127
00128 if (srec->count > 32)
00129 return S_TOO_LONG;
00130 count = srec->count + (alen / 2) + 1;
00131 line += sprintf(line, "%02X", count);
00132 sum += count;
00133
00134 while (alen) {
00135 int value;
00136 alen -= 2;
00137 value = (srec->addr >> (alen * 4)) & 0xff;
00138 line += sprintf(line, "%02X", value);
00139 sum += value;
00140 }
00141
00142 for (pos = 0; pos < srec->count; pos++) {
00143 line += sprintf(line, "%02X", srec->data[pos]);
00144 sum += srec->data[pos];
00145 }
00146
00147 sprintf(line, "%02X\n", (~sum) & 0xff);
00148
00149 return S_OK;
00150 }