diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index 30e8e50..008cc9f 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
#include <bluetooth/l2cap.h>
#include "monitor/mainloop.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-client.h"
#define ATT_CID 4
+#define PRLOG(format, ...) \
+ printf(format, __VA_ARGS__); print_prompt();
+
static bool verbose = false;
+struct client {
+ int fd;
+ struct bt_gatt_client *gatt;
+};
+
static void print_prompt(void)
{
printf("[GATT client]# ");
fflush(stdout);
}
+static void att_disconnect_cb(void *user_data)
+{
+ printf("Device disconnected\n");
+
+ mainloop_quit();
+}
+
+static void att_debug(const char *str, void *user_data)
+{
+ const char *prefix = user_data;
+
+ PRLOG("%s%s\n", prefix, str);
+}
+
+static struct client *client_create(int fd, uint16_t mtu)
+{
+ struct client *cli;
+ struct bt_att *att;
+
+ cli = new0(struct client, 1);
+ if (!cli) {
+ fprintf(stderr, "Failed to allocate memory for client\n");
+ return NULL;
+ }
+
+ att = bt_att_new(fd);
+ if (!att) {
+ fprintf(stderr, "Failed to initialze ATT transport layer\n");
+ bt_att_unref(att);
+ free(cli);
+ return NULL;
+ }
+
+ if (!bt_att_set_close_on_unref(att, true)) {
+ fprintf(stderr, "Failed to set up ATT transport layer\n");
+ bt_att_unref(att);
+ free(cli);
+ return NULL;
+ }
+
+ if (!bt_att_register_disconnect(att, att_disconnect_cb, NULL, NULL)) {
+ fprintf(stderr, "Failed to set ATT disconnect handler\n");
+ bt_att_unref(att);
+ free(cli);
+ return NULL;
+ }
+
+ if (verbose)
+ bt_att_set_debug(att, att_debug, "att: ", NULL);
+
+ cli->fd = fd;
+ cli->gatt = bt_gatt_client_new(att, mtu);
+ if (!cli->gatt) {
+ fprintf(stderr, "Failed to create GATT client\n");
+ bt_att_unref(att);
+ free(cli);
+ return NULL;
+ }
+
+ /* bt_gatt_client already holds a reference */
+ bt_att_unref(att);
+
+ return cli;
+}
+
+static void client_destroy(struct client *cli)
+{
+ bt_gatt_client_unref(cli->gatt);
+}
+
static void prompt_read_cb(int fd, uint32_t events, void *user_data)
{
size_t len = 0;
free(line);
}
+static void signal_cb(int signum, void *user_data)
+{
+ switch (signum) {
+ case SIGINT:
+ case SIGTERM:
+ mainloop_quit();
+ break;
+ default:
+ break;
+ }
+}
+
static int l2cap_le_att_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t dst_type,
int sec)
{
ba2str(src, srcaddr_str);
ba2str(dst, dstaddr_str);
- printf("Opening L2CAP LE connection on ATT channel:\n"
- "\t src: %s\n\tdest: %s\n",
- srcaddr_str, dstaddr_str);
+ printf("btgatt-client: Opening L2CAP LE connection on ATT "
+ "channel:\n\t src: %s\n\tdest: %s\n",
+ srcaddr_str, dstaddr_str);
}
sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
bdaddr_t src_addr, dst_addr;
int dev_id = -1;
int fd;
+ sigset_t mask;
+ struct client *cli;
while ((opt = getopt_long(argc, argv, "+hvs:m:t:d:i:",
main_options, NULL)) != -1) {
if (fd < 0)
return EXIT_FAILURE;
+ cli = client_create(fd, mtu);
+ if (!cli) {
+ close(fd);
+ return EXIT_FAILURE;
+ }
+
if (mainloop_add_fd(fileno(stdin),
EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR,
prompt_read_cb, NULL, NULL) < 0) {
return EXIT_FAILURE;
}
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+
+ mainloop_set_signal(&mask, signal_cb, NULL, NULL);
+
print_prompt();
mainloop_run();
+ printf("\n\nShutting down...\n");
+
+ client_destroy(cli);
+
return EXIT_SUCCESS;
}