2013-05-25 11:03:40 +02:00
/**************************************************************************/
/*!
2013-05-28 10:24:27 +02:00
@ file hid_device . c
2013-05-25 11:03:40 +02:00
@ author hathach ( tinyusb . org )
@ section LICENSE
Software License Agreement ( BSD License )
Copyright ( c ) 2013 , hathach ( tinyusb . org )
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. 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 .
3. Neither the name of the copyright holders 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 ' ' 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 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 .
This file is part of the tinyusb stack .
*/
/**************************************************************************/
# include "tusb_option.h"
2013-05-29 09:39:14 +02:00
# if (MODE_DEVICE_SUPPORTED && DEVICE_CLASS_HID)
2013-05-25 11:03:40 +02:00
# define _TINY_USB_SOURCE_FILE_
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
2013-05-28 10:24:27 +02:00
# include "common/common.h"
# include "hid_device.h"
2013-06-01 16:54:08 +02:00
# include "tusb_descriptors.h"
2013-05-25 11:03:40 +02:00
2013-06-12 16:06:43 +02:00
tusb_error_t hidd_init ( uint8_t coreid , tusb_descriptor_interface_t const * p_interface_desc , uint16_t * p_length )
{
uint8_t const * p_desc = ( uint8_t const * ) p_interface_desc ;
//------------- HID descriptor -------------//
p_desc + = p_desc [ DESCRIPTOR_OFFSET_LENGTH ] ;
tusb_hid_descriptor_hid_t const * p_desc_hid = ( tusb_hid_descriptor_hid_t const * ) p_desc ;
ASSERT_INT ( HID_DESC_TYPE_HID , p_desc_hid - > bDescriptorType , TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ) ;
//------------- Endpoint Descriptor -------------//
p_desc + = p_desc [ DESCRIPTOR_OFFSET_LENGTH ] ;
tusb_descriptor_endpoint_t const * p_desc_endpoint = ( tusb_descriptor_endpoint_t const * ) p_desc ;
ASSERT_INT ( TUSB_DESC_TYPE_ENDPOINT , p_desc_endpoint - > bDescriptorType , TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ) ;
if ( p_interface_desc - > bInterfaceSubClass = = HID_SUBCLASS_BOOT )
{
switch ( p_interface_desc - > bInterfaceProtocol )
{
# if TUSB_CFG_DEVICE_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD :
ASSERT_STATUS ( dcd_endpoint_configure ( coreid , p_desc_endpoint ) ) ;
break ;
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
case HID_PROTOCOL_MOUSE :
ASSERT_STATUS ( hidd_interface_init ( p_interface_desc ,
app_tusb_mouse_desc_report , p_desc_hid - > wReportLength ,
hidd_mouse_buffer , sizeof ( hidd_mouse_buffer ) ) ) ;
break ;
# endif
default : // TODO unknown, unsupported protocol --> skip this interface
return TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ;
}
* p_length = sizeof ( tusb_descriptor_interface_t ) + sizeof ( tusb_hid_descriptor_hid_t ) + sizeof ( tusb_descriptor_endpoint_t ) ;
} else
{
// open generic
* p_length = 0 ;
return TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ;
}
return TUSB_ERROR_NONE ;
}
2013-06-04 08:36:18 +02:00
# if defined(CAP_DEVICE_ROMDRIVER) && TUSB_CFG_DEVICE_USE_ROM_DRIVER
# include "device/dcd_nxp_romdriver.h" // TODO remove rom driver dependency
2013-06-12 09:06:41 +02:00
2013-06-04 08:36:18 +02:00
2013-05-25 11:03:40 +02:00
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
2013-06-01 16:54:08 +02:00
# if TUSB_CFG_DEVICE_HID_KEYBOARD
TUSB_CFG_ATTR_USBRAM uint8_t hidd_keyboard_buffer [ 1024 ] ; // TODO memory reduce
TUSB_CFG_ATTR_USBRAM tusb_keyboard_report_t hid_keyboard_report ;
static volatile bool bKeyChanged = false ;
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
2013-06-03 09:31:17 +02:00
TUSB_CFG_ATTR_USBRAM uint8_t hidd_mouse_buffer [ 1024 ] ; // TODO memory reduce
2013-06-01 16:54:08 +02:00
TUSB_CFG_ATTR_USBRAM tusb_mouse_report_t hid_mouse_report ;
static volatile bool bMouseChanged = false ;
# endif
2013-05-25 11:03:40 +02:00
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
2013-06-12 16:06:43 +02:00
static tusb_error_t hidd_interface_init ( tusb_descriptor_interface_t const * p_interface_desc , uint8_t const * const p_report_desc ,
uint32_t report_length , uint8_t * mem_base , uint32_t mem_size ) ;
2013-06-01 16:54:08 +02:00
ErrorCode_t HID_GetReport ( USBD_HANDLE_T hHid , USB_SETUP_PACKET * pSetup , uint8_t * * pBuffer , uint16_t * plength ) ;
ErrorCode_t HID_SetReport ( USBD_HANDLE_T hHid , USB_SETUP_PACKET * pSetup , uint8_t * * pBuffer , uint16_t length ) ;
ErrorCode_t HID_EpIn_Hdlr ( USBD_HANDLE_T hUsb , void * data , uint32_t event ) ;
ErrorCode_t HID_EpOut_Hdlr ( USBD_HANDLE_T hUsb , void * data , uint32_t event ) ;
2013-05-25 11:03:40 +02:00
2013-06-03 10:56:14 +02:00
2013-05-25 11:03:40 +02:00
//--------------------------------------------------------------------+
2013-06-03 10:56:14 +02:00
// APPLICATION API
2013-05-25 11:03:40 +02:00
//--------------------------------------------------------------------+
2013-06-03 10:56:14 +02:00
# if TUSB_CFG_DEVICE_HID_KEYBOARD
tusb_error_t tusbd_hid_keyboard_send_report ( tusb_keyboard_report_t * p_kbd_report )
{
// uint32_t start_time = systickGetSecondsActive();
// while (bKeyChanged) // TODO blocking while previous key has yet sent - can use fifo to improve this
// {
// ASSERT_MESSAGE(systickGetSecondsActive() - start_time < 5, ERR_FAILED, "HID Keyboard Timeout");
// }
if ( bKeyChanged )
{
return TUSB_ERROR_FAILED ;
}
ASSERT_PTR ( p_kbd_report , TUSB_ERROR_FAILED ) ;
hid_keyboard_report = * p_kbd_report ;
bKeyChanged = true ;
return TUSB_ERROR_NONE ;
}
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
tusb_error_t tusbd_hid_mouse_send_report ( tusb_mouse_report_t * p_mouse_report )
{
// uint32_t start_time = systickGetSecondsActive();
// while (bMouseChanged) // TODO Block while previous key hasn't been sent - can use fifo to improve this
// {
// ASSERT_MESSAGE(systickGetSecondsActive() - start_time < 5, ERR_FAILED, "HID Mouse Timeout");
// }
2013-06-01 16:54:08 +02:00
2013-06-03 10:56:14 +02:00
if ( bMouseChanged )
{
return TUSB_ERROR_FAILED ;
}
hid_mouse_report = * p_mouse_report ;
bMouseChanged = true ;
return TUSB_ERROR_NONE ;
}
# endif
2013-06-01 16:54:08 +02:00
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
2013-06-04 08:36:18 +02:00
tusb_error_t hidd_configured ( void )
2013-06-03 10:56:14 +02:00
{
# if TUSB_CFG_DEVICE_HID_KEYBOARD
2013-06-04 08:36:18 +02:00
ROM_API - > hw - > WriteEP ( romdriver_hdl , HID_KEYBOARD_EP_IN , ( uint8_t * ) & hid_keyboard_report , sizeof ( tusb_keyboard_report_t ) ) ; // initial packet for IN endpoint , will not work if omitted
2013-06-03 10:56:14 +02:00
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
2013-06-04 08:36:18 +02:00
ROM_API - > hw - > WriteEP ( romdriver_hdl , HID_MOUSE_EP_IN , ( uint8_t * ) & hid_mouse_report , sizeof ( tusb_mouse_report_t ) ) ; // initial packet for IN endpoint, will not work if omitted
2013-06-03 10:56:14 +02:00
# endif
return TUSB_ERROR_NONE ;
}
2013-06-03 09:31:17 +02:00
tusb_error_t hidd_init ( tusb_descriptor_interface_t const * p_interface_desc , uint16_t * p_length )
2013-06-01 16:54:08 +02:00
{
uint8_t const * p_desc = ( uint8_t const * ) p_interface_desc ;
//------------- HID descriptor -------------//
p_desc + = p_desc [ DESCRIPTOR_OFFSET_LENGTH ] ;
tusb_hid_descriptor_hid_t const * p_desc_hid = ( tusb_hid_descriptor_hid_t const * ) p_desc ;
ASSERT_INT ( HID_DESC_TYPE_HID , p_desc_hid - > bDescriptorType , TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ) ;
2013-06-03 09:31:17 +02:00
if ( p_interface_desc - > bInterfaceSubClass = = HID_SUBCLASS_BOOT )
{
switch ( p_interface_desc - > bInterfaceProtocol )
{
# if TUSB_CFG_DEVICE_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD :
ASSERT_STATUS ( hidd_interface_init ( p_interface_desc ,
app_tusb_keyboard_desc_report , p_desc_hid - > wReportLength ,
hidd_keyboard_buffer , sizeof ( hidd_keyboard_buffer ) ) ) ;
break ;
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
case HID_PROTOCOL_MOUSE :
ASSERT_STATUS ( hidd_interface_init ( p_interface_desc ,
app_tusb_mouse_desc_report , p_desc_hid - > wReportLength ,
hidd_mouse_buffer , sizeof ( hidd_mouse_buffer ) ) ) ;
break ;
# endif
default : // TODO unknown, unsupported protocol --> skip this interface
return TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ;
}
* p_length = sizeof ( tusb_descriptor_interface_t ) + sizeof ( tusb_hid_descriptor_hid_t ) + sizeof ( tusb_descriptor_endpoint_t ) ;
} else
{
// open generic
* p_length = 0 ;
return TUSB_ERROR_HIDD_DESCRIPTOR_INTERFACE ;
}
2013-06-01 16:54:08 +02:00
return TUSB_ERROR_NONE ;
}
2013-06-12 16:06:43 +02:00
tusb_error_t hidd_interface_init ( tusb_descriptor_interface_t const * p_interface_desc , uint8_t const * const p_report_desc ,
uint32_t report_length , uint8_t * mem_base , uint32_t mem_size )
2013-06-01 16:54:08 +02:00
{
USB_HID_REPORT_T reports_data =
{
2013-06-12 16:06:43 +02:00
. desc = ( uint8_t * ) p_report_desc ,
. len = report_length ,
2013-06-01 16:54:08 +02:00
. idle_time = 0 ,
} ;
USBD_HID_INIT_PARAM_T hid_param =
{
. mem_base = ( uint32_t ) mem_base ,
. mem_size = mem_size ,
2013-06-12 16:06:43 +02:00
. intf_desc = ( uint8_t * ) p_interface_desc ,
2013-06-01 16:54:08 +02:00
. report_data = & reports_data ,
. max_reports = 1 ,
/* user defined functions */
. HID_GetReport = HID_GetReport ,
. HID_SetReport = HID_SetReport ,
. HID_EpIn_Hdlr = HID_EpIn_Hdlr ,
. HID_EpOut_Hdlr = HID_EpOut_Hdlr
} ;
ASSERT ( LPC_OK = = ROM_API - > hid - > init ( romdriver_hdl , & hid_param ) , TUSB_ERROR_FAILED ) ;
return TUSB_ERROR_NONE ;
}
2013-06-03 10:56:14 +02:00
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
2013-05-29 09:39:14 +02:00
ErrorCode_t HID_GetReport ( USBD_HANDLE_T hHid , USB_SETUP_PACKET * pSetup , uint8_t * * pBuffer , uint16_t * plength )
{
USB_HID_CTRL_T * pHidCtrl = ( USB_HID_CTRL_T * ) hHid ;
/* ReportID = SetupPacket.wValue.WB.L; */
if ( pSetup - > wValue . WB . H = = HID_REQUEST_REPORT_INPUT )
return ( ERR_USBD_STALL ) ; /* Not Supported */
switch ( pHidCtrl - > protocol )
{
# if TUSB_CFG_DEVICE_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD :
* pBuffer = ( uint8_t * ) & hid_keyboard_report ;
* plength = sizeof ( tusb_keyboard_report_t ) ;
if ( ! bKeyChanged )
{
memset ( pBuffer , 0 , * plength ) ;
}
bKeyChanged = false ;
break ;
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
case HID_PROTOCOL_MOUSE :
* pBuffer = ( uint8_t * ) & hid_mouse_report ;
* plength = sizeof ( tusb_mouse_report_t ) ;
if ( ! bMouseChanged )
{
memset ( pBuffer , 0 , * plength ) ;
}
bMouseChanged = false ;
break ;
# endif
default :
break ;
}
return ( LPC_OK ) ;
}
ErrorCode_t HID_SetReport ( USBD_HANDLE_T hHid , USB_SETUP_PACKET * pSetup , uint8_t * * pBuffer , uint16_t length )
{
/* we will reuse standard EP0Buf */
if ( length = = 0 )
return LPC_OK ;
/* ReportID = SetupPacket.wValue.WB.L; */
if ( pSetup - > wValue . WB . H ! = HID_REQUEST_REPORT_OUTPUT )
return ( ERR_USBD_STALL ) ; /* Not Supported */
return ( LPC_OK ) ;
}
ErrorCode_t HID_EpIn_Hdlr ( USBD_HANDLE_T hUsb , void * data , uint32_t event )
{
if ( USB_EVT_IN = = event )
{
USB_HID_CTRL_T * pHidCtrl = ( USB_HID_CTRL_T * ) data ;
switch ( pHidCtrl - > protocol )
{
# if TUSB_CFG_DEVICE_HID_KEYBOARD
case HID_PROTOCOL_KEYBOARD :
if ( ! bKeyChanged )
{
memset ( & hid_keyboard_report , 0 , sizeof ( tusb_keyboard_report_t ) ) ;
}
ROM_API - > hw - > WriteEP ( hUsb , pHidCtrl - > epin_adr , ( uint8_t * ) & hid_keyboard_report , sizeof ( tusb_keyboard_report_t ) ) ;
bKeyChanged = false ;
break ;
# endif
# if TUSB_CFG_DEVICE_HID_MOUSE
case HID_PROTOCOL_MOUSE :
if ( ! bMouseChanged )
{
memset ( & hid_mouse_report , 0 , sizeof ( tusb_mouse_report_t ) ) ;
}
ROM_API - > hw - > WriteEP ( hUsb , pHidCtrl - > epin_adr , ( uint8_t * ) & hid_mouse_report , sizeof ( tusb_mouse_report_t ) ) ;
bMouseChanged = false ;
break ;
# endif
default :
break ;
}
}
return LPC_OK ;
}
ErrorCode_t HID_EpOut_Hdlr ( USBD_HANDLE_T hUsb , void * data , uint32_t event )
{
if ( USB_EVT_OUT = = event )
{
// not used yet
// uint8_t outreport[8];
// USB_HID_CTRL_T* pHidCtrl = (USB_HID_CTRL_T*)data;
// ROM_API->hw->ReadEP(hUsb, pHidCtrl->epout_adr, outreport);
}
return LPC_OK ;
}
2013-06-12 09:06:41 +02:00
# endif
2013-05-29 09:39:14 +02:00
2013-05-25 11:03:40 +02:00
# endif