8b8b2b09bac3db85bf2286e3382eb2e5bebe5055
[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 <inttypes.h>
25 #include <getopt.h>
26 #include <ctype.h>
27 #include <usb.h>        /* this is libusb */
28 #include <arpa/inet.h>
29 #include "hexdump.h"
30 #include "opendevice.h" /* common code moved to separate module */
31
32 #include "../../firmware/requests.h"   /* custom request numbers */
33 #include "../../firmware/usbconfig.h"  /* device's VID/PID and names */
34
35 int safety_question_override=0;
36 int pad=-1;
37
38 char* fname;
39 usb_dev_handle *handle = NULL;
40
41 int8_t hex_to_int(char c) {
42     int8_t r = -1;
43     if (c >= '0' && c <= '9') {
44         r = c - '0';
45     } else {
46         c |= 'a' ^ 'A';
47         if (c >= 'a' && c <= 'f') {
48             r = 10 + c - 'a';
49         }
50     }
51     return r;
52 }
53
54 void press_button(char *param){
55     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_PRESS_BUTTON, 0, 0, NULL, 0, 5000);
56 }
57
58 void set_dbg(char *hex_string){
59         uint8_t buffer[(strlen(hex_string) + 1) / 2];
60         size_t i = 0, length = 0;
61         int8_t t;
62
63         memset(buffer, 0, (strlen(hex_string) + 1) / 2);
64
65         while (hex_string[i]) {
66             t = hex_to_int(hex_string[i]);
67             if (t == -1){
68                 break;
69             }
70             if (i & 1) {
71                 buffer[length++] |= t;
72             } else {
73                 buffer[length] |= t << 4;
74             }
75         }
76
77         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_DBG, 0, 0, (char*)buffer, length, 5000);
78 }
79
80 void get_dbg(char *param){
81         uint16_t buffer[256];
82         int cnt;
83         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_DBG, 0, 0, (char*)buffer, 256, 5000);
84         printf("DBG-Buffer:\n");
85         hexdump_block(stdout, buffer, 0, cnt, 16);
86 }
87
88 void clr_dbg(char *param){
89     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_CLR_DBG, 0, 0, NULL, 0, 5000);
90 }
91
92 void set_secret(char *hex_string){
93     uint8_t buffer[(strlen(hex_string) + 1) / 2];
94     size_t i = 0, length = 0;
95     int8_t t;
96
97     memset(buffer, 0, (strlen(hex_string) + 1) / 2);
98
99     while (hex_string[i]) {
100         t = hex_to_int(hex_string[i]);
101         if (t == -1){
102             break;
103         }
104         if (i & 1) {
105             buffer[length++] |= t;
106         } else {
107             buffer[length] |= t << 4;
108         }
109     }
110
111     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_SECRET, length * 8, 0, (char*)buffer, length, 5000);
112 }
113
114 void inc_counter(char *param){
115     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_INC_COUNTER, 0, 0, NULL, 0, 5000);
116 }
117
118 void get_counter(char *param){
119     uint32_t counter;
120     int cnt;
121     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_COUNTER, 0, 0, (char*)&counter, 4, 5000);
122     if (cnt == 4) {
123         printf("internal counter = %"PRId32"\n", counter);
124     } else {
125         fprintf(stderr, "Error: reading %d bytes for counter, expecting 4\n", cnt);
126     }
127 }
128
129 void reset_counter(char *param){
130     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET_COUNTER, 0, 0, NULL, 0, 5000);
131 }
132
133 void get_reset_counter (char *param){
134     uint8_t counter;
135     int cnt;
136     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_RESET_COUNTER, 0, 0, (char*)&counter, 1, 5000);
137     if (cnt == 1) {
138         printf("internal reset counter = %"PRId8"\n", counter);
139     } else {
140         fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
141     }
142 }
143
144 void get_digits(char *param){
145     uint8_t digits;
146     int cnt;
147     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_DIGITS, 0, 0, (char*)&digits, 1, 5000);
148     if (cnt == 1) {
149         printf("digits = %"PRId8"\n", digits);
150     } else {
151         fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
152     }
153 }
154
155 void set_digits(char *param){
156     long d;
157     d = strtol(param, NULL, 10);
158     if (d > 9 || d < 6) {
159         fprintf(stderr, "Error: <digits> must be in range 6, 7, 8 or 9\n");
160         return;
161     }
162     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_SET_DIGITS, d, 0, NULL, 0, 5000);
163 }
164
165 void get_token(char *param){
166     char token[10];
167     int cnt;
168     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_TOKEN, 0, 0, token, 9, 5000);
169     if (cnt < 9 ) {
170         token[cnt] = '\0';
171         printf("token = %s\n", token);
172     } else {
173         fprintf(stderr, "Error: reading %d bytes for token, expecting max. 9\n", cnt);
174     }
175 }
176
177 void read_mem(char* param){
178         int length=0;
179         uint8_t *buffer, *addr;
180         int cnt;
181         FILE* f=NULL;
182         if(fname){
183                 f = fopen(fname, "wb");
184                 if(!f){
185                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
186                         exit(1);
187                 }
188         }
189         sscanf(param, "%i:%i", (int*)&addr, &length);
190         if(length<=0){
191                 return;
192         }
193         buffer = malloc(length);
194         if(!buffer){
195                 if(f)
196                         fclose(f);
197                 fprintf(stderr, "ERROR: out of memory\n");
198                 exit(1);
199         }
200         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);
201         if(cnt!=length){
202                 if(f)
203                         fclose(f);
204                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
205                 exit(1);
206         }
207         if(f){
208                 cnt = fwrite(buffer, 1, length, f);
209                 fclose(f);
210                 if(cnt!=length){
211                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
212                         exit(1);
213                 }
214
215         }else{
216                 hexdump_block(stdout, buffer, addr, length, 8);
217         }
218 }
219
220 void write_mem(char* param){
221         int length;
222         uint8_t *addr, *buffer, *data=NULL;
223         int cnt=0;
224         FILE* f=NULL;
225
226         if(fname){
227                 f = fopen(fname, "rb");
228                 if(!f){
229                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
230                         exit(1);
231                 }
232         }
233         sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
234         data += cnt;
235         if(length<=0){
236                 return;
237         }
238         buffer = malloc(length);
239         if(!buffer){
240                 if(f)
241                         fclose(f);
242                 fprintf(stderr, "ERROR: out of memory\n");
243                 exit(1);
244         }
245         memset(buffer, (uint8_t)pad, length);
246         if(!data && !f && length==0){
247                 fprintf(stderr, "ERROR: no data to write\n");
248                 exit(1);
249         }
250         if(f){
251                 cnt = fread(buffer, 1, length, f);
252                 fclose(f);
253                 if(cnt!=length && pad==-1){
254                         fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
255                 }
256         }else if(data){
257                 char xbuffer[3]= {0, 0, 0};
258                 uint8_t fill=0;
259                 unsigned idx=0;
260                 while(*data && idx<length){
261                         while(*data && !isxdigit(*data)){
262                                 ++data;
263                         }
264                         xbuffer[fill++] = *data;
265                         if(fill==2){
266                                 uint8_t t;
267                                 t = strtoul(xbuffer, NULL, 16);
268                                 buffer[idx++] = t;
269                                 fill = 0;
270                         }
271                 }
272
273         }
274         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);
275         if(cnt!=length){
276                 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
277                 exit(1);
278         }
279
280 }
281
282 void read_flash(char* param) {
283         int length=0;
284         uint8_t *buffer, *addr;
285         int cnt;
286         FILE* f=NULL;
287         if (fname) {
288                 f = fopen(fname, "wb");
289                 if (!f) {
290                         fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
291                         exit(1);
292                 }
293         }
294         sscanf(param, "%i:%i", (int*)&addr, &length);
295         if (length <= 0){
296                 return;
297         }
298         buffer = malloc(length);
299         if (!buffer) {
300                 if (f)
301                         fclose(f);
302                 fprintf(stderr, "ERROR: out of memory\n");
303                 exit(1);
304         }
305         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);
306         if (cnt != length){
307                 if (f)
308                         fclose(f);
309                 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
310                 exit(1);
311         }
312         if (f) {
313                 cnt = fwrite(buffer, 1, length, f);
314                 fclose(f);
315                 if (cnt != length) {
316                         fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
317                         exit(1);
318                 }
319
320         } else {
321                 hexdump_block(stdout, buffer, addr, length, 8);
322         }
323 }
324
325 void soft_reset(char* param){
326         unsigned delay = 0;
327         if (param) {
328                 sscanf(param, "%i", &delay);
329         }
330         delay &= 0xf;
331         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
332 }
333
334 void read_button(char* param){
335         uint8_t v;
336         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
337         printf("button is %s\n",v?"on":"off");
338 }
339
340 void wait_for_button(char* param){
341         volatile uint8_t v = 0, x = 1;
342         if(param){
343                 printf("DBG: having param: %s\n", param);
344                 if (!(strcmp(param,"off") && strcmp(param,"0"))) {
345                         x = 0;
346                 }
347         }
348         do{
349                 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
350         }while(x!=v);
351         printf("button is %s\n",v?"on":"off");
352 }
353
354 void read_temperature(char* param){
355         uint16_t v;
356         int cnt;
357         cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
358         if (cnt == 2) {
359             printf("temperature raw value: %hd 0x%hx\n", v, v);
360         } else {
361         fprintf(stderr, "Error: reading %d bytes for temperature, expecting 2\n", cnt);
362         }
363 }
364
365
366 static struct option long_options[] =
367              {
368                /* These options don't set a flag.
369                   We distinguish them by their indices. */
370                {"set-secret",        required_argument, NULL, 's'},
371                {"inc-counter",       no_argument,       NULL, 'i'},
372                {"get-counter",       no_argument,       NULL, 'c'},
373                {"reset-counter",     no_argument,       NULL, 'r'},
374                {"get-reset-counter", no_argument,       NULL, 'q'},
375                {"get-digits",        no_argument,       NULL, 'D'},
376                {"set-digits",        required_argument, NULL, 'd'},
377                {"reset",             optional_argument, NULL, 'R'},
378                {"get-token",         no_argument,       NULL, 't'},
379                {"read-button",       no_argument,       NULL, 'b'},
380                {"press-button",      no_argument,       NULL, 'B'},
381                {"get-dbg",           no_argument,       NULL, 'x'},
382                {"set-dbg",           required_argument, NULL, 'y'},
383                {"clr-dbg",           no_argument,       NULL, 'z'},
384                {0, 0, 0, 0}
385              };
386
387 static void usage(char *name)
388 {
389         char *usage_str =
390         "usage:\n"
391     "    %s <command> <parameter string>\n"
392         "  <command> is one of the following\n"
393         "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
394         "    -i --inc-counter ............ increment internal counter\n"
395         "    -c --get-counter ............ get current counter value\n"
396         "    -r --reset-counter .......... reset internal counter to zero\n"
397         "    -q --get-reset-counter....... get the times the counter was reseted\n"
398         "    -D --get-digits ............. get the amount of digits per token\n"
399         "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
400     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
401     "    -t --get-token .............. get a token\n\n"
402         "    -b --read-button ............ read status of button\n"
403     "    -B --press-button ........... simulate a button press\n"
404         "    -x --get-dbg ................ get content of the debug register\n"
405     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
406     "    -z --clr-dbg ................ clear the content of the debug register\n"
407
408         " Please note:\n"
409         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
410         "   depending on if you use short or long options.\n"
411         "   Short options: You have to put the parameter directly behind the option letter. Exp: -R6\n"
412         "   Long options: You have to seperate the option from the parameter with '='. Exp: --reset=6\n"
413         ;
414         fprintf(stderr, usage_str, name);
415 }
416
417
418 int main(int argc, char **argv)
419 {
420   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
421   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
422   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
423   char product[] = {USB_CFG_DEVICE_NAME, 0};
424   int  vid, pid;
425   int  c, option_index;
426   void(*action_fn)(char*) = NULL;
427   char* main_arg = NULL;
428   usb_init();
429   if(argc < 2){   /* we need at least one argument */
430     usage(argv[0]);
431     exit(1);
432   }
433   /* compute VID/PID from usbconfig.h so that there is a central source of information */
434     vid = rawVid[1] * 256 + rawVid[0];
435     pid = rawPid[1] * 256 + rawPid[0];
436     /* The following function is in opendevice.c: */
437     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
438         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
439         exit(1);
440     }
441
442     for (;;) {
443         c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:z", long_options, &option_index);
444         if (c == -1) {
445                 break;
446         }
447
448         if (action_fn && strchr("sicrqDdRtbBxyz", c)) {
449                 /* action given while already having an action */
450                 usage(argv[0]);
451                 exit(1);
452         }
453
454         if(strchr("sdRy", c)){
455                 main_arg = optarg;
456         }
457 /*
458     "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
459     "    -i --inc-counter ............ increment internal counter\n"
460     "    -c --get-counter ............ get current counter value\n"
461     "    -r --reset-counter .......... reset internal counter to zero\n"
462     "    -q --get-reset-counter....... get the times the counter was reseted\n"
463     "    -D --get-digits ............. get the amount of digits per token\n"
464     "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
465     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
466     "    -t --get-token .............. get a token\n\n"
467     "    -b --read-button ............ read status of button\n"
468     "    -B --press-button ........... simulate a button press\n"
469     "    -x --get-dbg ................ get content of the debug register\n"
470     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
471     "    -z --clr-dbg ................ clear the content of the debug register\n"
472 */
473         switch (c) {
474         case 's': action_fn = set_secret; break;
475         case 'i': action_fn = inc_counter; break;
476         case 'c': action_fn = get_counter; break;
477         case 'r': action_fn = reset_counter; break;
478         case 'q': action_fn = get_reset_counter; break;
479         case 'D': action_fn = get_digits; break;
480         case 'd': action_fn = set_digits; break;
481         case 'R': action_fn = soft_reset; break;
482         case 't': action_fn = get_token; break;
483         case 'b': action_fn = read_button; break;
484         case 'B': action_fn = press_button; break;
485         case 'y': action_fn = set_dbg; break;
486         case 'x': action_fn = get_dbg; break;
487         case 'z': action_fn = clr_dbg; break;
488         default:
489                 break;
490         }
491     }
492
493     if (!action_fn) {
494         usage(argv[0]);
495         fprintf(stderr, "Error: no action specified\n");
496         return 1;
497     } else {
498         action_fn(main_arg);
499         usb_close(handle);
500         return 0;
501     }
502
503 }