@@ -65,6 +65,8 @@ struct spihid_interface {
6565 u32 max_input_report_len ;
6666 u32 max_output_report_len ;
6767 u8 name [32 ];
68+ u8 reply_buf [SPIHID_DESC_MAX ];
69+ u32 reply_len ;
6870 bool ready ;
6971};
7072
@@ -327,14 +329,33 @@ static int apple_ll_raw_request(struct hid_device *hdev,
327329{
328330 struct spihid_interface * idev = hdev -> driver_data ;
329331 struct spihid_apple * spihid = spihid_get_data (idev );
332+ int ret ;
330333
331334 dev_dbg (& spihid -> spidev -> dev ,
332335 "apple_ll_raw_request: device:%u reportnum:%hhu rtype:%hhu" ,
333336 idev -> id , reportnum , rtype );
334337
335338 switch (reqtype ) {
336339 case HID_REQ_GET_REPORT :
337- return - EINVAL ; // spihid_get_raw_report();
340+ if (rtype != HID_FEATURE_REPORT )
341+ return - EINVAL ;
342+
343+ idev -> reply_len = 0 ;
344+ ret = spihid_apple_request (spihid , idev -> id , 0x32 , reportnum , 0x00 , len , NULL , 0 );
345+ if (ret < 0 )
346+ return ret ;
347+
348+ ret = wait_event_interruptible_timeout (spihid -> wait , idev -> reply_len ,
349+ SPIHID_DEF_WAIT );
350+ if (ret == 0 )
351+ ret = - ETIMEDOUT ;
352+ if (ret < 0 ) {
353+ dev_err (& spihid -> spidev -> dev , "waiting for get report failed: %d" , ret );
354+ return ret ;
355+ }
356+ memcpy (buf , idev -> reply_buf , max_t (size_t , len , idev -> reply_len ));
357+ return idev -> reply_len ;
358+
338359 case HID_REQ_SET_REPORT :
339360 if (buf [0 ] != reportnum )
340361 return - EINVAL ;
@@ -606,7 +627,27 @@ static bool spihid_process_iface_hid_report_desc(struct spihid_apple *spihid,
606627 return true;
607628}
608629
609- static bool spihid_process_response (struct spihid_apple * spihid ,
630+ static bool spihid_process_iface_get_report (struct spihid_apple * spihid ,
631+ u32 device , u8 report ,
632+ u8 * payload , size_t len )
633+ {
634+ struct spihid_interface * iface = spihid_get_iface (spihid , device );
635+
636+ if (!iface )
637+ return false;
638+
639+ if (len > sizeof (iface -> reply_buf ) || len < 1 )
640+ return false;
641+
642+ memcpy (iface -> reply_buf , payload , len );
643+ iface -> reply_len = len ;
644+
645+ wake_up_interruptible (& spihid -> wait );
646+
647+ return true;
648+ }
649+
650+ static bool spihid_process_response (struct spihid_apple * spihid , u32 device ,
610651 struct spihid_msg_hdr * hdr , u8 * payload ,
611652 size_t len )
612653{
@@ -626,6 +667,10 @@ static bool spihid_process_response(struct spihid_apple *spihid,
626667 }
627668 }
628669
670+ if (hdr -> unknown0 == 0x32 ) {
671+ return spihid_process_iface_get_report (spihid , device , hdr -> unknown1 , payload , len );
672+ }
673+
629674 return false;
630675}
631676
@@ -653,7 +698,7 @@ static void spihid_process_message(struct spihid_apple *spihid, u8 *data,
653698 payload , le16_to_cpu (hdr -> length ));
654699 break ;
655700 case SPIHID_WRITE_PACKET :
656- handled = spihid_process_response (spihid , hdr , payload ,
701+ handled = spihid_process_response (spihid , device , hdr , payload ,
657702 le16_to_cpu (hdr -> length ));
658703 break ;
659704 default :
0 commit comments