diff options
Diffstat (limited to 'src/lib/razerdevice.c')
| -rwxr-xr-x | src/lib/razerdevice.c | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/src/lib/razerdevice.c b/src/lib/razerdevice.c new file mode 100755 index 0000000..2b1bda7 --- /dev/null +++ b/src/lib/razerdevice.c @@ -0,0 +1,470 @@ +#include <stdlib.h> +#include "razerdevice.h" + +bool is_razer_device(IOUSBDeviceInterface **dev) +{ + kern_return_t kr; + UInt16 vendor; + UInt16 product; + UInt16 release; + + kr = (*dev)->GetDeviceVendor(dev, &vendor); + kr = (*dev)->GetDeviceProduct(dev, &product); + kr = (*dev)->GetDeviceReleaseNumber(dev, &release); + + return vendor == USB_VENDOR_ID_RAZER; +} + +bool is_keyboard(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_NOSTROMO: + case USB_DEVICE_ID_RAZER_ORBWEAVER: + case USB_DEVICE_ID_RAZER_ORBWEAVER_CHROMA: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_STEALTH_EDITION: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2012: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2013: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_ULTIMATE_2016: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_ULTIMATE: + case USB_DEVICE_ID_RAZER_TARTARUS: + case USB_DEVICE_ID_RAZER_TARTARUS_CHROMA: + case USB_DEVICE_ID_RAZER_TARTARUS_V2: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_OVERWATCH: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA: + case USB_DEVICE_ID_RAZER_DEATHSTALKER_EXPERT: + case USB_DEVICE_ID_RAZER_DEATHSTALKER_CHROMA: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_TE: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_X_CHROMA_TE: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_LITE: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_2019: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_ESSENTIAL: + case USB_DEVICE_ID_RAZER_ORNATA: + case USB_DEVICE_ID_RAZER_ORNATA_CHROMA: + case USB_DEVICE_ID_RAZER_ORNATA_CHROMA_V2: + case USB_DEVICE_ID_RAZER_HUNTSMAN_ELITE: + case USB_DEVICE_ID_RAZER_HUNTSMAN_TE: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_ELITE: + case USB_DEVICE_ID_RAZER_HUNTSMAN: + case USB_DEVICE_ID_RAZER_CYNOSA_CHROMA: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_CHROMA_V2: + case USB_DEVICE_ID_RAZER_ANANSI: + case USB_DEVICE_ID_RAZER_CYNOSA_V2: + case USB_DEVICE_ID_RAZER_CYNOSA_LITE: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3: + case USB_DEVICE_ID_RAZER_BLACKWIDOW_V3_TK: + case USB_DEVICE_ID_RAZER_HUNTSMAN_MINI: + return true; + } + + return false; +} + +bool is_mouse(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_OROCHI_2011: + case USB_DEVICE_ID_RAZER_DEATHADDER_3_5G: + case USB_DEVICE_ID_RAZER_ABYSSUS_1800: + case USB_DEVICE_ID_RAZER_MAMBA_2012_WIRED: + case USB_DEVICE_ID_RAZER_MAMBA_2012_WIRELESS: + case USB_DEVICE_ID_RAZER_NAGA_2012: + case USB_DEVICE_ID_RAZER_IMPERATOR: + case USB_DEVICE_ID_RAZER_OUROBOROS: + case USB_DEVICE_ID_RAZER_TAIPAN: + case USB_DEVICE_ID_RAZER_NAGA_HEX_RED: + case USB_DEVICE_ID_RAZER_DEATHADDER_2013: + case USB_DEVICE_ID_RAZER_DEATHADDER_1800: + case USB_DEVICE_ID_RAZER_OROCHI_2013: + case USB_DEVICE_ID_RAZER_NAGA_2014: + case USB_DEVICE_ID_RAZER_NAGA_HEX: + case USB_DEVICE_ID_RAZER_ABYSSUS: + case USB_DEVICE_ID_RAZER_DEATHADDER_CHROMA: + case USB_DEVICE_ID_RAZER_MAMBA_WIRED: + case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS: + case USB_DEVICE_ID_RAZER_MAMBA_TE_WIRED: + case USB_DEVICE_ID_RAZER_OROCHI_CHROMA: + case USB_DEVICE_ID_RAZER_DIAMONDBACK_CHROMA: + case USB_DEVICE_ID_RAZER_NAGA_HEX_V2: + case USB_DEVICE_ID_RAZER_NAGA_CHROMA: + case USB_DEVICE_ID_RAZER_DEATHADDER_3500: + case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRED: + case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS: + case USB_DEVICE_ID_RAZER_ABYSSUS_V2: + case USB_DEVICE_ID_RAZER_DEATHADDER_ELITE: + case USB_DEVICE_ID_RAZER_ABYSSUS_2000: + case USB_DEVICE_ID_RAZER_LANCEHEAD_TE_WIRED: + case USB_DEVICE_ID_RAZER_BASILISK: + case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE: + case USB_DEVICE_ID_RAZER_BASILISK_ULTIMATE_RECEIVER: + case USB_DEVICE_ID_RAZER_NAGA_TRINITY: + case USB_DEVICE_ID_RAZER_ABYSSUS_ELITE_DVA_EDITION: + case USB_DEVICE_ID_RAZER_ABYSSUS_ESSENTIAL: + case USB_DEVICE_ID_RAZER_MAMBA_ELITE: + case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL: + case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_RECEIVER: + case USB_DEVICE_ID_RAZER_LANCEHEAD_WIRELESS_WIRED: + case USB_DEVICE_ID_RAZER_DEATHADDER_ESSENTIAL_WHITE_EDITION: + case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_RECEIVER: + case USB_DEVICE_ID_RAZER_MAMBA_WIRELESS_WIRED: + case USB_DEVICE_ID_RAZER_VIPER: + case USB_DEVICE_ID_RAZER_VIPER_8KHZ: + case USB_DEVICE_ID_RAZER_VIPER_MINI: + case USB_DEVICE_ID_RAZER_BASILISK_V2: + case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRED: + case USB_DEVICE_ID_RAZER_VIPER_ULTIMATE_WIRELESS: + case USB_DEVICE_ID_RAZER_DEATHADDER_V2: + case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRED: + case USB_DEVICE_ID_RAZER_DEATHADDER_V2_PRO_WIRELESS: + case USB_DEVICE_ID_RAZER_DEATHADDER_V2_MINI: + case USB_DEVICE_ID_RAZER_NAGA_LEFT_HANDED_2020: + case USB_DEVICE_ID_RAZER_ATHERIS_RECEIVER: + return true; + } + + return false; +} + +bool is_mouse_dock(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_MOUSE_CHARGING_DOCK: + return true; + } + + return false; +} + +bool is_mouse_mat(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_FIREFLY_HYPERFLUX: + case USB_DEVICE_ID_RAZER_FIREFLY: + case USB_DEVICE_ID_RAZER_FIREFLY_V2: + case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA: + case USB_DEVICE_ID_RAZER_GOLIATHUS_CHROMA_EXTENDED: + return true; + } + + return false; +} + +bool is_egpu(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_CORE_X_CHROMA: + return true; + } + + return false; +} + + +bool is_headphone(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_KRAKEN_KITTY_EDITION: + case USB_DEVICE_ID_RAZER_KRAKEN_V2: + case USB_DEVICE_ID_RAZER_KRAKEN_ULTIMATE: + return true; + } + + return false; +} + +bool is_accessory(IOUSBDeviceInterface **usb_dev) +{ + UInt16 product = -1; + (*usb_dev)->GetDeviceProduct(usb_dev, &product); + + switch (product) + { + case USB_DEVICE_ID_RAZER_NOMMO_CHROMA: + case USB_DEVICE_ID_RAZER_NOMMO_PRO: + case USB_DEVICE_ID_RAZER_CHROMA_MUG: + case USB_DEVICE_ID_RAZER_CHROMA_BASE: + case USB_DEVICE_ID_RAZER_CHROMA_HDK: + case USB_DEVICE_ID_RAZER_MOUSE_BUNGEE_V3_CHROMA: + case USB_DEVICE_ID_RAZER_BASE_STATION_V2_CHROMA: + return true; + } + + return false; +} + +IOUSBDeviceInterface **getRazerUSBDeviceInterface(int type) +{ + CFMutableDictionaryRef matchingDict; + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); + if (matchingDict == NULL) + { + return NULL; + } + + io_iterator_t iter; + kern_return_t kReturn = + IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter); + if (kReturn != kIOReturnSuccess) + { + return NULL; + } + + io_service_t usbDevice; + while ((usbDevice = IOIteratorNext(iter))) + { + IOCFPlugInInterface **plugInInterface = NULL; + SInt32 score; + + kReturn = IOCreatePlugInInterfaceForService( + usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); + + IOObjectRelease(usbDevice); // Not needed after plugin created + if ((kReturn != kIOReturnSuccess) || plugInInterface == NULL) + { + // printf("Unable to create plugin (0x%08x)\n", kReturn); + continue; + } + + IOUSBDeviceInterface **dev = NULL; + HRESULT hResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); + + (*plugInInterface)->Release(plugInInterface); // Not needed after device interface created + if (hResult || !dev) + { + // printf("Couldn’t create a device interface (0x%08x)\n", (int) hResult); + continue; + } + + // Filter out non-Razer devices + if (!is_razer_device(dev)) + { + (*dev)->Release(dev); + continue; + } + + switch (type) + { + case TYPE_KEYBOARD: + case TYPE_BLADE: + // Filter out non-keyboards and non-blade laptops + if (!(is_keyboard(dev) || is_blade_laptop(dev))) + { + (*dev)->Release(dev); + continue; + } + break; + + case TYPE_MOUSE: + // Filter out non-mice + if (!is_mouse(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + + case TYPE_MOUSE_DOCK: + // Filter out non-mice-mats + if (!is_mouse_dock(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + + case TYPE_MOUSE_MAT: + // Filter out non-mice-mats + if (!is_mouse_mat(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + + case TYPE_HEADPHONE: + if (!is_headphone(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + + case TYPE_EGPU: + // Filter out non-mice-mats + if (!is_egpu(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + case TYPE_ACCESSORY: + if (!is_accessory(dev)) + { + (*dev)->Release(dev); + continue; + } + break; + + default: + // Unsupported Razer peripheral type + (*dev)->Release(dev); + continue; + } + + kReturn = (*dev)->USBDeviceOpen(dev); + if (kReturn != kIOReturnSuccess) + { + printf("Unable to open USB device: %08x\n", kReturn); + (*dev)->Release(dev); + continue; + } + + // Success. We found the Razer USB device. + // Caller is responsible for closing USB and release device. + IOObjectRelease(iter); + return dev; + } + + IOObjectRelease(iter); + return NULL; +} + +void closeRazerUSBDeviceInterface(IOUSBDeviceInterface **dev) +{ + kern_return_t kr; + kr = (*dev)->USBDeviceClose(dev); + kr = (*dev)->Release(dev); +} + +RazerDevices getAllRazerDevices() +{ + RazerDevices allDevices = { .devices = NULL, .size = 0 }; + + CFMutableDictionaryRef matchingDict; + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); + if (matchingDict == NULL) + { + return allDevices; + } + + io_iterator_t iter; + kern_return_t kReturn = + IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter); + if (kReturn != kIOReturnSuccess) + { + return allDevices; + } + + int array_size = 0; + int array_index = -1; + RazerDevice *razerDevices = malloc(array_size * sizeof(RazerDevice)); + + io_service_t usbDevice; + while ((usbDevice = IOIteratorNext(iter))) + { + IOCFPlugInInterface **plugInInterface = NULL; + SInt32 score; + + kReturn = IOCreatePlugInInterfaceForService( + usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); + + IOObjectRelease(usbDevice); // Not needed after plugin created + if ((kReturn != kIOReturnSuccess) || plugInInterface == NULL) + { + // printf("Unable to create plugin (0x%08x)\n", kReturn); + continue; + } + + IOUSBDeviceInterface **dev = NULL; + HRESULT hResult = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID *)&dev); + + (*plugInInterface)->Release(plugInInterface); // Not needed after device interface created + if (hResult || !dev) + { + // printf("Couldn’t create a device interface (0x%08x)\n", (int) hResult); + continue; + } + + // Filter out non-Razer devices + if (!is_razer_device(dev)) + { + (*dev)->Release(dev); + continue; + } + + if(!is_keyboard(dev) + && !is_blade_laptop(dev) + && !is_mouse(dev) + && !is_mouse_dock(dev) + && !is_mouse_dock(dev) + && !is_mouse_mat(dev) + && !is_headphone(dev) + && !is_egpu(dev) + && !is_accessory(dev) + ) { + (*dev)->Release(dev); + continue; + } + + kReturn = (*dev)->USBDeviceOpen(dev); + if (kReturn != kIOReturnSuccess) + { + printf("Unable to open USB device: %08x\n", kReturn); + (*dev)->Release(dev); + continue; + } + + // Success. We found the Razer USB device. + // Caller is responsible for closing USB and release device. + array_size++; + razerDevices = realloc(razerDevices, array_size * sizeof(RazerDevice)); + array_index++; + + UInt16 productId; + (*dev)->GetDeviceProduct(dev, &productId); + + RazerDevice newDevice = { .usbDevice = dev, .internalDeviceId = array_index, .productId = productId }; + razerDevices[array_index] = newDevice; + } + + IOObjectRelease(iter); + allDevices.devices = razerDevices; + allDevices.size = array_size; + return allDevices; +} + +void closeAllRazerDevices(RazerDevices devices) +{ + for(int counter=0; counter < devices.size; ++counter) { + IOUSBDeviceInterface **dev = devices.devices[counter].usbDevice; + (*dev)->USBDeviceClose(dev); + (*dev)->Release(dev); + } + free(devices.devices); + devices.devices = NULL; +} |
