From 8a3af14d2220e65fdd6114fb04dbb78b7ae0b0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Jul 2024 00:05:07 +0800 Subject: [PATCH] BluetoothRadio (Windows): new module --- CMakeLists.txt | 7 + doc/json_schema.json | 32 ++- presets/all.jsonc | 1 + presets/ci.jsonc | 1 + src/common/modules.c | 1 + src/detection/bluetoothradio/bluetoothradio.h | 17 ++ .../bluetoothradio/bluetoothradio_nosupport.c | 6 + .../bluetoothradio/bluetoothradio_windows.c | 157 ++++++++++++++ src/modules/bluetoothradio/bluetoothradio.c | 198 ++++++++++++++++++ src/modules/bluetoothradio/bluetoothradio.h | 9 + src/modules/bluetoothradio/option.h | 12 ++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 15 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 src/detection/bluetoothradio/bluetoothradio.h create mode 100644 src/detection/bluetoothradio/bluetoothradio_nosupport.c create mode 100644 src/detection/bluetoothradio/bluetoothradio_windows.c create mode 100644 src/modules/bluetoothradio/bluetoothradio.c create mode 100644 src/modules/bluetoothradio/bluetoothradio.h create mode 100644 src/modules/bluetoothradio/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ebd32ab29..8e9e91fce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,7 @@ set(LIBFASTFETCH_SRC src/modules/battery/battery.c src/modules/bios/bios.c src/modules/bluetooth/bluetooth.c + src/modules/bluetoothradio/bluetoothradio.c src/modules/board/board.c src/modules/bootmgr/bootmgr.c src/modules/brightness/brightness.c @@ -421,6 +422,7 @@ if(LINUX) src/detection/cpuusage/cpuusage_linux.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/disk/disk_linux.c src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_linux.c @@ -488,6 +490,7 @@ elseif(ANDROID) src/detection/battery/battery_android.c src/detection/bios/bios_android.c src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_android.c src/detection/bootmgr/bootmgr_nosupport.c src/detection/brightness/brightness_nosupport.c @@ -550,6 +553,7 @@ elseif(BSD) src/detection/battery/battery_bsd.c src/detection/bios/bios_bsd.c src/detection/bluetooth/bluetooth_linux.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_bsd.c src/detection/bootmgr/bootmgr_bsd.c src/detection/brightness/brightness_bsd.c @@ -626,6 +630,7 @@ elseif(APPLE) src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c src/detection/bluetooth/bluetooth_apple.m + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_apple.c src/detection/bootmgr/bootmgr_apple.c src/detection/brightness/brightness_apple.c @@ -689,6 +694,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/bluetooth/bluetooth_windows.c + src/detection/bluetoothradio/bluetoothradio_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_windows.c src/detection/brightness/brightness_windows.cpp @@ -763,6 +769,7 @@ elseif(SunOS) src/detection/cpuusage/cpuusage_sunos.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/disk/disk_sunos.c src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_nosupport.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 0d8773b93..4af7a84df 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -745,6 +745,7 @@ "battery", "bios", "bluetooth", + "bluetoothradio", "board", "bootmgr", "break", @@ -1049,7 +1050,7 @@ "additionalProperties": false, "properties": { "type": { - "description": "List bluetooth devices", + "description": "List (connected) bluetooth devices", "const": "bluetooth" }, "showDisconnected": { @@ -1080,6 +1081,35 @@ } } }, + { + "title": "Bluetooth Radio", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "description": "List bluetooth radios width supported version and vendor", + "const": "bluetoothradio" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyIcon": { + "$ref": "#/$defs/keyIcon" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "Brightness", "type": "object", diff --git a/presets/all.jsonc b/presets/all.jsonc index 52d092d1c..e19041c20 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -73,6 +73,7 @@ "opencl", "users", "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index ac34edab2..2f3512ce2 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -75,6 +75,7 @@ "opencl", "users", "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", diff --git a/src/common/modules.c b/src/common/modules.c index d7607aa3a..3cd158984 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -8,6 +8,7 @@ static FFModuleBaseInfo* B[] = { (void*) &instance.config.modules.battery, (void*) &instance.config.modules.bios, (void*) &instance.config.modules.bluetooth, + (void*) &instance.config.modules.bluetoothRadio, (void*) &instance.config.modules.board, (void*) &instance.config.modules.bootmgr, (void*) &instance.config.modules.break_, diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h new file mode 100644 index 000000000..8aa911cb0 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -0,0 +1,17 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFBluetoothRadioResult +{ + FFstrbuf name; + FFstrbuf address; + uint8_t lmpVersion; + uint8_t hciVersion; + uint16_t lmpSubversion; + uint16_t hciRevision; + const char* vendor; + bool leSupported; +} FFBluetoothRadioResult; + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */); diff --git a/src/detection/bluetoothradio/bluetoothradio_nosupport.c b/src/detection/bluetoothradio/bluetoothradio_nosupport.c new file mode 100644 index 000000000..1df1ce0e3 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_nosupport.c @@ -0,0 +1,6 @@ +#include "bluetoothradio.h" + +const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c new file mode 100644 index 000000000..330409608 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -0,0 +1,157 @@ +#include "bluetoothradio.h" +#include "common/library.h" +#include "common/io/io.h" +#include "util/windows/unicode.h" + +#include +#include +#include + +// #include + +#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; +} __attribute__((__packed__)) BTH_RADIO_INFO; + +typedef struct _BTH_LOCAL_RADIO_INFO +{ + // Local BTH_ADDR, class of defice, 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; +} __attribute__((__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(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose) + + 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"; + 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 = ffListAdd(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[0], + addr.rgBytes[1], + addr.rgBytes[2], + addr.rgBytes[3], + addr.rgBytes[4], + addr.rgBytes[5]); + + device->lmpVersion = blri.radioInfo.lmpVersion; + device->lmpSubversion = blri.radioInfo.lmpSubversion; + device->hciVersion = blri.hciVersion; + device->hciRevision = blri.hciRevision; + device->leSupported = LMP_LE_SUPPORTED(blri.radioInfo.lmpSupportedFeatures); + + switch (blri.radioInfo.mfg) + { + case BTH_MFG_ERICSSON: device->vendor = "Ericsson"; break; + case BTH_MFG_NOKIA: device->vendor = "Nokia"; break; + case BTH_MFG_INTEL: device->vendor = "Intel"; break; + case BTH_MFG_IBM: device->vendor = "IBM"; break; + case BTH_MFG_TOSHIBA: device->vendor = "Toshiba"; break; + case BTH_MFG_3COM: device->vendor = "3Com"; break; + case BTH_MFG_MICROSOFT: device->vendor = "Microsoft"; break; + case BTH_MFG_LUCENT: device->vendor = "Lucent"; break; + case BTH_MFG_MOTOROLA: device->vendor = "Motorola"; break; + case BTH_MFG_INFINEON: device->vendor = "Infineon"; break; + case BTH_MFG_CSR: device->vendor = "CSR"; break; + case BTH_MFG_SILICONWAVE: device->vendor = "Silicon-Wave"; break; + case BTH_MFG_DIGIANSWER: device->vendor = "Digi-Answer"; break; + case BTH_MFG_TI: device->vendor = "Ti"; break; + case BTH_MFG_PARTHUS: device->vendor = "Parthus"; break; + case BTH_MFG_BROADCOM: device->vendor = "Broadcom"; break; + case BTH_MFG_MITEL: device->vendor = "Mitel"; break; + case BTH_MFG_WIDCOMM: device->vendor = "Widcomm"; break; + case BTH_MFG_ZEEVO: device->vendor = "Zeevo"; break; + case BTH_MFG_ATMEL: device->vendor = "Atmel"; break; + case BTH_MFG_MITSIBUSHI: device->vendor = "Mitsubishi"; break; + case BTH_MFG_RTX_TELECOM: device->vendor = "RTX Telecom"; break; + case BTH_MFG_KC_TECHNOLOGY: device->vendor = "KC Technology"; break; + case BTH_MFG_NEWLOGIC: device->vendor = "Newlogic"; break; + case BTH_MFG_TRANSILICA: device->vendor = "Transilica"; break; + case BTH_MFG_ROHDE_SCHWARZ: device->vendor = "Rohde-Schwarz"; break; + case BTH_MFG_TTPCOM: device->vendor = "TTPCom"; break; + case BTH_MFG_SIGNIA: device->vendor = "Signia"; break; + case BTH_MFG_CONEXANT: device->vendor = "Conexant"; break; + case BTH_MFG_QUALCOMM: device->vendor = "Qualcomm"; break; + case BTH_MFG_INVENTEL: device->vendor = "Inventel"; break; + case BTH_MFG_AVM_BERLIN: device->vendor = "AVM Berlin"; break; + case BTH_MFG_BANDSPEED: device->vendor = "Bandspeed"; break; + case BTH_MFG_MANSELLA: device->vendor = "Mansella"; break; + case BTH_MFG_NEC: device->vendor = "NEC"; break; + case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: device->vendor = "Waveplus"; break; + case BTH_MFG_ALCATEL: device->vendor = "Alcatel"; break; + case BTH_MFG_PHILIPS_SEMICONDUCTOR: device->vendor = "Philips Semiconductors"; break; + case BTH_MFG_C_TECHNOLOGIES: device->vendor = "C Technologies"; break; + case BTH_MFG_OPEN_INTERFACE: device->vendor = "Open Interface"; break; + case BTH_MFG_RF_MICRO_DEVICES: device->vendor = "RF Micro Devices"; break; + case BTH_MFG_HITACHI: device->vendor = "Hitachi"; break; + case BTH_MFG_SYMBOL_TECHNOLOGIES: device->vendor = "Symbol Technologies"; break; + case BTH_MFG_TENOVIS: device->vendor = "Tenovis"; break; + case BTH_MFG_MACRONIX_INTERNATIONAL: device->vendor = "Macronix International"; break; + case BTH_MFG_MARVELL: device->vendor = "Marvell"; break; + case BTH_MFG_APPLE: device->vendor = "Apple"; break; + case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: device->vendor = "Nordic Semiconductor ASA"; break; + case BTH_MFG_ARUBA_NETWORKS: device->vendor = "Aruba Networks"; break; + case BTH_MFG_INTERNAL_USE: device->vendor = "Internal Use"; break; + default: device->vendor = "Unknown"; break; + } + } while (ffBluetoothFindNextRadio(hFind, &hRadio)); + + ffBluetoothFindRadioClose(hFind); + + return NULL; +} diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c new file mode 100644 index 000000000..f85832b09 --- /dev/null +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -0,0 +1,198 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/bluetoothradio/bluetoothradio.h" +#include "modules/bluetoothradio/bluetoothradio.h" +#include "util/stringUtils.h" + +#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 7 +#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" + +static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) +{ + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + if (options->moduleArgs.key.length == 0) + { + ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars); + } + else + { + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index, "index"}, + {FF_FORMAT_ARG_TYPE_STRING, radio->name.chars, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &options->moduleArgs.keyIcon, "icon"}, + })); + } + + const char* version = NULL; + + switch (radio->lmpVersion) + { + case 0: version = "1.0b"; break; + case 1: version = "1.1"; break; + case 2: version = "1.2"; break; + case 3: version = "2.0 + EDR"; break; + case 4: version = "2.1 + EDR"; break; + case 5: version = "3.0 + HS"; break; + case 6: version = "4.0"; break; + case 7: version = "4.1"; break; + case 8: version = "4.2"; break; + case 9: version = "5.0"; break; + case 10: version = "5.1"; break; + case 11: version = "5.2"; break; + case 12: version = "5.3"; break; + case 13: version = "5.4"; break; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + + if (version) + printf("Bluetooth %s (%s)\n", version, radio->vendor); + else + fputs(radio->vendor, stdout); + } + else + { + FF_STRBUF_AUTO_DESTROY lmpVersion = ffStrbufCreateF("%u.%u", radio->lmpVersion, radio->lmpSubversion); + FF_STRBUF_AUTO_DESTROY hciVersion = ffStrbufCreateF("%u.%u", radio->hciVersion, radio->hciRevision); + + FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &radio->name, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &radio->address, "address"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &lmpVersion, "lmp-version"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &hciVersion, "hci-version"}, + {FF_FORMAT_ARG_TYPE_STRING, version, "version"}, + {FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"}, + {FF_FORMAT_ARG_TYPE_BOOL, &radio->leSupported, "le-supported"}, + })); + } +} + +void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) +{ + FF_LIST_AUTO_DESTROY radios = ffListCreate(sizeof (FFBluetoothRadioResult)); + const char* error = ffDetectBluetoothRadio(&radios); + + if(error) + { + ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + } + else + { + for(uint32_t i = 0; i < radios.length; i++) + { + uint8_t index = (uint8_t) (radios.length == 1 ? 0 : i + 1); + printDevice(options, FF_LIST_GET(FFBluetoothRadioResult, radios, i), index); + } + } + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, radios) + { + ffStrbufDestroy(&radio->name); + ffStrbufDestroy(&radio->address); + } +} + +bool ffParseBluetoothRadioCommandOptions(FFBluetoothRadioOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_BLUETOOTHRADIO_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateBluetoothRadioJsonConfig(FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyBluetoothRadioOptions))) FFBluetoothRadioOptions defaultOptions; + ffInitBluetoothRadioOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothRadioResult)); + + const char* error = ffDetectBluetoothRadio(&results); + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, item, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); + yyjson_mut_obj_add_uint(doc, obj, "lmpVersion", item->lmpVersion); + yyjson_mut_obj_add_uint(doc, obj, "lmpSubversion", item->lmpSubversion); + yyjson_mut_obj_add_uint(doc, obj, "hciVersion", item->hciVersion); + yyjson_mut_obj_add_uint(doc, obj, "hciRevision", item->hciRevision); + yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor); + yyjson_mut_obj_add_bool(doc, obj, "leSupported", item->leSupported); + } + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, results) + { + ffStrbufDestroy(&radio->name); + ffStrbufDestroy(&radio->address); + } +} + +void ffPrintBluetoothRadioHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTHRADIO_MODULE_NAME, "{1} ({4})", FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((const char* []) { + "Radio name for discovering - name", + "Address - local radio address", + "LMP version - lmp-version", + "HCI version - hci-version", + "Bluetooth version - version", + "Vendor - vendor", + "Is Bluetooth Low Energy (LE) supported - le-supported" + })); +} + +void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_BLUETOOTHRADIO_MODULE_NAME, + "List bluetooth radios width supported version and vendor", + ffParseBluetoothRadioCommandOptions, + ffParseBluetoothRadioJsonObject, + ffPrintBluetoothRadio, + ffGenerateBluetoothRadioJsonResult, + ffPrintBluetoothRadioHelpFormat, + ffGenerateBluetoothRadioJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰐻"); +} + +void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/bluetoothradio/bluetoothradio.h b/src/modules/bluetoothradio/bluetoothradio.h new file mode 100644 index 000000000..ee9ef1195 --- /dev/null +++ b/src/modules/bluetoothradio/bluetoothradio.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio" + +void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options); +void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options); +void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options); diff --git a/src/modules/bluetoothradio/option.h b/src/modules/bluetoothradio/option.h new file mode 100644 index 000000000..714200d3e --- /dev/null +++ b/src/modules/bluetoothradio/option.h @@ -0,0 +1,12 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" +#include "common/percent.h" + +typedef struct FFBluetoothRadioOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFBluetoothRadioOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 58ce1b98d..dbfebcf31 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -5,6 +5,7 @@ #include "modules/battery/battery.h" #include "modules/bios/bios.h" #include "modules/bluetooth/bluetooth.h" +#include "modules/bluetoothradio/bluetoothradio.h" #include "modules/brightness/brightness.h" #include "modules/board/board.h" #include "modules/bootmgr/bootmgr.h" diff --git a/src/modules/options.h b/src/modules/options.h index 49bd8fe6b..c705c7500 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -5,6 +5,7 @@ #include "modules/battery/option.h" #include "modules/bios/option.h" #include "modules/bluetooth/option.h" +#include "modules/bluetoothradio/option.h" #include "modules/board/option.h" #include "modules/bootmgr/option.h" #include "modules/break/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 7d80b2d86..0bc117e3e 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -6,6 +6,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitBatteryOptions(&options->battery); ffInitBiosOptions(&options->bios); ffInitBluetoothOptions(&options->bluetooth); + ffInitBluetoothRadioOptions(&options->bluetoothRadio); ffInitBoardOptions(&options->board); ffInitBootmgrOptions(&options->bootmgr); ffInitBreakOptions(&options->break_); @@ -77,6 +78,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyBatteryOptions(&options->battery); ffDestroyBiosOptions(&options->bios); ffDestroyBluetoothOptions(&options->bluetooth); + ffDestroyBluetoothRadioOptions(&options->bluetoothRadio); ffDestroyBoardOptions(&options->board); ffDestroyBootmgrOptions(&options->bootmgr); ffDestroyBreakOptions(&options->break_); diff --git a/src/options/modules.h b/src/options/modules.h index fdfae5e47..1768c8c18 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -7,6 +7,7 @@ typedef struct FFOptionsModules FFBatteryOptions battery; FFBiosOptions bios; FFBluetoothOptions bluetooth; + FFBluetoothRadioOptions bluetoothRadio; FFBoardOptions board; FFBootmgrOptions bootmgr; FFBreakOptions break_;