summaryrefslogtreecommitdiffstats
path: root/src/detection/mouse
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/mouse
Add the files
Diffstat (limited to 'src/detection/mouse')
-rw-r--r--src/detection/mouse/mouse.h8
-rw-r--r--src/detection/mouse/mouse_apple.c36
-rw-r--r--src/detection/mouse/mouse_bsd.c56
-rw-r--r--src/detection/mouse/mouse_haiku.cpp27
-rw-r--r--src/detection/mouse/mouse_linux.c45
-rw-r--r--src/detection/mouse/mouse_nosupport.c5
-rw-r--r--src/detection/mouse/mouse_windows.c84
7 files changed, 261 insertions, 0 deletions
diff --git a/src/detection/mouse/mouse.h b/src/detection/mouse/mouse.h
new file mode 100644
index 0000000..3247eeb
--- /dev/null
+++ b/src/detection/mouse/mouse.h
@@ -0,0 +1,8 @@
+#include "fastfetch.h"
+
+typedef struct FFMouseDevice {
+ FFstrbuf serial;
+ FFstrbuf name;
+} FFMouseDevice;
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */);
diff --git a/src/detection/mouse/mouse_apple.c b/src/detection/mouse/mouse_apple.c
new file mode 100644
index 0000000..2c5b2d7
--- /dev/null
+++ b/src/detection/mouse/mouse_apple.c
@@ -0,0 +1,36 @@
+#include "mouse.h"
+#include "common/apple/cf_helpers.h"
+#include "common/mallocHelper.h"
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/hid/IOHIDLib.h>
+
+static void enumSet(IOHIDDeviceRef value, FFlist* results) {
+ FFMouseDevice* device = FF_LIST_ADD(FFMouseDevice, *results);
+ ffStrbufInit(&device->serial);
+ ffStrbufInit(&device->name);
+
+ CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey));
+ ffCfStrGetString(product, &device->name);
+
+ CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey));
+ ffCfStrGetString(serialNumber, &device->serial);
+}
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) {
+ IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
+ return "IOHIDManagerOpen() failed";
+ }
+
+ CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void**) (CFStringRef[]) { CFSTR(kIOHIDDeviceUsagePageKey), CFSTR(kIOHIDDeviceUsageKey) }, (const void**) (CFNumberRef[]) { ffCfCreateInt(kHIDPage_GenericDesktop), ffCfCreateInt(kHIDUsage_GD_Mouse) }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ IOHIDManagerSetDeviceMatching(manager, matching1);
+
+ CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
+ if (set) {
+ CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices);
+ }
+ IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
+
+ return NULL;
+}
diff --git a/src/detection/mouse/mouse_bsd.c b/src/detection/mouse/mouse_bsd.c
new file mode 100644
index 0000000..da7783b
--- /dev/null
+++ b/src/detection/mouse/mouse_bsd.c
@@ -0,0 +1,56 @@
+#include "mouse.h"
+#include "common/io.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <usbhid.h>
+
+#if __has_include(<dev/usb/usb_ioctl.h>)
+ #include <dev/usb/usb_ioctl.h> // FreeBSD
+#else
+ #include <bus/u4b/usb_ioctl.h> // DragonFly
+#endif
+
+#define MAX_UHID_MICE 64
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) {
+ char path[16];
+ for (int i = 0; i < MAX_UHID_MICE; i++) {
+ snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i);
+ FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ if (errno == ENOENT) {
+ break; // No more devices
+ }
+ continue; // Device not found
+ }
+ report_desc_t repDesc = hid_get_report_desc(fd);
+ if (!repDesc) {
+ continue;
+ }
+
+ int reportId = hid_get_report_id(fd);
+
+ struct hid_data* hData = hid_start_parse(repDesc, 0, reportId);
+ if (hData) {
+ struct hid_item hItem;
+ while (hid_get_item(hData, &hItem) > 0) {
+ if (HID_PAGE(hItem.usage) != 1 || HID_USAGE(hItem.usage) != 2) {
+ continue;
+ }
+
+ struct usb_device_info di;
+ if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1) {
+ FFMouseDevice* device = FF_LIST_ADD(FFMouseDevice, *devices);
+ ffStrbufInitS(&device->serial, di.udi_serial);
+ ffStrbufInitS(&device->name, di.udi_product);
+ }
+ }
+ hid_end_parse(hData);
+ }
+
+ hid_dispose_report_desc(repDesc);
+ }
+
+ return NULL;
+}
diff --git a/src/detection/mouse/mouse_haiku.cpp b/src/detection/mouse/mouse_haiku.cpp
new file mode 100644
index 0000000..5835c8e
--- /dev/null
+++ b/src/detection/mouse/mouse_haiku.cpp
@@ -0,0 +1,27 @@
+extern "C" {
+#include "mouse.h"
+}
+
+#include <interface/Input.h>
+#include <support/List.h>
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) {
+ BList list;
+
+ if (get_input_devices(&list) != B_OK) {
+ return "get_input_devices() failed";
+ }
+
+ for (int32 i = 0, n = list.CountItems(); i < n; i++) {
+ BInputDevice* device = (BInputDevice*) list.ItemAt(i);
+ if (device->Type() != B_POINTING_DEVICE || !device->IsRunning()) {
+ continue;
+ }
+
+ FFMouseDevice* item = FF_LIST_ADD(FFMouseDevice, *devices);
+ ffStrbufInit(&item->serial);
+ ffStrbufInitS(&item->name, device->Name());
+ }
+
+ return NULL;
+}
diff --git a/src/detection/mouse/mouse_linux.c b/src/detection/mouse/mouse_linux.c
new file mode 100644
index 0000000..939c332
--- /dev/null
+++ b/src/detection/mouse/mouse_linux.c
@@ -0,0 +1,45 @@
+#include "mouse.h"
+#include "common/io.h"
+#include "common/strutil.h"
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) {
+ FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/");
+ if (dirp == NULL) {
+ return "opendir(\"/sys/class/input/\") == NULL";
+ }
+
+ FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/");
+ uint32_t baseLen = path.length;
+
+ struct dirent* entry;
+ while ((entry = readdir(dirp)) != NULL) {
+ if (!ffStrStartsWith(entry->d_name, "mouse")) {
+ continue;
+ }
+ if (!ffCharIsDigit(entry->d_name[strlen("mouse")])) {
+ continue;
+ }
+
+ ffStrbufAppendS(&path, entry->d_name);
+ ffStrbufAppendS(&path, "/device/name");
+
+ FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
+ if (ffAppendFileBuffer(path.chars, &name)) {
+ ffStrbufTrimRightSpace(&name);
+ ffStrbufSubstrBefore(&path, path.length - 4);
+
+ FFMouseDevice* device = FF_LIST_ADD(FFMouseDevice, *devices);
+ ffStrbufInitMove(&device->name, &name);
+ ffStrbufInit(&device->serial);
+
+ ffStrbufAppendS(&path, "uniq");
+ if (ffAppendFileBuffer(path.chars, &device->serial)) {
+ ffStrbufTrimRightSpace(&device->serial);
+ }
+ }
+
+ ffStrbufSubstrBefore(&path, baseLen);
+ }
+
+ return NULL;
+}
diff --git a/src/detection/mouse/mouse_nosupport.c b/src/detection/mouse/mouse_nosupport.c
new file mode 100644
index 0000000..aa1332d
--- /dev/null
+++ b/src/detection/mouse/mouse_nosupport.c
@@ -0,0 +1,5 @@
+#include "mouse.h"
+
+const char* ffDetectMouse(FF_A_UNUSED FFlist* devices /* List of FFMouseDevice */) {
+ return "No mouse support on this platform";
+}
diff --git a/src/detection/mouse/mouse_windows.c b/src/detection/mouse/mouse_windows.c
new file mode 100644
index 0000000..3f2370a
--- /dev/null
+++ b/src/detection/mouse/mouse_windows.c
@@ -0,0 +1,84 @@
+#define INITGUID
+
+#include "mouse.h"
+#include "common/io.h"
+#include "common/mallocHelper.h"
+#include "common/windows/unicode.h"
+
+#include <windows.h>
+#include <hidsdi.h>
+#include <cfgmgr32.h>
+#include <devpkey.h>
+
+const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) {
+ UINT nDevices = 0;
+ if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST))) {
+ return "GetRawInputDeviceList(NULL) failed";
+ }
+ if (nDevices == 0) {
+ return "No HID devices found";
+ }
+ RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
+ if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1) {
+ return "GetRawInputDeviceList(pRawInputDeviceList) failed";
+ }
+
+ for (UINT i = 0; i < nDevices; ++i) {
+ if (pRawInputDeviceList[i].dwType != RIM_TYPEMOUSE) {
+ continue;
+ }
+
+ HANDLE hDevice = pRawInputDeviceList[i].hDevice;
+
+ RID_DEVICE_INFO rdi;
+ UINT rdiSize = sizeof(rdi);
+ if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1) {
+ continue;
+ }
+
+ WCHAR devName[MAX_PATH];
+ UINT nameSize = MAX_PATH;
+ if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1) {
+ continue;
+ }
+
+ FFMouseDevice* device = FF_LIST_ADD(FFMouseDevice, *devices);
+ ffStrbufInit(&device->serial);
+ ffStrbufInit(&device->name);
+
+ wchar_t buffer[MAX_PATH];
+
+ HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, 0 /* must be 0 instead of GENERIC_READ */, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (hHidFile != INVALID_HANDLE_VALUE) {
+ if (HidD_GetProductString(hHidFile, buffer, (ULONG) sizeof(buffer))) {
+ ffStrbufSetWS(&device->name, buffer);
+ }
+
+ if (HidD_GetSerialNumberString(hHidFile, buffer, sizeof(buffer))) {
+ ffStrbufSetWS(&device->serial, buffer);
+ }
+ }
+
+ if (!device->name.length) {
+ // https://stackoverflow.com/a/64321096/9976392
+ DEVPROPTYPE propertyType;
+ ULONG propertySize = sizeof(buffer);
+
+ if (CM_Get_Device_Interface_PropertyW(devName, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) {
+ DEVINST devInst;
+ if (CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS) {
+ propertySize = sizeof(buffer);
+ if (CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) {
+ ffStrbufSetWS(&device->name, buffer);
+ }
+ }
+ }
+ }
+
+ if (!device->name.length) {
+ ffStrbufSetF(&device->name, "Unknown device %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
+ }
+ }
+
+ return NULL;
+}