野火rt1052标准usb_hid设备通信

        由于usb驱动功能复杂种类繁多,所以我根据目前的项目需求,在官方usb驱动例程上进行改动,重新封装了初始化和收发接口,自测可用。

        首先先看一下原有官方例程的源码如下

/*
 * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
 * Copyright 2016 - 2017 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of the copyright holder 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 HOLDER 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.
 */

#include "usb_host_config.h"
#include "usb_host.h"
#include "fsl_device_registers.h"
#include "usb_host_hid.h"
#include "board.h"
#include "host_hid_generic.h"
#include "fsl_common.h"
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
#include "fsl_sysmpu.h"
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
#include "app.h"
#include "board.h"

#if ((!USB_HOST_CONFIG_KHCI) && (!USB_HOST_CONFIG_EHCI) && (!USB_HOST_CONFIG_OHCI) && (!USB_HOST_CONFIG_IP3516HS))
#error Please enable USB_HOST_CONFIG_KHCI, USB_HOST_CONFIG_EHCI, USB_HOST_CONFIG_OHCI, or USB_HOST_CONFIG_IP3516HS in file usb_host_config.
#endif

#include "pin_mux.h"
#include "usb_phy.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*!
 * @brief host callback function.
 *
 * device attach/detach callback function.
 *
 * @param deviceHandle         device handle.
 * @param configurationHandle  attached device's configuration descriptor information.
 * @param eventCode            callback event code, please reference to enumeration host_event_t.
 *
 * @retval kStatus_USB_Success              The host is initialized successfully.
 * @retval kStatus_USB_NotSupported         The application don't support the configuration.
 */
static usb_status_t USB_HostEvent(usb_device_handle deviceHandle,
                                  usb_host_configuration_handle configurationHandle,
                                  uint32_t eventCode);

/*!
 * @brief app initialization.
 */
static void USB_HostApplicationInit(void);

extern void USB_HostClockInit(void);
extern void USB_HostIsrEnable(void);
extern void USB_HostTaskFn(void *param);
void BOARD_InitHardware(void);

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*! @brief USB host generic instance global variable */
extern usb_host_hid_generic_instance_t g_HostHidGeneric;
usb_host_handle g_HostHandle;

/*******************************************************************************
 * Code
 ******************************************************************************/
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
void USB_OTG1_IRQHandler(void)
{
    USB_HostEhciIsrFunction(g_HostHandle);
}
#endif
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
void USB_OTG2_IRQHandler(void)
{
    USB_HostEhciIsrFunction(g_HostHandle);
}
#endif
void USB_HostClockInit(void)
{
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
    usb_phy_config_struct_t phyConfig = {
        BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
    };
#endif
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
    if (CONTROLLER_ID == kUSB_ControllerEhci0)
    {
        CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
        CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
    }
    else
    {
        CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
        CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
    }
    USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig);
#endif
}

void USB_HostIsrEnable(void)
{
    uint8_t irqNumber;
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
    uint8_t usbHOSTEhciIrq[] = USBHS_IRQS;
    irqNumber = usbHOSTEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0];
#endif /* USB_HOST_CONFIG_EHCI */

/* Install isr, set priority, and enable IRQ. */
#if defined(__GIC_PRIO_BITS)
    GIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
#else
    NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
#endif
    EnableIRQ((IRQn_Type)irqNumber);
}

void USB_HostTaskFn(void *param)
{
#if defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)
    USB_HostEhciTaskFunction(param);
#endif
}

/*!
 * @brief USB isr function.
 */

static usb_status_t USB_HostEvent(usb_device_handle deviceHandle,
                                  usb_host_configuration_handle configurationHandle,
                                  uint32_t eventCode)
{
    usb_status_t status = kStatus_USB_Success;

    switch (eventCode)
    {
        case kUSB_HostEventAttach:
            status = USB_HostHidGenericEvent(deviceHandle, configurationHandle, eventCode);
            break;

        case kUSB_HostEventNotSupported:
            usb_echo("device not supported.\r\n");
            break;

        case kUSB_HostEventEnumerationDone:
            status = USB_HostHidGenericEvent(deviceHandle, configurationHandle, eventCode);
            break;

        case kUSB_HostEventDetach:
            status = USB_HostHidGenericEvent(deviceHandle, configurationHandle, eventCode);
            break;

        default:
            break;
    }
    return status;
}

static void USB_HostApplicationInit(void)
{
    usb_status_t status = kStatus_USB_Success;

    USB_HostClockInit();

#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT))
    SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */

    status = USB_HostInit(CONTROLLER_ID, &g_HostHandle, USB_HostEvent);
    if (status != kStatus_USB_Success)
    {
        usb_echo("host init error\r\n");
        return;
    }
    USB_HostIsrEnable();

    usb_echo("host init done\r\n");
}

int main(void)
{
    BOARD_ConfigMPU();
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();

    USB_HostApplicationInit();

    while (1)
    {
        USB_HostTaskFn(g_HostHandle);
        USB_HostHidGenericTask(&g_HostHidGeneric);
    }
}

可以看到主函数中行代码是对开发板资源初始化, USB_HostApplicationInit();函数是对usb相关资源初始化, 然后一个while循环执行USB主控的任务查询和hid设备的任务轮寻。

跟进USB_HostTaskFn(g_HostHandle);函数发现此函数是对USB主控器不同状态的轮寻,所以不做修改,而跟进USB_HostHidGenericTask函数发现这个函数与我们要进行的Hid设备数据传输相关,所以修改这个函数并重新封装接口。

USB_HostHidGenericTask函数的文件源码如下

/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016 - 2017 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of the copyright holder 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 HOLDER 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.
 */

#include "usb_host_config.h"
#include "usb_host.h"
#include "usb_host_hid.h"
#include "host_hid_generic.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*!
 * @brief process hid data and print generic data.
 *
 * @param genericInstance   hid generic instance pointer.
 */
static void USB_HostHidGenericProcessBuffer(usb_host_hid_generic_instance_t *genericInstance);

/*!
 * @brief host hid generic control transfer callback.
 *
 * This function is used as callback function for control transfer .
 *
 * @param param      the host hid generic instance pointer.
 * @param data       data buffer pointer.
 * @param dataLength data length.
 * @status           transfer result status.
 */
static void USB_HostHidControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status);

/*!
 * @brief host hid generic interrupt in transfer callback.
 *
 * This function is used as callback function when call USB_HostHidRecv .
 *
 * @param param      the host hid generic instance pointer.
 * @param data       data buffer pointer.
 * @param dataLength data length.
 * @status           transfer result status.
 */
static void USB_HostHidInCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status);

/*!
 * @brief host hid generic interrupt out transfer callback.
 *
 * This function is used as callback function when call USB_HostHidSend .
 *
 * @param param    the host hid generic instance pointer.
 * @param data     data buffer pointer.
 * @param dataLength data length.
 * @status         transfer result status.
 */
static void USB_HostHidOutCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status);

/*!
 * @brief host hid generic prepare data for sending.
 *
 * @param genericInstance  the host hid generic instance pointer.
 *
 * @retval kStatus_USB_Sucess  there is data.
 * @retval kStatus_USB_Error   data is sent done.
 */
static usb_status_t USB_HostHidGenericPrepareOutData(usb_host_hid_generic_instance_t *genericInstance);

/*******************************************************************************
 * Variables
 ******************************************************************************/

usb_host_hid_generic_instance_t g_HostHidGeneric; /* hid generic instance */
uint8_t testData[] =
    "Test string: This is usb host hid generic demo, it only support pid=0x00a2 and vid=0x1fc9 hid device. Host send "
    "this test string to device, device reply the data to host then host print the data\r\n";

USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
uint8_t s_GenericInBuffer[HID_GENERIC_IN_BUFFER_SIZE]; /*!< use to receive report descriptor and data */
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
uint8_t s_GenericOutBuffer[HID_GENERIC_IN_BUFFER_SIZE]; /*!< use to send data */

/*******************************************************************************
 * Code
 ******************************************************************************/

static void USB_HostHidGenericProcessBuffer(usb_host_hid_generic_instance_t *genericInstance)
{
    genericInstance->genericInBuffer[genericInstance->inMaxPacketSize] = 0;

    usb_echo("%s", genericInstance->genericInBuffer);
}

static void USB_HostHidControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;

    if (kStatus_USB_TransferStall == status) 
    {
        usb_echo("device don't support this ruquest \r\n");
    }
    else if (kStatus_USB_Success != status)
    {
        usb_echo("control transfer failed\r\n");
    }
    else
    {
    }

    if (genericInstance->runWaitState == kRunWaitSetInterface) /* set interface finish */
    {
        genericInstance->runState = kRunSetInterfaceDone;
    }
    else if (genericInstance->runWaitState == kRunWaitSetIdle) /* hid set idle finish */
    {
        genericInstance->runState = kRunSetIdleDone;
    }
    else if (genericInstance->runWaitState == kRunWaitGetReportDescriptor) /* hid get report descriptor finish */
    {
        genericInstance->runState = kRunGetReportDescriptorDone;
    }
    else if (genericInstance->runWaitState == kRunWaitSetProtocol) /* hid set protocol finish */
    {
        genericInstance->runState = kRunSetProtocolDone;
    }
    else
    {
    }
}

static void USB_HostHidInCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;

    if (genericInstance->runWaitState == kRunWaitDataReceived)
    {
        if (status == kStatus_USB_Success)
        {
            genericInstance->runState = kRunDataReceived; /* go to process data */
        }
        else
        {
            if (genericInstance->deviceState == kStatus_DEV_Attached)
            {
                genericInstance->runState = kRunPrimeDataReceive; /* go to prime next receiving */
            }
        }
    }
}

static void USB_HostHidOutCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{ /* NULL */
}

static usb_status_t USB_HostHidGenericPrepareOutData(usb_host_hid_generic_instance_t *genericInstance)
{
    uint16_t index = 0;

    if (genericInstance->sendIndex < (sizeof(testData) - 1)) /* sendIndex indicate the current position of testData */
    {
        /* get the max packet data, note: the data should be 0 when there is no actual data to send */
        for (index = 0; ((index + genericInstance->sendIndex) < (sizeof(testData) - 1)) &&
                        (index < genericInstance->outMaxPacketSize);
             ++index)
        {
            genericInstance->genericOutBuffer[index] = testData[index + genericInstance->sendIndex];
        }
        for (; index < genericInstance->outMaxPacketSize; ++index)
        {
            genericInstance->genericOutBuffer[index] = 0x00;
        }
        genericInstance->sendIndex += genericInstance->outMaxPacketSize;

        return kStatus_USB_Success;
    }
    else
    {
        return kStatus_USB_Error; /* there is no data to send */
    }
}

void USB_HostHidGenericTask(void *param)
{
    usb_status_t status;
    usb_host_hid_descriptor_t *hidDescriptor;
    uint32_t hidReportLength = 0;
    uint8_t *descriptor;
    uint32_t endPosition;
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;

    /* device state changes, process once for each state */
    if (genericInstance->deviceState != genericInstance->prevState)
    {
        genericInstance->prevState = genericInstance->deviceState;
        switch (genericInstance->deviceState)
        {
            case kStatus_DEV_Idle:
                break;

            case kStatus_DEV_Attached: /* deivce is attached and numeration is done */
                genericInstance->runState = kRunSetInterface;
                if (USB_HostHidInit(genericInstance->deviceHandle, &genericInstance->classHandle) !=
                    kStatus_USB_Success)
                {
                    usb_echo("host hid class initialize fail\r\n");
                }
                else
                {
                    usb_echo("hid generic attached\r\n");
                }
                genericInstance->sendIndex = 0;
                break;

            case kStatus_DEV_Detached: /* device is detached */
                genericInstance->deviceState = kStatus_DEV_Idle;
                genericInstance->runState = kRunIdle;
                USB_HostHidDeinit(genericInstance->deviceHandle, genericInstance->classHandle);
                genericInstance->classHandle = NULL;
                usb_echo("hid generic detached\r\n");
                break;

            default:
                break;
        }
    }

    /* run state */
    switch (genericInstance->runState)
    {
        case kRunIdle:
            break;

        case kRunSetInterface: /* 1. set hid interface */
            genericInstance->runWaitState = kRunWaitSetInterface;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidSetInterface(genericInstance->classHandle, genericInstance->interfaceHandle, 0,
                                        USB_HostHidControlCallback, genericInstance) != kStatus_USB_Success)
            {
                usb_echo("set interface error\r\n");
            }
            break;

        case kRunSetInterfaceDone: /* 2. hid set idle */
            genericInstance->inMaxPacketSize =
                USB_HostHidGetPacketsize(genericInstance->classHandle, USB_ENDPOINT_INTERRUPT, USB_IN);
            genericInstance->outMaxPacketSize =
                USB_HostHidGetPacketsize(genericInstance->classHandle, USB_ENDPOINT_INTERRUPT, USB_OUT);

            /* first: set idle */
            genericInstance->runWaitState = kRunWaitSetIdle;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidSetIdle(genericInstance->classHandle, 0, 0, USB_HostHidControlCallback, genericInstance) !=
                kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidSetIdle\r\n");
            }
            break;

        case kRunSetIdleDone: /* 3. hid get report descriptor */
            /* get report descriptor's length */
            hidDescriptor = NULL;
            descriptor = (uint8_t *)((usb_host_interface_t *)genericInstance->interfaceHandle)->interfaceExtension;
            endPosition = (uint32_t)descriptor +
                          ((usb_host_interface_t *)genericInstance->interfaceHandle)->interfaceExtensionLength;

            while ((uint32_t)descriptor < endPosition)
            {
                if (*(descriptor + 1) == USB_DESCRIPTOR_TYPE_HID) /* descriptor type */
                {
                    hidDescriptor = (usb_host_hid_descriptor_t *)descriptor;
                    break;
                }
                else
                {
                    descriptor = (uint8_t *)((uint32_t)descriptor + (*descriptor)); /* next descriptor */
                }
            }

            if (hidDescriptor != NULL)
            {
                usb_host_hid_class_descriptor_t *hidClassDescriptor;
                hidClassDescriptor = (usb_host_hid_class_descriptor_t *)&(hidDescriptor->bHidDescriptorType);
                for (uint8_t index = 0; index < hidDescriptor->bNumDescriptors; ++index)
                {
                    hidClassDescriptor += index;
                    if (hidClassDescriptor->bHidDescriptorType == USB_DESCRIPTOR_TYPE_HID_REPORT)
                    {
                        hidReportLength =
                            (uint16_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(hidClassDescriptor->wDescriptorLength);
                        break;
                    }
                }
            }
            if (hidReportLength > HID_GENERIC_IN_BUFFER_SIZE)
            {
                usb_echo("hid buffer is too small\r\n");
                genericInstance->runState = kRunIdle;
                return;
            }

            genericInstance->runWaitState = kRunWaitGetReportDescriptor;
            genericInstance->runState = kRunIdle;
            /* second: get report descriptor */
            USB_HostHidGetReportDescriptor(genericInstance->classHandle, genericInstance->genericInBuffer,
                                           hidReportLength, USB_HostHidControlCallback, genericInstance);
            break;

        case kRunGetReportDescriptorDone: /* 4. hid set protocol */
            genericInstance->runWaitState = kRunWaitSetProtocol;
            genericInstance->runState = kRunIdle;
            /* third: set protocol */
            if (USB_HostHidSetProtocol(genericInstance->classHandle, USB_HOST_HID_REQUEST_PROTOCOL_REPORT,
                                       USB_HostHidControlCallback, genericInstance) != kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidSetProtocol\r\n");
            }
            break;

        case kRunSetProtocolDone: /* 5. start to receive data and send data */
            genericInstance->runWaitState = kRunWaitDataReceived;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidRecv(genericInstance->classHandle, genericInstance->genericInBuffer,
                                genericInstance->inMaxPacketSize, USB_HostHidInCallback,
                                genericInstance) != kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidRecv\r\n");
            }
            status = USB_HostHidGenericPrepareOutData(genericInstance);
            if (status == kStatus_USB_Success)
            {
                if (USB_HostHidSend(genericInstance->classHandle, genericInstance->genericOutBuffer,
                                    genericInstance->outMaxPacketSize, USB_HostHidOutCallback,
                                    genericInstance) != kStatus_USB_Success)
                {
                    usb_echo("Error in USB_HostHidSend\r\n");
                }
            }
            break;

        case kRunDataReceived: /* process received data, receive next data and send next data */
            USB_HostHidGenericProcessBuffer(genericInstance);

            genericInstance->runWaitState = kRunWaitDataReceived;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidRecv(genericInstance->classHandle, genericInstance->genericInBuffer,
                                genericInstance->inMaxPacketSize, USB_HostHidInCallback,
                                genericInstance) != kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidRecv\r\n");
            }
            status = USB_HostHidGenericPrepareOutData(genericInstance);
            if (status == kStatus_USB_Success)
            {
                if (USB_HostHidSend(genericInstance->classHandle, genericInstance->genericOutBuffer,
                                    genericInstance->outMaxPacketSize, USB_HostHidOutCallback,
                                    genericInstance) != kStatus_USB_Success)
                {
                    usb_echo("Error in USB_HostHidSend\r\n");
                }
            }
            break;

        case kRunPrimeDataReceive: /* receive next data and send next data */
            genericInstance->runWaitState = kRunWaitDataReceived;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidRecv(genericInstance->classHandle, genericInstance->genericInBuffer,
                                genericInstance->inMaxPacketSize, USB_HostHidInCallback,
                                genericInstance) != kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidRecv\r\n");
            }
            status = USB_HostHidGenericPrepareOutData(genericInstance);
            if (status == kStatus_USB_Success)
            {
                if (USB_HostHidSend(genericInstance->classHandle, genericInstance->genericOutBuffer,
                                    genericInstance->outMaxPacketSize, USB_HostHidOutCallback,
                                    genericInstance) != kStatus_USB_Success)
                {
                    usb_echo("Error in USB_HostHidSend\r\n");
                }
            }
            break;

        default:
            break;
    }
}

usb_status_t USB_HostHidGenericEvent(usb_device_handle deviceHandle,
                                     usb_host_configuration_handle configurationHandle,
                                     uint32_t eventCode)
{
    uint32_t pid;
    uint32_t vid;
    usb_host_configuration_t *configuration;
    usb_host_interface_t *interface;
    uint32_t infoValue;
    usb_status_t status = kStatus_USB_Success;
    uint8_t interfaceIndex;
    uint8_t id;

    switch (eventCode)
    {
        case kUSB_HostEventAttach:
            /* judge whether is configurationHandle supported */
            configuration = (usb_host_configuration_t *)configurationHandle;
            for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex)
            {
                interface = &configuration->interfaceList[0];
                id = interface->interfaceDesc->bInterfaceClass;
                if (id != USB_HOST_HID_CLASS_CODE)
                {
                    continue;
                }
                id = interface->interfaceDesc->bInterfaceSubClass;
                if ((id != USB_HOST_HID_SUBCLASS_CODE_NONE) && (id != USB_HOST_HID_SUBCLASS_CODE_BOOT))
                {
                    continue;
                }
                USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &pid);
                USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &vid);
                if ((pid == 0x00a2) && (vid == 0x1fc9))
                {
                    if (g_HostHidGeneric.deviceState == kStatus_DEV_Idle)
                    {
                        /* the interface is supported by the application */
                        g_HostHidGeneric.genericInBuffer = s_GenericInBuffer;
                        g_HostHidGeneric.genericOutBuffer = s_GenericOutBuffer;
                        g_HostHidGeneric.deviceHandle = deviceHandle;
                        g_HostHidGeneric.interfaceHandle = interface;
                        g_HostHidGeneric.configHandle = configurationHandle;
                        return kStatus_USB_Success;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            status = kStatus_USB_NotSupported;
            break;

        case kUSB_HostEventNotSupported:
            break;

        case kUSB_HostEventEnumerationDone:
            if (g_HostHidGeneric.configHandle == configurationHandle)
            {
                if ((g_HostHidGeneric.deviceHandle != NULL) && (g_HostHidGeneric.interfaceHandle != NULL))
                {
                    /* the device enumeration is done */
                    if (g_HostHidGeneric.deviceState == kStatus_DEV_Idle)
                    {
                        g_HostHidGeneric.deviceState = kStatus_DEV_Attached;

                        USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &infoValue);
                        usb_echo("hid generic attached:pid=0x%x", infoValue);
                        USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &infoValue);
                        usb_echo("vid=0x%x ", infoValue);
                        USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
                        usb_echo("address=%d\r\n", infoValue);
                    }
                    else
                    {
                        usb_echo("not idle generic instance\r\n");
                        status = kStatus_USB_Error;
                    }
                }
            }
            break;

        case kUSB_HostEventDetach:
            if (g_HostHidGeneric.configHandle == configurationHandle)
            {
                /* the device is detached */
                g_HostHidGeneric.configHandle = NULL;
                if (g_HostHidGeneric.deviceState != kStatus_DEV_Idle)
                {
                    g_HostHidGeneric.deviceState = kStatus_DEV_Detached;
                }
            }
            break;

        default:
            break;
    }
    return status;
}

分析这部分源码可以得知每次执行USB_HostHidGenericTask函数时会在这个函数中进行设备状态的检测,刚插入设备时状态为USB_HostHidGenericTask,然后依次对hid设备进行设置,每次设置成功都会调用一个回调函数,改变当前设备状态,然后下次执行时根据设备的状态进行不同的操作。

当状态为kRunSetProtocolDone时,则意味着配置hid设备接口完成,可以进行收发数据数据。该例程中是执行了一次收发。我觉得这样用不太方便所以把收发单独提出重新封装了一层。

接下来看我封装的源码

host_hid_generic.c
/*分别修改了以下几个函数*/

/*! 发送数据的回调函数 !*/
static void USB_HostHidOutCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{ /* NULL */
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;
   // usb_echo("send back %d\r\n", dataLength);
    if(status == kStatus_USB_Success)
    {
        genericInstance->runState = kRunDataReceived; /* go to process data */
    }
    
    //usb_echo("send back %d\r\n", dataLength);
    
}


/*! 接收数据的回调函数 !*/
static void USB_HostHidInCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;

   //usb_echo("thit is usb_host_hidinCallback runwstate %d\r\n", genericInstance->runState);
    //if (genericInstance->runWaitState == kRunWaitDataReceived)
    //{
         //usb_echo("this is status is %d\r\n", status);
        if (status == kStatus_USB_Success)
        {
            //usb_echo("go to process data\r\n");
            genericInstance->runState = kRunDataDone; /* go to process data */
        }
        else
        {
            if (genericInstance->deviceState == kStatus_DEV_Attached)
            {
                genericInstance->runState = kRunPrimeDataReceive; /* go to prime next receiving */
            }
        }
    //}
}

/*! hid任务轮询函数 !*/
usb_status_t USB_HostHidGenericTask(void *param)
{
    //usb_status_t status;
    usb_host_hid_descriptor_t *hidDescriptor;
    uint32_t hidReportLength = 0;
    uint8_t *descriptor;
    uint32_t endPosition;
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;

    /* device state changes, process once for each state */
    if (genericInstance->deviceState != genericInstance->prevState)
    {
        genericInstance->prevState = genericInstance->deviceState;
        switch (genericInstance->deviceState)
        {
            case kStatus_DEV_Idle:
                break;

            case kStatus_DEV_Attached: /* deivce is attached and numeration is done */
                genericInstance->runState = kRunSetInterface;
                if (USB_HostHidInit(genericInstance->deviceHandle, &genericInstance->classHandle) !=
                    kStatus_USB_Success)
                {
                    usb_echo("host hid class initialize fail\r\n");
                }
                else
                {
                    usb_echo("hid generic attached\r\n");
                }
                
                break;

            case kStatus_DEV_Detached: /* device is detached */
                genericInstance->deviceState = kStatus_DEV_Idle;
                genericInstance->runState = kRunIdle;
                USB_HostHidDeinit(genericInstance->deviceHandle, genericInstance->classHandle);
                genericInstance->classHandle = NULL;
                usb_echo("hid generic detached\r\n");
                break;

            default:
                break;
        }
    }

    //usb_echo("genericInstance run state is %d\r\n", genericInstance->runState);
    /* run state */
    switch (genericInstance->runState)
    {
        case kRunIdle:
            break;

        case kRunSetInterface: /* 1. set hid interface */
            //usb_echo("this is kRunsetInterface\r\n");
            genericInstance->runWaitState = kRunWaitSetInterface;
            genericInstance->runState = kRunIdle;
        
       
            if (USB_HostHidSetInterface(genericInstance->classHandle, genericInstance->interfaceHandle, 0,
                                        USB_HostHidControlCallback, genericInstance) != kStatus_USB_Success)
            {
                usb_echo("set interface error\r\n");
            }
          
            break;

        case kRunSetInterfaceDone: /* 2. hid set idle */
            genericInstance->inMaxPacketSize =
                USB_HostHidGetPacketsize(genericInstance->classHandle, USB_ENDPOINT_INTERRUPT, USB_IN);
            genericInstance->outMaxPacketSize =
                USB_HostHidGetPacketsize(genericInstance->classHandle, USB_ENDPOINT_INTERRUPT, USB_OUT);

            /* first: set idle */
            genericInstance->runWaitState = kRunWaitSetIdle;
            genericInstance->runState = kRunIdle;
            if (USB_HostHidSetIdle(genericInstance->classHandle, 0, 0, USB_HostHidControlCallback, genericInstance) !=
                kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidSetIdle\r\n");
            }
            break;

        case kRunSetIdleDone: /* 3. hid get report descriptor */
            /* get report descriptor's length */
            hidDescriptor = NULL;
            descriptor = (uint8_t *)((usb_host_interface_t *)genericInstance->interfaceHandle)->interfaceExtension;
            endPosition = (uint32_t)descriptor +
                          ((usb_host_interface_t *)genericInstance->interfaceHandle)->interfaceExtensionLength;

            while ((uint32_t)descriptor < endPosition)
            {
                if (*(descriptor + 1) == USB_DESCRIPTOR_TYPE_HID) /* descriptor type */
                {
                    hidDescriptor = (usb_host_hid_descriptor_t *)descriptor;
                    break;
                }
                else
                {
                    descriptor = (uint8_t *)((uint32_t)descriptor + (*descriptor)); /* next descriptor */
                }
            }

            if (hidDescriptor != NULL)
            {
                usb_host_hid_class_descriptor_t *hidClassDescriptor;
                hidClassDescriptor = (usb_host_hid_class_descriptor_t *)&(hidDescriptor->bHidDescriptorType);
                for (uint8_t index = 0; index < hidDescriptor->bNumDescriptors; ++index)
                {
                    hidClassDescriptor += index;
                    if (hidClassDescriptor->bHidDescriptorType == USB_DESCRIPTOR_TYPE_HID_REPORT)
                    {
                        hidReportLength =
                            (uint16_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(hidClassDescriptor->wDescriptorLength);
                        break;
                    }
                }
            }
            if (hidReportLength > HID_GENERIC_IN_BUFFER_SIZE)
            {
                usb_echo("hid buffer is too small\r\n");
                genericInstance->runState = kRunIdle;
            }

            genericInstance->runWaitState = kRunWaitGetReportDescriptor;
            genericInstance->runState = kRunIdle;
            /* second: get report descriptor */
            USB_HostHidGetReportDescriptor(genericInstance->classHandle, genericInstance->genericInBuffer,
                                           hidReportLength, USB_HostHidControlCallback, genericInstance);
            break;

        case kRunGetReportDescriptorDone: /* 4. hid set protocol */
            genericInstance->runWaitState = kRunWaitSetProtocol;
            genericInstance->runState = kRunIdle;
            /* third: set protocol */
            if (USB_HostHidSetProtocol(genericInstance->classHandle, USB_HOST_HID_REQUEST_PROTOCOL_REPORT,
                                       USB_HostHidControlCallback, genericInstance) != kStatus_USB_Success)
            {
                usb_echo("Error in USB_HostHidSetProtocol\r\n");
            }
            break;
        case kRunSetProtocolDone:
            return kStatus_USB_Success;
        default:
            break;
    }
    return kStatus_USB_Retry;
}

/*添加了以下函数*/

/*! 发送数据函数 !*/
usb_status_t USB_SendData(void *param, uint8_t *data, uint32_t datalen)
{
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;
    usb_status_t status;
    
    if(datalen > sizeof(testData) || datalen <= 0)
    {
        usb_echo("datalen is error\r\n");
        return kStatus_USB_Error;
    }
    
    memset(testData, 0, sizeof(testData));
    memcpy(testData, data, datalen);
    
    status = USB_HostHidGenericPrepareOutData(genericInstance);
    if (status == kStatus_USB_Success)
    {
        if ((status = USB_HostHidSend(genericInstance->classHandle, genericInstance->genericOutBuffer,
                            genericInstance->outMaxPacketSize, USB_HostHidOutCallback,
                            genericInstance)) != kStatus_USB_Success)
        {
             usb_echo("Error in USB_HostHidSend\r\n");
        }
    }
    else
    {
        usb_echo("out data faile\r\n");
        return status;
    }
    
   // while(genericInstance->runState != kRunDataReceived)
   // {
        
   //     USB_HostHidGenericTask(param);
   // }
    
    return status;   
}

/*! 读数据函数 !*/
 usb_status_t USB_ReadData(void *param)
{
    usb_host_hid_generic_instance_t *genericInstance = (usb_host_hid_generic_instance_t *)param;   
    
    if (USB_HostHidRecv(genericInstance->classHandle, genericInstance->genericInBuffer,
                                genericInstance->inMaxPacketSize, USB_HostHidInCallback,
                                genericInstance) != kStatus_USB_Success)
    {
        usb_echo("Error in USB_HostHidRecv \r\n");
        return kStatus_USB_Error;
    }
      
    return kStatus_USB_Success; 
}


/* app.c        */
/*添加以下几个接口*/
usb_status_t USB_Send(void *param, uint8_t *data, uint32_t datalen)
{
    usb_status_t status;
    
    if((status = USB_SendData(&g_HostHidGeneric, data, datalen))== kStatus_USB_Success)
    {
        while(g_HostHidGeneric.runState != kRunDataReceived)
        {
            USB_HostTaskFn(g_HostHandle);
            USB_HostHidGenericTask(&g_HostHidGeneric);
        }
        g_HostHidGeneric.runState = kRunIdle;
        g_HostHidGeneric.sendIndex = 0;
    }
    
    return status;
}

uint32_t USB_Read(void *param, uint8_t *data)
{
    //uint8_t i;
    if(data == NULL)
        return 0;
    
    
    if(USB_ReadData(&g_HostHidGeneric) == kStatus_USB_Success)
    {
        while(g_HostHidGeneric.runState != kRunDataDone)
        {
            USB_HostTaskFn(g_HostHandle);
            USB_HostHidGenericTask(&g_HostHidGeneric);
        }
        
        g_HostHidGeneric.runState = kRunIdle;
        memcpy(data, g_HostHidGeneric.genericInBuffer, g_HostHidGeneric.inMaxPacketSize);

        //for(i=0; i<20; i++)
          // usb_echo("data[%d] = %x\r\n", i, data[i]);
        
        return g_HostHidGeneric.inMaxPacketSize;
    }
    
    return 0;
}

void USB_Hid_Init(void)
{
    uint8_t status;
    USB_HostApplicationInit();
    
    while (1)
    {
        USB_HostTaskFn(g_HostHandle);
        status  = USB_HostHidGenericTask(&g_HostHidGeneric);
        if(status == kStatus_USB_Success)
        {
            break;
        }
    }
}

app.c中添加的接口是阻塞的。

PS:本人对于USB协议也不是太了解,本程序完全是自己分析的,如有错误请指正。I will improve!!!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值