MCUXpresso_MIMXRT1052xxxxB/boards/evkbimxrt1050/usb_examples/usb_device_phdc_weighscale_lite/bm/weighscale.c
2022-04-08 22:46:35 +08:00

1083 lines
45 KiB
C

/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017, 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdbool.h>
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"
#include "usb_device_phdc.h"
#include "usb_device_ch9.h"
#include "usb_device_descriptor.h"
#include "ieee11073_timer.h"
#include "ieee11073_types.h"
#include "ieee11073_agent.h"
#include "usb_shim_agent.h"
#include "weighscale.h"
#include "fsl_device_registers.h"
#include "fsl_common.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
#include "fsl_sysmpu.h"
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#include "usb_phy.h"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
void BOARD_InitHardware(void);
void USB_DeviceClockInit(void);
void USB_DeviceIsrEnable(void);
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle);
#endif
static void APP_WeightScaleSendData(void *handle, weightscale_measurement_struct_t *measurementData);
static usb_status_t USB_DeviceWeightScaleSetConfigure(usb_device_handle handle, uint8_t configure);
static usb_status_t USB_DeviceWeightScaleClassRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint8_t **buffer,
uint32_t *length);
static usb_status_t USB_DeviceWeightScaleInterruptInCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam);
static usb_status_t USB_DeviceWeightScaleBulkInCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam);
static usb_status_t USB_DeviceWeightScaleBulkOutCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam);
/*******************************************************************************
* Variables
******************************************************************************/
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_SetupOutBuffer[8];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint32_t s_RecvDataBuffer[(APDU_MAX_BUFFER_SIZE + 3) / 4];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_PhdcClassBuffer[4];
/*! @brief agent instance */
usb_shim_agent_struct_t g_shimAgent;
/*! @brief scan report number */
volatile uint16_t scanReportNumber = 0U;
/*! @brief application event */
volatile uint8_t appEvent = APP_EVENT_UNDEFINED;
/*! @brief the message of measurement data */
weightscale_measurement_struct_t measurement = {
{
/* Simple-Nu-Observed-Value = 76.2 (kg) 76.0 (kg) */
0x02FAU,
0x02F8U,
},
{
/* Simple-Nu-Observed-Value = 24.3 (kg/m2) 24.2 (kg/m2) */
0x00F3U,
0x00F2U,
},
};
/*! @brief association request data to send */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t g_associationRequestData[ASSOCIATION_REQUEST_LENGTH] = {
0xE2U, 0x00U, /* APDU CHOICE Type (AarqApdu) */
0x00U, 0x32U, /* CHOICE.length = 50 */
0x80U, 0x00U, 0x00U, 0x00U, /* assoc-version */
0x00U, 0x01U, 0x00U, 0x2AU, /* data-proto-list.count = 1 | length = 42 */
0x50U, 0x79U, /* data-proto-id = 20601 */
0x00U, 0x26U, /* data-proto-info length = 38 */
0x80U, 0x00U, 0x00U, 0x00U, /* protocolVersion */
0xA0U, 0x00U, /* encoding rules = MDER or PER */
0x80U, 0x00U, 0x00U, 0x00U, /* nomenclatureVersion */
0x00U, 0x00U, 0x00U, 0x00U, /* functionalUnits no Test Association capabilities */
0x00U, 0x80U, 0x00U, 0x00U, /* systemType = sys-type-agent */
0x00U, 0x08U, /* system-id length = 8 and value (manufacturer- and device- specific) */
0x11U, 0x22U, 0x33U, 0x44U, 0x55U, 0x66U, 0x77U, 0x88U, 0x40U, 0x00U, /* dev-config-id extended configuration */
0x00U, 0x01U, /* data-req-mode-flags */
0x01U, 0x00U, /* data-req-init-agent-count, data-req-init-manager-count */
0x00U, 0x00U, 0x00U, 0x00U /* optionList.count = 0 | optionList.length = 0 */
};
/*! @brief remote operation invoke event report configuration data */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t g_roivEventRepostConfigurationData[EVENT_REPORT_CONFIGURATION_LENGTH] = {
0xE7U, 0x00U, /* APDU CHOICE Type (PrstApdu) */
0x00U, 0xA2U, /* CHOICE.length = 162 */
0x00U, 0xA0U, /* OCTET STRING.length = 160 */
0x12U, 0x35U, /* invoke-id = 0x1235 (start of DataApdu. MDER encoded.) */
0x01U, 0x01U, /* CHOICE(Remote Operation Invoke | Confirmed Event Report) */
0x00U, 0x9AU, /* CHOICE.length = 154 */
0x00U, 0x00U, /* obj-handle = 0 (MDS object) */
0xFFU, 0xFFU, 0xFFU, 0xFFU, /* event-time = 0xFFFFFFFF */
0x0DU, 0x1CU, /* event-type = MDC_NOTI_CONFIG */
0x00U, 0x90U, /* event-info.length = 144 (start of ConfigReport) */
0x40U, 0x00U, /* config-report-id */
0x00U, 0x03U, /* config-obj-list.count = 3 Measurement objects will be announced */
0x00U, 0x8AU, /* config-obj-list.length = 138 */
0x00U, 0x06U, /* obj-class = MDC_MOC_VMO_METRIC_NU */
0x00U, 0x01U, /* obj-handle = 1 (->1st Measurement is body weight) */
0x00U, 0x04U, /* attributes.count = 4 */
0x00U, 0x24U, /* attributes.length = 36 */
0x09U, 0x2FU, /* attribute-id = MDC_ATTR_ID_TYPE */
0x00U, 0x04U, /* attribute-value.length = 4 */
0x00U, 0x02U, 0xE1U, 0x40U, /* MDC_PART_SCADA | MDC_MASS_BODY_ACTUAL */
0x0AU, 0x46U, /* attribute-id = MDC_ATTR_METRIC_SPEC_SMALL */
0x00U, 0x02U, /* attribute-value.length = 2 */
0xF0U, 0x40U, /* intermittent, stored data, upd & msmt aperiodic, agent init, measured */
0x09U, 0x96U, /* attribute-id = MDC_ATTR_UNIT_CODE */
0x00U, 0x02U, /* attribute-value.length = 2 */
0x06U, 0xC3U, /* MDC_DIM_KILO_G */
0x0AU, 0x55U, /* attribute-id = MDC_ATTR_ATTRIBUTE_VAL_MAP */
0x00U, 0x0CU, /* attribute-value.length = 12 */
0x00U, 0x02U, /* AttrValMap.count = 2 */
0x00U, 0x08U, /* AttrValMap.length = 8 */
0x0AU, 0x56U, 0x00U, 0x04U, /* MDC_ATTR_NU_VAL_OBS_SIMP | value length = 4 */
0x09U, 0x90U, 0x00U, 0x08U, /* MDC_ATTR_TIME_STAMP_ABS | value length = 8 */
0x00U, 0x06U, /* obj-class = MDC_MOC_VMO_METRIC_NU */
0x00U, 0x02U, /* obj-handle = 2 (-> 2nd Measurement is body height) */
0x00U, 0x04U, /* attributes.count = 4 */
0x00U, 0x24U, /* attributes.length = 36 */
0x09U, 0x2FU, /* attribute-id = MDC_ATTR_ID_TYPE */
0x00U, 0x04U, /* attribute-value.length = 4 */
0x00U, 0x02U, 0xE1U, 0x44U, /* MDC_PART_SCADA | MDC_LEN_BODY_ACTUAL */
0x0AU, 0x46U, /* attribute-id = MDC_ATTR_METRIC_SPEC_SMALL */
0x00U, 0x02U, /* attribute-value.length = 2 */
0xF0U, 0x48U, /* intermittent, stored data, upd & msmt aperiodic, agent init, manual */
0x09U, 0x96U, /* attribute-id = MDC_ATTR_UNIT_CODE */
0x00U, 0x02U, /* attribute-value.length = 2 */
0x05U, 0x11U, /* MDC_DIM_CENTI_M */
0x0AU, 0x55U, /* attribute-id = MDC_ATTR_ATTRIBUTE_VAL_MAP */
0x00U, 0x0CU, /* attribute-value.length = 12 */
0x00U, 0x02U, /* AttrValMap.count = 2 */
0x00U, 0x08U, /* AttrValMap.length = 8 */
0x0AU, 0x56U, 0x00U, 0x04U, /* MDC_ATTR_NU_VAL_OBS_SIMP, 4 */
0x09U, 0x90U, 0x00U, 0x08U, /* MDC_ATTR_TIME_STAMP_ABS, 8 */
0x00U, 0x06U, /* obj-class = MDC_MOC_VMO_METRIC_NU */
0x00U, 0x03U, /* obj-handle = 3 (-> 3rd Measurement is body mass index) */
0x00U, 0x05U, /* attributes.count = 5 */
0x00U, 0x2AU, /* attributes.length = 42 */
0x09U, 0x2FU, /* attribute-id = MDC_ATTR_ID_TYPE */
0x00U, 0x04U, /* attribute-value.length = 4 */
0x00U, 0x02U, 0xE1U, 0x50U, /* MDC_PART_SCADA | MDC_RATIO_MASS_BODY_LEN_SQ */
0x0AU, 0x46U, /* attribute-id = MDC_ATTR_METRIC_SPEC_SMALL */
0x00U, 0x02U, /* attribute-value.length = 2 */
0xF0U, 0x42U, /* intermittent, stored data, upd & msmt aperiodic, agent init, calculated */
0x09U, 0x96U, /* attribute-id = MDC_ATTR_UNIT_CODE */
0x00U, 0x02U, /* attribute-value.length = 2 */
0x07U, 0xA0U, /* MDC_DIM_KG_PER_M_SQ */
0x0AU, 0x47U, /* attribute-id = MDC_ATTR_SOURCE_HANDLE_REF */
0x00U, 0x02U, /* attribute-value.length = 2 */
0x00U, 0x01U, /* reference handle = 1 */
0x0AU, 0x55U, /* attribute-id = MDC_ATTR_ATTRIBUTE_VAL_MAP */
0x00U, 0x0CU, /* attribute-value.length = 12 */
0x00U, 0x02U, /* AttrValMap.count = 2 */
0x00U, 0x08U, /* AttrValMap.length = 8 */
0x0AU, 0x56U, 0x00U, 0x04U, /* MDC_ATTR_NU_VAL_OBS_SIMP, 4 */
0x09U, 0x90U, 0x00U, 0x08U /* MDC_ATTR_TIME_STAMP_ABS, 8 */
};
/*! @brief remote operation response | Get with all MDS attributes */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t g_rorsCmipGetData[EVENT_RESPONSE_GET_LENGTH] = {
0xE7U, 0x00U, /* APDU CHOICE Type (PrstApdu) */
0x00U, 0x6EU, /* CHOICE.length = 110 */
0x00U, 0x6CU, /* OCTET STRING.length = 108 */
0x12U, 0x34U, /* invoke-id = 0x1234 (mirrored from request) */
0x02U, 0x03U, /* CHOICE (Remote Operation Response | Get) */
0x00U, 0x66U, /* CHOICE.length = 102 */
0x00U, 0x00U, /* handle = 0 (MDS object) */
0x00U, 0x06U, /* attribute-list.count = 6 */
0x00U, 0x60U, /* attribute-list.length = 96 */
0x0AU, 0x5AU, /* attribute id = MDC_ATTR_SYS_TYPE_SPEC_LIST */
0x00U, 0x08U, /* attribute-value.length = 8 */
0x00U, 0x01U, /* TypeVerList count = 1 */
0x00U, 0x04U, /* TypeVerList length = 4 */
0x10U, 0x0FU, /* type = MDC_DEV_SPEC_PROFILE_SCALE */
0x00U, 0x01U, /* version = version 1 of the specialization */
0x09U, 0x28U, /* attribute-id = MDC_ATTR_ID_MODEL */
0x00U, 0x1AU, /* attribute-value.length = 26 */
0x00U, 0x0AU, /* string length = 10 | Freescale\0 */
0x46U, 0x72U, 0x65U, 0x65U, 0x73U, 0x63U, 0x61U, 0x6CU, 0x65U, 0x00U, 0x00U, 0x0CU, /* string length = 12 |
WeightScale\0 */
0x57U, 0x65U, 0x69U, 0x67U, 0x68U, 0x74U, 0x53U, 0x63U, 0x61U, 0x6CU, 0x65U, 0x00U, 0x09U,
0x84U, /* attribute-id = MDC_ATTR_SYS_ID */
0x00U, 0x0AU, /* attribute-value.length = 10 */
0x00U, 0x08U, 0x11U, 0x22U, 0x33U, 0x44U, 0x55U, 0x66U, 0x77U, 0x88U, /* octet string length = 8 | EUI-64 */
0x0aU, 0x44U, /* attribute-id = MDC_ATTR_DEV_CONFIG_ID */
0x00U, 0x02U, /* attribute-value.length = 2 */
0x40U, 0x00U, /* dev-config-id = 16384 (extended-config-start) */
0x09U, 0x2DU, /* attribute-id = MDC_ATTR_ID_PROD_SPECN */
0x00U, 0x12U, /* attribute-value.length = 18 */
0x00U, 0x01U, /* ProductionSpec.count = 1 */
0x00U, 0x0EU, /* ProductionSpec.length = 14 */
0x00U, 0x01U, /* ProdSpecEntry.spec-type = 1 (serial-number) */
0x00U, 0x00U, /* ProdSpecEntry.component-id = 0 */
0x00U, 0x08U, 0x44U, 0x45U, /* string length = 8 | prodSpecEntry.prod-spec = DE124567 */
0x31U, 0x32U, 0x34U, 0x35U, 0x36U, 0x37U, 0x09U, 0x87U, /* attribute-id =MDC_ATTR_TIME_ABS */
0x00U, 0x08U, /* attribute-value.length = 8 */
0x20U, 0x07U, 0x02U, 0x01U, /* Absolute-Time-Stamp = 2007-02-01T12:05:0000 */
0x12U, 0x05U, 0x00U, 0x00};
/*! @brief measurements to send */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t g_eventReportData[EVENT_REPORT_DATA_LENGTH] = {
0xE7U, 0x00U, /* APDU CHOICE Type (PrstApdu) */
0x00U, 0x5AU, /* CHOICE.length = 90 */
0x00U, 0x58U, /* OCTET STRING.length = 88 */
0x12U, 0x36U, /* invoke-id = 0x1236 */
0x01U, 0x01U, /* CHOICE(Remote Operation Invoke | Confirmed Event Report) */
0x00U, 0x52U, /* CHOICE.length = 82 */
0x00U, 0x00U, /* obj-handle = 0 (MDS object) */
0x00U, 0x00U, 0x00U, 0x00U, /* event-time = 0 */
0x0DU, 0x1DU, /* event-type = MDC_NOTI_SCAN_REPORT_FIXED */
0x00U, 0x48U, /* event-info.length = 72 */
0xF0U, 0x00U, /* ScanReportInfoFixed.data-req-id = 0xF000 */
0x00U, 0x00U, /* ScanReportInfoFixed.scan-report-no = 0 */
0x00U, 0x04U, /* ScanReportInfoFixed.obs-scan-fixed.count = 4 */
0x00U, 0x40U, /* ScanReportInfoFixed.obs-scan-fixed.length = 64 */
0x00U, 0x01U, /* ScanReportInfoFixed.obs-scan-fixed.value[0].obj-handle = 1 */
0x00U, 0x0CU, /* ScanReportInfoFixed.obs-scan-fixed.value[0]. obs-val-data.length = 12 */
0xFFU, 0x00U, 0x02U, 0xFAU, /* Simple-Nu-Observed-Value = 76.2 (kg) */
0x20U, 0x07U, 0x12U, 0x06U, /* Absolute-Time-Stamp = 2007-12-06T12:10:0000 */
0x12U, 0x10U, 0x00U, 0x00U, 0x00U, 0x03U, /* ScanReportInfoFixed.obs-scan-fixed.value[1].obj-handle = 3 */
0x00U, 0x0CU, /* ScanReportInfoFixed.obs-scan-fixed.value[1]. obs-val-data.length = 12 */
0xFFU, 0x00U, 0x00U, 0xF3U, /* Simple-Nu-Observed-Value = 24.3 (kg/m2) */
0x20U, 0x07U, 0x12U, 0x06U, /* Absolute-Time-Stamp = 2007-12-06T12:10:0000 */
0x12U, 0x10U, 0x00U, 0x00U, 0x00U, 0x01U, /* ScanReportInfoFixed.obs-scan-fixed.value[0].obj-handle = 1 */
0x00U, 0x0CU, /* ScanReportInfoFixed.obs-scan-fixed.value[0]. obs-val-data.length = 12 */
0xFFU, 0x00U, 0x02U, 0xF8U, /* Simple-Nu-Observed-Value = 76.0 (kg) */
0x20U, 0x07U, 0x12U, 0x06U, /* Absolute-Time-Stamp = 2007-12-06T20:05:0000 */
0x20U, 0x05U, 0x00U, 0x00U, 0x00U, 0x03U, /* ScanReportInfoFixed.obs-scan-fixed.value[1].obj-handle = 3 */
0x00U, 0x0CU, /* ScanReportInfoFixed.obs-scan-fixed.value[1]. obs-val-data.length = 12 */
0xFFU, 0x00U, 0x00U, 0xF2U, /* Simple-Nu-Observed-Value = 24.2 (kg/m2) */
0x20U, 0x07U, 0x12U, 0x06U, /* Absolute-Time-Stamp = 2007-12-06T20:05:0000 */
0x20U, 0x05U, 0x00U, 0x00U};
/*******************************************************************************
* Code
******************************************************************************/
void USB_OTG1_IRQHandler(void)
{
USB_DeviceEhciIsrFunction(g_shimAgent.deviceHandle);
}
void USB_OTG2_IRQHandler(void)
{
USB_DeviceEhciIsrFunction(g_shimAgent.deviceHandle);
}
void USB_DeviceClockInit(void)
{
usb_phy_config_struct_t phyConfig = {
BOARD_USB_PHY_D_CAL,
BOARD_USB_PHY_TXCAL45DP,
BOARD_USB_PHY_TXCAL45DM,
};
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);
}
void USB_DeviceIsrEnable(void)
{
uint8_t irqNumber;
uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
irqNumber = usbDeviceEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0];
/* Install isr, set priority, and enable IRQ. */
NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
EnableIRQ((IRQn_Type)irqNumber);
}
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle)
{
USB_DeviceEhciTaskFunction(deviceHandle);
}
#endif
/*!
* @brief medical callback.
* This function handles the callback of medical system.
*
* @param handle the handle points to agent handle.
* @param eventType the event type.
* @param data the pointer to callback data.
*
* @return None.
*/
void AGENT_MedicalCallback(void *handle, uint8_t eventType, uint8_t *data)
{
switch (eventType)
{
case AGENT_EVENT_CONNECTED:
scanReportNumber = 0U;
appEvent = APP_EVENT_SEND_ASSOCIATION_REQUEST;
break;
case AGENT_EVENT_ACCEPTED_UNKNOWN_CONFIG_AARQ:
appEvent = APP_EVENT_SEND_DEVICE_CONFIGURATION;
break;
case AGENT_EVENT_REJECTED_AARQ:
case AGENT_EVENT_ACCEPTED_AARQ:
case AGENT_EVENT_UNSUPPORTED_CONFIG:
case AGENT_EVENT_ACCEPTED_CONFIG:
break;
case AGENT_EVENT_RECV_ROIV_CMIP_GET:
{
/* The invokeID is mirrored from request */
#if (ENDIANNESS == USB_BIG_ENDIAN)
g_rorsCmipGetData[7] = *data;
g_rorsCmipGetData[6] = *((uint8_t *)(data + 1U));
#else
g_rorsCmipGetData[6] = *data;
g_rorsCmipGetData[7] = *((uint8_t *)(data + 1U));
#endif
appEvent = APP_EVENT_SEND_MDS_OBJECT;
}
break;
case AGENT_EVENT_RORS_CMIP_GET_SENT:
case AGENT_EVENT_MEASUREMENT_SENT:
/* update the measurement data */
measurement.weight[0U]++;
measurement.weight[1U]++;
/* The weighs will be less than 100kg */
measurement.weight[0U] %= 1000U;
measurement.weight[1U] %= 1000U;
measurement.bodyMassIndex[0U]++;
measurement.bodyMassIndex[1U]++;
/* The body mass index will be less than 50 kg/m2 */
measurement.bodyMassIndex[0U] %= 500U;
measurement.bodyMassIndex[1U] %= 500U;
appEvent = APP_EVENT_SEND_MEASUREMENT_DATA;
break;
default:
break;
}
}
/*!
* @brief send weight scale data.
* This function is called to send the weight data to the host.
*
* @param handle the handle points to agent handle.
* @param measurement measurement data to send.
*/
static void APP_WeightScaleSendData(void *handle, weightscale_measurement_struct_t *measurementData)
{
/* second offset */
static uint8_t secondOffset = 0U;
/* minute offset */
static uint8_t minuteOffset[4U] = {0U, 0U, 5U, 5U};
/* hour offset */
static uint8_t hourOffset[4U] = {2U, 2U, 2U, 2U};
/* update scan report number */
uint8_t *scanReportTemp = (uint8_t *)&g_eventReportData[24U];
USB_SHORT_TO_BIG_ENDIAN_ADDRESS(scanReportNumber, scanReportTemp);
secondOffset++;
/* update absolute time data */
for (uint16_t timeOffset = 0U; timeOffset < 4U; timeOffset++)
{
absolute_time_t *absoluteTime = (absolute_time_t *)&g_eventReportData[38U + timeOffset * 16U];
if (!(secondOffset % 10U))
{
/* update the time in second */
secondOffset = 0U;
absoluteTime->second += 7U;
}
else
{
absoluteTime->second += 1U;
}
if (0x60U <= absoluteTime->second)
{
/* update the time in minute */
minuteOffset[timeOffset]++;
absoluteTime->second = 0U;
if (!(minuteOffset[timeOffset] % 10U))
{
minuteOffset[timeOffset] = 0U;
absoluteTime->minute += 7U;
}
else
{
absoluteTime->minute += 1U;
}
}
if (0x60U <= absoluteTime->minute)
{
/* update the time in hour */
hourOffset[timeOffset]++;
absoluteTime->minute = 0U;
if (!(hourOffset[timeOffset] % 10U))
{
hourOffset[timeOffset] = 0U;
absoluteTime->hour += 7U;
}
else
{
absoluteTime->hour += 1U;
}
}
if (0x24 <= absoluteTime->hour)
{
absoluteTime->hour = 0U;
}
}
for (uint8_t dataOffset = 0U; dataOffset < 4U; dataOffset++)
{
uint8_t dataIndex = (uint8_t)(dataOffset >> 1U);
uint8_t *dataTemp = (uint8_t *)&g_eventReportData[36U + dataOffset * 16U];
if ((dataOffset & 0x01U) == 0U)
{
/* update weight data */
USB_SHORT_TO_BIG_ENDIAN_ADDRESS(measurementData->weight[dataIndex], dataTemp);
}
else
{
/* update BMI data */
USB_SHORT_TO_BIG_ENDIAN_ADDRESS(measurementData->bodyMassIndex[dataIndex], dataTemp);
}
}
if (kStatus_USB_Success == USB_ShimAgentSendData(handle, AGENT_SEND_DATA_QOS, (uint8_t *)(&g_eventReportData[0]),
EVENT_REPORT_DATA_LENGTH))
{
/* update the scan report number */
scanReportNumber++;
}
}
/*!
* @brief device callback function.
* This function handles the usb standard event. more information, please refer to usb spec chapter 9.
*
* @param handle The USB device handle.
* @param event The USB device event type.
* @param param The parameter of the device specific request.
*
* @return kStatus_USB_Success or error.
*/
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
{
usb_status_t error = kStatus_USB_InvalidRequest;
uint8_t *temp8 = (uint8_t *)param;
switch (event)
{
case kUSB_DeviceEventBusReset:
{
g_shimAgent.attach = 0U;
g_shimAgent.currentConfig = 0U;
error = kStatus_USB_Success;
USB_DeviceControlPipeInit(handle);
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
/* Get USB speed to configure the device, including max packet size and interval of the endpoints. */
if (kStatus_USB_Success == USB_DeviceGetStatus(handle, kUSB_DeviceStatusSpeed, &g_shimAgent.speed))
{
USB_DeviceSetSpeed(g_shimAgent.speed);
}
#endif
/* save endpoint info */
if (USB_SPEED_HIGH == g_shimAgent.speed)
{
g_shimAgent.bulkOutData.epMaxPacketSize = HS_USB_PHDC_BULK_ENDPOINT_OUT_PACKET_SIZE;
}
else
{
g_shimAgent.bulkOutData.epMaxPacketSize = FS_USB_PHDC_BULK_ENDPOINT_OUT_PACKET_SIZE;
}
g_shimAgent.bulkOutData.epNumber = USB_PHDC_BULK_ENDPOINT_OUT;
g_shimAgent.bulkOutData.transferCount = 0U;
g_shimAgent.bulkOutData.recvData.transferSize = 0U;
g_shimAgent.bulkOutData.recvData.buffer = NULL;
/* bulk in endpoint information */
g_shimAgent.bulkInData.epNumber = USB_PHDC_BULK_ENDPOINT_IN;
g_shimAgent.bulkInData.seller = 0U;
g_shimAgent.bulkInData.buyer = 0U;
/* interrupt in endpoint information */
g_shimAgent.interruptInData.epNumber = USB_PHDC_INTERRUPT_ENDPOINT_IN;
g_shimAgent.interruptInData.seller = 0U;
g_shimAgent.interruptInData.buyer = 0U;
/* no endpoint has data */
g_shimAgent.endpointsHaveData = 0U;
#if META_DATA_MESSAGE_PREAMBLE_IMPLEMENTED
/* disable meta-data message preamble feature */
g_shimAgent.isMetaDataMessagePreambleEnabled = 0U;
/* initialize the number of transfer followed preamble message */
g_shimAgent.numberTransferBulkOut = 0U;
g_shimAgent.numberTransferBulkIn = 0U;
#endif
appEvent = APP_EVENT_UNDEFINED;
AGENT_SetAgentState((void *)handle, AGENT_STATE_DISCONNECTED);
}
break;
case kUSB_DeviceEventSetConfiguration:
if (0U == (*temp8))
{
g_shimAgent.attach = 0;
g_shimAgent.currentConfig = 0U;
error = kStatus_USB_Success;
}
else if (USB_PHDC_WEIGHT_SCALE_CONFIGURE_INDEX == (*temp8))
{
g_shimAgent.attach = 1U;
g_shimAgent.currentConfig = *temp8;
USB_DeviceWeightScaleSetConfigure(handle, (*temp8));
/* send the first NULL data to establish a connection between the device and host */
USB_ShimAgentSendData((void *)handle, AGENT_SEND_DATA_QOS, NULL, 0U);
/* prepare for the first receiving */
error = USB_DeviceRecvRequest(handle, g_shimAgent.bulkOutData.epNumber, g_shimAgent.recvDataBuffer,
g_shimAgent.bulkOutData.epMaxPacketSize);
}
else
{
/* no action, return kStatus_USB_InvalidRequest. */
}
break;
case kUSB_DeviceEventSetInterface:
error = kStatus_USB_Success;
break;
default:
break;
}
return error;
}
/*!
* @brief device set configuration.
* This function set configuration for the device.
*
* @param handle The USB device handle.
* @param configure configure index.
*
* @return kStatus_USB_Success or error.
*/
static usb_status_t USB_DeviceWeightScaleSetConfigure(usb_device_handle handle, uint8_t configure)
{
usb_device_endpoint_init_struct_t epInitStruct;
usb_device_endpoint_callback_struct_t epCallback;
if (USB_PHDC_WEIGHT_SCALE_CONFIGURE_INDEX == configure)
{
/* InterruptIN ep */
epCallback.callbackFn = USB_DeviceWeightScaleInterruptInCallback;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0U;
epInitStruct.transferType = USB_ENDPOINT_INTERRUPT;
epInitStruct.endpointAddress =
USB_PHDC_INTERRUPT_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == g_shimAgent.speed)
{
epInitStruct.maxPacketSize = HS_USB_PHDC_INTERRUPT_ENDPOINT_IN_PACKET_SIZE;
epInitStruct.interval = HS_USB_PHDC_INTERRUPT_ENDPOINT_IN_INTERVAL;
}
else
{
epInitStruct.maxPacketSize = FS_USB_PHDC_INTERRUPT_ENDPOINT_IN_PACKET_SIZE;
epInitStruct.interval = FS_USB_PHDC_INTERRUPT_ENDPOINT_IN_INTERVAL;
}
USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback);
/* BulkOUT ep */
epCallback.callbackFn = USB_DeviceWeightScaleBulkOutCallback;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0U;
epInitStruct.interval = 0U;
epInitStruct.transferType = USB_ENDPOINT_BULK;
epInitStruct.endpointAddress =
USB_PHDC_BULK_ENDPOINT_OUT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == g_shimAgent.speed)
{
epInitStruct.maxPacketSize = HS_USB_PHDC_BULK_ENDPOINT_OUT_PACKET_SIZE;
}
else
{
epInitStruct.maxPacketSize = FS_USB_PHDC_BULK_ENDPOINT_OUT_PACKET_SIZE;
}
USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback);
/* BulkIN ep */
epCallback.callbackFn = USB_DeviceWeightScaleBulkInCallback;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0U;
epInitStruct.interval = 0U;
epInitStruct.transferType = USB_ENDPOINT_BULK;
epInitStruct.endpointAddress =
USB_PHDC_BULK_ENDPOINT_IN | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == g_shimAgent.speed)
{
epInitStruct.maxPacketSize = HS_USB_PHDC_BULK_ENDPOINT_IN_PACKET_SIZE;
}
else
{
epInitStruct.maxPacketSize = FS_USB_PHDC_BULK_ENDPOINT_IN_PACKET_SIZE;
}
USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback);
}
return kStatus_USB_Error;
}
/*!
* @brief interrupt in callback function.
* This function is called when the interrupt in transfer is done.
*
* @param handle The USB device handle.
* @param message The result of the interrupt in transfer.
* @param callbackParam The parameter for the callback function.
*
* @return kStatus_USB_Success or error.
*/
static usb_status_t USB_DeviceWeightScaleInterruptInCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
usb_status_t error = kStatus_USB_Error;
/* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
if ((NULL == message) || (USB_CANCELLED_TRANSFER_LENGTH == message->length))
{
error = kStatus_USB_Error;
}
else
{
error = USB_ShimAgentSendComplete((void *)handle, USB_PHDC_EVENT_INTERRUPT_IN_SEND_COMPLETE, message);
}
return error;
}
/*!
* @brief bulk in callback function.
* This function is called when the bulk in transfer is done.
*
* @param handle The USB device handle.
* @param message The result of the bulk in transfer.
* @param callbackParam The parameter for the callback function.
*
* @return kStatus_USB_Success or error.
*/
static usb_status_t USB_DeviceWeightScaleBulkInCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
usb_status_t error = kStatus_USB_Error;
/* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
if ((NULL == message) || (USB_CANCELLED_TRANSFER_LENGTH == message->length))
{
error = kStatus_USB_Error;
}
else
{
error = USB_ShimAgentSendComplete((void *)handle, USB_PHDC_EVENT_BULK_IN_SEND_COMPLETE, message);
}
return error;
}
/*!
* @brief bulk out callback function.
* This function is called when the bulk out transfer is done.
*
* @param handle The USB device handle.
* @param message The result of the bulk out transfer.
* @param callbackParam The parameter for the callback function.
*
* @return kStatus_USB_Success or error.
*/
static usb_status_t USB_DeviceWeightScaleBulkOutCallback(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
return USB_ShimAgentRecvComplete((void *)handle, message);
}
/*!
* @brief Get the setup packet buffer.
*
* The function is used to get the setup packet buffer to save the setup packet data.
*
* @param handle The device handle.
* @param setupBuffer It is an OUT parameter, return the setup buffer address to the caller.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
{
static uint32_t phdcWeighscaleSetup[2U];
if (NULL == setupBuffer)
{
return kStatus_USB_InvalidParameter;
}
*setupBuffer = (usb_setup_struct_t *)&phdcWeighscaleSetup;
return kStatus_USB_Success;
}
/*!
* @brief Get the buffer to save the vendor specific data sent from host.
*
* The function is used to get the buffer to save the vendor specific data sent from host.
* The function will be called when the device receives a setup packet, and the host needs to send data to the device in
* the data stage.
*
* @param handle The device handle.
* @param setup The setup packet buffer address.
* @param length Pass the length the host needs to sent.
* @param buffer It is an OUT parameter, return the data buffer address to save the host's data.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetVendorReceiveBuffer(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
return kStatus_USB_Error;
}
/*!
* @brief Handle the vendor request.
*
* The function is used to handle the vendor request.
*
* @param handle The device handle.
* @param setup The setup packet buffer address.
* @param length It is an OUT parameter, return the data length need to be sent to host.
* @param buffer It is an OUT parameter, return the data buffer address.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceProcessVendorRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
return kStatus_USB_InvalidRequest;
}
/*!
* @brief Configure the device remote wakeup feature.
*#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || (defined(USB_DEVICE_CONFIG_LPCIP3511HS) &&
*(USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
* The function is used to configure the device remote wakeup feature, enable or disbale the remote wakeup feature.
*
* @param handle The device handle.
* @param enable The new feature value of the device remote wakeup, 0 - disable, 1 - enable.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
{
return kStatus_USB_InvalidRequest;
}
/*!
* @brief Configure a specified endpoint status.
*
* The function is used to configure a specified endpoint status, idle or halt.
*
* @param handle The device handle.
* @param endpointAddress The endpoint address, the BIT7 is the direction, 0 - USB_OUT, 1 - USB_IN.
* @param status The new status of the endpoint, 0 - idle, 1 - halt.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
{
if (status)
{
if ((USB_PHDC_INTERRUPT_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceStallEndpoint(handle, ep);
}
else if ((USB_PHDC_BULK_ENDPOINT_OUT == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceStallEndpoint(handle, ep);
}
else if ((USB_PHDC_BULK_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceStallEndpoint(handle, ep);
}
else
{
}
}
else
{
if ((USB_PHDC_INTERRUPT_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceUnstallEndpoint(handle, ep);
}
else if ((USB_PHDC_BULK_ENDPOINT_OUT == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceUnstallEndpoint(handle, ep);
}
else if ((USB_PHDC_BULK_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
return USB_DeviceUnstallEndpoint(handle, ep);
}
else
{
}
}
return kStatus_USB_InvalidRequest;
}
/*!
* @brief Get the buffer to save the class specific data sent from host.
*
* The function is used to get the buffer to save the class specific data sent from host.
* The function will be called when the device receives a setup packet, and the host needs to send data to the device in
* the data stage.
*
* @param handle The device handle.
* @param setup The setup packet buffer address.
* @param length Pass the length the host needs to sent.
* @param buffer It is an OUT parameter, return the data buffer address to save the host's data.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
if ((NULL == buffer) || ((*length) > sizeof(s_SetupOutBuffer)))
{
return kStatus_USB_InvalidRequest;
}
*buffer = s_SetupOutBuffer;
return kStatus_USB_Success;
}
/*!
* @brief Handle the class request.
*
* The function is used to handle the class request.
*
* @param handle The device handle.
* @param setup The setup packet buffer address.
* @param length It is an OUT parameter, return the data length need to be sent to host.
* @param buffer It is an OUT parameter, return the data buffer address.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
usb_status_t error = kStatus_USB_InvalidRequest;
if (USB_PHDC_WEIGHT_SCALE_INTERFACE_INDEX == setup->wIndex)
{
return USB_DeviceWeightScaleClassRequest(handle, setup, buffer, length);
}
else
{
}
return error;
}
/*!
* @brief device shim agent callback function.
* This function handles the PHDC class specified event.
*
* @param handle The USB class handle.
* @param event The USB device event type.
* @param param The parameter of the class specific event.
*
* @return kStatus_USB_Success or error.
*/
static usb_status_t USB_DeviceWeightScaleClassRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint8_t **buffer,
uint32_t *length)
{
usb_status_t error = kStatus_USB_InvalidRequest;
if (setup->wIndex != USB_PHDC_WEIGHT_SCALE_INTERFACE_INDEX)
{
return error;
}
switch (setup->bRequest)
{
case USB_DEVICE_PHDC_REQUEST_SET_FEATURE:
#if META_DATA_MESSAGE_PREAMBLE_IMPLEMENTED
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT)
&& (setup->wLength == 0U))
{
/* enable metadata feature */
g_shimAgent.isMetaDataMessagePreambleEnabled = 1U;
error = kStatus_USB_Success;
}
#else
/* respond the request with a stall */
error = kStatus_USB_InvalidRequest;
#endif
break;
case USB_DEVICE_PHDC_REQUEST_CLEAR_FEATURE:
#if META_DATA_MESSAGE_PREAMBLE_IMPLEMENTED
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT)
&& (setup->wLength == 0U))
{
/* disable metadata feature */
g_shimAgent.isMetaDataMessagePreambleEnabled = 0U;
error = kStatus_USB_Success;
}
#else
/* respond the request with a stall */
error = kStatus_USB_InvalidRequest;
#endif
break;
case USB_DEVICE_PHDC_REQUEST_GET_STATUS:
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
&& (setup->wLength <= 2U))
{
g_shimAgent.classBuffer[0] = ((uint8_t *)(&g_shimAgent.endpointsHaveData))[0];
g_shimAgent.classBuffer[1] = ((uint8_t *)(&g_shimAgent.endpointsHaveData))[1];
*buffer = g_shimAgent.classBuffer;
*length = 2U;
error = kStatus_USB_Success;
}
break;
default:
break;
}
return error;
}
/*!
* @brief application initialization.
* This function is the entry for the application (or other usage)
*
* @return None.
*/
static void USB_DeviceApplicationInit(void)
{
USB_DeviceClockInit();
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
g_shimAgent.speed = USB_SPEED_FULL;
g_shimAgent.attach = 0U;
g_shimAgent.deviceHandle = NULL;
g_shimAgent.recvDataBuffer = (uint8_t *)(&s_RecvDataBuffer[0]);
g_shimAgent.classBuffer = s_PhdcClassBuffer;
if (kStatus_USB_Success != USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &g_shimAgent.deviceHandle))
{
usb_echo("USB device PHDC weighscale demo init failed\r\n");
}
else
{
usb_echo("USB device PHDC weighscale demo\r\n");
AGENT_Init((void *)g_shimAgent.deviceHandle);
}
/* Install isr, set priority, and enable IRQ. */
USB_DeviceIsrEnable();
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
USB_DeviceRun(g_shimAgent.deviceHandle);
}
static void USB_DeviceApplicationTask(void *handle)
{
switch (appEvent)
{
/* bulk in qos is 0x08 - Medium/Best latency, reliability - the time needed
for a piece of information to send is from 20ms to 200ms, the device should
wait at least 20ms before sending the data to the host */
case APP_EVENT_SEND_ASSOCIATION_REQUEST:
for (uint32_t i = 10000000U; i > 0U; i--)
{
if (APP_EVENT_SEND_ASSOCIATION_REQUEST != appEvent)
{
return;
}
}
appEvent = APP_EVENT_UNDEFINED;
AGENT_SendAssociationRequest(handle, (uint8_t *)(&g_associationRequestData[0]), ASSOCIATION_REQUEST_LENGTH);
break;
case APP_EVENT_SEND_DEVICE_CONFIGURATION:
appEvent = APP_EVENT_UNDEFINED;
AGENT_SendConfig(handle, g_roivEventRepostConfigurationData, EVENT_REPORT_CONFIGURATION_LENGTH);
break;
case APP_EVENT_SEND_MDS_OBJECT:
{
appEvent = APP_EVENT_UNDEFINED;
USB_ShimAgentSendData(handle, AGENT_SEND_DATA_QOS, (uint8_t *)(&g_rorsCmipGetData[0]),
EVENT_RESPONSE_GET_LENGTH);
}
break;
case APP_EVENT_SEND_MEASUREMENT_DATA:
for (uint32_t i = 10000000U; i > 0U; i--)
{
if (APP_EVENT_SEND_MEASUREMENT_DATA != appEvent)
{
return;
}
}
appEvent = APP_EVENT_UNDEFINED;
APP_WeightScaleSendData(handle, &measurement);
break;
default:
break;
}
}
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)
int main(void)
#else
void main(void)
#endif
{
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
USB_DeviceApplicationInit();
while (1U)
{
#if USB_DEVICE_CONFIG_USE_TASK
USB_DeviceTaskFn(g_shimAgent.deviceHandle);
#endif
USB_DeviceApplicationTask((void *)g_shimAgent.deviceHandle);
}
}
/* EOF */