A Python library to wake PlayStation consoles via Bluetooth and extract MAC addresses via USB.
Project description
pywakepsx-on-bt
A Python library for waking PlayStation consoles (PS3, PS4, PS5) over Bluetooth from Linux.
It handles the full wake pipeline: extracting Bluetooth MAC addresses from a connected USB controller, spoofing the host adapter's BD_ADDR, sending the HCI Create Connection command to the console, and restoring the adapter afterwards.
Background
This library is the unified rewrite of two older projects:
- pywakeps4onbt — original PS4 Bluetooth wake implementation
- pywakepsXonbt — Generic PSX Bluetooth wake implementation
Both are now superseded by pywakepsx-on-bt, which consolidates their functionality, introduces proper BD_ADDR spoofing across multiple chipsets, and provides a clean Python API.
How it works
Waking a PlayStation over Bluetooth requires impersonating the paired controller, because the console only accepts an incoming connection from the specific controller it last paired with (identified by its Bluetooth MAC address, the BD_ADDR).
The full sequence is:
1. [USB] Extract the controller BD_ADDR and console BD_ADDR from the physical controller
2. [HCI] Spoof the host Bluetooth adapter's BD_ADDR to match the controller's
3. [HCI] Send HCI Create Connection targeting the console's BD_ADDR
4. [HCI] Wait for Connection Complete or Command Status event
5. [HCI] Restore the adapter's original BD_ADDR
Steps 2–5 require a raw HCI socket (AF_BLUETOOTH / SOCK_RAW / BTPROTO_HCI) and CAP_NET_RAW / CAP_NET_ADMIN capabilities (or root). Step 1 only requires USB access to the controller.
Installation
pip install pywakepsx-on-bt
Quick start
Step 1 — Extract MAC addresses via USB
Before issuing a wake command, you need two MAC addresses:
dsx_mac— the BD_ADDR of the PlayStation controller (DualShock 3/4, DualSense)psx_mac— the BD_ADDR of the PlayStation console the controller last paired with
Both are stored inside the controller itself. When you connect the controller via USB, it exposes a HID interface over which you can read these addresses using a USB control transfer (GET_REPORT request). pyusb provides the low-level USB access needed to issue this transfer; the built-in Python usb module does not exist on Linux.
from pywakepsx_on_bt import extract_psx_bt_macs
# Controller(s) must be connected via USB
results = extract_psx_bt_macs()
if not results:
print("No supported Sony controller found on USB.")
else:
# results is a list — one entry per connected supported controller
result = results[0]
print(f"Controller type: {result['controller_type']}")
print(f"Controller MAC: {result['dsx_mac']}") # → spoof target
print(f"Console MAC: {result['psx_mac']}") # → wake target
Each dict has three keys: dsx_mac, psx_mac, controller_type.
Supported controller types: dualshock3, dualshock4, dualsense, dualsense_edge.
Why not just read the pairing info from the Bluetooth stack? BlueZ stores pairing keys by BD_ADDR, but only after the host has connected as a primary device. When the host acts as a third-party waker (not the original pairing peer), those keys are absent. Reading directly from the controller via USB is the only reliable way to get both addresses without prior pairing.
Step 2 — Wake the console
from pywakepsx_on_bt import wake_psx, detect_strategy
dsx_mac = "AA:BB:CC:DD:EE:FF" # from extract_psx_bt_macs()
psx_mac = "11:22:33:44:55:66" # from extract_psx_bt_macs()
strategy = detect_strategy(0) # auto-detect chipset on hci0 and select spoof strategy
result = wake_psx(dsx_mac, psx_mac, adapter="hci0", spoof_strategy=strategy)
print(f"Status: {result.status_text} (0x{result.status_code:02X})")
Full pipeline
from pywakepsx_on_bt import extract_psx_bt_macs, wake_psx, detect_strategy
controllers = extract_psx_bt_macs()
if not controllers:
raise RuntimeError("No controller found on USB")
macs = controllers[0] # pick the first; iterate if multiple are connected
strategy = detect_strategy(0)
result = wake_psx(
macs["dsx_mac"],
macs["psx_mac"],
adapter="hci0",
spoof_strategy=strategy,
)
print(result.status_text)
API reference
extract_psx_bt_macs() -> list[dict[str, str]]
Scans USB for all connected supported Sony controllers. Returns a list of dicts, each containing "dsx_mac", "psx_mac", and "controller_type". Returns an empty list if no device is found.
wake_psx(dsx_mac, psx_mac, *, adapter, timeout, spoof_strategy, backend) -> WakeResult
High-level wake function. Delegates to wake_psx_linux by default. spoof_strategy must implement apply(dev_index: int, dsx_mac: str) -> None. Pass backend to override the default Linux raw-HCI implementation.
detect_strategy(dev_index: int) -> SpoofStrategy
Reads the manufacturer ID from hci{dev_index} via HCI_Read_Local_Version_Information and returns the matching spoof strategy instance. Returns UnsupportedSpoofStrategy (which raises SpoofNotSupportedError on use) if the chipset is not recognised.
list_compatible_adapters() -> list[AdapterInfo]
Enumerates all adapters found in /sys/class/bluetooth/, probes each one for its manufacturer ID, and returns a list of AdapterInfo dataclasses with adapter, manufacturer_id, manufacturer_name, strategy_name, support_rating, compatible, notes, and mac_address fields.
Filtering out adapters already managed by another application (e.g. the Home Assistant Bluetooth integration) is the caller's responsibility.
WakeResult
Dataclass returned by wake_psx / wake_psx_linux.
| Field / Property | Type | Description |
|---|---|---|
adapter |
str |
Adapter name used (e.g. "hci0") |
status_code |
int |
Raw HCI status code |
status_text |
str |
Human-readable status (e.g. "Page Timeout") |
command_packet |
bytes |
Raw HCI packet that was sent |
outcome |
str (property) |
Semantic result: "success", "timeout", or "error" |
Adapter spoof strategies
BD_ADDR spoofing uses vendor-specific HCI commands that differ per chipset (Broadcom, Intel, CSR, Cypress, Texas Instruments, Qualcomm/Atheros). Compatibility ratings, technical notes, and implementation details are documented in pywakepsx_on_bt/strategies/README.md.
Permissions
Raw HCI sockets require elevated privileges on Linux:
# Option 1 — grant capabilities to the Python interpreter
sudo setcap cap_net_raw,cap_net_admin+eip $(which python3)
# Option 2 — run with sudo
sudo python3 your_script.py
Home Assistant add-ons and containers may need network_mode: host and the appropriate capability grants.
Supported controllers
| Controller | Console | USB PID |
|---|---|---|
| DualShock 3 | PS3 | 0x0268 |
| DualShock 4 v1 | PS4 | 0x05C4 |
| DualShock 4 v2 | PS4 | 0x09CC |
| DualSense | PS5 | 0x0CE6 |
| DualSense Edge | PS5 | 0x0DF2 |
All controllers use USB Vendor ID 0x054C (Sony Corporation).
Supported Bluetooth adapters
→ For compatible Bluetooth adapters (chipsets), see Supported Chipsets.
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pywakepsx_on_bt-0.1.0.tar.gz.
File metadata
- Download URL: pywakepsx_on_bt-0.1.0.tar.gz
- Upload date:
- Size: 30.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fed3de96793527f3647c56c2b2fe1b24fc5c95754428af41e11c3d1d0aefa41
|
|
| MD5 |
92a85b3db0c84958da90d1bf92701f62
|
|
| BLAKE2b-256 |
56b36a98008fd569f63a7c3089400c6b78e395556bd42986cedcf02d38aafea5
|
File details
Details for the file pywakepsx_on_bt-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pywakepsx_on_bt-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db4322f881d9e80366bfe4d22ffe321cc879885cf1bc33d177529ce3c7362a75
|
|
| MD5 |
80947d60f074406eb58e1decd4a799ba
|
|
| BLAKE2b-256 |
a243a1f1893bf90ba70166ca5f3db80d6a2fdf4a48329e9199be7a8691c51d40
|