| /* |
| * |
| * BlueZ - Bluetooth protocol stack for Linux |
| * |
| * Copyright (C) 2011 Nokia Corporation |
| * Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org> |
| * |
| * |
| * 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 "log.h" |
| |
| #include "hcid.h" |
| #include "att.h" |
| #include "gattrib.h" |
| #include "attrib-server.h" |
| #include "reporter.h" |
| |
| #define IMMEDIATE_ALERT_SVC_UUID 0x1802 |
| #define LINK_LOSS_SVC_UUID 0x1803 |
| #define TX_POWER_SVC_UUID 0x1804 |
| #define ALERT_LEVEL_CHR_UUID 0x2A06 |
| #define POWER_LEVEL_CHR_UUID 0x2A07 |
| |
| enum { |
| NO_ALERT = 0x00, |
| MILD_ALERT = 0x01, |
| HIGH_ALERT = 0x02, |
| }; |
| |
| static uint16_t tx_power_handle; |
| |
| static void register_link_loss(void) |
| { |
| uint16_t start_handle, h; |
| const int svc_size = 3; |
| uint8_t atval[256]; |
| bt_uuid_t uuid; |
| |
| start_handle = attrib_db_find_avail(svc_size); |
| if (start_handle == 0) { |
| error("Not enough free handles to register service"); |
| return; |
| } |
| |
| DBG("start_handle=0x%04x", start_handle); |
| |
| h = start_handle; |
| |
| /* Primary service definition */ |
| bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); |
| att_put_u16(LINK_LOSS_SVC_UUID, &atval[0]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2); |
| |
| /* Alert level characteristic */ |
| bt_uuid16_create(&uuid, GATT_CHARAC_UUID); |
| atval[0] = ATT_CHAR_PROPER_READ | ATT_CHAR_PROPER_WRITE; |
| att_put_u16(h + 1, &atval[1]); |
| att_put_u16(ALERT_LEVEL_CHR_UUID, &atval[3]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5); |
| |
| /* Alert level value */ |
| bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID); |
| att_put_u8(NO_ALERT, &atval[0]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NONE, atval, 1); |
| |
| g_assert(h - start_handle == svc_size); |
| } |
| |
| static void register_tx_power(void) |
| { |
| uint16_t start_handle, h; |
| const int svc_size = 4; |
| uint8_t atval[256]; |
| bt_uuid_t uuid; |
| |
| start_handle = attrib_db_find_avail(svc_size); |
| if (start_handle == 0) { |
| error("Not enough free handles to register service"); |
| return; |
| } |
| |
| DBG("start_handle=0x%04x", start_handle); |
| |
| h = start_handle; |
| |
| /* Primary service definition */ |
| bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); |
| att_put_u16(TX_POWER_SVC_UUID, &atval[0]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2); |
| |
| /* Power level characteristic */ |
| bt_uuid16_create(&uuid, GATT_CHARAC_UUID); |
| atval[0] = ATT_CHAR_PROPER_READ | ATT_CHAR_PROPER_NOTIFY; |
| att_put_u16(h + 1, &atval[1]); |
| att_put_u16(POWER_LEVEL_CHR_UUID, &atval[3]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5); |
| |
| /* Power level value */ |
| bt_uuid16_create(&uuid, POWER_LEVEL_CHR_UUID); |
| att_put_u8(0x00, &atval[0]); |
| tx_power_handle = h; |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1); |
| |
| /* Client characteristic configuration */ |
| bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID); |
| atval[0] = 0x00; |
| atval[1] = 0x00; |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NONE, atval, 2); |
| |
| g_assert(h - start_handle == svc_size); |
| } |
| |
| static void register_immediate_alert(void) |
| { |
| uint16_t start_handle, h; |
| const int svc_size = 3; |
| uint8_t atval[256]; |
| bt_uuid_t uuid; |
| |
| start_handle = attrib_db_find_avail(svc_size); |
| if (start_handle == 0) { |
| error("Not enough free handles to register service"); |
| return; |
| } |
| |
| DBG("start_handle=0x%04x", start_handle); |
| |
| h = start_handle; |
| |
| /* Primary service definition */ |
| bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID); |
| att_put_u16(IMMEDIATE_ALERT_SVC_UUID, &atval[0]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2); |
| |
| /* Alert level characteristic */ |
| bt_uuid16_create(&uuid, GATT_CHARAC_UUID); |
| atval[0] = ATT_CHAR_PROPER_READ | ATT_CHAR_PROPER_WRITE; |
| att_put_u16(h + 1, &atval[1]); |
| att_put_u16(ALERT_LEVEL_CHR_UUID, &atval[3]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5); |
| |
| /* Alert level value */ |
| bt_uuid16_create(&uuid, ALERT_LEVEL_CHR_UUID); |
| att_put_u8(NO_ALERT, &atval[0]); |
| attrib_db_add(h++, &uuid, ATT_NONE, ATT_NONE, atval, 1); |
| |
| g_assert(h - start_handle == svc_size); |
| } |
| |
| int reporter_init(void) |
| { |
| if (!main_opts.attrib_server) { |
| DBG("Attribute server is disabled"); |
| return -1; |
| } |
| |
| DBG("Proximity Reporter"); |
| |
| register_link_loss(); |
| register_tx_power(); |
| register_immediate_alert(); |
| |
| return 0; |
| } |
| |
| void reporter_exit(void) |
| { |
| } |