diff options
Diffstat (limited to 'examples/hid-custom-rq')
-rw-r--r-- | examples/hid-custom-rq/Readme.txt | 28 | ||||
-rw-r--r-- | examples/hid-custom-rq/firmware/main.c | 119 | ||||
-rw-r--r-- | examples/hid-custom-rq/firmware/requests.h | 32 | ||||
-rwxr-xr-x | examples/hid-custom-rq/make-files.sh | 64 |
4 files changed, 243 insertions, 0 deletions
diff --git a/examples/hid-custom-rq/Readme.txt b/examples/hid-custom-rq/Readme.txt new file mode 100644 index 0000000..6a2ab3b --- /dev/null +++ b/examples/hid-custom-rq/Readme.txt @@ -0,0 +1,28 @@ +This is the Readme file for the hid-custom-rq example. This is basically the +same as the custom-class example, except that the device conforms to the USB +HID class. + + +WHAT IS DEMONSTRATED? +===================== +This example demonstrates how custom requests can be sent to devices which +are otherwise HID compliant. This mechanism can be used to prevent the +"driver CD" dialog on Windows and still control the device with libusb-win32. +It can also be used to extend the functionality of the USB class, e.g. by +setting parameters. + +Please note that you should install the filter version of libusb-win32 to +take full advantage or this mode. The device driver version only has access +to devices which have been registered for it with a *.inf file. The filter +version has access to all devices. + + +MORE INFORMATION +================ +For information about how to build this example and how to use the command +line tool see the Readme file in the custom-class example. + + +---------------------------------------------------------------------------- +(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH. +http://www.obdev.at/ diff --git a/examples/hid-custom-rq/firmware/main.c b/examples/hid-custom-rq/firmware/main.c new file mode 100644 index 0000000..85cae06 --- /dev/null +++ b/examples/hid-custom-rq/firmware/main.c @@ -0,0 +1,119 @@ +/* Name: main.c + * Project: hid-custom-rq example + * Author: Christian Starkjohann + * Creation Date: 2008-04-07 + * 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. +We assume that an LED is connected to port B bit 0. If you connect it to a +different port or bit, change the macros below: +*/ +#define LED_PORT_DDR DDRB +#define LED_PORT_OUTPUT PORTB +#define LED_BIT 0 + +#include <avr/io.h> +#include <avr/wdt.h> +#include <avr/interrupt.h> /* for sei() */ +#include <util/delay.h> /* for _delay_ms() */ + +#include <avr/pgmspace.h> /* required by usbdrv.h */ +#include "usbdrv.h" +#include "oddebug.h" /* This is also an example for using debug macros */ +#include "requests.h" /* The custom request numbers we use */ + +/* ------------------------------------------------------------------------- */ +/* ----------------------------- 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, 0x01, // REPORT_COUNT (1) + 0x09, 0x00, // USAGE (Undefined) + 0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf) + 0xc0 // END_COLLECTION +}; +/* The descriptor above is a dummy only, it silences the drivers. The report + * it describes consists of one byte of undefined data. + * We don't transfer our data through HID reports, we use custom requests + * instead. + */ + +/* ------------------------------------------------------------------------- */ + +uchar usbFunctionSetup(uchar data[8]) +{ +usbRequest_t *rq = (void *)data; + + if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR){ + DBG1(0x50, &rq->bRequest, 1); /* debug output: print our request */ + if(rq->bRequest == CUSTOM_RQ_SET_STATUS){ + if(rq->wValue.bytes[0] & 1){ /* set LED */ + LED_PORT_OUTPUT |= _BV(LED_BIT); + }else{ /* clear LED */ + LED_PORT_OUTPUT &= ~_BV(LED_BIT); + } + }else if(rq->bRequest == CUSTOM_RQ_GET_STATUS){ + static uchar dataBuffer[1]; /* buffer must stay valid when usbFunctionSetup returns */ + dataBuffer[0] = ((LED_PORT_OUTPUT & _BV(LED_BIT)) != 0); + usbMsgPtr = dataBuffer; /* tell the driver which data to return */ + return 1; /* tell the driver to send 1 byte */ + } + }else{ + /* calss requests USBRQ_HID_GET_REPORT and USBRQ_HID_SET_REPORT are + * not implemented since we never call them. The operating system + * won't call them either because our descriptor defines no meaning. + */ + } + return 0; /* default for not implemented requests: return no data back to host */ +} + +/* ------------------------------------------------------------------------- */ + +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(); + LED_PORT_DDR |= _BV(LED_BIT); /* make the LED bit an output */ + 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-custom-rq/firmware/requests.h b/examples/hid-custom-rq/firmware/requests.h new file mode 100644 index 0000000..b6a3c2b --- /dev/null +++ b/examples/hid-custom-rq/firmware/requests.h @@ -0,0 +1,32 @@ +/* Name: requests.h + * Project: custom-class, a basic USB example + * Author: Christian Starkjohann + * Creation Date: 2008-04-09 + * 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 header is shared between the firmware and the host software. It + * defines the USB request numbers (and optionally data types) used to + * communicate between the host and the device. + */ + +#ifndef __REQUESTS_H_INCLUDED__ +#define __REQUESTS_H_INCLUDED__ + +#define CUSTOM_RQ_SET_STATUS 1 +/* Set the LED status. Control-OUT. + * The requested status is passed in the "wValue" field of the control + * transfer. No OUT data is sent. Bit 0 of the low byte of wValue controls + * the LED. + */ + +#define CUSTOM_RQ_GET_STATUS 2 +/* Get the current LED status. Control-IN. + * This control transfer involves a 1 byte data phase where the device sends + * the current status to the host. The status is in bit 0 of the byte. + */ + +#endif /* __REQUESTS_H_INCLUDED__ */ diff --git a/examples/hid-custom-rq/make-files.sh b/examples/hid-custom-rq/make-files.sh new file mode 100755 index 0000000..b52dbf6 --- /dev/null +++ b/examples/hid-custom-rq/make-files.sh @@ -0,0 +1,64 @@ +#!/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/set-led.c + rm -f commandline/Makefile.windows + rm -f commandline/Makefile + rm -f commandline/opendevice.[ch] + 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 'L', 'E', 'D', 'C', 't', 'l', 'H', 'I', 'D'/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 40/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-custom-rq example/g +p +EOF + +cat << \EOF | sed -n -f /dev/stdin ../custom-class/commandline/set-led.c >commandline/set-led.c +/^\( [*] \)\{0,1\}[+].*$/ d +s/^ [*] Project: .*$/ * Project: hid-custom-rq example/g +p +EOF + +cat << \EOF | sed -n -f /dev/stdin ../usbtool/Makefile.windows >commandline/Makefile.windows +/^\( [*] \)\{0,1\}[+].*$/ d +s/^# Project: .*$/# Project: hid-custom-rq example/g +p +EOF + +cat << \EOF | sed -n -f /dev/stdin ../usbtool/Makefile >commandline/Makefile +/^\( [*] \)\{0,1\}[+].*$/ d +s/^# Project: .*$/# Project: hid-custom-rq example/g +s/^NAME = .*$/NAME = set-led/g +p +EOF + +cp ../../libs-host/opendevice.[ch] commandline/ |