diff options
Diffstat (limited to 'src/detection/bluetoothradio/bluetoothradio_windows.c')
| -rw-r--r-- | src/detection/bluetoothradio/bluetoothradio_windows.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c new file mode 100644 index 0000000..f0b55d4 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -0,0 +1,99 @@ +#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 = NULL; + 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, NULL, 0, &blri, sizeof(blri), &returned, NULL)) { + 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 NULL; +} |