Обновить

Разведка боем: Скрытая карта режимов 8BitDo Zero v1 и прошивка по воздуху через Linux

Короткая заметка для тех, кто ковыряет ретро-железо. Стояла задача: использовать микро-геймпад 8BitDo Zero 1-го поколения (Bluetooth 2.1) для специфического HID-ввода, изменив раскладку “намертво” внутри устройства.

Официальный софт под Windows давно заброшен, поэтому ремап делался по воздуху через Linux (RFCOMM). В процессе удалось полностью разобрать структуру конфигурационного пакета, отправляемого контроллеру.

Структура KEYMAP-пакета

При отправке команды +KEYMAP; геймпад принимает массив, где блоки идут друг за другом в зависимости от режима удержания кнопок при включении (по 12 байт на режим в аппаратном порядке: Вверх/Вниз/Влево/Вправо/Select/Start/B/A/X/Y/L/R):

  1. START — Режим стандартного джойстика (Usage Page 0x09)

  2. R + START — Режим PC-джойстика

  3. START + B — Стандартная клавиатура (Usage Page 0x07), выдает стрелки (52 51 50 4f) и Enter/Esc (28/29).

  4. START + B + R — Расширенная клавиатура.

  5. START + A — Режим iCade (раздельные HEX-коды на Press и Release).

  6. START + X — Скрытый сервисный/Emu-Touch режим прошивки (0F 0E 0D 0C...).

  7. Shutter (Селфи-пульт) — Комбинированный режим. Позволяет сочетать стандартные кнопки клавиатуры (Page 0x07) и мультимедиа-коды Consumer Page 0x0C (Громкость: 80/81, Яркость: 6F/70, Снимок: 65).

Как шить (Пайплайн в 3 окна)

  1. В первом окне терминала поднимаем RFCOMM-канал на 1-м L2CAP канале геймпада: sudo rfcomm connect 0 [MAC_АДРЕС] 1

  2. Во втором окне правим HEX-массив и инжектируем его Python-скриптом напрямую в /dev/rfcomm0 (скрипт прикреплен ниже). Контроллер должен вернуть успешную сигнатуру 0e0100a6.

  3. В третьем окне контролируем прохождение пакетов через sudo btmon.

В конце пакета обязательно должны идти маркеры валидации aa 55 aa 55, иначе чип отвергнет прошивку. Мне удалось успешно собрать кастомный Shutter-режим, внедрив туда нужные клавиатурные скан-коды (30 и 40) рядом с системными. Код скрипта прилагаю.

import serial
import time

# Настройки порта
PORT = '/dev/rfcomm0'

# Ваши данные для записи (с 07 07 07 07)
DATA = b'\x00\xa6WR+KEYMAP;\x00\x00\x64\x00\x00\x00\x00\x00\x1a\x1b\x11\x10\x13\x14\x16\x17\x01\x01\x01\x01\x1a\x1b\x11\x10\x13\x14\x16\x17\x52\x51\x50\x4f\x28\x29\x4d\x4e\x4a\x4b\x0e\x10\x13\x14\x15\x04\x1b\x1c\x18\x05\x16\x17\x19\x1a\x1a\x1b\x04\x07\x0f\x12\x0b\x18\x0d\x1c\x0e\x0c\x08\x1d\x14\x06\x19\x0a\x15\x09\x11\x17\x13\x10\x0f\x0e\x0d\x0c\x09\x00\x08\x07\x05\x06\x04\x03\x52\x51\x50\x4f\x28\x29\x4d\x4e\x4a\x4b\xea\xe9\xaa\x55\xaa\x55'

try:
    print(f"--- Попытка открыть {PORT} ---")
    # Открываем порт с таймаутом 2 секунды
    with serial.Serial(PORT, baudrate=115200, timeout=2) as ser:
        print("Порт открыт. Отправка данных...")
        ser.write(DATA)
        ser.flush()  # Гарантируем отправку всех байт
        
        print("Данные отправлены. Ждем подтверждения от геймпада...")
        response = ser.read(16) # Читаем ответ
        
        if response:
            print(f"ОТВЕТ ПОЛУЧЕН (HEX): {response.hex()}")
            if "0e0100a6" in response.hex():
                print("УСПЕХ: Геймпад подтвердил запись ремапа!")
            else:
                print("ВНИМАНИЕ: Ответ получен, но он не похож на стандартное подтверждение.")
        else:
            print("ОШИБКА: Геймпад ничего не ответил (таймаут).")

except Exception as e:
    print(f"КРИТИЧЕСКАЯ ОШИБКА: {e}")
Теги:
+1
Комментарии0

Разработчик сжёг токенов на $157 143, заплатив за них $400

Блогер‑разработчик OrcDev рассказал, что за последний месяц обработал 235 млрд токенов, которые при оплате по API‑тарифам обошлись бы ему в $157 143,39. При этом фактически он заплатил за использование моделей всего $400.

Разработчик сжёг токенов на $157 143, заплатив за них $400

Публикации