mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-06 06:34:35 +00:00
Web HIDAPI
This commit is contained in:
parent
006959ca87
commit
138683e645
9 changed files with 556 additions and 2 deletions
2
.github/workflows/create-test-plan.py
vendored
2
.github/workflows/create-test-plan.py
vendored
|
|
@ -621,7 +621,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool, ctest_args
|
|||
"-ffile-prefix-map=${PWD}=/SDL",
|
||||
))
|
||||
job.ldflags.extend((
|
||||
"--source-map-base", "/",
|
||||
"--source-map-base", "/", "-s", "ASYNCIFY",
|
||||
))
|
||||
pretest_cmd.extend((
|
||||
"# Start local HTTP server",
|
||||
|
|
|
|||
|
|
@ -1772,6 +1772,10 @@ elseif(EMSCRIPTEN)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(SDL_HIDAPI)
|
||||
CheckHIDAPI()
|
||||
endif()
|
||||
|
||||
if(SDL_JOYSTICK)
|
||||
set(SDL_JOYSTICK_EMSCRIPTEN 1)
|
||||
sdl_glob_sources(
|
||||
|
|
|
|||
|
|
@ -595,6 +595,8 @@ typedef struct PLATFORM_hid_device_ PLATFORM_hid_device;
|
|||
#include "SDL_hidapi_android.h"
|
||||
#elif defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS)
|
||||
#include "SDL_hidapi_ios.h"
|
||||
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
|
||||
#include "SDL_hidapi_emscripten.h"
|
||||
#endif
|
||||
|
||||
#undef api_version
|
||||
|
|
|
|||
25
src/hidapi/SDL_hidapi_emscripten.h
Normal file
25
src/hidapi/SDL_hidapi_emscripten.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#undef HIDAPI_H__
|
||||
#include "emscripten/hid.c"
|
||||
#define HAVE_PLATFORM_BACKEND 1
|
||||
#define udev_ctx 1
|
||||
495
src/hidapi/emscripten/hid.c
Normal file
495
src/hidapi/emscripten/hid.c
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
libusb/hidapi Team
|
||||
|
||||
Copyright 2022, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU General Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
https://github.com/libusb/hidapi .
|
||||
********************************************************/
|
||||
|
||||
#include "../hidapi/hidapi.h"
|
||||
#include <stdio.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
EM_JS_DEPS(hidapi, "$dynCall");
|
||||
|
||||
struct hid_device_ {
|
||||
int device_id;
|
||||
unsigned char *last_report;
|
||||
size_t last_report_length;
|
||||
int last_report_read;
|
||||
struct hid_device_info* device_info;
|
||||
};
|
||||
|
||||
static struct hid_api_version api_version = {
|
||||
.major = HID_API_VERSION_MAJOR,
|
||||
.minor = HID_API_VERSION_MINOR,
|
||||
.patch = HID_API_VERSION_PATCH
|
||||
};
|
||||
|
||||
static hid_device *new_hid_device(void)
|
||||
{
|
||||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
||||
if (dev == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->device_id = -1;
|
||||
dev->last_report = NULL;
|
||||
dev->last_report_length = 0;
|
||||
dev->last_report_read = 0;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void)
|
||||
{
|
||||
return &api_version;
|
||||
}
|
||||
|
||||
HID_API_EXPORT const char* HID_API_CALL hid_version_str(void)
|
||||
{
|
||||
return HID_API_VERSION_STR;
|
||||
}
|
||||
|
||||
// static void test(hid_device *dev, unsigned char *data, size_t length)
|
||||
// static void test(unsigned char *data)
|
||||
// {
|
||||
// // printf("Test function, device_id=%d\n", dev->device_id);
|
||||
// printf("Test function\n");
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// printf("Test function, data[%d]=%d\n", i, data[i]);
|
||||
// }
|
||||
// free(data);
|
||||
// }
|
||||
|
||||
int HID_API_EXPORT hid_init(void)
|
||||
{
|
||||
// MAIN_THREAD_EM_ASM({
|
||||
// const typedArray = Uint8Array.from([1,2,3]);
|
||||
// const heapPointer = _malloc(typedArray.length * typedArray.BYTES_PER_ELEMENT);
|
||||
// HEAPU8.set(typedArray, heapPointer);
|
||||
// dynCall('vi', $0, [heapPointer]);
|
||||
// }, &test);
|
||||
|
||||
return MAIN_THREAD_EM_ASM_INT({
|
||||
return "hid" in navigator ? 0 : -1;
|
||||
});
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_exit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hid_device_info * create_device_info_for_device(int device_id)
|
||||
{
|
||||
struct hid_device_info *root = NULL;
|
||||
struct hid_device_info *cur_dev = NULL;
|
||||
char path[16];
|
||||
/*wchar_t product_string[128];*/
|
||||
int ignore = 0;
|
||||
int input_report_count;
|
||||
|
||||
ignore = MAIN_THREAD_EM_ASM_INT({
|
||||
let device = window._hidDeviceList[$0];
|
||||
if (!device) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, device_id);
|
||||
|
||||
if (ignore)
|
||||
goto end;
|
||||
|
||||
/* Create the record. */
|
||||
root = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
|
||||
if (!root)
|
||||
goto end;
|
||||
|
||||
cur_dev = root;
|
||||
|
||||
snprintf(path, sizeof(path), "hid%d", device_id);
|
||||
cur_dev->path = strdup(path);
|
||||
|
||||
cur_dev->vendor_id = MAIN_THREAD_EM_ASM_INT({
|
||||
return window._hidDeviceList[$0].vendorId;
|
||||
}, device_id);
|
||||
cur_dev->product_id = MAIN_THREAD_EM_ASM_INT({
|
||||
return window._hidDeviceList[$0].productId;
|
||||
}, device_id);
|
||||
|
||||
cur_dev->serial_number = NULL;
|
||||
cur_dev->release_number = 0;
|
||||
cur_dev->manufacturer_string = NULL;
|
||||
|
||||
/* I'm too tired to make stringToUTF32 work correctly here, cmake doesn't want to include it in the build */
|
||||
/*MAIN_THREAD_EM_ASM({
|
||||
stringToUTF32(window._hidDeviceList[$0].productName, $1, Number($2));
|
||||
}, device_id, product_string, sizeof(product_string));
|
||||
|
||||
cur_dev->product_string = wcsdup(product_string);*/
|
||||
|
||||
cur_dev->product_string = NULL;
|
||||
|
||||
cur_dev->usage_page = MAIN_THREAD_EM_ASM_INT({
|
||||
return window._hidDeviceList[$0].collections[0].usagePage;
|
||||
}, device_id);
|
||||
cur_dev->usage = MAIN_THREAD_EM_ASM_INT({
|
||||
return window._hidDeviceList[$0].collections[0].usage;
|
||||
}, device_id);
|
||||
cur_dev->interface_number = 0;
|
||||
|
||||
input_report_count = MAIN_THREAD_EM_ASM_INT({
|
||||
return window._hidDeviceList[$0].collections[0].inputReports.length;
|
||||
}, device_id);
|
||||
|
||||
/* WebHID doesn't provide the bus type, so we have to guess it ourselves */
|
||||
if (input_report_count >= 5) {
|
||||
cur_dev->bus_type = HID_API_BUS_BLUETOOTH;
|
||||
} else {
|
||||
cur_dev->bus_type = HID_API_BUS_USB;
|
||||
}
|
||||
|
||||
cur_dev->next = NULL;
|
||||
|
||||
printf("HIDAPI: New device found: %d %d\n", cur_dev->vendor_id, cur_dev->product_id);
|
||||
end:
|
||||
return root;
|
||||
}
|
||||
|
||||
// TODO: remove all EM_ASYNC_JS
|
||||
EM_ASYNC_JS(int, hid_js_get_device_count, (), {
|
||||
window._hidDeviceList = await navigator.hid.getDevices();
|
||||
return window._hidDeviceList.length;
|
||||
});
|
||||
|
||||
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
int device_count;
|
||||
struct hid_device_info *root = NULL; /* return object */
|
||||
struct hid_device_info *cur_dev = NULL;
|
||||
|
||||
hid_init();
|
||||
|
||||
device_count = hid_js_get_device_count();
|
||||
|
||||
printf("hid_enumerate, device_count=%d\n", device_count);
|
||||
|
||||
int device_id;
|
||||
for (device_id = 0; device_id < device_count; device_id++) {
|
||||
struct hid_device_info * tmp;
|
||||
/* TODO: handle vendor_id and product_id */
|
||||
tmp = create_device_info_for_device(device_id);
|
||||
|
||||
if (tmp) {
|
||||
if (cur_dev) {
|
||||
cur_dev->next = tmp;
|
||||
}
|
||||
else {
|
||||
root = tmp;
|
||||
}
|
||||
cur_dev = tmp;
|
||||
|
||||
/* move the pointer to the tail of returned list */
|
||||
while (cur_dev->next != NULL) {
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs)
|
||||
{
|
||||
struct hid_device_info *d = devs;
|
||||
while (d) {
|
||||
struct hid_device_info *next = d->next;
|
||||
free(d->path);
|
||||
/*free(d->serial_number);
|
||||
free(d->manufacturer_string);
|
||||
free(d->product_string);*/
|
||||
free(d);
|
||||
d = next;
|
||||
}
|
||||
}
|
||||
|
||||
hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
||||
{
|
||||
struct hid_device_info *devs, *cur_dev;
|
||||
const char *path_to_open = NULL;
|
||||
hid_device *handle = NULL;
|
||||
|
||||
/* register_global_error: global error is reset by hid_enumerate/hid_init */
|
||||
devs = hid_enumerate(vendor_id, product_id);
|
||||
if (devs == NULL) {
|
||||
/* register_global_error: global error is already set by hid_enumerate */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cur_dev = devs;
|
||||
while (cur_dev) {
|
||||
if (cur_dev->vendor_id == vendor_id &&
|
||||
cur_dev->product_id == product_id) {
|
||||
if (serial_number) {
|
||||
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
|
||||
path_to_open = cur_dev->path;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
path_to_open = cur_dev->path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
|
||||
if (path_to_open) {
|
||||
/* Open the device */
|
||||
handle = hid_open_path(path_to_open);
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
typedef void(*SetByteCallback)(unsigned char *data, size_t length, int byte, size_t offset);
|
||||
typedef void(*SetReportCallback)(hid_device *dev, unsigned char *data, size_t length);
|
||||
|
||||
static void set_byte(unsigned char *data, size_t length, int byte, size_t offset)
|
||||
{
|
||||
if (offset >= length)
|
||||
return;
|
||||
data[offset] = (unsigned char)byte;
|
||||
// printf("set_byte: offset=%d byte=%d\n", (int)offset, byte);
|
||||
}
|
||||
|
||||
static void set_report(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
if (dev->last_report) {
|
||||
free(dev->last_report);
|
||||
}
|
||||
dev->last_report = data;
|
||||
dev->last_report_length = length;
|
||||
dev->last_report_read = 0;
|
||||
}
|
||||
|
||||
EM_ASYNC_JS(void, hid_js_open, (int device_id, hid_device *dev, SetByteCallback callback, SetReportCallback set_report_callback), {
|
||||
let device = window._hidDeviceList[device_id];
|
||||
console.log("Opening device1 " + device_id);
|
||||
if (device) {
|
||||
console.log("Opening device2 " + device_id);
|
||||
await device.open();
|
||||
device.addEventListener("inputreport", function (event) {
|
||||
const { data, device, reportId } = event;
|
||||
|
||||
let dataLength = data['byteLength']+1;
|
||||
let pointer = _malloc(dataLength);
|
||||
dynCall("viiii", callback, [pointer, dataLength, report_id, 0]);
|
||||
for (let i = 0; i < data['byteLength']; i++) {
|
||||
dynCall("viiii", callback, [pointer, dataLength, data['getUint8'](i), i+1]);
|
||||
}
|
||||
dynCall("viii", set_report_callback, [dev, pointer, dataLength]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
hid_device * HID_API_EXPORT hid_open_path(const char *path)
|
||||
{
|
||||
hid_device *dev = NULL;
|
||||
int device_id = 0;
|
||||
|
||||
hid_init();
|
||||
/* register_global_error: global error is reset by hid_init */
|
||||
|
||||
printf("hid_open_path: %s\n", path);
|
||||
dev = new_hid_device();
|
||||
if (!dev) {
|
||||
printf("hid_open_path: no memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sscanf(path, "hid%d", &device_id) != 1) {
|
||||
free(dev);
|
||||
printf("hid_open_path: invalid path\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->device_id = device_id;
|
||||
hid_js_open(device_id, dev, set_byte, set_report);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
EM_ASYNC_JS(int, hid_js_write, (int device_id, int report_id, const unsigned char *data, size_t length), {
|
||||
let device = window._hidDeviceList[device_id];
|
||||
if (device) {
|
||||
let dataArray = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
// console.log("hid_write: offset=" + i + " byte=" + HEAPU8[data+i]);
|
||||
dataArray[i] = HEAPU8[data+i];
|
||||
}
|
||||
await device.sendReport(report_id, dataArray);
|
||||
}
|
||||
});
|
||||
|
||||
int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
if (length < 1)
|
||||
return 0;
|
||||
hid_js_write(dev->device_id, data[0], data+1, length-1);
|
||||
return length;
|
||||
}
|
||||
|
||||
EM_ASYNC_JS(int, hid_js_read_timeout, (int device_id, unsigned char *data, size_t length, SetByteCallback callback), {
|
||||
let device = window._hidDeviceList[device_id];
|
||||
if (device) {
|
||||
let [report_id, dataView] = await new Promise(function(resolve, reject) {
|
||||
device.addEventListener("inputreport", function (event) {
|
||||
const { data, device, reportId } = event;
|
||||
resolve([reportId, data]); // done
|
||||
}, {once: true});
|
||||
});
|
||||
dynCall("viiii", callback, [data, length, report_id, 0]);
|
||||
for (let i = 0; i < dataView['byteLength']; i++) {
|
||||
dynCall("viiii", callback, [data, length, dataView['getUint8'](i), i+1]);
|
||||
}
|
||||
return dataView['byteLength']+1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
/* TODO: timeout */
|
||||
if (length < 1)
|
||||
return -1;
|
||||
if (milliseconds == 0) {
|
||||
if (dev->last_report && !dev->last_report_read) {
|
||||
size_t return_size = length;
|
||||
if (dev->last_report_length < length) {
|
||||
return_size = dev->last_report_length;
|
||||
}
|
||||
memcpy(data, dev->last_report, return_size);
|
||||
dev->last_report_read = 1;
|
||||
return return_size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return hid_js_read_timeout(dev->device_id, data, length, &set_byte);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
/* TODO: blocking */
|
||||
return hid_read_timeout(dev, data, length, -1);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EM_ASYNC_JS(void, hid_js_get_feature_report, (int device_id, int report_id, unsigned char *data, size_t length, SetByteCallback callback), {
|
||||
let device = window._hidDeviceList[device_id];
|
||||
if (device) {
|
||||
let dataView = await device['receiveFeatureReport'](report_id);
|
||||
for (let i = 0; i < dataView['byteLength']; i++) {
|
||||
dynCall("viiii", callback, [data, length, dataView['getUint8'](i), i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
if (length < 1)
|
||||
return -1;
|
||||
int report_id = (int)data[0];
|
||||
hid_js_get_feature_report(dev->device_id, report_id, data, length, &set_byte);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
EM_ASYNC_JS(int, hid_js_close, (int device_id), {
|
||||
let device = window._hidDeviceList[device_id];
|
||||
if (device) {
|
||||
await device.close();
|
||||
}
|
||||
});
|
||||
|
||||
void HID_API_EXPORT hid_close(hid_device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
if (dev->last_report) {
|
||||
free(dev->last_report);
|
||||
}
|
||||
|
||||
hid_js_close(dev->device_id);
|
||||
hid_free_enumeration(dev->device_info);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "SDL_sysjoystick_c.h"
|
||||
#include "../SDL_joystick_c.h"
|
||||
#include "../usb_ids.h"
|
||||
#include "../hidapi/SDL_hidapijoystick_c.h"
|
||||
|
||||
static SDL_joylist_item *JoystickByIndex(int index);
|
||||
|
||||
|
|
@ -120,6 +121,17 @@ static int SDL_GetEmscriptenOSID()
|
|||
});
|
||||
}
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
static void SDL_RequestWebHIDDevice(Uint16 vendor, Uint16 product)
|
||||
{
|
||||
MAIN_THREAD_EM_ASM({
|
||||
if ("hid" in navigator) {
|
||||
navigator["hid"]["requestDevice"]({ "filters": [ { "vendorId": $0, "productId": $1, } ]});
|
||||
}
|
||||
}, vendor, product);
|
||||
}
|
||||
#endif
|
||||
|
||||
static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
|
||||
{
|
||||
SDL_joylist_item *item;
|
||||
|
|
@ -148,6 +160,15 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
|
|||
product = SDL_GetEmscriptenJoystickProduct(gamepadEvent->index);
|
||||
is_xinput = SDL_IsEmscriptenJoystickXInput(gamepadEvent->index);
|
||||
|
||||
#ifdef SDL_JOYSTICK_HIDAPI
|
||||
if (HIDAPI_IsDeviceSupported(vendor, product, 0, "")) {
|
||||
SDL_RequestWebHIDDevice(vendor, product);
|
||||
printf("HIDAPI_IsDeviceSupported\n");
|
||||
SDL_free(item);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use a generic VID/PID representing an XInput controller
|
||||
if (!vendor && !product && is_xinput) {
|
||||
vendor = USB_VENDOR_MICROSOFT;
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,7 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
|
|||
SDL_SendJoystickTouchpad(timestamp, joystick, 0, 1, touchpad_down, touchpad_x * TOUCHPAD_SCALEX, touchpad_y * TOUCHPAD_SCALEY, touchpad_down ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
printf("PS4 Packet usb1 %d\n", packet->rgucButtonsHatAndCounter[0]);
|
||||
if (ctx->last_state.rgucButtonsHatAndCounter[0] != packet->rgucButtonsHatAndCounter[0]) {
|
||||
{
|
||||
Uint8 data = (packet->rgucButtonsHatAndCounter[0] >> 4);
|
||||
|
|
@ -1295,7 +1296,9 @@ static bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
#ifdef DEBUG_PS4_PROTOCOL
|
||||
HIDAPI_DumpPacket("PS4 packet: size = %d", data, size);
|
||||
#endif
|
||||
printf("PS4 Packet start\n");
|
||||
if (!HIDAPI_DriverPS4_IsPacketValid(ctx, data, size)) {
|
||||
printf("PS4 Packet invalid\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1303,11 +1306,13 @@ static bool HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
|
|||
ctx->last_packet = now;
|
||||
|
||||
if (!joystick) {
|
||||
printf("PS4 Packet no joystick\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (data[0]) {
|
||||
case k_EPS4ReportIdUsbState:
|
||||
printf("PS4 Packet usb, packet[1]=%d\n", +data[1]);
|
||||
HIDAPI_DriverPS4_HandleStatePacket(joystick, device->dev, ctx, (PS4StatePacket_t *)&data[1], size - 1);
|
||||
break;
|
||||
case k_EPS4ReportIdBluetoothState1:
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ static SDL_GamepadType SDL_GetJoystickGameControllerProtocol(const char *name, U
|
|||
return type;
|
||||
}
|
||||
|
||||
static bool HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
bool HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
int i;
|
||||
SDL_GamepadType type = SDL_GetJoystickGameControllerProtocol(name, vendor_id, product_id, -1, 0, 0, 0);
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ extern SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverZUIKI;
|
|||
(((Uint32)(C)) << 16) | \
|
||||
(((Uint32)(D)) << 24))
|
||||
|
||||
extern bool HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name);
|
||||
|
||||
// Return true if a HID device is present and supported as a joystick of the given type
|
||||
extern bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue