1/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/******************************************************************************
18 *
19 *  Filename:      hardware.c
20 *
21 *  Description:   Contains controller-specific functions, like
22 *                      firmware patch download
23 *                      low power mode operations
24 *
25 ******************************************************************************/
26
27#define LOG_TAG "bt_vendor"
28
29#include <utils/Log.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <signal.h>
33#include <time.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <dirent.h>
37#include <ctype.h>
38#include <cutils/properties.h>
39#include <stdlib.h>
40#include <string.h>
41#include "bt_hci_bdroid.h"
42#include "bt_vendor_qcom.h"
43#include <string.h>
44#define MAX_CNT_RETRY 100
45
46int hw_config(int nState)
47{
48    char *szState[] = {"true", "false"};
49    char *szReqSt = NULL;
50    char szBtSocStatus[PROPERTY_VALUE_MAX] = {'\0', };
51
52    if(nState == BT_VND_PWR_OFF)
53        szReqSt = szState[1];
54    else
55        szReqSt = szState[0];
56
57    if((property_get("bluetooth.status", szBtSocStatus, "") <= 0))
58    {
59       if(nState == BT_VND_PWR_ON ) {
60          ALOGW("Hw_config: First Time BT on after boot.Starting hciattach daemon BTStatus=%s",szBtSocStatus);
61          if (property_set("bluetooth.hciattach", szReqSt) < 0)
62          {
63              ALOGE("Hw_config: Property Setting fail");
64              return -1;
65          }
66       }
67    } else if( !(strncmp(szBtSocStatus, "on", strlen("on")))) {
68          //BTSOC is already on
69          ALOGW("Hw_config: nState = %d", nState);
70    } else {
71          ALOGW("Hw_config: trigerring hciattach");
72          if (property_set("bluetooth.hciattach", szReqSt) < 0)
73          {
74              ALOGE("Hw_config: Property Setting fail");
75              return -1;
76          }
77    }
78
79    return 0;
80}
81
82int readTrpState()
83{
84    char szBtStatus[PROPERTY_VALUE_MAX] = {0, };
85    if(property_get("bluetooth.status", szBtStatus, "") < 0){
86        ALOGE("Fail to get bluetooth status");
87        return FALSE;
88    }
89
90    if(!strncmp(szBtStatus, "on", strlen("on"))){
91        ALOGI("bluetooth status is on");
92        return TRUE;
93    }
94    return FALSE;
95}
96
97int is_hw_ready()
98{
99    int i=0;
100    char szStatus[10] = {0,};
101
102    for(i=MAX_CNT_RETRY; i>0; i--){
103       //TODO :: checking routine
104       if(readTrpState()==TRUE){
105           break;
106       }
107       usleep(50*1000);
108    }
109    return (i==0)? FALSE:TRUE;
110}
111
112#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
113/*******************************************************************************
114**
115** Function         hw_epilog_cback
116**
117** Description      Callback function for Command Complete Events from HCI
118**                  commands sent in epilog process.
119**
120** Returns          None
121**
122*******************************************************************************/
123void hw_epilog_cback(void *p_mem)
124{
125    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
126    char        *p_name, *p_tmp;
127    uint8_t     *p, status;
128    uint16_t    opcode;
129
130    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
131    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
132    STREAM_TO_UINT16(opcode,p);
133
134    ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
135
136    if (bt_vendor_cbacks)
137    {
138        /* Must free the RX event buffer */
139        bt_vendor_cbacks->dealloc(p_evt_buf);
140
141        /* Once epilog process is done, must call callback to notify caller */
142        bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
143    }
144}
145
146/*******************************************************************************
147**
148** Function         hw_epilog_process
149**
150** Description      Sample implementation of epilog process
151**
152** Returns          None
153**
154*******************************************************************************/
155void hw_epilog_process(void)
156{
157    HC_BT_HDR  *p_buf = NULL;
158    uint8_t     *p;
159
160    ALOGI("hw_epilog_process");
161
162    /* Sending a HCI_RESET */
163    if (bt_vendor_cbacks)
164    {
165        /* Must allocate command buffer via HC's alloc API */
166        p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
167                                                       HCI_CMD_PREAMBLE_SIZE);
168    }
169
170    if (p_buf)
171    {
172        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
173        p_buf->offset = 0;
174        p_buf->layer_specific = 0;
175        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
176
177        p = (uint8_t *) (p_buf + 1);
178        UINT16_TO_STREAM(p, HCI_RESET);
179        *p = 0; /* parameter length */
180
181        /* Send command via HC's xmit_cb API */
182        bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
183    }
184    else
185    {
186        if (bt_vendor_cbacks)
187        {
188            ALOGE("vendor lib epilog process aborted [no buffer]");
189            bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
190        }
191    }
192}
193#endif // (HW_NEED_END_WITH_HCI_RESET == TRUE)
194