@ -316,6 +316,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
static int hidp_output_raw_report ( struct hid_device * hid , unsigned char * data , size_t count ,
unsigned char report_type )
{
struct hidp_session * session = hid - > driver_data ;
int ret ;
switch ( report_type ) {
case HID_FEATURE_REPORT :
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE ;
@ -327,10 +330,47 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
return - EINVAL ;
}
if ( mutex_lock_interruptible ( & session - > report_mutex ) )
return - ERESTARTSYS ;
/* Set up our wait, and send the report request to the device. */
set_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ;
if ( hidp_send_ctrl_message ( hid - > driver_data , report_type ,
data , count ) )
return - ENOMEM ;
return count ;
data , count ) ) {
ret = - ENOMEM ;
goto err ;
}
/* Wait for the ACK from the device. */
while ( test_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ) {
int res ;
res = wait_event_interruptible_timeout ( session - > report_queue ,
! test_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ,
10 * HZ ) ;
if ( res = = 0 ) {
/* timeout */
ret = - EIO ;
goto err ;
}
if ( res < 0 ) {
/* signal */
ret = - ERESTARTSYS ;
goto err ;
}
}
if ( ! session - > output_report_success ) {
ret = - EIO ;
goto err ;
}
ret = count ;
err :
clear_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ;
mutex_unlock ( & session - > report_mutex ) ;
return ret ;
}
static void hidp_idle_timeout ( unsigned long arg )
@ -357,10 +397,12 @@ static void hidp_process_handshake(struct hidp_session *session,
unsigned char param )
{
BT_DBG ( " session %p param 0x%02x " , session , param ) ;
session - > output_report_success = 0 ; /* default condition */
switch ( param ) {
case HIDP_HSHK_SUCCESSFUL :
/* FIXME: Call into SET_ GET_ handlers here */
session - > output_report_success = 1 ;
break ;
case HIDP_HSHK_NOT_READY :
@ -385,6 +427,12 @@ static void hidp_process_handshake(struct hidp_session *session,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER , NULL , 0 ) ;
break ;
}
/* Wake up the waiting thread. */
if ( test_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ) {
clear_bit ( HIDP_WAITING_FOR_SEND_ACK , & session - > flags ) ;
wake_up_interruptible ( & session - > report_queue ) ;
}
}
static void hidp_process_hid_control ( struct hidp_session * session ,