uidevices/mouse/
protocol.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![expect(dead_code)]
5
6use guid::Guid;
7use static_assertions::const_assert_eq;
8use std::fmt;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13
14//cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a
15pub const INTERFACE_GUID: Guid = guid::guid!("cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a");
16
17//58f75a6d-d949-4320-99e1-a2a2576d581c
18pub const INSTANCE_GUID: Guid = guid::guid!("58f75a6d-d949-4320-99e1-a2a2576d581c");
19
20//SynthHID protocol
21const fn make_version(major: u16, minor: u16) -> u32 {
22    (minor as u32) | ((major as u32) << 16)
23}
24
25pub const SYNTHHID_INPUT_VERSION: u32 = make_version(2, 0);
26
27pub const SYNTHHID_PROTOCOL_REQUEST: u32 = 0;
28pub const SYNTHHID_PROTOCOL_RESPONSE: u32 = 1;
29pub const SYNTHHID_INIT_DEVICE_INFO: u32 = 2;
30pub const SYNTHHID_INIT_DEVICE_INFO_ACK: u32 = 3;
31pub const SYNTHHID_PROTOCOL_INPUT_REPORT: u32 = 4;
32pub const SYNTHHID_HID_MAX: u32 = 5;
33
34pub const HID_VENDOR_ID: u16 = 0x045e;
35pub const HID_PRODUCT_ID: u16 = 0x0621;
36pub const HID_VERSION_ID: u16 = 0x0001;
37
38pub const SYNTHHID_INPUT_REPORT_SIZE: u8 = 16;
39pub const MAX_HID_MESSAGE_SIZE: u16 = 512;
40pub const MAX_HID_REPORT_DESCRIPTOR: u16 = 256;
41
42//HID Protocol Structs
43#[repr(C)]
44#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
45pub struct HidAttributes {
46    pub size: u32,
47    pub vendor_id: u16,
48    pub product_id: u16,
49    pub version_id: u16,
50    pub padding: [u16; 11],
51}
52
53const_assert_eq!(0x20, size_of::<HidAttributes>());
54
55#[repr(C, packed)]
56#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
57pub struct HidDescriptor {
58    pub length: u8,
59    pub descriptor_type: u8,
60    pub hid: u16,
61    pub country: u8,
62    pub num_descriptors: u8,
63    pub descriptor_list: HidDescriptorList,
64}
65
66const_assert_eq!(0x9, size_of::<HidDescriptor>());
67
68#[repr(C, packed)]
69#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
70pub struct HidDescriptorList {
71    pub report_type: u8,
72    pub report_length: u16,
73}
74
75const_assert_eq!(0x3, size_of::<HidDescriptorList>());
76
77#[repr(C)]
78#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
79pub struct MessageHeader {
80    pub message_type: u32,
81    pub message_size: u32,
82}
83
84const_assert_eq!(0x8, size_of::<MessageHeader>());
85
86#[repr(C)]
87#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
88pub struct MessageProtocolRequest {
89    pub version: u32,
90}
91
92const_assert_eq!(0x4, size_of::<MessageProtocolRequest>());
93
94#[repr(C, packed)]
95#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
96pub struct MessageProtocolResponse {
97    pub version_requested: u32,
98    pub accepted: u8,
99}
100
101const_assert_eq!(0x5, size_of::<MessageProtocolResponse>());
102
103#[repr(C, packed)]
104#[derive(Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
105pub struct MessageDeviceInfo {
106    pub device_attributes: HidAttributes,
107    pub descriptor_info: HidDescriptor,
108    pub report_descriptor: [u8; 128],
109}
110
111const_assert_eq!(169, size_of::<MessageDeviceInfo>());
112
113impl fmt::Debug for MessageDeviceInfo {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        f.debug_struct("MessageDeviceInfo")
116            .field("descriptor_info", &self.descriptor_info)
117            .finish()
118    }
119}
120
121#[repr(C)]
122#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
123pub struct MessageDeviceInfoAck {
124    pub acknowledged: u8,
125}
126
127const_assert_eq!(1, size_of::<MessageDeviceInfoAck>());
128
129#[repr(C, packed)]
130#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
131pub struct MessageInputReport {
132    pub input_report: MousePacket,
133}
134
135const_assert_eq!(7, size_of::<MessageInputReport>());
136
137pub const REPORT_DESCRIPTOR: [u8; 67] = [
138    0x05, 0x01, // USAGE_PAGE (Generic Desktop)
139    0x09, 0x02, // USAGE (Mouse)
140    0xA1, 0x01, // COLLECTION (Application)
141    0x09, 0x01, //   USAGE (Pointer)
142    0xA1, 0x00, //   COLLECTION (Physical)
143    0x05, 0x09, //     USAGE_PAGE (Buttons)
144    0x19, 0x01, //     Usage Minimum (01)
145    0x29, 0x05, //     Usage Maximum (05)
146    0x15, 0x00, //     Logical Minimum (00)
147    0x25, 0x01, //     Logical Maximum (01)
148    0x95, 0x05, //     Report Count (5)
149    0x75, 0x01, //     Report Size (1)
150    0x81, 0x02, //     Input (Data, Variable, Absolute) ;
151    //         5 button bits
152    0x95, 0x01, //     Report Count (1)
153    0x75, 0x03, //     Report Size (3)
154    0x81, 0x01, //     Input (Constant) ; 3 bit padding
155    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
156    0x09, 0x30, //     USAGE (X)
157    0x09, 0x31, //     USAGE (Y)
158    0x15, 0x00, //     Logical Minimum (0)
159    0x26, 0xFF, 0x7F, //     Logical Maximum (32767)
160    0x75, 0x10, //     Report Size (16)
161    0x95, 0x02, //     Report Count (2)
162    0x81, 0x02, //     Input (Data, Variable, Absolute) ;
163    //         2 Axes absolute data.
164    0x05, 0x01, //     USAGE_PAGE (Generic Desktop)
165    0x09, 0x38, //     USAGE (Wheel)
166    0x16, 0x01, 0x80, //     Logical Minimum (-32767)
167    0x26, 0xFF, 0x7F, //     Logical Maximum (32767)
168    0x75, 0x10, //     Report Size (16)
169    0x95, 0x01, //     Report Count (1)
170    0x81, 0x06, //     Input (Data, Variable, Relative) ;
171    //         1 Axes relative data.
172    0xC0, //   END_COLLECTION
173    0xC0, // END_COLLECTION
174];
175
176pub const HID_MOUSE_BUTTON_LEFT: u8 = 0x01;
177pub const HID_MOUSE_BUTTON_RIGHT: u8 = 0x02;
178pub const HID_MOUSE_BUTTON_MIDDLE: u8 = 0x04;
179
180pub const MOUSE_NUMBER_BUTTONS: usize = 5;
181
182pub enum MouseButton {
183    Left = 0,
184    Right = 1,
185    Middle = 2,
186    Fourth = 3,
187    Fifth = 4,
188}
189
190#[derive(Copy, Clone, Debug)]
191pub enum ScrollType {
192    //we use -1, 1, because we want to increment the z-value (i16) in the corresponding direction
193    Down = -1,
194    NoChange = 0,
195    Up = 1,
196}
197
198pub const MOUSE_EVENT_FLAG_XY_ABSOLUTE: u32 = 1 << 0;
199
200pub const fn event_no_change(button: u8) -> u32 {
201    1 << ((button as u32) + 1)
202}
203
204pub const MOUSE_EVENT_FLAG_LEFT_BUTTON_NO_CHANGE: u32 = event_no_change(MouseButton::Left as u8);
205pub const MOUSE_EVENT_FLAG_RIGHT_BUTTON_NO_CHANGE: u32 = event_no_change(MouseButton::Right as u8);
206pub const MOUSE_EVENT_FLAG_MIDDLE_BUTTON_NO_CHANGE: u32 =
207    event_no_change(MouseButton::Middle as u8);
208pub const MOUSE_EVENT_FLAG_FOURTH_BUTTON_NO_CHANGE: u32 =
209    event_no_change(MouseButton::Fourth as u8);
210pub const MOUSE_EVENT_FLAG_FIFTH_BUTTON_NO_CHANGE: u32 = event_no_change(MouseButton::Fifth as u8);
211
212pub const MOUSE_EVENT_FLAG_ALL_BUTTONS_NO_CHANGE: u32 = MOUSE_EVENT_FLAG_LEFT_BUTTON_NO_CHANGE
213    | MOUSE_EVENT_FLAG_MIDDLE_BUTTON_NO_CHANGE
214    | MOUSE_EVENT_FLAG_RIGHT_BUTTON_NO_CHANGE
215    | MOUSE_EVENT_FLAG_FOURTH_BUTTON_NO_CHANGE
216    | MOUSE_EVENT_FLAG_FIFTH_BUTTON_NO_CHANGE;
217
218pub const fn event_single_change(button: MouseButton) -> u32 {
219    MOUSE_EVENT_FLAG_ALL_BUTTONS_NO_CHANGE & (!(event_no_change(button as u8)))
220}
221
222pub const MOUSE_EVENT_FLAG_FORCE_REPORT_EVENT: u32 = 1 << 8;
223
224#[repr(C, packed)]
225#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
226pub struct MousePacket {
227    pub button_data: u8,
228
229    pub x: u16,
230    pub y: u16,
231    pub z: i16,
232}
233
234const_assert_eq!(7, size_of::<MousePacket>());