Exemple #1
0
static ble_service_db *BleServiceDbFindRecord(BD_ADDR *bd_addr)
{
    ble_service_db *servicedb;

    servicedb = (ble_service_db *)GetHeadList(&BleDbCtx(servicedbList));
    while ((ListEntry *)servicedb != &BleDbCtx(servicedbList))
    {
        if (OS_MemCmp(bd_addr->addr, 6, servicedb->bdAddr.addr, 6))
        {
            return servicedb;
        }
        servicedb = (ble_service_db *)GetNextNode(&servicedb->node);
    }

    return NULL;
}
Exemple #2
0
void BleServiceDbUpdateRecord(ble_service_db *servicedb)
{
    S32 fd;
    S32 pos_current;
    S32 pos_end;
    U32 mode = BTMTK_FS_READ_WRITE;
    U8 *db_buff;

    if (!btmtk_fs_is_dir_exist((const U8*)BLE_SERVICE_DATABASE_FILE))
    {
        mode |= BTMTK_FS_CREATE;
    }

    fd = btmtk_fs_open((const U8*)BLE_SERVICE_DATABASE_FILE, mode);
    if (fd < 0)
    {
        return;
    }

    pos_end = btmtk_fs_seek(fd, 0, BTMTK_FS_SEEK_END);
    pos_current = btmtk_fs_seek(fd, 0, BTMTK_FS_SEEK_BEGIN);

    db_buff = (U8 *)get_ctrl_buffer(sizeof(ble_service_db) - sizeof(ListEntry));
    
    while (pos_current < pos_end)
    {
        btmtk_fs_read(fd, db_buff, sizeof(ble_service_db) - sizeof(ListEntry));
        if (OS_MemCmp(db_buff, 6, servicedb->bdAddr.addr, 6))
        {
            btmtk_fs_seek(fd, pos_current, BTMTK_FS_SEEK_BEGIN);
            break;
        }
        pos_current += (sizeof(ble_service_db) - sizeof(ListEntry));
    }

    free_ctrl_buffer(db_buff);

    Report(("[BleDB] Update record in file, seek offset: %d", pos_current));
//    kal_trace(BT_TRACE_BLE_PROFILES, BLEDB_UPDATERECORD_OFFSET, pos_current);
    btmtk_fs_write(fd, ((U8 *)servicedb) + sizeof(ListEntry), sizeof(ble_service_db) - sizeof(ListEntry));
    btmtk_fs_close(fd);
    
}
Exemple #3
0
/*---------------------------------------------------------------------------
 *            OBEXH_VerifyAuthResponse
 *---------------------------------------------------------------------------
 *
 * Synopsis: This function is used by both client & servers to verify the
 *           received authentication response digest against the expected value.
 *
 * Return:   TRUE - The response is authenticated.
 */
BOOL OBEXH_VerifyAuthResponse(ObexAuthResponseVerify *Verify)
{
    xMD5Context     context;
    U8              digest[AUTH_NONCE_LEN];

#if XA_ERROR_CHECK == XA_ENABLED
    if (!Verify) {
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */
    ASSERT(Verify);
    
    xMD5Init(&context);
    xMD5Update(&context, Verify->nonce, AUTH_NONCE_LEN);
    xMD5Update(&context, (U8 *)":", 1);
    xMD5Update(&context, Verify->password, Verify->passwordLen);
    xMD5Final(digest, &context);

    return OS_MemCmp(digest, AUTH_NONCE_LEN, Verify->digest, AUTH_NONCE_LEN);
}
Exemple #4
0
/*****************************************************************************
 * FUNCTION
 *  write_wifi_setting
 * DESCRIPTION
 *  
 * PARAMETERS
 *  ptr     [IN]
 * RETURNS
 *  void
 *****************************************************************************/
void write_wifi_setting(bt_wifi_set_chnl_req_struct *ptr)
{
#ifndef __BTMODULE_RFMD3500__
#ifdef MTK_BT_DEBUG_TRACE
    kal_trace(TRACE_GROUP_1, PTRAFHxDPTRPTAxD, ptr->afh, ptr->pta);
    OS_Report("ptr->chnl_map=%X%X%X%X%X%X%X%X%X%X", 
        ptr->chnl_map[0], ptr->chnl_map[1], ptr->chnl_map[2],
        ptr->chnl_map[3], ptr->chnl_map[4], ptr->chnl_map[5],
        ptr->chnl_map[6], ptr->chnl_map[7], ptr->chnl_map[8],
        ptr->chnl_map[9]);
#endif 
    if (ptr->afh != 0)
    {
        bt_prompt_trace(MOD_BT, "BTWIFIC(freq)=%d, ", BTWIFIC(freq));
        OS_Report("BTWIFIC(chnl_map)=%X%X%X%X%X%X%X%X%X%X", 
            BTWIFIC(chnl_map)[0], BTWIFIC(chnl_map)[1], BTWIFIC(chnl_map)[2],
            BTWIFIC(chnl_map)[3], BTWIFIC(chnl_map)[4], BTWIFIC(chnl_map)[5],
            BTWIFIC(chnl_map)[6], BTWIFIC(chnl_map)[7], BTWIFIC(chnl_map)[8],
            BTWIFIC(chnl_map)[9]);
        if (ptr->freq != BTWIFIC(freq)
            #ifdef __DIRECT_CHNL_MAP__
            || OS_MemCmp((const U8*)BTWIFIC(chnl_map), sizeof(BTWIFIC(chnl_map)), (const U8*)ptr->chnl_map, sizeof(ptr->chnl_map)) != 0
            #endif
            )
        {
            bt_prompt_trace(MOD_BT, "AFH command is needed");
            BTWIFIC(afh_cmd_wait) = 1;
            BTWIFIC(freq) = ptr->freq;
            #ifdef __DIRECT_CHNL_MAP__
            OS_MemCopy((U8*)BTWIFIC(chnl_map), (const U8*)ptr->chnl_map, sizeof(BTWIFIC(chnl_map)));
            #endif
            #if defined (WIFI_BB_MT5921) && (defined (__BT_CHIP_VERSION_1__))
            /* We set hb command while freq is different from the current setting. */
            BTWIFIC(hb) = ptr->hb;
            #endif
        }
    #ifdef MTK_BT_DEBUG_TRACE
        else
        {
            kal_trace(TRACE_GROUP_1, THE_SAME_FREQ);
        }
    #endif /* MTK_BT_DEBUG_TRACE */ 
    }
    else
    {
        /* BTWIFIC(afh_cmd_wait) = 0; */
        bt_prompt_trace(MOD_BT, "ptr->afh is 0. Nothing for afh");
    }
    if (ptr->pta != 0)
    {
    #ifdef MTK_BT_DEBUG_TRACE
        kal_trace(TRACE_GROUP_1, WE_SHALL_CHECK_THE_PTA_COMMAND);
    #endif 
        if (ptr->pta_action != BTWIFIC(pta_action))
        {
            BTWIFIC(pta_cmd_wait) = 1;
            BTWIFIC(pta_action) = ptr->pta_action;
        #ifdef MTK_BT_DEBUG_TRACE
            kal_trace(TRACE_GROUP_1, PTA_ACTIONxD, BTWIFIC(pta_action));
        #endif 
        }
    #ifdef MTK_BT_DEBUG_TRACE
        else
        {
            kal_trace(TRACE_GROUP_1, THE_SAME_PTA_ACTION);
        }
    #endif /* MTK_BT_DEBUG_TRACE */ 
    }
    else
    {
       /* BTWIFIC(pta_cmd_wait) = 0; */
       bt_prompt_trace(MOD_BT, "ptr->pta is 0. Nothing for pta");
    }
#endif /* __BTMODULE_RFMD3500__ */ 
}
Exemple #5
0
/*---------------------------------------------------------------------------
 *            BipResponderCallback
 *---------------------------------------------------------------------------
 *
 * Synopsis:  This function processes Responder events.
 *
 * Return:    void
 *
 */
void BipResponderCallback(GoepServerEvent *event)
{
    ObexRespCode        rcode;
    ObStatus            status;
    BipObexServer      *server;
    BipCallbackParms    parms;
    U8                 *p;
    BipImgHandlePtr     ih = NULL;

    parms.obex.server = FindBipResponder(event->handler);
    if (parms.obex.server == 0) {
		kal_trace(BT_TRACE_G6_OBEX,BT_BIP_RESPONDER_NOT_FOUND);
        return;
    }
    server = parms.obex.server;

    switch (event->event) {
    case GOEP_EVENT_TP_CONNECTED:
        //Report(("[BIP ADP] Server: Transport Connection has come up.\n"));
        break;

    case GOEP_EVENT_TP_DISCONNECTED:
        //Report(("[BIP ADP] Server: Transport Connection has been disconnected.\n"));

        if (server->object) {
            /* close any objects associated with the aborted operation */
            BIPOBS_Close(&server->object);
        }
        server->request.bipOp = BIPOP_CONNECT;
        BipAppCallBack(&parms, OB_STATUS_DISCONNECT, BIPRESPONDER_COMPLETE);

        server->request.offset = server->request.totLen = 0;
        break;

    case GOEP_EVENT_ABORTED:
		/*
        since OBEX do not updated now...
        if (event->abortReason != OBRC_LINK_DISCONNECT)
        */
		{
            /* Check if thumbnail is requested by Partial Content rspcode */		
        if ((event->oper == GOEP_OPER_PUSH) &&
			(server->object) && 
            (server->object->bipOp == BIPOP_PUT_IMAGE) &&
            (server->object->code == OBRC_PARTIAL_CONTENT)) {
            /* Handle the Partial Content special case on PutImage */
            BIPOBS_Close(&server->object);
            BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPRESPONDER_COMPLETE);
            break;
        }
        if ((event->oper == GOEP_OPER_PULL) && server->object &&
            (server->object->bipOp == BIPOP_GET_IMAGES_LIST) &&
            (server->object->code == OBRC_PARTIAL_CONTENT)) {
            /* Handle the Partial Content special case on PutImage */
            BIPOBS_Close(&server->object);
            BipAppCallBack(&parms, OBRC_PARTIAL_CONTENT, BIPRESPONDER_COMPLETE);
            break;
        }
		}

        kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_OPER_ABORTED, event->oper);
        if (server->object) {
            /* close any objects associated with the aborted operation */
            BIPOBS_Close(&server->object);
        }
            
        /* Tell the responder to abort */
        BipAppCallBack(&parms, 0, BIPRESPONDER_ABORT);
        break;

    case GOEP_EVENT_PRECOMPLETE:
        if ((event->oper == GOEP_OPER_PUSH) && 
            (server->object->bipOp == BIPOP_PUT_IMAGE) &&
            (server->object->code == OBRC_PARTIAL_CONTENT)) {
            /* Handle the Partial Content special case on PutImage */
            kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_PARTIAL_CONTENT_PUTIMG);
            GOEP_ServerAbort(&server->sApp, OBRC_PARTIAL_CONTENT);
        }
        else if ((event->oper == GOEP_OPER_PULL) && 
            (server->object->bipOp == BIPOP_GET_IMAGES_LIST) &&
            (server->object->code == OBRC_PARTIAL_CONTENT)) {
            /* Handle the Partial Content special case on PutImage */
            kal_trace(BT_TRACE_G6_OBEX,BT_BIP_SERVER_PARTIAL_CONTENT_GETIMGLIST);
	        
            GOEP_ServerAbort(&server->sApp, OBRC_PARTIAL_CONTENT);
        }
        break;

    case GOEP_EVENT_CONTINUE:
        status = OB_STATUS_SUCCESS;

        switch(event->oper) {
        case GOEP_OPER_DISCONNECT:
            status = OB_STATUS_DISCONNECT;
            /* No break; fall through */
        case GOEP_OPER_ABORT:
            /* <!-- added by yfchu on 2007.8.16 */
            GOEP_ServerContinue(&server->sApp);
            /* -->    */
            return;

        case GOEP_OPER_CONNECT:
            server->request.bipOp = BIPOP_CONNECT;
            break;
            
        case GOEP_OPER_PUSH:
            if ((server->object->bipOp == BIPOP_PUT_IMAGE) &&
                (event->info.pushpull.finalBit)) {
                /* Queue the Image Handle header in the final Put Response packet */
/*            Avoid to abort operation for lack of image handle info
                if (server->request.r.rImg.imgHandle[0] == 0) {
                GOEP_ServerAbort(&server->sApp, OBRC_INTERNAL_SERVER_ERR);
                }
*/
                if (server->request.r.rImg.imgHandle != 0) {
                    int i = 0;
                    
                    server->request.r.rImg.imgHandle[7] = 0;

                    while (server->request.r.rImg.imgHandle[i] != 0)
                    {
                        server->request.r.rImg.imgHandleUni[2*i] = 0;
                        server->request.r.rImg.imgHandleUni[2*i + 1] = server->request.r.rImg.imgHandle[i];
                        i++;
                    }
                    server->request.r.rImg.imgHandleUni[2*i] = 0;
                    server->request.r.rImg.imgHandleUni[2*i + 1] = 0;
        
                    if (GOEP_ServerQueueHeader(&server->sApp, BIPH_IMG_HANDLE,
                        (U8 *)server->request.r.rImg.imgHandleUni, (U16)(2*i+2)) == FALSE) {
                        GOEP_ServerAbort(&server->sApp, OBRC_INTERNAL_SERVER_ERR);
                    }
                }
            }
            else if (server->request.bipOp == BIPOP_PUT_IMAGE && 
                (server->request.r.rImg.name[0] == 0 &&
                server->request.r.rImg.name[1] == 0))
            {
                OS_MemCopy(server->request.r.rImg.name, server->object->name,
                    GOEP_MAX_UNICODE_LEN*2);
                server->request.r.rImg.img_len = server->object->objLen;
            }
            break;
        }

		parms.FinalPacket = event->info.pushpull.finalBit;
        BipAppCallBack(&parms, status, BIPRESPONDER_CONTINUE);
        break;

    case GOEP_EVENT_COMPLETE:
        switch (event->oper) {
        case GOEP_OPER_CONNECT:
            server->request.bipOp = BIPOP_CONNECT;
            BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPRESPONDER_COMPLETE);
            break;

        case GOEP_OPER_PUSH:
        case GOEP_OPER_PULL:
            rcode = BIPOBS_Close(&server->object);
            if (rcode != OBRC_SUCCESS) {
                GOEP_ServerAbort(&server->sApp, rcode);
            }
            BipAppCallBack(&parms, OB_STATUS_SUCCESS, BIPRESPONDER_COMPLETE);
            break;

        default:
            break;
        }

        //Report(("BIP: Server: %d operation complete.\n", event->oper));
        server->request.offset = server->request.totLen = 0;
        server->request.bipOp = BIPOP_NOP;
        break;

    case GOEP_EVENT_START:
        if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) {
            BipObexServer  *rServer = parms.obex.server;

            rServer->object = BIPOBS_New(&rServer->sApp);
            Assert(rServer->object);

            /* New operation, initialize BipData */
            OS_MemSet((U8 *)&rServer->request, 0, sizeof(BipData));
        } 
		if (event->oper == GOEP_OPER_CONNECT)
		{
            BipObexServer  *rServer = parms.obex.server;
            /* New operation, initialize connect target */
            OS_MemSet(rServer->request.r.rConnect.targetUuid, 0, sizeof(rServer->request.r.rConnect.targetUuid));
			rServer->request.r.rConnect.targetLen = 0;
            rServer->request.r.rConnect.targetService = 0;
		}
        break;

    case GOEP_EVENT_HEADER_RX:
        switch (event->header.type) {
        case OBEXH_LENGTH:
            if (event->oper == GOEP_OPER_PUSH) {
                /* Set the object length for Put operations only */
                BIPOBS_SetObjectLen(server->object, event->info.pushpull.objectLen);
            }
            break;

        case BIPH_IMG_DESCRIPTION:
            if (event->header.len == 0 ||
                event->header.len == event->header.totalLen) {
                /* reset the offset */
                server->request.offset = 0;
            }
            if (event->header.len != 0) {
                /* tell the responder we have data */
                server->request.totLen = event->header.totalLen;
                server->request.len = event->header.len;

                switch (server->request.bipOp) {
                case BIPOP_GET_IMAGES_LIST:
                    server->request.i.iHDsc.buff = event->header.buffer;
                    server->request.dataType = BIPIND_HANDLES_DESCRIPTOR;
                    break;

                case BIPOP_PUT_IMAGE:
                case BIPOP_GET_IMAGE:
                    server->request.i.iIDsc.buff = event->header.buffer;
                    server->request.dataType = BIPIND_IMAGE_DESCRIPTOR;
                    break;

                default:
                    if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) {
                        BipResponderOp(event, &parms);
                    }
                    server->request.i.iIDsc.buff = event->header.buffer;
                    server->request.dataType = BIPIND_IMAGE_DESCRIPTOR;
                    break;
                }

                BipAppCallBack(&parms, 0, BIPRESPONDER_DATA_IND);

                /* Check if we have the entire description */
                if (server->request.totLen >
                    event->header.len + server->request.offset) {
                    server->request.offset += event->header.len;
                }
                else {
                    /* Set the offset back to null */
                    server->request.offset = server->request.totLen = 0;
                }
            }
            break;

        case BIPH_IMG_HANDLE:
            /* GOEP indicates the entire Unicode header */
            if (event->header.len != 0) {
                int i;
                switch (server->request.bipOp) {
                case BIPOP_GET_IMAGE_PROPERTIES:
                    ih = server->request.r.rProp.imgHandle;
                    break;

                case BIPOP_PUT_LINKED_THUMBNAIL:
                case BIPOP_GET_LINKED_THUMBNAIL:
                    ih = server->request.r.rThm.imgHandle;
                    break;

                case BIPOP_GET_IMAGE:
                    ih = server->request.r.rImg.imgHandle;
                    break;

                default:
                    /* We must not have the type header yet. Assume this is
                     * a PUT_LINKED_THUMBNAIL.
                     */
                    if (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH) {
                        BipResponderOp(event, &parms);
                    ih = server->request.r.rThm.imgHandle;
                    }
                    break;
                }

                /* copy the data from the buffer */
				if (ih != NULL)
				{
	                for(i = 0; i < (event->header.len/2); i++)
	                {
	                    ih[i] = event->header.buffer[2*i+1];
	                }
					/*OS_MemCopy((U8 *)ih, event->header.buffer, event->header.len); */
				}
            }
            break;

        case OBEXH_APP_PARAMS:
            /* Check for parameters */
            if (event->header.len == 0) {
                break;
            }

            /* Reassemble the parameters */
			ASSERT(server->appParms[0] + event->header.len <= sizeof(server->appParms));
            p = server->appParms + server->appParms[0] + 1;
            OS_MemCopy(p, event->header.buffer, event->header.len);
            server->appParms[0] += event->header.len;

            if (server->appParms[0] == event->header.totalLen) {
                /* Parse the App Parameters */
                p = server->appParms + 1;
                while (p - (server->appParms + 1) < event->header.totalLen) {
                    switch (p[0]) {
                    case BIPAPTAG_NB_RETURNED_HANDLES:
                        server->request.r.rList.nbReturnedHandles =
                            BEtoHost16(p + 2);
                        break;

                    case BIPAPTAG_LIST_START_OFFSET:
                        server->request.r.rList.listStartOffset =
                            BEtoHost16(p + 2);
                        break;

                    case BIPAPTAG_LATEST_CAPTURED_IMAGES:
                        server->request.r.rList.latestCapturedImages = p[2];
                        break;

                    case BIPAPTAG_STORE_FLAG:
                        server->request.r.rMon.storeFlag = p[2];
                        break;

                    case BIPAPTAG_PARTIAL_FILE_LENGTH:
                    case BIPAPTAG_PARTIAL_FILE_START_OFFSET:
                    case BIPAPTAG_TOTAL_FILE_SIZE:
                    case BIPAPTAG_END_FLAG:
                    case BIPAPTAG_REMOTE_DISPLAY:
                    case BIPAPTAG_SERVICE_ID:
                        break;

                    default:
                        break;
                    }
                    p += p[1] + 2;
                }
                /* Reset the App Param length */
                server->appParms[0] = 0;
            }
            break;

        case OBEXH_BODY:
            break;

        case OBEXH_END_BODY:
            break;

        case OBEXH_TARGET: /* CONNECT TARGET header */
			{    
				U8 len;

	            /* Reassemble the header */
				ASSERT (server->request.r.rConnect.targetLen + event->header.len <= sizeof(server->request.r.rConnect.targetUuid));
	            p = (U8*)(server->request.r.rConnect.targetUuid) + server->request.r.rConnect.targetLen;
	            OS_MemCopy(p, event->header.buffer, event->header.len);
	            server->request.r.rConnect.targetLen += event->header.len;

				len = server->request.r.rConnect.targetLen;
				p = (U8 *)(server->request.r.rConnect.targetUuid);
	            if (len == event->header.totalLen) 
				{
				    BipService targetService = 0;
				   
				    /* target header received */
	                if (OS_MemCmp(p, len, server->bipImgPullUuid, sizeof(server->bipImgPullUuid)))
	                {
	                    targetService = BIPSVC_IMAGE_PULL;
	                }
					else if (OS_MemCmp(p, len, server->bipImgPushUuid, sizeof(server->bipImgPushUuid)))
	                {
	                    targetService = BIPSVC_IMAGE_PUSH;
	                }

					server->request.r.rConnect.targetService = targetService;
	            }
        	}
			
            break;

        default:
            break;
        }
        break;

    case GOEP_EVENT_PROVIDE_OBJECT:
        /* If an operation has not yet been assigned, figure it out */
        if ((server->request.bipOp == BIPOP_NOP) &&
            (event->oper == GOEP_OPER_PULL || event->oper == GOEP_OPER_PUSH)) {
            BipResponderOp(event, &parms);
        }

        if (event->oper == GOEP_OPER_PULL &&
            server->request.bipOp & BIPOP_PULL_MASK) {
            BipAppCallBack(&parms, 0, BIPRESPONDER_REQUEST);
            if ((server->object->objLen != 0) &&
                (server->request.bipOp == BIPOP_GET_IMAGE ||
                server->request.bipOp == BIPOP_GET_MONITORING_IMAGE)) {
                /* Setup the LENGTH header for a Get Image response only */
                event->info.pushpull.objectLen = server->object->objLen;
            } else {
                /* Make sure we do not issue a LENGTH header for any other responses.  It
                 * is possible that we could have a value, if we received a LENGTH header 
                 * in a GET Request, so we always want to reset this value to zero.
                 */
                event->info.pushpull.objectLen = 0;
            }
        }
        else if (event->oper == GOEP_OPER_PUSH &&
            (server->request.bipOp == BIPOP_PUT_IMAGE ||
            server->request.bipOp == BIPOP_PUT_LINKED_THUMBNAIL)) {
            if (server->request.bipOp == BIPOP_PUT_IMAGE) {
                OS_MemCopy(server->request.r.rImg.name, server->object->name,
                    GOEP_MAX_UNICODE_LEN*2);
                server->request.r.rImg.img_len = server->object->objLen;
            }
            BipAppCallBack(&parms, 0, BIPRESPONDER_REQUEST);
        }
        GOEP_ServerAccept(&server->sApp, server->object);
        break;

    case GOEP_EVENT_AUTHORIZE_IND:
        BipAppCallBack(&parms, 0, BIPRESPONDER_AUTHORIZE_IND);
        break;

#if OBEX_AUTHENTICATION == XA_ENABLED

    case GOEP_EVENT_AUTH_CHALLENGE:
        parms.challenge = &event->challenge;
        BipAppCallBack(&parms, 0, BIP_OBAUTH_CHAL);
        break;

    case GOEP_EVENT_AUTH_RESPONSE:
        parms.response = &event->response;
        BipAppCallBack(&parms, 0, BIP_OBAUTH_RSP);
        break;
        
#endif /* OBEX_AUTHENTICATION == XA_ENABLED */

    default:
        //Report(("BIP: Server Event %d ignored.\n", event));
        break;
    }
}
Exemple #6
0
static void BleServiceDbRemoveRecord(const BD_ADDR *bd_addr)
{
    S32 fd;
    S32 fd_temp;
    S32 pos_current;
    S32 pos_end;
    U8 *db_buff;
    U8 *buffer;
    
    if (!btmtk_fs_is_dir_exist((const U8*)BLE_SERVICE_DATABASE_FILE))
    {
        return;
    }
    
    fd = btmtk_fs_open((const U8*)BLE_SERVICE_DATABASE_FILE, BTMTK_FS_READ_WRITE);
    if (fd < 0)
    {
        return;
    }

    pos_end = btmtk_fs_seek(fd, 0, BTMTK_FS_SEEK_END);
    pos_current = btmtk_fs_seek(fd, 0, BTMTK_FS_SEEK_BEGIN);

    db_buff = (U8 *)get_ctrl_buffer(sizeof(ble_service_db) - sizeof(ListEntry));
    while (pos_current < pos_end)
    {
        btmtk_fs_read(fd, db_buff, sizeof(ble_service_db) - sizeof(ListEntry));
        if (OS_MemCmp(db_buff, 6, bd_addr->addr, 6))
        {
            break;
        }
        pos_current += (sizeof(ble_service_db) - sizeof(ListEntry));
    }
    free_ctrl_buffer(db_buff);

    if (pos_current == pos_end)
    {
        Report(("[BleDB] Remove record, NOT FOUND!"));    
//        kal_trace(BT_TRACE_BLE_PROFILES, BLEDB_REMOVERECORD_NOTFOUND);.
        return;
    }

    /* Case 1:  If there is only one database, delete the file directly */
    if (pos_end - pos_current == sizeof(ble_service_db) - sizeof(ListEntry))
    {
        Report(("[BleDB] Remove record, delete file directly..."));    
    
//        kal_trace(BT_TRACE_BLE_PROFILES, BLEDB_REMOVERECORD_DELETEFILE);
        btmtk_fs_delete((const U8 *)BLE_SERVICE_DATABASE_FILE);
        return;
    }

    /* Case 2:  If there is more than one database, create a new temp file, 
    *   move the left database to the temp file, delete the original database
    *   file, and rename the temp file as the new database file. 
    */
    fd_temp = btmtk_fs_open((const U8*)BLE_SERVICE_DATABASE_TEMP_FILE, BTMTK_FS_READ_WRITE | BTMTK_FS_CREATE);
    if (fd_temp < 0)
    {
        return;
    }

    if (pos_current > 0)
    {
        /* Move first half of the database to temp file */
        buffer = (U8 *)get_ctrl_buffer(pos_current);
        btmtk_fs_seek(fd, 0, BTMTK_FS_SEEK_BEGIN);
        btmtk_fs_read(fd, buffer, pos_current);
        btmtk_fs_write(fd_temp, buffer, pos_current);
        free_ctrl_buffer(buffer);
        
    }
    pos_current = btmtk_fs_seek(fd, sizeof(ble_service_db) - sizeof(ListEntry), BTMTK_FS_SEEK_CURRENT);

    if (pos_current < pos_end)
    {
        /* Move first half of the database to temp file */
        buffer = (U8 *)get_ctrl_buffer(pos_end - pos_current);
        btmtk_fs_read(fd, buffer, pos_end - pos_current);
        btmtk_fs_write(fd_temp, buffer, pos_end - pos_current);
        free_ctrl_buffer(buffer);
    }

    Report(("[BleDB] pos cur: %d, pos end: %d", pos_current, pos_end));

    btmtk_fs_close(fd);
    btmtk_fs_close(fd_temp);

    btmtk_fs_delete((const U8 *)BLE_SERVICE_DATABASE_FILE);
    btmtk_fs_rename((const U8 *)BLE_SERVICE_DATABASE_TEMP_FILE, (const U8 *)BLE_SERVICE_DATABASE_FILE);
}