10ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*
20ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Copyright 2012 The Android Open Source Project
30ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
40ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Licensed under the Apache License, Version 2.0 (the "License");
50ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * you may not use this file except in compliance with the License.
60ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * You may obtain a copy of the License at
70ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
80ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *      http://www.apache.org/licenses/LICENSE-2.0
90ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Unless required by applicable law or agreed to in writing, software
110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * distributed under the License is distributed on an "AS IS" BASIS,
120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * See the License for the specific language governing permissions and
140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * limitations under the License.
150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel */
160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Filename:      hardware.c
200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Description:   Contains controller-specific functions, like
220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *                      firmware patch download
230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *                      low power mode operations
240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel ******************************************************************************/
260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define LOG_TAG "bt_vendor"
280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <utils/Log.h>
300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <sys/types.h>
310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <sys/stat.h>
320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <signal.h>
330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <time.h>
340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <errno.h>
350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <fcntl.h>
360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <dirent.h>
370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <ctype.h>
380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <cutils/properties.h>
390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <stdlib.h>
400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_hci_bdroid.h"
410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_vendor_qcom.h"
420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <string.h>
430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define MAX_CNT_RETRY 100
440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint hw_config(int nState)
460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char *szState[] = {"true", "false"};
480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char *szReqSt = NULL;
490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char szBtSocStatus[PROPERTY_VALUE_MAX] = {'\0', };
500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(nState == BT_VND_PWR_OFF)
520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        szReqSt = szState[1];
530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else
540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        szReqSt = szState[0];
550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if((property_get("bluetooth.status", szBtSocStatus, "") <= 0))
570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       if(nState == BT_VND_PWR_ON ) {
590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          ALOGW("Hw_config: First Time BT on after boot.Starting hciattach daemon BTStatus=%s",szBtSocStatus);
600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          if (property_set("bluetooth.hciattach", szReqSt) < 0)
610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          {
620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              ALOGE("Hw_config: Property Setting fail");
630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              return -1;
640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          }
650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    } else if( !(strncmp(szBtSocStatus, "on", strlen("on")))) {
670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          //BTSOC is already on
680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          ALOGW("Hw_config: nState = %d", nState);
690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    } else {
700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          ALOGW("Hw_config: trigerring hciattach");
710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          if (property_set("bluetooth.hciattach", szReqSt) < 0)
720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          {
730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              ALOGE("Hw_config: Property Setting fail");
740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              return -1;
750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          }
760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return 0;
790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint readTrpState()
820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char szBtStatus[PROPERTY_VALUE_MAX] = {0, };
840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(property_get("bluetooth.status", szBtStatus, "") < 0){
850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("Fail to get bluetooth status");
860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return FALSE;
870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(!strncmp(szBtStatus, "on", strlen("on"))){
900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGI("bluetooth status is on");
910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return TRUE;
920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return FALSE;
940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint is_hw_ready()
970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int i=0;
990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char szStatus[10] = {0,};
1000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    for(i=MAX_CNT_RETRY; i>0; i--){
1020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       //TODO :: checking routine
1030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       if(readTrpState()==TRUE){
1040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           break;
1050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
1060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       usleep(50*1000);
1070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return (i==0)? FALSE:TRUE;
1090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
1120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*******************************************************************************
1130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** Function         hw_epilog_cback
1150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** Description      Callback function for Command Complete Events from HCI
1170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**                  commands sent in epilog process.
1180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** Returns          None
1200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*******************************************************************************/
1220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelvoid hw_epilog_cback(void *p_mem)
1230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
1250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char        *p_name, *p_tmp;
1260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    uint8_t     *p, status;
1270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    uint16_t    opcode;
1280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
1300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
1310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    STREAM_TO_UINT16(opcode,p);
1320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
1340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1355752ddcecf884adefc166873565da60e70f59400Thierry Strudel    pthread_mutex_lock(&q_lock);
1365752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (!q) {
1375752ddcecf884adefc166873565da60e70f59400Thierry Strudel        ALOGE("hw_epilog_cback called with NULL context");
1385752ddcecf884adefc166873565da60e70f59400Thierry Strudel        goto out;
1395752ddcecf884adefc166873565da60e70f59400Thierry Strudel    }
14020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    /* Must free the RX event buffer */
1415752ddcecf884adefc166873565da60e70f59400Thierry Strudel    q->cb->dealloc(p_evt_buf);
14220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
14320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    /* Once epilog process is done, must call callback to notify caller */
1445752ddcecf884adefc166873565da60e70f59400Thierry Strudel    q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
1455752ddcecf884adefc166873565da60e70f59400Thierry Strudelout:
1465752ddcecf884adefc166873565da60e70f59400Thierry Strudel    pthread_mutex_unlock(&q_lock);
1470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*******************************************************************************
1500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** Function         hw_epilog_process
1520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
15320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel** Description      Sample implementation of epilog process. This process is
1545752ddcecf884adefc166873565da60e70f59400Thierry Strudel**                  called with q_lock held and q->cb is assumed to be valid.
1550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** Returns          None
1570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
1580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*******************************************************************************/
15920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelvoid __hw_epilog_process(void)
1600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    HC_BT_HDR  *p_buf = NULL;
1620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    uint8_t     *p;
1630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("hw_epilog_process");
1650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* Sending a HCI_RESET */
16720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    /* Must allocate command buffer via HC's alloc API */
1685752ddcecf884adefc166873565da60e70f59400Thierry Strudel    p_buf = (HC_BT_HDR *) q->cb->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE);
1690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (p_buf)
1700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
1710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
1720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        p_buf->offset = 0;
1730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        p_buf->layer_specific = 0;
1740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
1750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        p = (uint8_t *) (p_buf + 1);
1770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        UINT16_TO_STREAM(p, HCI_RESET);
1780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        *p = 0; /* parameter length */
1790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        /* Send command via HC's xmit_cb API */
1815752ddcecf884adefc166873565da60e70f59400Thierry Strudel        q->cb->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
1820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else
1840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
18520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ALOGE("vendor lib epilog process aborted [no buffer]");
1865752ddcecf884adefc166873565da60e70f59400Thierry Strudel        q->cb->epilog_cb(BT_VND_OP_RESULT_FAIL);
1870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif // (HW_NEED_END_WITH_HCI_RESET == TRUE)
190