8bitdo: Add initial SF30/SN30 Pro support (#350)

The SF30/SN30 pro support 4 different modes:
* Switch mode (START + Y)
This looks like a nintendo switch pro controller
* Xinput mode (START + X)
This looks like an XBOX 360 controller
* Dinput mode (START + B)
This looks like a more generic gamepad
* macOS mode (START + A)
This looks like a Sony DS4 controller

3 modes have had a difficult time enumerating in fwupd.
Switch mode:
* failed to add USB device: unexpected device response
Xinput mode:
* failed to add USB device: USB error on device 045e:028e : Pipe error [-9]
macOS mode:
* failed to add USB device: failed to send to device on ep 0x01: USB error on device 054c:05c4 : Input/output error [-1]

The only mode I've gotten a nearly full update flow working is Dinput
so far. After updating the controller comes back in switch mode.
This commit is contained in:
Mario Limonciello 2018-01-03 21:46:05 -06:00 committed by Mario Limonciello
parent 5bed9341b4
commit 3955e6e97d
4 changed files with 397 additions and 0 deletions

View File

@ -0,0 +1,362 @@
Start + Y
---------
Bus 001 Device 008: ID 057e:2009 Nintendo Co., Ltd
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x057e Nintendo Co., Ltd
idProduct 0x2009
bcdDevice 2.00
iManufacturer 1 Nintendo Co., Ltd.
iProduct 2 Pro Controller
iSerial 3 000000000001
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 41
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 203
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Device Status: 0x0000
(Bus Powered)
Start + B
------------
Bus 001 Device 009: ID 2dc8:6000
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x2dc8
idProduct 0x6000
bcdDevice 0.01
iManufacturer 1 8Bitdo SF30 Pro
iProduct 2 8Bitdo SF30 Pro
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 41
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 480mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 123
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 5
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 16
Device Status: 0x0000
(Bus Powered)
Start + A
---------
Bus 001 Device 012: ID 054c:05c4 Sony Corp. DualShock 4
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x054c Sony Corp.
idProduct 0x05c4 DualShock 4
bcdDevice 1.00
iManufacturer 1 Sony Computer Entertainment
iProduct 2 Wireless Controller
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 41
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 499
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 5
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 5
Device Status: 0x0000
(Bus Powered)
Start + X
---------
Bus 001 Device 013: ID 045e:028e Microsoft Corp. Xbox360 Controller
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 255 Vendor Specific Subclass
bDeviceProtocol 255 Vendor Specific Protocol
bMaxPacketSize0 8
idVendor 0x045e Microsoft Corp.
idProduct 0x028e Xbox360 Controller
bcdDevice 1.14
iManufacturer 1 8Bitdo SF30 Pro
iProduct 2 Controller
iSerial 3 (error)
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 153
bNumInterfaces 4
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 93
bInterfaceProtocol 1
iInterface 0
** UNRECOGNIZED: 11 21 00 01 01 25 81 14 00 00 00 00 13 01 08 00 00
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 4
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 8
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 4
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 93
bInterfaceProtocol 3
iInterface 0
** UNRECOGNIZED: 1b 21 00 01 01 01 82 40 01 02 20 16 83 00 00 00 00 00 00 16 03 00 00 00 00 00 00
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 2
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 4
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 64
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 93
bInterfaceProtocol 2
iInterface 0
** UNRECOGNIZED: 09 21 00 01 01 22 84 07 00
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 253
bInterfaceProtocol 19
iInterface 4 µ∡H釰俸샴`翰⣸贠øĀ贤Ǹɀ败˸赐ϸ桀F㏰៸贠ø贀Ǹ赀˸赐ϸ桀F⟰
** UNRECOGNIZED: 06 41 00 01 01 03
Device Status: 0x0000
(Bus Powered)

View File

@ -31,3 +31,15 @@ USB\VID_2DC8&PID_9001=none
# FC30_ARCADE
USB\VID_8000&PID_1002=none
USB\VID_2DC8&PID_1002=none
# SF30 PRO/SN30 PRO
## Nintendo Switch mode (Start + Y)
USB\VID_057E&PID_2009=none
## Dinput mode (Start + B)
USB\VID_2DC8&PID_6000=none
USB\VID_2DC8&PID_6001=none
## Xinput mode (Start + X)
USB\VID_045E&PID_028E=none
# macOS mode (Start + A)
USB\VID_054C&PID_05C4=none

View File

@ -262,6 +262,21 @@ fu_ebitdo_device_validate (FuEbitdoDevice *device, GError **error)
if (g_usb_device_get_vid (usb_device) == 0x2dc8)
return TRUE;
/* SF30/SN30 Pro when started with "START + Y"
* Emulates a "Nintendo Switch Pro Controller"
* "Real" Nintendo Switch controllers don't work over USB */
if (g_usb_device_get_vid (usb_device) == 0x057e &&
g_usb_device_get_pid (usb_device) == 0x2009)
return TRUE;
/* SF30/SN30 Pro when started with "START + A"
* Emulates a Sony Dualshock 4 controller
* Unknown if real DS4 controller will also match */
if (g_usb_device_get_vid (usb_device) == 0x054c &&
g_usb_device_get_pid (usb_device) == 0x05c4)
return TRUE;
/* verify the vendor prefix against a whitelist */
idx = g_usb_device_get_manufacturer_index (usb_device);
ven = g_usb_device_get_string_descriptor (usb_device, idx, error);

View File

@ -118,6 +118,14 @@ main (int argc, char **argv)
g_print ("2. Hold down L1+R1+HOME for 3 seconds until "
"both blue LED and green LED blink.\n");
break;
case 0x2009: /* SF30/SN30 pro: switch mode */
case 0x6000: /* SF30 pro: Dinput mode */
case 0x6001: /* SN30 pro: Dinput mode */
case 0x028e: /* SF30/SN30 pro: Xinput mode */
case 0x05c4: /* SF30/SN30 pro: macOS mode */
g_print ("2. Press and hold L1+R1+START for 3 seconds "
"until the LED on top blinks red.\n");
break;
default:
g_print ("2. Do what it says in the manual.\n");
break;