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;
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);
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);
119 void get_counter(char *param){
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);
124 printf("internal counter = %"PRId32"\n", counter);
126 fprintf(stderr, "Error: reading %d bytes for counter, expecting 4\n", cnt);
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);
134 void get_reset_counter (char *param){
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);
139 printf("internal reset counter = %"PRId8"\n", counter);
141 fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
145 void get_digits(char *param){
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);
150 printf("digits = %"PRId8"\n", digits);
152 fprintf(stderr, "Error: reading %d bytes for reset counter, expecting 1\n", cnt);
156 void set_digits(char *param){
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");
163 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_SET_DIGITS, d, 0, NULL, 0, 5000);
166 void get_token(char *param){
169 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_TOKEN, 0, 0, token, 9, 5000);
172 printf("token = %s\n", token);
174 fprintf(stderr, "Error: reading %d bytes for token, expecting max. 9\n", cnt);
178 void soft_reset(char* param){
181 sscanf(param, "%i", &delay);
184 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
187 void read_button(char* param){
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);
193 void get_secret(char *param){
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);
198 printf("Secret (%d):\n", cnt);
199 hexdump_block(stdout, buffer, NULL, cnt, 16);
201 fprintf(stderr, "Error: usb_control_msg(...) returned %d\n", cnt);
206 static struct option long_options[] =
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'},
228 static void usage(char *name)
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"
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"
255 fprintf(stderr, usage_str, name);
259 int main(int argc, char **argv)
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};
267 void(*action_fn)(char*) = NULL;
268 char* main_arg = NULL;
270 if(argc < 2){ /* we need at least one argument */
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);
284 c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:zS", long_options, &option_index);
289 if (action_fn && strchr("sicrqDdRtbBxyzS", c)) {
290 /* action given while already having an action */
295 if(strchr("sdRy", c)){
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"
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;
337 fprintf(stderr, "Error: no action specified\n");