由于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!!!