From: Prathibha Madugonde <quic_prathm@xxxxxxxxxxx> Fix for below Test Cases: GAP/SEC/SEM/BV-56-C GAP/SEC/SEM/BV-57-C GAP/SEC/SEM/BV-58-C GAP/SEC/SEM/BV-59-C GAP/SEC/SEM/BV-60-C GAP/SEC/SEM/BV-61-C For all above test cases, PTS tool is adding Battery Level Characteristics in the GAP service. And PTS is expecting to write value to Battery Level Characteristics. When IUT and PTS are connected from bluetoothctl tool, GAP service and its characterisitics are not showing in the bluetoothctl terminal. Therefore need to use other existing tools, here we used btgatt-client tool. For GAP/SEC/SEM/BV-56-C , GAP/SEC/SEM/BV-57-C, GAP/SEC/SEM/BV-58-C test cases the IUT should be in peripheral mode(advertise and accept connection) and GATT client role as per GAP.TS.p44. Added peripheral mode in the btgatt-client tool for PASSING those test cases. Signed-off-by: Prathibha Madugonde <quic_prathm@xxxxxxxxxxx> --- tools/btgatt-client.c | 97 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 6 deletions(-) diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c index b47914da3..2b732e454 100644 --- a/tools/btgatt-client.c +++ b/tools/btgatt-client.c @@ -36,6 +36,8 @@ #include "src/shared/gatt-helpers.h" #define ATT_CID 4 +#define CENTRAL_MODE 1 +#define PERIPHERAL_MODE 2 #define PRLOG(...) \ printf(__VA_ARGS__); print_prompt(); @@ -1633,6 +1635,68 @@ static void signal_cb(int signum, void *user_data) } } +static int l2cap_le_att_listen_and_accept(bdaddr_t *src, int sec, + uint8_t src_type) +{ + int sk, nsk; + struct sockaddr_l2 srcaddr, addr; + socklen_t optlen; + struct bt_security btsec; + char ba[18]; + + sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (sk < 0) { + perror("Failed to create L2CAP socket"); + return -1; + } + + /* Set up source address */ + memset(&srcaddr, 0, sizeof(srcaddr)); + srcaddr.l2_family = AF_BLUETOOTH; + srcaddr.l2_cid = htobs(ATT_CID); + srcaddr.l2_bdaddr_type = src_type; + bacpy(&srcaddr.l2_bdaddr, src); + + if (bind(sk, (struct sockaddr *) &srcaddr, sizeof(srcaddr)) < 0) { + perror("Failed to bind L2CAP socket"); + goto fail; + } + + /* Set the security level */ + memset(&btsec, 0, sizeof(btsec)); + btsec.level = sec; + if (setsockopt(sk, SOL_BLUETOOTH, BT_SECURITY, &btsec, + sizeof(btsec)) != 0) { + fprintf(stderr, "Failed to set L2CAP security level\n"); + goto fail; + } + + if (listen(sk, 10) < 0) { + perror("Listening on socket failed"); + goto fail; + } + + printf("Started listening on ATT channel. Waiting for connections\n"); + + memset(&addr, 0, sizeof(addr)); + optlen = sizeof(addr); + nsk = accept(sk, (struct sockaddr *) &addr, &optlen); + if (nsk < 0) { + perror("Accept failed"); + goto fail; + } + + ba2str(&addr.l2_bdaddr, ba); + printf("Connect from %s\n", ba); + close(sk); + + return nsk; + +fail: + close(sk); + return -1; +} + static int l2cap_le_att_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type, int sec) { @@ -1709,6 +1773,7 @@ static void usage(void) printf("Options:\n" "\t-i, --index <id>\t\tSpecify adapter index, e.g. hci0\n" "\t-d, --dest <addr>\t\tSpecify the destination address\n" + "\t-p, --peripheral mode\t\t\tStar Listening on Att Channel\n" "\t-t, --type [random|public] \tSpecify the LE address type\n" "\t-m, --mtu <mtu> \t\tThe ATT MTU to use\n" "\t-s, --security-level <sec> \tSet security level (low|medium|" @@ -1720,6 +1785,7 @@ static void usage(void) static struct option main_options[] = { { "index", 1, 0, 'i' }, { "dest", 1, 0, 'd' }, + { "peripheral", 1, 0, 'p' }, { "type", 1, 0, 't' }, { "mtu", 1, 0, 'm' }, { "security-level", 1, 0, 's' }, @@ -1738,9 +1804,10 @@ int main(int argc, char *argv[]) bdaddr_t src_addr, dst_addr; int dev_id = -1; int fd; + int peri_cent = CENTRAL_MODE; struct client *cli; - while ((opt = getopt_long(argc, argv, "+hvs:m:t:d:i:", + while ((opt = getopt_long(argc, argv, "+hvs:m:t:d:p:i:", main_options, NULL)) != -1) { switch (opt) { case 'h': @@ -1809,6 +1876,17 @@ int main(int argc, char *argv[]) } break; + case 'p': + if (strcmp(optarg, "peripheral") == 0) + peri_cent = PERIPHERAL_MODE; + else if (strcmp(optarg, "central") == 0) + peri_cent = CENTRAL_MODE; + else { + fprintf(stderr, + "Allowed Modes: peripheral, central\n"); + return EXIT_FAILURE; + } + break; default: fprintf(stderr, "Invalid option: %c\n", opt); return EXIT_FAILURE; @@ -1836,14 +1914,21 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!dst_addr_given) { - fprintf(stderr, "Destination address required!\n"); - return EXIT_FAILURE; - } + if(peri_cent == CENTRAL_MODE) + { + if (!dst_addr_given) { + fprintf(stderr, "Destination address required!\n"); + return EXIT_FAILURE; + } + + } mainloop_init(); - fd = l2cap_le_att_connect(&src_addr, &dst_addr, dst_type, sec); + if(peri_cent == CENTRAL_MODE) + fd = l2cap_le_att_connect(&src_addr, &dst_addr, dst_type, sec); + else + fd = l2cap_le_att_listen_and_accept(&src_addr, sec, BDADDR_LE_PUBLIC); if (fd < 0) return EXIT_FAILURE; -- 2.17.1