OSDN Git Service

Fix miscellaneous compilation errors
[android-x86/system-bt.git] / stack / gatt / att_protocol.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 2008-2014 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 ATT protocol functions
22  *
23  ******************************************************************************/
24
25 #include "bt_target.h"
26
27 #if BLE_INCLUDED == TRUE
28
29 #include "gatt_int.h"
30 #include "l2c_api.h"
31
32 #define GATT_HDR_FIND_TYPE_VALUE_LEN    21
33 #define GATT_OP_CODE_SIZE   1
34 /**********************************************************************
35 **   ATT protocl message building utility                              *
36 ***********************************************************************/
37 /*******************************************************************************
38 **
39 ** Function         attp_build_mtu_exec_cmd
40 **
41 ** Description      Build a exchange MTU request
42 **
43 ** Returns          None.
44 **
45 *******************************************************************************/
46 BT_HDR *attp_build_mtu_cmd(UINT8 op_code, UINT16 rx_mtu)
47 {
48     UINT8 *p;
49     BT_HDR *p_buf =
50         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + GATT_HDR_SIZE + L2CAP_MIN_OFFSET);
51
52     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
53     UINT8_TO_STREAM(p, op_code);
54     UINT16_TO_STREAM(p, rx_mtu);
55
56     p_buf->offset = L2CAP_MIN_OFFSET;
57     p_buf->len = GATT_HDR_SIZE; /* opcode + 2 bytes mtu */
58
59     return p_buf;
60 }
61 /*******************************************************************************
62 **
63 ** Function         attp_build_exec_write_cmd
64 **
65 ** Description      Build a execute write request or response.
66 **
67 ** Returns          None.
68 **
69 *******************************************************************************/
70 BT_HDR *attp_build_exec_write_cmd (UINT8 op_code, UINT8 flag)
71 {
72     BT_HDR      *p_buf = (BT_HDR *)osi_malloc(GATT_DATA_BUF_SIZE);
73     UINT8       *p;
74
75     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
76
77     p_buf->offset = L2CAP_MIN_OFFSET;
78     p_buf->len = GATT_OP_CODE_SIZE;
79
80     UINT8_TO_STREAM(p, op_code);
81
82     if (op_code == GATT_REQ_EXEC_WRITE) {
83         flag &= GATT_PREP_WRITE_EXEC;
84         UINT8_TO_STREAM (p, flag);
85         p_buf->len += 1;
86     }
87
88     return p_buf;
89 }
90
91 /*******************************************************************************
92 **
93 ** Function         attp_build_err_cmd
94 **
95 ** Description      Build a exchange MTU request
96 **
97 ** Returns          None.
98 **
99 *******************************************************************************/
100 BT_HDR *attp_build_err_cmd(UINT8 cmd_code, UINT16 err_handle, UINT8 reason)
101 {
102     UINT8 *p;
103     BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + 5);
104
105     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
106     UINT8_TO_STREAM(p, GATT_RSP_ERROR);
107     UINT8_TO_STREAM(p, cmd_code);
108     UINT16_TO_STREAM(p, err_handle);
109     UINT8_TO_STREAM(p, reason);
110
111     p_buf->offset = L2CAP_MIN_OFFSET;
112     /* GATT_HDR_SIZE (1B ERR_RSP op code+ 2B handle) + 1B cmd_op_code  + 1B status */
113     p_buf->len = GATT_HDR_SIZE + 1 + 1;
114
115     return p_buf;
116 }
117 /*******************************************************************************
118 **
119 ** Function         attp_build_browse_cmd
120 **
121 ** Description      Build a read information request or read by type request
122 **
123 ** Returns          None.
124 **
125 *******************************************************************************/
126 BT_HDR *attp_build_browse_cmd(UINT8 op_code, UINT16 s_hdl, UINT16 e_hdl, tBT_UUID uuid)
127 {
128     UINT8 *p;
129     BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + 8 + L2CAP_MIN_OFFSET);
130
131     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
132     /* Describe the built message location and size */
133     p_buf->offset = L2CAP_MIN_OFFSET;
134     p_buf->len = GATT_OP_CODE_SIZE + 4;
135
136     UINT8_TO_STREAM(p, op_code);
137     UINT16_TO_STREAM(p, s_hdl);
138     UINT16_TO_STREAM(p, e_hdl);
139     p_buf->len += gatt_build_uuid_to_stream(&p, uuid);
140
141     return p_buf;
142 }
143
144 /*******************************************************************************
145 **
146 ** Function         attp_build_read_handles_cmd
147 **
148 ** Description      Build a read by type and value request.
149 **
150 ** Returns          pointer to the command buffer.
151 **
152 *******************************************************************************/
153 BT_HDR *attp_build_read_by_type_value_cmd (UINT16 payload_size, tGATT_FIND_TYPE_VALUE *p_value_type)
154 {
155     UINT8 *p;
156     UINT16 len = p_value_type->value_len;
157     BT_HDR *p_buf =
158         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
159
160     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
161     p_buf->offset = L2CAP_MIN_OFFSET;
162     p_buf->len = 5; /* opcode + s_handle + e_handle */
163
164     UINT8_TO_STREAM(p, GATT_REQ_FIND_TYPE_VALUE);
165     UINT16_TO_STREAM(p, p_value_type->s_handle);
166     UINT16_TO_STREAM(p, p_value_type->e_handle);
167
168     p_buf->len += gatt_build_uuid_to_stream(&p, p_value_type->uuid);
169
170     if (p_value_type->value_len +  p_buf->len > payload_size)
171         len = payload_size - p_buf->len;
172
173     memcpy(p, p_value_type->value, len);
174     p_buf->len += len;
175
176     return p_buf;
177 }
178
179 /*******************************************************************************
180 **
181 ** Function         attp_build_read_multi_cmd
182 **
183 ** Description      Build a read multiple request
184 **
185 ** Returns          None.
186 **
187 *******************************************************************************/
188 BT_HDR *attp_build_read_multi_cmd(UINT16 payload_size, UINT16 num_handle, UINT16 *p_handle)
189 {
190     UINT8 *p, i = 0;
191     BT_HDR *p_buf =
192         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + num_handle * 2 + 1 + L2CAP_MIN_OFFSET);
193
194     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
195     p_buf->offset = L2CAP_MIN_OFFSET;
196     p_buf->len = 1;
197
198     UINT8_TO_STREAM(p, GATT_REQ_READ_MULTI);
199
200     for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i ++) {
201       UINT16_TO_STREAM (p, *(p_handle + i));
202       p_buf->len += 2;
203     }
204
205     return p_buf;
206 }
207 /*******************************************************************************
208 **
209 ** Function         attp_build_handle_cmd
210 **
211 ** Description      Build a read /read blob request
212 **
213 ** Returns          None.
214 **
215 *******************************************************************************/
216 BT_HDR *attp_build_handle_cmd(UINT8 op_code, UINT16 handle, UINT16 offset)
217 {
218     UINT8 *p;
219     BT_HDR *p_buf =
220         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + 5 + L2CAP_MIN_OFFSET);
221
222     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
223     p_buf->offset = L2CAP_MIN_OFFSET;
224
225     UINT8_TO_STREAM(p, op_code);
226     p_buf->len  = 1;
227
228     UINT16_TO_STREAM(p, handle);
229     p_buf->len += 2;
230
231     if (op_code == GATT_REQ_READ_BLOB) {
232         UINT16_TO_STREAM (p, offset);
233         p_buf->len += 2;
234     }
235
236     return p_buf;
237 }
238
239 /*******************************************************************************
240 **
241 ** Function         attp_build_opcode_cmd
242 **
243 ** Description      Build a  request/response with opcode only.
244 **
245 ** Returns          None.
246 **
247 *******************************************************************************/
248 BT_HDR *attp_build_opcode_cmd(UINT8 op_code)
249 {
250     UINT8 *p;
251     BT_HDR *p_buf =
252         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + 1 + L2CAP_MIN_OFFSET);
253
254     p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
255     p_buf->offset = L2CAP_MIN_OFFSET;
256
257     UINT8_TO_STREAM(p, op_code);
258     p_buf->len  = 1;
259
260     return p_buf;
261 }
262
263 /*******************************************************************************
264 **
265 ** Function         attp_build_value_cmd
266 **
267 ** Description      Build a attribute value request
268 **
269 ** Returns          None.
270 **
271 *******************************************************************************/
272 BT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle,
273                               UINT16 offset, UINT16 len, UINT8 *p_data)
274 {
275     UINT8 *p, *pp, pair_len, *p_pair_len;
276     BT_HDR *p_buf =
277         (BT_HDR *)osi_malloc(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET);
278
279     p = pp = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
280     UINT8_TO_STREAM(p, op_code);
281     p_buf->offset = L2CAP_MIN_OFFSET;
282     p_buf->len = 1;
283
284     if (op_code == GATT_RSP_READ_BY_TYPE) {
285         p_pair_len = p;
286         pair_len = len + 2;
287         UINT8_TO_STREAM (p, pair_len);
288         p_buf->len += 1;
289     }
290     if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ) {
291         UINT16_TO_STREAM (p, handle);
292         p_buf->len += 2;
293     }
294
295     if (op_code == GATT_REQ_PREPARE_WRITE ||op_code == GATT_RSP_PREPARE_WRITE) {
296         UINT16_TO_STREAM (p, offset);
297         p_buf->len += 2;
298     }
299
300     if (len > 0 && p_data != NULL) {
301         /* ensure data not exceed MTU size */
302         if (payload_size - p_buf->len < len) {
303             len = payload_size - p_buf->len;
304             /* update handle value pair length */
305             if (op_code == GATT_RSP_READ_BY_TYPE)
306                 *p_pair_len = (len + 2);
307
308             GATT_TRACE_WARNING("attribute value too long, to be truncated to %d", len);
309         }
310
311         ARRAY_TO_STREAM(p, p_data, len);
312         p_buf->len += len;
313     }
314
315     return p_buf;
316 }
317
318 /*******************************************************************************
319 **
320 ** Function         attp_send_msg_to_l2cap
321 **
322 ** Description      Send message to L2CAP.
323 **
324 *******************************************************************************/
325 tGATT_STATUS attp_send_msg_to_l2cap(tGATT_TCB *p_tcb, BT_HDR *p_toL2CAP)
326 {
327     UINT16      l2cap_ret;
328
329
330     if (p_tcb->att_lcid == L2CAP_ATT_CID)
331         l2cap_ret = L2CA_SendFixedChnlData (L2CAP_ATT_CID, p_tcb->peer_bda, p_toL2CAP);
332     else
333         l2cap_ret = (UINT16) L2CA_DataWrite (p_tcb->att_lcid, p_toL2CAP);
334
335     if (l2cap_ret == L2CAP_DW_FAILED)
336     {
337         GATT_TRACE_ERROR("ATT   failed to pass msg:0x%0x to L2CAP",
338             *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset));
339         return GATT_INTERNAL_ERROR;
340     }
341     else if (l2cap_ret == L2CAP_DW_CONGESTED)
342     {
343         GATT_TRACE_DEBUG("ATT congested, message accepted");
344         return GATT_CONGESTED;
345     }
346     return GATT_SUCCESS;
347 }
348
349 /*******************************************************************************
350 **
351 ** Function         attp_build_sr_msg
352 **
353 ** Description      Build ATT Server PDUs.
354 **
355 *******************************************************************************/
356 BT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg)
357 {
358     BT_HDR          *p_cmd = NULL;
359     UINT16          offset = 0;
360
361     switch (op_code)
362     {
363     case GATT_RSP_READ_BLOB:
364     case GATT_RSP_PREPARE_WRITE:
365         GATT_TRACE_EVENT ("ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
366                     p_msg->attr_value.len, p_msg->attr_value.offset);
367         offset = p_msg->attr_value.offset;
368 /* Coverity: [FALSE-POSITIVE error] intended fall through */
369 /* Missing break statement between cases in switch statement */
370         /* fall through */
371     case GATT_RSP_READ_BY_TYPE:
372     case GATT_RSP_READ:
373     case GATT_HANDLE_VALUE_NOTIF:
374     case GATT_HANDLE_VALUE_IND:
375         p_cmd = attp_build_value_cmd(p_tcb->payload_size,
376                                      op_code,
377                                      p_msg->attr_value.handle,
378                                      offset,
379                                      p_msg->attr_value.len,
380                                      p_msg->attr_value.value);
381         break;
382
383     case GATT_RSP_WRITE:
384         p_cmd = attp_build_opcode_cmd(op_code);
385         break;
386
387     case GATT_RSP_ERROR:
388         p_cmd = attp_build_err_cmd(p_msg->error.cmd_code, p_msg->error.handle, p_msg->error.reason);
389         break;
390
391     case GATT_RSP_EXEC_WRITE:
392         p_cmd = attp_build_exec_write_cmd(op_code, 0);
393         break;
394
395     case GATT_RSP_MTU:
396         p_cmd = attp_build_mtu_cmd(op_code, p_msg->mtu);
397         break;
398
399     default:
400         GATT_TRACE_DEBUG("attp_build_sr_msg: unknown op code = %d", op_code);
401         break;
402     }
403
404     if (!p_cmd)
405         GATT_TRACE_ERROR("No resources");
406
407     return p_cmd;
408 }
409
410 /*******************************************************************************
411 **
412 ** Function         attp_send_sr_msg
413 **
414 ** Description      This function sends the server response or indication message
415 **                  to client.
416 **
417 ** Parameter        p_tcb: pointer to the connecton control block.
418 **                  p_msg: pointer to message parameters structure.
419 **
420 ** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
421 **
422 **
423 *******************************************************************************/
424 tGATT_STATUS attp_send_sr_msg (tGATT_TCB *p_tcb, BT_HDR *p_msg)
425 {
426     tGATT_STATUS     cmd_sent = GATT_NO_RESOURCES;
427
428     if (p_tcb != NULL)
429     {
430         if (p_msg != NULL)
431         {
432             p_msg->offset = L2CAP_MIN_OFFSET;
433             cmd_sent = attp_send_msg_to_l2cap (p_tcb, p_msg);
434         }
435     }
436     return cmd_sent;
437 }
438
439 /*******************************************************************************
440 **
441 ** Function         attp_cl_send_cmd
442 **
443 ** Description      Send a ATT command or enqueue it.
444 **
445 ** Returns          GATT_SUCCESS if command sent
446 **                  GATT_CONGESTED if command sent but channel congested
447 **                  GATT_CMD_STARTED if command queue up in GATT
448 **                  GATT_ERROR if command sending failure
449 **
450 *******************************************************************************/
451 tGATT_STATUS attp_cl_send_cmd(tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 cmd_code, BT_HDR *p_cmd)
452 {
453     tGATT_STATUS att_ret = GATT_SUCCESS;
454
455     if (p_tcb != NULL)
456     {
457         cmd_code &= ~GATT_AUTH_SIGN_MASK;
458
459         /* no pending request or value confirmation */
460         if (p_tcb->pending_cl_req == p_tcb->next_slot_inq ||
461             cmd_code == GATT_HANDLE_VALUE_CONF)
462         {
463             att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd);
464             if (att_ret == GATT_CONGESTED || att_ret == GATT_SUCCESS)
465             {
466                 /* do not enq cmd if handle value confirmation or set request */
467                 if (cmd_code != GATT_HANDLE_VALUE_CONF && cmd_code != GATT_CMD_WRITE)
468                 {
469                     gatt_start_rsp_timer (clcb_idx);
470                     gatt_cmd_enq(p_tcb, clcb_idx, FALSE, cmd_code, NULL);
471                 }
472             }
473             else
474                 att_ret = GATT_INTERNAL_ERROR;
475         }
476         else
477         {
478             att_ret = GATT_CMD_STARTED;
479             gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
480         }
481     }
482     else
483         att_ret = GATT_ERROR;
484
485     return att_ret;
486 }
487 /*******************************************************************************
488 **
489 ** Function         attp_send_cl_msg
490 **
491 ** Description      This function sends the client request or confirmation message
492 **                  to server.
493 **
494 ** Parameter        p_tcb: pointer to the connectino control block.
495 **                  clcb_idx: clcb index
496 **                  op_code: message op code.
497 **                  p_msg: pointer to message parameters structure.
498 **
499 ** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
500 **
501 **
502 *******************************************************************************/
503 tGATT_STATUS attp_send_cl_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code, tGATT_CL_MSG *p_msg)
504 {
505     tGATT_STATUS     status = GATT_NO_RESOURCES;
506     BT_HDR          *p_cmd = NULL;
507     UINT16          offset = 0, handle;
508
509     if (p_tcb != NULL)
510     {
511         switch (op_code)
512         {
513         case GATT_REQ_MTU:
514             if (p_msg->mtu <= GATT_MAX_MTU_SIZE)
515             {
516                 p_tcb->payload_size = p_msg->mtu;
517                 p_cmd = attp_build_mtu_cmd(GATT_REQ_MTU, p_msg->mtu);
518             }
519             else
520                 status = GATT_ILLEGAL_PARAMETER;
521             break;
522
523         case GATT_REQ_FIND_INFO:
524         case GATT_REQ_READ_BY_TYPE:
525         case GATT_REQ_READ_BY_GRP_TYPE:
526             if (GATT_HANDLE_IS_VALID (p_msg->browse.s_handle) &&
527                 GATT_HANDLE_IS_VALID (p_msg->browse.e_handle)  &&
528                 p_msg->browse.s_handle <= p_msg->browse.e_handle)
529             {
530                 p_cmd = attp_build_browse_cmd(op_code,
531                                             p_msg->browse.s_handle,
532                                             p_msg->browse.e_handle,
533                                             p_msg->browse.uuid);
534             }
535             else
536                 status = GATT_ILLEGAL_PARAMETER;
537             break;
538
539         case GATT_REQ_READ_BLOB:
540             offset = p_msg->read_blob.offset;
541             /* fall through */
542         case GATT_REQ_READ:
543             handle = (op_code == GATT_REQ_READ) ? p_msg->handle: p_msg->read_blob.handle;
544             /*  handle checking */
545             if (GATT_HANDLE_IS_VALID (handle))
546             {
547                 p_cmd = attp_build_handle_cmd(op_code, handle, offset);
548             }
549             else
550                 status = GATT_ILLEGAL_PARAMETER;
551             break;
552
553         case GATT_HANDLE_VALUE_CONF:
554             p_cmd = attp_build_opcode_cmd(op_code);
555             break;
556
557         case GATT_REQ_PREPARE_WRITE:
558             offset = p_msg->attr_value.offset;
559             /* fall through */
560         case GATT_REQ_WRITE:
561         case GATT_CMD_WRITE:
562         case GATT_SIGN_CMD_WRITE:
563             if (GATT_HANDLE_IS_VALID (p_msg->attr_value.handle))
564             {
565                 p_cmd = attp_build_value_cmd (p_tcb->payload_size,
566                                               op_code, p_msg->attr_value.handle,
567                                               offset,
568                                               p_msg->attr_value.len,
569                                               p_msg->attr_value.value);
570             }
571             else
572                 status = GATT_ILLEGAL_PARAMETER;
573             break;
574
575         case GATT_REQ_EXEC_WRITE:
576             p_cmd = attp_build_exec_write_cmd(op_code, p_msg->exec_write);
577             break;
578
579         case GATT_REQ_FIND_TYPE_VALUE:
580             p_cmd = attp_build_read_by_type_value_cmd(p_tcb->payload_size, &p_msg->find_type_value);
581             break;
582
583         case GATT_REQ_READ_MULTI:
584             p_cmd = attp_build_read_multi_cmd(p_tcb->payload_size,
585                                               p_msg->read_multi.num_handles,
586                                               p_msg->read_multi.handles);
587             break;
588
589         default:
590             break;
591         }
592
593         if (p_cmd != NULL)
594             status = attp_cl_send_cmd(p_tcb, clcb_idx, op_code, p_cmd);
595
596     }
597     else
598     {
599         GATT_TRACE_ERROR("Peer device not connected");
600     }
601
602     return status;
603 }
604 #endif