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