diff --git a/TL866_Updater.X/18f87j50.lkr b/FirmwareDumper/18f87j50.lkr similarity index 100% rename from TL866_Updater.X/18f87j50.lkr rename to FirmwareDumper/18f87j50.lkr diff --git a/TL866_Updater.X/HardwareProfile.h b/FirmwareDumper/HardwareProfile.h similarity index 99% rename from TL866_Updater.X/HardwareProfile.h rename to FirmwareDumper/HardwareProfile.h index dbdfdab..5252c70 100644 --- a/TL866_Updater.X/HardwareProfile.h +++ b/FirmwareDumper/HardwareProfile.h @@ -55,5 +55,4 @@ #define CLOCK_FREQ 48000000 #define GetSystemClock() CLOCK_FREQ #define GetInstructionClock() CLOCK_FREQ - #endif diff --git a/TL866_Updater.X/Makefile b/FirmwareDumper/Makefile similarity index 100% rename from TL866_Updater.X/Makefile rename to FirmwareDumper/Makefile diff --git a/FirmwareDumper/USB/Compiler.h b/FirmwareDumper/USB/Compiler.h new file mode 100644 index 0000000..3a97af0 --- /dev/null +++ b/FirmwareDumper/USB/Compiler.h @@ -0,0 +1,218 @@ +/********************************************************************* + * + * Compiler and hardware specific definitions + * + ********************************************************************* + * FileName: Compiler.h + * Dependencies: None + * Processor: PIC10, PIC12, PIC16, PIC18, PIC24, dsPIC, PIC32 + * Compiler: Microchip C32 v2.02 or higher + * Microchip C30 v3.31 or higher + * Microchip C18 v3.40 or higher + * HI-TECH PICC-18 PRO 9.66 or higher + * HI-TECH PICC PRO V9.81 or higher + * Company: Microchip Technology, Inc. + * + * Software License Agreement + * + * Copyright (C) 2012 Microchip Technology Inc. All rights + * reserved. + * + * Microchip licenses to you the right to use, modify, copy, and + * distribute: + * (i) the Software when embedded on a Microchip microcontroller or + * digital signal controller product ("Device") which is + * integrated into Licensee's product; or + * (ii) ONLY the Software driver source files ENC28J60.c and + * ENC28J60.h ported to a non-Microchip device used in + * conjunction with a Microchip ethernet controller for the + * sole purpose of interfacing with the ethernet controller. + * + * You should refer to the license agreement accompanying this + * Software for additional information regarding your rights and + * obligations. + * + * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT + * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF + * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS + * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE + * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER + * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT + * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. + * + * + * Date Comment + *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * 10/03/2006 Original, copied from old Compiler.h + * 11/07/2007 Reorganized and simplified + * 03/31/2010 Removed dependency on WORD and DWORD typedefs + * 04/14/2010 Added defines to uniquely identify each compiler + * 10/13/2010 Added support for PIC10, PIC12, and PIC16 with PICC compiler + * 02/15/2012 Added re-define check for Nop, ClrWdt, Reset, Sleep + ********************************************************************/ +#ifndef __COMPILER_H +#define __COMPILER_H + +// Include proper device header file +#if defined(__18CXX) && !defined(HI_TECH_C) + // PIC18 processor with Microchip C18 compiler + #define COMPILER_MPLAB_C18 + #include +#elif defined(__PICC18__) && defined(HI_TECH_C) + // PIC18 processor with (Microchip) HI-TECH PICC-18 compiler + #if !defined(__18CXX) + #define __18CXX + #endif + #define COMPILER_HITECH_PICC18 + #include +#elif (defined(_PIC12) || defined(_PIC14) || defined(_PIC14E)) && defined(HI_TECH_C) + // PIC10/12/16 processor with (Microchip) HI-TECH PICC compiler + #define COMPILER_HITECH_PICC + #include +#elif (defined(__PIC24F__) || defined(__PIC24FK__)) && defined(__C30__) // Microchip C30 compiler + // PIC24F processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__PIC24H__) && defined(__C30__) // Microchip C30 compiler + // PIC24H processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__PIC24E__) && defined(__C30__) // Microchip C30 compiler + // PIC24E processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__dsPIC33F__) && defined(__C30__) // Microchip C30 compiler + // dsPIC33F processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__dsPIC33E__) && defined(__C30__) // Microchip C30 compiler + // dsPIC33E processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__dsPIC30F__) && defined(__C30__) // Microchip C30 compiler + // dsPIC30F processor + #define COMPILER_MPLAB_C30 + #include +#elif defined(__C30__) // Microchip C30 compiler, but targeting "generic-16bit" processor. + #define COMPILER_MPLAB_C30 + #include + // Define some useful inline assembly functions which are normally in the + // processor header files, but absent from the generic p30sim.h file. + #if !defined(Nop) + #define Nop() __builtin_nop() + #define ClrWdt() {__asm__ volatile ("clrwdt");} + #define Sleep() {__asm__ volatile ("pwrsav #0");} + #define Idle() {__asm__ volatile ("pwrsav #1");} + #endif +#elif defined(__PIC32MX__) // Microchip C32 compiler + #if !defined(__C32__) + #define __C32__ + #endif + #define COMPILER_MPLAB_C32 + #include + #include +#else + #error Unknown processor or compiler. See Compiler.h +#endif + +#include +#include +#include + + +// Base RAM and ROM pointer types for given architecture +#if defined(__PIC32MX__) + #define PTR_BASE unsigned long + #define ROM_PTR_BASE unsigned long +#elif defined(__C30__) + #define PTR_BASE unsigned short + #define ROM_PTR_BASE unsigned short +#elif defined(COMPILER_MPLAB_C18) + #define PTR_BASE unsigned short + #define ROM_PTR_BASE unsigned short long +#elif defined(COMPILER_HITECH_PICC18) + #define PTR_BASE unsigned short + #define ROM_PTR_BASE unsigned long +#endif + + +// Definitions that apply to all except Microchip MPLAB C Compiler for PIC18 MCUs (C18) +#if !defined(COMPILER_MPLAB_C18) + #define memcmppgm2ram(a,b,c) memcmp(a,b,c) + #define strcmppgm2ram(a,b) strcmp(a,b) + #define memcpypgm2ram(a,b,c) memcpy(a,b,c) + #define strcpypgm2ram(a,b) strcpy(a,b) + #define strncpypgm2ram(a,b,c) strncpy(a,b,c) + #define strstrrampgm(a,b) strstr(a,b) + #define strlenpgm(a) strlen(a) + #define strchrpgm(a,b) strchr(a,b) + #define strcatpgm2ram(a,b) strcat(a,b) +#endif + + +// Definitions that apply to all 8-bit products +// (PIC10, PIC12, PIC16, PIC18) +#if defined(__18CXX) || defined(COMPILER_HITECH_PICC) + #define __attribute__(a) + + #define FAR far + + // Microchip C18 specific defines + #if defined(COMPILER_MPLAB_C18) + #define ROM rom + #endif + + // HI TECH specific defines + #if defined(COMPILER_HITECH_PICC18) || defined(COMPILER_HITECH_PICC) + #define ROM const + #define rom + #ifndef Nop() + #define Nop() asm("NOP"); + #endif + #ifndef ClrWdt() + #define ClrWdt() asm("CLRWDT"); + #endif + #ifndef Reset() + #define Reset() asm("RESET"); + #endif + #ifndef Sleep() + #define Sleep() asm("SLEEP"); + #endif + #endif + +// Definitions that apply to all 16-bit and 32-bit products +// (PIC24F, PIC24H, dsPIC30F, dsPIC33F, and PIC32) +#else + #define ROM const + + // 16-bit specific defines (PIC24F, PIC24H, dsPIC30F, dsPIC33F) + #if defined(__C30__) + #define Reset() asm("reset") + #define FAR __attribute__((far)) + #endif + + // 32-bit specific defines (PIC32) + #if defined(__PIC32MX__) + #if (__C32_VERSION__ < 200) + #define persistent + #endif + #define far + #define FAR + #define Reset() SoftReset() + #define ClrWdt() (WDTCONSET = _WDTCON_WDTCLR_MASK) + + // MPLAB C Compiler for PIC32 MCUs version 1.04 and below don't have a + // Nop() function. However, version 1.05 has Nop() declared as _nop(). + #if !defined(Nop) && (__C32_VERSION__ <= 104) + #define Nop() asm("nop") + #endif + #endif +#endif + + + +#endif diff --git a/FirmwareDumper/USB/ReadMe b/FirmwareDumper/USB/ReadMe new file mode 100644 index 0000000..4f21293 --- /dev/null +++ b/FirmwareDumper/USB/ReadMe @@ -0,0 +1 @@ +Required Microchip USB stack from microchip solutions v2013-06-15 \ No newline at end of file diff --git a/FirmwareDumper/USB/usb.h b/FirmwareDumper/USB/usb.h new file mode 100644 index 0000000..7710710 --- /dev/null +++ b/FirmwareDumper/USB/usb.h @@ -0,0 +1,146 @@ +//DOM-IGNORE-BEGIN +/********************************************************************* + * The following lines are used by VDI. + * GUID=E537A0C0-6FEE-4afd-89B9-0C35BF72A80B + * GUIInterfaceVersion=1.00 + * LibraryVersion=2.4 + *********************************************************************/ +//DOM-IGNORE-END +/******************************************************************************* + + USB Header File + +Summary: + This file aggregates all necessary header files for the Microchip USB Host, + Device, and OTG libraries. It provides a single-file can be included in + application code. The USB libraries simplify the implementation of USB + applications by providing an abstraction of the USB module and its registers + and bits such that the source code for the can be the same across various + hardware platforms. + +Description: + This file aggregates all necessary header files for the Microchip USB Host, + Device, and OTG libraries. It provides a single-file can be included in + application code. The USB libraries simplify the implementation of USB + applications by providing an abstraction of the USB module and its registers + and bits such that the source code for the can be the same across various + hardware platforms. + + Note that this file does not include the header files for any client or + function drivers. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + + ..\\..\\Microchip\\Include + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + +******************************************************************************/ +/****************************************************************************** + FileName: usb.h + Dependencies: See INCLUDES section + Processor: PIC18, PIC24, & PIC32 USB Microcontrollers + Hardware: + Complier: Microchip C18 (for PIC18), C30 (for PIC24), or C32 (for PIC32) + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the "Company") for its PICmicro(r) Microcontroller is intended and + supplied to you, the Company's customer, for use solely and + exclusively on Microchip PICmicro Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. +********************************************************************/ +//DOM-IGNORE-END + +//DOM-IGNORE-BEGIN +/******************************************************************** + File Description: + + Change History: + Rev Description + ---------- ----------- + 2.6 - 2.9 No change except stack revision number +********************************************************************/ +//DOM-IGNORE-END + +#ifndef _USB_H_ +#define _USB_H_ +//DOM-IGNORE-END + + +// ***************************************************************************** +// ***************************************************************************** +// Section: All necessary USB Library headers +// ***************************************************************************** +// ***************************************************************************** + +#include "GenericTypeDefs.h" +#include "Compiler.h" + +#include "usb_config.h" // Must be defined by the application + +#include "USB/usb_common.h" // Common USB library definitions +#include "USB/usb_ch9.h" // USB device framework definitions + +#if defined( USB_SUPPORT_DEVICE ) + #include "USB/usb_device.h" // USB Device abstraction layer interface +#endif + +#if defined( USB_SUPPORT_HOST ) + #include "USB/usb_host.h" // USB Host abstraction layer interface +#endif + +#if defined ( USB_SUPPORT_OTG ) + #include "USB/usb_otg.h" +#endif + +#include "USB/usb_hal.h" // Hardware Abstraction Layer interface + +// ***************************************************************************** +// ***************************************************************************** +// Section: MCHPFSUSB Firmware Version +// ***************************************************************************** +// ***************************************************************************** + +#define USB_MAJOR_VER 2 // Firmware version, major release number. +#define USB_MINOR_VER 9 // Firmware version, minor release number. +#define USB_DOT_VER 0 // Firmware version, dot release number. + +#endif // _USB_H_ +/************************************************************************* + * EOF + */ + diff --git a/FirmwareDumper/USB/usb_ch9.h b/FirmwareDumper/USB/usb_ch9.h new file mode 100644 index 0000000..90321e5 --- /dev/null +++ b/FirmwareDumper/USB/usb_ch9.h @@ -0,0 +1,618 @@ +/******************************************************************************* + + USB Chapter 9 Protocol (Header File) + +Summary: + This file defines data structures, constants, and macros that are used to + to support the USB Device Framework protocol described in Chapter 9 of the + USB 2.0 specification. + +Description: + This file defines data structures, constants, and macros that are used to + to support the USB Device Framework protocol described in Chapter 9 of the + USB 2.0 specification. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + + ..\\..\\Microchip\\Include + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application +*******************************************************************************/ +//DOM-IGNORE-BEGIN +/******************************************************************************* + +* FileName: usb_ch9.h +* Dependencies: None +* Processor: PIC18/PIC24/PIC32MX microcontrollers with USB module +* Compiler: C18 v3.13+/C30 v2.01+/C32 v0.00.18+ +* Company: Microchip Technology, Inc. +* File Description: +* This file contains the definitions and prototypes used for +* specification chapter 9 compliance. + +Software License Agreement + +The software supplied herewith by Microchip Technology Incorporated +(the “Company”) for its PICmicro® Microcontroller is intended and +supplied to you, the Company’s customer, for use solely and +exclusively on Microchip PICmicro Microcontroller products. The +software is owned by the Company and/or its supplier, and is +protected under applicable copyright laws. All rights are reserved. +Any use in violation of the foregoing restrictions may subject the +user to criminal sanctions under applicable laws, as well as to +civil liability for the breach of the terms and conditions of this +license. + +THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, +WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED +TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, +IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + +*******************************************************************************/ +//DOM-IGNORE-END + +//DOM-IGNORE-BEGIN +/******************************************************************** + Change History: + Rev Description + ---- ----------- + 2.6 Moved many of the CH9 defintions from the device stack files + into this file. +********************************************************************/ +//DOM-IGNORE-END + +//DOM-IGNORE-BEGIN +#ifndef _USB_CH9_H_ +#define _USB_CH9_H_ +//DOM-IGNORE-END + + +// ***************************************************************************** +// ***************************************************************************** +// Section: USB Descriptors +// ***************************************************************************** +// ***************************************************************************** + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +// ***************************************************************************** +/* USB Device Descriptor Structure + +This struct defines the structure of a USB Device Descriptor. Note that this +structure may need to be packed, or even accessed as bytes, to properly access +the correct fields when used on some device architectures. +*/ +typedef struct __attribute__ ((packed)) _USB_DEVICE_DESCRIPTOR +{ + BYTE bLength; // Length of this descriptor. + BYTE bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + WORD bcdUSB; // USB Spec Release Number (BCD). + BYTE bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + BYTE bDeviceSubClass; // Subclass code (assigned by the USB-IF). + BYTE bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + BYTE bMaxPacketSize0; // Maximum packet size for endpoint 0. + WORD idVendor; // Vendor ID (assigned by the USB-IF). + WORD idProduct; // Product ID (assigned by the manufacturer). + WORD bcdDevice; // Device release number (BCD). + BYTE iManufacturer; // Index of String Descriptor describing the manufacturer. + BYTE iProduct; // Index of String Descriptor describing the product. + BYTE iSerialNumber; // Index of String Descriptor with the device's serial number. + BYTE bNumConfigurations; // Number of possible configurations. +} USB_DEVICE_DESCRIPTOR; + + +// ***************************************************************************** +/* USB Configuration Descriptor Structure + +This struct defines the structure of a USB Configuration Descriptor. Note that this +structure may need to be packed, or even accessed as bytes, to properly access +the correct fields when used on some device architectures. +*/ +typedef struct __attribute__ ((packed)) _USB_CONFIGURATION_DESCRIPTOR +{ + BYTE bLength; // Length of this descriptor. + BYTE bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + WORD wTotalLength; // Total length of all descriptors for this configuration. + BYTE bNumInterfaces; // Number of interfaces in this configuration. + BYTE bConfigurationValue; // Value of this configuration (1 based). + BYTE iConfiguration; // Index of String Descriptor describing the configuration. + BYTE bmAttributes; // Configuration characteristics. + BYTE bMaxPower; // Maximum power consumed by this configuration. +} USB_CONFIGURATION_DESCRIPTOR; + +// Attributes bits +#define USB_CFG_DSC_REQUIRED 0x80 // Required attribute +#define USB_CFG_DSC_SELF_PWR (0x40|USB_CFG_DSC_REQUIRED) // Device is self powered. +#define USB_CFG_DSC_REM_WAKE (0x20|USB_CFG_DSC_REQUIRED) // Device can request remote wakup + + +// ***************************************************************************** +/* USB Interface Descriptor Structure + +This struct defines the structure of a USB Interface Descriptor. Note that this +structure may need to be packed, or even accessed as bytes, to properly access +the correct fields when used on some device architectures. +*/ +typedef struct __attribute__ ((packed)) _USB_INTERFACE_DESCRIPTOR +{ + BYTE bLength; // Length of this descriptor. + BYTE bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + BYTE bInterfaceNumber; // Number of this interface (0 based). + BYTE bAlternateSetting; // Value of this alternate interface setting. + BYTE bNumEndpoints; // Number of endpoints in this interface. + BYTE bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + BYTE bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + BYTE bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + BYTE iInterface; // Index of String Descriptor describing the interface. +} USB_INTERFACE_DESCRIPTOR; + + +// ***************************************************************************** +/* USB Endpoint Descriptor Structure + +This struct defines the structure of a USB Endpoint Descriptor. Note that this +structure may need to be packed, or even accessed as bytes, to properly access +the correct fields when used on some device architectures. +*/ +typedef struct __attribute__ ((packed)) _USB_ENDPOINT_DESCRIPTOR +{ + BYTE bLength; // Length of this descriptor. + BYTE bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + BYTE bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + BYTE bmAttributes; // Endpoint transfer type. + WORD wMaxPacketSize; // Maximum packet size. + BYTE bInterval; // Polling interval in frames. +} USB_ENDPOINT_DESCRIPTOR; + + +// Endpoint Direction +#define EP_DIR_IN 0x80 // Data flows from device to host +#define EP_DIR_OUT 0x00 // Data flows from host to device + + +// ****************************************************************** +// USB Endpoint Attributes +// ****************************************************************** + +// Section: Transfer Types +#define EP_ATTR_CONTROL (0<<0) // Endoint used for control transfers +#define EP_ATTR_ISOCH (1<<0) // Endpoint used for isochronous transfers +#define EP_ATTR_BULK (2<<0) // Endpoint used for bulk transfers +#define EP_ATTR_INTR (3<<0) // Endpoint used for interrupt transfers + +// Section: Synchronization Types (for isochronous enpoints) +#define EP_ATTR_NO_SYNC (0<<2) // No Synchronization +#define EP_ATTR_ASYNC (1<<2) // Asynchronous +#define EP_ATTR_ADAPT (2<<2) // Adaptive synchronization +#define EP_ATTR_SYNC (3<<2) // Synchronous + +// Section: Usage Types (for isochronous endpoints) +#define EP_ATTR_DATA (0<<4) // Data Endpoint +#define EP_ATTR_FEEDBACK (1<<4) // Feedback endpoint +#define EP_ATTR_IMP_FB (2<<4) // Implicit Feedback data EP + +// Section: Max Packet Sizes +#define EP_MAX_PKT_INTR_LS 8 // Max low-speed interrupt packet +#define EP_MAX_PKT_INTR_FS 64 // Max full-speed interrupt packet +#define EP_MAX_PKT_ISOCH_FS 1023 // Max full-speed isochronous packet +#define EP_MAX_PKT_BULK_FS 64 // Max full-speed bulk packet +#define EP_LG_PKT_BULK_FS 32 // Large full-speed bulk packet +#define EP_MED_PKT_BULK_FS 16 // Medium full-speed bulk packet +#define EP_SM_PKT_BULK_FS 8 // Small full-speed bulk packet + +/* Descriptor IDs +The descriptor ID type defines the information required by the HOST during a +GET_DESCRIPTOR request +*/ +typedef struct +{ + BYTE index; + BYTE type; + UINT16 language_id; + +} DESCRIPTOR_ID; + +// ***************************************************************************** +/* USB OTG Descriptor Structure + +This struct defines the structure of a USB OTG Descriptor. Note that this +structure may need to be packed, or even accessed as bytes, to properly access +the correct fields when used on some device architectures. +*/ +typedef struct __attribute__ ((packed)) _USB_OTG_DESCRIPTOR +{ + BYTE bLength; // Length of this descriptor. + BYTE bDescriptorType; // OTG descriptor type (USB_DESCRIPTOR_OTG). + BYTE bmAttributes; // OTG attributes. +} USB_OTG_DESCRIPTOR; + + +// ****************************************************************** +// Section: USB String Descriptor Structure +// ****************************************************************** +// This structure describes the USB string descriptor. The string +// descriptor provides user-readable information about various aspects of +// the device. The first string desriptor (string descriptor zero (0)), +// provides a list of the number of languages supported by the set of +// string descriptors for this device instead of an actual string. +// +// Note: The strings are in 2-byte-per-character unicode, not ASCII. +// +// Note: This structure only describes the "header" of the string +// descriptor. The actual data (either the language ID array or the +// array of unicode characters making up the string, must be allocated +// immediately following this header with no padding between them. + +typedef struct __attribute__ ((packed)) _USB_STRING_DSC +{ + BYTE bLength; // Size of this descriptor + BYTE bDescriptorType; // Type, USB_DSC_STRING + +} USB_STRING_DESCRIPTOR; + + +// ****************************************************************** +// Section: USB Device Qualifier Descriptor Structure +// ****************************************************************** +// This structure describes the device qualifier descriptor. The device +// qualifier descriptor provides overall device information if the device +// supports "other" speeds. +// +// Note: A high-speed device may support "other" speeds (ie. full or low). +// If so, it may need to implement the the device qualifier and other +// speed descriptors. + +typedef struct __attribute__ ((packed)) _USB_DEVICE_QUALIFIER_DESCRIPTOR +{ + BYTE bLength; // Size of this descriptor + BYTE bType; // Type, always USB_DESCRIPTOR_DEVICE_QUALIFIER + WORD bcdUSB; // USB spec version, in BCD + BYTE bDeviceClass; // Device class code + BYTE bDeviceSubClass; // Device sub-class code + BYTE bDeviceProtocol; // Device protocol + BYTE bMaxPacketSize0; // EP0, max packet size + BYTE bNumConfigurations; // Number of "other-speed" configurations + BYTE bReserved; // Always zero (0) + +} USB_DEVICE_QUALIFIER_DESCRIPTOR; + +// ****************************************************************** +// Section: USB Setup Packet Structure +// ****************************************************************** +// This structure describes the data contained in a USB standard device +// request's setup packet. It is the data packet sent from the host to +// the device to control and configure the device. +// +// Note: Refer to the USB 2.0 specification for additional details on the +// usage of the setup packet and standard device requests. +typedef union __attribute__ ((packed)) +{ + /** Standard Device Requests ***********************************/ + struct __attribute__ ((packed)) + { + BYTE bmRequestType; //from table 9-2 of USB2.0 spec + BYTE bRequest; //from table 9-2 of USB2.0 spec + WORD wValue; //from table 9-2 of USB2.0 spec + WORD wIndex; //from table 9-2 of USB2.0 spec + WORD wLength; //from table 9-2 of USB2.0 spec + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + WORD_VAL W_Value; //from table 9-2 of USB2.0 spec, allows byte/bitwise access + WORD_VAL W_Index; //from table 9-2 of USB2.0 spec, allows byte/bitwise access + WORD_VAL W_Length; //from table 9-2 of USB2.0 spec, allows byte/bitwise access + }; + struct __attribute__ ((packed)) + { + unsigned Recipient:5; //Device,Interface,Endpoint,Other + unsigned RequestType:2; //Standard,Class,Vendor,Reserved + unsigned DataDir:1; //Host-to-device,Device-to-host + unsigned :8; + BYTE bFeature; //DEVICE_REMOTE_WAKEUP,ENDPOINT_HALT + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + union // offset description + { // ------ ------------------------ + BYTE bmRequestType; // 0 Bit-map of request type + struct + { + BYTE recipient: 5; // Recipient of the request + BYTE type: 2; // Type of request + BYTE direction: 1; // Direction of data X-fer + }; + }requestInfo; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + BYTE bDscIndex; //For Configuration and String DSC Only + BYTE bDescriptorType; //Device,Configuration,String + WORD wLangID; //Language ID + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + BYTE_VAL bDevADR; //Device Address 0-127 + BYTE bDevADRH; //Must equal zero + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + BYTE bConfigurationValue; //Configuration Value 0-255 + BYTE bCfgRSD; //Must equal zero (Reserved) + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + BYTE bAltID; //Alternate Setting Value 0-255 + BYTE bAltID_H; //Must equal zero + BYTE bIntfID; //Interface Number Value 0-255 + BYTE bIntfID_H; //Must equal zero + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + BYTE bEPID; //Endpoint ID (Number & Direction) + BYTE bEPID_H; //Must equal zero + unsigned :8; + unsigned :8; + }; + struct __attribute__ ((packed)) + { + unsigned :8; + unsigned :8; + unsigned :8; + unsigned :8; + unsigned EPNum:4; //Endpoint Number 0-15 + unsigned :3; + unsigned EPDir:1; //Endpoint Direction: 0-OUT, 1-IN + unsigned :8; + unsigned :8; + unsigned :8; + }; + + /** End: Standard Device Requests ******************************/ + +} CTRL_TRF_SETUP, SETUP_PKT, *PSETUP_PKT; + + +// ****************************************************************** +// ****************************************************************** +// Section: USB Specification Constants +// ****************************************************************** +// ****************************************************************** + +// Section: Valid PID Values +//DOM-IGNORE-BEGIN +#define PID_OUT 0x1 // PID for an OUT token +#define PID_ACK 0x2 // PID for an ACK handshake +#define PID_DATA0 0x3 // PID for DATA0 data +#define PID_PING 0x4 // Special PID PING +#define PID_SOF 0x5 // PID for a SOF token +#define PID_NYET 0x6 // PID for a NYET handshake +#define PID_DATA2 0x7 // PID for DATA2 data +#define PID_SPLIT 0x8 // Special PID SPLIT +#define PID_IN 0x9 // PID for a IN token +#define PID_NAK 0xA // PID for a NAK handshake +#define PID_DATA1 0xB // PID for DATA1 data +#define PID_PRE 0xC // Special PID PRE (Same as PID_ERR) +#define PID_ERR 0xC // Special PID ERR (Same as PID_PRE) +#define PID_SETUP 0xD // PID for a SETUP token +#define PID_STALL 0xE // PID for a STALL handshake +#define PID_MDATA 0xF // PID for MDATA data + +#define PID_MASK_DATA 0x03 // Data PID mask +#define PID_MASK_DATA_SHIFTED (PID_MASK_DATA << 2) // Data PID shift to proper position +//DOM-IGNORE-END + +// Section: USB Token Types +//DOM-IGNORE-BEGIN +#define USB_TOKEN_OUT 0x01 // U1TOK - OUT token +#define USB_TOKEN_IN 0x09 // U1TOK - IN token +#define USB_TOKEN_SETUP 0x0D // U1TOK - SETUP token +//DOM-IGNORE-END + +// Section: OTG Descriptor Constants + +#define OTG_HNP_SUPPORT 0x02 // OTG Descriptor bmAttributes - HNP support flag +#define OTG_SRP_SUPPORT 0x01 // OTG Descriptor bmAttributes - SRP support flag + +// Section: Endpoint Directions + +#define USB_IN_EP 0x80 // IN endpoint mask +#define USB_OUT_EP 0x00 // OUT endpoint mask + +// Section: Standard Device Requests + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +// Section: Setup Data Constants + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +#define USB_SETUP_HOST_TO_DEVICE_BITFIELD (USB_SETUP_HOST_TO_DEVICE>>7) // Device Request bmRequestType transfer direction - host to device transfer - bit definition +#define USB_SETUP_DEVICE_TO_HOST_BITFIELD (USB_SETUP_DEVICE_TO_HOST>>7) // Device Request bmRequestType transfer direction - device to host transfer - bit definition +#define USB_SETUP_TYPE_STANDARD_BITFIELD (USB_SETUP_TYPE_STANDARD>>5) // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS_BITFIELD (USB_SETUP_TYPE_CLASS>>5) // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR_BITFIELD (USB_SETUP_TYPE_VENDOR>>5) // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE_BITFIELD (USB_SETUP_RECIPIENT_DEVICE) // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE_BITFIELD (USB_SETUP_RECIPIENT_INTERFACE) // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT_BITFIELD (USB_SETUP_RECIPIENT_ENDPOINT) // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER_BITFIELD (USB_SETUP_RECIPIENT_OTHER) // Device Request bmRequestType recipient - other + +// Section: OTG SET FEATURE Constants + +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +// Section: USB Endpoint Transfer Types + +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. + +// Section: Standard Feature Selectors for CLEAR_FEATURE Requests +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient + + +// Section: USB Class Code Definitions +#define USB_HUB_CLASSCODE 0x09 // Class code for a hub. + +/******************************************************************** +USB Endpoint Definitions +USB Standard EP Address Format: DIR:X:X:X:EP3:EP2:EP1:EP0 +This is used in the descriptors. +********************************************************************/ +#define _EP_IN 0x80 +#define _EP_OUT 0x00 +#define _EP01_OUT 0x01 +#define _EP01_IN 0x81 +#define _EP02_OUT 0x02 +#define _EP02_IN 0x82 +#define _EP03_OUT 0x03 +#define _EP03_IN 0x83 +#define _EP04_OUT 0x04 +#define _EP04_IN 0x84 +#define _EP05_OUT 0x05 +#define _EP05_IN 0x85 +#define _EP06_OUT 0x06 +#define _EP06_IN 0x86 +#define _EP07_OUT 0x07 +#define _EP07_IN 0x87 +#define _EP08_OUT 0x08 +#define _EP08_IN 0x88 +#define _EP09_OUT 0x09 +#define _EP09_IN 0x89 +#define _EP10_OUT 0x0A +#define _EP10_IN 0x8A +#define _EP11_OUT 0x0B +#define _EP11_IN 0x8B +#define _EP12_OUT 0x0C +#define _EP12_IN 0x8C +#define _EP13_OUT 0x0D +#define _EP13_IN 0x8D +#define _EP14_OUT 0x0E +#define _EP14_IN 0x8E +#define _EP15_OUT 0x0F +#define _EP15_IN 0x8F + +/* Configuration Attributes */ +#define _DEFAULT (0x01<<7) //Default Value (Bit 7 is set) +#define _SELF (0x01<<6) //Self-powered (Supports if set) +#define _RWU (0x01<<5) //Remote Wakeup (Supports if set) +#define _HNP (0x01 << 1) //HNP (Supports if set) +#define _SRP (0x01) //SRP (Supports if set) + +/* Endpoint Transfer Type */ +#define _CTRL 0x00 //Control Transfer +#define _ISO 0x01 //Isochronous Transfer +#define _BULK 0x02 //Bulk Transfer + +#define _INTERRUPT 0x03 //Interrupt Transfer +#if defined(__18CXX) || defined(__C30__) || defined __XC16__ + #define _INT 0x03 //Interrupt Transfer +#endif + +/* Isochronous Endpoint Synchronization Type */ +#define _NS (0x00<<2) //No Synchronization +#define _AS (0x01<<2) //Asynchronous +#define _AD (0x02<<2) //Adaptive +#define _SY (0x03<<2) //Synchronous + +/* Isochronous Endpoint Usage Type */ +#define _DE (0x00<<4) //Data endpoint +#define _FE (0x01<<4) //Feedback endpoint +#define _IE (0x02<<4) //Implicit feedback Data endpoint + +//These are the directional indicators used for the USBTransferOnePacket() +// function. +#define OUT_FROM_HOST 0 +#define IN_TO_HOST 1 + +#endif // _USB_CH9_H_ +/************************************************************************* + * EOF + */ + diff --git a/FirmwareDumper/USB/usb_common.h b/FirmwareDumper/USB/usb_common.h new file mode 100644 index 0000000..25b0921 --- /dev/null +++ b/FirmwareDumper/USB/usb_common.h @@ -0,0 +1,601 @@ +/****************************************************************************** + + Common USB Library Definitions (Header File) + +Summary: + This file defines data types, constants, and macros that are common to + multiple layers of the Microchip USB Firmware Stack. + +Description: + This file defines data types, constants, and macros that are common to + multiple layers of the Microchip USB Firmware Stack. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + ..\\..\\MicrochipInclude + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application +*******************************************************************************/ +//DOM-IGNORE-BEGIN +/******************************************************************************* + + FileName: usb_common.h + Dependencies: See included files, below. + Processor: PIC18/PIC24/PIC32MX microcontrollers with USB module + Compiler: C18 v3.13+/C30 v2.01+/C32 v0.00.18+ + Company: Microchip Technology, Inc. + +Software License Agreement + +The software supplied herewith by Microchip Technology Incorporated +(the “Company”) for its PICmicro® Microcontroller is intended and +supplied to you, the Company’s customer, for use solely and +exclusively on Microchip PICmicro Microcontroller products. The +software is owned by the Company and/or its supplier, and is +protected under applicable copyright laws. All rights are reserved. +Any use in violation of the foregoing restrictions may subject the +user to criminal sanctions under applicable laws, as well as to +civil liability for the breach of the terms and conditions of this +license. + +THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, +WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED +TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, +IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + +*******************************************************************************/ +//DOM-IGNORE-END + +//DOM-IGNORE-BEGIN +/******************************************************************** + Change History: + Rev Description + ---- ----------- + 2.6 Moved many of the USB events + 2.6a Changed the limit of USB_EVENT from UINT_MAX to INT_MAX + 2.7 No change +********************************************************************/ +//DOM-IGNORE-END + + +//DOM-IGNORE-BEGIN +#ifndef _USB_COMMON_H_ +#define _USB_COMMON_H_ +//DOM-IGNORE-END + +#include + +// ***************************************************************************** +// ***************************************************************************** +// Section: USB Constants +// ***************************************************************************** +// ***************************************************************************** + +// Section: Error Code Values + +#define USB_SUCCESS 0x00 // USB operation successful. +#define USB_INVALID_STATE 0x01 // Operation cannot be performed in current state. +#define USB_BUSY 0x02 // A transaction is already in progress. +#define USB_ILLEGAL_REQUEST 0x03 // Cannot perform requested operation. +#define USB_INVALID_CONFIGURATION 0x04 // Configuration descriptor not found. +#define USB_MEMORY_ALLOCATION_ERROR 0x05 // Out of dynamic memory. +#define USB_UNKNOWN_DEVICE 0x06 // Device with specified address is not attached. +#define USB_CANNOT_ENUMERATE 0x07 // Cannot enumerate the attached device. +#define USB_EVENT_QUEUE_FULL 0x08 // Event queue was full when an event occured. +#define USB_ENDPOINT_BUSY 0x10 // Endpoint is currently processing a transaction. +#define USB_ENDPOINT_STALLED 0x11 // Endpoint is currently stalled. User must clear the condition. +#define USB_ENDPOINT_ERROR 0x12 // Will need more than this eventually +#define USB_ENDPOINT_ERROR_ILLEGAL_PID 0x13 // Illegal PID received. +#define USB_ENDPOINT_NOT_FOUND 0x14 // Requested endpoint does not exist on device. +#define USB_ENDPOINT_ILLEGAL_DIRECTION 0x15 // Reads must be performe on IN endpoints, writes on OUT endpoints. +//#define USB_ENDPOINT_TRANSACTION_IN_PROGRESS 0x16 +#define USB_ENDPOINT_NAK_TIMEOUT 0x17 // Too many NAK's occurred while waiting for the current transaction. +#define USB_ENDPOINT_ILLEGAL_TYPE 0x18 // Transfer type must match endpoint description. +#define USB_ENDPOINT_UNRESOLVED_STATE 0x19 // Endpoint is in an unknown state after completing a transaction. +#define USB_ENDPOINT_ERROR_BIT_STUFF 0x20 // USB Module - Bit stuff error. +#define USB_ENDPOINT_ERROR_DMA 0x21 // USB Module - DMA error. +#define USB_ENDPOINT_ERROR_TIMEOUT 0x22 // USB Module - Bus timeout. +#define USB_ENDPOINT_ERROR_DATA_FIELD 0x23 // USB Module - Data field size error. +#define USB_ENDPOINT_ERROR_CRC16 0x24 // USB Module - CRC16 failure. +#define USB_ENDPOINT_ERROR_END_OF_FRAME 0x25 // USB Module - End of Frame error. +#define USB_ENDPOINT_ERROR_PID_CHECK 0x26 // USB Module - Illegal PID received. +#define USB_ENDPOINT_ERROR_BMX 0x27 // USB Module - Bus Matrix error. +#define USB_ERROR_INSUFFICIENT_POWER 0x28 // Too much power was requested + +// Section: Return values for USBHostDeviceStatus() + +#define USB_DEVICE_STATUS 0x30 // Offset for USBHostDeviceStatus() return codes +#define USB_DEVICE_ATTACHED (USB_DEVICE_STATUS | 0x30) // Device is attached and running +#define USB_DEVICE_DETACHED (USB_DEVICE_STATUS | 0x01) // No device is attached +#define USB_DEVICE_ENUMERATING (USB_DEVICE_STATUS | 0x02) // Device is enumerating +#define USB_HOLDING_OUT_OF_MEMORY (USB_DEVICE_STATUS | 0x03) // Not enough heap space available +#define USB_HOLDING_UNSUPPORTED_DEVICE (USB_DEVICE_STATUS | 0x04) // Invalid configuration or unsupported class +#define USB_HOLDING_UNSUPPORTED_HUB (USB_DEVICE_STATUS | 0x05) // Hubs are not supported +#define USB_HOLDING_INVALID_CONFIGURATION (USB_DEVICE_STATUS | 0x06) // Invalid configuration requested +#define USB_HOLDING_PROCESSING_CAPACITY (USB_DEVICE_STATUS | 0x07) // Processing requirement excessive +#define USB_HOLDING_POWER_REQUIREMENT (USB_DEVICE_STATUS | 0x08) // Power requirement excessive +#define USB_HOLDING_CLIENT_INIT_ERROR (USB_DEVICE_STATUS | 0x09) // Client driver failed to initialize +#define USB_DEVICE_SUSPENDED (USB_DEVICE_STATUS | 0x0A) // Device is suspended + +#define USB_ERROR_CLASS_DEFINED 0x50 // Offset for application defined errors + +#define USB_SINGLE_DEVICE_ADDRESS 0x01 // Default USB device address (single device support) + + +// ***************************************************************************** +// ***************************************************************************** +// Section: USB Data Types +// ***************************************************************************** +// ***************************************************************************** + +// ***************************************************************************** +/* Data Transfer Flags + +The following flags are used in the flags parameter of the "USBDEVTransferData" +and "USBHALTransferData" routines. They can be accessed by the bitfield +definitions or the macros can be OR'd together to identify the endpoint number +and properties of the data transfer. + + + 7 6 5 4 3 2 1 0 - Field name + | | | | \_____/ + | | | | +----- ep_num - Endpoint number + | | | +---------- zero_pkt - End transfer with short or zero-sized packet + | | +------------ dts - 0=DATA0 packet, 1=DATA1 packet + | +-------------- force_dts - Force data toggle sync to match dts field + +---------------- direction - Transfer direction: 0=Receive, 1=Transmit + +*/ + +typedef union +{ + BYTE bitmap; + struct + { + BYTE ep_num: 4; + BYTE zero_pkt: 1; + BYTE dts: 1; + BYTE force_dts: 1; + BYTE direction: 1; + }field; + +} TRANSFER_FLAGS; + +// ***************************************************************************** +/* Data Transfer Flags, Endpoint Number Constants + +These macros can be used as values for the "ep_num" field of the TRANSFER_FLAGS +data type. +*/ +#define USB_EP0 0 // +#define USB_EP1 1 // +#define USB_EP2 2 // +#define USB_EP3 3 // +#define USB_EP4 4 // +#define USB_EP5 5 // +#define USB_EP6 6 // +#define USB_EP7 7 // +#define USB_EP8 8 // +#define USB_EP9 9 // +#define USB_EP10 10 // +#define USB_EP11 11 // +#define USB_EP12 12 // +#define USB_EP13 13 // +#define USB_EP14 14 // +#define USB_EP15 15 // + +// ***************************************************************************** +/* Data Transfer Flags, Bitmap Constants + +These macros can be used as values for the "bitmap" field of the TRANSFER_FLAGS +data type. +*/ +#define USB_TRANSMIT 0x80 // Data will be transmitted to the USB +#define USB_RECEIVE 0x00 // Data will be received from the USB +#define USB_FORCE_DTS 0x40 // Forces data toggle sync as below: +#define USB_DTS_MASK 0x20 // Mask for DTS bit (below) +#define USB_ZERO_PKT 0x10 // End transfer w/a short or zero-length packet +#define USB_DATA0 0x00|USB_FORCE_DTS // Force DATA0 +#define USB_DATA1 0x20|USB_FORCE_DTS // Force DATA1 +#define USB_SETUP_PKT USB_RECEIVE|USB_DATA0|USB_EP0 // Setup Packet +#define USB_SETUP_DATA USB_DATA1|USB_ZERO_PKT|USB_EP0 // Setup-transfer Data Packet +#define USB_SETUP_STATUS USB_DATA1|USB_EP0 // Setup-transfer Status Packet +#define USB_EP_NUM_MASK 0x0F // Endpoint number (ep_num) mask + +// ***************************************************************************** +/* Data Transfer Flags, Initialization Macro + +This macro can be used with the above bitmap constants to initialize a +TRANSFER_FLAGS value. It provides the correct data type to avoid compiler +warnings. +*/ +#define XFLAGS(f) ((TRANSFER_FLAGS)((BYTE)(f))) // Initialization Macro + + +// ***************************************************************************** +/* USB Events + +This enumeration identifies USB events that occur. It is used to +inform USB drivers and applications of events on the bus. It is passed +as a parameter to the event-handling routine, which must match the +prototype of the USB_CLIENT_EVENT_HANDLER data type, when an event occurs. +*/ + +typedef enum +{ + // No event occured (NULL event) + EVENT_NONE = 0, + + EVENT_DEVICE_STACK_BASE = 1, + + EVENT_HOST_STACK_BASE = 100, + + // A USB hub has been attached. Hub support is not currently available. + EVENT_HUB_ATTACH, + + // A stall has occured. This event is not used by the Host stack. + EVENT_STALL, + + // VBus SRP Pulse, (VBus > 2.0v), Data: BYTE Port Number (For future support) + EVENT_VBUS_SES_REQUEST, + + // The voltage on Vbus has dropped below 4.4V/4.7V. The application is + // responsible for monitoring Vbus and calling USBHostVbusEvent() with this + // event. This event is not generated by the stack. + EVENT_VBUS_OVERCURRENT, + + // An enumerating device is requesting power. The data associated with this + // event is of the data type USB_VBUS_POWER_EVENT_DATA. Note that + // the requested current is specified in 2mA units, identical to the power + // specification in a device's Configuration Descriptor. + EVENT_VBUS_REQUEST_POWER, + + // Release power from a detaching device. The data associated with this + // event is of the data type USB_VBUS_POWER_EVENT_DATA. The current value + // specified in the data can be ignored. + EVENT_VBUS_RELEASE_POWER, + + // The voltage on Vbus is good, and the USB OTG module can be powered on. + // The application is responsible for monitoring Vbus and calling + // USBHostVbusEvent() with this event. This event is not generated by the + // stack. If the application issues an EVENT_VBUS_OVERCURRENT, then no + // power will be applied to that port, and no device can attach to that + // port, until the application issues the EVENT_VBUS_POWER_AVAILABLE for + // the port. + EVENT_VBUS_POWER_AVAILABLE, + + // The attached device is not supported by the application. The attached + // device is not allowed to enumerate. + EVENT_UNSUPPORTED_DEVICE, + + // Cannot enumerate the attached device. This is generated if communication + // errors prevent the device from enumerating. + EVENT_CANNOT_ENUMERATE, + + // The client driver cannot initialize the the attached device. The + // attached is not allowed to enumerate. + EVENT_CLIENT_INIT_ERROR, + + // The Host stack does not have enough heap space to enumerate the device. + // Check the amount of heap space allocated to the application. In MPLAB, + // select Project> Build Options...> Project. Select the appropriate + // linker tab, and inspect the "Heap size" entry. + EVENT_OUT_OF_MEMORY, + + // Unspecified host error. (This error should not occur). + EVENT_UNSPECIFIED_ERROR, + + // USB cable has been detached. The data associated with this event is the + // address of detached device, a single BYTE. + EVENT_DETACH, + + // A USB transfer has completed. The data associated with this event is of + // the data type HOST_TRANSFER_DATA if the event is generated from the host + // stack. + EVENT_TRANSFER, + + // A USB Start of Frame token has been received. This event is not + // used by the Host stack. + EVENT_SOF, + + // Device-mode resume received. This event is not used by the Host stack. + EVENT_RESUME, + + // Device-mode suspend/idle event received. This event is not used by the + // Host stack. + EVENT_SUSPEND, + + // Device-mode bus reset received. This event is not used by the Host + // stack. + EVENT_RESET, + + // In Host mode, an isochronous data read has completed. This event will only + // be passed to the DataEventHandler, which is only utilized if it is defined. + // Note that the DataEventHandler is called from within the USB interrupt, so + // it is critical that it return in time for the next isochronous data packet. + EVENT_DATA_ISOC_READ, + + // In Host mode, an isochronous data write has completed. This event will only + // be passed to the DataEventHandler, which is only utilized if it is defined. + // Note that the DataEventHandler is called from within the USB interrupt, so + // it is critical that it return in time for the next isochronous data packet. + EVENT_DATA_ISOC_WRITE, + + // In Host mode, this event gives the application layer the option to reject + // a client driver that was selected by the stack. This is needed when multiple + // devices are supported by class level support, but one configuration and client + // driver is preferred over another. Since configuration number is not guaranteed, + // the stack cannot do this automatically. This event is issued only when + // looking through configuration descriptors; the driver selected at the device + // level cannot be overridden, since there shouldn't be any other options to + // choose from. + EVENT_OVERRIDE_CLIENT_DRIVER_SELECTION, + + // In host mode, this event is thrown for every millisecond that passes. Like all + // events, this is thrown from the USBHostTasks() or USBTasks() routine so its + // timeliness will be determined by the rate that these functions are called. If + // they are not called very often, then the 1ms events will build up and be + // dispatched as the USBTasks() or USBHostTasks() functions are called (one event + // per call to these functions. + EVENT_1MS, + + // Class-defined event offsets start here: + EVENT_GENERIC_BASE = 400, // Offset for Generic class events + + EVENT_MSD_BASE = 500, // Offset for Mass Storage Device class events + + EVENT_HID_BASE = 600, // Offset for Human Interface Device class events + + EVENT_PRINTER_BASE = 700, // Offset for Printer class events + + EVENT_CDC_BASE = 800, // Offset for CDC class events + + EVENT_CHARGER_BASE = 900, // Offset for Charger client driver events. + + EVENT_AUDIO_BASE = 1000, // Offset for Audio client driver events. + + EVENT_USER_BASE = 10000, // Add integral values to this event number + // to create user-defined events. + + // There was a transfer error on the USB. The data associated with this + // event is of data type HOST_TRANSFER_DATA. + EVENT_BUS_ERROR = INT_MAX + +} USB_EVENT; + + +// ***************************************************************************** +/* EVENT_TRANSFER Data + +This data structure is passed to the appropriate layer's +USB_EVENT_HANDLER when an EVT_XFER event has occured, indicating +that a transfer has completed on the USB. It provides the endpoint, +direction, and actual size of the transfer. + */ + +typedef struct _transfer_event_data +{ + TRANSFER_FLAGS flags; // Transfer flags (see above) + UINT32 size; // Actual number of bytes transferred + BYTE pid; // Packet ID + +} USB_TRANSFER_EVENT_DATA; + + +// ***************************************************************************** +/* EVENT_VBUS_REQUEST_POWER and EVENT_VBUS_RELEASE_POWER Data + +This data structure is passed to the appropriate layer's +USB_EVENT_HANDLER when an EVENT_VBUS_REQUEST_POWER or EVENT_VBUS_RELEASE_POWER +event has occured, indicating that a change in Vbus power is being requested. +*/ + +typedef struct _vbus_power_data +{ + BYTE port; // Physical port number + BYTE current; // Current in 2mA units +} USB_VBUS_POWER_EVENT_DATA; + + +// ***************************************************************************** +/* USB_OVERRIDE_CLIENT_DRIVER_EVENT_DATA Data + +This data structure is passed to the application layer when a client driver is +select, in case multiple client drivers can support a particular device. +*/ +typedef struct _override_client_driver_data +{ + WORD idVendor; + WORD idProduct; + BYTE bDeviceClass; + BYTE bDeviceSubClass; + BYTE bDeviceProtocol; +} USB_OVERRIDE_CLIENT_DRIVER_EVENT_DATA; + + +// ***************************************************************************** +/* EVT_STALL Data + +The EVT_STALL event has a 16-bit data value associated with it where +a bit is set in the position for each endpoint that is currently +stalled (ie. bit 0 = EP0, bit 1 = EP1, etc.) +*/ + + +// ***************************************************************************** +// ***************************************************************************** +// Section: Event Handling Routines +// ***************************************************************************** +// ***************************************************************************** + +/******************************************************************************* + Function: + BOOL ( USB_EVENT event, + void *data, unsigned int size ) + + Description: + This routine is a "call out" routine that must be implemented by + any layer of the USB SW Stack (except the HAL which is at the + root of the event-call tree that needs to receive events. When + an event occurs, the HAL calls the next higher layer in the + stack to handle the event. Each layer either handles the event + or calls the layer above it to handle the event. Events are + identified by the "event" parameter and may have associated + data. If the higher layer was able to handle the event, it + should return TRUE. If not, it should return FALSE. + + Preconditions: + USBInitialize must have been called to initialize the USB SW + Stack. + + Paramters: + USB_EVENT event - Identifies the bus event that occured + void *data - Pointer to event-specific data + unsigned int size - Size of the event-specific data + + Return Values: + None + + Remarks: + The function is name is defined by the layer that implements + it. A pointer to the function will be placed by into a table + that the lower-layer will use to call it. This requires the + function to use a specific call "signature" (return data type + and values and data parameter types and values). + +*******************************************************************************/ + +typedef BOOL (*USB_EVENT_HANDLER) ( USB_EVENT event, void *data, unsigned int size ); + + +// ***************************************************************************** +// ***************************************************************************** +// Section: USB Application Program Interface (API) Routines +// ***************************************************************************** +// ***************************************************************************** + +/**************************************************************************** + Function: + BOOL USBInitialize ( unsigned long flags ) + + Summary: + This interface initializes the variables of the USB host stack. + + Description: + This interface initializes the USB stack. + + Precondition: + None + + Parameters: + flags - reserved + + Return Values: + TRUE - Initialization successful + FALSE - Initialization failure + + Remarks: + This interface is implemented as a macro that can be defined by the + application or by default is defined correctly for the stack mode. + + ***************************************************************************/ + +#ifndef USBInitialize + #if defined( USB_SUPPORT_DEVICE ) + #if defined( USB_SUPPORT_HOST ) + #if defined( USB_SUPPORT_OTG ) + #error "USB OTG is not yet supported." + #else + #define USBInitialize(f) \ + (USBDEVInitialize(f) && USBHostInit(f)) ? \ + TRUE : FALSE + #endif + #else + #define USBInitialize(f) USBDeviceInit() + #endif + #else + #if defined( USB_SUPPORT_HOST ) + #define USBInitialize(f) USBHostInit(f) + #else + #error "Application must define support mode in usb_config.h" + #endif + #endif +#endif + + +/**************************************************************************** + Function: + void USBTasks( void ) + + Summary: + This function executes the tasks for USB operation. + + Description: + This function executes the tasks for USB host operation. It must be + executed on a regular basis to keep everything functioning. + + Precondition: + USBInitialize() has been called. + + Parameters: + None + + Returns: + None + + Remarks: + This interface is implemented as a macro that can be defined by the + application or by default is defined correctly for the stack mode. + + ***************************************************************************/ + +#ifndef USBTasks // Implemented as a macro that can be overridden. + #if defined( USB_SUPPORT_DEVICE ) + #if defined( USB_SUPPORT_HOST ) + #if defined( USB_SUPPORT_OTG ) + #error "USB OTG is not yet supported." + #else + #define USBTasks() {USBHostTasks(); USBHALHandleBusEvent();} + #endif + #else + #define USBTasks() USBDeviceTasks() + #endif + #else + #if defined( USB_SUPPORT_HOST ) + #define USBTasks() USBHostTasks() + #else + #error "Application must define support mode in usb_config.h" + #endif + #endif +#endif + +#define USB_PING_PONG__NO_PING_PONG 0x00 //0b00 +#define USB_PING_PONG__EP0_OUT_ONLY 0x01 //0b01 +#define USB_PING_PONG__FULL_PING_PONG 0x02 //0b10 +#define USB_PING_PONG__ALL_BUT_EP0 0x03 //0b11 + +#endif // _USB_COMMON_H_ +/************************************************************************* + * EOF + */ + diff --git a/FirmwareDumper/USB/usb_device.c b/FirmwareDumper/USB/usb_device.c new file mode 100644 index 0000000..5ab2a10 --- /dev/null +++ b/FirmwareDumper/USB/usb_device.c @@ -0,0 +1,3134 @@ +/******************************************************************** + File Information: + FileName: usb_device.c + Dependencies: See INCLUDES section + Processor: PIC18,PIC24, PIC32 and dsPIC33E USB Microcontrollers + Hardware: This code is natively intended to be used on Mirochip USB + demo boards. See www.microchip.com/usb (Software & Tools + section) for list of available platforms. The firmware may + be modified for use on other USB platforms by editing the + HardwareProfile.h and HardwareProfile - [platform].h files. + Complier: Microchip C18 (for PIC18),C30 (for PIC24 and dsPIC33E) + and C32 (for PIC32) + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the "Company") for its PIC(r) Microcontroller is intended and + supplied to you, the Company's customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + Summary: + This file contains functions, macros, definitions, variables, + datatypes, etc. that are required for usage with the MCHPFSUSB device + stack. This file should be included in projects that use the device stack. + + This file is located in the "\\\Microchip\\USB" + directory. + + Description: + USB Device Stack File + + This file contains functions, macros, definitions, variables, + datatypes, etc. that are required for usage with the MCHPFSUSB device + stack. This file should be included in projects that use the device stack. + + This file is located in the "\\\Microchip\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + ..\\..\\MicrochipInclude + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + +******************************************************************** + File Description: + + Change History: + Rev Description + ---- ----------- + 2.6 Added USBCancelIO() function. Moved and some stack + defintions to be more consistant with the host stack. + + 2.6a Fixed issue where a SET_CONFIGURATION received could cause + inability to transmit on an endpoint if using ping-pong + and an odd number of packets had been sent on that endpoint + + 2.7 Fixed error where the USB error interrupt flag was not getting + cleared properly for PIC32 resulting in lots of extra error interrupts. + http://www.microchip.com/forums/tm.aspx?m=479085 + + Fixed issue with dual role mode when device run in polling + mode. Interrupts were remaining enabled after the host mode + operation was complete. This was incompatible with polling + mode operation. + + Changed how the bus sensing works. In previous revisions it + was impossible to use the USBDeviceDetach to detach from the + bus if the bus voltage was still present. This is now + possible. It was also possible to move the device to the + ATTACHED state in interrupt mode even if the bus voltage + wasn't available. This is now prohibited unless VBUS is + present. + + Improved error case handling when the host sends more OUT + bytes in a control transfer than the firmware was expecting + to receive (based on the size parameter when calling USBEP0Receive()). + + In the USBStdSetCfgHandler(), modified the code so the USBDeviceState + variable only gets updated to the CONFIGURED_STATE at the end of the + function. + + 2.7a Update to support the PIC18F47J53 A1 and later revision + devices. + + Fixed an error on 16-bit and 32-bit processors where a word access + could be performed on a byte pointer resulting in possible address + errors with odd aligned pointers. + + 2.8 Several changes to the way control transfers get processed, + so as to support the ability to allow application/class specific + handler code to defer the status stage. + Implemented USBCtrlEPAllowStatusStage() API function. + Implemented USBDeferStatusStage() API function (macro). + These changes also greatly relax the USBDeviceTasks() calling frequency + requirement, while allowing USB class handlers more flexibility. + + Also implemented the following API functions and macros, for delaying + the data stage of a control transfer (with data stage): + USBDeferINDataStage() + USBDeferOUTDataStage() + USBOUTDataStageDeferred() + USBINDataStageDeferred() + USBCtrlEPAllowDataStage() + + Fixed USB reset event handler issue, where the USB stack would + re-initialize global interrupt settings in the interrupt context, on + PIC18 devices with the stack operated in USB_INTERRUPT mode. + + Fixed handling of SET/CLEAR FEATURE (endpoint halt) host requests. + Previous implementation would not always initialize endpoints correctly + to DATA0 DTS state after a clear feature endpoint halt request, for + all ping pong mode and usage scenarios. + + 2.9 Fixed an issue with STALL handling behavior on non-EP0 endpoints, for + PIC24 and PIC32 devices. + + Fixed an issue where the ep_data_in[]/ep_data_out[] flags weren't + getting re-initialized coincident with the hardware ping pong pointer + reset during set configuration events. + + Implemented USBGetNextHandle() API function (actually a macro, defined + in usb_device.h). + + 2.9d Added build option for disabling DTS checking + + 2.9f Adding pragma for PIC18F97J94 Family BDT location. + + 2.9h Updated to be able to support optional Microsoft OS Descriptors + + 2.9i Updated to set UCON bit on PIC16F USB devices during + suspend, so as to save power. + +********************************************************************/ + +/*---------------------------------------------------------------------------------- +The USBDeviceTasks() function is responsible for detecting and processing various +USB bus events and host requests, such as those required for USB enumeration, when +the USB cable is first attached to the host. This function is the main dispatcher +routine for the USB stack. + +Additional API functions and macros are also provided by the USB stack, which can be +used to send/receive USB data to/from the host, among other things. A full list +of the available implemented functions/macros are provided in the +"MCHPFSUSB Library Help". For normal installations of the MCHPFSUSB Framework, +the USB API documentation can be found from: + +Start menu --> (All Programs) --> Microchip --> MCHPFSUSB vX.x --> Documents --> MCHPFSUSB Library Help + +Once the help file is opened, the API functions/macros are described in the following section: +Library Interface (API) --> Device/Peripheral --> Device Stack --> Interface Routines +Additional API functions may also be provided depending upon the specific USB device class +implemented, and these functions are also documented in the MCHPFSUSB Library Help. + + +If the USB stack is operated in "USB_POLLING" mode (user selectable option in +usb_config.h), then the application firmware is reponsible for calling the +USBDeviceTasks() function periodically. If the USB stack is operated in the +"USB_INTERRUPT" mode, then the application firmware does not have to directly +call USBDeviceTasks(), as it will execute only when necessary as an interrupt handler. + +In order to properly operate a USB connection, and to correctly process and respond +to control transfers in the maximum time allowed by the USB specifications, the +USBDeviceTasks() function/interrupt handler must be allowed to execute in a timely +fashion. + +When the USB module is enabled, the USB cable is attached to the host, the USB bus +is not in the suspend state, and the USB stack is operated in the USB_POLLING mode +with ping pong buffering enabled (at least) on EP0 OUT, then the maximum allowed +time between calls to the USBDeviceTasks() function needs to be: + +The faster of: +1. Once per ~1.8ms, when USBDeviceState == ADR_PENDING_STATE +2. Once per ~9.8ms, when USBDeviceState == (any other value other than ADR_PENDING_STATE) +3. Fast enough to ensure the USTAT FIFO can never get full. See additional explanation below. + +Additional details of the above timing limits are provided: + +Timing item #1: This parameter originates from the 2ms set address "recovery interval" +specification dictated by section "9.2.6.3 Set Address Processing" of the official +USB 2.0 specifications. + +Timing item #2: This parameter originates from several "10 ms" criteria in the +USB 2.0 specifications. For example, reset recovery intervals, resume recovery +intervals, suspend to actual current reduction, etc. have timing maximums of 10ms. + +Timing item #3: This is not a fixed X.X ms parameter, but depends on the +transaction rate implemented by the application. The USBDeviceTasks() function is +responsible for popping entries off the USTAT FIFO. If the FIFO ever gets full, +then no further USB transactions are allowed to occur, until the firmware pops entries +off the FIFO. In practice, this means the firmware should call USBDeviceTasks() at +a rate at least as fast as once every three times the USBTransferOnePacket() function +is called. This ensures that the rate that USTAT FIFO entries are getting added to +the FIFO is lower than the rate that the entries are getting popped off the FIFO (the +USBDeviceTasks() function will pop up to 4 entries per call), which is a +necessary criteria to ensure the USTAT FIFO entries don't "pile up." Calling +USBDeviceTasks() even more often, ex: >=1 to 1 ratio of USBDeviceTasks() to +USBTransferOnePacket(), adds further protection against the USTAT FIFO getting full, +and is therefore recommended. + +When the USB stack is operated in USB_INTERRUPT mode, then the above timing +parameters should be interpreted to be the longest allowed time that the USB +interrupts may be masked/disabled for, before re-enabling the USB interrupts. + +Calling USBDeviceTasks() (or allowing USBDeviceTasks() to be called) more often +will still have potential USB data rate speed and processing latency benefits. +It is also beneficial to call USBDeviceTasks() more often than theoretically +required, since it has been observed that not all host/drivers/bios/hubs are +100% consistently compliant with all timing parameters of the USB 2.0 specifications. +Therefore, in a USB_POLLING based application, it is still suggested to call +USBDeviceTasks() as often as there are free CPU cycles. This ensures best +performance, along with best possible compatibility with all existing USB +hosts/hubs (both those that are compliant and [partially] non-compliant). + +If ping pong buffering is not enabled on (at least) EP0 OUT, then it is required +to call (or allow to execute) USBDeviceTasks() much more frequently (ex: once +per 100us, or preferrably faster). Therefore, in all applications, it is +normally recommended to select either the USB_PING_PONG__FULL_PING_PONG or +USB_PING_PONG__EP0_OUT_ONLY mode (user option in usb_config.h), as these modes +allow for much more relaxed timing requirements, and therefore greater application +firmware design flexibility. +//----------------------------------------------------------------------------------*/ + +/** INCLUDES *******************************************************/ +#include "./USB/usb.h" +#include "HardwareProfile.h" + +#include "../USB/usb_device_local.h" + + +#if defined(USB_USE_MSD) + #include "./USB/usb_function_msd.h" +#endif + +#if !defined(USE_USB_BUS_SENSE_IO) + #undef USB_BUS_SENSE + #define USB_BUS_SENSE 1 +#endif + +#if defined(USB_DEVICE_DISABLE_DTS_CHECKING) + #define _DTS_CHECKING_ENABLED 0 +#else + #define _DTS_CHECKING_ENABLED _DTSEN +#endif + +/** DEFINITIONS ****************************************************/ + +/** VARIABLES ******************************************************/ +#if defined(__18CXX) + #pragma udata +#endif + +USB_VOLATILE USB_DEVICE_STATE USBDeviceState; +USB_VOLATILE BYTE USBActiveConfiguration; +USB_VOLATILE BYTE USBAlternateInterface[USB_MAX_NUM_INT]; +volatile BDT_ENTRY *pBDTEntryEP0OutCurrent; +volatile BDT_ENTRY *pBDTEntryEP0OutNext; +volatile BDT_ENTRY *pBDTEntryOut[USB_MAX_EP_NUMBER+1]; +volatile BDT_ENTRY *pBDTEntryIn[USB_MAX_EP_NUMBER+1]; +USB_VOLATILE BYTE shortPacketStatus; +USB_VOLATILE BYTE controlTransferState; +USB_VOLATILE IN_PIPE inPipes[1]; +USB_VOLATILE OUT_PIPE outPipes[1]; +USB_VOLATILE BYTE *pDst; +USB_VOLATILE BOOL RemoteWakeup; +USB_VOLATILE BOOL USBBusIsSuspended; +USB_VOLATILE USTAT_FIELDS USTATcopy; +USB_VOLATILE BYTE endpoint_number; +USB_VOLATILE BOOL BothEP0OutUOWNsSet; +USB_VOLATILE EP_STATUS ep_data_in[USB_MAX_EP_NUMBER+1]; +USB_VOLATILE EP_STATUS ep_data_out[USB_MAX_EP_NUMBER+1]; +USB_VOLATILE BYTE USBStatusStageTimeoutCounter; +volatile BOOL USBDeferStatusStagePacket; +volatile BOOL USBStatusStageEnabledFlag1; +volatile BOOL USBStatusStageEnabledFlag2; +volatile BOOL USBDeferINDataStagePackets; +volatile BOOL USBDeferOUTDataStagePackets; + + +#if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) + #define BDT_NUM_ENTRIES ((USB_MAX_EP_NUMBER + 1) * 2) +#elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) + #define BDT_NUM_ENTRIES (((USB_MAX_EP_NUMBER + 1) * 2)+1) +#elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + #define BDT_NUM_ENTRIES ((USB_MAX_EP_NUMBER + 1) * 4) +#elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) + #define BDT_NUM_ENTRIES (((USB_MAX_EP_NUMBER + 1) * 4)-2) +#else + #error "No ping pong mode defined." +#endif + +/** USB FIXED LOCATION VARIABLES ***********************************/ +#if defined(__18CXX) + #pragma udata USB_BDT=USB_BDT_ADDRESS +#endif + +volatile BDT_ENTRY BDT[BDT_NUM_ENTRIES] BDT_BASE_ADDR_TAG; + +/******************************************************************** + * Section B: EP0 Buffer Space + *******************************************************************/ +volatile CTRL_TRF_SETUP SetupPkt CTRL_TRF_SETUP_ADDR_TAG; +volatile BYTE CtrlTrfData[USB_EP0_BUFF_SIZE] CTRL_TRF_DATA_ADDR_TAG; + +/******************************************************************** + * Section C: non-EP0 Buffer Space + *******************************************************************/ +#if defined(USB_USE_MSD) + //volatile far USB_MSD_CBW_CSW msd_cbw_csw; + volatile USB_MSD_CBW msd_cbw; + volatile USB_MSD_CSW msd_csw; + //#pragma udata + + #if defined(__18CXX) + #pragma udata myMSD=MSD_BUFFER_ADDRESS + #endif + volatile char msd_buffer[512]; +#endif + + + +////Depricated in v2.2 - will be removed in a future revision +#if !defined(USB_USER_DEVICE_DESCRIPTOR) + //Device descriptor + extern ROM USB_DEVICE_DESCRIPTOR device_dsc; +#else + USB_USER_DEVICE_DESCRIPTOR_INCLUDE; +#endif + +#if !defined(USB_USER_CONFIG_DESCRIPTOR) + //Array of configuration descriptors + extern ROM BYTE *ROM USB_CD_Ptr[]; +#else + USB_USER_CONFIG_DESCRIPTOR_INCLUDE; +#endif + +extern ROM BYTE *ROM USB_SD_Ptr[]; + +/** DECLARATIONS ***************************************************/ +#if defined(__18CXX) + #pragma code +#endif + +/** Macros *********************************************************/ + +/** Function Prototypes ********************************************/ +//External +//This is the prototype for the required user event handler +BOOL USER_USB_CALLBACK_EVENT_HANDLER(int event, void *pdata, WORD size); + +//Internal Functions +static void USBCtrlEPService(void); +static void USBCtrlTrfSetupHandler(void); +static void USBCtrlTrfInHandler(void); +static void USBCheckStdRequest(void); +static void USBStdGetDscHandler(void); +static void USBCtrlEPServiceComplete(void); +static void USBCtrlTrfTxService(void); +static void USBCtrlTrfRxService(void); +static void USBStdSetCfgHandler(void); +static void USBStdGetStatusHandler(void); +static void USBStdFeatureReqHandler(void); +static void USBCtrlTrfOutHandler(void); +static void USBConfigureEndpoint(BYTE EPNum, BYTE direction); +static void USBWakeFromSuspend(void); +static void USBSuspend(void); +static void USBStallHandler(void); + +//static BOOL USBIsTxBusy(BYTE EPNumber); +//static void USBPut(BYTE EPNum, BYTE Data); +//static void USBEPService(void); +//static void USBProtocolResetHandler(void); + +/******************************************************************************/ +/** Function Implementations *************************************************/ +/******************************************************************************/ + +/******************************************************************************/ +/** Internal Macros *********************************************************/ +/******************************************************************************/ + +/**************************************************************************** + Function: + void USBAdvancePingPongBuffer(BDT_ENTRY** buffer) + + Description: + This function will advance the passed pointer to the next buffer based on + the ping pong option setting. This function should be used for EP1-EP15 + only. This function is not valid for EP0. + + Precondition: + None + + Parameters: + BDT_ENTRY** - pointer to the BDT_ENTRY pointer that you want to be advanced + to the next buffer state + + Return Values: + None + + Remarks: + None + + ***************************************************************************/ +#define USBAdvancePingPongBuffer(buffer) ((BYTE_VAL*)buffer)->Val ^= USB_NEXT_PING_PONG; +#define USBHALPingPongSetToOdd(buffer) {((BYTE_VAL*)buffer)->Val |= USB_NEXT_PING_PONG;} +#define USBHALPingPongSetToEven(buffer) {((BYTE_VAL*)buffer)->Val &= ~USB_NEXT_PING_PONG;} + + +/******************************************************************************/ +/** External API Functions ****************************************************/ +/******************************************************************************/ + +/************************************************************************** + Function: + void USBDeviceInit(void) + + Description: + This function initializes the device stack it in the default state. The + USB module will be completely reset including all of the internal + variables, registers, and interrupt flags. + + Precondition: + This function must be called before any of the other USB Device + functions can be called, including USBDeviceTasks(). + + Parameters: + None + + Return Values: + None + + Remarks: + None + + ***************************************************************************/ +void USBDeviceInit(void) +{ + BYTE i; + + USBDisableInterrupts(); + + // Clear all USB error flags + USBClearInterruptRegister(U1EIR); + + // Clears all USB interrupts + USBClearInterruptRegister(U1IR); + + //Clear all of the endpoint control registers + U1EP0 = 0; + + DisableNonZeroEndpoints(USB_MAX_EP_NUMBER); + + SetConfigurationOptions(); + + //power up the module (if not already powered) + USBPowerModule(); + + //set the address of the BDT (if applicable) + USBSetBDTAddress(BDT); + + //Clear all of the BDT entries + for(i=0;i<(sizeof(BDT)/sizeof(BDT_ENTRY));i++) + { + BDT[i].Val = 0x00; + } + + // Assert reset request to all of the Ping Pong buffer pointers + USBPingPongBufferReset = 1; + + // Reset to default address + U1ADDR = 0x00; + + // Make sure packet processing is enabled + USBPacketDisable = 0; + + //Stop trying to reset ping pong buffer pointers + USBPingPongBufferReset = 0; + + // Flush any pending transactions + while(USBTransactionCompleteIF == 1) + { + USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum); + //Initialize USB stack software state variables + inPipes[0].info.Val = 0; + outPipes[0].info.Val = 0; + outPipes[0].wCount.Val = 0; + } + + //Set flags to TRUE, so the USBCtrlEPAllowStatusStage() function knows not to + //try and arm a status stage, even before the first control transfer starts. + USBStatusStageEnabledFlag1 = TRUE; + USBStatusStageEnabledFlag2 = TRUE; + //Initialize other flags + USBDeferINDataStagePackets = FALSE; + USBDeferOUTDataStagePackets = FALSE; + USBBusIsSuspended = FALSE; + + //Initialize all pBDTEntryIn[] and pBDTEntryOut[] + //pointers to NULL, so they don't get used inadvertently. + for(i = 0; i < (BYTE)(USB_MAX_EP_NUMBER+1u); i++) + { + pBDTEntryIn[i] = 0u; + pBDTEntryOut[i] = 0u; + ep_data_in[i].Val = 0u; + ep_data_out[i].Val = 0u; + } + + //Get ready for the first packet + pBDTEntryIn[0] = (volatile BDT_ENTRY*)&BDT[EP0_IN_EVEN]; + // Initialize EP0 as a Ctrl EP + U1EP0 = EP_CTRL|USB_HANDSHAKE_ENABLED; + //Prepare for the first SETUP on EP0 OUT + BDT[EP0_OUT_EVEN].ADR = ConvertToPhysicalAddress(&SetupPkt); + BDT[EP0_OUT_EVEN].CNT = USB_EP0_BUFF_SIZE; + BDT[EP0_OUT_EVEN].STAT.Val = _USIE|_DAT0|_BSTALL; + + // Clear active configuration + USBActiveConfiguration = 0; + + //Indicate that we are now in the detached state + USBDeviceState = DETACHED_STATE; +} + +/************************************************************************** + Function: + void USBDeviceTasks(void) + + Summary: + This function is the main state machine/transaction handler of the USB + device side stack. When the USB stack is operated in "USB_POLLING" mode + (usb_config.h user option) the USBDeviceTasks() function should be called + periodically to receive and transmit packets through the stack. This + function also takes care of control transfers associated with the USB + enumeration process, and detecting various USB events (such as suspend). + This function should be called at least once every 1.8ms during the USB + enumeration process. After the enumeration process is complete (which can + be determined when USBGetDeviceState() returns CONFIGURED_STATE), the + USBDeviceTasks() handler may be called the faster of: either once + every 9.8ms, or as often as needed to make sure that the hardware USTAT + FIFO never gets full. A good rule of thumb is to call USBDeviceTasks() at + a minimum rate of either the frequency that USBTransferOnePacket() gets + called, or, once/1.8ms, whichever is faster. See the inline code comments + near the top of usb_device.c for more details about minimum timing + requirements when calling USBDeviceTasks(). + + When the USB stack is operated in "USB_INTERRUPT" mode, it is not necessary + to call USBDeviceTasks() from the main loop context. In the USB_INTERRUPT + mode, the USBDeviceTasks() handler only needs to execute when a USB + interrupt occurs, and therefore only needs to be called from the interrupt + context. + + Description: + This function is the main state machine/transaction handler of the USB + device side stack. When the USB stack is operated in "USB_POLLING" mode + (usb_config.h user option) the USBDeviceTasks() function should be called + periodically to receive and transmit packets through the stack. This + function also takes care of control transfers associated with the USB + enumeration process, and detecting various USB events (such as suspend). + This function should be called at least once every 1.8ms during the USB + enumeration process. After the enumeration process is complete (which can + be determined when USBGetDeviceState() returns CONFIGURED_STATE), the + USBDeviceTasks() handler may be called the faster of: either once + every 9.8ms, or as often as needed to make sure that the hardware USTAT + FIFO never gets full. A good rule of thumb is to call USBDeviceTasks() at + a minimum rate of either the frequency that USBTransferOnePacket() gets + called, or, once/1.8ms, whichever is faster. See the inline code comments + near the top of usb_device.c for more details about minimum timing + requirements when calling USBDeviceTasks(). + + When the USB stack is operated in "USB_INTERRUPT" mode, it is not necessary + to call USBDeviceTasks() from the main loop context. In the USB_INTERRUPT + mode, the USBDeviceTasks() handler only needs to execute when a USB + interrupt occurs, and therefore only needs to be called from the interrupt + context. + + Typical usage: + + void main(void) + { + USBDeviceInit(); + while(1) + { + USBDeviceTasks(); //Takes care of enumeration and other USB events + if((USBGetDeviceState() \< CONFIGURED_STATE) || + (USBIsDeviceSuspended() == TRUE)) + { + //Either the device is not configured or we are suspended, + // so we don't want to execute any USB related application code + continue; //go back to the top of the while loop + } + else + { + //Otherwise we are free to run USB and non-USB related user + //application code. + UserApplication(); + } + } + } + + + Precondition: + Make sure the USBDeviceInit() function has been called prior to calling + USBDeviceTasks() for the first time. + Remarks: + USBDeviceTasks() does not need to be called while in the USB suspend mode, + if the user application firmware in the USBCBSuspend() callback function + enables the ACTVIF USB interrupt source and put the microcontroller into + sleep mode. If the application firmware decides not to sleep the + microcontroller core during USB suspend (ex: continues running at full + frequency, or clock switches to a lower frequency), then the USBDeviceTasks() + function must still be called periodically, at a rate frequent enough to + ensure the 10ms resume recovery interval USB specification is met. Assuming + a worst case primary oscillator and PLL start up time of <5ms, then + USBDeviceTasks() should be called once every 5ms in this scenario. + + When the USB cable is detached, or the USB host is not actively powering + the VBUS line to +5V nominal, the application firmware does not always have + to call USBDeviceTasks() frequently, as no USB activity will be taking + place. However, if USBDeviceTasks() is not called regularly, some + alternative means of promptly detecting when VBUS is powered (indicating + host attachment), or not powered (host powered down or USB cable unplugged) + is still needed. For self or dual self/bus powered USB applications, see + the USBDeviceAttach() and USBDeviceDetach() API documentation for additional + considerations. + + **************************************************************************/ + +#if defined(USB_INTERRUPT) +#if defined(__18CXX) || defined (_PIC14E) + void USBDeviceTasks(void) + #elif defined(__C30__) || defined __XC16__ + void __attribute__((interrupt,auto_psv)) _USB1Interrupt() + #elif defined(__PIC32MX__) + void __attribute__((interrupt(),vector(_USB_1_VECTOR))) _USB1Interrupt( void ) + #endif +#else +void USBDeviceTasks(void) +#endif +{ + BYTE i; + +#ifdef USB_SUPPORT_OTG + //SRP Time Out Check + if (USBOTGSRPIsReady()) + { + if (USBT1MSECIF && USBT1MSECIE) + { + if (USBOTGGetSRPTimeOutFlag()) + { + if (USBOTGIsSRPTimeOutExpired()) + { + USB_OTGEventHandler(0,OTG_EVENT_SRP_FAILED,0,0); + } + } + + //Clear Interrupt Flag + USBClearInterruptFlag(USBT1MSECIFReg,USBT1MSECIFBitNum); + } + } +#endif + + #if defined(USB_POLLING) + //If the interrupt option is selected then the customer is required + // to notify the stack when the device is attached or removed from the + // bus by calling the USBDeviceAttach() and USBDeviceDetach() functions. + if (USB_BUS_SENSE != 1) + { + // Disable module & detach from bus + U1CON = 0; + + // Mask all USB interrupts + U1IE = 0; + + //Move to the detached state + USBDeviceState = DETACHED_STATE; + + #ifdef USB_SUPPORT_OTG + //Disable D+ Pullup + U1OTGCONbits.DPPULUP = 0; + + //Disable HNP + USBOTGDisableHnp(); + + //Deactivate HNP + USBOTGDeactivateHnp(); + + //If ID Pin Changed State + if (USBIDIF && USBIDIE) + { + //Re-detect & Initialize + USBOTGInitialize(); + + //Clear ID Interrupt Flag + USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum); + } + #endif + + #if defined __C30__ || defined __XC16__ + //USBClearInterruptFlag(U1OTGIR, 3); + #endif + //return so that we don't go through the rest of + //the state machine + USBClearUSBInterrupt(); + return; + } + + #ifdef USB_SUPPORT_OTG + //If Session Is Started Then + else + { + //If SRP Is Ready + if (USBOTGSRPIsReady()) + { + //Clear SRPReady + USBOTGClearSRPReady(); + + //Clear SRP Timeout Flag + USBOTGClearSRPTimeOutFlag(); + + //Indicate Session Started + UART2PrintString( "\r\n***** USB OTG B Event - Session Started *****\r\n" ); + } + } + #endif //#ifdef USB_SUPPORT_OTG + + //if we are in the detached state + if(USBDeviceState == DETACHED_STATE) + { + //Initialize register to known value + U1CON = 0; + + // Mask all USB interrupts + U1IE = 0; + + //Enable/set things like: pull ups, full/low-speed mode, + //set the ping pong mode, and set internal transceiver + SetConfigurationOptions(); + + // Enable module & attach to bus + while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;} + + //moved to the attached state + USBDeviceState = ATTACHED_STATE; + + #ifdef USB_SUPPORT_OTG + U1OTGCON |= USB_OTG_DPLUS_ENABLE | USB_OTG_ENABLE; + #endif + } + #endif //#if defined(USB_POLLING) + + if(USBDeviceState == ATTACHED_STATE) + { + /* + * After enabling the USB module, it takes some time for the + * voltage on the D+ or D- line to rise high enough to get out + * of the SE0 condition. The USB Reset interrupt should not be + * unmasked until the SE0 condition is cleared. This helps + * prevent the firmware from misinterpreting this unique event + * as a USB bus reset from the USB host. + */ + + if(!USBSE0Event) + { + USBClearInterruptRegister(U1IR);// Clear all USB interrupts + #if defined(USB_POLLING) + U1IE=0; // Mask all USB interrupts + #endif + USBResetIE = 1; // Unmask RESET interrupt + USBIdleIE = 1; // Unmask IDLE interrupt + USBDeviceState = POWERED_STATE; + } + } + + #ifdef USB_SUPPORT_OTG + //If ID Pin Changed State + if (USBIDIF && USBIDIE) + { + //Re-detect & Initialize + USBOTGInitialize(); + + USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum); + } + #endif + + /* + * Task A: Service USB Activity Interrupt + */ + if(USBActivityIF && USBActivityIE) + { + USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum); + #if defined(USB_SUPPORT_OTG) + U1OTGIR = 0x10; + #else + USBWakeFromSuspend(); + #endif + } + + /* + * Pointless to continue servicing if the device is in suspend mode. + */ + if(USBSuspendControl==1) + { + USBClearUSBInterrupt(); + return; + } + + /* + * Task B: Service USB Bus Reset Interrupt. + * When bus reset is received during suspend, ACTVIF will be set first, + * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted. + * This is why URSTIF is checked after ACTVIF. + * + * The USB reset flag is masked when the USB state is in + * DETACHED_STATE or ATTACHED_STATE, and therefore cannot + * cause a USB reset event during these two states. + */ + if(USBResetIF && USBResetIE) + { + USBDeviceInit(); + + //Re-enable the interrupts since the USBDeviceInit() function will + // disable them. This will do nothing in a polling setup + USBUnmaskInterrupts(); + + USBDeviceState = DEFAULT_STATE; + + #ifdef USB_SUPPORT_OTG + //Disable HNP + USBOTGDisableHnp(); + + //Deactivate HNP + USBOTGDeactivateHnp(); + #endif + + USBClearInterruptFlag(USBResetIFReg,USBResetIFBitNum); + } + + /* + * Task C: Service other USB interrupts + */ + if(USBIdleIF && USBIdleIE) + { + #ifdef USB_SUPPORT_OTG + //If Suspended, Try to switch to Host + USBOTGSelectRole(ROLE_HOST); + #else + USBSuspend(); + #endif + + USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum); + } + + if(USBSOFIF) + { + if(USBSOFIE) + { + USB_SOF_HANDLER(EVENT_SOF,0,1); + } + USBClearInterruptFlag(USBSOFIFReg,USBSOFIFBitNum); + + #if defined(USB_ENABLE_STATUS_STAGE_TIMEOUTS) + //Supporting this feature requires a 1ms timebase for keeping track of the timeout interval. + #if(USB_SPEED_OPTION == USB_LOW_SPEED) + #warning "Double click this message. See inline code comments." + //The "USB_ENABLE_STATUS_STAGE_TIMEOUTS" feature is optional and is + //not strictly needed in all applications (ex: those that never call + //USBDeferStatusStage() and don't use host to device (OUT) control + //transfers with data stage). + //However, if this feature is enabled and used, it requires a timer + //(preferrably 1ms) to decrement the USBStatusStageTimeoutCounter. + //In USB Full Speed applications, the host sends Start-of-Frame (SOF) + //packets at a 1ms rate, which generates SOFIF interrupts. + //These interrupts can be used to decrement USBStatusStageTimeoutCounter as shown + //below. However, the host does not send SOF packets to Low Speed devices. + //Therefore, some other method (ex: using a general purpose microcontroller + //timer, such as Timer0) needs to be implemented to call and execute the below code + //at a once/1ms rate, in a low speed USB application. + //Note: Pre-condition to executing the below code: USBDeviceInit() should have + //been called at least once (since the last microcontroller reset/power up), + //prior to executing the below code. + #endif + + //Decrement our status stage counter. + if(USBStatusStageTimeoutCounter != 0u) + { + USBStatusStageTimeoutCounter--; + } + //Check if too much time has elapsed since progress was made in + //processing the control transfer, without arming the status stage. + //If so, auto-arm the status stage to ensure that the control + //transfer can [eventually] complete, within the timing limits + //dictated by section 9.2.6 of the official USB 2.0 specifications. + if(USBStatusStageTimeoutCounter == 0) + { + USBCtrlEPAllowStatusStage(); //Does nothing if the status stage was already armed. + } + #endif + } + + if(USBStallIF && USBStallIE) + { + USBStallHandler(); + } + + if(USBErrorIF && USBErrorIE) + { + USB_ERROR_HANDLER(EVENT_BUS_ERROR,0,1); + USBClearInterruptRegister(U1EIR); // This clears UERRIF + + //On PIC18, clearing the source of the error will automatically clear + // the interrupt flag. On other devices the interrupt flag must be + // manually cleared. + #if defined(__C32__) || defined(__C30__) || defined __XC16__ + USBClearInterruptFlag( USBErrorIFReg, USBErrorIFBitNum ); + #endif + } + + /* + * Pointless to continue servicing if the host has not sent a bus reset. + * Once bus reset is received, the device transitions into the DEFAULT + * state and is ready for communication. + */ + if(USBDeviceState < DEFAULT_STATE) + { + USBClearUSBInterrupt(); + return; + } + + /* + * Task D: Servicing USB Transaction Complete Interrupt + */ + if(USBTransactionCompleteIE) + { + for(i = 0; i < 4u; i++) //Drain or deplete the USAT FIFO entries. If the USB FIFO ever gets full, USB bandwidth + { //utilization can be compromised, and the device won't be able to receive SETUP packets. + if(USBTransactionCompleteIF) + { + //Save and extract USTAT register info. Will use this info later. + USTATcopy.Val = U1STAT; + endpoint_number = USBHALGetLastEndpoint(USTATcopy); + + USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum); + + //Keep track of the hardware ping pong state for endpoints other + //than EP0, if ping pong buffering is enabled. + #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + if(USBHALGetLastDirection(USTATcopy) == OUT_FROM_HOST) + { + ep_data_out[endpoint_number].bits.ping_pong_state ^= 1; + } + else + { + ep_data_in[endpoint_number].bits.ping_pong_state ^= 1; + } + #endif + + //USBCtrlEPService only services transactions over EP0. + //It ignores all other EP transactions. + if(endpoint_number == 0) + { + USBCtrlEPService(); + } + else + { + USB_TRANSFER_COMPLETE_HANDLER(EVENT_TRANSFER, (BYTE*)&USTATcopy.Val, 0); + } + }//end if(USBTransactionCompleteIF) + else + break; //USTAT FIFO must be empty. + }//end for() + }//end if(USBTransactionCompleteIE) + + USBClearUSBInterrupt(); +}//end of USBDeviceTasks() + +/******************************************************************************* + Function: + void USBEnableEndpoint(BYTE ep, BYTE options) + + Summary: + This function will enable the specified endpoint with the specified + options + Description: + This function will enable the specified endpoint with the specified + options. + + Typical Usage: + + void USBCBInitEP(void) + { + USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); + USBMSDInit(); + } + + + In the above example endpoint number MSD_DATA_IN_EP is being configured + for both IN and OUT traffic with handshaking enabled. Also since + MSD_DATA_IN_EP is not endpoint 0 (MSD does not allow this), then we can + explicitly disable SETUP packets on this endpoint. + Conditions: + None + Input: + BYTE ep - the endpoint to be configured + BYTE options - optional settings for the endpoint. The options should + be ORed together to form a single options string. The + available optional settings for the endpoint. The + options should be ORed together to form a single options + string. The available options are the following\: + * USB_HANDSHAKE_ENABLED enables USB handshaking (ACK, + NAK) + * USB_HANDSHAKE_DISABLED disables USB handshaking (ACK, + NAK) + * USB_OUT_ENABLED enables the out direction + * USB_OUT_DISABLED disables the out direction + * USB_IN_ENABLED enables the in direction + * USB_IN_DISABLED disables the in direction + * USB_ALLOW_SETUP enables control transfers + * USB_DISALLOW_SETUP disables control transfers + * USB_STALL_ENDPOINT STALLs this endpoint + Return: + None + Remarks: + None + *****************************************************************************/ +void USBEnableEndpoint(BYTE ep, BYTE options) +{ + unsigned char* p; + + //Use USBConfigureEndpoint() to set up the pBDTEntryIn/Out[ep] pointer and + //starting DTS state in the BDT entry. + if(options & USB_OUT_ENABLED) + { + USBConfigureEndpoint(ep, OUT_FROM_HOST); + } + if(options & USB_IN_ENABLED) + { + USBConfigureEndpoint(ep, IN_TO_HOST); + } + + //Update the relevant UEPx register to actually enable the endpoint with + //the specified options (ex: handshaking enabled, control transfers allowed, + //etc.) + #if defined(__C32__) + p = (unsigned char*)(&U1EP0+(4*ep)); + #else + p = (unsigned char*)(&U1EP0+ep); + #endif + *p = options; +} + + +/************************************************************************* + Function: + USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, BYTE len) + + Summary: + Transfers a single packet (one transaction) of data on the USB bus. + + Description: + The USBTransferOnePacket() function prepares a USB endpoint + so that it may send data to the host (an IN transaction), or + receive data from the host (an OUT transaction). The + USBTransferOnePacket() function can be used both to receive and + send data to the host. This function is the primary API function + provided by the USB stack firmware for sending or receiving application + data over the USB port. + + The USBTransferOnePacket() is intended for use with all application + endpoints. It is not used for sending or receiving applicaiton data + through endpoint 0 by using control transfers. Separate API + functions, such as USBEP0Receive(), USBEP0SendRAMPtr(), and + USBEP0SendROMPtr() are provided for this purpose. + + The USBTransferOnePacket() writes to the Buffer Descriptor Table (BDT) + entry associated with an endpoint buffer, and sets the UOWN bit, which + prepares the USB hardware to allow the transaction to complete. The + application firmware can use the USBHandleBusy() macro to check the + status of the transaction, to see if the data has been successfully + transmitted yet. + + + Typical Usage + + //make sure that the we are in the configured state + if(USBGetDeviceState() == CONFIGURED_STATE) + { + //make sure that the last transaction isn't busy by checking the handle + if(!USBHandleBusy(USBInHandle)) + { + //Write the new data that we wish to send to the host to the INPacket[] array + INPacket[0] = USEFUL_APPLICATION_VALUE1; + INPacket[1] = USEFUL_APPLICATION_VALUE2; + //INPacket[2] = ... (fill in the rest of the packet data) + + //Send the data contained in the INPacket[] array through endpoint "EP_NUM" + USBInHandle = USBTransferOnePacket(EP_NUM,IN_TO_HOST,(BYTE*)&INPacket[0],sizeof(INPacket)); + } + } + + + Conditions: + Before calling USBTransferOnePacket(), the following should be true. + 1. The USB stack has already been initialized (USBDeviceInit() was called). + 2. A transaction is not already pending on the specified endpoint. This + is done by checking the previous request using the USBHandleBusy() + macro (see the typical usage example). + 3. The host has already sent a set configuration request and the + enumeration process is complete. + This can be checked by verifying that the USBGetDeviceState() + macro returns "CONFIGURED_STATE", prior to calling + USBTransferOnePacket(). + + Input: + BYTE ep - The endpoint number that the data will be transmitted or + received on + BYTE dir - The direction of the transfer + This value is either OUT_FROM_HOST or IN_TO_HOST + BYTE* data - For IN transactions: pointer to the RAM buffer containing + the data to be sent to the host. For OUT transactions: pointer + to the RAM buffer that the received data should get written to. + BYTE len - Length of the data needing to be sent (for IN transactions). + For OUT transactions, the len parameter should normally be set + to the endpoint size specified in the endpoint descriptor. + + Return Values: + USB_HANDLE - handle to the transfer. The handle is a pointer to + the BDT entry associated with this transaction. The + status of the transaction (ex: if it is complete or still + pending) can be checked using the USBHandleBusy() macro + and supplying the USB_HANDLE provided by + USBTransferOnePacket(). + + Remarks: + If calling the USBTransferOnePacket() function from within the USBCBInitEP() + callback function, the set configuration is still being processed and the + USBDeviceState may not be == CONFIGURED_STATE yet. In this special case, + the USBTransferOnePacket() may still be called, but make sure that the + endpoint has been enabled and initialized by the USBEnableEndpoint() + function first. + + *************************************************************************/ +USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,BYTE len) +{ + volatile BDT_ENTRY* handle; + + //If the direction is IN + if(dir != 0) + { + //point to the IN BDT of the specified endpoint + handle = pBDTEntryIn[ep]; + } + else + { + //else point to the OUT BDT of the specified endpoint + handle = pBDTEntryOut[ep]; + } + + //Error checking code. Make sure the handle (pBDTEntryIn[ep] or + //pBDTEntryOut[ep]) is initialized before using it. + if(handle == 0) + { + return 0; + } + + //Toggle the DTS bit if required + #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) + handle->STAT.Val ^= _DTSMASK; + #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) + if(ep != 0) + { + handle->STAT.Val ^= _DTSMASK; + } + #endif + + //Set the data pointer, data length, and enable the endpoint + handle->ADR = ConvertToPhysicalAddress(data); + handle->CNT = len; + handle->STAT.Val &= _DTSMASK; + handle->STAT.Val |= _USIE | (_DTSEN & _DTS_CHECKING_ENABLED); + + //Point to the next buffer for ping pong purposes. + if(dir != OUT_FROM_HOST) + { + //toggle over the to the next buffer for an IN endpoint + USBAdvancePingPongBuffer(&pBDTEntryIn[ep]); + } + else + { + //toggle over the to the next buffer for an OUT endpoint + USBAdvancePingPongBuffer(&pBDTEntryOut[ep]); + } + return (USB_HANDLE)handle; +} + + +/******************************************************************** + Function: + void USBStallEndpoint(BYTE ep, BYTE dir) + + Summary: + Configures the specified endpoint to send STALL to the host, the next + time the host tries to access the endpoint. + + PreCondition: + None + + Parameters: + BYTE ep - The endpoint number that should be configured to send STALL. + BYTE dir - The direction of the endpoint to STALL, either + IN_TO_HOST or OUT_FROM_HOST. + + Return Values: + None + + Remarks: + None + + *******************************************************************/ +void USBStallEndpoint(BYTE ep, BYTE dir) +{ + BDT_ENTRY *p; + + if(ep == 0) + { + //For control endpoints (ex: EP0), we need to STALL both IN and OUT + //endpoints. EP0 OUT must also be prepared to receive the next SETUP + //packet that will arrrive. + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED)|_BSTALL; + pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; + + } + else + { + p = (BDT_ENTRY*)(&BDT[EP(ep,dir,0)]); + p->STAT.Val |= _BSTALL | _USIE; + + //If the device is in FULL or ALL_BUT_EP0 ping pong modes + //then stall that entry as well + #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) || (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) + + p = (BDT_ENTRY*)(&BDT[EP(ep,dir,1)]); + p->STAT.Val |= _BSTALL | _USIE; + #endif + } +} + +/************************************************************************** + Function: + void USBCancelIO(BYTE endpoint) + + Description: + This function cancels the transfers pending on the specified endpoint. + This function can only be used after a SETUP packet is received and + before that setup packet is handled. This is the time period in which + the EVENT_EP0_REQUEST is thrown, before the event handler function + returns to the stack. + + Precondition: + + Parameters: + BYTE endpoint - the endpoint number you wish to cancel the transfers for + + Return Values: + None + + Remarks: + None + + **************************************************************************/ +void USBCancelIO(BYTE endpoint) +{ + if(USBPacketDisable == 1) + { + //The PKTDIS bit is currently set right now. It is therefore "safe" + //to mess with the BDT right now. + pBDTEntryIn[endpoint]->Val &= _DTSMASK; //Makes UOWN = 0 (_UCPU mode). Deactivates endpoint. Only sends NAKs. + pBDTEntryIn[endpoint]->Val ^= _DTSMASK; //Toggle the DTS bit. This packet didn't get sent yet, and the next call to USBTransferOnePacket() will re-toggle the DTS bit back to the original (correct) value. + + //Need to do additional handling if ping-pong buffering is being used + #if ((USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) || (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0)) + //Point to the next buffer for ping pong purposes. UOWN getting cleared + //(either due to SIE clearing it after a transaction, or the firmware + //clearing it) makes hardware ping pong pointer advance. + USBAdvancePingPongBuffer(&pBDTEntryIn[endpoint]); + + pBDTEntryIn[endpoint]->STAT.Val &= _DTSMASK; + pBDTEntryIn[endpoint]->STAT.Val ^= _DTSMASK; + #endif + } +} + +/************************************************************************** + Function: + void USBDeviceDetach(void) + + Summary: + This function configures the USB module to "soft detach" itself from + the USB host. + + Description: + This function configures the USB module to perform a "soft detach" + operation, by disabling the D+ (or D-) ~1.5k pull up resistor, which + lets the host know the device is present and attached. This will make + the host think that the device has been unplugged. This is potentially + useful, as it allows the USB device to force the host to re-enumerate + the device (on the firmware has re-enabled the USB module/pull up, by + calling USBDeviceAttach(), to "soft re-attach" to the host). + + Precondition: + Should only be called when USB_INTERRUPT is defined. See remarks + section if USB_POLLING mode option is being used (usb_config.h option). + + Additionally, this function should only be called from the main() loop + context. Do not call this function from within an interrupt handler, as + this function may modify global interrupt enable bits and settings. + + Parameters: + None + + Return Values: + None + + Remarks: + If the application firmware calls USBDeviceDetach(), it is strongly + recommended that the firmware wait at least >= 80ms before calling + USBDeviceAttach(). If the firmeware performs a soft detach, and then + re-attaches too soon (ex: after a few micro seconds for instance), some + hosts may interpret this as an unexpected "glitch" rather than as a + physical removal/re-attachment of the USB device. In this case the host + may simply ignore the event without re-enumerating the device. To + ensure that the host properly detects and processes the device soft + detach/re-attach, it is recommended to make sure the device remains + detached long enough to mimic a real human controlled USB + unplug/re-attach event (ex: after calling USBDeviceDetach(), do not + call USBDeviceAttach() for at least 80+ms, preferrably longer. + + Neither the USBDeviceDetach() or USBDeviceAttach() functions are blocking + or take long to execute. It is the application firmware's + responsibility for adding the 80+ms delay, when using these API + functions. + + Note: The Windows plug and play event handler processing is fairly + slow, especially in certain versions of Windows, and for certain USB + device classes. It has been observed that some device classes need to + provide even more USB detach dwell interval (before calling + USBDeviceAttach()), in order to work correctly after re-enumeration. + If the USB device is a CDC class device, it is recommended to wait + at least 1.5 seconds or longer, before soft re-attaching to the host, + to provide the plug and play event handler enough time to finish + processing the removal event, before the re-attach occurs. + + If the application is using the USB_POLLING mode option, then the + USBDeviceDetach() and USBDeviceAttach() functions are not available. + In this mode, the USB stack relies on the "#define USE_USB_BUS_SENSE_IO" + and "#define USB_BUS_SENSE" options in the + HardwareProfile – [platform name].h file. + + When using the USB_POLLING mode option, and the + "#define USE_USB_BUS_SENSE_IO" definition has been commented out, then + the USB stack assumes that it should always enable the USB module at + pretty much all times. Basically, anytime the application firmware + calls USBDeviceTasks(), the firmware will automatically enable the USB + module. This mode would typically be selected if the application was + designed to be a purely bus powered device. In this case, the + application is powered from the +5V VBUS supply from the USB port, so + it is correct and sensible in this type of application to power up and + turn on the USB module, at anytime that the microcontroller is + powered (which implies the USB cable is attached and the host is also + powered). + + In a self powered application, the USB stack is designed with the + intention that the user will enable the "#define USE_USB_BUS_SENSE_IO" + option in the HardwareProfile – [platform name].h file. When this + option is defined, then the USBDeviceTasks() function will automatically + check the I/O pin port value of the designated pin (based on the + #define USB_BUS_SENSE option in the HardwareProfile – [platform name].h + file), every time the application calls USBDeviceTasks(). If the + USBDeviceTasks() function is executed and finds that the pin defined by + the #define USB_BUS_SENSE is in a logic low state, then it will + automatically disable the USB module and tri-state the D+ and D- pins. + If however the USBDeviceTasks() function is executed and finds the pin + defined by the #define USB_BUS_SENSE is in a logic high state, then it + will automatically enable the USB module, if it has not already been + enabled. + + **************************************************************************/ +#if defined(USB_INTERRUPT) +void USBDeviceDetach(void) +{ + //If the interrupt option is selected then the customer is required + // to notify the stack when the device is attached or removed from the + // bus by calling the USBDeviceAttach() and USBDeviceDetach() functions. +#ifdef USB_SUPPORT_OTG + if (USB_BUS_SENSE != 1) +#endif + { + // Disable module & detach from bus + U1CON = 0; + + // Mask all USB interrupts + U1IE = 0; + + //Move to the detached state + USBDeviceState = DETACHED_STATE; + + #ifdef USB_SUPPORT_OTG + //Disable D+ Pullup + U1OTGCONbits.DPPULUP = 0; + + //Disable HNP + USBOTGDisableHnp(); + + //Deactivate HNP + USBOTGDeactivateHnp(); + + //If ID Pin Changed State + if (USBIDIF && USBIDIE) + { + //Re-detect & Initialize + USBOTGInitialize(); + + //Clear ID Interrupt Flag + USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum); + } + #endif + + #if defined __C30__ || defined __XC16__ + //USBClearInterruptFlag(U1OTGIR, 3); + #endif + //return so that we don't go through the rest of + //the state machine + return; + } + +#ifdef USB_SUPPORT_OTG + //If Session Is Started Then + else + { + //If SRP Is Ready + if (USBOTGSRPIsReady()) + { + //Clear SRPReady + USBOTGClearSRPReady(); + + //Clear SRP Timeout Flag + USBOTGClearSRPTimeOutFlag(); + + //Indicate Session Started + UART2PrintString( "\r\n***** USB OTG B Event - Session Started *****\r\n" ); + } + } +#endif +} +#endif //#if defined(USB_INTERRUPT) +/************************************************************************** + Function: + void USBDeviceAttach(void) + + Summary: + Checks if VBUS is present, and that the USB module is not already + initalized, and if so, enables the USB module so as to signal device + attachment to the USB host. + + Description: + This function indicates to the USB host that the USB device has been + attached to the bus. This function needs to be called in order for the + device to start to enumerate on the bus. + + Precondition: + Should only be called when USB_INTERRUPT is defined. Also, should only + be called from the main() loop context. Do not call USBDeviceAttach() + from within an interrupt handler, as the USBDeviceAttach() function + may modify global interrupt enable bits and settings. + + For normal USB devices: + Make sure that if the module was previously on, that it has been turned off + for a long time (ex: 100ms+) before calling this function to re-enable the module. + If the device turns off the D+ (for full speed) or D- (for low speed) ~1.5k ohm + pull up resistor, and then turns it back on very quickly, common hosts will sometimes + reject this event, since no human could ever unplug and reattach a USB device in a + microseconds (or nanoseconds) timescale. The host could simply treat this as some kind + of glitch and ignore the event altogether. + Parameters: + None + + Return Values: + None + + Remarks: + See also the USBDeviceDetach() API function documentation. +****************************************************************************/ +#if defined(USB_INTERRUPT) +void USBDeviceAttach(void) +{ + //if we are in the detached state + if(USBDeviceState == DETACHED_STATE) + { + if(USB_BUS_SENSE == 1) + { + //Initialize registers to known states. + U1CON = 0; + + // Mask all USB interrupts + U1IE = 0; + + //Configure things like: pull ups, full/low-speed mode, + //set the ping pong mode, and set internal transceiver + SetConfigurationOptions(); + + USBEnableInterrupts(); //Modifies global interrupt settings + + // Enable module & attach to bus + while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;} + + //moved to the attached state + USBDeviceState = ATTACHED_STATE; + + #ifdef USB_SUPPORT_OTG + U1OTGCON = USB_OTG_DPLUS_ENABLE | USB_OTG_ENABLE; + #endif + } + } +} +#endif //#if defined(USB_INTERRUPT) + + +/******************************************************************************* + Function: void USBCtrlEPAllowStatusStage(void); + + Summary: This function prepares the proper endpoint 0 IN or endpoint 0 OUT + (based on the controlTransferState) to allow the status stage packet + of a control transfer to complete. This function gets used + internally by the USB stack itself, but it may also be called from + the application firmware, IF the application firmware called + the USBDeferStatusStage() function during the initial processing + of the control transfer request. In this case, the application + must call the USBCtrlEPAllowStatusStage() once, after it has fully + completed processing and handling the data stage portion of the + request. + + If the application firmware has no need for delaying control + transfers, and therefore never calls USBDeferStatusStage(), then the + application firmware should not call USBCtrlEPAllowStatusStage(). + + Description: + + Conditions: + None + + Input: + + Return: + + Remarks: + None + *****************************************************************************/ +void USBCtrlEPAllowStatusStage(void) +{ + //Check and set two flags, prior to actually modifying any BDT entries. + //This double checking is necessary to make certain that + //USBCtrlEPAllowStatusStage() can be called twice simultaneously (ex: once + //in main loop context, while simultaneously getting an interrupt which + //tries to call USBCtrlEPAllowStatusStage() again, at the same time). + if(USBStatusStageEnabledFlag1 == FALSE) + { + USBStatusStageEnabledFlag1 = TRUE; + if(USBStatusStageEnabledFlag2 == FALSE) + { + USBStatusStageEnabledFlag2 = TRUE; + + //Determine which endpoints (EP0 IN or OUT needs arming for the status + //stage), based on the type of control transfer currently pending. + if(controlTransferState == CTRL_TRF_RX) + { + pBDTEntryIn[0]->CNT = 0; + pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|(_DTSEN & _DTS_CHECKING_ENABLED); + } + else if(controlTransferState == CTRL_TRF_TX) + { + BothEP0OutUOWNsSet = FALSE; //Indicator flag used in USBCtrlTrfOutHandler() + + //This buffer (when ping pong buffering is enabled on EP0 OUT) receives the + //next SETUP packet. + #if((USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)) + pBDTEntryEP0OutCurrent->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutCurrent->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutCurrent->STAT.Val = _USIE|_BSTALL; //Prepare endpoint to accept a SETUP transaction + BothEP0OutUOWNsSet = TRUE; //Indicator flag used in USBCtrlTrfOutHandler() + #endif + + //This EP0 OUT buffer receives the 0-byte OUT status stage packet. + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutNext->STAT.Val = _USIE; // Note: DTSEN is 0 + } + } + } +} + + +/******************************************************************************* + Function: void USBCtrlEPAllowDataStage(void); + + Summary: This function allows the data stage of either a host-to-device or + device-to-host control transfer (with data stage) to complete. + This function is meant to be used in conjunction with either the + USBDeferOUTDataStage() or USBDeferINDataStage(). If the firmware + does not call either USBDeferOUTDataStage() or USBDeferINDataStage(), + then the firmware does not need to manually call + USBCtrlEPAllowDataStage(), as the USB stack will call this function + instead. + + Description: + + Conditions: A control transfer (with data stage) should already be pending, + if the firmware calls this function. Additionally, the firmware + should have called either USBDeferOUTDataStage() or + USBDeferINDataStage() at the start of the control transfer, if + the firmware will be calling this function manually. + + Input: + + Return: + + Remarks: + *****************************************************************************/ +void USBCtrlEPAllowDataStage(void) +{ + USBDeferINDataStagePackets = FALSE; + USBDeferOUTDataStagePackets = FALSE; + + if(controlTransferState == CTRL_TRF_RX) //(...) + { + //Prepare EP0 OUT to receive the first OUT data packet in the data stage sequence. + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&CtrlTrfData); + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|(_DTSEN & _DTS_CHECKING_ENABLED); + } + else //else must be controlTransferState == CTRL_TRF_TX (...) + { + //Error check the data stage byte count. Make sure the user specified + //value was no greater than the number of bytes the host requested. + if(SetupPkt.wLength < inPipes[0].wCount.Val) + { + inPipes[0].wCount.Val = SetupPkt.wLength; + } + USBCtrlTrfTxService(); //Copies one IN data packet worth of data from application buffer + //to CtrlTrfData buffer. Also keeps track of how many bytes remaining. + + //Cnt should have been initialized by responsible request owner (ex: by + //using the USBEP0SendRAMPtr() or USBEP0SendROMPtr() API function). + pBDTEntryIn[0]->ADR = ConvertToPhysicalAddress(&CtrlTrfData); + pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|(_DTSEN & _DTS_CHECKING_ENABLED); + } +} + + +/******************************************************************************/ +/** Internal Functions *********************************************************/ +/******************************************************************************/ + +/******************************************************************** + * Function: void USBConfigureEndpoint(BYTE EPNum, BYTE direction) + * + * PreCondition: None + * + * Input: BYTE EPNum - the endpoint to be configured + * BYTE direction - the direction to be configured + * (either OUT_FROM_HOST or IN_TO_HOST) + * + * Output: None + * + * Side Effects: None + * + * Overview: This function will configure the specified + * endpoint + * + * Note: None + *******************************************************************/ +static void USBConfigureEndpoint(BYTE EPNum, BYTE direction) +{ + volatile BDT_ENTRY* handle; + + //Compute a pointer to the even BDT entry corresponding to the + //EPNum and direction values passed to this function. + handle = (volatile BDT_ENTRY*)&BDT[EP0_OUT_EVEN]; //Get address of start of BDT + handle += EP(EPNum,direction,0u); //Add in offset to the BDT of interest + + handle->STAT.UOWN = 0; //mostly redundant, since USBStdSetCfgHandler() + //already cleared the entire BDT table + + //Make sure our pBDTEntryIn/Out[] pointer is initialized. Needed later + //for USBTransferOnePacket() API calls. + if(direction == OUT_FROM_HOST) + { + pBDTEntryOut[EPNum] = handle; + } + else + { + pBDTEntryIn[EPNum] = handle; + } + + #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + handle->STAT.DTS = 0; + (handle+1)->STAT.DTS = 1; + #elif (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) + //Set DTS to one because the first thing we will do + //when transmitting is toggle the bit + handle->STAT.DTS = 1; + #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) + if(EPNum != 0) + { + handle->STAT.DTS = 1; + } + #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) + if(EPNum != 0) + { + handle->STAT.DTS = 0; + (handle+1)->STAT.DTS = 1; + } + #endif +} + + +/****************************************************************************** + * Function: void USBCtrlEPServiceComplete(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine wrap up the remaining tasks in servicing + * a Setup Request. Its main task is to set the endpoint + * controls appropriately for a given situation. See code + * below. + * There are three main scenarios: + * a) There was no handler for the Request, in this case + * a STALL should be sent out. + * b) The host has requested a read control transfer, + * endpoints are required to be setup in a specific way. + * c) The host has requested a write control transfer, or + * a control data stage is not required, endpoints are + * required to be setup in a specific way. + * + * Packet processing is resumed by clearing PKTDIS bit. + * + * Note: None + *****************************************************************************/ +static void USBCtrlEPServiceComplete(void) +{ + /* + * PKTDIS bit is set when a Setup Transaction is received. + * Clear to resume packet processing. + */ + USBPacketDisable = 0; + + //Check the busy bits and the SetupPtk.DataDir variables to determine what type of + //control transfer is currently in progress. We need to know the type of control + //transfer that is currently pending, in order to know how to properly arm the + //EP0 IN and EP0 OUT endpoints. + if(inPipes[0].info.bits.busy == 0) + { + if(outPipes[0].info.bits.busy == 1) + { + controlTransferState = CTRL_TRF_RX; + /* + * Control Write: + * ... | + */ + + //1. Prepare OUT EP to receive data, unless a USB class request handler + // function decided to defer the data stage (ex: because the intended + // RAM buffer wasn't available yet) by calling USBDeferDataStage(). + // If it did so, it is then responsible for calling USBCtrlEPAllowDataStage(), + // once it is ready to begin receiving the data. + if(USBDeferOUTDataStagePackets == FALSE) + { + USBCtrlEPAllowDataStage(); + } + + //2. IN endpoint 0 status stage will be armed by USBCtrlEPAllowStatusStage() + //after all of the OUT data has been received and consumed, or if a timeout occurs. + USBStatusStageEnabledFlag2 = FALSE; + USBStatusStageEnabledFlag1 = FALSE; + } + else + { + /* + * If no one knows how to service this request then stall. + * Must also prepare EP0 to receive the next SETUP transaction. + */ + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED)|_BSTALL; + pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; + } + } + else // A module has claimed ownership of the control transfer session. + { + if(SetupPkt.DataDir == USB_SETUP_DEVICE_TO_HOST_BITFIELD) + { + controlTransferState = CTRL_TRF_TX; + /* + * Control Read: + * ... | + * + * 1. Prepare IN EP to transfer data to the host. If however the data + * wasn't ready yet (ex: because the firmware needs to go and read it from + * some slow/currently unavailable resource, such as an external I2C EEPROM), + * Then the class request handler reponsible should call the USBDeferDataStage() + * macro. In this case, the firmware may wait up to 500ms, before it is required + * to transmit the first IN data packet. Once the data is ready, and the firmware + * is ready to begin sending the data, it should then call the + * USBCtrlEPAllowDataStage() function to start the data stage. + */ + if(USBDeferINDataStagePackets == FALSE) + { + USBCtrlEPAllowDataStage(); + } + + // 2. (Optionally) allow the status stage now, to prepare for early termination. + // Note: If a class request handler decided to set USBDeferStatusStagePacket == TRUE, + // then it is responsible for eventually calling USBCtrlEPAllowStatusStage() once it + // is ready. If the class request handler does this, it needs to be careful to + // be written so that it can handle the early termination scenario. + // Ex: It should call USBCtrlEPAllowStatusStage() when any of the following occurs: + // 1. The desired total number of bytes were sent to the host. + // 2. The number of bytes that the host originally requested (in the SETUP packet that + // started the control transfer) has been reached. + // 3. Or, if a timeout occurs (ex: <50ms since the last successful EP0 IN transaction), regardless + // of how many bytes have actually been sent. This is necessary to prevent a deadlock situation + // (where the control transfer can't complete, due to continuous NAK on status stage) if the + // host performs early termination. If enabled, the USB_ENABLE_STATUS_STAGE_TIMEOUTS usb_config.h + // option can take care of this for you. + // Note: For this type of control transfer, there is normally no harm in simply arming the + // status stage packet right now, even if the IN data is not ready yet. This allows for + // immediate early termination, without adding unecessary delay. Therefore, it is generally not + // recommended for the USB class handler firmware to call USBDeferStatusStage(), for this + // type of control transfer. If the USB class handler firmware needs more time to fetch the IN + // data that needs to be sent to the host, it should instead use the USBDeferDataStage() function. + USBStatusStageEnabledFlag2 = FALSE; + USBStatusStageEnabledFlag1 = FALSE; + if(USBDeferStatusStagePacket == FALSE) + { + USBCtrlEPAllowStatusStage(); + } + } + else // (SetupPkt.DataDir == USB_SETUP_DIRECTION_HOST_TO_DEVICE) + { + //This situation occurs for special types of control transfers, + //such as that which occurs when the host sends a SET_ADDRESS + //control transfer. Ex: + // + // | + + //Although the data direction is HOST_TO_DEVICE, there is no data stage + //(hence: outPipes[0].info.bits.busy == 0). There is however still + //an IN status stage. + + controlTransferState = CTRL_TRF_RX; //Since this is a HOST_TO_DEVICE control transfer + + //1. Prepare OUT EP to receive the next SETUP packet. + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutNext->STAT.Val = _USIE|_BSTALL; + + //2. Prepare for IN status stage of the control transfer + USBStatusStageEnabledFlag2 = FALSE; + USBStatusStageEnabledFlag1 = FALSE; + if(USBDeferStatusStagePacket == FALSE) + { + USBCtrlEPAllowStatusStage(); + } + } + + }//end if(ctrl_trf_session_owner == MUID_NULL) + +}//end USBCtrlEPServiceComplete + + +/****************************************************************************** + * Function: void USBCtrlTrfTxService(void) + * + * PreCondition: pSrc, wCount, and usb_stat.ctrl_trf_mem are setup properly. + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine is used for device to host control transfers + * (IN transactions). This function takes care of managing a + * transfer over multiple USB transactions. + * This routine should be called from only two places. + * One from USBCtrlEPServiceComplete() and one from + * USBCtrlTrfInHandler(). + * + * Note: + *****************************************************************************/ +static void USBCtrlTrfTxService(void) +{ + BYTE byteToSend; + + //Figure out how many bytes of data to send in the next IN transaction. + //Assume a full size packet, unless otherwise determined below. + byteToSend = USB_EP0_BUFF_SIZE; + if(inPipes[0].wCount.Val < (BYTE)USB_EP0_BUFF_SIZE) + { + byteToSend = inPipes[0].wCount.Val; + + //Keep track of whether or not we have sent a "short packet" yet. + //This is useful so that later on, we can configure EP0 IN to STALL, + //after we have sent all of the intended data. This makes sure the + //hardware STALLs if the host erroneously tries to send more IN token + //packets, requesting more data than intended in the control transfer. + if(shortPacketStatus == SHORT_PKT_NOT_USED) + { + shortPacketStatus = SHORT_PKT_PENDING; + } + else if(shortPacketStatus == SHORT_PKT_PENDING) + { + shortPacketStatus = SHORT_PKT_SENT; + } + } + + //Keep track of how many bytes remain to be sent in the transfer, by + //subtracting the number of bytes about to be sent from the total. + inPipes[0].wCount.Val = inPipes[0].wCount.Val - byteToSend; + + //Next, load the number of bytes to send to BC7..0 in buffer descriptor. + //Note: Control endpoints may never have a max packet size of > 64 bytes. + //Therefore, the BC8 and BC9 bits should always be maintained clear. + pBDTEntryIn[0]->CNT = byteToSend; + + //Now copy the data from the source location, to the CtrlTrfData[] buffer, + //which we will send to the host. + pDst = (USB_VOLATILE BYTE*)CtrlTrfData; // Set destination pointer + if(inPipes[0].info.bits.ctrl_trf_mem == USB_EP0_ROM) // Determine type of memory source + { + while(byteToSend) + { + *pDst++ = *inPipes[0].pSrc.bRom++; + byteToSend--; + }//end while(byte_to_send.Val) + } + else // RAM + { + while(byteToSend) + { + *pDst++ = *inPipes[0].pSrc.bRam++; + byteToSend--; + }//end while(byte_to_send.Val) + }//end if(usb_stat.ctrl_trf_mem == _ROM) +}//end USBCtrlTrfTxService + +/****************************************************************************** + * Function: void USBCtrlTrfRxService(void) + * + * PreCondition: pDst and wCount are setup properly. + * pSrc is always &CtrlTrfData + * usb_stat.ctrl_trf_mem is always USB_EP0_RAM. + * wCount should be set to 0 at the start of each control + * transfer. + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine is used for host to device control transfers + * (uses OUT transactions). This function receives the data that arrives + * on EP0 OUT, and copies it into the appropriate outPipes[0].pDst.bRam + * buffer. Once the host has sent all the data it was intending + * to send, this function will call the appropriate outPipes[0].pFunc() + * handler (unless it is NULL), so that it can be used by the + * intended target firmware. + * + * Note: None + *****************************************************************************/ +static void USBCtrlTrfRxService(void) +{ + BYTE byteToRead; + BYTE i; + + //Load byteToRead with the number of bytes the host just sent us in the + //last OUT transaction. + byteToRead = pBDTEntryEP0OutCurrent->CNT; + + //Update the "outPipes[0].wCount.Val", which keeps track of the total number + //of remaining bytes expected to be received from the host, in the control + //transfer. First check to see if the host sent us more bytes than the + //application firmware was expecting to receive. + if(byteToRead > outPipes[0].wCount.Val) + { + byteToRead = outPipes[0].wCount.Val; + } + //Reduce the number of remaining bytes by the number we just received. + outPipes[0].wCount.Val = outPipes[0].wCount.Val - byteToRead; + + //Copy the OUT DATAx packet bytes that we just received from the host, + //into the user application buffer space. + for(i=0;i 0) + { + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&CtrlTrfData); + if(pBDTEntryEP0OutCurrent->STAT.DTS == 0) + { + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|(_DTSEN & _DTS_CHECKING_ENABLED); + } + else + { + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED); + } + } + else + { + //We have received all OUT packets that we were expecting to + //receive for the control transfer. Prepare EP0 OUT to receive + //the next SETUP transaction that may arrive. + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + //Configure EP0 OUT to receive the next SETUP transaction for any future + //control transfers. However, set BSTALL in case the host tries to send + //more data than it claims it was going to send. + pBDTEntryEP0OutNext->STAT.Val = _USIE|_BSTALL; + + //All data bytes for the host to device control write (OUT) have now been + //received successfully. + //Go ahead and call the user specified callback function, to use/consume + //the control transfer data (ex: if the "void (*function)" parameter + //was non-NULL when USBEP0Receive() was called). + if(outPipes[0].pFunc != NULL) + { + #if defined(__XC8) + //Special pragmas to suppress an expected/harmless warning + //message when building with the XC8 compiler + #pragma warning push + #pragma warning disable 1088 + outPipes[0].pFunc(); //Call the user's callback function + #pragma warning pop + #else + outPipes[0].pFunc(); //Call the user's callback function + #endif + } + outPipes[0].info.bits.busy = 0; + + //Ready to arm status stage IN transaction now, if the application + //firmware has completed processing the request. If it is still busy + //and needs more time to finish handling the request, then the user + //callback (the one called by the outPipes[0].pFunc();) should set the + //USBDeferStatusStagePacket to TRUE (by calling USBDeferStatusStage()). In + //this case, it is the application's firmware responsibility to call + //the USBCtrlEPAllowStatusStage() function, once it is fully done handling the request. + //Note: The application firmware must process the request and call + //USBCtrlEPAllowStatusStage() in a semi-timely fashion. "Semi-timely" + //means either 50ms, 500ms, or 5 seconds, depending on the type of + //control transfer. See the USB 2.0 specification section 9.2.6 for + //more details. + if(USBDeferStatusStagePacket == FALSE) + { + USBCtrlEPAllowStatusStage(); + } + } + +}//end USBCtrlTrfRxService + + +/******************************************************************** + * Function: void USBStdSetCfgHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine first disables all endpoints by + * clearing UEP registers. It then configures + * (initializes) endpoints by calling the callback + * function USBCBInitEP(). + * + * Note: None + *******************************************************************/ +static void USBStdSetCfgHandler(void) +{ + BYTE i; + + // This will generate a zero length packet + inPipes[0].info.bits.busy = 1; + + //Clear all of the endpoint control registers + DisableNonZeroEndpoints(USB_MAX_EP_NUMBER); + + //Clear all of the BDT entries + memset((void*)&BDT[0], 0x00, sizeof(BDT)); + + // Assert reset request to all of the Ping Pong buffer pointers + USBPingPongBufferReset = 1; + + //Re-Initialize all ping pong software state bits to 0 (which corresponds to + //the EVEN buffer being the next one that will be used), since we are also + //doing a hardware ping pong pointer reset above. + for(i = 0; i < (BYTE)(USB_MAX_EP_NUMBER+1u); i++) + { + ep_data_in[i].Val = 0u; + ep_data_out[i].Val = 0u; + } + + //clear the alternate interface settings + memset((void*)&USBAlternateInterface,0x00,USB_MAX_NUM_INT); + + //Stop trying to reset ping pong buffer pointers + USBPingPongBufferReset = 0; + + pBDTEntryIn[0] = (volatile BDT_ENTRY*)&BDT[EP0_IN_EVEN]; + + //Set the next out to the current out packet + pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[EP0_OUT_EVEN]; + pBDTEntryEP0OutNext = pBDTEntryEP0OutCurrent; + + //set the current configuration + USBActiveConfiguration = SetupPkt.bConfigurationValue; + + //if the configuration value == 0 + if(USBActiveConfiguration == 0) + { + //Go back to the addressed state + USBDeviceState = ADDRESS_STATE; + } + else + { + //initialize the required endpoints + USB_SET_CONFIGURATION_HANDLER(EVENT_CONFIGURED,(void*)&USBActiveConfiguration,1); + + //Otherwise go to the configured state. Update the state variable last, + //after performing all of the set configuration related initialization + //tasks. + USBDeviceState = CONFIGURED_STATE; + }//end if(SetupPkt.bConfigurationValue == 0) +}//end USBStdSetCfgHandler + + +/******************************************************************** + * Function: void USBStdGetDscHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine handles the standard GET_DESCRIPTOR + * request. + * + * Note: None + *******************************************************************/ +static void USBStdGetDscHandler(void) +{ + if(SetupPkt.bmRequestType == 0x80) + { + inPipes[0].info.Val = USB_EP0_ROM | USB_EP0_BUSY | USB_EP0_INCLUDE_ZERO; + + switch(SetupPkt.bDescriptorType) + { + case USB_DESCRIPTOR_DEVICE: + #if !defined(USB_USER_DEVICE_DESCRIPTOR) + inPipes[0].pSrc.bRom = (ROM BYTE*)&device_dsc; + #else + inPipes[0].pSrc.bRom = (ROM BYTE*)USB_USER_DEVICE_DESCRIPTOR; + #endif + inPipes[0].wCount.Val = sizeof(device_dsc); + break; + case USB_DESCRIPTOR_CONFIGURATION: + #if !defined(USB_USER_CONFIG_DESCRIPTOR) + inPipes[0].pSrc.bRom = *(USB_CD_Ptr+SetupPkt.bDscIndex); + #else + inPipes[0].pSrc.bRom = *(USB_USER_CONFIG_DESCRIPTOR+SetupPkt.bDscIndex); + #endif + + //This must be loaded using byte addressing. The source pointer + // may not be word aligned for the 16 or 32 bit machines resulting + // in an address error on the dereference. + inPipes[0].wCount.byte.LB = *(inPipes[0].pSrc.bRom+2); + inPipes[0].wCount.byte.HB = *(inPipes[0].pSrc.bRom+3); + break; + case USB_DESCRIPTOR_STRING: + //USB_NUM_STRING_DESCRIPTORS was introduced as optional in release v2.3. In v2.4 and + // later it is now manditory. This should be defined in usb_config.h and should + // indicate the number of string descriptors. + if(SetupPkt.bDscIndexSTAT.UOWN == 1) && (p->STAT.BSTALL == 1)) + CtrlTrfData[0]=0x01; // Set bit0 + break; + } + }//end switch + + if(inPipes[0].info.bits.busy == 1) + { + inPipes[0].pSrc.bRam = (BYTE*)&CtrlTrfData; // Set Source + inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type + inPipes[0].wCount.v[0] = 2; // Set data count + }//end if(...) +}//end USBStdGetStatusHandler + +/******************************************************************** + * Function: void USBStallHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: + * + * Overview: This function handles the event of a STALL + * occuring on the bus + * + * Note: None + *******************************************************************/ +static void USBStallHandler(void) +{ + /* + * Does not really have to do anything here, + * even for the control endpoint. + * All BDs of Endpoint 0 are owned by SIE right now, + * but once a Setup Transaction is received, the ownership + * for EP0_OUT will be returned to CPU. + * When the Setup Transaction is serviced, the ownership + * for EP0_IN will then be forced back to CPU by firmware. + */ + + /* v2b fix */ + if(U1EP0bits.EPSTALL == 1) + { + // UOWN - if 0, owned by CPU, if 1, owned by SIE + if((pBDTEntryEP0OutCurrent->STAT.Val == _USIE) && (pBDTEntryIn[0]->STAT.Val == (_USIE|_BSTALL))) + { + // Set ep0Bo to stall also + pBDTEntryEP0OutCurrent->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED)|_BSTALL; + }//end if + U1EP0bits.EPSTALL = 0; // Clear stall status + }//end if + + USBClearInterruptFlag(USBStallIFReg,USBStallIFBitNum); +} + +/******************************************************************** + * Function: void USBSuspend(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: + * + * Overview: This function handles if the host tries to + * suspend the device + * + * Note: None + *******************************************************************/ +static void USBSuspend(void) +{ + /* + * NOTE: Do not clear UIRbits.ACTVIF here! + * Reason: + * ACTVIF is only generated once an IDLEIF has been generated. + * This is a 1:1 ratio interrupt generation. + * For every IDLEIF, there will be only one ACTVIF regardless of + * the number of subsequent bus transitions. + * + * If the ACTIF is cleared here, a problem could occur when: + * [ IDLE ][bus activity -> + * <--- 3 ms -----> ^ + * ^ ACTVIF=1 + * IDLEIF=1 + * # # # # (#=Program polling flags) + * ^ + * This polling loop will see both + * IDLEIF=1 and ACTVIF=1. + * However, the program services IDLEIF first + * because ACTIVIE=0. + * If this routine clears the only ACTIVIF, + * then it can never get out of the suspend + * mode. + */ + USBActivityIE = 1; // Enable bus activity interrupt + USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum); + + #if defined(__18CXX) || defined(_PIC14E) + U1CONbits.SUSPND = 1; // Put USB module in power conserve + // mode, SIE clock inactive + #endif + USBBusIsSuspended = TRUE; + + /* + * At this point the PIC can go into sleep,idle, or + * switch to a slower clock, etc. This should be done in the + * USBCBSuspend() if necessary. + */ + USB_SUSPEND_HANDLER(EVENT_SUSPEND,0,0); +} + +/******************************************************************** + * Function: void USBWakeFromSuspend(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: + * + * Note: None + *******************************************************************/ +static void USBWakeFromSuspend(void) +{ + USBBusIsSuspended = FALSE; + + /* + * If using clock switching, the place to restore the original + * microcontroller core clock frequency is in the USBCBWakeFromSuspend() callback + */ + USB_WAKEUP_FROM_SUSPEND_HANDLER(EVENT_RESUME,0,0); + + #if defined(__18CXX) || defined(_PIC14E) + //To avoid improperly clocking the USB module, make sure the oscillator + //settings are consistant with USB operation before clearing the SUSPND bit. + //Make sure the correct oscillator settings are selected in the + //"USB_WAKEUP_FROM_SUSPEND_HANDLER(EVENT_RESUME,0,0)" handler. + U1CONbits.SUSPND = 0; // Bring USB module out of power conserve + // mode. + #endif + + + USBActivityIE = 0; + + /******************************************************************** + Bug Fix: Feb 26, 2007 v2.1 + ********************************************************************* + The ACTVIF bit cannot be cleared immediately after the USB module wakes + up from Suspend or while the USB module is suspended. A few clock cycles + are required to synchronize the internal hardware state machine before + the ACTIVIF bit can be cleared by firmware. Clearing the ACTVIF bit + before the internal hardware is synchronized may not have an effect on + the value of ACTVIF. Additonally, if the USB module uses the clock from + the 96 MHz PLL source, then after clearing the SUSPND bit, the USB + module may not be immediately operational while waiting for the 96 MHz + PLL to lock. + ********************************************************************/ + + // UIRbits.ACTVIF = 0; // Removed + #if defined(__18CXX) + while(USBActivityIF) + #endif + { + USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum); + } // Added + +}//end USBWakeFromSuspend + +/******************************************************************** + * Function: void USBCtrlEPService(void) + * + * PreCondition: USTAT is loaded with a valid endpoint address. + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: USBCtrlEPService checks for three transaction + * types that it knows how to service and services + * them: + * 1. EP0 SETUP + * 2. EP0 OUT + * 3. EP0 IN + * It ignores all other types (i.e. EP1, EP2, etc.) + * + * Note: None + *******************************************************************/ +static void USBCtrlEPService(void) +{ + //If we get to here, that means a successful transaction has just occurred + //on EP0. This means "progress" has occurred in the currently pending + //control transfer, so we should re-initialize our timeout counter. + #if defined(USB_ENABLE_STATUS_STAGE_TIMEOUTS) + USBStatusStageTimeoutCounter = USB_STATUS_STAGE_TIMEOUT; + #endif + + //Check if the last transaction was on EP0 OUT endpoint (of any kind, to either the even or odd buffer if ping pong buffers used) + if((USTATcopy.Val & USTAT_EP0_PP_MASK) == USTAT_EP0_OUT_EVEN) + { + //Point to the EP0 OUT buffer of the buffer that arrived + #if defined (_PIC14E) || defined(__18CXX) + pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy.Val & USTAT_EP_MASK)>>1]; + #elif defined(__C30__) || defined(__C32__) || defined __XC16__ + pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy.Val & USTAT_EP_MASK)>>2]; + #else + #error "unimplemented" + #endif + + //Set the next out to the current out packet + pBDTEntryEP0OutNext = pBDTEntryEP0OutCurrent; + //Toggle it to the next ping pong buffer (if applicable) + ((BYTE_VAL*)&pBDTEntryEP0OutNext)->Val ^= USB_NEXT_EP0_OUT_PING_PONG; + + //If the current EP0 OUT buffer has a SETUP packet + if(pBDTEntryEP0OutCurrent->STAT.PID == PID_SETUP) + { + unsigned char setup_cnt; + + //The SETUP transaction data may have gone into the the CtrlTrfData + //buffer, or elsewhere, depending upon how the BDT was prepared + //before the transaction. Therefore, we should copy the data to the + //SetupPkt buffer so it can be processed correctly by USBCtrlTrfSetupHandler(). + for(setup_cnt = 0; setup_cnt < 8u; setup_cnt++) //SETUP data packets always contain exactly 8 bytes. + { + *(BYTE*)((BYTE*)&SetupPkt + setup_cnt) = *(BYTE*)ConvertToVirtualAddress(pBDTEntryEP0OutCurrent->ADR); + pBDTEntryEP0OutCurrent->ADR++; + } + pBDTEntryEP0OutCurrent->ADR = ConvertToPhysicalAddress(&SetupPkt); + + //Handle the control transfer (parse the 8-byte SETUP command and figure out what to do) + USBCtrlTrfSetupHandler(); + } + else + { + //Handle the DATA transfer + USBCtrlTrfOutHandler(); + } + } + else if((USTATcopy.Val & USTAT_EP0_PP_MASK) == USTAT_EP0_IN) + { + //Otherwise the transmission was and EP0 IN + // so take care of the IN transfer + USBCtrlTrfInHandler(); + } + +}//end USBCtrlEPService + +/******************************************************************** + * Function: void USBCtrlTrfSetupHandler(void) + * + * PreCondition: SetupPkt buffer is loaded with valid USB Setup Data + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine is a task dispatcher and has 3 stages. + * 1. It initializes the control transfer state machine. + * 2. It calls on each of the module that may know how to + * service the Setup Request from the host. + * Module Example: USBD, HID, CDC, MSD, ... + * A callback function, USBCBCheckOtherReq(), + * is required to call other module handlers. + * 3. Once each of the modules has had a chance to check if + * it is responsible for servicing the request, stage 3 + * then checks direction of the transfer to determine how + * to prepare EP0 for the control transfer. + * Refer to USBCtrlEPServiceComplete() for more details. + * + * Note: Microchip USB Firmware has three different states for + * the control transfer state machine: + * 1. WAIT_SETUP + * 2. CTRL_TRF_TX (device sends data to host through IN transactions) + * 3. CTRL_TRF_RX (device receives data from host through OUT transactions) + * Refer to firmware manual to find out how one state + * is transitioned to another. + * + * A Control Transfer is composed of many USB transactions. + * When transferring data over multiple transactions, + * it is important to keep track of data source, data + * destination, and data count. These three parameters are + * stored in pSrc,pDst, and wCount. A flag is used to + * note if the data source is from ROM or RAM. + * + *******************************************************************/ +static void USBCtrlTrfSetupHandler(void) +{ + //-------------------------------------------------------------------------- + //1. Re-initialize state tracking variables related to control transfers. + //-------------------------------------------------------------------------- + shortPacketStatus = SHORT_PKT_NOT_USED; + USBDeferStatusStagePacket = FALSE; + USBDeferINDataStagePackets = FALSE; + USBDeferOUTDataStagePackets = FALSE; + BothEP0OutUOWNsSet = FALSE; + controlTransferState = WAIT_SETUP; + + //Abandon any previous control transfers that might have been using EP0. + //Ordinarily, nothing actually needs abandoning, since the previous control + //transfer would have completed successfully prior to the host sending the next + //SETUP packet. However, in a timeout error case, or after an EP0 STALL event, + //one or more UOWN bits might still be set. If so, we should clear the UOWN bits, + //so the EP0 IN/OUT endpoints are in a known inactive state, ready for re-arming + //by the class request handler that will be called next. + pBDTEntryIn[0]->STAT.Val &= ~(_USIE); + ((BYTE_VAL*)&pBDTEntryIn[0])->Val ^= USB_NEXT_EP0_IN_PING_PONG; + pBDTEntryIn[0]->STAT.Val &= ~(_USIE); + ((BYTE_VAL*)&pBDTEntryIn[0])->Val ^= USB_NEXT_EP0_IN_PING_PONG; + pBDTEntryEP0OutNext->STAT.Val &= ~(_USIE); + + inPipes[0].info.Val = 0; + inPipes[0].wCount.Val = 0; + outPipes[0].info.Val = 0; + outPipes[0].wCount.Val = 0; + + + //-------------------------------------------------------------------------- + //2. Now find out what was in the SETUP packet, and begin handling the request. + //-------------------------------------------------------------------------- + USBCheckStdRequest(); //Check for standard USB "Chapter 9" requests. + USB_NONSTANDARD_EP0_REQUEST_HANDLER(EVENT_EP0_REQUEST,0,0); //Check for USB device class specific requests + + + //-------------------------------------------------------------------------- + //3. Re-arm EP0 IN and EP0 OUT endpoints, based on the control transfer in + // progress. If one of the above handlers (in step 2) knew how to process + // the request, it will have set one of the inPipes[0].info.bits.busy or + // outPipes[0].info.bits.busy flags = 1. This lets the + // USBCtrlEPServiceComplete() function know how and which endpoints to + // arm. If both info.bits.busy flags are = 0, then no one knew how to + // process the request. In this case, the default behavior will be to + // perform protocol STALL on EP0. + //-------------------------------------------------------------------------- + USBCtrlEPServiceComplete(); +}//end USBCtrlTrfSetupHandler + + +/****************************************************************************** + * Function: void USBCtrlTrfOutHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine handles an OUT transaction according to + * which control transfer state is currently active. + * + * Note: Note that if the the control transfer was from + * host to device, the session owner should be notified + * at the end of each OUT transaction to service the + * received data. + * + *****************************************************************************/ +static void USBCtrlTrfOutHandler(void) +{ + if(controlTransferState == CTRL_TRF_RX) + { + USBCtrlTrfRxService(); //Copies the newly received data into the appropriate buffer and configures EP0 OUT for next transaction. + } + else //In this case the last OUT transaction must have been a status stage of a CTRL_TRF_TX (... <-- this last OUT just occurred as the status stage) + { + //If the status stage is complete, this means we are done with the + //control transfer. Go back to the idle "WAIT_SETUP" state. + controlTransferState = WAIT_SETUP; + + //Prepare EP0 OUT for the next SETUP transaction, however, it may have + //already been prepared if ping-pong buffering was enabled on EP0 OUT, + //and the last control transfer was of direction: device to host, see + //USBCtrlEPServiceComplete(). If it was already prepared, do not want + //to do anything to the BDT. + if(BothEP0OutUOWNsSet == FALSE) + { + pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE; + pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt); + pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED)|_BSTALL; + } + else + { + BothEP0OutUOWNsSet = FALSE; + } + } +} + +/****************************************************************************** + * Function: void USBCtrlTrfInHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine handles an IN transaction according to + * which control transfer state is currently active. + * + * Note: A Set Address Request must not change the acutal address + * of the device until the completion of the control + * transfer. The end of the control transfer for Set Address + * Request is an IN transaction. Therefore it is necessary + * to service this unique situation when the condition is + * right. Macro mUSBCheckAdrPendingState is defined in + * usb9.h and its function is to specifically service this + * event. + *****************************************************************************/ +static void USBCtrlTrfInHandler(void) +{ + BYTE lastDTS; + + lastDTS = pBDTEntryIn[0]->STAT.DTS; + + //switch to the next ping pong buffer + ((BYTE_VAL*)&pBDTEntryIn[0])->Val ^= USB_NEXT_EP0_IN_PING_PONG; + + //Must check if in ADR_PENDING_STATE. If so, we need to update the address + //now, since the IN status stage of the (set address) control transfer has + //evidently completed successfully. + if(USBDeviceState == ADR_PENDING_STATE) + { + U1ADDR = SetupPkt.bDevADR.Val; + if(U1ADDR != 0u) + { + USBDeviceState=ADDRESS_STATE; + } + else + { + USBDeviceState=DEFAULT_STATE; + } + }//end if + + + if(controlTransferState == CTRL_TRF_TX) + { + pBDTEntryIn[0]->ADR = ConvertToPhysicalAddress(CtrlTrfData); + USBCtrlTrfTxService(); + + //Check if we have already sent a short packet. If so, configure + //the endpoint to STALL in response to any further IN tokens (in the + //case that the host erroneously tries to receive more data than it + //should). + if(shortPacketStatus == SHORT_PKT_SENT) + { + // If a short packet has been sent, don't want to send any more, + // stall next time if host is still trying to read. + pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; + } + else + { + if(lastDTS == 0) + { + pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|(_DTSEN & _DTS_CHECKING_ENABLED); + } + else + { + pBDTEntryIn[0]->STAT.Val = _USIE|_DAT0|(_DTSEN & _DTS_CHECKING_ENABLED); + } + }//end if(...)else + } + else // must have been a CTRL_TRF_RX status stage IN packet (... <-- this last IN just occurred as the status stage) + { + //if someone is still expecting data from the control transfer + // then make sure to terminate that request and let them know that + // they are done + if(outPipes[0].info.bits.busy == 1) + { + if(outPipes[0].pFunc != NULL) + { + outPipes[0].pFunc(); + } + outPipes[0].info.bits.busy = 0; + } + + controlTransferState = WAIT_SETUP; + //Don't need to arm EP0 OUT here. It was already armed by the last that + //got processed by the USBCtrlTrfRxService() handler. + } + +} + + +/******************************************************************** + * Function: void USBCheckStdRequest(void) + * + * PreCondition: None + * + * Input: None + * + * Output: None + * + * Side Effects: None + * + * Overview: This routine checks the setup data packet to see + * if it knows how to handle it + * + * Note: None + *******************************************************************/ +static void USBCheckStdRequest(void) +{ + if(SetupPkt.RequestType != USB_SETUP_TYPE_STANDARD_BITFIELD) return; + + switch(SetupPkt.bRequest) + { + case USB_REQUEST_SET_ADDRESS: + inPipes[0].info.bits.busy = 1; // This will generate a zero length packet + USBDeviceState = ADR_PENDING_STATE; // Update state only + /* See USBCtrlTrfInHandler() for the next step */ + break; + case USB_REQUEST_GET_DESCRIPTOR: + USBStdGetDscHandler(); + break; + case USB_REQUEST_SET_CONFIGURATION: + USBStdSetCfgHandler(); + break; + case USB_REQUEST_GET_CONFIGURATION: + inPipes[0].pSrc.bRam = (BYTE*)&USBActiveConfiguration; // Set Source + inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type + inPipes[0].wCount.v[0] = 1; // Set data count + inPipes[0].info.bits.busy = 1; + break; + case USB_REQUEST_GET_STATUS: + USBStdGetStatusHandler(); + break; + case USB_REQUEST_CLEAR_FEATURE: + case USB_REQUEST_SET_FEATURE: + USBStdFeatureReqHandler(); + break; + case USB_REQUEST_GET_INTERFACE: + inPipes[0].pSrc.bRam = (BYTE*)&USBAlternateInterface[SetupPkt.bIntfID]; // Set source + inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type + inPipes[0].wCount.v[0] = 1; // Set data count + inPipes[0].info.bits.busy = 1; + break; + case USB_REQUEST_SET_INTERFACE: + inPipes[0].info.bits.busy = 1; + USBAlternateInterface[SetupPkt.bIntfID] = SetupPkt.bAltID; + break; + case USB_REQUEST_SET_DESCRIPTOR: + USB_SET_DESCRIPTOR_HANDLER(EVENT_SET_DESCRIPTOR,0,0); + break; + case USB_REQUEST_SYNCH_FRAME: + default: + break; + }//end switch +}//end USBCheckStdRequest + +/******************************************************************** + * Function: void USBStdFeatureReqHandler(void) + * + * PreCondition: None + * + * Input: None + * + * Output: Can alter BDT entries. Can also modify USB stack + * Maintained variables. + * + * Side Effects: None + * + * Overview: This routine handles the standard SET & CLEAR + * FEATURES requests + * + * Note: This is a private function, intended for internal + * use by the USB stack, when processing SET/CLEAR + * feature requests. + *******************************************************************/ +static void USBStdFeatureReqHandler(void) +{ + BDT_ENTRY *p; + EP_STATUS current_ep_data; + #if defined(__C32__) + DWORD* pUEP; + #else + unsigned char* pUEP; + #endif + + + #ifdef USB_SUPPORT_OTG + //Check for USB On-The-Go (OTG) specific requests + if ((SetupPkt.bFeature == OTG_FEATURE_B_HNP_ENABLE)&& + (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD)) + { + inPipes[0].info.bits.busy = 1; + if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + USBOTGEnableHnp(); + else + USBOTGDisableHnp(); + } + + if ((SetupPkt.bFeature == OTG_FEATURE_A_HNP_SUPPORT)&& + (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD)) + { + inPipes[0].info.bits.busy = 1; + if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + USBOTGEnableSupportHnp(); + else + USBOTGDisableSupportHnp(); + } + + if ((SetupPkt.bFeature == OTG_FEATURE_A_ALT_HNP_SUPPORT)&& + (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD)) + { + inPipes[0].info.bits.busy = 1; + if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + USBOTGEnableAltHnp(); + else + USBOTGDisableAltHnp(); + } + #endif //#ifdef USB_SUPPORT_OTG + + //Check if the host sent a valid SET or CLEAR feature (remote wakeup) request. + if((SetupPkt.bFeature == USB_FEATURE_DEVICE_REMOTE_WAKEUP)&& + (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD)) + { + inPipes[0].info.bits.busy = 1; + if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + RemoteWakeup = TRUE; + else + RemoteWakeup = FALSE; + }//end if + + //Check if the host sent a valid SET or CLEAR endpoint halt request. + if((SetupPkt.bFeature == USB_FEATURE_ENDPOINT_HALT)&& + (SetupPkt.Recipient == USB_SETUP_RECIPIENT_ENDPOINT_BITFIELD)&& + (SetupPkt.EPNum != 0) && (SetupPkt.EPNum <= USB_MAX_EP_NUMBER)&& + (USBDeviceState == CONFIGURED_STATE)) + { + //The request was valid. Take control of the control transfer and + //perform the host requested action. + inPipes[0].info.bits.busy = 1; + + //Fetch a pointer to the BDT that the host wants to SET/CLEAR halt on. + if(SetupPkt.EPDir == OUT_FROM_HOST) + { + p = (BDT_ENTRY*)pBDTEntryOut[SetupPkt.EPNum]; + current_ep_data.Val = ep_data_out[SetupPkt.EPNum].Val; + } + else + { + p = (BDT_ENTRY*)pBDTEntryIn[SetupPkt.EPNum]; + current_ep_data.Val = ep_data_in[SetupPkt.EPNum].Val; + } + + //If ping pong buffering is enabled on the requested endpoint, need + //to point to the one that is the active BDT entry which the SIE will + //use for the next attempted transaction on that EP number. + #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + if(current_ep_data.bits.ping_pong_state == 0) //Check if even + { + USBHALPingPongSetToEven(&p); + } + else //else must have been odd + { + USBHALPingPongSetToOdd(&p); + } + #endif + + //Update the BDT pointers with the new, next entry based on the feature + // request + if(SetupPkt.EPDir == OUT_FROM_HOST) + { + pBDTEntryOut[SetupPkt.EPNum] = (volatile BDT_ENTRY *)p; + } + else + { + pBDTEntryIn[SetupPkt.EPNum] = (volatile BDT_ENTRY *)p; + } + + //Check if it was a SET_FEATURE endpoint halt request + if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + { + if(p->STAT.UOWN == 1) + { + //Mark that we are terminating this transfer and that the user + // needs to be notified later + if(SetupPkt.EPDir == OUT_FROM_HOST) + { + ep_data_out[SetupPkt.EPNum].bits.transfer_terminated = 1; + } + else + { + ep_data_in[SetupPkt.EPNum].bits.transfer_terminated = 1; + } + } + + //Then STALL the endpoint + p->STAT.Val |= _USIE|_BSTALL; + }//if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + else + { + //Else the request must have been a CLEAR_FEATURE endpoint halt. + #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + //toggle over the to the non-active BDT + USBAdvancePingPongBuffer(&p); + + if(p->STAT.UOWN == 1) + { + //Clear UOWN and set DTS state so it will be correct the next time + //the application firmware uses USBTransferOnePacket() on the EP. + p->STAT.Val &= (~_USIE); //Clear UOWN bit + p->STAT.Val |= _DAT1; //Set DTS to DATA1 + USB_TRANSFER_TERMINATED_HANDLER(EVENT_TRANSFER_TERMINATED,p,sizeof(p)); + } + else + { + //UOWN already clear, but still need to set DTS to DATA1 + p->STAT.Val |= _DAT1; + } + + //toggle back to the active BDT (the one the SIE is currently looking at + //and will use for the next successful transaction to take place on the EP + USBAdvancePingPongBuffer(&p); + + //Check if we are currently terminating, or have previously terminated + //a transaction on the given endpoint. If so, need to clear UOWN, + //set DTS to the proper state, and call the application callback + //function. + if((current_ep_data.bits.transfer_terminated != 0) || (p->STAT.UOWN == 1)) + { + if(SetupPkt.EPDir == OUT_FROM_HOST) + { + ep_data_out[SetupPkt.EPNum].bits.transfer_terminated = 0; + } + else + { + ep_data_in[SetupPkt.EPNum].bits.transfer_terminated = 0; + } + //clear UOWN, clear DTS to DATA0, and finally remove the STALL condition + p->STAT.Val &= ~(_USIE | _DAT1 | _BSTALL); + //Call the application event handler callback function, so it can + //decide if the endpoint should get re-armed again or not. + USB_TRANSFER_TERMINATED_HANDLER(EVENT_TRANSFER_TERMINATED,p,sizeof(p)); + } + else + { + //clear UOWN, clear DTS to DATA0, and finally remove the STALL condition + p->STAT.Val &= ~(_USIE | _DAT1 | _BSTALL); + } + #else //else we must not be using ping-pong buffering on the requested endpoint + //Check if we need to call the user transfer terminated event callback function. + //We should call the callback, if the endpoint was previously terminated, + //or the endpoint is currently armed, and the host is performing clear + //endpoint halt, even though the endpoint wasn't stalled. + if((current_ep_data.bits.transfer_terminated != 0) || (p->STAT.UOWN == 1)) + { + //We are going to call the user transfer terminated callback. + //Clear the flag so we know we took care of it and don't need + //to call it again later. + if(SetupPkt.EPDir == OUT_FROM_HOST) + { + ep_data_out[SetupPkt.EPNum].bits.transfer_terminated = 0; + } + else + { + ep_data_in[SetupPkt.EPNum].bits.transfer_terminated = 0; + } + + //Clear UOWN and remove the STALL condition. + // In this case we also need to set the DTS bit to 1 so that + // it toggles to DATA0 the next time the application firmware + // calls USBTransferOnePacket() (or equivalent macro). + p->STAT.Val &= ~(_USIE | _BSTALL); + p->STAT.Val |= _DAT1; + //Let the application firmware know a transaction just + //got terminated by the host, and that it is now free to + //re-arm the endpoint or do other tasks if desired. + USB_TRANSFER_TERMINATED_HANDLER(EVENT_TRANSFER_TERMINATED,p,sizeof(p)); + } + else + { + //Clear UOWN and remove the STALL condition. + // In this case we also need to set the DTS bit to 1 so that + // it toggles to DATA0 the next time the application firmware + // calls USBTransferOnePacket() (or equivalent macro). + p->STAT.Val &= ~(_USIE | _BSTALL); + p->STAT.Val |= _DAT1; + } + #endif //end of #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) + + //Get a pointer to the appropriate UEPn register + #if defined(__C32__) + pUEP = (DWORD*)(&U1EP0); + pUEP += (SetupPkt.EPNum*4); + #else + pUEP = (unsigned char*)(&U1EP0+SetupPkt.EPNum); + #endif + + //Clear the STALL bit in the UEP register + *pUEP &= ~UEP_STALL; + }//end if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE) + }//end if (lots of checks for set/clear endpoint halt) +}//end USBStdFeatureReqHandler + + +/** EOF USBDevice.c *****************************************************/ diff --git a/FirmwareDumper/USB/usb_device.h b/FirmwareDumper/USB/usb_device.h new file mode 100644 index 0000000..cdb480b --- /dev/null +++ b/FirmwareDumper/USB/usb_device.h @@ -0,0 +1,1988 @@ +/******************************************************************************* + + USB Device header file + +Summary: + This file, with its associated C source file, provides the main substance of + the USB device side stack. These files will receive, transmit, and process + various USB commands as well as take action when required for various events + that occur on the bus. + +Description: + This file, with its associated C source file, provides the main substance of + the USB device side stack. These files will receive, transmit, and process + various USB commands as well as take action when required for various events + that occur on the bus. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + ..\\..\\Microchip\\Include + + . + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + +******************************************************************************/ +//DOM-IGNORE-BEGIN +/****************************************************************************** + FileName: usb_device.h + Dependencies: See INCLUDES section + Processor: All Microchip parts with a USB module + Hardware: Please see documentation in "/Microchip/Help" + folder for details. + Complier: Microchip C18 + XC16 + XC32 + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the "Company") for its PIC(R) Microcontroller is intended and + supplied to you, the Company’s customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. +*******************************************************************/ + +/******************************************************************** + Change History: + Rev Description + ---- ----------- + 2.1 Added "(" & ")" to EP definitions + updated for simplicity and to use common + coding style + + 2.6 Removed many of the device specific information to the + HAL layer files. Moved many of the CH9 defintions to the + CH9 file. + + 2.6a No Change + + 2.7 Fixed error where USBHandleGetAddr() didn't convert the + return address from a physical address to a virtual address + for PIC32. + + Added macro versions of USBDeviceAttach() and USBDeviceDetach() + so they will compile without error when using polling mode. + + 2.7a No Change + + 2.8 Added EVENT_TRANSFER_TERMINATED event enum item. + +********************************************************************/ + +#ifndef USBDEVICE_H +#define USBDEVICE_H +//DOM-IGNORE-END + +/** DEFINITIONS ****************************************************/ + +//USB_HANDLE is a pointer to an entry in the BDT. This pointer can be used +// to read the length of the last transfer, the status of the last transfer, +// and various other information. Insure to initialize USB_HANDLE objects +// to NULL so that they are in a known state during their first usage. +#define USB_HANDLE void* + +#define USB_EP0_ROM 0x00 //Data comes from RAM +#define USB_EP0_RAM 0x01 //Data comes from ROM +#define USB_EP0_BUSY 0x80 //The PIPE is busy +#define USB_EP0_INCLUDE_ZERO 0x40 //include a trailing zero packet +#define USB_EP0_NO_DATA 0x00 //no data to send +#define USB_EP0_NO_OPTIONS 0x00 //no options set + +/******************************************************************** + * Standard Request Codes + * USB 2.0 Spec Ref Table 9-4 + *******************************************************************/ + +/* USB Device States as returned by USBGetDeviceState(). Only the defintions + for these states should be used. The actual value for each state should + not be relied upon as constant and may change based on the implementation. */ +typedef enum +{ + /* Detached is the state in which the device is not attached to the bus. When + in the detached state a device should not have any pull-ups attached to either + the D+ or D- line. */ + DETACHED_STATE + /*DOM-IGNORE-BEGIN*/ = 0x00 /*DOM-IGNORE-END*/, + /* Attached is the state in which the device is attached ot the bus but the + hub/port that it is attached to is not yet configured. */ + ATTACHED_STATE + /*DOM-IGNORE-BEGIN*/ = 0x01 /*DOM-IGNORE-END*/, + /* Powered is the state in which the device is attached to the bus and the + hub/port that it is attached to is configured. */ + POWERED_STATE + /*DOM-IGNORE-BEGIN*/ = 0x02 /*DOM-IGNORE-END*/, + /* Default state is the state after the device receives a RESET command from + the host. */ + DEFAULT_STATE + /*DOM-IGNORE-BEGIN*/ = 0x04 /*DOM-IGNORE-END*/, + /* Address pending state is not an official state of the USB defined states. + This state is internally used to indicate that the device has received a + SET_ADDRESS command but has not received the STATUS stage of the transfer yet. + The device is should not switch addresses until after the STATUS stage is + complete. */ + ADR_PENDING_STATE + /*DOM-IGNORE-BEGIN*/ = 0x08 /*DOM-IGNORE-END*/, + /* Address is the state in which the device has its own specific address on the + bus. */ + ADDRESS_STATE + /*DOM-IGNORE-BEGIN*/ = 0x10 /*DOM-IGNORE-END*/, + /* Configured is the state where the device has been fully enumerated and is + operating on the bus. The device is now allowed to excute its application + specific tasks. It is also allowed to increase its current consumption to the + value specified in the configuration descriptor of the current configuration. + */ + CONFIGURED_STATE + /*DOM-IGNORE-BEGIN*/ = 0x20 /*DOM-IGNORE-END*/ +} USB_DEVICE_STATE; + + +/* USB device stack events description here - DWF */ +typedef enum +{ + // Notification that a SET_CONFIGURATION() command was received (device) + EVENT_CONFIGURED + /*DOM-IGNORE-BEGIN*/ = EVENT_DEVICE_STACK_BASE /*DOM-IGNORE-END*/, + + // A SET_DESCRIPTOR request was received (device) + EVENT_SET_DESCRIPTOR, + + // An endpoint 0 request was received that the stack did not know how to + // handle. This is most often a request for one of the class drivers. + // Please refer to the class driver documenation for information related + // to what to do if this request is received. (device) + EVENT_EP0_REQUEST, + +// // A USB transfer has completed. The data associated with this event is of +// // the data type HOST_TRANSFER_DATA if the event is generated from the host +// // stack. +// EVENT_TRANSFER, +// +// // A USB Start of Frame token has been received. This event is not +// // used by the Host stack. +// EVENT_SOF, +// +// // Device-mode resume received. This event is not used by the Host stack. +// EVENT_RESUME, +// +// // Device-mode suspend/idle event received. This event is not used by the +// // Host stack. +// EVENT_SUSPEND, +// +// // Device-mode bus reset received. This event is not used by the Host +// // stack. +// EVENT_RESET, + +// // Device Mode: A setup packet received (data: SETUP_PKT). This event is +// // not used by the Host stack. +// EVENT_SETUP, + + // Device-mode USB cable has been attached. This event is not used by the + // Host stack. The client driver may provide an application event when a + // device attaches. + EVENT_ATTACH, + + // A user transfer was terminated by the stack. This event will pass back + // the value of the handle that was terminated. Compare this value against + // the current valid handles to determine which transfer was terminated. + EVENT_TRANSFER_TERMINATED + +} USB_DEVICE_STACK_EVENTS; + +/** Function Prototypes **********************************************/ + + +/******************************************************************************/ +/** External API Functions ****************************************************/ +/******************************************************************************/ + +/************************************************************************** + Function: + void USBDeviceInit(void) + + Description: + This function initializes the device stack it in the default state. The + USB module will be completely reset including all of the internal + variables, registers, and interrupt flags. + + Precondition: + This function must be called before any of the other USB Device + functions can be called, including USBDeviceTasks(). + + Parameters: + None + + Return Values: + None + + Remarks: + None + + **************************************************************************/ +void USBDeviceInit(void); + +/************************************************************************** + Function: + void USBDeviceTasks(void) + + Summary: + This function is the main state machine/transaction handler of the USB + device side stack. When the USB stack is operated in "USB_POLLING" mode + (usb_config.h user option) the USBDeviceTasks() function should be called + periodically to receive and transmit packets through the stack. This + function also takes care of control transfers associated with the USB + enumeration process, and detecting various USB events (such as suspend). + This function should be called at least once every 1.8ms during the USB + enumeration process. After the enumeration process is complete (which can + be determined when USBGetDeviceState() returns CONFIGURED_STATE), the + USBDeviceTasks() handler may be called the faster of: either once + every 9.8ms, or as often as needed to make sure that the hardware USTAT + FIFO never gets full. A good rule of thumb is to call USBDeviceTasks() at + a minimum rate of either the frequency that USBTransferOnePacket() gets + called, or, once/1.8ms, whichever is faster. See the inline code comments + near the top of usb_device.c for more details about minimum timing + requirements when calling USBDeviceTasks(). + + When the USB stack is operated in "USB_INTERRUPT" mode, it is not necessary + to call USBDeviceTasks() from the main loop context. In the USB_INTERRUPT + mode, the USBDeviceTasks() handler only needs to execute when a USB + interrupt occurs, and therefore only needs to be called from the interrupt + context. + + Description: + This function is the main state machine/transaction handler of the USB + device side stack. When the USB stack is operated in "USB_POLLING" mode + (usb_config.h user option) the USBDeviceTasks() function should be called + periodically to receive and transmit packets through the stack. This + function also takes care of control transfers associated with the USB + enumeration process, and detecting various USB events (such as suspend). + This function should be called at least once every 1.8ms during the USB + enumeration process. After the enumeration process is complete (which can + be determined when USBGetDeviceState() returns CONFIGURED_STATE), the + USBDeviceTasks() handler may be called the faster of: either once + every 9.8ms, or as often as needed to make sure that the hardware USTAT + FIFO never gets full. A good rule of thumb is to call USBDeviceTasks() at + a minimum rate of either the frequency that USBTransferOnePacket() gets + called, or, once/1.8ms, whichever is faster. See the inline code comments + near the top of usb_device.c for more details about minimum timing + requirements when calling USBDeviceTasks(). + + When the USB stack is operated in "USB_INTERRUPT" mode, it is not necessary + to call USBDeviceTasks() from the main loop context. In the USB_INTERRUPT + mode, the USBDeviceTasks() handler only needs to execute when a USB + interrupt occurs, and therefore only needs to be called from the interrupt + context. + + Typical usage: + + void main(void) + { + USBDeviceInit(); + while(1) + { + USBDeviceTasks(); //Takes care of enumeration and other USB events + if((USBGetDeviceState() \< CONFIGURED_STATE) || + (USBIsDeviceSuspended() == TRUE)) + { + //Either the device is not configured or we are suspended, + // so we don't want to execute any USB related application code + continue; //go back to the top of the while loop + } + else + { + //Otherwise we are free to run USB and non-USB related user + //application code. + UserApplication(); + } + } + } + + + Precondition: + Make sure the USBDeviceInit() function has been called prior to calling + USBDeviceTasks() for the first time. + Remarks: + USBDeviceTasks() does not need to be called while in the USB suspend mode, + if the user application firmware in the USBCBSuspend() callback function + enables the ACTVIF USB interrupt source and put the microcontroller into + sleep mode. If the application firmware decides not to sleep the + microcontroller core during USB suspend (ex: continues running at full + frequency, or clock switches to a lower frequency), then the USBDeviceTasks() + function must still be called periodically, at a rate frequent enough to + ensure the 10ms resume recovery interval USB specification is met. Assuming + a worst case primary oscillator and PLL start up time of <5ms, then + USBDeviceTasks() should be called once every 5ms in this scenario. + + When the USB cable is detached, or the USB host is not actively powering + the VBUS line to +5V nominal, the application firmware does not always have + to call USBDeviceTasks() frequently, as no USB activity will be taking + place. However, if USBDeviceTasks() is not called regularly, some + alternative means of promptly detecting when VBUS is powered (indicating + host attachment), or not powered (host powered down or USB cable unplugged) + is still needed. For self or dual self/bus powered USB applications, see + the USBDeviceAttach() and USBDeviceDetach() API documentation for additional + considerations. + + **************************************************************************/ +void USBDeviceTasks(void); + + +/******************************************************************************* + Function: + void USBEnableEndpoint(BYTE ep, BYTE options) + + Summary: + This function will enable the specified endpoint with the specified + options + Description: + This function will enable the specified endpoint with the specified + options. + + Typical Usage: + + void USBCBInitEP(void) + { + USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); + USBMSDInit(); + } + + + In the above example endpoint number MSD_DATA_IN_EP is being configured + for both IN and OUT traffic with handshaking enabled. Also since + MSD_DATA_IN_EP is not endpoint 0 (MSD does not allow this), then we can + explicitly disable SETUP packets on this endpoint. + Conditions: + None + Input: + BYTE ep - the endpoint to be configured + BYTE options - optional settings for the endpoint. The options should + be ORed together to form a single options string. The + available optional settings for the endpoint. The + options should be ORed together to form a single options + string. The available options are the following\: + * USB_HANDSHAKE_ENABLED enables USB handshaking (ACK, + NAK) + * USB_HANDSHAKE_DISABLED disables USB handshaking (ACK, + NAK) + * USB_OUT_ENABLED enables the out direction + * USB_OUT_DISABLED disables the out direction + * USB_IN_ENABLED enables the in direction + * USB_IN_DISABLED disables the in direction + * USB_ALLOW_SETUP enables control transfers + * USB_DISALLOW_SETUP disables control transfers + * USB_STALL_ENDPOINT STALLs this endpoint + Return: + None + Remarks: + None + *****************************************************************************/ +void USBEnableEndpoint(BYTE ep, BYTE options); + + +/************************************************************************* + Function: + USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, BYTE len) + + Summary: + Transfers a single packet (one transaction) of data on the USB bus. + + Description: + The USBTransferOnePacket() function prepares a USB endpoint + so that it may send data to the host (an IN transaction), or + receive data from the host (an OUT transaction). The + USBTransferOnePacket() function can be used both to receive and + send data to the host. This function is the primary API function + provided by the USB stack firmware for sending or receiving application + data over the USB port. + + The USBTransferOnePacket() is intended for use with all application + endpoints. It is not used for sending or receiving applicaiton data + through endpoint 0 by using control transfers. Separate API + functions, such as USBEP0Receive(), USBEP0SendRAMPtr(), and + USBEP0SendROMPtr() are provided for this purpose. + + The USBTransferOnePacket() writes to the Buffer Descriptor Table (BDT) + entry associated with an endpoint buffer, and sets the UOWN bit, which + prepares the USB hardware to allow the transaction to complete. The + application firmware can use the USBHandleBusy() macro to check the + status of the transaction, to see if the data has been successfully + transmitted yet. + + + Typical Usage + + //make sure that the we are in the configured state + if(USBGetDeviceState() == CONFIGURED_STATE) + { + //make sure that the last transaction isn't busy by checking the handle + if(!USBHandleBusy(USBInHandle)) + { + //Write the new data that we wish to send to the host to the INPacket[] array + INPacket[0] = USEFUL_APPLICATION_VALUE1; + INPacket[1] = USEFUL_APPLICATION_VALUE2; + //INPacket[2] = ... (fill in the rest of the packet data) + + //Send the data contained in the INPacket[] array through endpoint "EP_NUM" + USBInHandle = USBTransferOnePacket(EP_NUM,IN_TO_HOST,(BYTE*)&INPacket[0],sizeof(INPacket)); + } + } + + + Conditions: + Before calling USBTransferOnePacket(), the following should be true. + 1. The USB stack has already been initialized (USBDeviceInit() was called). + 2. A transaction is not already pending on the specified endpoint. This + is done by checking the previous request using the USBHandleBusy() + macro (see the typical usage example). + 3. The host has already sent a set configuration request and the + enumeration process is complete. + This can be checked by verifying that the USBGetDeviceState() + macro returns "CONFIGURED_STATE", prior to calling + USBTransferOnePacket(). + + Input: + BYTE ep - The endpoint number that the data will be transmitted or + received on + BYTE dir - The direction of the transfer + This value is either OUT_FROM_HOST or IN_TO_HOST + BYTE* data - For IN transactions: pointer to the RAM buffer containing + the data to be sent to the host. For OUT transactions: pointer + to the RAM buffer that the received data should get written to. + BYTE len - Length of the data needing to be sent (for IN transactions). + For OUT transactions, the len parameter should normally be set + to the endpoint size specified in the endpoint descriptor. + + Return Values: + USB_HANDLE - handle to the transfer. The handle is a pointer to + the BDT entry associated with this transaction. The + status of the transaction (ex: if it is complete or still + pending) can be checked using the USBHandleBusy() macro + and supplying the USB_HANDLE provided by + USBTransferOnePacket(). + + Remarks: + If calling the USBTransferOnePacket() function from within the USBCBInitEP() + callback function, the set configuration is still being processed and the + USBDeviceState may not be == CONFIGURED_STATE yet. In this special case, + the USBTransferOnePacket() may still be called, but make sure that the + endpoint has been enabled and initialized by the USBEnableEndpoint() + function first. + + *************************************************************************/ +USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,BYTE len); + +/******************************************************************** + Function: + void USBStallEndpoint(BYTE ep, BYTE dir) + + Summary: + Configures the specified endpoint to send STALL to the host, the next + time the host tries to access the endpoint. + + PreCondition: + None + + Parameters: + BYTE ep - The endpoint number that should be configured to send STALL. + BYTE dir - The direction of the endpoint to STALL, either + IN_TO_HOST or OUT_FROM_HOST. + + Return Values: + None + + Remarks: + None + + *******************************************************************/ +void USBStallEndpoint(BYTE ep, BYTE dir); +/************************************************************************** + Function: + void USBCancelIO(BYTE endpoint) + + Description: + This function cancels the transfers pending on the specified endpoint. + This function can only be used after a SETUP packet is received and + before that setup packet is handled. This is the time period in which + the EVENT_EP0_REQUEST is thrown, before the event handler function + returns to the stack. + + Precondition: + + Parameters: + BYTE endpoint - the endpoint number you wish to cancel the transfers for + + Return Values: + None + + Remarks: + None + + **************************************************************************/ +void USBCancelIO(BYTE endpoint); + +/************************************************************************** + Function: + void USBDeviceDetach(void) + + Summary: + This function configures the USB module to "soft detach" itself from + the USB host. + + Description: + This function configures the USB module to perform a "soft detach" + operation, by disabling the D+ (or D-) ~1.5k pull up resistor, which + lets the host know the device is present and attached. This will make + the host think that the device has been unplugged. This is potentially + useful, as it allows the USB device to force the host to re-enumerate + the device (on the firmware has re-enabled the USB module/pull up, by + calling USBDeviceAttach(), to "soft re-attach" to the host). + + Precondition: + Should only be called when USB_INTERRUPT is defined. See remarks + section if USB_POLLING mode option is being used (usb_config.h option). + + Additionally, this function should only be called from the main() loop + context. Do not call this function from within an interrupt handler, as + this function may modify global interrupt enable bits and settings. + + Parameters: + None + + Return Values: + None + + Remarks: + If the application firmware calls USBDeviceDetach(), it is strongly + recommended that the firmware wait at least >= 80ms before calling + USBDeviceAttach(). If the firmeware performs a soft detach, and then + re-attaches too soon (ex: after a few micro seconds for instance), some + hosts may interpret this as an unexpected "glitch" rather than as a + physical removal/re-attachment of the USB device. In this case the host + may simply ignore the event without re-enumerating the device. To + ensure that the host properly detects and processes the device soft + detach/re-attach, it is recommended to make sure the device remains + detached long enough to mimic a real human controlled USB + unplug/re-attach event (ex: after calling USBDeviceDetach(), do not + call USBDeviceAttach() for at least 80+ms, preferrably longer. + + Neither the USBDeviceDetach() or USBDeviceAttach() functions are blocking + or take long to execute. It is the application firmware's + responsibility for adding the 80+ms delay, when using these API + functions. + + Note: The Windows plug and play event handler processing is fairly + slow, especially in certain versions of Windows, and for certain USB + device classes. It has been observed that some device classes need to + provide even more USB detach dwell interval (before calling + USBDeviceAttach()), in order to work correctly after re-enumeration. + If the USB device is a CDC class device, it is recommended to wait + at least 1.5 seconds or longer, before soft re-attaching to the host, + to provide the plug and play event handler enough time to finish + processing the removal event, before the re-attach occurs. + + If the application is using the USB_POLLING mode option, then the + USBDeviceDetach() and USBDeviceAttach() functions are not available. + In this mode, the USB stack relies on the "#define USE_USB_BUS_SENSE_IO" + and "#define USB_BUS_SENSE" options in the + HardwareProfile – [platform name].h file. + + When using the USB_POLLING mode option, and the + "#define USE_USB_BUS_SENSE_IO" definition has been commented out, then + the USB stack assumes that it should always enable the USB module at + pretty much all times. Basically, anytime the application firmware + calls USBDeviceTasks(), the firmware will automatically enable the USB + module. This mode would typically be selected if the application was + designed to be a purely bus powered device. In this case, the + application is powered from the +5V VBUS supply from the USB port, so + it is correct and sensible in this type of application to power up and + turn on the USB module, at anytime that the microcontroller is + powered (which implies the USB cable is attached and the host is also + powered). + + In a self powered application, the USB stack is designed with the + intention that the user will enable the "#define USE_USB_BUS_SENSE_IO" + option in the HardwareProfile – [platform name].h file. When this + option is defined, then the USBDeviceTasks() function will automatically + check the I/O pin port value of the designated pin (based on the + #define USB_BUS_SENSE option in the HardwareProfile – [platform name].h + file), every time the application calls USBDeviceTasks(). If the + USBDeviceTasks() function is executed and finds that the pin defined by + the #define USB_BUS_SENSE is in a logic low state, then it will + automatically disable the USB module and tri-state the D+ and D- pins. + If however the USBDeviceTasks() function is executed and finds the pin + defined by the #define USB_BUS_SENSE is in a logic high state, then it + will automatically enable the USB module, if it has not already been + enabled. + + **************************************************************************/ +void USBDeviceDetach(void); + +/*DOM-IGNORE-BEGIN*/ +#if !defined(USB_INTERRUPT) + #define USBDeviceDetach() +#endif +/*DOM-IGNORE-END*/ + +/************************************************************************** + Function: + void USBDeviceAttach(void) + + Summary: + Checks if VBUS is present, and that the USB module is not already + initalized, and if so, enables the USB module so as to signal device + attachment to the USB host. + + Description: + This function indicates to the USB host that the USB device has been + attached to the bus. This function needs to be called in order for the + device to start to enumerate on the bus. + + Precondition: + Should only be called when USB_INTERRUPT is defined. Also, should only + be called from the main() loop context. Do not call USBDeviceAttach() + from within an interrupt handler, as the USBDeviceAttach() function + may modify global interrupt enable bits and settings. + + For normal USB devices: + Make sure that if the module was previously on, that it has been turned off + for a long time (ex: 100ms+) before calling this function to re-enable the module. + If the device turns off the D+ (for full speed) or D- (for low speed) ~1.5k ohm + pull up resistor, and then turns it back on very quickly, common hosts will sometimes + reject this event, since no human could ever unplug and reattach a USB device in a + microseconds (or nanoseconds) timescale. The host could simply treat this as some kind + of glitch and ignore the event altogether. + Parameters: + None + + Return Values: + None + + Remarks: + See also the USBDeviceDetach() API function documentation. +****************************************************************************/ +void USBDeviceAttach(void); + +/*DOM-IGNORE-BEGIN*/ +#if !defined(USB_INTERRUPT) + #define USBDeviceAttach() +#endif +/*DOM-IGNORE-END*/ + + +/******************************************************************************* + Function: void USBCtrlEPAllowStatusStage(void); + + Summary: This function prepares the proper endpoint 0 IN or endpoint 0 OUT + (based on the controlTransferState) to allow the status stage packet + of a control transfer to complete. This function gets used + internally by the USB stack itself, but it may also be called from + the application firmware, IF the application firmware called + the USBDeferStatusStage() function during the initial processing + of the control transfer request. In this case, the application + must call the USBCtrlEPAllowStatusStage() once, after it has fully + completed processing and handling the data stage portion of the + request. + + If the application firmware has no need for delaying control + transfers, and therefore never calls USBDeferStatusStage(), then the + application firmware should not call USBCtrlEPAllowStatusStage(). + + Description: + + Conditions: + None + + Input: + + Return: + + Remarks: + None + *****************************************************************************/ +void USBCtrlEPAllowStatusStage(void); + + + +/******************************************************************************* + Function: void USBCtrlEPAllowDataStage(void); + + Summary: This function allows the data stage of either a host-to-device or + device-to-host control transfer (with data stage) to complete. + This function is meant to be used in conjunction with either the + USBDeferOUTDataStage() or USBDeferINDataStage(). If the firmware + does not call either USBDeferOUTDataStage() or USBDeferINDataStage(), + then the firmware does not need to manually call + USBCtrlEPAllowDataStage(), as the USB stack will call this function + instead. + + Description: + + Conditions: A control transfer (with data stage) should already be pending, + if the firmware calls this function. Additionally, the firmware + should have called either USBDeferOUTDataStage() or + USBDeferINDataStage() at the start of the control transfer, if + the firmware will be calling this function manually. + + Input: + + Return: + + Remarks: + *****************************************************************************/ +void USBCtrlEPAllowDataStage(void); + + +/******************************************************************************* + Function: void USBDeferOUTDataStage(void); + + Summary: This function will cause the USB hardware to continuously NAK the + OUT data packets sent from the host, during the data stage of a + device to host control transfer. This allows the firmware more time + to prepare the RAM buffer that will eventually be used to receive the + data from the host. This is also useful, if the firmware wishes to + receive the OUT data in a different context than what the + USBDeviceTasks() function executes at. + + Calling this function (macro) will assert ownership of the currently + pending control transfer. Therefore, the USB stack will not STALL + when it reaches the data stage of the control transfer, even if the + firmware has not (yet) called the USBEP0Receive() API function. + However, the application firware must still (eventually, once it is + ready) call one of the aforementioned API function. + + Example Usage: + + 1. Host sends a SETUP packet to the device, requesting a host to + device control transfer, with data stage (OUT data packets). + 2. USBDeviceTasks() executes, and then calls the USBCBCheckOtherReq() + callback event handler. The USBCBCheckOtherReq() calls the + application specific/device class specific handler that detects + the type of control transfer. + 3. If the firmware needs more time before it wishes to receive the + first OUT data packet, or, if the firmware wishes to process the + command in a different context, then it may call + USBDeferOUTDataStage(), in the context of the + USBCBCheckOtherReq() handler function. + 4. If the firmware called USBDeferOUTDataStage() in step #3 above, + then the hardware will NAK the OUT data packets sent by the + host, for the OUT data stage. + 5. Once the firmware is ready, it should then call USBEP0Receive(), + to prepare the USB stack to receive the OUT data from the host, + and to write it to the user specified buffer. + 6. The firmware should now call USBCtrlEPAllowDataStage(). This + will allow the data stage to complete. Once all OUT data has + been received, the user callback function (provided by the + function pointer provided when calling USBEP0Receive()) will + get called. + 7. Once all data has been received from the host, the status stage + (a 0-byte IN packet) will complete automatically (assuming the + firmware did not call USBDeferStatusStage() during step #3). + + + Description: + + Conditions: Before calling USBDeferOUTDataStage(), the firmware should first + verify that the control transfer has a data stage, and that + it is of type host-to-device (OUT). + + Input: + + Return: + + Remarks: Section 9.2.6 of the official USB 2.0 specifications indicates that + the USB device must be able to receive all bytes and complete the + control transfer within a maximum of 5 seconds. + + If the firmware calls USBDeferOUTDataStage(), it must eventually call + USBEP0Receive(), and then call USBCtrlEPAllowDataStage(). If it does + not do this, the control transfer will never be able to complete. + This will break the USB connection, as the host needs to be able to + communicate over EP0, in order to perform basic tasks including + enumeration. + + The firmware should never call both USBDeferINDataStage() and + USBDeferOUTDataStage() during the same control transfer. These + functions are mutually exclusive (a control transfer with data stage + can never contain both IN and OUT data packets during the data stage). + *****************************************************************************/ +void USBDeferOUTDataStage(void); +extern volatile BOOL USBDeferOUTDataStagePackets; +/*DOM-IGNORE-BEGIN*/ +#define USBDeferOUTDataStage() {USBDeferOUTDataStagePackets = TRUE; outPipes[0].info.bits.busy = 1;} +/*DOM-IGNORE-END*/ + +/******************************************************************************* + Function: void USBDeferStatusStage(void); + + Summary: Calling this function will prevent the USB stack from automatically + enabling the status stage for the currently pending control transfer + from completing immediately after all data bytes have been sent or + received. This is useful if a class handler or USB application + firmware project uses control transfers for sending/receiving data + over EP0, but requires time in order to finish processing and/or to + consume the data. + + For example: Consider an application which receives OUT data from the + USB host, through EP0 using control transfers. Now assume that this + application wishes to do something time consuming with this data (ex: + transmit it to and save it to an external EEPROM device, connected + via SPI/I2C/etc.). In this case, it would typically be desireable to + defer allowing the USB status stage of the control transfer to complete, + until after the data has been fully sent to the EEPROM device and saved. + + If the USB class handler firmware that processes the control transfer + SETUP packet determines that it will need extra time to complete the + control transfer, it may optionally call USBDeferStatusStage(). If it + does so, it is then the responsibility of the application firmware to + eventually call USBCtrlEPAllowStatusStage(), once the firmware has + finished processing the data associated with the control transfer. + + If the firmware call USBDeferStatusStage(), but never calls + USBCtrlEPAllowStatusStage(), then one of two possibilities will occur. + + 1. If the "USB_ENABLE_STATUS_STAGE_TIMEOUTS" option is commented in + usb_config.h, then the status stage of the control transfer will + never be able to complete. This is an error case and should be + avoided. + 2. If the "USB_ENABLE_STATUS_STAGE_TIMEOUTS" option is enabled in + usb_config.h, then the USBDeviceTasks() function will + automatically call USBCtrlEPAllowStatusStage(), after the + "USB_STATUS_STAGE_TIMEOUT" has elapsed, since the last quanta of + "progress" has occurred in the control transfer. Progress is + defined as the last successful transaction completing on EP0 IN or + EP0 OUT. + Although the timeouts feature allows the status stage to + [eventually] complete, it is still preferable to manually call + USBCtrlEPAllowStatusStage() after the application firmware has + finished processing/consuming the control transfer data, as this + will allow for much faster processing of control transfers, and + therefore much higher data rates and better user responsiveness. + Description: + + Conditions: + None + + Input: + + Return: + + Remarks: If this function is called, is should get called after the SETUP + packet has arrived (the control transfer has started), but before + the USBCtrlEPServiceComplete() function has been called by the USB + stack. Therefore, the normal place to call USBDeferStatusStage() + would be from within the USBCBCheckOtherReq() handler context. For + example, in a HID application using control transfers, the + USBDeferStatusStage() function would be called from within the + USER_GET_REPORT_HANDLER or USER_SET_REPORT_HANDLER functions. + *****************************************************************************/ +void USBDeferStatusStage(void); +extern volatile BOOL USBDeferStatusStagePacket; +/*DOM-IGNORE-BEGIN*/ +#define USBDeferStatusStage() {USBDeferStatusStagePacket = TRUE;} +/*DOM-IGNORE-END*/ + + +/******************************************************************************* + Function: BOOL USBOUTDataStageDeferred(void); + + Summary: Returns TRUE if a control transfer with OUT data stage is pending, + and the firmware has called USBDeferOUTDataStage(), but has not + yet called USBCtrlEPAllowDataStage(). + Returns FALSE if a control transfer with OUT data stage is either + not pending, or the firmware did not call USBDeferOUTDataStage() + at the start of the control transfer. + + This function (macro) would typically be used in the case where the + USBDeviceTasks() function executes in the interrupt context (ex: + USB_INTERRUPT option selected in usb_config.h), but the firmware + wishes to take care of handling the data stage of the control transfer + in the main loop context. + + In this scenario, typical usage would be: + 1. Host starts a control transfer with OUT data stage. + 2. USBDeviceTasks() (in this scenario, interrupt context) executes. + 3. USBDeviceTasks() calls USBCBCheckOtherReq(), which in turn + determines that the control transfer is class specific, with + OUT data stage. + 4. The user code in USBCBCheckOtherReq() (also in interrupt context, + since it is called from USBDeviceTasks(), and therefore executes + at the same priority/context) calls USBDeferOUTDataStage(). + + 5. Meanwhile, in the main loop context, a polling handler may be + periodically checking if(USBOUTDataStageDeferred() == TRUE). + Ordinarily, it would evaluate false, but when a control transfer + becomes pending, and after the USBDeferOUTDataStage() macro has + been called (ex: in the interrupt context), the if() statement + will evaluate true. In this case, the main loop context can then + take care of receiving the data, by calling USBEP0Receive() and + USBCtrlEPAllowDataStage(). + + Description: + + Conditions: + + Input: + + Return: + + Remarks: + *****************************************************************************/ +BOOL USBOUTDataStageDeferred(void); +/*DOM-IGNORE-BEGIN*/ +#define USBOUTDataStageDeferred() USBDeferOUTDataStagePackets +/*DOM-IGNORE-END*/ + +/******************************************************************************* + Function: void USBDeferINDataStage(void); + + Summary: This function will cause the USB hardware to continuously NAK the + IN token packets sent from the host, during the data stage of a + device to host control transfer. This allows the firmware more time + to process and prepare the IN data packets that will eventually be + sent to the host. This is also useful, if the firmware needs to + process/prepare the IN data in a different context than what the + USBDeviceTasks() function executes at. + + Calling this function (macro) will assert ownership of the currently + pending control transfer. Therefore, the USB stack will not STALL + when it reaches the data stage of the control transfer, even if the + firmware has not (yet) called the USBEP0SendRAMPtr() or + USBEP0SendROMPtr() API function. However, the application firware + must still (eventually, once it is ready) call one of the + aforementioned API functions. + + Example Usage: + + 1. Host sends a SETUP packet to the device, requesting a device to + host control transfer, with data stage. + 2. USBDeviceTasks() executes, and then calls the USBCBCheckOtherReq() + callback event handler. The USBCBCheckOtherReq() calls the + application specific/device class specific handler that detects + the type of control transfer. + 3. If the firmware needs more time to prepare the first IN data packet, + or, if the firmware wishes to process the command in a different + context (ex: if USBDeviceTasks() executes as an interrupt handler, + but the IN data stage data needs to be prepared in the main loop + context), then it may call USBDeferINDataStage(), in the context + of the USBCBCheckOtherReq() handler function. + 4. If the firmware called USBDeferINDataStage() in step #3 above, + then the hardware will NAK the IN token packets sent by the + host, for the IN data stage. + 5. Once the firmware is ready, and has successfully prepared the + data to be sent to the host in fulfillment of the control + transfer, it should then call USBEP0SendRAMPtr() or + USBEP0SendROMPtr(), to prepare the USB stack to know how many + bytes to send to the host, and from what source location. + 6. The firmware should now call USBCtrlEPAllowDataStage(). This + will allow the data stage to complete. The USB stack will send + the data buffer specified by the USBEP0SendRAMPtr() or + USBEP0SendROMPtr() function, when it was called. + 7. Once all data has been sent to the host, or if the host performs + early termination, the status stage (a 0-byte OUT packet) will + complete automatically (assuming the firmware did not call + USBDeferStatusStage() during step #3). + + + Description: + + Conditions: Before calling USBDeferINDataStage(), the firmware should first + verify that the control transfer has a data stage, and that + it is of type device-to-host (IN). + + Input: + + Return: + + Remarks: Section 9.2.6 of the official USB 2.0 specifications indicates that + the USB device must return the first IN data packet within 500ms + of the start of the control transfer. In order to meet this + specification, the firmware must call USBEP0SendRAMPtr() or + USBEP0SendROMPtr(), and then call USBCtrlEPAllowDataStage(), in + less than 500ms from the start of the control transfer. + + If the firmware calls USBDeferINDataStage(), it must eventually call + USBEP0SendRAMPtr() or USBEP0SendROMPtr(), and then call + USBCtrlEPAllowDataStage(). If it does not do this, the control + transfer will never be able to complete. + + The firmware should never call both USBDeferINDataStage() and + USBDeferOUTDataStage() during the same control transfer. These + functions are mutually exclusive (a control transfer with data stage + can never contain both IN and OUT data packets during the data stage). + *****************************************************************************/ +void USBDeferINDataStage(void); +extern volatile BOOL USBDeferINDataStagePackets; +/*DOM-IGNORE-BEGIN*/ +#define USBDeferINDataStage() {USBDeferINDataStagePackets = TRUE; inPipes[0].info.bits.busy = 1;} +/*DOM-IGNORE-END*/ + + + +/******************************************************************************* + Function: BOOL USBINDataStageDeferred(void); + + Summary: Returns TRUE if a control transfer with IN data stage is pending, + and the firmware has called USBDeferINDataStage(), but has not + yet called USBCtrlEPAllowDataStage(). + Returns FALSE if a control transfer with IN data stage is either + not pending, or the firmware did not call USBDeferINDataStage() + at the start of the control transfer. + + This function (macro) would typically be used in the case where the + USBDeviceTasks() function executes in the interrupt context (ex: + USB_INTERRUPT option selected in usb_config.h), but the firmware + wishes to take care of handling the data stage of the control transfer + in the main loop context. + + In this scenario, typical usage would be: + 1. Host starts a control transfer with IN data stage. + 2. USBDeviceTasks() (in this scenario, interrupt context) executes. + 3. USBDeviceTasks() calls USBCBCheckOtherReq(), which in turn + determines that the control transfer is class specific, with + IN data stage. + 4. The user code in USBCBCheckOtherReq() (also in interrupt context, + since it is called from USBDeviceTasks(), and therefore executes + at the same priority/context) calls USBDeferINDataStage(). + + 5. Meanwhile, in the main loop context, a polling handler may be + periodically checking if(USBINDataStageDeferred() == TRUE). + Ordinarily, it would evaluate false, but when a control transfer + becomes pending, and after the USBDeferINDataStage() macro has + been called (ex: in the interrupt context), the if() statement + will evaluate true. In this case, the main loop context can then + take care of sending the data (when ready), by calling + USBEP0SendRAMPtr() or USBEP0SendROMPtr() and + USBCtrlEPAllowDataStage(). + + Description: + + Conditions: + + Input: + + Return: + + Remarks: + *****************************************************************************/ +BOOL USBINDataStageDeferred(void); +/*DOM-IGNORE-BEGIN*/ +#define USBINDataStageDeferred() USBDeferINDataStagePackets +/*DOM-IGNORE-END*/ + + + +/******************************************************************** + Function: + BOOL USBGetRemoteWakeupStatus(void) + + Summary: + This function indicates if remote wakeup has been enabled by the host. + Devices that support remote wakeup should use this function to + determine if it should send a remote wakeup. + + Description: + This function indicates if remote wakeup has been enabled by the host. + Devices that support remote wakeup should use this function to + determine if it should send a remote wakeup. + + If a device does not support remote wakeup (the Remote wakeup bit, bit + 5, of the bmAttributes field of the Configuration descriptor is set to + 1), then it should not send a remote wakeup command to the PC and this + function is not of any use to the device. If a device does support + remote wakeup then it should use this function as described below. + + If this function returns FALSE and the device is suspended, it should + not issue a remote wakeup (resume). + + If this function returns TRUE and the device is suspended, it should + issue a remote wakeup (resume). + + A device can add remote wakeup support by having the _RWU symbol added + in the configuration descriptor (located in the usb_descriptors.c file + in the project). This done in the 8th byte of the configuration + descriptor. For example: + + + ROM BYTE configDescriptor1[]={ + 0x09, // Size + USB_DESCRIPTOR_CONFIGURATION, // descriptor type + DESC_CONFIG_WORD(0x0022), // Total length + 1, // Number of interfaces + 1, // Index value of this cfg + 0, // Configuration string index + _DEFAULT | _SELF | _RWU, // Attributes, see usb_device.h + 50, // Max power consumption in 2X mA(100mA) + + //The rest of the configuration descriptor should follow + + + For more information about remote wakeup, see the following section of + the USB v2.0 specification available at www.usb.org: + * Section 9.2.5.2 + * Table 9-10 + * Section 7.1.7.7 + * Section 9.4.5 + + Conditions: + None + + Return Values: + TRUE - Remote Wakeup has been enabled by the host + FALSE - Remote Wakeup is not currently enabled + + Remarks: + None + + *******************************************************************/ +BOOL USBGetRemoteWakeupStatus(void); +/*DOM-IGNORE-BEGIN*/ +#define USBGetRemoteWakeupStatus() RemoteWakeup +/*DOM-IGNORE-END*/ + +/*************************************************************************** + Function: + USB_DEVICE_STATE USBGetDeviceState(void) + + Summary: + This function will return the current state of the device on the USB. + This function should return CONFIGURED_STATE before an application + tries to send information on the bus. + Description: + This function returns the current state of the device on the USB. This + \function is used to determine when the device is ready to communicate + on the bus. Applications should not try to send or receive data until + this function returns CONFIGURED_STATE. + + It is also important that applications yield as much time as possible + to the USBDeviceTasks() function as possible while the this function + \returns any value between ATTACHED_STATE through CONFIGURED_STATE. + + For more information about the various device states, please refer to + the USB specification section 9.1 available from www.usb.org. + + Typical usage: + + void main(void) + { + USBDeviceInit() + while(1) + { + USBDeviceTasks(); + if((USBGetDeviceState() \< CONFIGURED_STATE) || + (USBIsDeviceSuspended() == TRUE)) + { + //Either the device is not configured or we are suspended + // so we don't want to do execute any application code + continue; //go back to the top of the while loop + } + else + { + //Otherwise we are free to run user application code. + UserApplication(); + } + } + } + + Conditions: + None + Return Values: + USB_DEVICE_STATE - the current state of the device on the bus + + Remarks: + None + ***************************************************************************/ +USB_DEVICE_STATE USBGetDeviceState(void); +/*DOM-IGNORE-BEGIN*/ +#define USBGetDeviceState() USBDeviceState +/*DOM-IGNORE-END*/ + + + +/*************************************************************************** + Function: + BOOL USBGetSuspendState(void) + + Summary: + This function indicates if the USB port that this device is attached to is + currently suspended. When suspended, it will not be able to transfer data + over the bus. + Description: + This function indicates if the USB port that this device is attached to is + currently suspended. When suspended, it will not be able to transfer data + over the bus. + This function can be used by the application to skip over section of + code that do not need to exectute if the device is unable to send data + over the bus. This function can also be used to help determine when it is + legal to perform USB remote wakeup signalling, for devices supporting this + feature. + + Typical usage: + + void main(void) + { + USBDeviceInit() + while(1) + { + USBDeviceTasks(); + if((USBGetDeviceState() \< CONFIGURED_STATE) || + (USBGetSuspendState() == TRUE)) + { + //Either the device is not configured or we are suspended + // so we don't want to do execute any application code + continue; //go back to the top of the while loop + } + else + { + //Otherwise we are free to run user application code. + UserApplication(); + } + } + } + + Conditions: + None + Return Values: + TRUE - the USB port this device is attached to is suspended. + FALSE - the USB port this device is attached to is not suspended. + Remarks: + This function is the same as USBIsBusSuspended(). + ***************************************************************************/ +BOOL USBGetSuspendState(void); +/*DOM-IGNORE-BEGIN*/ +#define USBGetSuspendState() USBBusIsSuspended +/*DOM-IGNORE-END*/ + +/******************************************************************************* + Function: + BOOL USBIsDeviceSuspended(void) + + Summary: + This function indicates if the USB module is in suspend mode. + + Description: + This function indicates if the USB module is in suspend mode. This function + does NOT indicate that a suspend request has been received. It only + reflects the state of the USB module. + + Typical Usage: + + if(USBIsDeviceSuspended() == TRUE) + { + return; + } + // otherwise do some application specific tasks + + + Conditions: + None + Input: + None + Return: + None + Remarks: + None + *****************************************************************************/ +BOOL USBIsDeviceSuspended(void); +/*DOM-IGNORE-BEGIN*/ +#define USBIsDeviceSuspended() USBSuspendControl +/*DOM-IGNORE-END*/ + + +/******************************************************************************* + Function: + BOOL USBIsBusSuspended(void); + + Summary: + This function indicates if the USB bus is in suspend mode. + + Description: + This function indicates if the USB bus is in suspend mode. This function + is typically used for checking if the conditions are consistent with + performing a USB remote wakeup sequence. + + Typical Usage: + + if((USBIsBusSuspended() == TRUE) && (USBGetRemoteWakeupStatus() == TRUE)) + { + //Check if some stimulus occured, which will be used as the wakeup source + if(sw3 == 0) + { + USBCBSendResume(); //Send the remote wakeup signalling to the host + } + } + // otherwise do some other application specific tasks + + + Conditions: + None + Input: + None + Return: + None + Remarks: + The USBIsBusSuspended() function relies on the USBBusIsSuspended boolean + variable, which gets updated by the USBDeviceTasks() function. Therefore, + in order to be sure the return value is not "stale", it is suggested to make + sure USBDeviceTasks() has executed recently (if using USB polling mode). + *****************************************************************************/ +BOOL USBIsBusSuspended(void); +/*DOM-IGNORE-BEGIN*/ +#define USBIsBusSuspended() USBBusIsSuspended +/*DOM-IGNORE-END*/ + +/******************************************************************************* + Function: + void USBSoftDetach(void); + + Summary: + This function performs a detach from the USB bus via software. + + Description: + This function performs a detach from the USB bus via software. + + Conditions: + None + Input: + None + Return: + None + Remarks: + Caution should be used when detaching from the bus. Some PC drivers and + programs may require additional time after a detach before a device can be + reattached to the bus. + *****************************************************************************/ +void USBSoftDetach(void); +/*DOM-IGNORE-BEGIN*/ +#define USBSoftDetach() U1CON = 0; U1IE = 0; USBDeviceState = DETACHED_STATE; +/*DOM-IGNORE-END*/ + + +/************************************************************************* + Function: + BOOL USBHandleBusy(USB_HANDLE handle) + + Summary: + Checks to see if the input handle is busy + + Description: + Checks to see if the input handle is busy + + Typical Usage + + //make sure that the last transfer isn't busy by checking the handle + if(!USBHandleBusy(USBGenericInHandle)) + { + //Send the data contained in the INPacket[] array out on + // endpoint USBGEN_EP_NUM + USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket[0],sizeof(INPacket)); + } + + + Conditions: + None + Input: + USB_HANDLE handle - handle of the transfer that you want to check the + status of + Return Values: + TRUE - The specified handle is busy + FALSE - The specified handle is free and available for a transfer + Remarks: + None + *************************************************************************/ +BOOL USBHandleBusy(USB_HANDLE handle); +/*DOM-IGNORE-BEGIN*/ +#define USBHandleBusy(handle) (handle==0?0:((volatile BDT_ENTRY*)handle)->STAT.UOWN) +/*DOM-IGNORE-END*/ + +/******************************************************************** + Function: + WORD USBHandleGetLength(USB_HANDLE handle) + + Summary: + Retrieves the length of the destination buffer of the input + handle + + Description: + Retrieves the length of the destination buffer of the input + handle + + PreCondition: + None + + Parameters: + USB_HANDLE handle - the handle to the transfer you want the + address for. + + Return Values: + WORD - length of the current buffer that the input handle + points to. If the transfer is complete then this is the + length of the data transmitted or the length of data + actually received. + + Remarks: + None + + *******************************************************************/ +WORD USBHandleGetLength(USB_HANDLE handle); +/*DOM-IGNORE-BEGIN*/ +#define USBHandleGetLength(handle) (((volatile BDT_ENTRY*)handle)->CNT) +/*DOM-IGNORE-END*/ + +/******************************************************************** + Function: + WORD USBHandleGetAddr(USB_HANDLE) + + Summary: + Retrieves the address of the destination buffer of the input + handle + + Description: + Retrieves the address of the destination buffer of the input + handle + + PreCondition: + None + + Parameters: + USB_HANDLE handle - the handle to the transfer you want the + address for. + + Return Values: + WORD - address of the current buffer that the input handle + points to. + + Remarks: + None + + *******************************************************************/ +WORD USBHandleGetAddr(USB_HANDLE); +/*DOM-IGNORE-BEGIN*/ +#define USBHandleGetAddr(handle) ConvertToVirtualAddress((((volatile BDT_ENTRY*)handle)->ADR)) +/*DOM-IGNORE-END*/ + + +/******************************************************************** + Function: + USB_HANDLE USBGetNextHandle(BYTE ep_num, BYTE ep_dir) + Summary: + Retrieves the handle to the next endpoint BDT entry that the + USBTransferOnePacket() will use. + Description: + Retrieves the handle to the next endpoint BDT that the + USBTransferOnePacket() will use. Useful for initialization and when + ping pong buffering will be used on application endpoints. + PreCondition: + Will return NULL if the USB device has not yet been configured/the + endpoint specified has not yet been initalized by USBEnableEndpoint(). + Parameters: + BYTE ep_num - The endpoint number to get the handle for (valid + values are 1-15, 0 is not a valid input value for this API) + BYTE ep_dir - The endpoint direction associated with the endpoint number + to get the handle for (valid values are OUT_FROM_HOST and IN_TO_HOST). + Return Values: + USB_HANDLE - Returns the USB_HANDLE (a pointer) to the BDT that will be + used next time the USBTransferOnePacket() function is called, for the + given ep_num and ep_dir + Remarks: + This API is useful for initializing USB_HANDLEs during initialization of + the application firmware. It is also useful when ping-pong bufferring is + enabled, and the application firmware wishes to arm both the even and odd + BDTs for an endpoint simultaneously. In this case, the application + firmware for sending data to the host would typically be something like + follows: + + + USB_HANDLE Handle1; + USB_HANDLE Handle2; + USB_HANDLE* pHandle = &Handle1; + BYTE UserDataBuffer1[64]; + BYTE UserDataBuffer2[64]; + BYTE* pDataBuffer = &UserDataBuffer1[0]; + + //Add some code that loads UserDataBuffer1[] with useful data to send, + //using the pDataBuffer pointer, for example: + //for(i = 0; i < 64; i++) + //{ + // *pDataBuffer++ = [useful data value]; + //} + + //Check if the next USB endpoint BDT is available + if(!USBHandleBusy(USBGetNextHandle(ep_num, IN_TO_HOST)) + { + //The endpoint is available. Send the data. + *pHandle = USBTransferOnePacket(ep_num, ep_dir, pDataBuffer, bytecount); + //Toggle the handle and buffer pointer for the next transaction + if(pHandle == &Handle1) + { + pHandle = &Handle2; + pDataBuffer = &UserDataBuffer2[0]; + } + else + { + pHandle = &Handle1; + pDataBuffer = &UserDataBuffer1[0]; + } + } + + //The firmware can then load the next data buffer (in this case + //UserDataBuffer2)with useful data, and send it using the same + //process. For example: + + //Add some code that loads UserDataBuffer2[] with useful data to send, + //using the pDataBuffer pointer, for example: + //for(i = 0; i < 64; i++) + //{ + // *pDataBuffer++ = [useful data value]; + //} + + //Check if the next USB endpoint BDT is available + if(!USBHandleBusy(USBGetNextHandle(ep_num, IN_TO_HOST)) + { + //The endpoint is available. Send the data. + *pHandle = USBTransferOnePacket(ep_num, ep_dir, pDataBuffer, bytecount); + //Toggle the handle and buffer pointer for the next transaction + if(pHandle == &Handle1) + { + pHandle = &Handle2; + pDataBuffer = &UserDataBuffer2[0]; + } + else + { + pHandle = &Handle1; + pDataBuffer = &UserDataBuffer1[0]; + } + } + + + *******************************************************************/ +USB_HANDLE USBGetNextHandle(BYTE ep_num, BYTE ep_dir); +/*DOM-IGNORE-BEGIN*/ +#define USBGetNextHandle(ep_num, ep_dir) ((ep_dir == OUT_FROM_HOST)?((USB_HANDLE)pBDTEntryOut[ep_num]):((USB_HANDLE)pBDTEntryIn[ep_num])) +/*DOM-IGNORE-END*/ + +/******************************************************************** + Function: + void USBEP0Transmit(BYTE options) + + Summary: + Sets the address of the data to send over the + control endpoint + + PreCondition: + None + + Paramters: + options - the various options that you want + when sending the control data. Options are: + USB_EP0_ROM + USB_EP0_RAM + USB_EP0_BUSY + USB_EP0_INCLUDE_ZERO + USB_EP0_NO_DATA + USB_EP0_NO_OPTIONS + + Return Values: + None + + Remarks: + None + + *******************************************************************/ +void USBEP0Transmit(BYTE options); +/*DOM-IGNORE-BEGIN*/ +#define USBEP0Transmit(options) inPipes[0].info.Val = options | USB_EP0_BUSY +/*DOM-IGNORE-END*/ + +/************************************************************************* + Function: + void USBEP0SendRAMPtr(BYTE* src, WORD size, BYTE Options) + + Summary: + Sets the source, size, and options of the data you wish to send from a + RAM source + Conditions: + None + Input: + src - address of the data to send + size - the size of the data needing to be transmitted + options - the various options that you want when sending the control + data. Options are\: + * USB_EP0_ROM + * USB_EP0_RAM + * USB_EP0_BUSY + * USB_EP0_INCLUDE_ZERO + * USB_EP0_NO_DATA + * USB_EP0_NO_OPTIONS + Remarks: + None + *************************************************************************/ +void USBEP0SendRAMPtr(BYTE* src, WORD size, BYTE Options); +/*DOM-IGNORE-BEGIN*/ +#define USBEP0SendRAMPtr(src,size,options) {\ + inPipes[0].pSrc.bRam = src;\ + inPipes[0].wCount.Val = size;\ + inPipes[0].info.Val = options | USB_EP0_BUSY | USB_EP0_RAM;\ + } +/*DOM-IGNORE-END*/ + +/************************************************************************** + Function: + void USBEP0SendROMPtr(BYTE* src, WORD size, BYTE Options) + + Summary: + Sets the source, size, and options of the data you wish to send from a + ROM source + Conditions: + None + Input: + src - address of the data to send + size - the size of the data needing to be transmitted + options - the various options that you want when sending the control + data. Options are\: + * USB_EP0_ROM + * USB_EP0_RAM + * USB_EP0_BUSY + * USB_EP0_INCLUDE_ZERO + * USB_EP0_NO_DATA + * USB_EP0_NO_OPTIONS + Remarks: + None + **************************************************************************/ +void USBEP0SendROMPtr(BYTE* src, WORD size, BYTE Options); +/*DOM-IGNORE-BEGIN*/ +#define USBEP0SendROMPtr(src,size,options) {\ + inPipes[0].pSrc.bRom = src;\ + inPipes[0].wCount.Val = size;\ + inPipes[0].info.Val = options | USB_EP0_BUSY | USB_EP0_ROM;\ + } +/*DOM-IGNORE-END*/ + +/*************************************************************************** + Function: + void USBEP0Receive(BYTE* dest, WORD size, void (*function)) + Summary: + Sets the destination, size, and a function to call on the completion of + the next control write. + Conditions: + None + Input: + dest - address of where the incoming data will go (make sure that this + address is directly accessable by the USB module for parts with + dedicated USB RAM this address must be in that space) + size - the size of the data being received (is almost always going tobe + presented by the preceeding setup packet SetupPkt.wLength) + (*function) - a function that you want called once the data is received. If + this is specificed as NULL then no function is called. + Remarks: + None + ***************************************************************************/ +void USBEP0Receive(BYTE* dest, WORD size, void (*function)); +/*DOM-IGNORE-BEGIN*/ +#define USBEP0Receive(dest,size,function) {outPipes[0].pDst.bRam = dest;outPipes[0].wCount.Val = size;outPipes[0].pFunc = function;outPipes[0].info.bits.busy = 1; } +/*DOM-IGNORE-END*/ + +/******************************************************************** + Function: + USB_HANDLE USBTxOnePacket(BYTE ep, BYTE* data, WORD len) + + Summary: + Sends the specified data out the specified endpoint + + PreCondition: + None + + Parameters: + ep - the endpoint number you want to send the data out of + data - pointer to a user buffer that contains the data that you wish to + send to the host. Note: This RAM buffer must be accessible by + the USB module. + len - the number of bytes of data that you wish to send to the host, + in the next transaction on this endpoint. Note: this value + should always be less than or equal to the endpoint size, as + specified in the USB endpoint descriptor. + + Return Values: + USB_HANDLE - Returns a pointer to the BDT entry associated with the + transaction. The firmware can check for completion + of the transaction by using the USBHandleBusy() function, + using the returned USB_HANDLE value. + + Remarks: + None + + *******************************************************************/ +USB_HANDLE USBTxOnePacket(BYTE ep, BYTE* data, WORD len); +/*DOM-IGNORE-BEGIN*/ +#define USBTxOnePacket(ep,data,len) USBTransferOnePacket(ep,IN_TO_HOST,data,len) +/*DOM-IGNORE-END*/ + +/******************************************************************** + Function: + USB_HANDLE USBRxOnePacket(BYTE ep, BYTE* data, WORD len) + + Summary: + Receives the specified data out the specified endpoint + + PreCondition: + None + + Parameters: + ep - The endpoint number you want to receive the data on. + data - Pointer to a user buffer where the data will go when + it arrives from the host. Note: This RAM must be USB module + accessible. + len - The len parameter should always be set to the maximum endpoint packet + size, specified in the USB descriptor for this endpoint. The host + may send <= the number of bytes as the endpoint size in the endpoint + descriptor. After the transaction is complete, the application + firmware can call USBHandleGetLength() to determine how many bytes + the host actually sent in the last transaction on this endpoint. + + Return Values: + USB_HANDLE - Returns a pointer to the BDT entry associated with the + transaction. The firmware can check for completion + of the transaction by using the USBHandleBusy() function, + using the returned USB_HANDLE value. + + Remarks: + None + + *******************************************************************/ +USB_HANDLE USBRxOnePacket(BYTE ep, BYTE* data, WORD len); +/*DOM-IGNORE-BEGIN*/ +#define USBRxOnePacket(ep,data,len) USBTransferOnePacket(ep,OUT_FROM_HOST,data,len) +/*DOM-IGNORE-END*/ + +/******************************************************************************* + Function: + BOOL USB_APPLICATION_EVENT_HANDLER(BYTE address, USB_EVENT event, void *pdata, WORD size); + + Summary: + This function is called whenever the USB stack wants to notify the user of + an event. + + Description: + This function is called whenever the USB stack wants to notify the user of + an event. This function should be implemented by the user. + + Example Usage: + Conditions: + None + + Input: + BYTE address - the address of the device when the event happened + BYTE event - The event input specifies which event happened. The + possible options are listed in the USB_DEVICE_STACK_EVENTS + enumeration. + + Return: + None + Remarks: + None + *****************************************************************************/ +BOOL USB_APPLICATION_EVENT_HANDLER(BYTE address, USB_EVENT event, void *pdata, WORD size); + +/******************************************************************************* + Function: + ROM void *USBDeviceCBGetDescriptor (UINT16 *length, DESCRIPTOR_ID *id); + + Summary: + This function is called whenever the USB stack gets a USB GET_DESCRIPTOR + request. + + Description: + This function is called whenever the USB stack gets a USB GET_DESCRIPTOR + request. This function is responsible for returning a pointer to the + requested descriptor and setting that the length for the that descriptor. + + This function should be implemented by the user. This function might be + generated automatically by the USB configuration tool. + + Conditions: + None + + Input: + BYTE *length - pointer to a variable that should be set to the length of + the requested descriptor. + BYTE *id - This structure contains information about the requested + descriptor + + Return: + ROM void* - pointer to the requested descriptor. + Remarks: + None + *****************************************************************************/ +void *USBDeviceCBGetDescriptor ( UINT16 *length, + UINT8 *ptr_type, + DESCRIPTOR_ID *id); + + + +/** Section: MACROS ******************************************************/ + +/* The DESC_CONFIG_WORD() macro is implemented for convinence. Since the + configuration descriptor array is a BYTE array, each entry needs to be a + BYTE in LSB format. The DESC_CONFIG_WORD() macro breaks up a WORD into + the appropriate BYTE entries in LSB. + Typical Usage: + + ROM BYTE configDescriptor1[]={ + 0x09, // Size of this descriptor in bytes + USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type + DESC_CONFIG_WORD(0x0022), // Total length of data for this cfg + +*/ +#define DESC_CONFIG_WORD(a) (a&0xFF),((a>>8)&0xFF) + +/* The DESC_CONFIG_DWORD() macro is implemented for convinence. Since the + configuration descriptor array is a BYTE array, each entry needs to be a + BYTE in LSB format. The DESC_CONFIG_DWORD() macro breaks up a DWORD into + the appropriate BYTE entries in LSB. +*/ +#define DESC_CONFIG_DWORD(a) (a&0xFF),((a>>8)&0xFF),((a>>16)&0xFF),((a>>24)&0xFF) + +/* The DESC_CONFIG_BYTE() macro is implemented for convinence. The + DESC_CONFIG_BYTE() macro provides a consistant macro for use with a byte + when generating a configuratin descriptor when using either the + DESC_CONFIG_WORD() or DESC_CONFIG_DWORD() macros. +*/ +#define DESC_CONFIG_BYTE(a) (a) + + + + + + + + + + + + + + + + +/* DOM-IGNORE-BEGIN */ +/******************************************************************************* +******************************************************************************** +******************************************************************************** + This section contains implementation specific information that may vary + between releases as the implementation needs to change. This section is + included for compilation reasons only. +******************************************************************************** +******************************************************************************** +*******************************************************************************/ + +#if defined(USB_POLLING) + #define USB_VOLATILE +#else + #define USB_VOLATILE volatile +#endif + +#define CTRL_TRF_RETURN void +#define CTRL_TRF_PARAMS void + +// Defintion of the PIPE structure +// This structure is used to keep track of data that is sent out +// of the stack automatically. +typedef struct __attribute__ ((packed)) +{ + union __attribute__ ((packed)) + { + //Various options of pointers that are available to + // get the data from + BYTE *bRam; + ROM BYTE *bRom; + WORD *wRam; + ROM WORD *wRom; + }pSrc; + union __attribute__ ((packed)) + { + struct __attribute__ ((packed)) + { + //is this transfer from RAM or ROM? + BYTE ctrl_trf_mem :1; + BYTE reserved :5; + //include a zero length packet after + //data is done if data_size%ep_size = 0? + BYTE includeZero :1; + //is this PIPE currently in use + BYTE busy :1; + }bits; + BYTE Val; + }info; + WORD_VAL __attribute__((aligned)) wCount; +}IN_PIPE; + +extern USB_VOLATILE IN_PIPE inPipes[]; + +typedef struct __attribute__ ((packed)) +{ + union __attribute__ ((packed)) + { + //Various options of pointers that are available to + // get the data from + BYTE *bRam; + WORD *wRam; + }pDst; + union __attribute__ ((packed)) + { + struct __attribute__ ((packed)) + { + BYTE reserved :7; + //is this PIPE currently in use + BYTE busy :1; + }bits; + BYTE Val; + }info; + WORD_VAL wCount; + CTRL_TRF_RETURN (*pFunc)(CTRL_TRF_PARAMS); +}OUT_PIPE; + +/************* DWF - SHOULD BE REIMPLEMENTED AS AN EVENT *******************/ +//#if defined(ENABLE_EP0_DATA_RECEIVED_CALLBACK) +// void USBCBEP0DataReceived(void); +// #define USBCB_EP0_DATA_RECEIVED() USBCBEP0DataReceived() +//#else +// #define USBCB_EP0_DATA_RECEIVED() +//#endif + +extern USB_VOLATILE BOOL RemoteWakeup; +extern USB_VOLATILE BOOL USBBusIsSuspended; +extern USB_VOLATILE USB_DEVICE_STATE USBDeviceState; +extern USB_VOLATILE BYTE USBActiveConfiguration; +/******************************************************************************/ +/* DOM-IGNORE-END */ + +#endif //USBD_H diff --git a/FirmwareDumper/USB/usb_device_local.h b/FirmwareDumper/USB/usb_device_local.h new file mode 100644 index 0000000..8f97465 --- /dev/null +++ b/FirmwareDumper/USB/usb_device_local.h @@ -0,0 +1,490 @@ +/******************************************************************** + File Information: + FileName: usb_device_local.h + Dependencies: See INCLUDES section + Processor: PIC18,PIC24, PIC32 and dsPIC33E USB Microcontrollers + Hardware: The code is natively intended to be used on the following + hardware platforms: PICDEM� FS USB Demo Board, + PIC18F87J50 FS USB Plug-In Module, or + Explorer 16 + compatible USB PIM. The firmware may be + modified for use on other USB platforms by editing the + HardwareProfile.h file. + Complier: Microchip C18 (for PIC18),C30 (for PIC24 and dsPIC33E) + and C32 (for PIC32) + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the �Company�) for its PIC� Microcontroller is intended and + supplied to you, the Company�s customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN �AS IS� CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + Summary: + This file contains functions, macros, definitions, variables, + datatypes, etc. that are required for usage with the MCHPFSUSB device + stack. This file should be included in projects that use the device stack. + + This file is located in the "\\\Microchip\\USB" + directory. + + Description: + USB Device Stack File + + This file contains functions, macros, definitions, variables, + datatypes, etc. that are required for usage with the MCHPFSUSB device + stack. This file should be included in projects that use the device stack. + + This file is located in the "\\\Microchip\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + ..\\..\\MicrochipInclude + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + +******************************************************************** + File Description: + + Change History: + Rev Description + ---- ----------- + 2.8 Initial revision. Contents extracted from the previous usb_device.c + file, so as to make the usb_device.c file less cluttered. + Fixed BD() and EP() macro computation error, when running in + USB_PING_PONG__EP0_OUT_ONLY mode. + 2.9 No functional change. Fixed spelling typo in the name of + "USB_TRANSFER_COMPLETE_HANDLER()" +********************************************************************/ +#include "usb_config.h" + +/* Short Packet States - Used by Control Transfer Read - CTRL_TRF_TX */ +#define SHORT_PKT_NOT_USED 0 +#define SHORT_PKT_PENDING 1 +#define SHORT_PKT_SENT 2 + +/* Control Transfer States */ +#define WAIT_SETUP 0 +#define CTRL_TRF_TX 1 +#define CTRL_TRF_RX 2 + + +typedef union +{ + struct + { + unsigned char ping_pong_state :1; + unsigned char transfer_terminated :1; + } bits; + BYTE Val; +} EP_STATUS; + +#if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) + #define USB_NEXT_EP0_OUT_PING_PONG 0x0000 // Used in USB Device Mode only + #define USB_NEXT_EP0_IN_PING_PONG 0x0000 // Used in USB Device Mode only + #define USB_NEXT_PING_PONG 0x0000 // Used in USB Device Mode only + #define EP0_OUT_EVEN 0 // Used in USB Device Mode only + #define EP0_OUT_ODD 0 // Used in USB Device Mode only + #define EP0_IN_EVEN 1 // Used in USB Device Mode only + #define EP0_IN_ODD 1 // Used in USB Device Mode only + #define EP1_OUT_EVEN 2 // Used in USB Device Mode only + #define EP1_OUT_ODD 2 // Used in USB Device Mode only + #define EP1_IN_EVEN 3 // Used in USB Device Mode only + #define EP1_IN_ODD 3 // Used in USB Device Mode only + #define EP2_OUT_EVEN 4 // Used in USB Device Mode only + #define EP2_OUT_ODD 4 // Used in USB Device Mode only + #define EP2_IN_EVEN 5 // Used in USB Device Mode only + #define EP2_IN_ODD 5 // Used in USB Device Mode only + #define EP3_OUT_EVEN 6 // Used in USB Device Mode only + #define EP3_OUT_ODD 6 // Used in USB Device Mode only + #define EP3_IN_EVEN 7 // Used in USB Device Mode only + #define EP3_IN_ODD 7 // Used in USB Device Mode only + #define EP4_OUT_EVEN 8 // Used in USB Device Mode only + #define EP4_OUT_ODD 8 // Used in USB Device Mode only + #define EP4_IN_EVEN 9 // Used in USB Device Mode only + #define EP4_IN_ODD 9 // Used in USB Device Mode only + #define EP5_OUT_EVEN 10 // Used in USB Device Mode only + #define EP5_OUT_ODD 10 // Used in USB Device Mode only + #define EP5_IN_EVEN 11 // Used in USB Device Mode only + #define EP5_IN_ODD 11 // Used in USB Device Mode only + #define EP6_OUT_EVEN 12 // Used in USB Device Mode only + #define EP6_OUT_ODD 12 // Used in USB Device Mode only + #define EP6_IN_EVEN 13 // Used in USB Device Mode only + #define EP6_IN_ODD 13 // Used in USB Device Mode only + #define EP7_OUT_EVEN 14 // Used in USB Device Mode only + #define EP7_OUT_ODD 14 // Used in USB Device Mode only + #define EP7_IN_EVEN 15 // Used in USB Device Mode only + #define EP7_IN_ODD 15 // Used in USB Device Mode only + #define EP8_OUT_EVEN 16 // Used in USB Device Mode only + #define EP8_OUT_ODD 16 // Used in USB Device Mode only + #define EP8_IN_EVEN 17 // Used in USB Device Mode only + #define EP8_IN_ODD 17 // Used in USB Device Mode only + #define EP9_OUT_EVEN 18 // Used in USB Device Mode only + #define EP9_OUT_ODD 18 // Used in USB Device Mode only + #define EP9_IN_EVEN 19 // Used in USB Device Mode only + #define EP9_IN_ODD 19 // Used in USB Device Mode only + #define EP10_OUT_EVEN 20 // Used in USB Device Mode only + #define EP10_OUT_ODD 20 // Used in USB Device Mode only + #define EP10_IN_EVEN 21 // Used in USB Device Mode only + #define EP10_IN_ODD 21 // Used in USB Device Mode only + #define EP11_OUT_EVEN 22 // Used in USB Device Mode only + #define EP11_OUT_ODD 22 // Used in USB Device Mode only + #define EP11_IN_EVEN 23 // Used in USB Device Mode only + #define EP11_IN_ODD 23 // Used in USB Device Mode only + #define EP12_OUT_EVEN 24 // Used in USB Device Mode only + #define EP12_OUT_ODD 24 // Used in USB Device Mode only + #define EP12_IN_EVEN 25 // Used in USB Device Mode only + #define EP12_IN_ODD 25 // Used in USB Device Mode only + #define EP13_OUT_EVEN 26 // Used in USB Device Mode only + #define EP13_OUT_ODD 26 // Used in USB Device Mode only + #define EP13_IN_EVEN 27 // Used in USB Device Mode only + #define EP13_IN_ODD 27 // Used in USB Device Mode only + #define EP14_OUT_EVEN 28 // Used in USB Device Mode only + #define EP14_OUT_ODD 28 // Used in USB Device Mode only + #define EP14_IN_EVEN 29 // Used in USB Device Mode only + #define EP14_IN_ODD 29 // Used in USB Device Mode only + #define EP15_OUT_EVEN 30 // Used in USB Device Mode only + #define EP15_OUT_ODD 30 // Used in USB Device Mode only + #define EP15_IN_EVEN 31 // Used in USB Device Mode only + #define EP15_IN_ODD 31 // Used in USB Device Mode only + + #define EP(ep,dir,pp) (2*ep+dir) // Used in USB Device Mode only + #define BD(ep,dir,pp) ((8 * ep) + (4 * dir)) // Used in USB Device Mode only + +#elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) + #define USB_NEXT_EP0_OUT_PING_PONG 0x0004 + #define USB_NEXT_EP0_IN_PING_PONG 0x0000 + #define USB_NEXT_PING_PONG 0x0000 + #define EP0_OUT_EVEN 0 + #define EP0_OUT_ODD 1 + #define EP0_IN_EVEN 2 + #define EP0_IN_ODD 2 + #define EP1_OUT_EVEN 3 + #define EP1_OUT_ODD 3 + #define EP1_IN_EVEN 4 + #define EP1_IN_ODD 4 + #define EP2_OUT_EVEN 5 + #define EP2_OUT_ODD 5 + #define EP2_IN_EVEN 6 + #define EP2_IN_ODD 6 + #define EP3_OUT_EVEN 7 + #define EP3_OUT_ODD 7 + #define EP3_IN_EVEN 8 + #define EP3_IN_ODD 8 + #define EP4_OUT_EVEN 9 + #define EP4_OUT_ODD 9 + #define EP4_IN_EVEN 10 + #define EP4_IN_ODD 10 + #define EP5_OUT_EVEN 11 + #define EP5_OUT_ODD 11 + #define EP5_IN_EVEN 12 + #define EP5_IN_ODD 12 + #define EP6_OUT_EVEN 13 + #define EP6_OUT_ODD 13 + #define EP6_IN_EVEN 14 + #define EP6_IN_ODD 14 + #define EP7_OUT_EVEN 15 + #define EP7_OUT_ODD 15 + #define EP7_IN_EVEN 16 + #define EP7_IN_ODD 16 + #define EP8_OUT_EVEN 17 + #define EP8_OUT_ODD 17 + #define EP8_IN_EVEN 18 + #define EP8_IN_ODD 18 + #define EP9_OUT_EVEN 19 + #define EP9_OUT_ODD 19 + #define EP9_IN_EVEN 20 + #define EP9_IN_ODD 20 + #define EP10_OUT_EVEN 21 + #define EP10_OUT_ODD 21 + #define EP10_IN_EVEN 22 + #define EP10_IN_ODD 22 + #define EP11_OUT_EVEN 23 + #define EP11_OUT_ODD 23 + #define EP11_IN_EVEN 24 + #define EP11_IN_ODD 24 + #define EP12_OUT_EVEN 25 + #define EP12_OUT_ODD 25 + #define EP12_IN_EVEN 26 + #define EP12_IN_ODD 26 + #define EP13_OUT_EVEN 27 + #define EP13_OUT_ODD 27 + #define EP13_IN_EVEN 28 + #define EP13_IN_ODD 28 + #define EP14_OUT_EVEN 29 + #define EP14_OUT_ODD 29 + #define EP14_IN_EVEN 30 + #define EP14_IN_ODD 30 + #define EP15_OUT_EVEN 31 + #define EP15_OUT_ODD 31 + #define EP15_IN_EVEN 32 + #define EP15_IN_ODD 32 + + #define EP(ep,dir,pp) (2u*ep+dir+(((ep==0)&&(dir==0))?pp:1)) + #define BD(ep,dir,pp) (4u*((2u*ep)+dir+(((ep==0)&&(dir==0))?pp:1))) + +#elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) +#if defined (__18CXX) || defined(__C30__) || defined __XC16__ || defined(__XC8) + #if (defined (__dsPIC33E__) || defined (__PIC24E__)) + #define USB_NEXT_EP0_OUT_PING_PONG 0x0008 + #define USB_NEXT_EP0_IN_PING_PONG 0x0008 + #define USB_NEXT_PING_PONG 0x0008 + #else + #define USB_NEXT_EP0_OUT_PING_PONG 0x0004 + #define USB_NEXT_EP0_IN_PING_PONG 0x0004 + #define USB_NEXT_PING_PONG 0x0004 + #endif + #elif defined(__C32__) + #define USB_NEXT_EP0_OUT_PING_PONG 0x0008 + #define USB_NEXT_EP0_IN_PING_PONG 0x0008 + #define USB_NEXT_PING_PONG 0x0008 + #else + #error "Not defined for this compiler" + #endif + #define EP0_OUT_EVEN 0 + #define EP0_OUT_ODD 1 + #define EP0_IN_EVEN 2 + #define EP0_IN_ODD 3 + #define EP1_OUT_EVEN 4 + #define EP1_OUT_ODD 5 + #define EP1_IN_EVEN 6 + #define EP1_IN_ODD 7 + #define EP2_OUT_EVEN 8 + #define EP2_OUT_ODD 9 + #define EP2_IN_EVEN 10 + #define EP2_IN_ODD 11 + #define EP3_OUT_EVEN 12 + #define EP3_OUT_ODD 13 + #define EP3_IN_EVEN 14 + #define EP3_IN_ODD 15 + #define EP4_OUT_EVEN 16 + #define EP4_OUT_ODD 17 + #define EP4_IN_EVEN 18 + #define EP4_IN_ODD 19 + #define EP5_OUT_EVEN 20 + #define EP5_OUT_ODD 21 + #define EP5_IN_EVEN 22 + #define EP5_IN_ODD 23 + #define EP6_OUT_EVEN 24 + #define EP6_OUT_ODD 25 + #define EP6_IN_EVEN 26 + #define EP6_IN_ODD 27 + #define EP7_OUT_EVEN 28 + #define EP7_OUT_ODD 29 + #define EP7_IN_EVEN 30 + #define EP7_IN_ODD 31 + #define EP8_OUT_EVEN 32 + #define EP8_OUT_ODD 33 + #define EP8_IN_EVEN 34 + #define EP8_IN_ODD 35 + #define EP9_OUT_EVEN 36 + #define EP9_OUT_ODD 37 + #define EP9_IN_EVEN 38 + #define EP9_IN_ODD 39 + #define EP10_OUT_EVEN 40 + #define EP10_OUT_ODD 41 + #define EP10_IN_EVEN 42 + #define EP10_IN_ODD 43 + #define EP11_OUT_EVEN 44 + #define EP11_OUT_ODD 45 + #define EP11_IN_EVEN 46 + #define EP11_IN_ODD 47 + #define EP12_OUT_EVEN 48 + #define EP12_OUT_ODD 49 + #define EP12_IN_EVEN 50 + #define EP12_IN_ODD 51 + #define EP13_OUT_EVEN 52 + #define EP13_OUT_ODD 53 + #define EP13_IN_EVEN 54 + #define EP13_IN_ODD 55 + #define EP14_OUT_EVEN 56 + #define EP14_OUT_ODD 57 + #define EP14_IN_EVEN 58 + #define EP14_IN_ODD 59 + #define EP15_OUT_EVEN 60 + #define EP15_OUT_ODD 61 + #define EP15_IN_EVEN 62 + #define EP15_IN_ODD 63 + + #define EP(ep,dir,pp) (4*ep+2*dir+pp) + + #if defined (__18CXX) || defined(__C30__) || defined __XC16__ || (__XC8) + #if (defined(__dsPIC33E__) || defined (__PIC24E__)) + #define BD(ep,dir,pp) (8*(4*ep+2*dir+pp)) + #else + #define BD(ep,dir,pp) (4*(4*ep+2*dir+pp)) + #endif + #elif defined(__C32__) + #define BD(ep,dir,pp) (8*(4*ep+2*dir+pp)) + #else + #error "Not defined for this compiler" + #endif + +#elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) + #define USB_NEXT_EP0_OUT_PING_PONG 0x0000 + #define USB_NEXT_EP0_IN_PING_PONG 0x0000 + #define USB_NEXT_PING_PONG 0x0004 + #define EP0_OUT_EVEN 0 + #define EP0_OUT_ODD 0 + #define EP0_IN_EVEN 1 + #define EP0_IN_ODD 1 + #define EP1_OUT_EVEN 2 + #define EP1_OUT_ODD 3 + #define EP1_IN_EVEN 4 + #define EP1_IN_ODD 5 + #define EP2_OUT_EVEN 6 + #define EP2_OUT_ODD 7 + #define EP2_IN_EVEN 8 + #define EP2_IN_ODD 9 + #define EP3_OUT_EVEN 10 + #define EP3_OUT_ODD 11 + #define EP3_IN_EVEN 12 + #define EP3_IN_ODD 13 + #define EP4_OUT_EVEN 14 + #define EP4_OUT_ODD 15 + #define EP4_IN_EVEN 16 + #define EP4_IN_ODD 17 + #define EP5_OUT_EVEN 18 + #define EP5_OUT_ODD 19 + #define EP5_IN_EVEN 20 + #define EP5_IN_ODD 21 + #define EP6_OUT_EVEN 22 + #define EP6_OUT_ODD 23 + #define EP6_IN_EVEN 24 + #define EP6_IN_ODD 25 + #define EP7_OUT_EVEN 26 + #define EP7_OUT_ODD 27 + #define EP7_IN_EVEN 28 + #define EP7_IN_ODD 29 + #define EP8_OUT_EVEN 30 + #define EP8_OUT_ODD 31 + #define EP8_IN_EVEN 32 + #define EP8_IN_ODD 33 + #define EP9_OUT_EVEN 34 + #define EP9_OUT_ODD 35 + #define EP9_IN_EVEN 36 + #define EP9_IN_ODD 37 + #define EP10_OUT_EVEN 38 + #define EP10_OUT_ODD 39 + #define EP10_IN_EVEN 40 + #define EP10_IN_ODD 41 + #define EP11_OUT_EVEN 42 + #define EP11_OUT_ODD 43 + #define EP11_IN_EVEN 44 + #define EP11_IN_ODD 45 + #define EP12_OUT_EVEN 46 + #define EP12_OUT_ODD 47 + #define EP12_IN_EVEN 48 + #define EP12_IN_ODD 49 + #define EP13_OUT_EVEN 50 + #define EP13_OUT_ODD 51 + #define EP13_IN_EVEN 52 + #define EP13_IN_ODD 53 + #define EP14_OUT_EVEN 54 + #define EP14_OUT_ODD 55 + #define EP14_IN_EVEN 56 + #define EP14_IN_ODD 57 + #define EP15_OUT_EVEN 58 + #define EP15_OUT_ODD 59 + #define EP15_IN_EVEN 60 + #define EP15_IN_ODD 61 + + #define EP(ep,dir,pp) (4*ep+2*dir+((ep==0)?0:(pp-2))) + #define BD(ep,dir,pp) (4*(4*ep+2*dir+((ep==0)?0:(pp-2)))) + +#else + #error "No ping pong mode defined." +#endif + +/****** Event callback enabling/disabling macros ******************** + This section of code is used to disable specific USB events that may not be + desired by the user. This can save code size and increase throughput and + decrease CPU utiliazation. +********************************************************************/ +#if defined USB_DISABLE_SUSPEND_HANDLER + #define USB_SUSPEND_HANDLER(event,pointer,size) + + #warning "Disabling the suspend handler is not recommended. Proper suspend handling is required to create a compliant USB device." +#else + #define USB_SUSPEND_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_WAKEUP_FROM_SUSPEND_HANDLER + #define USB_WAKEUP_FROM_SUSPEND_HANDLER(event,pointer,size) + + #warning "Disabling the wake from suspend handler is not recommended. Proper suspend handling is required to create a compliant USB device." +#else + #define USB_WAKEUP_FROM_SUSPEND_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_SOF_HANDLER + #define USB_SOF_HANDLER(event,pointer,size) +#else + #define USB_SOF_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_TRANSFER_TERMINATED_HANDLER + #define USB_TRANSFER_TERMINATED_HANDLER(event,pointer,size) +#else + #define USB_TRANSFER_TERMINATED_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_ERROR_HANDLER + #define USB_ERROR_HANDLER(event,pointer,size) +#else + #define USB_ERROR_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER + #define USB_NONSTANDARD_EP0_REQUEST_HANDLER(event,pointer,size) +#else + #define USB_NONSTANDARD_EP0_REQUEST_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_SET_DESCRIPTOR_HANDLER + #define USB_SET_DESCRIPTOR_HANDLER(event,pointer,size) +#else + #define USB_SET_DESCRIPTOR_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_SET_CONFIGURATION_HANDLER + #define USB_SET_CONFIGURATION_HANDLER(event,pointer,size) +#else + #define USB_SET_CONFIGURATION_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + +#if defined USB_DISABLE_TRANSFER_COMPLETE_HANDLER + #define USB_TRANSFER_COMPLETE_HANDLER(event,pointer,size) +#else + #define USB_TRANSFER_COMPLETE_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size) +#endif + diff --git a/FirmwareDumper/USB/usb_function_generic.c b/FirmwareDumper/USB/usb_function_generic.c new file mode 100644 index 0000000..0fed42f --- /dev/null +++ b/FirmwareDumper/USB/usb_function_generic.c @@ -0,0 +1,300 @@ +/****************************************************************************** + File Information: + FileName: usb_function_generic.c + Dependencies: See INCLUDES section below + Processor: Microchip USB Microcontrollers + Hardware: See "\Microchip\Help" for details. + + Compiler: C18, C30, or C32 + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the "Company") for its PIC(R) Microcontroller is intended and + supplied to you, the Company's customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + Change History: + Rev Description + + Summary: + This file contains all of functions, macros, definitions, variables, + datatypes, etc. that are required for usage with vendor class function + drivers. This file should be included in projects that use vendor class + \function drivers. Vendor class function drivers include MCHPUSB + (Microchip's custom class driver), WinUSB, and LibUSB. + + + + This file is located in the "\\\Microchip\\USB\\Generic + Device Driver" directory. + Description: + USB Vender Class Custom Driver Header File + + This file contains functions, macros, definitions, variables, + datatypes, etc. that are required for use of vendor class function + drivers. This file should be included in projects that use vendor class + \function drivers. + + This file is located in the "\\\Microchip\\USB\\Generic + Device Driver" directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + ..\\..\\Microchip\\Include + . + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + ******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************** + File Description: + + Change History: + Rev Description + ---- ----------- + 2.6 Minor changes in include file structure. + 2.9h Implemented USBCheckVendorRequest() function, in order to + support MS OS Feature Descriptor handling. +******************************************************************** +//DOM-IGNORE-END + +******************************************************************************/ + +/** I N C L U D E S **********************************************************/ +#include "USB/usb.h" +#include "./USB/usb_function_generic.h" + +#if defined(USB_USE_GEN) + +/** V A R I A B L E S ********************************************************/ +extern volatile CTRL_TRF_SETUP SetupPkt; //Common buffer that receives the + //8-byte SETUP packet data from the + //host during control transfer + //requests. + +/** P R I V A T E P R O T O T Y P E S ***************************************/ + +/** D E C L A R A T I O N S **************************************************/ + +/** U S E R A P I ***********************************************************/ + +/******************************************************************** + Function: + USB_HANDLE USBGenWrite(BYTE ep, BYTE* data, WORD len) + + Summary: + Sends the specified data out the specified endpoint + + Description: + This function sends the specified data out the specified + endpoint and returns a handle to the transfer information. + + Typical Usage: + + //make sure that the last transfer isn't busy by checking the handle + if(!USBHandleBusy(USBGenericInHandle)) + { + //Send the data contained in the INPacket[] array out on + // endpoint USBGEN_EP_NUM + USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket[0],sizeof(INPacket)); + } + + + PreCondition: + None + + Parameters: + BYTE ep - the endpoint you want to send the data out of + BYTE* data - pointer to the data that you wish to send + WORD len - the length of the data that you wish to send + + Return Values: + USB_HANDLE - a handle for the transfer. This information + should be kept to track the status of the transfer + + Remarks: + None + + *******************************************************************/ + // Implemented as a macro. See usb_function_generic.h + +/******************************************************************** + Function: + USB_HANDLE USBGenRead(BYTE ep, BYTE* data, WORD len) + + Summary: + Receives the specified data out the specified endpoint + + Description: + Receives the specified data out the specified endpoint. + + Typical Usage: + + //Read 64-bytes from endpoint USBGEN_EP_NUM, into the OUTPacket array. + // Make sure to save the return handle so that we can check it later + // to determine when the transfer is complete. + if(!USBHandleBusy(USBOutHandle)) + { + USBOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,64); + } + + + PreCondition: + None + + Parameters: + BYTE ep - the endpoint you want to receive the data into + BYTE* data - pointer to where the data will go when it arrives + WORD len - the length of the data that you wish to receive + + Return Values: + USB_HANDLE - a handle for the transfer. This information + should be kept to track the status of the transfer + + Remarks: + None + + *******************************************************************/ + // Implemented as a macro. See usb_function_generic.h + + +/******************************************************************** + Function: + void USBCheckVendorRequest(void) + + Summary: + This routine handles vendor class specific requests that happen on EP0. + This function should be called from the USBCBCheckOtherReq() call back + function whenever implementing a custom/vendor class device. + + Description: + This routine handles vendor specific requests that may arrive on EP0 as + a control transfer. These can include, but are not necessarily + limited to, requests for Microsft specific OS feature descriptor(s). + This function should be called from the USBCBCheckOtherReq() call back + function whenever using a vendor class device. + + Typical Usage: + + void USBCBCheckOtherReq(void) + { + //Since the stack didn't handle the request I need to check + // my class drivers to see if it is for them + USBCheckVendorRequest(); + } + + + PreCondition: + None + + Parameters: + Although this function has a void input, this handler function will + typically need to look at the 8-byte SETUP packet contents that the + host just sent, which may contain the vendor class specific request. + + Therefore, the statically allocated SetupPkt structure may be looked + at while in the context of this function, and it will contain the most + recently received 8-byte SETUP packet data. + + Return Values: + None + + Remarks: + This function normally gets called within the same context as the + USBDeviceTasks() function, just after a new control transfer request + from the host has arrived. If the USB stack is operated in + USB_INTERRUPT mode (a usb_config.h option), then this function + will be executed in the interrupt context. If however the USB stack + is operated in the USB_POLLING mode, then this function executes in the + main loop context. + + In order to respond to class specific control transfer request(s) in + this handler function, it is suggested to use one or more of the + USBEP0SendRAMPtr(), USBEP0SendROMPtr(), or USBEP0Receive() API + functions. + + *******************************************************************/ +void USBCheckVendorRequest(void) +{ + #if defined(IMPLEMENT_MICROSOFT_OS_DESCRIPTOR) + WORD Length; + + //Check if the most recent SETUP request is class specific + if(SetupPkt.bmRequestType == 0b11000000) //Class specific, device to host, device level target + { + //Check if the host is requesting an MS feature descriptor + if(SetupPkt.bRequest == GET_MS_DESCRIPTOR) + { + //Figure out which descriptor is being requested + if(SetupPkt.wIndex == EXTENDED_COMPAT_ID) + { + //Determine number of bytes to send to host + //Lesser of: requested amount, or total size of the descriptor + Length = CompatIDFeatureDescriptor.dwLength; + if(SetupPkt.wLength < Length) + { + Length = SetupPkt.wLength; + } + + //Prepare to send the requested descriptor to the host + USBEP0SendROMPtr((ROM BYTE*)&CompatIDFeatureDescriptor, Length, USB_EP0_ROM | USB_EP0_INCLUDE_ZERO); + } + } + }//if(SetupPkt.bmRequestType == 0b11000000) + else if(SetupPkt.bmRequestType == 0b11000001) //Class specific, device to host, interface target + { + //Check if the host is requesting an MS feature descriptor + if(SetupPkt.bRequest == GET_MS_DESCRIPTOR) + { + //Figure out which descriptor is being requested + if(SetupPkt.wIndex == EXTENDED_PROPERTIES) + { + //Determine number of bytes to send to host + //Lesser of: requested amount, or total size of the descriptor + Length = ExtPropertyFeatureDescriptor.dwLength; + if(SetupPkt.wLength < Length) + { + Length = SetupPkt.wLength; + } + + //Prepare to send the requested descriptor to the host + USBEP0SendROMPtr((ROM BYTE*)&ExtPropertyFeatureDescriptor, Length, USB_EP0_ROM | USB_EP0_INCLUDE_ZERO); + } + } + }//else if(SetupPkt.bmRequestType == 0b11000001) + #endif //#if defined(IMPLEMENT_MICROSOFT_OS_DESCRIPTOR) +}//void USBCheckVendorRequest(void) + + +#endif //def USB_USE_GEN +/** EOF usbgen.c *************************************************************/ diff --git a/FirmwareDumper/USB/usb_function_generic.h b/FirmwareDumper/USB/usb_function_generic.h new file mode 100644 index 0000000..d4b1ae3 --- /dev/null +++ b/FirmwareDumper/USB/usb_function_generic.h @@ -0,0 +1,253 @@ +/****************************************************************************** + File Information: + FileName: usb_function_generic.h + Dependencies: See INCLUDES section below + Processor: PIC18 or PIC24 USB Microcontrollers + Hardware: The code is natively intended to be used on the following + hardware platforms: PICDEM(TM) FS USB Demo Board, + PIC18F87J50 FS USB Plug-In Module, or + Explorer 16 + PIC24 USB PIM. The firmware may be + modified for use on other USB platforms by editing the + HardwareProfile.h file. + Compiler: C18, C30, or C32 + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the "Company") for its PIC(R) Microcontroller is intended and + supplied to you, the Company's customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + Change History: + Rev Description + + Summary: + This file contains all of functions, macros, definitions, variables, + datatypes, etc. that are required for usage with vendor class function + drivers. This file should be included in projects that use vendor class + \function drivers. Vendor class function drivers include MCHPUSB + (Microchip's custom class driver), WinUSB, and LibUSB. This file should also be included into the + usb_descriptors.c file and any other user file that requires access to + vendor class interfaces. + + + + This file is located in the "\\\Microchip\\Include\\USB" directory. + Description: + USB Vender Class Custom Driver File + + This file contains all of functions, macros, definitions, variables, + datatypes, etc. that are required for usage with vendor class function + drivers. This file should be included in projects that use vendor class + \function drivers. This file should also be included into the + usb_descriptors.c file and any other user file that requires access to + vendor class interfaces. + + This file is located in the "\\\Microchip\\Include\\USB" directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + ..\\..\\Microchip\\Include + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + ******************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************** + File Description: + + Change History: + Rev Description + ---- ----------- + 2.6 No Change + 2.9h Added prototype for USBCheckVendorRequest() +********************************************************************/ +//DOM-IGNORE-END + +#ifndef USBGEN_H +#define USBGEN_H + +#include "GenericTypeDefs.h" +#include "usb_config.h" + +/** I N C L U D E S **********************************************************/ + +/** D E F I N I T I O N S ****************************************************/ + +/** S T R U C T U R E S ******************************************************/ + +/** E X T E R N S ************************************************************/ + +/** P U B L I C P R O T O T Y P E S *****************************************/ + +/******************************************************************** + Function: + USB_HANDLE USBGenWrite(BYTE ep, BYTE* data, WORD len) + + Summary: + Sends the specified data out the specified endpoint + + Description: + This function sends the specified data out the specified + endpoint and returns a handle to the transfer information. + + Typical Usage: + + //make sure that the last transfer isn't busy by checking the handle + if(!USBHandleBusy(USBGenericInHandle)) + { + //Send the data contained in the INPacket[] array out on + // endpoint USBGEN_EP_NUM + USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket[0],sizeof(INPacket)); + } + + + PreCondition: + None + + Parameters: + BYTE ep - the endpoint you want to send the data out of + BYTE* data - pointer to the data that you wish to send + WORD len - the length of the data that you wish to send + + Return Values: + USB_HANDLE - a handle for the transfer. This information + should be kept to track the status of the transfer + + Remarks: + None + + *******************************************************************/ +#define USBGenWrite(ep,data,len) USBTxOnePacket(ep,data,len) + + +/******************************************************************** + Function: + USB_HANDLE USBGenRead(BYTE ep, BYTE* data, WORD len) + + Summary: + Receives the specified data out the specified endpoint + + Description: + Receives the specified data out the specified endpoint. + + Typical Usage: + + //Read 64-bytes from endpoint USBGEN_EP_NUM, into the OUTPacket array. + // Make sure to save the return handle so that we can check it later + // to determine when the transfer is complete. + if(!USBHandleBusy(USBOutHandle)) + { + USBOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,64); + } + + + PreCondition: + None + + Parameters: + BYTE ep - the endpoint you want to receive the data into + BYTE* data - pointer to where the data will go when it arrives + WORD len - the length of the data that you wish to receive + + Return Values: + USB_HANDLE - a handle for the transfer. This information + should be kept to track the status of the transfer + + Remarks: + None + + *******************************************************************/ +#define USBGenRead(ep,data,len) USBRxOnePacket(ep,data,len) + + +/******************************************************************** + Function: + void USBCheckVendorRequest(void) + + Summary: + This routine handles vendor class specific requests that happen on EP0. + This function should be called from the USBCBCheckOtherReq() call back + function whenever implementing a custom/vendor class device. + + Description: + This routine handles vendor specific requests that may arrive on EP0 as + a control transfer. These can include, but are not necessarily + limited to, requests for Microsft specific OS feature descriptor(s). + This function should be called from the USBCBCheckOtherReq() call back + function whenever using a vendor class device. + + Typical Usage: + + void USBCBCheckOtherReq(void) + { + //Since the stack didn't handle the request I need to check + // my class drivers to see if it is for them + USBCheckVendorRequest(); + } + + + PreCondition: + None + + Parameters: + Although this function has a void input, this handler function will + typically need to look at the 8-byte SETUP packet contents that the + host just sent, which may contain the vendor class specific request. + + Therefore, the statically allocated SetupPkt structure may be looked + at while in the context of this function, and it will contain the most + recently received 8-byte SETUP packet data. + + Return Values: + None + + Remarks: + This function normally gets called within the same context as the + USBDeviceTasks() function, just after a new control transfer request + from the host has arrived. If the USB stack is operated in + USB_INTERRUPT mode (a usb_config.h option), then this function + will be executed in the interrupt context. If however the USB stack + is operated in the USB_POLLING mode, then this function executes in the + main loop context. + + In order to respond to class specific control transfer request(s) in + this handler function, it is suggested to use one or more of the + USBEP0SendRAMPtr(), USBEP0SendROMPtr(), or USBEP0Receive() API + functions. + + *******************************************************************/ +void USBCheckVendorRequest(void); + +#endif //USBGEN_H diff --git a/FirmwareDumper/USB/usb_hal.h b/FirmwareDumper/USB/usb_hal.h new file mode 100644 index 0000000..fb6d0be --- /dev/null +++ b/FirmwareDumper/USB/usb_hal.h @@ -0,0 +1,653 @@ +/****************************************************************************** + + USB Hardware Abstraction Layer (HAL) (Header File) + +Summary: + This file abstracts the hardware interface. + +Description: + This file abstracts the hardware interface. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + ..\\..\\MicrochipInclude + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application +*******************************************************************************/ +//DOM-IGNORE-BEGIN +/****************************************************************************** + + File Description: + + This file defines the interface to the USB hardware abstraction layer. + + Filename: usb_hal.h + Dependancies: none + Processor: PIC18, PIC24, or PIC32 USB Microcontrollers + Hardware: The code is natively intended to be used on the following + hardware platforms: PICDEM™ FS USB Demo Board, + PIC18F87J50 FS USB Plug-In Module, or + Explorer 16 + PIC24 USB PIM. The firmware may be + modified for use on other USB platforms by editing the + HardwareProfile.h file. + Compiler: Microchip C18 (for PIC18) or C30 (for PIC24) + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the “Company”) for its PICmicro® Microcontroller is intended and + supplied to you, the Company’s customer, for use solely and + exclusively on Microchip PICmicro Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + *************************************************************************/ + +/******************************************************************** + Change History: + Rev Description + ---- ----------- + 2.6- No Change + 2.6a + + 2.7 Minor changes changes to the structure of the conditional + compilation statement ordering. + + 2.7a No Change +********************************************************************/ + +#ifndef _USB_HAL_H_ +#define _USB_HAL_H_ +//DOM-IGNORE-END + +#if defined(__18CXX) + #include "USB/usb_hal_pic18.h" +#elif defined(__C30__) || defined __XC16__ + #if defined(__dsPIC33E__) + #include "USB/usb_hal_dspic33E.h" + #elif defined(__PIC24E__) + #include "USB/usb_hal_pic24e.h" + #else + #include "USB/usb_hal_pic24.h" + #endif +#elif defined(__PIC32MX__) + #include "USB/usb_hal_pic32.h" +#elif defined(_PIC14E) + #include "USB/usb_hal_pic16f1.h" +#else + #error "Silicon Platform not defined" +#endif + + +/********************** + Interface Routines + **********************/ + +/************************************************************************* + Function: + void USBHALSetBusAddress( BYTE addr ) + + Description: + This routine sets the address of the system on the USB + when acting as a peripheral device. + + Preconditions: + 1. USBHALInitialize must have been called to + initialize the USB HAL. + 2. Endpoint zero (0) must be configured as appropriate + by calls to USBHALSetEpConfiguration. + 3. The system must have been enumerated on the USB (as + a device). + + Parameters: + addr Desired address of this device on the USB. + + Return Values: + None + + Side Effect: + The bus address has been set. + + Remmarks: + The address is assigned by the host and is received in + a SET_ADDRESS setup request. + + *************************************************************************/ +/* + This routine is implemented as a macro to a lower-level level routine. + */ + +#define USBHALSetBusAddress OTGCORE_SetDeviceAddr + +void USBHALSetBusAddress( BYTE addr ); + + +/************************************************************************* + Function: + void USBHALControlUsbResistors( BYTE flags ); + + Description: + This routine enables or disables the USB pull-up or + pull-down resistors as requested. + + Precondition: + USBInitialize must have been called to initialize the + USB SW stack. + + Parameters: + flags - This is a bit-mapped flags value indicating + which resistors to enable or disable (see below). + + Return Values: + TRUE if successful, FALSE if not. + + Side Effects: + The resistors are enabled as requested. + + Remarks: + Used for USB peripheral control to connect to or + disconnect from the bus. Otherwise, used for OTG + SRP/HNP and host support. + + *************************************************************************/ + +/* + This routine is implemented as a macro to a lower-level level routine. + */ + #if defined(__18CXX) + void USBHALControlUsbResistors( BYTE flags ); + #else + #define USBHALControlUsbResistors OTGCORE_ControlUsbResistors + void USBHALControlUsbResistors( BYTE flags ); +#endif + +/* USBHALControlUsbResistors flags */ +#define USB_HAL_PULL_UP_D_PLUS 0x80 // Pull D+ line high +#define USB_HAL_PULL_UP_D_MINUS 0x40 // Pull D- line high +#define USB_HAL_PULL_DN_D_PLUS 0x20 // Pull D+ line low +#define USB_HAL_PULL_DN_D_MINUS 0x10 // Pull D- line low +/* + The following are defined for convenience: + */ +#define USB_HAL_DEV_CONN_FULL_SPD USB_HAL_PULL_UP_D_PLUS +#define USB_HAL_DEV_CONN_LOW_SPD USB_HAL_PULL_UP_D_MINUS +#define USB_HAL_DEV_DISCONNECT 0 + + +/* + MCHP: Define a method to check for SE0 & a way to send a reset (SE0). + */ + + +/************************************************************************* + Function: + BOOL USBHALSessionIsValid( void ) + + Description: + This routine determines if there is currently a valid + USB session or not. + + Precondition: + USBInitialize must have been called to initialize the + USB SW stack. + + Parameters: + None + + Return Values: + TRUE if the session is currently valid, FALSE if not. + + Remarks: + Only used for host and OTG support. + + *************************************************************************/ + +BOOL USBHALSessionIsValid( void ); + + +/************************************************************************* + Function: + USBHALControlBusPower + + Description: + This routine provides a bitmap of the most recent + error conditions to occur. + + Precondition: + USBInitialize must have been called to initialize the + USB SW stack. + + Parameters: + cmd - Identifies desired command (see below). + + Return Values: + TRUE if successful, FALSE if not. + + Remarks: + Only used for host and OTG support. + + *************************************************************************/ + +BOOL USBHALControlBusPower( BYTE cmd ); + +/* USBHALControlBusPower Commands */ +#define USB_VBUS_DISCHARGE 0 // Dicharge Vbus via resistor +#define USB_VBUS_CHARGE 1 // Charge Vbus via resistor +#define USB_VBUS_POWER_ON 3 // Supply power to Vbus +#define USB_VBUS_POWER_OFF 4 // Do not supply power to Vbus +/* + Note: All commands except USB_VBUS_POWER_ON imply that this device + does not actively supply power to Vbus. + */ + + +/************************************************************************* + Function: + unsigned long USBHALGetLastError( void ) + + Description: + This routine provides a bitmap of the most recent + error conditions to occur. + + Precondition: + USBInitialize must have been called to initialize the + USB SW stack. + + Parameters: + None + + Return Values: + Bitmap indicating the most recent error condition(s). + + Side Effect: + Error record is cleared. + + Remarks: + Although record of the error state is cleared, nothing + is done to fix the condition or recover from the + error. The client must take appropriate steps. + + *************************************************************************/ + +unsigned long USBHALGetLastError( void ); + +/* + USBHALGetLastError Error Bits. + */ +#define USBHAL_PID_ERR 0x00000001 // Packet ID Error +#define USBHAL_CRC5 0x00000002 // (Host) Token CRC5 check failed +#define USBHAL_HOST_EOF 0x00000002 // (Host) EOF not reached before next SOF +#define USBHAL_CRC16 0x00000004 // Data packet CRC error +#define USBHAL_DFN8 0x00000008 // Data field size not n*8 bits +#define USBHAL_BTO_ERR 0x00000010 // Bus turn-around timeout +#define USBHAL_DMA_ERR 0x00000020 // DMA error, unable to read/write memory +#define USBHAL_BTS_ERR 0x00000080 // Bit-stuffing error +#define USBHAL_XFER_ID 0x00000100 // Unable to identify transfer EP +#define USBHAL_NO_EP 0x00000200 // Invalid endpoint number +#define USBHAL_DMA_ERR2 0x00000400 // Error starting DMA transaction + + +/************************************************************************* + Function: + void USBHALHandleBusEvent ( void ) + + Description: + This routine checks the USB for any events that may + have occured and handles them appropriately. It may + be called directly to poll the USB and handle events + or it may be called in response to an interrupt. + + Precondition: + USBInitialize must have been called to initialize the + USB SW stack. + + Parameters: + None + + Return Values: + None + + Side Effects: + Depend on the event that may have occured. + + Remarks: + None + + *************************************************************************/ + +void USBHALHandleBusEvent ( void ); + + +/************************************************************************* + Function: + BOOL USBHALStallPipe( TRANSFER_FLAGS pipe ) + + Description: + This routine stalls the given endpoint. + + Preconditions: + USBHALInitialize must have been called to initialize + the USB HAL. + + Parameters: + pipe - Uses the TRANSFER_FLAGS (see USBCommon.h) format to + identify the endpoint and direction making up the + pipe to stall. + + Note: Only ep_num and direction fields are required. + + Return Values: + TRUE if able to stall endpoint, FALSE if not. + + Side Effects: + The endpoint will stall if additional data transfer is + attempted. + Given endpoint has been stalled. + + Remarks: + Starting another data transfer automatically + "un-stalls" the endpoint. + + *************************************************************************/ +/* + Note: This function is implemented as a macro, calling directly into + an internal HAL routine. + */ + +#define USBHALStallPipe OTGCORE_StallPipe + +BOOL USBHALStallPipe( TRANSFER_FLAGS pipe ); + + +/****************************************************************************** + Function: + BOOL USBHALUnstallPipe( TRANSFER_FLAGS pipe ) + + Description: + This routine clears the stall condition for the given pipe. + + PreCondition: + Assumes OTGCORE_DeviceEnable has been called and + OTGCORE_StallPipe has been called on the given pipe. + + Parameters: + pipe - Uses the TRANSFER_FLAGS (see USBCommon.h) format to + identify the endpoint and direction making up the + pipe to unstall. + + Return Values: + TRUE if able to stall the pipe, FALSE if not. + + Side Effects: + The BSTALL and UOWN bits (and all other control bits) in + the BDT for the given pipe will be cleared. + + Remarks: + None + + *****************************************************************************/ +/* + Note: This function is implemented as a macro, calling directly into + an internal HAL routine. + */ + +#define USBHALUnstallPipe OTGCORE_UnstallPipe + +BOOL USBHALUnstallPipe( TRANSFER_FLAGS pipe ); + + +/************************************************************************** + Function: + USBHALGetStalledEndpoints + + Description: + This function returns a 16-bit bitmapped value with a + bit set in the position of any endpoint that is stalled + (i.e. if endpoint 0 is stalled then bit 0 is set, if + endpoint 1 is stalled then bit 1 is set, etc.). + + Preconditions: + USBHALInitialize must have been called to initialize + the USB HAL. + + Parameters: + None + + Return Values: + Bitmap of the currently stalled endpoints (see overview). + + Remarks: + None + *************************************************************************/ + +/* + Note: This function is implemented as a macro, calling directly into + a HAL routine. + */ + +#define USBHALGetStalledEndpoints OTGCORE_GetStalledEndpoints + +UINT16 USBHALGetStalledEndpoints ( void ); + + +/****************************************************************************** + Function: + BOOL USBHALFlushPipe( TRANSFER_FLAGS pipe ) + + Description: + This routine clears any pending transfers on the given + pipe. + + Preconditions: + USBHALInitialize must have been called to initialize the + USB HAL. + + The caller must ensure that there is no possible way for + hardware to be currently accessing the pipe (see notes). + + Parameters: + pipe - Uses the TRANSFER_FLAGS (see USBCommon.h) format to + identify the endpoint and direction making up the + pipe to flush. + + Return Values: + TRUE if successful, FALSE if not. + + Side Effects: + Transfer data for this pipe has been zero'd out. + + Remarks: + This routine ignores the normal HW protocol for ownership + of the pipe data and flushes the pipe, even if it is in + process. Thus, the caller must ensure that data transfer + cannot be in process. This situation occurs when a + transfer has been terminated early by the host. + *****************************************************************************/ + +BOOL USBHALFlushPipe( TRANSFER_FLAGS pipe ); + + +/************************************************************************** + Function: + USBHALTransferData + + Description: + This routine prepares to transfer data on the USB. + If the system is in device mode, the actual transfer + will not occur until the host peforms an OUT request + to the given endpoint. If the system is in host mode, + the transfer will not start until the token has been + sent on the bus. + + Preconditions: + 1. USBHALInitialize must have been called to + initialize the USB HAL. + 2. The endpoint through which the data will be + transferred must be configured as appropriate by a + call to USBHALSetEpConfiguration. + 3. The bus must have been enumerated (either as a host + or device). Except for EP0 transfers. + + Parameters: + flags - Flags consists of the endpoint number OR'd + with one or more flags indicating transfer + direction and such (see "Data Transfer + Macros" in USBCommon.h): + + 7 6 5 4 3 2 1 0 - Description + | | | | \_____/ + | | | | +----- Endpoint Number + | | | +---------- Short or zero-size pkt + | | +------------ Data Toggle 0/1 + | +-------------- Force Data Toggle + +---------------- 1=Transmit/0=Receive + + buffer Address of the buffer to receive data. + + size Number of bytes of data to transfer. + + Return Values: + TRUE if the HAL was able to successfully start the + data transfer, FALSE if not. + + Side Effects: + The HAL has prepared to transfer the data on the USB. + + Ramarks: + The HAL will continue the data transfer, keeping track + of the buffer address, data remaining, and ping-pong + buffer details internally when USBHALHandleBusEvent is + called (either polled or in response to an interrupt). + The caller will receive notification that the transfer + has completed when the EVT_XFER event is passed into + the USBHALBusEventCallout call-out function. + + *************************************************************************/ + +BOOL USBHALTransferData ( TRANSFER_FLAGS flags, + void *buffer, + unsigned int size ); + + +/************************************************************************* + Function: + USBHALSetEpConfiguration + + Description: + This routine allows the caller to configure various + options (see "Flags for USBHALSetEpConfiguration", + below) and set the behavior for the given endpoint. + + Precondition: + USBHALInitialize has been called. + + Parameters: + ep_num - Number of endpoint to configur, Must be + (ep_num >=0) && (ep_num <= USB_DEV_HIGHEST_EP_NUMBER) + max_pkt_size Size of largest packet this enpoint can + transfer. + + flags - Configuration flags (see below) + + Return Values: + TRUE if successful, FALSE if not. + + Side Effects: + The endpoint has been configured as desired. + + Remarks: + The base address and size of the buffer is not set by + this routine. Those features of an endpoint are + dynamically managed by the USBHALTransferData routine. + An endpoint can be "de-configured" by setting its max + packet size to 0. When doing this, you should also + set all flags to 0. + *************************************************************************/ + +BOOL USBHALSetEpConfiguration ( BYTE ep_num, UINT16 max_pkt_size, UINT16 flags ); + +/* Flags for USBHALSetEpConfiguration */ +#if defined(__18CXX) + #define USB_HAL_TRANSMIT 0x0400 // Enable EP for transmitting data + #define USB_HAL_RECEIVE 0x0200 // Enable EP for receiving data + #define USB_HAL_HANDSHAKE 0x1000 // Enable EP to give ACK/NACK (non isoch) + + #define USB_HAL_NO_INC 0x0010 // Use for DMA to another device FIFO + #define USB_HAL_HW_KEEPS 0x0020 // Cause HW to keep EP +#else + #define USB_HAL_TRANSMIT 0x0400 // Enable EP for transmitting data + #define USB_HAL_RECEIVE 0x0800 // Enable EP for receiving data + #define USB_HAL_HANDSHAKE 0x0100 // Enable EP to give ACK/NACK (non isoch) + + /* Does not work, Fix this if needed. 3/1/07 - Bud + #define USB_HAL_NO_INC 0x0010 // Use for DMA to another device FIFO + #define USB_HAL_HW_KEEPS 0x0020 // Cause HW to keep EP + */ + #define USB_HAL_ALLOW_HUB 0x8000 // (host only) Enable low-spd hub support + #define USB_HAL_NO_RETRY 0x4000 // (host only) disable auto-retry on NACK +#endif + + +/************************************************************************* + Function: + USBHALInitialize + + Description: + This call performs the basic initialization of the USB + HAL. This routine must be called before any of the + other HAL interface routines are called. + + Precondition: + The system has been initialized. + + Paramters: + flags - Initialization flags + + Return Values: + TRUE if successful, FALSE if not. + + Side Effects: + The USB HAL SW stack was initialized. + + Remarks: + This routine can be called to reset the controller. + + *************************************************************************/ + +BOOL USBHALInitialize ( unsigned long flags ); + +#endif // _USB_HAL_H_ +/************************************************************************* + * EOF + */ + diff --git a/FirmwareDumper/USB/usb_hal_pic18.h b/FirmwareDumper/USB/usb_hal_pic18.h new file mode 100644 index 0000000..4a22a5f --- /dev/null +++ b/FirmwareDumper/USB/usb_hal_pic18.h @@ -0,0 +1,600 @@ +/****************************************************************************** + + USB Hardware Abstraction Layer (HAL) (Header File) + +Summary: + This file abstracts the hardware interface. The USB stack firmware can be + compiled to work on different USB microcontrollers, such as PIC18 and PIC24. + The USB related special function registers and bit names are generally very + similar between the device families, but small differences in naming exist. + +Description: + This file abstracts the hardware interface. The USB stack firmware can be + compiled to work on different USB microcontrollers, such as PIC18 and PIC24. + The USB related special function registers and bit names are generally very + similar between the device families, but small differences in naming exist. + + In order to make the same set of firmware work accross the device families, + when modifying SFR contents, a slightly abstracted name is used, which is + then "mapped" to the appropriate real name in the usb_hal_picxx.h header. + + Make sure to include the correct version of the usb_hal_picxx.h file for + the microcontroller family which will be used. + + This file is located in the "\\\Microchip\\Include\\USB" + directory. + + When including this file in a new project, this file can either be + referenced from the directory in which it was installed or copied + directly into the user application folder. If the first method is + chosen to keep the file located in the folder in which it is installed + then include paths need to be added so that the library and the + application both know where to reference each others files. If the + application folder is located in the same folder as the Microchip + folder (like the current demo folders), then the following include + paths need to be added to the application's project: + + . + + ..\\..\\MicrochipInclude + + If a different directory structure is used, modify the paths as + required. An example using absolute paths instead of relative paths + would be the following: + + C:\\Microchip Solutions\\Microchip\\Include + + C:\\Microchip Solutions\\My Demo Application + +*******************************************************************************/ +//DOM-IGNORE-BEGIN +/****************************************************************************** + + File Description: + + This file defines the interface to the USB hardware abstraction layer. + + * Filename: usb_hal_pic18.h + Dependencies: See INCLUDES section + Processor: Use this header file when using this firmware with PIC18 USB + microcontrollers + Hardware: + Complier: Microchip C18 (for PIC18) + Company: Microchip Technology, Inc. + + Software License Agreement: + + The software supplied herewith by Microchip Technology Incorporated + (the “Company”) for its PIC® Microcontroller is intended and + supplied to you, the Company’s customer, for use solely and + exclusively on Microchip PIC Microcontroller products. The + software is owned by the Company and/or its supplier, and is + protected under applicable copyright laws. All rights are reserved. + Any use in violation of the foregoing restrictions may subject the + user to criminal sanctions under applicable laws, as well as to + civil liability for the breach of the terms and conditions of this + license. + + THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, + WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED + TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, + IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + + *************************************************************************/ + +//DOM-IGNORE-BEGIN +/******************************************************************** + Change History: + Rev Description + ---- ----------- + 2.6 Changed the inplementation of the interrupt clearing macro + to be more efficient. + + 2.6a Added DisableNonZeroEndpoints() function + + 2.7 Added ConvertToPhysicalAddress() and ConvertToVirtualAddress() + macros. Needed for compatiblity with PIC32. + + Added USBDisableInterrupts() macro. Fixes issue in dual role + example where a device in polling mode can still have interrupts + enabled from the host mode causing an incorrect vectoring to the + host interrupt controller while in device mode. + + 2.7a No change + + 2.8 Added USTAT_FIELDS typedef and associated macros. +********************************************************************/ +//DOM-IGNORE-END + +#ifndef USB_HAL_PIC18_H +#define USB_HAL_PIC18_H + +/*****************************************************************************/ +/****** include files ********************************************************/ +/*****************************************************************************/ + +#include "Compiler.h" +#include "usb_config.h" + +/*****************************************************************************/ +/****** Constant definitions *************************************************/ +/*****************************************************************************/ + +//----- USBEnableEndpoint() input defintions ---------------------------------- +#define USB_HANDSHAKE_ENABLED 0x10 +#define USB_HANDSHAKE_DISABLED 0x00 + +#define USB_OUT_ENABLED 0x04 +#define USB_OUT_DISABLED 0x00 + +#define USB_IN_ENABLED 0x02 +#define USB_IN_DISABLED 0x00 + +#define USB_ALLOW_SETUP 0x00 +#define USB_DISALLOW_SETUP 0x08 + +#define USB_STALL_ENDPOINT 0x01 + +//----- usb_config.h input defintions ----------------------------------------- +#define USB_PULLUP_ENABLE 0x10 +#define USB_PULLUP_DISABLED 0x00 + +#define USB_INTERNAL_TRANSCEIVER 0x00 +#define USB_EXTERNAL_TRANSCEIVER 0x08 + +#define USB_FULL_SPEED 0x04 +#define USB_LOW_SPEED 0x00 + +//----- Interrupt Flag definitions -------------------------------------------- +#define USBTransactionCompleteIE UIEbits.TRNIE +#define USBTransactionCompleteIF UIRbits.TRNIF +#define USBTransactionCompleteIFReg UIR +#define USBTransactionCompleteIFBitNum 0xF7 //AND mask for clearing TRNIF bit position 4 + +#define USBResetIE UIEbits.URSTIE +#define USBResetIF UIRbits.URSTIF +#define USBResetIFReg UIR +#define USBResetIFBitNum 0xFE //AND mask for clearing URSTIF bit position 0 + +#define USBIdleIE UIEbits.IDLEIE +#define USBIdleIF UIRbits.IDLEIF +#define USBIdleIFReg UIR +#define USBIdleIFBitNum 0xEF //AND mask for clearing IDLEIF bit position 5 + +#define USBActivityIE UIEbits.ACTVIE +#define USBActivityIF UIRbits.ACTVIF +#define USBActivityIFReg UIR +#define USBActivityIFBitNum 0xFB //AND mask for clearing ACTVIF bit position 2 + +#define USBSOFIE UIEbits.SOFIE +#define USBSOFIF UIRbits.SOFIF +#define USBSOFIFReg UIR +#define USBSOFIFBitNum 0xBF //AND mask for clearing SOFIF bit position 6 + +#define USBStallIE UIEbits.STALLIE +#define USBStallIF UIRbits.STALLIF +#define USBStallIFReg UIR +#define USBStallIFBitNum 0xDF //AND mask for clearing STALLIF bit position 5 + +#define USBErrorIE UIEbits.UERRIE +#define USBErrorIF UIRbits.UERRIF +#define USBErrorIFReg UIR +#define USBErrorIFBitNum 0xFD //UERRIF bit position 1. Note: This bit is read only and is cleared by clearing the enabled UEIR flags + +//----- Event call back defintions -------------------------------------------- +#if defined(USB_DISABLE_SOF_HANDLER) + #define USB_SOF_INTERRUPT 0x00 +#else + #define USB_SOF_INTERRUPT 0x40 +#endif + +#if defined(USB_DISABLE_ERROR_HANDLER) + #define USB_ERROR_INTERRUPT 0x02 +#else + #define USB_ERROR_INTERRUPT 0x02 +#endif + +//----- USB module control bits ----------------------------------------------- +#define USBPingPongBufferReset UCONbits.PPBRST +#define USBSE0Event UCONbits.SE0 +#define USBSuspendControl UCONbits.SUSPND +#define USBPacketDisable UCONbits.PKTDIS +#define USBResumeControl UCONbits.RESUME + +//----- BDnSTAT bit definitions ----------------------------------------------- +#define _BSTALL 0x04 //Buffer Stall enable +#define _DTSEN 0x08 //Data Toggle Synch enable +#define _INCDIS 0x10 //Address increment disable +#define _KEN 0x20 //SIE keeps buff descriptors enable +#define _DAT0 0x00 //DATA0 packet expected next +#define _DAT1 0x40 //DATA1 packet expected next +#define _DTSMASK 0x40 //DTS Mask +#define _USIE 0x80 //SIE owns buffer +#define _UCPU 0x00 //CPU owns buffer +#define _STAT_MASK 0xFF + +#define USTAT_EP0_PP_MASK ~0x02 +#define USTAT_EP_MASK 0x7E +#define USTAT_EP0_OUT 0x00 +#define USTAT_EP0_OUT_EVEN 0x00 +#define USTAT_EP0_OUT_ODD 0x02 +#define USTAT_EP0_IN 0x04 +#define USTAT_EP0_IN_EVEN 0x04 +#define USTAT_EP0_IN_ODD 0x06 + +#define ENDPOINT_MASK 0b01111000 + +//----- U1EP bit definitions -------------------------------------------------- +#define UEP_STALL 0x0001 +// Cfg Control pipe for this ep +/* Endpoint configuration options for USBEnableEndpoint() function */ +#define EP_CTRL 0x06 // Cfg Control pipe for this ep +#define EP_OUT 0x0C // Cfg OUT only pipe for this ep +#define EP_IN 0x0A // Cfg IN only pipe for this ep +#define EP_OUT_IN 0x0E // Cfg both OUT & IN pipes for this ep + +//----- Remap the PIC18 register name space------------------------------------ +#define U1ADDR UADDR +#define U1IE UIE +#define U1IR UIR +#define U1EIR UEIR +#define U1EIE UEIE +#define U1CON UCON +#define U1EP0 UEP0 +#define U1CONbits UCONbits +#define U1EP1 UEP1 +#define U1CNFG1 UCFG +#define U1STAT USTAT +#define U1EP0bits UEP0bits + +//----- Defintions for BDT address -------------------------------------------- +#if defined(__18CXX) + #if defined(__18F14K50) || defined(__18F13K50) || defined(__18LF14K50) || defined(__18LF13K50) + #define USB_BDT_ADDRESS 0x200 //See Linker Script, BDT in bank 2 on these devices - usb2:0x200-0x2FF(256-byte) + #elif defined(__18F47J53) || defined(__18F46J53) || defined(__18F27J53) || defined(__18F26J53) || defined(__18LF47J53) || defined(__18LF46J53) || defined(__18LF27J53) || defined(__18LF26J53) + #define USB_BDT_ADDRESS 0xD00 //BDT in Bank 13 on these devices + #elif defined(__18F97J94) || defined(__18F87J94) || defined(__18F67J94) || defined(__18F96J94) || defined(__18F86J94) || defined(__18F66J94) || defined(__18F96J99) || defined(__18F95J94) || defined(__18F86J99) || defined(__18F85J94) || defined(__18F66J99) || defined(__18F65J94) + #define USB_BDT_ADDRESS 0x100 //BDT in Bank 1 on these devices + #else + #define USB_BDT_ADDRESS 0x400 //All other PIC18 devices place the BDT in usb4:0x400-0x4FF(256-byte) + #endif +#endif + +#define BDT_BASE_ADDR_TAG __attribute__ ((aligned (512))) +#define CTRL_TRF_SETUP_ADDR_TAG +#define CTRL_TRF_DATA_ADDR_TAG + +//----- Depricated defintions - will be removed at some point of time---------- +//--------- Depricated in v2.2 +#define _LS 0x00 // Use Low-Speed USB Mode +#define _FS 0x04 // Use Full-Speed USB Mode +#define _TRINT 0x00 // Use internal transceiver +#define _TREXT 0x08 // Use external transceiver +#define _PUEN 0x10 // Use internal pull-up resistor +#define _OEMON 0x40 // Use SIE output indicator + +/*****************************************************************************/ +/****** Type definitions *****************************************************/ +/*****************************************************************************/ + +// Buffer Descriptor Status Register layout. +typedef union _BD_STAT +{ + BYTE Val; + struct{ + //If the CPU owns the buffer then these are the values + unsigned BC8:1; //bit 8 of the byte count + unsigned BC9:1; //bit 9 of the byte count + unsigned BSTALL:1; //Buffer Stall Enable + unsigned DTSEN:1; //Data Toggle Synch Enable + unsigned INCDIS:1; //Address Increment Disable + unsigned KEN:1; //BD Keep Enable + unsigned DTS:1; //Data Toggle Synch Value + unsigned UOWN:1; //USB Ownership + }; + struct{ + //if the USB module owns the buffer then these are + // the values + unsigned :2; + unsigned PID0:1; //Packet Identifier + unsigned PID1:1; + unsigned PID2:1; + unsigned PID3:1; + unsigned :1; + }; + struct{ + unsigned :2; + unsigned PID:4; //Packet Identifier + unsigned :2; + }; +} BD_STAT; //Buffer Descriptor Status Register + +// BDT Entry Layout +typedef union __BDT +{ + struct + { + BD_STAT STAT; + BYTE CNT; + BYTE ADRL; //Buffer Address Low + BYTE ADRH; //Buffer Address High + }; + struct + { + unsigned :8; + unsigned :8; + WORD ADR; //Buffer Address + }; + DWORD Val; + BYTE v[4]; +} BDT_ENTRY; + +// USTAT Register Layout +typedef union __USTAT +{ + struct + { + unsigned char filler1:1; + unsigned char ping_pong:1; + unsigned char direction:1; + unsigned char endpoint_number:4; + }; + BYTE Val; +} USTAT_FIELDS; + +//Macros for fetching parameters from a USTAT_FIELDS variable. +#define USBHALGetLastEndpoint(stat) stat.endpoint_number +#define USBHALGetLastDirection(stat) stat.direction +#define USBHALGetLastPingPong(stat) stat.ping_pong + + +typedef union _POINTER +{ + struct + { + BYTE bLow; + BYTE bHigh; + //byte bUpper; + }; + WORD _word; // bLow & bHigh + + //pFunc _pFunc; // Usage: ptr.pFunc(); Init: ptr.pFunc = &; + + BYTE* bRam; // Ram byte pointer: 2 bytes pointer pointing + // to 1 byte of data + WORD* wRam; // Ram word poitner: 2 bytes poitner pointing + // to 2 bytes of data + + ROM BYTE* bRom; // Size depends on compiler setting + ROM WORD* wRom; + //rom near byte* nbRom; // Near = 2 bytes pointer + //rom near word* nwRom; + //rom far byte* fbRom; // Far = 3 bytes pointer + //rom far word* fwRom; +} POINTER; + +/*****************************************************************************/ +/****** Function prototypes and macro functions ******************************/ +/*****************************************************************************/ + +#define ConvertToPhysicalAddress(a) ((WORD)(a)) +#define ConvertToVirtualAddress(a) ((void *)(a)) + + +//------------------------------------------------------------------------------ +//This section is for the PIC18F45K50 Family microcontrollers +//------------------------------------------------------------------------------ +#if defined(__18F45K50) || defined(__18F25K50) || defined(__18F24K50) || defined(__18LF45K50) || defined(__18LF25K50) || defined(__18LF24K50) + #define USBClearUSBInterrupt() PIR3bits.USBIF = 0; + #if defined(USB_INTERRUPT) + #define USBMaskInterrupts() {PIE3bits.USBIE = 0;} + #define USBUnmaskInterrupts() {PIE3bits.USBIE = 1;} + #else + #define USBMaskInterrupts() + #define USBUnmaskInterrupts() + #endif + + #define USBInterruptFlag PIR3bits.USBIF + + //STALLIE, IDLEIE, TRNIE, and URSTIE are all enabled by default and are required + #if defined(USB_INTERRUPT) + #define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR3bits.USBIP = 1;PIE3bits.USBIE = 1;INTCONbits.GIEH = 1;} + #else + #define USBEnableInterrupts() + #endif + + #define USBDisableInterrupts() {PIE3bits.USBIE = 0;} + + #define SetConfigurationOptions() {\ + U1CNFG1 = USB_PULLUP_OPTION | USB_TRANSCEIVER_OPTION | USB_SPEED_OPTION | USB_PING_PONG_MODE;\ + U1EIE = 0x9F;\ + UIE = 0x39 | USB_SOF_INTERRUPT | USB_ERROR_INTERRUPT;\ + } +#else +//------------------------------------------------------------------------------ +//This section is for all other PIC18 USB microcontrollers +//------------------------------------------------------------------------------ + #define USBClearUSBInterrupt() PIR2bits.USBIF = 0; + #if defined(USB_INTERRUPT) + #define USBMaskInterrupts() {PIE2bits.USBIE = 0;} + #define USBUnmaskInterrupts() {PIE2bits.USBIE = 1;} + #else + #define USBMaskInterrupts() + #define USBUnmaskInterrupts() + #endif + + #define USBInterruptFlag PIR2bits.USBIF + + //STALLIE, IDLEIE, TRNIE, and URSTIE are all enabled by default and are required + #if defined(USB_INTERRUPT) + #define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR2bits.USBIP = 1;PIE2bits.USBIE = 1;INTCONbits.GIEH = 1;} + #else + #define USBEnableInterrupts() + #endif + + #define USBDisableInterrupts() {PIE2bits.USBIE = 0;} + + #define SetConfigurationOptions() {\ + U1CNFG1 = USB_PULLUP_OPTION | USB_TRANSCEIVER_OPTION | USB_SPEED_OPTION | USB_PING_PONG_MODE;\ + U1EIE = 0x9F;\ + UIE = 0x39 | USB_SOF_INTERRUPT | USB_ERROR_INTERRUPT;\ + } +#endif //end of #if defined(__18F45K50) || defined(__18F25K50)... +//------------------------------------------------------------------------------ + + +/**************************************************************** + Function: + void USBPowerModule(void) + + Description: + This macro is used to power up the USB module if required
+ PIC18: defines as nothing
+ PIC24: defines as U1PWRCbits.USBPWR = 1;
+ + Parameters: + None + + Return Values: + None + + Remarks: + None + + ****************************************************************/ +#define USBPowerModule() + +/**************************************************************** + Function: + void USBModuleDisable(void) + + Description: + This macro is used to disable the USB module + + Parameters: + None + + Return Values: + None + + Remarks: + None + + ****************************************************************/ +#define USBModuleDisable() {\ + UCON = 0;\ + UIE = 0;\ + USBDeviceState = DETACHED_STATE;\ +} + +/**************************************************************** + Function: + USBSetBDTAddress(addr) + + Description: + This macro is used to power up the USB module if required + + Parameters: + None + + Return Values: + None + + Remarks: + None + + ****************************************************************/ +#define USBSetBDTAddress(addr) + +/******************************************************************** + * Function (macro): void USBClearInterruptFlag(register, BYTE if_and_flag_mask) + * + * PreCondition: None + * + * Input: + * register - the register mnemonic for the register holding the interrupt + flag to be cleared + * BYTE if_and_flag_mask - an AND mask for the interrupt flag that will be + cleared + * + * Output: None + * + * Side Effects: None + * + * Overview: Clears the specified USB interrupt flag. + * + * Note: + *******************************************************************/ +#define USBClearInterruptFlag(reg_name, if_and_flag_mask) (reg_name &= if_and_flag_mask) + +/******************************************************************** + Function: + void USBClearInterruptRegister(WORD reg) + + Summary: + Clears the specified interrupt register + + PreCondition: + None + + Parameters: + WORD reg - the register name that needs to be cleared + + Return Values: + None + + Remarks: + None + + *******************************************************************/ +#define USBClearInterruptRegister(reg) reg = 0; + +/******************************************************************** + Function: + void DisableNonZeroEndpoints(UINT8 last_ep_num) + + Summary: + Clears the control registers for the specified non-zero endpoints + + PreCondition: + None + + Parameters: + UINT8 last_ep_num - the last endpoint number to clear. This + number should include all endpoints used in any configuration. + + Return Values: + None + + Remarks: + None + + *******************************************************************/ +#define DisableNonZeroEndpoints(last_ep_num) memset((void*)&U1EP1,0x00,(last_ep_num)); + +/*****************************************************************************/ +/****** Compiler checks ******************************************************/ +/*****************************************************************************/ + +//Definitions for the BDT +#ifndef USB_PING_PONG_MODE + #error "No ping pong mode defined." +#endif + +/*****************************************************************************/ +/****** Extern variable definitions ******************************************/ +/*****************************************************************************/ + +#if !defined(USBDEVICE_C) + //extern USB_VOLATILE USB_DEVICE_STATE USBDeviceState; + extern USB_VOLATILE BYTE USBActiveConfiguration; + extern USB_VOLATILE IN_PIPE inPipes[1]; + extern USB_VOLATILE OUT_PIPE outPipes[1]; +#endif + +extern volatile BDT_ENTRY* pBDTEntryOut[USB_MAX_EP_NUMBER+1]; +extern volatile BDT_ENTRY* pBDTEntryIn[USB_MAX_EP_NUMBER+1]; + +#endif //#ifndef USB_HAL_PIC18_H diff --git a/TL866_Updater.X/config_bits.h b/FirmwareDumper/config_bits.h similarity index 100% rename from TL866_Updater.X/config_bits.h rename to FirmwareDumper/config_bits.h diff --git a/TL866_Updater.X/main.c b/FirmwareDumper/main.c similarity index 91% rename from TL866_Updater.X/main.c rename to FirmwareDumper/main.c index 417e33e..5755427 100644 --- a/TL866_Updater.X/main.c +++ b/FirmwareDumper/main.c @@ -2,7 +2,7 @@ * File: main.c * Author: Radioman * - * + * Created on 09 aprilie 2013, 07:20 */ @@ -10,7 +10,6 @@ #include #include "HardwareProfile.h" -#include "main.h" #include "config_bits.h" #include #include @@ -21,6 +20,89 @@ #define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS 0x1808 #define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS 0x1818 +//TL866 Ports settings +#define INIT_LATA (0b00010000) +#define INIT_LATB (0b00000010) +#define INIT_LATC (0b00000000) +#define INIT_LATD (0b00000000) +#define INIT_LATE (0b00000000) +#define INIT_LATF (0b00000000) +#define INIT_LATG (0b00010000) +#define INIT_LATH (0b00000000) +#define INIT_LATJ (0b00000000) + +#define INIT_TRISA (0b00000000) +#define INIT_TRISB (0b00000001) +#define INIT_TRISC (0b00000000) +#define INIT_TRISD (0b00000000) +#define INIT_TRISE (0b00000000) +#define INIT_TRISF (0b00000000) +#define INIT_TRISG (0b00000000) +#define INIT_TRISH (0b00000000) +#define INIT_TRISJ (0b00000000) + +#define LE0 (LATHbits.LATH0)//vpp0 +#define LE1 (LATHbits.LATH1)//vpp1 +#define LE2 (LATAbits.LATA2)//vcc0 +#define LE3 (LATAbits.LATA0)//vcc1 +#define LE4 (LATAbits.LATA5)//vcc2 +#define LE5 (LATAbits.LATA3)//gnd0 +#define LE6 (LATHbits.LATH4)//gnd2 +#define LE7 (LATAbits.LATA1)//gnd3 +#define OE_VPP (LATGbits.LATG4)//OE_VPP +#define OE_VCC (LATAbits.LATA4)//OE_VCC +#define SR_DAT (LATHbits.LATH2)//shift register data line +#define SR_CLK (LATHbits.LATH3)//shift register clock line (register shift on 1) + +#define LED_PIN (LATCbits.LATC0) +#define LED_ON 1 +#define LED_OFF 0 + +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 +#define FLAG_FALSE 0 +#define FLAG_TRUE 1 + +#define VERSION_A 1 +#define VERSION_CS 2 + +#define OVER_HEAD 5 //Overhead: +#define DATA_SIZE (USBGEN_EP_SIZE - OVER_HEAD) + +#define READ_VERSION 0x00 +#define READ_FLASH 0x01 +#define WRITE_BOOTLOADER 0x02 +#define WRITE_CONFIG 0x03 +#define WRITE_INFO 0x04 +#define GET_INFO 0x05 +#define GET_PORT_INP 0x80 +#define GET_PORT_LAT 0x81 +#define GET_PORT_TRIS 0x82 +#define SET_PORT_TRIS 0x83 +#define SET_PORT_LAT 0x84 +#define SET_SHIFTREG 0x85 +#define RESET 0xFF + +typedef union { + unsigned char _byte[USBGEN_EP_SIZE]; //For Byte Access + + struct { + unsigned char CMD; + unsigned char len; + + union { + rom far char *pAdr; //Address Pointer + + struct { + unsigned char low; //Little-endian order + unsigned char high; + unsigned char upper; + }; + } ADR; + unsigned char data[DATA_SIZE]; + }; +} DATA_PACKET; + extern void _startup(void); void high_ISR(void); void low_ISR(void); diff --git a/FirmwareDumper/nbproject/Makefile-genesis.properties b/FirmwareDumper/nbproject/Makefile-genesis.properties new file mode 100644 index 0000000..3ba2c59 --- /dev/null +++ b/FirmwareDumper/nbproject/Makefile-genesis.properties @@ -0,0 +1,9 @@ +# +#Fri Jul 21 18:24:37 EEST 2017 +default.com-microchip-mplab-nbide-toolchainC18-C18LanguageToolchain.md5=9dcf4e78c5f3f3a1c5abbecc04eb7cbf +default.languagetoolchain.dir=F\:\\SDK\\Microchip\\C18\\bin +configurations-xml=eabbc0b82768a7d80950657b544b883c +com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=671be5dae89725b69579225ccba7468e +default.languagetoolchain.version=3.45 +host.platform=windows +conf.ids=default diff --git a/FirmwareDumper/nbproject/configurations.xml b/FirmwareDumper/nbproject/configurations.xml new file mode 100644 index 0000000..1fc8195 --- /dev/null +++ b/FirmwareDumper/nbproject/configurations.xml @@ -0,0 +1,449 @@ + + + + + config_bits.h + usb_config.h + HardwareProfile.h + + + 18f87j50.lkr + + + main.c + usb_descriptors.c + USB/usb_device.c + USB/usb_function_generic.c + + + Makefile + + + + USB + + Makefile + + + + localhost + PIC18F87J50 + + + Simulator + C18 + 3.45 + 3 + + + + + + + + + + false + false + + + + + + + false + + false + + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TL866_Updater.X/nbproject/project.xml b/FirmwareDumper/nbproject/project.xml similarity index 89% rename from TL866_Updater.X/nbproject/project.xml rename to FirmwareDumper/nbproject/project.xml index ce77a59..6931d1b 100644 --- a/TL866_Updater.X/nbproject/project.xml +++ b/FirmwareDumper/nbproject/project.xml @@ -3,13 +3,14 @@ com.microchip.mplab.nbide.embedded.makeproject - TL866_Updater + FirmwareDumper c6c863ce-cc00-448b-983f-c3179648c58d 0 c h ISO-8859-1 + diff --git a/TL866_Updater.X/usb_config.h b/FirmwareDumper/usb_config.h similarity index 100% rename from TL866_Updater.X/usb_config.h rename to FirmwareDumper/usb_config.h diff --git a/TL866_Updater.X/usb_descriptors.c b/FirmwareDumper/usb_descriptors.c similarity index 100% rename from TL866_Updater.X/usb_descriptors.c rename to FirmwareDumper/usb_descriptors.c diff --git a/TL866_Updater.X/main.h b/TL866_Updater.X/main.h deleted file mode 100644 index 04efe95..0000000 --- a/TL866_Updater.X/main.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * File: main.h - * Author: Radioman - * - * - */ - -#ifndef MAIN_H -#define MAIN_H - - - - -#define _XTAL_FREQ 48000000 - -//TL866 Ports settings -#define INIT_LATA (0b00010000) -#define INIT_LATB (0b00000010) -#define INIT_LATC (0b00000000) -#define INIT_LATD (0b00000000) -#define INIT_LATE (0b00000000) -#define INIT_LATF (0b00000000) -#define INIT_LATG (0b00010000) -#define INIT_LATH (0b00000000) -#define INIT_LATJ (0b00000000) - -#define INIT_TRISA (0b00000000) -#define INIT_TRISB (0b00000001) -#define INIT_TRISC (0b00000000) -#define INIT_TRISD (0b00000000) -#define INIT_TRISE (0b00000000) -#define INIT_TRISF (0b00000000) -#define INIT_TRISG (0b00000000) -#define INIT_TRISH (0b00000000) -#define INIT_TRISJ (0b00000000) - -#define LE0 (LATHbits.LATH0)//vpp0 -#define LE1 (LATHbits.LATH1)//vpp1 -#define LE2 (LATAbits.LATA2)//vcc0 -#define LE3 (LATAbits.LATA0)//vcc1 -#define LE4 (LATAbits.LATA5)//vcc2 -#define LE5 (LATAbits.LATA3)//gnd0 -#define LE6 (LATHbits.LATH4)//gnd2 -#define LE7 (LATAbits.LATA1)//gnd3 -#define OE_VPP (LATGbits.LATG4)//OE_VPP -#define OE_VCC (LATAbits.LATA4)//OE_VCC -#define SR_DAT (LATHbits.LATH2)// shift register data line -#define SR_CLK (LATHbits.LATH3)// shift register clock line (register shift on 1) - -#define LED_PIN (LATCbits.LATC0) -#define LED_ON 1 -#define LED_OFF 0 - -#define INPUT_PIN 1 -#define OUTPUT_PIN 0 -#define FLAG_FALSE 0 -#define FLAG_TRUE 1 - -#define VERSION_A 1 -#define VERSION_CS 2 - -#define OVER_HEAD 5 //Overhead: -#define DATA_SIZE (USBGEN_EP_SIZE - OVER_HEAD) - -#define READ_VERSION 0x00 -#define READ_FLASH 0x01 -#define WRITE_BOOTLOADER 0x02 -#define WRITE_CONFIG 0x03 -#define WRITE_INFO 0x04 -#define GET_INFO 0x05 -//#define DEBUG_PACKET 0x7F -#define GET_PORT_INP 0x80 -#define GET_PORT_LAT 0x81 -#define GET_PORT_TRIS 0x82 -#define SET_PORT_TRIS 0x83 -#define SET_PORT_LAT 0x84 -#define SET_SHIFTREG 0x85 -#define RESET 0xFF - -typedef union { - unsigned char _byte[USBGEN_EP_SIZE]; //For Byte Access - - struct { - unsigned char CMD; - unsigned char len; - - union { - rom far char *pAdr; //Address Pointer - - struct { - unsigned char low; //Little-endian order - unsigned char high; - unsigned char upper; - }; - } ADR; - unsigned char data[DATA_SIZE]; - }; -} DATA_PACKET; - -#endif /* MAIN_H */ - diff --git a/TL866_Updater.X/nbproject/configurations.xml b/TL866_Updater.X/nbproject/configurations.xml deleted file mode 100644 index d844506..0000000 --- a/TL866_Updater.X/nbproject/configurations.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - - config_bits.h - main.h - usb_config.h - HardwareProfile.h - - - 18f87j50.lkr - - - main.c - usb_descriptors.c - F:/SDK/Microchip/microchip_solutions_v2013-06-15/Microchip/USB/Generic Device Driver/usb_function_generic.c - F:/SDK/Microchip/microchip_solutions_v2013-06-15/Microchip/USB/usb_device.c - - - Makefile - - - Makefile - - - - localhost - PIC18F87J50 - - - Simulator - C18 - 3.45 - 3 - - - - - - - - false - - - - - false - - false - - false - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/TL866_Updater.X/nbproject/project.properties b/TL866_Updater.X/nbproject/project.properties deleted file mode 100644 index e69de29..0000000