bool USB_sendData(uint32_t retransMax)
{
	uint32_t retransCount = 0;

	// Wait until the usb bus is free to transmit new data
	while (g_USBTxState != USB_TX_IDLE)
		;

	// After the data is received and ack from the host, this variable will be
	// reset to USB_TX_IDLE state by the uint32_t SwarmControlTransmitEventHandler()
	g_USBTxState = USB_TX_SENDING;

	while (retransCount <= retransMax)
	{
		// This function support checking HID state and the index of the data sent.
		if (USBDHIDReportWrite(pvDevice, usbBufferDeviceToHost, USB_BUFFER_SIZE,
		true))
			return 1;

		retransCount++;
	}

	// Reach the maximum number of retransmission
	// Signal to the caller that we can't send data to the host
	return 0;
}
//*****************************************************************************
//
//! Reports a mouse state change, pointer movement or button press, to the USB
//! host.
//!
//! \param pvInstance is the pointer to the mouse device instance structure.
//! \param cDeltaX is the relative horizontal pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating movement to the right.
//! \param cDeltaY is the relative vertical pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating downward movement.
//! \param ucButtons is a bit mask indicating which (if any) of the three
//! mouse buttons is pressed.  Valid values are logical OR combinations of
//! \e MOUSE_REPORT_BUTTON_1, \e MOUSE_REPORT_BUTTON_2 and \e
//! MOUSE_REPORT_BUTTON_3.
//!
//! This function is called to report changes in the mouse state to the USB
//! host.  These changes can be movement of the pointer, reported relative to
//! its previous position, or changes in the states of up to 3 buttons that
//! the mouse may support.  The return code indicates whether or not the
//! mouse report could be sent to the host.  In cases where a previous
//! report is still being transmitted, \b MOUSE_ERR_TX_ERROR will be returned
//! and the state change will be ignored.
//!
//! \return Returns \b MOUSE_SUCCESS on success, \b MOUSE_ERR_TX_ERROR if an
//! error occurred while attempting to schedule transmission of the mouse
//! report to the host (typically due to a previous report which has not yet
//! completed transmission or due to disconnection of the host) or \b
//! MOUSE_ERR_NOT_CONFIGURED if called before a host has connected to and
//! configured the device.
//
//*****************************************************************************
unsigned long
USBDHIDMouseStateChange(void *pvInstance, char cDeltaX, char cDeltaY,
                        unsigned char ucButtons)
{
    unsigned long ulRetcode;
    unsigned long ulCount;
    tHIDMouseInstance *psInst;
    tUSBDHIDMouseDevice *psDevice;
    tUSBDHIDDevice *psHIDDevice;

    //
    // Get a pointer to the device.
    //
    psDevice = (tUSBDHIDMouseDevice *)pvInstance;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psDevice->psPrivateHIDMouseData->sHIDDevice;

    //
    // Get a pointer to our instance data
    //
    psInst = psDevice->psPrivateHIDMouseData;

    //
    // Update the global mouse report with the information passed.
    //
    psInst->pucReport[HID_REPORT_BUTTONS] = ucButtons;
    psInst->pucReport[HID_REPORT_X] = (unsigned char)cDeltaX;
    psInst->pucReport[HID_REPORT_Y] = (unsigned char)cDeltaY;

    //
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(!psInst->ucUSBConfigured)
    {
        return(MOUSE_ERR_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->eMouseState = HID_MOUSE_STATE_SEND;
        ulCount = USBDHIDReportWrite((void *)psHIDDevice,
                                     psInst->pucReport, MOUSE_REPORT_SIZE,
                                     true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(!ulCount)
        {
            //
            // No - report the error to the caller.
            //
            ulRetcode = MOUSE_ERR_TX_ERROR;
        }
        else
        {
            ulRetcode = MOUSE_SUCCESS;
        }
    }
    else
    {
        ulRetcode = MOUSE_ERR_TX_ERROR;
    }
    //
    // Return the relevant error code to the caller.
    //
    return(ulRetcode);
}
示例#3
0
//*****************************************************************************
//
// HID device class transmit channel event handler function.
//
// \param pvKeyboardDevice is the event callback pointer provided during
// USBDHIDInit().  This is a pointer to our HID device structure
// (&g_sHIDKeybDevice).
// \param ui32Event identifies the event we are being called back for.
// \param ui32MsgData is an event-specific value.
// \param pvMsgData is an event-specific pointer.
//
// This function is called by the HID device class driver to inform the
// application of particular asynchronous events related to report
// transmissions made using the interrupt IN endpoint.
//
// \return Returns a value which is event-specific.
//
//*****************************************************************************
static uint32_t
HIDKeyboardTxHandler(void *pvKeyboardDevice, uint32_t ui32Event,
                     uint32_t ui32MsgData, void *pvMsgData)
{
    tHIDKeyboardInstance *psInst;
    tUSBDHIDKeyboardDevice *psHIDKbDevice;
    tUSBDHIDDevice *psHIDDevice;
    uint32_t ui32Count;

    //
    // Make sure we did not get a NULL pointer.
    //
    ASSERT(pvKeyboardDevice);

    //
    // Get a pointer to our instance data
    //
    psHIDKbDevice = (tUSBDHIDKeyboardDevice *)pvKeyboardDevice;
    psInst = &psHIDKbDevice->sPrivateData;
    psHIDDevice = &psInst->sHIDDevice;

    //
    // Which event were we sent?
    //
    switch (ui32Event)
    {
        //
        // A report transmitted via the interrupt IN endpoint was acknowledged
        // by the host.
        //
        case USB_EVENT_TX_COMPLETE:
        {
            //
            // Do we have any pending changes needing transmitted?
            //
            if(psInst->bChangeMade)
            {
                //
                // Yes - go ahead and send another report immediately.
                //
                ui32Count = USBDHIDReportWrite((void *)psHIDDevice,
                                             psInst->pui8Report,
                                             KEYB_IN_REPORT_SIZE, true);

                //
                // If we scheduled the report for transmission, clear the
                // change flag.
                //
                if(ui32Count != 0)
                {
                    psInst->bChangeMade = false;
                }
            }
            else
            {
                //
                // Our last transmission is complete and we have nothing more
                // to send.
                //
                psInst->eKeyboardState = HID_KEYBOARD_STATE_IDLE;
            }

            //
            // Pass the event on to the client.
            //
            psHIDKbDevice->pfnCallback(psHIDKbDevice->pvCBData,
                                       USB_EVENT_TX_COMPLETE, ui32MsgData,
                                       (void *)0);

            break;
        }

        //
        // We ignore all other events related to transmission of reports via
        // the interrupt IN endpoint.
        //
        default:
        {
            break;
        }
    }

    return(0);
}
示例#4
0
//*****************************************************************************
//
//! Reports a key state change to the USB host.
//!
//! \param pvKeyboardDevice is the pointer to the device instance structure
//! as returned by USBDHIDKeyboardInit().
//! \param ui8Modifiers contains the states of each of the keyboard modifiers
//! (left/right shift, ctrl, alt or GUI keys).  Valid values are logical OR
//! combinations of the labels \b HID_KEYB_LEFT_CTRL, \b HID_KEYB_LEFT_SHIFT,
//! \b HID_KEYB_LEFT_ALT, \b HID_KEYB_LEFT_GUI, \b HID_KEYB_RIGHT_CTRL, \b
//! HID_KEYB_RIGHT_SHIFT, \b HID_KEYB_RIGHT_ALT and \b HID_KEYB_RIGHT_GUI.
//! Presence of one of these bit flags indicates that the relevant modifier
//! key is pressed and absence indicates that it is released.
//! \param ui8UsageCode is the usage code of the key whose state has changed.
//! If only modifier keys have changed, \b HID_KEYB_USAGE_RESERVED should be
//! passed in this parameter.
//! \param bPress is \b true if the key has been pressed or \b false if it has
//! been released.  If only modifier keys have changed state, this parameter is
//! ignored.
//!
//! This function adds or removes a key usage code from the list of keys
//! currently pressed and schedules a report transmission to the host to
//! inform it of the new keyboard state.  If the maximum number of simultaneous
//! key presses are already recorded, the report to the host will contain the
//! rollover error code, HID_KEYB_USAGE_ROLLOVER instead of key usage codes
//! and the caller will receive return code KEYB_ERR_TOO_MANY_KEYS.
//!
//! \return Returns \b KEYB_SUCCESS if the key usage code was added to or
//! removed from the current list successfully.  \b KEYB_ERR_TOO_MANY_KEYS is
//! returned if an attempt is made to press a 7th key (the BIOS keyboard
//! protocol can report no more than 6 simultaneously pressed keys).  If called
//! before the USB host has configured the device, \b KEYB_ERR_NOT_CONFIGURED
//! is returned and, if an error is reported while attempting to transmit the
//! report, \b KEYB_ERR_TX_ERROR is returned.  If an attempt is made to remove
//! a key from the pressed list (by setting parameter \e bPressed to \b false)
//! but the key usage code is not found, \b KEYB_ERR_NOT_FOUND is returned.
//
//*****************************************************************************
uint32_t
USBDHIDKeyboardKeyStateChange(void *pvKeyboardDevice, uint8_t ui8Modifiers,
                              uint8_t ui8UsageCode, bool bPress)
{
    bool bRetcode;
    uint32_t ui32Loop, ui32Count;
    tHIDKeyboardInstance *psInst;
    tUSBDHIDKeyboardDevice *psHIDKbDevice;
    tUSBDHIDDevice *psHIDDevice;

    psHIDKbDevice = (tUSBDHIDKeyboardDevice *)pvKeyboardDevice;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psHIDKbDevice->sPrivateData.sHIDDevice;

    //
    // Assume all is well until we determine otherwise.
    //
    bRetcode = true;

    //
    // Get a pointer to our instance data
    //
    psInst = &psHIDKbDevice->sPrivateData;

    //
    // Update the global keyboard report with the information passed.
    //
    psInst->pui8Report[0] = ui8Modifiers;
    psInst->pui8Report[1] = 0;

    //
    // Were we passed a usage code for a new key press or release or was
    // this call just telling us about a modifier change?
    //
    if(ui8UsageCode != HID_KEYB_USAGE_RESERVED)
    {
        //
        // Has a key been pressed or released?
        //
        if(bPress)
        {
            //
            // A key has been pressed - add it to the list if there is space an
            // and the key is not already in the list.
            //
            bRetcode = AddKeyToPressedList(psInst, ui8UsageCode);
        }
        else
        {
            //
            // A key has been released - remove it from the list.
            //
            bRetcode = RemoveKeyFromPressedList(psInst, ui8UsageCode);

            //
            // The return code here indicates whether the key was found.  If it
            // wasn't, the list has not changes so merely exit at this point
            // without sending anything to the host.
            //
            if(!bRetcode)
            {
                return(KEYB_ERR_NOT_FOUND);
            }
        }

        //
        // Build the report from the current list of keys.  If we added a key
        // and got a bad return code indicating a roll over error, we need to
        // send a roll over report
        //
        for(ui32Loop = 0; ui32Loop < KEYB_MAX_CHARS_PER_REPORT; ui32Loop++)
        {
            psInst->pui8Report[2 + ui32Loop] = (bRetcode ?
                psInst->pui8KeysPressed[ui32Loop] : HID_KEYB_USAGE_ROLLOVER);
        }
    }

    //
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(!psInst->ui8USBConfigured)
    {
        return(KEYB_ERR_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->eKeyboardState = HID_KEYBOARD_STATE_SEND;
        ui32Count = USBDHIDReportWrite((void *)psHIDDevice,
                                       psInst->pui8Report, KEYB_IN_REPORT_SIZE,
                                       true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(!ui32Count)
        {
            //
            // No - report the error to the caller.
            //
            return(KEYB_ERR_TX_ERROR);
        }
    }
    else
    {
        //
        // We can't send the report immediately so mark the instance so that
        // it is sent next time the transmitter is free.
        //
        psInst->bChangeMade = true;
    }

    //
    // If we get this far, the key information was sent successfully.  Are
    // too many keys currently pressed, though?
    //
    return(bRetcode ? KEYB_SUCCESS : KEYB_ERR_TOO_MANY_KEYS);
}
示例#5
0
//*****************************************************************************
//
//! Reports a mouse state change, pointer movement or button press, to the USB
//! host.
//!
//! \param pvMouseDevice is the pointer to the mouse device instance structure.
//! \param i8DeltaX is the relative horizontal pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating movement to the right.
//! \param i8DeltaY is the relative vertical pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating downward movement.
//! \param ui8Buttons is a bit mask indicating which (if any) of the three
//! mouse buttons is pressed.  Valid values are logical OR combinations of
//! \b MOUSE_REPORT_BUTTON_1, \b MOUSE_REPORT_BUTTON_2 and
//! \b MOUSE_REPORT_BUTTON_3.
//!
//! This function is called to report changes in the mouse state to the USB
//! host.  These changes can be movement of the pointer, reported relative to
//! its previous position, or changes in the states of up to 3 buttons that
//! the mouse may support.  The return code indicates whether or not the
//! mouse report could be sent to the host.  In cases where a previous
//! report is still being transmitted, \b MOUSE_ERR_TX_ERROR is returned
//! and the state change is ignored.
//!
//! \return Returns \b MOUSE_SUCCESS on success, \b MOUSE_ERR_TX_ERROR if an
//! error occurred while attempting to schedule transmission of the mouse
//! report to the host (typically due to a previous report which has not yet
//! completed transmission or due to disconnection of the host) or \b
//! MOUSE_ERR_NOT_CONFIGURED if called before a host has connected to and
//! configured the device.
//
//*****************************************************************************
uint32_t
USBDHIDMouseStateChange(void *pvMouseDevice, int8_t i8DeltaX, int8_t i8DeltaY,
                        uint8_t ui8Buttons)
{
    uint32_t ui32Retcode, ui32Count;
    tHIDMouseInstance *psInst;
    tUSBDHIDMouseDevice *psMouseDevice;
    tUSBDHIDDevice *psHIDDevice;

    //
    // Get a pointer to the device.
    //
    psMouseDevice = (tUSBDHIDMouseDevice *)pvMouseDevice;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psMouseDevice->sPrivateData.sHIDDevice;

    //
    // Get a pointer to our instance data
    //
    psInst = &psMouseDevice->sPrivateData;

    //
    // Update the global mouse report with the information passed.
    //
    psInst->pui8Report[HID_REPORT_BUTTONS] = ui8Buttons;
    psInst->pui8Report[HID_REPORT_X] = (uint8_t)i8DeltaX;
    psInst->pui8Report[HID_REPORT_Y] = (uint8_t)i8DeltaY;

    //
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(!psInst->ui8USBConfigured)
    {
        return(MOUSE_ERR_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->iMouseState = eHIDMouseStateSend;
        ui32Count = USBDHIDReportWrite((void *)psHIDDevice,
                                       psInst->pui8Report, MOUSE_REPORT_SIZE,
                                       true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(!ui32Count)
        {
            //
            // No - report the error to the caller.
            //
            ui32Retcode = MOUSE_ERR_TX_ERROR;
        }
        else
        {
            ui32Retcode = MOUSE_SUCCESS;
        }
    }
    else
    {
        ui32Retcode = MOUSE_ERR_TX_ERROR;
    }
    //
    // Return the relevant error code to the caller.
    //
    return(ui32Retcode);
}
//*****************************************************************************
//
// Reports a customhid state change, pointer movement or button press
//
//*****************************************************************************
uint32_t
USBDHIDCustomHidStateChange(void *pvCustomHidDevice, uint8_t ReportID, signed char HIDData[])
{
    uint32_t ui32Retcode, ui32Count;
    uint8_t i;
    tHIDCustomHidInstance *psInst;
    tUSBDHIDCustomHidDevice *psCustomHidDevice;
    tUSBDHIDDevice *psHIDDevice;

    //
    // Get a pointer to the device.
    //
    psCustomHidDevice = (tUSBDHIDCustomHidDevice *)pvCustomHidDevice;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psCustomHidDevice->sPrivateData.sHIDDevice;

    //
    // Get a pointer to our instance data
    //
    psInst = &psCustomHidDevice->sPrivateData;

	if (ReportID > 0)
	{
		psInst->pui8Report[0] = ReportID; //ReportID

		for(i = 1; i < CUSTOMHID_REPORT_SIZE; i++)
		{
			psInst->pui8Report[i] = HIDData[i-1];; //Data is offset by 1 due to the ReportID
		}
	}
	else
	{
		for(i = 0; i < CUSTOMHID_REPORT_SIZE; i++)
		{
			psInst->pui8Report[i] = HIDData[i];; //No ReportID so no offset
		}
	}

    //
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(!psInst->ui8USBConfigured)
    {
        return(CUSTOMHID_ERR_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->iCustomHidState = eHIDCustomHidStateSend;
        ui32Count = USBDHIDReportWrite((void *)psHIDDevice,
                                       psInst->pui8Report, CUSTOMHID_REPORT_SIZE,
                                       true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(!ui32Count)
        {
            //
            // No - report the error to the caller.
            //
            ui32Retcode = CUSTOMHID_ERR_TX_ERROR;
        }
        else
        {
            ui32Retcode = CUSTOMHID_SUCCESS;
        }
    }
    else
    {
        ui32Retcode = CUSTOMHID_ERR_TX_ERROR;
    }
    //
    // Return the relevant error code to the caller.
    //
    return(ui32Retcode);
}
示例#7
0
//*****************************************************************************
//
//! Schedules a report to be sent once the host requests more data.
//!
//! \param psHIDGamepad is the structure pointer that is returned from the
//! USBDHIDGamepadCompositeInit() or USBDHIDGamepadInit() functions.
//! \param pvReport is the data to send to the host.
//! \param ui32Size is the number of bytes in the \e pvReport buffer.
//!
//! This call is made by an application to schedule data to be sent to the
//! host when the host requests an update from the device.  The application
//! must then wait for a \b USB_EVENT_TX_COMPLETE event in the function
//! provided in the \e pfnCallback pointer in the tUSBDHIDGamepadDevice
//! structure before being able to send more data with this function.  The
//! pointer passed in the \e pvReport can be updated once this call returns as
//! the data has been copied from the buffer.  The function returns
//! \b USBDGAMEPAD_SUCCESS if the transmission was successfully scheduled or
//! \b USBDGAMEPAD_TX_ERROR if the report could not be sent at this time.
//! If the call is made before the device is connected or ready to communicate
//! with the host, then the function can return \b USBDGAMEPAD_NOT_CONFIGURED.
//!
//! \return The function returns one of the \b USBDGAMEPAD_* values.
//
//*****************************************************************************
uint32_t
USBDHIDGamepadSendReport(tUSBDHIDGamepadDevice *psHIDGamepad, void *pvReport,
                         uint32_t ui32Size)
{
    uint32_t ui32Retcode, ui32Count;
    tUSBDGamepadInstance *psInst;
    tUSBDHIDDevice *psHIDDevice;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psHIDGamepad->sPrivateData.sHIDDevice;

    //
    // Get a pointer to our instance data
    //
    psInst = &psHIDGamepad->sPrivateData;

    //
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(psInst->iState == eHIDGamepadStateNotConnected)
    {
        return(USBDGAMEPAD_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->iState = eHIDGamepadStateSending;
        ui32Count = USBDHIDReportWrite((void *)psHIDDevice, pvReport, ui32Size,
                                       true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(ui32Count == 0)
        {
            //
            // No - report the error to the caller.
            //
            ui32Retcode = USBDGAMEPAD_TX_ERROR;
        }
        else
        {
            ui32Retcode = USBDGAMEPAD_SUCCESS;
        }
    }
    else
    {
        ui32Retcode = USBDGAMEPAD_TX_ERROR;
    }

    //
    // Return the relevant error code to the caller.
    //
    return(ui32Retcode);
}
示例#8
0
int main(void) {
	int i;
	uint8_t data[64];

    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    ROM_FPULazyStackingEnable();

    // Set the clocking to run from the PLL at 50MHz.
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    // Enable the GPIO peripheral used for USB, and configure the USB
    // pins.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    ROM_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 + GPIO_PIN_2 + GPIO_PIN_3);
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 + GPIO_PIN_2 + GPIO_PIN_3, 0);

    // Init diagnostic
    diagnostic_clear_eventhistory();

    // Init UART
    ConfigureUART();

    // Print welcome message
    UARTprintf("Configuring USB\n");

    //------------------------------------------------------
//    // Set the USB stack mode to Device mode with VBUS monitoring.
//    USBStackModeSet(0, eUSBModeForceDevice, 0);
//
//    // Pass our device information to the USB library and place the device
//    // on the bus.
//    USBDHIDInit(0, &hiddatapipe_device);

    //------------------------------------------------------

    USBStackModeSet(0, eUSBModeForceDevice, 0);
    USBDHIDCompositeInit(0, &hiddatapipe_device, &(composite_device.psDevices[0]));
	USBDDFUCompositeInit(0, &dfu_device, &(composite_device.psDevices[1]));

	//
	// Pass the USB library our device information, initialize the USB
	// controller and connect the device to the bus.
	//
	USBDCompositeInit(0, &composite_device, DESCRIPTOR_BUFFER_SIZE, composite_descriptorbuffer);

    // Block until connected
    while (!usbstate.connected)
    	;

    // Configure SysTick
	ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 1000); // 1 ms
	ROM_SysTickEnable();
	ROM_SysTickIntEnable();

	// enable first IN report by clearing USB tx complete
	usbstate.txcomplete = 1;

    while(1) {

    	// uncomment this if event history log is needed
//        if (events.print_history == true)
//        	diagnostic_print_eventhistory();

        // usbstate.txcomplete flag was set to 1 by txhandler after usbdhidreportwrite had succeeded
        if (usbstate.txcomplete  && usbstate.txdataupdated) {
        	// clear usbstate.txcomplete flag to indicate that usbdhidreportwrite is busy
        	usbstate.txcomplete = 0;
        	usbstate.txdataupdated = 0;
        	// put data (1 byte in this case) into the usb pipeline and the host will poll&read it
        	// the polling rate is defined in the interrupt IN endpoint descriptor

        	data[0] = txdata.buffer[0]; // temp buffer to avoid update change of txdata.buffer between the next 2 calls
        	USBDHIDReportWrite(&hiddatapipe_device, data, 1, 0);
        	UARTprintf("Sending irq IN to host: %d\n", data[0]);

        }

        if (usbstate.hostsentreport) {
        	// clear hostsentreport flag
        	usbstate.hostsentreport = 0;

        	for (i = 0; i < HID_REPORTOUT_SIZE; i++) {
        		UARTprintf("Received OUT report from host: %02x\n", rxdata.buffer[i]);
        		rxdata.buffer[i] = 0;
        	}

        }

    }
}
//*****************************************************************************
//
//! Reports a customhid state change, pointer movement or button press, to the USB
//! host.
//!
//! \param pvInstance is the pointer to the customhid device instance structure.
//! \param cDeltaX is the relative horizontal pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating movement to the right.
//! \param cDeltaY is the relative vertical pointer movement that the
//! application wishes to report.  Valid values are in the range [-127, 127]
//! with positive values indicating downward movement.
//! \param ucButtons is a bit mask indicating which (if any) of the three
//! customhid buttons is pressed.  Valid values are logical OR combinations of
//! \e CUSTOMHID_REPORT_BUTTON_1, \e CUSTOMHID_REPORT_BUTTON_2 and \e
//! CUSTOMHID_REPORT_BUTTON_3.
//!
//! This function is called to report changes in the customhid state to the USB
//! host.  These changes can be movement of the pointer, reported relative to
//! its previous position, or changes in the states of up to 3 buttons that
//! the customhid may support.  The return code indicates whether or not the
//! customhid report could be sent to the host.  In cases where a previous
//! report is still being transmitted, \b CUSTOMHID_ERR_TX_ERROR will be returned
//! and the state change will be ignored.
//!
//! \return Returns \b CUSTOMHID_SUCCESS on success, \b CUSTOMHID_ERR_TX_ERROR if an
//! error occurred while attempting to schedule transmission of the customhid
//! report to the host (typically due to a previous report which has not yet
//! completed transmission or due to disconnection of the host) or \b
//! CUSTOMHID_ERR_NOT_CONFIGURED if called before a host has connected to and
//! configured the device.
//
//*****************************************************************************
unsigned long
USBDHIDCustomHidStateChange(void *pvInstance, char ReportID, signed char HIDData[])
{
    unsigned long ulRetcode;
    unsigned long ulCount;
    int i;
    tHIDCustomHidInstance *psInst;
    tUSBDHIDCustomHidDevice *psDevice;
    tUSBDHIDDevice *psHIDDevice;

    //
    // Get a pointer to the device.
    //
    psDevice = (tUSBDHIDCustomHidDevice *)pvInstance;

    //
    // Get a pointer to the HID device data.
    //
    psHIDDevice = &psDevice->psPrivateHIDCustomHidData->sHIDDevice;

    //
    // Get a pointer to our instance data
    //
    psInst = psDevice->psPrivateHIDCustomHidData;


    //
    // You can pass 0 as the report ID in which case the function assumes it is a single report
    // If the descriptor has multiple reportIDs start them at 1 in the descriptor and then pass into this function
    //
    if (ReportID > 0)
    {
		psInst->pucReport[0] = ReportID; //ReportID

		for(i = 1; i < CUSTOMHID_REPORT_SIZE; i++)
		{
			psInst->pucReport[i] = HIDData[i-1];; //Data is offset by 1 due to the ReportID
		}
    }
    else
    {
    	for(i = 0; i < CUSTOMHID_REPORT_SIZE; i++)
    	{
    		psInst->pucReport[i] = HIDData[i];; //No ReportID so no offset
    	}
    }

   	//
    // If we are not configured, return an error here before trying to send
    // anything.
    //
    if(!psInst->ucUSBConfigured)
    {
        return(CUSTOMHID_ERR_NOT_CONFIGURED);
    }

    //
    // Only send a report if the transmitter is currently free.
    //
    if(USBDHIDTxPacketAvailable((void *)psHIDDevice))
    {
        //
        // Send the report to the host.
        //
        psInst->eCustomHidState = HID_CUSTOMHID_STATE_SEND;
        ulCount = USBDHIDReportWrite((void *)psHIDDevice, psInst->pucReport, CUSTOMHID_REPORT_SIZE, true);

        //
        // Did we schedule a packet for transmission correctly?
        //
        if(!ulCount)
        {
            //
            // No - report the error to the caller.
            //
            ulRetcode = CUSTOMHID_ERR_TX_ERROR;
        }
        else
        {
            ulRetcode = CUSTOMHID_SUCCESS;
        }
    }
    else
    {
        ulRetcode = CUSTOMHID_ERR_TX_ERROR;
    }
    //
    // Return the relevant error code to the caller.
    //
    return(ulRetcode);
}