@@ -117,7 +121,7 @@ export default function SettingsKeyboardMouseRoute() {
diff --git a/usb.go b/usb.go
index 0be8bd0..6989ed4 100644
--- a/usb.go
+++ b/usb.go
@@ -74,7 +74,18 @@ var gadgetConfig = map[string]gadgetConfigItem{
"subclass": "1",
"report_length": "6",
},
- reportDesc: CombinedMouseReportDesc,
+ reportDesc: CombinedAbsoluteMouseReportDesc,
+ },
+ // relative mouse HID
+ "relative_mouse": {
+ path: []string{"functions", "hid.usb2"},
+ configPath: path.Join(configC1Path, "hid.usb2"),
+ attrs: gadgetAttributes{
+ "protocol": "2",
+ "subclass": "1",
+ "report_length": "4",
+ },
+ reportDesc: CombinedRelativeMouseReportDesc,
},
// mass storage
"mass_storage_base": {
@@ -311,10 +322,14 @@ func rebindUsb(ignoreUnbindError bool) error {
return nil
}
-var keyboardHidFile *os.File
-var keyboardLock = sync.Mutex{}
-var mouseHidFile *os.File
-var mouseLock = sync.Mutex{}
+var (
+ keyboardHidFile *os.File
+ keyboardLock = sync.Mutex{}
+ mouseHidFile *os.File
+ mouseLock = sync.Mutex{}
+ relMouseHidFile *os.File
+ relMouseLock = sync.Mutex{}
+)
func rpcKeyboardReport(modifier uint8, keys []uint8) error {
keyboardLock.Lock()
@@ -406,6 +421,32 @@ func abs(x float64) float64 {
return x
}
+func rpcRelMouseReport(mx, my int8, buttons uint8) error {
+ relMouseLock.Lock()
+ defer relMouseLock.Unlock()
+ if relMouseHidFile == nil {
+ var err error
+ relMouseHidFile, err = os.OpenFile("/dev/hidg2", os.O_RDWR, 0666)
+ if err != nil {
+ return fmt.Errorf("failed to open hidg2: %w", err)
+ }
+ }
+ resetUserInputTime()
+ _, err := relMouseHidFile.Write([]byte{
+ buttons, // Buttons
+ uint8(mx), // X
+ uint8(my), // Y
+ 0, // Wheel
+ })
+ if err != nil {
+ logger.Errorf("failed to write to hidg2: %v", err)
+ relMouseHidFile.Close()
+ relMouseHidFile = nil
+ return err
+ }
+ return nil
+}
+
var usbState = "unknown"
func rpcGetUSBState() (state string) {
@@ -482,7 +523,7 @@ var KeyboardReportDesc = []byte{
}
// Combined absolute and relative mouse report descriptor with report ID
-var CombinedMouseReportDesc = []byte{
+var CombinedAbsoluteMouseReportDesc = []byte{
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
@@ -525,3 +566,39 @@ var CombinedMouseReportDesc = []byte{
0xC0, // End Collection
}
+
+var CombinedRelativeMouseReportDesc = []byte{
+ // from: https://github.com/NicoHood/HID/blob/b16be57caef4295c6cd382a7e4c64db5073647f7/src/SingleReport/BootMouse.cpp#L26
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 54
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+
+ // Pointer and Physical are required by Apple Recovery
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+
+ // 8 Buttons
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x08, // USAGE_MAXIMUM (Button 8)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x08, // REPORT_COUNT (8)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+
+ // X, Y, Wheel
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x03, // REPORT_COUNT (3)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+
+ // End
+ 0xc0, // End Collection (Physical)
+ 0xc0, // End Collection
+}