ffffc606a87de162ec86737bc7031f631e7e53ac
[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, (int)((unsigned)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, (int)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, (int)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         printf("temperature raw value: %hd 0x%hx\n", v, v);
269 }
270
271
272 static struct option long_options[] =
273              {
274                /* These options set a flag. */
275                {"i-am-sure",       no_argument, &safety_question_override, 1},
276                {"pad",             optional_argument, 0, 'p'},
277                /* These options don't set a flag.
278                   We distinguish them by their indices. */
279                {"set-rgb",         required_argument, 0, 's'},
280                {"get-rgb",               no_argument, 0, 'g'},
281                {"read-mem",        required_argument, 0, 'r'},
282                {"write-mem",       required_argument, 0, 'w'},
283                {"read-flash",      required_argument, 0, 'z'},
284                {"exec-spm",        required_argument, 0, 'x'},
285                {"read-adc",        required_argument, 0, 'a'},
286                {"reset",           optional_argument, 0, 'q'},
287                {"read-button",     required_argument, 0, 'b'},
288                {"wait-for-button", optional_argument, 0, 'k'},
289                {"read-temperature",      no_argument, 0, 't'},
290                {"file",            required_argument, 0, 'f'},
291                {"loop",            required_argument, 0, 'l'},
292                {0, 0, 0, 0}
293              };
294
295 static void usage(char *name)
296 {
297         char *usage_str =
298         "usage:\n"
299     "    %s [<option>] <command> <parameter string>\n"
300     "  where <option> is one of the following:\n"
301         "    -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
302         "    -f --file <name> .................................. use file <name> for reading or writing data\n"
303         "    --i-am-sure ....................................... do not ask safety question\n"
304         "    -l --loop <value> ................................. execute action <value> times\n"
305         "  <command> is one of the following\n"
306         "    -s --set-rgb <red>:<green>:<blue> ................. set color\n"
307         "    -g --get-rgb ...................................... read color from device and print\n"
308         "    -r --read-mem <addr>:<length> ..................... read RAM\n"
309         "    -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
310         "    -z --read-flash <addr>:<length> ................... read flash\n"
311 /*      "    -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
312         "    -a --read-adc <adc> ............................... read ADC\n" */
313         "    -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
314         "    -b --read-button .................................. read status of button\n"
315         "    -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
316         "    -t --read-temperature ............................. read temperature sensor and output raw value\n"
317         " Please note:\n"
318         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
319         "   depending on if you use short or long options.\n"
320         "   Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
321         "   Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
322         ;
323         fprintf(stderr, usage_str, name);
324 }
325
326
327 int main(int argc, char **argv)
328 {
329   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
330   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
331   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
332   char product[] = {USB_CFG_DEVICE_NAME, 0};
333   int  vid, pid;
334   int  c, option_index;
335   void(*action_fn)(char*) = NULL;
336   char* main_arg = NULL;
337   unsigned exec_loops=(unsigned)-1;
338   usb_init();
339   if(argc < 2){   /* we need at least one argument */
340     usage(argv[0]);
341     exit(1);
342   }
343   /* compute VID/PID from usbconfig.h so that there is a central source of information */
344     vid = rawVid[1] * 256 + rawVid[0];
345     pid = rawPid[1] * 256 + rawPid[0];
346     /* The following function is in opendevice.c: */
347     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
348         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
349         exit(1);
350     }
351
352     for(;;){
353         c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:e",
354                 long_options, &option_index);
355         if(c == -1){
356                 break;
357         }
358
359         if(action_fn && strchr("sgrzwxaqbkte", c)){
360                 /* action given while already having an action */
361                 usage(argv[0]);
362                 exit(1);
363         }
364
365         if(strchr("sgrzwxaqkte", c)){
366                 main_arg = optarg;
367         }
368
369         switch(c){
370         case 's': action_fn = set_dbg; break;
371         case 'g': action_fn = get_dbg; break;
372         case 'r': action_fn = read_mem; break;
373         case 'z': action_fn = read_flash; break;
374         case 'w': action_fn = write_mem; break;
375         case 'q': action_fn = soft_reset; break;
376         case 'b': action_fn = read_button; break;
377         case 'k': action_fn = wait_for_button; break;
378         case 't': action_fn = read_temperature; break;
379         case 'f': fname = optarg; break;
380         case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
381         case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
382         case 'e': action_fn = press_button; break;
383         case 'x':
384         case 'a':
385         default:
386                 break;
387         }
388     }
389
390     if(!action_fn){
391         usage(argv[0]);
392         fprintf(stderr, "Error: no action specified\n");
393         return 1;
394     }else{
395         if(exec_loops==(unsigned)-1){
396                 exec_loops = 1;
397         }
398         while(exec_loops--){
399                 action_fn(main_arg);
400         }
401         usb_close(handle);
402         return 0;
403     }
404
405 }