From afecba641ac553a30a1958bbb187776ba32b50fb Mon Sep 17 00:00:00 2001 From: Simon Danner Date: Thu, 13 May 2021 15:28:21 +0200 Subject: [PATCH 1/9] Add Polish, russion to voice prompt languages * Make it work with new firmware by changing the mask * Add new languages to get / set for voice prompts --- based.h | 6 +++++- main.c | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/based.h b/based.h index acbde75..fe7ce33 100644 --- a/based.h +++ b/based.h @@ -11,7 +11,7 @@ #define MAX_NUM_DEVICES 8 #define MAX_BT_PACK_LEN 0x1000 #define VER_STR_LEN 6 -#define VP_MASK 0x20 +#define VP_MASK 0x7F enum NoiseCancelling { NC_HIGH = 0x01, @@ -38,9 +38,13 @@ enum PromptLanguage { PL_PT = 0x27, PL_ZH = 0x28, PL_KO = 0x29, + PL_PL = 0x2B, + PL_RU = 0x2A, PL_NL = 0x2e, PL_JA = 0x2f, PL_SV = 0x32 + + }; enum Pairing { diff --git a/main.c b/main.c index d629397..60702c2 100644 --- a/main.c +++ b/main.c @@ -89,7 +89,11 @@ static int do_set_prompt_language(int sock, const char *arg) { pl = PL_ZH; } else if (strcmp(arg, "ko") == 0) { pl = PL_KO; - } else if (strcmp(arg, "nl") == 0) { + } else if (strcmp(arg, "pl") == 0) { + pl = PL_PL; + } else if (strcmp(arg, "ru") == 0) { + pl = PL_RU; + } else if (strcmp(arg, "nl") == 0) { pl = PL_NL; } else if (strcmp(arg, "ja") == 0) { pl = PL_JA; @@ -191,7 +195,7 @@ static int do_get_device_status(int sock) { char *print; printf("Name: %s\n", name); - switch (pl | VP_MASK) { + switch (pl & VP_MASK) { case PL_EN: print = "en"; break; @@ -225,8 +229,15 @@ static int do_get_device_status(int sock) { case PL_SV: print = "sv"; break; + case PL_RU: + print = "ru"; + break; + case PL_PL: + print = "pl"; + break; default: - return 1; + print = "unknown"; + break; } printf("Language: %s\n", print); printf("Voice Prompts: %s\n", pl & VP_MASK ? "on" : "off"); From 135a4d231715a7b2c6b8d998149c0e07e3f39225 Mon Sep 17 00:00:00 2001 From: Simon Danner Date: Thu, 13 May 2021 15:56:21 +0200 Subject: [PATCH 2/9] Device status: make it work * No idea what previous BT command did / why it was there. * The last check failed so it didn't proceed to status printing, without it works, so remove it ;) --- based.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/based.c b/based.c index 40bd1bf..bd3d889 100644 --- a/based.c +++ b/based.c @@ -320,9 +320,7 @@ int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *level = NC_DNE; } - static const uint8_t ack2[] = { 0x01, 0x01, 0x06, 0x00 }; - uint8_t buffer2[sizeof(ack2)]; - return read_check(sock, buffer2, sizeof(buffer2), ack2, NULL); + return status; } int set_pairing(int sock, enum Pairing pairing) { From a3c008f8a4142978db20d2ab43e7e5b69f255c87 Mon Sep 17 00:00:00 2001 From: Simon Danner Date: Thu, 13 May 2021 16:55:18 +0200 Subject: [PATCH 3/9] Add Self-voice setting --- based.c | 10 ++++++++++ based.h | 8 ++++++++ main.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/based.c b/based.c index bd3d889..6375e46 100644 --- a/based.c +++ b/based.c @@ -331,6 +331,16 @@ int set_pairing(int sock, enum Pairing pairing) { return write_check(sock, send, sizeof(send), ack, sizeof(ack)); } +int set_self_voice(int sock, enum SelfVoice selfvoice) { + static uint8_t send[] = { 0x01, 0x0b, 0x02, 0x02, 0x01, ANY, 0x38 }; + static uint8_t ack[] = { 0x01, 0x0b, 0x03, 0x03, 0x01, ANY, 0x0f}; + + send[5] = selfvoice; + ack[5] = selfvoice; + return write_check(sock, send, sizeof(send), ack, sizeof(ack)); +} + + int get_firmware_version(int sock, char version[VER_STR_LEN]) { static const uint8_t send[] = { 0x00, 0x05, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x05, 0x03, 0x05 }; diff --git a/based.h b/based.h index fe7ce33..0c56d79 100644 --- a/based.h +++ b/based.h @@ -63,6 +63,13 @@ enum DevicesConnected { DC_TWO = 0x03 }; +enum SelfVoice { + SV_OFF = 0x0, + SV_HIGH = 0x1, + SV_MEDIUM = 0x2, + SV_LOW = 0x3, +}; + struct Device { bdaddr_t address; enum DeviceStatus status; @@ -81,6 +88,7 @@ int set_noise_cancelling(int sock, enum NoiseCancelling level); int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, enum AutoOff *minutes, enum NoiseCancelling *level); int set_pairing(int sock, enum Pairing pairing); +int set_self_voice(int sock, enum SelfVoice selfVoice); int get_firmware_version(int sock, char version[VER_STR_LEN]); int get_serial_number(int sock, char serial[0x100]); int get_battery_level(int sock, unsigned int *level); diff --git a/main.c b/main.c index 60702c2..7128d0b 100644 --- a/main.c +++ b/main.c @@ -53,6 +53,9 @@ static void usage() { "\t\tRemove the device at address from the pairing list.\n" "\t--device-id\n" "\t\tPrint the device id followed by the index revision.\n" + "\t-e, --self-voice\n" + "\t\tChange the self voice level.\n" + "\t\tlevel: high, medium, low, off\n" , program_name); } @@ -286,6 +289,26 @@ static int do_set_pairing(int sock, const char *arg) { return set_pairing(sock, p); } +static int do_set_self_voice(int sock, const char *arg) { + enum SelfVoice p; + + if (strcmp(arg, "high") == 0) { + p = SV_HIGH; + } else if (strcmp(arg, "medium") == 0) { + p = SV_MEDIUM; + } else if (strcmp(arg, "low") == 0) { + p = SV_LOW; + } else if (strcmp(arg, "off") == 0) { + p = SV_OFF; + } else { + fprintf(stderr, "Invalid self voice argument: %s\n", arg); + usage(); + return 1; + } + + return set_self_voice(sock, p); +} + static int do_get_firmware_version(int sock) { char version[VER_STR_LEN]; int status = get_firmware_version(sock, version); @@ -431,7 +454,7 @@ static int do_send_packet(int sock, const char *arg) { } int main(int argc, char *argv[]) { - static const char *short_opt = "hn:l:v:o:c:dp:fsba"; + static const char *short_opt = "hn:l:v:o:c:e:dp:fsba"; static const struct option long_opt[] = { { "help", no_argument, NULL, 'h' }, { "name", required_argument, NULL, 'n' }, @@ -449,6 +472,7 @@ int main(int argc, char *argv[]) { { "disconnect-device", required_argument, NULL, 3 }, { "remove-device", required_argument, NULL, 4 }, { "device-id", no_argument, NULL, 5 }, + { "self-voice", required_argument, NULL, 'e' }, { "send-packet", required_argument, NULL, 1 }, { 0, 0, 0, 0 } }; @@ -546,6 +570,9 @@ int main(int argc, char *argv[]) { case 'a': status = do_get_paired_devices(sock); break; + case 'e': + status = do_set_self_voice(sock, optarg); + break; case 2: status = do_connect_device(sock, optarg); break; From ca9c15453191a7b84d6a582efd9be4bdb6bcdd38 Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Mon, 8 Aug 2022 08:15:06 +0200 Subject: [PATCH 4/9] Compiling --- CMakeLists.txt | 27 +++++++++++ README.txt | 18 ++++++- based.c | 128 ++++++++++++++++++++++++++----------------------- based.h | 6 +++ bluetooth.c | 64 ++++++++++++++++++++++++- bluetooth.h | 14 ++++++ main.c | 45 +++++++++++++++-- 7 files changed, 235 insertions(+), 67 deletions(-) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c5fb3d4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +project(based-connect) + +cmake_minimum_required(VERSION 3.2) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +find_path(GETOPT_HEADER NAMES getopt.h REQUIRED) +find_library(GETOPT_LIBRARIES NAMES getopt REQUIRED) +message(WARNING "Found lib ${GETOPT_LIBRARIES}") + +include_directories(${GETOPT_HEADER}) + +add_executable(based-connect + based.c + based.h + bluetooth.c + bluetooth.h + main.c + util.c + util.h +) +set_property(TARGET based-connect PROPERTY C_STANDARD 99) +target_link_libraries(based-connect ${GETOPT_LIBRARIES}) +if (WIN32) + target_link_libraries(based-connect wsock32 ws2_32) +endif (WIN32) diff --git a/README.txt b/README.txt index 73e89e7..6518ec6 100644 --- a/README.txt +++ b/README.txt @@ -71,8 +71,22 @@ Options: Building -------- -Simply run `make -j` to build the program. The executable produced will be -called `based-connect`. +Create a build directory (e.g., `mkdir build`) and enter it. Run +```sh +cmake .. +``` +to create a Makefile, and then run +```sh +cmake --build . +``` +to build the project. + +On Windows, you'll need `vcpkg` with the `getopt` package installed. Run +```powershell +cmake -T ClangCL -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" .. +``` +to create the build files (You'll need Visual Studio 2019 with the clang build +tools installed). Installing ---------- diff --git a/based.c b/based.c index 40bd1bf..8fde24e 100644 --- a/based.c +++ b/based.c @@ -2,7 +2,14 @@ #include #include #include +#ifdef _WIN32 +#include +#define read(sock, buf, size) recv(sock, (void *) buf, (int) size, 0) +#define write(sock, buf, size) send(sock, (char *) buf, size, 0) +#define bswap_16(x) _byteswap_ushort(x) +#else #include +#endif #include "based.h" #include "bluetooth.h" @@ -22,10 +29,13 @@ int has_noise_cancelling(unsigned int device_id) { } static int masked_memcmp(const void *ptr1, const void *ptr2, size_t num, const void *mask) { + const uint8_t *p1 = (const uint8_t *) ptr1; + const uint8_t *p2 = (const uint8_t *) ptr2; + const uint8_t *m = (const uint8_t *) mask; while (num-- > 0) { - uint8_t mask_byte = *(uint8_t *) mask++; - uint8_t byte1 = *(uint8_t *) ptr1++ & mask_byte; - uint8_t byte2 = *(uint8_t *) ptr2++ & mask_byte; + uint8_t mask_byte = *m++; + uint8_t byte1 = *p1++ & mask_byte; + uint8_t byte2 = *p2++ & mask_byte; if (byte1 != byte2) { return byte1 - byte2; @@ -46,19 +56,19 @@ static int read_check(int sock, void *recieve, size_t recieve_n, const void *ack : memcmp(ack, recieve, recieve_n)); } -static int write_check(int sock, const void *send, size_t send_n, +static int write_check(int sock, const void *send_b, size_t send_n, const void *ack, size_t ack_n) { uint8_t buffer[ack_n]; - int status = write(sock, send, send_n); + int status = write(sock, send_b, send_n); if (status != send_n) { return status ? status : 1; } return read_check(sock, buffer, sizeof(buffer), ack, NULL); } -int send_packet(int sock, const void *send, size_t send_n, uint8_t recieved[MAX_BT_PACK_LEN]) { - int status = write(sock, send, send_n); +int send_packet(int sock, const void *send_b, size_t send_n, uint8_t recieved[MAX_BT_PACK_LEN]) { + int status = write(sock, send_b, send_n); if (status != send_n) { return status ? status : 1; } @@ -67,10 +77,10 @@ int send_packet(int sock, const void *send, size_t send_n, uint8_t recieved[MAX_ } int init_connection(int sock) { - static const uint8_t send[] = { 0x00, 0x01, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x00, 0x01, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x01, 0x03, 0x05 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -87,10 +97,10 @@ int init_connection(int sock) { } int get_device_id(int sock, unsigned int *device_id, unsigned int *index) { - static const uint8_t send[] = { 0x00, 0x03, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x00, 0x03, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x03, 0x03, 0x03 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -134,14 +144,14 @@ static int get_name(int sock, char name[MAX_NAME_LEN + 1]) { } int set_name(int sock, const char *name) { - static uint8_t send[CN_BASE_PACK_LEN + MAX_NAME_LEN] = { 0x01, 0x02, 0x02, ANY }; + static uint8_t send_buf[CN_BASE_PACK_LEN + MAX_NAME_LEN] = { 0x01, 0x02, 0x02, ANY }; size_t length = strlen(name); - send[3] = length; - strncpy((char *) &send[CN_BASE_PACK_LEN], name, MAX_NAME_LEN); + send_buf[3] = length; + strncpy_s((char *) &send_buf[CN_BASE_PACK_LEN], sizeof(send_buf) - CN_BASE_PACK_LEN, name, MAX_NAME_LEN); size_t send_size = CN_BASE_PACK_LEN + length; - int status = write(sock, send, send_size); + int status = write(sock, send_buf, send_size); if (status != send_size) { return status ? status : 1; } @@ -172,11 +182,11 @@ static int get_prompt_language(int sock, enum PromptLanguage *language) { } int set_prompt_language(int sock, enum PromptLanguage language) { - static uint8_t send[] = { 0x01, 0x03, 0x02, 0x01, ANY }; - send[4] = language; + static uint8_t send_buf[] = { 0x01, 0x03, 0x02, 0x01, ANY }; + send_buf[4] = language; - int status = write(sock, send, sizeof(send)); - if (status != sizeof(send)) { + int status = write(sock, send_buf, sizeof(send_buf)); + if (status != sizeof(send_buf)) { return status ? status : 1; } @@ -224,11 +234,11 @@ static int get_auto_off(int sock, enum AutoOff *minutes) { } int set_auto_off(int sock, enum AutoOff minutes) { - static uint8_t send[] = { 0x01, 0x04, 0x02, 0x01, ANY }; - send[4] = minutes; + static uint8_t send_buf[] = { 0x01, 0x04, 0x02, 0x01, ANY }; + send_buf[4] = minutes; - int status = write(sock, send, sizeof(send)); - if (status != sizeof(send)) { + int status = write(sock, send_buf, sizeof(send_buf)); + if (status != sizeof(send_buf)) { return status ? status : 1; } @@ -256,11 +266,11 @@ static int get_noise_cancelling(int sock, enum NoiseCancelling *level) { } int set_noise_cancelling(int sock, enum NoiseCancelling level) { - static uint8_t send[] = { 0x01, 0x06, 0x02, 0x01, ANY }; - send[4] = level; + static uint8_t send_buf[] = { 0x01, 0x06, 0x02, 0x01, ANY }; + send_buf[4] = level; - int status = write(sock, send, sizeof(send)); - if (status != sizeof(send)) { + int status = write(sock, send_buf, sizeof(send_buf)); + if (status != sizeof(send_buf)) { return status ? status : 1; } @@ -282,9 +292,9 @@ int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage return status; } - static const uint8_t send[] = { 0x01, 0x01, 0x05, 0x00 }; - status = write(sock, send, sizeof(send)); - if (status != sizeof(send)) { + static const uint8_t send_buf[] = { 0x01, 0x01, 0x05, 0x00 }; + status = write(sock, send_buf, sizeof(send_buf)); + if (status != sizeof(send_buf)) { return status ? status : 1; } @@ -326,18 +336,18 @@ int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage } int set_pairing(int sock, enum Pairing pairing) { - static uint8_t send[] = { 0x04, 0x08, 0x05, 0x01, ANY }; + static uint8_t send_buf[] = { 0x04, 0x08, 0x05, 0x01, ANY }; static uint8_t ack[] = { 0x04, 0x08, 0x06, 0x01, ANY }; - send[4] = pairing; + send_buf[4] = pairing; ack[4] = pairing; - return write_check(sock, send, sizeof(send), ack, sizeof(ack)); + return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } int get_firmware_version(int sock, char version[VER_STR_LEN]) { - static const uint8_t send[] = { 0x00, 0x05, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x00, 0x05, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x05, 0x03, 0x05 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -352,10 +362,10 @@ int get_firmware_version(int sock, char version[VER_STR_LEN]) { } int get_serial_number(int sock, char serial[0x100]) { - static const uint8_t send[] = { 0x00, 0x07, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x00, 0x07, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x07, 0x03 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -376,10 +386,10 @@ int get_serial_number(int sock, char serial[0x100]) { } int get_battery_level(int sock, unsigned int *level) { - static const uint8_t send[] = { 0x02, 0x02, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x02, 0x02, 0x01, 0x00 }; static const uint8_t ack[] = { 0x02, 0x02, 0x03, 0x01 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -391,12 +401,12 @@ int get_battery_level(int sock, unsigned int *level) { } int get_device_info(int sock, bdaddr_t address, struct Device *device) { - static uint8_t send[10] = { 0x04, 0x05, 0x01, BT_ADDR_LEN }; + static uint8_t send_buf[10] = { 0x04, 0x05, 0x01, BT_ADDR_LEN }; static const uint8_t ack[] = { 0x04, 0x05, 0x03 }; - memcpy(&send[4], &address.b, BT_ADDR_LEN); + memcpy(&send_buf[4], &BDADDR_BYTES(address), BT_ADDR_LEN); - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -407,13 +417,13 @@ int get_device_info(int sock, bdaddr_t address, struct Device *device) { return status ? status : 1; } - status = read(sock, &device->address.b, BT_ADDR_LEN); + status = read(sock, &BDADDR_BYTES(device->address), BT_ADDR_LEN); if (status != BT_ADDR_LEN) { return status ? status : 1; } length -= BT_ADDR_LEN; - status = memcmp(&address.b, &device->address.b, BT_ADDR_LEN); + status = memcmp(&BDADDR_BYTES(address), &BDADDR_BYTES(device->address), BT_ADDR_LEN); if (status) { return abs(status); } @@ -446,10 +456,10 @@ int get_device_info(int sock, bdaddr_t address, struct Device *device) { int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, enum DevicesConnected *connected) { - static const uint8_t send[] = { 0x04, 0x04, 0x01, 0x00 }; + static const uint8_t send_buf[] = { 0x04, 0x04, 0x01, 0x00 }; static const uint8_t ack[] = { 0x04, 0x04, 0x03 }; - int status = write_check(sock, send, sizeof(send), ack, sizeof(ack)); + int status = write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); if (status) { return status; } @@ -475,7 +485,7 @@ int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *nu size_t i; for (i = 0; i < num_devices_byte; ++i) { - status = read(sock, &addresses[i].b, BT_ADDR_LEN); + status = read(sock, &BDADDR_BYTES(addresses[i]), BT_ADDR_LEN); if (status != BT_ADDR_LEN) { return status ? status : 1; } @@ -485,25 +495,25 @@ int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *nu } int connect_device(int sock, bdaddr_t address) { - static uint8_t send[11] = { 0x04, 0x01, 0x05, BT_ADDR_LEN + 1, 0x00 }; + static uint8_t send_buf[11] = { 0x04, 0x01, 0x05, BT_ADDR_LEN + 1, 0x00 }; static uint8_t ack[10] = { 0x04, 0x01, 0x07, BT_ADDR_LEN }; - memcpy(&send[5], &address.b, BT_ADDR_LEN); - memcpy(&ack[4], &address.b, BT_ADDR_LEN); - return write_check(sock, send, sizeof(send), ack, sizeof(ack)); + memcpy(&send_buf[5], &BDADDR_BYTES(address), BT_ADDR_LEN); + memcpy(&ack[4], &BDADDR_BYTES(address), BT_ADDR_LEN); + return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } int disconnect_device(int sock, bdaddr_t address) { - static uint8_t send[10] = { 0x04, 0x02, 0x05, BT_ADDR_LEN }; + static uint8_t send_buf[10] = { 0x04, 0x02, 0x05, BT_ADDR_LEN }; static uint8_t ack[10] = { 0x04, 0x02, 0x07, BT_ADDR_LEN }; - memcpy(&send[4], &address.b, BT_ADDR_LEN); - memcpy(&ack[4], &address.b, BT_ADDR_LEN); - return write_check(sock, send, sizeof(send), ack, sizeof(ack)); + memcpy(&send_buf[4], &BDADDR_BYTES(address), BT_ADDR_LEN); + memcpy(&ack[4], &BDADDR_BYTES(address), BT_ADDR_LEN); + return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } int remove_device(int sock, bdaddr_t address) { - static uint8_t send[10] = { 0x04, 0x03, 0x05, BT_ADDR_LEN }; + static uint8_t send_buf[10] = { 0x04, 0x03, 0x05, BT_ADDR_LEN }; static uint8_t ack[10] = { 0x04, 0x03, 0x06, BT_ADDR_LEN }; - memcpy(&send[4], &address.b, BT_ADDR_LEN); - memcpy(&ack[4], &address.b, BT_ADDR_LEN); - return write_check(sock, send, sizeof(send), ack, sizeof(ack)); + memcpy(&send_buf[4], &BDADDR_BYTES(address), BT_ADDR_LEN); + memcpy(&ack[4], &BDADDR_BYTES(address), BT_ADDR_LEN); + return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } diff --git a/based.h b/based.h index acbde75..927b6bb 100644 --- a/based.h +++ b/based.h @@ -1,7 +1,13 @@ #ifndef BASED_H #define BASED_H +#ifdef _WIN32 +#include +#include +#else #include +#endif + #include #include "bluetooth.h" diff --git a/bluetooth.c b/bluetooth.c index 3571e92..33d18e7 100644 --- a/bluetooth.c +++ b/bluetooth.c @@ -1,4 +1,11 @@ +#ifdef _WIN32 +#include +#include +#include +#else #include +#endif + #include #include "bluetooth.h" @@ -9,7 +16,7 @@ int reverse_ba2str(const bdaddr_t *ba, char *str) { return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - ba->b[0], ba->b[1], ba->b[2], ba->b[3], ba->b[4], ba->b[5]); + BDADDR_BYTES(*ba)[0], BDADDR_BYTES(*ba)[1], BDADDR_BYTES(*ba)[2], BDADDR_BYTES(*ba)[3], BDADDR_BYTES(*ba)[4], BDADDR_BYTES(*ba)[5]); } int reverse_str2ba(const char *str, bdaddr_t *ba) { @@ -21,7 +28,60 @@ int reverse_str2ba(const char *str, bdaddr_t *ba) { } for (i = 0; i < 6; i++, str += 3) - ba->b[i] = strtol(str, NULL, 16); + BDADDR_BYTES(*ba)[i] = strtol(str, NULL, 16); + + return 0; +} + +#ifdef _WIN32 +int bachk(const char *str) +{ + char tmp[18], *ptr = tmp; + if (!str) + return -1; + if (strlen(str) != 17) + return -1; + memcpy(tmp, str, 18); + while (*ptr) { + *ptr = toupper(*ptr); + if (*ptr < '0'|| (*ptr > '9' && *ptr < 'A') || *ptr > 'F') + return -1; + ptr++; + *ptr = toupper(*ptr); + if (*ptr < '0'|| (*ptr > '9' && *ptr < 'A') || *ptr > 'F') + return -1; + ptr++; + *ptr = toupper(*ptr); + if (*ptr == 0) + break; + if (*ptr != ':') + return -1; + ptr++; + } + return 0; +} +int str2ba(const char *str, bdaddr_t *ba) +{ + uint8_t b[6]; + const char *ptr = str; + int i; + for (i = 0; i < 6; i++) { + b[i] = (uint8_t) strtol(ptr, NULL, 16); + if (i != 5 && !(ptr = strchr(ptr, ':'))) + ptr = ":00:00:00:00:00"; + ptr++; + } + baswap(ba, (bdaddr_t *) b); return 0; } + +void baswap(bdaddr_t *dst, const bdaddr_t *src) +{ + register unsigned char *d = (unsigned char *) dst; + register const unsigned char *s = (const unsigned char *) src; + register int i; + for (i = 0; i < 6; i++) + d[i] = s[5-i]; +} +#endif diff --git a/bluetooth.h b/bluetooth.h index 62cae9c..4d2c986 100644 --- a/bluetooth.h +++ b/bluetooth.h @@ -1,11 +1,25 @@ #ifndef BLUETOOTH_H #define BLUETOOTH_H +#ifdef _WIN32 +#define bdaddr_t BLUETOOTH_ADDRESS_STRUCT +#define BDADDR_BYTES(x) ((x).rgBytes) +#include +#include +#include +#else #include +#define BDADDR_BYTES(x) ((x).b) +#endif #define BT_ADDR_LEN 6 int reverse_ba2str(const bdaddr_t *ba, char *str); int reverse_str2ba(const char *str, bdaddr_t *ba); +#ifdef _WIN32 +int bachk(const char *str); +int str2ba(const char *str, bdaddr_t *ba); +void baswap(bdaddr_t *dst, const bdaddr_t *src); +#endif #endif diff --git a/main.c b/main.c index f7615d7..8b9691c 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,28 @@ +#ifdef _WIN32 +#include +#else #include #include +#endif + #include #include #include +#ifdef _WIN32 +#include +#else #include +#endif #include "based.h" #include "bluetooth.h" #include "util.h" +#ifdef _WIN32 +#define AF_BLUETOOTH AF_BTH +#define BTPROTO_RFCOMM BTHPROTO_RFCOMM +#endif + static const char *program_name; static void usage() { @@ -442,19 +456,33 @@ int main(int argc, char *argv[]) { { 0, 0, 0, 0 } }; - static const struct timeval send_timeout = { 5, 0 }; - static const struct timeval recieve_timeout = { 1, 0 }; int sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); +#ifdef _WIN32 +// static const uint32_t send_timeout = 5000; +// if (setsockopt(sock, SOL_RFCOMM, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)) < 0) { +// perror("Could not set socket send timeout"); +// return 1; +// } +// +// static const uint32_t receive_timeout = 1000; +// if (setsockopt(sock, SOL_RFCOMM, SO_RCVTIMEO, &receive_timeout, sizeof(receive_timeout)) < 0) { +// perror("Could not set socket recieve timeout"); +// return 1; +// } +#else + static const struct timeval send_timeout = { 5, 0 }; if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)) < 0) { perror("Could not set socket send timeout"); return 1; } - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &recieve_timeout, sizeof(recieve_timeout)) < 0) { + static const struct timeval receive_timeout = { 1, 0 }; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &recieve_timeout, sizeof(receive_timeout)) < 0) { perror("Could not set socket recieve timeout"); return 1; } +#endif program_name = argv[0]; @@ -481,7 +509,15 @@ int main(int argc, char *argv[]) { usage(); return 1; } - +#ifdef _WIN32 + SOCKADDR_BTH address; + address.addressFamily = AF_BTH; + address.port = BOSE_CHANNEL; + if (str2ba(argv[optind], &address.btAddr) != 0) { + fprintf(stderr, "Invalid bluetooth address: %s\n", argv[optind]); + return 1; + } +#else struct sockaddr_rc address; address.rc_family = AF_BLUETOOTH; address.rc_channel = BOSE_CHANNEL; @@ -489,6 +525,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Invalid bluetooth address: %s\n", argv[optind]); return 1; } +#endif if (connect(sock, (struct sockaddr *) &address, sizeof(address)) != 0) { perror("Could not connect to Bluetooth device"); From be481eeb2ef2373ebfc8b8f390cb32b55c070464 Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Mon, 8 Aug 2022 11:11:32 +0200 Subject: [PATCH 5/9] Tool working on Windows --- README.txt | 15 +++++++-- based.c | 67 ++++++++++++++++++++-------------------- based.h | 43 ++++++++++++-------------- bluetooth.c | 6 ++-- bluetooth.h | 2 +- main.c | 88 ++++++++++++++++++++++++++--------------------------- socket.h | 29 ++++++++++++++++++ 7 files changed, 142 insertions(+), 108 deletions(-) create mode 100644 socket.h diff --git a/README.txt b/README.txt index 6518ec6..1c30fe6 100644 --- a/README.txt +++ b/README.txt @@ -83,10 +83,9 @@ to build the project. On Windows, you'll need `vcpkg` with the `getopt` package installed. Run ```powershell -cmake -T ClangCL -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" .. +cmake -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" .. ``` -to create the build files (You'll need Visual Studio 2019 with the clang build -tools installed). +to create the build files. Installing ---------- @@ -98,6 +97,16 @@ Alternatively, if you run Arch Linux, you can download it from the AUR here: https://aur.archlinux.org/packages/based-connect-git/ +Running +------- + +On Windows, use +```powershell +Get-PnpDevice -class Bluetooth | Select-Object -Property FriendlyName, +DeviceID +``` +to enumerate the Bluetooth device ID. + Dependencies ------------ diff --git a/based.c b/based.c index 8fde24e..b36ee1b 100644 --- a/based.c +++ b/based.c @@ -5,7 +5,7 @@ #ifdef _WIN32 #include #define read(sock, buf, size) recv(sock, (void *) buf, (int) size, 0) -#define write(sock, buf, size) send(sock, (char *) buf, size, 0) +#define write(sock, buf, size) send(sock, (char *) buf, (int) size, 0) #define bswap_16(x) _byteswap_ushort(x) #else #include @@ -13,6 +13,7 @@ #include "based.h" #include "bluetooth.h" +#include "malloc.h" #define ANY 0x00 #define CN_BASE_PACK_LEN 4 @@ -44,39 +45,39 @@ static int masked_memcmp(const void *ptr1, const void *ptr2, size_t num, const v return 0; } -static int read_check(int sock, void *recieve, size_t recieve_n, const void *ack, +static int read_check(socktype_t sock, void *receive, size_t receive_n, const void *ack, const void *mask) { - int status = read(sock, recieve, recieve_n); - if (status != recieve_n) { + int status = read(sock, receive, receive_n); + if (status != receive_n) { return status ? status : 1; } return abs(mask - ? masked_memcmp(ack, recieve, recieve_n, mask) - : memcmp(ack, recieve, recieve_n)); + ? masked_memcmp(ack, receive, receive_n, mask) + : memcmp(ack, receive, receive_n)); } -static int write_check(int sock, const void *send_b, size_t send_n, +static int write_check(socktype_t sock, const void *send_b, size_t send_n, const void *ack, size_t ack_n) { - uint8_t buffer[ack_n]; + uint8_t *buffer = alloca(ack_n); int status = write(sock, send_b, send_n); if (status != send_n) { return status ? status : 1; } - return read_check(sock, buffer, sizeof(buffer), ack, NULL); + return read_check(sock, buffer, ack_n, ack, NULL); } -int send_packet(int sock, const void *send_b, size_t send_n, uint8_t recieved[MAX_BT_PACK_LEN]) { +int send_packet(socktype_t sock, const void *send_b, size_t send_n, uint8_t received[MAX_BT_PACK_LEN]) { int status = write(sock, send_b, send_n); if (status != send_n) { return status ? status : 1; } - return read(sock, recieved, MAX_BT_PACK_LEN); + return read(sock, received, MAX_BT_PACK_LEN); } -int init_connection(int sock) { +int init_connection(socktype_t sock) { static const uint8_t send_buf[] = { 0x00, 0x01, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x01, 0x03, 0x05 }; @@ -96,7 +97,7 @@ int init_connection(int sock) { return 0; } -int get_device_id(int sock, unsigned int *device_id, unsigned int *index) { +int get_device_id(socktype_t sock, unsigned int *device_id, unsigned int *index) { static const uint8_t send_buf[] = { 0x00, 0x03, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x03, 0x03, 0x03 }; @@ -123,7 +124,7 @@ int get_device_id(int sock, unsigned int *device_id, unsigned int *index) { return 0; } -static int get_name(int sock, char name[MAX_NAME_LEN + 1]) { +static int get_name(socktype_t sock, char name[MAX_NAME_LEN + 1]) { static const uint8_t ack[] = { 0x01, 0x02, 0x03, ANY, 0x00 }; static const uint8_t mask[] = { 0xff, 0xff, 0xff, 0x00, 0xff }; uint8_t buffer[sizeof(ack)]; @@ -143,11 +144,11 @@ static int get_name(int sock, char name[MAX_NAME_LEN + 1]) { return 0; } -int set_name(int sock, const char *name) { +int set_name(socktype_t sock, const char *name) { static uint8_t send_buf[CN_BASE_PACK_LEN + MAX_NAME_LEN] = { 0x01, 0x02, 0x02, ANY }; size_t length = strlen(name); - send_buf[3] = length; + send_buf[3] = (uint8_t) length; strncpy_s((char *) &send_buf[CN_BASE_PACK_LEN], sizeof(send_buf) - CN_BASE_PACK_LEN, name, MAX_NAME_LEN); size_t send_size = CN_BASE_PACK_LEN + length; @@ -165,7 +166,7 @@ int set_name(int sock, const char *name) { return abs(strcmp(name, got_name)); } -static int get_prompt_language(int sock, enum PromptLanguage *language) { +static int get_prompt_language(socktype_t sock, enum PromptLanguage *language) { // TODO: ensure that this value is correct // TODO: figure out what bytes 6 and 7 are for static const uint8_t ack[] = { 0x01, 0x03, 0x03, 0x05, ANY, 0x00, ANY, ANY, 0xde }; @@ -181,7 +182,7 @@ static int get_prompt_language(int sock, enum PromptLanguage *language) { return 0; } -int set_prompt_language(int sock, enum PromptLanguage language) { +int set_prompt_language(socktype_t sock, enum PromptLanguage language) { static uint8_t send_buf[] = { 0x01, 0x03, 0x02, 0x01, ANY }; send_buf[4] = language; @@ -199,7 +200,7 @@ int set_prompt_language(int sock, enum PromptLanguage language) { return abs(language - got_language); } -int set_voice_prompts(int sock, int on) { +int set_voice_prompts(socktype_t sock, int on) { char name[MAX_NAME_LEN + 1]; enum PromptLanguage pl; enum AutoOff ao; @@ -219,7 +220,7 @@ int set_voice_prompts(int sock, int on) { return set_prompt_language(sock, pl); } -static int get_auto_off(int sock, enum AutoOff *minutes) { +static int get_auto_off(socktype_t sock, enum AutoOff *minutes) { static const uint8_t ack[] = { 0x01, 0x04, 0x03, 0x01, ANY }; static const uint8_t mask[] = { 0xff, 0xff, 0xff, 0xff, 0x00 }; uint8_t buffer[sizeof(ack)]; @@ -233,7 +234,7 @@ static int get_auto_off(int sock, enum AutoOff *minutes) { return 0; } -int set_auto_off(int sock, enum AutoOff minutes) { +int set_auto_off(socktype_t sock, enum AutoOff minutes) { static uint8_t send_buf[] = { 0x01, 0x04, 0x02, 0x01, ANY }; send_buf[4] = minutes; @@ -251,7 +252,7 @@ int set_auto_off(int sock, enum AutoOff minutes) { return abs(minutes - got_minutes); } -static int get_noise_cancelling(int sock, enum NoiseCancelling *level) { +static int get_noise_cancelling(socktype_t sock, enum NoiseCancelling *level) { static const uint8_t ack[] = { 0x01, 0x06, 0x03, 0x02, ANY, 0x0b }; static const uint8_t mask[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff }; uint8_t buffer[sizeof(ack)]; @@ -265,7 +266,7 @@ static int get_noise_cancelling(int sock, enum NoiseCancelling *level) { return 0; } -int set_noise_cancelling(int sock, enum NoiseCancelling level) { +int set_noise_cancelling(socktype_t sock, enum NoiseCancelling level) { static uint8_t send_buf[] = { 0x01, 0x06, 0x02, 0x01, ANY }; send_buf[4] = level; @@ -283,7 +284,7 @@ int set_noise_cancelling(int sock, enum NoiseCancelling level) { return abs(level - got_level); } -int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, +int get_device_status(socktype_t sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, enum AutoOff *minutes, enum NoiseCancelling *level) { unsigned int device_id; unsigned int index; @@ -335,7 +336,7 @@ int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage return read_check(sock, buffer2, sizeof(buffer2), ack2, NULL); } -int set_pairing(int sock, enum Pairing pairing) { +int set_pairing(socktype_t sock, enum Pairing pairing) { static uint8_t send_buf[] = { 0x04, 0x08, 0x05, 0x01, ANY }; static uint8_t ack[] = { 0x04, 0x08, 0x06, 0x01, ANY }; send_buf[4] = pairing; @@ -343,7 +344,7 @@ int set_pairing(int sock, enum Pairing pairing) { return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } -int get_firmware_version(int sock, char version[VER_STR_LEN]) { +int get_firmware_version(socktype_t sock, char version[VER_STR_LEN]) { static const uint8_t send_buf[] = { 0x00, 0x05, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x05, 0x03, 0x05 }; @@ -361,7 +362,7 @@ int get_firmware_version(int sock, char version[VER_STR_LEN]) { return 0; } -int get_serial_number(int sock, char serial[0x100]) { +int get_serial_number(socktype_t sock, char serial[0x100]) { static const uint8_t send_buf[] = { 0x00, 0x07, 0x01, 0x00 }; static const uint8_t ack[] = { 0x00, 0x07, 0x03 }; @@ -385,7 +386,7 @@ int get_serial_number(int sock, char serial[0x100]) { return 0; } -int get_battery_level(int sock, unsigned int *level) { +int get_battery_level(socktype_t sock, unsigned int *level) { static const uint8_t send_buf[] = { 0x02, 0x02, 0x01, 0x00 }; static const uint8_t ack[] = { 0x02, 0x02, 0x03, 0x01 }; @@ -400,7 +401,7 @@ int get_battery_level(int sock, unsigned int *level) { return 0; } -int get_device_info(int sock, bdaddr_t address, struct Device *device) { +int get_device_info(socktype_t sock, bdaddr_t address, struct Device *device) { static uint8_t send_buf[10] = { 0x04, 0x05, 0x01, BT_ADDR_LEN }; static const uint8_t ack[] = { 0x04, 0x05, 0x03 }; @@ -454,7 +455,7 @@ int get_device_info(int sock, bdaddr_t address, struct Device *device) { return 0; } -int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, +int get_paired_devices(socktype_t sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, enum DevicesConnected *connected) { static const uint8_t send_buf[] = { 0x04, 0x04, 0x01, 0x00 }; static const uint8_t ack[] = { 0x04, 0x04, 0x03 }; @@ -494,7 +495,7 @@ int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *nu return 0; } -int connect_device(int sock, bdaddr_t address) { +int connect_device(socktype_t sock, bdaddr_t address) { static uint8_t send_buf[11] = { 0x04, 0x01, 0x05, BT_ADDR_LEN + 1, 0x00 }; static uint8_t ack[10] = { 0x04, 0x01, 0x07, BT_ADDR_LEN }; memcpy(&send_buf[5], &BDADDR_BYTES(address), BT_ADDR_LEN); @@ -502,7 +503,7 @@ int connect_device(int sock, bdaddr_t address) { return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } -int disconnect_device(int sock, bdaddr_t address) { +int disconnect_device(socktype_t sock, bdaddr_t address) { static uint8_t send_buf[10] = { 0x04, 0x02, 0x05, BT_ADDR_LEN }; static uint8_t ack[10] = { 0x04, 0x02, 0x07, BT_ADDR_LEN }; memcpy(&send_buf[4], &BDADDR_BYTES(address), BT_ADDR_LEN); @@ -510,7 +511,7 @@ int disconnect_device(int sock, bdaddr_t address) { return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } -int remove_device(int sock, bdaddr_t address) { +int remove_device(socktype_t sock, bdaddr_t address) { static uint8_t send_buf[10] = { 0x04, 0x03, 0x05, BT_ADDR_LEN }; static uint8_t ack[10] = { 0x04, 0x03, 0x06, BT_ADDR_LEN }; memcpy(&send_buf[4], &BDADDR_BYTES(address), BT_ADDR_LEN); diff --git a/based.h b/based.h index 927b6bb..35d6aa8 100644 --- a/based.h +++ b/based.h @@ -1,12 +1,7 @@ #ifndef BASED_H #define BASED_H -#ifdef _WIN32 -#include -#include -#else -#include -#endif +#include "socket.h" #include @@ -72,25 +67,25 @@ struct Device { }; int has_noise_cancelling(unsigned int device_id); -int init_connection(int sock); -int send_packet(int sock, const void *send, size_t send_n, uint8_t recieved[MAX_BT_PACK_LEN]); -int get_device_id(int sock, unsigned int *device_id, unsigned int *index); -int set_name(int sock, const char *name); -int set_prompt_language(int sock, enum PromptLanguage language); -int set_voice_prompts(int sock, int on); -int set_auto_off(int sock, enum AutoOff minutes); -int set_noise_cancelling(int sock, enum NoiseCancelling level); -int get_device_status(int sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, +int init_connection(socktype_t sock); +int send_packet(socktype_t sock, const void *send, size_t send_n, uint8_t recieved[MAX_BT_PACK_LEN]); +int get_device_id(socktype_t sock, unsigned int *device_id, unsigned int *index); +int set_name(socktype_t sock, const char *name); +int set_prompt_language(socktype_t sock, enum PromptLanguage language); +int set_voice_prompts(socktype_t sock, int on); +int set_auto_off(socktype_t sock, enum AutoOff minutes); +int set_noise_cancelling(socktype_t sock, enum NoiseCancelling level); +int get_device_status(socktype_t sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, enum AutoOff *minutes, enum NoiseCancelling *level); -int set_pairing(int sock, enum Pairing pairing); -int get_firmware_version(int sock, char version[VER_STR_LEN]); -int get_serial_number(int sock, char serial[0x100]); -int get_battery_level(int sock, unsigned int *level); -int get_device_info(int sock, bdaddr_t address, struct Device *device); -int get_paired_devices(int sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, +int set_pairing(socktype_t sock, enum Pairing pairing); +int get_firmware_version(socktype_t sock, char version[VER_STR_LEN]); +int get_serial_number(socktype_t sock, char serial[0x100]); +int get_battery_level(socktype_t sock, unsigned int *level); +int get_device_info(socktype_t sock, bdaddr_t address, struct Device *device); +int get_paired_devices(socktype_t sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, enum DevicesConnected *connected); -int connect_device(int sock, bdaddr_t address); -int disconnect_device(int sock, bdaddr_t address); -int remove_device(int sock, bdaddr_t address); +int connect_device(socktype_t sock, bdaddr_t address); +int disconnect_device(socktype_t sock, bdaddr_t address); +int remove_device(socktype_t sock, bdaddr_t address); #endif diff --git a/bluetooth.c b/bluetooth.c index 33d18e7..937ad94 100644 --- a/bluetooth.c +++ b/bluetooth.c @@ -14,8 +14,8 @@ * Based on code taken from the BlueZ library. */ -int reverse_ba2str(const bdaddr_t *ba, char *str) { - return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", +int reverse_ba2str(const bdaddr_t *ba, char *str, size_t str_len) { + return sprintf_s(str, str_len, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", BDADDR_BYTES(*ba)[0], BDADDR_BYTES(*ba)[1], BDADDR_BYTES(*ba)[2], BDADDR_BYTES(*ba)[3], BDADDR_BYTES(*ba)[4], BDADDR_BYTES(*ba)[5]); } @@ -28,7 +28,7 @@ int reverse_str2ba(const char *str, bdaddr_t *ba) { } for (i = 0; i < 6; i++, str += 3) - BDADDR_BYTES(*ba)[i] = strtol(str, NULL, 16); + BDADDR_BYTES(*ba)[i] = (uint8_t) strtol(str, NULL, 16); return 0; } diff --git a/bluetooth.h b/bluetooth.h index 4d2c986..5f62c94 100644 --- a/bluetooth.h +++ b/bluetooth.h @@ -14,7 +14,7 @@ #define BT_ADDR_LEN 6 -int reverse_ba2str(const bdaddr_t *ba, char *str); +int reverse_ba2str(const bdaddr_t *ba, char *str, size_t str_len); int reverse_str2ba(const char *str, bdaddr_t *ba); #ifdef _WIN32 int bachk(const char *str); diff --git a/main.c b/main.c index 8b9691c..d117bfb 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,4 @@ -#ifdef _WIN32 -#include -#else +#ifndef _WIN32 #include #include #endif @@ -14,14 +12,11 @@ #include #endif +#include "socket.h" #include "based.h" #include "bluetooth.h" #include "util.h" -#ifdef _WIN32 -#define AF_BLUETOOTH AF_BTH -#define BTPROTO_RFCOMM BTHPROTO_RFCOMM -#endif static const char *program_name; @@ -70,7 +65,7 @@ static void usage() { , program_name); } -static int do_set_name(int sock, const char *arg) { +static int do_set_name(socktype_t sock, const char *arg) { char name_buffer[MAX_NAME_LEN + 1] = { 0 }; int status; @@ -78,13 +73,13 @@ static int do_set_name(int sock, const char *arg) { fprintf(stderr, "Name exceeds %d character maximum. Truncating.\n", MAX_NAME_LEN); status = 1; } else { - strncpy(name_buffer, arg, MAX_NAME_LEN); + strncpy_s(name_buffer, MAX_NAME_LEN, arg, MAX_NAME_LEN); status = set_name(sock, name_buffer); } return status; } -static int do_set_prompt_language(int sock, const char *arg) { +static int do_set_prompt_language(socktype_t sock, const char *arg) { enum PromptLanguage pl; if (strcmp(arg, "en") == 0) { @@ -118,7 +113,7 @@ static int do_set_prompt_language(int sock, const char *arg) { return set_prompt_language(sock, pl); } -static int do_set_voice_prompts(int sock, const char *arg) { +static int do_set_voice_prompts(socktype_t sock, const char *arg) { int on; if (strcmp(arg, "on") == 0) { @@ -134,7 +129,7 @@ static int do_set_voice_prompts(int sock, const char *arg) { return set_voice_prompts(sock, on); } -static int do_set_auto_off(int sock, const char *arg) { +static int do_set_auto_off(socktype_t sock, const char *arg) { enum AutoOff ao; int parsed = atoi(arg); @@ -160,7 +155,7 @@ static int do_set_auto_off(int sock, const char *arg) { return set_auto_off(sock, ao); } -static int do_set_noise_cancelling(int sock, const char *arg) { +static int do_set_noise_cancelling(socktype_t sock, const char *arg) { enum NoiseCancelling nc; if (strcmp(arg, "high") == 0) { @@ -191,7 +186,7 @@ static int do_set_noise_cancelling(int sock, const char *arg) { return set_noise_cancelling(sock, nc); } -static int do_get_device_status(int sock) { +static int do_get_device_status(socktype_t sock) { char name[MAX_NAME_LEN + 1]; enum PromptLanguage pl; enum AutoOff ao; @@ -273,7 +268,7 @@ static int do_get_device_status(int sock) { return 0; } -static int do_set_pairing(int sock, const char *arg) { +static int do_set_pairing(socktype_t sock, const char *arg) { enum Pairing p; if (strcmp(arg, "on") == 0) { @@ -289,7 +284,7 @@ static int do_set_pairing(int sock, const char *arg) { return set_pairing(sock, p); } -static int do_get_firmware_version(int sock) { +static int do_get_firmware_version(socktype_t sock) { char version[VER_STR_LEN]; int status = get_firmware_version(sock, version); @@ -301,7 +296,7 @@ static int do_get_firmware_version(int sock) { return 0; } -static int do_get_serial_number(int sock) { +static int do_get_serial_number(socktype_t sock) { char serial[0x100]; int status = get_serial_number(sock, serial); @@ -313,7 +308,7 @@ static int do_get_serial_number(int sock) { return 0; } -static int do_get_battery_level(int sock) { +static int do_get_battery_level(socktype_t sock) { unsigned int level; int status = get_battery_level(sock, &level); @@ -325,7 +320,7 @@ static int do_get_battery_level(int sock) { return 0; } -static int do_get_paired_devices(int sock) { +static int do_get_paired_devices(socktype_t sock) { bdaddr_t devices[MAX_NUM_DEVICES]; size_t num_devices; enum DevicesConnected connected; @@ -357,7 +352,7 @@ static int do_get_paired_devices(int sock) { } char address[18]; - reverse_ba2str(&device.address, address); + reverse_ba2str(&device.address, address, sizeof(address)); char status_symb; switch (device.status) { @@ -380,25 +375,25 @@ static int do_get_paired_devices(int sock) { return 0; } -static int do_connect_device(int sock, const char *arg) { +static int do_connect_device(socktype_t sock, const char *arg) { bdaddr_t address; reverse_str2ba(arg, &address); return connect_device(sock, address); } -static int do_disconnect_device(int sock, const char *arg) { +static int do_disconnect_device(socktype_t sock, const char *arg) { bdaddr_t address; reverse_str2ba(arg, &address); return disconnect_device(sock, address); } -static int do_remove_device(int sock, const char *arg) { +static int do_remove_device(socktype_t sock, const char *arg) { bdaddr_t address; reverse_str2ba(arg, &address); return remove_device(sock, address); } -static int do_get_device_id(int sock) { +static int do_get_device_id(socktype_t sock) { unsigned int device_id; unsigned int index; int status = get_device_id(sock, &device_id, &index); @@ -411,7 +406,7 @@ static int do_get_device_id(int sock) { return 0; } -static int do_send_packet(int sock, const char *arg) { +static int do_send_packet(socktype_t sock, const char *arg) { uint8_t send[sizeof(arg) / 2]; size_t i; for (i = 0; arg[i * 2]; ++i) { @@ -455,31 +450,36 @@ int main(int argc, char *argv[]) { { "send-packet", required_argument, NULL, 1 }, { 0, 0, 0, 0 } }; +#ifdef _WIN32 + WORD version_requested = MAKEWORD(2, 2); + WSADATA wsa_data; + WSAStartup(version_requested, &wsa_data); +#endif - int sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + socktype_t sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); #ifdef _WIN32 -// static const uint32_t send_timeout = 5000; -// if (setsockopt(sock, SOL_RFCOMM, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)) < 0) { -// perror("Could not set socket send timeout"); -// return 1; -// } -// -// static const uint32_t receive_timeout = 1000; -// if (setsockopt(sock, SOL_RFCOMM, SO_RCVTIMEO, &receive_timeout, sizeof(receive_timeout)) < 0) { -// perror("Could not set socket recieve timeout"); -// return 1; -// } + static const DWORD send_timeout = 5000; + if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *) &send_timeout, sizeof(send_timeout)) < 0) { + psockerror("Could not set socket send timeout"); + return 1; + } + + static const DWORD receive_timeout = 1000; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *) &receive_timeout, sizeof(receive_timeout)) < 0) { + psockerror("Could not set socket receive timeout"); + return 1; + } #else static const struct timeval send_timeout = { 5, 0 }; if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &send_timeout, sizeof(send_timeout)) < 0) { - perror("Could not set socket send timeout"); + psockerror("Could not set socket send timeout"); return 1; } static const struct timeval receive_timeout = { 1, 0 }; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &recieve_timeout, sizeof(receive_timeout)) < 0) { - perror("Could not set socket recieve timeout"); + psockerror("Could not set socket recieve timeout"); return 1; } #endif @@ -510,15 +510,15 @@ int main(int argc, char *argv[]) { return 1; } #ifdef _WIN32 - SOCKADDR_BTH address; + SOCKADDR_BTH address = {0}; address.addressFamily = AF_BTH; address.port = BOSE_CHANNEL; - if (str2ba(argv[optind], &address.btAddr) != 0) { + if (str2ba(argv[optind], (BLUETOOTH_ADDRESS_STRUCT *) &address.btAddr) != 0) { fprintf(stderr, "Invalid bluetooth address: %s\n", argv[optind]); return 1; } #else - struct sockaddr_rc address; + struct sockaddr_rc address = {0}; address.rc_family = AF_BLUETOOTH; address.rc_channel = BOSE_CHANNEL; if (str2ba(argv[optind], &address.rc_bdaddr) != 0) { @@ -528,7 +528,7 @@ int main(int argc, char *argv[]) { #endif if (connect(sock, (struct sockaddr *) &address, sizeof(address)) != 0) { - perror("Could not connect to Bluetooth device"); + psockerror("Could not connect to Bluetooth device"); return 1; } @@ -596,7 +596,7 @@ int main(int argc, char *argv[]) { } if (status < 0) { - perror("Error trying to change setting"); + psockerror("Error trying to change setting"); } close(sock); diff --git a/socket.h b/socket.h new file mode 100644 index 0000000..72b32ec --- /dev/null +++ b/socket.h @@ -0,0 +1,29 @@ +// Minimal abstraction layer over WinSock2 / BSD sockets + +#ifndef _SOCKET_H +#define _SOCKET_H + +#ifdef _WIN32 + +#include +#include +#define psockerror(x) do { \ + wchar_t *s = NULL; \ + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&s, 0, NULL); \ + fprintf(stderr, "%s: %S\n", x, s); \ + LocalFree(s); \ + } while (0) +#define close(x) closesocket(x) +typedef SOCKET socktype_t; +#define AF_BLUETOOTH AF_BTH +#define BTPROTO_RFCOMM BTHPROTO_RFCOMM + +#else + +#include +#define psockerror(x) perror(x) +typedef int socktype_t; + +#endif + +#endif /* _SOCKET_H */ From e0a6a28e27d2cefcba008fe75884277462cdf7ef Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Wed, 17 Aug 2022 21:54:44 +0200 Subject: [PATCH 6/9] Added script for analyzing trace --- scripts/analyze_trace.py | 184 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 scripts/analyze_trace.py diff --git a/scripts/analyze_trace.py b/scripts/analyze_trace.py new file mode 100644 index 0000000..279b71e --- /dev/null +++ b/scripts/analyze_trace.py @@ -0,0 +1,184 @@ +import sys +import binascii +import os +import subprocess +import argparse + +PRODUCT_INFO = {0: "FUNCTION_BLOCK_INFO", + 1: "BMAP_VERSION", + 2: "ALL_FUNCTION_BLOCKS", + 3: "PRODUCT_ID_VARIANT", + 4: "GET_ALL_FUNCTIONS", + 5: "FIRMWARE_VERSION", + 6: "MAC_ADDRESS", + 7: "SERIAL_NUMBER", + 10: "HARDWARE_REVISION", + 11: "COMPONENT_DEVICES", + } + +DEVICE_MANAGEMENT = { + 0: "FUNCTION_BLOCK_INFO", + 1: "CONNECT", + 2: "DISCONNECT", + 3: "REMOVE_DEVICE", + 4: "LIST_DEVICES", + 5: "INFO", + 6: "EXTENDED_INFO", + 7: "CLEAR_DEVICE_LIST", + 8: "PAIRING_MODE", + 9: "LOCAL_MAC_ADDRESS", + 10: "PREPARE_P2P", + 11: "P2P_MODE", + 12: "ROUTING", +} + +AUDIO_MANAGEMENT = {0: "FUNCTION_BLOCK_INFO", +1: "SOURCE", +2: "GET_ALL", +3: "CONTROL", +4: "STATUS", +5: "VOLUME", +6: "NOW_PLAYING", +} + +SETTINGS = { +0: "FUNCTION_BLOCK_INFO", +1: "GET_ALL", +2: "PRODUCT_NAME", +3: "VOICE_PROMPTS", +4: "STANDBY_TIMER", +5: "CNC", +6: "ANR", +7: "BASS_CONTROL", +8: "ALERTS", +9: "BUTTONS", +10: "MULTIPOINT", +11: "SIDETONE", +21: "IMU_VOLUME_CONTROL", +} + +STATUS = { +0: "FUNCTION_BLOCK_INFO", +1: "GET_ALL_FUNCTIONS", +2: "BATTERY_LEVEL", +3: "AUX_CABLE_DETECTION", +4: "MIC_LEVEL", +5: "CHARGER_DETECT", +} + +CONTROL = { +0: "FUNCTION_BLOCK_INFO", +1: "GET_ALL", +2: "CHIRP", +} + +VPA = { +0: "FUNCTION_BLOCK_INFO", +1: "GET_ALL", +2: "SUPPORTED_VPAS", +} + +FUNCTION_BLOCKS = { + 0: ("PRODUCT_INFO", PRODUCT_INFO), + 1: ("SETTINGS", SETTINGS), + 2: ("STATUS", STATUS), + 3: ("FIRMWARE_UPDATE", {}), + 4: ("DEVICE_MANAGEMENT", DEVICE_MANAGEMENT), + 5: ("AUDIO_MANAGEMENT", AUDIO_MANAGEMENT), + 6: ("CALL_MANAGEMENT", {}), + 7: ("CONTROL", CONTROL), + 8: ("DEBUG", {}), + 9: ("NOTIFICATION", {}), + 10: ("RESERVED_BOSEBUILD_1", {}), + 11: ("RESERVED_BOSEBUILD_2", {}), + 12: ("HEARING_ASSISTANCE", {}), + 13: ("DATA_COLLECTION", {}), + 14: ("HEART_RATE", {}), + 16: ("VPA", VPA), + 21: ("AUGMENTED_REALITY", {}), +} + +OPERATORS = { +0: "SET", +1: "GET", +2: "SET_GET", +3: "STATUS", +4: "ERROR", +5: "START", +6: "RESULT", +7: "PROCESSING", +} + +ERRORS = { + 1: ("LENGTH", "Invalid length"), + 2: ("CHKSUM", "Invalid Checksum"), + 3: ("FBLOCK_NOT_SUPP", "FBlock not supported"), + 4: ("FUNC_NOT_SUPP", "Function not supported"), + 5: ("OP_NOT_SUPP", "Operator is not supported for that function."), + 6: ("INVALID_DATA", "Data values sent to headset are incorrect."), + 7: ("DATA_UNAVAILABLE", "Requested data is not available"), + 8: ("RUNTIME", "Failure to read/write the information requested that is temporary."), + 9: ("TIMEOUT", "Timeout related errors."), + 10: ("INVALID_STATE", "Action requested is not applicable to the current state."), + 11: ("DEVICE_NOT_FOUND", "Device not found in Paired Device List"), + 12: ("BUSY", "Device is busy to service the BMAP message"), + 13: ("NOCONN_TIMEOUT", "Soundlink device fails to connect to a device in the Paired Device List"), + 14: ("NOCONN_KEY", "Soundlink device fails to connect to a device because the pairing information has been deleted from the source device."), + 15: ("OTA_UPDATE", "OTA firmware update cannot be initialized because an update is already in progress"), + 16: ("OTA_LOW_BATT", "OTA firmware update cannot be initialized because product battery voltage is too low"), + 17: ("OTA_NO_CHARGER", "OTA firmware update cannot be applied because charger is not connected"), + -1: ("FBLOCK_SPECIFIC", "Error code is Function Block specific and an extra byte will be included in the payload to differentiate between different FBlock specific error codes. Refer to the respective FBlock section for a list of error codes for that particular FBlock."), +} + +TSHARK_WINDOWS = r'C:\Program Files\Wireshark\tshark.exe' +TSHARK = TSHARK_WINDOWS if os.path.exists(TSHARK_WINDOWS) else "tshark" + +def parse_packet(p): + try: + return ((p[0], p[1], p[2], p[4: 4 + p[3]]), p[4 + p[3]:]) + except IndexError: + return (None, b'') + +def parse_packets(p): + rest = p + while rest: + (p, rest) = parse_packet(rest) + yield p + + +def parse_packets_readable(p): + for p in parse_packets(p): + if p is None: + yield None + else: + yield (f"{FUNCTION_BLOCKS[p[0]][0]} ({p[0]})", \ + f"{FUNCTION_BLOCKS[p[0]][1].get(p[1], 'UNKNOWN')} ({p[1]})", \ + f"{OPERATORS.get(p[2], 'UNKNOWN')} ({p[2]})", \ + f"{ERRORS[p[3][0]]} ({p[3][0]})" if p[2] == 4 and len(p[3]) == 1 else p[3]) + + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("tracefile", help = "Wireshark pcap file") + return parser.parse_args() + + +def main(args): + proc = subprocess.run((TSHARK, "-r", args.tracefile, "-e", "hci_h4.direction", "-e", "btspp.data", "-Tfields"), capture_output = True) + + text = proc.stdout.decode(encoding = "ascii").replace("\r\n", "\n") + + a = [x.split("\t") for x in text.split("\n") if len(x.split("\t")) > 1 and x.split("\t")[1]] + b = [(x[0], binascii.unhexlify(x[1])) for x in a] + c = [x[1] for x in b if x[0] == '0x00'] + #d = [(FUNCTION_BLOCKS[y[0]][0], FUNCTION_BLOCKS[y[0]][0].get(y[1], ""), y[2], y[3]) for y in parse_packets(x[1][0]) if x[0] == '0x00' else x[1] for x in b] + d = [("=>" if x[0] == '0x00' else "<=", list(parse_packets_readable(x[1]))) for x in b] + + for x in d: + print(x) + + +if __name__ == "__main__": + main(parse_args()) + From 81638017dd2d6baa2233ee21e7321229b39bc446 Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Thu, 18 Aug 2022 21:08:59 +0200 Subject: [PATCH 7/9] Implemented music share connect --- README.txt | 3 ++- based.c | 15 +++++++++++++++ based.h | 4 +++- main.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index 1c30fe6..6a61126 100644 --- a/README.txt +++ b/README.txt @@ -105,7 +105,8 @@ On Windows, use Get-PnpDevice -class Bluetooth | Select-Object -Property FriendlyName, DeviceID ``` -to enumerate the Bluetooth device ID. +to enumerate the Bluetooth device ID. The device ID needs to be written as +AA:BB:CC:DD:EE:FF. Dependencies ------------ diff --git a/based.c b/based.c index 23bf923..104ff89 100644 --- a/based.c +++ b/based.c @@ -18,6 +18,12 @@ #define ANY 0x00 #define CN_BASE_PACK_LEN 4 +#define FUNCTION_BLOCK_DEVICE_MANAGEMENT 0x04 + +#define DEVICE_MANAGEMENT_CONNECT 0x01 + +#define OPERATOR_START 0x05 + int has_noise_cancelling(unsigned int device_id) { switch (device_id) { case 0x4014: @@ -510,6 +516,15 @@ int connect_device(socktype_t sock, bdaddr_t address) { return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); } +int connect_music_share(socktype_t sock, bdaddr_t puppet_address, bdaddr_t master_address) { + static uint8_t send_buf[5 + 2 * BT_ADDR_LEN] = { FUNCTION_BLOCK_DEVICE_MANAGEMENT, DEVICE_MANAGEMENT_CONNECT, OPERATOR_START, BT_ADDR_LEN * 2 + 1, 0x10 }; + static uint8_t ack[10] = { 0x04, 0x01, 0x07, BT_ADDR_LEN }; + memcpy(&send_buf[5], &BDADDR_BYTES(puppet_address), BT_ADDR_LEN); + memcpy(&send_buf[5 + BT_ADDR_LEN], &BDADDR_BYTES(master_address), BT_ADDR_LEN); + memcpy(&ack[4], &BDADDR_BYTES(puppet_address), BT_ADDR_LEN); + return write_check(sock, send_buf, sizeof(send_buf), ack, sizeof(ack)); +} + int disconnect_device(socktype_t sock, bdaddr_t address) { static uint8_t send_buf[10] = { 0x04, 0x02, 0x05, BT_ADDR_LEN }; static uint8_t ack[10] = { 0x04, 0x02, 0x07, BT_ADDR_LEN }; diff --git a/based.h b/based.h index 00e7793..f9c4f8c 100644 --- a/based.h +++ b/based.h @@ -56,7 +56,8 @@ enum Pairing { enum DeviceStatus { DS_THIS = 0x03, DS_CONNECTED = 0x01, - DS_DISCONNECTED = 0x00 + DS_DISCONNECTED = 0x00, + DS_MUSICSHARE = 0x45 }; enum DevicesConnected { @@ -97,6 +98,7 @@ int get_device_info(socktype_t sock, bdaddr_t address, struct Device *device); int get_paired_devices(socktype_t sock, bdaddr_t addresses[MAX_NUM_DEVICES], size_t *num_devices, enum DevicesConnected *connected); int connect_device(socktype_t sock, bdaddr_t address); +int connect_music_share(socktype_t sock, bdaddr_t address, bdaddr_t own_address); int disconnect_device(socktype_t sock, bdaddr_t address); int remove_device(socktype_t sock, bdaddr_t address); diff --git a/main.c b/main.c index 0f51c14..46dca3f 100644 --- a/main.c +++ b/main.c @@ -54,8 +54,11 @@ static void usage() { "\t\tPrint the devices currently connected to the device.\n" "\t\t!: indicates the current device\n" "\t\t*: indicates other connected devices\n" + "\t\tS: indicates a device that music is shared to\n" "\t--connect-device=
\n" "\t\tAttempt to connect to the device at address.\n" + "\t--connect-music-share=
\n" + "\t\tAttempt to connect to the device at address and share music.\n" "\t--disconnect-device=
\n" "\t\tDisconnect the device at address.\n" "\t--remove-device=
\n" @@ -399,6 +402,9 @@ static int do_get_paired_devices(socktype_t sock) { case DS_DISCONNECTED: status_symb = ' '; break; + case DS_MUSICSHARE: + status_symb = 'S'; + break; default: return 1; } @@ -415,6 +421,25 @@ static int do_connect_device(socktype_t sock, const char *arg) { return connect_device(sock, address); } +static int do_connect_music_share(socktype_t sock, const char *arg) { + bdaddr_t master_address = {0}; + bdaddr_t puppet_address = {0}; + const char *master_address_str = strchr(arg, ','); + char puppet_address_str[BT_ADDR_LEN * 3]; + if (master_address_str != NULL && *master_address_str != '\0' && (master_address_str - arg) <= BT_ADDR_LEN * 3) { + strncpy_s(puppet_address_str, sizeof(puppet_address_str), arg, sizeof(puppet_address_str) - 1); + puppet_address_str[sizeof(puppet_address_str) - 1] = 0; + reverse_str2ba(puppet_address_str, &puppet_address); + reverse_str2ba(master_address_str + 1, &master_address); + return connect_music_share(sock, puppet_address, master_address); + } + else { + fprintf(stderr, "Invalid music share argument: Argument must be given as \",\"\n"); + return 1; + } +} + + static int do_disconnect_device(socktype_t sock, const char *arg) { bdaddr_t address; reverse_str2ba(arg, &address); @@ -478,6 +503,7 @@ int main(int argc, char *argv[]) { { "battery-level", no_argument, NULL, 'b' }, { "paired-devices", no_argument, NULL, 'a' }, { "connect-device", required_argument, NULL, 2 }, + { "connect-music-share", required_argument, NULL, 6 }, { "disconnect-device", required_argument, NULL, 3 }, { "remove-device", required_argument, NULL, 4 }, { "device-id", no_argument, NULL, 5 }, @@ -485,6 +511,7 @@ int main(int argc, char *argv[]) { { "send-packet", required_argument, NULL, 1 }, { 0, 0, 0, 0 } }; + #ifdef _WIN32 WORD version_requested = MAKEWORD(2, 2); WSADATA wsa_data; @@ -616,6 +643,9 @@ int main(int argc, char *argv[]) { case 2: status = do_connect_device(sock, optarg); break; + case 6: + status = do_connect_music_share(sock, optarg); + break; case 3: status = do_disconnect_device(sock, optarg); break; From 1c457490ea55b4e79227f401eb13b87b0ea1d132 Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Tue, 23 Aug 2022 21:20:25 +0200 Subject: [PATCH 8/9] Added README for dissector script --- scripts/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 scripts/README.md diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..f758702 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,4 @@ +# Scripts + +## analyze\_trace.py +This is a dissector for recorded bluetooth PCAP files. Record your trace on an Android phone by activating the "HCI snoop log" in developer mode ([described here](https://source.android.com/docs/core/bluetooth/verifying_debugging#debugging-with-logs)). Then pull the bugreport with `adb bugreport my-bugreport.zip` and get the bluetooth log files from `FS/data/misc/bluetooth/logs` in the zip. I imported the first `.cfa` file into Wireshark and then added the others with Wireshark's `Merge ...` menu option. Save the PCAP, and call the python dissector script on it. Known messages will be decoded as far as the protocol is known, so that the traffic is easier to read. From 2fe41bbedc923c7947e6c5e07215759a244170cf Mon Sep 17 00:00:00 2001 From: Jonas Zaddach Date: Tue, 23 Aug 2022 23:14:29 +0200 Subject: [PATCH 9/9] Small corrections --- README.txt | 10 ++++++++-- based.h | 1 + main.c | 6 ++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.txt b/README.txt index 6a61126..dd4c2e3 100644 --- a/README.txt +++ b/README.txt @@ -55,9 +55,15 @@ Options: Print the devices currently connected to the device. !: indicates the current device *: indicates other connected devices + S: indicates a device that music is shared to - --connect-device=
- Attempt to connect to the device at address. + --connect-device=
+ Attempt to connect to the device at address. + + --connect-music-share=, + Attempt to connect to the puppet device at address + (secondary headphones) and share music from source + address (computer). --disconnect-device=
Disconnect the device at address. diff --git a/based.h b/based.h index f9c4f8c..790908d 100644 --- a/based.h +++ b/based.h @@ -90,6 +90,7 @@ int set_noise_cancelling(socktype_t sock, enum NoiseCancelling level); int get_device_status(socktype_t sock, char name[MAX_NAME_LEN + 1], enum PromptLanguage *language, enum AutoOff *minutes, enum NoiseCancelling *level); int set_pairing(socktype_t sock, enum Pairing pairing); +int set_self_voice(socktype_t sock, enum SelfVoice selfvoice); int get_firmware_version(socktype_t sock, char version[VER_STR_LEN]); int get_firmware_version(socktype_t sock, char version[VER_STR_LEN]); int get_serial_number(socktype_t sock, char serial[0x100]); diff --git a/main.c b/main.c index 46dca3f..a2891c9 100644 --- a/main.c +++ b/main.c @@ -57,8 +57,10 @@ static void usage() { "\t\tS: indicates a device that music is shared to\n" "\t--connect-device=
\n" "\t\tAttempt to connect to the device at address.\n" - "\t--connect-music-share=
\n" - "\t\tAttempt to connect to the device at address and share music.\n" + "\t--connect-music-share=,\n" + "\t\tAttempt to connect to the puppet device at address\n" + "\t\t(secondary headphones) and share music from source\n" + "\t\taddress (computer).\n" "\t--disconnect-device=
\n" "\t\tDisconnect the device at address.\n" "\t--remove-device=
\n"