Expand Up
@@ -121,7 +121,7 @@ static void __hidp_unlink_session(struct hidp_session *session)
module_put (THIS_MODULE );
}
static void __hidp_copy_session (struct hidp_session * session , struct hidp_conninfo * ci )
static void hidp_copy_session (struct hidp_session * session , struct hidp_conninfo * ci )
{
memset (ci , 0 , sizeof (* ci ));
bacpy (& ci -> bdaddr , & session -> bdaddr );
Expand Down
Expand Up
@@ -151,58 +151,80 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
}
}
static int hidp_queue_event (struct hidp_session * session , struct input_dev * dev ,
unsigned int type , unsigned int code , int value )
/* assemble skb, queue message on @transmit and wake up the session thread */
static int hidp_send_message (struct hidp_session * session , struct socket * sock ,
struct sk_buff_head * transmit , unsigned char hdr ,
const unsigned char * data , int size )
{
unsigned char newleds ;
struct sk_buff * skb ;
struct sock * sk = sock -> sk ;
BT_DBG ("session %p type %d code %d value %d" , session , type , code , value );
if (type != EV_LED )
return -1 ;
newleds = (!!test_bit (LED_KANA , dev -> led ) << 3 ) |
(!!test_bit (LED_COMPOSE , dev -> led ) << 3 ) |
(!!test_bit (LED_SCROLLL , dev -> led ) << 2 ) |
(!!test_bit (LED_CAPSL , dev -> led ) << 1 ) |
(!!test_bit (LED_NUML , dev -> led ));
if (session -> leds == newleds )
return 0 ;
BT_DBG ("session %p data %p size %d" , session , data , size );
session -> leds = newleds ;
if (atomic_read (& session -> terminate ))
return - EIO ;
skb = alloc_skb (3 , GFP_ATOMIC );
skb = alloc_skb (size + 1 , GFP_ATOMIC );
if (!skb ) {
BT_ERR ("Can't allocate memory for new frame" );
return - ENOMEM ;
}
* skb_put (skb , 1 ) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT ;
* skb_put (skb , 1 ) = 0x01 ;
* skb_put (skb , 1 ) = newleds ;
skb_queue_tail (& session -> intr_transmit , skb );
* skb_put (skb , 1 ) = hdr ;
if (data && size > 0 )
memcpy (skb_put (skb , size ), data , size );
hidp_schedule (session );
skb_queue_tail (transmit , skb );
wake_up_interruptible (sk_sleep (sk ));
return 0 ;
}
static int hidp_hidinput_event (struct input_dev * dev , unsigned int type , unsigned int code , int value )
static int hidp_send_ctrl_message (struct hidp_session * session ,
unsigned char hdr , const unsigned char * data ,
int size )
{
struct hid_device * hid = input_get_drvdata (dev );
struct hidp_session * session = hid -> driver_data ;
return hidp_send_message (session , session -> ctrl_sock ,
& session -> ctrl_transmit , hdr , data , size );
}
return hidp_queue_event (session , dev , type , code , value );
static int hidp_send_intr_message (struct hidp_session * session ,
unsigned char hdr , const unsigned char * data ,
int size )
{
return hidp_send_message (session , session -> intr_sock ,
& session -> intr_transmit , hdr , data , size );
}
static int hidp_input_event (struct input_dev * dev , unsigned int type , unsigned int code , int value )
static int hidp_input_event (struct input_dev * dev , unsigned int type ,
unsigned int code , int value )
{
struct hidp_session * session = input_get_drvdata (dev );
unsigned char newleds ;
unsigned char hdr , data [2 ];
BT_DBG ("session %p type %d code %d value %d" ,
session , type , code , value );
return hidp_queue_event (session , dev , type , code , value );
if (type != EV_LED )
return -1 ;
newleds = (!!test_bit (LED_KANA , dev -> led ) << 3 ) |
(!!test_bit (LED_COMPOSE , dev -> led ) << 3 ) |
(!!test_bit (LED_SCROLLL , dev -> led ) << 2 ) |
(!!test_bit (LED_CAPSL , dev -> led ) << 1 ) |
(!!test_bit (LED_NUML , dev -> led ));
if (session -> leds == newleds )
return 0 ;
session -> leds = newleds ;
hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT ;
data [0 ] = 0x01 ;
data [1 ] = newleds ;
return hidp_send_intr_message (session , hdr , data , 2 );
}
static void hidp_input_report (struct hidp_session * session , struct sk_buff * skb )
Expand Down
Expand Up
@@ -260,94 +282,61 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync (dev );
}
static int __hidp_send_ctrl_message (struct hidp_session * session ,
unsigned char hdr , unsigned char * data , int size )
static int hidp_send_report (struct hidp_session * session , struct hid_report * report )
{
struct sk_buff * skb ;
BT_DBG ("session %p data %p size %d" , session , data , size );
skb = alloc_skb (size + 1 , GFP_ATOMIC );
if (!skb ) {
BT_ERR ("Can't allocate memory for new frame" );
return - ENOMEM ;
}
unsigned char buf [32 ], hdr ;
int rsize ;
* skb_put ( skb , 1 ) = hdr ;
if (data && size > 0 )
memcpy ( skb_put ( skb , size ), data , size ) ;
rsize = (( report -> size - 1 ) >> 3 ) + 1 + ( report -> id > 0 ) ;
if (rsize > sizeof ( buf ) )
return - EIO ;
skb_queue_tail (& session -> ctrl_transmit , skb );
hid_output_report (report , buf );
hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT ;
return 0 ;
return hidp_send_intr_message ( session , hdr , buf , rsize ) ;
}
static inline int hidp_send_ctrl_message (struct hidp_session * session ,
unsigned char hdr , unsigned char * data , int size )
static int hidp_hidinput_event (struct input_dev * dev , unsigned int type ,
unsigned int code , int value )
{
int err ;
err = __hidp_send_ctrl_message (session , hdr , data , size );
hidp_schedule (session );
return err ;
}
struct hid_device * hid = input_get_drvdata (dev );
struct hidp_session * session = hid -> driver_data ;
struct hid_field * field ;
int offset ;
static int hidp_queue_report (struct hidp_session * session ,
unsigned char * data , int size )
{
struct sk_buff * skb ;
BT_DBG ("session %p type %d code %d value %d" ,
session , type , code , value );
BT_DBG ("session %p hid %p data %p size %d" , session , session -> hid , data , size );
if (type != EV_LED )
return -1 ;
skb = alloc_skb ( size + 1 , GFP_ATOMIC );
if (! skb ) {
BT_ERR ( "Can't allocate memory for new frame " );
return - ENOMEM ;
offset = hidinput_find_field ( hid , type , code , & field );
if (offset == -1 ) {
hid_warn ( dev , "event field not found\n " );
return -1 ;
}
* skb_put (skb , 1 ) = 0xa2 ;
if (size > 0 )
memcpy (skb_put (skb , size ), data , size );
skb_queue_tail (& session -> intr_transmit , skb );
hid_set_field (field , offset , value );
hidp_schedule (session );
return 0 ;
}
static int hidp_send_report (struct hidp_session * session , struct hid_report * report )
{
unsigned char buf [32 ];
int rsize ;
rsize = ((report -> size - 1 ) >> 3 ) + 1 + (report -> id > 0 );
if (rsize > sizeof (buf ))
return - EIO ;
hid_output_report (report , buf );
return hidp_queue_report (session , buf , rsize );
return hidp_send_report (session , field -> report );
}
static int hidp_output_raw_report (struct hid_device * hid , unsigned char * data , size_t count ,
unsigned char report_type )
{
switch (report_type ) {
case HID_FEATURE_REPORT :
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE ;
break ;
case HID_OUTPUT_REPORT :
struct hidp_session * session = hid -> driver_data ;
if (report_type == HID_OUTPUT_REPORT ) {
report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT ;
break ;
default :
return hidp_send_intr_message (session , report_type ,
data , count );
} else if (report_type != HID_FEATURE_REPORT ) {
return - EINVAL ;
}
if ( hidp_send_ctrl_message ( hid -> driver_data , report_type ,
data , count ))
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE ;
if ( hidp_send_ctrl_message ( session , report_type , data , count ))
return - ENOMEM ;
return count ;
}
Expand Down
Expand Up
@@ -395,12 +384,12 @@ static void hidp_process_handshake(struct hidp_session *session,
case HIDP_HSHK_ERR_FATAL :
/* Device requests a reboot, as this is the only way this error
* can be recovered. */
__hidp_send_ctrl_message (session ,
hidp_send_ctrl_message (session ,
HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET , NULL , 0 );
break ;
default :
__hidp_send_ctrl_message (session ,
hidp_send_ctrl_message (session ,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER , NULL , 0 );
break ;
}
Expand Down
Expand Up
@@ -445,7 +434,7 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
break ;
default :
__hidp_send_ctrl_message (session ,
hidp_send_ctrl_message (session ,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER , NULL , 0 );
}
}
Expand Down
Expand Up
@@ -477,7 +466,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break ;
default :
__hidp_send_ctrl_message (session ,
hidp_send_ctrl_message (session ,
HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST , NULL , 0 );
break ;
}
Expand Down
Expand Up
@@ -751,17 +740,6 @@ static int hidp_parse(struct hid_device *hid)
static int hidp_start (struct hid_device * hid )
{
struct hidp_session * session = hid -> driver_data ;
struct hid_report * report ;
list_for_each_entry (report , & hid -> report_enum [HID_INPUT_REPORT ].
report_list , list )
hidp_send_report (session , report );
list_for_each_entry (report , & hid -> report_enum [HID_FEATURE_REPORT ].
report_list , list )
hidp_send_report (session , report );
return 0 ;
}
Expand Down
Expand Up
@@ -1003,7 +981,7 @@ int hidp_get_connlist(struct hidp_connlist_req *req)
session = list_entry (p , struct hidp_session , list );
__hidp_copy_session (session , & ci );
hidp_copy_session (session , & ci );
if (copy_to_user (req -> ci , & ci , sizeof (ci ))) {
err = - EFAULT ;
Expand All
@@ -1030,7 +1008,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
session = __hidp_get_session (& ci -> bdaddr );
if (session )
__hidp_copy_session (session , ci );
hidp_copy_session (session , ci );
else
err = - ENOENT ;
Expand Down