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
bt_hci_set_transport()35 bt_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
63 static char *s_pszDevSmd[] = {
64 "/dev/smd3",
65 "/dev/smd2"
66 };
67
bt_hci_init_transport(int * pFd)68 int 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
bt_hci_init_transport_id(int chId)82 int 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
bt_hci_deinit_transport(int * pFd)148 int bt_hci_deinit_transport(int *pFd)
149 {
150 close(pFd[0]);
151 close(pFd[1]);
152 return TRUE;
153 }
154