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 soft_reset(char* param){
180 sscanf(param, "%i", &delay);
183 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
186 void read_button(char* param){
188 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
189 printf("button is %s\n",v?"on":"off");
192 static struct option long_options[] =
194 /* These options don't set a flag.
195 We distinguish them by their indices. */
196 {"set-secret", required_argument, NULL, 's'},
197 {"inc-counter", no_argument, NULL, 'i'},
198 {"get-counter", no_argument, NULL, 'c'},
199 {"reset-counter", no_argument, NULL, 'r'},
200 {"get-reset-counter", no_argument, NULL, 'q'},
201 {"get-digits", no_argument, NULL, 'D'},
202 {"set-digits", required_argument, NULL, 'd'},
203 {"reset", optional_argument, NULL, 'R'},
204 {"get-token", no_argument, NULL, 't'},
205 {"read-button", no_argument, NULL, 'b'},
206 {"press-button", no_argument, NULL, 'B'},
207 {"get-dbg", no_argument, NULL, 'x'},
208 {"set-dbg", required_argument, NULL, 'y'},
209 {"clr-dbg", no_argument, NULL, 'z'},
213 static void usage(char *name)
217 " %s <command> <parameter string>\n"
218 " <command> is one of the following\n"
219 " -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
220 " -i --inc-counter ............ increment internal counter\n"
221 " -c --get-counter ............ get current counter value\n"
222 " -r --reset-counter .......... reset internal counter to zero\n"
223 " -q --get-reset-counter....... get the times the counter was reseted\n"
224 " -D --get-digits ............. get the amount of digits per token\n"
225 " -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
226 " -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
227 " -t --get-token .............. get a token\n\n"
228 " -b --read-button ............ read status of button\n"
229 " -B --press-button ........... simulate a button press\n"
230 " -x --get-dbg ................ get content of the debug register\n"
231 " -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
232 " -z --clr-dbg ................ clear the content of the debug register\n"
235 " If you use optional parameters you have to use two different way to specify the parameter,\n"
236 " depending on if you use short or long options.\n"
237 " Short options: You have to put the parameter directly behind the option letter. Exp: -R6\n"
238 " Long options: You have to seperate the option from the parameter with '='. Exp: --reset=6\n"
240 fprintf(stderr, usage_str, name);
244 int main(int argc, char **argv)
246 const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
247 const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
248 char vendor[] = {USB_CFG_VENDOR_NAME, 0};
249 char product[] = {USB_CFG_DEVICE_NAME, 0};
252 void(*action_fn)(char*) = NULL;
253 char* main_arg = NULL;
255 if(argc < 2){ /* we need at least one argument */
259 /* compute VID/PID from usbconfig.h so that there is a central source of information */
260 vid = rawVid[1] * 256 + rawVid[0];
261 pid = rawPid[1] * 256 + rawPid[0];
262 /* The following function is in opendevice.c: */
263 if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
264 fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
269 c = getopt_long(argc, argv, "s:icrqDd:R::tbBxy:z", long_options, &option_index);
274 if (action_fn && strchr("sicrqDdRtbBxyz", c)) {
275 /* action given while already having an action */
280 if(strchr("sdRy", c)){
284 " -s --set-secret <secret> .... set secret (<secret> is a byte sequence in hex)\n"
285 " -i --inc-counter ............ increment internal counter\n"
286 " -c --get-counter ............ get current counter value\n"
287 " -r --reset-counter .......... reset internal counter to zero\n"
288 " -q --get-reset-counter....... get the times the counter was reseted\n"
289 " -D --get-digits ............. get the amount of digits per token\n"
290 " -d --set-digits <digits>..... set the amount of digits per token (in range 6..9)\n"
291 " -R --reset[=<delay>] ........ reset the controller with delay (in range 0..9)\n"
292 " -t --get-token .............. get a token\n\n"
293 " -b --read-button ............ read status of button\n"
294 " -B --press-button ........... simulate a button press\n"
295 " -x --get-dbg ................ get content of the debug register\n"
296 " -y --set-dbg <data>.......... set content of the debug register (<data> is a byte squence in hex of max. 8 bytes)\n"
297 " -z --clr-dbg ................ clear the content of the debug register\n"
300 case 's': action_fn = set_secret; break;
301 case 'i': action_fn = inc_counter; break;
302 case 'c': action_fn = get_counter; break;
303 case 'r': action_fn = reset_counter; break;
304 case 'q': action_fn = get_reset_counter; break;
305 case 'D': action_fn = get_digits; break;
306 case 'd': action_fn = set_digits; break;
307 case 'R': action_fn = soft_reset; break;
308 case 't': action_fn = get_token; break;
309 case 'b': action_fn = read_button; break;
310 case 'B': action_fn = press_button; break;
311 case 'y': action_fn = set_dbg; break;
312 case 'x': action_fn = get_dbg; break;
313 case 'z': action_fn = clr_dbg; break;
321 fprintf(stderr, "Error: no action specified\n");