mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-11-04 09:44:35 +00:00 
			
		
		
		
	SInput: ABXY Style Application and Code Cleanup (#13624)
ABXY Face Style Application
- The abxy face style extraction now applies to any SInput device.
- The use-case here is that gamepads that allow for changing styles can dynamically adjust the button labels firmware-side to have the physical location better represent the actual button being pressed.
SInput Sub-Type Clarification
- The code has been updated to better reflect the intention behind the sub-type field of the GUID byte 15.
- Any SInput device may utilize the Sub-Type field to indicate variants of the same device (Same device that has rear paddles or additional physical features but is otherwise identical, etc.).
"Firebird" Company Name Clarification
- "Bonjiri" was a wrong translation. Got clarification from the company and official PID registration for the official English spelling (See 0c5234cd92).
- Fixed this spelling for all references (official mapping strings still pending and this will return NULL until this is provided).
Code Notes
- Various notes have been updated to have more clear indications.
- I have moved the face-type and sub-type debug messages to be paired with the extraction for easier location.
- I've removed an incorrect note left-over from a previous commit regarding command response information.
			
			
This commit is contained in:
		@@ -800,50 +800,53 @@ static GamepadMapping_t *SDL_CreateMappingForHIDAPIGamepad(SDL_GUID guid)
 | 
			
		||||
            SDL_strlcat(mapping_string, "a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
 | 
			
		||||
    } else if (SDL_IsJoystickSInputController(vendor, product)) {
 | 
			
		||||
        Uint8 face_style = (guid.data[15] & 0xE0) >> 5;
 | 
			
		||||
        Uint8 sinput_id  = guid.data[15] & 0x1F;
 | 
			
		||||
        Uint8 sub_type  = guid.data[15] & 0x1F;
 | 
			
		||||
 | 
			
		||||
        // Apply face style according to gamepad response
 | 
			
		||||
        switch (face_style) {
 | 
			
		||||
        default:
 | 
			
		||||
            SDL_strlcat(mapping_string, "face:abxy,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            SDL_strlcat(mapping_string, "face:axby,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
        case 3:
 | 
			
		||||
            SDL_strlcat(mapping_string, "face:bayx,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
        case 4:
 | 
			
		||||
            SDL_strlcat(mapping_string, "face:sony,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch (product) {
 | 
			
		||||
        case USB_PRODUCT_HANDHELDLEGEND_PROGCC:
 | 
			
		||||
            // ProGCC Mapping
 | 
			
		||||
            SDL_strlcat(mapping_string, "a:b1,b:b0,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE:
 | 
			
		||||
            // GC Ultimate Map
 | 
			
		||||
            SDL_strlcat(mapping_string, "a:b0,b:b2,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b7,rightstick:b5,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b1,y:b3,misc3:b8,misc4:b9,hint:!SDL_GAMECONTROLLER_USE_GAMECUBE_LABELS:=1,", sizeof(mapping_string));
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
 | 
			
		||||
            // Apply mapping profile for type
 | 
			
		||||
            switch (sinput_id) {
 | 
			
		||||
            switch (sub_type) {
 | 
			
		||||
            default:
 | 
			
		||||
            case 0:
 | 
			
		||||
                // Default Fully Exposed Mapping
 | 
			
		||||
                // ProGCC Primary Mapping
 | 
			
		||||
                SDL_strlcat(mapping_string, "a:b1,b:b0,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE:
 | 
			
		||||
            switch (sub_type) {
 | 
			
		||||
            default:
 | 
			
		||||
                // GC Ultimate Primary Map
 | 
			
		||||
                SDL_strlcat(mapping_string, "a:b0,b:b2,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b4,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b7,rightstick:b5,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b1,y:b3,misc3:b8,misc4:b9,hint:!SDL_GAMECONTROLLER_USE_GAMECUBE_LABELS:=1,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            } 
 | 
			
		||||
            break;
 | 
			
		||||
        case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
 | 
			
		||||
            switch (sub_type) {
 | 
			
		||||
            default:
 | 
			
		||||
                // Default Fully Exposed Mapping (Development Purposes)
 | 
			
		||||
                SDL_strlcat(mapping_string, "leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,b:b0,a:b1,y:b2,x:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b4,rightstick:b5,leftshoulder:b6,rightshoulder:b7,paddle1:b10,paddle2:b11,start:b12,back:b13,guide:b14,misc1:b15,paddle3:b16,paddle4:b17,touchpad:b18,misc2:b19,misc3:b20,misc4:b21,misc5:b22,misc6:b23", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Apply face style
 | 
			
		||||
            switch (face_style) {
 | 
			
		||||
            default:
 | 
			
		||||
            case 1:
 | 
			
		||||
                SDL_strlcat(mapping_string, "face:abxy,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            case 2:
 | 
			
		||||
                SDL_strlcat(mapping_string, "face:axby,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            case 3:
 | 
			
		||||
                SDL_strlcat(mapping_string, "face:bayx,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            case 4:
 | 
			
		||||
                SDL_strlcat(mapping_string, "face:sony,", sizeof(mapping_string));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        
 | 
			
		||||
        case USB_PRODUCT_BONZIRICHANNEL_FIREBIRD:
 | 
			
		||||
        default:
 | 
			
		||||
        case USB_PRODUCT_BONJIRICHANNEL_FIREBIRD:
 | 
			
		||||
            // Unmapped devices
 | 
			
		||||
            // Unmapped device
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -3212,7 +3212,7 @@ bool SDL_IsJoystickSInputController(Uint16 vendor_id, Uint16 product_id)
 | 
			
		||||
        if (product_id == USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC ||
 | 
			
		||||
            product_id == USB_PRODUCT_HANDHELDLEGEND_PROGCC ||
 | 
			
		||||
            product_id == USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE ||
 | 
			
		||||
            product_id == USB_PRODUCT_BONJIRICHANNEL_FIREBIRD) {
 | 
			
		||||
            product_id == USB_PRODUCT_BONZIRICHANNEL_FIREBIRD) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -86,10 +86,10 @@
 | 
			
		||||
#define SINPUT_REPORT_IDX_TOUCH2_Y          43
 | 
			
		||||
#define SINPUT_REPORT_IDX_TOUCH2_P          45
 | 
			
		||||
 | 
			
		||||
#define SINPUT_BUTTON_IDX_SOUTH             0
 | 
			
		||||
#define SINPUT_BUTTON_IDX_EAST              1
 | 
			
		||||
#define SINPUT_BUTTON_IDX_WEST              2
 | 
			
		||||
#define SINPUT_BUTTON_IDX_NORTH             3
 | 
			
		||||
#define SINPUT_BUTTON_IDX_EAST              0
 | 
			
		||||
#define SINPUT_BUTTON_IDX_SOUTH             1
 | 
			
		||||
#define SINPUT_BUTTON_IDX_NORTH             2
 | 
			
		||||
#define SINPUT_BUTTON_IDX_WEST              3
 | 
			
		||||
#define SINPUT_BUTTON_IDX_DPAD_UP           4
 | 
			
		||||
#define SINPUT_BUTTON_IDX_DPAD_DOWN         5
 | 
			
		||||
#define SINPUT_BUTTON_IDX_DPAD_LEFT         6
 | 
			
		||||
@@ -256,6 +256,8 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
 | 
			
		||||
 | 
			
		||||
    ctx->is_handheld = (data[3] & 0x04) != 0;
 | 
			
		||||
 | 
			
		||||
    // The gamepad type represents a style of gamepad that most closely
 | 
			
		||||
    // resembles the gamepad in question (Button style, button layout)
 | 
			
		||||
    SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN;
 | 
			
		||||
    type = (SDL_GamepadType)SDL_clamp(data[4], SDL_GAMEPAD_TYPE_UNKNOWN, SDL_GAMEPAD_TYPE_COUNT);
 | 
			
		||||
    device->type = type;
 | 
			
		||||
@@ -266,20 +268,20 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
 | 
			
		||||
 | 
			
		||||
    ctx->sub_type = (data[5] & 0x1F);
 | 
			
		||||
 | 
			
		||||
#if defined(DEBUG_SINPUT_INIT)
 | 
			
		||||
    SDL_Log("SInput Face Style: %d", (data[5] & 0xE0) >> 5);
 | 
			
		||||
    SDL_Log("SInput Sub-type: %d", (data[5] & 0x1F));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ctx->polling_rate_ms = data[6];
 | 
			
		||||
 | 
			
		||||
    ctx->accelRange = EXTRACTUINT16(data, 8);
 | 
			
		||||
    ctx->gyroRange = EXTRACTUINT16(data, 10);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if ((device->product_id == USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC) && (device->vendor_id == USB_VENDOR_RASPBERRYPI)) {
 | 
			
		||||
 | 
			
		||||
#if defined(DEBUG_SINPUT_INIT)
 | 
			
		||||
        SDL_Log("SInput Face Style: %d", (data[5] & 0xE0) >> 5);
 | 
			
		||||
        SDL_Log("SInput Sub-type: %d", (data[5] & 0x1F));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        switch (ctx->sub_type) {
 | 
			
		||||
        // Default generic device, exposes all buttons
 | 
			
		||||
        // SInput generic device, exposes all buttons
 | 
			
		||||
        default:
 | 
			
		||||
        case 0:
 | 
			
		||||
            ctx->usage_masks[0] = 0xFF;
 | 
			
		||||
@@ -294,7 +296,7 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
 | 
			
		||||
        ctx->usage_masks[0] = data[12];
 | 
			
		||||
 | 
			
		||||
        // Stick Left, Stick Right, L Shoulder, R Shoulder,
 | 
			
		||||
        // L Trigger, R Trigger, L Paddle 1, R Paddle 1
 | 
			
		||||
        // L Digital Trigger, R Digital Trigger, L Paddle 1, R Paddle 1
 | 
			
		||||
        ctx->usage_masks[1] = data[13];
 | 
			
		||||
 | 
			
		||||
        // Start, Back, Guide, Capture, L Paddle 2, R Paddle 2, Touchpad L, Touchpad R
 | 
			
		||||
@@ -336,6 +338,7 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
 | 
			
		||||
    char serial[18];
 | 
			
		||||
    (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
 | 
			
		||||
                       data[18], data[19], data[20], data[21], data[22], data[23]);
 | 
			
		||||
 | 
			
		||||
#if defined(DEBUG_SINPUT_INIT)
 | 
			
		||||
    SDL_Log("Serial num: %s", serial);
 | 
			
		||||
#endif
 | 
			
		||||
@@ -464,6 +467,10 @@ static bool HIDAPI_DriverSInput_InitDevice(SDL_HIDAPI_Device *device)
 | 
			
		||||
    case USB_PRODUCT_HANDHELDLEGEND_PROGCC:
 | 
			
		||||
        HIDAPI_SetDeviceName(device, "HHL ProGCC");
 | 
			
		||||
        break;
 | 
			
		||||
    case USB_PRODUCT_BONZIRICHANNEL_FIREBIRD:
 | 
			
		||||
        HIDAPI_SetDeviceName(device, "Bonziri Firebird");
 | 
			
		||||
        break;
 | 
			
		||||
    case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
 | 
			
		||||
    default:
 | 
			
		||||
        // Use the USB product name
 | 
			
		||||
        break;
 | 
			
		||||
@@ -898,7 +905,6 @@ static bool HIDAPI_DriverSInput_UpdateDevice(SDL_HIDAPI_Device *device)
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Handle command response information
 | 
			
		||||
        if (data[0] == SINPUT_DEVICE_REPORT_ID_JOYSTICK_INPUT) {
 | 
			
		||||
            HIDAPI_DriverSInput_HandleStatePacket(joystick, ctx, data, size);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -165,7 +165,7 @@
 | 
			
		||||
#define USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC         0x10c6
 | 
			
		||||
#define USB_PRODUCT_HANDHELDLEGEND_PROGCC                 0x10df
 | 
			
		||||
#define USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE             0x10dd
 | 
			
		||||
#define USB_PRODUCT_BONJIRICHANNEL_FIREBIRD               0x10e0 
 | 
			
		||||
#define USB_PRODUCT_BONZIRICHANNEL_FIREBIRD               0x10e0 
 | 
			
		||||
 | 
			
		||||
// USB usage pages
 | 
			
		||||
#define USB_USAGEPAGE_GENERIC_DESKTOP 0x0001
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user