seems to be working ok
[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         ++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     uint16_t buffer[256];
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, 256, 5000);
197     printf("Secret:\n");
198     hexdump_block(stdout, buffer, 0, cnt, 16);
199 }
200
201
202 static struct option long_options[] =
203              {
204                /* These options don't set a flag.
205                   We distinguish them by their indices. */
206                {"set-secret",        required_argument, NULL, 's'},
207                {"inc-counter",       no_argument,       NULL, 'i'},
208                {"get-counter",       no_argument,       NULL, 'c'},
209                {"reset-counter",     no_argument,       NULL, 'r'},
210                {"get-reset-counter", no_argument,       NULL, 'q'},
211                {"get-digits",        no_argument,       NULL, 'D'},
212                {"set-digits",        required_argument, NULL, 'd'},
213                {"reset",             optional_argument, NULL, 'R'},
214                {"get-token",         no_argument,       NULL, 't'},
215                {"read-button",       no_argument,       NULL, 'b'},
216                {"press-button",      no_argument,       NULL, 'B'},
217                {"get-dbg",           no_argument,       NULL, 'x'},
218                {"set-dbg",           required_argument, NULL, 'y'},
219                {"clr-dbg",           no_argument,       NULL, 'z'},
220                {"get-secret",        no_argument,       NULL, 'S'},
221                {0, 0, 0, 0}
222              };
223
224 static void usage(char *name)
225 {
226         char *usage_str =
227         "usage:\n"
228     "    %s <command> <parameter string>\n"
229         "  <command> is one of the following\n"
230         "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
231         "    -i --inc-counter ............ increment internal counter\n"
232         "    -c --get-counter ............ get current counter value\n"
233         "    -r --reset-counter .......... reset internal counter to zero\n"
234         "    -q --get-reset-counter....... get the times the counter was reseted\n"
235         "    -D --get-digits ............. get the amount of digits per token\n"
236         "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
237     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
238     "    -t --get-token .............. get a token\n\n"
239         "    -b --read-button ............ read status of button\n"
240     "    -B --press-button ........... simulate a button press\n"
241         "    -x --get-dbg ................ get content of the debug register\n"
242     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
243     "    -z --clr-dbg ................ clear the content of the debug register\n"
244     "    -S --get-secret ............. get secret (deactivated for productive devices)\n\n"
245         " Please note:\n"
246         "   If you use optional parameters you have to use two different way to specify the parameter,\n"
247         "   depending on if you use short or long options.\n"
248         "   Short options: You have to put the parameter directly behind the option letter. Exp: -R6\n"
249         "   Long options: You have to seperate the option from the parameter with '='. Exp: --reset=6\n"
250         ;
251         fprintf(stderr, usage_str, name);
252 }
253
254
255 int main(int argc, char **argv)
256 {
257   const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
258   const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
259   char vendor[] = {USB_CFG_VENDOR_NAME, 0};
260   char product[] = {USB_CFG_DEVICE_NAME, 0};
261   int  vid, pid;
262   int  c, option_index;
263   void(*action_fn)(char*) = NULL;
264   char* main_arg = NULL;
265   usb_init();
266   if(argc < 2){   /* we need at least one argument */
267     usage(argv[0]);
268     exit(1);
269   }
270   /* compute VID/PID from usbconfig.h so that there is a central source of information */
271     vid = rawVid[1] * 256 + rawVid[0];
272     pid = rawPid[1] * 256 + rawPid[0];
273     /* The following function is in opendevice.c: */
274     if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
275         fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
276         exit(1);
277     }
278
279     for (;;) {
280         c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:zS", long_options, &option_index);
281         if (c == -1) {
282                 break;
283         }
284
285         if (action_fn && strchr("sicrqDdRtbBxyzS", c)) {
286                 /* action given while already having an action */
287                 usage(argv[0]);
288                 exit(1);
289         }
290
291         if(strchr("sdRy", c)){
292                 main_arg = optarg;
293         }
294 /*
295     "    -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
296     "    -i --inc-counter ............ increment internal counter\n"
297     "    -c --get-counter ............ get current counter value\n"
298     "    -r --reset-counter .......... reset internal counter to zero\n"
299     "    -q --get-reset-counter....... get the times the counter was reseted\n"
300     "    -D --get-digits ............. get the amount of digits per token\n"
301     "    -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
302     "    -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
303     "    -t --get-token .............. get a token\n\n"
304     "    -b --read-button ............ read status of button\n"
305     "    -B --press-button ........... simulate a button press\n"
306     "    -x --get-dbg ................ get content of the debug register\n"
307     "    -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
308     "    -z --clr-dbg ................ clear the content of the debug register\n"
309 */
310         switch (c) {
311         case 's': action_fn = set_secret; break;
312         case 'i': action_fn = inc_counter; break;
313         case 'c': action_fn = get_counter; break;
314         case 'r': action_fn = reset_counter; break;
315         case 'q': action_fn = get_reset_counter; break;
316         case 'D': action_fn = get_digits; break;
317         case 'd': action_fn = set_digits; break;
318         case 'R': action_fn = soft_reset; break;
319         case 't': action_fn = get_token; break;
320         case 'b': action_fn = read_button; break;
321         case 'B': action_fn = press_button; break;
322         case 'y': action_fn = set_dbg; break;
323         case 'x': action_fn = get_dbg; break;
324         case 'z': action_fn = clr_dbg; break;
325         case 'S': action_fn = get_secret; break;
326         default:
327                 break;
328         }
329     }
330
331     if (!action_fn) {
332         usage(argv[0]);
333         fprintf(stderr, "Error: no action specified\n");
334         return 1;
335     } else {
336         action_fn(main_arg);
337         usb_close(handle);
338         return 0;
339     }
340
341 }