2012-07-09 21:10:23

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 01/14] input: remove unneeded header inclusions

From: Gustavo Padovan <[email protected]>

---
input/device.c | 5 -----
input/fakehid.c | 4 ----
input/manager.c | 3 ---
3 files changed, 12 deletions(-)

diff --git a/input/device.c b/input/device.c
index 7eac71e..829ca03 100644
--- a/input/device.c
+++ b/input/device.c
@@ -29,9 +29,6 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hidp.h>
@@ -39,8 +36,6 @@
#include <bluetooth/sdp_lib.h>
#include <bluetooth/uuid.h>

-#include <glib.h>
-#include <dbus/dbus.h>
#include <gdbus.h>

#include "log.h"
diff --git a/input/fakehid.c b/input/fakehid.c
index 3181538..3be1489 100644
--- a/input/fakehid.c
+++ b/input/fakehid.c
@@ -25,12 +25,8 @@
#include <config.h>
#endif

-#include <stdio.h>
-#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>

#include <bluetooth/bluetooth.h>

diff --git a/input/manager.c b/input/manager.c
index 01f83ce..928a2f5 100644
--- a/input/manager.c
+++ b/input/manager.c
@@ -28,13 +28,10 @@
#include <errno.h>

#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/uuid.h>

-#include <gdbus.h>
-
#include "log.h"
#include "../src/adapter.h"
#include "../src/device.h"
--
1.7.10.2



2012-07-10 02:36:48

by Vinicius Costa Gomes

[permalink] [raw]
Subject: Re: [PATCH 03/14] btmgmt: move to tools folder

Hi Gustavo,

On 18:10 Mon 09 Jul, Gustavo Padovan wrote:
> From: Gustavo Padovan <[email protected]>
>
> ---
> .gitignore | 2 +-
> Makefile.tools | 6 +-
> mgmt/main.c | 1933 --------------------------------------------------------
> 3 files changed, 4 insertions(+), 1937 deletions(-)
> delete mode 100644 mgmt/main.c

It may be that I am missing something, but this doesn't look like a move.

>
> diff --git a/.gitignore b/.gitignore
> index c7d079e..bc65dcf 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -86,7 +86,7 @@ compat/dund
> compat/hidd
> compat/pand
> unit/test-eir
> -mgmt/btmgmt
> +tools/mgmt/btmgmt

Wouldn't it be just "tools/btmgmt"?

> monitor/btmon
> emulator/btvirt
>
> diff --git a/Makefile.tools b/Makefile.tools
> index 3cb105c..56839b7 100644
> --- a/Makefile.tools
> +++ b/Makefile.tools
> @@ -50,10 +50,10 @@ tools_ppporc_LDADD = lib/libbluetooth-private.la
>
> tools_hcieventmask_LDADD = lib/libbluetooth-private.la
>
> -noinst_PROGRAMS += mgmt/btmgmt monitor/btmon emulator/btvirt
> +noinst_PROGRAMS += tools/btmgmt monitor/btmon emulator/btvirt
>
> -mgmt_btmgmt_SOURCES = mgmt/main.c src/glib-helper.c
> -mgmt_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
> +tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c
> +tools_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
>
> monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
> monitor/mainloop.h monitor/mainloop.c \
> diff --git a/mgmt/main.c b/mgmt/main.c
> deleted file mode 100644
> index b2d6c3c..0000000
> --- a/mgmt/main.c
> +++ /dev/null
> @@ -1,1933 +0,0 @@
> -/*
> - * BlueZ - Bluetooth protocol stack for Linux
> - *
> - * Copyright (C) 2011 Intel Corporation. All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> - *
> - */
> -
> -#ifdef HAVE_CONFIG_H
> -#include <config.h>
> -#endif
> -
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <unistd.h>
> -#include <errno.h>
> -#include <string.h>
> -#include <sys/types.h>
> -#include <sys/socket.h>
> -#include <poll.h>
> -#include <getopt.h>
> -#include <stdbool.h>
> -
> -#include <bluetooth/bluetooth.h>
> -#include <bluetooth/hci.h>
> -#include <bluetooth/hci_lib.h>
> -#include <bluetooth/sdp.h>
> -#include <bluetooth/sdp_lib.h>
> -#include <bluetooth/mgmt.h>
> -
> -#include <glib.h>
> -#include "glib-helper.h"
> -
> -static bool monitor = false;
> -static bool discovery = false;
> -static bool resolve_names = true;
> -
> -typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data);
> -
> -static struct pending_cmd {
> - uint16_t op;
> - uint16_t id;
> - cmd_cb cb;
> - void *user_data;
> - struct pending_cmd *next;
> -} *pending = NULL;
> -
> -static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
> - size_t len, cmd_cb func, void *user_data)
> -{
> - char buf[1024];
> - struct pending_cmd *cmd;
> - struct mgmt_hdr *hdr = (void *) buf;
> -
> - if (len + MGMT_HDR_SIZE > sizeof(buf))
> - return -EINVAL;
> -
> - cmd = calloc(1, sizeof(struct pending_cmd));
> - if (cmd == NULL)
> - return -errno;
> -
> - cmd->op = op;
> - cmd->id = id;
> - cmd->cb = func;
> - cmd->user_data = user_data;
> -
> - memset(buf, 0, sizeof(buf));
> - hdr->opcode = htobs(op);
> - hdr->index = htobs(id);
> - hdr->len = htobs(len);
> - memcpy(buf + MGMT_HDR_SIZE, data, len);
> -
> - if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
> - fprintf(stderr, "Unable to write to socket: %s\n",
> - strerror(errno));
> - free(cmd);
> - return -1;
> - }
> -
> - cmd->next = pending;
> - pending = cmd;
> -
> - return 0;
> -}
> -
> -static int mgmt_open(void)
> -{
> - struct sockaddr_hci addr;
> - int sk;
> -
> - sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
> - if (sk < 0) {
> - fprintf(stderr, "socket: %s\n", strerror(errno));
> - return sk;
> - }
> -
> - memset(&addr, 0, sizeof(addr));
> - addr.hci_family = AF_BLUETOOTH;
> - addr.hci_dev = HCI_DEV_NONE;
> - addr.hci_channel = HCI_CHANNEL_CONTROL;
> -
> - if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> - fprintf(stderr, "bind: %s\n", strerror(errno));
> - close(sk);
> - return -1;
> - }
> -
> - return sk;
> -}
> -
> -static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
> - uint16_t status, void *data, uint16_t len)
> -{
> - struct pending_cmd *c, *prev;
> -
> - for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
> - if (c->op != op)
> - continue;
> - if (c->id != index)
> - continue;
> -
> - if (c == pending)
> - pending = c->next;
> - else
> - prev->next = c->next;
> -
> - c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
> -
> - free(c);
> - break;
> - }
> -}
> -
> -static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_cmd_complete *ev, uint16_t len)
> -{
> - uint16_t op;
> -
> - if (len < sizeof(*ev)) {
> - fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
> - len);
> - return -EINVAL;
> - }
> -
> - op = bt_get_le16(&ev->opcode);
> -
> - len -= sizeof(*ev);
> -
> - if (monitor)
> - printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
> - op, len);
> -
> - mgmt_check_pending(mgmt_sk, op, index, ev->status, ev->data, len);
> -
> - return 0;
> -}
> -
> -static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_cmd_status *ev, uint16_t len)
> -{
> - uint16_t opcode;
> -
> - if (len < sizeof(*ev)) {
> - fprintf(stderr, "Too short (%u bytes) cmd status event\n",
> - len);
> - return -EINVAL;
> - }
> -
> - opcode = bt_get_le16(&ev->opcode);
> -
> - if (monitor)
> - printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
> - opcode, ev->status, mgmt_errstr(ev->status));
> -
> - if (ev->status != 0)
> - mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
> - NULL, 0);
> -
> - return 0;
> -}
> -
> -static int mgmt_controller_error(uint16_t index,
> - struct mgmt_ev_controller_error *ev,
> - uint16_t len)
> -{
> - if (len < sizeof(*ev)) {
> - fprintf(stderr,
> - "Too short (%u bytes) controller error event\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor)
> - printf("hci%u error 0x%02x\n", index, ev->error_code);
> -
> - return 0;
> -}
> -
> -static int mgmt_index_added(int mgmt_sk, uint16_t index)
> -{
> - if (monitor)
> - printf("hci%u added\n", index);
> - return 0;
> -}
> -
> -static int mgmt_index_removed(int mgmt_sk, uint16_t index)
> -{
> - if (monitor)
> - printf("hci%u removed\n", index);
> - return 0;
> -}
> -
> -static const char *settings_str[] = {
> - "powered",
> - "connectable",
> - "fast-connectable",
> - "discoverable",
> - "pairable",
> - "link-security",
> - "ssp",
> - "br/edr",
> - "hs",
> - "le" ,
> -};
> -
> -static void print_settings(uint32_t settings)
> -{
> - unsigned i;
> -
> - for (i = 0; i < NELEM(settings_str); i++) {
> - if ((settings & (1 << i)) != 0)
> - printf("%s ", settings_str[i]);
> - }
> -}
> -
> -static int mgmt_new_settings(int mgmt_sk, uint16_t index,
> - uint32_t *ev, uint16_t len)
> -{
> - if (len < sizeof(*ev)) {
> - fprintf(stderr, "Too short new_settings event (%u)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - printf("hci%u new_settings: ", index);
> - print_settings(bt_get_le32(ev));
> - printf("\n");
> - }
> -
> - return 0;
> -}
> -
> -static int mgmt_discovering(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_discovering *ev, uint16_t len)
> -{
> - if (len < sizeof(*ev)) {
> - fprintf(stderr, "Too short (%u bytes) discovering event\n",
> - len);
> - return -EINVAL;
> - }
> -
> - if (ev->discovering == 0 && discovery)
> - exit(EXIT_SUCCESS);
> -
> - if (monitor)
> - printf("hci%u type %u discovering %s\n", index,
> - ev->type, ev->discovering ? "on" : "off");
> -
> - return 0;
> -}
> -
> -static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_new_link_key *ev, uint16_t len)
> -{
> -
> - if (len != sizeof(*ev)) {
> - fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
> - len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->key.addr.bdaddr, addr);
> - printf("hci%u new_link_key %s type 0x%02x pin_len %d "
> - "store_hint %u\n", index, addr, ev->key.type,
> - ev->key.pin_len, ev->store_hint);
> - }
> -
> - return 0;
> -}
> -
> -static const char *typestr(uint8_t type)
> -{
> - const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
> -
> - if (type <= BDADDR_LE_RANDOM)
> - return str[type];
> -
> - return "(unknown)";
> -}
> -
> -static int mgmt_connected(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_device_connected *ev,
> - uint16_t len)
> -{
> - uint16_t eir_len;
> -
> - if (len < sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid connected event length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - eir_len = bt_get_le16(&ev->eir_len);
> - if (len != sizeof(*ev) + eir_len) {
> - fprintf(stderr, "Invalid connected event length "
> - "(%u bytes, eir_len %u bytes)\n", len, eir_len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->addr.bdaddr, addr);
> - printf("hci%u %s type %s connected eir_len %u\n", index, addr,
> - typestr(ev->addr.type), eir_len);
> - }
> -
> - return 0;
> -}
> -
> -static int mgmt_disconnected(int mgmt_sk, uint16_t index,
> - struct mgmt_addr_info *ev, uint16_t len)
> -{
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid disconnected event length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->bdaddr, addr);
> - printf("hci%u %s type %s disconnected\n", index, addr,
> - typestr(ev->type));
> - }
> -
> - return 0;
> -}
> -
> -static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_connect_failed *ev,
> - uint16_t len)
> -{
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid connect_failed event length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->addr.bdaddr, addr);
> - printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
> - index, addr, typestr(ev->addr.type), ev->status,
> - mgmt_errstr(ev->status));
> - }
> -
> - return 0;
> -}
> -
> -static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_auth_failed *ev,
> - uint16_t len)
> -{
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid auth_failed event length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->addr.bdaddr, addr);
> - printf("hci%u %s auth failed with status 0x%02x (%s)\n",
> - index, addr, ev->status, mgmt_errstr(ev->status));
> - }
> -
> - return 0;
> -}
> -
> -static int mgmt_name_changed(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_local_name_changed *ev,
> - uint16_t len)
> -{
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid local_name_changed length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor)
> - printf("hci%u name changed: %s\n", index, ev->name);
> -
> - return 0;
> -}
> -
> -static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> - uint8_t status, void *rsp, uint16_t len,
> - void *user_data)
> -{
> - struct mgmt_rp_confirm_name *rp = rsp;
> - char addr[18];
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr,
> - "hci%u confirm_name failed with status 0x%02x (%s)\n",
> - id, status, mgmt_errstr(status));
> - return;
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr,
> - "hci%u confirm_name rsp length %u instead of %zu\n",
> - id, len, sizeof(*rp));
> - return;
> - }
> -
> - ba2str(&rp->addr.bdaddr, addr);
> -
> - if (status != 0)
> - fprintf(stderr,
> - "hci%u confirm_name for %s failed: 0x%02x (%s)\n",
> - id, addr, status, mgmt_errstr(status));
> - else
> - printf("hci%u confirm_name succeeded for %s\n", id, addr);
> -}
> -
> -static int mgmt_device_found(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_device_found *ev, uint16_t len)
> -{
> - uint32_t flags;
> - uint16_t eir_len;
> -
> - if (len < sizeof(*ev)) {
> - fprintf(stderr,
> - "Too short device_found length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - flags = btohs(ev->flags);
> -
> - eir_len = bt_get_le16(&ev->eir_len);
> - if (len != sizeof(*ev) + eir_len) {
> - fprintf(stderr, "dev_found: expected %zu bytes, got %u bytes",
> - sizeof(*ev) + eir_len, len);
> - return -EINVAL;
> - }
> -
> - if (monitor || discovery) {
> - char addr[18];
> - ba2str(&ev->addr.bdaddr, addr);
> - printf("hci%u dev_found: %s type %s rssi %d "
> - "flags 0x%04x eir_len %u\n", index, addr,
> - typestr(ev->addr.type), ev->rssi, flags, eir_len);
> - }
> -
> - if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
> - struct mgmt_cp_confirm_name cp;
> -
> - memset(&cp, 0, sizeof(cp));
> - memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
> - if (resolve_names)
> - cp.name_known = 0;
> - else
> - cp.name_known = 1;
> -
> - mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
> - &cp, sizeof(cp), confirm_name_rsp,
> - NULL);
> - }
> -
> - return 0;
> -}
> -
> -static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr,
> - "hci%u PIN Code reply failed with status 0x%02x (%s)",
> - id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("hci%u PIN Reply successful\n", id);
> -}
> -
> -static int mgmt_pin_reply(int mgmt_sk, uint16_t index,
> - struct mgmt_addr_info *addr,
> - const char *pin, size_t len)
> -{
> - struct mgmt_cp_pin_code_reply cp;
> -
> - memset(&cp, 0, sizeof(cp));
> - memcpy(&cp.addr, addr, sizeof(cp.addr));
> - cp.pin_len = len;
> - memcpy(cp.pin_code, pin, len);
> -
> - return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
> - &cp, sizeof(cp), pin_rsp, NULL);
> -}
> -
> -static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr,
> - "hci%u PIN Neg reply failed with status 0x%02x (%s)",
> - id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("hci%u PIN Negative Reply successful\n", id);
> -}
> -
> -static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index,
> - struct mgmt_addr_info *addr)
> -{
> - struct mgmt_cp_pin_code_neg_reply cp;
> -
> - memset(&cp, 0, sizeof(cp));
> - memcpy(&cp.addr, addr, sizeof(cp.addr));
> -
> - return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
> - &cp, sizeof(cp), pin_neg_rsp, NULL);
> -}
> -
> -static int mgmt_request_pin(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_pin_code_request *ev,
> - uint16_t len)
> -{
> - char pin[18];
> - size_t pin_len;
> -
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid pin_code request length (%u bytes)\n", len);
> - return -EINVAL;
> - }
> -
> - if (monitor) {
> - char addr[18];
> - ba2str(&ev->addr.bdaddr, addr);
> - printf("hci%u %s request PIN\n", index, addr);
> - }
> -
> - printf("PIN Request (press enter to reject) >> ");
> - fflush(stdout);
> -
> - memset(pin, 0, sizeof(pin));
> -
> - if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
> - return mgmt_pin_neg_reply(mgmt_sk, index, &ev->addr);
> -
> - pin_len = strlen(pin);
> - if (pin[pin_len - 1] == '\n') {
> - pin[pin_len - 1] = '\0';
> - pin_len--;
> - }
> -
> - return mgmt_pin_reply(mgmt_sk, index, &ev->addr, pin, pin_len);
> -}
> -
> -static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr,
> - "hci%u User Confirm reply failed. status 0x%02x (%s)",
> - id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("hci%u User Confirm Reply successful\n", id);
> -}
> -
> -static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
> -{
> - struct mgmt_cp_user_confirm_reply cp;
> -
> - memset(&cp, 0, sizeof(cp));
> - bacpy(&cp.addr.bdaddr, bdaddr);
> -
> - return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
> - &cp, sizeof(cp), confirm_rsp, NULL);
> -}
> -
> -static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> - uint8_t status, void *rsp, uint16_t len,
> - void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr,
> - "hci%u Confirm Neg reply failed. status 0x%02x (%s)",
> - id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("hci%u User Confirm Negative Reply successful\n", id);
> -}
> -
> -static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
> - bdaddr_t *bdaddr)
> -{
> - struct mgmt_cp_user_confirm_reply cp;
> -
> - memset(&cp, 0, sizeof(cp));
> - bacpy(&cp.addr.bdaddr, bdaddr);
> -
> - return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
> - &cp, sizeof(cp), confirm_neg_rsp, NULL);
> -}
> -
> -
> -static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
> - struct mgmt_ev_user_confirm_request *ev,
> - uint16_t len)
> -{
> - char rsp[5];
> - size_t rsp_len;
> - uint32_t val;
> - char addr[18];
> -
> - if (len != sizeof(*ev)) {
> - fprintf(stderr,
> - "Invalid user_confirm request length (%u)\n", len);
> - return -EINVAL;
> - }
> -
> - ba2str(&ev->addr.bdaddr, addr);
> - val = bt_get_le32(&ev->value);
> -
> - if (monitor)
> - printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
> - val, ev->confirm_hint);
> -
> - if (ev->confirm_hint)
> - printf("Accept pairing with %s (yes/no) >> ", addr);
> - else
> - printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
> -
> - fflush(stdout);
> -
> - memset(rsp, 0, sizeof(rsp));
> -
> - if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
> - return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
> -
> - rsp_len = strlen(rsp);
> - if (rsp[rsp_len - 1] == '\n') {
> - rsp[rsp_len - 1] = '\0';
> - rsp_len--;
> - }
> -
> - if (rsp[0] == 'y' || rsp[0] == 'Y')
> - return mgmt_confirm_reply(mgmt_sk, index, &ev->addr.bdaddr);
> - else
> - return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
> -}
> -
> -static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
> - void *data, uint16_t len)
> -{
> - if (monitor)
> - printf("event: %s\n", mgmt_evstr(ev));
> -
> - switch (ev) {
> - case MGMT_EV_CMD_COMPLETE:
> - return mgmt_cmd_complete(mgmt_sk, index, data, len);
> - case MGMT_EV_CMD_STATUS:
> - return mgmt_cmd_status(mgmt_sk, index, data, len);
> - case MGMT_EV_CONTROLLER_ERROR:
> - return mgmt_controller_error(index, data, len);
> - case MGMT_EV_INDEX_ADDED:
> - return mgmt_index_added(mgmt_sk, index);
> - case MGMT_EV_INDEX_REMOVED:
> - return mgmt_index_removed(mgmt_sk, index);
> - case MGMT_EV_NEW_SETTINGS:
> - return mgmt_new_settings(mgmt_sk, index, data, len);
> - case MGMT_EV_DISCOVERING:
> - return mgmt_discovering(mgmt_sk, index, data, len);
> - case MGMT_EV_NEW_LINK_KEY:
> - return mgmt_new_link_key(mgmt_sk, index, data, len);
> - case MGMT_EV_DEVICE_CONNECTED:
> - return mgmt_connected(mgmt_sk, index, data, len);
> - case MGMT_EV_DEVICE_DISCONNECTED:
> - return mgmt_disconnected(mgmt_sk, index, data, len);
> - case MGMT_EV_CONNECT_FAILED:
> - return mgmt_conn_failed(mgmt_sk, index, data, len);
> - case MGMT_EV_AUTH_FAILED:
> - return mgmt_auth_failed(mgmt_sk, index, data, len);
> - case MGMT_EV_LOCAL_NAME_CHANGED:
> - return mgmt_name_changed(mgmt_sk, index, data, len);
> - case MGMT_EV_DEVICE_FOUND:
> - return mgmt_device_found(mgmt_sk, index, data, len);
> - case MGMT_EV_PIN_CODE_REQUEST:
> - return mgmt_request_pin(mgmt_sk, index, data, len);
> - case MGMT_EV_USER_CONFIRM_REQUEST:
> - return mgmt_user_confirm(mgmt_sk, index, data, len);
> - default:
> - if (monitor)
> - printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
> - return 0;
> - }
> -}
> -
> -static int mgmt_process_data(int mgmt_sk)
> -{
> - char buf[1024];
> - struct mgmt_hdr *hdr = (void *) buf;
> - uint16_t len, ev, index;
> - ssize_t ret;
> -
> - ret = read(mgmt_sk, buf, sizeof(buf));
> - if (ret < 0) {
> - fprintf(stderr, "read: %s\n", strerror(errno));
> - return ret;
> - }
> -
> - if (ret < MGMT_HDR_SIZE) {
> - fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
> - return 0;
> - }
> -
> - ev = bt_get_le16(&hdr->opcode);
> - index = bt_get_le16(&hdr->index);
> - len = bt_get_le16(&hdr->len);
> -
> - if (monitor)
> - printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
> -
> - if (ret != MGMT_HDR_SIZE + len) {
> - fprintf(stderr, "Packet length mismatch. ret %zd len %u",
> - ret, len);
> - return 0;
> - }
> -
> - mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
> -
> - return 0;
> -}
> -
> -static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - printf("Monitoring mgmt events...\n");
> - monitor = true;
> -}
> -
> -static void version_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_read_version *rp = rsp;
> -
> - if (status != 0) {
> - fprintf(stderr, "Reading mgmt version failed with status"
> - " 0x%02x (%s)\n", status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small version reply (%u bytes)\n", len);
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("MGMT Version %u, revision %u\n", rp->version,
> - bt_get_le16(&rp->revision));
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_version(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
> - NULL, 0, version_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send read_version cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void commands_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_read_commands *rp = rsp;
> - uint16_t num_commands, num_events, *opcode;
> - size_t expected_len;
> - int i;
> -
> - if (status != 0) {
> - fprintf(stderr, "Reading supported commands failed with status"
> - " 0x%02x (%s)\n", status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small commands reply (%u bytes)\n", len);
> - exit(EXIT_FAILURE);
> - }
> -
> - num_commands = bt_get_le16(&rp->num_commands);
> - num_events = bt_get_le16(&rp->num_events);
> -
> - expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
> - num_events * sizeof(uint16_t);
> -
> - if (len < expected_len) {
> - fprintf(stderr, "Too small commands reply (%u != %zu)\n",
> - len, expected_len);
> - exit(EXIT_FAILURE);
> - }
> -
> - opcode = rp->opcodes;
> -
> - printf("%u commands:\n", num_commands);
> - for (i = 0; i < num_commands; i++) {
> - uint16_t op = bt_get_le16(opcode++);
> - printf("\t%s (0x%04x)\n", mgmt_opstr(op), op);
> - }
> -
> - printf("%u events:\n", num_events);
> - for (i = 0; i < num_events; i++) {
> - uint16_t ev = bt_get_le16(opcode++);
> - printf("\t%s (0x%04x)\n", mgmt_evstr(ev), ev);
> - }
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_commands(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
> - NULL, 0, commands_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send read_commands cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_read_info *rp = rsp;
> - char addr[18];
> -
> - if (status != 0) {
> - fprintf(stderr,
> - "Reading hci%u info failed with status 0x%02x (%s)\n",
> - id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small info reply (%u bytes)\n", len);
> - exit(EXIT_FAILURE);
> - }
> -
> - ba2str(&rp->bdaddr, addr);
> - printf("hci%u:\taddr %s version %u manufacturer %u"
> - " class 0x%02x%02x%02x\n",
> - id, addr, rp->version, bt_get_le16(&rp->manufacturer),
> - rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
> -
> - printf("\tsupported settings: ");
> - print_settings(bt_get_le32(&rp->supported_settings));
> -
> - printf("\n\tcurrent settings: ");
> - print_settings(bt_get_le32(&rp->current_settings));
> -
> - printf("\n\tname %s\n", rp->name);
> - printf("\tshort name %s\n", rp->short_name);
> -
> - if (pending == NULL)
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_read_index_list *rp = rsp;
> - uint16_t count;
> - unsigned int i;
> -
> - if (status != 0) {
> - fprintf(stderr,
> - "Reading index list failed with status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small index list reply (%u bytes)\n",
> - len);
> - exit(EXIT_FAILURE);
> - }
> -
> - count = bt_get_le16(&rp->num_controllers);
> -
> - if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
> - fprintf(stderr,
> - "Index count (%u) doesn't match reply length (%u)\n",
> - count, len);
> - exit(EXIT_FAILURE);
> - }
> -
> - if (monitor)
> - printf("Index list with %u item%s\n",
> - count, count > 1 ? "s" : "");
> -
> - if (count == 0)
> - exit(EXIT_SUCCESS);
> -
> - if (monitor && count > 0)
> - printf("\t");
> -
> - for (i = 0; i < count; i++) {
> - uint16_t index;
> -
> - index = bt_get_le16(&rp->index[i]);
> -
> - if (monitor)
> - printf("hci%u ", index);
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
> - 0, info_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send read_info cmd\n");
> - exit(EXIT_FAILURE);
> - }
> - }
> -
> - if (monitor && count > 0)
> - printf("\n");
> -}
> -
> -static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - if (index == MGMT_INDEX_NONE) {
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
> - MGMT_INDEX_NONE, NULL, 0,
> - index_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send index_list cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -
> - return;
> - }
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
> - 0, info_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send read_info cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - uint32_t *rp = rsp;
> -
> - if (status != 0) {
> - fprintf(stderr,
> - "%s for hci%u failed with status 0x%02x (%s)\n",
> - mgmt_opstr(op), id, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small %s response (%u bytes)\n",
> - mgmt_opstr(op), len);
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
> - print_settings(bt_get_le32(rp));
> - printf("\n");
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
> - int argc, char **argv)
> -{
> - uint8_t val;
> -
> - if (argc < 2) {
> - printf("Specify \"on\" or \"off\"\n");
> - exit(EXIT_FAILURE);
> - }
> -
> - if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
> - val = 1;
> - else if (strcasecmp(argv[1], "off") == 0)
> - val = 0;
> - else
> - val = atoi(argv[1]);
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
> - setting_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
> -}
> -
> -static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_set_discoverable cp;
> -
> - if (argc < 2) {
> - printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
> - exit(EXIT_FAILURE);
> - }
> -
> - memset(&cp, 0, sizeof(cp));
> -
> - if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
> - cp.val = 1;
> - else if (strcasecmp(argv[1], "off") == 0)
> - cp.val = 0;
> - else
> - cp.val = atoi(argv[1]);
> -
> - if (argc > 2)
> - cp.timeout = htobs(atoi(argv[2]));
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
> - &cp, sizeof(cp), setting_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send set_discoverable cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
> -}
> -
> -static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
> -}
> -
> -static void cmd_linksec(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_LINK_SECURITY, argc, argv);
> -}
> -
> -static void cmd_ssp(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_SSP, argc, argv);
> -}
> -
> -static void cmd_hs(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_HS, argc, argv);
> -}
> -
> -static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
> -}
> -
> -static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_ev_class_of_dev_changed *rp = rsp;
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
> - mgmt_opstr(op), status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("%s succeeded. Class 0x%02x%02x%02x\n", mgmt_opstr(op),
> - rp->class_of_dev[2], rp->class_of_dev[1], rp->class_of_dev[0]);
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - uint8_t class[2];
> -
> - if (argc < 3) {
> - printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
> - exit(EXIT_FAILURE);
> - }
> -
> - class[0] = atoi(argv[1]);
> - class[1] = atoi(argv[2]);
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
> - class, sizeof(class), class_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send set_dev_class cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
> - uint8_t status, void *rsp, uint16_t len,
> - void *user_data)
> -{
> - struct mgmt_rp_disconnect *rp = rsp;
> - char addr[18];
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr, "Invalid disconnect response length (%u)\n",
> - len);
> - exit(EXIT_FAILURE);
> - }
> -
> - ba2str(&rp->addr.bdaddr, addr);
> -
> - if (status == 0) {
> - printf("%s disconnected\n", addr);
> - exit(EXIT_SUCCESS);
> - } else {
> - fprintf(stderr,
> - "Disconnecting %s failed with status 0x%02x (%s)\n",
> - addr, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_disconnect cp;
> -
> - if (argc < 2) {
> - printf("Usage: btmgmt %s <address>\n", argv[0]);
> - exit(EXIT_FAILURE);
> - }
> -
> - str2ba(argv[1], &cp.addr.bdaddr);
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
> - &cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send disconnect cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_get_connections *rp = rsp;
> - uint16_t count, i;
> -
> - if (len < sizeof(*rp)) {
> - fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
> - len);
> - exit(EXIT_FAILURE);
> - }
> -
> - count = bt_get_le16(&rp->conn_count);
> - if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
> - fprintf(stderr, "Invalid get_connections length "
> - " (count=%u, len=%u)\n", count, len);
> - exit(EXIT_FAILURE);
> - }
> -
> - for (i = 0; i < count; i++) {
> - char addr[18];
> -
> - ba2str(&rp->addr[i].bdaddr, addr);
> -
> - printf("%s type %s\n", addr, typestr(rp->addr[i].type));
> - }
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
> - con_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send get_connections cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr,
> - "Unable to start discovery. status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("Discovery started\n");
> - discovery = true;
> -}
> -
> -static void find_usage(void)
> -{
> - printf("Usage: btmgmt find [-l|-b]>\n");
> -}
> -
> -static struct option find_options[] = {
> - { "help", 0, 0, 'h' },
> - { "le-only", 1, 0, 'l' },
> - { "bredr-only", 1, 0, 'b' },
> - { 0, 0, 0, 0 }
> -};
> -
> -static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_start_discovery cp;
> - uint8_t type;
> - int opt;
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - type = 0;
> - hci_set_bit(BDADDR_BREDR, &type);
> - hci_set_bit(BDADDR_LE_PUBLIC, &type);
> - hci_set_bit(BDADDR_LE_RANDOM, &type);
> -
> - while ((opt = getopt_long(argc, argv, "+lbh", find_options,
> - NULL)) != -1) {
> - switch (opt) {
> - case 'l':
> - hci_clear_bit(BDADDR_BREDR, &type);
> - hci_set_bit(BDADDR_LE_PUBLIC, &type);
> - hci_set_bit(BDADDR_LE_RANDOM, &type);
> - break;
> - case 'b':
> - hci_set_bit(BDADDR_BREDR, &type);
> - hci_clear_bit(BDADDR_LE_PUBLIC, &type);
> - hci_clear_bit(BDADDR_LE_RANDOM, &type);
> - break;
> - case 'h':
> - default:
> - find_usage();
> - exit(EXIT_SUCCESS);
> - }
> - }
> -
> - argc -= optind;
> - argv += optind;
> - optind = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - cp.type = type;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
> - &cp, sizeof(cp), find_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send start_discovery cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_set_local_name cp;
> -
> - if (argc < 2) {
> - printf("Usage: btmgmt %s <name> [shortname]\n", argv[0]);
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
> - if (argc > 2)
> - strncpy((char *) cp.short_name, argv[2],
> - MGMT_MAX_SHORT_NAME_LENGTH);
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
> - &cp, sizeof(cp), name_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send set_name cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_pair_device *rp = rsp;
> - char addr[18];
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
> - exit(EXIT_FAILURE);
> - }
> -
> - ba2str(&rp->addr.bdaddr, addr);
> -
> - if (status != 0) {
> - fprintf(stderr,
> - "Pairing with %s (%s) failed. status 0x%02x (%s)\n",
> - addr, typestr(rp->addr.type), status,
> - mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("Paired with %s\n", addr);
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void pair_usage(void)
> -{
> - printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
> -}
> -
> -static struct option pair_options[] = {
> - { "help", 0, 0, 'h' },
> - { "capability", 1, 0, 'c' },
> - { "type", 1, 0, 't' },
> - { 0, 0, 0, 0 }
> -};
> -
> -static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_pair_device cp;
> - uint8_t cap = 0x01;
> - uint8_t type = BDADDR_BREDR;
> - int opt;
> -
> - while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
> - NULL)) != -1) {
> - switch (opt) {
> - case 'c':
> - cap = strtol(optarg, NULL, 0);
> - break;
> - case 't':
> - type = strtol(optarg, NULL, 0);
> - break;
> - case 'h':
> - default:
> - pair_usage();
> - exit(EXIT_SUCCESS);
> - }
> - }
> -
> - argc -= optind;
> - argv += optind;
> - optind = 0;
> -
> - if (argc < 1) {
> - pair_usage();
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - str2ba(argv[0], &cp.addr.bdaddr);
> - cp.addr.type = type;
> - cp.io_cap = cap;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
> - pair_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send pair_device cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void unpair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_rp_unpair_device *rp = rsp;
> - char addr[18];
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr, "Unpair device failed. status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr, "Unexpected unpair_device_rsp len %u\n", len);
> - exit(EXIT_FAILURE);
> - }
> -
> - ba2str(&rp->addr.bdaddr, addr);
> -
> - if (status != 0) {
> - fprintf(stderr,
> - "Unpairing %s failed. status 0x%02x (%s)\n",
> - addr, status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("%s unpaired\n", addr);
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_unpair(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_unpair_device cp;
> -
> - if (argc < 2) {
> - printf("Usage: btmgmt %s <remote address>\n", argv[0]);
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - str2ba(argv[1], &cp.addr.bdaddr);
> - cp.disconnect = 1;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNPAIR_DEVICE, index, &cp,
> - sizeof(cp), unpair_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send unpair_device cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("Keys successfully loaded\n");
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_load_link_keys cp;
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
> - &cp, sizeof(cp), keys_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send load_keys cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void block_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - struct mgmt_addr_info *rp = rsp;
> - char addr[18];
> -
> - if (len == 0 && status != 0) {
> - fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
> - mgmt_opstr(op), status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - if (len != sizeof(*rp)) {
> - fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
> - exit(EXIT_FAILURE);
> - }
> -
> - ba2str(&rp->bdaddr, addr);
> -
> - if (status != 0) {
> - fprintf(stderr, "%s %s (%s) failed. status 0x%02x (%s)\n",
> - mgmt_opstr(op), addr, typestr(rp->type),
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("%s %s succeeded\n", mgmt_opstr(op), addr);
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void block_usage(void)
> -{
> - printf("Usage: btmgmt block [-t type] <remote address>\n");
> -}
> -
> -static struct option block_options[] = {
> - { "help", 0, 0, 'h' },
> - { "type", 1, 0, 't' },
> - { 0, 0, 0, 0 }
> -};
> -
> -static void cmd_block(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_block_device cp;
> - uint8_t type = BDADDR_BREDR;
> - int opt;
> -
> - while ((opt = getopt_long(argc, argv, "+t:h", block_options,
> - NULL)) != -1) {
> - switch (opt) {
> - case 't':
> - type = strtol(optarg, NULL, 0);
> - break;
> - case 'h':
> - default:
> - block_usage();
> - exit(EXIT_SUCCESS);
> - }
> - }
> -
> - argc -= optind;
> - argv += optind;
> - optind = 0;
> -
> - if (argc < 1) {
> - block_usage();
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - str2ba(argv[0], &cp.addr.bdaddr);
> - cp.addr.type = type;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_BLOCK_DEVICE, index,
> - &cp, sizeof(cp), block_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send block_device cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void unblock_usage(void)
> -{
> - printf("Usage: btmgmt unblock [-t type] <remote address>\n");
> -}
> -
> -static void cmd_unblock(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_unblock_device cp;
> - uint8_t type = BDADDR_BREDR;
> - int opt;
> -
> - while ((opt = getopt_long(argc, argv, "+t:h", block_options,
> - NULL)) != -1) {
> - switch (opt) {
> - case 't':
> - type = strtol(optarg, NULL, 0);
> - break;
> - case 'h':
> - default:
> - unblock_usage();
> - exit(EXIT_SUCCESS);
> - }
> - }
> -
> - argc -= optind;
> - argv += optind;
> - optind = 0;
> -
> - if (argc < 1) {
> - unblock_usage();
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - memset(&cp, 0, sizeof(cp));
> - str2ba(argv[0], &cp.addr.bdaddr);
> - cp.addr.type = type;
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNBLOCK_DEVICE, index,
> - &cp, sizeof(cp), block_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send unblock_device cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> -{
> - if (uuid->type == SDP_UUID16)
> - sdp_uuid16_to_uuid128(uuid128, uuid);
> - else if (uuid->type == SDP_UUID32)
> - sdp_uuid32_to_uuid128(uuid128, uuid);
> - else
> - memcpy(uuid128, uuid, sizeof(*uuid));
> -}
> -
> -static void cmd_add_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_add_uuid cp;
> - uint128_t uint128;
> - uuid_t uuid, uuid128;
> -
> - if (argc < 3) {
> - printf("UUID and service hint needed\n");
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (bt_string2uuid(&uuid, argv[1]) < 0) {
> - printf("Invalid UUID: %s\n", argv[1]);
> - exit(EXIT_FAILURE);
> - }
> -
> - memset(&cp, 0, sizeof(cp));
> -
> - uuid_to_uuid128(&uuid128, &uuid);
> - ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> - htob128(&uint128, (uint128_t *) cp.uuid);
> -
> - cp.svc_hint = atoi(argv[2]);
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_ADD_UUID, index,
> - &cp, sizeof(cp), class_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send add_uuid cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void cmd_remove_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_remove_uuid cp;
> - uint128_t uint128;
> - uuid_t uuid, uuid128;
> -
> - if (argc < 2) {
> - printf("UUID needed\n");
> - exit(EXIT_FAILURE);
> - }
> -
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - if (bt_string2uuid(&uuid, argv[1]) < 0) {
> - printf("Invalid UUID: %s\n", argv[1]);
> - exit(EXIT_FAILURE);
> - }
> -
> - memset(&cp, 0, sizeof(cp));
> -
> - uuid_to_uuid128(&uuid128, &uuid);
> - ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> - htob128(&uint128, (uint128_t *) cp.uuid);
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_UUID, index,
> - &cp, sizeof(cp), class_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send remove_uuid cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static void cmd_clr_uuids(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - char *uuid_any = "00000000-0000-0000-0000-000000000000";
> - char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
> -
> - cmd_remove_uuid(mgmt_sk, index, 2, rm_argv);
> -}
> -
> -static void did_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
> - void *rsp, uint16_t len, void *user_data)
> -{
> - if (status != 0) {
> - fprintf(stderr, "Set Device ID failed with status 0x%02x (%s)\n",
> - status, mgmt_errstr(status));
> - exit(EXIT_FAILURE);
> - }
> -
> - printf("Device ID successfully set\n");
> -
> - exit(EXIT_SUCCESS);
> -}
> -
> -static void did_usage(void)
> -{
> - printf("Usage: btmgmt did <source>:<vendor>:<product>:<version>\n");
> - printf(" possible source values: bluetooth, usb\n");
> -}
> -
> -static void cmd_did(int mgmt_sk, uint16_t index, int argc, char **argv)
> -{
> - struct mgmt_cp_set_device_id cp;
> - uint16_t vendor, product, version , source;
> - int result;
> -
> - if (argc < 2) {
> - did_usage();
> - exit(EXIT_FAILURE);
> - }
> -
> - result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
> - &version);
> - if (result == 3) {
> - source = 0x0001;
> - goto done;
> - }
> -
> - result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
> - &version);
> - if (result == 3) {
> - source = 0x0002;
> - goto done;
> - }
> -
> - did_usage();
> - exit(EXIT_FAILURE);
> -
> -done:
> - if (index == MGMT_INDEX_NONE)
> - index = 0;
> -
> - cp.source = htobs(source);
> - cp.vendor = htobs(vendor);
> - cp.product = htobs(product);
> - cp.version = htobs(version);
> -
> - if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEVICE_ID, index,
> - &cp, sizeof(cp), did_rsp, NULL) < 0) {
> - fprintf(stderr, "Unable to send set_dev_class cmd\n");
> - exit(EXIT_FAILURE);
> - }
> -}
> -
> -static struct {
> - char *cmd;
> - void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
> - char *doc;
> -} command[] = {
> - { "monitor", cmd_monitor, "Monitor events" },
> - { "version", cmd_version, "Get the MGMT Version" },
> - { "commands", cmd_commands, "List supported commands" },
> - { "info", cmd_info, "Show controller info" },
> - { "power", cmd_power, "Toggle powered state" },
> - { "discov", cmd_discov, "Toggle discoverable state" },
> - { "connectable",cmd_connectable,"Toggle connectable state" },
> - { "pairable", cmd_pairable, "Toggle pairable state" },
> - { "linksec", cmd_linksec, "Toggle link level security" },
> - { "ssp", cmd_ssp, "Toggle SSP mode" },
> - { "hs", cmd_hs, "Toggle HS Support" },
> - { "le", cmd_le, "Toggle LE Support" },
> - { "class", cmd_class, "Set device major/minor class" },
> - { "disconnect", cmd_disconnect, "Disconnect device" },
> - { "con", cmd_con, "List connections" },
> - { "find", cmd_find, "Discover nearby devices" },
> - { "name", cmd_name, "Set local name" },
> - { "pair", cmd_pair, "Pair with a remote device" },
> - { "unpair", cmd_unpair, "Unpair device" },
> - { "keys", cmd_keys, "Load Keys" },
> - { "block", cmd_block, "Block Device" },
> - { "unblock", cmd_unblock, "Unblock Device" },
> - { "add-uuid", cmd_add_uuid, "Add UUID" },
> - { "rm-uuid", cmd_add_uuid, "Remove UUID" },
> - { "clr-uuids", cmd_clr_uuids, "Clear UUIDs", },
> - { "did", cmd_did, "Set Device ID", },
> - { NULL, NULL, 0 }
> -};
> -
> -static void usage(void)
> -{
> - int i;
> -
> - printf("btmgmt ver %s\n", VERSION);
> - printf("Usage:\n"
> - "\tbtmgmt [options] <command> [command parameters]\n");
> -
> - printf("Options:\n"
> - "\t--index <id>\tSpecify adapter index\n"
> - "\t--verbose\tEnable extra logging\n"
> - "\t--help\tDisplay help\n");
> -
> - printf("Commands:\n");
> - for (i = 0; command[i].cmd; i++)
> - printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
> -
> - printf("\n"
> - "For more information on the usage of each command use:\n"
> - "\tbtmgmt <command> --help\n" );
> -}
> -
> -static struct option main_options[] = {
> - { "index", 1, 0, 'i' },
> - { "verbose", 0, 0, 'v' },
> - { "help", 0, 0, 'h' },
> - { 0, 0, 0, 0 }
> -};
> -
> -int main(int argc, char *argv[])
> -{
> - int opt, i, mgmt_sk;
> - uint16_t index = MGMT_INDEX_NONE;
> - struct pollfd pollfd;
> -
> - while ((opt = getopt_long(argc, argv, "+hvi:",
> - main_options, NULL)) != -1) {
> - switch (opt) {
> - case 'i':
> - if (strlen(optarg) > 3 &&
> - strncasecmp(optarg, "hci", 3) == 0)
> - index = atoi(&optarg[4]);
> - else
> - index = atoi(optarg);
> - break;
> - case 'v':
> - monitor = true;
> - break;
> - case 'h':
> - default:
> - usage();
> - return 0;
> - }
> - }
> -
> - argc -= optind;
> - argv += optind;
> - optind = 0;
> -
> - if (argc < 1) {
> - usage();
> - return 0;
> - }
> -
> - mgmt_sk = mgmt_open();
> - if (mgmt_sk < 0) {
> - fprintf(stderr, "Unable to open mgmt socket\n");
> - return -1;
> - }
> -
> - for (i = 0; command[i].cmd; i++) {
> - if (strcmp(command[i].cmd, argv[0]) != 0)
> - continue;
> -
> - command[i].func(mgmt_sk, index, argc, argv);
> - break;
> - }
> -
> - if (command[i].cmd == NULL) {
> - fprintf(stderr, "Unknown command: %s\n", argv[0]);
> - close(mgmt_sk);
> - return -1;
> - }
> -
> - pollfd.fd = mgmt_sk;
> - pollfd.events = POLLIN;
> - pollfd.revents = 0;
> -
> - while (poll(&pollfd, 1, -1) >= 0) {
> - if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
> - break;
> -
> - if (pollfd.revents & POLLIN)
> - mgmt_process_data(mgmt_sk);
> -
> - pollfd.revents = 0;
> - }
> -
> - close(mgmt_sk);
> -
> - return 0;
> -}
> --
> 1.7.10.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


Cheers,
--
Vinicius

2012-07-09 21:10:34

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 12/14] cups: move it to profiles folder

From: Gustavo Padovan <[email protected]>

---
Makefile.tools | 12 +-
cups/cups.h | 38 ---
cups/hcrp.c | 368 ---------------------
cups/main.c | 896 --------------------------------------------------
cups/sdp.c | 119 -------
cups/spp.c | 118 -------
profiles/cups/cups.h | 38 +++
profiles/cups/hcrp.c | 368 +++++++++++++++++++++
profiles/cups/main.c | 896 ++++++++++++++++++++++++++++++++++++++++++++++++++
profiles/cups/sdp.c | 119 +++++++
profiles/cups/spp.c | 118 +++++++
11 files changed, 1547 insertions(+), 1543 deletions(-)
delete mode 100644 cups/cups.h
delete mode 100644 cups/hcrp.c
delete mode 100644 cups/main.c
delete mode 100644 cups/sdp.c
delete mode 100644 cups/spp.c
create mode 100644 profiles/cups/cups.h
create mode 100644 profiles/cups/hcrp.c
create mode 100644 profiles/cups/main.c
create mode 100644 profiles/cups/sdp.c
create mode 100644 profiles/cups/spp.c

diff --git a/Makefile.tools b/Makefile.tools
index 56839b7..fccac2d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -148,12 +148,16 @@ EXTRA_DIST += tools/dfubabel.1 tools/avctrl.8
if CUPS
cupsdir = $(libdir)/cups/backend

-cups_PROGRAMS = cups/bluetooth
+cups_PROGRAMS = profiles/cups/bluetooth

-cups_bluetooth_SOURCES = $(gdbus_sources) cups/main.c cups/cups.h \
- cups/sdp.c cups/spp.c cups/hcrp.c
+profiles_cups_bluetooth_SOURCES = $(gdbus_sources) profiles/cups/main.c \
+ profiles/cups/cups.h \
+ profiles/cups/sdp.c \
+ profiles/cups/spp.c \
+ profiles/cups/hcrp.c

-cups_bluetooth_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ lib/libbluetooth-private.la
+profiles_cups_bluetooth_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ \
+ lib/libbluetooth-private.la
endif


diff --git a/cups/cups.h b/cups/cups.h
deleted file mode 100644
index f4e0c01..0000000
--- a/cups/cups.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-enum { /**** Backend exit codes ****/
- CUPS_BACKEND_OK = 0, /* Job completed successfully */
- CUPS_BACKEND_FAILED = 1, /* Job failed, use error-policy */
- CUPS_BACKEND_AUTH_REQUIRED = 2, /* Job failed, authentication required */
- CUPS_BACKEND_HOLD = 3, /* Job failed, hold job */
- CUPS_BACKEND_STOP = 4, /* Job failed, stop queue */
- CUPS_BACKEND_CANCEL = 5, /* Job failed, cancel job */
- CUPS_BACKEND_RETRY = 6, /* Failure requires us to retry (BlueZ specific) */
-};
-
-int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
-int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);
-
-int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);
-int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);
diff --git a/cups/hcrp.c b/cups/hcrp.c
deleted file mode 100644
index a93dda0..0000000
--- a/cups/hcrp.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/l2cap.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <netinet/in.h>
-
-#include "cups.h"
-
-#define HCRP_PDU_CREDIT_GRANT 0x0001
-#define HCRP_PDU_CREDIT_REQUEST 0x0002
-#define HCRP_PDU_GET_LPT_STATUS 0x0005
-
-#define HCRP_STATUS_FEATURE_UNSUPPORTED 0x0000
-#define HCRP_STATUS_SUCCESS 0x0001
-#define HCRP_STATUS_CREDIT_SYNC_ERROR 0x0002
-#define HCRP_STATUS_GENERIC_FAILURE 0xffff
-
-struct hcrp_pdu_hdr {
- uint16_t pid;
- uint16_t tid;
- uint16_t plen;
-} __attribute__ ((packed));
-#define HCRP_PDU_HDR_SIZE 6
-
-struct hcrp_credit_grant_cp {
- uint32_t credit;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_GRANT_CP_SIZE 4
-
-struct hcrp_credit_grant_rp {
- uint16_t status;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_GRANT_RP_SIZE 2
-
-struct hcrp_credit_request_rp {
- uint16_t status;
- uint32_t credit;
-} __attribute__ ((packed));
-#define HCRP_CREDIT_REQUEST_RP_SIZE 6
-
-struct hcrp_get_lpt_status_rp {
- uint16_t status;
- uint8_t lpt_status;
-} __attribute__ ((packed));
-#define HCRP_GET_LPT_STATUS_RP_SIZE 3
-
-static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
-{
- struct hcrp_pdu_hdr hdr;
- struct hcrp_credit_grant_cp cp;
- struct hcrp_credit_grant_rp rp;
- unsigned char buf[128];
- int len;
-
- hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
- hdr.tid = htons(tid);
- hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
- cp.credit = credit;
- memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
- memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
- len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
- if (len < 0)
- return len;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- return len;
-
- memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
- memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
-
- if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
- errno = EIO;
- return -1;
- }
-
- return 0;
-}
-
-static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
-{
- struct hcrp_pdu_hdr hdr;
- struct hcrp_credit_request_rp rp;
- unsigned char buf[128];
- int len;
-
- hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
- hdr.tid = htons(tid);
- hdr.plen = htons(0);
- memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
- len = write(sk, buf, HCRP_PDU_HDR_SIZE);
- if (len < 0)
- return len;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- return len;
-
- memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
- memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
-
- if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
- errno = EIO;
- return -1;
- }
-
- if (credit)
- *credit = ntohl(rp.credit);
-
- return 0;
-}
-
-static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
-{
- struct hcrp_pdu_hdr hdr;
- struct hcrp_get_lpt_status_rp rp;
- unsigned char buf[128];
- int len;
-
- hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
- hdr.tid = htons(tid);
- hdr.plen = htons(0);
- memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
- len = write(sk, buf, HCRP_PDU_HDR_SIZE);
- if (len < 0)
- return len;
-
- len = read(sk, buf, sizeof(buf));
- if (len < 0)
- return len;
-
- memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
- memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
-
- if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
- errno = EIO;
- return -1;
- }
-
- if (lpt_status)
- *lpt_status = rp.lpt_status;
-
- return 0;
-}
-
-static inline int hcrp_get_next_tid(int tid)
-{
- if (tid > 0xf000)
- return 0;
- else
- return tid + 1;
-}
-
-int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class)
-{
- struct sockaddr_l2 addr;
- struct l2cap_options opts;
- socklen_t size;
- unsigned char buf[2048];
- int i, ctrl_sk, data_sk, count, len, timeout = 0;
- unsigned int mtu;
- uint8_t status;
- uint16_t tid = 0;
- uint32_t tmp, credit = 0;
-
- if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
- perror("ERROR: Can't create socket");
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, src);
-
- if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't bind socket");
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, dst);
- addr.l2_psm = htobs(ctrl_psm);
-
- if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't connect to device");
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
- perror("ERROR: Can't create socket");
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, src);
-
- if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't bind socket");
- close(data_sk);
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.l2_family = AF_BLUETOOTH;
- bacpy(&addr.l2_bdaddr, dst);
- addr.l2_psm = htobs(data_psm);
-
- if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't connect to device");
- close(data_sk);
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- fputs("STATE: -connecting-to-device\n", stderr);
-
- memset(&opts, 0, sizeof(opts));
- size = sizeof(opts);
-
- if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
- perror("ERROR: Can't get socket options");
- close(data_sk);
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- mtu = opts.omtu;
-
- /* Ignore SIGTERM signals if printing from stdin */
- if (fd == 0) {
-#ifdef HAVE_SIGSET
- sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = SIG_IGN;
- sigaction(SIGTERM, &action, NULL);
-#else
- signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
- }
-
- tid = hcrp_get_next_tid(tid);
- if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
- fprintf(stderr, "ERROR: Can't grant initial credits\n");
- close(data_sk);
- close(ctrl_sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- for (i = 0; i < copies; i++) {
-
- if (fd != 0) {
- fprintf(stderr, "PAGE: 1 1\n");
- lseek(fd, 0, SEEK_SET);
- }
-
- while (1) {
- if (credit < mtu) {
- tid = hcrp_get_next_tid(tid);
- if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
- credit += tmp;
- timeout = 0;
- }
- }
-
- if (!credit) {
- if (timeout++ > 300) {
- tid = hcrp_get_next_tid(tid);
- if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
- fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
- break;
- }
-
- sleep(1);
- continue;
- }
-
- count = read(fd, buf, (credit > mtu) ? mtu : credit);
- if (count <= 0)
- break;
-
- len = write(data_sk, buf, count);
- if (len < 0) {
- perror("ERROR: Error writing to device");
- close(data_sk);
- close(ctrl_sk);
- return CUPS_BACKEND_FAILED;
- }
-
- if (len != count)
- fprintf(stderr, "ERROR: Can't send complete data\n");
-
- credit -= len;
- }
-
- }
-
- close(data_sk);
- close(ctrl_sk);
-
- return CUPS_BACKEND_OK;
-}
diff --git a/cups/main.c b/cups/main.c
deleted file mode 100644
index a884c6e..0000000
--- a/cups/main.c
+++ /dev/null
@@ -1,896 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <glib.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <gdbus.h>
-
-#include "cups.h"
-
-struct cups_device {
- char *bdaddr;
- char *name;
- char *id;
-};
-
-static GSList *device_list = NULL;
-static GMainLoop *loop = NULL;
-static DBusConnection *conn = NULL;
-static gboolean doing_disco = FALSE;
-
-#define ATTRID_1284ID 0x0300
-
-struct context_data {
- gboolean found;
- char *id;
-};
-
-static void element_start(GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data, GError **err)
-{
- struct context_data *ctx_data = user_data;
-
- if (!strcmp(element_name, "record"))
- return;
-
- if (!strcmp(element_name, "attribute")) {
- int i;
- for (i = 0; attribute_names[i]; i++) {
- if (strcmp(attribute_names[i], "id") != 0)
- continue;
- if (strtol(attribute_values[i], 0, 0) == ATTRID_1284ID)
- ctx_data->found = TRUE;
- break;
- }
- return;
- }
-
- if (ctx_data->found && !strcmp(element_name, "text")) {
- int i;
- for (i = 0; attribute_names[i]; i++) {
- if (!strcmp(attribute_names[i], "value")) {
- ctx_data->id = g_strdup(attribute_values[i] + 2);
- ctx_data->found = FALSE;
- }
- }
- }
-}
-
-static GMarkupParser parser = {
- element_start, NULL, NULL, NULL, NULL
-};
-
-static char *sdp_xml_parse_record(const char *data)
-{
- GMarkupParseContext *ctx;
- struct context_data ctx_data;
- int size;
-
- size = strlen(data);
- ctx_data.found = FALSE;
- ctx_data.id = NULL;
- ctx = g_markup_parse_context_new(&parser, 0, &ctx_data, NULL);
-
- if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
- g_markup_parse_context_free(ctx);
- g_free(ctx_data.id);
- return NULL;
- }
-
- g_markup_parse_context_free(ctx);
-
- return ctx_data.id;
-}
-
-static char *device_get_ieee1284_id(const char *adapter, const char *device)
-{
- DBusMessage *message, *reply;
- DBusMessageIter iter, reply_iter;
- DBusMessageIter reply_iter_entry;
- const char *hcr_print = "00001126-0000-1000-8000-00805f9b34fb";
- const char *xml;
- char *id = NULL;
-
- /* Look for the service handle of the HCRP service */
- message = dbus_message_new_method_call("org.bluez", device,
- "org.bluez.Device",
- "DiscoverServices");
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &hcr_print);
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply)
- return NULL;
-
- dbus_message_iter_init(reply, &reply_iter);
-
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
- dbus_message_unref(reply);
- return NULL;
- }
-
- dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
-
- /* Hopefully we only get one handle, or take a punt */
- while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
- DBUS_TYPE_DICT_ENTRY) {
- guint32 key;
- DBusMessageIter dict_entry;
-
- dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
-
- /* Key ? */
- dbus_message_iter_get_basic(&dict_entry, &key);
- if (!key) {
- dbus_message_iter_next(&reply_iter_entry);
- continue;
- }
-
- /* Try to get the value */
- if (!dbus_message_iter_next(&dict_entry)) {
- dbus_message_iter_next(&reply_iter_entry);
- continue;
- }
-
- dbus_message_iter_get_basic(&dict_entry, &xml);
-
- id = sdp_xml_parse_record(xml);
- if (id != NULL)
- break;
- dbus_message_iter_next(&reply_iter_entry);
- }
-
- dbus_message_unref(reply);
-
- return id;
-}
-
-static void print_printer_details(const char *name, const char *bdaddr,
- const char *id)
-{
- char *uri, *escaped;
-
- escaped = g_strdelimit(g_strdup(name), "\"", '\'');
- uri = g_strdup_printf("bluetooth://%c%c%c%c%c%c%c%c%c%c%c%c",
- bdaddr[0], bdaddr[1],
- bdaddr[3], bdaddr[4],
- bdaddr[6], bdaddr[7],
- bdaddr[9], bdaddr[10],
- bdaddr[12], bdaddr[13],
- bdaddr[15], bdaddr[16]);
- printf("direct %s \"%s\" \"%s (Bluetooth)\"", uri, escaped, escaped);
- if (id != NULL)
- printf(" \"%s\"\n", id);
- else
- printf("\n");
- g_free(escaped);
- g_free(uri);
-}
-
-static void add_device_to_list(const char *name, const char *bdaddr,
- const char *id)
-{
- struct cups_device *device;
- GSList *l;
-
- /* Look for the device in the list */
- for (l = device_list; l != NULL; l = l->next) {
- device = (struct cups_device *) l->data;
-
- if (strcmp(device->bdaddr, bdaddr) == 0) {
- if (device->name != name) {
- g_free(device->name);
- device->name = g_strdup(name);
- }
- g_free(device->id);
- device->id = g_strdup(id);
- return;
- }
- }
-
- /* Or add it to the list if it's not there */
- device = g_new0(struct cups_device, 1);
- device->bdaddr = g_strdup(bdaddr);
- device->name = g_strdup(name);
- device->id = g_strdup(id);
-
- device_list = g_slist_prepend(device_list, device);
- print_printer_details(device->name, device->bdaddr, device->id);
-}
-
-static gboolean parse_device_properties(DBusMessageIter *reply_iter,
- char **name, char **bdaddr)
-{
- guint32 class = 0;
- DBusMessageIter reply_iter_entry;
-
- if (dbus_message_iter_get_arg_type(reply_iter) != DBUS_TYPE_ARRAY)
- return FALSE;
-
- dbus_message_iter_recurse(reply_iter, &reply_iter_entry);
-
- while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
- DBUS_TYPE_DICT_ENTRY) {
- const char *key;
- DBusMessageIter dict_entry, iter_dict_val;
-
- dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
-
- /* Key == Class ? */
- dbus_message_iter_get_basic(&dict_entry, &key);
- if (!key) {
- dbus_message_iter_next(&reply_iter_entry);
- continue;
- }
-
- if (strcmp(key, "Class") != 0 &&
- strcmp(key, "Alias") != 0 &&
- strcmp(key, "Address") != 0) {
- dbus_message_iter_next(&reply_iter_entry);
- continue;
- }
-
- /* Try to get the value */
- if (!dbus_message_iter_next(&dict_entry)) {
- dbus_message_iter_next(&reply_iter_entry);
- continue;
- }
- dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
- if (strcmp(key, "Class") == 0) {
- dbus_message_iter_get_basic(&iter_dict_val, &class);
- } else {
- const char *value;
- dbus_message_iter_get_basic(&iter_dict_val, &value);
- if (strcmp(key, "Alias") == 0) {
- *name = g_strdup(value);
- } else if (bdaddr) {
- *bdaddr = g_strdup(value);
- }
- }
- dbus_message_iter_next(&reply_iter_entry);
- }
-
- if (class == 0)
- return FALSE;
- if (((class & 0x1f00) >> 8) == 0x06 && (class & 0x80))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean device_is_printer(const char *adapter, const char *device_path, char **name, char **bdaddr)
-{
- DBusMessage *message, *reply;
- DBusMessageIter reply_iter;
- gboolean retval;
-
- message = dbus_message_new_method_call("org.bluez", device_path,
- "org.bluez.Device",
- "GetProperties");
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply)
- return FALSE;
-
- dbus_message_iter_init(reply, &reply_iter);
-
- retval = parse_device_properties(&reply_iter, name, bdaddr);
-
- dbus_message_unref(reply);
-
- return retval;
-}
-
-static void remote_device_found(const char *adapter, const char *bdaddr,
- const char *name)
-{
- DBusMessage *message, *reply, *adapter_reply;
- DBusMessageIter iter;
- char *object_path = NULL;
- char *id;
-
- adapter_reply = NULL;
-
- if (adapter == NULL) {
- message = dbus_message_new_method_call("org.bluez", "/",
- "org.bluez.Manager",
- "DefaultAdapter");
-
- adapter_reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!adapter_reply)
- return;
-
- if (dbus_message_get_args(adapter_reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &adapter,
- DBUS_TYPE_INVALID) == FALSE) {
- dbus_message_unref(adapter_reply);
- return;
- }
- }
-
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "FindDevice");
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
- if (adapter_reply != NULL)
- dbus_message_unref(adapter_reply);
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply) {
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "CreateDevice");
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply)
- return;
- }
-
- if (dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &object_path,
- DBUS_TYPE_INVALID) == FALSE) {
- dbus_message_unref(reply);
- return;
- }
-
- id = device_get_ieee1284_id(adapter, object_path);
- add_device_to_list(name, bdaddr, id);
- g_free(id);
-
- dbus_message_unref(reply);
-}
-
-static void discovery_completed(void)
-{
- g_slist_free(device_list);
- device_list = NULL;
-
- g_main_loop_quit(loop);
-}
-
-static void remote_device_disappeared(const char *bdaddr)
-{
- GSList *l;
-
- for (l = device_list; l != NULL; l = l->next) {
- struct cups_device *device = l->data;
-
- if (strcmp(device->bdaddr, bdaddr) == 0) {
- g_free(device->name);
- g_free(device->bdaddr);
- g_free(device);
- device_list = g_slist_delete_link(device_list, l);
- return;
- }
- }
-}
-
-static gboolean list_known_printers(const char *adapter)
-{
- DBusMessageIter reply_iter, iter_array;
- DBusError error;
- DBusMessage *message, *reply;
-
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "ListDevices");
- if (message == NULL)
- return FALSE;
-
- dbus_error_init(&error);
- reply = dbus_connection_send_with_reply_and_block(conn, message,
- -1, &error);
-
- dbus_message_unref(message);
-
- if (dbus_error_is_set(&error))
- return FALSE;
-
- dbus_message_iter_init(reply, &reply_iter);
- if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
- dbus_message_unref(reply);
- return FALSE;
- }
-
- dbus_message_iter_recurse(&reply_iter, &iter_array);
- while (dbus_message_iter_get_arg_type(&iter_array) ==
- DBUS_TYPE_OBJECT_PATH) {
- const char *object_path;
- char *name = NULL;
- char *bdaddr = NULL;
-
- dbus_message_iter_get_basic(&iter_array, &object_path);
- if (device_is_printer(adapter, object_path, &name, &bdaddr)) {
- char *id;
-
- id = device_get_ieee1284_id(adapter, object_path);
- add_device_to_list(name, bdaddr, id);
- g_free(id);
- }
- g_free(name);
- g_free(bdaddr);
- dbus_message_iter_next(&iter_array);
- }
-
- dbus_message_unref(reply);
-
- return FALSE;
-}
-
-static DBusHandlerResult filter_func(DBusConnection *connection,
- DBusMessage *message, void *user_data)
-{
- if (dbus_message_is_signal(message, "org.bluez.Adapter",
- "DeviceFound")) {
- const char *adapter, *bdaddr;
- char *name;
- DBusMessageIter iter;
-
- dbus_message_iter_init(message, &iter);
- dbus_message_iter_get_basic(&iter, &bdaddr);
- dbus_message_iter_next(&iter);
-
- adapter = dbus_message_get_path(message);
- if (parse_device_properties(&iter, &name, NULL))
- remote_device_found(adapter, bdaddr, name);
- g_free (name);
- } else if (dbus_message_is_signal(message, "org.bluez.Adapter",
- "DeviceDisappeared")) {
- const char *bdaddr;
-
- dbus_message_get_args(message, NULL,
- DBUS_TYPE_STRING, &bdaddr,
- DBUS_TYPE_INVALID);
- remote_device_disappeared(bdaddr);
- } else if (dbus_message_is_signal(message, "org.bluez.Adapter",
- "PropertyChanged")) {
- DBusMessageIter iter, value_iter;
- const char *name;
- gboolean discovering;
-
- dbus_message_iter_init(message, &iter);
- dbus_message_iter_get_basic(&iter, &name);
- if (name == NULL || strcmp(name, "Discovering") != 0)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &value_iter);
- dbus_message_iter_get_basic(&value_iter, &discovering);
-
- if (discovering == FALSE && doing_disco) {
- doing_disco = FALSE;
- discovery_completed();
- }
- }
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static gboolean list_printers(void)
-{
- /* 1. Connect to the bus
- * 2. Get the manager
- * 3. Get the default adapter
- * 4. Get a list of devices
- * 5. Get the class of each device
- * 6. Print the details from each printer device
- */
- DBusError error;
- dbus_bool_t hcid_exists;
- DBusMessage *reply, *message;
- DBusMessageIter reply_iter;
- char *adapter, *match;
-
- conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
- if (conn == NULL)
- return TRUE;
-
- dbus_error_init(&error);
- hcid_exists = dbus_bus_name_has_owner(conn, "org.bluez", &error);
- if (dbus_error_is_set(&error))
- return TRUE;
-
- if (!hcid_exists)
- return TRUE;
-
- /* Get the default adapter */
- message = dbus_message_new_method_call("org.bluez", "/",
- "org.bluez.Manager",
- "DefaultAdapter");
- if (message == NULL) {
- dbus_connection_unref(conn);
- return FALSE;
- }
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, &error);
-
- dbus_message_unref(message);
-
- if (dbus_error_is_set(&error)) {
- dbus_connection_unref(conn);
- /* No adapter */
- return TRUE;
- }
-
- dbus_message_iter_init(reply, &reply_iter);
- if (dbus_message_iter_get_arg_type(&reply_iter) !=
- DBUS_TYPE_OBJECT_PATH) {
- dbus_message_unref(reply);
- dbus_connection_unref(conn);
- return FALSE;
- }
-
- dbus_message_iter_get_basic(&reply_iter, &adapter);
- adapter = g_strdup(adapter);
- dbus_message_unref(reply);
-
- if (!dbus_connection_add_filter(conn, filter_func, adapter, g_free)) {
- g_free(adapter);
- dbus_connection_unref(conn);
- return FALSE;
- }
-
-#define MATCH_FORMAT \
- "type='signal'," \
- "interface='org.bluez.Adapter'," \
- "sender='org.bluez'," \
- "path='%s'"
-
- match = g_strdup_printf(MATCH_FORMAT, adapter);
- dbus_bus_add_match(conn, match, &error);
- g_free(match);
-
- /* Add the the recent devices */
- list_known_printers(adapter);
-
- doing_disco = TRUE;
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "StartDiscovery");
-
- if (!dbus_connection_send_with_reply(conn, message, NULL, -1)) {
- dbus_message_unref(message);
- dbus_connection_unref(conn);
- g_free(adapter);
- return FALSE;
- }
- dbus_message_unref(message);
-
- loop = g_main_loop_new(NULL, TRUE);
- g_main_loop_run(loop);
-
- g_free(adapter);
- dbus_connection_unref(conn);
-
- return TRUE;
-}
-
-static gboolean print_ieee1284(const char *bdaddr)
-{
- DBusMessage *message, *reply, *adapter_reply;
- DBusMessageIter iter;
- char *object_path = NULL;
- char *adapter;
- char *id;
-
- adapter_reply = NULL;
-
- conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
- if (conn == NULL)
- return FALSE;
-
- message = dbus_message_new_method_call("org.bluez", "/",
- "org.bluez.Manager",
- "DefaultAdapter");
-
- adapter_reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!adapter_reply)
- return FALSE;
-
- if (dbus_message_get_args(adapter_reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &adapter,
- DBUS_TYPE_INVALID) == FALSE) {
- dbus_message_unref(adapter_reply);
- return FALSE;
- }
-
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "FindDevice");
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
-
- if (adapter_reply != NULL)
- dbus_message_unref(adapter_reply);
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply) {
- message = dbus_message_new_method_call("org.bluez", adapter,
- "org.bluez.Adapter",
- "CreateDevice");
- dbus_message_iter_init_append(message, &iter);
- dbus_message_iter_append_basic(&iter,
- DBUS_TYPE_STRING, &bdaddr);
-
- reply = dbus_connection_send_with_reply_and_block(conn,
- message, -1, NULL);
-
- dbus_message_unref(message);
-
- if (!reply)
- return FALSE;
- }
-
- if (dbus_message_get_args(reply, NULL,
- DBUS_TYPE_OBJECT_PATH, &object_path,
- DBUS_TYPE_INVALID) == FALSE) {
- dbus_message_unref(reply);
- return FALSE;
- }
-
- id = device_get_ieee1284_id(adapter, object_path);
- if (id == NULL) {
- dbus_message_unref(reply);
- return FALSE;
- }
- printf("%s", id);
- g_free(id);
-
- dbus_message_unref(reply);
-
- return TRUE;
-}
-
-/*
- * Usage: printer-uri job-id user title copies options [file]
- *
- */
-
-int main(int argc, char *argv[])
-{
- sdp_session_t *sdp;
- bdaddr_t bdaddr;
- unsigned short ctrl_psm, data_psm;
- uint8_t channel, b[6];
- char *ptr, str[3], device[18], service[12];
- const char *uri, *cups_class;
- int i, err, fd, copies, proto;
-
- /* Make sure status messages are not buffered */
- setbuf(stderr, NULL);
-
- /* Make sure output is not buffered */
- setbuf(stdout, NULL);
-
- /* Ignore SIGPIPE signals */
-#ifdef HAVE_SIGSET
- sigset(SIGPIPE, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
- action.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &action, NULL);
-#else
- signal(SIGPIPE, SIG_IGN);
-#endif /* HAVE_SIGSET */
-
- if (argc == 1) {
- if (list_printers() == TRUE)
- return CUPS_BACKEND_OK;
- else
- return CUPS_BACKEND_FAILED;
- } else if (argc == 3 && strcmp(argv[1], "--get-deviceid") == 0) {
- if (bachk(argv[2]) < 0) {
- fprintf(stderr, "Invalid Bluetooth address '%s'\n",
- argv[2]);
- return CUPS_BACKEND_FAILED;
- }
- if (print_ieee1284(argv[2]) == FALSE)
- return CUPS_BACKEND_FAILED;
- return CUPS_BACKEND_OK;
- }
-
- if (argc < 6 || argc > 7) {
- fprintf(stderr, "Usage: bluetooth job-id user title copies"
- " options [file]\n");
- fprintf(stderr, " bluetooth --get-deviceid [bdaddr]\n");
- return CUPS_BACKEND_FAILED;
- }
-
- if (argc == 6) {
- fd = 0;
- copies = 1;
- } else {
- if ((fd = open(argv[6], O_RDONLY)) < 0) {
- perror("ERROR: Unable to open print file");
- return CUPS_BACKEND_FAILED;
- }
- copies = atoi(argv[4]);
- }
-
- uri = getenv("DEVICE_URI");
- if (!uri)
- uri = argv[0];
-
- if (strncasecmp(uri, "bluetooth://", 12)) {
- fprintf(stderr, "ERROR: No device URI found\n");
- return CUPS_BACKEND_FAILED;
- }
-
- ptr = argv[0] + 12;
- for (i = 0; i < 6; i++) {
- strncpy(str, ptr, 2);
- b[i] = (uint8_t) strtol(str, NULL, 16);
- ptr += 2;
- }
- sprintf(device, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
- b[0], b[1], b[2], b[3], b[4], b[5]);
-
- str2ba(device, &bdaddr);
-
- ptr = strchr(ptr, '/');
- if (ptr) {
- strncpy(service, ptr + 1, 12);
-
- if (!strncasecmp(ptr + 1, "spp", 3))
- proto = 1;
- else if (!strncasecmp(ptr + 1, "hcrp", 4))
- proto = 2;
- else
- proto = 0;
- } else {
- strcpy(service, "auto");
- proto = 0;
- }
-
- cups_class = getenv("CLASS");
-
- fprintf(stderr,
- "DEBUG: %s device %s service %s fd %d copies %d class %s\n",
- argv[0], device, service, fd, copies,
- cups_class ? cups_class : "(none)");
-
- fputs("STATE: +connecting-to-device\n", stderr);
-
-service_search:
- sdp = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
- if (!sdp) {
- fprintf(stderr, "ERROR: Can't open Bluetooth connection\n");
- return CUPS_BACKEND_FAILED;
- }
-
- switch (proto) {
- case 1:
- err = sdp_search_spp(sdp, &channel);
- break;
- case 2:
- err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
- break;
- default:
- proto = 2;
- err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
- if (err) {
- proto = 1;
- err = sdp_search_spp(sdp, &channel);
- }
- break;
- }
-
- sdp_close(sdp);
-
- if (err) {
- if (cups_class) {
- fputs("INFO: Unable to contact printer, queuing on "
- "next printer in class...\n", stderr);
- sleep(5);
- return CUPS_BACKEND_FAILED;
- }
- sleep(20);
- fprintf(stderr, "ERROR: Can't get service information\n");
- goto service_search;
- }
-
-connect:
- switch (proto) {
- case 1:
- err = spp_print(BDADDR_ANY, &bdaddr, channel,
- fd, copies, cups_class);
- break;
- case 2:
- err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm,
- fd, copies, cups_class);
- break;
- default:
- err = CUPS_BACKEND_FAILED;
- fprintf(stderr, "ERROR: Unsupported protocol\n");
- break;
- }
-
- if (err == CUPS_BACKEND_FAILED && cups_class) {
- fputs("INFO: Unable to contact printer, queuing on "
- "next printer in class...\n", stderr);
- sleep(5);
- return CUPS_BACKEND_FAILED;
- } else if (err == CUPS_BACKEND_RETRY) {
- sleep(20);
- goto connect;
- }
-
- if (fd != 0)
- close(fd);
-
- if (!err)
- fprintf(stderr, "INFO: Ready to print\n");
-
- return err;
-}
diff --git a/cups/sdp.c b/cups/sdp.c
deleted file mode 100644
index c7f17a4..0000000
--- a/cups/sdp.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include "cups.h"
-
-int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm)
-{
- sdp_list_t *srch, *attrs, *rsp;
- uuid_t svclass;
- uint16_t attr1, attr2;
- int err;
-
- if (!sdp)
- return -1;
-
- sdp_uuid16_create(&svclass, HCR_PRINT_SVCLASS_ID);
- srch = sdp_list_append(NULL, &svclass);
-
- attr1 = SDP_ATTR_PROTO_DESC_LIST;
- attrs = sdp_list_append(NULL, &attr1);
- attr2 = SDP_ATTR_ADD_PROTO_DESC_LIST;
- attrs = sdp_list_append(attrs, &attr2);
-
- err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
- if (err)
- return -1;
-
- for (; rsp; rsp = rsp->next) {
- sdp_record_t *rec = (sdp_record_t *) rsp->data;
- sdp_list_t *protos;
-
- if (!sdp_get_access_protos(rec, &protos)) {
- unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
- if (psm > 0) {
- *ctrl_psm = psm;
- }
- }
-
- if (!sdp_get_add_access_protos(rec, &protos)) {
- unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
- if (psm > 0 && *ctrl_psm > 0) {
- *data_psm = psm;
- return 0;
- }
- }
- }
-
- return -1;
-}
-
-int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel)
-{
- sdp_list_t *srch, *attrs, *rsp;
- uuid_t svclass;
- uint16_t attr;
- int err;
-
- if (!sdp)
- return -1;
-
- sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
- srch = sdp_list_append(NULL, &svclass);
-
- attr = SDP_ATTR_PROTO_DESC_LIST;
- attrs = sdp_list_append(NULL, &attr);
-
- err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
- if (err)
- return -1;
-
- for (; rsp; rsp = rsp->next) {
- sdp_record_t *rec = (sdp_record_t *) rsp->data;
- sdp_list_t *protos;
-
- if (!sdp_get_access_protos(rec, &protos)) {
- uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
- if (ch > 0) {
- *channel = ch;
- return 0;
- }
- }
- }
-
- return -1;
-}
diff --git a/cups/spp.c b/cups/spp.c
deleted file mode 100644
index d906ed2..0000000
--- a/cups/spp.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/socket.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include "cups.h"
-
-int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class)
-{
- struct sockaddr_rc addr;
- unsigned char buf[2048];
- int i, sk, err, len;
-
- if ((sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
- perror("ERROR: Can't create socket");
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, src);
- addr.rc_channel = 0;
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't bind socket");
- close(sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, dst);
- addr.rc_channel = channel;
-
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("ERROR: Can't connect to device");
- close(sk);
- if (cups_class)
- return CUPS_BACKEND_FAILED;
- else
- return CUPS_BACKEND_RETRY;
- }
-
- fputs("STATE: -connecting-to-device\n", stderr);
-
- /* Ignore SIGTERM signals if printing from stdin */
- if (fd == 0) {
-#ifdef HAVE_SIGSET
- sigset(SIGTERM, SIG_IGN);
-#elif defined(HAVE_SIGACTION)
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = SIG_IGN;
- sigaction(SIGTERM, &action, NULL);
-#else
- signal(SIGTERM, SIG_IGN);
-#endif /* HAVE_SIGSET */
- }
-
- for (i = 0; i < copies; i++) {
-
- if (fd != 0) {
- fprintf(stderr, "PAGE: 1 1\n");
- lseek(fd, 0, SEEK_SET);
- }
-
- while ((len = read(fd, buf, sizeof(buf))) > 0) {
- err = write(sk, buf, len);
- if (err < 0) {
- perror("ERROR: Error writing to device");
- close(sk);
- return CUPS_BACKEND_FAILED;
- }
- }
-
- }
-
- close(sk);
-
- return CUPS_BACKEND_OK;
-}
diff --git a/profiles/cups/cups.h b/profiles/cups/cups.h
new file mode 100644
index 0000000..f4e0c01
--- /dev/null
+++ b/profiles/cups/cups.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum { /**** Backend exit codes ****/
+ CUPS_BACKEND_OK = 0, /* Job completed successfully */
+ CUPS_BACKEND_FAILED = 1, /* Job failed, use error-policy */
+ CUPS_BACKEND_AUTH_REQUIRED = 2, /* Job failed, authentication required */
+ CUPS_BACKEND_HOLD = 3, /* Job failed, hold job */
+ CUPS_BACKEND_STOP = 4, /* Job failed, stop queue */
+ CUPS_BACKEND_CANCEL = 5, /* Job failed, cancel job */
+ CUPS_BACKEND_RETRY = 6, /* Failure requires us to retry (BlueZ specific) */
+};
+
+int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
+int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm);
+
+int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class);
+int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class);
diff --git a/profiles/cups/hcrp.c b/profiles/cups/hcrp.c
new file mode 100644
index 0000000..a93dda0
--- /dev/null
+++ b/profiles/cups/hcrp.c
@@ -0,0 +1,368 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <netinet/in.h>
+
+#include "cups.h"
+
+#define HCRP_PDU_CREDIT_GRANT 0x0001
+#define HCRP_PDU_CREDIT_REQUEST 0x0002
+#define HCRP_PDU_GET_LPT_STATUS 0x0005
+
+#define HCRP_STATUS_FEATURE_UNSUPPORTED 0x0000
+#define HCRP_STATUS_SUCCESS 0x0001
+#define HCRP_STATUS_CREDIT_SYNC_ERROR 0x0002
+#define HCRP_STATUS_GENERIC_FAILURE 0xffff
+
+struct hcrp_pdu_hdr {
+ uint16_t pid;
+ uint16_t tid;
+ uint16_t plen;
+} __attribute__ ((packed));
+#define HCRP_PDU_HDR_SIZE 6
+
+struct hcrp_credit_grant_cp {
+ uint32_t credit;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_GRANT_CP_SIZE 4
+
+struct hcrp_credit_grant_rp {
+ uint16_t status;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_GRANT_RP_SIZE 2
+
+struct hcrp_credit_request_rp {
+ uint16_t status;
+ uint32_t credit;
+} __attribute__ ((packed));
+#define HCRP_CREDIT_REQUEST_RP_SIZE 6
+
+struct hcrp_get_lpt_status_rp {
+ uint16_t status;
+ uint8_t lpt_status;
+} __attribute__ ((packed));
+#define HCRP_GET_LPT_STATUS_RP_SIZE 3
+
+static int hcrp_credit_grant(int sk, uint16_t tid, uint32_t credit)
+{
+ struct hcrp_pdu_hdr hdr;
+ struct hcrp_credit_grant_cp cp;
+ struct hcrp_credit_grant_rp rp;
+ unsigned char buf[128];
+ int len;
+
+ hdr.pid = htons(HCRP_PDU_CREDIT_GRANT);
+ hdr.tid = htons(tid);
+ hdr.plen = htons(HCRP_CREDIT_GRANT_CP_SIZE);
+ cp.credit = credit;
+ memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+ memcpy(buf + HCRP_PDU_HDR_SIZE, &cp, HCRP_CREDIT_GRANT_CP_SIZE);
+ len = write(sk, buf, HCRP_PDU_HDR_SIZE + HCRP_CREDIT_GRANT_CP_SIZE);
+ if (len < 0)
+ return len;
+
+ len = read(sk, buf, sizeof(buf));
+ if (len < 0)
+ return len;
+
+ memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+ memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_GRANT_RP_SIZE);
+
+ if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int hcrp_credit_request(int sk, uint16_t tid, uint32_t *credit)
+{
+ struct hcrp_pdu_hdr hdr;
+ struct hcrp_credit_request_rp rp;
+ unsigned char buf[128];
+ int len;
+
+ hdr.pid = htons(HCRP_PDU_CREDIT_REQUEST);
+ hdr.tid = htons(tid);
+ hdr.plen = htons(0);
+ memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+ len = write(sk, buf, HCRP_PDU_HDR_SIZE);
+ if (len < 0)
+ return len;
+
+ len = read(sk, buf, sizeof(buf));
+ if (len < 0)
+ return len;
+
+ memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+ memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_CREDIT_REQUEST_RP_SIZE);
+
+ if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (credit)
+ *credit = ntohl(rp.credit);
+
+ return 0;
+}
+
+static int hcrp_get_lpt_status(int sk, uint16_t tid, uint8_t *lpt_status)
+{
+ struct hcrp_pdu_hdr hdr;
+ struct hcrp_get_lpt_status_rp rp;
+ unsigned char buf[128];
+ int len;
+
+ hdr.pid = htons(HCRP_PDU_GET_LPT_STATUS);
+ hdr.tid = htons(tid);
+ hdr.plen = htons(0);
+ memcpy(buf, &hdr, HCRP_PDU_HDR_SIZE);
+ len = write(sk, buf, HCRP_PDU_HDR_SIZE);
+ if (len < 0)
+ return len;
+
+ len = read(sk, buf, sizeof(buf));
+ if (len < 0)
+ return len;
+
+ memcpy(&hdr, buf, HCRP_PDU_HDR_SIZE);
+ memcpy(&rp, buf + HCRP_PDU_HDR_SIZE, HCRP_GET_LPT_STATUS_RP_SIZE);
+
+ if (ntohs(rp.status) != HCRP_STATUS_SUCCESS) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (lpt_status)
+ *lpt_status = rp.lpt_status;
+
+ return 0;
+}
+
+static inline int hcrp_get_next_tid(int tid)
+{
+ if (tid > 0xf000)
+ return 0;
+ else
+ return tid + 1;
+}
+
+int hcrp_print(bdaddr_t *src, bdaddr_t *dst, unsigned short ctrl_psm, unsigned short data_psm, int fd, int copies, const char *cups_class)
+{
+ struct sockaddr_l2 addr;
+ struct l2cap_options opts;
+ socklen_t size;
+ unsigned char buf[2048];
+ int i, ctrl_sk, data_sk, count, len, timeout = 0;
+ unsigned int mtu;
+ uint8_t status;
+ uint16_t tid = 0;
+ uint32_t tmp, credit = 0;
+
+ if ((ctrl_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
+ perror("ERROR: Can't create socket");
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, src);
+
+ if (bind(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't bind socket");
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, dst);
+ addr.l2_psm = htobs(ctrl_psm);
+
+ if (connect(ctrl_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't connect to device");
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ if ((data_sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
+ perror("ERROR: Can't create socket");
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, src);
+
+ if (bind(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't bind socket");
+ close(data_sk);
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.l2_family = AF_BLUETOOTH;
+ bacpy(&addr.l2_bdaddr, dst);
+ addr.l2_psm = htobs(data_psm);
+
+ if (connect(data_sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't connect to device");
+ close(data_sk);
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ fputs("STATE: -connecting-to-device\n", stderr);
+
+ memset(&opts, 0, sizeof(opts));
+ size = sizeof(opts);
+
+ if (getsockopt(data_sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
+ perror("ERROR: Can't get socket options");
+ close(data_sk);
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ mtu = opts.omtu;
+
+ /* Ignore SIGTERM signals if printing from stdin */
+ if (fd == 0) {
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ tid = hcrp_get_next_tid(tid);
+ if (hcrp_credit_grant(ctrl_sk, tid, 0) < 0) {
+ fprintf(stderr, "ERROR: Can't grant initial credits\n");
+ close(data_sk);
+ close(ctrl_sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ for (i = 0; i < copies; i++) {
+
+ if (fd != 0) {
+ fprintf(stderr, "PAGE: 1 1\n");
+ lseek(fd, 0, SEEK_SET);
+ }
+
+ while (1) {
+ if (credit < mtu) {
+ tid = hcrp_get_next_tid(tid);
+ if (!hcrp_credit_request(ctrl_sk, tid, &tmp)) {
+ credit += tmp;
+ timeout = 0;
+ }
+ }
+
+ if (!credit) {
+ if (timeout++ > 300) {
+ tid = hcrp_get_next_tid(tid);
+ if (!hcrp_get_lpt_status(ctrl_sk, tid, &status))
+ fprintf(stderr, "ERROR: LPT status 0x%02x\n", status);
+ break;
+ }
+
+ sleep(1);
+ continue;
+ }
+
+ count = read(fd, buf, (credit > mtu) ? mtu : credit);
+ if (count <= 0)
+ break;
+
+ len = write(data_sk, buf, count);
+ if (len < 0) {
+ perror("ERROR: Error writing to device");
+ close(data_sk);
+ close(ctrl_sk);
+ return CUPS_BACKEND_FAILED;
+ }
+
+ if (len != count)
+ fprintf(stderr, "ERROR: Can't send complete data\n");
+
+ credit -= len;
+ }
+
+ }
+
+ close(data_sk);
+ close(ctrl_sk);
+
+ return CUPS_BACKEND_OK;
+}
diff --git a/profiles/cups/main.c b/profiles/cups/main.c
new file mode 100644
index 0000000..a884c6e
--- /dev/null
+++ b/profiles/cups/main.c
@@ -0,0 +1,896 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <gdbus.h>
+
+#include "cups.h"
+
+struct cups_device {
+ char *bdaddr;
+ char *name;
+ char *id;
+};
+
+static GSList *device_list = NULL;
+static GMainLoop *loop = NULL;
+static DBusConnection *conn = NULL;
+static gboolean doing_disco = FALSE;
+
+#define ATTRID_1284ID 0x0300
+
+struct context_data {
+ gboolean found;
+ char *id;
+};
+
+static void element_start(GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data, GError **err)
+{
+ struct context_data *ctx_data = user_data;
+
+ if (!strcmp(element_name, "record"))
+ return;
+
+ if (!strcmp(element_name, "attribute")) {
+ int i;
+ for (i = 0; attribute_names[i]; i++) {
+ if (strcmp(attribute_names[i], "id") != 0)
+ continue;
+ if (strtol(attribute_values[i], 0, 0) == ATTRID_1284ID)
+ ctx_data->found = TRUE;
+ break;
+ }
+ return;
+ }
+
+ if (ctx_data->found && !strcmp(element_name, "text")) {
+ int i;
+ for (i = 0; attribute_names[i]; i++) {
+ if (!strcmp(attribute_names[i], "value")) {
+ ctx_data->id = g_strdup(attribute_values[i] + 2);
+ ctx_data->found = FALSE;
+ }
+ }
+ }
+}
+
+static GMarkupParser parser = {
+ element_start, NULL, NULL, NULL, NULL
+};
+
+static char *sdp_xml_parse_record(const char *data)
+{
+ GMarkupParseContext *ctx;
+ struct context_data ctx_data;
+ int size;
+
+ size = strlen(data);
+ ctx_data.found = FALSE;
+ ctx_data.id = NULL;
+ ctx = g_markup_parse_context_new(&parser, 0, &ctx_data, NULL);
+
+ if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
+ g_markup_parse_context_free(ctx);
+ g_free(ctx_data.id);
+ return NULL;
+ }
+
+ g_markup_parse_context_free(ctx);
+
+ return ctx_data.id;
+}
+
+static char *device_get_ieee1284_id(const char *adapter, const char *device)
+{
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, reply_iter;
+ DBusMessageIter reply_iter_entry;
+ const char *hcr_print = "00001126-0000-1000-8000-00805f9b34fb";
+ const char *xml;
+ char *id = NULL;
+
+ /* Look for the service handle of the HCRP service */
+ message = dbus_message_new_method_call("org.bluez", device,
+ "org.bluez.Device",
+ "DiscoverServices");
+ dbus_message_iter_init_append(message, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &hcr_print);
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init(reply, &reply_iter);
+
+ if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
+ dbus_message_unref(reply);
+ return NULL;
+ }
+
+ dbus_message_iter_recurse(&reply_iter, &reply_iter_entry);
+
+ /* Hopefully we only get one handle, or take a punt */
+ while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
+ DBUS_TYPE_DICT_ENTRY) {
+ guint32 key;
+ DBusMessageIter dict_entry;
+
+ dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
+
+ /* Key ? */
+ dbus_message_iter_get_basic(&dict_entry, &key);
+ if (!key) {
+ dbus_message_iter_next(&reply_iter_entry);
+ continue;
+ }
+
+ /* Try to get the value */
+ if (!dbus_message_iter_next(&dict_entry)) {
+ dbus_message_iter_next(&reply_iter_entry);
+ continue;
+ }
+
+ dbus_message_iter_get_basic(&dict_entry, &xml);
+
+ id = sdp_xml_parse_record(xml);
+ if (id != NULL)
+ break;
+ dbus_message_iter_next(&reply_iter_entry);
+ }
+
+ dbus_message_unref(reply);
+
+ return id;
+}
+
+static void print_printer_details(const char *name, const char *bdaddr,
+ const char *id)
+{
+ char *uri, *escaped;
+
+ escaped = g_strdelimit(g_strdup(name), "\"", '\'');
+ uri = g_strdup_printf("bluetooth://%c%c%c%c%c%c%c%c%c%c%c%c",
+ bdaddr[0], bdaddr[1],
+ bdaddr[3], bdaddr[4],
+ bdaddr[6], bdaddr[7],
+ bdaddr[9], bdaddr[10],
+ bdaddr[12], bdaddr[13],
+ bdaddr[15], bdaddr[16]);
+ printf("direct %s \"%s\" \"%s (Bluetooth)\"", uri, escaped, escaped);
+ if (id != NULL)
+ printf(" \"%s\"\n", id);
+ else
+ printf("\n");
+ g_free(escaped);
+ g_free(uri);
+}
+
+static void add_device_to_list(const char *name, const char *bdaddr,
+ const char *id)
+{
+ struct cups_device *device;
+ GSList *l;
+
+ /* Look for the device in the list */
+ for (l = device_list; l != NULL; l = l->next) {
+ device = (struct cups_device *) l->data;
+
+ if (strcmp(device->bdaddr, bdaddr) == 0) {
+ if (device->name != name) {
+ g_free(device->name);
+ device->name = g_strdup(name);
+ }
+ g_free(device->id);
+ device->id = g_strdup(id);
+ return;
+ }
+ }
+
+ /* Or add it to the list if it's not there */
+ device = g_new0(struct cups_device, 1);
+ device->bdaddr = g_strdup(bdaddr);
+ device->name = g_strdup(name);
+ device->id = g_strdup(id);
+
+ device_list = g_slist_prepend(device_list, device);
+ print_printer_details(device->name, device->bdaddr, device->id);
+}
+
+static gboolean parse_device_properties(DBusMessageIter *reply_iter,
+ char **name, char **bdaddr)
+{
+ guint32 class = 0;
+ DBusMessageIter reply_iter_entry;
+
+ if (dbus_message_iter_get_arg_type(reply_iter) != DBUS_TYPE_ARRAY)
+ return FALSE;
+
+ dbus_message_iter_recurse(reply_iter, &reply_iter_entry);
+
+ while (dbus_message_iter_get_arg_type(&reply_iter_entry) ==
+ DBUS_TYPE_DICT_ENTRY) {
+ const char *key;
+ DBusMessageIter dict_entry, iter_dict_val;
+
+ dbus_message_iter_recurse(&reply_iter_entry, &dict_entry);
+
+ /* Key == Class ? */
+ dbus_message_iter_get_basic(&dict_entry, &key);
+ if (!key) {
+ dbus_message_iter_next(&reply_iter_entry);
+ continue;
+ }
+
+ if (strcmp(key, "Class") != 0 &&
+ strcmp(key, "Alias") != 0 &&
+ strcmp(key, "Address") != 0) {
+ dbus_message_iter_next(&reply_iter_entry);
+ continue;
+ }
+
+ /* Try to get the value */
+ if (!dbus_message_iter_next(&dict_entry)) {
+ dbus_message_iter_next(&reply_iter_entry);
+ continue;
+ }
+ dbus_message_iter_recurse(&dict_entry, &iter_dict_val);
+ if (strcmp(key, "Class") == 0) {
+ dbus_message_iter_get_basic(&iter_dict_val, &class);
+ } else {
+ const char *value;
+ dbus_message_iter_get_basic(&iter_dict_val, &value);
+ if (strcmp(key, "Alias") == 0) {
+ *name = g_strdup(value);
+ } else if (bdaddr) {
+ *bdaddr = g_strdup(value);
+ }
+ }
+ dbus_message_iter_next(&reply_iter_entry);
+ }
+
+ if (class == 0)
+ return FALSE;
+ if (((class & 0x1f00) >> 8) == 0x06 && (class & 0x80))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean device_is_printer(const char *adapter, const char *device_path, char **name, char **bdaddr)
+{
+ DBusMessage *message, *reply;
+ DBusMessageIter reply_iter;
+ gboolean retval;
+
+ message = dbus_message_new_method_call("org.bluez", device_path,
+ "org.bluez.Device",
+ "GetProperties");
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply)
+ return FALSE;
+
+ dbus_message_iter_init(reply, &reply_iter);
+
+ retval = parse_device_properties(&reply_iter, name, bdaddr);
+
+ dbus_message_unref(reply);
+
+ return retval;
+}
+
+static void remote_device_found(const char *adapter, const char *bdaddr,
+ const char *name)
+{
+ DBusMessage *message, *reply, *adapter_reply;
+ DBusMessageIter iter;
+ char *object_path = NULL;
+ char *id;
+
+ adapter_reply = NULL;
+
+ if (adapter == NULL) {
+ message = dbus_message_new_method_call("org.bluez", "/",
+ "org.bluez.Manager",
+ "DefaultAdapter");
+
+ adapter_reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!adapter_reply)
+ return;
+
+ if (dbus_message_get_args(adapter_reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &adapter,
+ DBUS_TYPE_INVALID) == FALSE) {
+ dbus_message_unref(adapter_reply);
+ return;
+ }
+ }
+
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "FindDevice");
+ dbus_message_iter_init_append(message, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+ if (adapter_reply != NULL)
+ dbus_message_unref(adapter_reply);
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply) {
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "CreateDevice");
+ dbus_message_iter_init_append(message, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply)
+ return;
+ }
+
+ if (dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &object_path,
+ DBUS_TYPE_INVALID) == FALSE) {
+ dbus_message_unref(reply);
+ return;
+ }
+
+ id = device_get_ieee1284_id(adapter, object_path);
+ add_device_to_list(name, bdaddr, id);
+ g_free(id);
+
+ dbus_message_unref(reply);
+}
+
+static void discovery_completed(void)
+{
+ g_slist_free(device_list);
+ device_list = NULL;
+
+ g_main_loop_quit(loop);
+}
+
+static void remote_device_disappeared(const char *bdaddr)
+{
+ GSList *l;
+
+ for (l = device_list; l != NULL; l = l->next) {
+ struct cups_device *device = l->data;
+
+ if (strcmp(device->bdaddr, bdaddr) == 0) {
+ g_free(device->name);
+ g_free(device->bdaddr);
+ g_free(device);
+ device_list = g_slist_delete_link(device_list, l);
+ return;
+ }
+ }
+}
+
+static gboolean list_known_printers(const char *adapter)
+{
+ DBusMessageIter reply_iter, iter_array;
+ DBusError error;
+ DBusMessage *message, *reply;
+
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "ListDevices");
+ if (message == NULL)
+ return FALSE;
+
+ dbus_error_init(&error);
+ reply = dbus_connection_send_with_reply_and_block(conn, message,
+ -1, &error);
+
+ dbus_message_unref(message);
+
+ if (dbus_error_is_set(&error))
+ return FALSE;
+
+ dbus_message_iter_init(reply, &reply_iter);
+ if (dbus_message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_ARRAY) {
+ dbus_message_unref(reply);
+ return FALSE;
+ }
+
+ dbus_message_iter_recurse(&reply_iter, &iter_array);
+ while (dbus_message_iter_get_arg_type(&iter_array) ==
+ DBUS_TYPE_OBJECT_PATH) {
+ const char *object_path;
+ char *name = NULL;
+ char *bdaddr = NULL;
+
+ dbus_message_iter_get_basic(&iter_array, &object_path);
+ if (device_is_printer(adapter, object_path, &name, &bdaddr)) {
+ char *id;
+
+ id = device_get_ieee1284_id(adapter, object_path);
+ add_device_to_list(name, bdaddr, id);
+ g_free(id);
+ }
+ g_free(name);
+ g_free(bdaddr);
+ dbus_message_iter_next(&iter_array);
+ }
+
+ dbus_message_unref(reply);
+
+ return FALSE;
+}
+
+static DBusHandlerResult filter_func(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ if (dbus_message_is_signal(message, "org.bluez.Adapter",
+ "DeviceFound")) {
+ const char *adapter, *bdaddr;
+ char *name;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &bdaddr);
+ dbus_message_iter_next(&iter);
+
+ adapter = dbus_message_get_path(message);
+ if (parse_device_properties(&iter, &name, NULL))
+ remote_device_found(adapter, bdaddr, name);
+ g_free (name);
+ } else if (dbus_message_is_signal(message, "org.bluez.Adapter",
+ "DeviceDisappeared")) {
+ const char *bdaddr;
+
+ dbus_message_get_args(message, NULL,
+ DBUS_TYPE_STRING, &bdaddr,
+ DBUS_TYPE_INVALID);
+ remote_device_disappeared(bdaddr);
+ } else if (dbus_message_is_signal(message, "org.bluez.Adapter",
+ "PropertyChanged")) {
+ DBusMessageIter iter, value_iter;
+ const char *name;
+ gboolean discovering;
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &name);
+ if (name == NULL || strcmp(name, "Discovering") != 0)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &value_iter);
+ dbus_message_iter_get_basic(&value_iter, &discovering);
+
+ if (discovering == FALSE && doing_disco) {
+ doing_disco = FALSE;
+ discovery_completed();
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean list_printers(void)
+{
+ /* 1. Connect to the bus
+ * 2. Get the manager
+ * 3. Get the default adapter
+ * 4. Get a list of devices
+ * 5. Get the class of each device
+ * 6. Print the details from each printer device
+ */
+ DBusError error;
+ dbus_bool_t hcid_exists;
+ DBusMessage *reply, *message;
+ DBusMessageIter reply_iter;
+ char *adapter, *match;
+
+ conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+ if (conn == NULL)
+ return TRUE;
+
+ dbus_error_init(&error);
+ hcid_exists = dbus_bus_name_has_owner(conn, "org.bluez", &error);
+ if (dbus_error_is_set(&error))
+ return TRUE;
+
+ if (!hcid_exists)
+ return TRUE;
+
+ /* Get the default adapter */
+ message = dbus_message_new_method_call("org.bluez", "/",
+ "org.bluez.Manager",
+ "DefaultAdapter");
+ if (message == NULL) {
+ dbus_connection_unref(conn);
+ return FALSE;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, &error);
+
+ dbus_message_unref(message);
+
+ if (dbus_error_is_set(&error)) {
+ dbus_connection_unref(conn);
+ /* No adapter */
+ return TRUE;
+ }
+
+ dbus_message_iter_init(reply, &reply_iter);
+ if (dbus_message_iter_get_arg_type(&reply_iter) !=
+ DBUS_TYPE_OBJECT_PATH) {
+ dbus_message_unref(reply);
+ dbus_connection_unref(conn);
+ return FALSE;
+ }
+
+ dbus_message_iter_get_basic(&reply_iter, &adapter);
+ adapter = g_strdup(adapter);
+ dbus_message_unref(reply);
+
+ if (!dbus_connection_add_filter(conn, filter_func, adapter, g_free)) {
+ g_free(adapter);
+ dbus_connection_unref(conn);
+ return FALSE;
+ }
+
+#define MATCH_FORMAT \
+ "type='signal'," \
+ "interface='org.bluez.Adapter'," \
+ "sender='org.bluez'," \
+ "path='%s'"
+
+ match = g_strdup_printf(MATCH_FORMAT, adapter);
+ dbus_bus_add_match(conn, match, &error);
+ g_free(match);
+
+ /* Add the the recent devices */
+ list_known_printers(adapter);
+
+ doing_disco = TRUE;
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "StartDiscovery");
+
+ if (!dbus_connection_send_with_reply(conn, message, NULL, -1)) {
+ dbus_message_unref(message);
+ dbus_connection_unref(conn);
+ g_free(adapter);
+ return FALSE;
+ }
+ dbus_message_unref(message);
+
+ loop = g_main_loop_new(NULL, TRUE);
+ g_main_loop_run(loop);
+
+ g_free(adapter);
+ dbus_connection_unref(conn);
+
+ return TRUE;
+}
+
+static gboolean print_ieee1284(const char *bdaddr)
+{
+ DBusMessage *message, *reply, *adapter_reply;
+ DBusMessageIter iter;
+ char *object_path = NULL;
+ char *adapter;
+ char *id;
+
+ adapter_reply = NULL;
+
+ conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+ if (conn == NULL)
+ return FALSE;
+
+ message = dbus_message_new_method_call("org.bluez", "/",
+ "org.bluez.Manager",
+ "DefaultAdapter");
+
+ adapter_reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!adapter_reply)
+ return FALSE;
+
+ if (dbus_message_get_args(adapter_reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &adapter,
+ DBUS_TYPE_INVALID) == FALSE) {
+ dbus_message_unref(adapter_reply);
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "FindDevice");
+ dbus_message_iter_init_append(message, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bdaddr);
+
+ if (adapter_reply != NULL)
+ dbus_message_unref(adapter_reply);
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply) {
+ message = dbus_message_new_method_call("org.bluez", adapter,
+ "org.bluez.Adapter",
+ "CreateDevice");
+ dbus_message_iter_init_append(message, &iter);
+ dbus_message_iter_append_basic(&iter,
+ DBUS_TYPE_STRING, &bdaddr);
+
+ reply = dbus_connection_send_with_reply_and_block(conn,
+ message, -1, NULL);
+
+ dbus_message_unref(message);
+
+ if (!reply)
+ return FALSE;
+ }
+
+ if (dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &object_path,
+ DBUS_TYPE_INVALID) == FALSE) {
+ dbus_message_unref(reply);
+ return FALSE;
+ }
+
+ id = device_get_ieee1284_id(adapter, object_path);
+ if (id == NULL) {
+ dbus_message_unref(reply);
+ return FALSE;
+ }
+ printf("%s", id);
+ g_free(id);
+
+ dbus_message_unref(reply);
+
+ return TRUE;
+}
+
+/*
+ * Usage: printer-uri job-id user title copies options [file]
+ *
+ */
+
+int main(int argc, char *argv[])
+{
+ sdp_session_t *sdp;
+ bdaddr_t bdaddr;
+ unsigned short ctrl_psm, data_psm;
+ uint8_t channel, b[6];
+ char *ptr, str[3], device[18], service[12];
+ const char *uri, *cups_class;
+ int i, err, fd, copies, proto;
+
+ /* Make sure status messages are not buffered */
+ setbuf(stderr, NULL);
+
+ /* Make sure output is not buffered */
+ setbuf(stdout, NULL);
+
+ /* Ignore SIGPIPE signals */
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ if (argc == 1) {
+ if (list_printers() == TRUE)
+ return CUPS_BACKEND_OK;
+ else
+ return CUPS_BACKEND_FAILED;
+ } else if (argc == 3 && strcmp(argv[1], "--get-deviceid") == 0) {
+ if (bachk(argv[2]) < 0) {
+ fprintf(stderr, "Invalid Bluetooth address '%s'\n",
+ argv[2]);
+ return CUPS_BACKEND_FAILED;
+ }
+ if (print_ieee1284(argv[2]) == FALSE)
+ return CUPS_BACKEND_FAILED;
+ return CUPS_BACKEND_OK;
+ }
+
+ if (argc < 6 || argc > 7) {
+ fprintf(stderr, "Usage: bluetooth job-id user title copies"
+ " options [file]\n");
+ fprintf(stderr, " bluetooth --get-deviceid [bdaddr]\n");
+ return CUPS_BACKEND_FAILED;
+ }
+
+ if (argc == 6) {
+ fd = 0;
+ copies = 1;
+ } else {
+ if ((fd = open(argv[6], O_RDONLY)) < 0) {
+ perror("ERROR: Unable to open print file");
+ return CUPS_BACKEND_FAILED;
+ }
+ copies = atoi(argv[4]);
+ }
+
+ uri = getenv("DEVICE_URI");
+ if (!uri)
+ uri = argv[0];
+
+ if (strncasecmp(uri, "bluetooth://", 12)) {
+ fprintf(stderr, "ERROR: No device URI found\n");
+ return CUPS_BACKEND_FAILED;
+ }
+
+ ptr = argv[0] + 12;
+ for (i = 0; i < 6; i++) {
+ strncpy(str, ptr, 2);
+ b[i] = (uint8_t) strtol(str, NULL, 16);
+ ptr += 2;
+ }
+ sprintf(device, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+ b[0], b[1], b[2], b[3], b[4], b[5]);
+
+ str2ba(device, &bdaddr);
+
+ ptr = strchr(ptr, '/');
+ if (ptr) {
+ strncpy(service, ptr + 1, 12);
+
+ if (!strncasecmp(ptr + 1, "spp", 3))
+ proto = 1;
+ else if (!strncasecmp(ptr + 1, "hcrp", 4))
+ proto = 2;
+ else
+ proto = 0;
+ } else {
+ strcpy(service, "auto");
+ proto = 0;
+ }
+
+ cups_class = getenv("CLASS");
+
+ fprintf(stderr,
+ "DEBUG: %s device %s service %s fd %d copies %d class %s\n",
+ argv[0], device, service, fd, copies,
+ cups_class ? cups_class : "(none)");
+
+ fputs("STATE: +connecting-to-device\n", stderr);
+
+service_search:
+ sdp = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
+ if (!sdp) {
+ fprintf(stderr, "ERROR: Can't open Bluetooth connection\n");
+ return CUPS_BACKEND_FAILED;
+ }
+
+ switch (proto) {
+ case 1:
+ err = sdp_search_spp(sdp, &channel);
+ break;
+ case 2:
+ err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
+ break;
+ default:
+ proto = 2;
+ err = sdp_search_hcrp(sdp, &ctrl_psm, &data_psm);
+ if (err) {
+ proto = 1;
+ err = sdp_search_spp(sdp, &channel);
+ }
+ break;
+ }
+
+ sdp_close(sdp);
+
+ if (err) {
+ if (cups_class) {
+ fputs("INFO: Unable to contact printer, queuing on "
+ "next printer in class...\n", stderr);
+ sleep(5);
+ return CUPS_BACKEND_FAILED;
+ }
+ sleep(20);
+ fprintf(stderr, "ERROR: Can't get service information\n");
+ goto service_search;
+ }
+
+connect:
+ switch (proto) {
+ case 1:
+ err = spp_print(BDADDR_ANY, &bdaddr, channel,
+ fd, copies, cups_class);
+ break;
+ case 2:
+ err = hcrp_print(BDADDR_ANY, &bdaddr, ctrl_psm, data_psm,
+ fd, copies, cups_class);
+ break;
+ default:
+ err = CUPS_BACKEND_FAILED;
+ fprintf(stderr, "ERROR: Unsupported protocol\n");
+ break;
+ }
+
+ if (err == CUPS_BACKEND_FAILED && cups_class) {
+ fputs("INFO: Unable to contact printer, queuing on "
+ "next printer in class...\n", stderr);
+ sleep(5);
+ return CUPS_BACKEND_FAILED;
+ } else if (err == CUPS_BACKEND_RETRY) {
+ sleep(20);
+ goto connect;
+ }
+
+ if (fd != 0)
+ close(fd);
+
+ if (!err)
+ fprintf(stderr, "INFO: Ready to print\n");
+
+ return err;
+}
diff --git a/profiles/cups/sdp.c b/profiles/cups/sdp.c
new file mode 100644
index 0000000..c7f17a4
--- /dev/null
+++ b/profiles/cups/sdp.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "cups.h"
+
+int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm)
+{
+ sdp_list_t *srch, *attrs, *rsp;
+ uuid_t svclass;
+ uint16_t attr1, attr2;
+ int err;
+
+ if (!sdp)
+ return -1;
+
+ sdp_uuid16_create(&svclass, HCR_PRINT_SVCLASS_ID);
+ srch = sdp_list_append(NULL, &svclass);
+
+ attr1 = SDP_ATTR_PROTO_DESC_LIST;
+ attrs = sdp_list_append(NULL, &attr1);
+ attr2 = SDP_ATTR_ADD_PROTO_DESC_LIST;
+ attrs = sdp_list_append(attrs, &attr2);
+
+ err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
+ if (err)
+ return -1;
+
+ for (; rsp; rsp = rsp->next) {
+ sdp_record_t *rec = (sdp_record_t *) rsp->data;
+ sdp_list_t *protos;
+
+ if (!sdp_get_access_protos(rec, &protos)) {
+ unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
+ if (psm > 0) {
+ *ctrl_psm = psm;
+ }
+ }
+
+ if (!sdp_get_add_access_protos(rec, &protos)) {
+ unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID);
+ if (psm > 0 && *ctrl_psm > 0) {
+ *data_psm = psm;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel)
+{
+ sdp_list_t *srch, *attrs, *rsp;
+ uuid_t svclass;
+ uint16_t attr;
+ int err;
+
+ if (!sdp)
+ return -1;
+
+ sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID);
+ srch = sdp_list_append(NULL, &svclass);
+
+ attr = SDP_ATTR_PROTO_DESC_LIST;
+ attrs = sdp_list_append(NULL, &attr);
+
+ err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
+ if (err)
+ return -1;
+
+ for (; rsp; rsp = rsp->next) {
+ sdp_record_t *rec = (sdp_record_t *) rsp->data;
+ sdp_list_t *protos;
+
+ if (!sdp_get_access_protos(rec, &protos)) {
+ uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID);
+ if (ch > 0) {
+ *channel = ch;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
diff --git a/profiles/cups/spp.c b/profiles/cups/spp.c
new file mode 100644
index 0000000..d906ed2
--- /dev/null
+++ b/profiles/cups/spp.c
@@ -0,0 +1,118 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2003-2010 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "cups.h"
+
+int spp_print(bdaddr_t *src, bdaddr_t *dst, uint8_t channel, int fd, int copies, const char *cups_class)
+{
+ struct sockaddr_rc addr;
+ unsigned char buf[2048];
+ int i, sk, err, len;
+
+ if ((sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
+ perror("ERROR: Can't create socket");
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ addr.rc_family = AF_BLUETOOTH;
+ bacpy(&addr.rc_bdaddr, src);
+ addr.rc_channel = 0;
+
+ if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't bind socket");
+ close(sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ addr.rc_family = AF_BLUETOOTH;
+ bacpy(&addr.rc_bdaddr, dst);
+ addr.rc_channel = channel;
+
+ if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("ERROR: Can't connect to device");
+ close(sk);
+ if (cups_class)
+ return CUPS_BACKEND_FAILED;
+ else
+ return CUPS_BACKEND_RETRY;
+ }
+
+ fputs("STATE: -connecting-to-device\n", stderr);
+
+ /* Ignore SIGTERM signals if printing from stdin */
+ if (fd == 0) {
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ for (i = 0; i < copies; i++) {
+
+ if (fd != 0) {
+ fprintf(stderr, "PAGE: 1 1\n");
+ lseek(fd, 0, SEEK_SET);
+ }
+
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ err = write(sk, buf, len);
+ if (err < 0) {
+ perror("ERROR: Error writing to device");
+ close(sk);
+ return CUPS_BACKEND_FAILED;
+ }
+ }
+
+ }
+
+ close(sk);
+
+ return CUPS_BACKEND_OK;
+}
--
1.7.10.2


2012-07-09 21:10:36

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 14/14] plugins: remove unmaintained plugins

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 15 --
acinclude.m4 | 18 --
bootstrap-configure | 2 -
plugins/hal.c | 144 --------------
plugins/maemo6.c | 283 ---------------------------
plugins/pnat.c | 526 ---------------------------------------------------
6 files changed, 988 deletions(-)
delete mode 100644 plugins/hal.c
delete mode 100644 plugins/maemo6.c
delete mode 100644 plugins/pnat.c

diff --git a/Makefile.am b/Makefile.am
index a769228..65d2b78 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,11 +132,6 @@ mcap_sources += profiles/health/mcap_lib.h profiles/health/mcap_internal.h \
profiles/health/mcap_sync.c
endif

-if PNATPLUGIN
-builtin_modules += pnat
-builtin_sources += plugins/pnat.c
-endif
-
if AUDIOPLUGIN
builtin_modules += audio
builtin_sources += audio/main.c \
@@ -248,13 +243,8 @@ endif
builtin_modules += mgmtops
builtin_sources += plugins/mgmtops.c

-if HAL
-builtin_modules += hal
-builtin_sources += plugins/hal.c
-else
builtin_modules += formfactor
builtin_sources += plugins/formfactor.c
-endif

EXTRA_DIST += plugins/hal.c plugins/formfactor.c

@@ -269,11 +259,6 @@ builtin_modules += wiimote
builtin_sources += plugins/wiimote.c
endif

-if MAEMO6PLUGIN
-builtin_modules += maemo6
-builtin_sources += plugins/maemo6.c
-endif
-
if DBUSOOBPLUGIN
builtin_modules += dbusoob
builtin_sources += plugins/dbusoob.c
diff --git a/acinclude.m4 b/acinclude.m4
index 842eea3..39b0a18 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -167,7 +167,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
fortify_enable=yes
pie_enable=yes
sndfile_enable=${sndfile_found}
- hal_enable=no
usb_enable=${usb_found}
gstreamer_enable=${gstreamer_found}
audio_enable=yes
@@ -176,7 +175,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
sap_enable=no
service_enable=yes
health_enable=no
- pnat_enable=no
tools_enable=yes
cups_enable=no
test_enable=no
@@ -186,7 +184,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
dfutool_enable=no
datafiles_enable=yes
telephony_driver=dummy
- maemo6_enable=no
sap_driver=dummy
dbusoob_enable=no
wiimote_enable=no
@@ -233,10 +230,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
health_enable=${enableval}
])

- AC_ARG_ENABLE(pnat, AC_HELP_STRING([--enable-pnat], [enable pnat plugin]), [
- pnat_enable=${enableval}
- ])
-
AC_ARG_ENABLE(gstreamer, AC_HELP_STRING([--enable-gstreamer], [enable GStreamer support]), [
gstreamer_enable=${enableval}
])
@@ -287,10 +280,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [

AC_SUBST([TELEPHONY_DRIVER], [telephony-${telephony_driver}.c])

- AC_ARG_ENABLE(maemo6, AC_HELP_STRING([--enable-maemo6], [compile with maemo6 plugin]), [
- maemo6_enable=${enableval}
- ])
-
AC_ARG_ENABLE(dbusoob, AC_HELP_STRING([--enable-dbusoob], [compile with D-Bus OOB plugin]), [
dbusoob_enable=${enableval}
])
@@ -299,10 +288,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
wiimote_enable=${enableval}
])

- AC_ARG_ENABLE(hal, AC_HELP_STRING([--enable-hal], [Use HAL to determine adapter class]), [
- hal_enable=${enableval}
- ])
-
AC_ARG_ENABLE(gatt, AC_HELP_STRING([--enable-gatt], [enable gatt module]), [
gatt_enable=${enableval}
])
@@ -345,9 +330,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
AM_CONDITIONAL(HEALTHPLUGIN, test "${health_enable}" = "yes")
AM_CONDITIONAL(MCAP, test "${health_enable}" = "yes")
- AM_CONDITIONAL(HAL, test "${hal_enable}" = "yes")
AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
- AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
AM_CONDITIONAL(CUPS, test "${cups_enable}" = "yes")
AM_CONDITIONAL(TEST, test "${test_enable}" = "yes" && test "${check_found}" = "yes")
AM_CONDITIONAL(TOOLS, test "${tools_enable}" = "yes")
@@ -356,7 +339,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(HID2HCI, test "${hid2hci_enable}" = "yes" && test "${usb_found}" = "yes" && test "${udev_found}" = "yes")
AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(DATAFILES, test "${datafiles_enable}" = "yes")
- AM_CONDITIONAL(MAEMO6PLUGIN, test "${maemo6_enable}" = "yes")
AM_CONDITIONAL(DBUSOOBPLUGIN, test "${dbusoob_enable}" = "yes")
AM_CONDITIONAL(WIIMOTEPLUGIN, test "${wiimote_enable}" = "yes")
AM_CONDITIONAL(GATTMODULES, test "${gatt_enable}" = "yes")
diff --git a/bootstrap-configure b/bootstrap-configure
index ff63c58..7177c65 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -24,8 +24,6 @@ fi
--enable-test \
--enable-cups \
--enable-dbusoob \
- --enable-maemo6 \
- --enable-pnat \
--enable-sap \
--enable-wiimote \
--disable-pcmcia \
diff --git a/plugins/hal.c b/plugins/hal.c
deleted file mode 100644
index 21d7688..0000000
--- a/plugins/hal.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <dbus/dbus.h>
-
-#include <bluetooth/bluetooth.h>
-
-#include "plugin.h"
-#include "adapter.h"
-#include "log.h"
-
-static void formfactor_reply(DBusPendingCall *call, void *user_data)
-{
- struct btd_adapter *adapter = user_data;
- const char *formfactor = NULL;
- DBusMessage *reply;
- uint8_t minor = 0;
-
- reply = dbus_pending_call_steal_reply(call);
-
- if (dbus_set_error_from_message(NULL, reply) == TRUE) {
- error("Failed to access HAL");
- dbus_message_unref(reply);
- return;
- }
-
- if (dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING, &formfactor,
- DBUS_TYPE_INVALID) == FALSE) {
- error("Wrong formfactor arguments");
- dbus_message_unref(reply);
- return;
- }
-
- DBG("Computer is classified as %s", formfactor);
-
- if (formfactor != NULL) {
- if (g_str_equal(formfactor, "laptop") == TRUE)
- minor |= (1 << 2) | (1 << 3);
- else if (g_str_equal(formfactor, "desktop") == TRUE)
- minor |= 1 << 2;
- else if (g_str_equal(formfactor, "server") == TRUE)
- minor |= 1 << 3;
- else if (g_str_equal(formfactor, "handheld") == TRUE)
- minor += 1 << 4;
- }
-
- dbus_message_unref(reply);
-
- /* Computer major class */
- DBG("Setting 0x%06x for major/minor device class", (1 << 8) | minor);
-
- btd_adapter_set_class(adapter, 0x01, minor);
-}
-
-static DBusConnection *connection;
-
-static int hal_probe(struct btd_adapter *adapter)
-{
- const char *property = "system.formfactor";
- DBusMessage *message;
- DBusPendingCall *call;
-
- connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (connection == NULL)
- return -ENOMEM;
-
- message = dbus_message_new_method_call("org.freedesktop.Hal",
- "/org/freedesktop/Hal/devices/computer",
- "org.freedesktop.Hal.Device",
- "GetPropertyString");
- if (message == NULL) {
- error("Failed to create formfactor request");
- dbus_connection_unref(connection);
- return -ENOMEM;
- }
-
- dbus_message_append_args(message, DBUS_TYPE_STRING, &property,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send_with_reply(connection, message,
- &call, -1) == FALSE) {
- error("Failed to send formfactor request");
- dbus_message_unref(message);
- dbus_connection_unref(connection);
- return -EIO;
- }
-
- dbus_pending_call_set_notify(call, formfactor_reply, adapter, NULL);
-
- dbus_pending_call_unref(call);
-
- dbus_message_unref(message);
-
- return 0;
-}
-
-static void hal_remove(struct btd_adapter *adapter)
-{
- dbus_connection_unref(connection);
-}
-
-static struct btd_adapter_driver hal_driver = {
- .name = "hal",
- .probe = hal_probe,
- .remove = hal_remove,
-};
-
-static int hal_init(void)
-{
- return btd_register_adapter_driver(&hal_driver);
-}
-
-static void hal_exit(void)
-{
- btd_unregister_adapter_driver(&hal_driver);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(hal, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_LOW, hal_init, hal_exit)
diff --git a/plugins/maemo6.c b/plugins/maemo6.c
deleted file mode 100644
index 4819af4..0000000
--- a/plugins/maemo6.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2006-2010 Nokia Corporation
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <dbus/dbus.h>
-
-#include "adapter.h"
-#include "plugin.h"
-#include "log.h"
-#include "gdbus.h"
-
-/* from mce/mode-names.h */
-#define MCE_RADIO_STATE_BLUETOOTH (1 << 3)
-
-/* from mce/dbus-names.h */
-#define MCE_SERVICE "com.nokia.mce"
-#define MCE_REQUEST_IF "com.nokia.mce.request"
-#define MCE_SIGNAL_IF "com.nokia.mce.signal"
-#define MCE_REQUEST_PATH "/com/nokia/mce/request"
-#define MCE_SIGNAL_PATH "/com/nokia/mce/signal"
-#define MCE_RADIO_STATES_CHANGE_REQ "req_radio_states_change"
-#define MCE_RADIO_STATES_GET "get_radio_states"
-#define MCE_RADIO_STATES_SIG "radio_states_ind"
-#define MCE_TKLOCK_MODE_SIG "tklock_mode_ind"
-
-static guint watch_id;
-static guint tklock_watch_id;
-static DBusConnection *conn = NULL;
-static gboolean mce_bt_set = FALSE;
-static gboolean mce_bt_on = FALSE;
-
-static gboolean mce_tklock_mode_cb(DBusConnection *connection,
- DBusMessage *message, void *user_data)
-{
- struct btd_adapter *adapter = user_data;
- DBusMessageIter args;
- const char *sigvalue;
-
- if (!dbus_message_iter_init(message, &args)) {
- error("message has no arguments");
- } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
- error("argument is not string");
- } else {
-
- dbus_message_iter_get_basic(&args, &sigvalue);
- DBG("got signal with value %s", sigvalue);
-
- if (g_strcmp0("unlocked", sigvalue) == 0 && mce_bt_on)
- btd_adapter_enable_auto_connect(adapter);
- }
-
- return TRUE;
-}
-
-static gboolean mce_signal_callback(DBusConnection *connection,
- DBusMessage *message, void *user_data)
-{
- DBusMessageIter args;
- uint32_t sigvalue;
- struct btd_adapter *adapter = user_data;
- int err;
-
- DBG("received mce signal");
-
- if (!dbus_message_iter_init(message, &args))
- error("message has no arguments");
- else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
- error("argument is not uint32");
- else {
- dbus_message_iter_get_basic(&args, &sigvalue);
- DBG("got signal with value %u", sigvalue);
-
- /* set the adapter according to the mce signal
- and remember the value */
- mce_bt_on = sigvalue & MCE_RADIO_STATE_BLUETOOTH ? TRUE : FALSE;
-
- if (mce_bt_on)
- err = btd_adapter_switch_online(adapter);
- else
- err = btd_adapter_switch_offline(adapter);
-
- if (err == 0)
- mce_bt_set = TRUE;
-
- }
-
- return TRUE;
-}
-
-static void read_radio_states_cb(DBusPendingCall *call, void *user_data)
-{
- DBusError derr;
- DBusMessage *reply;
- dbus_uint32_t radio_states;
- struct btd_adapter *adapter = user_data;
- int err;
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- error("mce replied with an error: %s, %s",
- derr.name, derr.message);
- dbus_error_free(&derr);
- goto done;
- }
-
- if (dbus_message_get_args(reply, &derr,
- DBUS_TYPE_UINT32, &radio_states,
- DBUS_TYPE_INVALID) == FALSE) {
- error("unable to parse get_radio_states reply: %s, %s",
- derr.name, derr.message);
- dbus_error_free(&derr);
- goto done;
- }
-
- DBG("radio_states: %d", radio_states);
-
- mce_bt_on = radio_states & MCE_RADIO_STATE_BLUETOOTH ? TRUE : FALSE;
-
- if (mce_bt_on)
- err = btd_adapter_switch_online(adapter);
- else
- err = btd_adapter_switch_offline(adapter);
-
- if (err == 0)
- mce_bt_set = TRUE;
-
-done:
- dbus_message_unref(reply);
-}
-
-static void adapter_powered(struct btd_adapter *adapter, gboolean powered)
-{
- DBusMessage *msg;
- static gboolean startup = TRUE;
-
- DBG("adapter_powered called with %d", powered);
-
- if (startup) {
- DBusPendingCall *call;
-
- /* Initialization: sync adapter state and MCE radio state */
-
- DBG("Startup: reading MCE Bluetooth radio state...");
- startup = FALSE;
-
- msg = dbus_message_new_method_call(MCE_SERVICE,
- MCE_REQUEST_PATH, MCE_REQUEST_IF,
- MCE_RADIO_STATES_GET);
-
- if (!dbus_connection_send_with_reply(conn, msg, &call, -1)) {
- error("calling %s failed", MCE_RADIO_STATES_GET);
- dbus_message_unref(msg);
- return;
- }
-
- dbus_pending_call_set_notify(call, read_radio_states_cb,
- adapter, NULL);
- dbus_pending_call_unref(call);
- dbus_message_unref(msg);
- return;
- }
-
- /* MCE initiated operation */
- if (mce_bt_set == TRUE) {
- mce_bt_set = FALSE;
- return;
- }
-
- /* Non MCE operation: set MCE according to adapter state */
- if (mce_bt_on != powered) {
- dbus_uint32_t radio_states;
- dbus_uint32_t radio_mask = MCE_RADIO_STATE_BLUETOOTH;
-
- msg = dbus_message_new_method_call(MCE_SERVICE,
- MCE_REQUEST_PATH, MCE_REQUEST_IF,
- MCE_RADIO_STATES_CHANGE_REQ);
-
- radio_states = (powered ? MCE_RADIO_STATE_BLUETOOTH : 0);
-
- DBG("Changing MCE Bluetooth radio state to: %d", radio_states);
-
- dbus_message_append_args(msg, DBUS_TYPE_UINT32, &radio_states,
- DBUS_TYPE_UINT32, &radio_mask,
- DBUS_TYPE_INVALID);
-
- if (dbus_connection_send(conn, msg, NULL))
- mce_bt_on = powered;
- else
- error("calling %s failed", MCE_RADIO_STATES_CHANGE_REQ);
-
- dbus_message_unref(msg);
- }
-}
-
-static int mce_probe(struct btd_adapter *adapter)
-{
-
- DBG("path %s", adapter_get_path(adapter));
-
- watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
- MCE_SIGNAL_IF, MCE_RADIO_STATES_SIG,
- mce_signal_callback, adapter, NULL);
-
- tklock_watch_id = g_dbus_add_signal_watch(conn, NULL, MCE_SIGNAL_PATH,
- MCE_SIGNAL_IF, MCE_TKLOCK_MODE_SIG,
- mce_tklock_mode_cb, adapter, NULL);
-
- btd_adapter_register_powered_callback(adapter, adapter_powered);
-
- return 0;
-}
-
-static void mce_remove(struct btd_adapter *adapter)
-{
- DBG("path %s", adapter_get_path(adapter));
-
- if (watch_id > 0)
- g_dbus_remove_watch(conn, watch_id);
-
- if (tklock_watch_id > 0)
- g_dbus_remove_watch(conn, tklock_watch_id);
-
- btd_adapter_unregister_powered_callback(adapter, adapter_powered);
-}
-
-static struct btd_adapter_driver mce_driver = {
- .name = "mce",
- .probe = mce_probe,
- .remove = mce_remove,
-};
-
-static int maemo6_init(void)
-{
- DBG("init maemo6 plugin");
-
- conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (conn == NULL) {
- error("Unable to connect to D-Bus");
- return -1;
- }
-
- return btd_register_adapter_driver(&mce_driver);
-}
-
-static void maemo6_exit(void)
-{
- DBG("exit maemo6 plugin");
-
- if (conn != NULL)
- dbus_connection_unref(conn);
-
- btd_unregister_adapter_driver(&mce_driver);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(maemo6, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, maemo6_init, maemo6_exit)
diff --git a/plugins/pnat.c b/plugins/pnat.c
deleted file mode 100644
index 3c611a9..0000000
--- a/plugins/pnat.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/uuid.h>
-
-#include <glib.h>
-
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "sdpd.h"
-#include "btio.h"
-#include "adapter.h"
-#include "log.h"
-
-/* FIXME: This location should be build-time configurable */
-#define PNATD "/usr/bin/phonet-at"
-
-#define DUN_CHANNEL 1
-
-#define TTY_TIMEOUT 100
-#define TTY_TRIES 10
-
-struct dun_client {
- bdaddr_t bda;
-
- GIOChannel *io; /* Client socket */
- guint io_watch; /* Client IO watch id */
-
- guint tty_timer;
- int tty_tries;
- gboolean tty_open;
- int tty_id;
- char tty_name[PATH_MAX];
-
- GPid pnatd_pid;
-};
-
-struct dun_server {
- bdaddr_t bda; /* Local adapter address */
-
- uint32_t record_handle; /* Local SDP record handle */
- GIOChannel *server; /* Server socket */
-
- int rfcomm_ctl;
-
- struct dun_client client;
-};
-
-static GSList *servers = NULL;
-
-static void disconnect(struct dun_server *server)
-{
- struct dun_client *client = &server->client;
-
- if (!client->io)
- return;
-
- if (client->io_watch > 0) {
- g_source_remove(client->io_watch);
- client->io_watch = 0;
- }
-
- g_io_channel_shutdown(client->io, TRUE, NULL);
- g_io_channel_unref(client->io);
- client->io = NULL;
-
- if (client->pnatd_pid > 0) {
- kill(client->pnatd_pid, SIGTERM);
- client->pnatd_pid = 0;
- }
-
- if (client->tty_timer > 0) {
- g_source_remove(client->tty_timer);
- client->tty_timer = 0;
- }
-
- if (client->tty_id >= 0) {
- struct rfcomm_dev_req req;
-
- memset(&req, 0, sizeof(req));
- req.dev_id = client->tty_id;
- req.flags = (1 << RFCOMM_HANGUP_NOW);
- ioctl(server->rfcomm_ctl, RFCOMMRELEASEDEV, &req);
-
- client->tty_name[0] = '\0';
- client->tty_open = FALSE;
- client->tty_id = -1;
- }
-}
-
-static gboolean client_event(GIOChannel *chan,
- GIOCondition cond, gpointer data)
-{
- struct dun_server *server = data;
- struct dun_client *client = &server->client;
- char addr[18];
-
- ba2str(&client->bda, addr);
-
- DBG("Disconnected DUN from %s (%s)", addr, client->tty_name);
-
- client->io_watch = 0;
- disconnect(server);
-
- return FALSE;
-}
-
-static void pnatd_exit(GPid pid, gint status, gpointer user_data)
-{
- struct dun_server *server = user_data;
- struct dun_client *client = &server->client;
-
- if (WIFEXITED(status))
- DBG("pnatd (%d) exited with status %d", pid,
- WEXITSTATUS(status));
- else
- DBG("pnatd (%d) was killed by signal %d", pid,
- WTERMSIG(status));
- g_spawn_close_pid(pid);
-
- if (pid != client->pnatd_pid)
- return;
-
- /* So disconnect() doesn't send SIGTERM to a non-existing process */
- client->pnatd_pid = 0;
-
- disconnect(server);
-}
-
-static gboolean start_pnatd(struct dun_server *server)
-{
- struct dun_client *client = &server->client;
- GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH;
- char *argv[] = { PNATD, client->tty_name, NULL };
- GError *err = NULL;
- GPid pid;
-
- g_spawn_async(NULL, argv, NULL, flags, NULL, NULL, &pid, &err);
- if (err != NULL) {
- error("Unable to spawn pnatd: %s", err->message);
- g_error_free(err);
- return FALSE;
- }
-
- DBG("pnatd started for %s with pid %d", client->tty_name, pid);
-
- client->pnatd_pid = pid;
-
- /* We do not store the GSource id since g_remove_source doesn't
- * make sense for a child watch. If the callback gets removed
- * waitpid won't be called and the child remains as a zombie)
- */
- g_child_watch_add(pid, pnatd_exit, server);
-
- return TRUE;
-}
-
-static gboolean tty_try_open(gpointer user_data)
-{
- struct dun_server *server = user_data;
- struct dun_client *client = &server->client;
- int tty_fd;
-
- tty_fd = open(client->tty_name, O_RDONLY | O_NOCTTY);
- if (tty_fd < 0) {
- if (errno == EACCES)
- goto disconnect;
-
- client->tty_tries--;
-
- if (client->tty_tries <= 0)
- goto disconnect;
-
- return TRUE;
- }
-
- DBG("%s created for DUN", client->tty_name);
-
- client->tty_open = TRUE;
- client->tty_timer = 0;
-
- g_io_channel_unref(client->io);
- g_source_remove(client->io_watch);
-
- client->io = g_io_channel_unix_new(tty_fd);
- client->io_watch = g_io_add_watch(client->io,
- G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- client_event, server);
-
- if (!start_pnatd(server))
- goto disconnect;
-
- return FALSE;
-
-disconnect:
- client->tty_timer = 0;
- disconnect(server);
- return FALSE;
-}
-
-static gboolean create_tty(struct dun_server *server)
-{
- struct dun_client *client = &server->client;
- struct rfcomm_dev_req req;
- int sk = g_io_channel_unix_get_fd(client->io);
-
- memset(&req, 0, sizeof(req));
- req.dev_id = -1;
- req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
-
- bacpy(&req.src, &server->bda);
- bacpy(&req.dst, &client->bda);
-
- bt_io_get(client->io, BT_IO_RFCOMM, NULL,
- BT_IO_OPT_DEST_CHANNEL, &req.channel,
- BT_IO_OPT_INVALID);
-
- client->tty_id = ioctl(sk, RFCOMMCREATEDEV, &req);
- if (client->tty_id < 0) {
- error("Can't create RFCOMM TTY: %s", strerror(errno));
- return FALSE;
- }
-
- snprintf(client->tty_name, PATH_MAX - 1, "/dev/rfcomm%d",
- client->tty_id);
-
- client->tty_tries = TTY_TRIES;
-
- tty_try_open(server);
- if (!client->tty_open && client->tty_tries > 0)
- client->tty_timer = g_timeout_add(TTY_TIMEOUT,
- tty_try_open, server);
-
- return TRUE;
-}
-
-static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
-{
- struct dun_server *server = user_data;
-
- if (err) {
- error("Accepting DUN connection failed: %s", err->message);
- disconnect(server);
- return;
- }
-
- if (!create_tty(server)) {
- error("Device creation failed");
- disconnect(server);
- }
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
- struct dun_server *server = user_data;
- struct dun_client *client = &server->client;
- GError *err = NULL;
-
- if (derr && dbus_error_is_set(derr)) {
- error("DUN access denied: %s", derr->message);
- goto drop;
- }
-
- if (!bt_io_accept(client->io, connect_cb, server, NULL, &err)) {
- error("bt_io_accept: %s", err->message);
- g_error_free(err);
- goto drop;
- }
-
- return;
-
-drop:
- disconnect(server);
-}
-
-static gboolean auth_watch(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
- struct dun_server *server = data;
- struct dun_client *client = &server->client;
-
- error("DUN client disconnected while waiting for authorization");
-
- btd_cancel_authorization(&server->bda, &client->bda);
-
- disconnect(server);
-
- return FALSE;
-}
-
-static void confirm_cb(GIOChannel *io, gpointer user_data)
-{
- struct dun_server *server = user_data;
- struct dun_client *client = &server->client;
- GError *err = NULL;
-
- if (client->io) {
- error("Rejecting DUN connection since one already exists");
- return;
- }
-
- bt_io_get(io, BT_IO_RFCOMM, &err,
- BT_IO_OPT_DEST_BDADDR, &client->bda,
- BT_IO_OPT_INVALID);
- if (err != NULL) {
- error("Unable to get DUN source and dest address: %s",
- err->message);
- g_error_free(err);
- return;
- }
-
- if (btd_request_authorization(&server->bda, &client->bda, DUN_GW_UUID,
- auth_cb, user_data) < 0) {
- error("Requesting DUN authorization failed");
- return;
- }
-
- client->io_watch = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) auth_watch, server);
- client->io = g_io_channel_ref(io);
-}
-
-static sdp_record_t *dun_record(uint8_t ch)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
- uuid_t root_uuid, dun, gn, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_list_t *proto[2];
- sdp_record_t *record;
- sdp_data_t *channel;
-
- record = sdp_record_alloc();
- if (!record)
- return NULL;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(record, root);
-
- sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &dun);
- sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &gn);
- sdp_set_service_classes(record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
- profile.version = 0x0100;
- pfseq = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, pfseq);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap);
- apseq = sdp_list_append(NULL, proto[0]);
-
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(NULL, &rfcomm);
- channel = sdp_data_alloc(SDP_UINT8, &ch);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(0, apseq);
- sdp_set_access_protos(record, aproto);
-
- sdp_set_info_attr(record, "Dial-Up Networking", 0, 0);
-
- sdp_data_free(channel);
- sdp_list_free(root, NULL);
- sdp_list_free(svclass_id, NULL);
- sdp_list_free(proto[0], NULL);
- sdp_list_free(proto[1], NULL);
- sdp_list_free(pfseq, NULL);
- sdp_list_free(apseq, NULL);
- sdp_list_free(aproto, NULL);
-
- return record;
-}
-
-static gint server_cmp(gconstpointer a, gconstpointer b)
-{
- const struct dun_server *server = a;
- const bdaddr_t *src = b;
-
- return bacmp(src, &server->bda);
-}
-
-static int pnat_probe(struct btd_adapter *adapter)
-{
- struct dun_server *server;
- GIOChannel *io;
- GError *err = NULL;
- sdp_record_t *record;
- bdaddr_t src;
-
- adapter_get_address(adapter, &src);
-
- server = g_new0(struct dun_server, 1);
-
- io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_cb, server, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, &src,
- BT_IO_OPT_CHANNEL, DUN_CHANNEL,
- BT_IO_OPT_INVALID);
- if (err != NULL) {
- error("Failed to start DUN server: %s", err->message);
- g_error_free(err);
- goto fail;
- }
-
- record = dun_record(DUN_CHANNEL);
- if (!record) {
- error("Unable to allocate new service record");
- goto fail;
- }
-
- if (add_record_to_server(&src, record) < 0) {
- error("Unable to register DUN service record");
- goto fail;
- }
-
- server->rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
- if (server->rfcomm_ctl < 0) {
- error("Unable to create RFCOMM control socket: %s (%d)",
- strerror(errno), errno);
- goto fail;
- }
-
- server->server = io;
- server->record_handle = record->handle;
- bacpy(&server->bda, &src);
-
- servers = g_slist_append(servers, server);
-
- return 0;
-
-fail:
- if (io != NULL)
- g_io_channel_unref(io);
- g_free(server);
- return -EIO;
-}
-
-static void pnat_remove(struct btd_adapter *adapter)
-{
- struct dun_server *server;
- GSList *match;
- bdaddr_t src;
-
- adapter_get_address(adapter, &src);
-
- match = g_slist_find_custom(servers, &src, server_cmp);
- if (match == NULL)
- return;
-
- server = match->data;
-
- servers = g_slist_delete_link(servers, match);
-
- disconnect(server);
-
- remove_record_from_server(server->record_handle);
- close(server->rfcomm_ctl);
- g_io_channel_shutdown(server->server, TRUE, NULL);
- g_io_channel_unref(server->server);
- g_free(server);
-}
-
-static struct btd_adapter_driver pnat_server = {
- .name = "pnat-server",
- .probe = pnat_probe,
- .remove = pnat_remove,
-};
-
-static int pnat_init(void)
-{
- DBG("Setup Phonet AT (DUN) plugin");
-
- return btd_register_adapter_driver(&pnat_server);
-}
-
-static void pnat_exit(void)
-{
- DBG("Cleanup Phonet AT (DUN) plugin");
-
- btd_unregister_adapter_driver(&pnat_server);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(pnat, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- pnat_init, pnat_exit)
--
1.7.10.2


2012-07-09 21:10:29

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 07/14] thermometer: move to the profiles folder

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 8 +-
profiles/thermometer/main.c | 70 ++
profiles/thermometer/manager.c | 92 +++
profiles/thermometer/manager.h | 24 +
profiles/thermometer/thermometer.c | 1274 ++++++++++++++++++++++++++++++++++++
profiles/thermometer/thermometer.h | 25 +
thermometer/main.c | 70 --
thermometer/manager.c | 92 ---
thermometer/manager.h | 24 -
thermometer/thermometer.c | 1274 ------------------------------------
thermometer/thermometer.h | 25 -
11 files changed, 1490 insertions(+), 1488 deletions(-)
create mode 100644 profiles/thermometer/main.c
create mode 100644 profiles/thermometer/manager.c
create mode 100644 profiles/thermometer/manager.h
create mode 100644 profiles/thermometer/thermometer.c
create mode 100644 profiles/thermometer/thermometer.h
delete mode 100644 thermometer/main.c
delete mode 100644 thermometer/manager.c
delete mode 100644 thermometer/manager.h
delete mode 100644 thermometer/thermometer.c
delete mode 100644 thermometer/thermometer.h

diff --git a/Makefile.am b/Makefile.am
index 2f6d539..c8b2475 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -215,9 +215,11 @@ endif

if GATTMODULES
builtin_modules += thermometer alert time gatt_example proximity deviceinfo
-builtin_sources += thermometer/main.c \
- thermometer/manager.h thermometer/manager.c \
- thermometer/thermometer.h thermometer/thermometer.c \
+builtin_sources += profiles/thermometer/main.c \
+ profiles/thermometer/manager.h \
+ profiles/thermometer/manager.c \
+ profiles/thermometer/thermometer.h \
+ profiles/thermometer/thermometer.c \
profiles/alert/main.c profiles/alert/server.h \
profiles/alert/server.c \
time/main.c time/server.h time/server.c \
diff --git a/profiles/thermometer/main.c b/profiles/thermometer/main.c
new file mode 100644
index 0000000..4447b52
--- /dev/null
+++ b/profiles/thermometer/main.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+#include <gdbus.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static DBusConnection *connection = NULL;
+
+static int thermometer_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ DBG("GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (connection == NULL)
+ return -EIO;
+
+ if (thermometer_manager_init(connection) < 0) {
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void thermometer_exit(void)
+{
+ if (!main_opts.gatt_enabled)
+ return;
+
+ thermometer_manager_exit();
+
+ dbus_connection_unref(connection);
+ connection = NULL;
+}
+
+BLUETOOTH_PLUGIN_DEFINE(thermometer, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ thermometer_init, thermometer_exit)
diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c
new file mode 100644
index 0000000..3d5452b
--- /dev/null
+++ b/profiles/thermometer/manager.c
@@ -0,0 +1,92 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <gdbus.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "thermometer.h"
+#include "manager.h"
+
+static DBusConnection *connection = NULL;
+
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const char *uuid = b;
+
+ return g_strcmp0(prim->uuid, uuid);
+}
+
+static int thermometer_driver_probe(struct btd_device *device, GSList *uuids)
+{
+ struct gatt_primary *tattr;
+ GSList *primaries, *l;
+
+ primaries = btd_device_get_primaries(device);
+
+ l = g_slist_find_custom(primaries, HEALTH_THERMOMETER_UUID,
+ primary_uuid_cmp);
+ if (l == NULL)
+ return -EINVAL;
+
+ tattr = l->data;
+
+ return thermometer_register(connection, device, tattr);
+}
+
+static void thermometer_driver_remove(struct btd_device *device)
+{
+ thermometer_unregister(device);
+}
+
+static struct btd_device_driver thermometer_device_driver = {
+ .name = "thermometer-device-driver",
+ .uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID),
+ .probe = thermometer_driver_probe,
+ .remove = thermometer_driver_remove
+};
+
+int thermometer_manager_init(DBusConnection *conn)
+{
+ int ret;
+
+ ret = btd_register_device_driver(&thermometer_device_driver);
+ if (ret < 0)
+ return ret;
+
+ connection = dbus_connection_ref(conn);
+ return 0;
+}
+
+void thermometer_manager_exit(void)
+{
+ btd_unregister_device_driver(&thermometer_device_driver);
+
+ dbus_connection_unref(connection);
+ connection = NULL;
+}
diff --git a/profiles/thermometer/manager.h b/profiles/thermometer/manager.h
new file mode 100644
index 0000000..ed928ad
--- /dev/null
+++ b/profiles/thermometer/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int thermometer_manager_init(DBusConnection *conn);
+void thermometer_manager_exit(void);
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
new file mode 100644
index 0000000..087662e
--- /dev/null
+++ b/profiles/thermometer/thermometer.c
@@ -0,0 +1,1274 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gdbus.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "dbus-common.h"
+#include "adapter.h"
+#include "device.h"
+#include "error.h"
+#include "log.h"
+#include "gattrib.h"
+#include "attio.h"
+#include "att.h"
+#include "gatt.h"
+#include "thermometer.h"
+
+#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
+
+/* Temperature measurement flag fields */
+#define TEMP_UNITS 0x01
+#define TEMP_TIME_STAMP 0x02
+#define TEMP_TYPE 0x04
+
+#define FLOAT_MAX_MANTISSA 16777216 /* 2^24 */
+
+#define VALID_RANGE_DESC_SIZE 4
+#define TEMPERATURE_TYPE_SIZE 1
+#define MEASUREMENT_INTERVAL_SIZE 2
+
+struct thermometer {
+ DBusConnection *conn; /* The connection to the bus */
+ struct btd_device *dev; /* Device reference */
+ GAttrib *attrib; /* GATT connection */
+ struct att_range *svc_range; /* Thermometer range */
+ guint attioid; /* Att watcher id */
+ guint attindid; /* Att incications id */
+ guint attnotid; /* Att notifications id */
+ GSList *chars; /* Characteristics */
+ GSList *fwatchers; /* Final measurements */
+ GSList *iwatchers; /* Intermediate measurements */
+ gboolean intermediate;
+ uint8_t type;
+ uint16_t interval;
+ uint16_t max;
+ uint16_t min;
+ gboolean has_type;
+ gboolean has_interval;
+};
+
+struct characteristic {
+ struct gatt_char attr; /* Characteristic */
+ GSList *desc; /* Descriptors */
+ struct thermometer *t; /* Thermometer where the char belongs */
+};
+
+struct descriptor {
+ struct characteristic *ch;
+ uint16_t handle;
+ bt_uuid_t uuid;
+};
+
+struct watcher {
+ struct thermometer *t;
+ guint id;
+ char *srv;
+ char *path;
+};
+
+struct measurement {
+ int16_t exp;
+ int32_t mant;
+ uint64_t time;
+ gboolean suptime;
+ char *unit;
+ char *type;
+ char *value;
+};
+
+struct tmp_interval_data {
+ struct thermometer *thermometer;
+ uint16_t interval;
+};
+
+static GSList *thermometers = NULL;
+
+const char *temp_type[] = {
+ "<reserved>",
+ "Armpit",
+ "Body",
+ "Ear",
+ "Finger",
+ "Intestines",
+ "Mouth",
+ "Rectum",
+ "Toe",
+ "Tympanum"
+};
+
+static const gchar *temptype2str(uint8_t value)
+{
+ if (value > 0 && value < G_N_ELEMENTS(temp_type))
+ return temp_type[value];
+
+ error("Temperature type %d reserved for future use", value);
+ return NULL;
+}
+
+static void destroy_watcher(gpointer user_data)
+{
+ struct watcher *watcher = user_data;
+
+ g_free(watcher->path);
+ g_free(watcher->srv);
+ g_free(watcher);
+}
+
+static void remove_watcher(gpointer user_data)
+{
+ struct watcher *watcher = user_data;
+
+ g_dbus_remove_watch(watcher->t->conn, watcher->id);
+}
+
+static void destroy_char(gpointer user_data)
+{
+ struct characteristic *c = user_data;
+
+ g_slist_free_full(c->desc, g_free);
+ g_free(c);
+}
+
+static void destroy_thermometer(gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ if (t->attioid > 0)
+ btd_device_remove_attio_callback(t->dev, t->attioid);
+
+ if (t->attindid > 0)
+ g_attrib_unregister(t->attrib, t->attindid);
+
+ if (t->attnotid > 0)
+ g_attrib_unregister(t->attrib, t->attnotid);
+
+ if (t->attrib != NULL)
+ g_attrib_unref(t->attrib);
+
+ if (t->chars != NULL)
+ g_slist_free_full(t->chars, destroy_char);
+
+ if (t->fwatchers != NULL)
+ g_slist_free_full(t->fwatchers, remove_watcher);
+
+ dbus_connection_unref(t->conn);
+ btd_device_unref(t->dev);
+ g_free(t->svc_range);
+ g_free(t);
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+ const struct thermometer *t = a;
+ const struct btd_device *dev = b;
+
+ if (dev == t->dev)
+ return 0;
+
+ return -1;
+}
+
+static gint cmp_watcher(gconstpointer a, gconstpointer b)
+{
+ const struct watcher *watcher = a;
+ const struct watcher *match = b;
+ int ret;
+
+ ret = g_strcmp0(watcher->srv, match->srv);
+ if (ret != 0)
+ return ret;
+
+ return g_strcmp0(watcher->path, match->path);
+}
+
+static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
+{
+ const struct characteristic *ch = a;
+ const char *uuid = b;
+
+ return g_strcmp0(ch->attr.uuid, uuid);
+}
+
+static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
+{
+ const struct characteristic *ch = a;
+ const uint16_t *handle = b;
+
+ return ch->attr.value_handle - *handle;
+}
+
+static gint cmp_descriptor(gconstpointer a, gconstpointer b)
+{
+ const struct descriptor *desc = a;
+ const bt_uuid_t *uuid = b;
+
+ return bt_uuid_cmp(&desc->uuid, uuid);
+}
+
+static struct characteristic *get_characteristic(struct thermometer *t,
+ const char *uuid)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
+ if (l == NULL)
+ return NULL;
+
+ return l->data;
+}
+
+static struct descriptor *get_descriptor(struct characteristic *ch,
+ const bt_uuid_t *uuid)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
+ if (l == NULL)
+ return NULL;
+
+ return l->data;
+}
+
+static void change_property(struct thermometer *t, const char *name,
+ gpointer value) {
+ if (g_strcmp0(name, "Intermediate") == 0) {
+ gboolean *intermediate = value;
+ if (t->intermediate == *intermediate)
+ return;
+
+ t->intermediate = *intermediate;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_BOOLEAN, &t->intermediate);
+ } else if (g_strcmp0(name, "Interval") == 0) {
+ uint16_t *interval = value;
+ if (t->has_interval && t->interval == *interval)
+ return;
+
+ t->has_interval = TRUE;
+ t->interval = *interval;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16, &t->interval);
+ } else if (g_strcmp0(name, "Maximum") == 0) {
+ uint16_t *max = value;
+ if (t->max == *max)
+ return;
+
+ t->max = *max;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16, &t->max);
+ } else if (g_strcmp0(name, "Minimum") == 0) {
+ uint16_t *min = value;
+ if (t->min == *min)
+ return;
+
+ t->min = *min;
+ emit_property_changed(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE, name,
+ DBUS_TYPE_UINT16, &t->min);
+ } else
+ DBG("%s is not a thermometer property", name);
+}
+
+static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct descriptor *desc = user_data;
+ uint8_t value[VALID_RANGE_DESC_SIZE];
+ uint16_t max, min;
+ ssize_t vlen;
+
+ if (status != 0) {
+ DBG("Valid Range descriptor read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ DBG("Protocol error\n");
+ return;
+ }
+
+ if (vlen < 4) {
+ DBG("Invalid range received");
+ return;
+ }
+
+ min = att_get_u16(&value[0]);
+ max = att_get_u16(&value[2]);
+
+ if (min == 0 || min > max) {
+ DBG("Invalid range");
+ return;
+ }
+
+ change_property(desc->ch->t, "Maximum", &max);
+ change_property(desc->ch->t, "Minimum", &min);
+}
+
+static void measurement_cb(guint8 status, const guint8 *pdu,
+ guint16 len, gpointer user_data)
+{
+ char *msg = user_data;
+
+ if (status != 0)
+ error("%s failed", msg);
+
+ g_free(msg);
+}
+
+static void process_thermometer_desc(struct descriptor *desc)
+{
+ struct characteristic *ch = desc->ch;
+ char uuidstr[MAX_LEN_UUID_STR];
+ bt_uuid_t btuuid;
+
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+
+ if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
+ uint8_t atval[2];
+ uint16_t val;
+ char *msg;
+
+ if (g_strcmp0(ch->attr.uuid,
+ TEMPERATURE_MEASUREMENT_UUID) == 0) {
+ if (g_slist_length(ch->t->fwatchers) == 0)
+ return;
+
+ val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
+ msg = g_strdup("Enable Temperature Measurement "
+ "indication");
+ } else if (g_strcmp0(ch->attr.uuid,
+ INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+ if (g_slist_length(ch->t->iwatchers) == 0)
+ return;
+
+ val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
+ msg = g_strdup("Enable Intermediate Temperature "
+ "notification");
+ } else if (g_strcmp0(ch->attr.uuid,
+ MEASUREMENT_INTERVAL_UUID) == 0) {
+ val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
+ msg = g_strdup("Enable Measurement Interval "
+ "indication");
+ } else
+ goto done;
+
+ att_put_u16(val, atval);
+ gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
+ measurement_cb, msg);
+ return;
+ }
+
+ bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
+
+ if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
+ MEASUREMENT_INTERVAL_UUID) == 0) {
+ gatt_read_char(ch->t->attrib, desc->handle, 0,
+ valid_range_desc_cb, desc);
+ return;
+ }
+
+done:
+ bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
+ DBG("Ignored descriptor %s in characteristic %s", uuidstr,
+ ch->attr.uuid);
+}
+
+static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+ struct att_data_list *list;
+ uint8_t format;
+ int i;
+
+ if (status != 0) {
+ error("Discover all characteristic descriptors failed [%s]: %s",
+ ch->attr.uuid, att_ecode2str(status));
+ return;
+ }
+
+ list = dec_find_info_resp(pdu, len, &format);
+ if (list == NULL)
+ return;
+
+ for (i = 0; i < list->num; i++) {
+ struct descriptor *desc;
+ uint8_t *value;
+
+ value = list->data[i];
+ desc = g_new0(struct descriptor, 1);
+ desc->handle = att_get_u16(value);
+ desc->ch = ch;
+
+ if (format == 0x01)
+ desc->uuid = att_get_uuid16(&value[2]);
+ else
+ desc->uuid = att_get_uuid128(&value[2]);
+
+ ch->desc = g_slist_append(ch->desc, desc);
+ process_thermometer_desc(desc);
+ }
+
+ att_data_list_free(list);
+}
+
+static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+ struct thermometer *t = ch->t;
+ uint8_t value[TEMPERATURE_TYPE_SIZE];
+ ssize_t vlen;
+
+ if (status != 0) {
+ DBG("Temperature Type value read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ DBG("Protocol error.");
+ return;
+ }
+
+ if (vlen != 1) {
+ DBG("Invalid length for Temperature type");
+ return;
+ }
+
+ t->has_type = TRUE;
+ t->type = value[0];
+}
+
+static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+ uint8_t value[MEASUREMENT_INTERVAL_SIZE];
+ uint16_t interval;
+ ssize_t vlen;
+
+ if (status != 0) {
+ DBG("Measurement Interval value read failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ DBG("Protocol error\n");
+ return;
+ }
+
+ if (vlen < 2) {
+ DBG("Invalid Interval received");
+ return;
+ }
+
+ interval = att_get_u16(&value[0]);
+ change_property(ch->t, "Interval", &interval);
+}
+
+static void process_thermometer_char(struct characteristic *ch)
+{
+ if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
+ gboolean intermediate = TRUE;
+ change_property(ch->t, "Intermediate", &intermediate);
+ return;
+ } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
+ gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
+ read_temp_type_cb, ch);
+ else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
+ read_interval_cb, ch);
+}
+
+static void configure_thermometer_cb(GSList *characteristics, guint8 status,
+ gpointer user_data)
+{
+ struct thermometer *t = user_data;
+ GSList *l;
+
+ if (status != 0) {
+ error("Discover thermometer characteristics: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ for (l = characteristics; l; l = l->next) {
+ struct gatt_char *c = l->data;
+ struct characteristic *ch;
+ uint16_t start, end;
+
+ ch = g_new0(struct characteristic, 1);
+ ch->attr.handle = c->handle;
+ ch->attr.properties = c->properties;
+ ch->attr.value_handle = c->value_handle;
+ memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
+ ch->t = t;
+
+ t->chars = g_slist_append(t->chars, ch);
+
+ process_thermometer_char(ch);
+
+ start = c->value_handle + 1;
+
+ if (l->next != NULL) {
+ struct gatt_char *c = l->next->data;
+ if (start == c->handle)
+ continue;
+ end = c->handle - 1;
+ } else if (c->value_handle != t->svc_range->end)
+ end = t->svc_range->end;
+ else
+ continue;
+
+ gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
+ }
+}
+
+static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct thermometer *t = data;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(msg);
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dict_append_entry(&dict, "Intermediate", DBUS_TYPE_BOOLEAN,
+ &t->intermediate);
+
+ if (t->has_interval) {
+ dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT16,
+ &t->interval);
+ dict_append_entry(&dict, "Maximum", DBUS_TYPE_UINT16, &t->max);
+ dict_append_entry(&dict, "Minimum", DBUS_TYPE_UINT16, &t->min);
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct tmp_interval_data *data = user_data;
+
+ if (status != 0) {
+ error("Interval Write Request failed %s",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ if (!dec_write_resp(pdu, len)) {
+ error("Interval Write Request: protocol error");
+ goto done;
+ }
+
+ change_property(data->thermometer, "Interval", &data->interval);
+
+done:
+ g_free(user_data);
+}
+
+static DBusMessage *write_attr_interval(struct thermometer *t, DBusMessage *msg,
+ uint16_t value)
+{
+ struct tmp_interval_data *data;
+ struct characteristic *ch;
+ uint8_t atval[2];
+
+ if (t->attrib == NULL)
+ return btd_error_not_connected(msg);
+
+ ch = get_characteristic(t, MEASUREMENT_INTERVAL_UUID);
+ if (ch == NULL)
+ return btd_error_not_available(msg);
+
+ if (value < t->min || value > t->max)
+ return btd_error_invalid_args(msg);
+
+ att_put_u16(value, &atval[0]);
+
+ data = g_new0(struct tmp_interval_data, 1);
+ data->thermometer = t;
+ data->interval = value;
+ gatt_write_char(t->attrib, ch->attr.value_handle, atval, 2,
+ write_interval_cb, data);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct thermometer *t = data;
+ const char *property;
+ DBusMessageIter iter;
+ DBusMessageIter sub;
+ uint16_t value;
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return btd_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &property);
+ if (g_strcmp0("Interval", property) != 0)
+ return btd_error_invalid_args(msg);
+
+ if (!t->has_interval)
+ return btd_error_not_available(msg);
+
+ dbus_message_iter_next(&iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT16)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&sub, &value);
+
+ return write_attr_interval(t, msg, value);
+}
+
+static void enable_final_measurement(struct thermometer *t)
+{
+ struct characteristic *ch;
+ struct descriptor *desc;
+ bt_uuid_t btuuid;
+ uint8_t atval[2];
+ char *msg;
+
+ if (t->attrib == NULL)
+ return;
+
+ ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+ if (ch == NULL) {
+ DBG("Temperature measurement characteristic not found");
+ return;
+ }
+
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ desc = get_descriptor(ch, &btuuid);
+ if (desc == NULL) {
+ DBG("Client characteristic configuration descriptor not found");
+ return;
+ }
+
+ atval[0] = 0x02;
+ atval[1] = 0x00;
+ msg = g_strdup("Enable final measurement");
+ gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void enable_intermediate_measurement(struct thermometer *t)
+{
+ struct characteristic *ch;
+ struct descriptor *desc;
+ bt_uuid_t btuuid;
+ uint8_t atval[2];
+ char *msg;
+
+ if (t->attrib == NULL)
+ return;
+
+ ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+ if (ch == NULL) {
+ DBG("Intermediate measurement characteristic not found");
+ return;
+ }
+
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ desc = get_descriptor(ch, &btuuid);
+ if (desc == NULL) {
+ DBG("Client characteristic configuration descriptor not found");
+ return;
+ }
+
+ atval[0] = 0x01;
+ atval[1] = 0x00;
+ msg = g_strdup("Enable intermediate measurement");
+ gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void disable_final_measurement(struct thermometer *t)
+{
+ struct characteristic *ch;
+ struct descriptor *desc;
+ bt_uuid_t btuuid;
+ uint8_t atval[2];
+ char *msg;
+
+ if (t->attrib == NULL)
+ return;
+
+ ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
+ if (ch == NULL) {
+ DBG("Temperature measurement characteristic not found");
+ return;
+ }
+
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ desc = get_descriptor(ch, &btuuid);
+ if (desc == NULL) {
+ DBG("Client characteristic configuration descriptor not found");
+ return;
+ }
+
+ atval[0] = 0x00;
+ atval[1] = 0x00;
+ msg = g_strdup("Disable final measurement");
+ gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void disable_intermediate_measurement(struct thermometer *t)
+{
+ struct characteristic *ch;
+ struct descriptor *desc;
+ bt_uuid_t btuuid;
+ uint8_t atval[2];
+ char *msg;
+
+ if (t->attrib == NULL)
+ return;
+
+ ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
+ if (ch == NULL) {
+ DBG("Intermediate measurement characteristic not found");
+ return;
+ }
+
+ bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ desc = get_descriptor(ch, &btuuid);
+ if (desc == NULL) {
+ DBG("Client characteristic configuration descriptor not found");
+ return;
+ }
+
+ atval[0] = 0x00;
+ atval[1] = 0x00;
+ msg = g_strdup("Disable intermediate measurement");
+ gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
+}
+
+static void remove_int_watcher(struct thermometer *t, struct watcher *w)
+{
+ if (!g_slist_find(t->iwatchers, w))
+ return;
+
+ t->iwatchers = g_slist_remove(t->iwatchers, w);
+
+ if (g_slist_length(t->iwatchers) == 0)
+ disable_intermediate_measurement(t);
+}
+
+static void watcher_exit(DBusConnection *conn, void *user_data)
+{
+ struct watcher *watcher = user_data;
+ struct thermometer *t = watcher->t;
+
+ DBG("Thermometer watcher %s disconnected", watcher->path);
+
+ remove_int_watcher(t, watcher);
+
+ t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+ g_dbus_remove_watch(watcher->t->conn, watcher->id);
+
+ if (g_slist_length(t->fwatchers) == 0)
+ disable_final_measurement(t);
+}
+
+static struct watcher *find_watcher(GSList *list, const char *sender,
+ const char *path)
+{
+ struct watcher *match;
+ GSList *l;
+
+ match = g_new0(struct watcher, 1);
+ match->srv = g_strdup(sender);
+ match->path = g_strdup(path);
+
+ l = g_slist_find_custom(list, match, cmp_watcher);
+ destroy_watcher(match);
+
+ if (l != NULL)
+ return l->data;
+
+ return NULL;
+}
+
+static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *sender = dbus_message_get_sender(msg);
+ struct thermometer *t = data;
+ struct watcher *watcher;
+ char *path;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ watcher = find_watcher(t->fwatchers, sender, path);
+ if (watcher != NULL)
+ return btd_error_already_exists(msg);
+
+ DBG("Thermometer watcher %s registered", path);
+
+ watcher = g_new0(struct watcher, 1);
+ watcher->srv = g_strdup(sender);
+ watcher->path = g_strdup(path);
+ watcher->t = t;
+ watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
+ watcher, destroy_watcher);
+
+ if (g_slist_length(t->fwatchers) == 0)
+ enable_final_measurement(t);
+
+ t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *sender = dbus_message_get_sender(msg);
+ struct thermometer *t = data;
+ struct watcher *watcher;
+ char *path;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ watcher = find_watcher(t->fwatchers, sender, path);
+ if (watcher == NULL)
+ return btd_error_does_not_exist(msg);
+
+ DBG("Thermometer watcher %s unregistered", path);
+
+ remove_int_watcher(t, watcher);
+
+ t->fwatchers = g_slist_remove(t->fwatchers, watcher);
+ g_dbus_remove_watch(watcher->t->conn, watcher->id);
+
+ if (g_slist_length(t->fwatchers) == 0)
+ disable_final_measurement(t);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *sender = dbus_message_get_sender(msg);
+ struct thermometer *t = data;
+ struct watcher *watcher;
+ char *path;
+
+ if (!t->intermediate)
+ return btd_error_not_supported(msg);
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ watcher = find_watcher(t->fwatchers, sender, path);
+ if (watcher == NULL)
+ return btd_error_does_not_exist(msg);
+
+ if (find_watcher(t->iwatchers, sender, path))
+ return btd_error_already_exists(msg);
+
+ DBG("Intermediate measurement watcher %s registered", path);
+
+ if (g_slist_length(t->iwatchers) == 0)
+ enable_intermediate_measurement(t);
+
+ t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *sender = dbus_message_get_sender(msg);
+ struct thermometer *t = data;
+ struct watcher *watcher;
+ char *path;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ watcher = find_watcher(t->iwatchers, sender, path);
+ if (watcher == NULL)
+ return btd_error_does_not_exist(msg);
+
+ DBG("Intermediate measurement %s unregistered", path);
+
+ remove_int_watcher(t, watcher);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable thermometer_methods[] = {
+ { GDBUS_METHOD("GetProperties",
+ NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+ get_properties) },
+ { GDBUS_ASYNC_METHOD("SetProperty",
+ GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
+ set_property) },
+ { GDBUS_METHOD("RegisterWatcher",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ register_watcher) },
+ { GDBUS_METHOD("UnregisterWatcher",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ unregister_watcher) },
+ { GDBUS_METHOD("EnableIntermediateMeasurement",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ enable_intermediate) },
+ { GDBUS_METHOD("DisableIntermediateMeasurement",
+ GDBUS_ARGS({ "agent", "o" }), NULL,
+ disable_intermediate) },
+ { }
+};
+
+static const GDBusSignalTable thermometer_signals[] = {
+ { GDBUS_SIGNAL("PropertyChanged",
+ GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+ { }
+};
+
+static void update_watcher(gpointer data, gpointer user_data)
+{
+ struct watcher *w = data;
+ struct measurement *m = user_data;
+ DBusConnection *conn = w->t->conn;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ DBusMessage *msg;
+
+ msg = dbus_message_new_method_call(w->srv, w->path,
+ "org.bluez.ThermometerWatcher",
+ "MeasurementReceived");
+ if (msg == NULL)
+ return;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ dict_append_entry(&dict, "Exponent", DBUS_TYPE_INT16, &m->exp);
+ dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant);
+ dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit);
+
+ if (m->suptime)
+ dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time);
+
+ dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type);
+ dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->value);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_message_set_no_reply(msg, TRUE);
+ g_dbus_send_message(conn, msg);
+}
+
+static void recv_measurement(struct thermometer *t, struct measurement *m)
+{
+ GSList *wlist;
+
+ if (g_strcmp0(m->value, "Intermediate") == 0)
+ wlist = t->iwatchers;
+ else
+ wlist = t->fwatchers;
+
+ g_slist_foreach(wlist, update_watcher, m);
+}
+
+static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
+ uint16_t len, gboolean final)
+{
+ struct measurement m;
+ const char *type;
+ uint8_t flags;
+ uint32_t raw;
+
+ if (len < 4) {
+ DBG("Mandatory flags are not provided");
+ return;
+ }
+
+ flags = pdu[3];
+ if (flags & TEMP_UNITS)
+ m.unit = "Fahrenheit";
+ else
+ m.unit = "Celsius";
+
+ if (len < 8) {
+ DBG("Temperature measurement value is not provided");
+ return;
+ }
+
+ raw = att_get_u32(&pdu[4]);
+ m.mant = raw & 0x00FFFFFF;
+ m.exp = ((int32_t) raw) >> 24;
+
+ if (m.mant & 0x00800000) {
+ /* convert to C2 negative value */
+ m.mant = m.mant - FLOAT_MAX_MANTISSA;
+ }
+
+ if (flags & TEMP_TIME_STAMP) {
+ struct tm ts;
+ time_t time;
+
+ if (len < 15) {
+ DBG("Can't get time stamp value");
+ return;
+ }
+
+ ts.tm_year = att_get_u16(&pdu[8]) - 1900;
+ ts.tm_mon = pdu[10] - 1;
+ ts.tm_mday = pdu[11];
+ ts.tm_hour = pdu[12];
+ ts.tm_min = pdu[13];
+ ts.tm_sec = pdu[14];
+ ts.tm_isdst = -1;
+
+ time = mktime(&ts);
+ m.time = (uint64_t) time;
+ m.suptime = TRUE;
+ } else
+ m.suptime = FALSE;
+
+ if (flags & TEMP_TYPE) {
+ uint8_t index;
+
+ if (m.suptime && len >= 16)
+ index = 15;
+ else if (!m.suptime && len >= 9)
+ index = 9;
+ else {
+ DBG("Can't get temperature type");
+ return;
+ }
+
+ type = temptype2str(pdu[index]);
+ } else if (t->has_type)
+ type = temptype2str(t->type);
+ else
+ type = NULL;
+
+ m.type = type ? g_strdup(type) : NULL;
+ m.value = final ? "Final" : "Intermediate";
+
+ recv_measurement(t, &m);
+ g_free(m.type);
+}
+
+static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
+ uint16_t len)
+{
+ uint16_t interval;
+
+ if (len < 5) {
+ DBG("Measurement interval value is not provided");
+ return;
+ }
+
+ interval = att_get_u16(&pdu[3]);
+
+ change_property(t, "Interval", &interval);
+}
+
+static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ struct thermometer *t = user_data;
+ const struct characteristic *ch;
+ uint8_t *opdu;
+ uint16_t handle, olen;
+ GSList *l;
+ int plen;
+
+ if (len < 3) {
+ DBG("Bad pdu received");
+ return;
+ }
+
+ handle = att_get_u16(&pdu[1]);
+ l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+ if (l == NULL) {
+ DBG("Unexpected handle: 0x%04x", handle);
+ return;
+ }
+
+ ch = l->data;
+
+ if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0)
+ proc_measurement(t, pdu, len, TRUE);
+ else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
+ proc_measurement_interval(t, pdu, len);
+
+ opdu = g_attrib_get_buffer(t->attrib, &plen);
+ olen = enc_confirmation(opdu, plen);
+
+ if (olen > 0)
+ g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
+ NULL);
+}
+
+static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
+{
+ struct thermometer *t = user_data;
+ const struct characteristic *ch;
+ uint16_t handle;
+ GSList *l;
+
+ if (len < 3) {
+ DBG("Bad pdu received");
+ return;
+ }
+
+ handle = att_get_u16(&pdu[1]);
+ l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
+ if (l == NULL) {
+ DBG("Unexpected handle: 0x%04x", handle);
+ return;
+ }
+
+ ch = l->data;
+ if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0)
+ proc_measurement(t, pdu, len, FALSE);
+}
+
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ t->attrib = g_attrib_ref(attrib);
+
+ t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
+ ind_handler, t, NULL);
+ t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
+ notif_handler, t, NULL);
+ gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
+ NULL, configure_thermometer_cb, t);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct thermometer *t = user_data;
+
+ DBG("GATT Disconnected");
+
+ if (t->attindid > 0) {
+ g_attrib_unregister(t->attrib, t->attindid);
+ t->attindid = 0;
+ }
+
+ if (t->attnotid > 0) {
+ g_attrib_unregister(t->attrib, t->attnotid);
+ t->attnotid = 0;
+ }
+
+ g_attrib_unref(t->attrib);
+ t->attrib = NULL;
+}
+
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+ struct gatt_primary *tattr)
+{
+ const gchar *path = device_get_path(device);
+ struct thermometer *t;
+
+ t = g_new0(struct thermometer, 1);
+ t->conn = dbus_connection_ref(connection);
+ t->dev = btd_device_ref(device);
+ t->svc_range = g_new0(struct att_range, 1);
+ t->svc_range->start = tattr->range.start;
+ t->svc_range->end = tattr->range.end;
+
+ if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
+ thermometer_methods, thermometer_signals,
+ NULL, t, destroy_thermometer)) {
+ error("D-Bus failed to register %s interface",
+ THERMOMETER_INTERFACE);
+ destroy_thermometer(t);
+ return -EIO;
+ }
+
+ thermometers = g_slist_prepend(thermometers, t);
+
+ t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+ attio_disconnected_cb, t);
+ return 0;
+}
+
+void thermometer_unregister(struct btd_device *device)
+{
+ struct thermometer *t;
+ GSList *l;
+
+ l = g_slist_find_custom(thermometers, device, cmp_device);
+ if (l == NULL)
+ return;
+
+ t = l->data;
+ thermometers = g_slist_remove(thermometers, t);
+ g_dbus_unregister_interface(t->conn, device_get_path(t->dev),
+ THERMOMETER_INTERFACE);
+}
diff --git a/profiles/thermometer/thermometer.h b/profiles/thermometer/thermometer.h
new file mode 100644
index 0000000..330503c
--- /dev/null
+++ b/profiles/thermometer/thermometer.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int thermometer_register(DBusConnection *connection, struct btd_device *device,
+ struct gatt_primary *tattr);
+void thermometer_unregister(struct btd_device *device);
diff --git a/thermometer/main.c b/thermometer/main.c
deleted file mode 100644
index 4447b52..0000000
--- a/thermometer/main.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "manager.h"
-#include "hcid.h"
-#include "log.h"
-
-static DBusConnection *connection = NULL;
-
-static int thermometer_init(void)
-{
- if (!main_opts.gatt_enabled) {
- DBG("GATT is disabled");
- return -ENOTSUP;
- }
-
- connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (connection == NULL)
- return -EIO;
-
- if (thermometer_manager_init(connection) < 0) {
- dbus_connection_unref(connection);
- return -EIO;
- }
-
- return 0;
-}
-
-static void thermometer_exit(void)
-{
- if (!main_opts.gatt_enabled)
- return;
-
- thermometer_manager_exit();
-
- dbus_connection_unref(connection);
- connection = NULL;
-}
-
-BLUETOOTH_PLUGIN_DEFINE(thermometer, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- thermometer_init, thermometer_exit)
diff --git a/thermometer/manager.c b/thermometer/manager.c
deleted file mode 100644
index 3d5452b..0000000
--- a/thermometer/manager.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <gdbus.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "thermometer.h"
-#include "manager.h"
-
-static DBusConnection *connection = NULL;
-
-static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
-{
- const struct gatt_primary *prim = a;
- const char *uuid = b;
-
- return g_strcmp0(prim->uuid, uuid);
-}
-
-static int thermometer_driver_probe(struct btd_device *device, GSList *uuids)
-{
- struct gatt_primary *tattr;
- GSList *primaries, *l;
-
- primaries = btd_device_get_primaries(device);
-
- l = g_slist_find_custom(primaries, HEALTH_THERMOMETER_UUID,
- primary_uuid_cmp);
- if (l == NULL)
- return -EINVAL;
-
- tattr = l->data;
-
- return thermometer_register(connection, device, tattr);
-}
-
-static void thermometer_driver_remove(struct btd_device *device)
-{
- thermometer_unregister(device);
-}
-
-static struct btd_device_driver thermometer_device_driver = {
- .name = "thermometer-device-driver",
- .uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID),
- .probe = thermometer_driver_probe,
- .remove = thermometer_driver_remove
-};
-
-int thermometer_manager_init(DBusConnection *conn)
-{
- int ret;
-
- ret = btd_register_device_driver(&thermometer_device_driver);
- if (ret < 0)
- return ret;
-
- connection = dbus_connection_ref(conn);
- return 0;
-}
-
-void thermometer_manager_exit(void)
-{
- btd_unregister_device_driver(&thermometer_device_driver);
-
- dbus_connection_unref(connection);
- connection = NULL;
-}
diff --git a/thermometer/manager.h b/thermometer/manager.h
deleted file mode 100644
index ed928ad..0000000
--- a/thermometer/manager.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int thermometer_manager_init(DBusConnection *conn);
-void thermometer_manager_exit(void);
diff --git a/thermometer/thermometer.c b/thermometer/thermometer.c
deleted file mode 100644
index 087662e..0000000
--- a/thermometer/thermometer.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gdbus.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "dbus-common.h"
-#include "adapter.h"
-#include "device.h"
-#include "error.h"
-#include "log.h"
-#include "gattrib.h"
-#include "attio.h"
-#include "att.h"
-#include "gatt.h"
-#include "thermometer.h"
-
-#define THERMOMETER_INTERFACE "org.bluez.Thermometer"
-
-/* Temperature measurement flag fields */
-#define TEMP_UNITS 0x01
-#define TEMP_TIME_STAMP 0x02
-#define TEMP_TYPE 0x04
-
-#define FLOAT_MAX_MANTISSA 16777216 /* 2^24 */
-
-#define VALID_RANGE_DESC_SIZE 4
-#define TEMPERATURE_TYPE_SIZE 1
-#define MEASUREMENT_INTERVAL_SIZE 2
-
-struct thermometer {
- DBusConnection *conn; /* The connection to the bus */
- struct btd_device *dev; /* Device reference */
- GAttrib *attrib; /* GATT connection */
- struct att_range *svc_range; /* Thermometer range */
- guint attioid; /* Att watcher id */
- guint attindid; /* Att incications id */
- guint attnotid; /* Att notifications id */
- GSList *chars; /* Characteristics */
- GSList *fwatchers; /* Final measurements */
- GSList *iwatchers; /* Intermediate measurements */
- gboolean intermediate;
- uint8_t type;
- uint16_t interval;
- uint16_t max;
- uint16_t min;
- gboolean has_type;
- gboolean has_interval;
-};
-
-struct characteristic {
- struct gatt_char attr; /* Characteristic */
- GSList *desc; /* Descriptors */
- struct thermometer *t; /* Thermometer where the char belongs */
-};
-
-struct descriptor {
- struct characteristic *ch;
- uint16_t handle;
- bt_uuid_t uuid;
-};
-
-struct watcher {
- struct thermometer *t;
- guint id;
- char *srv;
- char *path;
-};
-
-struct measurement {
- int16_t exp;
- int32_t mant;
- uint64_t time;
- gboolean suptime;
- char *unit;
- char *type;
- char *value;
-};
-
-struct tmp_interval_data {
- struct thermometer *thermometer;
- uint16_t interval;
-};
-
-static GSList *thermometers = NULL;
-
-const char *temp_type[] = {
- "<reserved>",
- "Armpit",
- "Body",
- "Ear",
- "Finger",
- "Intestines",
- "Mouth",
- "Rectum",
- "Toe",
- "Tympanum"
-};
-
-static const gchar *temptype2str(uint8_t value)
-{
- if (value > 0 && value < G_N_ELEMENTS(temp_type))
- return temp_type[value];
-
- error("Temperature type %d reserved for future use", value);
- return NULL;
-}
-
-static void destroy_watcher(gpointer user_data)
-{
- struct watcher *watcher = user_data;
-
- g_free(watcher->path);
- g_free(watcher->srv);
- g_free(watcher);
-}
-
-static void remove_watcher(gpointer user_data)
-{
- struct watcher *watcher = user_data;
-
- g_dbus_remove_watch(watcher->t->conn, watcher->id);
-}
-
-static void destroy_char(gpointer user_data)
-{
- struct characteristic *c = user_data;
-
- g_slist_free_full(c->desc, g_free);
- g_free(c);
-}
-
-static void destroy_thermometer(gpointer user_data)
-{
- struct thermometer *t = user_data;
-
- if (t->attioid > 0)
- btd_device_remove_attio_callback(t->dev, t->attioid);
-
- if (t->attindid > 0)
- g_attrib_unregister(t->attrib, t->attindid);
-
- if (t->attnotid > 0)
- g_attrib_unregister(t->attrib, t->attnotid);
-
- if (t->attrib != NULL)
- g_attrib_unref(t->attrib);
-
- if (t->chars != NULL)
- g_slist_free_full(t->chars, destroy_char);
-
- if (t->fwatchers != NULL)
- g_slist_free_full(t->fwatchers, remove_watcher);
-
- dbus_connection_unref(t->conn);
- btd_device_unref(t->dev);
- g_free(t->svc_range);
- g_free(t);
-}
-
-static gint cmp_device(gconstpointer a, gconstpointer b)
-{
- const struct thermometer *t = a;
- const struct btd_device *dev = b;
-
- if (dev == t->dev)
- return 0;
-
- return -1;
-}
-
-static gint cmp_watcher(gconstpointer a, gconstpointer b)
-{
- const struct watcher *watcher = a;
- const struct watcher *match = b;
- int ret;
-
- ret = g_strcmp0(watcher->srv, match->srv);
- if (ret != 0)
- return ret;
-
- return g_strcmp0(watcher->path, match->path);
-}
-
-static gint cmp_char_uuid(gconstpointer a, gconstpointer b)
-{
- const struct characteristic *ch = a;
- const char *uuid = b;
-
- return g_strcmp0(ch->attr.uuid, uuid);
-}
-
-static gint cmp_char_val_handle(gconstpointer a, gconstpointer b)
-{
- const struct characteristic *ch = a;
- const uint16_t *handle = b;
-
- return ch->attr.value_handle - *handle;
-}
-
-static gint cmp_descriptor(gconstpointer a, gconstpointer b)
-{
- const struct descriptor *desc = a;
- const bt_uuid_t *uuid = b;
-
- return bt_uuid_cmp(&desc->uuid, uuid);
-}
-
-static struct characteristic *get_characteristic(struct thermometer *t,
- const char *uuid)
-{
- GSList *l;
-
- l = g_slist_find_custom(t->chars, uuid, cmp_char_uuid);
- if (l == NULL)
- return NULL;
-
- return l->data;
-}
-
-static struct descriptor *get_descriptor(struct characteristic *ch,
- const bt_uuid_t *uuid)
-{
- GSList *l;
-
- l = g_slist_find_custom(ch->desc, uuid, cmp_descriptor);
- if (l == NULL)
- return NULL;
-
- return l->data;
-}
-
-static void change_property(struct thermometer *t, const char *name,
- gpointer value) {
- if (g_strcmp0(name, "Intermediate") == 0) {
- gboolean *intermediate = value;
- if (t->intermediate == *intermediate)
- return;
-
- t->intermediate = *intermediate;
- emit_property_changed(t->conn, device_get_path(t->dev),
- THERMOMETER_INTERFACE, name,
- DBUS_TYPE_BOOLEAN, &t->intermediate);
- } else if (g_strcmp0(name, "Interval") == 0) {
- uint16_t *interval = value;
- if (t->has_interval && t->interval == *interval)
- return;
-
- t->has_interval = TRUE;
- t->interval = *interval;
- emit_property_changed(t->conn, device_get_path(t->dev),
- THERMOMETER_INTERFACE, name,
- DBUS_TYPE_UINT16, &t->interval);
- } else if (g_strcmp0(name, "Maximum") == 0) {
- uint16_t *max = value;
- if (t->max == *max)
- return;
-
- t->max = *max;
- emit_property_changed(t->conn, device_get_path(t->dev),
- THERMOMETER_INTERFACE, name,
- DBUS_TYPE_UINT16, &t->max);
- } else if (g_strcmp0(name, "Minimum") == 0) {
- uint16_t *min = value;
- if (t->min == *min)
- return;
-
- t->min = *min;
- emit_property_changed(t->conn, device_get_path(t->dev),
- THERMOMETER_INTERFACE, name,
- DBUS_TYPE_UINT16, &t->min);
- } else
- DBG("%s is not a thermometer property", name);
-}
-
-static void valid_range_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct descriptor *desc = user_data;
- uint8_t value[VALID_RANGE_DESC_SIZE];
- uint16_t max, min;
- ssize_t vlen;
-
- if (status != 0) {
- DBG("Valid Range descriptor read failed: %s",
- att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, len, value, sizeof(value));
- if (vlen < 0) {
- DBG("Protocol error\n");
- return;
- }
-
- if (vlen < 4) {
- DBG("Invalid range received");
- return;
- }
-
- min = att_get_u16(&value[0]);
- max = att_get_u16(&value[2]);
-
- if (min == 0 || min > max) {
- DBG("Invalid range");
- return;
- }
-
- change_property(desc->ch->t, "Maximum", &max);
- change_property(desc->ch->t, "Minimum", &min);
-}
-
-static void measurement_cb(guint8 status, const guint8 *pdu,
- guint16 len, gpointer user_data)
-{
- char *msg = user_data;
-
- if (status != 0)
- error("%s failed", msg);
-
- g_free(msg);
-}
-
-static void process_thermometer_desc(struct descriptor *desc)
-{
- struct characteristic *ch = desc->ch;
- char uuidstr[MAX_LEN_UUID_STR];
- bt_uuid_t btuuid;
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
-
- if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0) {
- uint8_t atval[2];
- uint16_t val;
- char *msg;
-
- if (g_strcmp0(ch->attr.uuid,
- TEMPERATURE_MEASUREMENT_UUID) == 0) {
- if (g_slist_length(ch->t->fwatchers) == 0)
- return;
-
- val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
- msg = g_strdup("Enable Temperature Measurement "
- "indication");
- } else if (g_strcmp0(ch->attr.uuid,
- INTERMEDIATE_TEMPERATURE_UUID) == 0) {
- if (g_slist_length(ch->t->iwatchers) == 0)
- return;
-
- val = GATT_CLIENT_CHARAC_CFG_NOTIF_BIT;
- msg = g_strdup("Enable Intermediate Temperature "
- "notification");
- } else if (g_strcmp0(ch->attr.uuid,
- MEASUREMENT_INTERVAL_UUID) == 0) {
- val = GATT_CLIENT_CHARAC_CFG_IND_BIT;
- msg = g_strdup("Enable Measurement Interval "
- "indication");
- } else
- goto done;
-
- att_put_u16(val, atval);
- gatt_write_char(ch->t->attrib, desc->handle, atval, 2,
- measurement_cb, msg);
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CHARAC_VALID_RANGE_UUID);
-
- if (bt_uuid_cmp(&desc->uuid, &btuuid) == 0 && g_strcmp0(ch->attr.uuid,
- MEASUREMENT_INTERVAL_UUID) == 0) {
- gatt_read_char(ch->t->attrib, desc->handle, 0,
- valid_range_desc_cb, desc);
- return;
- }
-
-done:
- bt_uuid_to_string(&desc->uuid, uuidstr, MAX_LEN_UUID_STR);
- DBG("Ignored descriptor %s in characteristic %s", uuidstr,
- ch->attr.uuid);
-}
-
-static void discover_desc_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct characteristic *ch = user_data;
- struct att_data_list *list;
- uint8_t format;
- int i;
-
- if (status != 0) {
- error("Discover all characteristic descriptors failed [%s]: %s",
- ch->attr.uuid, att_ecode2str(status));
- return;
- }
-
- list = dec_find_info_resp(pdu, len, &format);
- if (list == NULL)
- return;
-
- for (i = 0; i < list->num; i++) {
- struct descriptor *desc;
- uint8_t *value;
-
- value = list->data[i];
- desc = g_new0(struct descriptor, 1);
- desc->handle = att_get_u16(value);
- desc->ch = ch;
-
- if (format == 0x01)
- desc->uuid = att_get_uuid16(&value[2]);
- else
- desc->uuid = att_get_uuid128(&value[2]);
-
- ch->desc = g_slist_append(ch->desc, desc);
- process_thermometer_desc(desc);
- }
-
- att_data_list_free(list);
-}
-
-static void read_temp_type_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct characteristic *ch = user_data;
- struct thermometer *t = ch->t;
- uint8_t value[TEMPERATURE_TYPE_SIZE];
- ssize_t vlen;
-
- if (status != 0) {
- DBG("Temperature Type value read failed: %s",
- att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, len, value, sizeof(value));
- if (vlen < 0) {
- DBG("Protocol error.");
- return;
- }
-
- if (vlen != 1) {
- DBG("Invalid length for Temperature type");
- return;
- }
-
- t->has_type = TRUE;
- t->type = value[0];
-}
-
-static void read_interval_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct characteristic *ch = user_data;
- uint8_t value[MEASUREMENT_INTERVAL_SIZE];
- uint16_t interval;
- ssize_t vlen;
-
- if (status != 0) {
- DBG("Measurement Interval value read failed: %s",
- att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, len, value, sizeof(value));
- if (vlen < 0) {
- DBG("Protocol error\n");
- return;
- }
-
- if (vlen < 2) {
- DBG("Invalid Interval received");
- return;
- }
-
- interval = att_get_u16(&value[0]);
- change_property(ch->t, "Interval", &interval);
-}
-
-static void process_thermometer_char(struct characteristic *ch)
-{
- if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0) {
- gboolean intermediate = TRUE;
- change_property(ch->t, "Intermediate", &intermediate);
- return;
- } else if (g_strcmp0(ch->attr.uuid, TEMPERATURE_TYPE_UUID) == 0)
- gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
- read_temp_type_cb, ch);
- else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
- gatt_read_char(ch->t->attrib, ch->attr.value_handle, 0,
- read_interval_cb, ch);
-}
-
-static void configure_thermometer_cb(GSList *characteristics, guint8 status,
- gpointer user_data)
-{
- struct thermometer *t = user_data;
- GSList *l;
-
- if (status != 0) {
- error("Discover thermometer characteristics: %s",
- att_ecode2str(status));
- return;
- }
-
- for (l = characteristics; l; l = l->next) {
- struct gatt_char *c = l->data;
- struct characteristic *ch;
- uint16_t start, end;
-
- ch = g_new0(struct characteristic, 1);
- ch->attr.handle = c->handle;
- ch->attr.properties = c->properties;
- ch->attr.value_handle = c->value_handle;
- memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
- ch->t = t;
-
- t->chars = g_slist_append(t->chars, ch);
-
- process_thermometer_char(ch);
-
- start = c->value_handle + 1;
-
- if (l->next != NULL) {
- struct gatt_char *c = l->next->data;
- if (start == c->handle)
- continue;
- end = c->handle - 1;
- } else if (c->value_handle != t->svc_range->end)
- end = t->svc_range->end;
- else
- continue;
-
- gatt_find_info(t->attrib, start, end, discover_desc_cb, ch);
- }
-}
-
-static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct thermometer *t = data;
- DBusMessageIter iter;
- DBusMessageIter dict;
- DBusMessage *reply;
-
- reply = dbus_message_new_method_return(msg);
- if (reply == NULL)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- dict_append_entry(&dict, "Intermediate", DBUS_TYPE_BOOLEAN,
- &t->intermediate);
-
- if (t->has_interval) {
- dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT16,
- &t->interval);
- dict_append_entry(&dict, "Maximum", DBUS_TYPE_UINT16, &t->max);
- dict_append_entry(&dict, "Minimum", DBUS_TYPE_UINT16, &t->min);
- }
-
- dbus_message_iter_close_container(&iter, &dict);
-
- return reply;
-}
-
-static void write_interval_cb (guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct tmp_interval_data *data = user_data;
-
- if (status != 0) {
- error("Interval Write Request failed %s",
- att_ecode2str(status));
- goto done;
- }
-
- if (!dec_write_resp(pdu, len)) {
- error("Interval Write Request: protocol error");
- goto done;
- }
-
- change_property(data->thermometer, "Interval", &data->interval);
-
-done:
- g_free(user_data);
-}
-
-static DBusMessage *write_attr_interval(struct thermometer *t, DBusMessage *msg,
- uint16_t value)
-{
- struct tmp_interval_data *data;
- struct characteristic *ch;
- uint8_t atval[2];
-
- if (t->attrib == NULL)
- return btd_error_not_connected(msg);
-
- ch = get_characteristic(t, MEASUREMENT_INTERVAL_UUID);
- if (ch == NULL)
- return btd_error_not_available(msg);
-
- if (value < t->min || value > t->max)
- return btd_error_invalid_args(msg);
-
- att_put_u16(value, &atval[0]);
-
- data = g_new0(struct tmp_interval_data, 1);
- data->thermometer = t;
- data->interval = value;
- gatt_write_char(t->attrib, ch->attr.value_handle, atval, 2,
- write_interval_cb, data);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct thermometer *t = data;
- const char *property;
- DBusMessageIter iter;
- DBusMessageIter sub;
- uint16_t value;
-
- if (!dbus_message_iter_init(msg, &iter))
- return btd_error_invalid_args(msg);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_get_basic(&iter, &property);
- if (g_strcmp0("Interval", property) != 0)
- return btd_error_invalid_args(msg);
-
- if (!t->has_interval)
- return btd_error_not_available(msg);
-
- dbus_message_iter_next(&iter);
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_recurse(&iter, &sub);
-
- if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT16)
- return btd_error_invalid_args(msg);
-
- dbus_message_iter_get_basic(&sub, &value);
-
- return write_attr_interval(t, msg, value);
-}
-
-static void enable_final_measurement(struct thermometer *t)
-{
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
- if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x02;
- atval[1] = 0x00;
- msg = g_strdup("Enable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void enable_intermediate_measurement(struct thermometer *t)
-{
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x01;
- atval[1] = 0x00;
- msg = g_strdup("Enable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void disable_final_measurement(struct thermometer *t)
-{
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, TEMPERATURE_MEASUREMENT_UUID);
- if (ch == NULL) {
- DBG("Temperature measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable final measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void disable_intermediate_measurement(struct thermometer *t)
-{
- struct characteristic *ch;
- struct descriptor *desc;
- bt_uuid_t btuuid;
- uint8_t atval[2];
- char *msg;
-
- if (t->attrib == NULL)
- return;
-
- ch = get_characteristic(t, INTERMEDIATE_TEMPERATURE_UUID);
- if (ch == NULL) {
- DBG("Intermediate measurement characteristic not found");
- return;
- }
-
- bt_uuid16_create(&btuuid, GATT_CLIENT_CHARAC_CFG_UUID);
- desc = get_descriptor(ch, &btuuid);
- if (desc == NULL) {
- DBG("Client characteristic configuration descriptor not found");
- return;
- }
-
- atval[0] = 0x00;
- atval[1] = 0x00;
- msg = g_strdup("Disable intermediate measurement");
- gatt_write_char(t->attrib, desc->handle, atval, 2, measurement_cb, msg);
-}
-
-static void remove_int_watcher(struct thermometer *t, struct watcher *w)
-{
- if (!g_slist_find(t->iwatchers, w))
- return;
-
- t->iwatchers = g_slist_remove(t->iwatchers, w);
-
- if (g_slist_length(t->iwatchers) == 0)
- disable_intermediate_measurement(t);
-}
-
-static void watcher_exit(DBusConnection *conn, void *user_data)
-{
- struct watcher *watcher = user_data;
- struct thermometer *t = watcher->t;
-
- DBG("Thermometer watcher %s disconnected", watcher->path);
-
- remove_int_watcher(t, watcher);
-
- t->fwatchers = g_slist_remove(t->fwatchers, watcher);
- g_dbus_remove_watch(watcher->t->conn, watcher->id);
-
- if (g_slist_length(t->fwatchers) == 0)
- disable_final_measurement(t);
-}
-
-static struct watcher *find_watcher(GSList *list, const char *sender,
- const char *path)
-{
- struct watcher *match;
- GSList *l;
-
- match = g_new0(struct watcher, 1);
- match->srv = g_strdup(sender);
- match->path = g_strdup(path);
-
- l = g_slist_find_custom(list, match, cmp_watcher);
- destroy_watcher(match);
-
- if (l != NULL)
- return l->data;
-
- return NULL;
-}
-
-static DBusMessage *register_watcher(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
- struct watcher *watcher;
- char *path;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- watcher = find_watcher(t->fwatchers, sender, path);
- if (watcher != NULL)
- return btd_error_already_exists(msg);
-
- DBG("Thermometer watcher %s registered", path);
-
- watcher = g_new0(struct watcher, 1);
- watcher->srv = g_strdup(sender);
- watcher->path = g_strdup(path);
- watcher->t = t;
- watcher->id = g_dbus_add_disconnect_watch(conn, sender, watcher_exit,
- watcher, destroy_watcher);
-
- if (g_slist_length(t->fwatchers) == 0)
- enable_final_measurement(t);
-
- t->fwatchers = g_slist_prepend(t->fwatchers, watcher);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *unregister_watcher(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
- struct watcher *watcher;
- char *path;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- watcher = find_watcher(t->fwatchers, sender, path);
- if (watcher == NULL)
- return btd_error_does_not_exist(msg);
-
- DBG("Thermometer watcher %s unregistered", path);
-
- remove_int_watcher(t, watcher);
-
- t->fwatchers = g_slist_remove(t->fwatchers, watcher);
- g_dbus_remove_watch(watcher->t->conn, watcher->id);
-
- if (g_slist_length(t->fwatchers) == 0)
- disable_final_measurement(t);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *enable_intermediate(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
- struct watcher *watcher;
- char *path;
-
- if (!t->intermediate)
- return btd_error_not_supported(msg);
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- watcher = find_watcher(t->fwatchers, sender, path);
- if (watcher == NULL)
- return btd_error_does_not_exist(msg);
-
- if (find_watcher(t->iwatchers, sender, path))
- return btd_error_already_exists(msg);
-
- DBG("Intermediate measurement watcher %s registered", path);
-
- if (g_slist_length(t->iwatchers) == 0)
- enable_intermediate_measurement(t);
-
- t->iwatchers = g_slist_prepend(t->iwatchers, watcher);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *disable_intermediate(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- const char *sender = dbus_message_get_sender(msg);
- struct thermometer *t = data;
- struct watcher *watcher;
- char *path;
-
- if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID))
- return btd_error_invalid_args(msg);
-
- watcher = find_watcher(t->iwatchers, sender, path);
- if (watcher == NULL)
- return btd_error_does_not_exist(msg);
-
- DBG("Intermediate measurement %s unregistered", path);
-
- remove_int_watcher(t, watcher);
-
- return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable thermometer_methods[] = {
- { GDBUS_METHOD("GetProperties",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- get_properties) },
- { GDBUS_ASYNC_METHOD("SetProperty",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
- set_property) },
- { GDBUS_METHOD("RegisterWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- register_watcher) },
- { GDBUS_METHOD("UnregisterWatcher",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- unregister_watcher) },
- { GDBUS_METHOD("EnableIntermediateMeasurement",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- enable_intermediate) },
- { GDBUS_METHOD("DisableIntermediateMeasurement",
- GDBUS_ARGS({ "agent", "o" }), NULL,
- disable_intermediate) },
- { }
-};
-
-static const GDBusSignalTable thermometer_signals[] = {
- { GDBUS_SIGNAL("PropertyChanged",
- GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
- { }
-};
-
-static void update_watcher(gpointer data, gpointer user_data)
-{
- struct watcher *w = data;
- struct measurement *m = user_data;
- DBusConnection *conn = w->t->conn;
- DBusMessageIter iter;
- DBusMessageIter dict;
- DBusMessage *msg;
-
- msg = dbus_message_new_method_call(w->srv, w->path,
- "org.bluez.ThermometerWatcher",
- "MeasurementReceived");
- if (msg == NULL)
- return;
-
- dbus_message_iter_init_append(msg, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- dict_append_entry(&dict, "Exponent", DBUS_TYPE_INT16, &m->exp);
- dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant);
- dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit);
-
- if (m->suptime)
- dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time);
-
- dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type);
- dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->value);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- dbus_message_set_no_reply(msg, TRUE);
- g_dbus_send_message(conn, msg);
-}
-
-static void recv_measurement(struct thermometer *t, struct measurement *m)
-{
- GSList *wlist;
-
- if (g_strcmp0(m->value, "Intermediate") == 0)
- wlist = t->iwatchers;
- else
- wlist = t->fwatchers;
-
- g_slist_foreach(wlist, update_watcher, m);
-}
-
-static void proc_measurement(struct thermometer *t, const uint8_t *pdu,
- uint16_t len, gboolean final)
-{
- struct measurement m;
- const char *type;
- uint8_t flags;
- uint32_t raw;
-
- if (len < 4) {
- DBG("Mandatory flags are not provided");
- return;
- }
-
- flags = pdu[3];
- if (flags & TEMP_UNITS)
- m.unit = "Fahrenheit";
- else
- m.unit = "Celsius";
-
- if (len < 8) {
- DBG("Temperature measurement value is not provided");
- return;
- }
-
- raw = att_get_u32(&pdu[4]);
- m.mant = raw & 0x00FFFFFF;
- m.exp = ((int32_t) raw) >> 24;
-
- if (m.mant & 0x00800000) {
- /* convert to C2 negative value */
- m.mant = m.mant - FLOAT_MAX_MANTISSA;
- }
-
- if (flags & TEMP_TIME_STAMP) {
- struct tm ts;
- time_t time;
-
- if (len < 15) {
- DBG("Can't get time stamp value");
- return;
- }
-
- ts.tm_year = att_get_u16(&pdu[8]) - 1900;
- ts.tm_mon = pdu[10] - 1;
- ts.tm_mday = pdu[11];
- ts.tm_hour = pdu[12];
- ts.tm_min = pdu[13];
- ts.tm_sec = pdu[14];
- ts.tm_isdst = -1;
-
- time = mktime(&ts);
- m.time = (uint64_t) time;
- m.suptime = TRUE;
- } else
- m.suptime = FALSE;
-
- if (flags & TEMP_TYPE) {
- uint8_t index;
-
- if (m.suptime && len >= 16)
- index = 15;
- else if (!m.suptime && len >= 9)
- index = 9;
- else {
- DBG("Can't get temperature type");
- return;
- }
-
- type = temptype2str(pdu[index]);
- } else if (t->has_type)
- type = temptype2str(t->type);
- else
- type = NULL;
-
- m.type = type ? g_strdup(type) : NULL;
- m.value = final ? "Final" : "Intermediate";
-
- recv_measurement(t, &m);
- g_free(m.type);
-}
-
-static void proc_measurement_interval(struct thermometer *t, const uint8_t *pdu,
- uint16_t len)
-{
- uint16_t interval;
-
- if (len < 5) {
- DBG("Measurement interval value is not provided");
- return;
- }
-
- interval = att_get_u16(&pdu[3]);
-
- change_property(t, "Interval", &interval);
-}
-
-static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
- struct thermometer *t = user_data;
- const struct characteristic *ch;
- uint8_t *opdu;
- uint16_t handle, olen;
- GSList *l;
- int plen;
-
- if (len < 3) {
- DBG("Bad pdu received");
- return;
- }
-
- handle = att_get_u16(&pdu[1]);
- l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
- if (l == NULL) {
- DBG("Unexpected handle: 0x%04x", handle);
- return;
- }
-
- ch = l->data;
-
- if (g_strcmp0(ch->attr.uuid, TEMPERATURE_MEASUREMENT_UUID) == 0)
- proc_measurement(t, pdu, len, TRUE);
- else if (g_strcmp0(ch->attr.uuid, MEASUREMENT_INTERVAL_UUID) == 0)
- proc_measurement_interval(t, pdu, len);
-
- opdu = g_attrib_get_buffer(t->attrib, &plen);
- olen = enc_confirmation(opdu, plen);
-
- if (olen > 0)
- g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
- NULL);
-}
-
-static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
-{
- struct thermometer *t = user_data;
- const struct characteristic *ch;
- uint16_t handle;
- GSList *l;
-
- if (len < 3) {
- DBG("Bad pdu received");
- return;
- }
-
- handle = att_get_u16(&pdu[1]);
- l = g_slist_find_custom(t->chars, &handle, cmp_char_val_handle);
- if (l == NULL) {
- DBG("Unexpected handle: 0x%04x", handle);
- return;
- }
-
- ch = l->data;
- if (g_strcmp0(ch->attr.uuid, INTERMEDIATE_TEMPERATURE_UUID) == 0)
- proc_measurement(t, pdu, len, FALSE);
-}
-
-static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
-{
- struct thermometer *t = user_data;
-
- t->attrib = g_attrib_ref(attrib);
-
- t->attindid = g_attrib_register(t->attrib, ATT_OP_HANDLE_IND,
- ind_handler, t, NULL);
- t->attnotid = g_attrib_register(t->attrib, ATT_OP_HANDLE_NOTIFY,
- notif_handler, t, NULL);
- gatt_discover_char(t->attrib, t->svc_range->start, t->svc_range->end,
- NULL, configure_thermometer_cb, t);
-}
-
-static void attio_disconnected_cb(gpointer user_data)
-{
- struct thermometer *t = user_data;
-
- DBG("GATT Disconnected");
-
- if (t->attindid > 0) {
- g_attrib_unregister(t->attrib, t->attindid);
- t->attindid = 0;
- }
-
- if (t->attnotid > 0) {
- g_attrib_unregister(t->attrib, t->attnotid);
- t->attnotid = 0;
- }
-
- g_attrib_unref(t->attrib);
- t->attrib = NULL;
-}
-
-int thermometer_register(DBusConnection *connection, struct btd_device *device,
- struct gatt_primary *tattr)
-{
- const gchar *path = device_get_path(device);
- struct thermometer *t;
-
- t = g_new0(struct thermometer, 1);
- t->conn = dbus_connection_ref(connection);
- t->dev = btd_device_ref(device);
- t->svc_range = g_new0(struct att_range, 1);
- t->svc_range->start = tattr->range.start;
- t->svc_range->end = tattr->range.end;
-
- if (!g_dbus_register_interface(t->conn, path, THERMOMETER_INTERFACE,
- thermometer_methods, thermometer_signals,
- NULL, t, destroy_thermometer)) {
- error("D-Bus failed to register %s interface",
- THERMOMETER_INTERFACE);
- destroy_thermometer(t);
- return -EIO;
- }
-
- thermometers = g_slist_prepend(thermometers, t);
-
- t->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
- attio_disconnected_cb, t);
- return 0;
-}
-
-void thermometer_unregister(struct btd_device *device)
-{
- struct thermometer *t;
- GSList *l;
-
- l = g_slist_find_custom(thermometers, device, cmp_device);
- if (l == NULL)
- return;
-
- t = l->data;
- thermometers = g_slist_remove(thermometers, t);
- g_dbus_unregister_interface(t->conn, device_get_path(t->dev),
- THERMOMETER_INTERFACE);
-}
diff --git a/thermometer/thermometer.h b/thermometer/thermometer.h
deleted file mode 100644
index 330503c..0000000
--- a/thermometer/thermometer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 GSyC/LibreSoft, Universidad Rey Juan Carlos.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int thermometer_register(DBusConnection *connection, struct btd_device *device,
- struct gatt_primary *tattr);
-void thermometer_unregister(struct btd_device *device);
--
1.7.10.2


2012-07-09 21:10:30

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 08/14] time: move to the profiles folder

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 5 +-
profiles/time/main.c | 58 ++++++++++++
profiles/time/manager.c | 49 ++++++++++
profiles/time/manager.h | 26 ++++++
profiles/time/server.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++
profiles/time/server.h | 45 +++++++++
time/main.c | 58 ------------
time/manager.c | 49 ----------
time/manager.h | 26 ------
time/server.c | 234 -----------------------------------------------
time/server.h | 45 ---------
11 files changed, 415 insertions(+), 414 deletions(-)
create mode 100644 profiles/time/main.c
create mode 100644 profiles/time/manager.c
create mode 100644 profiles/time/manager.h
create mode 100644 profiles/time/server.c
create mode 100644 profiles/time/server.h
delete mode 100644 time/main.c
delete mode 100644 time/manager.c
delete mode 100644 time/manager.h
delete mode 100644 time/server.c
delete mode 100644 time/server.h

diff --git a/Makefile.am b/Makefile.am
index c8b2475..7e23f5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -222,8 +222,9 @@ builtin_sources += profiles/thermometer/main.c \
profiles/thermometer/thermometer.c \
profiles/alert/main.c profiles/alert/server.h \
profiles/alert/server.c \
- time/main.c time/server.h time/server.c \
- time/manager.h time/manager.c \
+ profiles/time/main.c profiles/time/server.h \
+ profiles/time/server.c profiles/time/manager.c \
+ profiles/time/manager.h \
plugins/gatt-example.c \
profiles/proximity/main.c profiles/proximity/manager.h \
profiles/proximity/manager.c \
diff --git a/profiles/time/main.c b/profiles/time/main.c
new file mode 100644
index 0000000..9ef5bf1
--- /dev/null
+++ b/profiles/time/main.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "hcid.h"
+#include "log.h"
+#include "manager.h"
+
+static int time_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ DBG("GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ return time_manager_init();
+}
+
+static void time_exit(void)
+{
+ if (!main_opts.gatt_enabled)
+ return;
+
+ time_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(time, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ time_init, time_exit)
diff --git a/profiles/time/manager.c b/profiles/time/manager.c
new file mode 100644
index 0000000..285c7b1
--- /dev/null
+++ b/profiles/time/manager.c
@@ -0,0 +1,49 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nokia Corporation
+ * Copyright (C) 2012 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "adapter.h"
+#include "manager.h"
+#include "server.h"
+
+struct btd_adapter_driver time_server_driver = {
+ .name = "gatt-time-server",
+ .probe = time_server_init,
+ .remove = time_server_exit,
+};
+
+int time_manager_init(void)
+{
+ btd_register_adapter_driver(&time_server_driver);
+
+ return 0;
+}
+
+void time_manager_exit(void)
+{
+ btd_unregister_adapter_driver(&time_server_driver);
+}
diff --git a/profiles/time/manager.h b/profiles/time/manager.h
new file mode 100644
index 0000000..74641d6
--- /dev/null
+++ b/profiles/time/manager.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nokia Corporation
+ * Copyright (C) 2012 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int time_manager_init(void);
+void time_manager_exit(void);
diff --git a/profiles/time/server.c b/profiles/time/server.c
new file mode 100644
index 0000000..be6e196
--- /dev/null
+++ b/profiles/time/server.c
@@ -0,0 +1,234 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <time.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+#include <adapter.h>
+
+#include "gattrib.h"
+#include "att.h"
+#include "gatt.h"
+#include "att-database.h"
+#include "attrib-server.h"
+#include "gatt-service.h"
+#include "log.h"
+#include "server.h"
+
+#define CURRENT_TIME_SVC_UUID 0x1805
+#define REF_TIME_UPDATE_SVC_UUID 0x1806
+
+#define LOCAL_TIME_INFO_CHR_UUID 0x2A0F
+#define TIME_UPDATE_CTRL_CHR_UUID 0x2A16
+#define TIME_UPDATE_STAT_CHR_UUID 0x2A17
+#define CT_TIME_CHR_UUID 0x2A2B
+
+static int encode_current_time(uint8_t value[10])
+{
+ struct timespec tp;
+ struct tm tm;
+
+ if (clock_gettime(CLOCK_REALTIME, &tp) == -1) {
+ int err = -errno;
+
+ error("clock_gettime: %s", strerror(-err));
+ return err;
+ }
+
+ if (localtime_r(&tp.tv_sec, &tm) == NULL) {
+ error("localtime_r() failed");
+ /* localtime_r() does not set errno */
+ return -EINVAL;
+ }
+
+ att_put_u16(1900 + tm.tm_year, &value[0]); /* Year */
+ value[2] = tm.tm_mon + 1; /* Month */
+ value[3] = tm.tm_mday; /* Day */
+ value[4] = tm.tm_hour; /* Hours */
+ value[5] = tm.tm_min; /* Minutes */
+ value[6] = tm.tm_sec; /* Seconds */
+ value[7] = tm.tm_wday == 0 ? 7 : tm.tm_wday; /* Day of Week */
+ /* From Time Profile spec: "The number of 1/256 fractions of a second."
+ * In 1s there are 256 fractions, in 1ns there are 256/10^9 fractions.
+ * To avoid integer overflow, we use the equivalent 1/3906250 ratio. */
+ value[8] = tp.tv_nsec / 3906250; /* Fractions256 */
+ value[9] = 0x00; /* Adjust Reason */
+
+ return 0;
+}
+
+static uint8_t current_time_read(struct attribute *a,
+ struct btd_device *device, gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ uint8_t value[10];
+
+ if (encode_current_time(value) < 0)
+ return ATT_ECODE_IO;
+
+ attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+ return 0;
+}
+
+static uint8_t local_time_info_read(struct attribute *a,
+ struct btd_device *device, gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ uint8_t value[2];
+
+ DBG("a=%p", a);
+
+ tzset();
+
+ /* FIXME: POSIX "daylight" variable only indicates whether there is DST
+ * for the local time or not. The offset is unknown. */
+ value[0] = daylight ? 0xff : 0x00;
+
+ /* Convert POSIX "timezone" (seconds West of GMT) to Time Profile
+ * format (offset from UTC in number of 15 minutes increments). */
+ value[1] = (uint8_t) (-1 * timezone / (60 * 15));
+
+ attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+ return 0;
+}
+
+static gboolean register_current_time_service(struct btd_adapter *adapter)
+{
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, CURRENT_TIME_SVC_UUID);
+
+ /* Current Time service */
+ return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ /* CT Time characteristic */
+ GATT_OPT_CHR_UUID, CT_TIME_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
+ ATT_CHAR_PROPER_NOTIFY,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ current_time_read, adapter,
+
+ /* Local Time Information characteristic */
+ GATT_OPT_CHR_UUID, LOCAL_TIME_INFO_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ local_time_info_read, adapter,
+
+ GATT_OPT_INVALID);
+}
+
+static uint8_t time_update_control(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ DBG("handle 0x%04x", a->handle);
+
+ if (a->len != 1)
+ DBG("Invalid control point value size: %d", a->len);
+
+ switch (a->data[0]) {
+ case GET_REFERENCE_UPDATE:
+ DBG("Get Reference Update");
+ break;
+ case CANCEL_REFERENCE_UPDATE:
+ DBG("Cancel Reference Update");
+ break;
+ default:
+ DBG("Unknown command: 0x%02x", a->data[0]);
+ }
+
+ return 0;
+}
+
+static uint8_t time_update_status(struct attribute *a,
+ struct btd_device *device,
+ gpointer user_data)
+{
+ struct btd_adapter *adapter = user_data;
+ uint8_t value[2];
+
+ DBG("handle 0x%04x", a->handle);
+
+ value[0] = UPDATE_STATE_IDLE;
+ value[1] = UPDATE_RESULT_SUCCESSFUL;
+ attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+
+ return 0;
+}
+
+static gboolean register_ref_time_update_service(struct btd_adapter *adapter)
+{
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, REF_TIME_UPDATE_SVC_UUID);
+
+ /* Reference Time Update service */
+ return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+ /* Time Update control point */
+ GATT_OPT_CHR_UUID, TIME_UPDATE_CTRL_CHR_UUID,
+ GATT_OPT_CHR_PROPS,
+ ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
+ time_update_control, adapter,
+
+ /* Time Update status */
+ GATT_OPT_CHR_UUID, TIME_UPDATE_STAT_CHR_UUID,
+ GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
+ GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
+ time_update_status, adapter,
+
+ GATT_OPT_INVALID);
+}
+
+int time_server_init(struct btd_adapter *adapter)
+{
+ const char *path = adapter_get_path(adapter);
+
+ DBG("path %s", path);
+
+ if (!register_current_time_service(adapter)) {
+ error("Current Time Service could not be registered");
+ return -EIO;
+ }
+
+ if (!register_ref_time_update_service(adapter)) {
+ error("Reference Time Update Service could not be registered");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+void time_server_exit(struct btd_adapter *adapter)
+{
+ const char *path = adapter_get_path(adapter);
+
+ DBG("path %s", path);
+}
diff --git a/profiles/time/server.h b/profiles/time/server.h
new file mode 100644
index 0000000..c7b997d
--- /dev/null
+++ b/profiles/time/server.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum {
+ UPDATE_RESULT_SUCCESSFUL = 0,
+ UPDATE_RESULT_CANCELED = 1,
+ UPDATE_RESULT_NO_CONN = 2,
+ UPDATE_RESULT_ERROR = 3,
+ UPDATE_RESULT_TIMEOUT = 4,
+ UPDATE_RESULT_NOT_ATTEMPTED = 5,
+};
+
+enum {
+ UPDATE_STATE_IDLE = 0,
+ UPDATE_STATE_PENDING = 1,
+};
+
+enum {
+ GET_REFERENCE_UPDATE = 1,
+ CANCEL_REFERENCE_UPDATE = 2,
+};
+
+int time_server_init(struct btd_adapter *adapter);
+void time_server_exit(struct btd_adapter *adapter);
diff --git a/time/main.c b/time/main.c
deleted file mode 100644
index 9ef5bf1..0000000
--- a/time/main.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-
-#include "plugin.h"
-#include "hcid.h"
-#include "log.h"
-#include "manager.h"
-
-static int time_init(void)
-{
- if (!main_opts.gatt_enabled) {
- DBG("GATT is disabled");
- return -ENOTSUP;
- }
-
- return time_manager_init();
-}
-
-static void time_exit(void)
-{
- if (!main_opts.gatt_enabled)
- return;
-
- time_manager_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(time, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- time_init, time_exit)
diff --git a/time/manager.c b/time/manager.c
deleted file mode 100644
index 285c7b1..0000000
--- a/time/manager.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Nokia Corporation
- * Copyright (C) 2012 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "adapter.h"
-#include "manager.h"
-#include "server.h"
-
-struct btd_adapter_driver time_server_driver = {
- .name = "gatt-time-server",
- .probe = time_server_init,
- .remove = time_server_exit,
-};
-
-int time_manager_init(void)
-{
- btd_register_adapter_driver(&time_server_driver);
-
- return 0;
-}
-
-void time_manager_exit(void)
-{
- btd_unregister_adapter_driver(&time_server_driver);
-}
diff --git a/time/manager.h b/time/manager.h
deleted file mode 100644
index 74641d6..0000000
--- a/time/manager.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Nokia Corporation
- * Copyright (C) 2012 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int time_manager_init(void);
-void time_manager_exit(void);
diff --git a/time/server.c b/time/server.c
deleted file mode 100644
index be6e196..0000000
--- a/time/server.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <time.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-#include <adapter.h>
-
-#include "gattrib.h"
-#include "att.h"
-#include "gatt.h"
-#include "att-database.h"
-#include "attrib-server.h"
-#include "gatt-service.h"
-#include "log.h"
-#include "server.h"
-
-#define CURRENT_TIME_SVC_UUID 0x1805
-#define REF_TIME_UPDATE_SVC_UUID 0x1806
-
-#define LOCAL_TIME_INFO_CHR_UUID 0x2A0F
-#define TIME_UPDATE_CTRL_CHR_UUID 0x2A16
-#define TIME_UPDATE_STAT_CHR_UUID 0x2A17
-#define CT_TIME_CHR_UUID 0x2A2B
-
-static int encode_current_time(uint8_t value[10])
-{
- struct timespec tp;
- struct tm tm;
-
- if (clock_gettime(CLOCK_REALTIME, &tp) == -1) {
- int err = -errno;
-
- error("clock_gettime: %s", strerror(-err));
- return err;
- }
-
- if (localtime_r(&tp.tv_sec, &tm) == NULL) {
- error("localtime_r() failed");
- /* localtime_r() does not set errno */
- return -EINVAL;
- }
-
- att_put_u16(1900 + tm.tm_year, &value[0]); /* Year */
- value[2] = tm.tm_mon + 1; /* Month */
- value[3] = tm.tm_mday; /* Day */
- value[4] = tm.tm_hour; /* Hours */
- value[5] = tm.tm_min; /* Minutes */
- value[6] = tm.tm_sec; /* Seconds */
- value[7] = tm.tm_wday == 0 ? 7 : tm.tm_wday; /* Day of Week */
- /* From Time Profile spec: "The number of 1/256 fractions of a second."
- * In 1s there are 256 fractions, in 1ns there are 256/10^9 fractions.
- * To avoid integer overflow, we use the equivalent 1/3906250 ratio. */
- value[8] = tp.tv_nsec / 3906250; /* Fractions256 */
- value[9] = 0x00; /* Adjust Reason */
-
- return 0;
-}
-
-static uint8_t current_time_read(struct attribute *a,
- struct btd_device *device, gpointer user_data)
-{
- struct btd_adapter *adapter = user_data;
- uint8_t value[10];
-
- if (encode_current_time(value) < 0)
- return ATT_ECODE_IO;
-
- attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
- return 0;
-}
-
-static uint8_t local_time_info_read(struct attribute *a,
- struct btd_device *device, gpointer user_data)
-{
- struct btd_adapter *adapter = user_data;
- uint8_t value[2];
-
- DBG("a=%p", a);
-
- tzset();
-
- /* FIXME: POSIX "daylight" variable only indicates whether there is DST
- * for the local time or not. The offset is unknown. */
- value[0] = daylight ? 0xff : 0x00;
-
- /* Convert POSIX "timezone" (seconds West of GMT) to Time Profile
- * format (offset from UTC in number of 15 minutes increments). */
- value[1] = (uint8_t) (-1 * timezone / (60 * 15));
-
- attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
- return 0;
-}
-
-static gboolean register_current_time_service(struct btd_adapter *adapter)
-{
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, CURRENT_TIME_SVC_UUID);
-
- /* Current Time service */
- return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
- /* CT Time characteristic */
- GATT_OPT_CHR_UUID, CT_TIME_CHR_UUID,
- GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ |
- ATT_CHAR_PROPER_NOTIFY,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
- current_time_read, adapter,
-
- /* Local Time Information characteristic */
- GATT_OPT_CHR_UUID, LOCAL_TIME_INFO_CHR_UUID,
- GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
- local_time_info_read, adapter,
-
- GATT_OPT_INVALID);
-}
-
-static uint8_t time_update_control(struct attribute *a,
- struct btd_device *device,
- gpointer user_data)
-{
- DBG("handle 0x%04x", a->handle);
-
- if (a->len != 1)
- DBG("Invalid control point value size: %d", a->len);
-
- switch (a->data[0]) {
- case GET_REFERENCE_UPDATE:
- DBG("Get Reference Update");
- break;
- case CANCEL_REFERENCE_UPDATE:
- DBG("Cancel Reference Update");
- break;
- default:
- DBG("Unknown command: 0x%02x", a->data[0]);
- }
-
- return 0;
-}
-
-static uint8_t time_update_status(struct attribute *a,
- struct btd_device *device,
- gpointer user_data)
-{
- struct btd_adapter *adapter = user_data;
- uint8_t value[2];
-
- DBG("handle 0x%04x", a->handle);
-
- value[0] = UPDATE_STATE_IDLE;
- value[1] = UPDATE_RESULT_SUCCESSFUL;
- attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
-
- return 0;
-}
-
-static gboolean register_ref_time_update_service(struct btd_adapter *adapter)
-{
- bt_uuid_t uuid;
-
- bt_uuid16_create(&uuid, REF_TIME_UPDATE_SVC_UUID);
-
- /* Reference Time Update service */
- return gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
- /* Time Update control point */
- GATT_OPT_CHR_UUID, TIME_UPDATE_CTRL_CHR_UUID,
- GATT_OPT_CHR_PROPS,
- ATT_CHAR_PROPER_WRITE_WITHOUT_RESP,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_WRITE,
- time_update_control, adapter,
-
- /* Time Update status */
- GATT_OPT_CHR_UUID, TIME_UPDATE_STAT_CHR_UUID,
- GATT_OPT_CHR_PROPS, ATT_CHAR_PROPER_READ,
- GATT_OPT_CHR_VALUE_CB, ATTRIB_READ,
- time_update_status, adapter,
-
- GATT_OPT_INVALID);
-}
-
-int time_server_init(struct btd_adapter *adapter)
-{
- const char *path = adapter_get_path(adapter);
-
- DBG("path %s", path);
-
- if (!register_current_time_service(adapter)) {
- error("Current Time Service could not be registered");
- return -EIO;
- }
-
- if (!register_ref_time_update_service(adapter)) {
- error("Reference Time Update Service could not be registered");
- return -EIO;
- }
-
- return 0;
-}
-
-void time_server_exit(struct btd_adapter *adapter)
-{
- const char *path = adapter_get_path(adapter);
-
- DBG("path %s", path);
-}
diff --git a/time/server.h b/time/server.h
deleted file mode 100644
index c7b997d..0000000
--- a/time/server.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-enum {
- UPDATE_RESULT_SUCCESSFUL = 0,
- UPDATE_RESULT_CANCELED = 1,
- UPDATE_RESULT_NO_CONN = 2,
- UPDATE_RESULT_ERROR = 3,
- UPDATE_RESULT_TIMEOUT = 4,
- UPDATE_RESULT_NOT_ATTEMPTED = 5,
-};
-
-enum {
- UPDATE_STATE_IDLE = 0,
- UPDATE_STATE_PENDING = 1,
-};
-
-enum {
- GET_REFERENCE_UPDATE = 1,
- CANCEL_REFERENCE_UPDATE = 2,
-};
-
-int time_server_init(struct btd_adapter *adapter);
-void time_server_exit(struct btd_adapter *adapter);
--
1.7.10.2


2012-07-09 21:10:27

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 05/14] deviceinfo: move to profiles folder

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 11 ++-
deviceinfo/deviceinfo.c | 195 --------------------------------------
deviceinfo/deviceinfo.h | 24 -----
deviceinfo/main.c | 52 ----------
deviceinfo/manager.c | 80 ----------------
deviceinfo/manager.h | 24 -----
profiles/deviceinfo/deviceinfo.c | 195 ++++++++++++++++++++++++++++++++++++++
profiles/deviceinfo/deviceinfo.h | 24 +++++
profiles/deviceinfo/main.c | 52 ++++++++++
profiles/deviceinfo/manager.c | 80 ++++++++++++++++
profiles/deviceinfo/manager.h | 24 +++++
11 files changed, 381 insertions(+), 380 deletions(-)
delete mode 100644 deviceinfo/deviceinfo.c
delete mode 100644 deviceinfo/deviceinfo.h
delete mode 100644 deviceinfo/main.c
delete mode 100644 deviceinfo/manager.c
delete mode 100644 deviceinfo/manager.h
create mode 100644 profiles/deviceinfo/deviceinfo.c
create mode 100644 profiles/deviceinfo/deviceinfo.h
create mode 100644 profiles/deviceinfo/main.c
create mode 100644 profiles/deviceinfo/manager.c
create mode 100644 profiles/deviceinfo/manager.h

diff --git a/Makefile.am b/Makefile.am
index f0e82d1..2487368 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -214,8 +214,7 @@ builtin_sources += health/hdp_main.c health/hdp_types.h \
endif

if GATTMODULES
-builtin_modules += thermometer alert time gatt_example proximity \
- deviceinfo
+builtin_modules += thermometer alert time gatt_example proximity deviceinfo
builtin_sources += thermometer/main.c \
thermometer/manager.h thermometer/manager.c \
thermometer/thermometer.h thermometer/thermometer.c \
@@ -229,9 +228,11 @@ builtin_sources += thermometer/main.c \
proximity/reporter.h proximity/reporter.c \
proximity/linkloss.h proximity/linkloss.c \
proximity/immalert.h proximity/immalert.c \
- deviceinfo/main.c \
- deviceinfo/manager.h deviceinfo/manager.c \
- deviceinfo/deviceinfo.h deviceinfo/deviceinfo.c
+ profiles/deviceinfo/main.c \
+ profiles/deviceinfo/manager.h \
+ profiles/deviceinfo/manager.c \
+ profiles/deviceinfo/deviceinfo.h \
+ profiles/deviceinfo/deviceinfo.c
endif


diff --git a/deviceinfo/deviceinfo.c b/deviceinfo/deviceinfo.c
deleted file mode 100644
index 4548553..0000000
--- a/deviceinfo/deviceinfo.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "gattrib.h"
-#include "attio.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "log.h"
-#include "deviceinfo.h"
-
-#define PNP_ID_SIZE 7
-
-struct deviceinfo {
- struct btd_device *dev; /* Device reference */
- GAttrib *attrib; /* GATT connection */
- guint attioid; /* Att watcher id */
- struct att_range *svc_range; /* DeviceInfo range */
- GSList *chars; /* Characteristics */
-};
-
-static GSList *servers = NULL;
-
-struct characteristic {
- struct gatt_char attr; /* Characteristic */
- struct deviceinfo *d; /* deviceinfo where the char belongs */
-};
-
-static void deviceinfo_free(gpointer user_data)
-{
- struct deviceinfo *d = user_data;
-
- if (d->attioid > 0)
- btd_device_remove_attio_callback(d->dev, d->attioid);
-
- if (d->attrib != NULL)
- g_attrib_unref(d->attrib);
-
- g_slist_free_full(d->chars, g_free);
-
- btd_device_unref(d->dev);
- g_free(d->svc_range);
- g_free(d);
-}
-
-static gint cmp_device(gconstpointer a, gconstpointer b)
-{
- const struct deviceinfo *d = a;
- const struct btd_device *dev = b;
-
- if (dev == d->dev)
- return 0;
-
- return -1;
-}
-
-static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
-{
- struct characteristic *ch = user_data;
- uint8_t value[PNP_ID_SIZE];
- ssize_t vlen;
-
- if (status != 0) {
- error("Error reading PNP_ID value: %s", att_ecode2str(status));
- return;
- }
-
- vlen = dec_read_resp(pdu, len, value, sizeof(value));
- if (vlen < 0) {
- error("Error reading PNP_ID: Protocol error");
- return;
- }
-
- if (vlen < 7) {
- error("Error reading PNP_ID: Invalid pdu length received");
- return;
- }
-
- device_set_pnpid(ch->d->dev, value[0], att_get_u16(&value[1]),
- att_get_u16(&value[3]), att_get_u16(&value[5]));
-}
-
-static void process_deviceinfo_char(struct characteristic *ch)
-{
- if (g_strcmp0(ch->attr.uuid, PNPID_UUID) == 0)
- gatt_read_char(ch->d->attrib, ch->attr.value_handle, 0,
- read_pnpid_cb, ch);
-}
-
-static void configure_deviceinfo_cb(GSList *characteristics, guint8 status,
- gpointer user_data)
-{
- struct deviceinfo *d = user_data;
- GSList *l;
-
- if (status != 0) {
- error("Discover deviceinfo characteristics: %s",
- att_ecode2str(status));
- return;
- }
-
- for (l = characteristics; l; l = l->next) {
- struct gatt_char *c = l->data;
- struct characteristic *ch;
-
- ch = g_new0(struct characteristic, 1);
- ch->attr.handle = c->handle;
- ch->attr.properties = c->properties;
- ch->attr.value_handle = c->value_handle;
- memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
- ch->d = d;
-
- d->chars = g_slist_append(d->chars, ch);
-
- process_deviceinfo_char(ch);
- }
-}
-static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
-{
- struct deviceinfo *d = user_data;
-
- d->attrib = g_attrib_ref(attrib);
-
- gatt_discover_char(d->attrib, d->svc_range->start, d->svc_range->end,
- NULL, configure_deviceinfo_cb, d);
-}
-
-static void attio_disconnected_cb(gpointer user_data)
-{
- struct deviceinfo *d = user_data;
-
- g_attrib_unref(d->attrib);
- d->attrib = NULL;
-}
-
-int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim)
-{
- struct deviceinfo *d;
-
- d = g_new0(struct deviceinfo, 1);
- d->dev = btd_device_ref(device);
- d->svc_range = g_new0(struct att_range, 1);
- d->svc_range->start = prim->range.start;
- d->svc_range->end = prim->range.end;
-
- servers = g_slist_prepend(servers, d);
-
- d->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
- attio_disconnected_cb, d);
- return 0;
-}
-
-void deviceinfo_unregister(struct btd_device *device)
-{
- struct deviceinfo *d;
- GSList *l;
-
- l = g_slist_find_custom(servers, device, cmp_device);
- if (l == NULL)
- return;
-
- d = l->data;
- servers = g_slist_remove(servers, d);
-
- deviceinfo_free(d);
-}
diff --git a/deviceinfo/deviceinfo.h b/deviceinfo/deviceinfo.h
deleted file mode 100644
index 7a804a5..0000000
--- a/deviceinfo/deviceinfo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim);
-void deviceinfo_unregister(struct btd_device *device);
diff --git a/deviceinfo/main.c b/deviceinfo/main.c
deleted file mode 100644
index 82ecc82..0000000
--- a/deviceinfo/main.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include "plugin.h"
-#include "manager.h"
-#include "hcid.h"
-#include "log.h"
-
-static int deviceinfo_init(void)
-{
- if (!main_opts.gatt_enabled) {
- error("DIS cannot start: GATT is disabled");
- return -ENOTSUP;
- }
-
- return deviceinfo_manager_init();
-}
-
-static void deviceinfo_exit(void)
-{
- deviceinfo_manager_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- deviceinfo_init, deviceinfo_exit)
diff --git a/deviceinfo/manager.c b/deviceinfo/manager.c
deleted file mode 100644
index 1d59918..0000000
--- a/deviceinfo/manager.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include <glib.h>
-#include <errno.h>
-#include <bluetooth/uuid.h>
-
-#include "adapter.h"
-#include "device.h"
-#include "att.h"
-#include "gattrib.h"
-#include "gatt.h"
-#include "deviceinfo.h"
-#include "manager.h"
-
-static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
-{
- const struct gatt_primary *prim = a;
- const char *uuid = b;
-
- return g_strcmp0(prim->uuid, uuid);
-}
-
-static int deviceinfo_driver_probe(struct btd_device *device, GSList *uuids)
-{
- struct gatt_primary *prim;
- GSList *primaries, *l;
-
- primaries = btd_device_get_primaries(device);
-
- l = g_slist_find_custom(primaries, DEVICE_INFORMATION_UUID,
- primary_uuid_cmp);
- if (l == NULL)
- return -EINVAL;
-
- prim = l->data;
-
- return deviceinfo_register(device, prim);
-}
-
-static void deviceinfo_driver_remove(struct btd_device *device)
-{
- deviceinfo_unregister(device);
-}
-
-static struct btd_device_driver deviceinfo_device_driver = {
- .name = "deviceinfo-driver",
- .uuids = BTD_UUIDS(DEVICE_INFORMATION_UUID),
- .probe = deviceinfo_driver_probe,
- .remove = deviceinfo_driver_remove
-};
-
-int deviceinfo_manager_init(void)
-{
- return btd_register_device_driver(&deviceinfo_device_driver);
-}
-
-void deviceinfo_manager_exit(void)
-{
- btd_unregister_device_driver(&deviceinfo_device_driver);
-}
diff --git a/deviceinfo/manager.h b/deviceinfo/manager.h
deleted file mode 100644
index 0f742ca..0000000
--- a/deviceinfo/manager.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int deviceinfo_manager_init(void);
-void deviceinfo_manager_exit(void);
diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
new file mode 100644
index 0000000..4548553
--- /dev/null
+++ b/profiles/deviceinfo/deviceinfo.c
@@ -0,0 +1,195 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "gattrib.h"
+#include "attio.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "log.h"
+#include "deviceinfo.h"
+
+#define PNP_ID_SIZE 7
+
+struct deviceinfo {
+ struct btd_device *dev; /* Device reference */
+ GAttrib *attrib; /* GATT connection */
+ guint attioid; /* Att watcher id */
+ struct att_range *svc_range; /* DeviceInfo range */
+ GSList *chars; /* Characteristics */
+};
+
+static GSList *servers = NULL;
+
+struct characteristic {
+ struct gatt_char attr; /* Characteristic */
+ struct deviceinfo *d; /* deviceinfo where the char belongs */
+};
+
+static void deviceinfo_free(gpointer user_data)
+{
+ struct deviceinfo *d = user_data;
+
+ if (d->attioid > 0)
+ btd_device_remove_attio_callback(d->dev, d->attioid);
+
+ if (d->attrib != NULL)
+ g_attrib_unref(d->attrib);
+
+ g_slist_free_full(d->chars, g_free);
+
+ btd_device_unref(d->dev);
+ g_free(d->svc_range);
+ g_free(d);
+}
+
+static gint cmp_device(gconstpointer a, gconstpointer b)
+{
+ const struct deviceinfo *d = a;
+ const struct btd_device *dev = b;
+
+ if (dev == d->dev)
+ return 0;
+
+ return -1;
+}
+
+static void read_pnpid_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct characteristic *ch = user_data;
+ uint8_t value[PNP_ID_SIZE];
+ ssize_t vlen;
+
+ if (status != 0) {
+ error("Error reading PNP_ID value: %s", att_ecode2str(status));
+ return;
+ }
+
+ vlen = dec_read_resp(pdu, len, value, sizeof(value));
+ if (vlen < 0) {
+ error("Error reading PNP_ID: Protocol error");
+ return;
+ }
+
+ if (vlen < 7) {
+ error("Error reading PNP_ID: Invalid pdu length received");
+ return;
+ }
+
+ device_set_pnpid(ch->d->dev, value[0], att_get_u16(&value[1]),
+ att_get_u16(&value[3]), att_get_u16(&value[5]));
+}
+
+static void process_deviceinfo_char(struct characteristic *ch)
+{
+ if (g_strcmp0(ch->attr.uuid, PNPID_UUID) == 0)
+ gatt_read_char(ch->d->attrib, ch->attr.value_handle, 0,
+ read_pnpid_cb, ch);
+}
+
+static void configure_deviceinfo_cb(GSList *characteristics, guint8 status,
+ gpointer user_data)
+{
+ struct deviceinfo *d = user_data;
+ GSList *l;
+
+ if (status != 0) {
+ error("Discover deviceinfo characteristics: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ for (l = characteristics; l; l = l->next) {
+ struct gatt_char *c = l->data;
+ struct characteristic *ch;
+
+ ch = g_new0(struct characteristic, 1);
+ ch->attr.handle = c->handle;
+ ch->attr.properties = c->properties;
+ ch->attr.value_handle = c->value_handle;
+ memcpy(ch->attr.uuid, c->uuid, MAX_LEN_UUID_STR + 1);
+ ch->d = d;
+
+ d->chars = g_slist_append(d->chars, ch);
+
+ process_deviceinfo_char(ch);
+ }
+}
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct deviceinfo *d = user_data;
+
+ d->attrib = g_attrib_ref(attrib);
+
+ gatt_discover_char(d->attrib, d->svc_range->start, d->svc_range->end,
+ NULL, configure_deviceinfo_cb, d);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct deviceinfo *d = user_data;
+
+ g_attrib_unref(d->attrib);
+ d->attrib = NULL;
+}
+
+int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim)
+{
+ struct deviceinfo *d;
+
+ d = g_new0(struct deviceinfo, 1);
+ d->dev = btd_device_ref(device);
+ d->svc_range = g_new0(struct att_range, 1);
+ d->svc_range->start = prim->range.start;
+ d->svc_range->end = prim->range.end;
+
+ servers = g_slist_prepend(servers, d);
+
+ d->attioid = btd_device_add_attio_callback(device, attio_connected_cb,
+ attio_disconnected_cb, d);
+ return 0;
+}
+
+void deviceinfo_unregister(struct btd_device *device)
+{
+ struct deviceinfo *d;
+ GSList *l;
+
+ l = g_slist_find_custom(servers, device, cmp_device);
+ if (l == NULL)
+ return;
+
+ d = l->data;
+ servers = g_slist_remove(servers, d);
+
+ deviceinfo_free(d);
+}
diff --git a/profiles/deviceinfo/deviceinfo.h b/profiles/deviceinfo/deviceinfo.h
new file mode 100644
index 0000000..7a804a5
--- /dev/null
+++ b/profiles/deviceinfo/deviceinfo.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int deviceinfo_register(struct btd_device *device, struct gatt_primary *prim);
+void deviceinfo_unregister(struct btd_device *device);
diff --git a/profiles/deviceinfo/main.c b/profiles/deviceinfo/main.c
new file mode 100644
index 0000000..82ecc82
--- /dev/null
+++ b/profiles/deviceinfo/main.c
@@ -0,0 +1,52 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "plugin.h"
+#include "manager.h"
+#include "hcid.h"
+#include "log.h"
+
+static int deviceinfo_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ error("DIS cannot start: GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ return deviceinfo_manager_init();
+}
+
+static void deviceinfo_exit(void)
+{
+ deviceinfo_manager_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(deviceinfo, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ deviceinfo_init, deviceinfo_exit)
diff --git a/profiles/deviceinfo/manager.c b/profiles/deviceinfo/manager.c
new file mode 100644
index 0000000..1d59918
--- /dev/null
+++ b/profiles/deviceinfo/manager.c
@@ -0,0 +1,80 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <glib.h>
+#include <errno.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "deviceinfo.h"
+#include "manager.h"
+
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const char *uuid = b;
+
+ return g_strcmp0(prim->uuid, uuid);
+}
+
+static int deviceinfo_driver_probe(struct btd_device *device, GSList *uuids)
+{
+ struct gatt_primary *prim;
+ GSList *primaries, *l;
+
+ primaries = btd_device_get_primaries(device);
+
+ l = g_slist_find_custom(primaries, DEVICE_INFORMATION_UUID,
+ primary_uuid_cmp);
+ if (l == NULL)
+ return -EINVAL;
+
+ prim = l->data;
+
+ return deviceinfo_register(device, prim);
+}
+
+static void deviceinfo_driver_remove(struct btd_device *device)
+{
+ deviceinfo_unregister(device);
+}
+
+static struct btd_device_driver deviceinfo_device_driver = {
+ .name = "deviceinfo-driver",
+ .uuids = BTD_UUIDS(DEVICE_INFORMATION_UUID),
+ .probe = deviceinfo_driver_probe,
+ .remove = deviceinfo_driver_remove
+};
+
+int deviceinfo_manager_init(void)
+{
+ return btd_register_device_driver(&deviceinfo_device_driver);
+}
+
+void deviceinfo_manager_exit(void)
+{
+ btd_unregister_device_driver(&deviceinfo_device_driver);
+}
diff --git a/profiles/deviceinfo/manager.h b/profiles/deviceinfo/manager.h
new file mode 100644
index 0000000..0f742ca
--- /dev/null
+++ b/profiles/deviceinfo/manager.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int deviceinfo_manager_init(void);
+void deviceinfo_manager_exit(void);
--
1.7.10.2


2012-07-09 21:10:26

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 04/14] alert: move alert to profiles dir

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 3 ++-
alert/main.c | 58 -----------------------------------------------
alert/server.c | 38 -------------------------------
alert/server.h | 26 ---------------------
profiles/alert/main.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++
profiles/alert/server.c | 38 +++++++++++++++++++++++++++++++
profiles/alert/server.h | 26 +++++++++++++++++++++
7 files changed, 124 insertions(+), 123 deletions(-)
delete mode 100644 alert/main.c
delete mode 100644 alert/server.c
delete mode 100644 alert/server.h
create mode 100644 profiles/alert/main.c
create mode 100644 profiles/alert/server.c
create mode 100644 profiles/alert/server.h

diff --git a/Makefile.am b/Makefile.am
index a2c85e2..f0e82d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -219,7 +219,8 @@ builtin_modules += thermometer alert time gatt_example proximity \
builtin_sources += thermometer/main.c \
thermometer/manager.h thermometer/manager.c \
thermometer/thermometer.h thermometer/thermometer.c \
- alert/main.c alert/server.h alert/server.c \
+ profiles/alert/main.c profiles/alert/server.h \
+ profiles/alert/server.c \
time/main.c time/server.h time/server.c \
time/manager.h time/manager.c \
plugins/gatt-example.c \
diff --git a/alert/main.c b/alert/main.c
deleted file mode 100644
index ec4ab6d..0000000
--- a/alert/main.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-#include <errno.h>
-
-#include "plugin.h"
-#include "hcid.h"
-#include "log.h"
-#include "server.h"
-
-static int alert_init(void)
-{
- if (!main_opts.gatt_enabled) {
- DBG("GATT is disabled");
- return -ENOTSUP;
- }
-
- return alert_server_init();
-}
-
-static void alert_exit(void)
-{
- if (!main_opts.gatt_enabled)
- return;
-
- alert_server_exit();
-}
-
-BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
- alert_init, alert_exit)
diff --git a/alert/server.c b/alert/server.c
deleted file mode 100644
index d91b156..0000000
--- a/alert/server.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "server.h"
-
-int alert_server_init(void)
-{
- return 0;
-}
-
-void alert_server_exit(void)
-{
-}
diff --git a/alert/server.h b/alert/server.h
deleted file mode 100644
index e59bdb1..0000000
--- a/alert/server.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Nokia Corporation
- * Copyright (C) 2011 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int alert_server_init(void);
-void alert_server_exit(void);
diff --git a/profiles/alert/main.c b/profiles/alert/main.c
new file mode 100644
index 0000000..ec4ab6d
--- /dev/null
+++ b/profiles/alert/main.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+#include <errno.h>
+
+#include "plugin.h"
+#include "hcid.h"
+#include "log.h"
+#include "server.h"
+
+static int alert_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ DBG("GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ return alert_server_init();
+}
+
+static void alert_exit(void)
+{
+ if (!main_opts.gatt_enabled)
+ return;
+
+ alert_server_exit();
+}
+
+BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ alert_init, alert_exit)
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
new file mode 100644
index 0000000..d91b156
--- /dev/null
+++ b/profiles/alert/server.c
@@ -0,0 +1,38 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "server.h"
+
+int alert_server_init(void)
+{
+ return 0;
+}
+
+void alert_server_exit(void)
+{
+}
diff --git a/profiles/alert/server.h b/profiles/alert/server.h
new file mode 100644
index 0000000..e59bdb1
--- /dev/null
+++ b/profiles/alert/server.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Marcel Holtmann <[email protected]>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int alert_server_init(void);
+void alert_server_exit(void);
--
1.7.10.2


2012-07-09 21:10:25

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 03/14] btmgmt: move to tools folder

From: Gustavo Padovan <[email protected]>

---
.gitignore | 2 +-
Makefile.tools | 6 +-
mgmt/main.c | 1933 --------------------------------------------------------
3 files changed, 4 insertions(+), 1937 deletions(-)
delete mode 100644 mgmt/main.c

diff --git a/.gitignore b/.gitignore
index c7d079e..bc65dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,7 +86,7 @@ compat/dund
compat/hidd
compat/pand
unit/test-eir
-mgmt/btmgmt
+tools/mgmt/btmgmt
monitor/btmon
emulator/btvirt

diff --git a/Makefile.tools b/Makefile.tools
index 3cb105c..56839b7 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -50,10 +50,10 @@ tools_ppporc_LDADD = lib/libbluetooth-private.la

tools_hcieventmask_LDADD = lib/libbluetooth-private.la

-noinst_PROGRAMS += mgmt/btmgmt monitor/btmon emulator/btvirt
+noinst_PROGRAMS += tools/btmgmt monitor/btmon emulator/btvirt

-mgmt_btmgmt_SOURCES = mgmt/main.c src/glib-helper.c
-mgmt_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
+tools_btmgmt_SOURCES = tools/btmgmt.c src/glib-helper.c
+tools_btmgmt_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@

monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
monitor/mainloop.h monitor/mainloop.c \
diff --git a/mgmt/main.c b/mgmt/main.c
deleted file mode 100644
index b2d6c3c..0000000
--- a/mgmt/main.c
+++ /dev/null
@@ -1,1933 +0,0 @@
-/*
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2011 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <poll.h>
-#include <getopt.h>
-#include <stdbool.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/mgmt.h>
-
-#include <glib.h>
-#include "glib-helper.h"
-
-static bool monitor = false;
-static bool discovery = false;
-static bool resolve_names = true;
-
-typedef void (*cmd_cb)(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data);
-
-static struct pending_cmd {
- uint16_t op;
- uint16_t id;
- cmd_cb cb;
- void *user_data;
- struct pending_cmd *next;
-} *pending = NULL;
-
-static int mgmt_send_cmd(int mgmt_sk, uint16_t op, uint16_t id, void *data,
- size_t len, cmd_cb func, void *user_data)
-{
- char buf[1024];
- struct pending_cmd *cmd;
- struct mgmt_hdr *hdr = (void *) buf;
-
- if (len + MGMT_HDR_SIZE > sizeof(buf))
- return -EINVAL;
-
- cmd = calloc(1, sizeof(struct pending_cmd));
- if (cmd == NULL)
- return -errno;
-
- cmd->op = op;
- cmd->id = id;
- cmd->cb = func;
- cmd->user_data = user_data;
-
- memset(buf, 0, sizeof(buf));
- hdr->opcode = htobs(op);
- hdr->index = htobs(id);
- hdr->len = htobs(len);
- memcpy(buf + MGMT_HDR_SIZE, data, len);
-
- if (write(mgmt_sk, buf, MGMT_HDR_SIZE + len) < 0) {
- fprintf(stderr, "Unable to write to socket: %s\n",
- strerror(errno));
- free(cmd);
- return -1;
- }
-
- cmd->next = pending;
- pending = cmd;
-
- return 0;
-}
-
-static int mgmt_open(void)
-{
- struct sockaddr_hci addr;
- int sk;
-
- sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
- if (sk < 0) {
- fprintf(stderr, "socket: %s\n", strerror(errno));
- return sk;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.hci_family = AF_BLUETOOTH;
- addr.hci_dev = HCI_DEV_NONE;
- addr.hci_channel = HCI_CHANNEL_CONTROL;
-
- if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- fprintf(stderr, "bind: %s\n", strerror(errno));
- close(sk);
- return -1;
- }
-
- return sk;
-}
-
-static void mgmt_check_pending(int mgmt_sk, uint16_t op, uint16_t index,
- uint16_t status, void *data, uint16_t len)
-{
- struct pending_cmd *c, *prev;
-
- for (c = pending, prev = NULL; c != NULL; prev = c, c = c->next) {
- if (c->op != op)
- continue;
- if (c->id != index)
- continue;
-
- if (c == pending)
- pending = c->next;
- else
- prev->next = c->next;
-
- c->cb(mgmt_sk, op, index, status, data, len, c->user_data);
-
- free(c);
- break;
- }
-}
-
-static int mgmt_cmd_complete(int mgmt_sk, uint16_t index,
- struct mgmt_ev_cmd_complete *ev, uint16_t len)
-{
- uint16_t op;
-
- if (len < sizeof(*ev)) {
- fprintf(stderr, "Too short (%u bytes) cmd complete event\n",
- len);
- return -EINVAL;
- }
-
- op = bt_get_le16(&ev->opcode);
-
- len -= sizeof(*ev);
-
- if (monitor)
- printf("%s complete, opcode 0x%04x len %u\n", mgmt_opstr(op),
- op, len);
-
- mgmt_check_pending(mgmt_sk, op, index, ev->status, ev->data, len);
-
- return 0;
-}
-
-static int mgmt_cmd_status(int mgmt_sk, uint16_t index,
- struct mgmt_ev_cmd_status *ev, uint16_t len)
-{
- uint16_t opcode;
-
- if (len < sizeof(*ev)) {
- fprintf(stderr, "Too short (%u bytes) cmd status event\n",
- len);
- return -EINVAL;
- }
-
- opcode = bt_get_le16(&ev->opcode);
-
- if (monitor)
- printf("cmd status, opcode 0x%04x status 0x%02x (%s)\n",
- opcode, ev->status, mgmt_errstr(ev->status));
-
- if (ev->status != 0)
- mgmt_check_pending(mgmt_sk, opcode, index, ev->status,
- NULL, 0);
-
- return 0;
-}
-
-static int mgmt_controller_error(uint16_t index,
- struct mgmt_ev_controller_error *ev,
- uint16_t len)
-{
- if (len < sizeof(*ev)) {
- fprintf(stderr,
- "Too short (%u bytes) controller error event\n", len);
- return -EINVAL;
- }
-
- if (monitor)
- printf("hci%u error 0x%02x\n", index, ev->error_code);
-
- return 0;
-}
-
-static int mgmt_index_added(int mgmt_sk, uint16_t index)
-{
- if (monitor)
- printf("hci%u added\n", index);
- return 0;
-}
-
-static int mgmt_index_removed(int mgmt_sk, uint16_t index)
-{
- if (monitor)
- printf("hci%u removed\n", index);
- return 0;
-}
-
-static const char *settings_str[] = {
- "powered",
- "connectable",
- "fast-connectable",
- "discoverable",
- "pairable",
- "link-security",
- "ssp",
- "br/edr",
- "hs",
- "le" ,
-};
-
-static void print_settings(uint32_t settings)
-{
- unsigned i;
-
- for (i = 0; i < NELEM(settings_str); i++) {
- if ((settings & (1 << i)) != 0)
- printf("%s ", settings_str[i]);
- }
-}
-
-static int mgmt_new_settings(int mgmt_sk, uint16_t index,
- uint32_t *ev, uint16_t len)
-{
- if (len < sizeof(*ev)) {
- fprintf(stderr, "Too short new_settings event (%u)\n", len);
- return -EINVAL;
- }
-
- if (monitor) {
- printf("hci%u new_settings: ", index);
- print_settings(bt_get_le32(ev));
- printf("\n");
- }
-
- return 0;
-}
-
-static int mgmt_discovering(int mgmt_sk, uint16_t index,
- struct mgmt_ev_discovering *ev, uint16_t len)
-{
- if (len < sizeof(*ev)) {
- fprintf(stderr, "Too short (%u bytes) discovering event\n",
- len);
- return -EINVAL;
- }
-
- if (ev->discovering == 0 && discovery)
- exit(EXIT_SUCCESS);
-
- if (monitor)
- printf("hci%u type %u discovering %s\n", index,
- ev->type, ev->discovering ? "on" : "off");
-
- return 0;
-}
-
-static int mgmt_new_link_key(int mgmt_sk, uint16_t index,
- struct mgmt_ev_new_link_key *ev, uint16_t len)
-{
-
- if (len != sizeof(*ev)) {
- fprintf(stderr, "Invalid new_link_key length (%u bytes)\n",
- len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->key.addr.bdaddr, addr);
- printf("hci%u new_link_key %s type 0x%02x pin_len %d "
- "store_hint %u\n", index, addr, ev->key.type,
- ev->key.pin_len, ev->store_hint);
- }
-
- return 0;
-}
-
-static const char *typestr(uint8_t type)
-{
- const char *str[] = { "BR/EDR", "LE Public", "LE Random" };
-
- if (type <= BDADDR_LE_RANDOM)
- return str[type];
-
- return "(unknown)";
-}
-
-static int mgmt_connected(int mgmt_sk, uint16_t index,
- struct mgmt_ev_device_connected *ev,
- uint16_t len)
-{
- uint16_t eir_len;
-
- if (len < sizeof(*ev)) {
- fprintf(stderr,
- "Invalid connected event length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- eir_len = bt_get_le16(&ev->eir_len);
- if (len != sizeof(*ev) + eir_len) {
- fprintf(stderr, "Invalid connected event length "
- "(%u bytes, eir_len %u bytes)\n", len, eir_len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->addr.bdaddr, addr);
- printf("hci%u %s type %s connected eir_len %u\n", index, addr,
- typestr(ev->addr.type), eir_len);
- }
-
- return 0;
-}
-
-static int mgmt_disconnected(int mgmt_sk, uint16_t index,
- struct mgmt_addr_info *ev, uint16_t len)
-{
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid disconnected event length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->bdaddr, addr);
- printf("hci%u %s type %s disconnected\n", index, addr,
- typestr(ev->type));
- }
-
- return 0;
-}
-
-static int mgmt_conn_failed(int mgmt_sk, uint16_t index,
- struct mgmt_ev_connect_failed *ev,
- uint16_t len)
-{
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid connect_failed event length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->addr.bdaddr, addr);
- printf("hci%u %s type %s connect failed (status 0x%02x, %s)\n",
- index, addr, typestr(ev->addr.type), ev->status,
- mgmt_errstr(ev->status));
- }
-
- return 0;
-}
-
-static int mgmt_auth_failed(int mgmt_sk, uint16_t index,
- struct mgmt_ev_auth_failed *ev,
- uint16_t len)
-{
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid auth_failed event length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->addr.bdaddr, addr);
- printf("hci%u %s auth failed with status 0x%02x (%s)\n",
- index, addr, ev->status, mgmt_errstr(ev->status));
- }
-
- return 0;
-}
-
-static int mgmt_name_changed(int mgmt_sk, uint16_t index,
- struct mgmt_ev_local_name_changed *ev,
- uint16_t len)
-{
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid local_name_changed length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- if (monitor)
- printf("hci%u name changed: %s\n", index, ev->name);
-
- return 0;
-}
-
-static void confirm_name_rsp(int mgmt_sk, uint16_t op, uint16_t id,
- uint8_t status, void *rsp, uint16_t len,
- void *user_data)
-{
- struct mgmt_rp_confirm_name *rp = rsp;
- char addr[18];
-
- if (len == 0 && status != 0) {
- fprintf(stderr,
- "hci%u confirm_name failed with status 0x%02x (%s)\n",
- id, status, mgmt_errstr(status));
- return;
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr,
- "hci%u confirm_name rsp length %u instead of %zu\n",
- id, len, sizeof(*rp));
- return;
- }
-
- ba2str(&rp->addr.bdaddr, addr);
-
- if (status != 0)
- fprintf(stderr,
- "hci%u confirm_name for %s failed: 0x%02x (%s)\n",
- id, addr, status, mgmt_errstr(status));
- else
- printf("hci%u confirm_name succeeded for %s\n", id, addr);
-}
-
-static int mgmt_device_found(int mgmt_sk, uint16_t index,
- struct mgmt_ev_device_found *ev, uint16_t len)
-{
- uint32_t flags;
- uint16_t eir_len;
-
- if (len < sizeof(*ev)) {
- fprintf(stderr,
- "Too short device_found length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- flags = btohs(ev->flags);
-
- eir_len = bt_get_le16(&ev->eir_len);
- if (len != sizeof(*ev) + eir_len) {
- fprintf(stderr, "dev_found: expected %zu bytes, got %u bytes",
- sizeof(*ev) + eir_len, len);
- return -EINVAL;
- }
-
- if (monitor || discovery) {
- char addr[18];
- ba2str(&ev->addr.bdaddr, addr);
- printf("hci%u dev_found: %s type %s rssi %d "
- "flags 0x%04x eir_len %u\n", index, addr,
- typestr(ev->addr.type), ev->rssi, flags, eir_len);
- }
-
- if (discovery && (flags & MGMT_DEV_FOUND_CONFIRM_NAME)) {
- struct mgmt_cp_confirm_name cp;
-
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.addr, &ev->addr, sizeof(cp.addr));
- if (resolve_names)
- cp.name_known = 0;
- else
- cp.name_known = 1;
-
- mgmt_send_cmd(mgmt_sk, MGMT_OP_CONFIRM_NAME, index,
- &cp, sizeof(cp), confirm_name_rsp,
- NULL);
- }
-
- return 0;
-}
-
-static void pin_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr,
- "hci%u PIN Code reply failed with status 0x%02x (%s)",
- id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("hci%u PIN Reply successful\n", id);
-}
-
-static int mgmt_pin_reply(int mgmt_sk, uint16_t index,
- struct mgmt_addr_info *addr,
- const char *pin, size_t len)
-{
- struct mgmt_cp_pin_code_reply cp;
-
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.addr, addr, sizeof(cp.addr));
- cp.pin_len = len;
- memcpy(cp.pin_code, pin, len);
-
- return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_REPLY, index,
- &cp, sizeof(cp), pin_rsp, NULL);
-}
-
-static void pin_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr,
- "hci%u PIN Neg reply failed with status 0x%02x (%s)",
- id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("hci%u PIN Negative Reply successful\n", id);
-}
-
-static int mgmt_pin_neg_reply(int mgmt_sk, uint16_t index,
- struct mgmt_addr_info *addr)
-{
- struct mgmt_cp_pin_code_neg_reply cp;
-
- memset(&cp, 0, sizeof(cp));
- memcpy(&cp.addr, addr, sizeof(cp.addr));
-
- return mgmt_send_cmd(mgmt_sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
- &cp, sizeof(cp), pin_neg_rsp, NULL);
-}
-
-static int mgmt_request_pin(int mgmt_sk, uint16_t index,
- struct mgmt_ev_pin_code_request *ev,
- uint16_t len)
-{
- char pin[18];
- size_t pin_len;
-
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid pin_code request length (%u bytes)\n", len);
- return -EINVAL;
- }
-
- if (monitor) {
- char addr[18];
- ba2str(&ev->addr.bdaddr, addr);
- printf("hci%u %s request PIN\n", index, addr);
- }
-
- printf("PIN Request (press enter to reject) >> ");
- fflush(stdout);
-
- memset(pin, 0, sizeof(pin));
-
- if (fgets(pin, sizeof(pin), stdin) == NULL || pin[0] == '\n')
- return mgmt_pin_neg_reply(mgmt_sk, index, &ev->addr);
-
- pin_len = strlen(pin);
- if (pin[pin_len - 1] == '\n') {
- pin[pin_len - 1] = '\0';
- pin_len--;
- }
-
- return mgmt_pin_reply(mgmt_sk, index, &ev->addr, pin, pin_len);
-}
-
-static void confirm_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr,
- "hci%u User Confirm reply failed. status 0x%02x (%s)",
- id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("hci%u User Confirm Reply successful\n", id);
-}
-
-static int mgmt_confirm_reply(int mgmt_sk, uint16_t index, bdaddr_t *bdaddr)
-{
- struct mgmt_cp_user_confirm_reply cp;
-
- memset(&cp, 0, sizeof(cp));
- bacpy(&cp.addr.bdaddr, bdaddr);
-
- return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_REPLY, index,
- &cp, sizeof(cp), confirm_rsp, NULL);
-}
-
-static void confirm_neg_rsp(int mgmt_sk, uint16_t op, uint16_t id,
- uint8_t status, void *rsp, uint16_t len,
- void *user_data)
-{
- if (status != 0) {
- fprintf(stderr,
- "hci%u Confirm Neg reply failed. status 0x%02x (%s)",
- id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("hci%u User Confirm Negative Reply successful\n", id);
-}
-
-static int mgmt_confirm_neg_reply(int mgmt_sk, uint16_t index,
- bdaddr_t *bdaddr)
-{
- struct mgmt_cp_user_confirm_reply cp;
-
- memset(&cp, 0, sizeof(cp));
- bacpy(&cp.addr.bdaddr, bdaddr);
-
- return mgmt_send_cmd(mgmt_sk, MGMT_OP_USER_CONFIRM_NEG_REPLY, index,
- &cp, sizeof(cp), confirm_neg_rsp, NULL);
-}
-
-
-static int mgmt_user_confirm(int mgmt_sk, uint16_t index,
- struct mgmt_ev_user_confirm_request *ev,
- uint16_t len)
-{
- char rsp[5];
- size_t rsp_len;
- uint32_t val;
- char addr[18];
-
- if (len != sizeof(*ev)) {
- fprintf(stderr,
- "Invalid user_confirm request length (%u)\n", len);
- return -EINVAL;
- }
-
- ba2str(&ev->addr.bdaddr, addr);
- val = bt_get_le32(&ev->value);
-
- if (monitor)
- printf("hci%u %s User Confirm %06u hint %u\n", index, addr,
- val, ev->confirm_hint);
-
- if (ev->confirm_hint)
- printf("Accept pairing with %s (yes/no) >> ", addr);
- else
- printf("Confirm value %06u for %s (yes/no) >> ", val, addr);
-
- fflush(stdout);
-
- memset(rsp, 0, sizeof(rsp));
-
- if (fgets(rsp, sizeof(rsp), stdin) == NULL || rsp[0] == '\n')
- return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
-
- rsp_len = strlen(rsp);
- if (rsp[rsp_len - 1] == '\n') {
- rsp[rsp_len - 1] = '\0';
- rsp_len--;
- }
-
- if (rsp[0] == 'y' || rsp[0] == 'Y')
- return mgmt_confirm_reply(mgmt_sk, index, &ev->addr.bdaddr);
- else
- return mgmt_confirm_neg_reply(mgmt_sk, index, &ev->addr.bdaddr);
-}
-
-static int mgmt_handle_event(int mgmt_sk, uint16_t ev, uint16_t index,
- void *data, uint16_t len)
-{
- if (monitor)
- printf("event: %s\n", mgmt_evstr(ev));
-
- switch (ev) {
- case MGMT_EV_CMD_COMPLETE:
- return mgmt_cmd_complete(mgmt_sk, index, data, len);
- case MGMT_EV_CMD_STATUS:
- return mgmt_cmd_status(mgmt_sk, index, data, len);
- case MGMT_EV_CONTROLLER_ERROR:
- return mgmt_controller_error(index, data, len);
- case MGMT_EV_INDEX_ADDED:
- return mgmt_index_added(mgmt_sk, index);
- case MGMT_EV_INDEX_REMOVED:
- return mgmt_index_removed(mgmt_sk, index);
- case MGMT_EV_NEW_SETTINGS:
- return mgmt_new_settings(mgmt_sk, index, data, len);
- case MGMT_EV_DISCOVERING:
- return mgmt_discovering(mgmt_sk, index, data, len);
- case MGMT_EV_NEW_LINK_KEY:
- return mgmt_new_link_key(mgmt_sk, index, data, len);
- case MGMT_EV_DEVICE_CONNECTED:
- return mgmt_connected(mgmt_sk, index, data, len);
- case MGMT_EV_DEVICE_DISCONNECTED:
- return mgmt_disconnected(mgmt_sk, index, data, len);
- case MGMT_EV_CONNECT_FAILED:
- return mgmt_conn_failed(mgmt_sk, index, data, len);
- case MGMT_EV_AUTH_FAILED:
- return mgmt_auth_failed(mgmt_sk, index, data, len);
- case MGMT_EV_LOCAL_NAME_CHANGED:
- return mgmt_name_changed(mgmt_sk, index, data, len);
- case MGMT_EV_DEVICE_FOUND:
- return mgmt_device_found(mgmt_sk, index, data, len);
- case MGMT_EV_PIN_CODE_REQUEST:
- return mgmt_request_pin(mgmt_sk, index, data, len);
- case MGMT_EV_USER_CONFIRM_REQUEST:
- return mgmt_user_confirm(mgmt_sk, index, data, len);
- default:
- if (monitor)
- printf("Unhandled event 0x%04x (%s)\n", ev, mgmt_evstr(ev));
- return 0;
- }
-}
-
-static int mgmt_process_data(int mgmt_sk)
-{
- char buf[1024];
- struct mgmt_hdr *hdr = (void *) buf;
- uint16_t len, ev, index;
- ssize_t ret;
-
- ret = read(mgmt_sk, buf, sizeof(buf));
- if (ret < 0) {
- fprintf(stderr, "read: %s\n", strerror(errno));
- return ret;
- }
-
- if (ret < MGMT_HDR_SIZE) {
- fprintf(stderr, "Too small mgmt packet (%zd bytes)\n", ret);
- return 0;
- }
-
- ev = bt_get_le16(&hdr->opcode);
- index = bt_get_le16(&hdr->index);
- len = bt_get_le16(&hdr->len);
-
- if (monitor)
- printf("event 0x%04x len 0x%04x index 0x%04x\n", ev, len, index);
-
- if (ret != MGMT_HDR_SIZE + len) {
- fprintf(stderr, "Packet length mismatch. ret %zd len %u",
- ret, len);
- return 0;
- }
-
- mgmt_handle_event(mgmt_sk, ev, index, buf + MGMT_HDR_SIZE, len);
-
- return 0;
-}
-
-static void cmd_monitor(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- printf("Monitoring mgmt events...\n");
- monitor = true;
-}
-
-static void version_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_read_version *rp = rsp;
-
- if (status != 0) {
- fprintf(stderr, "Reading mgmt version failed with status"
- " 0x%02x (%s)\n", status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small version reply (%u bytes)\n", len);
- exit(EXIT_FAILURE);
- }
-
- printf("MGMT Version %u, revision %u\n", rp->version,
- bt_get_le16(&rp->revision));
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_version(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_VERSION, MGMT_INDEX_NONE,
- NULL, 0, version_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send read_version cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void commands_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_read_commands *rp = rsp;
- uint16_t num_commands, num_events, *opcode;
- size_t expected_len;
- int i;
-
- if (status != 0) {
- fprintf(stderr, "Reading supported commands failed with status"
- " 0x%02x (%s)\n", status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small commands reply (%u bytes)\n", len);
- exit(EXIT_FAILURE);
- }
-
- num_commands = bt_get_le16(&rp->num_commands);
- num_events = bt_get_le16(&rp->num_events);
-
- expected_len = sizeof(*rp) + num_commands * sizeof(uint16_t) +
- num_events * sizeof(uint16_t);
-
- if (len < expected_len) {
- fprintf(stderr, "Too small commands reply (%u != %zu)\n",
- len, expected_len);
- exit(EXIT_FAILURE);
- }
-
- opcode = rp->opcodes;
-
- printf("%u commands:\n", num_commands);
- for (i = 0; i < num_commands; i++) {
- uint16_t op = bt_get_le16(opcode++);
- printf("\t%s (0x%04x)\n", mgmt_opstr(op), op);
- }
-
- printf("%u events:\n", num_events);
- for (i = 0; i < num_events; i++) {
- uint16_t ev = bt_get_le16(opcode++);
- printf("\t%s (0x%04x)\n", mgmt_evstr(ev), ev);
- }
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_commands(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_COMMANDS, MGMT_INDEX_NONE,
- NULL, 0, commands_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send read_commands cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void info_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_read_info *rp = rsp;
- char addr[18];
-
- if (status != 0) {
- fprintf(stderr,
- "Reading hci%u info failed with status 0x%02x (%s)\n",
- id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small info reply (%u bytes)\n", len);
- exit(EXIT_FAILURE);
- }
-
- ba2str(&rp->bdaddr, addr);
- printf("hci%u:\taddr %s version %u manufacturer %u"
- " class 0x%02x%02x%02x\n",
- id, addr, rp->version, bt_get_le16(&rp->manufacturer),
- rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
-
- printf("\tsupported settings: ");
- print_settings(bt_get_le32(&rp->supported_settings));
-
- printf("\n\tcurrent settings: ");
- print_settings(bt_get_le32(&rp->current_settings));
-
- printf("\n\tname %s\n", rp->name);
- printf("\tshort name %s\n", rp->short_name);
-
- if (pending == NULL)
- exit(EXIT_SUCCESS);
-}
-
-static void index_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_read_index_list *rp = rsp;
- uint16_t count;
- unsigned int i;
-
- if (status != 0) {
- fprintf(stderr,
- "Reading index list failed with status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small index list reply (%u bytes)\n",
- len);
- exit(EXIT_FAILURE);
- }
-
- count = bt_get_le16(&rp->num_controllers);
-
- if (len < sizeof(*rp) + count * sizeof(uint16_t)) {
- fprintf(stderr,
- "Index count (%u) doesn't match reply length (%u)\n",
- count, len);
- exit(EXIT_FAILURE);
- }
-
- if (monitor)
- printf("Index list with %u item%s\n",
- count, count > 1 ? "s" : "");
-
- if (count == 0)
- exit(EXIT_SUCCESS);
-
- if (monitor && count > 0)
- printf("\t");
-
- for (i = 0; i < count; i++) {
- uint16_t index;
-
- index = bt_get_le16(&rp->index[i]);
-
- if (monitor)
- printf("hci%u ", index);
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
- 0, info_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send read_info cmd\n");
- exit(EXIT_FAILURE);
- }
- }
-
- if (monitor && count > 0)
- printf("\n");
-}
-
-static void cmd_info(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- if (index == MGMT_INDEX_NONE) {
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INDEX_LIST,
- MGMT_INDEX_NONE, NULL, 0,
- index_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send index_list cmd\n");
- exit(EXIT_FAILURE);
- }
-
- return;
- }
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_READ_INFO, index, NULL,
- 0, info_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send read_info cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void setting_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- uint32_t *rp = rsp;
-
- if (status != 0) {
- fprintf(stderr,
- "%s for hci%u failed with status 0x%02x (%s)\n",
- mgmt_opstr(op), id, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small %s response (%u bytes)\n",
- mgmt_opstr(op), len);
- exit(EXIT_FAILURE);
- }
-
- printf("hci%u %s complete, settings: ", id, mgmt_opstr(op));
- print_settings(bt_get_le32(rp));
- printf("\n");
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_setting(int mgmt_sk, uint16_t index, uint16_t op,
- int argc, char **argv)
-{
- uint8_t val;
-
- if (argc < 2) {
- printf("Specify \"on\" or \"off\"\n");
- exit(EXIT_FAILURE);
- }
-
- if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
- val = 1;
- else if (strcasecmp(argv[1], "off") == 0)
- val = 0;
- else
- val = atoi(argv[1]);
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (mgmt_send_cmd(mgmt_sk, op, index, &val, sizeof(val),
- setting_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send %s cmd\n", mgmt_opstr(op));
- exit(EXIT_FAILURE);
- }
-}
-
-static void cmd_power(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_POWERED, argc, argv);
-}
-
-static void cmd_discov(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_set_discoverable cp;
-
- if (argc < 2) {
- printf("Usage: btmgmt %s <yes/no> [timeout]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- memset(&cp, 0, sizeof(cp));
-
- if (strcasecmp(argv[1], "on") == 0 || strcasecmp(argv[1], "yes") == 0)
- cp.val = 1;
- else if (strcasecmp(argv[1], "off") == 0)
- cp.val = 0;
- else
- cp.val = atoi(argv[1]);
-
- if (argc > 2)
- cp.timeout = htobs(atoi(argv[2]));
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DISCOVERABLE, index,
- &cp, sizeof(cp), setting_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send set_discoverable cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void cmd_connectable(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_CONNECTABLE, argc, argv);
-}
-
-static void cmd_pairable(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_PAIRABLE, argc, argv);
-}
-
-static void cmd_linksec(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_LINK_SECURITY, argc, argv);
-}
-
-static void cmd_ssp(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_SSP, argc, argv);
-}
-
-static void cmd_hs(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_HS, argc, argv);
-}
-
-static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
-}
-
-static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_ev_class_of_dev_changed *rp = rsp;
-
- if (len == 0 && status != 0) {
- fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
- mgmt_opstr(op), status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
- exit(EXIT_FAILURE);
- }
-
- printf("%s succeeded. Class 0x%02x%02x%02x\n", mgmt_opstr(op),
- rp->class_of_dev[2], rp->class_of_dev[1], rp->class_of_dev[0]);
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_class(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- uint8_t class[2];
-
- if (argc < 3) {
- printf("Usage: btmgmt %s <major> <minor>\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- class[0] = atoi(argv[1]);
- class[1] = atoi(argv[2]);
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEV_CLASS, index,
- class, sizeof(class), class_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send set_dev_class cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void disconnect_rsp(int mgmt_sk, uint16_t op, uint16_t id,
- uint8_t status, void *rsp, uint16_t len,
- void *user_data)
-{
- struct mgmt_rp_disconnect *rp = rsp;
- char addr[18];
-
- if (len == 0 && status != 0) {
- fprintf(stderr, "Disconnect failed with status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr, "Invalid disconnect response length (%u)\n",
- len);
- exit(EXIT_FAILURE);
- }
-
- ba2str(&rp->addr.bdaddr, addr);
-
- if (status == 0) {
- printf("%s disconnected\n", addr);
- exit(EXIT_SUCCESS);
- } else {
- fprintf(stderr,
- "Disconnecting %s failed with status 0x%02x (%s)\n",
- addr, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-}
-
-static void cmd_disconnect(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_disconnect cp;
-
- if (argc < 2) {
- printf("Usage: btmgmt %s <address>\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- str2ba(argv[1], &cp.addr.bdaddr);
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_DISCONNECT, index,
- &cp, sizeof(cp), disconnect_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send disconnect cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void con_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_get_connections *rp = rsp;
- uint16_t count, i;
-
- if (len < sizeof(*rp)) {
- fprintf(stderr, "Too small (%u bytes) get_connections rsp\n",
- len);
- exit(EXIT_FAILURE);
- }
-
- count = bt_get_le16(&rp->conn_count);
- if (len != sizeof(*rp) + count * sizeof(struct mgmt_addr_info)) {
- fprintf(stderr, "Invalid get_connections length "
- " (count=%u, len=%u)\n", count, len);
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < count; i++) {
- char addr[18];
-
- ba2str(&rp->addr[i].bdaddr, addr);
-
- printf("%s type %s\n", addr, typestr(rp->addr[i].type));
- }
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_con(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_GET_CONNECTIONS, index, NULL, 0,
- con_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send get_connections cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void find_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr,
- "Unable to start discovery. status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("Discovery started\n");
- discovery = true;
-}
-
-static void find_usage(void)
-{
- printf("Usage: btmgmt find [-l|-b]>\n");
-}
-
-static struct option find_options[] = {
- { "help", 0, 0, 'h' },
- { "le-only", 1, 0, 'l' },
- { "bredr-only", 1, 0, 'b' },
- { 0, 0, 0, 0 }
-};
-
-static void cmd_find(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_start_discovery cp;
- uint8_t type;
- int opt;
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- type = 0;
- hci_set_bit(BDADDR_BREDR, &type);
- hci_set_bit(BDADDR_LE_PUBLIC, &type);
- hci_set_bit(BDADDR_LE_RANDOM, &type);
-
- while ((opt = getopt_long(argc, argv, "+lbh", find_options,
- NULL)) != -1) {
- switch (opt) {
- case 'l':
- hci_clear_bit(BDADDR_BREDR, &type);
- hci_set_bit(BDADDR_LE_PUBLIC, &type);
- hci_set_bit(BDADDR_LE_RANDOM, &type);
- break;
- case 'b':
- hci_set_bit(BDADDR_BREDR, &type);
- hci_clear_bit(BDADDR_LE_PUBLIC, &type);
- hci_clear_bit(BDADDR_LE_RANDOM, &type);
- break;
- case 'h':
- default:
- find_usage();
- exit(EXIT_SUCCESS);
- }
- }
-
- argc -= optind;
- argv += optind;
- optind = 0;
-
- memset(&cp, 0, sizeof(cp));
- cp.type = type;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_START_DISCOVERY, index,
- &cp, sizeof(cp), find_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send start_discovery cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void name_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr, "Unable to set local name. status 0x%02x (%s)",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_name(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_set_local_name cp;
-
- if (argc < 2) {
- printf("Usage: btmgmt %s <name> [shortname]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
- strncpy((char *) cp.name, argv[1], HCI_MAX_NAME_LENGTH);
- if (argc > 2)
- strncpy((char *) cp.short_name, argv[2],
- MGMT_MAX_SHORT_NAME_LENGTH);
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_LOCAL_NAME, index,
- &cp, sizeof(cp), name_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send set_name cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void pair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_pair_device *rp = rsp;
- char addr[18];
-
- if (len == 0 && status != 0) {
- fprintf(stderr, "Pairing failed with status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr, "Unexpected pair_rsp len %u\n", len);
- exit(EXIT_FAILURE);
- }
-
- ba2str(&rp->addr.bdaddr, addr);
-
- if (status != 0) {
- fprintf(stderr,
- "Pairing with %s (%s) failed. status 0x%02x (%s)\n",
- addr, typestr(rp->addr.type), status,
- mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("Paired with %s\n", addr);
-
- exit(EXIT_SUCCESS);
-}
-
-static void pair_usage(void)
-{
- printf("Usage: btmgmt pair [-c cap] [-t type] <remote address>\n");
-}
-
-static struct option pair_options[] = {
- { "help", 0, 0, 'h' },
- { "capability", 1, 0, 'c' },
- { "type", 1, 0, 't' },
- { 0, 0, 0, 0 }
-};
-
-static void cmd_pair(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_pair_device cp;
- uint8_t cap = 0x01;
- uint8_t type = BDADDR_BREDR;
- int opt;
-
- while ((opt = getopt_long(argc, argv, "+c:t:h", pair_options,
- NULL)) != -1) {
- switch (opt) {
- case 'c':
- cap = strtol(optarg, NULL, 0);
- break;
- case 't':
- type = strtol(optarg, NULL, 0);
- break;
- case 'h':
- default:
- pair_usage();
- exit(EXIT_SUCCESS);
- }
- }
-
- argc -= optind;
- argv += optind;
- optind = 0;
-
- if (argc < 1) {
- pair_usage();
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
- str2ba(argv[0], &cp.addr.bdaddr);
- cp.addr.type = type;
- cp.io_cap = cap;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_PAIR_DEVICE, index, &cp, sizeof(cp),
- pair_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send pair_device cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void unpair_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_rp_unpair_device *rp = rsp;
- char addr[18];
-
- if (len == 0 && status != 0) {
- fprintf(stderr, "Unpair device failed. status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr, "Unexpected unpair_device_rsp len %u\n", len);
- exit(EXIT_FAILURE);
- }
-
- ba2str(&rp->addr.bdaddr, addr);
-
- if (status != 0) {
- fprintf(stderr,
- "Unpairing %s failed. status 0x%02x (%s)\n",
- addr, status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("%s unpaired\n", addr);
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_unpair(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_unpair_device cp;
-
- if (argc < 2) {
- printf("Usage: btmgmt %s <remote address>\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
- str2ba(argv[1], &cp.addr.bdaddr);
- cp.disconnect = 1;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNPAIR_DEVICE, index, &cp,
- sizeof(cp), unpair_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send unpair_device cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void keys_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr, "Load keys failed with status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("Keys successfully loaded\n");
-
- exit(EXIT_SUCCESS);
-}
-
-static void cmd_keys(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_load_link_keys cp;
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_LOAD_LINK_KEYS, index,
- &cp, sizeof(cp), keys_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send load_keys cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void block_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- struct mgmt_addr_info *rp = rsp;
- char addr[18];
-
- if (len == 0 && status != 0) {
- fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
- mgmt_opstr(op), status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- if (len != sizeof(*rp)) {
- fprintf(stderr, "Unexpected %s len %u\n", mgmt_opstr(op), len);
- exit(EXIT_FAILURE);
- }
-
- ba2str(&rp->bdaddr, addr);
-
- if (status != 0) {
- fprintf(stderr, "%s %s (%s) failed. status 0x%02x (%s)\n",
- mgmt_opstr(op), addr, typestr(rp->type),
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("%s %s succeeded\n", mgmt_opstr(op), addr);
-
- exit(EXIT_SUCCESS);
-}
-
-static void block_usage(void)
-{
- printf("Usage: btmgmt block [-t type] <remote address>\n");
-}
-
-static struct option block_options[] = {
- { "help", 0, 0, 'h' },
- { "type", 1, 0, 't' },
- { 0, 0, 0, 0 }
-};
-
-static void cmd_block(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_block_device cp;
- uint8_t type = BDADDR_BREDR;
- int opt;
-
- while ((opt = getopt_long(argc, argv, "+t:h", block_options,
- NULL)) != -1) {
- switch (opt) {
- case 't':
- type = strtol(optarg, NULL, 0);
- break;
- case 'h':
- default:
- block_usage();
- exit(EXIT_SUCCESS);
- }
- }
-
- argc -= optind;
- argv += optind;
- optind = 0;
-
- if (argc < 1) {
- block_usage();
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
- str2ba(argv[0], &cp.addr.bdaddr);
- cp.addr.type = type;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_BLOCK_DEVICE, index,
- &cp, sizeof(cp), block_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send block_device cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void unblock_usage(void)
-{
- printf("Usage: btmgmt unblock [-t type] <remote address>\n");
-}
-
-static void cmd_unblock(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_unblock_device cp;
- uint8_t type = BDADDR_BREDR;
- int opt;
-
- while ((opt = getopt_long(argc, argv, "+t:h", block_options,
- NULL)) != -1) {
- switch (opt) {
- case 't':
- type = strtol(optarg, NULL, 0);
- break;
- case 'h':
- default:
- unblock_usage();
- exit(EXIT_SUCCESS);
- }
- }
-
- argc -= optind;
- argv += optind;
- optind = 0;
-
- if (argc < 1) {
- unblock_usage();
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- memset(&cp, 0, sizeof(cp));
- str2ba(argv[0], &cp.addr.bdaddr);
- cp.addr.type = type;
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNBLOCK_DEVICE, index,
- &cp, sizeof(cp), block_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send unblock_device cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
-{
- if (uuid->type == SDP_UUID16)
- sdp_uuid16_to_uuid128(uuid128, uuid);
- else if (uuid->type == SDP_UUID32)
- sdp_uuid32_to_uuid128(uuid128, uuid);
- else
- memcpy(uuid128, uuid, sizeof(*uuid));
-}
-
-static void cmd_add_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_add_uuid cp;
- uint128_t uint128;
- uuid_t uuid, uuid128;
-
- if (argc < 3) {
- printf("UUID and service hint needed\n");
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (bt_string2uuid(&uuid, argv[1]) < 0) {
- printf("Invalid UUID: %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
-
- memset(&cp, 0, sizeof(cp));
-
- uuid_to_uuid128(&uuid128, &uuid);
- ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
- htob128(&uint128, (uint128_t *) cp.uuid);
-
- cp.svc_hint = atoi(argv[2]);
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_ADD_UUID, index,
- &cp, sizeof(cp), class_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send add_uuid cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void cmd_remove_uuid(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_remove_uuid cp;
- uint128_t uint128;
- uuid_t uuid, uuid128;
-
- if (argc < 2) {
- printf("UUID needed\n");
- exit(EXIT_FAILURE);
- }
-
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- if (bt_string2uuid(&uuid, argv[1]) < 0) {
- printf("Invalid UUID: %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
-
- memset(&cp, 0, sizeof(cp));
-
- uuid_to_uuid128(&uuid128, &uuid);
- ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
- htob128(&uint128, (uint128_t *) cp.uuid);
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_REMOVE_UUID, index,
- &cp, sizeof(cp), class_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send remove_uuid cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void cmd_clr_uuids(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- char *uuid_any = "00000000-0000-0000-0000-000000000000";
- char *rm_argv[] = { "rm-uuid", uuid_any, NULL };
-
- cmd_remove_uuid(mgmt_sk, index, 2, rm_argv);
-}
-
-static void did_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
- void *rsp, uint16_t len, void *user_data)
-{
- if (status != 0) {
- fprintf(stderr, "Set Device ID failed with status 0x%02x (%s)\n",
- status, mgmt_errstr(status));
- exit(EXIT_FAILURE);
- }
-
- printf("Device ID successfully set\n");
-
- exit(EXIT_SUCCESS);
-}
-
-static void did_usage(void)
-{
- printf("Usage: btmgmt did <source>:<vendor>:<product>:<version>\n");
- printf(" possible source values: bluetooth, usb\n");
-}
-
-static void cmd_did(int mgmt_sk, uint16_t index, int argc, char **argv)
-{
- struct mgmt_cp_set_device_id cp;
- uint16_t vendor, product, version , source;
- int result;
-
- if (argc < 2) {
- did_usage();
- exit(EXIT_FAILURE);
- }
-
- result = sscanf(argv[1], "bluetooth:%4hx:%4hx:%4hx", &vendor, &product,
- &version);
- if (result == 3) {
- source = 0x0001;
- goto done;
- }
-
- result = sscanf(argv[1], "usb:%4hx:%4hx:%4hx", &vendor, &product,
- &version);
- if (result == 3) {
- source = 0x0002;
- goto done;
- }
-
- did_usage();
- exit(EXIT_FAILURE);
-
-done:
- if (index == MGMT_INDEX_NONE)
- index = 0;
-
- cp.source = htobs(source);
- cp.vendor = htobs(vendor);
- cp.product = htobs(product);
- cp.version = htobs(version);
-
- if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_DEVICE_ID, index,
- &cp, sizeof(cp), did_rsp, NULL) < 0) {
- fprintf(stderr, "Unable to send set_dev_class cmd\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static struct {
- char *cmd;
- void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
- char *doc;
-} command[] = {
- { "monitor", cmd_monitor, "Monitor events" },
- { "version", cmd_version, "Get the MGMT Version" },
- { "commands", cmd_commands, "List supported commands" },
- { "info", cmd_info, "Show controller info" },
- { "power", cmd_power, "Toggle powered state" },
- { "discov", cmd_discov, "Toggle discoverable state" },
- { "connectable",cmd_connectable,"Toggle connectable state" },
- { "pairable", cmd_pairable, "Toggle pairable state" },
- { "linksec", cmd_linksec, "Toggle link level security" },
- { "ssp", cmd_ssp, "Toggle SSP mode" },
- { "hs", cmd_hs, "Toggle HS Support" },
- { "le", cmd_le, "Toggle LE Support" },
- { "class", cmd_class, "Set device major/minor class" },
- { "disconnect", cmd_disconnect, "Disconnect device" },
- { "con", cmd_con, "List connections" },
- { "find", cmd_find, "Discover nearby devices" },
- { "name", cmd_name, "Set local name" },
- { "pair", cmd_pair, "Pair with a remote device" },
- { "unpair", cmd_unpair, "Unpair device" },
- { "keys", cmd_keys, "Load Keys" },
- { "block", cmd_block, "Block Device" },
- { "unblock", cmd_unblock, "Unblock Device" },
- { "add-uuid", cmd_add_uuid, "Add UUID" },
- { "rm-uuid", cmd_add_uuid, "Remove UUID" },
- { "clr-uuids", cmd_clr_uuids, "Clear UUIDs", },
- { "did", cmd_did, "Set Device ID", },
- { NULL, NULL, 0 }
-};
-
-static void usage(void)
-{
- int i;
-
- printf("btmgmt ver %s\n", VERSION);
- printf("Usage:\n"
- "\tbtmgmt [options] <command> [command parameters]\n");
-
- printf("Options:\n"
- "\t--index <id>\tSpecify adapter index\n"
- "\t--verbose\tEnable extra logging\n"
- "\t--help\tDisplay help\n");
-
- printf("Commands:\n");
- for (i = 0; command[i].cmd; i++)
- printf("\t%-15s\t%s\n", command[i].cmd, command[i].doc);
-
- printf("\n"
- "For more information on the usage of each command use:\n"
- "\tbtmgmt <command> --help\n" );
-}
-
-static struct option main_options[] = {
- { "index", 1, 0, 'i' },
- { "verbose", 0, 0, 'v' },
- { "help", 0, 0, 'h' },
- { 0, 0, 0, 0 }
-};
-
-int main(int argc, char *argv[])
-{
- int opt, i, mgmt_sk;
- uint16_t index = MGMT_INDEX_NONE;
- struct pollfd pollfd;
-
- while ((opt = getopt_long(argc, argv, "+hvi:",
- main_options, NULL)) != -1) {
- switch (opt) {
- case 'i':
- if (strlen(optarg) > 3 &&
- strncasecmp(optarg, "hci", 3) == 0)
- index = atoi(&optarg[4]);
- else
- index = atoi(optarg);
- break;
- case 'v':
- monitor = true;
- break;
- case 'h':
- default:
- usage();
- return 0;
- }
- }
-
- argc -= optind;
- argv += optind;
- optind = 0;
-
- if (argc < 1) {
- usage();
- return 0;
- }
-
- mgmt_sk = mgmt_open();
- if (mgmt_sk < 0) {
- fprintf(stderr, "Unable to open mgmt socket\n");
- return -1;
- }
-
- for (i = 0; command[i].cmd; i++) {
- if (strcmp(command[i].cmd, argv[0]) != 0)
- continue;
-
- command[i].func(mgmt_sk, index, argc, argv);
- break;
- }
-
- if (command[i].cmd == NULL) {
- fprintf(stderr, "Unknown command: %s\n", argv[0]);
- close(mgmt_sk);
- return -1;
- }
-
- pollfd.fd = mgmt_sk;
- pollfd.events = POLLIN;
- pollfd.revents = 0;
-
- while (poll(&pollfd, 1, -1) >= 0) {
- if (pollfd.revents & (POLLHUP | POLLERR | POLLNVAL))
- break;
-
- if (pollfd.revents & POLLIN)
- mgmt_process_data(mgmt_sk);
-
- pollfd.revents = 0;
- }
-
- close(mgmt_sk);
-
- return 0;
-}
--
1.7.10.2


2012-07-09 21:10:24

by Gustavo Padovan

[permalink] [raw]
Subject: [PATCH 02/14] serial: remove the whole serial code

From: Gustavo Padovan <[email protected]>

---
Makefile.am | 20 +-
acinclude.m4 | 6 -
doc/serial-api.txt | 138 +-----
serial/main.c | 59 ---
serial/manager.c | 174 -------
serial/manager.h | 25 --
serial/port.c | 646 --------------------------
serial/port.h | 29 --
serial/proxy.c | 1269 ----------------------------------------------------
serial/proxy.h | 25 --
serial/serial.conf | 10 -
11 files changed, 6 insertions(+), 2395 deletions(-)
delete mode 100644 serial/main.c
delete mode 100644 serial/manager.c
delete mode 100644 serial/manager.h
delete mode 100644 serial/port.c
delete mode 100644 serial/port.h
delete mode 100644 serial/proxy.c
delete mode 100644 serial/proxy.h
delete mode 100644 serial/serial.conf

diff --git a/Makefile.am b/Makefile.am
index 97146c9..a2c85e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -191,14 +191,6 @@ builtin_modules += hog
builtin_sources += input/hog_device.h input/hog_device.c
endif

-if SERIALPLUGIN
-builtin_modules += serial
-builtin_sources += serial/main.c \
- serial/manager.h serial/manager.c \
- serial/proxy.h serial/proxy.c \
- serial/port.h serial/port.c
-endif
-
if NETWORKPLUGIN
builtin_modules += network
builtin_sources += network/main.c \
@@ -334,11 +326,10 @@ endif

EXTRA_DIST += src/genbuiltin src/bluetooth.conf src/org.bluez.service \
src/main.conf network/network.conf \
- input/input.conf serial/serial.conf \
+ input/input.conf proximity/proximity.conf \
audio/audio.conf audio/telephony-dummy.c \
audio/telephony-maemo5.c audio/telephony-ofono.c \
- audio/telephony-maemo6.c sap/sap-dummy.c sap/sap-u8500.c \
- proximity/proximity.conf
+ audio/telephony-maemo6.c sap/sap-dummy.c sap/sap-u8500.c

if AUDIOPLUGIN
if GSTREAMER
@@ -392,10 +383,9 @@ EXTRA_DIST += scripts/bluetooth-hid2hci.rules scripts/bluetooth-serial.rules
EXTRA_DIST += doc/manager-api.txt \
doc/adapter-api.txt doc/device-api.txt \
doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
- doc/serial-api.txt doc/network-api.txt \
- doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
- doc/hfp-api.txt doc/health-api.txt doc/sap-api.txt \
- doc/media-api.txt doc/assigned-numbers.txt
+ doc/network-api.txt doc/input-api.txt doc/audio-api.txt \
+ doc/control-api.txt doc/hfp-api.txt doc/health-api.txt \
+ doc/sap-api.txt doc/media-api.txt doc/assigned-numbers.txt

AM_YFLAGS = -d

diff --git a/acinclude.m4 b/acinclude.m4
index 3a2a50a..842eea3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -172,7 +172,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
gstreamer_enable=${gstreamer_found}
audio_enable=yes
input_enable=yes
- serial_enable=yes
network_enable=yes
sap_enable=no
service_enable=yes
@@ -218,10 +217,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
])
AC_SUBST([SAP_DRIVER], [sap-${sap_driver}.c])

- AC_ARG_ENABLE(serial, AC_HELP_STRING([--disable-serial], [disable serial plugin]), [
- serial_enable=${enableval}
- ])
-
AC_ARG_ENABLE(input, AC_HELP_STRING([--disable-input], [disable input plugin]), [
input_enable=${enableval}
])
@@ -345,7 +340,6 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(GSTREAMER, test "${gstreamer_enable}" = "yes" && test "${gstreamer_found}" = "yes")
AM_CONDITIONAL(AUDIOPLUGIN, test "${audio_enable}" = "yes")
AM_CONDITIONAL(INPUTPLUGIN, test "${input_enable}" = "yes")
- AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes")
AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes")
AM_CONDITIONAL(SAPPLUGIN, test "${sap_enable}" = "yes")
AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
diff --git a/doc/serial-api.txt b/doc/serial-api.txt
index 0bdbdcd..9bb0054 100644
--- a/doc/serial-api.txt
+++ b/doc/serial-api.txt
@@ -11,22 +11,7 @@ Service org.bluez
Interface org.bluez.Serial
Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX

-Methods string Connect(string pattern)
-
- Connects to a specific RFCOMM based service on a
- remote device and then creates a RFCOMM TTY
- device for it. The RFCOMM TTY device is returned.
-
- Possible patterns: UUID 128 bit as string
- Profile short names, e.g: spp, dun
- RFCOMM channel as string, 1-30
-
- Possible errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.InProgress
- org.bluez.Error.ConnectionAttemptFailed
- org.bluez.Error.NotSupported
-
-Methods fd ConnectFD(string pattern) [experimental]
+Methods fd Connect(string pattern)

Connects to a specific RFCOMM based service on a
remote device and returns a file descriptor to talk
@@ -40,124 +25,3 @@ Methods fd ConnectFD(string pattern) [experimental]
org.bluez.Error.InProgress
org.bluez.Error.ConnectionAttemptFailed
org.bluez.Error.NotSupported
-
-
- void Disconnect(string device)
-
- Disconnect a RFCOMM TTY device that has been
- created by Connect method.
-
- To abort a connection attempt in case of errors or
- timeouts in the client it is fine to call this method.
-
- In that case one of patterns of the Connect method should
- be supplied instead of the TTY device.
-
- Possible errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.DoesNotExist
-
-Serial Proxy Manager hierarchy [experimental]
-=============================================
-
-Service org.bluez
-Interface org.bluez.SerialProxyManager
-Object path [variable prefix]/{hci0,hci1,...}
-
-Methods array{string} ListProxies()
-
- Returns an array of the object path strings of
- all the proxies created for the adapter.
-
- string CreateProxy(string pattern, string address)
-
- Possible patterns: UUID 128 bit as string
- Profile short names, e.g: spp, dun
- RFCOMM channel as string, 1-30
-
- Address is the path to the TTY or Unix socket to be used.
- Only one proxy per address (TTY or Unix socket)
- is allowed.
-
- The object path of created proxy is returned.
- On success this will emit a ProxyCreated signal.
-
- Possible Errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.AlreadyExists
- org.bluez.Error.Failed
-
- void RemoveProxy(string path)
-
- This removes the proxy object at the given path.
- On success this will emit a ProxyRemoved signal.
-
- Possible Errors: org.bluez.Error.DoesNotExist
- org.bluez.Error.NotAuthorized
-
-Signals ProxyCreated(string path)
-
- This signal indicates a proxy was created.
- Parameter is object path of created proxy.
-
- ProxyRemoved(string path)
-
- This signal indicates a proxy was removed.
- Parameter is object path of removed proxy.
-
-Serial Proxy hierarchy [experimental]
-=====================================
-
-Service org.bluez
-Interface org.bluez.SerialProxy
-Object path [variable prefix]/{hci0,hci1,...}/{proxy0,proxy1,...}
-
-Methods void Enable()
-
- Starts to listen to the TTY or Unix socket, allocates
- a RFCOMM channel and add record to the server.
-
- Possible errors: org.bluez.Error.Failed
-
- void Disable()
-
- Stops to listen to the TTY or Unix socket, shutdown
- the RFCOMM channel allocated for the proxy, and remove
- record from the server.
-
- Possible errors: org.bluez.Error.Failed
-
- dict GetInfo()
-
- Returns all properties for the proxy. See the
- properties section for available properties.
-
- void SetSerialParameters(string rate, uint8 data, uint8 stop,
- string parity)
-
- Configures serial communication setting baud rate,
- data bits, stop bits and parity.
-
- Doesn't allow change TTY settings if it is open.
-
- Possible errors: org.bluez.Error.InvalidArguments
- org.bluez.Error.NotAuthorized
-
-Properties string uuid [readonly]
-
- 128-bit UUID that represents the available remote service.
-
- string address [readonly]
-
- Address is the path to the TTY or Unix socket name used,
- set when the proxy was created.
-
- uint8 channel [readonly]
-
- RFCOMM channel.
-
- boolean enabled [readonly]
-
- Indicates if the proxy is currently enabled.
-
- boolean connected [readonly]
-
- Indicates if the proxy is currently connected.
diff --git a/serial/main.c b/serial/main.c
deleted file mode 100644
index 38ded03..0000000
--- a/serial/main.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-
-#include <gdbus.h>
-
-#include "plugin.h"
-#include "manager.h"
-
-static DBusConnection *connection;
-
-static int serial_init(void)
-{
- connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
- if (connection == NULL)
- return -EIO;
-
- if (serial_manager_init(connection) < 0) {
- dbus_connection_unref(connection);
- return -EIO;
- }
-
- return 0;
-}
-
-static void serial_exit(void)
-{
- serial_manager_exit();
-
- dbus_connection_unref(connection);
-}
-
-BLUETOOTH_PLUGIN_DEFINE(serial, VERSION,
- BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, serial_init, serial_exit)
diff --git a/serial/manager.c b/serial/manager.c
deleted file mode 100644
index 438ba6c..0000000
--- a/serial/manager.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/uuid.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-#include "adapter.h"
-#include "device.h"
-
-#include "log.h"
-
-#include "error.h"
-#include "port.h"
-#include "proxy.h"
-#include "storage.h"
-#include "manager.h"
-#include "sdpd.h"
-#include "glib-helper.h"
-
-static DBusConnection *connection = NULL;
-
-static int serial_probe(struct btd_device *device, const char *uuid)
-{
- struct btd_adapter *adapter = device_get_adapter(device);
- const gchar *path = device_get_path(device);
- sdp_list_t *protos;
- int ch;
- bdaddr_t src, dst;
- const sdp_record_t *rec;
-
- DBG("path %s: %s", path, uuid);
-
- rec = btd_device_get_record(device, uuid);
- if (!rec)
- return -EINVAL;
-
- if (sdp_get_access_protos(rec, &protos) < 0)
- return -EINVAL;
-
- ch = sdp_get_proto_port(protos, RFCOMM_UUID);
- sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
- sdp_list_free(protos, NULL);
-
- if (ch < 1 || ch > 30) {
- error("Channel out of range: %d", ch);
- return -EINVAL;
- }
-
- adapter_get_address(adapter, &src);
- device_get_address(device, &dst, NULL);
-
- return port_register(connection, path, &src, &dst, uuid, ch);
-}
-
-static void serial_remove(struct btd_device *device)
-{
- const gchar *path = device_get_path(device);
-
- DBG("path %s", path);
-
- port_unregister(path);
-}
-
-
-static int port_probe(struct btd_device *device, GSList *uuids)
-{
- while (uuids) {
- serial_probe(device, uuids->data);
- uuids = uuids->next;
- }
-
- return 0;
-}
-
-static void port_remove(struct btd_device *device)
-{
- return serial_remove(device);
-}
-
-static struct btd_device_driver serial_port_driver = {
- .name = "serial-port",
- .uuids = BTD_UUIDS(RFCOMM_UUID_STR),
- .probe = port_probe,
- .remove = port_remove,
-};
-
-static int proxy_probe(struct btd_adapter *adapter)
-{
- const char *path = adapter_get_path(adapter);
-
- DBG("path %s", path);
-
- return proxy_register(connection, adapter);
-}
-
-static void proxy_remove(struct btd_adapter *adapter)
-{
- const char *path = adapter_get_path(adapter);
-
- DBG("path %s", path);
-
- proxy_unregister(adapter);
-}
-
-static struct btd_adapter_driver serial_proxy_driver = {
- .name = "serial-proxy",
- .probe = proxy_probe,
- .remove = proxy_remove,
-};
-
-int serial_manager_init(DBusConnection *conn)
-{
- connection = dbus_connection_ref(conn);
-
- btd_register_adapter_driver(&serial_proxy_driver);
- btd_register_device_driver(&serial_port_driver);
-
- return 0;
-}
-
-void serial_manager_exit(void)
-{
- btd_unregister_device_driver(&serial_port_driver);
-
- dbus_connection_unref(connection);
- connection = NULL;
-}
diff --git a/serial/manager.h b/serial/manager.h
deleted file mode 100644
index c8b96e8..0000000
--- a/serial/manager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int serial_manager_init(DBusConnection *conn);
-void serial_manager_exit(void);
diff --git a/serial/port.c b/serial/port.c
deleted file mode 100644
index f90bb6a..0000000
--- a/serial/port.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-
-#include "log.h"
-#include "glib-helper.h"
-#include "sdp-client.h"
-#include "btio.h"
-
-#include "error.h"
-#include "manager.h"
-#include "adapter.h"
-#include "device.h"
-#include "storage.h"
-#include "port.h"
-
-#define SERIAL_PORT_INTERFACE "org.bluez.Serial"
-
-#define MAX_OPEN_TRIES 5
-#define OPEN_WAIT 300 /* ms. udev node creation retry wait */
-
-struct serial_device {
- DBusConnection *conn; /* for name listener handling */
- bdaddr_t src; /* Source (local) address */
- bdaddr_t dst; /* Destination address */
- char *path; /* Device path */
- GSList *ports; /* Available ports */
-};
-
-struct serial_port {
- DBusMessage *msg; /* for name listener handling */
- int16_t id; /* RFCOMM device id */
- uint8_t channel; /* RFCOMM channel */
- char *uuid; /* service identification */
- char *dev; /* RFCOMM device name */
- int fd; /* Opened file descriptor */
- GIOChannel *io; /* BtIO channel */
- guint listener_id;
- struct serial_device *device;
-};
-
-static GSList *devices = NULL;
-
-static struct serial_device *find_device(GSList *devices, const char *path)
-{
- GSList *l;
-
- for (l = devices; l != NULL; l = l->next) {
- struct serial_device *device = l->data;
-
- if (!strcmp(device->path, path))
- return device;
- }
-
- return NULL;
-}
-
-static struct serial_port *find_port(GSList *ports, const char *pattern)
-{
- GSList *l;
- int channel;
- char *endptr = NULL;
-
- channel = strtol(pattern, &endptr, 10);
-
- for (l = ports; l != NULL; l = l->next) {
- struct serial_port *port = l->data;
- char *uuid_str;
- int ret;
-
- if (port->uuid && !strcasecmp(port->uuid, pattern))
- return port;
-
- if (endptr && *endptr == '\0' && port->channel == channel)
- return port;
-
- if (port->dev && !strcmp(port->dev, pattern))
- return port;
-
- if (!port->uuid)
- continue;
-
- uuid_str = bt_name2string(pattern);
- if (!uuid_str)
- continue;
-
- ret = strcasecmp(port->uuid, uuid_str);
- g_free(uuid_str);
- if (ret == 0)
- return port;
- }
-
- return NULL;
-}
-
-static int port_release(struct serial_port *port)
-{
- struct rfcomm_dev_req req;
- int rfcomm_ctl;
- int err = 0;
-
- if (port->id < 0) {
- if (port->io) {
- g_io_channel_shutdown(port->io, TRUE, NULL);
- g_io_channel_unref(port->io);
- port->io = NULL;
- } else
- bt_cancel_discovery(&port->device->src,
- &port->device->dst);
-
- return 0;
- }
-
- DBG("Serial port %s released", port->dev);
-
- rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
- if (rfcomm_ctl < 0)
- return -errno;
-
- if (port->fd >= 0) {
- close(port->fd);
- port->fd = -1;
- }
-
- memset(&req, 0, sizeof(req));
- req.dev_id = port->id;
-
- /*
- * We are hitting a kernel bug inside RFCOMM code when
- * RFCOMM_HANGUP_NOW bit is set on request's flags passed to
- * ioctl(RFCOMMRELEASEDEV)!
- */
- req.flags = (1 << RFCOMM_HANGUP_NOW);
-
- if (ioctl(rfcomm_ctl, RFCOMMRELEASEDEV, &req) < 0) {
- err = -errno;
- error("Can't release device %s: %s (%d)",
- port->dev, strerror(-err), -err);
- }
-
- g_free(port->dev);
- port->dev = NULL;
- port->id = -1;
- close(rfcomm_ctl);
- return err;
-}
-
-static void serial_port_free(void *data)
-{
- struct serial_port *port = data;
- struct serial_device *device = port->device;
-
- if (device && port->listener_id > 0)
- g_dbus_remove_watch(device->conn, port->listener_id);
-
- port_release(port);
-
- g_free(port->uuid);
- g_free(port);
-}
-
-static void serial_device_free(void *data)
-{
- struct serial_device *device = data;
-
- g_free(device->path);
- if (device->conn)
- dbus_connection_unref(device->conn);
- g_free(device);
-}
-
-static void port_owner_exited(DBusConnection *conn, void *user_data)
-{
- struct serial_port *port = user_data;
-
- port_release(port);
-
- port->listener_id = 0;
-}
-
-static void path_unregister(void *data)
-{
- struct serial_device *device = data;
-
- DBG("Unregistered interface %s on path %s", SERIAL_PORT_INTERFACE,
- device->path);
-
- devices = g_slist_remove(devices, device);
- serial_device_free(device);
-}
-
-void port_release_all(void)
-{
- g_slist_free_full(devices, serial_device_free);
-}
-
-static void open_notify(int fd, int err, struct serial_port *port)
-{
- struct serial_device *device = port->device;
- DBusMessage *reply;
-
- if (err < 0) {
- /* Max tries exceeded */
- port_release(port);
- reply = btd_error_failed(port->msg, strerror(-err));
- } else {
- port->fd = fd;
- reply = g_dbus_create_reply(port->msg,
- DBUS_TYPE_STRING, &port->dev,
- DBUS_TYPE_INVALID);
- }
-
- /* Reply to the requestor */
- g_dbus_send_message(device->conn, reply);
-}
-
-static gboolean open_continue(gpointer user_data)
-{
- struct serial_port *port = user_data;
- int fd;
- static int ntries = MAX_OPEN_TRIES;
-
- if (!port->listener_id)
- return FALSE; /* Owner exited */
-
- fd = open(port->dev, O_RDONLY | O_NOCTTY);
- if (fd < 0) {
- int err = -errno;
- error("Could not open %s: %s (%d)",
- port->dev, strerror(-err), -err);
- if (!--ntries) {
- /* Reporting error */
- open_notify(fd, err, port);
- ntries = MAX_OPEN_TRIES;
- return FALSE;
- }
- return TRUE;
- }
-
- /* Connection succeeded */
- open_notify(fd, 0, port);
- return FALSE;
-}
-
-static int port_open(struct serial_port *port)
-{
- int fd;
-
- fd = open(port->dev, O_RDONLY | O_NOCTTY);
- if (fd < 0) {
- g_timeout_add(OPEN_WAIT, open_continue, port);
- return -EINPROGRESS;
- }
-
- return fd;
-}
-
-static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err,
- gpointer user_data)
-{
- struct serial_port *port = user_data;
- struct serial_device *device = port->device;
- struct rfcomm_dev_req req;
- int sk, fd;
- DBusMessage *reply;
-
- /* Owner exited? */
- if (!port->listener_id)
- return;
-
- if (conn_err) {
- error("%s", conn_err->message);
- reply = btd_error_failed(port->msg, conn_err->message);
- goto fail;
- }
-
- sk = g_io_channel_unix_get_fd(chan);
-
- if (dbus_message_has_member(port->msg, "ConnectFD")) {
- reply = g_dbus_create_reply(port->msg, DBUS_TYPE_UNIX_FD, &sk,
- DBUS_TYPE_INVALID);
- g_dbus_send_message(device->conn, reply);
-
- close(sk);
-
- g_dbus_remove_watch(device->conn, port->listener_id);
- port->listener_id = 0;
-
- return;
- }
-
- memset(&req, 0, sizeof(req));
- req.dev_id = -1;
- req.flags = (1 << RFCOMM_REUSE_DLC);
- bacpy(&req.src, &device->src);
- bacpy(&req.dst, &device->dst);
- req.channel = port->channel;
-
- g_io_channel_unref(port->io);
- port->io = NULL;
-
- port->id = ioctl(sk, RFCOMMCREATEDEV, &req);
- if (port->id < 0) {
- int err = -errno;
- error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(-err), -err);
- reply = btd_error_failed(port->msg, strerror(-err));
- g_io_channel_shutdown(chan, TRUE, NULL);
- goto fail;
- }
-
- port->dev = g_strdup_printf("/dev/rfcomm%d", port->id);
-
- DBG("Serial port %s created", port->dev);
-
- g_io_channel_shutdown(chan, TRUE, NULL);
-
- /* Addressing connect port */
- fd = port_open(port);
- if (fd < 0)
- /* Open in progress: Wait the callback */
- return;
-
- open_notify(fd, 0, port);
- return;
-
-fail:
- g_dbus_send_message(device->conn, reply);
- g_dbus_remove_watch(device->conn, port->listener_id);
- port->listener_id = 0;
-}
-
-static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
-{
- struct serial_port *port = user_data;
- struct serial_device *device = port->device;
- sdp_record_t *record = NULL;
- sdp_list_t *protos;
- DBusMessage *reply;
- GError *gerr = NULL;
-
- if (!port->listener_id)
- return;
-
- if (err < 0) {
- error("Unable to get service record: %s (%d)", strerror(-err),
- -err);
- reply = btd_error_failed(port->msg, strerror(-err));
- goto failed;
- }
-
- if (!recs || !recs->data) {
- error("No record found");
- reply = btd_error_failed(port->msg, "No record found");
- goto failed;
- }
-
- record = recs->data;
-
- if (sdp_get_access_protos(record, &protos) < 0) {
- error("Unable to get access protos from port record");
- reply = btd_error_failed(port->msg, "Invalid channel");
- goto failed;
- }
-
- port->channel = sdp_get_proto_port(protos, RFCOMM_UUID);
-
- sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
- sdp_list_free(protos, NULL);
-
- port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
- NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR, &device->src,
- BT_IO_OPT_DEST_BDADDR, &device->dst,
- BT_IO_OPT_CHANNEL, port->channel,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_INVALID);
- if (!port->io) {
- error("%s", gerr->message);
- reply = btd_error_failed(port->msg, gerr->message);
- g_error_free(gerr);
- goto failed;
- }
-
- return;
-
-failed:
- g_dbus_remove_watch(device->conn, port->listener_id);
- port->listener_id = 0;
- g_dbus_send_message(device->conn, reply);
-}
-
-static int connect_port(struct serial_port *port)
-{
- struct serial_device *device = port->device;
- uuid_t uuid;
- int err;
-
- if (!port->uuid)
- goto connect;
-
- err = bt_string2uuid(&uuid, port->uuid);
- if (err < 0)
- return err;
-
- sdp_uuid128_to_uuid(&uuid);
-
- return bt_search_service(&device->src, &device->dst, &uuid,
- get_record_cb, port, NULL);
-
-connect:
- port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port,
- NULL, NULL,
- BT_IO_OPT_SOURCE_BDADDR, &device->src,
- BT_IO_OPT_DEST_BDADDR, &device->dst,
- BT_IO_OPT_CHANNEL, port->channel,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_INVALID);
- if (port->io == NULL)
- return -EIO;
-
- return 0;
-}
-
-static struct serial_port *create_port(struct serial_device *device,
- const char *uuid, uint8_t channel)
-{
- struct serial_port *port;
-
- port = g_new0(struct serial_port, 1);
- port->uuid = g_strdup(uuid);
- port->channel = channel;
- port->device = device;
- port->id = -1;
- port->fd = -1;
-
- device->ports = g_slist_append(device->ports, port);
-
- return port;
-}
-
-static DBusMessage *port_connect(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
-{
- struct serial_device *device = user_data;
- struct serial_port *port;
- const char *pattern;
- int err;
-
- if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
- DBUS_TYPE_INVALID) == FALSE)
- return NULL;
-
- port = find_port(device->ports, pattern);
- if (!port) {
- char *endptr = NULL;
- int channel;
-
- channel = strtol(pattern, &endptr, 10);
- if ((endptr && *endptr != '\0') || channel < 1 || channel > 30)
- return btd_error_does_not_exist(msg);
-
- port = create_port(device, NULL, channel);
- }
-
- if (port->listener_id)
- return btd_error_failed(msg, "Port already in use");
-
- port->listener_id = g_dbus_add_disconnect_watch(conn,
- dbus_message_get_sender(msg),
- port_owner_exited, port,
- NULL);
-
- port->msg = dbus_message_ref(msg);
-
- err = connect_port(port);
- if (err < 0) {
- error("%s", strerror(-err));
- g_dbus_remove_watch(conn, port->listener_id);
- port->listener_id = 0;
-
- return btd_error_failed(msg, strerror(-err));
- }
-
- return NULL;
-}
-
-static DBusMessage *port_disconnect(DBusConnection *conn,
- DBusMessage *msg, void *user_data)
-{
- struct serial_device *device = user_data;
- struct serial_port *port;
- const char *dev, *owner, *caller;
-
- if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dev,
- DBUS_TYPE_INVALID) == FALSE)
- return NULL;
-
- port = find_port(device->ports, dev);
- if (!port)
- return btd_error_does_not_exist(msg);
-
- if (!port->listener_id)
- return btd_error_not_connected(msg);
-
- owner = dbus_message_get_sender(port->msg);
- caller = dbus_message_get_sender(msg);
- if (!g_str_equal(owner, caller))
- return btd_error_not_authorized(msg);
-
- port_release(port);
-
- g_dbus_remove_watch(conn, port->listener_id);
- port->listener_id = 0;
-
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
-}
-
-static const GDBusMethodTable port_methods[] = {
- { GDBUS_ASYNC_METHOD("Connect",
- GDBUS_ARGS({ "pattern", "s" }), GDBUS_ARGS({ "tty", "s" }),
- port_connect) },
- { GDBUS_ASYNC_METHOD("ConnectFD",
- GDBUS_ARGS({ "pattern", "s" }), GDBUS_ARGS({ "fd", "s" }),
- port_connect) },
- { GDBUS_METHOD("Disconnect",
- GDBUS_ARGS({ "device", "s" }), NULL,
- port_disconnect) },
- { }
-};
-
-static struct serial_device *create_serial_device(DBusConnection *conn,
- const char *path, bdaddr_t *src,
- bdaddr_t *dst)
-{
- struct serial_device *device;
-
- device = g_new0(struct serial_device, 1);
- device->conn = dbus_connection_ref(conn);
- bacpy(&device->dst, dst);
- bacpy(&device->src, src);
- device->path = g_strdup(path);
-
- if (!g_dbus_register_interface(conn, path,
- SERIAL_PORT_INTERFACE,
- port_methods, NULL, NULL,
- device, path_unregister)) {
- error("D-Bus failed to register %s interface",
- SERIAL_PORT_INTERFACE);
- serial_device_free(device);
- return NULL;
- }
-
- DBG("Registered interface %s on path %s",
- SERIAL_PORT_INTERFACE, path);
-
- return device;
-}
-
-int port_register(DBusConnection *conn, const char *path, bdaddr_t *src,
- bdaddr_t *dst, const char *uuid, uint8_t channel)
-{
- struct serial_device *device;
- struct serial_port *port;
-
- device = find_device(devices, path);
- if (!device) {
- device = create_serial_device(conn, path, src, dst);
- if (!device)
- return -1;
- devices = g_slist_append(devices, device);
- }
-
- if (find_port(device->ports, uuid))
- return 0;
-
- port = g_new0(struct serial_port, 1);
- port->uuid = g_strdup(uuid);
- port->channel = channel;
- port->device = device;
- port->id = -1;
- port->fd = -1;
-
- device->ports = g_slist_append(device->ports, port);
-
- return 0;
-}
-
-int port_unregister(const char *path)
-{
- struct serial_device *device;
-
- device = find_device(devices, path);
- if (!device)
- return -ENOENT;
-
- g_slist_free_full(device->ports, serial_port_free);
-
- g_dbus_unregister_interface(device->conn, path, SERIAL_PORT_INTERFACE);
-
- return 0;
-}
diff --git a/serial/port.h b/serial/port.h
deleted file mode 100644
index 74ac9f0..0000000
--- a/serial/port.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-void port_release_all(void);
-
-int port_register(DBusConnection *conn, const char *path, bdaddr_t *src,
- bdaddr_t *dst, const char *name, uint8_t channel);
-
-int port_unregister(const char *path);
diff --git a/serial/proxy.c b/serial/proxy.c
deleted file mode 100644
index dd38317..0000000
--- a/serial/proxy.c
+++ /dev/null
@@ -1,1269 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/un.h>
-
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-#include <bluetooth/rfcomm.h>
-
-#include <glib.h>
-#include <gdbus.h>
-
-#include "../src/dbus-common.h"
-#include "../src/adapter.h"
-
-#include "log.h"
-
-#include "error.h"
-#include "sdpd.h"
-#include "glib-helper.h"
-#include "btio.h"
-#include "proxy.h"
-
-#define SERIAL_PROXY_INTERFACE "org.bluez.SerialProxy"
-#define SERIAL_MANAGER_INTERFACE "org.bluez.SerialProxyManager"
-#define BUF_SIZE 1024
-
-typedef enum {
- TTY_PROXY,
- UNIX_SOCKET_PROXY,
- TCP_SOCKET_PROXY,
- UNKNOWN_PROXY_TYPE = 0xFF
-} proxy_type_t;
-
-struct serial_adapter {
- struct btd_adapter *btd_adapter; /* Adapter pointer */
- DBusConnection *conn; /* Adapter connection */
- GSList *proxies; /* Proxies list */
-};
-
-struct serial_proxy {
- bdaddr_t src; /* Local address */
- bdaddr_t dst; /* Remote address */
- char *path; /* Proxy path */
- char *uuid128; /* UUID 128 */
- char *address; /* TTY or Unix socket name */
- char *owner; /* Application bus name */
- guint watch; /* Application watch */
- short int port; /* TCP port */
- proxy_type_t type; /* TTY or Unix socket */
- struct termios sys_ti; /* Default TTY setting */
- struct termios proxy_ti; /* Proxy TTY settings */
- uint8_t channel; /* RFCOMM channel */
- uint32_t record_id; /* Service record id */
- GIOChannel *io; /* Server listen */
- GIOChannel *rfcomm; /* Remote RFCOMM channel*/
- GIOChannel *local; /* Local channel: TTY or Unix socket */
- struct serial_adapter *adapter; /* Adapter pointer */
-};
-
-static GSList *adapters = NULL;
-static int sk_counter = 0;
-
-static void disable_proxy(struct serial_proxy *prx)
-{
- if (prx->rfcomm) {
- g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
- g_io_channel_unref(prx->rfcomm);
- prx->rfcomm = NULL;
- }
-
- if (prx->local) {
- g_io_channel_shutdown(prx->local, TRUE, NULL);
- g_io_channel_unref(prx->local);
- prx->local = NULL;
- }
-
- remove_record_from_server(prx->record_id);
- prx->record_id = 0;
-
- g_io_channel_unref(prx->io);
- prx->io = NULL;
-}
-
-static void proxy_free(struct serial_proxy *prx)
-{
- g_free(prx->owner);
- g_free(prx->path);
- g_free(prx->address);
- g_free(prx->uuid128);
- g_free(prx);
-}
-
-static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel)
-{
- sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;
- uuid_t uuid, root_uuid, l2cap, rfcomm;
- sdp_profile_desc_t profile;
- sdp_record_t *record;
- sdp_data_t *ch;
-
- record = sdp_record_alloc();
- if (!record)
- return NULL;
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(record, root);
- sdp_list_free(root, NULL);
-
- bt_string2uuid(&uuid, uuid128);
- sdp_uuid128_to_uuid(&uuid);
- svclass_id = sdp_list_append(NULL, &uuid);
- sdp_set_service_classes(record, svclass_id);
- sdp_list_free(svclass_id, NULL);
-
- sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
- profile.version = 0x0100;
- profiles = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, profiles);
- sdp_list_free(profiles, NULL);
-
- sdp_uuid16_create(&l2cap, L2CAP_UUID);
- proto[0] = sdp_list_append(NULL, &l2cap);
- apseq = sdp_list_append(NULL, proto[0]);
-
- sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
- proto[1] = sdp_list_append(NULL, &rfcomm);
- ch = sdp_data_alloc(SDP_UINT8, &channel);
- proto[1] = sdp_list_append(proto[1], ch);
- apseq = sdp_list_append(apseq, proto[1]);
-
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(record, aproto);
-
- sdp_add_lang_attr(record);
-
- sdp_set_info_attr(record, "Serial Proxy", NULL, "Serial Proxy");
-
- sdp_data_free(ch);
- sdp_list_free(proto[0], NULL);
- sdp_list_free(proto[1], NULL);
- sdp_list_free(apseq, NULL);
- sdp_list_free(aproto, NULL);
-
- return record;
-}
-
-static int channel_write(GIOChannel *chan, char *buf, size_t size)
-{
- size_t wbytes;
- ssize_t written;
- int fd;
-
- fd = g_io_channel_unix_get_fd(chan);
-
- wbytes = 0;
- while (wbytes < size) {
- written = write(fd, buf + wbytes, size - wbytes);
- if (written < 0)
- return -errno;
-
- wbytes += written;
- }
-
- return 0;
-}
-
-static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data)
-{
- char buf[BUF_SIZE];
- struct serial_proxy *prx = data;
- GIOChannel *dest;
- ssize_t rbytes;
- int fd, err;
-
- if (cond & G_IO_NVAL)
- return FALSE;
-
- dest = (chan == prx->rfcomm) ? prx->local : prx->rfcomm;
-
- fd = g_io_channel_unix_get_fd(chan);
-
- if (cond & (G_IO_HUP | G_IO_ERR)) {
- /* Try forward remaining data */
- do {
- rbytes = read(fd, buf, sizeof(buf));
- if (rbytes <= 0)
- break;
-
- err = channel_write(dest, buf, rbytes);
- } while (err == 0);
-
- g_io_channel_shutdown(prx->local, TRUE, NULL);
- g_io_channel_unref(prx->local);
- prx->local = NULL;
-
- g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
- g_io_channel_unref(prx->rfcomm);
- prx->rfcomm = NULL;
-
- return FALSE;
- }
-
- rbytes = read(fd, buf, sizeof(buf));
- if (rbytes < 0)
- return FALSE;
-
- err = channel_write(dest, buf, rbytes);
- if (err != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static inline int unix_socket_connect(const char *address)
-{
- struct sockaddr_un addr;
- int err, sk;
-
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = PF_UNIX;
-
- if (strncmp("x00", address, 3) == 0) {
- /*
- * Abstract namespace: first byte NULL, x00
- * must be removed from the original address.
- */
- strncpy(addr.sun_path + 1, address + 3,
- sizeof(addr.sun_path) - 2);
- } else {
- /* Filesystem address */
- strncpy(addr.sun_path, address, sizeof(addr.sun_path) - 1);
- }
-
- /* Unix socket */
- sk = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sk < 0) {
- err = -errno;
- error("Unix socket(%s) create failed: %s(%d)",
- address, strerror(-err), -err);
- return err;
- }
-
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- err = -errno;
- error("Unix socket(%s) connect failed: %s(%d)",
- address, strerror(-err), -err);
- close(sk);
- return err;
- }
-
- return sk;
-}
-
-static int tcp_socket_connect(const char *address)
-{
- struct sockaddr_in addr;
- int err, sk, port;
-
- memset(&addr, 0, sizeof(addr));
-
- if (strncmp(address, "localhost", 9) != 0) {
- error("Address should have the form localhost:port.");
- return -1;
- }
- port = atoi(strchr(address, ':') + 1);
- if (port <= 0) {
- error("Invalid port '%d'.", port);
- return -1;
- }
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- addr.sin_port = htons(port);
-
- sk = socket(PF_INET, SOCK_STREAM, 0);
- if (sk < 0) {
- err = -errno;
- error("TCP socket(%s) create failed %s(%d)", address,
- strerror(-err), -err);
- return err;
- }
- if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- err = -errno;
- error("TCP socket(%s) connect failed: %s(%d)",
- address, strerror(-err), -err);
- close(sk);
- return err;
- }
- return sk;
-}
-
-static inline int tty_open(const char *tty, struct termios *ti)
-{
- int err, sk;
-
- sk = open(tty, O_RDWR | O_NOCTTY);
- if (sk < 0) {
- err = -errno;
- error("Can't open TTY %s: %s(%d)", tty, strerror(-err), -err);
- return err;
- }
-
- if (ti && tcsetattr(sk, TCSANOW, ti) < 0) {
- err = -errno;
- error("Can't change serial settings: %s(%d)",
- strerror(-err), -err);
- close(sk);
- return err;
- }
-
- return sk;
-}
-
-static void connect_event_cb(GIOChannel *chan, GError *conn_err, gpointer data)
-{
- struct serial_proxy *prx = data;
- int sk;
-
- if (conn_err) {
- error("%s", conn_err->message);
- goto drop;
- }
-
- /* Connect local */
- switch (prx->type) {
- case UNIX_SOCKET_PROXY:
- sk = unix_socket_connect(prx->address);
- break;
- case TTY_PROXY:
- sk = tty_open(prx->address, &prx->proxy_ti);
- break;
- case TCP_SOCKET_PROXY:
- sk = tcp_socket_connect(prx->address);
- break;
- default:
- sk = -1;
- }
-
- if (sk < 0)
- goto drop;
-
- prx->local = g_io_channel_unix_new(sk);
-
- g_io_add_watch(prx->rfcomm,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- forward_data, prx);
-
- g_io_add_watch(prx->local,
- G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- forward_data, prx);
-
- return;
-
-drop:
- g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
- g_io_channel_unref(prx->rfcomm);
- prx->rfcomm = NULL;
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
- struct serial_proxy *prx = user_data;
- GError *err = NULL;
-
- if (derr) {
- error("Access denied: %s", derr->message);
- goto reject;
- }
-
- if (!bt_io_accept(prx->rfcomm, connect_event_cb, prx, NULL,
- &err)) {
- error("bt_io_accept: %s", err->message);
- g_error_free(err);
- goto reject;
- }
-
- return;
-
-reject:
- g_io_channel_shutdown(prx->rfcomm, TRUE, NULL);
- g_io_channel_unref(prx->rfcomm);
- prx->rfcomm = NULL;
-}
-
-static void confirm_event_cb(GIOChannel *chan, gpointer user_data)
-{
- struct serial_proxy *prx = user_data;
- int perr;
- char address[18];
- GError *err = NULL;
-
- bt_io_get(chan, BT_IO_RFCOMM, &err,
- BT_IO_OPT_DEST_BDADDR, &prx->dst,
- BT_IO_OPT_DEST, address,
- BT_IO_OPT_INVALID);
- if (err) {
- error("%s", err->message);
- g_error_free(err);
- goto drop;
- }
-
- if (prx->rfcomm) {
- error("Refusing connect from %s: Proxy already in use",
- address);
- goto drop;
- }
-
- DBG("Serial Proxy: incoming connect from %s", address);
-
- prx->rfcomm = g_io_channel_ref(chan);
-
- perr = btd_request_authorization(&prx->src, &prx->dst,
- prx->uuid128, auth_cb, prx);
- if (perr < 0) {
- error("Refusing connect from %s: %s (%d)", address,
- strerror(-perr), -perr);
- g_io_channel_unref(prx->rfcomm);
- prx->rfcomm = NULL;
- goto drop;
- }
-
- return;
-
-drop:
- g_io_channel_shutdown(chan, TRUE, NULL);
-}
-
-static int enable_proxy(struct serial_proxy *prx)
-{
- sdp_record_t *record;
- GError *gerr = NULL;
- int err;
-
- if (prx->io)
- return -EALREADY;
-
- /* Listen */
- prx->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event_cb, prx,
- NULL, &gerr,
- BT_IO_OPT_SOURCE_BDADDR, &prx->src,
- BT_IO_OPT_INVALID);
- if (!prx->io)
- goto failed;
-
- bt_io_get(prx->io, BT_IO_RFCOMM, &gerr,
- BT_IO_OPT_CHANNEL, &prx->channel,
- BT_IO_OPT_INVALID);
- if (gerr) {
- g_io_channel_unref(prx->io);
- prx->io = NULL;
- goto failed;
- }
-
- DBG("Allocated channel %d", prx->channel);
-
- g_io_channel_set_close_on_unref(prx->io, TRUE);
-
- record = proxy_record_new(prx->uuid128, prx->channel);
- if (!record) {
- g_io_channel_unref(prx->io);
- return -ENOMEM;
- }
-
- err = add_record_to_server(&prx->src, record);
- if (err < 0) {
- sdp_record_free(record);
- g_io_channel_unref(prx->io);
- return err;
- }
-
- prx->record_id = record->handle;
-
- return 0;
-
-failed:
- error("%s", gerr->message);
- g_error_free(gerr);
- return -EIO;
-
-}
-static DBusMessage *proxy_enable(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_proxy *prx = data;
- int err;
-
- err = enable_proxy(prx);
- if (err < 0)
- return btd_error_failed(msg, strerror(-err));
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *proxy_disable(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_proxy *prx = data;
-
- if (!prx->io)
- return btd_error_failed(msg, "Not enabled");
-
- /* Remove the watches and unregister the record */
- disable_proxy(prx);
-
- return dbus_message_new_method_return(msg);
-}
-
-static DBusMessage *proxy_get_info(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_proxy *prx = data;
- DBusMessage *reply;
- DBusMessageIter iter, dict;
- dbus_bool_t boolean;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- dict_append_entry(&dict, "uuid", DBUS_TYPE_STRING, &prx->uuid128);
-
- dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &prx->address);
-
- if (prx->channel)
- dict_append_entry(&dict, "channel",
- DBUS_TYPE_BYTE, &prx->channel);
-
- boolean = (prx->io ? TRUE : FALSE);
- dict_append_entry(&dict, "enabled", DBUS_TYPE_BOOLEAN, &boolean);
-
- boolean = (prx->rfcomm ? TRUE : FALSE);
- dict_append_entry(&dict, "connected", DBUS_TYPE_BOOLEAN, &boolean);
-
- /* If connected: append the remote address */
- if (boolean) {
- char bda[18];
- const char *pstr = bda;
-
- ba2str(&prx->dst, bda);
- dict_append_entry(&dict, "address", DBUS_TYPE_STRING, &pstr);
- }
-
- dbus_message_iter_close_container(&iter, &dict);
-
- return reply;
-}
-
-static struct {
- const char *str;
- speed_t speed;
-} supported_speed[] = {
- {"50", B50 },
- {"300", B300 },
- {"600", B600 },
- {"1200", B1200 },
- {"1800", B1800 },
- {"2400", B2400 },
- {"4800", B4800 },
- {"9600", B9600 },
- {"19200", B19200 },
- {"38400", B38400 },
- {"57600", B57600 },
- {"115200", B115200 },
- { NULL, B0 }
-};
-
-static speed_t str2speed(const char *str, speed_t *speed)
-{
- int i;
-
- for (i = 0; supported_speed[i].str; i++) {
- if (strcmp(supported_speed[i].str, str) != 0)
- continue;
-
- if (speed)
- *speed = supported_speed[i].speed;
-
- return supported_speed[i].speed;
- }
-
- return B0;
-}
-
-static int set_parity(const char *str, tcflag_t *ctrl)
-{
- if (strcasecmp("even", str) == 0) {
- *ctrl |= PARENB;
- *ctrl &= ~PARODD;
- } else if (strcasecmp("odd", str) == 0) {
- *ctrl |= PARENB;
- *ctrl |= PARODD;
- } else if (strcasecmp("mark", str) == 0)
- *ctrl |= PARENB;
- else if ((strcasecmp("none", str) == 0) ||
- (strcasecmp("space", str) == 0))
- *ctrl &= ~PARENB;
- else
- return -1;
-
- return 0;
-}
-
-static int set_databits(uint8_t databits, tcflag_t *ctrl)
-{
- if (databits < 5 || databits > 8)
- return -EINVAL;
-
- *ctrl &= ~CSIZE;
- switch (databits) {
- case 5:
- *ctrl |= CS5;
- break;
- case 6:
- *ctrl |= CS6;
- break;
- case 7:
- *ctrl |= CS7;
- break;
- case 8:
- *ctrl |= CS8;
- break;
- }
-
- return 0;
-}
-
-static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl)
-{
- /* 1.5 will not be allowed */
- switch (stopbits) {
- case 1:
- *ctrl &= ~CSTOPB;
- return 0;
- case 2:
- *ctrl |= CSTOPB;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static DBusMessage *proxy_set_serial_params(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_proxy *prx = data;
- const char *ratestr, *paritystr;
- uint8_t databits, stopbits;
- tcflag_t ctrl; /* Control mode flags */
- speed_t speed = B0; /* In/Out speed */
-
- /* Don't allow change TTY settings if it is open */
- if (prx->local)
- return btd_error_not_authorized(msg);
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &ratestr,
- DBUS_TYPE_BYTE, &databits,
- DBUS_TYPE_BYTE, &stopbits,
- DBUS_TYPE_STRING, &paritystr,
- DBUS_TYPE_INVALID))
- return NULL;
-
- if (str2speed(ratestr, &speed) == B0)
- return btd_error_invalid_args(msg);
-
- ctrl = prx->proxy_ti.c_cflag;
- if (set_databits(databits, &ctrl) < 0)
- return btd_error_invalid_args(msg);
-
- if (set_stopbits(stopbits, &ctrl) < 0)
- return btd_error_invalid_args(msg);
-
- if (set_parity(paritystr, &ctrl) < 0)
- return btd_error_invalid_args(msg);
-
- prx->proxy_ti.c_cflag = ctrl;
- prx->proxy_ti.c_cflag |= (CLOCAL | CREAD);
- cfsetispeed(&prx->proxy_ti, speed);
- cfsetospeed(&prx->proxy_ti, speed);
-
- return dbus_message_new_method_return(msg);
-}
-
-static const GDBusMethodTable proxy_methods[] = {
- { GDBUS_METHOD("Enable", NULL, NULL, proxy_enable) },
- { GDBUS_METHOD("Disable", NULL, NULL, proxy_disable) },
- { GDBUS_METHOD("GetInfo",
- NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
- proxy_get_info) },
- { GDBUS_METHOD("SetSerialParameters",
- GDBUS_ARGS({ "rate", "s" }, { "data", "y" },
- { "stop", "y" }, { "parity", "s" }),
- NULL, proxy_set_serial_params) },
- { },
-};
-
-static void proxy_path_unregister(gpointer data)
-{
- struct serial_proxy *prx = data;
- int sk;
-
- DBG("Unregistered proxy: %s", prx->address);
-
- if (prx->type != TTY_PROXY)
- goto done;
-
- /* Restore the initial TTY configuration */
- sk = open(prx->address, O_RDWR | O_NOCTTY);
- if (sk >= 0) {
- tcsetattr(sk, TCSAFLUSH, &prx->sys_ti);
- close(sk);
- }
-done:
-
- proxy_free(prx);
-}
-
-static int register_proxy_object(struct serial_proxy *prx)
-{
- struct serial_adapter *adapter = prx->adapter;
- char path[MAX_PATH_LENGTH + 1];
-
- snprintf(path, MAX_PATH_LENGTH, "%s/proxy%d",
- adapter_get_path(adapter->btd_adapter), sk_counter++);
-
- if (!g_dbus_register_interface(adapter->conn, path,
- SERIAL_PROXY_INTERFACE,
- proxy_methods, NULL, NULL,
- prx, proxy_path_unregister)) {
- error("D-Bus failed to register %s path", path);
- return -1;
- }
-
- prx->path = g_strdup(path);
- adapter->proxies = g_slist_append(adapter->proxies, prx);
-
- DBG("Registered proxy: %s", path);
-
- return 0;
-}
-
-static int proxy_tty_register(struct serial_adapter *adapter,
- const char *uuid128, const char *address,
- struct termios *ti,
- struct serial_proxy **proxy)
-{
- struct termios sys_ti;
- struct serial_proxy *prx;
- int sk, ret;
-
- sk = open(address, O_RDONLY | O_NOCTTY);
- if (sk < 0) {
- error("Can't open TTY: %s(%d)", strerror(errno), errno);
- return -EINVAL;
- }
-
- prx = g_new0(struct serial_proxy, 1);
- prx->address = g_strdup(address);
- prx->uuid128 = g_strdup(uuid128);
- prx->type = TTY_PROXY;
- adapter_get_address(adapter->btd_adapter, &prx->src);
- prx->adapter = adapter;
-
- /* Current TTY settings */
- memset(&sys_ti, 0, sizeof(sys_ti));
- tcgetattr(sk, &sys_ti);
- memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti));
- close(sk);
-
- if (!ti) {
- /* Use current settings */
- memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti));
- } else {
- /* New TTY settings: user provided */
- memcpy(&prx->proxy_ti, ti, sizeof(*ti));
- }
-
- ret = register_proxy_object(prx);
- if (ret < 0) {
- proxy_free(prx);
- return ret;
- }
-
- *proxy = prx;
-
- return ret;
-}
-
-static int proxy_socket_register(struct serial_adapter *adapter,
- const char *uuid128, const char *address,
- struct serial_proxy **proxy)
-{
- struct serial_proxy *prx;
- int ret;
-
- prx = g_new0(struct serial_proxy, 1);
- prx->address = g_strdup(address);
- prx->uuid128 = g_strdup(uuid128);
- prx->type = UNIX_SOCKET_PROXY;
- adapter_get_address(adapter->btd_adapter, &prx->src);
- prx->adapter = adapter;
-
- ret = register_proxy_object(prx);
- if (ret < 0) {
- proxy_free(prx);
- return ret;
- }
-
- *proxy = prx;
-
- return ret;
-}
-
-static int proxy_tcp_register(struct serial_adapter *adapter,
- const char *uuid128, const char *address,
- struct serial_proxy **proxy)
-{
- struct serial_proxy *prx;
- int ret;
-
- prx = g_new0(struct serial_proxy, 1);
- prx->address = g_strdup(address);
- prx->uuid128 = g_strdup(uuid128);
- prx->type = TCP_SOCKET_PROXY;
- adapter_get_address(adapter->btd_adapter, &prx->src);
- prx->adapter = adapter;
-
- ret = register_proxy_object(prx);
- if (ret < 0) {
- proxy_free(prx);
- return ret;
- }
-
- *proxy = prx;
-
- return ret;
-}
-
-static proxy_type_t addr2type(const char *address)
-{
- struct stat st;
-
- if (stat(address, &st) < 0) {
- /*
- * Unix socket: if the sun_path starts with null byte
- * it refers to abstract namespace. 'x00' will be used
- * to represent the null byte.
- */
- if (strncmp("localhost:", address, 10) == 0)
- return TCP_SOCKET_PROXY;
- if (strncmp("x00", address, 3) != 0)
- return UNKNOWN_PROXY_TYPE;
- else
- return UNIX_SOCKET_PROXY;
- } else {
- /* Filesystem: char device or unix socket */
- if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0)
- return TTY_PROXY;
- else if (S_ISSOCK(st.st_mode))
- return UNIX_SOCKET_PROXY;
- else
- return UNKNOWN_PROXY_TYPE;
- }
-}
-
-static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr)
-{
- const struct serial_proxy *prx = proxy;
- const char *address = addr;
-
- return strcmp(prx->address, address);
-}
-
-static int proxy_pathcmp(gconstpointer proxy, gconstpointer p)
-{
- const struct serial_proxy *prx = proxy;
- const char *path = p;
-
- return strcmp(prx->path, path);
-}
-
-static int register_proxy(struct serial_adapter *adapter,
- const char *uuid_str, const char *address,
- struct serial_proxy **proxy)
-{
- proxy_type_t type;
- int err;
-
- type = addr2type(address);
- if (type == UNKNOWN_PROXY_TYPE)
- return -EINVAL;
-
- /* Only one proxy per address(TTY or unix socket) is allowed */
- if (g_slist_find_custom(adapter->proxies, address, proxy_addrcmp))
- return -EALREADY;
-
- switch (type) {
- case UNIX_SOCKET_PROXY:
- err = proxy_socket_register(adapter, uuid_str, address, proxy);
- break;
- case TTY_PROXY:
- err = proxy_tty_register(adapter, uuid_str, address, NULL,
- proxy);
- break;
- case TCP_SOCKET_PROXY:
- err = proxy_tcp_register(adapter, uuid_str, address, proxy);
- break;
- default:
- err = -EINVAL;
- }
-
- if (err < 0)
- return err;
-
- g_dbus_emit_signal(adapter->conn,
- adapter_get_path(adapter->btd_adapter),
- SERIAL_MANAGER_INTERFACE, "ProxyCreated",
- DBUS_TYPE_STRING, &(*proxy)->path,
- DBUS_TYPE_INVALID);
-
- return 0;
-}
-
-static void unregister_proxy(struct serial_proxy *proxy)
-{
- struct serial_adapter *adapter = proxy->adapter;
- char *path = g_strdup(proxy->path);
-
- if (proxy->watch > 0)
- g_dbus_remove_watch(adapter->conn, proxy->watch);
-
- g_dbus_emit_signal(adapter->conn,
- adapter_get_path(adapter->btd_adapter),
- SERIAL_MANAGER_INTERFACE, "ProxyRemoved",
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID);
-
- adapter->proxies = g_slist_remove(adapter->proxies, proxy);
-
- g_dbus_unregister_interface(adapter->conn, path,
- SERIAL_PROXY_INTERFACE);
-
- g_free(path);
-}
-
-static void watch_proxy(DBusConnection *connection, void *user_data)
-{
- struct serial_proxy *proxy = user_data;
-
- proxy->watch = 0;
- unregister_proxy(proxy);
-}
-
-static DBusMessage *create_proxy(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_adapter *adapter = data;
- struct serial_proxy *proxy;
- const char *pattern, *address;
- char *uuid_str;
- int err;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &pattern,
- DBUS_TYPE_STRING, &address,
- DBUS_TYPE_INVALID))
- return NULL;
-
- uuid_str = bt_name2string(pattern);
- if (!uuid_str)
- return btd_error_invalid_args(msg);
-
- err = register_proxy(adapter, uuid_str, address, &proxy);
- g_free(uuid_str);
-
- if (err == -EINVAL)
- return btd_error_invalid_args(msg);
- else if (err == -EALREADY)
- return btd_error_already_exists(msg);
- else if (err < 0)
- return btd_error_failed(msg, strerror(-err));
-
- proxy->owner = g_strdup(dbus_message_get_sender(msg));
- proxy->watch = g_dbus_add_disconnect_watch(conn, proxy->owner,
- watch_proxy,
- proxy, NULL);
-
- return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &proxy->path,
- DBUS_TYPE_INVALID);
-}
-
-static DBusMessage *list_proxies(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_adapter *adapter = data;
- const GSList *l;
- DBusMessage *reply;
- DBusMessageIter iter, iter_array;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply)
- return NULL;
-
- dbus_message_iter_init_append(reply, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_STRING_AS_STRING, &iter_array);
-
- for (l = adapter->proxies; l; l = l->next) {
- struct serial_proxy *prx = l->data;
-
- dbus_message_iter_append_basic(&iter_array,
- DBUS_TYPE_STRING, &prx->path);
- }
-
- dbus_message_iter_close_container(&iter, &iter_array);
-
- return reply;
-}
-
-static DBusMessage *remove_proxy(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- struct serial_adapter *adapter = data;
- struct serial_proxy *prx;
- const char *path, *sender;
- GSList *l;
-
- if (!dbus_message_get_args(msg, NULL,
- DBUS_TYPE_STRING, &path,
- DBUS_TYPE_INVALID))
- return NULL;
-
- l = g_slist_find_custom(adapter->proxies, path, proxy_pathcmp);
- if (!l)
- return btd_error_does_not_exist(msg);
-
- prx = l->data;
-
- sender = dbus_message_get_sender(msg);
- if (g_strcmp0(prx->owner, sender) != 0)
- return btd_error_not_authorized(msg);
-
- unregister_proxy(prx);
-
- return dbus_message_new_method_return(msg);
-}
-
-static void manager_path_unregister(void *data)
-{
- struct serial_adapter *adapter = data;
- GSList *l;
-
- /* Remove proxy objects */
- for (l = adapter->proxies; l; l = l->next) {
- struct serial_proxy *prx = l->data;
- char *path = g_strdup(prx->path);
-
- g_dbus_unregister_interface(adapter->conn, path,
- SERIAL_PROXY_INTERFACE);
- g_free(path);
- }
-
- if (adapter->conn)
- dbus_connection_unref(adapter->conn);
-
- adapters = g_slist_remove(adapters, adapter);
- g_slist_free(adapter->proxies);
- btd_adapter_unref(adapter->btd_adapter);
- g_free(adapter);
-}
-
-static const GDBusMethodTable manager_methods[] = {
- { GDBUS_METHOD("CreateProxy",
- GDBUS_ARGS({ "pattern", "s" },
- { "address", "s" }),
- GDBUS_ARGS({ "path", "s" }),
- create_proxy) },
- { GDBUS_METHOD("ListProxies",
- NULL, GDBUS_ARGS({ "paths", "as" }),
- list_proxies) },
- { GDBUS_METHOD("RemoveProxy",
- GDBUS_ARGS({ "path", "s" }), NULL,
- remove_proxy) },
- { },
-};
-
-static const GDBusSignalTable manager_signals[] = {
- { GDBUS_SIGNAL("ProxyCreated", GDBUS_ARGS({ "path", "s" })) },
- { GDBUS_SIGNAL("ProxyRemoved", GDBUS_ARGS({ "path", "s" })) },
- { }
-};
-
-static struct serial_adapter *find_adapter(GSList *list,
- struct btd_adapter *btd_adapter)
-{
- for (; list; list = list->next) {
- struct serial_adapter *adapter = list->data;
-
- if (adapter->btd_adapter == btd_adapter)
- return adapter;
- }
-
- return NULL;
-}
-
-static void serial_proxy_init(struct serial_adapter *adapter)
-{
- GKeyFile *config;
- GError *gerr = NULL;
- const char *file = CONFIGDIR "/serial.conf";
- char **group_list;
- int i;
-
- config = g_key_file_new();
-
- if (!g_key_file_load_from_file(config, file, 0, &gerr)) {
- error("Parsing %s failed: %s", file, gerr->message);
- g_error_free(gerr);
- g_key_file_free(config);
- return;
- }
-
- group_list = g_key_file_get_groups(config, NULL);
-
- for (i = 0; group_list[i] != NULL; i++) {
- char *group_str = group_list[i], *uuid_str, *address;
- int err;
- struct serial_proxy *prx;
-
- /* string length of "Proxy" is 5 */
- if (strlen(group_str) < 5 || strncmp(group_str, "Proxy", 5))
- continue;
-
- uuid_str = g_key_file_get_string(config, group_str, "UUID",
- &gerr);
- if (gerr) {
- DBG("%s: %s", file, gerr->message);
- g_error_free(gerr);
- g_key_file_free(config);
- g_strfreev(group_list);
- return;
- }
-
- address = g_key_file_get_string(config, group_str, "Address",
- &gerr);
- if (gerr) {
- DBG("%s: %s", file, gerr->message);
- g_error_free(gerr);
- g_key_file_free(config);
- g_free(uuid_str);
- g_strfreev(group_list);
- return;
- }
-
- err = register_proxy(adapter, uuid_str, address, &prx);
- if (err == -EINVAL)
- error("Invalid address.");
- else if (err == -EALREADY)
- DBG("Proxy already exists.");
- else if (err < 0)
- error("Proxy creation failed (%s)", strerror(-err));
- else {
- err = enable_proxy(prx);
- if (err < 0)
- error("Proxy enable failed (%s)",
- strerror(-err));
- }
-
- g_free(uuid_str);
- g_free(address);
- }
-
- g_strfreev(group_list);
- g_key_file_free(config);
-}
-
-int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter)
-{
- struct serial_adapter *adapter;
- const char *path;
-
- adapter = find_adapter(adapters, btd_adapter);
- if (adapter)
- return -EINVAL;
-
- adapter = g_new0(struct serial_adapter, 1);
- adapter->conn = dbus_connection_ref(conn);
- adapter->btd_adapter = btd_adapter_ref(btd_adapter);
-
- path = adapter_get_path(btd_adapter);
-
- if (!g_dbus_register_interface(conn, path,
- SERIAL_MANAGER_INTERFACE,
- manager_methods, manager_signals, NULL,
- adapter, manager_path_unregister)) {
- error("Failed to register %s interface to %s",
- SERIAL_MANAGER_INTERFACE, path);
- return -1;
- }
-
- adapters = g_slist_append(adapters, adapter);
-
- DBG("Registered interface %s on path %s",
- SERIAL_MANAGER_INTERFACE, path);
-
- serial_proxy_init(adapter);
-
- return 0;
-}
-
-void proxy_unregister(struct btd_adapter *btd_adapter)
-{
- struct serial_adapter *adapter;
-
- adapter = find_adapter(adapters, btd_adapter);
- if (!adapter)
- return;
-
- g_dbus_unregister_interface(adapter->conn,
- adapter_get_path(btd_adapter),
- SERIAL_MANAGER_INTERFACE);
-}
diff --git a/serial/proxy.h b/serial/proxy.h
deleted file mode 100644
index 7871665..0000000
--- a/serial/proxy.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2004-2010 Marcel Holtmann <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter);
-void proxy_unregister(struct btd_adapter *btd_adapter);
diff --git a/serial/serial.conf b/serial/serial.conf
deleted file mode 100644
index 43ee6af..0000000
--- a/serial/serial.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# Configuration file for serial
-
-# There could be multiple proxy sections, the format is [Proxy <user chosen name>]
-#[Proxy DUN]
-
-# UUID for DUN proxy service
-#UUID=00001103-0000-1000-8000-00805F9B34FB
-
-# Address for device node
-#Address=/dev/ttyx
--
1.7.10.2