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){
194 uint16_t buffer[256];
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);
198 hexdump_block(stdout, buffer, 0, cnt, 16);
202 static struct option long_options[] =
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'},
224 static void usage(char *name)
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"
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"
251 fprintf(stderr, usage_str, name);
255 int main(int argc, char **argv)
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};
263 void(*action_fn)(char*) = NULL;
264 char* main_arg = NULL;
266 if(argc < 2){ /* we need at least one argument */
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);
280 c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:zS", long_options, &option_index);
285 if (action_fn && strchr("sicrqDdRtbBxyzS", c)) {
286 /* action given while already having an action */
291 if(strchr("sdRy", c)){
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"
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;
333 fprintf(stderr, "Error: no action specified\n");