Contiki 3.x
shell-crc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Block-wise hexadecimal conversion and CRC commands
36  * \author
37  * Fredrik Osterlind <fros@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "shell.h"
42 #include "lib/crc16.h"
43 
44 #include <ctype.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 
49 #ifdef __CC65__
50 #define HAVE_ALLOCA 0
51 #else
52 #define HAVE_ALLOCA 1
53 #endif
54 
55 #define DEBUG 0
56 #if DEBUG
57 #include <stdio.h>
58 #define PRINTF(...) printf(__VA_ARGS__)
59 #else
60 #define PRINTF(...)
61 #endif
62 
63 /*---------------------------------------------------------------------------*/
64 #if HAVE_ALLOCA
65 PROCESS(shell_bin2hex_process, "bin2hex");
66 SHELL_COMMAND(bin2hex_command,
67  "bin2hex",
68  "bin2hex: binary to hexadecimal",
69  &shell_bin2hex_process);
70 PROCESS(shell_hex2bin_process, "hex2bin");
71 SHELL_COMMAND(hex2bin_command,
72  "hex2bin",
73  "hex2bin: hexadecimal to binary",
74  &shell_hex2bin_process);
75 PROCESS(shell_crc_process, "crc");
76 SHELL_COMMAND(crc_command,
77  "crc",
78  "crc: append per-block crc",
79  &shell_crc_process);
80 #endif /* HAVE_ALLOCA */
81 PROCESS(shell_crcvalidate_process, "crc-v");
82 SHELL_COMMAND(crcvalidate_command,
83  "crc-v",
84  "crc-v: verify crc and output if valid",
85  &shell_crcvalidate_process);
86 /*---------------------------------------------------------------------------*/
87 #if HAVE_ALLOCA
88 static unsigned char
89 fromhexchar(unsigned char c)
90 {
91  unsigned char h;
92  if(c >= '0' && c <= '9') {
93  h = c-'0';
94  } else if(c >= 'a' && c <= 'f') {
95  h = c-'a'+10;
96  } else if(c >= 'A' && c <= 'F') {
97  h = c-'A'+10;
98  } else {
99  PRINTF("Bad hex input: %c", c);
100  h = 0;
101  }
102  return h;
103 }
104 /*---------------------------------------------------------------------------*/
105 static unsigned char
106 fromhex(unsigned char c1, unsigned char c2)
107 {
108  return (fromhexchar(c1)<<4) + fromhexchar(c2);
109 }
110 /*---------------------------------------------------------------------------*/
111 PROCESS_THREAD(shell_bin2hex_process, ev, data)
112 {
113  struct shell_input *input;
114  int i;
115  char *bufptr;
116  char *buf;
117 
118  PROCESS_BEGIN();
119 
120  while(1) {
122  input = data;
123 
124  if(input->len1 + input->len2 == 0) {
125  PROCESS_EXIT();
126  }
127 
128  buf = alloca((input->len1 + input->len2)*2);
129 
130  bufptr = buf;
131  for(i = 0; i < input->len1; i++) {
132  bufptr += sprintf(bufptr, "%02x", 0xff&((char*)input->data1)[i]);
133  }
134  for(i = 0; i < input->len2; i++) {
135  bufptr += sprintf(bufptr, "%02x", 0xff&((char*)input->data2)[i]);
136  }
137 
138  shell_output(
139  &bin2hex_command,
140  buf, ((input->len1 + input->len2)*2), "", 0);
141  }
142 
143  PROCESS_END();
144 }
145 /*---------------------------------------------------------------------------*/
146 PROCESS_THREAD(shell_hex2bin_process, ev, data)
147 {
148  struct shell_input *input;
149  int i, cnt;
150  char* buf;
151 
152  PROCESS_BEGIN();
153 
154  /* Reads data in hexadecimal format and prints in binary */
155 
156  while(1) {
158  input = data;
159 
160  if(input->len1 + input->len2 == 0) {
161  PROCESS_EXIT();
162  }
163 
164  if(input->len1 % 2 != 0) {
165  PRINTF("Bad input length 1: %d\n", input->len1);
166  continue;
167  }
168  if(input->len2 % 2 != 0) {
169  PRINTF("Bad input length 2: %d\n", input->len2);
170  continue;
171  }
172 
173  buf = alloca((input->len1 + input->len2)/2+1);
174 
175  cnt = 0;
176  for(i = 0; i < input->len1; i += 2) {
177  buf[cnt++] = fromhex(
178  ((char*)input->data1)[i],
179  ((char*)input->data1)[i+1]);
180  }
181  for(i = 0; i < input->len2; i += 2) {
182  buf[cnt++] = fromhex(
183  ((char*)input->data2)[i],
184  ((char*)input->data2)[i+1]);
185  }
186 
187  shell_output(&hex2bin_command, buf, cnt, "", 0);
188  }
189 
190  PROCESS_END();
191 }
192 /*---------------------------------------------------------------------------*/
193 PROCESS_THREAD(shell_crc_process, ev, data)
194 {
195  struct shell_input *input;
196  int i;
197  uint16_t crc;
198  char *buf;
199 
200  PROCESS_BEGIN();
201 
202  /* Append per-block 16-bit CRC */
203 
204  while(1) {
206  input = data;
207 
208  if(input->len1 + input->len2 == 0) {
209  PROCESS_EXIT();
210  }
211 
212  /* calculate crc */
213  crc = 0;
214  for(i = 0; i < input->len1; i++) {
215  crc = crc16_add(((char*)(input->data1))[i], crc);
216  }
217  for(i = 0; i < input->len2; i++) {
218  crc = crc16_add(((char*)(input->data2))[i], crc);
219  }
220 
221  /* input + 16-bit CRC */
222  buf = alloca(input->len2+2);
223 
224  memcpy(buf, input->data2, input->len2);
225  buf[input->len2] = crc&0xff;
226  buf[input->len2+1] = (crc>>8)&0xff;
227 
228  shell_output(&crc_command, input->data1, input->len1, buf, input->len2+2);
229  }
230 
231  PROCESS_END();
232 }
233 #endif /* HAVE_ALLOCA */
234 /*---------------------------------------------------------------------------*/
235 PROCESS_THREAD(shell_crcvalidate_process, ev, data)
236 {
237  struct shell_input *input;
238  int i;
239  char crc1, crc2;
240  uint16_t crc, crc_footer;
241 
242  PROCESS_BEGIN();
243 
244  /* Per-block 16-bit CRC verification:
245  * outputs data without CRCs matches, otherwise nothing */
246 
247  while(1) {
249  input = data;
250 
251  if(input->len1 + input->len2 == 0) {
252  PROCESS_EXIT();
253  }
254 
255  if(input->len1 + input->len2 < 2) {
256  /* too short - no output */
257  PRINTF("Too short input: %d+%d\n", input->len1, input->len2);
258  continue;
259  }
260 
261  if(input->len2 == 1) {
262  crc1 = ((char*)input->data1)[input->len1-1];
263  crc2 = ((char*)input->data2)[input->len2-1];
264  input->len1 -= 1;
265  input->len2 -= 1;
266  } else if(input->len2 >= 2) {
267  crc1 = ((char*)input->data2)[input->len2-2];
268  crc2 = ((char*)input->data2)[input->len2-1];
269  input->len2 -= 2;
270  } else {
271  crc1 = ((char*)input->data1)[input->len1-2];
272  crc2 = ((char*)input->data1)[input->len1-1];
273  input->len1 -= 2;
274  }
275 
276  /* recalculate crc */
277  crc = 0;
278  for(i = 0; i < input->len1; i++) {
279  crc = crc16_add(((char*)(input->data1))[i], crc);
280  }
281  for(i = 0; i < input->len2; i++) {
282  crc = crc16_add(((char*)(input->data2))[i], crc);
283  }
284 
285  /* compare with input crc */
286  crc_footer = ((0xff&crc2)<<8) | (0xff&crc1);
287 
288  /* output if matching crcs */
289  if(crc_footer == crc) {
290  shell_output(
291  &crcvalidate_command,
292  input->data1, input->len1, input->data2, input->len2);
293  }
294  }
295 
296  PROCESS_END();
297 }
298 /*---------------------------------------------------------------------------*/
299 void
300 shell_crc_init(void)
301 {
302 #if HAVE_ALLOCA
303  shell_register_command(&bin2hex_command);
304  shell_register_command(&hex2bin_command);
305  shell_register_command(&crc_command);
306 #endif /* HAVE_ALLOCA */
307  shell_register_command(&crcvalidate_command);
308 }
309 /*---------------------------------------------------------------------------*/
#define PROCESS_EXIT()
Exit the currently running process.
Definition: process.h:200
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
Main header file for the Contiki shell
void shell_output(struct shell_command *c, void *data1, int len1, const void *data2, int len2)
Output data from a shell command.
Definition: shell.c:395
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
Structure for shell input data.
Definition: shell.h:365
void shell_register_command(struct shell_command *c)
Register a command with the shell.
Definition: shell.c:413
#define PROCESS_WAIT_EVENT_UNTIL(c)
Wait for an event to be posted to the process, with an extra condition.
Definition: process.h:157
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
int shell_event_input
The event number for shell input data.
Definition: shell.c:70
unsigned short crc16_add(unsigned char b, unsigned short acc)
Update an accumulated CRC16 checksum with one byte.
Definition: crc16.c:47
Header file for the CRC16 calculcation
#define SHELL_COMMAND(name, command, description, process)
Define a shell command.
Definition: shell.h:219