blob: 3da64f91ae979bd80d12608bc5f8aa89c953f890 [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 *
79 * Description This function check the server command queue is empty or not.
80 *
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 *
250 * Description This function checks whether the response message from application
251 * match any pending request or not.
252 *
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 *
672 * Description check to see if the ReadByType request can be handled internally.
673 *
674 * Returns void
675 *
676 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700677static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t *p_len,
678 uint8_t **p_data, tBT_UUID *p_uuid_filter,
679 uint16_t *p_s_hdl, uint16_t *p_e_hdl)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800680{
681 tGATT_STATUS reason = GATT_SUCCESS;
Marie Janssend19e0782016-07-15 12:48:27 -0700682 uint16_t uuid_len, s_hdl = 0, e_hdl = 0;
683 uint16_t len = *p_len;
684 uint8_t *p = *p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800685
686 if (len >= 4)
687 {
688 /* obtain starting handle, and ending handle */
689 STREAM_TO_UINT16(s_hdl, p);
690 STREAM_TO_UINT16(e_hdl, p);
691 len -= 4;
692
693 if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl))
694 {
695 reason = GATT_INVALID_HANDLE;
696 }
697 /* for these PDUs, uuid filter must present */
698 else if (op_code == GATT_REQ_READ_BY_GRP_TYPE ||
699 op_code == GATT_REQ_FIND_TYPE_VALUE ||
700 op_code == GATT_REQ_READ_BY_TYPE)
701 {
702 if (len >= 2 && p_uuid_filter != NULL)
703 {
704 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len;
705
706 /* parse uuid now */
Marie Janssend19e0782016-07-15 12:48:27 -0700707 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == false ||
The Android Open Source Project5738f832012-12-12 16:00:35 -0800708 p_uuid_filter->len == 0)
709 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700710 GATT_TRACE_DEBUG("UUID filter does not exsit");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800711 reason = GATT_INVALID_PDU;
712 }
713 else
714 len -= p_uuid_filter->len;
715 }
716 else
717 reason = GATT_INVALID_PDU;
718 }
719 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700720 else
721 reason = GATT_INVALID_PDU;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722
723 *p_data = p;
724 *p_len = len;
725 *p_s_hdl = s_hdl;
726 *p_e_hdl = e_hdl;
727
728 return reason;
729}
730
731/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800732 *
733 * Function gatts_process_primary_service_req
734 *
735 * Description process ReadByGroupType/ReadByTypeValue request, for discover
736 * all primary services or discover primary service by UUID request.
737 *
738 * Returns void
739 *
740 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700741void 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 -0800742{
Marie Janssend19e0782016-07-15 12:48:27 -0700743 uint8_t reason = GATT_INVALID_PDU;
744 uint16_t s_hdl = 0, e_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800745 tBT_UUID uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
746 BT_HDR *p_msg = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700747 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 -0800748
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700749 memset (&value, 0, sizeof(tBT_UUID));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800750 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
751
752 if (reason == GATT_SUCCESS)
753 {
754 if (gatt_uuid_compare(uuid, primary_service))
755 {
756 if (op_code == GATT_REQ_FIND_TYPE_VALUE)
757 {
Marie Janssend19e0782016-07-15 12:48:27 -0700758 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800759 reason = GATT_INVALID_PDU;
760 }
761
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800762 if (reason == GATT_SUCCESS) {
763 p_msg = (BT_HDR *)osi_calloc(msg_len);
764 reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code,
765 s_hdl, e_hdl, p_data,
766 value);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800767 }
768 }
769 else
770 {
771 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
772 {
773 reason = GATT_UNSUPPORT_GRP_TYPE;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700774 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800775 }
776 else
777 {
778 /* we do not support ReadByTypeValue with any non-primamry_service type */
779 reason = GATT_NOT_FOUND;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700780 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800781 }
782 }
783 }
784
785 if (reason != GATT_SUCCESS)
786 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800787 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700788 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800789 }
790 else
791 attp_send_sr_msg(p_tcb, p_msg);
792
793}
794
795/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800796 *
797 * Function gatts_process_find_info
798 *
799 * Description process find information request, for discover character
800 * descriptors.
801 *
802 * Returns void
803 *
804 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700805static 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 -0800806{
Marie Janssend19e0782016-07-15 12:48:27 -0700807 uint8_t reason = GATT_INVALID_PDU, *p;
808 uint16_t s_hdl = 0, e_hdl = 0, buf_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800809 BT_HDR *p_msg = NULL;
810 tGATT_SR_REG *p_rcb;
811 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
812 tGATT_SRV_LIST_ELEM *p_srv=NULL;
813
814 reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl);
815
816 if (reason == GATT_SUCCESS)
817 {
Marie Janssend19e0782016-07-15 12:48:27 -0700818 buf_len = (uint16_t)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800820 p_msg = (BT_HDR *)osi_calloc(buf_len);
821 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800822
Marie Janssend19e0782016-07-15 12:48:27 -0700823 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800824 *p ++ = op_code + 1;
825 p_msg->len = 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800826
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800827 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800829 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800830
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800831 while (p_srv) {
832 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800833
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800834 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
835 p_rcb->e_hdl < s_hdl)) {
836 reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len,
837 s_hdl, e_hdl);
838 if (reason == GATT_NO_RESOURCES) {
839 reason = GATT_SUCCESS;
840 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800841 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800842 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800843 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800844 }
Marie Janssend19e0782016-07-15 12:48:27 -0700845 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800846
847 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800848 }
849
850 if (reason != GATT_SUCCESS)
851 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800852 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700853 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800854 }
855 else
856 attp_send_sr_msg(p_tcb, p_msg);
857
858}
859
860/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800861 *
862 * Function gatts_process_mtu_req
863 *
864 * Description This function is called to process excahnge MTU request.
865 * Only used on LE.
866 *
867 * Returns void
868 *
869 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700870static 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 -0800871{
Marie Janssend19e0782016-07-15 12:48:27 -0700872 uint16_t mtu = 0;
873 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800874 BT_HDR *p_buf;
Marie Janssend19e0782016-07-15 12:48:27 -0700875 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876
The Android Open Source Project5738f832012-12-12 16:00:35 -0800877 /* BR/EDR conenction, send error response */
878 if (p_tcb->att_lcid != L2CAP_ATT_CID)
879 {
Marie Janssend19e0782016-07-15 12:48:27 -0700880 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 -0800881 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700882 else if (len < GATT_MTU_REQ_MIN_LEN)
883 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700884 GATT_TRACE_ERROR("invalid MTU request PDU received.");
Marie Janssend19e0782016-07-15 12:48:27 -0700885 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false);
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700886 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800887 else
888 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700889 STREAM_TO_UINT16 (mtu, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800890 /* mtu must be greater than default MTU which is 23/48 */
Andre Eisenbach4b638692013-06-14 13:22:25 -0700891 if (mtu < GATT_DEF_BLE_MTU_SIZE)
892 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
893 else if (mtu > GATT_MAX_MTU_SIZE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800894 p_tcb->payload_size = GATT_MAX_MTU_SIZE;
Andre Eisenbach4b638692013-06-14 13:22:25 -0700895 else
896 p_tcb->payload_size = mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700898 GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
Zhihai Xu52c0ccb2014-03-20 17:50:12 -0700899
Priti Aghera636d6712014-12-18 13:55:48 -0800900 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
901
Marie Janssenf33b6f42016-11-22 15:01:42 -0800902 p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU,
903 (tGATT_SR_MSG *)&p_tcb->payload_size);
904 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800905 {
906 attp_send_sr_msg (p_tcb, p_buf);
907
908 /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
909 /* of 0, as no response is allowed from applcations */
910
911 for (i = 0; i < GATT_MAX_APPS; i ++)
912 {
913 if (gatt_cb.cl_rcb[i].in_use )
914 {
915 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
916 gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
917 (tGATTS_DATA *)&p_tcb->payload_size);
918 }
919 }
920
921 }
922 }
923}
924
925/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800926 *
927 * Function gatts_process_read_by_type_req
928 *
929 * Description process Read By type request.
930 * This PDU can be used to perform:
931 * - read characteristic value
932 * - read characteristic descriptor value
933 * - discover characteristic
934 * - discover characteristic by UUID
935 * - relationship discovery
936 *
937 * Returns void
938 *
939 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700940void 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 -0800941{
942 tBT_UUID uuid;
943 tGATT_SR_REG *p_rcb;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800944 size_t msg_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
Marie Janssend19e0782016-07-15 12:48:27 -0700945 uint16_t buf_len, s_hdl, e_hdl, err_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800946 BT_HDR *p_msg = NULL;
947 tGATT_STATUS reason, ret;
Marie Janssend19e0782016-07-15 12:48:27 -0700948 uint8_t *p;
949 uint8_t sec_flag, key_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800950 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
951 tGATT_SRV_LIST_ELEM *p_srv=NULL;
952
953 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
954
Marie Janssend19e0782016-07-15 12:48:27 -0700955#if (GATT_CONFORMANCE_TESTING == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800956 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
957 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700958 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 -0800959
Marie Janssend19e0782016-07-15 12:48:27 -0700960 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 -0800961
962 return;
963 }
964#endif
965
966 if (reason == GATT_SUCCESS)
967 {
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800968 p_msg = (BT_HDR *)osi_calloc(msg_len);
Marie Janssend19e0782016-07-15 12:48:27 -0700969 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800970
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800971 *p ++ = op_code + 1;
972 /* reserve length byte */
973 p_msg->len = 2;
974 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800976 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800977
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800978 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800979
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800980 while (p_srv) {
981 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800982
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800983 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
984 p_rcb->e_hdl < s_hdl)) {
985 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport,
986 &sec_flag, &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800987
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800988 ret = gatts_db_read_attr_value_by_type(p_tcb,
989 p_rcb->p_db,
990 op_code,
991 p_msg,
992 s_hdl,
993 e_hdl,
994 uuid,
995 &buf_len,
996 sec_flag,
997 key_size,
998 0,
999 &err_hdl);
1000 if (ret != GATT_NOT_FOUND) {
1001 reason = ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001002
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001003 if (ret == GATT_NO_RESOURCES)
1004 reason = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001005 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001006 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND) {
1007 s_hdl = err_hdl;
1008 break;
1009 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001010 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001011 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001012 }
Marie Janssend19e0782016-07-15 12:48:27 -07001013 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001014 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001015 }
1016 if (reason != GATT_SUCCESS)
1017 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001018 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001019
1020 /* in theroy BUSY is not possible(should already been checked), protected check */
1021 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001022 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001023 }
1024 else
1025 attp_send_sr_msg(p_tcb, p_msg);
1026
1027}
1028
1029/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001030 *
1031 * Function gatts_process_write_req
1032 *
1033 * Description This function is called to process the write request
1034 * from client.
1035 *
1036 * Returns void
1037 *
1038 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001039void gatts_process_write_req (tGATT_TCB *p_tcb, uint8_t i_rcb, uint16_t handle,
1040 uint8_t op_code, uint16_t len, uint8_t *p_data,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001041 bt_gatt_db_attribute_type_t gatt_type)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001042{
1043 tGATTS_DATA sr_data;
Marie Janssend19e0782016-07-15 12:48:27 -07001044 uint32_t trans_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045 tGATT_STATUS status;
Marie Janssend19e0782016-07-15 12:48:27 -07001046 uint8_t sec_flag, key_size, *p = p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001047 tGATT_SR_REG *p_sreg;
Marie Janssend19e0782016-07-15 12:48:27 -07001048 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001049
1050 memset(&sr_data, 0, sizeof(tGATTS_DATA));
1051
1052 switch (op_code)
1053 {
1054 case GATT_REQ_PREPARE_WRITE:
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001055 if (len < 2) {
1056 GATT_TRACE_ERROR("%s: Prepare write request was invalid - missing offset, sending error response", __func__);
Marie Janssend19e0782016-07-15 12:48:27 -07001057 gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, false);
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001058 return;
1059 }
Marie Janssend19e0782016-07-15 12:48:27 -07001060 sr_data.write_req.is_prep = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001061 STREAM_TO_UINT16(sr_data.write_req.offset, p);
1062 len -= 2;
1063 /* fall through */
1064 case GATT_SIGN_CMD_WRITE:
1065 if (op_code == GATT_SIGN_CMD_WRITE)
1066 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001067 GATT_TRACE_DEBUG("Write CMD with data sigining" );
The Android Open Source Project5738f832012-12-12 16:00:35 -08001068 len -= GATT_AUTH_SIGN_LEN;
1069 }
1070 /* fall through */
1071 case GATT_CMD_WRITE:
1072 case GATT_REQ_WRITE:
1073 if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001074 sr_data.write_req.need_rsp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001075 sr_data.write_req.handle = handle;
1076 sr_data.write_req.len = len;
Satya Calloji444a8da2015-03-06 10:38:22 -08001077 if (len != 0 && p != NULL)
1078 {
1079 memcpy (sr_data.write_req.value, p, len);
1080 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001081 break;
1082 }
1083
1084 gatt_sr_get_sec_info(p_tcb->peer_bda,
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001085 p_tcb->transport,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001086 &sec_flag,
1087 &key_size);
1088
1089 status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
1090 op_code,
1091 handle,
1092 sr_data.write_req.offset,
1093 p,
1094 len,
1095 sec_flag,
1096 key_size);
1097
1098 if (status == GATT_SUCCESS)
1099 {
Marie Janssenf33b6f42016-11-22 15:01:42 -08001100 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1101 if (trans_id != 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001102 {
1103 p_sreg = &gatt_cb.sr_reg[i_rcb];
1104 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001105
Marie Janssend19e0782016-07-15 12:48:27 -07001106 uint8_t opcode = 0;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001107 if (gatt_type == BTGATT_DB_DESCRIPTOR) {
1108 opcode = GATTS_REQ_TYPE_WRITE_DESCRIPTOR;
1109 } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
1110 opcode = GATTS_REQ_TYPE_WRITE_CHARACTERISTIC;
1111 } else {
1112 GATT_TRACE_ERROR("%s: Attempt to write attribute that's not tied with"
1113 " characteristic or descriptor value.", __func__);
1114 status = GATT_ERROR;
1115 }
1116
1117 if (opcode) {
1118 gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
1119 status = GATT_PENDING;
1120 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121 }
1122 else
1123 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001124 GATT_TRACE_ERROR("max pending command, send error");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001125 status = GATT_BUSY; /* max pending command, application error */
1126 }
1127 }
1128
1129 /* in theroy BUSY is not possible(should already been checked), protected check */
1130 if (status != GATT_PENDING && status != GATT_BUSY &&
1131 (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
1132 {
Marie Janssend19e0782016-07-15 12:48:27 -07001133 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001134 }
1135 return;
1136}
1137
1138/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001139 *
1140 * Function gatts_process_read_req
1141 *
1142 * Description This function is called to process the read request
1143 * from client.
1144 *
1145 * Returns void
1146 *
1147 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001148static 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 -07001149 uint16_t handle,
1150 UNUSED_ATTR uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001151{
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001152 size_t buf_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001153 tGATT_STATUS reason;
Marie Janssend19e0782016-07-15 12:48:27 -07001154 uint8_t sec_flag, key_size, *p;
1155 uint16_t offset = 0, value_len = 0;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001156 BT_HDR *p_msg = (BT_HDR *)osi_calloc(buf_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001157
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001158 if (op_code == GATT_REQ_READ_BLOB)
1159 STREAM_TO_UINT16(offset, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001160
Marie Janssend19e0782016-07-15 12:48:27 -07001161 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001162 *p ++ = op_code + 1;
1163 p_msg->len = 1;
1164 buf_len = p_tcb->payload_size - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001165
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001166 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, &sec_flag,
1167 &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001168
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001169 reason = gatts_read_attr_value_by_handle(p_tcb,
1170 p_rcb->p_db,
1171 op_code,
1172 handle,
1173 offset,
1174 p,
1175 &value_len,
1176 (uint16_t)buf_len,
1177 sec_flag,
1178 key_size,
1179 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001180
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001181 p_msg->len += value_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001182
1183 if (reason != GATT_SUCCESS)
1184 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001185 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001186
1187 /* in theroy BUSY is not possible(should already been checked), protected check */
1188 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001189 gatt_send_error_rsp (p_tcb, reason, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001190 }
1191 else
1192 attp_send_sr_msg(p_tcb, p_msg);
1193
1194}
1195
1196/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001197 *
1198 * Function gatts_process_attribute_req
1199 *
1200 * Description This function is called to process the per attribute handle request
1201 * from client.
1202 *
1203 * Returns void
1204 *
1205 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001206void gatts_process_attribute_req (tGATT_TCB *p_tcb, uint8_t op_code,
1207 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001208{
Marie Janssend19e0782016-07-15 12:48:27 -07001209 uint16_t handle = 0;
1210 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001211 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
1212 tGATT_STATUS status = GATT_INVALID_HANDLE;
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001213 tGATT_ATTR *p_attr;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001214
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001215 if (len < 2)
1216 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001217 GATT_TRACE_ERROR("Illegal PDU length, discard request");
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001218 status = GATT_INVALID_PDU;
1219 }
1220 else
1221 {
1222 STREAM_TO_UINT16(handle, p);
1223 len -= 2;
1224 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001225
Marie Janssend19e0782016-07-15 12:48:27 -07001226#if (GATT_CONFORMANCE_TESTING == TRUE)
Andre Eisenbach6975b4d2013-08-05 16:55:38 -07001227 gatt_cb.handle = handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001228 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
1229 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001230 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 -08001231
Marie Janssend19e0782016-07-15 12:48:27 -07001232 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 -08001233
1234 return;
1235 }
1236#endif
1237
1238 if (GATT_HANDLE_IS_VALID(handle))
1239 {
1240 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1241 {
1242 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1243 {
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001244 p_attr = (tGATT_ATTR *)p_rcb->p_db->p_attr_list;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001245
1246 while (p_attr)
1247 {
1248 if (p_attr->handle == handle)
1249 {
1250 switch (op_code)
1251 {
1252 case GATT_REQ_READ: /* read char/char descriptor value */
1253 case GATT_REQ_READ_BLOB:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001254 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001255 break;
1256
1257 case GATT_REQ_WRITE: /* write char/char descriptor value */
1258 case GATT_CMD_WRITE:
1259 case GATT_SIGN_CMD_WRITE:
1260 case GATT_REQ_PREPARE_WRITE:
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001261 gatts_process_write_req(p_tcb, i, handle, op_code, len, p,
1262 p_attr->gatt_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001263 break;
1264 default:
1265 break;
1266 }
1267 status = GATT_SUCCESS;
1268 break;
1269 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001270 p_attr = (tGATT_ATTR *)p_attr->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001271 }
1272 break;
1273 }
1274 }
1275 }
1276
1277 if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001278 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001279}
1280
1281/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001282 *
1283 * Function gatts_proc_srv_chg_ind_ack
1284 *
1285 * Description This function process the service changed indicaiton ACK
1286 *
1287 * Returns void
1288 *
1289 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001290static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
1291{
1292 tGATTS_SRV_CHG_REQ req;
1293 tGATTS_SRV_CHG *p_buf = NULL;
1294
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001295 GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001296
Marie Janssenf33b6f42016-11-22 15:01:42 -08001297 p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
1298 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001299 {
Marie Janssend19e0782016-07-15 12:48:27 -07001300 GATT_TRACE_DEBUG("NV update set srv chg = false");
1301 p_buf->srv_changed = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001302 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
1303 if (gatt_cb.cb_info.p_srv_chg_callback)
1304 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
1305 }
1306}
1307
1308/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001309 *
1310 * Function gatts_chk_pending_ind
1311 *
1312 * Description This function check any pending indication needs to be sent if
1313 * there is a pending indication then sent the indication
1314 *
1315 * Returns void
1316 *
1317 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -08001318static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
1319{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001320 GATT_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001321
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001322 tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q);
1323 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001324 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001325 GATTS_HandleValueIndication(p_buf->conn_id,
1326 p_buf->handle,
1327 p_buf->len,
1328 p_buf->value);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001329 osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q,
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001330 p_buf));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001331 }
1332}
1333
1334/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001335 *
1336 * Function gatts_proc_ind_ack
1337 *
1338 * Description This function process the Indication ack
1339 *
1340 * Returns true continue to process the indication ack by the aaplication
1341 * if the ACk is not a Service Changed Indication Ack
1342 *
1343 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001344static bool gatts_proc_ind_ack(tGATT_TCB *p_tcb, uint16_t ack_handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001345{
Marie Janssend19e0782016-07-15 12:48:27 -07001346 bool continue_processing = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001347
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001348 GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001349
1350 if (ack_handle == gatt_cb.handle_of_h_r)
1351 {
1352 gatts_proc_srv_chg_ind_ack(p_tcb);
1353 /* there is no need to inform the application since srv chg is handled internally by GATT */
Marie Janssend19e0782016-07-15 12:48:27 -07001354 continue_processing = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001355 }
1356
1357 gatts_chk_pending_ind(p_tcb);
1358 return continue_processing;
1359}
1360
1361/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001362 *
1363 * Function gatts_process_value_conf
1364 *
1365 * Description This function is called to process the handle value confirmation.
1366 *
1367 * Returns void
1368 *
1369 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001370void gatts_process_value_conf(tGATT_TCB *p_tcb, uint8_t op_code)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001371{
Marie Janssend19e0782016-07-15 12:48:27 -07001372 uint16_t handle = p_tcb->indicate_handle;
1373 uint32_t trans_id;
1374 uint8_t i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001375 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
Marie Janssend19e0782016-07-15 12:48:27 -07001376 bool continue_processing;
1377 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001378
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001379 alarm_cancel(p_tcb->conf_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001380 if (GATT_HANDLE_IS_VALID(handle))
1381 {
1382 p_tcb->indicate_handle = 0;
1383 continue_processing = gatts_proc_ind_ack(p_tcb, handle);
1384
1385 if (continue_processing)
1386 {
1387 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1388 {
1389 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1390 {
1391 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1392 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
1393 gatt_sr_send_req_callback(conn_id,
1394 trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
1395 }
1396 }
1397 }
1398 }
1399 else
1400 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001401 GATT_TRACE_ERROR("unexpected handle value confirmation");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001402 }
1403}
1404
1405/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001406 *
1407 * Function gatt_server_handle_client_req
1408 *
1409 * Description This function is called to handle the client requests to
1410 * server.
1411 *
1412 *
1413 * Returns void
1414 *
1415 ******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001416void gatt_server_handle_client_req (tGATT_TCB *p_tcb, uint8_t op_code,
1417 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001418{
1419 /* there is pending command, discard this one */
1420 if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
1421 return;
1422
1423 /* the size of the message may not be bigger than the local max PDU size*/
1424 /* The message has to be smaller than the agreed MTU, len does not include op code */
1425 if (len >= p_tcb->payload_size)
1426 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001427 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 -08001428 /* for invalid request expecting response, send it now */
1429 if (op_code != GATT_CMD_WRITE &&
1430 op_code != GATT_SIGN_CMD_WRITE &&
1431 op_code != GATT_HANDLE_VALUE_CONF)
1432 {
Marie Janssend19e0782016-07-15 12:48:27 -07001433 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001434 }
1435 /* otherwise, ignore the pkt */
1436 }
1437 else
1438 {
1439 switch (op_code)
1440 {
1441 case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
1442 case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
1443 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
1444 break;
1445
1446 case GATT_REQ_FIND_INFO:/* discover char descrptor */
1447 gatts_process_find_info(p_tcb, op_code, len, p_data);
1448 break;
1449
1450 case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
1451 /* discover characteristic, discover char by UUID */
1452 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
1453 break;
1454
1455
1456 case GATT_REQ_READ: /* read char/char descriptor value */
1457 case GATT_REQ_READ_BLOB:
1458 case GATT_REQ_WRITE: /* write char/char descriptor value */
1459 case GATT_CMD_WRITE:
1460 case GATT_SIGN_CMD_WRITE:
1461 case GATT_REQ_PREPARE_WRITE:
1462 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
1463 break;
1464
1465 case GATT_HANDLE_VALUE_CONF:
1466 gatts_process_value_conf (p_tcb, op_code);
1467 break;
1468
1469 case GATT_REQ_MTU:
1470 gatts_process_mtu_req (p_tcb, len, p_data);
1471 break;
1472
1473 case GATT_REQ_EXEC_WRITE:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001474 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001475 break;
1476
1477 case GATT_REQ_READ_MULTI:
1478 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
1479 break;
1480
1481 default:
1482 break;
1483 }
1484 }
1485}