/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016, 2018 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _HOST_HID_GENERIC_H_
#define _HOST_HID_GENERIC_H_

/*******************************************************************************
 * Definitions
 ******************************************************************************/
/*! @brief buffer for receiving report descriptor and data */
#define HID_GENERIC_IN_BUFFER_SIZE (200U)
/*! @brief buffer for sending data */
#define HID_GENERIC_OUT_BUFFER_SIZE (8U)

/*! @brief host app run status */
typedef enum _usb_host_hid_generic_run_state
{
    kUSB_HostHidRunIdle = 0,                /*!< idle */
    kUSB_HostHidRunSetInterface,            /*!< execute set interface code */
    kUSB_HostHidRunWaitSetInterface,        /*!< wait set interface done */
    kUSB_HostHidRunSetInterfaceDone,        /*!< set interface is done, execute next step */
    kUSB_HostHidRunWaitSetIdle,             /*!< wait set idle done */
    kUSB_HostHidRunSetIdleDone,             /*!< set idle is done, execute next step */
    kUSB_HostHidRunWaitGetReportDescriptor, /*!< wait get report descriptor done */
    kUSB_HostHidRunGetReportDescriptorDone, /*!< get report descriptor is done, execute next step */
    kUSB_HostHidRunWaitGetFeatureReport,    /*!< wait get feature report done */
    kUSB_HostHidRunGetFeatureReportDone,    /*!< get feature report is done, execute next step */
    kUSB_HostHidRunWaitDataReceived,        /*!< wait interrupt in data */
    kUSB_HostHidRunDataReceived,            /*!< interrupt in data received */
    kUSB_HostHidRunPrimeDataReceive,        /*!< prime interrupt in receive */
} usb_host_hid_generic_run_state_t;

/*! @brief USB host hid generic instance structure */
typedef struct _usb_host_hid_generic_instance
{
    usb_host_configuration_handle configHandle; /*!< the hid generic's configuration handle */
    usb_device_handle deviceHandle;             /*!< the hid generic's device handle */
    usb_host_class_handle classHandle;          /*!< the hid generic's class handle */
    usb_host_interface_handle interfaceHandle;  /*!< the hid generic's interface handle */
    uint8_t deviceState;                        /*!< device attach/detach status */
    uint8_t prevState;                          /*!< device attach/detach previous status */
    uint8_t runState;                           /*!< hid generic application run status */
    uint8_t
        runWaitState; /*!< hid generic application wait status, go to next run status when the wait status success */
    uint16_t inMaxPacketSize;  /*!< Interrupt in max packet size */
    uint8_t *genericInBuffer;  /*!< use to receive report descriptor and data */
    uint16_t sendIndex;        /*!< data sending position */
    uint32_t bytesInBuffer;    /*!< how many bytes are available in genericInBuffer */
    uint32_t vidpid;
} usb_host_hid_generic_instance_t;

/*******************************************************************************
 * API
 ******************************************************************************/

/*!
 * @brief host hid generic task function.
 *
 * This function implements the host hid generic action, it is used to create task.
 *
 * @param param   the host hid generic instance pointer.
 */
extern void USB_HostHidGenericTask(void *param);

/*!
 * @brief host hid generic callback function.
 *
 * This function should be called in the host 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 configuration don't contain hid generic interface.
 */
extern usb_status_t USB_HostHidGenericEvent(usb_device_handle deviceHandle,
                                            usb_host_configuration_handle configurationHandle,
                                            uint32_t eventCode);


/*!
 * @brief VID/PID acceptance callback function typedef.
 *
 * This callback function is called after enumeration to ask if the VID/PID combination
 * should be accepted or ignored.
 *
 * bool my_acceptor(uint16_t vid, uint16_t pid)
 * {
 *    return (vid==0x1234) && (pid==0x5678);
 * }
 *
 * @param vid     The VendorID.
 * @param pid     The ProductID.
 * @return True if the VID/PID is recognized, false if it should be ignored.
 */
typedef bool (* VidPidFunction_t)( uint16_t vid, uint16_t pid );

/*!
 * @brief HID Input Report callback function typedef.
 *
 * This callback function is called each time a new HID Input Report is received,
 * so that the data can be decoded, X/Y/Pressed data extracted and if needed scaled
 * to the currently selected display resolution.
 *
 * bool my_extractor(uint32_t vidpid, const uint8_t* buff, uint32_t len, uint16_t* x, uint16_t* y, bool* pressed)
 * {
 *    // Assuming this device report is 5 bytes [ pressed, x lsb, x msb, y lsb, y msb ]
 *    if ((vidpid==0x12345678) && (len>=5)) {
 *       *pressed = buff[0];
 *       uint32_t tmpx = buff[1] + (buff[2]<<8);
 *       uint32_t tmpy = buff[3] + (buff[4]<<8);
 *
 *       // Scale to resolution, assuming display width 800 and touch resolution 1000
 *       *x = (uint16_t)((tmpx*800)/1000);
 *
 *       // Scale to resolution, assuming display height 480 and touch resolution 1000
 *       *y = (uint16_t)((tmpy*480)/1000);
 *       return true;
 *    }
 *    return false; // invalid data or not from our device - to be ignored
 * }
 *
 * @param vidpid  The VendorID in the upper 16 bits, ProductID in the lower 16 bits.
 * @param buff    The raw data from the input report.
 * @param len     Number of bytes in the input report.
 * @param x       Return value for the X coordinate.
 * @param y       Return value for the Y coordinate.
 * @param pressed Return value for touch status (true if touched).
 * @return True if the input report was valid.
 */
typedef bool (* ExtractFunction_t)( uint32_t vidpid, const uint8_t* buff, uint32_t len, uint16_t* x, uint16_t* y, bool* pressed );

/*!
 * @brief Register override functions for USB HID.
 *
 * This function is used to register callbacks to help with decoding USB Touch
 * devices that are not already builtin.
 *
 * @param vidpid  The VendorID in the upper 16 bits, ProductID in the lower 16 bits.
 * @param buff    The raw data from the input report.
 * @param len     Number of bytes in the input report.
 * @param x       Return value for the X coordinate.
 * @param y       Return value for the Y coordinate.
 * @param pressed Return value for touch status (true if touched).
 * @return True if the input report was valid.
 */
void BOARD_RegisterUSBTouchCallbacks(VidPidFunction_t vp, ExtractFunction_t e);

#endif /* _HOST_HID_GENERIC_H_ */
