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/
26 #include <usb.h> /* this is libusb */
27 #include <arpa/inet.h>
29 #include "opendevice.h" /* common code moved to separate module */
31 #include "../../firmware/requests.h" /* custom request numbers */
32 #include "../../firmware/usbconfig.h" /* device's VID/PID and names */
34 int safety_question_override=0;
38 usb_dev_handle *handle = NULL;
40 int8_t hex_to_int(char c) {
42 if (c >= '0' && c <= '9') {
46 if (c >= 'a' && c <= 'f') {
53 void press_button(char* param){
54 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_PRESS_BUTTON, 0, 0, NULL, 0, 5000);
57 void set_dbg(char *hex_string){
58 uint8_t buffer[(strlen(hex_string) + 1) / 2];
59 size_t i = 0, length = 0;
62 memset(buffer, 0, (strlen(hex_string) + 1) / 2);
64 while (hex_string[i]) {
65 t = hex_to_int(hex_string[i]);
70 buffer[length++] |= t;
72 buffer[length] |= t << 4;
76 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_DBG, 0, 0, (char*)buffer, length, 5000);
79 void get_dbg(char* param){
82 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_DBG, 0, 0, (char*)buffer, 256, 5000);
83 printf("DBG-Buffer:\n");
84 hexdump_block(stdout, buffer, 0, cnt, 16);
87 void read_mem(char* param){
89 uint8_t *buffer, *addr;
93 f = fopen(fname, "wb");
95 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
99 sscanf(param, "%i:%i", (int*)&addr, &length);
103 buffer = malloc(length);
107 fprintf(stderr, "ERROR: out of memory\n");
110 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_MEM, (int)((unsigned)addr), 0, (char*)buffer, length, 5000);
114 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
118 cnt = fwrite(buffer, 1, length, f);
121 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
126 hexdump_block(stdout, buffer, addr, length, 8);
130 void write_mem(char* param){
132 uint8_t *addr, *buffer, *data=NULL;
137 f = fopen(fname, "rb");
139 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
143 sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
148 buffer = malloc(length);
152 fprintf(stderr, "ERROR: out of memory\n");
155 memset(buffer, (uint8_t)pad, length);
156 if(!data && !f && length==0){
157 fprintf(stderr, "ERROR: no data to write\n");
161 cnt = fread(buffer, 1, length, f);
163 if(cnt!=length && pad==-1){
164 fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
167 char xbuffer[3]= {0, 0, 0};
170 while(*data && idx<length){
171 while(*data && !isxdigit(*data)){
174 xbuffer[fill++] = *data;
177 t = strtoul(xbuffer, NULL, 16);
184 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_WRITE_MEM, (int)addr, 0, (char*)buffer, length, 5000);
186 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
192 void read_flash(char* param){
194 uint8_t *buffer, *addr;
198 f = fopen(fname, "wb");
200 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
204 sscanf(param, "%i:%i", (int*)&addr, &length);
208 buffer = malloc(length);
212 fprintf(stderr, "ERROR: out of memory\n");
215 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_FLASH, (int)addr, 0, (char*)buffer, length, 5000);
219 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
223 cnt = fwrite(buffer, 1, length, f);
226 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
231 hexdump_block(stdout, buffer, addr, length, 8);
235 void soft_reset(char* param){
238 sscanf(param, "%i", &delay);
241 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
244 void read_button(char* param){
246 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
247 printf("button is %s\n",v?"on":"off");
250 void wait_for_button(char* param){
251 volatile uint8_t v=0, x=1;
253 printf("DBG: having param: %s\n", param);
254 if(!(strcmp(param,"off") && strcmp(param,"0"))){
259 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
261 printf("button is %s\n",v?"on":"off");
264 void read_temperature(char* param){
267 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
268 printf("temperature raw value: %hd 0x%hx\n", v, v);
272 static struct option long_options[] =
274 /* These options set a flag. */
275 {"i-am-sure", no_argument, &safety_question_override, 1},
276 {"pad", optional_argument, 0, 'p'},
277 /* These options don't set a flag.
278 We distinguish them by their indices. */
279 {"set-rgb", required_argument, 0, 's'},
280 {"get-rgb", no_argument, 0, 'g'},
281 {"read-mem", required_argument, 0, 'r'},
282 {"write-mem", required_argument, 0, 'w'},
283 {"read-flash", required_argument, 0, 'z'},
284 {"exec-spm", required_argument, 0, 'x'},
285 {"read-adc", required_argument, 0, 'a'},
286 {"reset", optional_argument, 0, 'q'},
287 {"read-button", required_argument, 0, 'b'},
288 {"wait-for-button", optional_argument, 0, 'k'},
289 {"read-temperature", no_argument, 0, 't'},
290 {"file", required_argument, 0, 'f'},
291 {"loop", required_argument, 0, 'l'},
295 static void usage(char *name)
299 " %s [<option>] <command> <parameter string>\n"
300 " where <option> is one of the following:\n"
301 " -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
302 " -f --file <name> .................................. use file <name> for reading or writing data\n"
303 " --i-am-sure ....................................... do not ask safety question\n"
304 " -l --loop <value> ................................. execute action <value> times\n"
305 " <command> is one of the following\n"
306 " -s --set-rgb <red>:<green>:<blue> ................. set color\n"
307 " -g --get-rgb ...................................... read color from device and print\n"
308 " -r --read-mem <addr>:<length> ..................... read RAM\n"
309 " -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
310 " -z --read-flash <addr>:<length> ................... read flash\n"
311 /* " -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
312 " -a --read-adc <adc> ............................... read ADC\n" */
313 " -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
314 " -b --read-button .................................. read status of button\n"
315 " -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
316 " -t --read-temperature ............................. read temperature sensor and output raw value\n"
318 " If you use optional parameters you have to use two different way to specify the parameter,\n"
319 " depending on if you use short or long options.\n"
320 " Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
321 " Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
323 fprintf(stderr, usage_str, name);
327 int main(int argc, char **argv)
329 const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
330 const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
331 char vendor[] = {USB_CFG_VENDOR_NAME, 0};
332 char product[] = {USB_CFG_DEVICE_NAME, 0};
335 void(*action_fn)(char*) = NULL;
336 char* main_arg = NULL;
337 unsigned exec_loops=(unsigned)-1;
339 if(argc < 2){ /* we need at least one argument */
343 /* compute VID/PID from usbconfig.h so that there is a central source of information */
344 vid = rawVid[1] * 256 + rawVid[0];
345 pid = rawPid[1] * 256 + rawPid[0];
346 /* The following function is in opendevice.c: */
347 if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
348 fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
353 c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:e",
354 long_options, &option_index);
359 if(action_fn && strchr("sgrzwxaqbkte", c)){
360 /* action given while already having an action */
365 if(strchr("sgrzwxaqkte", c)){
370 case 's': action_fn = set_dbg; break;
371 case 'g': action_fn = get_dbg; break;
372 case 'r': action_fn = read_mem; break;
373 case 'z': action_fn = read_flash; break;
374 case 'w': action_fn = write_mem; break;
375 case 'q': action_fn = soft_reset; break;
376 case 'b': action_fn = read_button; break;
377 case 'k': action_fn = wait_for_button; break;
378 case 't': action_fn = read_temperature; break;
379 case 'f': fname = optarg; break;
380 case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
381 case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
382 case 'e': action_fn = press_button; break;
392 fprintf(stderr, "Error: no action specified\n");
395 if(exec_loops==(unsigned)-1){