GATT Server refactoring (4/4)

Right now in order to add gatt service, we need to add it piece by
piece - each characteristic and descriptor separately. This causes lots
of concurrency errors in higher layers. Instead accept whole service
definition and start whole service at once.

Also, use handles to identify GATT server attributes. It's already done
on clinet side.

Bug: 27999121
Change-Id: I42c796809423d116fe6755ef8b1c40da270427a5
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index d92665a..5dc6f2d 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -28,6 +28,7 @@
 #include "gatt_int.h"
 #include "btm_int.h"
 #include "hcimsgs.h"
+#include "btcore/include/uuid.h"
 
 #define GAP_CHAR_ICON_SIZE          2
 #define GAP_CHAR_DEV_NAME_SIZE      248
@@ -338,11 +339,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             if (!p_data->write_req.need_rsp)
                 ignore = TRUE;
 
@@ -380,10 +383,7 @@
 void gap_attr_db_init(void)
 {
     tBT_UUID        app_uuid = {LEN_UUID_128,{0}};
-    tBT_UUID        uuid     = {LEN_UUID_16,{UUID_SERVCLASS_GAP_SERVER}};
     UINT16          service_handle;
-    tGAP_ATTR       *p_db_attr = &gap_cb.gatt_attr[0];
-    tGATT_STATUS    status;
 
     /* Fill our internal UUID with a fixed pattern 0x82 */
     memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
@@ -393,60 +393,48 @@
 
     GATT_StartIf(gap_cb.gatt_if);
 
-    /* Create a GAP service */
-    service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
+    bt_uuid_t svc_uuid, name_uuid, icon_uuid, pref_uuid, addr_res_uuid;
+    uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_GAP_SERVER);
+    uuid_128_from_16(&name_uuid, GATT_UUID_GAP_DEVICE_NAME);
+    uuid_128_from_16(&icon_uuid, GATT_UUID_GAP_ICON);
+    uuid_128_from_16(&pref_uuid, GATT_UUID_GAP_PREF_CONN_PARAM);
+    uuid_128_from_16(&addr_res_uuid, GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
 
-    GAP_TRACE_EVENT ("gap_attr_db_init service_handle = %d", service_handle);
-
-    /* add Device Name Characteristic
-    */
-    uuid.len = LEN_UUID_16;
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
-
-    /* add Icon characteristic
-    */
-    uuid.uu.uuid16   = p_db_attr->uuid = GATT_UUID_GAP_ICON;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
-                                                &uuid,
-                                                GATT_PERM_READ,
-                                                GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
-
+    btgatt_db_element_t service[] = {
+        {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = svc_uuid},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = name_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = icon_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = addr_res_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ}
 #if BTM_PERIPHERAL_ENABLED == TRUE       /* Only needed for peripheral testing */
-    /* add preferred connection parameter characteristic
-    */
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
-    p_db_attr->attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
-    p_db_attr->attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
-    p_db_attr->attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
-    p_db_attr->attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
-                                                &uuid,
-                                                GATT_PERM_READ,
-                                                GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
+        ,{.type = BTGATT_DB_CHARACTERISTIC, .uuid = pref_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ}
 #endif
+    };
 
-    /* add Central address resolution Characteristic */
-    uuid.len = LEN_UUID_16;
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
-                                                GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-    p_db_attr->attr_value.addr_resolution = 0;
-    p_db_attr++;
+    /* Add a GAP service */
+    GATTS_AddService(gap_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+    service_handle = service[0].attribute_handle;
 
-    /* start service now */
-    memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+    GAP_TRACE_EVENT("%s: service_handle = %d",__func__, service_handle);
 
-    status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
+    gap_cb.gatt_attr[0].uuid = GATT_UUID_GAP_DEVICE_NAME;
+    gap_cb.gatt_attr[0].handle = service[1].attribute_handle;
 
-    GAP_TRACE_EVENT ("GAP App gatt_if: %d  s_hdl = %d start_status=%d",
-                      gap_cb.gatt_if, service_handle, status);
+    gap_cb.gatt_attr[1].uuid = GATT_UUID_GAP_ICON;
+    gap_cb.gatt_attr[1].handle = service[2].attribute_handle;
 
+    gap_cb.gatt_attr[2].uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
+    gap_cb.gatt_attr[2].handle = service[3].attribute_handle;
+    gap_cb.gatt_attr[2].attr_value.addr_resolution = 0;
 
+#if BTM_PERIPHERAL_ENABLED == TRUE      /*  Only needed for peripheral testing */
 
+    gap_cb.gatt_attr[3].uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
+    gap_cb.gatt_attr[3].attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
+    gap_cb.gatt_attr[3].handle = service[4].attribute_handle;
+#endif
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 2b3fd13..96f603c 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -120,124 +120,152 @@
     return status;
 }
 
+
+static unsigned char BASE_UUID[16] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+    0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb, };
+
+static int uuidType(unsigned char* p_uuid)
+{
+    if (memcmp(p_uuid+4, BASE_UUID+4, 12) != 0)
+        return LEN_UUID_128;
+    if (memcmp(p_uuid, BASE_UUID, 2) != 0)
+        return LEN_UUID_32;
+
+    return LEN_UUID_16;
+}
+
+/*******************************************************************************
+ * BTIF -> BTA conversion functions
+ *******************************************************************************/
+
+static void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+    char *p_byte = (char*)p_src;
+    int i = 0;
+
+    p_dest->len = uuidType(p_src->uu);
+
+    switch (p_dest->len)
+    {
+        case LEN_UUID_16:
+            p_dest->uu.uuid16 = (p_src->uu[2] << 8) + p_src->uu[3];
+            break;
+
+        case LEN_UUID_32:
+            p_dest->uu.uuid32  = (p_src->uu[0] << 24) + (p_src->uu[1] << 16)
+                               + (p_src->uu[2] <<  8) + p_src->uu[3];
+            break;
+
+        case LEN_UUID_128:
+            for(i = 0; i != 16; ++i)
+                p_dest->uu.uuid128[i] = p_byte[i];
+            break;
+
+        default:
+            GATT_TRACE_ERROR("%s: Unknown UUID length %d!", __func__, p_dest->len);
+            break;
+    }
+}
+
+static UINT16 compute_service_size(btgatt_db_element_t *service, int count) {
+    int db_size = 0;
+    btgatt_db_element_t *el = service;
+
+    for (int i = 0; i<count; i++, el++)
+        if (el->type == BTGATT_DB_PRIMARY_SERVICE ||
+            el->type == BTGATT_DB_SECONDARY_SERVICE ||
+            el->type == BTGATT_DB_DESCRIPTOR ||
+            el->type == BTGATT_DB_INCLUDED_SERVICE)
+            db_size += 1;
+        else if (el->type == BTGATT_DB_CHARACTERISTIC)
+            db_size += 2;
+        else
+            GATT_TRACE_ERROR("%s: Unknown element type: %d", __func__, el->type);
+
+    return db_size;
+}
 /*******************************************************************************
 **
 ** Function         GATTS_CreateService
 **
-** Description      This function is called to reserve a block of handles for a service.
+** Description      This function is called to add GATT service.
 **
-**                  *** It should be called only once per service instance  ***
+** Parameter        gatt_if : application if
+**                  service : pseudo-representation of service and it's content
+**                  count   : size of service
 **
-** Parameter        gatt_if       : application if
-**                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
-**                  num_handles   : number of handles needed by the service.
-**                  is_pri        : is a primary service or not.
-**
-** Returns          service handle if sucessful, otherwise 0.
+** Returns          on success GATT_SERVICE_STARTED is returned, and
+**                  attribute_handle field inside service elements are filled.
+**                  on error error status is returned.
 **
 *******************************************************************************/
-UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
-                            UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri)
-{
-
+UINT16 GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t *service, int count) {
     tGATT_HDL_LIST_INFO     *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM     *p_list=NULL;
     UINT16                  s_hdl=0;
     BOOLEAN                 save_hdl=FALSE;
-    tGATTS_PENDING_NEW_SRV_START      *p_buf=NULL;
     tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
     tBT_UUID     *p_app_uuid128;
 
+    bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
+    tBT_UUID svc_uuid;
+    btif_to_bta_uuid(&svc_uuid, &service->uuid);
 
-    GATT_TRACE_API ("GATTS_CreateService" );
+    GATT_TRACE_API("%s", __func__);
 
     if (p_reg == NULL)
     {
         GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if);
-        return(0);
+        return GATT_INTERNAL_ERROR;
     }
 
     p_app_uuid128 = &p_reg->app_uuid128;
 
-    if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL)
-    {
-        s_hdl = p_list->asgn_range.s_handle;
-        GATT_TRACE_DEBUG ("Service already been created!!");
-    }
-    else
-    {
-        if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER))
-        {
+    UINT16 num_handles = compute_service_size(service, count);
+
+    if ( (svc_uuid.len == LEN_UUID_16) && (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) {
             s_hdl=  gatt_cb.hdl_cfg.gatt_start_hdl;
-        }
-        else if ((p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GAP_SERVER))
-        {
+    } else if ((svc_uuid.len == LEN_UUID_16) && (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER)) {
             s_hdl= gatt_cb.hdl_cfg.gap_start_hdl;
-        }
-        else
-        {
-            p_list = p_list_info->p_first;
+    } else {
+        p_list = p_list_info->p_first;
 
-            if (p_list)
-            {
-                s_hdl = p_list->asgn_range.e_handle + 1;
-            }
+        if (p_list)
+            s_hdl = p_list->asgn_range.e_handle + 1;
 
-            if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
-            {
+        if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
+            s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
 
-                s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
-            }
-            save_hdl = TRUE;
-        }
-
-        /* check for space */
-        if (num_handles > (0xFFFF - s_hdl + 1))
-        {
-            GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl, num_handles);
-            return(0);
-        }
-
-        if ( (p_list = gatt_alloc_hdl_buffer()) == NULL)
-        {
-            /* No free entry */
-            GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
-            return(0);
-        }
-
-        p_list->asgn_range.app_uuid128 = *p_app_uuid128;
-        p_list->asgn_range.svc_uuid    = *p_svc_uuid;
-        p_list->asgn_range.svc_inst    = svc_inst;
-        p_list->asgn_range.s_handle    = s_hdl;
-        p_list->asgn_range.e_handle    = s_hdl+num_handles-1;
-        p_list->asgn_range.is_primary  = is_pri;
-
-        gatt_add_an_item_to_list(p_list_info, p_list);
-
-        if (save_hdl)
-        {
-            if (gatt_cb.cb_info.p_nv_save_callback)
-                (*gatt_cb.cb_info.p_nv_save_callback)(TRUE, &p_list->asgn_range);
-            /* add a pending new  service change item to the list */
-            if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL)
-            {
-                /* No free entry */
-                GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks");
-
-                if (p_list)
-                {
-                    gatt_remove_an_item_from_list(p_list_info, p_list);
-                    gatt_free_hdl_buffer(p_list);
-                }
-                return(0);
-            }
-
-            GATT_TRACE_DEBUG ("Add a new srv chg item");
-        }
+        save_hdl = TRUE;
     }
 
-    if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles))
+    /* check for space */
+    if (num_handles > (0xFFFF - s_hdl + 1)) {
+        GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl, num_handles);
+        return GATT_INTERNAL_ERROR;
+    }
+
+    if ( (p_list = gatt_alloc_hdl_buffer()) == NULL) {
+        /* No free entry */
+        GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
+        return GATT_INTERNAL_ERROR;
+    }
+
+    p_list->asgn_range.app_uuid128 = *p_app_uuid128;
+    p_list->asgn_range.svc_uuid    = svc_uuid;
+    p_list->asgn_range.s_handle    = s_hdl;
+    p_list->asgn_range.e_handle    = s_hdl+num_handles-1;
+    p_list->asgn_range.is_primary  = is_pri;
+
+    gatt_add_an_item_to_list(p_list_info, p_list);
+
+    if (save_hdl) {
+        if (gatt_cb.cb_info.p_nv_save_callback)
+            (*gatt_cb.cb_info.p_nv_save_callback)(TRUE, &p_list->asgn_range);
+    }
+
+    if (!gatts_init_service_db(&p_list->svc_db, &svc_uuid, is_pri, s_hdl , num_handles))
     {
         GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed");
         if (p_list)
@@ -246,146 +274,92 @@
             gatt_free_hdl_buffer(p_list);
         }
 
-        if (p_buf)
-            osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-        return(0);
+        return GATT_INTERNAL_ERROR;
     }
 
-    GATT_TRACE_DEBUG ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d",
+    GATT_TRACE_DEBUG ("%d: handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d", __func__,
                        num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle,
                        ((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16": "uuid128" ),
                        p_list->asgn_range.svc_uuid.uu.uuid16,
                        p_list->asgn_range.is_primary);
 
-    return(s_hdl);
+    service->attribute_handle = s_hdl;
+
+    btgatt_db_element_t *el = service +1;
+    for (int i = 0; i<count-1; i++, el++) {
+        tBT_UUID uuid;
+        btif_to_bta_uuid(&uuid, &el->uuid);
+
+        if (el->type == BTGATT_DB_CHARACTERISTIC) {
+            /* data validity checking */
+            if (((el->properties & GATT_CHAR_PROP_BIT_AUTH) && !(el->permissions & GATT_WRITE_SIGNED_PERM)) ||
+                ((el->permissions & GATT_WRITE_SIGNED_PERM) && !(el->properties & GATT_CHAR_PROP_BIT_AUTH)) ) {
+                GATT_TRACE_DEBUG("Invalid configuration property=0x%02x perm=0x%04x ", el->properties, el->permissions);
+                return GATT_INTERNAL_ERROR;
+            }
+
+            el->attribute_handle = gatts_add_characteristic(&p_list->svc_db, el->permissions, el->properties, &uuid);
+        } else if (el->type == BTGATT_DB_DESCRIPTOR) {
+            el->attribute_handle = gatts_add_char_descr(&p_list->svc_db, el->permissions, &uuid);
+        } else if (el->type == BTGATT_DB_INCLUDED_SERVICE) {
+            tGATT_HDL_LIST_ELEM  *p_incl_decl;
+            if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(el->attribute_handle)) == NULL) {
+                GATT_TRACE_DEBUG("Included Service not created");
+                return GATT_INTERNAL_ERROR;
+            }
+
+            el->attribute_handle = gatts_add_included_service(&p_list->svc_db,
+                                              p_incl_decl->asgn_range.s_handle,
+                                              p_incl_decl->asgn_range.e_handle,
+                                              p_incl_decl->asgn_range.svc_uuid);
+        }
+    }
+
+    tGATT_SR_REG            *p_sreg;
+    UINT8                    i_sreg;
+    tBT_UUID                *p_uuid;
+
+    GATT_TRACE_API ("%s: service parsed correctly, now starting", __func__);
+
+    /*this is a new application servoce start */
+    if ((i_sreg = gatt_sr_alloc_rcb(p_list)) ==  GATT_MAX_SR_PROFILES) {
+        GATT_TRACE_ERROR ("%s: no free server registration block", __func__);
+        return GATT_NO_RESOURCES;
+    }
+
+    p_sreg = &gatt_cb.sr_reg[i_sreg];
+    p_sreg->gatt_if = gatt_if;
+
+    if (p_sreg->type == GATT_UUID_PRI_SERVICE) {
+        p_uuid = gatts_get_service_uuid(p_sreg->p_db);
+        p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
+    }
+
+    gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
+                               p_list->asgn_range.is_primary);
+
+    gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
+
+    GATT_TRACE_DEBUG ("%s: allocated i_sreg=%d ",__func__, i_sreg);
+    GATT_TRACE_DEBUG ("%s: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
+                       p_sreg->s_hdl,p_sreg->e_hdl,
+                       p_sreg->type,
+                       p_sreg->sdp_handle);
+
+    gatt_proc_srv_chg();
+
+    return GATT_SERVICE_STARTED;
 }
 
 /*******************************************************************************
 **
-** Function         GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  include_svc_handle    : included service handle.
-**
-** Returns          included service attribute handle. If 0, add included service
-**                  fail.
-**
-*******************************************************************************/
-UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle)
-
-{
-    tGATT_HDL_LIST_ELEM  *p_decl, *p_incl_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(include_svc_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Included Service not created");
-        return 0;
-    }
-
-    return gatts_add_included_service(&p_decl->svc_db,
-                                      p_incl_decl->asgn_range.s_handle,
-                                      p_incl_decl->asgn_range.e_handle,
-                                      p_incl_decl->asgn_range.svc_uuid);
-}
-/*******************************************************************************
-**
-** Function         GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**                  It will add a characteristic declaration and characteristic
-**                  value declaration into the service database identified by the
-**                  service handle.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          Characteristic value declaration attribute handle. 0 if failed.
-**
-*******************************************************************************/
-UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
-                                tGATT_PERM perm,tGATT_CHAR_PROP property)
-{
-    tGATT_HDL_LIST_ELEM  *p_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    /* data validity checking */
-    if (  ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) ||
-          ((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) )
-    {
-        GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm);
-        return 0;
-    }
-
-    return gatts_add_characteristic(&p_decl->svc_db,
-                                    perm,
-                                    property,
-                                    p_char_uuid);
-}
-/*******************************************************************************
-**
-** Function         GATTS_AddCharDescriptor
-**
-** Description      This function is called to add a characteristic descriptor
-**                  into a service database. Add descriptor should follow add char
-**                  to which it belongs, and next add char should be done only
-**                  after all add descriptors for the previous char.
-**
-** Parameter        service_handle  : To which service this characteristic descriptor
-**                                    is added to.
-**                  perm            : Characteristic value declaration attribute
-**                                    permission.
-**                  p_descr_uuid    : Characteristic descriptor UUID
-**
-** Returns         Characteristic descriptor attribute handle. 0 if add
-**                 characteristic descriptor failed.
-**
-*******************************************************************************/
-UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
-                                 tGATT_PERM perm,
-                                 tBT_UUID  * p_descr_uuid)
-{
-    tGATT_HDL_LIST_ELEM  *p_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    if (p_descr_uuid == NULL ||
-        (p_descr_uuid->len != LEN_UUID_128 && p_descr_uuid->len !=  LEN_UUID_16
-         && p_descr_uuid->len !=  LEN_UUID_32))
-    {
-        GATT_TRACE_DEBUG("Illegal parameter");
-        return 0;
-    }
-
-    return gatts_add_char_descr(&p_decl->svc_db,
-                                perm,
-                                p_descr_uuid);
-
-}
-/*******************************************************************************
-**
 ** Function         GATTS_DeleteService
 **
 ** Description      This function is called to delete a service.
 **
 ** Parameter        gatt_if       : application interface
 **                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
+**                  start_handle  : start handle of the service
 **
 ** Returns          TRUE if operation succeed, FALSE if handle block was not found.
 **
@@ -396,7 +370,6 @@
     tGATT_HDL_LIST_INFO             *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM             *p_list=NULL;
     UINT8                           i_sreg;
-    tGATTS_PENDING_NEW_SRV_START    *p_buf;
     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
     tBT_UUID *p_app_uuid128;
 
@@ -415,17 +388,7 @@
         return(FALSE);
     }
 
-    if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
-                                         &p_list->asgn_range.svc_uuid,
-                                         p_list->asgn_range.svc_inst)) != NULL)
-    {
-        GATT_TRACE_DEBUG ("Delete a new service changed item - the service has not yet started");
-        osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-    }
-    else
-    {
-        gatt_proc_srv_chg();
-    }
+    gatt_proc_srv_chg();
 
     if ((i_sreg = gatt_sr_find_i_rcb_by_app_id (p_app_uuid128,
                                                 p_svc_uuid,
@@ -449,104 +412,6 @@
 
 /*******************************************************************************
 **
-** Function         GATTS_StartService
-**
-** Description      This function is called to start a service with GATT
-**
-** Parameter        gatt_if : service handle.
-**                  p_cback       : application service callback functions.
-**                  sup_transport : supported transport(s) for this primary service
-**
-** return           GATT_SUCCESS if sucessfully started; otherwise error code.
-**
-*******************************************************************************/
-tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
-                                 tGATT_TRANSPORT sup_transport)
-{
-    tGATT_SR_REG            *p_sreg;
-    tGATT_HDL_LIST_ELEM      *p_list=NULL;
-    UINT8                    i_sreg;
-    tBT_UUID                *p_uuid;
-    tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
-
-    tGATTS_PENDING_NEW_SRV_START *p_buf;
-
-    GATT_TRACE_API ("GATTS_StartService");
-
-    if (p_reg == NULL)
-    {
-        /* Not found  */
-        GATT_TRACE_ERROR ("Applicaiton not found ");
-        return GATT_NOT_FOUND;
-    }
-
-    if ((p_list = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        /* Not found  */
-        GATT_TRACE_ERROR ("no service found");
-        return GATT_NOT_FOUND;
-    }
-
-    if (gatt_sr_find_i_rcb_by_app_id (&p_list->asgn_range.app_uuid128,
-                                      &p_list->asgn_range.svc_uuid,
-                                      p_list->asgn_range.svc_inst) != GATT_MAX_SR_PROFILES)
-    {
-        GATT_TRACE_ERROR ("Duplicate Service start - Service already started");
-        return GATT_SERVICE_STARTED;
-    }
-
-    /*this is a new application servoce start */
-    if ((i_sreg = gatt_sr_alloc_rcb(p_list)) ==  GATT_MAX_SR_PROFILES)
-    {
-        GATT_TRACE_ERROR ("GATTS_StartService: no free server registration block");
-        return GATT_NO_RESOURCES;
-    }
-
-    p_sreg = &gatt_cb.sr_reg[i_sreg];
-    p_sreg->gatt_if = gatt_if;
-
-    switch (sup_transport)
-    {
-        case GATT_TRANSPORT_BR_EDR:
-        case GATT_TRANSPORT_LE_BR_EDR:
-            if (p_sreg->type == GATT_UUID_PRI_SERVICE)
-            {
-                p_uuid = gatts_get_service_uuid (p_sreg->p_db);
-
-                p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
-            }
-            break;
-        default:
-            break;
-    }
-
-    gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
-                               p_list->asgn_range.is_primary);
-
-    gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
-
-    GATT_TRACE_DEBUG ("allocated i_sreg=%d ",i_sreg);
-
-    GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x",
-                       p_sreg->s_hdl,p_sreg->e_hdl,
-                       p_sreg->type,  p_sreg->service_instance,
-                       p_sreg->sdp_handle);
-
-
-    if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
-                                         &p_list->asgn_range.svc_uuid,
-                                         p_list->asgn_range.svc_inst)) != NULL)
-    {
-        gatt_proc_srv_chg();
-        /* remove the new service element after the srv changed processing is completed*/
-
-        osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-    }
-    return GATT_SUCCESS;
-}
-
-/*******************************************************************************
-**
 ** Function         GATTS_StopService
 **
 ** Description      This function is called to stop a service
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 9a2c6fa..e2d01a6 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -28,6 +28,7 @@
 
 #include "gatt_api.h"
 #include "gatt_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -191,11 +192,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             status = GATT_READ_NOT_PERMIT;
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             status = GATT_WRITE_NOT_PERMIT;
             break;
 
@@ -266,35 +269,33 @@
 void gatt_profile_db_init (void)
 {
     tBT_UUID          app_uuid = {LEN_UUID_128, {0}};
-    tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}};
     UINT16            service_handle = 0;
-    tGATT_STATUS      status;
 
     /* Fill our internal UUID with a fixed pattern 0x81 */
     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
 
-
     /* Create a GATT profile service */
     gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
     GATT_StartIf(gatt_cb.gatt_if);
 
-    service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
-    /* add Service Changed characteristic
-    */
-    uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
-    gatt_cb.gattp_attr.service_change = 0;
-    gatt_cb.gattp_attr.handle   =
-    gatt_cb.handle_of_h_r       = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
+    bt_uuid_t service_uuid;
+    uuid_128_from_16(&service_uuid, UUID_SERVCLASS_GATT_SERVER);
 
-    GATT_TRACE_DEBUG ("gatt_profile_db_init:  handle of service changed%d",
-                       gatt_cb.handle_of_h_r  );
+    bt_uuid_t char_uuid;
+    uuid_128_from_16(&char_uuid, GATT_UUID_GATT_SRV_CHGD);
 
-    /* start service
-    */
-    status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
+    btgatt_db_element_t service[] = {
+        {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = service_uuid},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = char_uuid,
+            .properties = GATT_CHAR_PROP_BIT_INDICATE, .permissions = 0}
+    };
 
-    GATT_TRACE_DEBUG ("gatt_profile_db_init:  gatt_if=%d   start status%d",
-                       gatt_cb.gatt_if,  status);
+    GATTS_AddService(gatt_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+
+    service_handle = service[0].attribute_handle;
+    gatt_cb.handle_of_h_r = service[1].attribute_handle;
+
+    GATT_TRACE_ERROR("gatt_profile_db_init:  gatt_if=%d", gatt_cb.gatt_if);
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index 91da722..5f8c406 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -45,7 +45,8 @@
 
 static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri);
 static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
-                                                UINT16 handle, UINT16 offset, UINT32 trans_id);
+                                                UINT16 handle, UINT16 offset, UINT32 trans_id,
+                                                bt_gatt_db_attribute_type_t gatt_type);
 
 /*******************************************************************************
 **
@@ -133,32 +134,32 @@
 
     if (!(perm & GATT_READ_ALLOWED))
     {
-        GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT");
+        GATT_TRACE_ERROR("%s: GATT_READ_NOT_PERMIT", __func__);
         return GATT_READ_NOT_PERMIT;
     }
 
     if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
         !(sec_flag & BTM_SEC_FLAG_ENCRYPTED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION", __func__);
         return GATT_INSUF_AUTHENTICATION;
     }
 
     if ((perm & GATT_READ_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION: MITM Required", __func__);
         return GATT_INSUF_AUTHENTICATION;
     }
 
     if ((perm & GATT_READ_ENCRYPTED_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_ENCRYPTION", __func__);
         return GATT_INSUF_ENCRYPTION;
     }
 
     if ( (perm & GATT_READ_ENCRYPTED_REQUIRED) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_KEY_SIZE", __func__);
         return GATT_INSUF_KEY_SIZE;
     }
 
@@ -175,7 +176,7 @@
             case GATT_UUID_CHAR_CLIENT_CONFIG:
             case GATT_UUID_CHAR_SRVR_CONFIG:
             case GATT_UUID_CHAR_PRESENT_FORMAT:
-                GATT_TRACE_ERROR("GATT_NOT_LONG");
+                GATT_TRACE_ERROR("%s: GATT_NOT_LONG", __func__);
                 return GATT_NOT_LONG;
 
             default:
@@ -218,7 +219,7 @@
     tGATT_STATUS    status;
     tGATT_ATTR    *p_attr16  = (tGATT_ATTR  *)p_attr;
 
-    GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d",
+    GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d",
                       p_attr16->uuid,
                       p_attr16->permission,
                       sec_flag,
@@ -359,7 +360,8 @@
 
                 if (status == GATT_PENDING)
                 {
-                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id);
+                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0,
+                                                         trans_id, p_attr->gatt_type);
 
                     /* one callback at a time */
                     break;
@@ -479,7 +481,7 @@
     tGATT_ATTR     *p_char_decl, *p_char_val;
     tBT_UUID        uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
 
-    GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property);
+    GATT_TRACE_DEBUG("%s: perm=0x%0x property=0x%0x", __func__, perm, property);
 
     if ((p_char_decl = (tGATT_ATTR *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL)
     {
@@ -500,6 +502,7 @@
         p_char_decl->p_value->char_decl.property = property;
         p_char_decl->p_value->char_decl.char_val_handle  = p_char_val->handle;
 
+        p_char_val->gatt_type = BTGATT_DB_CHARACTERISTIC;
         p_char_val->p_value = NULL;
 
         return p_char_val->handle;
@@ -584,6 +587,7 @@
     }
     else
     {
+        p_char_dscptr->gatt_type = BTGATT_DB_DESCRIPTOR;
         return p_char_dscptr->handle;
     }
 }
@@ -638,7 +642,8 @@
 
                 if (status == GATT_PENDING)
                 {
-                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id);
+                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset,
+                                                         trans_id, p_attr->gatt_type);
                 }
                 break;
             }
@@ -724,8 +729,8 @@
     tGATT_PERM      perm;
     UINT16          min_key_size;
 
-    GATT_TRACE_DEBUG( "gatts_write_attr_perm_check op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x key_size=%d",
-                       op_code, handle, offset, len, sec_flag, key_size);
+    GATT_TRACE_DEBUG( "%s: op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x key_size=%d",
+                       __func__, op_code, handle, offset, len, sec_flag, key_size);
 
     if (p_db != NULL)
     {
@@ -741,9 +746,8 @@
                 {
                     min_key_size +=6;
                 }
-                GATT_TRACE_DEBUG( "gatts_write_attr_perm_check p_attr->permission =0x%04x min_key_size==0x%04x",
-                                   p_attr->permission,
-                                   min_key_size);
+                GATT_TRACE_DEBUG( "%s: p_attr->permission =0x%04x min_key_size==0x%04x",
+                                   __func__, p_attr->permission, min_key_size);
 
                 if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE)
                     && (perm & GATT_WRITE_SIGNED_PERM))
@@ -768,45 +772,45 @@
                 if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM))
                 {
                     status = GATT_WRITE_NOT_PERMIT;
-                    GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed");
+                    GATT_TRACE_DEBUG( "%s: sign cmd write not allowed", __func__);
                 }
                  if ((op_code == GATT_SIGN_CMD_WRITE) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED))
                 {
                     status = GATT_INVALID_PDU;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link");
+                    GATT_TRACE_ERROR( "%s: Error!! sign cmd write sent on a encypted link", __func__);
                 }
                 else if (!(perm & GATT_WRITE_ALLOWED))
                 {
                     status = GATT_WRITE_NOT_PERMIT;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
+                    GATT_TRACE_ERROR( "%s: GATT_WRITE_NOT_PERMIT", __func__);
                 }
                 /* require authentication, but not been authenticated */
                 else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION", __func__);
                 }
                 else if ((perm & GATT_WRITE_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED))
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION: MITM required", __func__);
                 }
                 else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
                 {
                     status = GATT_INSUF_ENCRYPTION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_ENCRYPTION", __func__);
                 }
                 else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size))
                 {
                     status = GATT_INSUF_KEY_SIZE;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_KEY_SIZE", __func__);
                 }
                 /* LE security mode 2 attribute  */
                 else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)
                     &&  (perm & GATT_WRITE_ALLOWED) == 0)
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION: LE security mode 2 required", __func__);
                 }
                 else /* writable: must be char value declaration or char descritpors */
                 {
@@ -855,12 +859,12 @@
                         if (op_code == GATT_REQ_PREPARE_WRITE && offset != 0) /* does not allow write blob */
                         {
                             status = GATT_NOT_LONG;
-                            GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_NOT_LONG");
+                            GATT_TRACE_ERROR( "%s: GATT_NOT_LONG", __func__);
                         }
                         else if (len != max_size)    /* data does not match the required format */
                         {
                             status = GATT_INVALID_ATTR_LEN;
-                            GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
+                            GATT_TRACE_ERROR( "%s: GATT_INVALID_PDU", __func__);
                         }
                         else
                         {
@@ -1086,7 +1090,8 @@
 **
 *******************************************************************************/
 static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
-                                                UINT16 handle, UINT16 offset, UINT32 trans_id)
+                                                UINT16 handle, UINT16 offset, UINT32 trans_id,
+                                                bt_gatt_db_attribute_type_t gatt_type)
 {
     tGATTS_DATA   sr_data;
     UINT8       i_rcb;
@@ -1111,8 +1116,19 @@
         sr_data.read_req.is_long = (BOOLEAN)(op_code == GATT_REQ_READ_BLOB);
         sr_data.read_req.offset = offset;
 
+        UINT8 opcode;
+        if (gatt_type == BTGATT_DB_DESCRIPTOR) {
+            opcode = GATTS_REQ_TYPE_READ_DESCRIPTOR;
+        } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
+            opcode = GATTS_REQ_TYPE_READ_CHARACTERISTIC;
+        } else {
+            GATT_TRACE_ERROR("%s: Attempt to read attribute that's not tied with"
+                             " characteristic or descriptor value.", __func__);
+            return GATT_ERROR;
+        }
+
         gatt_sr_send_req_callback(conn_id,
-                                  trans_id, GATTS_REQ_TYPE_READ, &sr_data);
+                                  trans_id, opcode, &sr_data);
         return(tGATT_STATUS) GATT_PENDING;
     }
     else
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index f1dc1fc..cc9568a 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -183,6 +183,7 @@
     tGATT_PERM                          permission;
     UINT16                              handle;
     tBT_UUID                            uuid;
+    bt_gatt_db_attribute_type_t         gatt_type;
 } tGATT_ATTR;
 
 /* Service Database definition
@@ -207,7 +208,6 @@
     tGATT_SVC_DB    *p_db;      /* pointer to the service database */
     tBT_UUID        app_uuid;           /* applicatino UUID */
     UINT32          sdp_handle; /* primamry service SDP handle */
-    UINT16          service_instance;   /* service instance number */
     UINT16          type;       /* service type UUID, primary or secondary */
     UINT16          s_hdl;      /* service starting handle */
     UINT16          e_hdl;      /* service ending handle */
@@ -452,7 +452,6 @@
     tGATT_SRV_LIST_ELEM srv_list[GATT_MAX_SR_PROFILES];
 
     fixed_queue_t       *srv_chg_clt_q; /* service change clients queue */
-    fixed_queue_t       *pending_new_srv_start_q; /* pending new service start queue */
     tGATT_REG           cl_rcb[GATT_MAX_APPS];
     tGATT_CLCB          clcb[GATT_CL_MAX_LCB];  /* connection link control block*/
     tGATT_SCCB          sccb[GATT_MAX_SCCB];    /* sign complete callback function GATT_MAX_SCCB <= GATT_CL_MAX_LCB */
@@ -545,8 +544,6 @@
 extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
 extern tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb );
 
-extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
-
 extern BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb);
 extern tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda);
 
@@ -554,7 +551,6 @@
 extern void gatt_set_srv_chg(void);
 extern void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr);
 extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB  *p_tcb, tGATT_VALUE *p_ind);
-extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);
 extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id);
 extern BOOLEAN gatt_update_listen_mode(void);
 extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb);
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 3637981..7914217 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -106,7 +106,6 @@
     gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
     gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX);
     gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX);
-    gatt_cb.pending_new_srv_start_q = fixed_queue_new(SIZE_MAX);
     /* First, register fixed L2CAP channel for ATT over BLE */
     fixed_reg.fixed_chnl_opts.mode         = L2CAP_FCR_BASIC_MODE;
     fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
@@ -157,8 +156,6 @@
     gatt_cb.sign_op_queue = NULL;
     fixed_queue_free(gatt_cb.srv_chg_clt_q, NULL);
     gatt_cb.srv_chg_clt_q = NULL;
-    fixed_queue_free(gatt_cb.pending_new_srv_start_q, NULL);
-    gatt_cb.pending_new_srv_start_q = NULL;
     for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++)
     {
         fixed_queue_free(gatt_cb.tcb[i].pending_enc_clcb, NULL);
@@ -979,7 +976,6 @@
     UINT8   op_code, pseudo_op_code;
     UINT16  msg_len;
 
-
     if (p_buf->len > 0)
     {
         msg_len = p_buf->len - 1;
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index e55b6bb..58d28b7 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -1038,7 +1038,8 @@
 **
 *******************************************************************************/
 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
-                              UINT8 op_code, UINT16 len, UINT8 *p_data)
+                              UINT8 op_code, UINT16 len, UINT8 *p_data,
+                              bt_gatt_db_attribute_type_t gatt_type)
 {
     tGATTS_DATA     sr_data;
     UINT32          trans_id;
@@ -1101,12 +1102,22 @@
         {
             p_sreg = &gatt_cb.sr_reg[i_rcb];
             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
-            gatt_sr_send_req_callback(conn_id,
-                                      trans_id,
-                                      GATTS_REQ_TYPE_WRITE,
-                                      &sr_data);
 
-            status = GATT_PENDING;
+            UINT8 opcode = 0;
+            if (gatt_type == BTGATT_DB_DESCRIPTOR) {
+                opcode = GATTS_REQ_TYPE_WRITE_DESCRIPTOR;
+            } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
+                opcode = GATTS_REQ_TYPE_WRITE_CHARACTERISTIC;
+            } else {
+                GATT_TRACE_ERROR("%s: Attempt to write attribute that's not tied with"
+                                 " characteristic or descriptor value.", __func__);
+                status = GATT_ERROR;
+            }
+
+            if (opcode) {
+                gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
+                status = GATT_PENDING;
+            }
         }
         else
         {
@@ -1248,7 +1259,8 @@
                             case GATT_CMD_WRITE:
                             case GATT_SIGN_CMD_WRITE:
                             case GATT_REQ_PREPARE_WRITE:
-                                gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
+                                gatts_process_write_req(p_tcb, i, handle, op_code, len, p,
+                                                        p_attr->gatt_type);
                                 break;
                             default:
                                 break;
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index 03d6192..e8a6cf1 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -191,39 +191,6 @@
 
 /*******************************************************************************
 **
-** Function         gatt_sr_is_new_srv_chg
-**
-** Description     Find the app id in on the new service changed list
-**
-** Returns     Pointer to the found new service changed item othwerwise NULL
-**
-*******************************************************************************/
-tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
-{
-    tGATTS_PENDING_NEW_SRV_START *p_buf = NULL;
-
-    if (fixed_queue_is_empty(gatt_cb.pending_new_srv_start_q))
-        return NULL;
-
-    list_t *list = fixed_queue_get_list(gatt_cb.pending_new_srv_start_q);
-    for (const list_node_t *node = list_begin(list); node != list_end(list);
-         node = list_next(node)) {
-        p_buf = (tGATTS_PENDING_NEW_SRV_START *)list_node(node);
-        tGATTS_HNDL_RANGE *p = p_buf->p_new_srv_start;
-        if (gatt_uuid_compare(*p_app_uuid128, p->app_uuid128)
-            && gatt_uuid_compare (*p_svc_uuid, p->svc_uuid)
-            && (svc_inst == p->svc_inst)) {
-            GATT_TRACE_DEBUG("gatt_sr_is_new_srv_chg: Yes");
-            break;
-        }
-    }
-
-    return p_buf;
-}
-
-
-/*******************************************************************************
-**
 ** Function     gatt_add_pending_ind
 **
 ** Description  Add a pending indication
@@ -246,30 +213,6 @@
 
 /*******************************************************************************
 **
-** Function     gatt_add_pending_new_srv_start
-**
-** Description  Add a pending new srv start to the new service start queue
-**
-** Returns    Pointer to the new service start buffer, NULL no buffer available
-**
-*******************************************************************************/
-tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start(tGATTS_HNDL_RANGE *p_new_srv_start)
-{
-    tGATTS_PENDING_NEW_SRV_START *p_buf =
-        (tGATTS_PENDING_NEW_SRV_START *)osi_malloc(sizeof(tGATTS_PENDING_NEW_SRV_START));
-
-    GATT_TRACE_DEBUG("%s", __func__);
-    GATT_TRACE_DEBUG("enqueue a new pending new srv start");
-
-    p_buf->p_new_srv_start = p_new_srv_start;
-    fixed_queue_enqueue(gatt_cb.pending_new_srv_start_q, p_buf);
-
-    return p_buf;
-}
-
-
-/*******************************************************************************
-**
 ** Function     gatt_add_srv_chg_clt
 **
 ** Description  Add a service chnage client to the service change client queue
@@ -356,7 +299,7 @@
 *******************************************************************************/
 tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
                                                      tBT_UUID *p_svc_uuid,
-                                                     UINT16 svc_inst)
+                                                     UINT16 start_handle)
 {
     tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM      *p_list = NULL;
@@ -367,7 +310,7 @@
     {
         if ( gatt_uuid_compare (*p_app_uuid128, p_list->asgn_range.app_uuid128)
              &&  gatt_uuid_compare (*p_svc_uuid,    p_list->asgn_range.svc_uuid)
-             &&  (svc_inst == p_list->asgn_range.svc_inst) )
+             &&  (start_handle == p_list->asgn_range.s_handle) )
         {
             GATT_TRACE_DEBUG ("Already allocated handles for this service before!!");
             return(p_list);
@@ -1360,7 +1303,7 @@
 ** Returns          0 if not found. Otherwise index of th eservice.
 **
 *******************************************************************************/
-UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
+UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 start_handle)
 {
     UINT8           i_rcb = 0;
     tGATT_SR_REG    *p_sreg;
@@ -1375,7 +1318,7 @@
             if (p_this_uuid &&
                 gatt_uuid_compare (*p_app_uuid128, p_sreg->app_uuid ) &&
                 gatt_uuid_compare (*p_svc_uuid, *p_this_uuid) &&
-                (svc_inst == p_sreg->service_instance))
+                (start_handle == p_sreg->s_hdl))
             {
                 GATT_TRACE_ERROR ("Active Service Found ");
                 gatt_dbg_display_uuid(*p_svc_uuid);
@@ -1410,7 +1353,6 @@
             p_sreg->in_use = TRUE;
             memcpy (&p_sreg->app_uuid, &p_list->asgn_range.app_uuid128, sizeof(tBT_UUID));
 
-            p_sreg->service_instance    = p_list->asgn_range.svc_inst;
             p_sreg->type                = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
             p_sreg->s_hdl               = p_list->asgn_range.s_handle;
             p_sreg->e_hdl               = p_list->asgn_range.e_handle;
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 8b8d765..b2bf9d3 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -349,6 +349,7 @@
     UINT16        handle;
     UINT16        offset;
     BOOLEAN       is_long;
+    bt_gatt_db_attribute_type_t gatt_type; /* are we writing characteristic or descriptor */
 } tGATT_READ_REQ;
 
 /* write request data */
@@ -360,6 +361,7 @@
     UINT8           value[GATT_MAX_ATTR_LEN];  /* the actual attribute value */
     BOOLEAN         need_rsp;   /* need write response */
     BOOLEAN         is_prep;    /* is prepare write */
+    bt_gatt_db_attribute_type_t gatt_type; /* are we writing characteristic or descriptor */
 } tGATT_WRITE_REQ;
 
 /* callback data for server access request from client */
@@ -379,8 +381,10 @@
 
 enum
 {
-    GATTS_REQ_TYPE_READ = 1,        /* Attribute read request */
-    GATTS_REQ_TYPE_WRITE,           /* Attribute write request */
+    GATTS_REQ_TYPE_READ_CHARACTERISTIC = 1, /* Char read request */
+    GATTS_REQ_TYPE_READ_DESCRIPTOR,         /* Desc read request */
+    GATTS_REQ_TYPE_WRITE_CHARACTERISTIC,    /* Char write request */
+    GATTS_REQ_TYPE_WRITE_DESCRIPTOR,        /* Desc write request */
     GATTS_REQ_TYPE_WRITE_EXEC,      /* Execute write */
     GATTS_REQ_TYPE_MTU,             /* MTU exchange information */
     GATTS_REQ_TYPE_CONF             /* handle value confirmation */
@@ -608,7 +612,6 @@
 {
     tBT_UUID app_uuid128;
     tBT_UUID svc_uuid;
-    UINT16   svc_inst;
     UINT16   s_handle;
     UINT16   e_handle;
     BOOLEAN  is_primary;      /* primary service or secondary */
@@ -642,13 +645,6 @@
     UINT8 num_clients;
 } tGATTS_SRV_CHG_RSP;
 
-
-
-typedef struct
-{
-    tGATTS_HNDL_RANGE   *p_new_srv_start;
-} tGATTS_PENDING_NEW_SRV_START;
-
 /* Attibute server handle ranges NV storage callback functions
 */
 typedef void  (tGATTS_NV_SAVE_CBACK)(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
@@ -719,84 +715,22 @@
 
 /*******************************************************************************
 **
-** Function         GATTS_CreateService
+** Function         BTA_GATTS_AddService
 **
-** Description      This function is called to reserve a block of handles for a service.
+** Description      Add a service. When service is ready, a callback
+**                  event BTA_GATTS_ADD_SRVC_EVT is called to report status
+**                  and handles to the profile.
 **
-**                  *** It should be called only once per service instance  ***
+** Parameters       server_if: server interface.
+**                  service: pointer array describing service.
+**                  count: number of elements in service array.
 **
-** Parameter        gatt_if       : application if
-**                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
-**                  num_handles   : number of handles needed by the service.
-**                  is_pri        : is a primary service or not.
-**
-** Returns          service handle if sucessful, otherwise 0.
+** Returns          on success GATT_SERVICE_STARTED is returned, and
+**                  attribute_handle field inside service elements are filled.
+**                  on error error status is returned.
 **
 *******************************************************************************/
-extern UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
-                                   UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri);
-
-
-/*******************************************************************************
-**
-** Function         GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  include_svc_handle    : included service handle.
-**
-** Returns          included service attribute handle. If 0, add included service
-**                  fail.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddIncludeService (UINT16 service_handle,
-                                       UINT16 include_svc_handle);
-
-
-/*******************************************************************************
-**
-** Function         GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**                  It will add a characteristic declaration and characteristic
-**                  value declaration into the service database identified by the
-**                  service handle.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          Characteristic value declaration attribute handle. 0 if add
-**                  characteristic failed.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uuid,
-                                       tGATT_PERM perm,tGATT_CHAR_PROP property);
-
-/*******************************************************************************
-**
-** Function         GATTS_AddCharDescriptor
-**
-** Description      This function is called to add a characteristic descriptor
-**                  into a service database. Add descriptor should follow add char
-**                  to which it belongs, and next add char should be done only
-**                  after all add descriptors for the previous char.
-**
-** Parameter        service_handle  : To which service this characteristic descriptor
-**                                    is added to.
-**                  perm            : Characteristic value declaration attribute
-**                                    permission.
-**                  p_descr_uuid    : Characteristic descriptor UUID.
-**
-** Returns         Characteristic descriptor attribute handle. 0 if add
-**                 characteristic descriptor failed.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm,
-                                       tBT_UUID * p_descr_uuid);
+extern UINT16 GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t *service, int count);
 
 /*******************************************************************************
 **
@@ -814,22 +748,6 @@
 extern BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
                                     UINT16 svc_inst);
 
-/*******************************************************************************
-**
-** Function         GATTS_StartService
-**
-** Description      This function is called to start a service with GATT
-**
-** Parameter        gatt_if : service handle.
-**                  p_cback       : application service callback functions.
-**                  sup_transport : supported transport(s) for this primary service
-**
-** return           GATT_SUCCESS if sucessfully started; otherwise error code.
-**
-*******************************************************************************/
-extern tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
-                                        tGATT_TRANSPORT sup_transport);
-
 
 /*******************************************************************************
 **
diff --git a/stack/srvc/srvc_battery.c b/stack/srvc/srvc_battery.c
index 90632df..56151d5 100644
--- a/stack/srvc/srvc_battery.c
+++ b/stack/srvc/srvc_battery.c
@@ -22,6 +22,7 @@
 #include "gatt_int.h"
 #include "srvc_eng_int.h"
 #include "srvc_battery_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -197,11 +198,9 @@
 *******************************************************************************/
 UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info)
 {
-    tBT_UUID            uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
-    UINT16              srvc_hdl;
+    UINT16              srvc_hdl = 0;
     tGATT_STATUS        status = GATT_ERROR;
     tBA_INST            *p_inst;
-    tGATT_CHAR_PROP     prop = GATT_CHAR_PROP_BIT_READ;
 
     if (battery_cb.inst_id == BA_MAX_INT_NUM)
     {
@@ -211,16 +210,59 @@
 
     p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
 
-    srvc_hdl = GATTS_CreateService (srvc_eng_cb.gatt_if ,
-                                            &uuid,
-                                            battery_cb.inst_id ,
-                                            BA_MAX_ATTR_NUM,
-                                            p_reg_info->is_pri);
+    btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {};
 
-    if (srvc_hdl == 0)
-    {
-        GATT_TRACE_ERROR("Can not create service, Battery_Instantiate() failed!");
-        return 0;
+    bt_uuid_t service_uuid;
+    uuid_128_from_16(&service_uuid, UUID_SERVCLASS_BATTERY);
+    service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE;
+    service[0].uuid = service_uuid;
+
+    bt_uuid_t char_uuid;
+    uuid_128_from_16(&char_uuid, GATT_UUID_BATTERY_LEVEL);
+    service[1].type = BTGATT_DB_CHARACTERISTIC;
+    service[1].uuid = char_uuid;
+    service[1].properties = GATT_CHAR_PROP_BIT_READ;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
+        service[1].properties |= GATT_CHAR_PROP_BIT_NOTIFY;
+
+    int i=2;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_CLIENT_CONFIG);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = (GATT_PERM_READ|GATT_PERM_WRITE);
+        i++;
+    }
+
+    /* need presentation format descriptor? */
+    if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_PRESENT_FORMAT);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = GATT_PERM_READ;
+        i++;
+    }
+
+    /* need presentation format descriptor? */
+    if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_RPT_REF_DESCR);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = GATT_PERM_READ;
+        i++;
+    }
+
+    GATTS_AddService(srvc_eng_cb.gatt_if, service, i);
+
+    if (status != GATT_SUCCESS) {
+        battery_cb.inst_id --;
+        GATT_TRACE_ERROR("%s: Failed to add battery servuce!", __func__);
     }
 
     battery_cb.inst_id ++;
@@ -228,71 +270,23 @@
     p_inst->app_id  =   app_id;
     p_inst->p_cback =   p_reg_info->p_cback;
 
-    /* add battery level
-    */
-    uuid.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
+    srvc_hdl = service[0].attribute_handle;
+    p_inst->ba_level_hdl = service[1].attribute_handle;
 
-    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
-        prop |= GATT_CHAR_PROP_BIT_NOTIFY;
-
-    if ((p_inst->ba_level_hdl  = GATTS_AddCharacteristic(srvc_hdl,
-                                                &uuid,
-                                                BATTER_LEVEL_PERM,
-                                                prop)) == 0)
-    {
-        GATT_TRACE_ERROR("Can not add Battery Level, Battery_Instantiate() failed!");
-        status = GATT_ERROR;
-    }
-    else
-    {
-        if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
-        {
-            uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
-            p_inst->clt_cfg_hdl  = GATTS_AddCharDescriptor(srvc_hdl,
-                                                           (GATT_PERM_READ|GATT_PERM_WRITE),
-                                                           &uuid);
-            if (p_inst->clt_cfg_hdl == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level client notification FAILED!");
-            }
-        }
-        /* need presentation format descriptor? */
-        if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT)
-        {
-            uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
-            if ( (p_inst->pres_fmt_hdl = GATTS_AddCharDescriptor(srvc_hdl,
-                                                                 GATT_PERM_READ,
-                                                                 &uuid))
-                                       == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level presentation format descriptor FAILED!");
-            }
-
-        }
-        /* need presentation format descriptor? */
-        if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF)
-        {
-            uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
-            if ( (p_inst->rpt_ref_hdl = GATTS_AddCharDescriptor(srvc_hdl,
-                                                                GATT_PERM_READ,
-                                                                &uuid))
-                                       == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level report reference descriptor FAILED!");
-            }
-
-        }
-        /* start service
-        */
-        status = GATTS_StartService (srvc_eng_cb.gatt_if, srvc_hdl, p_reg_info->transport);
+    i=2;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
+        p_inst->clt_cfg_hdl = service[i].attribute_handle;
+        i++;
     }
 
-    if (status != GATT_SUCCESS)
-    {
-        battery_cb.inst_id --;
-        uuid.uu.uuid16 = UUID_SERVCLASS_BATTERY;
-        GATTS_DeleteService(srvc_eng_cb.gatt_if, &uuid, battery_cb.inst_id);
-        srvc_hdl = 0;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
+        p_inst->pres_fmt_hdl = service[i].attribute_handle;
+        i++;
+    }
+
+    if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
+        p_inst->rpt_ref_hdl = service[i].attribute_handle;
+        i++;
     }
 
     return srvc_hdl;
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
index ead8283..9fb5af2 100644
--- a/stack/srvc/srvc_dis.c
+++ b/stack/srvc/srvc_dis.c
@@ -25,6 +25,7 @@
 #include "osi/include/log.h"
 #include "srvc_dis_int.h"
 #include "srvc_eng_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -342,46 +343,54 @@
 *******************************************************************************/
 tDIS_STATUS DIS_SrInit (tDIS_ATTR_MASK dis_attr_mask)
 {
-    tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};
-    UINT16            i = 0;
     tGATT_STATUS      status;
-    tDIS_DB_ENTRY        *p_db_attr = &dis_cb.dis_attr[0];
 
-    if (dis_cb.enabled)
-    {
+    if (dis_cb.enabled) {
         GATT_TRACE_ERROR("DIS already initalized");
         return DIS_SUCCESS;
     }
 
     memset(&dis_cb, 0, sizeof(tDIS_CB));
 
-    dis_cb.service_handle = GATTS_CreateService (srvc_eng_cb.gatt_if , &uuid, 0, DIS_MAX_ATTR_NUM, TRUE);
+    btgatt_db_element_t service[DIS_MAX_ATTR_NUM] = { };
 
-    if (dis_cb.service_handle == 0)
-    {
-        GATT_TRACE_ERROR("Can not create service, DIS_Init failed!");
-        return GATT_ERROR;
-    }
-    dis_cb.max_handle = dis_cb.service_handle + DIS_MAX_ATTR_NUM;
+    bt_uuid_t svc_uuid;
+    uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_DEVICE_INFO);
+    service[0].type = BTGATT_DB_PRIMARY_SERVICE;
+    service[0].uuid = svc_uuid;
 
-    while (dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM)
-    {
-        /* add Manufacturer name
-        */
-        uuid.uu.uuid16 = p_db_attr->uuid = dis_attr_uuid[i];
-        p_db_attr->handle  = GATTS_AddCharacteristic(dis_cb.service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-        GATT_TRACE_DEBUG ("DIS_SrInit:  handle of new attribute 0x%04 = x%d", uuid.uu.uuid16, p_db_attr->handle  );
-        p_db_attr ++;
-        i ++;
+    for(int i=0; dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM; i++) {
+        dis_cb.dis_attr[i].uuid = dis_attr_uuid[i];
+
+        bt_uuid_t char_uuid;
+        uuid_128_from_16(&char_uuid, dis_cb.dis_attr[i].uuid);
+        /* index 0 is service, so characteristics start from 1 */
+        service[i+1].type = BTGATT_DB_CHARACTERISTIC;
+        service[i+1].uuid = char_uuid;
+        service[i+1].properties = GATT_CHAR_PROP_BIT_READ;
+        service[i+1].permissions = GATT_PERM_READ;
+
         dis_attr_mask >>= 1;
     }
 
-    /* start service
-    */
-    status = GATTS_StartService (srvc_eng_cb.gatt_if, dis_cb.service_handle, GATT_TRANSPORT_LE_BR_EDR);
+    /* Add a GAP service */
+    status = GATTS_AddService(srvc_eng_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+    if (status != GATT_SERVICE_STARTED) {
+        GATT_TRACE_ERROR("Can not create service, DIS_Init failed!");
+        return GATT_ERROR;
+    }
+
+    dis_cb.service_handle = service[0].attribute_handle;
+    dis_cb.max_handle = dis_cb.service_handle + DIS_MAX_ATTR_NUM;
+
+    for (int i = 0; i < DIS_MAX_CHAR_NUM; i++) {
+        dis_cb.dis_attr[i].handle = service[i+1].attribute_handle;
+
+        GATT_TRACE_DEBUG ("%s:  handle of new attribute 0x%04 = x%d", __func__,
+            dis_cb.dis_attr[i].uuid, dis_cb.dis_attr[i].handle);
+    }
 
     dis_cb.enabled = TRUE;
-
     return (tDIS_STATUS) status;
 }
 /*******************************************************************************
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
index 1c03b88..6ded138 100644
--- a/stack/srvc/srvc_eng.c
+++ b/stack/srvc/srvc_eng.c
@@ -278,11 +278,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             act = srvc_eng_process_read_req(clcb_idx, &p_data->read_req, &rsp_msg, &status);
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             act = srvc_eng_process_write_req(clcb_idx, &p_data->write_req, &rsp_msg, &status);
             if (!p_data->write_req.need_rsp)
                 act = SRVC_ACT_IGNORE;