adding old command-line-tool
authorbg <daniel.otte@rub.de>
Wed, 16 Oct 2013 00:04:39 +0000 (02:04 +0200)
committerbg <daniel.otte@rub.de>
Wed, 16 Oct 2013 00:04:39 +0000 (02:04 +0200)
hostware/commandline/Makefile [new file with mode: 0644]
hostware/commandline/hexdump.c [new file with mode: 0644]
hostware/commandline/hexdump.h [new file with mode: 0644]
hostware/commandline/main.c [new file with mode: 0644]
hostware/commandline/opendevice.c [new file with mode: 0644]
hostware/commandline/opendevice.h [new file with mode: 0644]

diff --git a/hostware/commandline/Makefile b/hostware/commandline/Makefile
new file mode 100644 (file)
index 0000000..46cfbdd
--- /dev/null
@@ -0,0 +1,48 @@
+# Name: Makefile
+# Project: hid-custom-rq example
+# Author: Christian Starkjohann
+# Creation Date: 2008-04-06
+# Tabsize: 4
+# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $
+
+
+# Concigure the following definitions according to your system.
+# This Makefile has been tested on Mac OS X, Linux and Windows.
+
+# Use the following 3 lines on Unix (uncomment the framework on Mac OS X):
+USBFLAGS = `libusb-config --cflags`
+USBLIBS = `libusb-config --libs`
+EXE_SUFFIX =
+
+# Use the following 3 lines on Windows and comment out the 3 above. You may
+# have to change the include paths to where you installed libusb-win32
+#USBFLAGS = -I/usr/local/include
+#USBLIBS = -L/usr/local/lib -lusb
+#EXE_SUFFIX = .exe
+
+NAME = badge-tool
+
+OBJECTS = opendevice.o hexdump.o main.o
+
+CC             = gcc
+CFLAGS = $(CPPFLAGS) $(USBFLAGS) -O -g -Wall
+LIBS   = $(USBLIBS)
+
+PROGRAM = $(NAME)$(EXE_SUFFIX)
+
+
+all: $(PROGRAM)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $<
+
+$(PROGRAM): $(OBJECTS)
+       $(CC) -o $(PROGRAM) $(OBJECTS) $(LIBS)
+
+strip: $(PROGRAM)
+       strip $(PROGRAM)
+
+clean:
+       rm -f *.o $(PROGRAM)
diff --git a/hostware/commandline/hexdump.c b/hostware/commandline/hexdump.c
new file mode 100644 (file)
index 0000000..6fb3742
--- /dev/null
@@ -0,0 +1,74 @@
+/* hexdump.c */
+/*
+    This file is part of the ARM-Crypto-Lib.
+    Copyright (C) 2006-2011 Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+static
+void int_hexdump_line_buffer(FILE* stream, uint8_t* buffer, unsigned width, unsigned fill){
+       unsigned i;
+       for(i=0; i<width; ++i){
+               if(i<fill){
+                       fprintf(stream, "%2.2x ", buffer[i]);
+               }else{
+                       fputs("   ", stream);
+               }
+       }
+       fputs("    |", stream);
+       for(i=0; i<width; ++i){
+               if(i<fill){
+                       if(isgraph(buffer[i])){
+                               fputc(buffer[i], stream);
+                       }else
+                               fputc('.', stream);
+               }else{
+                       fputs(" ", stream);
+               }
+       }
+       fputc('|', stream);
+
+}
+
+
+void hexdump_block(FILE* stream, void* block, void* print_addr, unsigned length, unsigned width){
+       uint8_t buffer[width];
+       unsigned index=0;
+       while(length>width){
+               memcpy(buffer, block, width);
+               if(print_addr){
+                       fprintf(stream, "%8.8x ", (uint32_t)print_addr);
+                       print_addr = (uint8_t*)print_addr + width;
+               }
+               fprintf(stream, "<%4.4x>: ", index);
+               int_hexdump_line_buffer(stream, buffer, width, width);
+               fputc('\n', stream);
+               block = (uint8_t*)block + width;
+               length -= width;
+               index += width;
+       }
+       memcpy(buffer, block, length);
+       if(print_addr){
+               fprintf(stream, "%8.8x ", (uint32_t)print_addr);
+       }
+       fprintf(stream, "<%4.4x>: ", index);
+       int_hexdump_line_buffer(stream, buffer, width, length);
+       fputc('\n', stream);
+}
diff --git a/hostware/commandline/hexdump.h b/hostware/commandline/hexdump.h
new file mode 100644 (file)
index 0000000..8b1cbcf
--- /dev/null
@@ -0,0 +1,25 @@
+/* hexdump.h */
+/*
+    This file is part of the AVR-Crypto-Lib.
+    Copyright (C) 2011 Daniel Otte (daniel.otte@rub.de)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HEXDUMP_H_
+#define HEXDUMP_H_
+
+void hexdump_block(FILE* stream, void* block, void* print_addr, unsigned length, unsigned width);
+
+#endif /* HEXDUMP_H_ */
diff --git a/hostware/commandline/main.c b/hostware/commandline/main.c
new file mode 100644 (file)
index 0000000..71d9b07
--- /dev/null
@@ -0,0 +1,377 @@
+/* Name: set-led.c
+ * Project: hid-custom-rq example
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: set-led.c 692 2008-11-07 15:07:40Z cs $
+ */
+
+/*
+General Description:
+This is the host-side driver for the custom-class example device. It searches
+the USB for the LEDControl device and sends the requests understood by this
+device.
+This program must be linked with libusb on Unix and libusb-win32 on Windows.
+See http://libusb.sourceforge.net/ or http://libusb-win32.sourceforge.net/
+respectively.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <usb.h>        /* this is libusb */
+#include <arpa/inet.h>
+#include "hexdump.h"
+#include "opendevice.h" /* common code moved to separate module */
+
+#include "../../firmware/requests.h"   /* custom request numbers */
+#include "../../firmware/usbconfig.h"  /* device's VID/PID and names */
+
+int safety_question_override=0;
+int pad=-1;
+
+char* fname;
+usb_dev_handle *handle = NULL;
+
+void set_rgb(char* color){
+       uint16_t buffer[3] = {0, 0, 0};
+       sscanf(color, "%hi:%hi:%hi", &(buffer[0]), &(buffer[1]), &(buffer[2]));
+       buffer[0] &= (1<<10)-1;
+       buffer[1] &= (1<<10)-1;
+       buffer[2] &= (1<<10)-1;
+       usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_RGB, 0, 0, (char*)buffer, 6, 5000);
+}
+
+void get_rgb(char* param){
+       uint16_t buffer[3];
+       int cnt;
+       cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_GET_RGB, 0, 0, (char*)buffer, 6, 5000);
+       if(cnt!=6){
+               fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, 6);
+               exit(1);
+       }
+       printf("red:   %5hu\ngreen: %5hu\nblue:  %5u\n", buffer[0], buffer[1], buffer[2]);
+}
+
+void read_mem(char* param){
+       int length=0;
+       uint8_t *buffer, *addr;
+       int cnt;
+       FILE* f=NULL;
+       if(fname){
+               f = fopen(fname, "wb");
+               if(!f){
+                       fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
+                       exit(1);
+               }
+       }
+       sscanf(param, "%i:%i", (int*)&addr, &length);
+       if(length<=0){
+               return;
+       }
+       buffer = malloc(length);
+       if(!buffer){
+               if(f)
+                       fclose(f);
+               fprintf(stderr, "ERROR: out of memory\n");
+               exit(1);
+       }
+       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);
+       if(cnt!=length){
+               if(f)
+                       fclose(f);
+               fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
+               exit(1);
+       }
+       if(f){
+               cnt = fwrite(buffer, 1, length, f);
+               fclose(f);
+               if(cnt!=length){
+                       fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
+                       exit(1);
+               }
+
+       }else{
+               hexdump_block(stdout, buffer, addr, length, 8);
+       }
+}
+
+void write_mem(char* param){
+       int length;
+       uint8_t *addr, *buffer, *data=NULL;
+       int cnt=0;
+       FILE* f=NULL;
+
+       if(fname){
+               f = fopen(fname, "rb");
+               if(!f){
+                       fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
+                       exit(1);
+               }
+       }
+       sscanf(param, "%i:%i:%n", (int*)&addr, &length, &cnt);
+       data += cnt;
+       if(length<=0){
+               return;
+       }
+       buffer = malloc(length);
+       if(!buffer){
+               if(f)
+                       fclose(f);
+               fprintf(stderr, "ERROR: out of memory\n");
+               exit(1);
+       }
+       memset(buffer, (uint8_t)pad, length);
+       if(!data && !f && length==0){
+               fprintf(stderr, "ERROR: no data to write\n");
+               exit(1);
+       }
+       if(f){
+               cnt = fread(buffer, 1, length, f);
+               fclose(f);
+               if(cnt!=length && pad==-1){
+                       fprintf(stderr, "Warning: could ony read %d bytes from file; will only write these bytes", cnt);
+               }
+       }else if(data){
+               char xbuffer[3]= {0, 0, 0};
+               uint8_t fill=0;
+               unsigned idx=0;
+               while(*data && idx<length){
+                       while(*data && !isxdigit(*data)){
+                               ++data;
+                       }
+                       xbuffer[fill++] = *data;
+                       if(fill==2){
+                               uint8_t t;
+                               t = strtoul(xbuffer, NULL, 16);
+                               buffer[idx++] = t;
+                               fill = 0;
+                       }
+               }
+
+       }
+       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);
+       if(cnt!=length){
+               fprintf(stderr, "ERROR: device accepted ony %d bytes out of %d\n", cnt, length);
+               exit(1);
+       }
+
+}
+
+void read_flash(char* param){
+       int length=0;
+       uint8_t *buffer, *addr;
+       int cnt;
+       FILE* f=NULL;
+       if(fname){
+               f = fopen(fname, "wb");
+               if(!f){
+                       fprintf(stderr, "ERROR: could not open %s for writing\n", fname);
+                       exit(1);
+               }
+       }
+       sscanf(param, "%i:%i", (int*)&addr, &length);
+       if(length<=0){
+               return;
+       }
+       buffer = malloc(length);
+       if(!buffer){
+               if(f)
+                       fclose(f);
+               fprintf(stderr, "ERROR: out of memory\n");
+               exit(1);
+       }
+       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);
+       if(cnt!=length){
+               if(f)
+                       fclose(f);
+               fprintf(stderr, "ERROR: received %d bytes from device while expecting %d bytes\n", cnt, length);
+               exit(1);
+       }
+       if(f){
+               cnt = fwrite(buffer, 1, length, f);
+               fclose(f);
+               if(cnt!=length){
+                       fprintf(stderr, "ERROR: could write only %d bytes out of %d bytes\n", cnt, length);
+                       exit(1);
+               }
+
+       }else{
+               hexdump_block(stdout, buffer, addr, length, 8);
+       }
+}
+
+void soft_reset(char* param){
+       unsigned delay=0;
+       if(param){
+               sscanf(param, "%i", &delay);
+       }
+       delay &= 0xf;
+       usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_RESET, (int)delay, 0, NULL, 0, 5000);
+}
+
+void read_button(char* param){
+       uint8_t v;
+       usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
+       printf("button is %s\n",v?"on":"off");
+}
+
+void wait_for_button(char* param){
+       volatile uint8_t v=0, x=1;
+       if(param){
+               printf("DBG: having param: %s\n", param);
+               if(!(strcmp(param,"off") && strcmp(param,"0"))){
+                       x = 0;
+               }
+       }
+       do{
+               usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_BUTTON, 0, 0, (char*)&v, 1, 5000);
+       }while(x!=v);
+       printf("button is %s\n",v?"on":"off");
+}
+
+void read_temperature(char* param){
+       uint16_t v;
+       int cnt;
+       cnt = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, CUSTOM_RQ_READ_TMPSENS, 0, 0, (char*)&v, 2, 5000);
+       printf("temperature raw value: %hd 0x%hx\n", v, v);
+}
+
+
+static struct option long_options[] =
+             {
+               /* These options set a flag. */
+               {"i-am-sure",       no_argument, &safety_question_override, 1},
+               {"pad",             optional_argument, 0, 'p'},
+               /* These options don't set a flag.
+                  We distinguish them by their indices. */
+               {"set-rgb",         required_argument, 0, 's'},
+               {"get-rgb",               no_argument, 0, 'g'},
+               {"read-mem",        required_argument, 0, 'r'},
+               {"write-mem",       required_argument, 0, 'w'},
+               {"read-flash",      required_argument, 0, 'z'},
+               {"exec-spm",        required_argument, 0, 'x'},
+               {"read-adc",        required_argument, 0, 'a'},
+               {"reset",           optional_argument, 0, 'q'},
+               {"read-button",     required_argument, 0, 'b'},
+               {"wait-for-button", optional_argument, 0, 'k'},
+               {"read-temperature",      no_argument, 0, 't'},
+               {"file",            required_argument, 0, 'f'},
+               {"loop",            required_argument, 0, 'l'},
+               {0, 0, 0, 0}
+             };
+
+static void usage(char *name)
+{
+       char *usage_str =
+       "usage:\n"
+    "    %s [<option>] <command> <parameter string>\n"
+    "  where <option> is one of the following:\n"
+       "    -p --pad[=<pad value>] ............................ pad writing data with <pad value> (default 0) to specified length\n"
+       "    -f --file <name> .................................. use file <name> for reading or writing data\n"
+       "    --i-am-sure ....................................... do not ask safety question\n"
+       "    -l --loop <value> ................................. execute action <value> times\n"
+       "  <command> is one of the following\n"
+       "    -s --set-rgb <red>:<green>:<blue> ................. set color\n"
+       "    -g --get-rgb ...................................... read color from device and print\n"
+       "    -r --read-mem <addr>:<length> ..................... read RAM\n"
+       "    -w --write-mem <addr>:<length>[:data] ............. write RAM\n"
+       "    -z --read-flash <addr>:<length> ................... read flash\n"
+/*     "    -x --exec-spm <addr>:<length>:<Z>:<R0R1>[:data] ... write RAM, set Z pointer, set r0:r1 and execute SPM\n"
+       "    -a --read-adc <adc> ............................... read ADC\n" */
+       "    -q --reset[=<delay>] .............................. reset the controller with delay in range 0..9\n"
+       "    -b --read-button .................................. read status of button\n"
+       "    -k --wait-for-button[=(on|off)] ................... wait for button press (default: on)\n\n"
+       "    -t --read-temperature ............................. read temperature sensor and output raw value\n"
+       " Please note:\n"
+       "   If you use optional parameters you have to use two different way to specify the parameter,\n"
+       "   depending on if you use short or long options.\n"
+       "   Short options: You have to put the parameter directly behind the option letter. Exp: -koff\n"
+       "   Long options: You have to seperate the option from the parameter with '='. Exp: --pad=0xAA\n"
+       ;
+       fprintf(stderr, usage_str, name);
+}
+
+
+int main(int argc, char **argv)
+{
+  const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}; 
+  const unsigned char rawPid[2] = {USB_CFG_DEVICE_ID};
+  char vendor[] = {USB_CFG_VENDOR_NAME, 0};
+  char product[] = {USB_CFG_DEVICE_NAME, 0};
+  int  vid, pid;
+  int  c, option_index;
+  void(*action_fn)(char*) = NULL;
+  char* main_arg = NULL;
+  unsigned exec_loops=(unsigned)-1;
+  usb_init();
+  if(argc < 2){   /* we need at least one argument */
+    usage(argv[0]);
+    exit(1);
+  }
+  /* compute VID/PID from usbconfig.h so that there is a central source of information */
+    vid = rawVid[1] * 256 + rawVid[0];
+    pid = rawPid[1] * 256 + rawPid[0];
+    /* The following function is in opendevice.c: */
+    if(usbOpenDevice(&handle, vid, vendor, pid, NULL, NULL, NULL, NULL) != 0){
+        fprintf(stderr, "Could not find USB device \"%s\" with vid=0x%x pid=0x%x\n", product, vid, pid);
+        exit(1);
+    }
+
+    for(;;){
+       c = getopt_long(argc, argv, "s:gr:z:w:x:a:f:p::q::bk::tl:",
+                long_options, &option_index);
+       if(c == -1){
+               break;
+       }
+
+       if(action_fn && strchr("sgrzwxaqbkt", c)){
+               /* action given while already having an action */
+               usage(argv[0]);
+               exit(1);
+       }
+
+       if(strchr("sgrzwxaqkt", c)){
+               main_arg = optarg;
+       }
+
+       switch(c){
+       case 's': action_fn = set_rgb; break;
+       case 'g': action_fn = get_rgb; break;
+       case 'r': action_fn = read_mem; break;
+       case 'z': action_fn = read_flash; break;
+       case 'w': action_fn = write_mem; break;
+       case 'q': action_fn = soft_reset; break;
+       case 'b': action_fn = read_button; break;
+       case 'k': action_fn = wait_for_button; break;
+       case 't': action_fn = read_temperature; break;
+       case 'f': fname = optarg; break;
+       case 'p': pad = 0; if(optarg) pad=strtoul(optarg, NULL, 0); break;
+               case 'l': exec_loops = strtoul(optarg, NULL, 0); break;
+        case 'x':
+       case 'a':
+       default:
+               break;
+       }
+    }
+
+    if(!action_fn){
+       usage(argv[0]);
+       fprintf(stderr, "Error: no action specified\n");
+       return 1;
+    }else{
+       if(exec_loops==(unsigned)-1){
+               exec_loops = 1;
+       }
+       while(exec_loops--){
+               action_fn(main_arg);
+       }
+        usb_close(handle);
+       return 0;
+    }
+
+}
diff --git a/hostware/commandline/opendevice.c b/hostware/commandline/opendevice.c
new file mode 100644 (file)
index 0000000..791175b
--- /dev/null
@@ -0,0 +1,203 @@
+/* Name: opendevice.c
+ * Project: AVR-USB host-side library
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: opendevice.c 692 2008-11-07 15:07:40Z cs $
+ */
+
+/*
+General Description:
+The functions in this module can be used to find and open a device based on
+libusb or libusb-win32.
+*/
+
+#include <stdio.h>
+#include "opendevice.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define MATCH_SUCCESS                  1
+#define MATCH_FAILED                   0
+#define MATCH_ABORT                            -1
+
+/* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */
+static int  _shellStyleMatch(char *text, char *p)
+{
+int last, matched, reverse;
+
+    for(; *p; text++, p++){
+        if(*text == 0 && *p != '*')
+            return MATCH_ABORT;
+        switch(*p){
+        case '\\':
+            /* Literal match with following character. */
+            p++;
+            /* FALLTHROUGH */
+        default:
+            if(*text != *p)
+                return MATCH_FAILED;
+            continue;
+        case '?':
+            /* Match anything. */
+            continue;
+        case '*':
+            while(*++p == '*')
+                /* Consecutive stars act just like one. */
+                continue;
+            if(*p == 0)
+                /* Trailing star matches everything. */
+                return MATCH_SUCCESS;
+            while(*text)
+                if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
+                    return matched;
+            return MATCH_ABORT;
+        case '[':
+            reverse = p[1] == '^';
+            if(reverse) /* Inverted character class. */
+                p++;
+            matched = MATCH_FAILED;
+            if(p[1] == ']' || p[1] == '-')
+                if(*++p == *text)
+                    matched = MATCH_SUCCESS;
+            for(last = *p; *++p && *p != ']'; last = *p)
+                if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
+                    matched = MATCH_SUCCESS;
+            if(matched == reverse)
+                return MATCH_FAILED;
+            continue;
+        }
+    }
+    return *text == 0;
+}
+
+/* public interface for shell style matching: returns 0 if fails, 1 if matches */
+static int shellStyleMatch(char *text, char *pattern)
+{
+    if(pattern == NULL) /* NULL pattern is synonymous to "*" */
+        return 1;
+    return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
+{
+char    buffer[256];
+int     rval, i;
+
+    if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
+        return rval;
+    if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
+        return rval;
+    if(buffer[1] != USB_DT_STRING){
+        *buf = 0;
+        return 0;
+    }
+    if((unsigned char)buffer[0] < rval)
+        rval = (unsigned char)buffer[0];
+    rval /= 2;
+    /* lossy conversion to ISO Latin1: */
+    for(i=1;i<rval;i++){
+        if(i > buflen)              /* destination buffer overflow */
+            break;
+        buf[i-1] = buffer[2 * i];
+        if(buffer[2 * i + 1] != 0)  /* outside of ISO Latin1 range */
+            buf[i-1] = '?';
+    }
+    buf[i-1] = 0;
+    return i-1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp)
+{
+struct usb_bus      *bus;
+struct usb_device   *dev;
+usb_dev_handle      *handle = NULL;
+int                 errorCode = USBOPEN_ERR_NOTFOUND;
+
+    usb_find_busses();
+    usb_find_devices();
+    for(bus = usb_get_busses(); bus; bus = bus->next){
+        for(dev = bus->devices; dev; dev = dev->next){  /* iterate over all devices on all busses */
+            if((vendorID == 0 || dev->descriptor.idVendor == vendorID)
+                        && (productID == 0 || dev->descriptor.idProduct == productID)){
+                char    vendor[256], product[256], serial[256];
+                int     len;
+                handle = usb_open(dev); /* we need to open the device in order to query strings */
+                if(!handle){
+                    errorCode = USBOPEN_ERR_ACCESS;
+                    if(warningsFp != NULL)
+                        fprintf(warningsFp, "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
+                    continue;
+                }
+                /* now check whether the names match: */
+                len = vendor[0] = 0;
+                if(dev->descriptor.iManufacturer > 0){
+                    len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, vendor, sizeof(vendor));
+                }
+                if(len < 0){
+                    errorCode = USBOPEN_ERR_ACCESS;
+                    if(warningsFp != NULL)
+                        fprintf(warningsFp, "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
+                }else{
+                    errorCode = USBOPEN_ERR_NOTFOUND;
+                    /* printf("seen device from vendor ->%s<-\n", vendor); */
+                    if(shellStyleMatch(vendor, vendorNamePattern)){
+                        len = product[0] = 0;
+                        if(dev->descriptor.iProduct > 0){
+                            len = usbGetStringAscii(handle, dev->descriptor.iProduct, product, sizeof(product));
+                        }
+                        if(len < 0){
+                            errorCode = USBOPEN_ERR_ACCESS;
+                            if(warningsFp != NULL)
+                                fprintf(warningsFp, "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
+                        }else{
+                            errorCode = USBOPEN_ERR_NOTFOUND;
+                            /* printf("seen product ->%s<-\n", product); */
+                            if(shellStyleMatch(product, productNamePattern)){
+                                len = serial[0] = 0;
+                                if(dev->descriptor.iSerialNumber > 0){
+                                    len = usbGetStringAscii(handle, dev->descriptor.iSerialNumber, serial, sizeof(serial));
+                                }
+                                if(len < 0){
+                                    errorCode = USBOPEN_ERR_ACCESS;
+                                    if(warningsFp != NULL)
+                                        fprintf(warningsFp, "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
+                                }
+                                if(shellStyleMatch(serial, serialNamePattern)){
+                                    if(printMatchingDevicesFp != NULL){
+                                        if(serial[0] == 0){
+                                            fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product);
+                                        }else{
+                                            fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product, serial);
+                                        }
+                                    }else{
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                usb_close(handle);
+                handle = NULL;
+            }
+        }
+        if(handle)  /* we have found a deice */
+            break;
+    }
+    if(handle != NULL){
+        errorCode = 0;
+        *device = handle;
+    }
+    if(printMatchingDevicesFp != NULL)  /* never return an error for listing only */
+        errorCode = 0;
+    return errorCode;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/hostware/commandline/opendevice.h b/hostware/commandline/opendevice.h
new file mode 100644 (file)
index 0000000..5e9b68b
--- /dev/null
@@ -0,0 +1,77 @@
+/* Name: opendevice.h
+ * Project: AVR-USB host-side library
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: opendevice.h 692 2008-11-07 15:07:40Z cs $
+ */
+
+/*
+General Description:
+This module offers additional functionality for host side drivers based on
+libusb or libusb-win32. It includes a function to find and open a device
+based on numeric IDs and textual description. It also includes a function to
+obtain textual descriptions from a device.
+
+To use this functionality, simply copy opendevice.c and opendevice.h into your
+project and add them to your Makefile. You may modify and redistribute these
+files according to the GNU General Public License (GPL) version 2 or 3.
+*/
+
+#ifndef __OPENDEVICE_H_INCLUDED__
+#define __OPENDEVICE_H_INCLUDED__
+
+#include <usb.h>    /* this is libusb, see http://libusb.sourceforge.net/ */
+#include <stdio.h>
+
+int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen);
+/* This function gets a string descriptor from the device. 'index' is the
+ * string descriptor index. The string is returned in ISO Latin 1 encoding in
+ * 'buf' and it is terminated with a 0-character. The buffer size must be
+ * passed in 'buflen' to prevent buffer overflows. A libusb device handle
+ * must be given in 'dev'.
+ * Returns: The length of the string (excluding the terminating 0) or
+ * a negative number in case of an error. If there was an error, use
+ * usb_strerror() to obtain the error message.
+ */
+
+int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp);
+/* This function iterates over all devices on all USB busses and searches for
+ * a device. Matching is done first by means of Vendor- and Product-ID (passed
+ * in 'vendorID' and 'productID'. An ID of 0 matches any numeric ID (wildcard).
+ * When a device matches by its IDs, matching by names is performed. Name
+ * matching can be done on textual vendor name ('vendorNamePattern'), product
+ * name ('productNamePattern') and serial number ('serialNamePattern'). A
+ * device matches only if all non-null pattern match. If you don't care about
+ * a string, pass NULL for the pattern. Patterns are Unix shell style pattern:
+ * '*' stands for 0 or more characters, '?' for one single character, a list
+ * of characters in square brackets for a single character from the list
+ * (dashes are allowed to specify a range) and if the lis of characters begins
+ * with a caret ('^'), it matches one character which is NOT in the list.
+ * Other parameters to the function: If 'warningsFp' is not NULL, warning
+ * messages are printed to this file descriptor with fprintf(). If
+ * 'printMatchingDevicesFp' is not NULL, no device is opened but matching
+ * devices are printed to the given file descriptor with fprintf().
+ * If a device is opened, the resulting USB handle is stored in '*device'. A
+ * pointer to a "usb_dev_handle *" type variable must be passed here.
+ * Returns: 0 on success, an error code (see defines below) on failure.
+ */
+
+/* usbOpenDevice() error codes: */
+#define USBOPEN_SUCCESS         0   /* no error */
+#define USBOPEN_ERR_ACCESS      1   /* not enough permissions to open device */
+#define USBOPEN_ERR_IO          2   /* I/O error */
+#define USBOPEN_ERR_NOTFOUND    3   /* device not found */
+
+
+/* Obdev's free USB IDs, see USBID-License.txt for details */
+
+#define USB_VID_OBDEV_SHARED        5824    /* obdev's shared vendor ID */
+#define USB_PID_OBDEV_SHARED_CUSTOM 1500    /* shared PID for custom class devices */
+#define USB_PID_OBDEV_SHARED_HID    1503    /* shared PID for HIDs except mice & keyboards */
+#define USB_PID_OBDEV_SHARED_CDCACM 1505    /* shared PID for CDC Modem devices */
+#define USB_PID_OBDEV_SHARED_MIDI   1508    /* shared PID for MIDI class devices */
+
+#endif /* __OPENDEVICE_H_INCLUDED__ */