small bug-fix
[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         uint8_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         ++i;
110     }
111
112     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_SECRET, length * 8, 0, (char*)buffer, length, 5000);
113 }
114
115 void inc_counter(char *param){
116     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_INC_COUNTER, 0, 0, NULL, 0, 5000);
117 }
118
119 void get_counter(char *param){
120     uint32_t counter;
121     int cnt;
122     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_COUNTER, 0, 0, (char*)&counter, 4, 5000);
123     if (cnt == 4) {
124         printf("internal counter = %"PRId32"\n", counter);
125     } else {
126         fprintf(stderr, "Error: reading %d bytes for counter, expecting 4\n", cnt);
127     }
128 }
129
130 void reset_counter(char *param){
131     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET_COUNTER, 0, 0, NULL, 0, 5000);
132 }
133
134 void get_reset_counter (char *param){
135     uint8_t counter;
136     int cnt;
137     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);
138     if (cnt == 1) {
139         printf("internal reset counter = %"PRId8"\n", counter);
140     } else {
141         fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
142     }
143 }
144
145 void get_digits(char *param){
146     uint8_t digits;
147     int cnt;
148     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_DIGITS, 0, 0, (char*)&digits, 1, 5000);
149     if (cnt == 1) {
150         printf("digits = %"PRId8"\n", digits);
151     } else {
152         fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
153     }
154 }
155
156 void set_digits(char *param){
157     long d;
158     d = strtol(param, NULL, 10);
159     if (d > 9 || d < 6) {
160         fprintf(stderr, "Error: <digits> must be in range 6, 7, 8 or 9\n");
161         return;
162     }
163     usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_SET_DIGITS, d, 0, NULL, 0, 5000);
164 }
165
166 void get_token(char *param){
167     char token[10];
168     int cnt;
169     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_TOKEN, 0, 0, token, 9, 5000);
170     if (cnt <= 9 ) {
171         token[cnt] = '\0';
172         printf("token = %s\n", token);
173     } else {
174         fprintf(stderr, "Error: reading %d bytes for token, expecting max. 9\n", cnt);
175     }
176 }
177
178 void soft_reset(char* param){
179         unsigned delay = 0;
180         if (param) {
181                 sscanf(param, "%i", &delay);
182         }
183         delay &= 0xf;
184         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
185 }
186
187 void read_button(char* param){
188         int8_t v;
189         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
190         printf("button is %s (%"PRId8")\n", v ? "on" : "off", v);
191 }
192
193 void get_secret(char *param){
194     uint8_t buffer[64];
195     int cnt;
196     cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_SECRET, 0, 0, (char*)buffer, 32, 5000);
197     if (cnt > 0) {
198     printf("Secret (%d):\n", cnt);
199     hexdump_block(stdout, buffer, NULL, cnt, 16);
200     } else {
201         fprintf(stderr, "Error: usb_control_msg(...) returned %d\n", cnt);
202     }
203 }
204
205
206 static struct option long_options[] =
207              {
208                /* These options don't set a flag.
209                   We distinguish them by their indices. */
210                {"set-secret",        required_argument, NULL, 's'},
211                {"inc-counter",       no_argument,       NULL, 'i'},
212                {"get-counter",       no_argument,       NULL, 'c'},
213                {"reset-counter",     no_argument,       NULL, 'r'},
214                {"get-reset-counter", no_argument,       NULL, 'q'},
215                {"get-digits",        no_argument,       NULL, 'D'},
216                {"set-digits",        required_argument, NULL, 'd'},
217                {"reset",             optional_argument, NULL, 'R'},
218                {"get-token",         no_argument,       NULL, 't'},
219                {"read-button",       no_argument,       NULL, 'b'},
220                {"press-button",      no_argument,       NULL, 'B'},
221                {"get-dbg",           no_argument,       NULL, 'x'},
222                {"set-dbg",           required_argument, NULL, 'y'},
223                {"clr-dbg",           no_argument,       NULL, 'z'},
224                {"get-secret",        no_argument,       NULL, 'S'},
225                {0, 0, 0, 0}
226              };
227
228 static void usage(char *name)
229 {
230         char *usage_str =
231         "usage:\n"
232     "    %s <command> <parameter string>\n"
233         "  <command> is one of the following\n"
234         "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
235         "    -i --inc-counter ............ increment internal counter\n"
236         "    -c --get-counter ............ get current counter value\n"
237         "    -r --reset-counter .......... reset internal counter to zero\n"
238         "    -q --get-reset-counter....... get the times the counter was reseted\n"
239         "    -D --get-digits ............. get the amount of digits per token\n"
240         "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
241     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
242     "    -t --get-token .............. get a token\n\n"
243         "    -b --read-button ............ read status of button\n"
244     "    -B --press-button ........... simulate a button press\n"
245         "    -x --get-dbg ................ get content of the debug register\n"
246     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
247     "    -z --clr-dbg ................ clear the content of the debug register\n"
248     "    -S --get-secret ............. get secret (deactivated for productive devices)\n\n"
249         " Please note:\n"
250         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
251         "   depending on if you use short or long options.\n"
252         "   Short options: You have to put the parameter directly behind the option letter. Exp: -R6\n"
253         "   Long options: You have to seperate the option from the parameter with '='. Exp: --reset=6\n"
254         ;
255         fprintf(stderr, usage_str, name);
256 }
257
258
259 int main(int argc, char **argv)
260 {
261   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
262   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
263   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
264   char product[] = {USB_CFG_DEVICE_NAME, 0};
265   int  vid, pid;
266   int  c, option_index;
267   void(*action_fn)(char*) = NULL;
268   char* main_arg = NULL;
269   usb_init();
270   if(argc < 2){   /* we need at least one argument */
271     usage(argv[0]);
272     exit(1);
273   }
274   /* compute VID/PID from usbconfig.h so that there is a central source of information */
275     vid = rawVid[1] * 256 + rawVid[0];
276     pid = rawPid[1] * 256 + rawPid[0];
277     /* The following function is in opendevice.c: */
278     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
279         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
280         exit(1);
281     }
282
283     for (;;) {
284         c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:zS", long_options, &option_index);
285         if (c == -1) {
286                 break;
287         }
288
289         if (action_fn && strchr("sicrqDdRtbBxyzS", c)) {
290                 /* action given while already having an action */
291                 usage(argv[0]);
292                 exit(1);
293         }
294
295         if(strchr("sdRy", c)){
296                 main_arg = optarg;
297         }
298 /*
299     "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
300     "    -i --inc-counter ............ increment internal counter\n"
301     "    -c --get-counter ............ get current counter value\n"
302     "    -r --reset-counter .......... reset internal counter to zero\n"
303     "    -q --get-reset-counter....... get the times the counter was reseted\n"
304     "    -D --get-digits ............. get the amount of digits per token\n"
305     "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
306     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
307     "    -t --get-token .............. get a token\n\n"
308     "    -b --read-button ............ read status of button\n"
309     "    -B --press-button ........... simulate a button press\n"
310     "    -x --get-dbg ................ get content of the debug register\n"
311     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
312     "    -z --clr-dbg ................ clear the content of the debug register\n"
313 */
314         switch (c) {
315         case 's': action_fn = set_secret; break;
316         case 'i': action_fn = inc_counter; break;
317         case 'c': action_fn = get_counter; break;
318         case 'r': action_fn = reset_counter; break;
319         case 'q': action_fn = get_reset_counter; break;
320         case 'D': action_fn = get_digits; break;
321         case 'd': action_fn = set_digits; break;
322         case 'R': action_fn = soft_reset; break;
323         case 't': action_fn = get_token; break;
324         case 'b': action_fn = read_button; break;
325         case 'B': action_fn = press_button; break;
326         case 'y': action_fn = set_dbg; break;
327         case 'x': action_fn = get_dbg; break;
328         case 'z': action_fn = clr_dbg; break;
329         case 'S': action_fn = get_secret; break;
330         default:
331                 break;
332         }
333     }
334
335     if (!action_fn) {
336         usage(argv[0]);
337         fprintf(stderr, "Error: no action specified\n");
338         return 1;
339     } else {
340         action_fn(main_arg);
341         usb_close(handle);
342         return 0;
343     }
344
345 }