mirror of
https://github.com/libretro/RetroArch
synced 2025-01-27 03:35:22 +00:00
Merge pull request #5815 from bparker06/blissbox
initial Bliss-Box support
This commit is contained in:
commit
17d4793c3f
@ -55,6 +55,7 @@ addons:
|
||||
- libsdl-image1.2-dev
|
||||
- libsdl-mixer1.2-dev
|
||||
- libsdl-ttf2.0-dev
|
||||
- libusb-1.0-0-dev
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "RetroArch"
|
||||
|
100
input/include/blissbox.h
Normal file
100
input/include/blissbox.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2016-2017 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __BLISSBOX_H
|
||||
#define __BLISSBOX_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#define BLISSBOX_VID 0x16d0 /* requires firmware 2.0 */
|
||||
#define BLISSBOX_PID 0x0d04 /* first of 4 controllers, each one increments PID by 1 */
|
||||
#define BLISSBOX_UPDATE_MODE_PID 0x0a5f
|
||||
#define BLISSBOX_OLD_PID 0x0a60
|
||||
#define BLISSBOX_MAX_PADS 4
|
||||
#define BLISSBOX_MAX_PAD_INDEX (BLISSBOX_MAX_PADS - 1)
|
||||
|
||||
#define BLISSBOX_USB_FEATURE_REPORT_ID 17
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int index;
|
||||
} blissbox_pad_type_t;
|
||||
|
||||
const blissbox_pad_type_t blissbox_pad_types[] =
|
||||
{
|
||||
{"A5200", 6},
|
||||
{"A5200_TB", 50},
|
||||
{"A7800", 4},
|
||||
{"ATARI_KEYPAD", 43},
|
||||
{"ATMARK", 10},
|
||||
{"BALLY", 42},
|
||||
{"CD32", 24},
|
||||
{"CDI", 33},
|
||||
{"COL", 1},
|
||||
{"DC_ASCI", 15},
|
||||
{"DC_PAD", 16},
|
||||
{"FC_ARKANOID", 53},
|
||||
{"FC_NES", 52},
|
||||
{"GC", 9},
|
||||
{"GC_WHEEL", 18},
|
||||
{"GEN_3", 20},
|
||||
{"GEN_6", 21},
|
||||
{"GRAVIS_EX", 38},
|
||||
{"gx4000", 2},
|
||||
{"HAMMERHEAD", 40},
|
||||
{"HPD", 7},
|
||||
{"INTELI", 14},
|
||||
{"JAG", 11},
|
||||
{"MSSW", 39},
|
||||
{"N64", 19},
|
||||
{"NEO", 49},
|
||||
{"NES", 17},
|
||||
{"PADDLES", 41},
|
||||
{"PC_FX", 26},
|
||||
{"PC_GAMEPAD", 46},
|
||||
{"PSX_DIGITAL", 65},
|
||||
{"PSX_DS", 115},
|
||||
{"PSX_DS2", 121},
|
||||
{"PSX_FS", 83},
|
||||
{"PSX_NEGCON", 51},
|
||||
{"PSX_WHEEL", 12},
|
||||
{"SAC", 34},
|
||||
{"SATURN_ANALOG", 8},
|
||||
{"SATURN_DIGITAL", 3},
|
||||
{"SMS", 22},
|
||||
{"SPEEK", 45},
|
||||
{"TG16", 23},
|
||||
{"THREE_DO", 25},
|
||||
{"THREE_DO_ANALOG", 37},
|
||||
{"VEC", 5},
|
||||
{"WII_NUNCHUK", 13},
|
||||
{"ZXSINC", 44},
|
||||
{"NES_ARKANOID", 30},
|
||||
{"NES_GUN", 28},
|
||||
{"NES_POWERPAD", 36},
|
||||
{"SNES", 27},
|
||||
{"V_BOY", 29},
|
||||
{"WII_CLASSIC", 31},
|
||||
{"WII_MPLUS", 32},
|
||||
{NULL, 0}, /* used to mark unconnected ports, do not remove */
|
||||
};
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2016-2017 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
@ -24,7 +25,16 @@
|
||||
#include <file/config_file.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
#ifdef __FreeBSD__
|
||||
#include <libusb.h>
|
||||
#else
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../input/input_driver.h"
|
||||
#include "../input/include/blissbox.h"
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../file_path_special.h"
|
||||
@ -33,6 +43,19 @@
|
||||
|
||||
#include "tasks_internal.h"
|
||||
|
||||
/* HID Class-Specific Requests values. See section 7.2 of the HID specifications */
|
||||
#define USB_HID_GET_REPORT 0x01
|
||||
#define USB_CTRL_IN LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE
|
||||
#define USB_PACKET_CTRL_LEN 64
|
||||
#define USB_TIMEOUT 5000 /* timeout in ms */
|
||||
|
||||
/* only one blissbox per machine is currently supported */
|
||||
static const blissbox_pad_type_t *blissbox_pads[BLISSBOX_MAX_PADS] = {NULL};
|
||||
|
||||
#ifdef HAVE_LIBUSB
|
||||
static struct libusb_device_handle *autoconfig_libusb_handle = NULL;
|
||||
#endif
|
||||
|
||||
typedef struct autoconfig_disconnect autoconfig_disconnect_t;
|
||||
typedef struct autoconfig_params autoconfig_params_t;
|
||||
|
||||
@ -120,13 +143,16 @@ static int input_autoconfigure_joypad_try_from_conf(config_file_t *conf,
|
||||
if (config_get_int (conf, "input_product_id", &tmp_int))
|
||||
input_pid = tmp_int;
|
||||
|
||||
if (params->vid == BLISSBOX_VID)
|
||||
input_pid = BLISSBOX_PID;
|
||||
|
||||
/* Check for VID/PID */
|
||||
if ( (params->vid == input_vid)
|
||||
&& (params->pid == input_pid)
|
||||
&& (params->vid != 0)
|
||||
&& (params->pid != 0)
|
||||
&& (input_vid != 0)
|
||||
&& (input_pid != 0))
|
||||
&& (params->vid != BLISSBOX_VID)
|
||||
&& (params->pid != BLISSBOX_PID))
|
||||
score += 3;
|
||||
|
||||
/* Check for name match */
|
||||
@ -333,6 +359,131 @@ static void input_autoconfigure_params_free(autoconfig_params_t *params)
|
||||
params->autoconfig_directory = NULL;
|
||||
}
|
||||
|
||||
static const blissbox_pad_type_t* input_autoconfigure_get_blissbox_pad_type(int vid, int pid)
|
||||
{
|
||||
#ifdef HAVE_LIBUSB
|
||||
unsigned char answer[USB_PACKET_CTRL_LEN] = {0};
|
||||
unsigned i;
|
||||
int ret = libusb_init(NULL);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not initialize libusb.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
autoconfig_libusb_handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
|
||||
|
||||
if (!autoconfig_libusb_handle)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Could not find or open libusb device %d:%d.\n", vid, pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_detach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
ret = libusb_set_configuration(autoconfig_libusb_handle, 1);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_set_configuration.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_claim_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_claim_interface.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = libusb_control_transfer(autoconfig_libusb_handle, USB_CTRL_IN, USB_HID_GET_REPORT, BLISSBOX_USB_FEATURE_REPORT_ID, 0, answer, USB_PACKET_CTRL_LEN, USB_TIMEOUT);
|
||||
|
||||
if (ret < 0)
|
||||
RARCH_ERR("[Autoconf]: Error during libusb_control_transfer.\n");
|
||||
|
||||
libusb_release_interface(autoconfig_libusb_handle, 0);
|
||||
|
||||
#ifdef __linux__
|
||||
libusb_attach_kernel_driver(autoconfig_libusb_handle, 0);
|
||||
#endif
|
||||
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
|
||||
for (i = 0; i < sizeof(blissbox_pad_types) / sizeof(blissbox_pad_types[0]); i++)
|
||||
{
|
||||
const blissbox_pad_type_t *pad = &blissbox_pad_types[i];
|
||||
|
||||
if (!pad || string_is_empty(pad->name))
|
||||
continue;
|
||||
|
||||
if (pad->index == answer[0])
|
||||
return pad;
|
||||
}
|
||||
|
||||
RARCH_LOG("[Autoconf]: Could not find connected pad in Bliss-Box port#%d.\n", pid - BLISSBOX_PID);
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
libusb_close(autoconfig_libusb_handle);
|
||||
libusb_exit(NULL);
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void input_autoconfigure_override_handler(autoconfig_params_t *params)
|
||||
{
|
||||
if (params->vid == BLISSBOX_VID)
|
||||
{
|
||||
if (params->pid == BLISSBOX_UPDATE_MODE_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box in update mode detected. Ignoring.\n");
|
||||
else if (params->pid == BLISSBOX_OLD_PID)
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box 1.0 firmware detected. Please update to 2.0 or later.\n");
|
||||
else if (params->pid >= BLISSBOX_PID && params->pid <= BLISSBOX_PID + BLISSBOX_MAX_PAD_INDEX)
|
||||
{
|
||||
const blissbox_pad_type_t *pad;
|
||||
char name[255] = {0};
|
||||
int index = params->pid - BLISSBOX_PID;
|
||||
|
||||
RARCH_LOG("[Autoconf]: Bliss-Box detected. Getting pad type...\n");
|
||||
|
||||
if (blissbox_pads[index])
|
||||
pad = blissbox_pads[index];
|
||||
else
|
||||
pad = input_autoconfigure_get_blissbox_pad_type(params->vid, params->pid);
|
||||
|
||||
if (pad && !string_is_empty(pad->name))
|
||||
{
|
||||
RARCH_LOG("[Autoconf]: Found Bliss-Box pad type: %s (%d) in port#%d\n", pad->name, pad->index, index);
|
||||
|
||||
if (params->name)
|
||||
free(params->name);
|
||||
|
||||
/* override name given to autoconfig so it knows what kind of pad this is */
|
||||
strlcat(name, "Bliss-Box ", sizeof(name));
|
||||
strlcat(name, pad->name, sizeof(name));
|
||||
|
||||
params->name = strdup(name);
|
||||
|
||||
blissbox_pads[index] = pad;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = sizeof(blissbox_pad_types) / sizeof(blissbox_pad_types[0]);
|
||||
/* use NULL entry to mark as an unconnected port */
|
||||
blissbox_pads[index] = &blissbox_pad_types[count - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void input_autoconfigure_connect_handler(retro_task_t *task)
|
||||
{
|
||||
autoconfig_params_t *params = (autoconfig_params_t*)task->state;
|
||||
@ -499,6 +650,8 @@ bool input_autoconfigure_connect(
|
||||
state->max_users = *(
|
||||
input_driver_get_uint(INPUT_ACTION_MAX_USERS));
|
||||
|
||||
input_autoconfigure_override_handler(state);
|
||||
|
||||
if (!string_is_empty(state->name))
|
||||
input_config_set_device_name(state->idx, state->name);
|
||||
input_config_set_pid(state->idx, state->pid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user