Last active
March 7, 2024 21:13
-
-
Save arlm/afcde9aaadd17c3d5994fed2d192143b to your computer and use it in GitHub Desktop.
Unpairing a DualShock 4 and Setting a new BDADDR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
netaddr==1.2.1 | |
pyusb==1.2.1 | |
hidapi==0.14.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Original code copyright: Frank Zhao | |
# From: https://eleccelerator.com/unpairing-a-dualshock-4-and-setting-a-new-bdaddr/ | |
# Pyhton 3 upgrade and macOS adaptation copyright: Alexandre Rocha Lima e Marcondes | |
# From: https://eleccelerator.com/unpairing-a-dualshock-4-and-setting-a-new-bdaddr/ | |
# This tool is supposed to override the PS4 BDADDR inside a DualShock 4 | |
# By Frank Zhao, see https://eleccelerator.com/wiki/index.php?title=DualShock_4 | |
# You may need to install a filter driver before libusb can access the device, use "install-filter-win.exe" from libusb-win32 | |
import sys, time, getopt, select | |
import usb.core, usb.util | |
import hid | |
from netaddr import * | |
def main(argv): | |
verbose = False | |
mac = False | |
needRead = False | |
ds4_v1 = False | |
ds4_v2 = False | |
try: | |
opts, args = getopt.getopt(argv,"hvra:",[]) | |
except getopt.GetoptError: | |
print ('Error: GetoptError') | |
printHelp() | |
sys.exit(2) | |
for opt, arg in opts: | |
if opt == '-h': | |
printHelp() | |
sys.exit() | |
elif opt in ("-a"): | |
mac = EUI(arg) | |
elif opt in ("-r"): | |
needRead = True | |
elif opt in ("-v"): | |
verbose = True | |
if mac != None and mac != False and mac != 0: | |
if verbose: | |
print ('Setting MAC to: ', str(mac), ' , words[', len(mac.words) ,']: ', mac.words) | |
if verbose: | |
print ('Searching for USB device with VID 0x054C and PID 0x05C4') | |
dev = usb.core.find(idVendor = 0x054C, idProduct = 0x05C4) | |
h = hid.device() | |
if dev == None or dev == False or dev == 0: | |
print ('Unable to find DualShock 4 v1 [CUH-ZCT1x]') | |
print ('') | |
if verbose: | |
print ('Searching for USB device with VID 0x054C and PID 0x09CC') | |
dev = usb.core.find(idVendor = 0x054C, idProduct = 0x09CC) | |
if dev == None or dev == False or dev == 0: | |
print ('Unable to find DualShock 4 v2 [CUH-ZCT2x]') | |
print ('You may need to install a filter driver before libusb can access the device, use "install-filter-win.exe" from libusb-win32') | |
print ('') | |
# Find all devices connected | |
dev = usb.core.find(find_all=True) | |
# Loop through devices and print idVendor and idProduct | |
for cfg in dev: | |
print('Device:', cfg) | |
print(' idVendor: %d (0x%04x)' % (cfg.idVendor, cfg.idVendor)) | |
print(' idProduct: %d (0x%04x)' % (cfg.idProduct, cfg.idProduct)) | |
quit() | |
else: | |
ds4_v2 = True | |
h.open(0x054C, 0x09CC) | |
else: | |
ds4_v1 = True | |
h.open(0x054C, 0x05C4) | |
if verbose: | |
print ('Found DualShock 4 in USB port') | |
print ('') | |
print("Manufacturer: %s" % h.get_manufacturer_string()) | |
print("Product: %s" % h.get_product_string()) | |
print ('') | |
dev.set_configuration() | |
if verbose: | |
print ('USB device set configuration') | |
print ('') | |
if needRead: | |
if verbose: | |
print ('Attempting read with USB control transfer GET REPORT on 0x12') | |
msg = h.get_input_report(0x12, 16) | |
if verbose: | |
print ('Read back raw data from report 0x12: [ ', printHexArray(msg), ']') | |
print ('') | |
print ('Read DualShock4 UID: ', EUI(format(msg[6], 'X') + '-' + format(msg[5], 'X') + '-' + format(msg[4], 'X') + '-' + format(msg[3], 'X') + '-' + format(msg[2], 'X') + '-' + format(msg[1], 'X'))) | |
print ('Read PlayStation4 MAC: ', EUI(format(msg[15], 'X') + '-' + format(msg[14], 'X') + '-' + format(msg[13], 'X') + '-' + format(msg[12], 'X') + '-' + format(msg[11], 'X') + '-' + format(msg[10], 'X'))) | |
print ('') | |
if mac != None and mac != False and mac != 0: | |
if verbose: | |
print ('USB sending control transfer SET REPORT on 0x13') | |
msg = [0x21, 0x09, 0x03, 0x13, 0x00, 0x00, 0x13, mac.words[5], mac.words[4], mac.words[3], mac.words[2], mac.words[1], mac.words[0], 0x56, 0xE8, 0x81, 0x38, 0x08, 0x06, 0x51, 0x41, 0xC0, 0x7F, 0x12, 0xAA, 0xD9, 0x66, 0x3C, 0xCE] | |
ret = h.write(msg) | |
print ('Written raw data to report 0x13, return code was: ', ret) | |
print ('') | |
if needRead: | |
if verbose: | |
print ('Attempting read with USB control transfer GET REPORT on 0x12') | |
msg = h.get_input_report(0x12, 16) | |
if verbose: | |
print ('Read back raw data from report 0x12: [ ', printHexArray(msg), ']') | |
print ('') | |
print ('Read DualShock4 UID: ', EUI(format(msg[6], 'X') + '-' + format(msg[5], 'X') + '-' + format(msg[4], 'X') + '-' + format(msg[3], 'X') + '-' + format(msg[2], 'X') + '-' + format(msg[1], 'X'))) | |
print ('Read PlayStation4 MAC: ', EUI(format(msg[15], 'X') + '-' + format(msg[14], 'X') + '-' + format(msg[13], 'X') + '-' + format(msg[12], 'X') + '-' + format(msg[11], 'X') + '-' + format(msg[10], 'X'))) | |
print ('') | |
if verbose: | |
print ('That\'s all this tool will do, goodbye') | |
h.close() | |
quit() | |
def printHexArray(arr): | |
str = '' | |
for i in arr: | |
str += '0x' + format(i, 'X') + ', ' | |
return str | |
def printHelp(): | |
print ('This tool is supposed to override the PS4 BDADDR inside a DualShock 4') | |
print ('') | |
print ('command line options:') | |
print ('-h') | |
print (' will print the help') | |
print ('') | |
print ('-a <PS4\'s BDADDR>') | |
print (' will set BDADDR, common formats accepted but no spaces allowed') | |
print ('') | |
print ('-r') | |
print (' will do a control transfer read on report 0x12') | |
print ('') | |
print ('-v') | |
print (' will enable verbose output') | |
print ('') | |
print ('By Frank Zhao, see https://eleccelerator.com/wiki/index.php?title=DualShock_4') | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment