winebus.sys: Identify DualSense Edge as a DualSense controller.
[wine.git] / dlls / winebus.sys / unixlib.c
blob82eab3717cacc65f775999b38d7c5be4d83871f1
1 /*
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
19 #if 0
20 #pragma makedep unix
21 #endif
23 #include "config.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winternl.h"
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 */
61 return FALSE;
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 */
70 return FALSE;
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 */
78 return FALSE;
81 struct mouse_device
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 =
143 mouse_destroy,
144 mouse_start,
145 mouse_stop,
146 mouse_haptics_start,
147 mouse_haptics_stop,
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 =
156 .vid = 0x845e,
157 .pid = 0x0001,
158 .input = -1,
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 =
234 keyboard_destroy,
235 keyboard_start,
236 keyboard_stop,
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 =
247 .vid = 0x845e,
248 .pid = 0x0002,
249 .input = -1,
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;
268 iface->vtbl = vtbl;
269 iface->ref = 1;
271 return iface;
274 static void unix_device_decref(struct unix_device *iface)
276 if (!InterlockedDecrement(&iface->ref))
278 iface->vtbl->destroy(iface);
279 free(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[] =
337 sdl_bus_init,
338 sdl_bus_wait,
339 sdl_bus_stop,
340 udev_bus_init,
341 udev_bus_wait,
342 udev_bus_stop,
343 iohid_bus_init,
344 iohid_bus_wait,
345 iohid_bus_stop,
346 mouse_device_create,
347 keyboard_device_create,
348 unix_device_remove,
349 unix_device_start,
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
367 struct list 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);
379 free(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 */
391 free(entry);
392 return FALSE;
395 entry->event.type = BUS_EVENT_TYPE_DEVICE_REMOVED;
396 entry->event.device = (UINT_PTR)device;
397 list_add_tail(queue, &entry->entry);
399 return TRUE;
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 */
410 free(entry);
411 return FALSE;
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);
419 return TRUE;
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 */
430 free(entry);
431 return FALSE;
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);
440 return TRUE;
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;
447 ULONG size;
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);
458 free(entry);
460 return TRUE;