Adding file with commands for non-regretion testing.
[lpctools] / isp_utils.c
1 /*********************************************************************
2  *
3  *   LPC1114 ISP - Utility functions
4  *
5  *
6  * Written by Nathael Pajani <nathael.pajani@nathael.net>
7  * 
8  * This programm is released under the terms of the GNU GPLv3 licence
9  * as can be found on the GNU website : <http://www.gnu.org/licenses/>
10  *
11  *********************************************************************/
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <stdint.h>
18 #include <unistd.h> /* for open, close */
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <errno.h>
24 #include <string.h> /* memcpy */
26 #include <termios.h> /* serial */
27 #include <ctype.h>
30 extern int trace_on;
32 /* display data as in hexdump -C :
33    00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
34  */
35 void isp_dump(const unsigned char* buf, unsigned int buf_size)
36 {
37         unsigned int count = 0;
38         char pass = 0;
39         if (buf_size == 0) {
40                 return;
41         }
42         while ((count < buf_size) || (pass == 0)) {
43                 if (count == buf_size) {
44                         while (count & 0x0F) {
45                                 printf("   ");
46                                 count++;
47                         }
48                         pass = 1;
49                         count -= 0x10;
50                 }
51                 if ((count % 0x10) == 0) {
52                         if (pass == 0) {
53                                 printf(" %08x  ", count);
54                         } else {
55                                 printf(" |");
56                         }
57                 }
58                 if (pass == 0) {
59                         printf("%02x ", buf[count]);
60                 } else {
61                         if (isgraph((int)buf[count])) {
62                                 printf("%c", buf[count]);
63                         } else {
64                                 printf(".");
65                         }
66                 }
67                 count++;
68                 if ((count % 0x10) == 0) {
69                         if (pass == 0) {
70                                 count -= 0x10;
71                         } else {
72                                 if (count == buf_size) {
73                                         break; /* prevent infinite loop */
74                                 }
75                                 printf("|\n");
76                         }
77                         pass = !pass;
78                 }
79         }
80         printf("|\n");
81 }
84 /* ---- Serial utility functions ---------------------------------------------------*/
86 static int serial_fd = -1;
88 /* Open the serial device and set it up.
89  * Returns 0 on success, negativ value on error.
90  * Actal setup is done according to LPC11xx user's manual.
91  * Only baudrate can be changed using command line option.
92  */
93 int isp_serial_open(int baudrate, char* serial_device)
94 {
95         struct termios tio;
97         if (serial_device == NULL) {
98                 printf("No serial device given on command line\n");
99                 return -2;
100         }
102         /* Open serial port */
103         serial_fd = open(serial_device, O_RDWR | O_NONBLOCK);
104         if (serial_fd < 0) {
105                 perror("Unable to open serial_device");
106                 printf("Tried to open \"%s\".\n", serial_device);
107                 return -1;
108         }
109         /* Setup serial port */
110         memset(&tio, 0, sizeof(tio));
111         tio.c_iflag = IXON | IXOFF;  /* See section 21.4.4 of LPC11xx user's manual (UM10398) */
112         tio.c_cflag = CS8 | CREAD | CLOCAL;  /* 8n1, see termios.h for more information */
113         tio.c_cc[VMIN] = 1;
114         tio.c_cc[VTIME] = 5;
115         cfsetospeed(&tio, baudrate);
116         cfsetispeed(&tio, baudrate);
117         tcsetattr(serial_fd, TCSANOW, &tio);
118         
119         return 0;
122 void isp_serial_close(void)
124         close(serial_fd);
127 /* Simple write() wrapper, with trace if enabled */
128 int isp_serial_write(const char* buf, unsigned int buf_size)
130         int nb = 0;
132         if (trace_on) {
133                 printf("Sending %d octet(s) :\n", buf_size);
134                 isp_dump((unsigned char*)buf, buf_size);
135         }
136         nb = write(serial_fd, buf, buf_size);
137         if (nb <= 0) {
138                 perror("Serial write error");
139                 return -1;
140         }
141         return nb;
144 /* Try to read at least "min_read" characters from the serial line.
145  * Returns -1 on error, 0 on end of file, or read count otherwise.
146  */
147 int isp_serial_read(char* buf, unsigned int buf_size, unsigned int min_read)
149         int nb = 0;
150         unsigned int count = 0;
151         unsigned int loops = 0; /* Used to create a timeout */
152         
153         if (min_read > buf_size) {
154                 printf("serial_read: buffer too small for min read value.\n");
155                 return -3;
156         }
158         do {
159                 nb = read(serial_fd, &buf[count], (buf_size - count));
160                 if (nb < 0) {
161                         if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
162                                 if (loops++ > 100) {
163                                         break; /* timeout at 500ms */
164                                 }
165                                 usleep( 5000 );
166                                 continue;
167                         }
168                         perror("Serial read error");
169                         return -1;
170                 } else if (nb == 0) {
171                         printf("serial_read: end of file !!!!\n");
172                         return 0;
173                 }
174                 if (trace_on == 2) {
175                         isp_dump((unsigned char*)(&buf[count]), nb);
176                 }       
177                 count += nb;
178         } while (count < min_read);
180         if (trace_on) {
181                 printf("Received %d octet(s) :\n", count);
182                 isp_dump((unsigned char*)buf, count);
183         }
184         return count;
188 /* ---- UU_Encoding utility functions ----------------------------------------------*/
190 /* This might have been taken from a lib, but I hate lib dependencies, and installing
191  *  a full window manager (or MTA or MUA for instance) for two functions is not an 
192  *  option */
193 #define UUENCODE_ADDED_VAL 32
194 #define LINE_DATA_LENGTH_MAX 45
195 #define LINE_LENGTH_NULL 96
197 int isp_uu_encode(char* dest, char* src, unsigned int orig_size)
199         unsigned int new_size = 0;
200         unsigned int pos = 0;
202         while (pos < orig_size) {
203                 unsigned int line_length = orig_size - pos;
204                 unsigned int i = 0;
205                 
206                 /* Start with line length */
207                 if (line_length > LINE_DATA_LENGTH_MAX) {
208                         line_length = LINE_DATA_LENGTH_MAX;
209                 }
210                 dest[new_size] = line_length + UUENCODE_ADDED_VAL;
211                 new_size++;
212                 
213                 /* Encode line */
214                 while (i < line_length) {
215                         uint32_t int_triplet = 0;
216                         int j = 0;
217                         
218                         /* Get original triplet (three bytes) */
219                         for (j=0; j<3; j++) {
220                                 int_triplet |= ((src[pos + i + j] & 0xFF) << (8 * (2 - j)));
221                                 /* if not enougth data, leave it as nul */
222                                 if ((i + j) > line_length) {
223                                         break;
224                                 }
225                         }
226                         for (j=0; j<4; j++) {
227                                 /* Store triplet in four bytes */
228                                 dest[new_size + j] = ((int_triplet >> (6 * (3 - j))) & 0x3F);
229                                 /* Add offset */
230                                 dest[new_size + j] += UUENCODE_ADDED_VAL;
231                         }
232                         i += 3;
233                         new_size += 4;
234                 }
235                 pos += line_length;
237                 /* Add \r\n */
238                 dest[new_size++] = '\r';
239                 dest[new_size++] = '\n';
240         }
241         return new_size;
244 int isp_uu_decode(char* dest, char* src, unsigned int orig_size)
246         unsigned int new_size = 0;
247         unsigned int pos = 0;
249         while (pos < orig_size) {
250                 unsigned int line_length = 0;
251                 unsigned int i = 0;
252                 int j = 0;
254                 /* Read line length */
255                 line_length = src[pos] - UUENCODE_ADDED_VAL;
256                 if (src[pos] == LINE_LENGTH_NULL) {
257                         /* Empty line ? then we are done converting
258                          * (should not happen in communication with ISP) */
259                         return new_size;
260                 }
261                 pos++;
263                 /* Decode line */
264                 while (i < line_length) {
265                         char quartet[4];
266                         uint32_t int_triplet = 0;
267                         /* copy data */
268                         memcpy(quartet, &src[pos], 4);
269                         pos += 4;
270                         /* Get the original bits */
271                         for (j=0; j<4; j++) {
272                                 /* Remove the offset added by uuencoding */
273                                 quartet[j] -= UUENCODE_ADDED_VAL;
274                                 int_triplet |= ((quartet[j] & 0x3F) << ((3 - j) * 6));
275                         }
276                         /* And store them */
277                         for (j=2; j>=0; j--) {
278                                 dest[new_size++] = ((int_triplet >> (j * 8)) & 0xFF );
279                                 i++;
280                                 if (i >= line_length) {
281                                         break;
282                                 }
283                         }
284                 }
285                 
286                 /* Find next line */
287                 while ((src[pos] < UUENCODE_ADDED_VAL) && (pos < orig_size))   {
288                         pos++;
289                 }
290         }
291         return new_size;