1 /******************************************************************************
2  *
3  *  Copyright 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /*****************************************************************************
20  *
21  *  This file contains main functions to support PAN profile
22  *  commands and events.
23  *
24  *****************************************************************************/
25 
26 #define LOG_TAG "pan"
27 
28 #include <bluetooth/log.h>
29 
30 #include <cstdint>
31 
32 #include "internal_include/bt_target.h"
33 #include "os/log.h"
34 #include "stack/include/bt_types.h"
35 #include "stack/include/bt_uuid16.h"
36 #include "stack/include/sdp_api.h"
37 #include "stack/include/sdpdefs.h"
38 #include "stack/pan/pan_int.h"
39 #include "types/raw_address.h"
40 
41 using namespace bluetooth;
42 using namespace bluetooth::legacy::stack::sdp;
43 
44 static const uint8_t pan_proto_elem_data[] = {
45     0x35, 0x18,       /* data element sequence of length 0x18 bytes */
46     0x35, 0x06,       /* data element sequence for L2CAP descriptor */
47     0x19, 0x01, 0x00, /* UUID for L2CAP - 0x0100 */
48     0x09, 0x00, 0x0F, /* PSM for BNEP - 0x000F */
49     0x35, 0x0E,       /* data element seqence for BNEP descriptor */
50     0x19, 0x00, 0x0F, /* UUID for BNEP - 0x000F */
51     0x09, 0x01,
52     0x00, /* BNEP specific parameter 0 -- Version of BNEP = version 1 = 0x0001
53            */
54     0x35,
55     0x06, /* BNEP specific parameter 1 -- Supported network packet type list */
56     0x09, 0x08, 0x00, /* network packet type IPv4 = 0x0800 */
57     0x09, 0x08, 0x06  /* network packet type ARP  = 0x0806 */
58 };
59 
60 /*******************************************************************************
61  *
62  * Function         pan_register_with_sdp
63  *
64  * Description
65  *
66  * Returns
67  *
68  ******************************************************************************/
pan_register_with_sdp(uint16_t uuid,const char * p_name,const char * p_desc)69 uint32_t pan_register_with_sdp(uint16_t uuid, const char* p_name,
70                                const char* p_desc) {
71   uint32_t sdp_handle;
72   uint16_t browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
73   uint16_t security = 0;
74   uint32_t proto_len = (uint32_t)pan_proto_elem_data[1];
75 
76   /* Create a record */
77   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
78 
79   if (sdp_handle == 0) {
80     log::error("PAN_SetRole - could not create SDP record");
81     return 0;
82   }
83 
84   /* Service Class ID List */
85   if (!get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(sdp_handle,
86                                                                     1, &uuid)) {
87     log::warn("Unable to add SDP class id list handle:{}", sdp_handle);
88   }
89 
90   /* Add protocol element sequence from the constant string */
91   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
92           sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST, DATA_ELE_SEQ_DESC_TYPE,
93           proto_len, (uint8_t*)(pan_proto_elem_data + 2))) {
94     log::warn("Unable to add SDP PAN profile attribute handle:{}", sdp_handle);
95   }
96 
97   /* Language base */
98   if (!get_legacy_stack_sdp_api()->handle.SDP_AddLanguageBaseAttrIDList(
99           sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8,
100           LANGUAGE_BASE_ID)) {
101     log::warn("Unable to add SDP language base attribute");
102   }
103 
104   /* Profile descriptor list */
105   if (!get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
106           sdp_handle, uuid, PAN_PROFILE_VERSION)) {
107     log::warn("Unable to add SDP PAN profile version");
108   }
109 
110   /* Service Name */
111   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
112           sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
113           (uint8_t)(strlen(p_name) + 1), (uint8_t*)p_name)) {
114     log::warn("Unable to add SDP service name attribute handle:{}", sdp_handle);
115   }
116 
117   /* Service description */
118   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
119           sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
120           (uint8_t)(strlen(p_desc) + 1), (uint8_t*)p_desc)) {
121     log::warn("Unable to add SDP service description attribute handle:{}",
122               sdp_handle);
123   }
124 
125   /* Security description */
126   // Only NAP and PANU has service level security; GN has no security
127   if (uuid == UUID_SERVCLASS_NAP || uuid == UUID_SERVCLASS_PANU) {
128     UINT16_TO_BE_FIELD(&security, 0x0001);
129   }
130   if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
131           sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2,
132           (uint8_t*)&security)) {
133     log::warn("Unable to add SDP security description attribute handle:{}",
134               sdp_handle);
135   }
136 
137   if (uuid == UUID_SERVCLASS_NAP) {
138     uint16_t NetAccessType = 0x0005;      /* Ethernet */
139     uint32_t NetAccessRate = 0x0001312D0; /* 10Mb/sec */
140     uint8_t array[10], *p;
141 
142     /* Net access type. */
143     p = array;
144     UINT16_TO_BE_STREAM(p, NetAccessType);
145     if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
146             sdp_handle, ATTR_ID_NET_ACCESS_TYPE, UINT_DESC_TYPE, 2, array)) {
147       log::warn("Unable to add SDP attribute net access type handle:{}",
148                 sdp_handle);
149     }
150 
151     /* Net access rate. */
152     p = array;
153     UINT32_TO_BE_STREAM(p, NetAccessRate);
154     if (!get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
155             sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4,
156             array)) {
157       log::warn("Unable to add SDP attribute net access rate handle:{}",
158                 sdp_handle);
159     }
160   }
161 
162   /* Make the service browsable */
163   if (!get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
164           sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_list)) {
165     log::warn("Unable to add SDP uuid sequence browse group list handle:{}",
166               sdp_handle);
167   }
168 
169   return sdp_handle;
170 }
171 
172 /*******************************************************************************
173  *
174  * Function         pan_allocate_pcb
175  *
176  * Description
177  *
178  * Returns
179  *
180  ******************************************************************************/
pan_allocate_pcb(const RawAddress & p_bda,uint16_t handle)181 tPAN_CONN* pan_allocate_pcb(const RawAddress& p_bda, uint16_t handle) {
182   uint16_t i;
183 
184   for (i = 0; i < MAX_PAN_CONNS; i++) {
185     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
186         pan_cb.pcb[i].handle == handle)
187       return NULL;
188   }
189 
190   for (i = 0; i < MAX_PAN_CONNS; i++) {
191     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
192         pan_cb.pcb[i].rem_bda == p_bda)
193       return NULL;
194   }
195 
196   for (i = 0; i < MAX_PAN_CONNS; i++) {
197     if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) {
198       memset(&(pan_cb.pcb[i]), 0, sizeof(tPAN_CONN));
199       pan_cb.pcb[i].rem_bda = p_bda;
200       pan_cb.pcb[i].handle = handle;
201       return &(pan_cb.pcb[i]);
202     }
203   }
204   return NULL;
205 }
206 
207 /*******************************************************************************
208  *
209  * Function         pan_get_pcb_by_handle
210  *
211  * Description
212  *
213  * Returns
214  *
215  ******************************************************************************/
pan_get_pcb_by_handle(uint16_t handle)216 tPAN_CONN* pan_get_pcb_by_handle(uint16_t handle) {
217   uint16_t i;
218 
219   for (i = 0; i < MAX_PAN_CONNS; i++) {
220     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
221         pan_cb.pcb[i].handle == handle)
222       return &(pan_cb.pcb[i]);
223   }
224 
225   return NULL;
226 }
227 
228 /*******************************************************************************
229  *
230  * Function         pan_get_pcb_by_addr
231  *
232  * Description
233  *
234  * Returns
235  *
236  ******************************************************************************/
pan_get_pcb_by_addr(const RawAddress & p_bda)237 tPAN_CONN* pan_get_pcb_by_addr(const RawAddress& p_bda) {
238   uint16_t i;
239 
240   for (i = 0; i < MAX_PAN_CONNS; i++) {
241     if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE) continue;
242 
243     if (pan_cb.pcb[i].rem_bda == p_bda) return &(pan_cb.pcb[i]);
244 
245     /*
246     if (pan_cb.pcb[i].mfilter_present &&
247         p_bda == pan_cb.pcb[i].multi_cast_bridge)
248         return &(pan_cb.pcb[i]);
249     */
250   }
251 
252   return NULL;
253 }
254 
255 /*******************************************************************************
256  *
257  * Function         pan_close_all_connections
258  *
259  * Description
260  *
261  * Returns          void
262  *
263  ******************************************************************************/
pan_close_all_connections(void)264 void pan_close_all_connections(void) {
265   uint16_t i;
266 
267   for (i = 0; i < MAX_PAN_CONNS; i++) {
268     if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE) {
269       BNEP_Disconnect(pan_cb.pcb[i].handle);
270       pan_cb.pcb[i].con_state = PAN_STATE_IDLE;
271     }
272   }
273 
274   pan_cb.active_role = PAN_ROLE_INACTIVE;
275   pan_cb.num_conns = 0;
276   return;
277 }
278 
279 /*******************************************************************************
280  *
281  * Function         pan_release_pcb
282  *
283  * Description      This function releases a PCB.
284  *
285  * Returns          void
286  *
287  ******************************************************************************/
pan_release_pcb(tPAN_CONN * p_pcb)288 void pan_release_pcb(tPAN_CONN* p_pcb) {
289   /* Drop any response pointer we may be holding */
290   memset(p_pcb, 0, sizeof(tPAN_CONN));
291   p_pcb->con_state = PAN_STATE_IDLE;
292 }
293 
294 /*******************************************************************************
295  *
296  * Function         pan_dump_status
297  *
298  * Description      This function dumps the pan control block and connection
299  *                  blocks information
300  *
301  * Returns          none
302  *
303  ******************************************************************************/
pan_dump_status(void)304 void pan_dump_status(void) {
305 #if (PAN_SUPPORTS_DEBUG_DUMP == TRUE)
306   uint16_t i;
307   tPAN_CONN* p_pcb;
308 
309   log::verbose("PAN role {:x}, active role {}, num_conns {}", pan_cb.role,
310                pan_cb.active_role, pan_cb.num_conns);
311 
312   for (i = 0, p_pcb = pan_cb.pcb; i < MAX_PAN_CONNS; i++, p_pcb++) {
313     log::verbose("{} state:{}, handle:{}, src{}, BD:{}", i, p_pcb->con_state,
314                  p_pcb->handle, p_pcb->src_uuid, p_pcb->rem_bda);
315   }
316 #endif
317 }
318