2 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #define WIN32_NO_STATUS
33 #include "ddk/hidtypes.h"
35 #include "wine/debug.h"
36 #include "wine/list.h"
37 #include "wine/unixlib.h"
39 #include "unix_private.h"
41 BOOL
is_xbox_gamepad(WORD vid
, WORD pid
)
43 if (vid
!= 0x045e) return FALSE
;
44 if (pid
== 0x0202) return TRUE
; /* Xbox Controller */
45 if (pid
== 0x0285) return TRUE
; /* Xbox Controller S */
46 if (pid
== 0x0289) return TRUE
; /* Xbox Controller S */
47 if (pid
== 0x028e) return TRUE
; /* Xbox360 Controller */
48 if (pid
== 0x028f) return TRUE
; /* Xbox360 Wireless Controller */
49 if (pid
== 0x02d1) return TRUE
; /* Xbox One Controller */
50 if (pid
== 0x02dd) return TRUE
; /* Xbox One Controller (Covert Forces/Firmware 2015) */
51 if (pid
== 0x02e0) return TRUE
; /* Xbox One X Controller */
52 if (pid
== 0x02e3) return TRUE
; /* Xbox One Elite Controller */
53 if (pid
== 0x02e6) return TRUE
; /* Wireless XBox Controller Dongle */
54 if (pid
== 0x02ea) return TRUE
; /* Xbox One S Controller */
55 if (pid
== 0x02fd) return TRUE
; /* Xbox One S Controller (Firmware 2017) */
56 if (pid
== 0x0b00) return TRUE
; /* Xbox Elite 2 */
57 if (pid
== 0x0b05) return TRUE
; /* Xbox Elite 2 Wireless */
58 if (pid
== 0x0b12) return TRUE
; /* Xbox Series */
59 if (pid
== 0x0b13) return TRUE
; /* Xbox Series Wireless */
60 if (pid
== 0x0719) return TRUE
; /* Xbox 360 Wireless Adapter */
64 BOOL
is_dualshock4_gamepad(WORD vid
, WORD pid
)
66 if (vid
!= 0x054c) return FALSE
;
67 if (pid
== 0x05c4) return TRUE
; /* DualShock 4 [CUH-ZCT1x] */
68 if (pid
== 0x09cc) return TRUE
; /* DualShock 4 [CUH-ZCT2x] */
69 if (pid
== 0x0ba0) return TRUE
; /* Dualshock 4 Wireless Adaptor */
73 BOOL
is_dualsense_gamepad(WORD vid
, WORD pid
)
75 if (vid
!= 0x054c) return FALSE
;
76 if (pid
== 0x0ce6) return TRUE
; /* DualSense */
77 if (pid
== 0x0df2) return TRUE
; /* DualSense Edge */
83 struct unix_device unix_device
;
86 static void mouse_destroy(struct unix_device
*iface
)
90 static NTSTATUS
mouse_start(struct unix_device
*iface
)
92 const USAGE_AND_PAGE device_usage
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_MOUSE
};
93 if (!hid_device_begin_report_descriptor(iface
, &device_usage
))
94 return STATUS_NO_MEMORY
;
95 if (!hid_device_add_buttons(iface
, HID_USAGE_PAGE_BUTTON
, 1, 3))
96 return STATUS_NO_MEMORY
;
97 if (!hid_device_end_report_descriptor(iface
))
98 return STATUS_NO_MEMORY
;
100 return STATUS_SUCCESS
;
103 static void mouse_stop(struct unix_device
*iface
)
107 static NTSTATUS
mouse_haptics_start(struct unix_device
*iface
, UINT duration
,
108 USHORT rumble_intensity
, USHORT buzz_intensity
,
109 USHORT left_intensity
, USHORT right_intensity
)
111 return STATUS_NOT_SUPPORTED
;
114 static NTSTATUS
mouse_haptics_stop(struct unix_device
*iface
)
116 return STATUS_NOT_SUPPORTED
;
119 static NTSTATUS
mouse_physical_device_control(struct unix_device
*iface
, USAGE control
)
121 return STATUS_NOT_SUPPORTED
;
124 static NTSTATUS
mouse_physical_device_set_gain(struct unix_device
*iface
, BYTE percent
)
126 return STATUS_NOT_SUPPORTED
;
129 static NTSTATUS
mouse_physical_effect_control(struct unix_device
*iface
, BYTE index
,
130 USAGE control
, BYTE iterations
)
132 return STATUS_NOT_SUPPORTED
;
135 static NTSTATUS
mouse_physical_effect_update(struct unix_device
*iface
, BYTE index
,
136 struct effect_params
*params
)
138 return STATUS_NOT_SUPPORTED
;
141 static const struct hid_device_vtbl mouse_vtbl
=
148 mouse_physical_device_control
,
149 mouse_physical_device_set_gain
,
150 mouse_physical_effect_control
,
151 mouse_physical_effect_update
,
154 static const struct device_desc mouse_device_desc
=
159 .manufacturer
= {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0},
160 .product
= {'W','i','n','e',' ','H','I','D',' ','m','o','u','s','e',0},
161 .serialnumber
= {'0','0','0','0',0},
164 static NTSTATUS
mouse_device_create(void *args
)
166 struct device_create_params
*params
= args
;
167 params
->desc
= mouse_device_desc
;
168 params
->device
= (UINT_PTR
)hid_device_create(&mouse_vtbl
, sizeof(struct mouse_device
));
169 return STATUS_SUCCESS
;
172 struct keyboard_device
174 struct unix_device unix_device
;
177 static void keyboard_destroy(struct unix_device
*iface
)
181 static NTSTATUS
keyboard_start(struct unix_device
*iface
)
183 const USAGE_AND_PAGE device_usage
= {.UsagePage
= HID_USAGE_PAGE_GENERIC
, .Usage
= HID_USAGE_GENERIC_KEYBOARD
};
184 if (!hid_device_begin_report_descriptor(iface
, &device_usage
))
185 return STATUS_NO_MEMORY
;
186 if (!hid_device_add_buttons(iface
, HID_USAGE_PAGE_KEYBOARD
, 0, 101))
187 return STATUS_NO_MEMORY
;
188 if (!hid_device_end_report_descriptor(iface
))
189 return STATUS_NO_MEMORY
;
191 return STATUS_SUCCESS
;
194 static void keyboard_stop(struct unix_device
*iface
)
198 static NTSTATUS
keyboard_haptics_start(struct unix_device
*iface
, UINT duration
,
199 USHORT rumble_intensity
, USHORT buzz_intensity
,
200 USHORT left_intensity
, USHORT right_intensity
)
202 return STATUS_NOT_SUPPORTED
;
205 static NTSTATUS
keyboard_haptics_stop(struct unix_device
*iface
)
207 return STATUS_NOT_SUPPORTED
;
210 static NTSTATUS
keyboard_physical_device_control(struct unix_device
*iface
, USAGE control
)
212 return STATUS_NOT_SUPPORTED
;
215 static NTSTATUS
keyboard_physical_device_set_gain(struct unix_device
*iface
, BYTE percent
)
217 return STATUS_NOT_SUPPORTED
;
220 static NTSTATUS
keyboard_physical_effect_control(struct unix_device
*iface
, BYTE index
,
221 USAGE control
, BYTE iterations
)
223 return STATUS_NOT_SUPPORTED
;
226 static NTSTATUS
keyboard_physical_effect_update(struct unix_device
*iface
, BYTE index
,
227 struct effect_params
*params
)
229 return STATUS_NOT_SUPPORTED
;
232 static const struct hid_device_vtbl keyboard_vtbl
=
237 keyboard_haptics_start
,
238 keyboard_haptics_stop
,
239 keyboard_physical_device_control
,
240 keyboard_physical_device_set_gain
,
241 keyboard_physical_effect_control
,
242 keyboard_physical_effect_update
,
245 static const struct device_desc keyboard_device_desc
=
250 .manufacturer
= {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0},
251 .product
= {'W','i','n','e',' ','H','I','D',' ','k','e','y','b','o','a','r','d',0},
252 .serialnumber
= {'0','0','0','0',0},
255 static NTSTATUS
keyboard_device_create(void *args
)
257 struct device_create_params
*params
= args
;
258 params
->desc
= keyboard_device_desc
;
259 params
->device
= (UINT_PTR
)hid_device_create(&keyboard_vtbl
, sizeof(struct keyboard_device
));
260 return STATUS_SUCCESS
;
263 void *raw_device_create(const struct raw_device_vtbl
*vtbl
, SIZE_T size
)
265 struct unix_device
*iface
;
267 if (!(iface
= calloc(1, size
))) return NULL
;
274 static void unix_device_decref(struct unix_device
*iface
)
276 if (!InterlockedDecrement(&iface
->ref
))
278 iface
->vtbl
->destroy(iface
);
283 static ULONG
unix_device_incref(struct unix_device
*iface
)
285 return InterlockedIncrement(&iface
->ref
);
288 static NTSTATUS
unix_device_remove(void *args
)
290 struct device_remove_params
*params
= args
;
291 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
292 iface
->vtbl
->stop(iface
);
293 unix_device_decref(iface
);
294 return STATUS_SUCCESS
;
297 static NTSTATUS
unix_device_start(void *args
)
299 struct device_start_params
*params
= args
;
300 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
301 return iface
->vtbl
->start(iface
);
304 static NTSTATUS
unix_device_get_report_descriptor(void *args
)
306 struct device_descriptor_params
*params
= args
;
307 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
308 return iface
->vtbl
->get_report_descriptor(iface
, params
->buffer
, params
->length
, params
->out_length
);
311 static NTSTATUS
unix_device_set_output_report(void *args
)
313 struct device_report_params
*params
= args
;
314 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
315 iface
->vtbl
->set_output_report(iface
, params
->packet
, params
->io
);
316 return STATUS_SUCCESS
;
319 static NTSTATUS
unix_device_get_feature_report(void *args
)
321 struct device_report_params
*params
= args
;
322 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
323 iface
->vtbl
->get_feature_report(iface
, params
->packet
, params
->io
);
324 return STATUS_SUCCESS
;
327 static NTSTATUS
unix_device_set_feature_report(void *args
)
329 struct device_report_params
*params
= args
;
330 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)params
->device
;
331 iface
->vtbl
->set_feature_report(iface
, params
->packet
, params
->io
);
332 return STATUS_SUCCESS
;
335 const unixlib_entry_t __wine_unix_call_funcs
[] =
347 keyboard_device_create
,
350 unix_device_get_report_descriptor
,
351 unix_device_set_output_report
,
352 unix_device_get_feature_report
,
353 unix_device_set_feature_report
,
356 C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs
) == unix_funcs_count
);
358 void bus_event_cleanup(struct bus_event
*event
)
360 struct unix_device
*iface
= (struct unix_device
*)(UINT_PTR
)event
->device
;
361 if (event
->type
== BUS_EVENT_TYPE_NONE
) return;
362 unix_device_decref(iface
);
365 struct bus_event_entry
368 struct bus_event event
;
371 void bus_event_queue_destroy(struct list
*queue
)
373 struct bus_event_entry
*entry
, *next
;
375 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, queue
, struct bus_event_entry
, entry
)
377 bus_event_cleanup(&entry
->event
);
378 list_remove(&entry
->entry
);
383 BOOL
bus_event_queue_device_removed(struct list
*queue
, struct unix_device
*device
)
385 ULONG size
= sizeof(struct bus_event_entry
);
386 struct bus_event_entry
*entry
= malloc(size
);
387 if (!entry
) return FALSE
;
389 if (unix_device_incref(device
) == 1) /* being destroyed */
395 entry
->event
.type
= BUS_EVENT_TYPE_DEVICE_REMOVED
;
396 entry
->event
.device
= (UINT_PTR
)device
;
397 list_add_tail(queue
, &entry
->entry
);
402 BOOL
bus_event_queue_device_created(struct list
*queue
, struct unix_device
*device
, struct device_desc
*desc
)
404 ULONG size
= sizeof(struct bus_event_entry
);
405 struct bus_event_entry
*entry
= malloc(size
);
406 if (!entry
) return FALSE
;
408 if (unix_device_incref(device
) == 1) /* being destroyed */
414 entry
->event
.type
= BUS_EVENT_TYPE_DEVICE_CREATED
;
415 entry
->event
.device
= (UINT_PTR
)device
;
416 entry
->event
.device_created
.desc
= *desc
;
417 list_add_tail(queue
, &entry
->entry
);
422 BOOL
bus_event_queue_input_report(struct list
*queue
, struct unix_device
*device
, BYTE
*report
, USHORT length
)
424 ULONG size
= offsetof(struct bus_event_entry
, event
.input_report
.buffer
[length
]);
425 struct bus_event_entry
*entry
= malloc(size
);
426 if (!entry
) return FALSE
;
428 if (unix_device_incref(device
) == 1) /* being destroyed */
434 entry
->event
.type
= BUS_EVENT_TYPE_INPUT_REPORT
;
435 entry
->event
.device
= (UINT_PTR
)device
;
436 entry
->event
.input_report
.length
= length
;
437 memcpy(entry
->event
.input_report
.buffer
, report
, length
);
438 list_add_tail(queue
, &entry
->entry
);
443 BOOL
bus_event_queue_pop(struct list
*queue
, struct bus_event
*event
)
445 struct list
*head
= list_head(queue
);
446 struct bus_event_entry
*entry
;
449 if (!head
) return FALSE
;
451 entry
= LIST_ENTRY(head
, struct bus_event_entry
, entry
);
452 list_remove(&entry
->entry
);
454 if (entry
->event
.type
!= BUS_EVENT_TYPE_INPUT_REPORT
) size
= sizeof(entry
->event
);
455 else size
= offsetof(struct bus_event
, input_report
.buffer
[entry
->event
.input_report
.length
]);
457 memcpy(event
, &entry
->event
, size
);