pacdrive hidapi implementation
This commit is contained in:
@@ -182,6 +182,7 @@ list(APPEND SMDATA_ARCH_LIGHTS_SRC "arch/Lights/LightsDriver.cpp"
|
|||||||
"arch/Lights/LightsDriver_SystemMessage.cpp"
|
"arch/Lights/LightsDriver_SystemMessage.cpp"
|
||||||
"arch/Lights/LightsDriver_stac.cpp"
|
"arch/Lights/LightsDriver_stac.cpp"
|
||||||
"arch/Lights/LightsDriver_snek.cpp"
|
"arch/Lights/LightsDriver_snek.cpp"
|
||||||
|
"arch/Lights/LightsDriver_PacDrive.cpp"
|
||||||
"arch/Lights/LightsDriver_HidBlueDot.cpp")
|
"arch/Lights/LightsDriver_HidBlueDot.cpp")
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_HPP "arch/Lights/LightsDriver.h"
|
list(APPEND SMDATA_ARCH_LIGHTS_HPP "arch/Lights/LightsDriver.h"
|
||||||
"arch/Lights/LightsDriver_Export.h"
|
"arch/Lights/LightsDriver_Export.h"
|
||||||
@@ -190,6 +191,7 @@ list(APPEND SMDATA_ARCH_LIGHTS_HPP "arch/Lights/LightsDriver.h"
|
|||||||
"arch/Lights/SextetUtils.h"
|
"arch/Lights/SextetUtils.h"
|
||||||
"arch/Lights/LightsDriver_stac.h"
|
"arch/Lights/LightsDriver_stac.h"
|
||||||
"arch/Lights/LightsDriver_snek.h"
|
"arch/Lights/LightsDriver_snek.h"
|
||||||
|
"arch/Lights/LightsDriver_PacDrive.h"
|
||||||
"arch/Lights/LightsDriver_HidBlueDot.h")
|
"arch/Lights/LightsDriver_HidBlueDot.h")
|
||||||
|
|
||||||
# TODO: Confirm if Apple can use the export.
|
# TODO: Confirm if Apple can use the export.
|
||||||
@@ -197,12 +199,10 @@ if(NOT APPLE)
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
||||||
"arch/Lights/LightsDriver_Win32Serial.cpp"
|
"arch/Lights/LightsDriver_Win32Serial.cpp"
|
||||||
"arch/Lights/LightsDriver_Win32Parallel.cpp"
|
"arch/Lights/LightsDriver_Win32Parallel.cpp")
|
||||||
"arch/Lights/LightsDriver_PacDrive.cpp")
|
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_HPP
|
list(APPEND SMDATA_ARCH_LIGHTS_HPP
|
||||||
"arch/Lights/LightsDriver_Win32Parallel.h"
|
"arch/Lights/LightsDriver_Win32Parallel.h"
|
||||||
"arch/Lights/LightsDriver_Win32Serial.h"
|
"arch/Lights/LightsDriver_Win32Serial.h")
|
||||||
"arch/Lights/LightsDriver_PacDrive.h")
|
|
||||||
if(WITH_MINIMAID)
|
if(WITH_MINIMAID)
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
||||||
"arch/Lights/LightsDriver_Win32Minimaid.cpp")
|
"arch/Lights/LightsDriver_Win32Minimaid.cpp")
|
||||||
@@ -218,7 +218,6 @@ if(NOT APPLE)
|
|||||||
"arch/Lights/LightsDriver_Linux_PIUIO_Leds.cpp"
|
"arch/Lights/LightsDriver_Linux_PIUIO_Leds.cpp"
|
||||||
"arch/Lights/LightsDriver_Linux_PIUIOBTN_Leds.cpp"
|
"arch/Lights/LightsDriver_Linux_PIUIOBTN_Leds.cpp"
|
||||||
"arch/Lights/LightsDriver_Linux_ITGIO.cpp"
|
"arch/Lights/LightsDriver_Linux_ITGIO.cpp"
|
||||||
"arch/Lights/LightsDriver_LinuxPacDrive.cpp"
|
|
||||||
"arch/Lights/LightsDriver_LinuxWeedTech.cpp")
|
"arch/Lights/LightsDriver_LinuxWeedTech.cpp")
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_HPP
|
list(APPEND SMDATA_ARCH_LIGHTS_HPP
|
||||||
"arch/Lights/LightsDriver_Linux_Leds.h"
|
"arch/Lights/LightsDriver_Linux_Leds.h"
|
||||||
@@ -226,7 +225,6 @@ if(NOT APPLE)
|
|||||||
"arch/Lights/LightsDriver_Linux_PIUIO_Leds.h"
|
"arch/Lights/LightsDriver_Linux_PIUIO_Leds.h"
|
||||||
"arch/Lights/LightsDriver_Linux_PIUIOBTN_Leds.h"
|
"arch/Lights/LightsDriver_Linux_PIUIOBTN_Leds.h"
|
||||||
"arch/Lights/LightsDriver_Linux_ITGIO.h"
|
"arch/Lights/LightsDriver_Linux_ITGIO.h"
|
||||||
"arch/Lights/LightsDriver_LinuxPacDrive.h"
|
|
||||||
"arch/Lights/LightsDriver_LinuxWeedTech.h")
|
"arch/Lights/LightsDriver_LinuxWeedTech.h")
|
||||||
if(WITH_MINIMAID)
|
if(WITH_MINIMAID)
|
||||||
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
list(APPEND SMDATA_ARCH_LIGHTS_SRC
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
// Cross-platform, libusb-based driver for outputting lights
|
|
||||||
// via a PacDrive (http://www.ultimarc.com/pacdrive.html)
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "RageLog.h"
|
|
||||||
#include "LightsDriver_LinuxPacDrive.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
|
|
||||||
REGISTER_LIGHTS_DRIVER_CLASS( LinuxPacDrive );
|
|
||||||
|
|
||||||
// HID Class-Specific Requests values. See section 7.2 of the HID specifications
|
|
||||||
#define HID_GET_REPORT 0x01
|
|
||||||
#define HID_GET_IDLE 0x02
|
|
||||||
#define HID_GET_PROTOCOL 0x03
|
|
||||||
#define HID_SET_REPORT 0x09
|
|
||||||
#define HID_SET_IDLE 0x0A
|
|
||||||
#define HID_SET_PROTOCOL 0x0B
|
|
||||||
#define HID_REPORT_TYPE_INPUT 0x01
|
|
||||||
#define HID_REPORT_TYPE_OUTPUT 0x02
|
|
||||||
#define HID_REPORT_TYPE_FEATURE 0x03
|
|
||||||
|
|
||||||
#define HID_IFACE_IN 256
|
|
||||||
#define HID_IFACE_OUT 512
|
|
||||||
|
|
||||||
// PacDrives have PIDs 1500 - 1507, but we'll handle that later.
|
|
||||||
const unsigned PACDRIVE_TIMEOUT = 10000;
|
|
||||||
const int PACDRIVE_VENDOR_ID = 0xD209;
|
|
||||||
const int PACDRIVE_PRODUCT_ID = 0x1500;
|
|
||||||
|
|
||||||
//Adds new preference to allow for different light wiring setups
|
|
||||||
static Preference<RString> g_sPacDriveLightOrdering("PacDriveLightOrdering", "openitg");
|
|
||||||
int iLightingOrder = 0;
|
|
||||||
|
|
||||||
LightsDriver_LinuxPacDrive::LightsDriver_LinuxPacDrive()
|
|
||||||
{
|
|
||||||
DeviceHandle = NULL;
|
|
||||||
|
|
||||||
OpenDevice();
|
|
||||||
|
|
||||||
// clear all lights
|
|
||||||
WriteDevice( 0 );
|
|
||||||
|
|
||||||
RString lightOrder = g_sPacDriveLightOrdering.Get();
|
|
||||||
if (lightOrder.CompareNoCase("lumenar") == 0 || lightOrder.CompareNoCase("openitg") == 0) {
|
|
||||||
iLightingOrder = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LightsDriver_LinuxPacDrive::~LightsDriver_LinuxPacDrive()
|
|
||||||
{
|
|
||||||
// clear all lights and close the connection
|
|
||||||
WriteDevice( 0 );
|
|
||||||
CloseDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightsDriver_LinuxPacDrive::Set( const LightsState *ls )
|
|
||||||
{
|
|
||||||
if ( !DeviceHandle ) return;
|
|
||||||
|
|
||||||
uint16_t outb = 0;
|
|
||||||
|
|
||||||
switch (iLightingOrder) {
|
|
||||||
case 1:
|
|
||||||
//Sets the cabinet light values to follow LumenAR/OpenITG wiring standards
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OpenITG PacDrive Order:
|
|
||||||
* Taken from LightsDriver_PacDrive::SetLightsMappings() in openitg.
|
|
||||||
*
|
|
||||||
* 0: Marquee UL
|
|
||||||
* 1: Marquee UR
|
|
||||||
* 2: Marquee DL
|
|
||||||
* 3: Marquee DR
|
|
||||||
*
|
|
||||||
* 4: P1 Button
|
|
||||||
* 5: P2 Button
|
|
||||||
*
|
|
||||||
* 6: Bass Left
|
|
||||||
* 7: Bass Right
|
|
||||||
*
|
|
||||||
* 8,9,10,11: P1 L R U D
|
|
||||||
* 12,13,14,15: P2 L R U D
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT]) outb |= BIT(0);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT]) outb |= BIT(1);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT]) outb |= BIT(2);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT]) outb |= BIT(3);
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START]) outb |= BIT(4);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START]) outb |= BIT(5);
|
|
||||||
|
|
||||||
//Most PacDrive/Cabinet setups only have *one* bass light, so mux them together here.
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT]) outb |= BIT(6);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT]) outb |= BIT(7);
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT]) outb |= BIT(8);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT]) outb |= BIT(9);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP]) outb |= BIT(10);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN]) outb |= BIT(11);
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT]) outb |= BIT(12);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT]) outb |= BIT(13);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP]) outb |= BIT(14);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN]) outb |= BIT(15);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
//If all else fails, falls back to original order
|
|
||||||
//reference page 7
|
|
||||||
//http://www.peeweepower.com/stepmania/sm509pacdriveinfo.pdf
|
|
||||||
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT]) outb |= BIT(0);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT]) outb |= BIT(1);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT]) outb |= BIT(2);
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT]) outb |= BIT(3);
|
|
||||||
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT]) outb |= BIT(4);
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT]) outb |= BIT(5);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT]) outb |= BIT(6);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP]) outb |= BIT(7);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN]) outb |= BIT(8);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START]) outb |= BIT(9);
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT]) outb |= BIT(10);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT]) outb |= BIT(11);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP]) outb |= BIT(12);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN]) outb |= BIT(13);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START]) outb |= BIT(14);
|
|
||||||
//Bit index 15 is unused.
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteDevice(outb);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightsDriver_LinuxPacDrive::OpenDevice()
|
|
||||||
{
|
|
||||||
libusb_device **devs;
|
|
||||||
libusb_device *dev = NULL;
|
|
||||||
ssize_t result;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
CloseDevice(); // Ensure any previously opened device is closed first to prevent conflicts
|
|
||||||
|
|
||||||
libusb_context* context = USBContext::getInstance().getContext();
|
|
||||||
if (!context)
|
|
||||||
{
|
|
||||||
LOG->Warn("libusb: Failed to initialize context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
|
|
||||||
|
|
||||||
result = libusb_get_device_list(context, &devs);
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
LOG->Warn("libusb_get_device_list failed: %s", libusb_error_name(result));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dev = devs[i++]) != NULL)
|
|
||||||
{
|
|
||||||
libusb_device_descriptor desc;
|
|
||||||
// Note since libusb-1.0.16, LIBUSBX_API_VERSION >= 0x01000102, this function always succeeds:
|
|
||||||
libusb_get_device_descriptor(dev, &desc);
|
|
||||||
|
|
||||||
if (PACDRIVE_VENDOR_ID == desc.idVendor &&
|
|
||||||
PACDRIVE_PRODUCT_ID <= desc.idProduct &&
|
|
||||||
PACDRIVE_PRODUCT_ID + 8 > desc.idProduct)
|
|
||||||
{
|
|
||||||
LOG->Info("PacDrive device was found vid: 0x%04x pid: 0x%04x", desc.idVendor, desc.idProduct);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dev)
|
|
||||||
{
|
|
||||||
LOG->Warn("PacDrive was not found");
|
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = libusb_open(dev, &DeviceHandle);
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
LOG->Warn("libusb_open failed: %s", libusb_error_name(result));
|
|
||||||
DeviceHandle = NULL;
|
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_free_device_list(devs, 1);
|
|
||||||
|
|
||||||
if (libusb_kernel_driver_active(DeviceHandle, 0) == 1)
|
|
||||||
{
|
|
||||||
LOG->Warn("Kernel Driver Active");
|
|
||||||
if (libusb_detach_kernel_driver(DeviceHandle, 0) == 0)
|
|
||||||
LOG->Warn("Kernel Driver Detached!");
|
|
||||||
}
|
|
||||||
|
|
||||||
result = libusb_claim_interface(DeviceHandle, 0);
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
LOG->Warn("libusb_claim_interface: cannot claim interface: %s", libusb_error_name(result));
|
|
||||||
libusb_close(DeviceHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG->Info("Device claimed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightsDriver_LinuxPacDrive::CloseDevice()
|
|
||||||
{
|
|
||||||
if (!DeviceHandle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ssize_t result;
|
|
||||||
|
|
||||||
result = libusb_release_interface(DeviceHandle, 0);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
LOG->Warn("libusb_release_interface: %s", libusb_error_name(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_close(DeviceHandle);
|
|
||||||
DeviceHandle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightsDriver_LinuxPacDrive::WriteDevice(uint16_t out)
|
|
||||||
{
|
|
||||||
if (!DeviceHandle) return;
|
|
||||||
|
|
||||||
// output is within the first 16 bits - accept a
|
|
||||||
// 16-bit arg and cast it, for simplicity's sake.
|
|
||||||
uint32_t data = (out << 16);
|
|
||||||
int expected = sizeof(data);
|
|
||||||
|
|
||||||
ssize_t result = libusb_control_transfer(DeviceHandle,
|
|
||||||
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE,
|
|
||||||
HID_SET_REPORT,
|
|
||||||
HID_IFACE_OUT,
|
|
||||||
0,
|
|
||||||
(unsigned char*)&data,
|
|
||||||
expected,
|
|
||||||
PACDRIVE_TIMEOUT);
|
|
||||||
|
|
||||||
if(result != expected) {
|
|
||||||
LOG->Warn("PacDrive writing failed: %li (%s)\n", result, libusb_error_name(result));
|
|
||||||
CloseDevice();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rewritten for libusb 1.0 2024 sirex
|
|
||||||
* Rewritten for libusb 1.0 2024 sukibaby
|
|
||||||
* Original libusb 0.1 file Copyright (c) 2008 BoXoRRoXoRs
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
||||||
* whom the Software is furnished to do so, provided that the above
|
|
||||||
* copyright notice(s) and this permission notice appear in all copies of
|
|
||||||
* the Software and that both the above copyright notice(s) and this
|
|
||||||
* permission notice appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
||||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
||||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
||||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#ifndef LIGHTSDRIVER_LINUXPACDRIVE_H
|
|
||||||
#define LIGHTSDRIVER_LINUXPACDRIVE_H
|
|
||||||
|
|
||||||
#include "LightsDriver.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#define BIT(i) (1<<(i))
|
|
||||||
|
|
||||||
class USBContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static USBContext& getInstance()
|
|
||||||
{
|
|
||||||
static USBContext instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_context* getContext() { return context; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
USBContext()
|
|
||||||
{
|
|
||||||
int result = libusb_init_context(&context, NULL, 0);
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
// initialization error
|
|
||||||
context = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~USBContext()
|
|
||||||
{
|
|
||||||
if (context)
|
|
||||||
{
|
|
||||||
libusb_exit(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_context* context;
|
|
||||||
|
|
||||||
// prevent copying
|
|
||||||
USBContext(const USBContext&) = delete;
|
|
||||||
USBContext& operator=(const USBContext&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LightsDriver_LinuxPacDrive: public LightsDriver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LightsDriver_LinuxPacDrive();
|
|
||||||
~LightsDriver_LinuxPacDrive();
|
|
||||||
|
|
||||||
void Set( const LightsState *ls );
|
|
||||||
private:
|
|
||||||
|
|
||||||
void OpenDevice();
|
|
||||||
void WriteDevice(uint16_t out);
|
|
||||||
void CloseDevice();
|
|
||||||
|
|
||||||
libusb_device_handle *DeviceHandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // LIGHTSDRIVER_LINUXPACDRIVE_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2008 BoXoRRoXoRs
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
||||||
* whom the Software is furnished to do so, provided that the above
|
|
||||||
* copyright notice(s) and this permission notice appear in all copies of
|
|
||||||
* the Software and that both the above copyright notice(s) and this
|
|
||||||
* permission notice appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
||||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
||||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
||||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
@@ -1,149 +1,123 @@
|
|||||||
// LightsDriver_PacDrive for use with a PacDrive hooked up with LEDs
|
|
||||||
// You need PacDrive64.dll in the StepMania directory to use this.
|
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "RageLog.h"
|
||||||
#include "LightsDriver_PacDrive.h"
|
#include "LightsDriver_PacDrive.h"
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include "GameState.h"
|
||||||
#include "windows.h"
|
#include "Game.h"
|
||||||
#include "RageUtil.h"
|
|
||||||
#include "Preference.h"
|
|
||||||
|
|
||||||
REGISTER_LIGHTS_DRIVER_CLASS(PacDrive);
|
REGISTER_LIGHTS_DRIVER_CLASS(PacDrive);
|
||||||
|
|
||||||
HINSTANCE PachDLL = nullptr;
|
static Preference<RString> g_sPacDriveLightOrdering("PacDriveLightOrdering", "openitg");
|
||||||
|
int iPacDriveLightOrder = 0;
|
||||||
|
|
||||||
bool PacDriveConnected = false;
|
LightsDriver_PacDrive::LightsDriver_PacDrive() : dev{PACDRIVE_VID, PACDRIVE_PID, PACDRIVE_INTERFACE}
|
||||||
typedef int (WINAPI PacInitialize)(void);
|
|
||||||
PacInitialize* m_pacinit = nullptr;
|
|
||||||
typedef void (WINAPI PacShutdown)(void);
|
|
||||||
PacShutdown* m_pacdone = nullptr;
|
|
||||||
typedef bool (WINAPI PacSetLEDStates)(int, short int);
|
|
||||||
PacSetLEDStates* m_pacset = nullptr;
|
|
||||||
int iLightingOrder = 0;
|
|
||||||
|
|
||||||
//Adds new preference to allow for different light wiring setups
|
|
||||||
static Preference<RString> g_sPacDriveLightOrdering("PacDriveLightOrdering", "lumenar");
|
|
||||||
|
|
||||||
|
|
||||||
LightsDriver_PacDrive::LightsDriver_PacDrive()
|
|
||||||
{
|
{
|
||||||
// init io.dll
|
prev_led_state.raw = 0;
|
||||||
PachDLL = LoadLibrary("pacdrive64.dll");
|
memset(state.raw_state, 0x00, sizeof(state.raw_state));
|
||||||
if(PachDLL == nullptr)
|
|
||||||
|
// TODO: Check for all 8 of the PacDrive PIDs instead of just the first one.
|
||||||
|
// Uncertain how many are not just the stock value.
|
||||||
|
|
||||||
|
RString lightOrder = g_sPacDriveLightOrdering.Get();
|
||||||
|
if (lightOrder.CompareNoCase("lumenar") == 0 || lightOrder.CompareNoCase("openitg") == 0)
|
||||||
{
|
{
|
||||||
MessageBox(nullptr, "Could not LoadLibrary( pacdrive64.dll ).", "ERROR", MB_OK );
|
iPacDriveLightOrder = 1;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the function pointers
|
|
||||||
m_pacinit = (PacInitialize*)GetProcAddress(PachDLL, "PacInitialize");
|
|
||||||
m_pacset = (PacSetLEDStates*)GetProcAddress(PachDLL, "PacSetLEDStates");
|
|
||||||
m_pacdone = (PacShutdown*)GetProcAddress(PachDLL, "PacShutdown");
|
|
||||||
|
|
||||||
int NumPacDrives = 0;
|
|
||||||
|
|
||||||
if (m_pacinit)
|
|
||||||
NumPacDrives = m_pacinit(); //initialize the pac drive
|
|
||||||
|
|
||||||
if (NumPacDrives == 0)
|
|
||||||
{
|
|
||||||
PacDriveConnected = false; // set not connected
|
|
||||||
MessageBox(nullptr, "Could not find connected PacDrive.", "ERROR", MB_OK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PacDriveConnected = true; // set connected
|
|
||||||
m_pacset(0, 0x0); // clear all lights for device i
|
|
||||||
RString lightOrder = g_sPacDriveLightOrdering.Get();
|
|
||||||
if (lightOrder.CompareNoCase("lumenar") == 0 || lightOrder.CompareNoCase("openitg") == 0) {
|
|
||||||
iLightingOrder = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LightsDriver_PacDrive::~LightsDriver_PacDrive()
|
LightsDriver_PacDrive::~LightsDriver_PacDrive()
|
||||||
{
|
{
|
||||||
if (PacDriveConnected && m_pacset)
|
|
||||||
m_pacset(0, 0x0); // clear all lights for device i
|
|
||||||
|
|
||||||
if (m_pacdone)
|
|
||||||
m_pacdone();
|
|
||||||
|
|
||||||
FreeLibrary(PachDLL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightsDriver_PacDrive::Set(const LightsState *ls)
|
void LightsDriver_PacDrive::Set(const LightsState *ls)
|
||||||
{
|
{
|
||||||
short int outb = 0;
|
if (!dev.FoundOnce())
|
||||||
switch (iLightingOrder) {
|
return;
|
||||||
case 1:
|
|
||||||
//Sets the cabinet light values to follow LumenAR/OpenITG wiring standards
|
|
||||||
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT]) outb |= BIT(0);
|
switch (iPacDriveLightOrder)
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT]) outb |= BIT(1);
|
{
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP]) outb |= BIT(2);
|
case 1:
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN]) outb |= BIT(3);
|
// Sets the cabinet light values to follow LumenAR/OpenITG wiring standards
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT]) outb |= BIT(4);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT]) outb |= BIT(5);
|
/*
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP]) outb |= BIT(6);
|
* OpenITG PacDrive Order:
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN]) outb |= BIT(7);
|
* Taken from LightsDriver_PacDrive::SetLightsMappings() in openitg.
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT]) outb |= BIT(8);
|
* (index of 1 as the PacDrive labels them as index 1)
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT]) outb |= BIT(9);
|
*
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT]) outb |= BIT(10);
|
* 1: Marquee UL
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT]) outb |= BIT(11);
|
* 2: Marquee UR
|
||||||
if (ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START]) outb |= BIT(12);
|
* 3: Marquee DL
|
||||||
if (ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START]) outb |= BIT(13);
|
* 4: Marquee DR
|
||||||
if (ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT]) outb |= BIT(14);
|
*
|
||||||
|
* 5: P1 Button
|
||||||
|
* 6: P2 Button
|
||||||
|
*
|
||||||
|
* 7: Bass Left
|
||||||
|
* 8: Bass Right
|
||||||
|
*
|
||||||
|
* 9,19,11,12: P1 L R U D
|
||||||
|
* 13,14,15,16: P2 L R U D
|
||||||
|
*/
|
||||||
|
|
||||||
|
state.leds.led01 = ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT];
|
||||||
|
state.leds.led02 = ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT];
|
||||||
|
state.leds.led03 = ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT];
|
||||||
|
state.leds.led04 = ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT];
|
||||||
|
|
||||||
|
state.leds.led05 = ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START];
|
||||||
|
state.leds.led06 = ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START];
|
||||||
|
|
||||||
|
state.leds.led07 = ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT];
|
||||||
|
state.leds.led08 = ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT];
|
||||||
|
|
||||||
|
state.leds.led09 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT];
|
||||||
|
state.leds.led10 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT];
|
||||||
|
state.leds.led11 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP];
|
||||||
|
state.leds.led12 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN];
|
||||||
|
|
||||||
|
state.leds.led13 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT];
|
||||||
|
state.leds.led14 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT];
|
||||||
|
state.leds.led15 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP];
|
||||||
|
state.leds.led16 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
//If all else fails, falls back to Minimaid order
|
// If all else fails, falls back to original order
|
||||||
|
// reference page 7
|
||||||
|
// http://www.peeweepower.com/stepmania/sm509pacdriveinfo.pdf
|
||||||
|
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT]) outb |= BIT(0);
|
state.leds.led01 = ls->m_bCabinetLights[LIGHT_MARQUEE_UP_LEFT];
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT]) outb |= BIT(1);
|
state.leds.led02 = ls->m_bCabinetLights[LIGHT_MARQUEE_UP_RIGHT];
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT]) outb |= BIT(2);
|
state.leds.led03 = ls->m_bCabinetLights[LIGHT_MARQUEE_LR_LEFT];
|
||||||
if (ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT]) outb |= BIT(3);
|
state.leds.led04 = ls->m_bCabinetLights[LIGHT_MARQUEE_LR_RIGHT];
|
||||||
if (ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT]) outb |= BIT(4);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT]) outb |= BIT(5);
|
state.leds.led05 = ls->m_bCabinetLights[LIGHT_BASS_LEFT] || ls->m_bCabinetLights[LIGHT_BASS_RIGHT];
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT]) outb |= BIT(6);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP]) outb |= BIT(7);
|
state.leds.led06 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_LEFT];
|
||||||
if (ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN]) outb |= BIT(8);
|
state.leds.led07 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_RIGHT];
|
||||||
if (ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START]) outb |= BIT(9);
|
state.leds.led08 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_UP];
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT]) outb |= BIT(10);
|
state.leds.led09 = ls->m_bGameButtonLights[GameController_1][DANCE_BUTTON_DOWN];
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT]) outb |= BIT(11);
|
state.leds.led10 = ls->m_bGameButtonLights[GameController_1][GAME_BUTTON_START];
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP]) outb |= BIT(12);
|
|
||||||
if (ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN]) outb |= BIT(13);
|
state.leds.led11 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_LEFT];
|
||||||
if (ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START]) outb |= BIT(14);
|
state.leds.led12 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_RIGHT];
|
||||||
|
state.leds.led13 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_UP];
|
||||||
|
state.leds.led14 = ls->m_bGameButtonLights[GameController_2][DANCE_BUTTON_DOWN];
|
||||||
|
state.leds.led15 = ls->m_bGameButtonLights[GameController_2][GAME_BUTTON_START];
|
||||||
|
|
||||||
|
// led16 is not used.
|
||||||
|
state.leds.led16 = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure m_pacset function call was loaded.
|
// only push on changes.
|
||||||
if (m_pacset)
|
if (state.leds.raw != prev_led_state.raw)
|
||||||
m_pacset(0, outb);
|
{
|
||||||
}
|
state.report_id = PACDRIVE_HIDREPORT_ID;
|
||||||
|
state.pad0 = 0;
|
||||||
|
state.pad1 = 0;
|
||||||
|
|
||||||
/* Modified 2015 Dave Barribeau for StepMania 5.09
|
dev.Write((unsigned char *)&state.raw_state, sizeof(state.raw_state));
|
||||||
* (c) 2003-2004 Chris Danford
|
prev_led_state = state.leds;
|
||||||
* All rights reserved.
|
}
|
||||||
*
|
}
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
||||||
* whom the Software is furnished to do so, provided that the above
|
|
||||||
* copyright notice(s) and this permission notice appear in all copies of
|
|
||||||
* the Software and that both the above copyright notice(s) and this
|
|
||||||
* permission notice appear in supporting documentation.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
||||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
||||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
||||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
* PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,28 +1,114 @@
|
|||||||
/*
|
/* LightsDriver_PacDrive: Control lights for the PacDrive by Ultimarc using hidapi */
|
||||||
* LightsDriver_PacDrive
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LightsDriver_PacDrive_H
|
#ifndef LightsDriver_PacDrive_H
|
||||||
#define LightsDriver_PacDrive_H
|
#define LightsDriver_PacDrive_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -------------------------- NOTE --------------------------
|
||||||
|
*
|
||||||
|
* This driver needs user read/write access to PacDrive.
|
||||||
|
* This can be achieved by using a udev rule like this:
|
||||||
|
*
|
||||||
|
* SUBSYSTEMS=="usb", ATTRS{idVendor}=="D209", ATTRS{idProduct}=="1500", OWNER="dance", GROUP="dance", MODE="0660"
|
||||||
|
*
|
||||||
|
* Refer to your distribution's documentation on how to properly apply a udev rule.
|
||||||
|
*
|
||||||
|
* -------------------------- NOTE --------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
#include "arch/Lights/LightsDriver.h"
|
#include "arch/Lights/LightsDriver.h"
|
||||||
|
|
||||||
#define BIT(i) (1<<(i))
|
#include <cstdint>
|
||||||
|
#include "archutils/Common/HidDevice.h"
|
||||||
|
|
||||||
|
// static information about the device in question.
|
||||||
|
#define PACDRIVE_VID 0xD209
|
||||||
|
|
||||||
|
// PacDrive PIDs range from 0x1500->0x1507
|
||||||
|
#define PACDRIVE_PID 0x1500
|
||||||
|
#define PACDRIVE_PID_MAX 8
|
||||||
|
|
||||||
|
#define PACDRIVE_INTERFACE 0
|
||||||
|
|
||||||
|
// the first byte of the buffer is a static report id.
|
||||||
|
// and I have no idea why ultimarc's report is 5 bytes wide...
|
||||||
|
#define PACDRIVE_HIDREPORT_SIZE 5
|
||||||
|
#define PACDRIVE_HIDREPORT_ID 0x00
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool led01 : 1;
|
||||||
|
bool led02 : 1;
|
||||||
|
bool led03 : 1;
|
||||||
|
bool led04 : 1;
|
||||||
|
bool led05 : 1;
|
||||||
|
bool led06 : 1;
|
||||||
|
bool led07 : 1;
|
||||||
|
bool led08 : 1;
|
||||||
|
bool led09 : 1;
|
||||||
|
bool led10 : 1;
|
||||||
|
bool led11 : 1;
|
||||||
|
bool led12 : 1;
|
||||||
|
bool led13 : 1;
|
||||||
|
bool led14 : 1;
|
||||||
|
bool led15 : 1;
|
||||||
|
bool led16 : 1;
|
||||||
|
};
|
||||||
|
uint16_t raw;
|
||||||
|
} pacdrive_leds_t;
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t report_id;
|
||||||
|
uint8_t pad0;
|
||||||
|
uint8_t pad1;
|
||||||
|
pacdrive_leds_t leds;
|
||||||
|
};
|
||||||
|
uint8_t raw_state[PACDRIVE_HIDREPORT_SIZE];
|
||||||
|
} pacdrive_state_t;
|
||||||
|
|
||||||
class LightsDriver_PacDrive : public LightsDriver
|
class LightsDriver_PacDrive : public LightsDriver
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
|
HidDevice dev;
|
||||||
|
|
||||||
|
pacdrive_state_t state;
|
||||||
|
pacdrive_leds_t prev_led_state;
|
||||||
|
|
||||||
|
public:
|
||||||
LightsDriver_PacDrive();
|
LightsDriver_PacDrive();
|
||||||
virtual ~LightsDriver_PacDrive();
|
virtual ~LightsDriver_PacDrive();
|
||||||
|
|
||||||
virtual void Set( const LightsState *ls );
|
virtual void Set(const LightsState *ls);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Modified 2015 - Dave Barribeau for StepMania 5.09
|
/*
|
||||||
* 2014 - twistedsymphony
|
* (c) 2025 din
|
||||||
* Created for use with Beware's StepMania 3.9 DDR Extreme Simulation
|
* All rights reserved.
|
||||||
* feel free to reuse and distribute this code
|
*
|
||||||
*/
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ bool HidDevice::Open(const char* path)
|
|||||||
if(nonBlockingWrite)
|
if(nonBlockingWrite)
|
||||||
hid_set_nonblocking(handle, 1);
|
hid_set_nonblocking(handle, 1);
|
||||||
|
|
||||||
|
if(handle)
|
||||||
|
LOG->Info("HidDevice opened %04x:%04x:%d by path %s", vid, pid, interfaceNum, path);
|
||||||
|
|
||||||
return handle != nullptr;
|
return handle != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +117,6 @@ void HidDevice::Read(unsigned char* data, size_t length)
|
|||||||
{
|
{
|
||||||
if (!CheckConnection())
|
if (!CheckConnection())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int result = hid_read(handle, data, length);
|
int result = hid_read(handle, data, length);
|
||||||
|
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
|
|||||||
Reference in New Issue
Block a user