|
@@ -19,7 +19,7 @@
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
*/
|
|
|
|
|
|
-/*
|
|
|
+/*
|
|
|
* To list the properties of a device, try something like:
|
|
|
* udevadm info -a -n snd/hwC0D0 (for a sound card)
|
|
|
* udevadm info --query=all -n input/event3 (for a keyboard, mouse, etc)
|
|
@@ -115,23 +115,23 @@ int
|
|
|
SDL_UDEV_Init(void)
|
|
|
{
|
|
|
int retval = 0;
|
|
|
-
|
|
|
+
|
|
|
if (_this == NULL) {
|
|
|
_this = (SDL_UDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
|
|
|
if(_this == NULL) {
|
|
|
return SDL_OutOfMemory();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
retval = SDL_UDEV_LoadLibrary();
|
|
|
if (retval < 0) {
|
|
|
SDL_UDEV_Quit();
|
|
|
return retval;
|
|
|
}
|
|
|
-
|
|
|
- /* Set up udev monitoring
|
|
|
+
|
|
|
+ /* Set up udev monitoring
|
|
|
* Listen for input devices (mouse, keyboard, joystick, etc) and sound devices
|
|
|
*/
|
|
|
-
|
|
|
+
|
|
|
_this->udev = _this->syms.udev_new();
|
|
|
if (_this->udev == NULL) {
|
|
|
SDL_UDEV_Quit();
|
|
@@ -143,18 +143,18 @@ SDL_UDEV_Init(void)
|
|
|
SDL_UDEV_Quit();
|
|
|
return SDL_SetError("udev_monitor_new_from_netlink() failed");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
|
|
|
_this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
|
|
|
_this->syms.udev_monitor_enable_receiving(_this->udev_mon);
|
|
|
-
|
|
|
+
|
|
|
/* Do an initial scan of existing devices */
|
|
|
SDL_UDEV_Scan();
|
|
|
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
_this->ref_count += 1;
|
|
|
-
|
|
|
+
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -162,15 +162,15 @@ void
|
|
|
SDL_UDEV_Quit(void)
|
|
|
{
|
|
|
SDL_UDEV_CallbackList *item;
|
|
|
-
|
|
|
+
|
|
|
if (_this == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
_this->ref_count -= 1;
|
|
|
-
|
|
|
+
|
|
|
if (_this->ref_count < 1) {
|
|
|
-
|
|
|
+
|
|
|
if (_this->udev_mon != NULL) {
|
|
|
_this->syms.udev_monitor_unref(_this->udev_mon);
|
|
|
_this->udev_mon = NULL;
|
|
@@ -179,14 +179,14 @@ SDL_UDEV_Quit(void)
|
|
|
_this->syms.udev_unref(_this->udev);
|
|
|
_this->udev = NULL;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/* Remove existing devices */
|
|
|
while (_this->first != NULL) {
|
|
|
item = _this->first;
|
|
|
_this->first = _this->first->next;
|
|
|
SDL_free(item);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
SDL_UDEV_UnloadLibrary();
|
|
|
SDL_free(_this);
|
|
|
_this = NULL;
|
|
@@ -198,22 +198,22 @@ SDL_UDEV_Scan(void)
|
|
|
{
|
|
|
struct udev_enumerate *enumerate = NULL;
|
|
|
struct udev_list_entry *devs = NULL;
|
|
|
- struct udev_list_entry *item = NULL;
|
|
|
-
|
|
|
+ struct udev_list_entry *item = NULL;
|
|
|
+
|
|
|
if (_this == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
enumerate = _this->syms.udev_enumerate_new(_this->udev);
|
|
|
if (enumerate == NULL) {
|
|
|
SDL_UDEV_Quit();
|
|
|
SDL_SetError("udev_enumerate_new() failed");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "input");
|
|
|
_this->syms.udev_enumerate_add_match_subsystem(enumerate, "sound");
|
|
|
-
|
|
|
+
|
|
|
_this->syms.udev_enumerate_scan_devices(enumerate);
|
|
|
devs = _this->syms.udev_enumerate_get_list_entry(enumerate);
|
|
|
for (item = devs; item; item = _this->syms.udev_list_entry_get_next(item)) {
|
|
@@ -228,6 +228,62 @@ SDL_UDEV_Scan(void)
|
|
|
_this->syms.udev_enumerate_unref(enumerate);
|
|
|
}
|
|
|
|
|
|
+SDL_bool
|
|
|
+SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version)
|
|
|
+{
|
|
|
+ struct udev_enumerate *enumerate = NULL;
|
|
|
+ struct udev_list_entry *devs = NULL;
|
|
|
+ struct udev_list_entry *item = NULL;
|
|
|
+ SDL_bool found = SDL_FALSE;
|
|
|
+
|
|
|
+ if (_this == NULL) {
|
|
|
+ return SDL_FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ enumerate = _this->syms.udev_enumerate_new(_this->udev);
|
|
|
+ if (enumerate == NULL) {
|
|
|
+ SDL_SetError("udev_enumerate_new() failed");
|
|
|
+ return SDL_FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ _this->syms.udev_enumerate_scan_devices(enumerate);
|
|
|
+ devs = _this->syms.udev_enumerate_get_list_entry(enumerate);
|
|
|
+ for (item = devs; item && !found; item = _this->syms.udev_list_entry_get_next(item)) {
|
|
|
+ const char *path = _this->syms.udev_list_entry_get_name(item);
|
|
|
+ struct udev_device *dev = _this->syms.udev_device_new_from_syspath(_this->udev, path);
|
|
|
+ if (dev != NULL) {
|
|
|
+ const char *val = NULL;
|
|
|
+ const char *existing_path;
|
|
|
+
|
|
|
+ existing_path = _this->syms.udev_device_get_devnode(dev);
|
|
|
+ if (existing_path && SDL_strcmp(device_path, existing_path) == 0) {
|
|
|
+ found = SDL_TRUE;
|
|
|
+
|
|
|
+ val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID");
|
|
|
+ if (val != NULL) {
|
|
|
+ *vendor = (Uint16)SDL_strtol(val, NULL, 16);
|
|
|
+ }
|
|
|
+
|
|
|
+ val = _this->syms.udev_device_get_property_value(dev, "ID_MODEL_ID");
|
|
|
+ if (val != NULL) {
|
|
|
+ *product = (Uint16)SDL_strtol(val, NULL, 16);
|
|
|
+ }
|
|
|
+
|
|
|
+ val = _this->syms.udev_device_get_property_value(dev, "ID_REVISION");
|
|
|
+ if (val != NULL) {
|
|
|
+ *version = (Uint16)SDL_strtol(val, NULL, 16);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _this->syms.udev_device_unref(dev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _this->syms.udev_enumerate_unref(enumerate);
|
|
|
+
|
|
|
+ return found;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
void
|
|
|
SDL_UDEV_UnloadLibrary(void)
|
|
@@ -235,7 +291,7 @@ SDL_UDEV_UnloadLibrary(void)
|
|
|
if (_this == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (_this->udev_handle != NULL) {
|
|
|
SDL_UnloadObject(_this->udev_handle);
|
|
|
_this->udev_handle = NULL;
|
|
@@ -246,11 +302,11 @@ int
|
|
|
SDL_UDEV_LoadLibrary(void)
|
|
|
{
|
|
|
int retval = 0, i;
|
|
|
-
|
|
|
+
|
|
|
if (_this == NULL) {
|
|
|
return SDL_SetError("UDEV not initialized");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/* See if there is a udev library already loaded */
|
|
|
if (SDL_UDEV_load_syms() == 0) {
|
|
|
return 0;
|
|
@@ -282,7 +338,7 @@ SDL_UDEV_LoadLibrary(void)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (_this->udev_handle == NULL) {
|
|
|
retval = -1;
|
|
|
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
|
@@ -352,26 +408,26 @@ guess_device_class(struct udev_device *dev)
|
|
|
&bitmask_rel[0]);
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|
|
+static void
|
|
|
+device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|
|
{
|
|
|
const char *subsystem;
|
|
|
const char *val = NULL;
|
|
|
int devclass = 0;
|
|
|
const char *path;
|
|
|
SDL_UDEV_CallbackList *item;
|
|
|
-
|
|
|
+
|
|
|
path = _this->syms.udev_device_get_devnode(dev);
|
|
|
if (path == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
subsystem = _this->syms.udev_device_get_subsystem(dev);
|
|
|
if (SDL_strcmp(subsystem, "sound") == 0) {
|
|
|
devclass = SDL_UDEV_DEVICE_SOUND;
|
|
|
} else if (SDL_strcmp(subsystem, "input") == 0) {
|
|
|
/* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */
|
|
|
-
|
|
|
+
|
|
|
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
|
|
|
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
|
|
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
|
@@ -381,13 +437,13 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|
|
if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE) &&
|
|
|
val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
|
|
devclass |= SDL_UDEV_DEVICE_JOYSTICK;
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+
|
|
|
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
|
|
|
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
|
|
devclass |= SDL_UDEV_DEVICE_MOUSE;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN");
|
|
|
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
|
|
|
devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
|
|
@@ -396,7 +452,7 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|
|
/* The undocumented rule is:
|
|
|
- All devices with keys get ID_INPUT_KEY
|
|
|
- From this subset, if they have ESC, numbers, and Q to D, it also gets ID_INPUT_KEYBOARD
|
|
|
-
|
|
|
+
|
|
|
Ref: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c#n183
|
|
|
*/
|
|
|
val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_KEY");
|
|
@@ -425,14 +481,14 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
|
|
|
} else {
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/* Process callbacks */
|
|
|
for (item = _this->first; item != NULL; item = item->next) {
|
|
|
item->callback(type, devclass, path);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
+void
|
|
|
SDL_UDEV_Poll(void)
|
|
|
{
|
|
|
struct udev_device *dev = NULL;
|
|
@@ -456,12 +512,12 @@ SDL_UDEV_Poll(void)
|
|
|
device_event(SDL_UDEV_DEVICEREMOVED, dev);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
_this->syms.udev_device_unref(dev);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-int
|
|
|
+int
|
|
|
SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
|
|
{
|
|
|
SDL_UDEV_CallbackList *item;
|
|
@@ -469,7 +525,7 @@ SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
|
|
if (item == NULL) {
|
|
|
return SDL_OutOfMemory();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
item->callback = cb;
|
|
|
|
|
|
if (_this->last == NULL) {
|
|
@@ -478,11 +534,11 @@ SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
|
|
|
_this->last->next = item;
|
|
|
_this->last = item;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
+void
|
|
|
SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
|
|
{
|
|
|
SDL_UDEV_CallbackList *item;
|
|
@@ -505,7 +561,6 @@ SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
|
|
|
}
|
|
|
prev = item;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
const SDL_UDEV_Symbols *
|