55//!
66//! Copyright (C) The Asahi Linux Contributors
77
8- use core:: { arch:: asm, mem, ptr, slice} ;
8+ use core:: { arch:: asm, cmp , mem, ptr, slice} ;
99
1010use kernel:: {
1111 bindings, c_str, device,
@@ -23,6 +23,7 @@ use kernel::{
2323 workqueue:: { self , impl_has_work, new_work, Work , WorkItem } ,
2424} ;
2525
26+ const AOP_MAX_CALLS : usize = 8 ;
2627const AOP_MMIO_SIZE : usize = 0x1e0000 ;
2728const ASC_MMIO_SIZE : usize = 0x4000 ;
2829const BOOTARGS_OFFSET : usize = 0x22c ;
@@ -54,6 +55,7 @@ const EPIC_SUBTYPE_STD_SERVICE: u16 = 0xc0;
5455const EPIC_SUBTYPE_FAKEHID_REPORT : u16 = 0xc4 ;
5556const EPIC_SUBTYPE_RETCODE : u16 = 0x84 ;
5657const EPIC_SUBTYPE_RETCODE_PAYLOAD : u16 = 0xa0 ;
58+ const EPIC_SUBTYPE_STRING : u16 = 0x8a ;
5759const QE_MAGIC1 : u32 = from_fourcc ( b" POI" ) ;
5860const QE_MAGIC2 : u32 = from_fourcc ( b" POA" ) ;
5961
@@ -115,7 +117,7 @@ struct FutureValue<T> {
115117 completion : CondVar ,
116118}
117119
118- impl < T : Clone > FutureValue < T > {
120+ impl < T > FutureValue < T > {
119121 fn pin_init ( ) -> impl PinInit < FutureValue < T > > {
120122 pin_init ! (
121123 FutureValue {
@@ -133,7 +135,7 @@ impl<T: Clone> FutureValue<T> {
133135 while ret_guard. is_none ( ) {
134136 self . completion . wait ( & mut ret_guard) ;
135137 }
136- ret_guard. as_ref ( ) . unwrap ( ) . clone ( )
138+ ret_guard. take ( ) . unwrap ( )
137139 }
138140 fn reset ( & self ) {
139141 * self . val . lock ( ) = None ;
@@ -146,13 +148,19 @@ struct AFKRingBuffer {
146148 buf_size : usize ,
147149}
148150
151+ struct CallResult {
152+ retcode : u32 ,
153+ extra_data : Option < KVec < u8 > > ,
154+ }
155+
149156struct AFKEndpoint {
150157 index : u8 ,
151158 iomem : Option < CoherentAllocation < u8 > > ,
152159 txbuf : Option < AFKRingBuffer > ,
153160 rxbuf : Option < AFKRingBuffer > ,
154161 seq : u16 ,
155- calls : [ Option < Arc < FutureValue < u32 > > > ; 8 ] ,
162+ calls : [ Option < Arc < FutureValue < CallResult > > > ; AOP_MAX_CALLS ] ,
163+ call_returns : [ Option < KVec < u8 > > ; AOP_MAX_CALLS ] ,
156164}
157165
158166unsafe impl Send for AFKEndpoint { }
@@ -165,7 +173,8 @@ impl AFKEndpoint {
165173 txbuf : None ,
166174 rxbuf : None ,
167175 seq : 0 ,
168- calls : [ const { None } ; 8 ] ,
176+ calls : [ const { None } ; AOP_MAX_CALLS ] ,
177+ call_returns : [ const { None } ; AOP_MAX_CALLS ] ,
169178 }
170179 }
171180
@@ -409,7 +418,10 @@ impl AFKEndpoint {
409418 return Err ( EIO ) ;
410419 }
411420 } else if ehdr. category == EPIC_CATEGORY_REPLY {
412- if subtype == EPIC_SUBTYPE_RETCODE_PAYLOAD || subtype == EPIC_SUBTYPE_RETCODE {
421+ if subtype == EPIC_SUBTYPE_RETCODE_PAYLOAD
422+ || subtype == EPIC_SUBTYPE_RETCODE
423+ || subtype == EPIC_SUBTYPE_STRING
424+ {
413425 if data. len ( ) < mem:: size_of :: < u32 > ( ) {
414426 dev_err ! (
415427 client. dev,
@@ -429,7 +441,20 @@ impl AFKEndpoint {
429441 ) ;
430442 return Err ( EIO ) ;
431443 }
432- self . calls [ tag - 1 ] . take ( ) . unwrap ( ) . complete ( retcode) ;
444+ let future = self . calls [ tag - 1 ] . take ( ) . unwrap ( ) ;
445+ let extra_data = if let Some ( mut ret) = self . call_returns [ tag - 1 ] . take ( ) {
446+ let len = cmp:: min ( data. len ( ) - 4 , ret. len ( ) ) ;
447+ ret[ ..len] . copy_from_slice ( & data[ 4 ..( len + 4 ) ] ) ;
448+ ret. truncate ( len) ;
449+ Some ( ret)
450+ } else {
451+ None
452+ } ;
453+ future. complete ( CallResult {
454+ retcode,
455+ extra_data,
456+ } ) ;
457+
433458 return Ok ( ( ) ) ;
434459 } else {
435460 dev_err ! (
@@ -510,7 +535,8 @@ impl AFKEndpoint {
510535 channel : u32 ,
511536 subtype : u16 ,
512537 data : & [ u8 ] ,
513- ) -> Result < Arc < FutureValue < u32 > > > {
538+ ret : Option < KVec < u8 > > ,
539+ ) -> Result < Arc < FutureValue < CallResult > > > {
514540 let mut tag = 0 ;
515541 for i in 0 ..self . calls . len ( ) {
516542 if self . calls [ i] . is_none ( ) {
@@ -537,6 +563,7 @@ impl AFKEndpoint {
537563 tag : tag as u16 ,
538564 ..EPICHeader :: default ( )
539565 } ;
566+ self . call_returns [ tag - 1 ] = ret;
540567 self . send_rb (
541568 client,
542569 rtkit,
@@ -785,9 +812,28 @@ impl AOP for AopData {
785812 let mut rtk_guard = self . rtkit . lock ( ) ;
786813 let rtk = rtk_guard. as_mut ( ) . unwrap ( ) ;
787814 let mut ep_guard = self . endpoints [ ep_idx as usize ] . lock ( ) ;
788- ep_guard. epic_notify ( self , rtk, svc. channel , subtype, msg_bytes) ?
815+ ep_guard. epic_notify ( self , rtk, svc. channel , subtype, msg_bytes, None ) ?
816+ } ;
817+ Ok ( call. wait ( ) . retcode )
818+ }
819+ fn epic_call_ret (
820+ & self ,
821+ svc : & EPICService ,
822+ subtype : u16 ,
823+ msg_bytes : & [ u8 ] ,
824+ ret_len : usize ,
825+ ) -> Result < ( u32 , KVec < u8 > ) > {
826+ let ep_idx = svc. endpoint - AFK_ENDPOINT_START ;
827+ let call = {
828+ let mut rtk_guard = self . rtkit . lock ( ) ;
829+ let rtk = rtk_guard. as_mut ( ) . unwrap ( ) ;
830+ let mut ep_guard = self . endpoints [ ep_idx as usize ] . lock ( ) ;
831+ let mut ret_buf = KVec :: new ( ) ;
832+ ret_buf. resize ( ret_len, 0 , GFP_KERNEL ) ?;
833+ ep_guard. epic_notify ( self , rtk, svc. channel , subtype, msg_bytes, Some ( ret_buf) ) ?
789834 } ;
790- Ok ( call. wait ( ) )
835+ let res = call. wait ( ) ;
836+ Ok ( ( res. retcode , res. extra_data . unwrap ( ) ) )
791837 }
792838 fn add_fakehid_listener (
793839 & self ,
0 commit comments