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 	bool target_set;
37 	uint8_t target_uuid[16];
38 	struct bt_mesh_proxy_role *srv;
39 } server;
40 
pb_gatt_msg_recv(struct bt_mesh_proxy_role * role)41 static void pb_gatt_msg_recv(struct bt_mesh_proxy_role *role)
42 {
43 	switch (role->msg_type) {
44 	case BT_MESH_PROXY_PROV:
45 		LOG_DBG("Mesh Provisioning PDU");
46 		bt_mesh_pb_gatt_recv(role->conn, &role->buf);
47 		break;
48 	default:
49 		LOG_WRN("Unhandled Message Type 0x%02x", role->msg_type);
50 		break;
51 	}
52 }
53 
pb_gatt_connected(struct bt_conn * conn,void * user_data)54 static void pb_gatt_connected(struct bt_conn *conn, void *user_data)
55 {
56 	server.srv = bt_mesh_proxy_role_setup(conn, bt_mesh_gatt_send,
57 					      pb_gatt_msg_recv);
58 
59 	server.target_set = false;
60 
61 	bt_mesh_pb_gatt_cli_start(conn);
62 }
63 
pb_gatt_link_open(struct bt_conn * conn)64 static void pb_gatt_link_open(struct bt_conn *conn)
65 {
66 	bt_mesh_pb_gatt_cli_open(conn);
67 }
68 
pb_gatt_disconnected(struct bt_conn * conn)69 static void pb_gatt_disconnected(struct bt_conn *conn)
70 {
71 	bt_mesh_pb_gatt_close(conn);
72 
73 	bt_mesh_proxy_role_cleanup(server.srv);
74 
75 	server.srv = NULL;
76 }
77 
78 static const struct bt_mesh_gatt_cli pbgatt = {
79 	.srv_uuid		= BT_UUID_INIT_16(BT_UUID_MESH_PROV_VAL),
80 	.data_in_uuid		= BT_UUID_INIT_16(BT_UUID_MESH_PROV_DATA_IN_VAL),
81 	.data_out_uuid		= BT_UUID_INIT_16(BT_UUID_MESH_PROV_DATA_OUT_VAL),
82 	.data_out_cccd_uuid	= BT_UUID_INIT_16(BT_UUID_GATT_CCC_VAL),
83 
84 	.connected		= pb_gatt_connected,
85 	.link_open		= pb_gatt_link_open,
86 	.disconnected		= pb_gatt_disconnected
87 };
88 
bt_mesh_pb_gatt_cli_setup(const uint8_t uuid[16])89 int bt_mesh_pb_gatt_cli_setup(const uint8_t uuid[16])
90 {
91 	if (server.srv) {
92 		return -EBUSY;
93 	}
94 
95 	memcpy(server.target_uuid, uuid, 16);
96 	server.target_set = true;
97 	return 0;
98 }
99 
bt_mesh_pb_gatt_cli_adv_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)100 void bt_mesh_pb_gatt_cli_adv_recv(const struct bt_le_scan_recv_info *info,
101 				  struct net_buf_simple *buf)
102 {
103 	uint8_t *uuid;
104 	bt_mesh_prov_oob_info_t oob_info;
105 
106 	if (server.srv) {
107 		return;
108 	}
109 
110 	if (buf->len != 18) {
111 		return;
112 	}
113 
114 	uuid = net_buf_simple_pull_mem(buf, 16);
115 
116 	if (server.target_set &&
117 	    !memcmp(server.target_uuid, uuid, 16)) {
118 		(void)bt_mesh_gatt_cli_connect(info->addr, &pbgatt, NULL);
119 		return;
120 	}
121 
122 	if (!bt_mesh_prov->unprovisioned_beacon_gatt) {
123 		return;
124 	}
125 
126 	oob_info = (bt_mesh_prov_oob_info_t)net_buf_simple_pull_le16(buf);
127 
128 	bt_mesh_prov->unprovisioned_beacon_gatt(uuid, oob_info);
129 }
130