Skip to content

Commit

Permalink
Merge pull request #13 from thewh1teagle/Feat/abs-rel-mouse
Browse files Browse the repository at this point in the history
Feat/abs rel mouse
  • Loading branch information
thewh1teagle committed Dec 4, 2023
2 parents 8c77778 + f1ba13d commit 55878ea
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 36 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Note: You should connect the data usb port (left one) to the raspberry, and NOT
from zero_hid import Mouse
m = Mouse()
for i in range(5):
m.move_relative(10, 10)
m.move(10, 10)
```
- Control keyboard
```python
Expand All @@ -37,6 +37,9 @@ k = Keyboard()
k.type('Hello world!')
```

## Examples
see [examples](examples)

## Tests
| Raspberry Pi Model | Raspbian Version | Kernel Version |
|---------------------|-------------------|----------------|
Expand Down
5 changes: 5 additions & 0 deletions examples/absolute_mouse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from zero_hid import Mouse

m = Mouse(absolute=True)
m.move(50,50)
m.close()
4 changes: 1 addition & 3 deletions examples/mouse_example.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from zero_hid import Mouse



m = Mouse()
for i in range(5):
m.move_relative(5,5)
m.move(5,5)
m.close()
2 changes: 1 addition & 1 deletion tests/mouse_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_left_click():
def test_move():
with open(random_file(), 'ab+') as f:
m = Mouse(f)
m.move_relative(100, 100)
m.move(100, 100)
f.seek(0)
data = f.read()
f.close()
Expand Down
81 changes: 69 additions & 12 deletions usb_gadget/init_usb_gadget
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ D=$(mktemp)
} >> "$D"
cp "$D" "${KEYBOARD_FUNCTIONS_DIR}/report_desc"

# Mouse
MOUSE_FUNCTIONS_DIR="functions/hid.mouse"
mkdir -p "$MOUSE_FUNCTIONS_DIR"
echo 0 > "${MOUSE_FUNCTIONS_DIR}/protocol"
echo 0 > "${MOUSE_FUNCTIONS_DIR}/subclass"
echo 7 > "${MOUSE_FUNCTIONS_DIR}/report_length"
# Mouse Relative
MOUSE_RELATIVE_FUNCTIONS_DIR="functions/hid.mouse_relative"
mkdir -p "$MOUSE_RELATIVE_FUNCTIONS_DIR"
echo 0 > "${MOUSE_RELATIVE_FUNCTIONS_DIR}/protocol"
echo 0 > "${MOUSE_RELATIVE_FUNCTIONS_DIR}/subclass"
echo 7 > "${MOUSE_RELATIVE_FUNCTIONS_DIR}/report_length"
# Write the report descriptor
D=$(mktemp)
{
Expand All @@ -95,15 +95,69 @@ echo -ne \\x25\\x01 # LOGICAL_MAXIMUM (1)
echo -ne \\x95\\x08 # REPORT_COUNT (8)
echo -ne \\x75\\x01 # REPORT_SIZE (1)
echo -ne \\x81\\x02 # INPUT (Data,Var,Abs)

# x,y relative coordinates
echo -ne \\x05\\x01 # USAGE_PAGE (Generic Desktop)
echo -ne \\x09\\x30 # USAGE (X)
echo -ne \\x09\\x31 # USAGE (Y)
echo -ne \\x15\\x81 # LOGICAL_MINIMUM (-127)
echo -ne \\x25\\x7f # LOGICAL_MAXIMUM (127)
echo -ne \\x15\\x81 # LOGICAL_MINIMUM (-127)
echo -ne \\x25\\x7f # LOGICAL_MAXIMUM (127)
echo -ne \\x75\\x08 # REPORT_SIZE (16)
echo -ne \\x95\\x02 # REPORT_COUNT (2)
echo -ne \\x81\\x06 # INPUT (Data,Var,Rel)

# vertical wheel
echo -ne \\x09\\x38 # USAGE (wheel)
echo -ne \\x15\\x81 # LOGICAL_MINIMUM (-127)
echo -ne \\x25\\x7F # LOGICAL_MAXIMUM (127)
echo -ne \\x75\\x08 # REPORT_SIZE (8)
echo -ne \\x95\\x01 # REPORT_COUNT (1)
echo -ne \\x81\\x06 # INPUT (Data,Var,Rel)
# horizontal wheel
echo -ne \\x05\\x0C # USAGE_PAGE (Consumer Devices)
echo -ne \\x0A\\x38\\x02 # USAGE (AC Pan)
echo -ne \\x15\\x81 # LOGICAL_MINIMUM (-127)
echo -ne \\x25\\x7F # LOGICAL_MAXIMUM (127)
echo -ne \\x75\\x08 # REPORT_SIZE (8)
echo -ne \\x95\\x01 # REPORT_COUNT (1)
echo -ne \\x81\\x06 # INPUT (Data,Var,Rel)
echo -ne \\xC0 # END_COLLECTION
} >> "$D"
cp "$D" "${MOUSE_RELATIVE_FUNCTIONS_DIR}/report_desc"

# Mouse Absolute
MOUSE_ABSOLUTE_FUNCTIONS_DIR="functions/hid.mouse_absolute"
mkdir -p "$MOUSE_ABSOLUTE_FUNCTIONS_DIR"
echo 0 > "${MOUSE_ABSOLUTE_FUNCTIONS_DIR}/protocol"
echo 0 > "${MOUSE_ABSOLUTE_FUNCTIONS_DIR}/subclass"
echo 7 > "${MOUSE_ABSOLUTE_FUNCTIONS_DIR}/report_length"
# Write the report descriptor
D=$(mktemp)
{
echo -ne \\x05\\x01 # USAGE_PAGE (Generic Desktop)
echo -ne \\x09\\x02 # USAGE (Mouse)
echo -ne \\xA1\\x01 # COLLECTION (Application)
# 8-buttons
echo -ne \\x05\\x09 # USAGE_PAGE (Button)
echo -ne \\x19\\x01 # USAGE_MINIMUM (Button 1)
echo -ne \\x29\\x08 # USAGE_MAXIMUM (Button 8)
echo -ne \\x15\\x00 # LOGICAL_MINIMUM (0)
echo -ne \\x25\\x01 # LOGICAL_MAXIMUM (1)
echo -ne \\x95\\x08 # REPORT_COUNT (8)
echo -ne \\x75\\x01 # REPORT_SIZE (1)
echo -ne \\x81\\x02 # INPUT (Data,Var,Abs)


# x,y absolute coordinates
echo -ne \\x05\\x01 # USAGE_PAGE (Generic Desktop)
echo -ne \\x09\\x30 # USAGE (X)
echo -ne \\x09\\x31 # USAGE (Y)
echo -ne \\x15\\x00 # LOGICAL_MINIMUM (0)
echo -ne \\x26\\xff\\x7f # LOGICAL_MAXIMUM (65535)
echo -ne \\x75\\x10 # REPORT_SIZE (16)
echo -ne \\x95\\x02 # REPORT_COUNT (2)
echo -ne \\x81\\x02 # INPUT (Data,Var,RAbs)

# vertical wheel
echo -ne \\x09\\x38 # USAGE (wheel)
echo -ne \\x15\\x81 # LOGICAL_MINIMUM (-127)
Expand All @@ -121,7 +175,7 @@ echo -ne \\x95\\x01 # REPORT_COUNT (1)
echo -ne \\x81\\x06 # INPUT (Data,Var,Rel)
echo -ne \\xC0 # END_COLLECTION
} >> "$D"
cp "$D" "${MOUSE_FUNCTIONS_DIR}/report_desc"
cp "$D" "${MOUSE_ABSOLUTE_FUNCTIONS_DIR}/report_desc"

CONFIG_INDEX=1
CONFIGS_DIR="configs/c.${CONFIG_INDEX}"
Expand All @@ -133,8 +187,11 @@ mkdir -p "$CONFIGS_STRINGS_DIR"
echo "Config ${CONFIG_INDEX}: ECM network" > "${CONFIGS_STRINGS_DIR}/configuration"

ln -s "$KEYBOARD_FUNCTIONS_DIR" "${CONFIGS_DIR}/"
ln -s "$MOUSE_FUNCTIONS_DIR" "${CONFIGS_DIR}/"
ln -s "$MOUSE_RELATIVE_FUNCTIONS_DIR" "${CONFIGS_DIR}/"
ln -s "$MOUSE_ABSOLUTE_FUNCTIONS_DIR" "${CONFIGS_DIR}/"
ls /sys/class/udc > UDC

chmod 777 /dev/hidg0
chmod 777 /dev/hidg1
chmod 777 /dev/hidg0 # Keyboard
chmod 777 /dev/hidg1 # Mouse Relative
chmod 777 /dev/hidg2 # Mouse Absolute

3 changes: 2 additions & 1 deletion zero_hid/Keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .hid.keyboard import send_keystroke, release_keys
from .hid.keycodes import KeyCodes
from . import defaults
from time import sleep
import json
import operator
Expand All @@ -12,7 +13,7 @@

class Keyboard:

def __init__(self, dev='/dev/hidg0') -> None:
def __init__(self, dev=defaults.KEYBOARD_PATH) -> None:
if not hasattr(dev, 'write'): # check if file like object
self.dev = open(dev, 'ab+')
else:
Expand Down
33 changes: 21 additions & 12 deletions zero_hid/Mouse.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
from .hid.mouse import send_mouse_event
from . import defaults
from .hid.mouse import relative_mouse_event, absolute_mouse_event
from typing import SupportsInt


class RelativeMoveRangeError(Exception):
pass


class Mouse:
def __init__(self, dev='/dev/hidg1') -> None:
def __init__(self, dev = None, absolute = False) -> None:
if dev is None:
dev = defaults.ABSOLUTE_MOUSE_PATH if absolute else defaults.RELATIVE_MOUSE_PATH
self.move = self.__move_absolute if absolute else self.__move_relative # dynamic move method
self.__send_mouse_event = absolute_mouse_event if absolute else relative_mouse_event # dynamic mouse event method
if not hasattr(dev, 'write'): # check if file like object
self.dev = open(dev, 'ab+')
else:
self.dev = dev


def left_click(self):
send_mouse_event(self.dev, 0x1, 0, 0, 0, 0)
send_mouse_event(self.dev, 0x0, 0, 0, 0, 0)
self.__send_mouse_event(self.dev, 0x1, 0, 0, 0, 0)
self.__send_mouse_event(self.dev, 0x0, 0, 0, 0, 0)

def right_click(self):
send_mouse_event(self.dev, 0x1, 0, 0, 0, 0)
send_mouse_event(self.dev, 0x2, 0, 0, 0, 0)
def move_relative(self, x, y):
self.__send_mouse_event(self.dev, 0x2, 0, 0, 0, 0)
self.__send_mouse_event(self.dev, 0x0, 0, 0, 0, 0)

def __move_relative(self, x, y):
"""
move the mouse in relative mode
x,y should be in range of -127 to 127
"""
if not -127 <= x <= 127:
raise RelativeMoveRangeError(f"Value of x: {x} out of range (-127 - 127)")
if not -127 <= y <= 127:
RelativeMoveRangeError(f"Value of x: {y} out of range (-127 - 127)")
send_mouse_event(self.dev, 0x0, x, y, 0, 0)
RelativeMoveRangeError(f"Value of y: {y} out of range (-127 - 127)")
self.__send_mouse_event(self.dev, 0x0, x, y, 0, 0)

def __move_absolute(self, x, y):
if not 0 <= x <= 65535:
raise RelativeMoveRangeError(f"Value of x: {x} out of range (0 - 65535)")
if not 0 <= y <= 65535:
RelativeMoveRangeError(f"Value of y: {y} out of range (0 - 65535)")
self.__send_mouse_event(self.dev, 0x0, x, y, 0, 0)


def __enter__(self):
Expand Down
8 changes: 7 additions & 1 deletion zero_hid/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from .Mouse import Mouse
from .Keyboard import Keyboard
from .hid.keycodes import KeyCodes
from . import defaults

__all__ = ['Mouse', 'Keyboard', 'KeyCodes']
__all__ = [
'Mouse',
'Keyboard',
'KeyCodes',
'defaults'
]
3 changes: 3 additions & 0 deletions zero_hid/defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
KEYBOARD_PATH = '/dev/hidg0'
RELATIVE_MOUSE_PATH = '/dev/hidg1'
ABSOLUTE_MOUSE_PATH = '/dev/hidg2'
23 changes: 18 additions & 5 deletions zero_hid/hid/mouse.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
from . import write as hid_write

def send_mouse_event(dev, buttons, relative_x, relative_y,
vertical_wheel_delta, horizontal_wheel_delta):
def relative_mouse_event(dev, buttons, x, y,
vertical_wheel_delta, horizontal_wheel_delta, absolute = False):
buf = [
buttons,
relative_x & 0xff,
relative_y & 0xff,
x & 0xff,
y & 0xff,
vertical_wheel_delta & 0xff,
horizontal_wheel_delta & 0xff
]
hid_write.write_to_hid_interface(dev, buf)



def absolute_mouse_event(dev, buttons, x, y,
vertical_wheel_delta, horizontal_wheel_delta):
buf = [
buttons,
x & 0xff,
(x >> 8) & 0xff, # Extract the upper byte of x
y & 0xff,
(y >> 8) & 0xff, # Extract the upper byte of y
vertical_wheel_delta & 0xff,
horizontal_wheel_delta & 0xff
]
hid_write.write_to_hid_interface(dev, buf)

0 comments on commit 55878ea

Please sign in to comment.