forked from PAWPAW-Mirror/lib_xua
Fix the handling of setidle requests
This commit is contained in:
@@ -374,15 +374,15 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
||||
|
||||
#if( 0 < HID_CONTROLS )
|
||||
UserHIDInit();
|
||||
{
|
||||
while (!hidIsReportDescriptorPrepared())
|
||||
;
|
||||
|
||||
/* Get the last report - we don't really care which it is, so long as there's some data we can grab. */
|
||||
int hidReportLength = (int) UserHIDGetData(hidGetReportIdLimit() - 1, g_hidData);
|
||||
while (!hidIsReportDescriptorPrepared())
|
||||
;
|
||||
|
||||
/* Get the a report - we don't really care which it is, so long as there's some data we can grab. */
|
||||
int hidReportLength = (int) UserHIDGetData(hidGetNextValidReportId(0), g_hidData);
|
||||
|
||||
XUD_SetReady_In(ep_hid, g_hidData, hidReportLength);
|
||||
|
||||
XUD_SetReady_In(ep_hid, g_hidData, hidReportLength);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (AUDIO_CLASS == 1)
|
||||
|
||||
@@ -129,6 +129,31 @@ static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, con
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure a hid report's next report time and idle status based on a setidle request
|
||||
*
|
||||
* \param[in] reportId -- The report ID to modify
|
||||
* \param[in] reportDuration -- The duration of the setidle request
|
||||
*
|
||||
*/
|
||||
static void HidUpdateReportPeriod( unsigned reportId, unsigned reportDuration ) {
|
||||
unsigned currentPeriod = hidGetReportPeriod( reportId );
|
||||
|
||||
hidSetIdle( reportId, ( 0U == duration ) || ( ENDPOINT_INT_INTERVAL_IN_HID < duration ));
|
||||
|
||||
if( hidIsIdleActive( reportId )) {
|
||||
unsigned reportTime = hidGetReportTime( reportId );
|
||||
unsigned reportToSetIdleInterval = HidCalcReportToSetIdleInterval( reportTime );
|
||||
unsigned nextReportTime = HidCalcNewReportTime( currentPeriod, reportTime, reportToSetIdleInterval, reportDuration * MS_IN_TICKS );
|
||||
hidSetNextReportTime( reportId, nextReportTime );
|
||||
currentPeriod = reportDuration * MS_IN_TICKS;
|
||||
} else {
|
||||
currentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
|
||||
}
|
||||
|
||||
hidSetReportPeriod( reportId, currentPeriod );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process a Set Idle request
|
||||
*
|
||||
@@ -166,22 +191,24 @@ static XUD_Result_t HidProcessSetIdleRequest( XUD_ep c_ep0_out, XUD_ep c_ep0_in,
|
||||
|
||||
Any Interface value other than INTERFACE_NUMBER_HID indicates an error by the USB Host.
|
||||
*/
|
||||
if(( 0U == reportId ) && ( INTERFACE_NUMBER_HID == interfaceNum )) {
|
||||
hidSetIdle( reportId, ( 0U == duration ) || ( ENDPOINT_INT_INTERVAL_IN_HID < duration ));
|
||||
if( INTERFACE_NUMBER_HID == interfaceNum ) {
|
||||
if( hidIsReportIdValid( reportId ) ) {
|
||||
HidUpdateReportPeriod( reportId, duration );
|
||||
|
||||
unsigned currentPeriod = hidGetReportPeriod( reportId );
|
||||
if( hidIsIdleActive( reportId )) {
|
||||
unsigned reportTime = hidGetReportTime( reportId );
|
||||
unsigned reportToSetIdleInterval = HidCalcReportToSetIdleInterval( reportTime );
|
||||
unsigned nextReportTime = HidCalcNewReportTime( currentPeriod, reportTime, reportToSetIdleInterval, duration * MS_IN_TICKS );
|
||||
hidSetNextReportTime( reportId, nextReportTime );
|
||||
currentPeriod = duration * MS_IN_TICKS;
|
||||
} else {
|
||||
currentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
|
||||
result = XUD_DoSetRequestStatus( c_ep0_in );
|
||||
}
|
||||
else if ( reportId == 0U ) {
|
||||
// Wildcard request - set all report IDs to idle
|
||||
unsigned startReportId = hidGetNextValidReportId(reportId);
|
||||
|
||||
hidSetReportPeriod( reportId, currentPeriod );
|
||||
result = XUD_DoSetRequestStatus( c_ep0_in );
|
||||
reportId = startReportId;
|
||||
do {
|
||||
HidUpdateReportPeriod( reportId, duration );
|
||||
reportId = hidGetNextValidReportId( reportId );
|
||||
} while( reportId != startReportId);
|
||||
|
||||
result = XUD_DoSetRequestStatus( c_ep0_in );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -254,6 +254,20 @@ unsigned hidIsReportIdInUse ( void ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned hidIsReportIdValid ( unsigned id ) {
|
||||
size_t retVal = 0;
|
||||
|
||||
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
|
||||
unsigned reportId = hidGetElementReportId( hidReports[ idx ]->location );
|
||||
if( reportId == id ) {
|
||||
retVal = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
unsigned hidGetNextValidReportId ( unsigned idPrev ) {
|
||||
size_t retIndex = 0;
|
||||
|
||||
|
||||
@@ -203,6 +203,20 @@ unsigned hidGetReportIdLimit ( void );
|
||||
*/
|
||||
unsigned hidIsReportIdInUse ( void );
|
||||
|
||||
/**
|
||||
* @brief Is the provided report ID valid for passing to other functions.
|
||||
*
|
||||
* e.g If Report IDs are not in use, then only 0 will return true.
|
||||
* e.g If Report IDs are in use, then 0 will return false and the report IDs that
|
||||
* are in use will return true when passed to thsi function.
|
||||
*
|
||||
* @param id The ID to check
|
||||
* @return boolean
|
||||
* @retval 0 The report ID is not valid, other functions may fail silently
|
||||
* @retval 1 The report ID is valid and can be used as the argument to other functions
|
||||
*/
|
||||
unsigned hidIsReportIdValid ( unsigned id );
|
||||
|
||||
/**
|
||||
* @brief Get the next valid report ID - iterator style.
|
||||
*
|
||||
|
||||
@@ -79,6 +79,30 @@ void test_get_next_valid_report_id( void ) {
|
||||
TEST_ASSERT_EQUAL_UINT( 1, reportId );
|
||||
}
|
||||
|
||||
void test_is_report_id_valid( void ) {
|
||||
unsigned isValid = 0;
|
||||
|
||||
unsigned reportId = 0;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 0, isValid );
|
||||
|
||||
reportId = 1;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 1, isValid );
|
||||
|
||||
reportId = 2;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 1, isValid );
|
||||
|
||||
reportId = 3;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 1, isValid );
|
||||
|
||||
reportId = 4;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 0, isValid );
|
||||
}
|
||||
|
||||
// Basic report descriptor tests
|
||||
void test_unprepared_hidGetReportDescriptor( void )
|
||||
{
|
||||
|
||||
@@ -60,6 +60,18 @@ void test_get_next_valid_report_id( void ) {
|
||||
TEST_ASSERT_EQUAL_UINT( 0, reportId );
|
||||
}
|
||||
|
||||
void test_is_report_id_valid( void ) {
|
||||
unsigned isValid = 0;
|
||||
|
||||
unsigned reportId = 0;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 1, isValid );
|
||||
|
||||
reportId = 1;
|
||||
isValid = hidIsReportIdValid( reportId );
|
||||
TEST_ASSERT_EQUAL_UINT( 0, isValid );
|
||||
}
|
||||
|
||||
// Basic report descriptor tests
|
||||
void test_unprepared_hidGetReportDescriptor( void )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user