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, (intptr_t)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, (intptr_t)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, (intptr_t)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);
269 printf("temperature raw value: %hd 0x%hx\n", v, v);
271 fprintf(stderr, "Error: reading %d bytes for temperature, expecting 2\n", cnt);
276 static struct option long_options[] =
278 /* These options set a flag. */
279 {"i-am-sure", no_argument, &safety_question_override, 1},
280 {"pad", optional_argument, 0, 'p'},
281 /* These options don't set a flag.
282 We distinguish them by their indices. */
283 {"set-rgb", required_argument, 0, 's'},
284 {"get-rgb", no_argument, 0, 'g'},
285 {"read-mem", required_argument, 0, 'r'},
286 {"write-mem", required_argument, 0, 'w'},
287 {"read-flash", required_argument, 0, 'z'},
288 {"exec-spm", required_argument, 0, 'x'},
289 {"read-adc", required_argument, 0, 'a'},
290 {"reset", optional_argument, 0, 'q'},
291 {"read-button", required_argument, 0, 'b'},
292 {"wait-for-button", optional_argument, 0, 'k'},
293 {"read-temperature", no_argument, 0, 't'},
294 {"file", required_argument, 0, 'f'},
295 {"loop", required_argument, 0, 'l'},
299 static void usage(char *name)
303 " %s [<option>] <command> <parameter string>\n"
304 " where <option> is one of the following:\n"
305 " -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
306 " -f --file <name> .................................. use file <name> for reading or writing data\n"
307 " --i-am-sure ....................................... do not ask safety question\n"
308 " -l --loop <value> ................................. execute action <value> times\n"
309 " <command> is one of the following\n"
310 " -s --set-rgb <red>:<green>:<blue> ................. set color\n"
311 " -g --get-rgb ...................................... read color from device and print\n"
312 " -r --read-mem <addr>:<length> ..................... read RAM\n"
313 " -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
314 " -z --read-flash <addr>:<length> ................... read flash\n"
315 /* " -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
316 " -a --read-adc <adc> ............................... read ADC\n" */
317 " -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
318 " -b --read-button .................................. read status of button\n"
319 " -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
320 " -t --read-temperature ............................. read temperature sensor and output raw value\n"
322 " If you use optional parameters you have to use two different way to specify the parameter,\n"
323 " depending on if you use short or long options.\n"
324 " Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
325 " Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
327 fprintf(stderr, usage_str, name);
331 int main(int argc, char **argv)
333 const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
334 const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
335 char vendor[] = {USB_CFG_VENDOR_NAME, 0};
336 char product[] = {USB_CFG_DEVICE_NAME, 0};
339 void(*action_fn)(char*) = NULL;
340 char* main_arg = NULL;
341 unsigned exec_loops=(unsigned)-1;
343 if(argc < 2){ /* we need at least one argument */
347 /* compute VID/PID from usbconfig.h so that there is a central source of information */
348 vid = rawVid[1] * 256 + rawVid[0];
349 pid = rawPid[1] * 256 + rawPid[0];
350 /* The following function is in opendevice.c: */
351 if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
352 fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
357 c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:e",
358 long_options, &option_index);
363 if(action_fn && strchr("sgrzwxaqbkte", c)){
364 /* action given while already having an action */
369 if(strchr("sgrzwxaqkte", c)){
374 case 's': action_fn = set_dbg; break;
375 case 'g': action_fn = get_dbg; break;
376 case 'r': action_fn = read_mem; break;
377 case 'z': action_fn = read_flash; break;
378 case 'w': action_fn = write_mem; break;
379 case 'q': action_fn = soft_reset; break;
380 case 'b': action_fn = read_button; break;
381 case 'k': action_fn = wait_for_button; break;
382 case 't': action_fn = read_temperature; break;
383 case 'f': fname = optarg; break;
384 case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
385 case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
386 case 'e': action_fn = press_button; break;
396 fprintf(stderr, "Error: no action specified\n");
399 if(exec_loops==(unsigned)-1){