2 * Project: hid-custom-rq example
3 * Author: Christian Starkjohann
4 * Creation Date: 2008-04-10
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 $
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
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/
27 #include <usb.h> /* this is libusb */
28 #include <arpa/inet.h>
30 #include "opendevice.h" /* common code moved to separate module */
32 #include "../../firmware/requests.h" /* custom request numbers */
33 #include "../../firmware/usbconfig.h" /* device's VID/PID and names */
35 int safety_question_override=0;
39 usb_dev_handle *handle = NULL;
41 int8_t hex_to_int(char c) {
43 if (c >= '0' && c <= '9') {
47 if (c >= 'a' && c <= 'f') {
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);
58 void set_dbg(char *hex_string){
59 uint8_t buffer[(strlen(hex_string) + 1) / 2];
60 size_t i = 0, length = 0;
63 memset(buffer, 0, (strlen(hex_string) + 1) / 2);
65 while (hex_string[i]) {
66 t = hex_to_int(hex_string[i]);
71 buffer[length++] |= t;
73 buffer[length] |= t << 4;
77 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_DBG, 0, 0, (char*)buffer, length, 5000);
80 void get_dbg(char *param){
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);
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);
92 void set_secret(char *hex_string){
93 uint8_t buffer[(strlen(hex_string) + 1) / 2];
94 size_t i = 0, length = 0;
97 memset(buffer, 0, (strlen(hex_string) + 1) / 2);
99 while (hex_string[i]) {
100 t = hex_to_int(hex_string[i]);
105 buffer[length++] |= t;
107 buffer[length] |= t << 4;
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);
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);
118 void get_counter(char *param){
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);
123 printf("internal counter = %"PRId32"\n", counter);
125 fprintf(stderr, "Error: reading %d bytes for counter, expecting 4\n", cnt);
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);
133 void get_reset_counter (char *param){
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);
138 printf("internal reset counter = %"PRId8"\n", counter);
140 fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
144 void get_digits(char *param){
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);
149 printf("digits = %"PRId8"\n", digits);
151 fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
155 void set_digits(char *param){
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");
162 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_SET_DIGITS, d, 0, NULL, 0, 5000);
165 void get_token(char *param){
168 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_TOKEN, 0, 0, token, 9, 5000);
171 printf("token = %s\n", token);
173 fprintf(stderr, "Error: reading %d bytes for token, expecting max. 9\n", cnt);
177 void read_mem(char* param){
179 uint8_t *buffer, *addr;
183 f = fopen(fname, "wb");
185 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
189 sscanf(param, "%i:%i", (int*)&addr, &length);
193 buffer = malloc(length);
197 fprintf(stderr, "ERROR: out of memory\n");
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);
204 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
208 cnt = fwrite(buffer, 1, length, f);
211 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
216 hexdump_block(stdout, buffer, addr, length, 8);
220 void write_mem(char* param){
222 uint8_t *addr, *buffer, *data=NULL;
227 f = fopen(fname, "rb");
229 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
233 sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
238 buffer = malloc(length);
242 fprintf(stderr, "ERROR: out of memory\n");
245 memset(buffer, (uint8_t)pad, length);
246 if(!data && !f && length==0){
247 fprintf(stderr, "ERROR: no data to write\n");
251 cnt = fread(buffer, 1, length, f);
253 if(cnt!=length && pad==-1){
254 fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
257 char xbuffer[3]= {0, 0, 0};
260 while(*data && idx<length){
261 while(*data && !isxdigit(*data)){
264 xbuffer[fill++] = *data;
267 t = strtoul(xbuffer, NULL, 16);
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);
276 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
282 void read_flash(char* param) {
284 uint8_t *buffer, *addr;
288 f = fopen(fname, "wb");
290 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
294 sscanf(param, "%i:%i", (int*)&addr, &length);
298 buffer = malloc(length);
302 fprintf(stderr, "ERROR: out of memory\n");
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);
309 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
313 cnt = fwrite(buffer, 1, length, f);
316 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
321 hexdump_block(stdout, buffer, addr, length, 8);
325 void soft_reset(char* param){
328 sscanf(param, "%i", &delay);
331 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
334 void read_button(char* param){
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");
340 void wait_for_button(char* param){
341 volatile uint8_t v = 0, x = 1;
343 printf("DBG: having param: %s\n", param);
344 if (!(strcmp(param,"off") && strcmp(param,"0"))) {
349 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
351 printf("button is %s\n",v?"on":"off");
354 void read_temperature(char* param){
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);
359 printf("temperature raw value: %hd 0x%hx\n", v, v);
361 fprintf(stderr, "Error: reading %d bytes for temperature, expecting 2\n", cnt);
366 static struct option long_options[] =
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'},
387 static void usage(char *name)
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"
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"
414 fprintf(stderr, usage_str, name);
418 int main(int argc, char **argv)
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};
426 void(*action_fn)(char*) = NULL;
427 char* main_arg = NULL;
429 if(argc < 2){ /* we need at least one argument */
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);
443 c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:z", long_options, &option_index);
448 if (action_fn && strchr("sicrqDdRtbBxyz", c)) {
449 /* action given while already having an action */
454 if(strchr("sdRy", c)){
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"
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;
495 fprintf(stderr, "Error: no action specified\n");