// SPDX-License-Identifier: GPL-2.0-or-later /* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2011-2012 David Herrmann * * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "bluetooth/bluetooth.h" #include "bluetooth/sdp.h" #include "src/plugin.h" #include "src/adapter.h" #include "src/device.h" #include "src/log.h" #include "src/storage.h" /* * Nintendo Wii Remote devices require the bdaddr of the host as pin input for * authentication. This plugin registers a pin-callback and forces this pin * to be used for authentication. * * There are two ways to place the wiimote into discoverable mode. * - Pressing the red-sync button on the back of the wiimote. This module * supports pairing via this method. Auto-reconnect should be possible after * the device was paired once. * - Pressing the 1+2 buttons on the front of the wiimote. This module does * not support this method since this method never enables auto-reconnect. * Hence, pairing is not needed. Use it without pairing if you want. * After connecting the wiimote you should immediately connect to the input * service of the wiimote. If you don't, the wiimote will close the connection. * The wiimote waits about 5 seconds until it turns off again. * Auto-reconnect is only enabled when pairing with the wiimote via the red * sync-button and then connecting to the input service. If you do not connect * to the input service, then auto-reconnect is not enabled. * If enabled, the wiimote connects to the host automatically when any button * is pressed. */ static uint16_t wii_ids[][2] = { { 0x057e, 0x0306 }, /* 1st gen */ { 0x054c, 0x0306 }, /* LEGO wiimote */ { 0x057e, 0x0330 }, /* 2nd gen */ }; static const char *wii_names[] = { "Nintendo RVL-CNT-01", /* 1st gen */ "Nintendo RVL-CNT-01-TR", /* 2nd gen */ "Nintendo RVL-CNT-01-UC", /* Wii U Pro Controller */ "Nintendo RVL-WBC-01", /* Balance Board */ }; static ssize_t wii_pincb(struct btd_adapter *adapter, struct btd_device *device, char *pinbuf, bool *display, unsigned int attempt) { uint16_t vendor, product; char addr[18], name[25]; unsigned int i; /* Only try the pin code once per device. If it's not correct then it's * an unknown device. */ if (attempt > 1) return 0; ba2str(device_get_address(device), addr); vendor = btd_device_get_vendor(device); product = btd_device_get_product(device); device_get_name(device, name, sizeof(name)); for (i = 0; i < G_N_ELEMENTS(wii_ids); ++i) { if (vendor == wii_ids[i][0] && product == wii_ids[i][1]) goto found; } for (i = 0; i < G_N_ELEMENTS(wii_names); ++i) { if (g_str_equal(name, wii_names[i])) goto found; } return 0; found: DBG("Forcing fixed pin on detected wiimote %s", addr); memcpy(pinbuf, btd_adapter_get_address(adapter), 6); return 6; } static int wii_probe(struct btd_adapter *adapter) { btd_adapter_register_pin_cb(adapter, wii_pincb); return 0; } static void wii_remove(struct btd_adapter *adapter) { btd_adapter_unregister_pin_cb(adapter, wii_pincb); } static struct btd_adapter_driver wii_driver = { .name = "wiimote", .probe = wii_probe, .remove = wii_remove, }; static int wii_init(void) { return btd_register_adapter_driver(&wii_driver); } static void wii_exit(void) { btd_unregister_adapter_driver(&wii_driver); } BLUETOOTH_PLUGIN_DEFINE(wiimote, VERSION, BLUETOOTH_PLUGIN_PRIORITY_LOW, wii_init, wii_exit)