This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430F5510:MSP430F5510:具有 MSP430 USB API 的 USB-HID 游戏手柄控制器

Guru**** 2303350 points
Other Parts Discussed in Thread: MSP430F5529
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1017677/msp430f5510-msp430f5510-usb-hid-gamepad-joystick-controller-with-msp430-usb-api

器件型号:MSP430F5529

各位专家、您好!

我目前正在尝试使用 USB-HID 在 Windows 10上模拟游戏手柄/游戏手柄。 MSP430将采用7-14个模拟输入并将其发送到 Windows、在 Windows 中它们将被视为 USB-HID 游戏控制器输入。

我正在处理 MSP430 USB API 中的 H7_Mouse 示例、因为没有用于传统游戏控制器的示例代码。 描述符是使用 USB-IF 的 HID 描述符工具创建的,然后粘贴到 TI USB 描述符工具中,以在 USB_config 文件夹中创建必要的描述符.c/h。  我正在使用 USB 描述符(如下所示)作为简单的4轴16按钮游戏手柄开始使用。  

0x05, 0x01, //		USAGE_PAGE (Generic Desktop)
0x09, 0x05, //		USAGE (Game Pad)
0xA1, 0x01, //		COLLECTION (Application)
0xA1, 0x00, //			COLLECTION (Physical)
0x05, 0x09, //				USAGE_PAGE (Button)
0x19, 0x01, //				USAGE_MINIMUM (Button 1)
0x29, 0x10, //				USAGE_MAXIMUM (Button 16)
0x15, 0x00, //				LOGICAL_MINIMUM (0)
0x25, 0x01, //				LOGICAL_MAXIMUM (1)
0x95, 0x10, //				REPORT_COUNT (16)
0x75, 0x01, //				REPORT_SIZE (1)
0x81, 0x02, //				INPUT (Data,Var,Abs)
0x05, 0x01, //				USAGE_PAGE (Generic Desktop)
0x09, 0x30, //				USAGE (X)
0x09, 0x31, //				USAGE (Y)
0x09, 0x32, //				USAGE (Z)
0x09, 0x33, //				USAGE (Rx)
0x15, 0x81, //				LOGICAL_MINIMUM (-127)
0x25, 0x7F, //				LOGICAL_MAXIMUM (127)
0x75, 0x08, //				REPORT_SIZE (8)
0x95, 0x04, //				REPORT_COUNT (4)
0x81, 0x02, //				INPUT (Data,Var,Abs)
0xC0, //			END COLLECTION
0xC0 //		END COLLECTION

main.c 文件(通过鼠标示例进行了细微编辑、以适应新的 HID 报告结构)如下所示:

 
 * ======== main.c ========
 * Mouse HID Demo:
 *
 * This example functions as a mouse on the host.  It causes the mouse pointer 
 * to move in a circular pattern on the screen.  Simply build and run the 
 * example.  To re-gain control of the mouse, unplug USB.  
 * Unlike the HID-Datapipe examples, this one does not communicate with the 
 * HID Demo Application
 *
 +----------------------------------------------------------------------------+
 * Please refer to the Examples Guide for more details.
 *----------------------------------------------------------------------------*/
#include <string.h>

#include "driverlib.h"

#include "USB_config/descriptors.h"
#include "USB_API/USB_Common/device.h"
#include "USB_API/USB_Common/usb.h"                 // USB-specific functions
#include "USB_API/USB_HID_API/UsbHid.h"

/*
 * NOTE: Modify hal.h to select a specific evaluation board and customize for
 * your own board.
 */
#include "hal.h"


#define LED_PORT    GPIO_PORT_P1
#define LED_PIN     GPIO_PIN0
#define BUTTON_PORT GPIO_PORT_P1
#define BUTTON_PIN GPIO_PIN1

typedef struct {

    uint16_t buttons;
    int8_t lx;
    int8_t ly;
    int8_t rx;
    int8_t ry;

} CONTROL_REPORT;

CONTROL_REPORT controlReport = { 0, 0, 0, 0, 0 };          // HID report, to be sent to the PC.
//const int16_t tableSinCosLookUp[93][2];                 // Lookup table for mouse data;
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
uint8_t index = 1;                                     // Index for lookup table
#endif
volatile uint8_t sendNewMousePosition = FALSE;        // Flag by which timer tells main
                                                    // loop to send a new report
Timer_A_initUpModeParam Timer_A_params = {0};

void initTimer (void);

volatile uint8_t buttonPressed = FALSE;

/*  
 * ======== main ========
 */
void main (void)
{
#if defined(__GNUC__) && (__MSP430__)
uint8_t index = 1;
#endif
    WDT_A_hold(WDT_A_BASE); // Stop watchdog timer

    // Minumum Vcore setting required for the USB API is PMM_CORE_LEVEL_2 .
    PMM_setVCore(PMM_CORE_LEVEL_2);
    USBHAL_initPorts();           // Config GPIOS for low-power (output low)
    USBHAL_initClocks(8000000);   // Config clocks. MCLK=SMCLK=FLL=8MHz; ACLK=REFO=32kHz
    initTimer();
    USB_setup(TRUE, TRUE); // Init USB & events; if a host is present, connect

    ///additional input button in dev kit P2.1
    GPIO_setAsInputPin(BUTTON_PORT, BUTTON_PIN);
    GPIO_setAsOutputPin(LED_PORT, LED_PIN);
    P1IES |= BIT1;
    P1IFG &= ~BIT1;
    P1IE |= BIT1;
    ///


    __enable_interrupt();                           // Enable interrupts globally
    
    while (1)
    {
        // Check the USB state and directly main loop accordingly
        switch (USB_getConnectionState())
        {
            // This case is executed while your device is enumerated on the
            // USB host
            case ST_ENUM_ACTIVE:

                // Start Timer
                Timer_A_startCounter(TIMER_A0_BASE,
                    TIMER_A_UP_MODE);

                // Enter LPM0, until the timer wakes the CPU
                __bis_SR_register(LPM0_bits + GIE);

                // Timer has awakened the CPU.  Proceed with main loop...
                if (sendNewMousePosition){
               
                    controlReport.ry += 1;
                    controlReport.buttons += 1;
                    controlReport.lx += 1;
                    controlReport.ly += 1;
                    controlReport.rx += 1;


                    // Send the report
                    USBHID_sendReport((void *)&controlReport, HID0_INTFNUM);

                    // Toggle LED on P1.0
                    GPIO_toggleOutputOnPin(LED_PORT, LED_PIN);
					
                }
                break;


            // These cases are executed while your device is disconnected from
            // the host (meaning, not enumerated); enumerated but suspended
            // by the host, or connected to a powered hub without a USB host
            // present.
            case ST_PHYS_DISCONNECTED:
            case ST_ENUM_SUSPENDED:
            case ST_PHYS_CONNECTED_NOENUM_SUSP:
                TA0CTL &= ~MC_1;
                P1OUT &= ~BIT0;
                __bis_SR_register(LPM3_bits + GIE);
                _NOP();
                break;

            // The default is executed for the momentary state
            // ST_ENUM_IN_PROGRESS.  Usually, this state only last a few
            // seconds.  Be sure not to enter LPM3 in this state; USB
            // communication is taking place here, and therefore the mode must
            // be LPM0 or active-CPU.
            case ST_ENUM_IN_PROGRESS:
            default:;
        }

    }  //while(1)
} //main()


/*  
 * ======== UNMI_ISR ========
 */
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector = UNMI_VECTOR
__interrupt void UNMI_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(UNMI_VECTOR))) UNMI_ISR (void)
#else
#error Compiler not found!
#endif
{
    switch (__even_in_range(SYSUNIV, SYSUNIV_BUSIFG ))
    {
        case SYSUNIV_NONE:
            __no_operation();
            break;
        case SYSUNIV_NMIIFG:
            __no_operation();
            break;
        case SYSUNIV_OFIFG:
            UCS_clearFaultFlag(UCS_XT2OFFG);
            UCS_clearFaultFlag(UCS_DCOFFG);
            SFR_clearInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);
            break;
        case SYSUNIV_ACCVIFG:
            __no_operation();
            break;
        case SYSUNIV_BUSIFG:
            // If the CPU accesses USB memory while the USB module is
            // suspended, a "bus error" can occur.  This generates an NMI.  If
            // USB is automatically disconnecting in your software, set a
            // breakpoint here and see if execution hits it.  See the
            // Programmer's Guide for more information.
            SYSBERRIV = 0; //clear bus error flag
            USB_disable(); //Disable
    }
}

/*  
 * ======== TIMER0_A0_ISR ========
 */
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
#else
#error Compiler not found!
#endif
{
sendNewMousePosition = TRUE;                 // Set flag telling main loop to send a report
__bic_SR_register_on_exit(LPM0_bits);        // Keep CPU awake after returning;
                                             // enables a run through the main loop
}

/*
 * ======== setTimer_A_Parameters ========
 */
// This function sets the timer A parameters
void setTimer_A_Parameters()
{
    Timer_A_params.clockSource = TIMER_A_CLOCKSOURCE_ACLK;
	Timer_A_params.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
    Timer_A_params.timerPeriod = 547;  // 547/32768 = a period of 16.7ms
	Timer_A_params.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
	Timer_A_params.captureCompareInterruptEnable_CCR0_CCIE =
		       TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;
	Timer_A_params.timerClear = TIMER_A_DO_CLEAR;
	Timer_A_params.startTimer = false;
}



/*
 * ======== initTimer ========
 */
void initTimer (void)
{
    setTimer_A_Parameters();
    
    // Start timer
    Timer_A_clearTimerInterrupt(TIMER_A0_BASE);

    Timer_A_initUpMode(TIMER_A0_BASE, &Timer_A_params);
}
//Released_Version_5_20_06_03

使用上述代码和描述符、Windows 使用正确的输入将 MSP430正确识别为游戏 epad -可在"控制面板\设置 USB 游戏控制器"下看到。 但是、当单击同一页上的"属性"并测试输入时(代码会定期将每个输入值递增1)、Windows 不会从控制器记录可见的按钮按压/操纵杆响应。 我尝试使用 USB API 中的 Java_HID_Demo 工具来查看是否可以通过查看发送的原始数据来调试问题、但软件无法连接到传统的 USB-HID 设备、即使 Windows 将其识别为游戏 epad。

描述符文件也在此处提供完整参考:

descriptors.h

/* --COPYRIGHT--,BSD
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/


// Generated by MSP USB Descriptor Tool: Fri Jul 09 10:27:06 BST 2021


#include <stdint.h>
#include "USB_API/USB_Common/usb.h"

#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_

#ifdef __cplusplus
extern "C"
{
#endif

/*-----------------------------------------------------------------------------+
| Include files                                                                |
|-----------------------------------------------------------------------------*/

//***********************************************************************************************
// CDC or HID - Define both for composite support
//***********************************************************************************************
#define _HID_          // Needed for HID interface

//***********************************************************************************************
// CONFIGURATION CONSTANTS
//***********************************************************************************************
// These constants configure the API stack and help define the USB descriptors.
// Refer to Sec. 6 of the MSP430 USB CDC API Programmer's Guide for descriptions of these constants.

// Configuration Constants that can change
// #define that relates to Device Descriptor
#define USB_VID               0x2047    // Vendor ID (VID)
#define USB_PID               0x0302        // Product ID (PID)

/*----------------------------------------------------------------------------+
| Firmware Version                                                            |
| How to detect version number of the FW running on MSP430?                   |
| on Windows Open ControlPanel->Systems->Hardware->DeviceManager->Ports->     |
|         Msp430->ApplicationUART->Details                                    |
+----------------------------------------------------------------------------*/
#define VER_FW_H              0x02          // Device release number, in binary-coded decimal
#define VER_FW_L              0x00          // Device release number, in binary-coded decimal

// If a serial number is to be reported, set this to the index within the string descriptor
//of the dummy serial number string.  It will then be automatically handled by the API.
// If no serial number is to be reported, set this to 0.
#define USB_STR_INDEX_SERNUM  3
#define PHDC_ENDPOINTS_NUMBER               2  // bulk in, bulk out


#define DESCRIPTOR_TOTAL_LENGTH            41            // wTotalLength, This is the sum of configuration descriptor length  + CDC descriptor length  + HID descriptor length
#define USB_NUM_INTERFACES                  1            //Number of implemented interfaces.

#define HID0_REPORT_INTERFACE                0              // Report interface number of HID0
#define HID0_OUTEP_ADDR                    0x01           // Output Endpoint number of HID0
#define HID0_INEP_ADDR                     0x81           // Input Endpoint number of HID0

#define CDC_NUM_INTERFACES                   0           //  Total Number of CDCs implemented. should set to 0 if there are no CDCs implemented.
#define HID_NUM_INTERFACES                   1           //  Total Number of HIDs implemented. should set to 0 if there are no HIDs implemented.
#define MSC_NUM_INTERFACES                   0           //  Total Number of MSCs implemented. should set to 0 if there are no MSCs implemented.
#define PHDC_NUM_INTERFACES                  0           //  Total Number of PHDCs implemented. should set to 0 if there are no PHDCs implemented.
// Interface numbers for the implemented CDSs and HIDs, This is to use in the Application(main.c) and in the interupt file(UsbIsr.c).
#define HID0_INTFNUM                0
#define MSC_MAX_LUN_NUMBER                   1           // Maximum number of LUNs supported

#define PUTWORD(x)      ((x)&0xFF),((x)>>8)
#define USB_OUTEP_INT_EN BIT0 | BIT1 
#define USB_INEP_INT_EN BIT0 | BIT1 
#define USB_USE_INTERNAL_3V3LDO TRUE
#define USB_XT2_BYPASS_MODE FALSE


// MCLK frequency of MCU, in Hz
// For running higher frequencies the Vcore voltage adjustment may required.
// Please refer to Data Sheet of the MSP430 device you use
#define USB_PLL_XT        2                  // Defines which XT is used by the PLL (1=XT1, 2=XT2)
#define USB_DISABLE_XT_SUSPEND 1             // If non-zero, then USB_suspend() will disable the oscillator
                                             // that is designated by USB_PLL_XT; if zero, USB_suspend won't
                                             // affect the oscillator
#define USB_DMA_CHAN           DMA_CHANNEL_0   // Set to 0xFF if no DMA channel will be used 0..7 for selected DMA channel

// Controls whether the remote wakeup feature is supported by this device.
// A value of 0x20 indicates that is it supported (this value is the mask for
// the bmAttributes field in the configuration descriptor).
// A value of zero indicates remote wakeup is not supported.
// Other values are undefined, as they will interfere with bmAttributes.
#define USB_SUPPORT_REM_WAKE 0x00
// Controls whether the application is self-powered to any degree.  Should be
// set to 0x40, unless the USB device is fully supplied by the bus.
#define USB_SUPPORT_SELF_POWERED 0x80

// Controls what the device reports to the host regarding how much power it will
// consume from VBUS.  Expressed in 2mA units; that is, the number of mA
// communicated is twice the value of this field.
#define USB_MAX_POWER 0x32
//Configuration constants that can not change ( Fixed Values)
#define CDC_CLASS  2
#define HID_CLASS  3
#define MSC_CLASS  4
#define PHDC_CLASS 5

#define MAX_PACKET_SIZE   0x40              // Max size of the USB packets.

//***********************************************************************************************
// DESCRIPTOR CONSTANTS
//***********************************************************************************************
#define SIZEOF_DEVICE_DESCRIPTOR  0x12
#define MAX_STRING_DESCRIPTOR_INDEX 5
#define report_desc_size_HID0 46
//#define SIZEOF_REPORT_DESCRIPTOR  36
//#define USBHID_REPORT_LENGTH      64  // length of whole HID report (including Report ID)
#define CONFIG_STRING_INDEX       4
#define INTF_STRING_INDEX         5
#define USB_CONFIG_VALUE          0x01
//***********************************************************************************************
// OUTWARD DECLARATIONS
//***********************************************************************************************

//Calculates the endpoint descriptor block number from given address
#define EDB(addr) ((addr&0x07)-1)

/* Structure for generic part of configuration descriptor */
struct abromConfigurationDescriptorGenric
{
    uint8_t sizeof_config_descriptor;            // bLength
     uint8_t desc_type_config;                    // bDescriptorType: 2
    uint8_t sizeof_configuration_descriptor1;    // wTotalLength
    uint8_t sizeof_configuration_descriptor2;
    uint8_t usb_num_configurations;              // bNumInterfaces
    uint8_t bconfigurationvalue;                 // bConfigurationValue
    uint8_t  config_string_index;                // iConfiguration Description offset
     uint8_t mattributes;                         // bmAttributes, bus power, remote wakeup
    uint8_t usb_max_power;                       // Max. Power Consumption at 2mA unit
};

/************************************************CDC Descriptor**************************/
struct abromConfigurationDescriptorCdc
{
// interface descriptor (9 bytes)
    uint8_t blength_intf;                          // blength: interface descriptor size
    uint8_t desc_type_interface;                  // bdescriptortype: interface
    uint8_t interface_number_cdc;                // binterfacenumber
    uint8_t balternatesetting;                   // balternatesetting: alternate setting
    uint8_t bnumendpoints;                       // bnumendpoints: three endpoints used
    uint8_t binterfaceclass;                     // binterfaceclass: communication interface class
    uint8_t binterfacesubclass;                  // binterfacesubclass: abstract control model
    uint8_t binterfaceprotocol;                  // binterfaceprotocol: common at commands 
    uint8_t intf_string_index;                      // interface:
//header functional descriptor
    uint8_t blength_header;                      // blength: endpoint descriptor size
    uint8_t bdescriptortype_header;              // bdescriptortype: cs_interface
    uint8_t bdescriptorsubtype_header;              // bdescriptorsubtype: header func desc
    uint8_t bcdcdc1;
    uint8_t bcdcdc2;                              // bcdcdc: spec release number

//call managment functional descriptor
    uint8_t bfunctionlength;                      // bfunctionlength
    uint8_t bdescriptortype_c;                      // bdescriptortype: cs_interface
    uint8_t bdescriptorsubtype_c;                  // bdescriptorsubtype: call management func desc
    uint8_t bmcapabilities;                      // bmcapabilities: d0+d1
    uint8_t intf_number_cdc;                     // bdatainterface: 0

//acm functional descriptor
    uint8_t bfunctionlength_acm;                  // bfunctionlength
    uint8_t bdescriptortype_acm;                  // bdescriptortype: cs_interface
    uint8_t bdescriptorsubtype_acm;              // bdescriptorsubtype: abstract control management desc
    uint8_t bmcapabilities_acm;                  // bmcapabilities

// Union Functional Descriptor
    uint8_t bLength_ufd;                         // Size, in bytes
    uint8_t bdescriptortype_ufd;                 // bDescriptorType: CS_INTERFACE
    uint8_t bdescriptorsubtype_ufd;              // bDescriptorSubtype: Union Functional Desc
    uint8_t bmasterinterface_ufd;                // bMasterInterface -- the controlling intf for the union
    uint8_t bslaveinterface_ufd;                 // bSlaveInterface -- the controlled intf for the union

//Interrupt end point related fields
    uint8_t sizeof_epintep_descriptor;           // blength: endpoint descriptor size
    uint8_t desc_type_epintep;                      // bdescriptortype: endpoint
    uint8_t cdc_intep_addr;                      // bendpointaddress: (in2)
    uint8_t epintep_desc_attr_type_int;          // bmattributes: interrupt
    uint8_t epintep_wmaxpacketsize1;
    uint8_t epintep_wmaxpacketsize;                 // wmaxpacketsize, 64 bytes
    uint8_t epintep_binterval;                   // binterval

// Data interface descriptor (9 bytes)
    uint8_t blength_slaveintf;                      // blength: interface descriptor size
    uint8_t desc_type_slaveinterface;              // bdescriptortype: interface
    uint8_t interface_number_slavecdc;           // binterfacenumber
    uint8_t balternatesetting_slave;             // balternatesetting: alternate setting
    uint8_t bnumendpoints_slave;                 // bnumendpoints: three endpoints used
    uint8_t binterfaceclass_slave;               // binterfaceclass: data interface class
    uint8_t binterfacesubclass_slave;            // binterfacesubclass: abstract control model
    uint8_t binterfaceprotocol_slave;            // binterfaceprotocol: common at commands
    uint8_t intf_string_index_slave;              // interface:

// Bulk out end point related fields
    uint8_t sizeof_outep_descriptor;             // blength: endpoint descriptor size
    uint8_t desc_type_outep;                      // bdescriptortype: endpoint
    uint8_t cdc_outep_addr;                      // bendpointaddress: (out3)
    uint8_t outep_desc_attr_type_bulk;              // bmattributes: bulk
    uint8_t outep_wmaxpacketsize1;
    uint8_t outep_wmaxpacketsize2;               // wmaxpacketsize, 64 bytes
    uint8_t outep_binterval;                       // binterval: ignored for bulk transfer

// Bulk in related fields
    uint8_t sizeof_inep_descriptor;              // blength: endpoint descriptor size
    uint8_t desc_type_inep;                      // bdescriptortype: endpoint
    uint8_t cdc_inep_addr;                          // bendpointaddress: (in3)
    uint8_t inep_desc_attr_type_bulk;              // bmattributes: bulk
    uint8_t inep_wmaxpacketsize1;
    uint8_t inep_wmaxpacketsize2;                // wmaxpacketsize, 64 bytes
    uint8_t inep_binterval;                      // binterval: ignored for bulk transfer
}    ;

/**************************************HID descriptor structure *************************/
struct abromConfigurationDescriptorHid
{
//INTERFACE DESCRIPTOR (9 bytes)
    uint8_t sizeof_interface_descriptor;        // Desc Length
    uint8_t desc_type_interface;                // DescriptorType
    uint8_t interface_number_hid;               // Interface number
    uint8_t balternatesetting;                  // Any alternate settings if supported
    uint8_t bnumendpoints;                      // Number of end points required
    uint8_t binterfaceclass;                    // Class ID
    uint8_t binterfacesubclass;                 // Sub class ID
    uint8_t binterfaceprotocol;                 // Protocol
    uint8_t intf_string_index;                  // String Index

//hid descriptor (9 bytes)
    uint8_t blength_hid_descriptor;             // HID Desc length
    uint8_t hid_descriptor_type;                // HID Desc Type
    uint8_t hidrevno1;                          // Rev no 
    uint8_t hidrevno2;                          // Rev no - 2nd part
    uint8_t tcountry;                              // Country code 
    uint8_t numhidclasses;                      // Number of HID classes to follow    
    uint8_t report_descriptor_type;             // Report desc type 
    uint8_t tlength;                            // Total length of report descriptor
    uint8_t size_rep_desc;

//input end point descriptor (7 bytes)
    uint8_t size_inp_endpoint_descriptor;       // End point desc size
    uint8_t desc_type_inp_endpoint;             // Desc type
    uint8_t hid_inep_addr;                      // Input end point address
    uint8_t ep_desc_attr_type_inp_int;          // Type of end point
    uint8_t  inp_wmaxpacketsize1;               // Max packet size
    uint8_t  inp_wmaxpacketsize2;
    uint8_t inp_binterval;                      // bInterval in ms

 // Output end point descriptor; (7 bytes)
    uint8_t size_out_endpoint_descriptor;       // Output endpoint desc size
    uint8_t desc_type_out_endpoint;             // Desc type
    uint8_t hid_outep_addr;                     // Output end point address
    uint8_t ep_desc_attr_type_out_int;          // End point type
    uint8_t out_wmaxpacketsize1;                // Max packet size
    uint8_t out_wmaxpacketsize2;
    uint8_t out_binterval;                      // bInterval in ms
};

/**************************************MSC descriptor structure *************************/
struct abromConfigurationDescriptorMsc
{
// INTERFACE DESCRIPTOR (9 bytes)
    uint8_t sizeof_interface_descriptor;         // Desc Length
    uint8_t desc_type_interface;                 // DescriptorType
    uint8_t interface_number_hid;                // Interface number
    uint8_t balternatesetting;                   // Any alternate settings if supported
    uint8_t bnumendpoints;                       // Number of end points required
    uint8_t binterfaceclass;                     // Class ID
    uint8_t binterfacesubclass;                  // Sub class ID
    uint8_t binterfaceprotocol;                  // Protocol
    uint8_t intf_string_index;                   // String Index

// input end point descriptor (7 bytes)
    uint8_t size_inp_endpoint_descriptor;        // End point desc size
    uint8_t desc_type_inp_endpoint;              // Desc type
    uint8_t hid_inep_addr;                       // Input end point address
    uint8_t ep_desc_attr_type_inp_int;           // Type of end point
    uint8_t  inp_wmaxpacketsize1;                // Max packet size
    uint8_t  inp_wmaxpacketsize2;
    uint8_t inp_binterval;                       // bInterval in ms

// Output end point descriptor; (7 bytes)
    uint8_t size_out_endpoint_descriptor;        // Output endpoint desc size
    uint8_t desc_type_out_endpoint;              // Desc type
    uint8_t hid_outep_addr;                      // Output end point address
    uint8_t ep_desc_attr_type_out_int;           // End point type
    uint8_t out_wmaxpacketsize1;                 // Max packet size
    uint8_t out_wmaxpacketsize2;
    uint8_t out_binterval;                       // bInterval in ms
};

/* Global structure having Generic,CDC,HID, MSC structures */
struct  abromConfigurationDescriptorGroup
{
    /* Generic part of config descriptor */
    const struct abromConfigurationDescriptorGenric abromConfigurationDescriptorGenric;
#ifdef _MSC_
    /* MSC descriptor structure */
    const struct abromConfigurationDescriptorMsc stMsc[MSC_NUM_INTERFACES];
#endif
#ifdef _CDC_ 
    /* CDC descriptor structure */
    const struct abromConfigurationDescriptorCdc stCdc[CDC_NUM_INTERFACES];
#endif
#ifdef _HID_
    /* HID descriptor structure */
    const struct abromConfigurationDescriptorHid stHid[HID_NUM_INTERFACES];
#endif
#ifdef _PHDC_
/* PDC descriptor structure */
    const struct abromConfigurationDescriptorPhdc stPhdc[PHDC_NUM_INTERFACES];
#endif
};

extern const struct  abromConfigurationDescriptorGroup abromConfigurationDescriptorGroup;
extern uint8_t const abromDeviceDescriptor[SIZEOF_DEVICE_DESCRIPTOR];
extern uint8_t const abromStringDescriptor[];
//extern uint8_t const abromReportDescriptor[SIZEOF_REPORT_DESCRIPTOR];

/* Handle Structure - Will be populated in descriptors.c based on number of CDC,HID interfaces */
struct tUsbHandle
{
    uint8_t ep_In_Addr;               // Input EP Addr 
    uint8_t ep_Out_Addr;              // Output EP Addr 
    uint8_t edb_Index;                // The EDB index 
    uint8_t dev_Class;                // Device Class- 2 for CDC, 3 for HID 
    uint16_t intepEP_X_Buffer;         // Interupt X Buffer Addr 
    uint16_t intepEP_Y_Buffer;         // Interupt Y Buffer Addr 
    uint16_t oep_X_Buffer;             // Output X buffer Addr 
    uint16_t oep_Y_Buffer;             // Output Y buffer Addr 
    uint16_t iep_X_Buffer;             // Input X Buffer Addr 
    uint16_t iep_Y_Buffer;             // Input  Y Buffer Addr 
};

extern const struct tUsbHandle stUsbHandle[CDC_NUM_INTERFACES + HID_NUM_INTERFACES + MSC_NUM_INTERFACES + PHDC_NUM_INTERFACES]; 
extern const tDEVICE_REQUEST_COMPARE tUsbRequestList[];

#ifdef __cplusplus
}
#endif

#endif

/*------------------------ Nothing Below This Line --------------------------*/

//Released_Version_5_20_06_03

-描述符.c

/* --COPYRIGHT--,BSD
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/


// Generated by MSP USB Descriptor Tool: Fri Jul 09 10:27:06 BST 2021

/*-----------------------------------------------------------------------------+
| Include files 
|-----------------------------------------------------------------------------*/
#include <USB_API/USB_Common/device.h>
#include <USB_API/USB_Common/defMSP430USB.h>
#include <USB_API/USB_Common/usb.h>              // USB-specific Data Structures
#include "descriptors.h"
#include <USB_API/USB_CDC_API/UsbCdc.h>
#include <USB_API/USB_HID_API/UsbHidReq.h>

uint16_t const report_desc_size[HID_NUM_INTERFACES] =
{
    46
};
uint8_t const report_len_input[HID_NUM_INTERFACES] =
{
    48
};

/*-----------------------------------------------------------------------------+
| Device Descriptor 
|-----------------------------------------------------------------------------*/
uint8_t const abromDeviceDescriptor[SIZEOF_DEVICE_DESCRIPTOR] = {
    SIZEOF_DEVICE_DESCRIPTOR,               // Length of this descriptor
    DESC_TYPE_DEVICE,                       // Type code of this descriptor
    0x00, 0x02,                             // Release of USB spec
    0x00,                                   // Device's base class code
    0x00,                                   // Device's sub class code
    0x00,                                   // Device's protocol type code
    EP0_PACKET_SIZE,                        // End point 0's packet size
    USB_VID&0xFF, USB_VID>>8,               // Vendor ID for device, TI=0x0451
                                            // You can order your own VID at www.usb.org"
    USB_PID&0xFF, USB_PID>>8,               // Product ID for device,
                                            // this ID is to only with this example
    VER_FW_L, VER_FW_H,                     // Revision level of device
    1,                                      // Index of manufacturer name string desc
    2,                                      // Index of product name string desc
    USB_STR_INDEX_SERNUM,                   // Index of serial number string desc
    1                                       //  Number of configurations supported
};

/*-----------------------------------------------------------------------------+
| Configuration Descriptor                                                     |
|-----------------------------------------------------------------------------*/
const struct abromConfigurationDescriptorGroup abromConfigurationDescriptorGroup=
{
    /* Generic part */
    {
        // CONFIGURATION DESCRIPTOR (9 bytes)
        SIZEOF_CONFIG_DESCRIPTOR,                          // bLength
        DESC_TYPE_CONFIG,                                  // bDescriptorType
        DESCRIPTOR_TOTAL_LENGTH, 0x00,                     // wTotalLength
        USB_NUM_INTERFACES,                                // bNumInterfaces
        USB_CONFIG_VALUE,                                  // bConfigurationvalue
        CONFIG_STRING_INDEX,                               // iConfiguration Description offset
        USB_SUPPORT_SELF_POWERED | USB_SUPPORT_REM_WAKE,   // bmAttributes, bus power, remote wakeup
        USB_MAX_POWER                                      // Max. Power Consumption
    },
    /******************************************************* start of HID*************************************/
    {
    /*start HID[0] Here */
        {
            //-------- Descriptor for HID class device -------------------------------------
            // INTERFACE DESCRIPTOR (9 bytes)
            SIZEOF_INTERFACE_DESCRIPTOR,        // bLength
            DESC_TYPE_INTERFACE,                // bDescriptorType: 4
            HID0_REPORT_INTERFACE,              // bInterfaceNumber
            0x00,                               // bAlternateSetting
            2,                                  // bNumEndpoints
            0x03,                               // bInterfaceClass: 3 = HID Device
            0,                                  // bInterfaceSubClass:
            0,                                  // bInterfaceProtocol:
            INTF_STRING_INDEX + 0,              // iInterface:1

            // HID DESCRIPTOR (9 bytes)
            0x09,                                 // bLength of HID descriptor
            0x21,                                 // HID Descriptor Type: 0x21
            0x01,0x01,                            // HID Revision number 1.01
            0x00,                                // Target country, nothing specified (00h)
            0x01,                                // Number of HID classes to follow
            0x22,                                // Report descriptor type
            (report_desc_size_HID0 & 0x0ff),  // Total length of report descriptor
            (report_desc_size_HID0  >> 8),

            SIZEOF_ENDPOINT_DESCRIPTOR,         // bLength
            DESC_TYPE_ENDPOINT,                 // bDescriptorType
            HID0_INEP_ADDR,                     // bEndpointAddress; bit7=1 for IN, bits 3-0=1 for ep1
            EP_DESC_ATTR_TYPE_INT,              // bmAttributes, interrupt transfers
            0x40, 0x00,                         // wMaxPacketSize, 64 bytes
            25,                                  // bInterval, ms

            SIZEOF_ENDPOINT_DESCRIPTOR,         // bLength
            DESC_TYPE_ENDPOINT,                 // bDescriptorType
            HID0_OUTEP_ADDR,                    // bEndpointAddress; bit7=1 for IN, bits 3-0=1 for ep1
            EP_DESC_ATTR_TYPE_INT,              // bmAttributes, interrupt transfers
            0x40, 0x00,                         // wMaxPacketSize, 64 bytes
            25,                                  // bInterval, ms
            /* end of HID[0]*/
        }

    }    /******************************************************* end of HID**************************************/

    
        
            
};

/*-----------------------------------------------------------------------------+
| String Descriptor                                                            |
|-----------------------------------------------------------------------------*/
uint8_t const abromStringDescriptor[] = {
    // String index0, language support

    4,        // Length of language descriptor ID
    3,        // LANGID tag
    0x09, 0x04,    // 0x0409 for English


    // String index1, Manufacturer

    36,        // Length of this string descriptor
    3,        // bDescriptorType
    'T',0x00,'e',0x00,'x',0x00,'a',0x00,'s',0x00,' ',0x00,
    'I',0x00,'n',0x00,'s',0x00,'t',0x00,'r',0x00,'u',0x00,
    'm',0x00,'e',0x00,'n',0x00,'t',0x00,'s',0x00,

    // String index2, Product

    38,        // Length of this string descriptor
    3,        // bDescriptorType
    'M',0x00,'S',0x00,'P',0x00,'4',0x00,'3',0x00,'0',0x00,
    '-',0x00,'U',0x00,'S',0x00,'B',0x00,' ',0x00,'E',0x00,
    'x',0x00,'a',0x00,'m',0x00,'p',0x00,'l',0x00,'e',0x00,

    // String index3, Serial Number

    4,        // Length of this string descriptor
    3,        // bDescriptorType
    '0',0x00,

    // String index4, Configuration String

    22,        // Length of this string descriptor
    3,        // bDescriptorType
    'M',0x00,'S',0x00,'P',0x00,'4',0x00,'3',0x00,'0',0x00,
    ' ',0x00,'U',0x00,'S',0x00,'B',0x00,


    // String index5, Interface String
    28,        // Length of this string descriptor
    3,        // bDescriptorType
    'H',0x00,'I',0x00,'D',0x00,' ',0x00,'I',0x00,'n',0x00,
    't',0x00,'e',0x00,'r',0x00,'f',0x00,'a',0x00,'c',0x00,
    'e',0x00
};

uint8_t const report_desc_HID0[]=
{
0x05, 0x01, //		USAGE_PAGE (Generic Desktop)
0x09, 0x05, //		USAGE (Game Pad)
0xA1, 0x01, //		COLLECTION (Application)
0xA1, 0x00, //			COLLECTION (Physical)
0x05, 0x09, //				USAGE_PAGE (Button)
0x19, 0x01, //				USAGE_MINIMUM (Button 1)
0x29, 0x10, //				USAGE_MAXIMUM (Button 16)
0x15, 0x00, //				LOGICAL_MINIMUM (0)
0x25, 0x01, //				LOGICAL_MAXIMUM (1)
0x95, 0x10, //				REPORT_COUNT (16)
0x75, 0x01, //				REPORT_SIZE (1)
0x81, 0x02, //				INPUT (Data,Var,Abs)
0x05, 0x01, //				USAGE_PAGE (Generic Desktop)
0x09, 0x30, //				USAGE (X)
0x09, 0x31, //				USAGE (Y)
0x09, 0x32, //				USAGE (Z)
0x09, 0x33, //				USAGE (Rx)
0x15, 0x81, //				LOGICAL_MINIMUM (-127)
0x25, 0x7F, //				LOGICAL_MAXIMUM (127)
0x75, 0x08, //				REPORT_SIZE (8)
0x95, 0x04, //				REPORT_COUNT (4)
0x81, 0x02, //				INPUT (Data,Var,Abs)
0xC0, //			END COLLECTION
0xC0 //		END COLLECTION
};

const uint8_t* report_desc[HID_NUM_INTERFACES] =
{
    (uint8_t*)&report_desc_HID0
};

/**** Populating the endpoint information handle here ****/
const struct tUsbHandle stUsbHandle[]=
{
    {
        HID0_INEP_ADDR,
        HID0_OUTEP_ADDR,
        0,
        HID_CLASS,
        0,
        0,
        OEP1_X_BUFFER_ADDRESS,
        OEP1_Y_BUFFER_ADDRESS,
        IEP1_X_BUFFER_ADDRESS,
        IEP1_Y_BUFFER_ADDRESS
    }

    
        
            
};

//-------------DEVICE REQUEST LIST---------------------------------------------

const tDEVICE_REQUEST_COMPARE tUsbRequestList[] = 
{

    {
        //---- HID 0 Class Requests -----//
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,

            USB_REQ_GET_REPORT,
            0xff,0xff,
            HID0_REPORT_INTERFACE,0x00,
            0xff,0xff,
            0xcc,&usbGetReport,
    },
    {
            // SET REPORT
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
            USB_REQ_SET_REPORT,
            0xff,0xFF,                          // bValueL is index and bValueH is type
            HID0_REPORT_INTERFACE,0x00,
            0xff,0xff,
            0xcc,&usbSetReport,
    },
    {
            // GET REPORT DESCRIPTOR
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
            USB_REQ_GET_DESCRIPTOR,
            0xff,DESC_TYPE_REPORT,              // bValueL is index and bValueH is type
            HID0_REPORT_INTERFACE,0x00,
            0xff,0xff,
            0xdc,&usbGetReportDescriptor,
    },
    {
            // GET HID DESCRIPTOR
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
            USB_REQ_GET_DESCRIPTOR,
            0xff,DESC_TYPE_HID,                 // bValueL is index and bValueH is type
            HID0_REPORT_INTERFACE,0x00,
            0xff,0xff,
            0xdc,&usbGetHidDescriptor,
    },

    {
        //---- USB Standard Requests -----//
            // clear device feature
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_CLEAR_FEATURE,
            FEATURE_REMOTE_WAKEUP,0x00,         // feature selector
            0x00,0x00,
            0x00,0x00,
            0xff,&usbClearDeviceFeature,
    },
    {

            // clear endpoint feature
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_ENDPOINT,
            USB_REQ_CLEAR_FEATURE,
            FEATURE_ENDPOINT_STALL,0x00,
            0xff,0x00,
            0x00,0x00,
            0xf7,&usbClearEndpointFeature,
    },
    {
            // get configuration
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_GET_CONFIGURATION,
            0x00,0x00, 
            0x00,0x00, 
            0x01,0x00,
            0xff,&usbGetConfiguration,
    },
    {
            // get device descriptor
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_GET_DESCRIPTOR,
            0xff,DESC_TYPE_DEVICE,              // bValueL is index and bValueH is type
            0xff,0xff,
            0xff,0xff,
            0xd0,&usbGetDeviceDescriptor,
    },
    {
            // get configuration descriptor
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_GET_DESCRIPTOR,
            0xff,DESC_TYPE_CONFIG,              // bValueL is index and bValueH is type
            0xff,0xff,
            0xff,0xff,
            0xd0,&usbGetConfigurationDescriptor,
    },
    {
            // get string descriptor
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_GET_DESCRIPTOR,
            0xff,DESC_TYPE_STRING,              // bValueL is index and bValueH is type
            0xff,0xff,
            0xff,0xff,
            0xd0,&usbGetStringDescriptor,
    },
    {
           // get interface
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
            USB_REQ_GET_INTERFACE,
            0x00,0x00,
            0xff,0xff,
            0x01,0x00,
            0xf3,&usbGetInterface,
    },
    {
            // get device status
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_GET_STATUS,
            0x00,0x00,
            0x00,0x00,
            0x02,0x00,
            0xff,&usbGetDeviceStatus, 
    },
    {
            // get interface status
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
            USB_REQ_GET_STATUS,
            0x00,0x00,
            0xff,0x00,
            0x02,0x00,
            0xf7,&usbGetInterfaceStatus,
    },
    {
            // get endpoint status
            USB_REQ_TYPE_INPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_ENDPOINT,
            USB_REQ_GET_STATUS,
            0x00,0x00,
            0xff,0x00,
            0x02,0x00,
            0xf7,&usbGetEndpointStatus,
    },
    {
            // set address
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_SET_ADDRESS,
            0xff,0x00,
            0x00,0x00,
            0x00,0x00,
            0xdf,&usbSetAddress,
    },
    {
            // set configuration
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_SET_CONFIGURATION,
            0xff,0x00,
            0x00,0x00,
            0x00,0x00,
            0xdf,&usbSetConfiguration,
    },
    {
           // set device feature
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_DEVICE,
            USB_REQ_SET_FEATURE,
            0xff,0x00,                      // feature selector
            0x00,0x00,
            0x00,0x00,
            0xdf,&usbSetDeviceFeature,
    },
    {
            // set endpoint feature
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_ENDPOINT,
            USB_REQ_SET_FEATURE,
            0xff,0x00,                      // feature selector
            0xff,0x00,                      // endpoint number <= 127
            0x00,0x00,
            0xd7,&usbSetEndpointFeature,
    },
    {
            // set interface
            USB_REQ_TYPE_OUTPUT | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
            USB_REQ_SET_INTERFACE,
            0xff,0x00,                      // feature selector
            0xff,0x00,                      // interface number
            0x00,0x00,
            0xd7,&usbSetInterface,
    },
    {

            // end of usb descriptor -- this one will be matched to any USB request
            // since bCompareMask is 0x00.
            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
            0x00,&usbInvalidRequest     // end of list
    }
	
};


/*-----------------------------------------------------------------------------+
| END OF Descriptor.c FILE
|-----------------------------------------------------------------------------*/


//Released_Version_5_20_06_03

使用实例

/* --COPYRIGHT--,BSD
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/


// Generated by MSP USB Descriptor Tool: Fri Jul 09 10:27:06 BST 2021

/*-----------------------------------------------------------------------------+
| Include files                                                                |
|-----------------------------------------------------------------------------*/
#include <USB_API/USB_Common/device.h>        // Basic Type declarations
#include <USB_API/USB_Common/defMSP430USB.h>
#include "descriptors.h"
#include <USB_API/USB_Common/usb.h>           //USB-specific Data Structures
#include <USB_API/USB_Common/UsbIsr.h>
#include <string.h>
#include <USB_API/USB_HID_API/UsbHid.h>
#include <USB_API/USB_HID_API/UsbHidReq.h>

/*----------------------------------------------------------------------------+
| External Variables                                                          |
+----------------------------------------------------------------------------*/
extern uint8_t  bFunctionSuspended;
extern __no_init tEDB0 __data16 tEndPoint0DescriptorBlock;
extern __no_init tEDB __data16 tInputEndPointDescriptorBlock[];
extern __no_init tEDB __data16 tOutputEndPointDescriptorBlock[];
extern volatile uint8_t bHostAsksUSBData;
extern volatile uint8_t bTransferInProgress;
extern volatile uint8_t bSecondUartTxDataCounter[];
extern volatile uint8_t* pbSecondUartTxData;
extern uint8_t bStatusAction;
extern uint16_t wUsbEventMask;
int16_t CdcToHostFromBuffer(uint8_t);
int16_t CdcToBufferFromHost(uint8_t);
int16_t CdcIsReceiveInProgress(uint8_t);
int16_t HidToHostFromBuffer(uint8_t);
int16_t HidToBufferFromHost(uint8_t);
int16_t HidIsReceiveInProgress(uint8_t);
extern uint16_t wUsbHidEventMask;
int16_t PHDCToHostFromBuffer(uint8_t);
int16_t PHDCToBufferFromHost(uint8_t);
int16_t PHDCIsReceiveInProgress(uint8_t);
uint16_t USB_determineFreq(void);
/*----------------------------------------------------------------------------+
| General Subroutines                                                         |
+----------------------------------------------------------------------------*/
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__) 
#pragma vector=USB_UBM_VECTOR
__interrupt void iUsbInterruptHandler(void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(USB_UBM_VECTOR))) iUsbInterruptHandler(void)
#endif
{
    uint8_t bWakeUp = FALSE;
//Check if the setup interrupt is pending.
    //We need to check it before other interrupts,
    //to work around that the Setup Int has lower priority then Input Endpoint 0
    if (USBIFG & SETUPIFG)
    {
        bWakeUp = SetupPacketInterruptHandler();  
#ifdef USB10_WORKAROUND
        tEndPoint0DescriptorBlock.bIEPCNFG &= ~EPCNF_UBME; // Clear ME to gate off SETUPIFG clear event
        tEndPoint0DescriptorBlock.bOEPCNFG &= ~EPCNF_UBME; // Clear ME to gate off SETUPIFG clear event
#endif
        USBIFG &= ~SETUPIFG;    // clear the interrupt bit
#ifdef USB10_WORKAROUND
        tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_UBME; // Set ME to continue with normal operation
        tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_UBME; // Set ME to continue with normal operation
#endif
    }   
    switch (__even_in_range(USBVECINT & 0x3f, USBVECINT_OUTPUT_ENDPOINT7))
    {
    case USBVECINT_NONE:
        break;
    case USBVECINT_PWR_DROP:
      __no_operation();
        break;
    case USBVECINT_PLL_LOCK:
        break;
    case USBVECINT_PLL_SIGNAL:
        break;
    case USBVECINT_PLL_RANGE:
        if (wUsbEventMask & USB_CLOCK_FAULT_EVENT)
        {
            bWakeUp = USB_handleClockEvent();
        }
        break;
    case USBVECINT_PWR_VBUSOn:
        PWRVBUSonHandler();
        if (wUsbEventMask & USB_VBUS_ON_EVENT)
        {
            bWakeUp = USB_handleVbusOnEvent();
        }
        break;
    case USBVECINT_PWR_VBUSOff:
        PWRVBUSoffHandler();
        if (wUsbEventMask & USB_VBUS_OFF_EVENT)
        {
            bWakeUp = USB_handleVbusOffEvent();
        }
        break;
    case USBVECINT_USB_TIMESTAMP:
        break;
    case USBVECINT_INPUT_ENDPOINT0:
        IEP0InterruptHandler();
        break;
    case USBVECINT_OUTPUT_ENDPOINT0:
        OEP0InterruptHandler();
        break;
    case USBVECINT_RSTR:
        USB_reset();
        if (wUsbEventMask & USB_RESET_EVENT)
        {
            bWakeUp = USB_handleResetEvent();
        }
        break;
    case USBVECINT_SUSR:
        USB_suspend();
        if (wUsbEventMask & USB_SUSPENDED_EVENT)
        {
            bWakeUp = USB_handleSuspendEvent();
        }
        break;
    case USBVECINT_RESR:
        USB_resume();
        if (wUsbEventMask & USB_RESUME_EVENT)
        {
            bWakeUp = USB_handleResumeEvent();
        }
        //-- after resume we will wake up! Independ what event handler says.
        bWakeUp = TRUE;
        break;
    case USBVECINT_SETUP_PACKET_RECEIVED:
        // NAK both IEP and OEP enpoints
        tEndPoint0DescriptorBlock.bIEPBCNT = EPBCNT_NAK;
        tEndPoint0DescriptorBlock.bOEPBCNT = EPBCNT_NAK;
        SetupPacketInterruptHandler();
        break;
    case USBVECINT_STPOW_PACKET_RECEIVED:
        break;
	case USBVECINT_INPUT_ENDPOINT1:
        //send saved bytes from buffer...
        bWakeUp = HidToHostFromBuffer(HID0_INTFNUM);
        break;
    case USBVECINT_INPUT_ENDPOINT2:
         break;
    case USBVECINT_INPUT_ENDPOINT3:
        break;
    case USBVECINT_INPUT_ENDPOINT4:
		break;
    case USBVECINT_INPUT_ENDPOINT5:
		break;
    case USBVECINT_INPUT_ENDPOINT6:
		break;
    case USBVECINT_INPUT_ENDPOINT7:
		break;
    case USBVECINT_OUTPUT_ENDPOINT1:
        //call callback function if no receive operation is underway
        if (!HidIsReceiveInProgress(HID0_INTFNUM))
        {
            if (wUsbEventMask & USB_DATA_RECEIVED_EVENT)
            {
                bWakeUp = USBHID_handleDataReceived(HID0_INTFNUM); 
            }
        }
        else
        {
                //complete receive opereation - copy data to user buffer
                bWakeUp = HidToBufferFromHost(HID0_INTFNUM);
        }
	    break;
    case USBVECINT_OUTPUT_ENDPOINT2:
        break;
    case USBVECINT_OUTPUT_ENDPOINT3:
        break;
    case USBVECINT_OUTPUT_ENDPOINT4:
        break;
    case USBVECINT_OUTPUT_ENDPOINT5:
        break;
    case USBVECINT_OUTPUT_ENDPOINT6:
        break;
    case USBVECINT_OUTPUT_ENDPOINT7:
        break;
    default:
        break;
    }

    if (bWakeUp)
    {
        __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM0-3
        __no_operation();  // Required for debugger
    }
}
	


/*----------------------------------------------------------------------------+
| Interrupt Sub-routines                                                      |
+----------------------------------------------------------------------------*/
uint8_t SetupPacketInterruptHandler(void)
{
    uint8_t bTemp;
    uint8_t bWakeUp = FALSE;
    USBCTL |= FRSTE;      // Function Reset Connection Enable - set enable after first setup packet was received
    usbProcessNewSetupPacket:
    // copy the MSB of bmRequestType to DIR bit of USBCTL
    if((tSetupPacket.bmRequestType & USB_REQ_TYPE_INPUT) == USB_REQ_TYPE_INPUT)
    {
        USBCTL |= DIR;
    }
    else
    {
        USBCTL &= ~DIR;
    }
    bStatusAction = STATUS_ACTION_NOTHING;
    // clear out return data buffer
    for(bTemp=0; bTemp<USB_RETURN_DATA_LENGTH; bTemp++)
    {
        abUsbRequestReturnData[bTemp] = 0x00;
    }
    // decode and process the request
    bWakeUp = usbDecodeAndProcessUsbRequest();
    // check if there is another setup packet pending
    // if it is, abandon current one by NAKing both data endpoint 0
    if((USBIFG & STPOWIFG) != 0x00)
    {
        USBIFG &= ~(STPOWIFG | SETUPIFG);
        goto usbProcessNewSetupPacket;
    }
    return bWakeUp;
}

//----------------------------------------------------------------------------
void PWRVBUSoffHandler(void)
{
   uint16_t MCLKFreq = USB_determineFreq();
   uint16_t DelayConstant_250us = ((MCLKFreq >> 6) + (MCLKFreq >> 7) + (MCLKFreq >> 9));
   volatile uint16_t i, j;

    //wait 1 ms till enable USB 
    for(j = 0; j < 4; j++)
    {
        for (i = 0; i < (DelayConstant_250us); i++){
            _NOP();
        }
   }
    if (!(USBPWRCTL & USBBGVBV))
    {
        USBKEYPID   =    0x9628;        // set KEY and PID to 0x9628 -> access to configuration registers enabled
        bEnumerationStatus = 0x00;      // device is not enumerated
        bFunctionSuspended = FALSE;     // device is not suspended
        USBCNF     =    0;              // disable USB module
        USBPLLCTL  &=  ~UPLLEN;         // disable PLL
        USBPWRCTL &= ~(VBOFFIE + VBOFFIFG + SLDOEN);          // disable interrupt VBUSoff
        USBKEYPID   =    0x9600;        // access to configuration registers disabled
    }
}

//----------------------------------------------------------------------------
void PWRVBUSonHandler(void)
{
   uint16_t MCLKFreq = USB_determineFreq();
   uint16_t DelayConstant_250us = ((MCLKFreq >> 6) + (MCLKFreq >> 7) + (MCLKFreq >> 9));
   volatile uint16_t i, j;

    //wait 1 ms till enable USB 
    for(j = 0; j < 4; j++)
    {
        for (i = 0; i < (DelayConstant_250us); i++){
            _NOP();
        }
   }
    if (USBPWRCTL & USBBGVBV)                //Checking for USB Bandgap and VBUS valid before modifying USBPWRCTL
    {
        USBKEYPID =  0x9628;                // set KEY and PID to 0x9628 -> access to configuration registers enabled
        USBPWRCTL |= VBOFFIE;               // enable interrupt VBUSoff
        USBPWRCTL &= ~ (VBONIFG + VBOFFIFG);             // clean int flag (bouncing)
        USBKEYPID =  0x9600;                // access to configuration registers disabled
    }
}

//----------------------------------------------------------------------------
void IEP0InterruptHandler(void)
{
    USBCTL |= FRSTE;                              // Function Reset Connection Enable
    tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;     
    if(bStatusAction == STATUS_ACTION_DATA_IN)
    {
        usbSendNextPacketOnIEP0();
    }
    else
    {
        tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_STALL; // no more data
    }
}

//----------------------------------------------------------------------------
uint8_t OEP0InterruptHandler(void)
{
    uint8_t bWakeUp = FALSE;
    USBCTL |= FRSTE;                              // Function Reset Connection Enable
    tEndPoint0DescriptorBlock.bIEPBCNT = 0x00;    
    if(bStatusAction == STATUS_ACTION_DATA_OUT)
    {
        usbReceiveNextPacketOnOEP0();
        if(bStatusAction == STATUS_ACTION_NOTHING)
        {
#           ifdef _CDC_
                if(tSetupPacket.bRequest == USB_CDC_SET_LINE_CODING)
                {
                    bWakeUp = Handler_SetLineCoding();
                }
#          endif
#ifdef _HID_
                if (tSetupPacket.bRequest == USB_REQ_SET_REPORT) {
                    bWakeUp = USBHID_handleEP0SetReportDataAvailable(tSetupPacket.wIndex);
                }
#endif
          }
    }
    else
    {
        tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL; // no more data
    }
    return (bWakeUp);
}



/*----------------------------------------------------------------------------+
| End of source file                                                          |
+----------------------------------------------------------------------------*/
/*------------------------ Nothing Below This Line --------------------------*/	
	//Released_Version_5_20_06_03

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Hishan,

    让我看看我是否能找到能够提供帮助的人。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Hishan,

    我对这个没有运气、所以让我看看我是否可以设置一些东西来模拟您尝试的东西。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    器件型号:MSP430F5529

    各位专家、您好!

    几周前、我尝试使用具有7-14个模拟输入的 MSP430来模拟 USB-HID 游戏。 我在为定制的 USB-HID 设备获取描述符时遇到问题。 我发布了我的代码、但没有人能帮助我。

    幸运  的是、我在网上看到了这个代码:GitHub - TI-FIRST /MSP430-Gamead:适用于 FRC 的 MSP430F5529 Gamead 代码、它帮助我启动 MSP430并将其作为具有8个模拟输入的游戏 epad 运行。

    main.c 文件包含更改报告结构的说明:  

    *此示例在主机上充当游戏 epad。 游戏手柄具有 HID 报告、如所述
    * descriptors.c 中的 REPORT_desc_HID0变量 请注意、如果是此报告结构
    *已更改、则需要更新以下长度-
    * 1. descriptors.h 中的#define REPORT_desc_size_HID0需要使用描述符大小进行更新
    * 2. 需要在描述符.c 中更新 REPORT_desc_size 和 REPORT_len_input
    *本演示将枚举18个字节的输入报告和2个字节的输出报告
    *游戏 epad 的输入和输出报告结构,如 USB_gamepad.h 中所述
    *输入报告用于报告 ADC 值和按钮状态(GPIO)
    *输出报告用于设置/复位指示器(GPIO)

    目前在 descriptors.c 文件中的描述符是:

    UsagePage(USB_HID_GENERIC_DESKTOP),
    Usage(USB_HID_JOYSTICK),
    Collection(USB_HID_APPLICATION),
        //
        // The axis for the controller.
        //
        UsagePage(USB_HID_GENERIC_DESKTOP),
        Usage (USB_HID_POINTER),
        Collection (USB_HID_PHYSICAL),
    
            //
            // The X, Y and Z values which are specified as 8-bit absolute
            // position values.
            //
            Usage (USB_HID_X),
            Usage (USB_HID_Y),
            Usage (USB_HID_Z),
            Usage (USB_HID_RX),
            Usage (USB_HID_RY),
            Usage (USB_HID_RZ),
            Usage (USB_HID_SLIDER),
            Usage (USB_HID_DIAL),
            //
            // 8 16-bit absolute values.
            //
            ReportSize(16),
            ReportCount(8),
            Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                  USB_HID_INPUT_ABS),
    
            //
            // Max 32 buttons.
            //
            UsagePage(USB_HID_BUTTONS),
            UsageMinimum(1),
            UsageMaximum(NUM_BUTTONS),
            LogicalMinimum(0),
            LogicalMaximum(1),
            PhysicalMinimum(0),
            PhysicalMaximum(1),
    
            //
            // 8 - 1 bit values for the buttons.
            //
            ReportSize(1),
            ReportCount(32),
            Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                  USB_HID_INPUT_ABS),
    
             //
             // Max 16 indicator bits
             //
             UsagePage(USB_HID_BUTTONS),
             UsageMinimum(1),
             UsageMaximum(NUM_INDICATORS),
             LogicalMinimum(0),
             LogicalMaximum(1),
             PhysicalMinimum(0),
             PhysicalMaximum(1),
    
             //
             // 8 - 1 bit values for the leds.
             //
             ReportSize(1),
             ReportCount(16),
             Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                   USB_HID_INPUT_ABS),
    
        EndCollection,
    EndCollection

    我想将其更改为14个16位模拟输入、如下所示:

    UsagePage(USB_HID_GENERIC_DESKTOP),
    Usage(USB_HID_JOYSTICK),
    Collection(USB_HID_APPLICATION),
        //
        // The axis for the controller.
        //
        UsagePage(USB_HID_GENERIC_DESKTOP),
        Usage (USB_HID_POINTER),
        Collection (USB_HID_PHYSICAL),
    
            //
            // The X, Y and Z values which are specified as 8-bit absolute
            // position values.
            //
            Usage (USB_HID_X),
            Usage (USB_HID_Y),
            Usage (USB_HID_Z),
            Usage (USB_HID_RX),
            Usage (USB_HID_RY),
            Usage (USB_HID_RZ),
            Usage (USB_HID_SLIDER),
            Usage (USB_HID_DIAL),
            Usage (USB_HID_VX),
            Usage (USB_HID_VY),
            Usage (USB_HID_VZ),
            Usage (USB_HID_VRX),
            Usage (USB_HID_VRY),
            Usage (USB_HID_VRZ),
            //
            // 8 16-bit absolute values.
            //
            ReportSize(16),
            ReportCount(14),
            Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                  USB_HID_INPUT_ABS),
    
            //
            // Max 32 buttons.
            //
            UsagePage(USB_HID_BUTTONS),
            UsageMinimum(1),
            UsageMaximum(6),
            LogicalMinimum(0),
            LogicalMaximum(1),
            PhysicalMinimum(0),
            PhysicalMaximum(1),
    
            //
            // 8 - 1 bit values for the buttons.
            //
            ReportSize(1),
            ReportCount(32),
            Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                  USB_HID_INPUT_ABS),
    
             //
             // Max 16 indicator bits
             //
             UsagePage(USB_HID_BUTTONS),
             UsageMinimum(1),
             UsageMaximum(6),
             LogicalMinimum(0),
             LogicalMaximum(1),
             PhysicalMinimum(0),
             PhysicalMaximum(1),
    
             //
             // 8 - 1 bit values for the leds.
             //
             ReportSize(1),
             ReportCount(16),
             Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
                   USB_HID_INPUT_ABS),
    
        EndCollection,
    EndCollection

    但是、我不知道如何计算描述符的长度/大小/字节。 我尝试了 USB-HID 规范(HID 1.11的器件类定义| USB-IF)、该规范指出项目具有字节前缀、但我无法确定要计数的项目以及它们的累加方式。 抱歉、我在 USB 方面经验不足。

    我认为描述符的大小是32字节? 但计算机在插入时未检测到游戏手柄、因为我认为 我在 report_len_input 中得到的值是错误的。

    是否有人能够查看代码、并让我知道 描述符文件中 REPORT_desc_size、REPORT_len_input 以及我需要更改的任何其他值、以扩展14个16位模拟输入的代码功能。

    P.S.要复制和查看正在工作的游戏 epad、只需将代码上传到开发套件并在 Windows 上搜索"设置 USB 游戏控制器"、如果一切运行正常且报告被接受、则应将其识别为游戏 epad。



    谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Hishan,

    我将您的帖子合并在一起、因为它们实际上与同一个主题有关。  

    对于 HID、我们的 USB 开发包和描述符工具本身仅支持一些 HID 类型、即键盘、鼠标和数据擦除。 任何其他"传统"HID 类型都需要通过描述符工具中的"自定义"功能来完成、您需要在该工具中输入原始报告描述符。 我们目前无法支持您创建此自定义描述符以满足您的需求。 我建议查看第三方资源或指南、了解描述符报告对于您所选 HID 类型的外观。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、

    我正在加入本次对话、因为我们遇到了与此非常类似的问题。  

    由于这个 USB 描述符工具是 TI 特有的、所以我很难理解如果您无法帮助我们、我们如何获得支持? 您能否向我介绍有关第三方资源、推荐阅读或指南、以了解我们如何在该问题上获得额外支持?

    谢谢

    垫  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、

    USB 描述符工具是 TI 制作的、用于帮助您在使用的 PC 上正确获取支持的 HID 类型。 我们允许自定义类别扩展到本机不支持的 HID 类类型。 游戏手柄/游戏手柄属于此类别。 您可以通过 USB HID 规范或其他在线论坛找到此类的正确描述符字段。 stackexchange 是一个查看一般知识的好论坛、430h.com 是一个独立的 MSP430特定论坛、您可以在其中找到所需的内容。