USB: Add evdev support for keyboardmania

This commit is contained in:
jackun
2021-07-12 18:09:39 +03:00
parent 238da17196
commit d0ada6b40a
14 changed files with 585 additions and 426 deletions
+3 -1
View File
@@ -12,6 +12,8 @@
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include <gtk/gtk.h>
GtkWidget* new_combobox(const char* label, GtkWidget* vbox, bool scrollable = false); // linux/config-gtk.cpp
+9 -3
View File
@@ -189,7 +189,7 @@ static void configureApi(GtkWidget* widget, gpointer data)
}
}
GtkWidget* new_combobox(const char* label, GtkWidget* vbox)
GtkWidget* new_combobox(const char* label, GtkWidget* vbox, bool scrollable)
{
GtkWidget *rs_hbox, *rs_label, *rs_cb;
@@ -199,10 +199,16 @@ GtkWidget* new_combobox(const char* label, GtkWidget* vbox)
rs_label = gtk_label_new(label);
gtk_box_pack_start(GTK_BOX(rs_hbox), rs_label, FALSE, TRUE, 5);
gtk_label_set_justify(GTK_LABEL(rs_label), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment(GTK_MISC(rs_label), 1, 0.5);
rs_cb = gtk_combo_box_text_new();
gtk_box_pack_start(GTK_BOX(rs_hbox), rs_cb, TRUE, TRUE, 5);
if (!scrollable)
gtk_box_pack_start(GTK_BOX(rs_hbox), rs_cb, TRUE, TRUE, 5);
else
{
GtkWidget* sw = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(sw), rs_cb);
gtk_box_pack_start(GTK_BOX(rs_hbox), sw, TRUE, TRUE, 5);
}
return rs_cb;
}
-2
View File
@@ -35,8 +35,6 @@
#include <linux/videodev2.h>
GtkWidget* new_combobox(const char* label, GtkWidget* vbox); // src/linux/config-gtk.cpp
#define CLEAR(x) memset(&(x), 0, sizeof(x))
namespace usb_eyetoy
-2
View File
@@ -20,8 +20,6 @@
#include <cstdio>
#include <sstream>
GtkWidget* new_combobox(const char* label, GtkWidget* vbox); // src/linux/config-gtk.cpp
namespace usb_hid
{
namespace evdev
-2
View File
@@ -19,8 +19,6 @@
#include "USB/dynlink/pulse.h"
#endif
GtkWidget* new_combobox(const char* label, GtkWidget* vbox); // src/linux/config-gtk.cpp
namespace usb_mic
{
namespace audiodev_pulse
+3 -3
View File
@@ -1316,7 +1316,7 @@ namespace usb_pad
INVERTFORCES[port] = SendDlgItemMessage(hWnd, IDC_CHECK1, BM_GETCHECK, 0, 0);
useRamp = !!SendDlgItemMessage(hWnd, IDC_CHECK3, BM_GETCHECK, 0, 0);
GAINZ[port][0] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER4), TBM_GETPOS, 0, 0);
FFMULTI[port][0] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER5), TBM_GETPOS, 0, 0);
FFMULTI[port][0] = SendMessage(GetDlgItem(hWnd, IDC_SLIDER5), TBM_GETPOS, 0, 0);
}
void SaveDInputConfig(int port, const char* dev_type)
@@ -1460,11 +1460,11 @@ namespace usb_pad
struct DXDlgSettings s;
s.port = port;
s.dev_type = dev_type;
if (strcmp(dev_type, "buzz_device") == 0)
if (strcmp(dev_type, BuzzDevice::TypeName()) == 0)
{
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_BUZZ), h.hWnd, DxDialogProc, (LPARAM)&s);
}
if (strcmp(dev_type, "keyboardmania") == 0)
if (strcmp(dev_type, KeyboardmaniaDevice::TypeName()) == 0)
{
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_KEYBOARDMANIA), h.hWnd, DxDialogProc, (LPARAM)&s);
}
+9 -9
View File
@@ -279,8 +279,8 @@ namespace usb_pad
"BRIGHTNESS_ZERO", /* linux:244 (KEY_BRIGHTNESS_ZERO) */
"DISPLAY_OFF", /* linux:245 (KEY_DISPLAY_OFF) */
"WIMAX", /* linux:246 (KEY_WIMAX) */
"247", /* linux:247 (unnamed) */
"248", /* linux:248 (unnamed) */
"RFKILL", /* linux:247 (KEY_RFKILL) */
"MICMUTE", /* linux:248 (KEY_MICMUTE) */
"249", /* linux:249 (unnamed) */
"250", /* linux:250 (unnamed) */
"251", /* linux:251 (unnamed) */
@@ -556,15 +556,15 @@ namespace usb_pad
"NUMERIC_9", /* linux:521 (KEY_NUMERIC_9) */
"NUMERIC_STAR", /* linux:522 (KEY_NUMERIC_STAR) */
"NUMERIC_POUND", /* linux:523 (KEY_NUMERIC_POUND) */
"RFKILL", /* linux:524 (KEY_RFKILL) */
"KEY_NUMERIC_A", /* linux:524 (KEY_NUMERIC_A) */
};
static bool GetEventName(const char* dev_type, int map, int event, const char** name)
static bool GetEventName(const char* dev_type, int map, int event, bool is_button, const char** name)
{
if (!name)
return false;
if (map < JOY_STEERING || !strcmp(dev_type, BuzzDevice::TypeName()))
if (is_button)
{
if (event < (int)key_to_str.size())
{
@@ -593,7 +593,7 @@ namespace usb_pad
};
AxisValue axisVal[ABS_MAX + 1]{};
unsigned long absbit[NBITS(ABS_MAX)]{};
struct axis_correct abs_correct[ABS_MAX]{};
axis_correct abs_correct[ABS_MAX]{};
inverted = false;
@@ -616,9 +616,7 @@ namespace usb_pad
while ((len = read(js.second.fd, &event, sizeof(event))) > 0)
;
struct timeval timeout
{
};
timeval timeout{};
timeout.tv_sec = 5;
int result = select(maxfd + 1, &fdset, NULL, NULL, &timeout);
@@ -744,6 +742,8 @@ namespace usb_pad
int ret = 0;
if (!strcmp(dev_type, BuzzDevice::TypeName()))
ret = GtkBuzzConfigure(port, dev_type, "Evdev Settings", evdev::APINAME, GTK_WINDOW(data), apicbs);
else if (!strcmp(dev_type, KeyboardmaniaDevice::TypeName()))
ret = GtkKeyboardmaniaConfigure(port, dev_type, "Evdev Settings", evdev::APINAME, GTK_WINDOW(data), apicbs);
else
ret = GtkPadConfigure(port, dev_type, "Evdev Settings", evdev::APINAME, GTK_WINDOW(data), apicbs);
return ret;
+21 -51
View File
@@ -108,7 +108,6 @@ namespace usb_pad
}
}
}
//quit:
closedir(dirp);
return false;
}
@@ -151,7 +150,7 @@ namespace usb_pad
str.clear();
str.str("");
str << EVDEV_DIR << dp->d_name;
std::string path = str.str();
const std::string path = str.str();
auto it = std::find_if(list_cache.begin(), list_cache.end(),
[&path](evdev_device& dev) {
@@ -168,14 +167,14 @@ namespace usb_pad
continue;
}
//list_cache.push_back(std::make_pair(std::string(dp->d_name), path));
res = ioctl(fd, EVIOCGNAME(sizeof(buf)), buf);
if (res < 0)
Console.Warning("EVIOCGNAME");
else
{
list_cache.push_back({buf, dp->d_name, path});
evdev_device dev{buf, dp->d_name, path, {}};
res = ioctl(fd, EVIOCGID, &dev.input_id);
list_cache.push_back(dev);
}
close(fd);
@@ -183,7 +182,6 @@ namespace usb_pad
}
list.assign(list_cache.begin(), list_cache.end());
//quit:
closedir(dirp);
}
@@ -220,7 +218,7 @@ namespace usb_pad
//case ABS_Y: mWheelData.clutch = NORM(value, 0xFF); break; //no wheel on PS2 has one, afaik
//case ABS_RX: mWheelData.axis_rx = NORM(event.value, 0xFF); break;
case ABS_RY:
//treat_me_like_ABS_RY:
//treat_me_like_ABS_RY:
mWheelData.throttle = 0xFF;
mWheelData.brake = 0xFF;
if (value < 0)
@@ -230,18 +228,10 @@ namespace usb_pad
break;
case 0x80 | JOY_THROTTLE:
case ABS_Z:
/*if (mIsGamepad)
mWheelData.brake = 0xFF - NORM(value, 0xFF);
else*/
mWheelData.throttle = device.cfg.inverted[1] ? NORM(value, 0xFF) : 0xFF - NORM(value, 0xFF);
break;
case 0x80 | JOY_BRAKE:
case ABS_RZ:
/*if (mIsGamepad)
mWheelData.throttle = 0xFF - NORM(value, 0xFF);
else if (mIsDualAnalog)
goto treat_me_like_ABS_RY;
else*/
mWheelData.brake = device.cfg.inverted[2] ? NORM(value, 0xFF) : 0xFF - NORM(value, 0xFF);
break;
@@ -323,9 +313,8 @@ namespace usb_pad
break;
value = AxisCorrect(device.abs_correct[event.code], event.value);
/*if (event.code == 0)
event.code, device.axis_map[event.code] & ~0x80, event.value, value);
*/
//if (event.code == 0)
// event.code, device.axis_map[event.code] & ~0x80, event.value, value);
SetAxis(device, event.code, value);
}
break;
@@ -333,7 +322,7 @@ namespace usb_pad
{
code = device.btn_map[event.code] != (uint16_t)-1 ? device.btn_map[event.code] : event.code;
if (mType == WT_BUZZ_CONTROLLER)
if (mType == WT_BUZZ_CONTROLLER || mType == WT_KEYBOARDMANIA_CONTROLLER)
{
if (device.btn_map[event.code] != (uint16_t)-1)
{
@@ -568,7 +557,7 @@ namespace usb_pad
}
if (joypath.empty() || !file_exists(joypath))
goto quit;
return 1;
int fd = -1;
if ((fd = open(joypath.c_str(), O_RDWR | O_NONBLOCK)) < 0)
@@ -584,16 +573,6 @@ namespace usb_pad
int pid, vid;
if ((mUseRawFF = FindHidraw(evphys, hid_dev, &vid, &pid)))
{
// For safety, only allow Logitech (classic ffb) devices
if (vid != 0x046D /* Logitech */ /*|| info.bustype != BUS_USB*/
|| pid == 0xc262 /* G920 hid mode */
|| pid == 0xc261 /* G920 xbox mode */
)
{
mUseRawFF = 0;
}
// check if still using hidraw and run the thread
if (mUseRawFF && !mWriterThreadIsRunning)
{
@@ -637,13 +616,6 @@ namespace usb_pad
continue;
}
/*unsigned int version;
if (ioctl(mHandle, EVIOCGVERSION, &version) < 0)
{
SysMessage("%s: Get version failed: %s\n", APINAME, strerror(errno));
return false;
}*/
int max_buttons = JOY_STEERING;
switch (mType)
{
@@ -651,8 +623,13 @@ namespace usb_pad
LoadBuzzMappings(mDevType, mPort, it.id, device.cfg);
max_buttons = 20;
break;
case WT_KEYBOARDMANIA_CONTROLLER:
max_buttons = 31;
LoadMappings(mDevType, mPort, it.id, max_buttons, 0, device.cfg);
break;
default:
LoadMappings(mDevType, mPort, it.id, device.cfg);
max_buttons = JOY_STEERING;
LoadMappings(mDevType, mPort, it.id, max_buttons, 3, device.cfg);
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN_ENABLED, b_gain))
b_gain = 1;
if (!LoadSetting(mDevType, mPort, APINAME, N_GAIN, gain))
@@ -715,12 +692,6 @@ namespace usb_pad
}
}
#ifndef NDEBUG
for (int i = 0; i < ABS_MAX; ++i)
{
}
#endif
for (int i = BTN_JOYSTICK; i < KEY_MAX; ++i)
{
if (test_bit(i, keybit))
@@ -763,10 +734,6 @@ namespace usb_pad
}
return 0;
quit:
Close();
return 1;
}
int EvDevPad::Close()
@@ -776,9 +743,12 @@ namespace usb_pad
if (mHidHandle != -1)
{
uint8_t reset[7] = {0};
reset[0] = 0xF3; //stop forces
write(mHidHandle, reset, sizeof(reset));
if (mType <= WT_GT_FORCE)
{
uint8_t reset[7] = {0};
reset[0] = 0xF3; //stop forces
write(mHidHandle, reset, sizeof(reset));
}
close(mHidHandle);
}
File diff suppressed because it is too large Load Diff
+50 -8
View File
@@ -16,6 +16,7 @@
#pragma once
#include <linux/joystick.h>
#include <unistd.h>
#include "Pcsx2Types.h"
#include "USB/gtk.h"
#include "USB/usb-pad/padproxy.h"
#include "USB/configuration.h"
@@ -31,10 +32,15 @@ struct evdev_device
std::string name;
std::string id;
std::string path;
struct {
uint16_t bustype;
uint16_t vendor;
uint16_t product;
uint16_t version;
} input_id;
};
typedef std::vector<evdev_device> device_list;
GtkWidget* new_combobox(const char* label, GtkWidget* vbox);
namespace usb_pad
{
@@ -46,7 +52,6 @@ namespace usb_pad
COL_NAME = 0,
COL_PS2,
COL_PC,
COL_COLUMN_WIDTH,
COL_BINDING,
NUM_COLS
};
@@ -76,7 +81,7 @@ namespace usb_pad
JOY_MAPS_COUNT
};
static constexpr const char* JoystickMapNames[] = {
constexpr const char* JoystickMapNames[]{
"cross",
"square",
"circle",
@@ -95,9 +100,10 @@ namespace usb_pad
"right",
"steering",
"throttle",
"brake"};
"brake",
};
static constexpr const char* buzz_map_names[] = {
constexpr const char* buzz_map_names[]{
"red",
"yellow",
"green",
@@ -105,6 +111,40 @@ namespace usb_pad
"blue",
};
constexpr const char* kbdmania_key_labels[]{
"C 1",
"C# 1",
"D 1",
"D# 1",
"E 1",
"F 1",
"F# 1",
"",
"G 1",
"G# 1",
"A 1",
"A# 1",
"B 1",
"C 2",
"Select",
"",
"C# 2",
"D 2",
"D# 2",
"E 2",
"F 2",
"F# 2",
"Start",
"",
"G 2",
"G# 2",
"A 2",
"A# 2",
"B 2",
"Up",
"Down",
};
struct Point
{
int x;
@@ -128,7 +168,7 @@ namespace usb_pad
struct ApiCallbacks
{
bool (*get_event_name)(const char* dev_type, int map, int event, const char** name);
bool (*get_event_name)(const char* dev_type, int map, int event, bool is_button, const char** name);
void (*populate)(device_list& jsdata);
bool (*poll)(const std::vector<std::pair<std::string, ConfigMapping>>& jsconf, std::string& dev_name, bool isaxis, int& value, bool& inverted, int& initial);
};
@@ -145,6 +185,7 @@ namespace usb_pad
ApiCallbacks* cb;
int use_hidraw_ff_pt;
const char* dev_type;
u32 max_axes, max_buttons;
};
struct axis_correct
@@ -167,8 +208,9 @@ namespace usb_pad
int GtkPadConfigure(int port, const char* dev_type, const char* title, const char* apiname, GtkWindow* parent, ApiCallbacks& apicbs);
int GtkBuzzConfigure(int port, const char* dev_type, const char* title, const char* apiname, GtkWindow* parent, ApiCallbacks& apicbs);
bool LoadMappings(const char* dev_type, int port, const std::string& joyname, ConfigMapping& cfg);
bool SaveMappings(const char* dev_type, int port, const std::string& joyname, const ConfigMapping& cfg);
int GtkKeyboardmaniaConfigure(int port, const char* dev_type, const char* apititle, const char* apiname, GtkWindow* parent, ApiCallbacks& apicbs);
bool LoadMappings(const char* dev_type, int port, const std::string& joyname, u32 max_buttons, u32 max_axes, ConfigMapping& cfg);
bool SaveMappings(const char* dev_type, int port, const std::string& joyname, u32 max_buttons, u32 max_axes, const ConfigMapping& cfg);
bool LoadBuzzMappings(const char* dev_type, int port, const std::string& joyname, ConfigMapping& cfg);
bool SaveBuzzMappings(const char* dev_type, int port, const std::string& joyname, const ConfigMapping& cfg);
} // namespace evdev
+2 -2
View File
@@ -32,10 +32,10 @@ namespace usb_pad
#define JOYTYPE "joytype"
#define CFG "cfg"
static bool GetEventName(const char* dev_type, int map, int event, const char** name)
static bool GetEventName(const char* dev_type, int map, int event, bool is_button, const char** name)
{
static char buf[256] = {0};
if (map < evdev::JOY_STEERING)
if (is_button)
{
snprintf(buf, sizeof(buf), "Button %d", event);
}
+9 -9
View File
@@ -73,7 +73,6 @@ namespace usb_pad
close(fd);
}
}
//quit:
closedir(dirp);
}
@@ -381,7 +380,7 @@ namespace usb_pad
continue;
}
LoadMappings(mDevType, mPort, device.name, device.cfg);
LoadMappings(mDevType, mPort, device.name, 3, 16, device.cfg);
// Axis Mapping
if (ioctl(device.cfg.fd, JSIOCGAXMAP, device.axis_map) < 0)
@@ -394,16 +393,17 @@ namespace usb_pad
if (ioctl(device.cfg.fd, JSIOCGAXES, &(count)) >= 0)
{
for (int i = 0; i < count; ++i)
for (int k = 0; k < count; k++)
{
for (int i = JOY_STEERING; i < JOY_MAPS_COUNT; i++)
for (int k = 0; k < count; k++)
{
if (k == device.cfg.controls[i])
for (int i = JOY_STEERING; i < JOY_MAPS_COUNT; i++)
{
device.axis_map[k] = 0x80 | i;
if (i == JOY_STEERING)
has_steering = true;
if (k == device.cfg.controls[i])
{
device.axis_map[k] = 0x80 | i;
if (i == JOY_STEERING)
has_steering = true;
}
}
}
}
+34 -76
View File
@@ -52,6 +52,7 @@ namespace usb_pad
"Logitech Buzz(tm) Controller V1",
"",
"Logitech"};
static const USBDescStrings kbm_desc_strings = {
"",
"USB Multipurpose Controller",
@@ -93,7 +94,7 @@ namespace usb_pad
std::list<std::string> KeyboardmaniaDevice::ListAPIs()
{
return PadDevice::ListAPIs();
return {"evdev"};
}
const TCHAR* KeyboardmaniaDevice::LongAPIName(const std::string& name)
@@ -319,7 +320,6 @@ namespace usb_pad
s->pad->Close();
}
void pad_reset_data(generic_data_t* d)
{
memset(d, 0, sizeof(generic_data_t));
@@ -540,6 +540,28 @@ namespace usb_pad
#endif
}
static void pad_init(PADState* s, int port, Pad* pad)
{
s->f.dev_subtype = pad->Type();
s->pad = pad;
s->port = port;
s->dev.speed = USB_SPEED_FULL;
s->dev.klass.handle_attach = usb_desc_attach;
s->dev.klass.handle_reset = pad_handle_reset;
s->dev.klass.handle_control = pad_handle_control;
s->dev.klass.handle_data = pad_handle_data;
s->dev.klass.unrealize = pad_handle_destroy;
s->dev.klass.open = pad_open;
s->dev.klass.close = pad_close;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = nullptr;
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);
pad_handle_reset((USBDevice*)s);
}
USBDevice* PadDevice::CreateDevice(int port)
{
std::string varApi;
@@ -554,13 +576,13 @@ namespace usb_pad
if (!proxy)
{
Console.WriteLn("USB: PAD: Invalid input API.\n");
return NULL;
return nullptr;
}
Pad* pad = proxy->CreateObject(port, TypeName());
if (!pad)
return NULL;
return nullptr;
pad->Type((PS2WheelTypes)GetSelectedSubtype(std::make_pair(port, TypeName())));
PADState* s = new PADState();
@@ -610,23 +632,7 @@ namespace usb_pad
if (usb_desc_parse_config(config_desc, config_desc_len, s->desc_dev) < 0)
goto fail;
s->f.dev_subtype = pad->Type();
s->pad = pad;
s->dev.speed = USB_SPEED_FULL;
s->dev.klass.handle_attach = usb_desc_attach;
s->dev.klass.handle_reset = pad_handle_reset;
s->dev.klass.handle_control = pad_handle_control;
s->dev.klass.handle_data = pad_handle_data;
s->dev.klass.unrealize = pad_handle_destroy;
s->dev.klass.open = pad_open;
s->dev.klass.close = pad_close;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = s->desc.str[2]; //not really used
s->port = port;
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);
pad_handle_reset((USBDevice*)s);
pad_init(s, port, pad);
return (USBDevice*)s;
@@ -682,13 +688,13 @@ namespace usb_pad
if (!proxy)
{
Console.WriteLn("RBDK: Invalid input API.\n");
return NULL;
return nullptr;
}
Pad* pad = proxy->CreateObject(port, TypeName());
if (!pad)
return NULL;
return nullptr;
pad->Type(WT_ROCKBAND1_DRUMKIT);
PADState* s = new PADState();
@@ -701,23 +707,7 @@ namespace usb_pad
if (usb_desc_parse_config(rb1_config_descriptor, sizeof(rb1_config_descriptor), s->desc_dev) < 0)
goto fail;
s->f.dev_subtype = pad->Type();
s->pad = pad;
s->port = port;
s->dev.speed = USB_SPEED_FULL;
s->dev.klass.handle_attach = usb_desc_attach;
s->dev.klass.handle_reset = pad_handle_reset;
s->dev.klass.handle_control = pad_handle_control;
s->dev.klass.handle_data = pad_handle_data;
s->dev.klass.unrealize = pad_handle_destroy;
s->dev.klass.open = pad_open;
s->dev.klass.close = pad_close;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = s->desc.str[2];
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);
pad_handle_reset((USBDevice*)s);
pad_init(s, port, pad);
return (USBDevice*)s;
@@ -774,23 +764,7 @@ namespace usb_pad
if (usb_desc_parse_config(buzz_config_descriptor, sizeof(buzz_config_descriptor), s->desc_dev) < 0)
goto fail;
s->f.dev_subtype = pad->Type();
s->pad = pad;
s->port = port;
s->dev.speed = USB_SPEED_FULL;
s->dev.klass.handle_attach = usb_desc_attach;
s->dev.klass.handle_reset = pad_handle_reset;
s->dev.klass.handle_control = pad_handle_control;
s->dev.klass.handle_data = pad_handle_data;
s->dev.klass.unrealize = pad_handle_destroy;
s->dev.klass.open = pad_open;
s->dev.klass.close = pad_close;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = s->desc.str[2];
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);
pad_handle_reset((USBDevice*)s);
pad_init(s, port, pad);
return (USBDevice*)s;
@@ -828,13 +802,13 @@ namespace usb_pad
if (!proxy)
{
Console.WriteLn("usb-pad: %s: Invalid input API.", TypeName());
return NULL;
return nullptr;
}
Pad* pad = proxy->CreateObject(port, TypeName());
if (!pad)
return NULL;
return nullptr;
pad->Type(WT_KEYBOARDMANIA_CONTROLLER);
PADState* s = new PADState();
@@ -847,23 +821,7 @@ namespace usb_pad
if (usb_desc_parse_config(kbm_config_descriptor, sizeof(kbm_config_descriptor), s->desc_dev) < 0)
goto fail;
s->f.dev_subtype = pad->Type();
s->pad = pad;
s->port = port;
s->dev.speed = USB_SPEED_FULL;
s->dev.klass.handle_attach = usb_desc_attach;
s->dev.klass.handle_reset = pad_handle_reset;
s->dev.klass.handle_control = pad_handle_control;
s->dev.klass.handle_data = pad_handle_data;
s->dev.klass.unrealize = pad_handle_destroy;
s->dev.klass.open = pad_open;
s->dev.klass.close = pad_close;
s->dev.klass.usb_desc = &s->desc;
s->dev.klass.product_desc = s->desc.str[2];
usb_desc_init(&s->dev);
usb_ep_init(&s->dev);
pad_handle_reset((USBDevice*)s);
pad_init(s, port, pad);
return (USBDevice*)s;
+12 -10
View File
@@ -109,7 +109,6 @@ namespace usb_pad
{
return {};
}
static void Initialize();
};
class SeamicDevice
@@ -475,27 +474,30 @@ namespace usb_pad
static const int HATS_8TO4[] = {PAD_HAT_N, PAD_HAT_E, PAD_HAT_S, PAD_HAT_W};
#define PAD_VID 0x046D
#define PAD_PID 0xCA03 //black MOMO
#define PAD_MOMO 0xCA03 //black MOMO
#define GENERIC_PID 0xC294 //actually Driving Force aka PID that most logitech wheels initially report
#define PID_DF 0xC294
#define PID_DFP 0xC298 //SELECT + R3 + RIGHT SHIFT PADDLE (R1) ???
#define PID_DFGT 0xC29A
#define PID_FORMULA 0xC202 //Yellow Wingman Formula
#define PID_FGP 0xC20E //Formula GP (maybe GT FORCE LPRC-1000)
#define PID_FFGP 0xC293 // Formula Force GP
#define PID_GTF 0xC293 // as is Formula Force GP
#define PID_G25 0xC299 // OutRun 2 (jp) supports it apparently
#define PID_FGP 0xC20E //Formula GP (maybe GT FORCE LPRC-1000)
#define PID_FFGP 0xC293 // Formula Force GP
#define PID_GTF 0xC293 // as is Formula Force GP
#define PID_G25 0xC299 // OutRun 2 (jp) supports it apparently
#define PID_G27 0xC29B
#define MAX_BUTTONS 32
#define MAX_AXES 7 //random 7: axes + hatswitch
#define MAX_JOYS 32
#define PAD_LG_FFB_WHITELIST \
PAD_MOMO, PID_DF, PID_DFP, PID_DFGT, PID_FORMULA, PID_FGP, PID_FFGP, PID_GTF, PID_G25, PID_G27
/**
linux hid-lg4ff.c
http://www.spinics.net/lists/linux-input/msg16570.html
Every Logitech wheel reports itself as generic Logitech Driving Force wheel (VID 046d, PID c294). This is done to ensure that the
wheel will work on every USB HID-aware system even when no Logitech driver is available. It however limits the capabilities of the
wheel - range is limited to 200 degrees, G25/G27 don't report the clutch pedal and there is only one combined axis for throttle and
brake. The switch to native mode is done via hardware-specific command which is different for each wheel. When the wheel
Every Logitech wheel reports itself as generic Logitech Driving Force wheel (VID 046d, PID c294). This is done to ensure that the
wheel will work on every USB HID-aware system even when no Logitech driver is available. It however limits the capabilities of the
wheel - range is limited to 200 degrees, G25/G27 don't report the clutch pedal and there is only one combined axis for throttle and
brake. The switch to native mode is done via hardware-specific command which is different for each wheel. When the wheel
receives such command, it simulates reconnect and reports to the OS with its actual PID.
Currently not emulating reattachment. Any games that expect to?
**/