mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
100 lines
3.5 KiB
C
100 lines
3.5 KiB
C
#include "bluetoothradio.h"
|
|
#include "common/library.h"
|
|
#include "common/io.h"
|
|
#include "common/windows/unicode.h"
|
|
|
|
#include <windows.h>
|
|
#include <bluetoothapis.h>
|
|
#include <winioctl.h>
|
|
|
|
// #include <bthioctl.h>
|
|
|
|
#define BTH_IOCTL_BASE 0
|
|
#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
|
|
#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE + 0x00)
|
|
#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1)
|
|
|
|
typedef struct _BTH_RADIO_INFO {
|
|
// Supported LMP features of the radio. Use LMP_XXX() to extract
|
|
// the desired bits.
|
|
ULONGLONG lmpSupportedFeatures;
|
|
|
|
// Manufacturer ID (possibly BTH_MFG_XXX)
|
|
USHORT mfg;
|
|
|
|
// LMP subversion
|
|
USHORT lmpSubversion;
|
|
|
|
// LMP version
|
|
UCHAR lmpVersion;
|
|
} FF_A_PACKED BTH_RADIO_INFO;
|
|
|
|
typedef struct _BTH_LOCAL_RADIO_INFO {
|
|
// Local BTH_ADDR, class of device, and radio name
|
|
BTH_DEVICE_INFO localInfo;
|
|
|
|
// Combo of LOCAL_RADIO_XXX values
|
|
ULONG flags;
|
|
|
|
// HCI revision, see core spec
|
|
USHORT hciRevision;
|
|
|
|
// HCI version, see core spec
|
|
UCHAR hciVersion;
|
|
|
|
// More information about the local radio (LMP, MFG)
|
|
BTH_RADIO_INFO radioInfo;
|
|
} FF_A_PACKED BTH_LOCAL_RADIO_INFO;
|
|
static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should be 292 bytes");
|
|
|
|
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
|
|
|
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) {
|
|
// Actually bluetoothapis.dll, but it's missing on Windows 7
|
|
FF_LIBRARY_LOAD_MESSAGE(bluetoothapis, "bluetoothapis.dll", 1)
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio)
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio)
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose)
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsConnectable)
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsDiscoverable)
|
|
|
|
HANDLE hRadio = nullptr;
|
|
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) {
|
|
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS) },
|
|
&hRadio);
|
|
if (!hFind) {
|
|
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
|
|
return "No Bluetooth radios found or service disabled";
|
|
} else {
|
|
return "BluetoothFindFirstRadio() failed";
|
|
}
|
|
}
|
|
|
|
do {
|
|
BTH_LOCAL_RADIO_INFO blri;
|
|
DWORD returned;
|
|
if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, nullptr, 0, &blri, sizeof(blri), &returned, nullptr)) {
|
|
continue;
|
|
}
|
|
|
|
FFBluetoothRadioResult* device = FF_LIST_ADD(FFBluetoothRadioResult, *devices);
|
|
ffStrbufInitS(&device->name, blri.localInfo.name);
|
|
|
|
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
|
|
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X", addr.rgBytes[5], addr.rgBytes[4], addr.rgBytes[3], addr.rgBytes[2], addr.rgBytes[1], addr.rgBytes[0]);
|
|
|
|
device->lmpVersion = blri.radioInfo.lmpVersion;
|
|
device->lmpSubversion = blri.radioInfo.lmpSubversion;
|
|
ffStrbufInitStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg));
|
|
device->enabled = true;
|
|
device->connectable = ffBluetoothIsConnectable(hRadio);
|
|
device->discoverable = ffBluetoothIsDiscoverable(hRadio);
|
|
|
|
NtClose(hRadio);
|
|
} while (ffBluetoothFindNextRadio(hFind, &hRadio));
|
|
|
|
ffBluetoothFindRadioClose(hFind);
|
|
|
|
return nullptr;
|
|
}
|