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