some minor editings
[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 int8_t hex_to_int(char c) {
41     int8_t r = -1;
42     if (c >= '0' && c <= '9') {
43         r = c - '0';
44     } else {
45         c |= 'a' ^ 'A';
46         if (c >= 'a' && c <= 'f') {
47             r = 10 + c - 'a';
48         }
49     }
50     return r;
51 }
52
53 void press_button(char* param){
54     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_PRESS_BUTTON, 0, 0, NULL, 0, 5000);
55 }
56
57 void set_dbg(char *hex_string){
58         uint8_t buffer[(strlen(hex_string) + 1) / 2];
59         size_t i = 0, length = 0;
60         int8_t t;
61
62         memset(buffer, 0, (strlen(hex_string) + 1) / 2);
63
64         while (hex_string[i]) {
65             t = hex_to_int(hex_string[i]);
66             if (t == -1){
67                 break;
68             }
69             if (i & 1) {
70                 buffer[length++] |= t;
71             } else {
72                 buffer[length] |= t << 4;
73             }
74         }
75
76         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_DBG, 0, 0, (char*)buffer, length, 5000);
77 }
78
79 void get_dbg(char* param){
80         uint16_t buffer[256];
81         int cnt;
82         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_DBG, 0, 0, (char*)buffer, 256, 5000);
83         printf("DBG-Buffer:\n");
84         hexdump_block(stdout, buffer, 0, cnt, 16);
85 }
86
87 void read_mem(char* param){
88         int length=0;
89         uint8_t *buffer, *addr;
90         int cnt;
91         FILE* f=NULL;
92         if(fname){
93                 f = fopen(fname, "wb");
94                 if(!f){
95                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
96                         exit(1);
97                 }
98         }
99         sscanf(param, "%i:%i", (int*)&addr, &length);
100         if(length<=0){
101                 return;
102         }
103         buffer = malloc(length);
104         if(!buffer){
105                 if(f)
106                         fclose(f);
107                 fprintf(stderr, "ERROR: out of memory\n");
108                 exit(1);
109         }
110         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_MEM, (intptr_t)addr, 0, (char*)buffer, length, 5000);
111         if(cnt!=length){
112                 if(f)
113                         fclose(f);
114                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
115                 exit(1);
116         }
117         if(f){
118                 cnt = fwrite(buffer, 1, length, f);
119                 fclose(f);
120                 if(cnt!=length){
121                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
122                         exit(1);
123                 }
124
125         }else{
126                 hexdump_block(stdout, buffer, addr, length, 8);
127         }
128 }
129
130 void write_mem(char* param){
131         int length;
132         uint8_t *addr, *buffer, *data=NULL;
133         int cnt=0;
134         FILE* f=NULL;
135
136         if(fname){
137                 f = fopen(fname, "rb");
138                 if(!f){
139                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
140                         exit(1);
141                 }
142         }
143         sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
144         data += cnt;
145         if(length<=0){
146                 return;
147         }
148         buffer = malloc(length);
149         if(!buffer){
150                 if(f)
151                         fclose(f);
152                 fprintf(stderr, "ERROR: out of memory\n");
153                 exit(1);
154         }
155         memset(buffer, (uint8_t)pad, length);
156         if(!data && !f && length==0){
157                 fprintf(stderr, "ERROR: no data to write\n");
158                 exit(1);
159         }
160         if(f){
161                 cnt = fread(buffer, 1, length, f);
162                 fclose(f);
163                 if(cnt!=length && pad==-1){
164                         fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
165                 }
166         }else if(data){
167                 char xbuffer[3]= {0, 0, 0};
168                 uint8_t fill=0;
169                 unsigned idx=0;
170                 while(*data && idx<length){
171                         while(*data && !isxdigit(*data)){
172                                 ++data;
173                         }
174                         xbuffer[fill++] = *data;
175                         if(fill==2){
176                                 uint8_t t;
177                                 t = strtoul(xbuffer, NULL, 16);
178                                 buffer[idx++] = t;
179                                 fill = 0;
180                         }
181                 }
182
183         }
184         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_WRITE_MEM, (intptr_t)addr, 0, (char*)buffer, length, 5000);
185         if(cnt!=length){
186                 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
187                 exit(1);
188         }
189
190 }
191
192 void read_flash(char* param){
193         int length=0;
194         uint8_t *buffer, *addr;
195         int cnt;
196         FILE* f=NULL;
197         if(fname){
198                 f = fopen(fname, "wb");
199                 if(!f){
200                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
201                         exit(1);
202                 }
203         }
204         sscanf(param, "%i:%i", (int*)&addr, &length);
205         if(length<=0){
206                 return;
207         }
208         buffer = malloc(length);
209         if(!buffer){
210                 if(f)
211                         fclose(f);
212                 fprintf(stderr, "ERROR: out of memory\n");
213                 exit(1);
214         }
215         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_FLASH, (intptr_t)addr, 0, (char*)buffer, length, 5000);
216         if(cnt!=length){
217                 if(f)
218                         fclose(f);
219                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
220                 exit(1);
221         }
222         if(f){
223                 cnt = fwrite(buffer, 1, length, f);
224                 fclose(f);
225                 if(cnt!=length){
226                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
227                         exit(1);
228                 }
229
230         }else{
231                 hexdump_block(stdout, buffer, addr, length, 8);
232         }
233 }
234
235 void soft_reset(char* param){
236         unsigned delay=0;
237         if(param){
238                 sscanf(param, "%i", &delay);
239         }
240         delay &= 0xf;
241         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
242 }
243
244 void read_button(char* param){
245         uint8_t v;
246         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
247         printf("button is %s\n",v?"on":"off");
248 }
249
250 void wait_for_button(char* param){
251         volatile uint8_t v=0, x=1;
252         if(param){
253                 printf("DBG: having param: %s\n", param);
254                 if(!(strcmp(param,"off") && strcmp(param,"0"))){
255                         x = 0;
256                 }
257         }
258         do{
259                 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
260         }while(x!=v);
261         printf("button is %s\n",v?"on":"off");
262 }
263
264 void read_temperature(char* param){
265         uint16_t v;
266         int cnt;
267         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
268         if (cnt == 2) {
269             printf("temperature raw value: %hd 0x%hx\n", v, v);
270         } else {
271         fprintf(stderr, "Error: reading %d bytes for temperature, expecting 2\n", cnt);
272         }
273 }
274
275
276 static struct option long_options[] =
277              {
278                /* These options set a flag. */
279                {"i-am-sure",       no_argument, &safety_question_override, 1},
280                {"pad",             optional_argument, 0, 'p'},
281                /* These options don't set a flag.
282                   We distinguish them by their indices. */
283                {"set-rgb",         required_argument, 0, 's'},
284                {"get-rgb",               no_argument, 0, 'g'},
285                {"read-mem",        required_argument, 0, 'r'},
286                {"write-mem",       required_argument, 0, 'w'},
287                {"read-flash",      required_argument, 0, 'z'},
288                {"exec-spm",        required_argument, 0, 'x'},
289                {"read-adc",        required_argument, 0, 'a'},
290                {"reset",           optional_argument, 0, 'q'},
291                {"read-button",     required_argument, 0, 'b'},
292                {"wait-for-button", optional_argument, 0, 'k'},
293                {"read-temperature",      no_argument, 0, 't'},
294                {"file",            required_argument, 0, 'f'},
295                {"loop",            required_argument, 0, 'l'},
296                {0, 0, 0, 0}
297              };
298
299 static void usage(char *name)
300 {
301         char *usage_str =
302         "usage:\n"
303     "    %s [<option>] <command> <parameter string>\n"
304     "  where <option> is one of the following:\n"
305         "    -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
306         "    -f --file <name> .................................. use file <name> for reading or writing data\n"
307         "    --i-am-sure ....................................... do not ask safety question\n"
308         "    -l --loop <value> ................................. execute action <value> times\n"
309         "  <command> is one of the following\n"
310         "    -s --set-rgb <red>:<green>:<blue> ................. set color\n"
311         "    -g --get-rgb ...................................... read color from device and print\n"
312         "    -r --read-mem <addr>:<length> ..................... read RAM\n"
313         "    -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
314         "    -z --read-flash <addr>:<length> ................... read flash\n"
315 /*      "    -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
316         "    -a --read-adc <adc> ............................... read ADC\n" */
317         "    -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
318         "    -b --read-button .................................. read status of button\n"
319         "    -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
320         "    -t --read-temperature ............................. read temperature sensor and output raw value\n"
321         " Please note:\n"
322         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
323         "   depending on if you use short or long options.\n"
324         "   Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
325         "   Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
326         ;
327         fprintf(stderr, usage_str, name);
328 }
329
330
331 int main(int argc, char **argv)
332 {
333   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
334   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
335   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
336   char product[] = {USB_CFG_DEVICE_NAME, 0};
337   int  vid, pid;
338   int  c, option_index;
339   void(*action_fn)(char*) = NULL;
340   char* main_arg = NULL;
341   unsigned exec_loops=(unsigned)-1;
342   usb_init();
343   if(argc < 2){   /* we need at least one argument */
344     usage(argv[0]);
345     exit(1);
346   }
347   /* compute VID/PID from usbconfig.h so that there is a central source of information */
348     vid = rawVid[1] * 256 + rawVid[0];
349     pid = rawPid[1] * 256 + rawPid[0];
350     /* The following function is in opendevice.c: */
351     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
352         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
353         exit(1);
354     }
355
356     for(;;){
357         c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:e",
358                 long_options, &option_index);
359         if(c == -1){
360                 break;
361         }
362
363         if(action_fn && strchr("sgrzwxaqbkte", c)){
364                 /* action given while already having an action */
365                 usage(argv[0]);
366                 exit(1);
367         }
368
369         if(strchr("sgrzwxaqkte", c)){
370                 main_arg = optarg;
371         }
372
373         switch(c){
374         case 's': action_fn = set_dbg; break;
375         case 'g': action_fn = get_dbg; break;
376         case 'r': action_fn = read_mem; break;
377         case 'z': action_fn = read_flash; break;
378         case 'w': action_fn = write_mem; break;
379         case 'q': action_fn = soft_reset; break;
380         case 'b': action_fn = read_button; break;
381         case 'k': action_fn = wait_for_button; break;
382         case 't': action_fn = read_temperature; break;
383         case 'f': fname = optarg; break;
384         case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
385         case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
386         case 'e': action_fn = press_button; break;
387         case 'x':
388         case 'a':
389         default:
390                 break;
391         }
392     }
393
394     if(!action_fn){
395         usage(argv[0]);
396         fprintf(stderr, "Error: no action specified\n");
397         return 1;
398     }else{
399         if(exec_loops==(unsigned)-1){
400                 exec_loops = 1;
401         }
402         while(exec_loops--){
403                 action_fn(main_arg);
404         }
405         usb_close(handle);
406         return 0;
407     }
408
409 }