1ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev/*
2ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * Copyright 2012 The Android Open Source Project
3ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
4ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License");
5ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * you may not use this file except in compliance with the License.
6ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * You may obtain a copy of the License at
7ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
8ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *      http://www.apache.org/licenses/LICENSE-2.0
9ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
10ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * Unless required by applicable law or agreed to in writing, software
11ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS,
12ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * See the License for the specific language governing permissions and
14ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev * limitations under the License.
15ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev */
16ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
17ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev/******************************************************************************
18ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
19ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *  Filename:      userial_vendor.c
20ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
21ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *  Description:   Contains vendor-specific userial functions
22ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev *
23ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev ******************************************************************************/
24ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
25ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#define LOG_TAG "bt_userial_vendor"
26ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
27ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include <utils/Log.h>
28ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include <termios.h>
29ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include <fcntl.h>
30ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include <errno.h>
31ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include <stdio.h>
32ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include "bt_vendor_qcom.h"
33ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#include "userial_vendor.h"
34ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
35ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchevbt_hci_transport_device_type bt_hci_set_transport()
36ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev{
37ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    int ret;
38ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    char transport_type[10] = {0,};
39ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    bt_hci_transport_device_type bt_hci_transport_device;
40ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
41ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ret = property_get("ro.qualcomm.bt.hci_transport", transport_type, NULL);
42ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    if(ret == 0)
43ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        printf("ro.qualcomm.bt.hci_transport not set\n");
44ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    else
45ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        printf("ro.qualcomm.bt.hci_transport: %s \n", transport_type);
46ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
47ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    if (!strcasecmp(transport_type, "smd"))
48ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    {
49ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.type = BT_HCI_SMD;
50ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.name = APPS_RIVA_BT_CMD_CH;
51ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.pkt_ind = 1;
52ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    }
53ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    else{
54ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.type = BT_HCI_UART;
55ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.name = BT_HS_UART_DEVICE;
56ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.pkt_ind = 0;
57ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    }
58ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
59ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return bt_hci_transport_device;
60ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev}
61ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
62ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev#define NUM_OF_DEVS 2
63ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchevstatic char *s_pszDevSmd[] = {
64ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    "/dev/smd3",
65ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    "/dev/smd2"
66ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev};
67ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
68ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchevint bt_hci_init_transport(int *pFd)
69ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev{
70ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    int i = 0;
71ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    int fd;
72ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    for(i=0; i < NUM_OF_DEVS; i++){
73ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev       fd = bt_hci_init_transport_id(i);
74ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev       if(fd < 0 ){
75ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev          return -1;
76ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev       }
77ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev       pFd[i] = fd;
78ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    }
79ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return 0;
80ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev}
81ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
82ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchevint bt_hci_init_transport_id (int chId )
83ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev{
84ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  struct termios   term;
85ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  int fd = -1;
86ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  int retry = 0;
87ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
88ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if(chId > 2 || chId <0)
89ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     return -1;
90ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
91ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
92ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
93ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  while ((-1 == fd) && (retry < 7)) {
94ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ALOGE("init_transport: Cannot open %s: %s\n. Retry after 2 seconds",
95ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.name, strerror(errno));
96ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    usleep(2000000);
97ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    fd = open(bt_hci_transport_device.name, (O_RDWR | O_NOCTTY));
98ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    retry++;
99ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  }
100ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
101ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if (-1 == fd)
102ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  {
103ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ALOGE("init_transport: Cannot open %s: %s\n",
104ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev        bt_hci_transport_device.name, strerror(errno));
105ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return -1;
106ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  }
107ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
108ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  /* Sleep (0.5sec) added giving time for the smd port to be successfully
109ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     opened internally. Currently successful return from open doesn't
110ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     ensure the smd port is successfully opened.
111ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     TODO: Following sleep to be removed once SMD port is successfully
112ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     opened immediately on return from the aforementioned open call */
113ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if(BT_HCI_SMD == bt_hci_transport_device.type)
114ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev     usleep(500000);
115ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
116ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if (tcflush(fd, TCIOFLUSH) < 0)
117ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  {
118ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ALOGE("init_uart: Cannot flush %s\n", bt_hci_transport_device.name);
119ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    close(fd);
120ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return -1;
121ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  }
122ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
123ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if (tcgetattr(fd, &term) < 0)
124ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  {
125ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ALOGE("init_uart: Error while getting attributes\n");
126ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    close(fd);
127ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return -1;
128ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  }
129ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
130ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  cfmakeraw(&term);
131ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
132ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  /* JN: Do I need to make flow control configurable, since 4020 cannot
133ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev   * disable it?
134ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev   */
135ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  term.c_cflag |= (CRTSCTS | CLOCAL);
136ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
137ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  if (tcsetattr(fd, TCSANOW, &term) < 0)
138ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  {
139ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    ALOGE("init_uart: Error while getting attributes\n");
140ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    close(fd);
141ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return -1;
142ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  }
143ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
144ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  ALOGI("Done intiailizing UART\n");
145ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev  return fd;
146ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev}
147ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev
148ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchevint bt_hci_deinit_transport(int *pFd)
149ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev{
150ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    close(pFd[0]);
151ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    close(pFd[1]);
152ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev    return TRUE;
153ad7eab092dae95101a71f1dd758086ad042dcf1dIliyan Malchev}
154