X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/273d814d87242c5526dd03dc4530f605951fe0d4..d7891f6fbbff073a9b408ba6ada9ef5f12ef3624:/firmware/usbdrv/usbdrv.h diff --git a/firmware/usbdrv/usbdrv.h b/firmware/usbdrv/usbdrv.h index 66be5ed2e..e8cc4b3ac 100644 --- a/firmware/usbdrv/usbdrv.h +++ b/firmware/usbdrv/usbdrv.h @@ -1,43 +1,45 @@ /* Name: usbdrv.h - * Project: AVR USB driver + * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers * Author: Christian Starkjohann * Creation Date: 2004-12-29 * Tabsize: 4 * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH - * License: Proprietary, free under certain conditions. See Documentation. - * This Revision: $Id: usbdrv.h 52 2005-04-12 16:57:29Z cs $ + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbdrv.h 793 2010-07-15 15:58:11Z cs $ */ #ifndef __usbdrv_h_included__ -#define __usbdrv_h_included__ +#define __usbdrv_h_included__ #include "usbconfig.h" +#include "usbportability.h" /* Hardware Prerequisites: ======================= -USB lines D+ and D- MUST be wired to the same I/O port. Line D- MUST be wired -to bit number 0. D+ must also be connected to INT0. D- requires a pullup of -1.5k to +3.5V (and the device must be powered at 3.5V) to identify as -low-speed USB device. A pullup of 1M SHOULD be connected from D+ to +3.5V to -prevent interference when no USB master is connected. We use D+ as interrupt -source and not D- because it does not trigger on keep-alive and RESET states. +USB lines D+ and D- MUST be wired to the same I/O port. We recommend that D+ +triggers the interrupt (best achieved by using INT0 for D+), but it is also +possible to trigger the interrupt from D-. If D- is used, interrupts are also +triggered by SOF packets. D- requires a pull-up of 1.5k to +3.5V (and the +device must be powered at 3.5V) to identify as low-speed USB device. A +pull-down or pull-up of 1M SHOULD be connected from D+ to +3.5V to prevent +interference when no USB master is connected. If you use Zener diodes to limit +the voltage on D+ and D-, you MUST use a pull-down resistor, not a pull-up. +We use D+ as interrupt source and not D- because it does not trigger on +keep-alive and RESET states. If you want to count keep-alive events with +USB_COUNT_SOF, you MUST use D- as an interrupt source. + +As a compile time option, the 1.5k pull-up resistor on D- can be made +switchable to allow the device to disconnect at will. See the definition of +usbDeviceConnect() and usbDeviceDisconnect() further down in this file. Please adapt the values in usbconfig.h according to your hardware! -The device MUST be clocked at 12 MHz. This is more than the 10 MHz allowed by -an AT90S2313 powered at 4.5V. However, if the supply voltage to maximum clock -relation is interpolated linearly, an ATtiny2313 meets the requirement by -specification. In practice, the AT90S2313 can be overclocked and works well. +The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz +or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details. Limitations: ============ -Compiling: -The bss segment of the driver must be in the first 256 bytes of the address -space because byte wide variables are used as pointers for efficiency reasons. -This is not a problem on devices with 128 byte RAM since the entire RAM -meets this condition. For larger devices please link usbdrv first. - Robustness with respect to communication errors: The driver assumes error-free communication. It DOES check for errors in the PID, but does NOT check bit stuffing errors, SE0 in middle of a byte, @@ -47,13 +49,6 @@ Bit stuffing and misplaced SE0 would have to be checked in real-time, but CPU performance does not permit that. The driver does not check Data0/Data1 toggling, but application software can implement the check. -Sampling jitter: -The driver guarantees a sampling window of 1/2 bit. The USB spec requires -that the receiver has at most 1/4 bit sampling window. The 1/2 bit window -should still work reliably enough because we work at low speed. If you want -to meet the spec, define the macro "USB_CFG_SAMPLE_EXACT" to 1 in usbconfig.h. -This will unroll a loop which results in bigger code size. - Input characteristics: Since no differential receiver circuit is used, electrical interference robustness may suffer. The driver samples only one of the data lines with @@ -63,13 +58,29 @@ bit rate over the same hardware, we should be on the safe side. Even the spec requires detection of asymmetric states at high bit rate for SE0 detection. Number of endpoints: -The driver supports up to two endpoints: One control endpoint (endpoint 0) and -one interrupt-in endpoint (endpoint 1) where the device can send interrupt -data to the host. Endpoint 1 is only compiled in if -USB_CFG_HAVE_INTRIN_ENDPOINT is defined to 1 in usbconfig.h. +The driver supports the following endpoints: + +- Endpoint 0, the default control endpoint. +- Any number of interrupt- or bulk-out endpoints. The data is sent to + usbFunctionWriteOut() and USB_CFG_IMPLEMENT_FN_WRITEOUT must be defined + to 1 to activate this feature. The endpoint number can be found in the + global variable 'usbRxToken'. +- One default interrupt- or bulk-in endpoint. This endpoint is used for + interrupt- or bulk-in transfers which are not handled by any other endpoint. + You must define USB_CFG_HAVE_INTRIN_ENDPOINT in order to activate this + feature and call usbSetInterrupt() to send interrupt/bulk data. +- One additional interrupt- or bulk-in endpoint. This was endpoint 3 in + previous versions of this driver but can now be configured to any endpoint + number. You must define USB_CFG_HAVE_INTRIN_ENDPOINT3 in order to activate + this feature and call usbSetInterrupt3() to send interrupt/bulk data. The + endpoint number can be set with USB_CFG_EP3_NUMBER. + +Please note that the USB standard forbids bulk endpoints for low speed devices! +Most operating systems allow them anyway, but the AVR will spend 90% of the CPU +time in the USB interrupt polling for bulk data. Maximum data payload: -Data payload of control in and out transfers may be up to 255 bytes. In order +Data payload of control in and out transfers may be up to 254 bytes. In order to accept payload data of out transfers, you need to implement 'usbFunctionWrite()'. @@ -80,27 +91,30 @@ bus power anyway. Bus-powered devices can achieve this only by putting the CPU in sleep mode. The driver does not implement suspend handling by itself. However, the application may implement activity monitoring and wakeup from sleep. The host sends regular SE0 states on the bus to keep it active. These -SE0 states can be detected by wiring the INT1 pin to D+. It is not necessary -to enable the interrupt, checking the interrupt pending flag should suffice. -Before entering sleep mode, the application should enable INT1 for a wakeup -on the next bus activity. +SE0 states can be detected by using D- as the interrupt source. Define +USB_COUNT_SOF to 1 and use the global variable usbSofCount to check for bus +activity. Operation without an USB master: The driver behaves neutral without connection to an USB master if D- reads as 1. To avoid spurious interrupts, we recommend a high impedance (e.g. 1M) -pullup resistor on D+. If D- becomes statically 0, the driver may block in -the interrupt routine. +pull-down or pull-up resistor on D+ (interrupt). If Zener diodes are used, +use a pull-down. If D- becomes statically 0, the driver may block in the +interrupt routine. Interrupt latency: The application must ensure that the USB interrupt is not disabled for more -than 20 cycles. +than 25 cycles (this is for 12 MHz, faster clocks allow longer latency). +This implies that all interrupt routines must either have the "ISR_NOBLOCK" +attribute set (see "avr/interrupt.h") or be written in assembler with "sei" +as the first instruction. Maximum interrupt duration / CPU cycle consumption: The driver handles all USB communication during the interrupt service routine. The routine will not return before an entire USB message is received -and the reply is sent. This may be up to ca. 1200 cycles = 100us if the host -conforms to the standard. The driver will consume CPU cycles for all USB -messages, even if they address an other (low-speed) device on the same bus. +and the reply is sent. This may be up to ca. 1200 cycles @ 12 MHz (= 100us) if +the host conforms to the standard. The driver will consume CPU cycles for all +USB messages, even if they address another (low-speed) device on the same bus. */ @@ -108,140 +122,499 @@ messages, even if they address an other (low-speed) device on the same bus. /* --------------------------- Module Interface ---------------------------- */ /* ------------------------------------------------------------------------- */ -#ifndef __ASSEMBLER__ +#define USBDRV_VERSION 20100715 +/* This define uniquely identifies a driver version. It is a decimal number + * constructed from the driver's release date in the form YYYYMMDD. If the + * driver's behavior or interface changes, you can use this constant to + * distinguish versions. If it is not defined, the driver's release date is + * older than 2006-01-25. + */ + + +#ifndef USB_PUBLIC +#define USB_PUBLIC +#endif +/* USB_PUBLIC is used as declaration attribute for all functions exported by + * the USB driver. The default is no attribute (see above). You may define it + * to static either in usbconfig.h or from the command line if you include + * usbdrv.c instead of linking against it. Including the C module of the driver + * directly in your code saves a couple of bytes in flash memory. + */ +#ifndef __ASSEMBLER__ #ifndef uchar -#define uchar unsigned char +#define uchar unsigned char +#endif +#ifndef schar +#define schar signed char #endif +/* shortcuts for well defined 8 bit integer types */ -#if USB_CFG_HAVE_INTRIN_ENDPOINT -void usbSetInterrupt(uchar *data, uchar len); -/* This function sets the message which will be sent during the next interrupt - * IN transfer. The message is copied to an internal buffer and must not exceed - * a length of 7 bytes. The message may be 0 bytes long just to indicate the - * interrupt status to the host. - * If you need to transfer more bytes, use a control read after the interrupt. +#if USB_CFG_LONG_TRANSFERS /* if more than 254 bytes transfer size required */ +# define usbMsgLen_t unsigned +#else +# define usbMsgLen_t uchar +#endif +/* usbMsgLen_t is the data type used for transfer lengths. By default, it is + * defined to uchar, allowing a maximum of 254 bytes (255 is reserved for + * USB_NO_MSG below). If the usbconfig.h defines USB_CFG_LONG_TRANSFERS to 1, + * a 16 bit data type is used, allowing up to 16384 bytes (the rest is used + * for flags in the descriptor configuration). */ -#endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */ +#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */ + +struct usbRequest; /* forward declaration */ -extern void usbInit(void); +USB_PUBLIC void usbInit(void); /* This function must be called before interrupts are enabled and the main - * loop is entered. + * loop is entered. We exepct that the PORT and DDR bits for D+ and D- have + * not been changed from their default status (which is 0). If you have changed + * them, set both back to 0 (configure them as input with no internal pull-up). */ -extern void usbPoll(void); +USB_PUBLIC void usbPoll(void); /* This function must be called at regular intervals from the main loop. - * Maximum delay between calls is somewhat less than 50ms (USB timeout between - * packages of a message). + * Maximum delay between calls is somewhat less than 50ms (USB timeout for + * accepting a Setup message). Otherwise the device will not be recognized. + * Please note that debug outputs through the UART take ~ 0.5ms per byte + * at 19200 bps. */ -extern uchar *usbMsgPtr; +extern uchar *usbMsgPtr; /* This variable may be used to pass transmit data to the driver from the * implementation of usbFunctionWrite(). It is also used internally by the * driver for standard control requests. */ -extern uchar usbFunctionSetup(uchar data[8]); -/* This function is called for all setup requests which are not of type - * "Standard" (in practice: class and vendor requests). The 8 bytes setup - * data is passed in 'data'. Data for control-out transfers is passed to the - * application in separate calls to usbFunctionWrite() (unless you have turned - * this option off). You should store the setup context in global/static - * variables to have it available in usbFunctionWrite(). Data for control-in - * transfers can be provided in two ways: (1) immediately as a result of - * usbFunctionSetup() or (2) on demand of the driver in calls to the separate - * function usbFunctionRead() (if enabled). For (1) write the data to a static - * buffer, set the global variable 'usbMsgPtr' to this buffer and return the - * data length (may be 0). To implement (2), simply return 0xff (== -1) in - * usbFunctionSetup(). The driver will call usbFunctionRead() when data is - * needed. You may use 'usbMsgPtr' to save your own status in this case. - * The data passed in 'data' has the following content (see USB 1.1 spec): - * struct usbControlData{ - * uchar requestType; //[0] - * uchar request; //[1] - * unsigned value; //[2], [3] - * unsigned index; //[4], [5] - * unsigned length; //[6], [7] - * }; +USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]); +/* This function is called when the driver receives a SETUP transaction from + * the host which is not answered by the driver itself (in practice: class and + * vendor requests). All control transfers start with a SETUP transaction where + * the host communicates the parameters of the following (optional) data + * transfer. The SETUP data is available in the 'data' parameter which can + * (and should) be casted to 'usbRequest_t *' for a more user-friendly access + * to parameters. + * + * If the SETUP indicates a control-in transfer, you should provide the + * requested data to the driver. There are two ways to transfer this data: + * (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data + * block and return the length of the data in 'usbFunctionSetup()'. The driver + * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The + * driver will then call 'usbFunctionRead()' when data is needed. See the + * documentation for usbFunctionRead() for details. + * + * If the SETUP indicates a control-out transfer, the only way to receive the + * data from the host is through the 'usbFunctionWrite()' call. If you + * implement this function, you must return USB_NO_MSG in 'usbFunctionSetup()' + * to indicate that 'usbFunctionWrite()' should be used. See the documentation + * of this function for more information. If you just want to ignore the data + * sent by the host, return 0 in 'usbFunctionSetup()'. + * + * Note that calls to the functions usbFunctionRead() and usbFunctionWrite() + * are only done if enabled by the configuration in usbconfig.h. + */ +USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq); +/* You need to implement this function ONLY if you provide USB descriptors at + * runtime (which is an expert feature). It is very similar to + * usbFunctionSetup() above, but it is called only to request USB descriptor + * data. See the documentation of usbFunctionSetup() above for more info. + */ +#if USB_CFG_HAVE_INTRIN_ENDPOINT +USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len); +/* This function sets the message which will be sent during the next interrupt + * IN transfer. The message is copied to an internal buffer and must not exceed + * a length of 8 bytes. The message may be 0 bytes long just to indicate the + * interrupt status to the host. + * If you need to transfer more bytes, use a control read after the interrupt. + */ +#define usbInterruptIsReady() (usbTxLen1 & 0x10) +/* This macro indicates whether the last interrupt message has already been + * sent. If you set a new interrupt message before the old was sent, the + * message already buffered will be lost. + */ +#if USB_CFG_HAVE_INTRIN_ENDPOINT3 +USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len); +#define usbInterruptIsReady3() (usbTxLen3 & 0x10) +/* Same as above for endpoint 3 */ +#endif +#endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */ +#if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* simplified interface for backward compatibility */ +#define usbHidReportDescriptor usbDescriptorHidReport +/* should be declared as: PROGMEM char usbHidReportDescriptor[]; */ +/* If you implement an HID device, you need to provide a report descriptor. + * The HID report descriptor syntax is a bit complex. If you understand how + * report descriptors are constructed, we recommend that you use the HID + * Descriptor Tool from usb.org, see http://www.usb.org/developers/hidpage/. + * Otherwise you should probably start with a working example. */ +#endif /* USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH */ #if USB_CFG_IMPLEMENT_FN_WRITE -extern uchar usbFunctionWrite(uchar *data, uchar len); +USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len); /* This function is called by the driver to provide a control transfer's * payload data (control-out). It is called in chunks of up to 8 bytes. The * total count provided in the current control transfer can be obtained from * the 'length' property in the setup data. If an error occurred during * processing, return 0xff (== -1). The driver will answer the entire transfer - * with a STALL token in this case. Otherwise return any number which is not - * 0xff. NOTE: Only the return value of the LAST usbFunctionWrite() call - * (the one immediately before the status phase) is used. + * with a STALL token in this case. If you have received the entire payload + * successfully, return 1. If you expect more data, return 0. If you don't + * know whether the host will send more data (you should know, the total is + * provided in the usbFunctionSetup() call!), return 1. + * NOTE: If you return 0xff for STALL, 'usbFunctionWrite()' may still be called + * for the remaining data. You must continue to return 0xff for STALL in these + * calls. + * In order to get usbFunctionWrite() called, define USB_CFG_IMPLEMENT_FN_WRITE + * to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. */ #endif /* USB_CFG_IMPLEMENT_FN_WRITE */ #if USB_CFG_IMPLEMENT_FN_READ -extern uchar usbFunctionRead(uchar *data, uchar len); +USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len); /* This function is called by the driver to ask the application for a control - * transfer's payload data (control-in). You should supply up to 'len' bytes of - * data in this chunk. 'len' will be 8 bytes for all but the last chunk. If - * you return less than 8 bytes, the control transfer ends. If you return an - * invalid value (e.g. -1), the driver sends a STALL token. + * transfer's payload data (control-in). It is called in chunks of up to 8 + * bytes each. You should copy the data to the location given by 'data' and + * return the actual number of bytes copied. If you return less than requested, + * the control-in transfer is terminated. If you return 0xff, the driver aborts + * the transfer with a STALL token. + * In order to get usbFunctionRead() called, define USB_CFG_IMPLEMENT_FN_READ + * to 1 in usbconfig.h and return 0xff in usbFunctionSetup().. */ #endif /* USB_CFG_IMPLEMENT_FN_READ */ -extern unsigned usbCrc16(uchar *data, uchar len); + +extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */ +#if USB_CFG_IMPLEMENT_FN_WRITEOUT +USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len); +/* This function is called by the driver when data is received on an interrupt- + * or bulk-out endpoint. The endpoint number can be found in the global + * variable usbRxToken. You must define USB_CFG_IMPLEMENT_FN_WRITEOUT to 1 in + * usbconfig.h to get this function called. + */ +#endif /* USB_CFG_IMPLEMENT_FN_WRITEOUT */ +#ifdef USB_CFG_PULLUP_IOPORTNAME +#define usbDeviceConnect() ((USB_PULLUP_DDR |= (1<device, 1=device->host + * t ..... type: 0=standard, 1=class, 2=vendor, 3=reserved + * r ..... recipient: 0=device, 1=interface, 2=endpoint, 3=other + */ /* USB setup recipient values */ -#define USBRQ_RCPT_DEVICE 0 -#define USBRQ_RCPT_INTERFACE 1 -#define USBRQ_RCPT_ENDPOINT 2 +#define USBRQ_RCPT_MASK 0x1f +#define USBRQ_RCPT_DEVICE 0 +#define USBRQ_RCPT_INTERFACE 1 +#define USBRQ_RCPT_ENDPOINT 2 /* USB request type values */ -#define USBRQ_TYPE_STANDARD 0 -#define USBRQ_TYPE_CLASS 1 -#define USBRQ_TYPE_VENDOR 2 +#define USBRQ_TYPE_MASK 0x60 +#define USBRQ_TYPE_STANDARD (0<<5) +#define USBRQ_TYPE_CLASS (1<<5) +#define USBRQ_TYPE_VENDOR (2<<5) + +/* USB direction values: */ +#define USBRQ_DIR_MASK 0x80 +#define USBRQ_DIR_HOST_TO_DEVICE (0<<7) +#define USBRQ_DIR_DEVICE_TO_HOST (1<<7) + +/* USB Standard Requests */ +#define USBRQ_GET_STATUS 0 +#define USBRQ_CLEAR_FEATURE 1 +#define USBRQ_SET_FEATURE 3 +#define USBRQ_SET_ADDRESS 5 +#define USBRQ_GET_DESCRIPTOR 6 +#define USBRQ_SET_DESCRIPTOR 7 +#define USBRQ_GET_CONFIGURATION 8 +#define USBRQ_SET_CONFIGURATION 9 +#define USBRQ_GET_INTERFACE 10 +#define USBRQ_SET_INTERFACE 11 +#define USBRQ_SYNCH_FRAME 12 +/* USB descriptor constants */ +#define USBDESCR_DEVICE 1 +#define USBDESCR_CONFIG 2 +#define USBDESCR_STRING 3 +#define USBDESCR_INTERFACE 4 +#define USBDESCR_ENDPOINT 5 +#define USBDESCR_HID 0x21 +#define USBDESCR_HID_REPORT 0x22 +#define USBDESCR_HID_PHYS 0x23 + +//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more +#define USBATTR_SELFPOWER 0x40 +#define USBATTR_REMOTEWAKE 0x20 + +/* USB HID Requests */ +#define USBRQ_HID_GET_REPORT 0x01 +#define USBRQ_HID_GET_IDLE 0x02 +#define USBRQ_HID_GET_PROTOCOL 0x03 +#define USBRQ_HID_SET_REPORT 0x09 +#define USBRQ_HID_SET_IDLE 0x0a +#define USBRQ_HID_SET_PROTOCOL 0x0b /* ------------------------------------------------------------------------- */