aboutsummaryrefslogtreecommitdiffstats
path: root/examples/hid-data
diff options
context:
space:
mode:
authorChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:00:20 +0000
committerChristian Starkjohann <cs+github@obdev.at>2008-04-17 19:00:20 +0000
commit95ca3f5bd696b5450820929e1b1a444d02f0bd1e (patch)
tree70ac0161a0e4548acaf2f89d2ecb77132579ff7a /examples/hid-data
parent2f465daef9e6c5a6b7bda3074c050cd7e8515770 (diff)
downloadv-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.gz
v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.tar.bz2
v-usb-95ca3f5bd696b5450820929e1b1a444d02f0bd1e.zip
- imported new files into project
Diffstat (limited to 'examples/hid-data')
-rw-r--r--examples/hid-data/Readme.txt75
-rw-r--r--examples/hid-data/commandline/Makefile42
-rw-r--r--examples/hid-data/commandline/Makefile.windows18
-rw-r--r--examples/hid-data/commandline/hidtool.c127
-rw-r--r--examples/hid-data/firmware/main.c141
-rwxr-xr-xexamples/hid-data/make-files.sh45
6 files changed, 448 insertions, 0 deletions
diff --git a/examples/hid-data/Readme.txt b/examples/hid-data/Readme.txt
new file mode 100644
index 0000000..4f925a8
--- /dev/null
+++ b/examples/hid-data/Readme.txt
@@ -0,0 +1,75 @@
+This is the Readme file for the hid-data example. In this example, we show
+how blocks of data can be exchanged with the device using only functionality
+compliant to the HID class. Since class drivers for HID are included with
+Windows, you don't need to install drivers on Windows.
+
+
+WHAT IS DEMONSTRATED?
+=====================
+This example demonstrates how the HID class can be misused to transfer fixed
+size blocks of data (up to the driver's transfer size limit) over HID feature
+reports. This technique is of great value on Windows because no driver DLLs
+are needed (the hid-custom-rq example still requires the libusb-win32 DLL,
+although it may be in the program's directory). The host side application
+requires no installation, it can even be started directly from a CD. This
+example also demonstrates how to transfer data using usbFunctionWrite() and
+usbFunctionRead().
+
+
+PREREQUISITES
+=============
+Target hardware: You need an AVR based circuit based on one of the examples
+(see the "circuits" directory at the top level of this package), e.g. the
+metaboard (http://metalab.at/wiki/Metaboard).
+
+AVR development environment: You need the gcc tool chain for the AVR, see
+the Prerequisites section in the top level Readme file for how to obtain it.
+
+Host development environment: A C compiler and libusb on Unix. On Windows
+you need the Driver Development Kit (DDK) Instead of libusb. MinGW ships
+with a free version of the DDK.
+
+
+BUILDING THE FIRMWARE
+=====================
+Change to the "firmware" directory and modify Makefile according to your
+architecture (CPU clock, target device, fuse values) and ISP programmer. Then
+edit usbconfig.h according to your pin assignments for D+ and D-. The default
+settings are for the metaboard hardware.
+
+Type "make hex" to build main.hex, then "make flash" to upload the firmware
+to the device. Don't forget to run "make fuse" once to program the fuses. If
+you use a prototyping board with boot loader, follow the instructions of the
+boot loader instead.
+
+Please note that the first "make hex" copies the driver from the top level
+into the firmware directory. If you use a different build system than our
+Makefile, you must copy the driver by hand.
+
+
+BUILDING THE HOST SOFTWARE
+==========================
+Make sure that you have libusb (on Unix) or the DDK (on Windows) installed.
+We recommend MinGW on Windows since it includes a free version of the DDK.
+Then change to directory "commandline" and run "make" on Unix or
+"make -f Makefile.windows" on Windows.
+
+
+USING THE COMMAND LINE TOOL
+===========================
+The device implements a data store of 128 bytes in EEPROM. You can send a
+block of 128 bytes to the device or read the block using the command line
+tool.
+
+To send a block to the device, use e.g.
+
+ hidtool write 0x01,0x02,0x03,0x04,...
+
+and to receive the block, use
+
+ hidtool read
+
+
+----------------------------------------------------------------------------
+(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
+http://www.obdev.at/
diff --git a/examples/hid-data/commandline/Makefile b/examples/hid-data/commandline/Makefile
new file mode 100644
index 0000000..97c6b06
--- /dev/null
+++ b/examples/hid-data/commandline/Makefile
@@ -0,0 +1,42 @@
+# Name: Makefile
+# Project: hid-data example
+# Author: Christian Starkjohann
+# Creation Date: 2008-04-11
+# Tabsize: 4
+# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+# This Revision: $Id$
+
+# Please read the definitions below and edit them as appropriate for your
+# system:
+
+# Use the following 3 lines on Unix and 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:
+#USBFLAGS=
+#USBLIBS= -lhid -lusb -lsetupapi
+#EXE_SUFFIX= .exe
+
+CC= gcc
+CFLAGS= -O -Wall $(USBFLAGS)
+LIBS= $(USBLIBS)
+
+OBJ= hidtool.o hiddata.o
+PROGRAM= hidtool$(EXE_SUFFIX)
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(OBJ)
+ $(CC) -o $(PROGRAM) $(OBJ) $(LIBS)
+
+strip: $(PROGRAM)
+ strip $(PROGRAM)
+
+clean:
+ rm -f $(OBJ) $(PROGRAM)
+
+.c.o:
+ $(CC) $(ARCH_COMPILE) $(CFLAGS) -c $*.c -o $*.o
diff --git a/examples/hid-data/commandline/Makefile.windows b/examples/hid-data/commandline/Makefile.windows
new file mode 100644
index 0000000..f0e6cfa
--- /dev/null
+++ b/examples/hid-data/commandline/Makefile.windows
@@ -0,0 +1,18 @@
+# Name: Makefile.windows
+# Project: hid-data example
+# Author: Christian Starkjohann
+# Creation Date: 2008-04-11
+# Tabsize: 4
+# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+# This Revision: $Id$
+
+# You may use this file with
+# make -f Makefile.windows
+# on Windows with MinGW instead of editing the main Makefile.
+
+include Makefile
+
+USBFLAGS=
+USBLIBS= -lhid -lusb -lsetupapi
+EXE_SUFFIX= .exe
diff --git a/examples/hid-data/commandline/hidtool.c b/examples/hid-data/commandline/hidtool.c
new file mode 100644
index 0000000..d03bca8
--- /dev/null
+++ b/examples/hid-data/commandline/hidtool.c
@@ -0,0 +1,127 @@
+/* Name: hidtool.c
+ * Project: hid-data example
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-11
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "hiddata.h"
+#include "../firmware/usbconfig.h" /* for device VID, PID, vendor name and product name */
+
+/* ------------------------------------------------------------------------- */
+
+static char *usbErrorMessage(int errCode)
+{
+static char buffer[80];
+
+ switch(errCode){
+ case USBOPEN_ERR_ACCESS: return "Access to device denied";
+ case USBOPEN_ERR_NOTFOUND: return "The specified device was not found";
+ case USBOPEN_ERR_IO: return "Communication error with device";
+ default:
+ sprintf(buffer, "Unknown USB error %d", errCode);
+ return buffer;
+ }
+ return NULL; /* not reached */
+}
+
+static usbDevice_t *openDevice(void)
+{
+usbDevice_t *dev = NULL;
+unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}, rawPid[2] = {USB_CFG_DEVICE_ID};
+char vendorName[] = {USB_CFG_VENDOR_NAME, 0}, productName[] = {USB_CFG_DEVICE_NAME, 0};
+int vid = rawVid[0] + 256 * rawVid[1];
+int pid = rawPid[0] + 256 * rawPid[1];
+int err;
+
+ if((err = usbhidOpenDevice(&dev, vid, vendorName, pid, productName, 0)) != 0){
+ fprintf(stderr, "error finding %s: %s\n", productName, usbErrorMessage(err));
+ return NULL;
+ }
+ return dev;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void hexdump(char *buffer, int len)
+{
+int i;
+FILE *fp = stdout;
+
+ for(i = 0; i < len; i++){
+ if(i != 0){
+ if(i % 16 == 0){
+ fprintf(fp, "\n");
+ }else{
+ fprintf(fp, " ");
+ }
+ }
+ fprintf(fp, "0x%02x", buffer[i] & 0xff);
+ }
+ if(i != 0)
+ fprintf(fp, "\n");
+}
+
+static int hexread(char *buffer, char *string, int buflen)
+{
+char *s;
+int pos = 0;
+
+ while((s = strtok(string, ", ")) != NULL && pos < buflen){
+ string = NULL;
+ buffer[pos++] = (char)strtol(s, NULL, 0);
+ }
+ return pos;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void usage(char *myName)
+{
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " %s read\n", myName);
+ fprintf(stderr, " %s write <listofbytes>\n", myName);
+}
+
+int main(int argc, char **argv)
+{
+usbDevice_t *dev;
+char buffer[129]; /* room for dummy report ID */
+int err;
+
+ if(argc < 2){
+ usage(argv[0]);
+ exit(1);
+ }
+ if((dev = openDevice()) == NULL)
+ exit(1);
+ if(strcasecmp(argv[1], "read") == 0){
+ int len = sizeof(buffer);
+ if((err = usbhidGetReport(dev, 0, buffer, &len)) != 0){
+ fprintf(stderr, "error reading data: %s\n", usbErrorMessage(err));
+ }else{
+ hexdump(buffer + 1, sizeof(buffer) - 1);
+ }
+ }else if(strcasecmp(argv[1], "write") == 0){
+ int i, pos;
+ bzero(buffer, sizeof(buffer));
+ for(pos = 1, i = 2; i < argc && pos < sizeof(buffer); i++){
+ pos += hexread(buffer + pos, argv[i], sizeof(buffer) - pos);
+ }
+ if((err = usbhidSetReport(dev, buffer, sizeof(buffer))) != 0) /* add a dummy report ID */
+ fprintf(stderr, "error writing data: %s\n", usbErrorMessage(err));
+ }else{
+ usage(argv[0]);
+ exit(1);
+ }
+ usbhidCloseDevice(dev);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/examples/hid-data/firmware/main.c b/examples/hid-data/firmware/main.c
new file mode 100644
index 0000000..3ef68d5
--- /dev/null
+++ b/examples/hid-data/firmware/main.c
@@ -0,0 +1,141 @@
+/* Name: main.c
+ * Project: hid-data, example how to use HID for data transfer
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-11
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+/*
+This example should run on most AVRs with only little changes. No special
+hardware resources except INT0 are used. You may have to change usbconfig.h for
+different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
+at least be connected to INT0 as well.
+*/
+
+#include <avr/io.h>
+#include <avr/wdt.h>
+#include <avr/interrupt.h> /* for sei() */
+#include <util/delay.h> /* for _delay_ms() */
+#include <avr/eeprom.h>
+
+#include <avr/pgmspace.h> /* required by usbdrv.h */
+#include "usbdrv.h"
+#include "oddebug.h" /* This is also an example for using debug macros */
+
+/* ------------------------------------------------------------------------- */
+/* ----------------------------- USB interface ----------------------------- */
+/* ------------------------------------------------------------------------- */
+
+PROGMEM char usbHidReportDescriptor[22] = { /* USB report descriptor */
+ 0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x01, // USAGE (Vendor Usage 1)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x80, // REPORT_COUNT (128)
+ 0x09, 0x00, // USAGE (Undefined)
+ 0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
+ 0xc0 // END_COLLECTION
+};
+/* Since we define only one feature report, we don't use report-IDs (which
+ * would be the first byte of the report). The entire report consists of 128
+ * opaque data bytes.
+ */
+
+/* The following variables store the status of the current data transfer */
+static uchar currentAddress;
+static uchar bytesRemaining;
+
+/* ------------------------------------------------------------------------- */
+
+/* usbFunctionRead() is called when the host requests a chunk of data from
+ * the device. For more information see the documentation in usbdrv/usbdrv.h.
+ */
+uchar usbFunctionRead(uchar *data, uchar len)
+{
+ if(len > bytesRemaining)
+ len = bytesRemaining;
+ eeprom_read_block(data, (uchar *)0 + currentAddress, len);
+ currentAddress += len;
+ bytesRemaining -= len;
+ return len;
+}
+
+/* usbFunctionWrite() is called when the host sends a chunk of data to the
+ * device. For more information see the documentation in usbdrv/usbdrv.h.
+ */
+uchar usbFunctionWrite(uchar *data, uchar len)
+{
+ if(bytesRemaining == 0)
+ return 1; /* end of transfer */
+ if(len > bytesRemaining)
+ len = bytesRemaining;
+ eeprom_write_block(data, (uchar *)0 + currentAddress, len);
+ currentAddress += len;
+ bytesRemaining -= len;
+ return bytesRemaining == 0; /* return 1 if this was the last chunk */
+}
+
+/* ------------------------------------------------------------------------- */
+
+uchar usbFunctionSetup(uchar data[8])
+{
+usbRequest_t *rq = (void *)data;
+
+ if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* HID class request */
+ if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
+ /* since we have only one report type, we can ignore the report-ID */
+ bytesRemaining = 128;
+ currentAddress = 0;
+ return 0xff; /* use usbFunctionRead() to obtain data */
+ }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
+ /* since we have only one report type, we can ignore the report-ID */
+ bytesRemaining = 128;
+ currentAddress = 0;
+ return 0xff; /* use usbFunctionWrite() to receive data from host */
+ }
+ }else{
+ /* ignore vendor type requests, we don't use any */
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int main(void)
+{
+uchar i;
+
+ wdt_enable(WDTO_1S);
+ /* Even if you don't use the watchdog, turn it off here. On newer devices,
+ * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
+ */
+ DBG1(0x00, 0, 0); /* debug output: main starts */
+ /* RESET status: all port bits are inputs without pull-up.
+ * That's the way we need D+ and D-. Therefore we don't need any
+ * additional hardware initialization.
+ */
+ odDebugInit();
+ usbInit();
+ usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
+ i = 0;
+ while(--i){ /* fake USB disconnect for > 250 ms */
+ wdt_reset();
+ _delay_ms(1);
+ }
+ usbDeviceConnect();
+ sei();
+ DBG1(0x01, 0, 0); /* debug output: main loop starts */
+ for(;;){ /* main event loop */
+ DBG1(0x02, 0, 0); /* debug output: main loop iterates */
+ wdt_reset();
+ usbPoll();
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/examples/hid-data/make-files.sh b/examples/hid-data/make-files.sh
new file mode 100755
index 0000000..a8d524c
--- /dev/null
+++ b/examples/hid-data/make-files.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Author: Christian Starkjohann
+# Creation Date: 2008-04-17
+# Tabsize: 4
+# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+# License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
+# This Revision: $Id$
+
+
+if [ "$1" = remove ]; then
+ (cd firmware; make clean)
+ rm -f firmware/usbconfig.h
+ rm -rf firmware/usbdrv
+ rm -f firmware/Makefile
+ rm -f commandline/hiddata.[ch]
+ rm -f commandline/hidsdi.h
+ exit
+fi
+
+cat << \EOF | sed -n -f /dev/stdin ../../usbdrv/usbconfig-prototype.h >firmware/usbconfig.h
+/^\( [*] \)\{0,1\}[+].*$/ d
+s/^#define USB_CFG_DMINUS_BIT .*$/#define USB_CFG_DMINUS_BIT 4/g
+s|^.*#define USB_CFG_CLOCK_KHZ.*$|#define USB_CFG_CLOCK_KHZ (F_CPU/1000)|g
+s/^#define USB_CFG_HAVE_INTRIN_ENDPOINT .*$/#define USB_CFG_HAVE_INTRIN_ENDPOINT 1/g
+s|^#define USB_CFG_DEVICE_ID .*$|#define USB_CFG_DEVICE_ID 0xdf, 0x05 /* obdev's shared PID for HIDs */|g
+s/^#define USB_CFG_DEVICE_NAME .*$/#define USB_CFG_DEVICE_NAME 'D', 'a', 't', 'a', 'S', 't', 'o', 'r', 'e'/g
+s/^#define USB_CFG_DEVICE_NAME_LEN .*$/#define USB_CFG_DEVICE_NAME_LEN 9/g
+
+s/^#define USB_CFG_INTR_POLL_INTERVAL .*$/#define USB_CFG_INTR_POLL_INTERVAL 100/g
+s/^#define USB_CFG_MAX_BUS_POWER .*$/#define USB_CFG_MAX_BUS_POWER 20/g
+s/^#define USB_CFG_IMPLEMENT_FN_WRITE .*$/#define USB_CFG_IMPLEMENT_FN_WRITE 1/g
+s/^#define USB_CFG_IMPLEMENT_FN_READ .*$/#define USB_CFG_IMPLEMENT_FN_READ 1/g
+s/^#define USB_CFG_DEVICE_CLASS .*$/#define USB_CFG_DEVICE_CLASS 0/g
+s/^#define USB_CFG_INTERFACE_CLASS .*$/#define USB_CFG_INTERFACE_CLASS 3/g
+s/^.*#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH.*$/#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 22/g
+p
+EOF
+
+cat << \EOF | sed -n -f /dev/stdin ../custom-class/firmware/Makefile >firmware/Makefile
+/^\( [*] \)\{0,1\}[+].*$/ d
+s/^# Project: .*$/# Project: hid-data example/g
+p
+EOF
+
+cp ../../libs-host/hiddata.[ch] ../../libs-host/hidsdi.h commandline