cleanup specfile for packaging
[profile/ivi/gpsd.git] / srecord.c
1 /*
2  * Copyright (c) 2005 Chris Kuethe <chris.kuethe@gmail.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <sys/types.h>
17 #include <stdio.h>
18 #include <string.h>
19
20 #include "gpsd.h"
21
22 /*
23  * See srec(5) for a description of this format.  
24  * We read and write 4-byte addresses.
25  *      S0: Comments
26  *      S3: Memory Loadable Data, 4byte address
27  *      S5: Count of S1, S2 and S3 Records
28  *      S7: starting execution address interpreted as a 4-byte address 
29  */
30 #define MAX_BYTES_PER_RECORD    16
31
32 /*
33  * bin2srec: turn a chunk of binary into an S-record
34  * offset: used to specify load address
35  * num: up to MAX_BYTES_PER_RECORD bytes can be encoded at one time
36  * bytes are read from bbuf and a ready-to-go srecord is placed in sbuf
37  */
38 int
39 bin2srec(unsigned int type, unsigned int offset, unsigned int num,
40          unsigned char *bbuf, unsigned char *sbuf)
41 {
42     unsigned char abuf[MAX_BYTES_PER_RECORD * 2 + 2], sum;
43     size_t len;
44
45     if ((num < 1) || (num > MAX_BYTES_PER_RECORD))
46         return -1;
47
48     len = (size_t) (4 + num + 1);
49     memset(abuf, 0, sizeof(abuf));
50     hexdump((size_t) num, bbuf, abuf);
51     sum = sr_sum((unsigned int)len, offset, bbuf);
52     (void)snprintf((char *)sbuf, MAX_BYTES_PER_RECORD * 2 + 17,
53                    "S%u%02X%08X%s%02X\r\n",
54                    type, (unsigned)len, offset, (char *)abuf, (unsigned)sum);
55     return 0;
56 }
57
58 int srec_hdr(unsigned int num, unsigned char *bbuf, unsigned char *sbuf)
59 {
60     return bin2srec(0, 0, num, bbuf, sbuf);
61 }
62
63 int srec_fin(unsigned int num, unsigned char *sbuf)
64 {
65     unsigned char bbuf[4], sum;
66
67     memset(bbuf, 0, 4);
68
69     bbuf[0] = (unsigned char)(num & 0xff);
70     bbuf[1] = (unsigned char)((num >> 8) & 0xff);
71     sum = sr_sum(3, 0, bbuf);
72     (void)snprintf((char *)sbuf, 13, "S503%04X%02X\r\n", num, (unsigned)sum);
73     return 0;
74 }
75
76
77 void hexdump(size_t len, unsigned char *bbuf, unsigned char *abuf)
78 {
79     size_t i;
80
81     memset(abuf, 0, MAX_BYTES_PER_RECORD * 2 + 2);
82     if (len > MAX_BYTES_PER_RECORD * 2)
83         len = MAX_BYTES_PER_RECORD * 2;
84
85     for (i = 0; i < len; i++) {
86         abuf[i * 2] = hc((bbuf[i] & 0xf0) >> 4);
87         abuf[i * 2 + 1] = hc(bbuf[i] & 0x0f);
88     }
89 }
90
91 /*@ -type @*/
92 unsigned char hc(unsigned char x)
93 {
94     switch (x) {
95     case 15:
96     case 14:
97     case 13:
98     case 12:
99     case 11:
100     case 10:
101         return ('A' + x - 10);
102     case 9:
103     case 8:
104     case 7:
105     case 6:
106     case 5:
107     case 4:
108     case 3:
109     case 2:
110     case 1:
111     case 0:
112         return ('0' + x);
113
114     default:
115         return '0';
116     }
117 }
118
119 /*@ -type @*/
120
121 unsigned char
122 sr_sum(unsigned int count, unsigned int addr, unsigned char *bbuf)
123 {
124     int i, j;
125     unsigned char k, sum = 0;
126
127     sum = (count & 0xff);
128     sum += ((addr & 0x000000ff));
129     sum += ((addr & 0x0000ff00) >> 8);
130     sum += ((addr & 0x00ff0000) >> 16);
131     sum += ((addr & 0xff000000) >> 24);
132     j = count - 5;
133     for (i = 0; i < j; i++) {
134         k = bbuf[i];
135         sum += k;
136     }
137     return ~sum;
138 }