Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      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 main GATT server attributes access request
     22  *  handling functions.
     23  *
     24  ******************************************************************************/
     25 
     26 #include "bt_target.h"
     27 #include "bt_utils.h"
     28 
     29 #include "gatt_api.h"
     30 #include "gatt_int.h"
     31 
     32 #if BLE_INCLUDED == TRUE
     33 
     34 #define GATTP_MAX_NUM_INC_SVR       0
     35 #define GATTP_MAX_CHAR_NUM          2
     36 #define GATTP_MAX_ATTR_NUM          (GATTP_MAX_CHAR_NUM * 2 + GATTP_MAX_NUM_INC_SVR + 1)
     37 #define GATTP_MAX_CHAR_VALUE_SIZE   50
     38 
     39 #ifndef GATTP_ATTR_DB_SIZE
     40 #define GATTP_ATTR_DB_SIZE      GATT_DB_MEM_SIZE(GATTP_MAX_NUM_INC_SVR, GATTP_MAX_CHAR_NUM, GATTP_MAX_CHAR_VALUE_SIZE)
     41 #endif
     42 
     43 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
     44 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
     45                                          BOOLEAN connected, tGATT_DISCONN_REASON reason, tBT_TRANSPORT transport);
     46 
     47 static tGATT_CBACK gatt_profile_cback =
     48 {
     49     gatt_profile_connect_cback,
     50     NULL,
     51     NULL,
     52     NULL,
     53     gatt_profile_request_cback,
     54     NULL,
     55     NULL
     56 } ;
     57 
     58 /*******************************************************************************
     59 **
     60 ** Function         gatt_profile_find_conn_id_by_bd_addr
     61 **
     62 ** Description      The function searches all LCB with macthing bd address
     63 **
     64 ** Returns          total number of clcb found.
     65 **
     66 *******************************************************************************/
     67 UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda)
     68 {
     69     UINT8 i_clcb;
     70     tGATT_PROFILE_CLCB    *p_clcb = NULL;
     71 
     72     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
     73     {
     74         if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
     75         {
     76             return p_clcb->conn_id;
     77         }
     78     }
     79 
     80     return GATT_INVALID_CONN_ID;
     81 }
     82 
     83 /*******************************************************************************
     84 **
     85 ** Function         gatt_profile_find_clcb_by_bd_addr
     86 **
     87 ** Description      The function searches all LCBs with macthing bd address.
     88 **
     89 ** Returns          Pointer to the found link conenction control block.
     90 **
     91 *******************************************************************************/
     92 static tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda, tBT_TRANSPORT transport)
     93 {
     94     UINT8 i_clcb;
     95     tGATT_PROFILE_CLCB    *p_clcb = NULL;
     96 
     97     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
     98     {
     99         if (p_clcb->in_use && p_clcb->transport == transport &&
    100             p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
    101         {
    102             return p_clcb;
    103         }
    104     }
    105 
    106     return p_clcb;
    107 }
    108 
    109 /*******************************************************************************
    110 **
    111 ** Function         gatt_profile_clcb_alloc
    112 **
    113 ** Description      The function allocates a GATT profile  connection link control block
    114 **
    115 ** Returns           NULL if not found. Otherwise pointer to the connection link block.
    116 **
    117 *******************************************************************************/
    118 tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda, tBT_TRANSPORT tranport)
    119 {
    120     UINT8                   i_clcb = 0;
    121     tGATT_PROFILE_CLCB      *p_clcb = NULL;
    122 
    123     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
    124     {
    125         if (!p_clcb->in_use)
    126         {
    127             p_clcb->in_use      = TRUE;
    128             p_clcb->conn_id     = conn_id;
    129             p_clcb->connected   = TRUE;
    130             p_clcb->transport   = tranport;
    131             memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
    132             break;
    133         }
    134     }
    135     return p_clcb;
    136 }
    137 /*******************************************************************************
    138 **
    139 ** Function         gatt_profile_clcb_dealloc
    140 **
    141 ** Description      The function deallocates a GATT profile  connection link control block
    142 **
    143 ** Returns           NTrue the deallocation is successful
    144 **
    145 *******************************************************************************/
    146 BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id)
    147 {
    148     UINT8                   i_clcb = 0;
    149     tGATT_PROFILE_CLCB      *p_clcb = NULL;
    150 
    151     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
    152     {
    153         if (p_clcb->in_use && p_clcb->connected && (p_clcb->conn_id == conn_id))
    154         {
    155             memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
    156             return TRUE;
    157         }
    158     }
    159     return FALSE;
    160 }
    161 
    162 
    163 /*******************************************************************************
    164 **
    165 ** Function         gatt_profile_request_cback
    166 **
    167 ** Description      GATT profile attribute access request callback.
    168 **
    169 ** Returns          void.
    170 **
    171 *******************************************************************************/
    172 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
    173                                         tGATTS_DATA *p_data)
    174 {
    175     UINT8       status = GATT_INVALID_PDU;
    176     tGATTS_RSP   rsp_msg ;
    177     BOOLEAN     ignore = FALSE;
    178 
    179     memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
    180 
    181     switch (type)
    182     {
    183         case GATTS_REQ_TYPE_READ:
    184             status = GATT_READ_NOT_PERMIT;
    185             break;
    186 
    187         case GATTS_REQ_TYPE_WRITE:
    188             status = GATT_WRITE_NOT_PERMIT;
    189             break;
    190 
    191         case GATTS_REQ_TYPE_WRITE_EXEC:
    192         case GATT_CMD_WRITE:
    193             ignore = TRUE;
    194             GATT_TRACE_EVENT("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
    195             break;
    196 
    197         case GATTS_REQ_TYPE_MTU:
    198             GATT_TRACE_EVENT("Get MTU exchange new mtu size: %d", p_data->mtu);
    199             ignore = TRUE;
    200             break;
    201 
    202         default:
    203             GATT_TRACE_EVENT("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
    204             break;
    205     }
    206 
    207     if (!ignore)
    208         GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
    209 
    210 }
    211 
    212 /*******************************************************************************
    213 **
    214 ** Function         gatt_profile_connect_cback
    215 **
    216 ** Description      Gatt profile connection callback.
    217 **
    218 ** Returns          void
    219 **
    220 *******************************************************************************/
    221 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
    222                                         BOOLEAN connected, tGATT_DISCONN_REASON reason,
    223                                         tBT_TRANSPORT transport)
    224 {
    225     UNUSED(gatt_if);
    226 
    227     GATT_TRACE_EVENT ("gatt_profile_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
    228                        (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
    229                        (bda[4]<<8)+bda[5], connected, conn_id, reason);
    230 
    231     if (connected)
    232     {
    233         if (gatt_profile_clcb_alloc(conn_id, bda, transport) == NULL)
    234         {
    235             GATT_TRACE_ERROR ("gatt_profile_connect_cback: no_resource");
    236             return;
    237         }
    238     }
    239     else
    240     {
    241         gatt_profile_clcb_dealloc(conn_id);
    242     }
    243 
    244 }
    245 
    246 /*******************************************************************************
    247 **
    248 ** Function         gatt_profile_db_init
    249 **
    250 ** Description      Initializa the GATT profile attribute database.
    251 **
    252 *******************************************************************************/
    253 void gatt_profile_db_init (void)
    254 {
    255     tBT_UUID          app_uuid = {LEN_UUID_128, {0}};
    256     tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}};
    257     UINT16            service_handle = 0;
    258     tGATT_STATUS      status;
    259 
    260     /* Fill our internal UUID with a fixed pattern 0x81 */
    261     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
    262 
    263 
    264     /* Create a GATT profile service */
    265     gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
    266     GATT_StartIf(gatt_cb.gatt_if);
    267 
    268     service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
    269     /* add Service Changed characteristic
    270     */
    271     uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
    272     gatt_cb.gattp_attr.service_change = 0;
    273     gatt_cb.gattp_attr.handle   =
    274     gatt_cb.handle_of_h_r       = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
    275 
    276     GATT_TRACE_DEBUG ("gatt_profile_db_init:  handle of service changed%d",
    277                        gatt_cb.handle_of_h_r  );
    278 
    279     /* start service
    280     */
    281     status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
    282 
    283     GATT_TRACE_DEBUG ("gatt_profile_db_init:  gatt_if=%d   start status%d",
    284                        gatt_cb.gatt_if,  status);
    285 }
    286 
    287 #endif  /* BLE_INCLUDED */
    288