@@ -4,7 +4,7 @@ use anyhow::{ensure, Result};
44use clap:: Parser ;
55use nom:: { IResult , branch:: alt, bytes:: complete:: tag, character:: complete:: alpha1, combinator:: { map, map_res, value} , sequence:: preceded} ;
66
7- use super :: { Key , Keyboard , Macro , KeyboardEvent , Modifier , MouseEvent , MouseAction , send_message} ;
7+ use super :: { Key , Keyboard , Macro , KeyboardEvent , Modifier , MouseEvent , MouseAction , MouseModifier , send_message} ;
88
99
1010/// LED modes for the K8850 firmware (confirmed via hardware testing).
@@ -213,34 +213,36 @@ impl Keyboard for Keyboard8850 {
213213 msg. push ( 0x00 ) ; // [8]
214214 msg. push ( low) ; // [9] consumer code
215215 }
216- Macro :: Mouse ( MouseEvent ( MouseAction :: Move ( dx, dy) , modifier) ) => {
217- msg. push ( 0x00 ) ; // [6] binding_mode
218- msg. push ( 0x00 ) ; // [7]
219- msg. push ( 0x00 ) ; // [8]
220- msg. push ( 0x00 ) ; // [9]
221- msg. extend_from_slice ( & [ 0x05 , modifier. map_or ( 0 , |m| m as u8 ) , 0 , * dx as u8 , * dy as u8 ] ) ;
222- }
223- Macro :: Mouse ( MouseEvent ( MouseAction :: Drag ( buttons, dx, dy) , modifier) ) => {
224- msg. push ( 0x00 ) ; // [6]
225- msg. push ( 0x00 ) ; // [7]
226- msg. push ( 0x00 ) ; // [8]
227- msg. push ( 0x00 ) ; // [9]
228- msg. extend_from_slice ( & [ 0x05 , modifier. map_or ( 0 , |m| m as u8 ) , buttons. as_u8 ( ) , * dx as u8 , * dy as u8 ] ) ;
229- }
230- Macro :: Mouse ( MouseEvent ( MouseAction :: Click ( buttons) , modifier) ) => {
231- ensure ! ( !buttons. is_empty( ) , "buttons must be given for click macro" ) ;
232- msg. push ( 0x00 ) ; // [6]
233- msg. push ( 0x00 ) ; // [7]
234- msg. push ( 0x00 ) ; // [8]
235- msg. push ( 0x00 ) ; // [9]
236- msg. extend_from_slice ( & [ 0x01 , modifier. map_or ( 0 , |m| m as u8 ) , buttons. as_u8 ( ) ] ) ;
237- }
238- Macro :: Mouse ( MouseEvent ( MouseAction :: Wheel ( delta) , modifier) ) => {
239- msg. push ( 0x00 ) ; // [6]
240- msg. push ( 0x00 ) ; // [7]
241- msg. push ( 0x00 ) ; // [8]
242- msg. push ( 0x00 ) ; // [9]
243- msg. extend_from_slice ( & [ 0x03 , modifier. map_or ( 0 , |m| m as u8 ) , 0 , 0 , 0 , * delta as u8 ] ) ;
216+ Macro :: Mouse ( MouseEvent ( action, modifier) ) => {
217+ // 8850 mouse format (confirmed via Frida capture + PR #154 by yawor):
218+ // Position [5] in the full packet is the start of mouse_data (not 0x00 like keyboard).
219+ // Format: [1, 4, 0, 0, modifier, 0, 0, buttons, 0, 0, dx, 0, 0, dy, 0, 0, wheel]
220+ msg. pop ( ) ; // Remove the header's 0x00 at [5]; mouse_data provides its own bytes
221+ let mut mouse_data = [ 0u8 ; 17 ] ;
222+ mouse_data[ 0 ] = 1 ;
223+ mouse_data[ 1 ] = 4 ;
224+ mouse_data[ 4 ] = modifier. map_or ( 0 , |m| mouse_modifier_firmware_id ( m) ) ;
225+
226+ match action {
227+ MouseAction :: Move ( dx, dy) => {
228+ mouse_data[ 10 ] = * dx as u8 ;
229+ mouse_data[ 13 ] = * dy as u8 ;
230+ }
231+ MouseAction :: Drag ( buttons, dx, dy) => {
232+ mouse_data[ 7 ] = buttons. as_u8 ( ) ;
233+ mouse_data[ 10 ] = * dx as u8 ;
234+ mouse_data[ 13 ] = * dy as u8 ;
235+ }
236+ MouseAction :: Click ( buttons) => {
237+ ensure ! ( !buttons. is_empty( ) , "buttons must be given for click macro" ) ;
238+ mouse_data[ 7 ] = buttons. as_u8 ( ) ;
239+ }
240+ MouseAction :: Wheel ( delta) => {
241+ mouse_data[ 16 ] = * delta as u8 ;
242+ }
243+ }
244+
245+ msg. extend_from_slice ( & mouse_data) ;
244246 }
245247 } ;
246248
@@ -311,6 +313,15 @@ fn modifier_firmware_id(m: Modifier) -> u8 {
311313 }
312314}
313315
316+ /// Map a MouseModifier to the 8850 firmware's modifier ID.
317+ fn mouse_modifier_firmware_id ( m : MouseModifier ) -> u8 {
318+ match m {
319+ MouseModifier :: Ctrl => 0xF1 ,
320+ MouseModifier :: Shift => 0xF2 ,
321+ MouseModifier :: Alt => 0xF3 ,
322+ }
323+ }
324+
314325impl Keyboard8850 {
315326 pub fn new ( buttons : u8 , knobs : u8 ) -> Result < Self > {
316327 ensure ! ( buttons <= 16 && knobs <= 3 , "8850 supports up to 16 buttons and 3 knobs" ) ;
0 commit comments