1 /*
2 * Copyright (c) 2021 Xiaomi Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/byteorder.h>
9
10 #include <zephyr/net_buf.h>
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/hci.h>
13 #include <zephyr/bluetooth/uuid.h>
14 #include <zephyr/bluetooth/conn.h>
15 #include <zephyr/bluetooth/gatt.h>
16 #include <zephyr/bluetooth/mesh.h>
17
18 #include "mesh.h"
19 #include "net.h"
20 #include "rpl.h"
21 #include "transport.h"
22 #include "prov.h"
23 #include "pb_gatt.h"
24 #include "beacon.h"
25 #include "foundation.h"
26 #include "access.h"
27 #include "proxy.h"
28 #include "gatt_cli.h"
29 #include "proxy_msg.h"
30
31 #define LOG_LEVEL CONFIG_BT_MESH_PROV_LOG_LEVEL
32 #include <zephyr/logging/log.h>
33 LOG_MODULE_REGISTER(bt_mesh_pb_gatt_client);
34
35 static struct {
36 const uint8_t *target;
37 struct bt_mesh_proxy_role *srv;
38 } server;
39
pb_gatt_msg_recv(struct bt_mesh_proxy_role * role)40 static void pb_gatt_msg_recv(struct bt_mesh_proxy_role *role)
41 {
42 switch (role->msg_type) {
43 case BT_MESH_PROXY_PROV:
44 LOG_DBG("Mesh Provisioning PDU");
45 bt_mesh_pb_gatt_recv(role->conn, &role->buf);
46 break;
47 default:
48 LOG_WRN("Unhandled Message Type 0x%02x", role->msg_type);
49 break;
50 }
51 }
52
pb_gatt_connected(struct bt_conn * conn,void * user_data)53 static void pb_gatt_connected(struct bt_conn *conn, void *user_data)
54 {
55 server.srv = bt_mesh_proxy_role_setup(conn, bt_mesh_gatt_send,
56 pb_gatt_msg_recv);
57
58 server.target = NULL;
59
60 bt_mesh_pb_gatt_cli_start(conn);
61 }
62
pb_gatt_link_open(struct bt_conn * conn)63 static void pb_gatt_link_open(struct bt_conn *conn)
64 {
65 bt_mesh_pb_gatt_cli_open(conn);
66 }
67
pb_gatt_disconnected(struct bt_conn * conn)68 static void pb_gatt_disconnected(struct bt_conn *conn)
69 {
70 bt_mesh_pb_gatt_close(conn);
71
72 bt_mesh_proxy_role_cleanup(server.srv);
73
74 server.srv = NULL;
75 }
76
77 static const struct bt_mesh_gatt_cli pbgatt = {
78 .srv_uuid = BT_UUID_INIT_16(BT_UUID_MESH_PROV_VAL),
79 .data_in_uuid = BT_UUID_INIT_16(BT_UUID_MESH_PROV_DATA_IN_VAL),
80 .data_out_uuid = BT_UUID_INIT_16(BT_UUID_MESH_PROV_DATA_OUT_VAL),
81 .data_out_cccd_uuid = BT_UUID_INIT_16(BT_UUID_GATT_CCC_VAL),
82
83 .connected = pb_gatt_connected,
84 .link_open = pb_gatt_link_open,
85 .disconnected = pb_gatt_disconnected
86 };
87
bt_mesh_pb_gatt_cli_setup(const uint8_t uuid[16])88 int bt_mesh_pb_gatt_cli_setup(const uint8_t uuid[16])
89 {
90 if (server.srv) {
91 return -EBUSY;
92 }
93
94 server.target = uuid;
95
96 return 0;
97 }
98
bt_mesh_pb_gatt_cli_adv_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)99 void bt_mesh_pb_gatt_cli_adv_recv(const struct bt_le_scan_recv_info *info,
100 struct net_buf_simple *buf)
101 {
102 uint8_t *uuid;
103 bt_mesh_prov_oob_info_t oob_info;
104
105 if (server.srv) {
106 return;
107 }
108
109 if (buf->len != 18) {
110 return;
111 }
112
113 uuid = net_buf_simple_pull_mem(buf, 16);
114
115 if (server.target &&
116 !memcmp(server.target, uuid, 16)) {
117 (void)bt_mesh_gatt_cli_connect(info->addr, &pbgatt, NULL);
118 return;
119 }
120
121 if (!bt_mesh_prov->unprovisioned_beacon_gatt) {
122 return;
123 }
124
125 oob_info = (bt_mesh_prov_oob_info_t)net_buf_simple_pull_le16(buf);
126
127 bt_mesh_prov->unprovisioned_beacon_gatt(uuid, oob_info);
128 }
129