blob: b0e5b87a2d3c52ea7981bda43fef16f877999bfa [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2008-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 the GATT server functions
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080026#include "bt_utils.h"
Myles Watsond7ffd642016-10-27 10:27:36 -070027#include "osi/include/osi.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080028
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include <string.h>
30#include "gatt_int.h"
31#include "l2c_api.h"
Priti Aghera636d6712014-12-18 13:55:48 -080032#include "l2c_int.h"
Andre Eisenbachccf9c152013-10-02 15:37:21 -070033#define GATT_MTU_REQ_MIN_LEN 2
34
The Android Open Source Project5738f832012-12-12 16:00:35 -080035
36/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080037 *
38 * Function gatt_sr_enqueue_cmd
39 *
40 * Description This function enqueue the request from client which needs a
41 * application response, and update the transaction ID.
42 *
43 * Returns void
44 *
45 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070046uint32_t gatt_sr_enqueue_cmd (tGATT_TCB *p_tcb, uint8_t op_code, uint16_t handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -080047{
48 tGATT_SR_CMD *p_cmd = &p_tcb->sr_cmd;
Marie Janssend19e0782016-07-15 12:48:27 -070049 uint32_t trans_id = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
51 if ( (p_cmd->op_code == 0) ||
52 (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */
53 {
54 if (op_code == GATT_CMD_WRITE ||
55 op_code == GATT_SIGN_CMD_WRITE ||
56 op_code == GATT_REQ_MTU ||
57 op_code == GATT_HANDLE_VALUE_CONF)
58 {
59 trans_id = ++p_tcb->trans_id;
60 }
61 else
62 {
63 p_cmd->trans_id = ++p_tcb->trans_id;
64 p_cmd->op_code = op_code;
65 p_cmd->handle = handle;
66 p_cmd->status = GATT_NOT_FOUND;
67 p_tcb->trans_id %= GATT_TRANS_ID_MAX;
68 trans_id = p_cmd->trans_id;
69 }
70 }
71
72 return trans_id;
73}
74
75/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080076 *
77 * Function gatt_sr_cmd_empty
78 *
Myles Watson9ca07092016-11-28 16:41:53 -080079 * Description This function checks if the server command queue is empty.
Myles Watsonee96a3c2016-11-23 14:49:54 -080080 *
81 * Returns true if empty, false if there is pending command.
82 *
83 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070084bool gatt_sr_cmd_empty (tGATT_TCB *p_tcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -080085{
86 return(p_tcb->sr_cmd.op_code == 0);
87}
88
89/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080090 *
91 * Function gatt_dequeue_sr_cmd
92 *
93 * Description This function dequeue the request from command queue.
94 *
95 * Returns void
96 *
97 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080098void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb)
99{
100 /* Double check in case any buffers are queued */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700101 GATT_TRACE_DEBUG("gatt_dequeue_sr_cmd" );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102 if (p_tcb->sr_cmd.p_rsp_msg)
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700103 GATT_TRACE_ERROR("free p_tcb->sr_cmd.p_rsp_msg = %d", p_tcb->sr_cmd.p_rsp_msg);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800104 osi_free_and_reset((void **)&p_tcb->sr_cmd.p_rsp_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800105
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700106 while (!fixed_queue_is_empty(p_tcb->sr_cmd.multi_rsp_q))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800107 osi_free(fixed_queue_try_dequeue(p_tcb->sr_cmd.multi_rsp_q));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700108 fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800109 memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
110}
111
112/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800113 *
114 * Function process_read_multi_rsp
115 *
116 * Description This function check the read multiple response.
117 *
118 * Returns bool if all replies have been received
119 *
120 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700121static bool process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
122 tGATTS_RSP *p_msg, uint16_t mtu)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800123{
Marie Janssend19e0782016-07-15 12:48:27 -0700124 uint16_t ii, total_len, len;
125 uint8_t *p;
126 bool is_overflow = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800127
Subramanian Srinivasan089cd112016-05-16 11:14:03 -0700128 GATT_TRACE_DEBUG ("%s status=%d mtu=%d", __func__, status, mtu);
129
130 if (p_cmd->multi_rsp_q == NULL)
131 p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800132
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133 /* Enqueue the response */
Subramanian Srinivasan089cd112016-05-16 11:14:03 -0700134 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800135 memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700136 fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800137
138 p_cmd->status = status;
139 if (status == GATT_SUCCESS)
140 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700141 GATT_TRACE_DEBUG("Multi read count=%d num_hdls=%d",
Pavlin Radoslavov43947202016-02-13 08:47:19 -0800142 fixed_queue_length(p_cmd->multi_rsp_q),
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700143 p_cmd->multi_req.num_handles);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800144 /* Wait till we get all the responses */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700145 if (fixed_queue_length(p_cmd->multi_rsp_q) == p_cmd->multi_req.num_handles)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 {
147 len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800148 p_buf = (BT_HDR *)osi_calloc(len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800149 p_buf->offset = L2CAP_MIN_OFFSET;
Marie Janssend19e0782016-07-15 12:48:27 -0700150 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800151
152 /* First byte in the response is the opcode */
153 *p++ = GATT_RSP_READ_MULTI;
154 p_buf->len = 1;
155
156 /* Now walk through the buffers puting the data into the response in order */
Pavlin Radoslavov577862e2015-10-07 18:07:48 -0700157 list_t *list = NULL;
158 const list_node_t *node = NULL;
159 if (! fixed_queue_is_empty(p_cmd->multi_rsp_q))
160 list = fixed_queue_get_list(p_cmd->multi_rsp_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800161 for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++)
162 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700163 tGATTS_RSP *p_rsp = NULL;
164
Pavlin Radoslavov577862e2015-10-07 18:07:48 -0700165 if (list != NULL) {
166 if (ii == 0)
167 node = list_begin(list);
168 else
169 node = list_next(node);
170 if (node != list_end(list))
171 p_rsp = (tGATTS_RSP *)list_node(node);
172 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800173
174 if (p_rsp != NULL)
175 {
176
177 total_len = (p_buf->len + p_rsp->attr_value.len);
178
179 if (total_len > mtu)
180 {
181 /* just send the partial response for the overflow case */
182 len = p_rsp->attr_value.len - (total_len - mtu);
Marie Janssend19e0782016-07-15 12:48:27 -0700183 is_overflow = true;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700184 GATT_TRACE_DEBUG ("multi read overflow available len=%d val_len=%d", len, p_rsp->attr_value.len );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185 }
186 else
187 {
188 len = p_rsp->attr_value.len;
189 }
190
191 if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii])
192 {
193 memcpy (p, p_rsp->attr_value.value, len);
194 if (!is_overflow)
195 p += len;
196 p_buf->len += len;
197 }
198 else
199 {
200 p_cmd->status = GATT_NOT_FOUND;
201 break;
202 }
203
204 if (is_overflow)
205 break;
206
207 }
208 else
209 {
210 p_cmd->status = GATT_NOT_FOUND;
211 break;
212 }
213
214 } /* loop through all handles*/
215
216
217 /* Sanity check on the buffer length */
218 if (p_buf->len == 0)
219 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700220 GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800221 p_cmd->status = GATT_NOT_FOUND;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800222 osi_free(p_buf);
223 GATT_TRACE_DEBUG("osi_free(p_buf)");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800224 }
225 else if (p_cmd->p_rsp_msg != NULL)
226 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800227 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800228 }
229 else
230 {
231 p_cmd->p_rsp_msg = p_buf;
232 }
233
Marie Janssend19e0782016-07-15 12:48:27 -0700234 return(true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800235 }
236 }
237 else /* any handle read exception occurs, return error */
238 {
Marie Janssend19e0782016-07-15 12:48:27 -0700239 return(true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240 }
241
242 /* If here, still waiting */
Marie Janssend19e0782016-07-15 12:48:27 -0700243 return(false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800244}
245
246/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800247 *
248 * Function gatt_sr_process_app_rsp
249 *
Myles Watson9ca07092016-11-28 16:41:53 -0800250 * Description This function checks whether the response message from
251 * application matches any pending request.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800252 *
253 * Returns void
254 *
255 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800256tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
Myles Watsond35a6482016-10-27 08:52:16 -0700257 UNUSED_ATTR uint32_t trans_id, uint8_t op_code,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800258 tGATT_STATUS status, tGATTS_RSP *p_msg)
259{
260 tGATT_STATUS ret_code = GATT_SUCCESS;
261
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700262 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800263
Marie Janssend19e0782016-07-15 12:48:27 -0700264 gatt_sr_update_cback_cnt(p_tcb, gatt_if, false, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800265
266 if (op_code == GATT_REQ_READ_MULTI)
267 {
268 /* If no error and still waiting, just return */
269 if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size))
270 return(GATT_SUCCESS);
271 }
272 else
273 {
274 if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS)
Marie Janssend19e0782016-07-15 12:48:27 -0700275 gatt_sr_update_prep_cnt(p_tcb, gatt_if, true, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800276
277 if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS)
278 gatt_sr_reset_cback_cnt(p_tcb);
279
280 p_tcb->sr_cmd.status = status;
281
282 if (gatt_sr_is_cback_cnt_zero(p_tcb)
283 && status == GATT_SUCCESS)
284 {
285 if (p_tcb->sr_cmd.p_rsp_msg == NULL)
286 {
Marie Janssend19e0782016-07-15 12:48:27 -0700287 p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (uint8_t)(op_code + 1), (tGATT_SR_MSG *)p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800288 }
289 else
290 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700291 GATT_TRACE_ERROR("Exception!!! already has respond message");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800292 }
293 }
294 }
295 if (gatt_sr_is_cback_cnt_zero(p_tcb))
296 {
297 if ( (p_tcb->sr_cmd.status == GATT_SUCCESS) && (p_tcb->sr_cmd.p_rsp_msg) )
298 {
299 ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg);
300 p_tcb->sr_cmd.p_rsp_msg = NULL;
301 }
302 else
303 {
Marie Janssend19e0782016-07-15 12:48:27 -0700304 ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800305 }
306
307 gatt_dequeue_sr_cmd(p_tcb);
308 }
309
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700310 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800311
312 return ret_code;
313}
314
315/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800316 *
317 * Function gatt_process_exec_write_req
318 *
319 * Description This function is called to process the execute write request
320 * from client.
321 *
322 * Returns void
323 *
324 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700325void gatt_process_exec_write_req (tGATT_TCB *p_tcb, uint8_t op_code,
326 UNUSED_ATTR uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800327{
Marie Janssend19e0782016-07-15 12:48:27 -0700328 uint8_t *p = p_data, flag, i = 0;
329 uint32_t trans_id = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800330 tGATT_IF gatt_if;
Marie Janssend19e0782016-07-15 12:48:27 -0700331 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800332
Marie Janssend19e0782016-07-15 12:48:27 -0700333#if (GATT_CONFORMANCE_TESTING == TRUE)
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800334 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
335 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700336 GATT_TRACE_DEBUG("Conformance tst: forced err rspv for Execute Write: error status=%d",
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700337 gatt_cb.err_status);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800338
Marie Janssend19e0782016-07-15 12:48:27 -0700339 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, false);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800340
341 return;
342 }
343#endif
344
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345 STREAM_TO_UINT8(flag, p);
346
347 /* mask the flag */
348 flag &= GATT_PREP_WRITE_EXEC;
349
350
351 /* no prep write is queued */
352 if (!gatt_sr_is_prep_cnt_zero(p_tcb))
353 {
354 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
355 gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
356
357 for (i=0; i<GATT_MAX_APPS; i++)
358 {
359 if (p_tcb->prep_cnt[i])
360 {
361 gatt_if = (tGATT_IF) (i+1);
362 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
363 gatt_sr_send_req_callback(conn_id,
364 trans_id,
365 GATTS_REQ_TYPE_WRITE_EXEC,
366 (tGATTS_DATA *)&flag);
367 p_tcb->prep_cnt[i]= 0;
368 }
369 }
370 }
371 else /* nothing needs to be executed , send response now */
372 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700373 GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
Marie Janssend19e0782016-07-15 12:48:27 -0700374 gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800375 }
376}
377
378/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800379 *
380 * Function gatt_process_read_multi_req
381 *
382 * Description This function is called to process the read multiple request
383 * from client.
384 *
385 * Returns void
386 *
387 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700388void gatt_process_read_multi_req (tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800389{
Marie Janssend19e0782016-07-15 12:48:27 -0700390 uint32_t trans_id;
391 uint16_t handle = 0, ll = len;
392 uint8_t *p = p_data, i_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393 tGATT_STATUS err = GATT_SUCCESS;
Marie Janssend19e0782016-07-15 12:48:27 -0700394 uint8_t sec_flag, key_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700396 GATT_TRACE_DEBUG("gatt_process_read_multi_req" );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800397 p_tcb->sr_cmd.multi_req.num_handles = 0;
398
399 gatt_sr_get_sec_info(p_tcb->peer_bda,
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700400 p_tcb->transport,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800401 &sec_flag,
402 &key_size);
403
Marie Janssend19e0782016-07-15 12:48:27 -0700404#if (GATT_CONFORMANCE_TESTING == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800405 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
406 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700407 GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800408
409 STREAM_TO_UINT16(handle, p);
410
Marie Janssend19e0782016-07-15 12:48:27 -0700411 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800412
413 return;
414 }
415#endif
416
417 while (ll >= 2 && p_tcb->sr_cmd.multi_req.num_handles < GATT_MAX_READ_MULTI_HANDLES)
418 {
419 STREAM_TO_UINT16(handle, p);
420
Marie Janssenf33b6f42016-11-22 15:01:42 -0800421 i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
422 if (i_rcb < GATT_MAX_SR_PROFILES)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800423 {
424 p_tcb->sr_cmd.multi_req.handles[p_tcb->sr_cmd.multi_req.num_handles++] = handle;
425
426 /* check read permission */
Marie Janssenf33b6f42016-11-22 15:01:42 -0800427 err = gatts_read_attr_perm_check(gatt_cb.sr_reg[i_rcb].p_db,
428 false, handle, sec_flag, key_size);
429 if (err != GATT_SUCCESS)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800430 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700431 GATT_TRACE_DEBUG("read permission denied : 0x%02x", err);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800432 break;
433 }
434 }
435 else
436 {
437 /* invalid handle */
438 err = GATT_INVALID_HANDLE;
439 break;
440 }
441 ll -= 2;
442 }
443
444 if (ll != 0)
445 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700446 GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request.");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800447 }
448
449 if (p_tcb->sr_cmd.multi_req.num_handles == 0)
450 err = GATT_INVALID_HANDLE;
451
452 if (err == GATT_SUCCESS)
453 {
Marie Janssenf33b6f42016-11-22 15:01:42 -0800454 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0]);
455 if (trans_id != 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800456 {
457 gatt_sr_reset_cback_cnt(p_tcb); /* read multiple use multi_rsp_q's count*/
458
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800459 for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++) {
460 tGATTS_RSP *p_msg = (tGATTS_RSP *)osi_calloc(sizeof(tGATTS_RSP));
461 handle = p_tcb->sr_cmd.multi_req.handles[ll];
462 i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800463
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800464 p_msg->attr_value.handle = handle;
465 err = gatts_read_attr_value_by_handle(p_tcb,
466 gatt_cb.sr_reg[i_rcb].p_db,
467 op_code,
468 handle,
469 0,
470 p_msg->attr_value.value,
471 &p_msg->attr_value.len,
472 GATT_MAX_ATTR_LEN,
473 sec_flag,
474 key_size,
475 trans_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800476
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800477 if (err == GATT_SUCCESS) {
478 gatt_sr_process_app_rsp(p_tcb, gatt_cb.sr_reg[i_rcb].gatt_if ,trans_id, op_code, GATT_SUCCESS, p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800479 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800480 /* either not using or done using the buffer, release it now */
481 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800482 }
483 }
484 else
485 err = GATT_NO_RESOURCES;
486 }
487
488 /* in theroy BUSY is not possible(should already been checked), protected check */
489 if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -0700490 gatt_send_error_rsp(p_tcb, err, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800491}
492
493/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800494 *
495 * Function gatt_build_primary_service_rsp
496 *
497 * Description Primamry service request processed internally. Theretically
498 * only deal with ReadByTypeVAlue and ReadByGroupType.
499 *
500 * Returns void
501 *
502 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800503static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb,
Marie Janssend19e0782016-07-15 12:48:27 -0700504 uint8_t op_code, uint16_t s_hdl,
Myles Watsond35a6482016-10-27 08:52:16 -0700505 uint16_t e_hdl,
506 UNUSED_ATTR uint8_t *p_data, tBT_UUID value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800507{
508 tGATT_STATUS status = GATT_NOT_FOUND;
Marie Janssend19e0782016-07-15 12:48:27 -0700509 uint8_t handle_len =4, *p ;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510 tGATT_SR_REG *p_rcb;
511 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
512 tGATT_SRV_LIST_ELEM *p_srv=NULL;
513 tBT_UUID *p_uuid;
514
Marie Janssend19e0782016-07-15 12:48:27 -0700515 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800516
517 p_srv = p_list->p_first;
518
519 while (p_srv)
520 {
521 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
522
523 if (p_rcb->in_use &&
524 p_rcb->s_hdl >= s_hdl &&
525 p_rcb->s_hdl <= e_hdl &&
526 p_rcb->type == GATT_UUID_PRI_SERVICE)
527 {
Marie Janssenf33b6f42016-11-22 15:01:42 -0800528 p_uuid = gatts_get_service_uuid(p_rcb->p_db);
529 if (p_uuid != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800530 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800531 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700532 handle_len = 4 + p_uuid->len;
533
534 /* get the length byte in the repsonse */
535 if (p_msg->offset ==0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800536 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700537 *p ++ = op_code + 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800538 p_msg->len ++;
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700539 p_msg->offset = handle_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800540
541 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700542 {
Marie Janssend19e0782016-07-15 12:48:27 -0700543 *p ++ = (uint8_t)p_msg->offset; /* length byte */
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700544 p_msg->len ++;
545 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800546 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700547
548 if (p_msg->len + p_msg->offset <= p_tcb->payload_size &&
549 handle_len == p_msg->offset)
550 {
551 if (op_code != GATT_REQ_FIND_TYPE_VALUE ||
552 gatt_uuid_compare(value, *p_uuid))
553 {
554 UINT16_TO_STREAM(p, p_rcb->s_hdl);
555
556 if (p_list->p_last_primary == p_srv &&
557 p_list->p_last_primary == p_list->p_last)
558 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700559 GATT_TRACE_DEBUG("Use 0xFFFF for the last primary attribute");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700560 UINT16_TO_STREAM(p, 0xFFFF); /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
561 }
562 else
563 {
564 UINT16_TO_STREAM(p, p_rcb->e_hdl);
565 }
566
567 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
568 gatt_build_uuid_to_stream(&p, *p_uuid);
569
570 status = GATT_SUCCESS;
571 p_msg->len += p_msg->offset;
572 }
573 }
574 else
575 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577 }
578 p_srv = p_srv->p_next;
579 }
580 p_msg->offset = L2CAP_MIN_OFFSET;
581
582 return status;
583}
584
585/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800586 *
587 * Function gatt_build_find_info_rsp
588 *
589 * Description fill the find information response information in the given
590 * buffer.
591 *
592 * Returns true: if data filled sucessfully.
593 * false: packet full, or format mismatch.
594 *
595 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700596static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, uint16_t *p_len,
597 uint16_t s_hdl, uint16_t e_hdl)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800598{
599 tGATT_STATUS status = GATT_NOT_FOUND;
Marie Janssend19e0782016-07-15 12:48:27 -0700600 uint8_t *p;
601 uint16_t len = *p_len;
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700602 tGATT_ATTR *p_attr = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700603 uint8_t info_pair_len[2] = {4, 18};
The Android Open Source Project5738f832012-12-12 16:00:35 -0800604
605 if (!p_rcb->p_db || !p_rcb->p_db->p_attr_list)
606 return status;
607
608 /* check the attribute database */
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700609 p_attr = (tGATT_ATTR *) p_rcb->p_db->p_attr_list;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800610
Marie Janssend19e0782016-07-15 12:48:27 -0700611 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET + p_msg->len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800612
613 while (p_attr)
614 {
615 if (p_attr->handle > e_hdl)
616 {
617 break;
618 }
619
620 if (p_attr->handle >= s_hdl)
621 {
622 if (p_msg->offset == 0)
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700623 p_msg->offset = (p_attr->uuid.len == LEN_UUID_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800624
625 if (len >= info_pair_len[p_msg->offset - 1])
626 {
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700627 if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 && p_attr->uuid.len == LEN_UUID_16)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800628 {
629 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700630 UINT16_TO_STREAM(p, p_attr->uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800631 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700632 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid.len == LEN_UUID_128 )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800633 {
634 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700635 ARRAY_TO_STREAM (p, p_attr->uuid.uu.uuid128, LEN_UUID_128);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800636 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700637 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid.len == LEN_UUID_32)
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700638 {
639 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700640 gatt_convert_uuid32_to_uuid128(p, p_attr->uuid.uu.uuid32);
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700641 p += LEN_UUID_128;
642 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800643 else
644 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700645 GATT_TRACE_ERROR("format mismatch");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800646 status = GATT_NO_RESOURCES;
647 break;
648 /* format mismatch */
649 }
650 p_msg->len += info_pair_len[p_msg->offset - 1];
651 len -= info_pair_len[p_msg->offset - 1];
652 status = GATT_SUCCESS;
653
654 }
655 else
656 {
657 status = GATT_NO_RESOURCES;
658 break;
659 }
660 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700661 p_attr = (tGATT_ATTR *)p_attr->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800662 }
663
664 *p_len = len;
665 return status;
666}
667
668/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800669 *
670 * Function gatts_internal_read_by_type_req
671 *
Myles Watson9ca07092016-11-28 16:41:53 -0800672 * Description Check to see if the ReadByType request can be handled
673 * internally.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800674 *
675 * Returns void
676 *
677 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700678static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t *p_len,
679 uint8_t **p_data, tBT_UUID *p_uuid_filter,
680 uint16_t *p_s_hdl, uint16_t *p_e_hdl)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800681{
682 tGATT_STATUS reason = GATT_SUCCESS;
Marie Janssend19e0782016-07-15 12:48:27 -0700683 uint16_t uuid_len, s_hdl = 0, e_hdl = 0;
684 uint16_t len = *p_len;
685 uint8_t *p = *p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800686
687 if (len >= 4)
688 {
689 /* obtain starting handle, and ending handle */
690 STREAM_TO_UINT16(s_hdl, p);
691 STREAM_TO_UINT16(e_hdl, p);
692 len -= 4;
693
694 if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl))
695 {
696 reason = GATT_INVALID_HANDLE;
697 }
698 /* for these PDUs, uuid filter must present */
699 else if (op_code == GATT_REQ_READ_BY_GRP_TYPE ||
700 op_code == GATT_REQ_FIND_TYPE_VALUE ||
701 op_code == GATT_REQ_READ_BY_TYPE)
702 {
703 if (len >= 2 && p_uuid_filter != NULL)
704 {
705 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len;
706
707 /* parse uuid now */
Marie Janssend19e0782016-07-15 12:48:27 -0700708 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == false ||
The Android Open Source Project5738f832012-12-12 16:00:35 -0800709 p_uuid_filter->len == 0)
710 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700711 GATT_TRACE_DEBUG("UUID filter does not exsit");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800712 reason = GATT_INVALID_PDU;
713 }
714 else
715 len -= p_uuid_filter->len;
716 }
717 else
718 reason = GATT_INVALID_PDU;
719 }
720 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700721 else
722 reason = GATT_INVALID_PDU;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800723
724 *p_data = p;
725 *p_len = len;
726 *p_s_hdl = s_hdl;
727 *p_e_hdl = e_hdl;
728
729 return reason;
730}
731
732/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800733 *
734 * Function gatts_process_primary_service_req
735 *
Myles Watson9ca07092016-11-28 16:41:53 -0800736 * Description Process ReadByGroupType/ReadByTypeValue request, for
737 * discovering all primary services or discover primary service
738 * by UUID request.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800739 *
740 * Returns void
741 *
742 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700743void gatts_process_primary_service_req(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800744{
Marie Janssend19e0782016-07-15 12:48:27 -0700745 uint8_t reason = GATT_INVALID_PDU;
746 uint16_t s_hdl = 0, e_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800747 tBT_UUID uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
748 BT_HDR *p_msg = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700749 uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800750
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700751 memset (&value, 0, sizeof(tBT_UUID));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800752 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
753
754 if (reason == GATT_SUCCESS)
755 {
756 if (gatt_uuid_compare(uuid, primary_service))
757 {
758 if (op_code == GATT_REQ_FIND_TYPE_VALUE)
759 {
Marie Janssend19e0782016-07-15 12:48:27 -0700760 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800761 reason = GATT_INVALID_PDU;
762 }
763
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800764 if (reason == GATT_SUCCESS) {
765 p_msg = (BT_HDR *)osi_calloc(msg_len);
766 reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code,
767 s_hdl, e_hdl, p_data,
768 value);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800769 }
770 }
771 else
772 {
773 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
774 {
775 reason = GATT_UNSUPPORT_GRP_TYPE;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700776 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800777 }
778 else
779 {
780 /* we do not support ReadByTypeValue with any non-primamry_service type */
781 reason = GATT_NOT_FOUND;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700782 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800783 }
784 }
785 }
786
787 if (reason != GATT_SUCCESS)
788 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800789 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700790 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800791 }
792 else
793 attp_send_sr_msg(p_tcb, p_msg);
794
795}
796
797/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800798 *
799 * Function gatts_process_find_info
800 *
801 * Description process find information request, for discover character
802 * descriptors.
803 *
804 * Returns void
805 *
806 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700807static void gatts_process_find_info(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800808{
Marie Janssend19e0782016-07-15 12:48:27 -0700809 uint8_t reason = GATT_INVALID_PDU, *p;
810 uint16_t s_hdl = 0, e_hdl = 0, buf_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800811 BT_HDR *p_msg = NULL;
812 tGATT_SR_REG *p_rcb;
813 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
814 tGATT_SRV_LIST_ELEM *p_srv=NULL;
815
816 reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl);
817
818 if (reason == GATT_SUCCESS)
819 {
Marie Janssend19e0782016-07-15 12:48:27 -0700820 buf_len = (uint16_t)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800821
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800822 p_msg = (BT_HDR *)osi_calloc(buf_len);
823 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800824
Marie Janssend19e0782016-07-15 12:48:27 -0700825 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800826 *p ++ = op_code + 1;
827 p_msg->len = 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800829 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800830
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800831 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800832
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800833 while (p_srv) {
834 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800835
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800836 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
837 p_rcb->e_hdl < s_hdl)) {
838 reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len,
839 s_hdl, e_hdl);
840 if (reason == GATT_NO_RESOURCES) {
841 reason = GATT_SUCCESS;
842 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800843 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800844 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800845 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800846 }
Marie Janssend19e0782016-07-15 12:48:27 -0700847 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800848
849 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800850 }
851
852 if (reason != GATT_SUCCESS)
853 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800854 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700855 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800856 }
857 else
858 attp_send_sr_msg(p_tcb, p_msg);
859
860}
861
862/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800863 *
864 * Function gatts_process_mtu_req
865 *
866 * Description This function is called to process excahnge MTU request.
867 * Only used on LE.
868 *
869 * Returns void
870 *
871 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700872static void gatts_process_mtu_req (tGATT_TCB *p_tcb, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800873{
Marie Janssend19e0782016-07-15 12:48:27 -0700874 uint16_t mtu = 0;
875 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876 BT_HDR *p_buf;
Marie Janssend19e0782016-07-15 12:48:27 -0700877 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800878
The Android Open Source Project5738f832012-12-12 16:00:35 -0800879 /* BR/EDR conenction, send error response */
880 if (p_tcb->att_lcid != L2CAP_ATT_CID)
881 {
Marie Janssend19e0782016-07-15 12:48:27 -0700882 gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800883 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700884 else if (len < GATT_MTU_REQ_MIN_LEN)
885 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700886 GATT_TRACE_ERROR("invalid MTU request PDU received.");
Marie Janssend19e0782016-07-15 12:48:27 -0700887 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false);
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700888 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800889 else
890 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700891 STREAM_TO_UINT16 (mtu, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800892 /* mtu must be greater than default MTU which is 23/48 */
Andre Eisenbach4b638692013-06-14 13:22:25 -0700893 if (mtu < GATT_DEF_BLE_MTU_SIZE)
894 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
895 else if (mtu > GATT_MAX_MTU_SIZE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800896 p_tcb->payload_size = GATT_MAX_MTU_SIZE;
Andre Eisenbach4b638692013-06-14 13:22:25 -0700897 else
898 p_tcb->payload_size = mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800899
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700900 GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
Zhihai Xu52c0ccb2014-03-20 17:50:12 -0700901
Priti Aghera636d6712014-12-18 13:55:48 -0800902 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
903
Marie Janssenf33b6f42016-11-22 15:01:42 -0800904 p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU,
905 (tGATT_SR_MSG *)&p_tcb->payload_size);
906 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800907 {
908 attp_send_sr_msg (p_tcb, p_buf);
909
910 /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
911 /* of 0, as no response is allowed from applcations */
912
913 for (i = 0; i < GATT_MAX_APPS; i ++)
914 {
915 if (gatt_cb.cl_rcb[i].in_use )
916 {
917 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
918 gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
919 (tGATTS_DATA *)&p_tcb->payload_size);
920 }
921 }
922
923 }
924 }
925}
926
927/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800928 *
929 * Function gatts_process_read_by_type_req
930 *
931 * Description process Read By type request.
932 * This PDU can be used to perform:
933 * - read characteristic value
934 * - read characteristic descriptor value
935 * - discover characteristic
936 * - discover characteristic by UUID
937 * - relationship discovery
938 *
939 * Returns void
940 *
941 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700942void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800943{
944 tBT_UUID uuid;
945 tGATT_SR_REG *p_rcb;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800946 size_t msg_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
Marie Janssend19e0782016-07-15 12:48:27 -0700947 uint16_t buf_len, s_hdl, e_hdl, err_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800948 BT_HDR *p_msg = NULL;
949 tGATT_STATUS reason, ret;
Marie Janssend19e0782016-07-15 12:48:27 -0700950 uint8_t *p;
951 uint8_t sec_flag, key_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800952 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
953 tGATT_SRV_LIST_ELEM *p_srv=NULL;
954
955 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
956
Marie Janssend19e0782016-07-15 12:48:27 -0700957#if (GATT_CONFORMANCE_TESTING == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800958 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
959 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700960 GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800961
Marie Janssend19e0782016-07-15 12:48:27 -0700962 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800963
964 return;
965 }
966#endif
967
968 if (reason == GATT_SUCCESS)
969 {
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800970 p_msg = (BT_HDR *)osi_calloc(msg_len);
Marie Janssend19e0782016-07-15 12:48:27 -0700971 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800972
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800973 *p ++ = op_code + 1;
974 /* reserve length byte */
975 p_msg->len = 2;
976 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800977
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800978 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800979
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800980 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800981
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800982 while (p_srv) {
983 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800984
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800985 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
986 p_rcb->e_hdl < s_hdl)) {
987 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport,
988 &sec_flag, &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800989
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800990 ret = gatts_db_read_attr_value_by_type(p_tcb,
991 p_rcb->p_db,
992 op_code,
993 p_msg,
994 s_hdl,
995 e_hdl,
996 uuid,
997 &buf_len,
998 sec_flag,
999 key_size,
1000 0,
1001 &err_hdl);
1002 if (ret != GATT_NOT_FOUND) {
1003 reason = ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001004
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001005 if (ret == GATT_NO_RESOURCES)
1006 reason = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001007 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001008 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND) {
1009 s_hdl = err_hdl;
1010 break;
1011 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001012 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001013 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001014 }
Marie Janssend19e0782016-07-15 12:48:27 -07001015 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001016 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001017 }
1018 if (reason != GATT_SUCCESS)
1019 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001020 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001021
1022 /* in theroy BUSY is not possible(should already been checked), protected check */
1023 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001024 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001025 }
1026 else
1027 attp_send_sr_msg(p_tcb, p_msg);
1028
1029}
1030
1031/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001032 *
1033 * Function gatts_process_write_req
1034 *
1035 * Description This function is called to process the write request
1036 * from client.
1037 *
1038 * Returns void
1039 *
1040 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001041void gatts_process_write_req (tGATT_TCB *p_tcb, uint8_t i_rcb, uint16_t handle,
1042 uint8_t op_code, uint16_t len, uint8_t *p_data,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001043 bt_gatt_db_attribute_type_t gatt_type)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001044{
1045 tGATTS_DATA sr_data;
Marie Janssend19e0782016-07-15 12:48:27 -07001046 uint32_t trans_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001047 tGATT_STATUS status;
Marie Janssend19e0782016-07-15 12:48:27 -07001048 uint8_t sec_flag, key_size, *p = p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001049 tGATT_SR_REG *p_sreg;
Marie Janssend19e0782016-07-15 12:48:27 -07001050 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001051
1052 memset(&sr_data, 0, sizeof(tGATTS_DATA));
1053
1054 switch (op_code)
1055 {
1056 case GATT_REQ_PREPARE_WRITE:
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001057 if (len < 2) {
1058 GATT_TRACE_ERROR("%s: Prepare write request was invalid - missing offset, sending error response", __func__);
Marie Janssend19e0782016-07-15 12:48:27 -07001059 gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, false);
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001060 return;
1061 }
Marie Janssend19e0782016-07-15 12:48:27 -07001062 sr_data.write_req.is_prep = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001063 STREAM_TO_UINT16(sr_data.write_req.offset, p);
1064 len -= 2;
1065 /* fall through */
1066 case GATT_SIGN_CMD_WRITE:
1067 if (op_code == GATT_SIGN_CMD_WRITE)
1068 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001069 GATT_TRACE_DEBUG("Write CMD with data sigining" );
The Android Open Source Project5738f832012-12-12 16:00:35 -08001070 len -= GATT_AUTH_SIGN_LEN;
1071 }
1072 /* fall through */
1073 case GATT_CMD_WRITE:
1074 case GATT_REQ_WRITE:
1075 if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001076 sr_data.write_req.need_rsp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001077 sr_data.write_req.handle = handle;
1078 sr_data.write_req.len = len;
Satya Calloji444a8da2015-03-06 10:38:22 -08001079 if (len != 0 && p != NULL)
1080 {
1081 memcpy (sr_data.write_req.value, p, len);
1082 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001083 break;
1084 }
1085
1086 gatt_sr_get_sec_info(p_tcb->peer_bda,
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001087 p_tcb->transport,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001088 &sec_flag,
1089 &key_size);
1090
1091 status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
1092 op_code,
1093 handle,
1094 sr_data.write_req.offset,
1095 p,
1096 len,
1097 sec_flag,
1098 key_size);
1099
1100 if (status == GATT_SUCCESS)
1101 {
Marie Janssenf33b6f42016-11-22 15:01:42 -08001102 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1103 if (trans_id != 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001104 {
1105 p_sreg = &gatt_cb.sr_reg[i_rcb];
1106 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001107
Marie Janssend19e0782016-07-15 12:48:27 -07001108 uint8_t opcode = 0;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001109 if (gatt_type == BTGATT_DB_DESCRIPTOR) {
1110 opcode = GATTS_REQ_TYPE_WRITE_DESCRIPTOR;
1111 } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
1112 opcode = GATTS_REQ_TYPE_WRITE_CHARACTERISTIC;
1113 } else {
1114 GATT_TRACE_ERROR("%s: Attempt to write attribute that's not tied with"
1115 " characteristic or descriptor value.", __func__);
1116 status = GATT_ERROR;
1117 }
1118
1119 if (opcode) {
1120 gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
1121 status = GATT_PENDING;
1122 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001123 }
1124 else
1125 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001126 GATT_TRACE_ERROR("max pending command, send error");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001127 status = GATT_BUSY; /* max pending command, application error */
1128 }
1129 }
1130
1131 /* in theroy BUSY is not possible(should already been checked), protected check */
1132 if (status != GATT_PENDING && status != GATT_BUSY &&
1133 (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
1134 {
Marie Janssend19e0782016-07-15 12:48:27 -07001135 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001136 }
1137 return;
1138}
1139
1140/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001141 *
1142 * Function gatts_process_read_req
1143 *
1144 * Description This function is called to process the read request
1145 * from client.
1146 *
1147 * Returns void
1148 *
1149 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001150static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, uint8_t op_code,
Myles Watsond35a6482016-10-27 08:52:16 -07001151 uint16_t handle,
1152 UNUSED_ATTR uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001153{
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001154 size_t buf_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001155 tGATT_STATUS reason;
Marie Janssend19e0782016-07-15 12:48:27 -07001156 uint8_t sec_flag, key_size, *p;
1157 uint16_t offset = 0, value_len = 0;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001158 BT_HDR *p_msg = (BT_HDR *)osi_calloc(buf_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001159
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001160 if (op_code == GATT_REQ_READ_BLOB)
1161 STREAM_TO_UINT16(offset, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001162
Marie Janssend19e0782016-07-15 12:48:27 -07001163 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001164 *p ++ = op_code + 1;
1165 p_msg->len = 1;
1166 buf_len = p_tcb->payload_size - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001167
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001168 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, &sec_flag,
1169 &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001170
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001171 reason = gatts_read_attr_value_by_handle(p_tcb,
1172 p_rcb->p_db,
1173 op_code,
1174 handle,
1175 offset,
1176 p,
1177 &value_len,
1178 (uint16_t)buf_len,
1179 sec_flag,
1180 key_size,
1181 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001182
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001183 p_msg->len += value_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001184
1185 if (reason != GATT_SUCCESS)
1186 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001187 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001188
1189 /* in theroy BUSY is not possible(should already been checked), protected check */
1190 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001191 gatt_send_error_rsp (p_tcb, reason, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001192 }
1193 else
1194 attp_send_sr_msg(p_tcb, p_msg);
1195
1196}
1197
1198/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001199 *
1200 * Function gatts_process_attribute_req
1201 *
Myles Watson9ca07092016-11-28 16:41:53 -08001202 * Description This function is called to process the per attribute handle
1203 * request from client.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001204 *
1205 * Returns void
1206 *
1207 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001208void gatts_process_attribute_req (tGATT_TCB *p_tcb, uint8_t op_code,
1209 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001210{
Marie Janssend19e0782016-07-15 12:48:27 -07001211 uint16_t handle = 0;
1212 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001213 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
1214 tGATT_STATUS status = GATT_INVALID_HANDLE;
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001215 tGATT_ATTR *p_attr;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001216
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001217 if (len < 2)
1218 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001219 GATT_TRACE_ERROR("Illegal PDU length, discard request");
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001220 status = GATT_INVALID_PDU;
1221 }
1222 else
1223 {
1224 STREAM_TO_UINT16(handle, p);
1225 len -= 2;
1226 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001227
Marie Janssend19e0782016-07-15 12:48:27 -07001228#if (GATT_CONFORMANCE_TESTING == TRUE)
Andre Eisenbach6975b4d2013-08-05 16:55:38 -07001229 gatt_cb.handle = handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001230 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
1231 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001232 GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001233
Marie Janssend19e0782016-07-15 12:48:27 -07001234 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001235
1236 return;
1237 }
1238#endif
1239
1240 if (GATT_HANDLE_IS_VALID(handle))
1241 {
1242 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1243 {
1244 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1245 {
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001246 p_attr = (tGATT_ATTR *)p_rcb->p_db->p_attr_list;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001247
1248 while (p_attr)
1249 {
1250 if (p_attr->handle == handle)
1251 {
1252 switch (op_code)
1253 {
1254 case GATT_REQ_READ: /* read char/char descriptor value */
1255 case GATT_REQ_READ_BLOB:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001256 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001257 break;
1258
1259 case GATT_REQ_WRITE: /* write char/char descriptor value */
1260 case GATT_CMD_WRITE:
1261 case GATT_SIGN_CMD_WRITE:
1262 case GATT_REQ_PREPARE_WRITE:
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001263 gatts_process_write_req(p_tcb, i, handle, op_code, len, p,
1264 p_attr->gatt_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001265 break;
1266 default:
1267 break;
1268 }
1269 status = GATT_SUCCESS;
1270 break;
1271 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001272 p_attr = (tGATT_ATTR *)p_attr->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001273 }
1274 break;
1275 }
1276 }
1277 }
1278
1279 if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001280 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001281}
1282
1283/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001284 *
1285 * Function gatts_proc_srv_chg_ind_ack
1286 *
1287 * Description This function process the service changed indicaiton ACK
1288 *
1289 * Returns void
1290 *
1291 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001292static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
1293{
1294 tGATTS_SRV_CHG_REQ req;
1295 tGATTS_SRV_CHG *p_buf = NULL;
1296
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001297 GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001298
Marie Janssenf33b6f42016-11-22 15:01:42 -08001299 p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
1300 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001301 {
Marie Janssend19e0782016-07-15 12:48:27 -07001302 GATT_TRACE_DEBUG("NV update set srv chg = false");
1303 p_buf->srv_changed = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001304 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
1305 if (gatt_cb.cb_info.p_srv_chg_callback)
1306 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
1307 }
1308}
1309
1310/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001311 *
1312 * Function gatts_chk_pending_ind
1313 *
Myles Watson9ca07092016-11-28 16:41:53 -08001314 * Description This function check any pending indication needs to be sent
1315 * if there is a pending indication then sent the indication
Myles Watsonee96a3c2016-11-23 14:49:54 -08001316 *
1317 * Returns void
1318 *
1319 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001320static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
1321{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001322 GATT_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001323
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001324 tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q);
1325 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001326 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001327 GATTS_HandleValueIndication(p_buf->conn_id,
1328 p_buf->handle,
1329 p_buf->len,
1330 p_buf->value);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001331 osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q,
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001332 p_buf));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001333 }
1334}
1335
1336/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001337 *
1338 * Function gatts_proc_ind_ack
1339 *
Myles Watson9ca07092016-11-28 16:41:53 -08001340 * Description This function processes the Indication ack
Myles Watsonee96a3c2016-11-23 14:49:54 -08001341 *
Myles Watson9ca07092016-11-28 16:41:53 -08001342 * Returns true continue to process the indication ack by the
1343 * application if the ACK is not a Service Changed Indication
Myles Watsonee96a3c2016-11-23 14:49:54 -08001344 *
1345 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001346static bool gatts_proc_ind_ack(tGATT_TCB *p_tcb, uint16_t ack_handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001347{
Marie Janssend19e0782016-07-15 12:48:27 -07001348 bool continue_processing = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001349
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001350 GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001351
1352 if (ack_handle == gatt_cb.handle_of_h_r)
1353 {
1354 gatts_proc_srv_chg_ind_ack(p_tcb);
1355 /* there is no need to inform the application since srv chg is handled internally by GATT */
Marie Janssend19e0782016-07-15 12:48:27 -07001356 continue_processing = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001357 }
1358
1359 gatts_chk_pending_ind(p_tcb);
1360 return continue_processing;
1361}
1362
1363/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001364 *
1365 * Function gatts_process_value_conf
1366 *
Myles Watson9ca07092016-11-28 16:41:53 -08001367 * Description This function is called to process the handle value
1368 * confirmation.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001369 *
1370 * Returns void
1371 *
1372 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001373void gatts_process_value_conf(tGATT_TCB *p_tcb, uint8_t op_code)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001374{
Marie Janssend19e0782016-07-15 12:48:27 -07001375 uint16_t handle = p_tcb->indicate_handle;
1376 uint32_t trans_id;
1377 uint8_t i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001378 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
Marie Janssend19e0782016-07-15 12:48:27 -07001379 bool continue_processing;
1380 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001381
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001382 alarm_cancel(p_tcb->conf_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001383 if (GATT_HANDLE_IS_VALID(handle))
1384 {
1385 p_tcb->indicate_handle = 0;
1386 continue_processing = gatts_proc_ind_ack(p_tcb, handle);
1387
1388 if (continue_processing)
1389 {
1390 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1391 {
1392 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1393 {
1394 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1395 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
1396 gatt_sr_send_req_callback(conn_id,
1397 trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
1398 }
1399 }
1400 }
1401 }
1402 else
1403 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001404 GATT_TRACE_ERROR("unexpected handle value confirmation");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001405 }
1406}
1407
1408/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001409 *
1410 * Function gatt_server_handle_client_req
1411 *
1412 * Description This function is called to handle the client requests to
1413 * server.
1414 *
1415 *
1416 * Returns void
1417 *
1418 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001419void gatt_server_handle_client_req (tGATT_TCB *p_tcb, uint8_t op_code,
1420 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001421{
1422 /* there is pending command, discard this one */
1423 if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
1424 return;
1425
1426 /* the size of the message may not be bigger than the local max PDU size*/
1427 /* The message has to be smaller than the agreed MTU, len does not include op code */
1428 if (len >= p_tcb->payload_size)
1429 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001430 GATT_TRACE_ERROR("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size );
The Android Open Source Project5738f832012-12-12 16:00:35 -08001431 /* for invalid request expecting response, send it now */
1432 if (op_code != GATT_CMD_WRITE &&
1433 op_code != GATT_SIGN_CMD_WRITE &&
1434 op_code != GATT_HANDLE_VALUE_CONF)
1435 {
Marie Janssend19e0782016-07-15 12:48:27 -07001436 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001437 }
1438 /* otherwise, ignore the pkt */
1439 }
1440 else
1441 {
1442 switch (op_code)
1443 {
1444 case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
1445 case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
1446 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
1447 break;
1448
1449 case GATT_REQ_FIND_INFO:/* discover char descrptor */
1450 gatts_process_find_info(p_tcb, op_code, len, p_data);
1451 break;
1452
1453 case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
1454 /* discover characteristic, discover char by UUID */
1455 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
1456 break;
1457
1458
1459 case GATT_REQ_READ: /* read char/char descriptor value */
1460 case GATT_REQ_READ_BLOB:
1461 case GATT_REQ_WRITE: /* write char/char descriptor value */
1462 case GATT_CMD_WRITE:
1463 case GATT_SIGN_CMD_WRITE:
1464 case GATT_REQ_PREPARE_WRITE:
1465 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
1466 break;
1467
1468 case GATT_HANDLE_VALUE_CONF:
1469 gatts_process_value_conf (p_tcb, op_code);
1470 break;
1471
1472 case GATT_REQ_MTU:
1473 gatts_process_mtu_req (p_tcb, len, p_data);
1474 break;
1475
1476 case GATT_REQ_EXEC_WRITE:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001477 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001478 break;
1479
1480 case GATT_REQ_READ_MULTI:
1481 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
1482 break;
1483
1484 default:
1485 break;
1486 }
1487 }
1488}