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:      userial_vendor.c
20 *
21 *  Description:   Contains vendor-specific userial functions
22 *
23 ******************************************************************************/
24
25#define LOG_TAG "bt_userial_vendor"
26
27#include <utils/Log.h>
28#include <termios.h>
29#include <fcntl.h>
30#include <errno.h>
31#include <stdio.h>
32#include "bt_vendor_qcom.h"
33#include "userial_vendor.h"
34
35bt_hci_transport_device_type bt_hci_set_transport()
36{
37    int ret;
38    char transport_type[10] = {0,};
39    bt_hci_transport_device_type bt_hci_transport_device;
40
41    ret = property_get("ro.qualcomm.bt.hci_transport", transport_type, NULL);
42    if(ret == 0)
43        printf("ro.qualcomm.bt.hci_transport not set\n");
44    else
45        printf("ro.qualcomm.bt.hci_transport: %s \n", transport_type);
46
47    if (!strcasecmp(transport_type, "smd"))
48    {
49        bt_hci_transport_device.type = BT_HCI_SMD;
50        bt_hci_transport_device.name = APPS_RIVA_BT_CMD_CH;
51        bt_hci_transport_device.pkt_ind = 1;
52    }
53    else{
54        bt_hci_transport_device.type = BT_HCI_UART;
55        bt_hci_transport_device.name = BT_HS_UART_DEVICE;
56        bt_hci_transport_device.pkt_ind = 0;
57    }
58
59    return bt_hci_transport_device;
60}
61
62#define NUM_OF_DEVS 2
63static char *s_pszDevSmd[] = {
64    "/dev/smd3",
65    "/dev/smd2"
66};
67
68int bt_hci_init_transport(int *pFd)
69{
70    int i = 0;
71    int fd;
72    for(i=0; i < NUM_OF_DEVS; i++){
73       fd = bt_hci_init_transport_id(i);
74       if(fd < 0 ){
75          return -1;
76       }
77       pFd[i] = fd;
78    }
79    return 0;
80}
81
82int bt_hci_init_transport_id (int chId )
83{
84  struct termios   term;
85  int fd = -1;
86  int retry = 0;
87
88  if(chId > 2 || chId <0)
89     return -1;
90
91  fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
92
93  while ((-1 == fd) && (retry < 7)) {
94    ALOGE("init_transport: Cannot open %s: %s\n. Retry after 2 seconds",
95        bt_hci_transport_device.name, strerror(errno));
96    usleep(2000000);
97    fd = open(bt_hci_transport_device.name, (O_RDWR | O_NOCTTY));
98    retry++;
99  }
100
101  if (-1 == fd)
102  {
103    ALOGE("init_transport: Cannot open %s: %s\n",
104        bt_hci_transport_device.name, strerror(errno));
105    return -1;
106  }
107
108  /* Sleep (0.5sec) added giving time for the smd port to be successfully
109     opened internally. Currently successful return from open doesn't
110     ensure the smd port is successfully opened.
111     TODO: Following sleep to be removed once SMD port is successfully
112     opened immediately on return from the aforementioned open call */
113  if(BT_HCI_SMD == bt_hci_transport_device.type)
114     usleep(500000);
115
116  if (tcflush(fd, TCIOFLUSH) < 0)
117  {
118    ALOGE("init_uart: Cannot flush %s\n", bt_hci_transport_device.name);
119    close(fd);
120    return -1;
121  }
122
123  if (tcgetattr(fd, &term) < 0)
124  {
125    ALOGE("init_uart: Error while getting attributes\n");
126    close(fd);
127    return -1;
128  }
129
130  cfmakeraw(&term);
131
132  /* JN: Do I need to make flow control configurable, since 4020 cannot
133   * disable it?
134   */
135  term.c_cflag |= (CRTSCTS | CLOCAL);
136
137  if (tcsetattr(fd, TCSANOW, &term) < 0)
138  {
139    ALOGE("init_uart: Error while getting attributes\n");
140    close(fd);
141    return -1;
142  }
143
144  ALOGI("Done intiailizing UART\n");
145  return fd;
146}
147
148int bt_hci_deinit_transport(int *pFd)
149{
150    close(pFd[0]);
151    close(pFd[1]);
152    return TRUE;
153}
154