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 void set_rgb(char* color){
41 uint16_t buffer[3] = {0, 0, 0};
42 sscanf(color, "%hi:%hi:%hi", &(buffer[0]), &(buffer[1]), &(buffer[2]));
43 buffer[0] &= (1<<10)-1;
44 buffer[1] &= (1<<10)-1;
45 buffer[2] &= (1<<10)-1;
46 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_RGB, 0, 0, (char*)buffer, 6, 5000);
49 void get_rgb(char* param){
52 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_RGB, 0, 0, (char*)buffer, 6, 5000);
54 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, 6);
57 printf("red: %5hu\ngreen: %5hu\nblue: %5u\n", buffer[0], buffer[1], buffer[2]);
60 void read_mem(char* param){
62 uint8_t *buffer, *addr;
66 f = fopen(fname, "wb");
68 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
72 sscanf(param, "%i:%i", (int*)&addr, &length);
76 buffer = malloc(length);
80 fprintf(stderr, "ERROR: out of memory\n");
83 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);
87 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
91 cnt = fwrite(buffer, 1, length, f);
94 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
99 hexdump_block(stdout, buffer, addr, length, 8);
103 void write_mem(char* param){
105 uint8_t *addr, *buffer, *data=NULL;
110 f = fopen(fname, "rb");
112 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
116 sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
121 buffer = malloc(length);
125 fprintf(stderr, "ERROR: out of memory\n");
128 memset(buffer, (uint8_t)pad, length);
129 if(!data && !f && length==0){
130 fprintf(stderr, "ERROR: no data to write\n");
134 cnt = fread(buffer, 1, length, f);
136 if(cnt!=length && pad==-1){
137 fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
140 char xbuffer[3]= {0, 0, 0};
143 while(*data && idx<length){
144 while(*data && !isxdigit(*data)){
147 xbuffer[fill++] = *data;
150 t = strtoul(xbuffer, NULL, 16);
157 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);
159 fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
165 void read_flash(char* param){
167 uint8_t *buffer, *addr;
171 f = fopen(fname, "wb");
173 fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
177 sscanf(param, "%i:%i", (int*)&addr, &length);
181 buffer = malloc(length);
185 fprintf(stderr, "ERROR: out of memory\n");
188 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);
192 fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
196 cnt = fwrite(buffer, 1, length, f);
199 fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
204 hexdump_block(stdout, buffer, addr, length, 8);
208 void soft_reset(char* param){
211 sscanf(param, "%i", &delay);
214 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
217 void read_button(char* param){
219 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
220 printf("button is %s\n",v?"on":"off");
223 void wait_for_button(char* param){
224 volatile uint8_t v=0, x=1;
226 printf("DBG: having param: %s\n", param);
227 if(!(strcmp(param,"off") && strcmp(param,"0"))){
232 usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
234 printf("button is %s\n",v?"on":"off");
237 void read_temperature(char* param){
240 cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
241 printf("temperature raw value: %hd 0x%hx\n", v, v);
245 static struct option long_options[] =
247 /* These options set a flag. */
248 {"i-am-sure", no_argument, &safety_question_override, 1},
249 {"pad", optional_argument, 0, 'p'},
250 /* These options don't set a flag.
251 We distinguish them by their indices. */
252 {"set-rgb", required_argument, 0, 's'},
253 {"get-rgb", no_argument, 0, 'g'},
254 {"read-mem", required_argument, 0, 'r'},
255 {"write-mem", required_argument, 0, 'w'},
256 {"read-flash", required_argument, 0, 'z'},
257 {"exec-spm", required_argument, 0, 'x'},
258 {"read-adc", required_argument, 0, 'a'},
259 {"reset", optional_argument, 0, 'q'},
260 {"read-button", required_argument, 0, 'b'},
261 {"wait-for-button", optional_argument, 0, 'k'},
262 {"read-temperature", no_argument, 0, 't'},
263 {"file", required_argument, 0, 'f'},
264 {"loop", required_argument, 0, 'l'},
268 static void usage(char *name)
272 " %s [<option>] <command> <parameter string>\n"
273 " where <option> is one of the following:\n"
274 " -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
275 " -f --file <name> .................................. use file <name> for reading or writing data\n"
276 " --i-am-sure ....................................... do not ask safety question\n"
277 " -l --loop <value> ................................. execute action <value> times\n"
278 " <command> is one of the following\n"
279 " -s --set-rgb <red>:<green>:<blue> ................. set color\n"
280 " -g --get-rgb ...................................... read color from device and print\n"
281 " -r --read-mem <addr>:<length> ..................... read RAM\n"
282 " -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
283 " -z --read-flash <addr>:<length> ................... read flash\n"
284 /* " -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
285 " -a --read-adc <adc> ............................... read ADC\n" */
286 " -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
287 " -b --read-button .................................. read status of button\n"
288 " -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
289 " -t --read-temperature ............................. read temperature sensor and output raw value\n"
291 " If you use optional parameters you have to use two different way to specify the parameter,\n"
292 " depending on if you use short or long options.\n"
293 " Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
294 " Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
296 fprintf(stderr, usage_str, name);
300 int main(int argc, char **argv)
302 const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID};
303 const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
304 char vendor[] = {USB_CFG_VENDOR_NAME, 0};
305 char product[] = {USB_CFG_DEVICE_NAME, 0};
308 void(*action_fn)(char*) = NULL;
309 char* main_arg = NULL;
310 unsigned exec_loops=(unsigned)-1;
312 if(argc < 2){ /* we need at least one argument */
316 /* compute VID/PID from usbconfig.h so that there is a central source of information */
317 vid = rawVid[1] * 256 + rawVid[0];
318 pid = rawPid[1] * 256 + rawPid[0];
319 /* The following function is in opendevice.c: */
320 if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
321 fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
326 c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:",
327 long_options, &option_index);
332 if(action_fn && strchr("sgrzwxaqbkt", c)){
333 /* action given while already having an action */
338 if(strchr("sgrzwxaqkt", c)){
343 case 's': action_fn = set_rgb; break;
344 case 'g': action_fn = get_rgb; break;
345 case 'r': action_fn = read_mem; break;
346 case 'z': action_fn = read_flash; break;
347 case 'w': action_fn = write_mem; break;
348 case 'q': action_fn = soft_reset; break;
349 case 'b': action_fn = read_button; break;
350 case 'k': action_fn = wait_for_button; break;
351 case 't': action_fn = read_temperature; break;
352 case 'f': fname = optarg; break;
353 case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
354 case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
364 fprintf(stderr, "Error: no action specified\n");
367 if(exec_loops==(unsigned)-1){