adding old command-line-tool
[labortage2013badge.git] / hostware / commandline / main.c
1 /* Name: set-led.c
2  * Project: hid-custom-rq example
3  * Author: Christian Starkjohann
4  * Creation Date: 2008-04-10
5  * Tabsize: 4
6  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
7  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8  * This Revision: $Id: set-led.c 692 2008-11-07 15:07:40Z cs $
9  */
10
11 /*
12 General Description:
13 This is the host-side driver for the custom-class example device. It searches
14 the USB for the LEDControl device and sends the requests understood by this
15 device.
16 This program must be linked with libusb on Unix and libusb-win32 on Windows.
17 See http://libusb.sourceforge.net/ or http://libusb-win32.sourceforge.net/
18 respectively.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <ctype.h>
26 #include <usb.h>        /* this is libusb */
27 #include <arpa/inet.h>
28 #include "hexdump.h"
29 #include "opendevice.h" /* common code moved to separate module */
30
31 #include "../../firmware/requests.h"   /* custom request numbers */
32 #include "../../firmware/usbconfig.h"  /* device's VID/PID and names */
33
34 int safety_question_override=0;
35 int pad=-1;
36
37 char* fname;
38 usb_dev_handle *handle = NULL;
39
40 void set_rgb(char* color){
41         uint16_t buffer[3] = {0, 0, 0};
42         sscanf(color, "%hi:%hi:%hi", &(buffer[0]), &(buffer[1]), &(buffer[2]));
43         buffer[0] &= (1<<10)-1;
44         buffer[1] &= (1<<10)-1;
45         buffer[2] &= (1<<10)-1;
46         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_RGB, 0, 0, (char*)buffer, 6, 5000);
47 }
48
49 void get_rgb(char* param){
50         uint16_t buffer[3];
51         int cnt;
52         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_RGB, 0, 0, (char*)buffer, 6, 5000);
53         if(cnt!=6){
54                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, 6);
55                 exit(1);
56         }
57         printf("red:   %5hu\ngreen: %5hu\nblue:  %5u\n", buffer[0], buffer[1], buffer[2]);
58 }
59
60 void read_mem(char* param){
61         int length=0;
62         uint8_t *buffer, *addr;
63         int cnt;
64         FILE* f=NULL;
65         if(fname){
66                 f = fopen(fname, "wb");
67                 if(!f){
68                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
69                         exit(1);
70                 }
71         }
72         sscanf(param, "%i:%i", (int*)&addr, &length);
73         if(length<=0){
74                 return;
75         }
76         buffer = malloc(length);
77         if(!buffer){
78                 if(f)
79                         fclose(f);
80                 fprintf(stderr, "ERROR: out of memory\n");
81                 exit(1);
82         }
83         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_MEM, (int)((unsigned)addr), 0, (char*)buffer, length, 5000);
84         if(cnt!=length){
85                 if(f)
86                         fclose(f);
87                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
88                 exit(1);
89         }
90         if(f){
91                 cnt = fwrite(buffer, 1, length, f);
92                 fclose(f);
93                 if(cnt!=length){
94                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
95                         exit(1);
96                 }
97
98         }else{
99                 hexdump_block(stdout, buffer, addr, length, 8);
100         }
101 }
102
103 void write_mem(char* param){
104         int length;
105         uint8_t *addr, *buffer, *data=NULL;
106         int cnt=0;
107         FILE* f=NULL;
108
109         if(fname){
110                 f = fopen(fname, "rb");
111                 if(!f){
112                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
113                         exit(1);
114                 }
115         }
116         sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
117         data += cnt;
118         if(length<=0){
119                 return;
120         }
121         buffer = malloc(length);
122         if(!buffer){
123                 if(f)
124                         fclose(f);
125                 fprintf(stderr, "ERROR: out of memory\n");
126                 exit(1);
127         }
128         memset(buffer, (uint8_t)pad, length);
129         if(!data && !f && length==0){
130                 fprintf(stderr, "ERROR: no data to write\n");
131                 exit(1);
132         }
133         if(f){
134                 cnt = fread(buffer, 1, length, f);
135                 fclose(f);
136                 if(cnt!=length && pad==-1){
137                         fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
138                 }
139         }else if(data){
140                 char xbuffer[3]= {0, 0, 0};
141                 uint8_t fill=0;
142                 unsigned idx=0;
143                 while(*data && idx<length){
144                         while(*data && !isxdigit(*data)){
145                                 ++data;
146                         }
147                         xbuffer[fill++] = *data;
148                         if(fill==2){
149                                 uint8_t t;
150                                 t = strtoul(xbuffer, NULL, 16);
151                                 buffer[idx++] = t;
152                                 fill = 0;
153                         }
154                 }
155
156         }
157         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_WRITE_MEM, (int)addr, 0, (char*)buffer, length, 5000);
158         if(cnt!=length){
159                 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
160                 exit(1);
161         }
162
163 }
164
165 void read_flash(char* param){
166         int length=0;
167         uint8_t *buffer, *addr;
168         int cnt;
169         FILE* f=NULL;
170         if(fname){
171                 f = fopen(fname, "wb");
172                 if(!f){
173                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
174                         exit(1);
175                 }
176         }
177         sscanf(param, "%i:%i", (int*)&addr, &length);
178         if(length<=0){
179                 return;
180         }
181         buffer = malloc(length);
182         if(!buffer){
183                 if(f)
184                         fclose(f);
185                 fprintf(stderr, "ERROR: out of memory\n");
186                 exit(1);
187         }
188         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_FLASH, (int)addr, 0, (char*)buffer, length, 5000);
189         if(cnt!=length){
190                 if(f)
191                         fclose(f);
192                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
193                 exit(1);
194         }
195         if(f){
196                 cnt = fwrite(buffer, 1, length, f);
197                 fclose(f);
198                 if(cnt!=length){
199                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
200                         exit(1);
201                 }
202
203         }else{
204                 hexdump_block(stdout, buffer, addr, length, 8);
205         }
206 }
207
208 void soft_reset(char* param){
209         unsigned delay=0;
210         if(param){
211                 sscanf(param, "%i", &delay);
212         }
213         delay &= 0xf;
214         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
215 }
216
217 void read_button(char* param){
218         uint8_t v;
219         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
220         printf("button is %s\n",v?"on":"off");
221 }
222
223 void wait_for_button(char* param){
224         volatile uint8_t v=0, x=1;
225         if(param){
226                 printf("DBG: having param: %s\n", param);
227                 if(!(strcmp(param,"off") && strcmp(param,"0"))){
228                         x = 0;
229                 }
230         }
231         do{
232                 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
233         }while(x!=v);
234         printf("button is %s\n",v?"on":"off");
235 }
236
237 void read_temperature(char* param){
238         uint16_t v;
239         int cnt;
240         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
241         printf("temperature raw value: %hd 0x%hx\n", v, v);
242 }
243
244
245 static struct option long_options[] =
246              {
247                /* These options set a flag. */
248                {"i-am-sure",       no_argument, &safety_question_override, 1},
249                {"pad",             optional_argument, 0, 'p'},
250                /* These options don't set a flag.
251                   We distinguish them by their indices. */
252                {"set-rgb",         required_argument, 0, 's'},
253                {"get-rgb",               no_argument, 0, 'g'},
254                {"read-mem",        required_argument, 0, 'r'},
255                {"write-mem",       required_argument, 0, 'w'},
256                {"read-flash",      required_argument, 0, 'z'},
257                {"exec-spm",        required_argument, 0, 'x'},
258                {"read-adc",        required_argument, 0, 'a'},
259                {"reset",           optional_argument, 0, 'q'},
260                {"read-button",     required_argument, 0, 'b'},
261                {"wait-for-button", optional_argument, 0, 'k'},
262                {"read-temperature",      no_argument, 0, 't'},
263                {"file",            required_argument, 0, 'f'},
264                {"loop",            required_argument, 0, 'l'},
265                {0, 0, 0, 0}
266              };
267
268 static void usage(char *name)
269 {
270         char *usage_str =
271         "usage:\n"
272     "    %s [<option>] <command> <parameter string>\n"
273     "  where <option> is one of the following:\n"
274         "    -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
275         "    -f --file <name> .................................. use file <name> for reading or writing data\n"
276         "    --i-am-sure ....................................... do not ask safety question\n"
277         "    -l --loop <value> ................................. execute action <value> times\n"
278         "  <command> is one of the following\n"
279         "    -s --set-rgb <red>:<green>:<blue> ................. set color\n"
280         "    -g --get-rgb ...................................... read color from device and print\n"
281         "    -r --read-mem <addr>:<length> ..................... read RAM\n"
282         "    -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
283         "    -z --read-flash <addr>:<length> ................... read flash\n"
284 /*      "    -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
285         "    -a --read-adc <adc> ............................... read ADC\n" */
286         "    -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
287         "    -b --read-button .................................. read status of button\n"
288         "    -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
289         "    -t --read-temperature ............................. read temperature sensor and output raw value\n"
290         " Please note:\n"
291         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
292         "   depending on if you use short or long options.\n"
293         "   Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
294         "   Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
295         ;
296         fprintf(stderr, usage_str, name);
297 }
298
299
300 int main(int argc, char **argv)
301 {
302   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
303   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
304   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
305   char product[] = {USB_CFG_DEVICE_NAME, 0};
306   int  vid, pid;
307   int  c, option_index;
308   void(*action_fn)(char*) = NULL;
309   char* main_arg = NULL;
310   unsigned exec_loops=(unsigned)-1;
311   usb_init();
312   if(argc < 2){   /* we need at least one argument */
313     usage(argv[0]);
314     exit(1);
315   }
316   /* compute VID/PID from usbconfig.h so that there is a central source of information */
317     vid = rawVid[1] * 256 + rawVid[0];
318     pid = rawPid[1] * 256 + rawPid[0];
319     /* The following function is in opendevice.c: */
320     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
321         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
322         exit(1);
323     }
324
325     for(;;){
326         c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:",
327                 long_options, &option_index);
328         if(c == -1){
329                 break;
330         }
331
332         if(action_fn && strchr("sgrzwxaqbkt", c)){
333                 /* action given while already having an action */
334                 usage(argv[0]);
335                 exit(1);
336         }
337
338         if(strchr("sgrzwxaqkt", c)){
339                 main_arg = optarg;
340         }
341
342         switch(c){
343         case 's': action_fn = set_rgb; break;
344         case 'g': action_fn = get_rgb; break;
345         case 'r': action_fn = read_mem; break;
346         case 'z': action_fn = read_flash; break;
347         case 'w': action_fn = write_mem; break;
348         case 'q': action_fn = soft_reset; break;
349         case 'b': action_fn = read_button; break;
350         case 'k': action_fn = wait_for_button; break;
351         case 't': action_fn = read_temperature; break;
352         case 'f': fname = optarg; break;
353         case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
354         case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
355         case 'x':
356         case 'a':
357         default:
358                 break;
359         }
360     }
361
362     if(!action_fn){
363         usage(argv[0]);
364         fprintf(stderr, "Error: no action specified\n");
365         return 1;
366     }else{
367         if(exec_loops==(unsigned)-1){
368                 exec_loops = 1;
369         }
370         while(exec_loops--){
371                 action_fn(main_arg);
372         }
373         usb_close(handle);
374         return 0;
375     }
376
377 }