1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  Filename:      userial_vendor.c
22  *
23  *  Description:   Contains vendor-specific userial functions
24  *
25  ******************************************************************************/
26 
27 #define LOG_TAG "bt_userial_vendor"
28 
29 #include <utils/Log.h>
30 #include <termios.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include "bt_vendor_brcm.h"
36 #include "userial.h"
37 #include "userial_vendor.h"
38 
39 /******************************************************************************
40 **  Constants & Macros
41 ******************************************************************************/
42 
43 #ifndef VNDUSERIAL_DBG
44 #define VNDUSERIAL_DBG FALSE
45 #endif
46 
47 #if (VNDUSERIAL_DBG == TRUE)
48 #define VNDUSERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
49 #else
50 #define VNDUSERIALDBG(param, ...) {}
51 #endif
52 
53 #define VND_PORT_NAME_MAXLEN    256
54 
55 /******************************************************************************
56 **  Local type definitions
57 ******************************************************************************/
58 
59 /* vendor serial control block */
60 typedef struct
61 {
62     int fd;                     /* fd to Bluetooth device */
63     struct termios termios;     /* serial terminal of BT port */
64     char port_name[VND_PORT_NAME_MAXLEN];
65 } vnd_userial_cb_t;
66 
67 /******************************************************************************
68 **  Static variables
69 ******************************************************************************/
70 
71 static vnd_userial_cb_t vnd_userial;
72 
73 /*****************************************************************************
74 **   Helper Functions
75 *****************************************************************************/
76 
77 /*******************************************************************************
78 **
79 ** Function        userial_to_tcio_baud
80 **
81 ** Description     helper function converts USERIAL baud rates into TCIO
82 **                  conforming baud rates
83 **
84 ** Returns         TRUE/FALSE
85 **
86 *******************************************************************************/
userial_to_tcio_baud(uint8_t cfg_baud,uint32_t * baud)87 uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud)
88 {
89     if (cfg_baud == USERIAL_BAUD_115200)
90         *baud = B115200;
91     else if (cfg_baud == USERIAL_BAUD_4M)
92         *baud = B4000000;
93     else if (cfg_baud == USERIAL_BAUD_3M)
94         *baud = B3000000;
95     else if (cfg_baud == USERIAL_BAUD_2M)
96         *baud = B2000000;
97     else if (cfg_baud == USERIAL_BAUD_1M)
98         *baud = B1000000;
99     else if (cfg_baud == USERIAL_BAUD_921600)
100         *baud = B921600;
101     else if (cfg_baud == USERIAL_BAUD_460800)
102         *baud = B460800;
103     else if (cfg_baud == USERIAL_BAUD_230400)
104         *baud = B230400;
105     else if (cfg_baud == USERIAL_BAUD_57600)
106         *baud = B57600;
107     else if (cfg_baud == USERIAL_BAUD_19200)
108         *baud = B19200;
109     else if (cfg_baud == USERIAL_BAUD_9600)
110         *baud = B9600;
111     else if (cfg_baud == USERIAL_BAUD_1200)
112         *baud = B1200;
113     else if (cfg_baud == USERIAL_BAUD_600)
114         *baud = B600;
115     else
116     {
117         ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud);
118         *baud = B115200;
119         return FALSE;
120     }
121 
122     return TRUE;
123 }
124 
125 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
126 /*******************************************************************************
127 **
128 ** Function        userial_ioctl_init_bt_wake
129 **
130 ** Description     helper function to set the open state of the bt_wake if ioctl
131 **                  is used. it should not hurt in the rfkill case but it might
132 **                  be better to compile it out.
133 **
134 ** Returns         none
135 **
136 *******************************************************************************/
userial_ioctl_init_bt_wake(int fd)137 void userial_ioctl_init_bt_wake(int fd)
138 {
139     uint32_t bt_wake_state;
140 
141 #if (BT_WAKE_USERIAL_LDISC==TRUE)
142     int ldisc = N_BRCM_HCI; /* brcm sleep mode support line discipline */
143 
144     /* attempt to load enable discipline driver */
145     if (ioctl(vnd_userial.fd, TIOCSETD, &ldisc) < 0)
146     {
147         VNDUSERIALDBG("USERIAL_Open():fd %d, TIOCSETD failed: error %d for ldisc: %d",
148                       fd, errno, ldisc);
149     }
150 #endif
151 
152 
153 
154     /* assert BT_WAKE through ioctl */
155     ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
156     ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state);
157     VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \
158                bt_wake_state);
159 }
160 #endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
161 
162 
163 /*****************************************************************************
164 **   Userial Vendor API Functions
165 *****************************************************************************/
166 
167 /*******************************************************************************
168 **
169 ** Function        userial_vendor_init
170 **
171 ** Description     Initialize userial vendor-specific control block
172 **
173 ** Returns         None
174 **
175 *******************************************************************************/
userial_vendor_init(void)176 void userial_vendor_init(void)
177 {
178     vnd_userial.fd = -1;
179     snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \
180             BLUETOOTH_UART_DEVICE_PORT);
181 }
182 
183 /*******************************************************************************
184 **
185 ** Function        userial_vendor_open
186 **
187 ** Description     Open the serial port with the given configuration
188 **
189 ** Returns         device fd
190 **
191 *******************************************************************************/
userial_vendor_open(tUSERIAL_CFG * p_cfg)192 int userial_vendor_open(tUSERIAL_CFG *p_cfg)
193 {
194     uint32_t baud;
195     uint8_t data_bits;
196     uint16_t parity;
197     uint8_t stop_bits;
198 
199     vnd_userial.fd = -1;
200 
201     if (!userial_to_tcio_baud(p_cfg->baud, &baud))
202     {
203         return -1;
204     }
205 
206     if(p_cfg->fmt & USERIAL_DATABITS_8)
207         data_bits = CS8;
208     else if(p_cfg->fmt & USERIAL_DATABITS_7)
209         data_bits = CS7;
210     else if(p_cfg->fmt & USERIAL_DATABITS_6)
211         data_bits = CS6;
212     else if(p_cfg->fmt & USERIAL_DATABITS_5)
213         data_bits = CS5;
214     else
215     {
216         ALOGE("userial vendor open: unsupported data bits");
217         return -1;
218     }
219 
220     if(p_cfg->fmt & USERIAL_PARITY_NONE)
221         parity = 0;
222     else if(p_cfg->fmt & USERIAL_PARITY_EVEN)
223         parity = PARENB;
224     else if(p_cfg->fmt & USERIAL_PARITY_ODD)
225         parity = (PARENB | PARODD);
226     else
227     {
228         ALOGE("userial vendor open: unsupported parity bit mode");
229         return -1;
230     }
231 
232     if(p_cfg->fmt & USERIAL_STOPBITS_1)
233         stop_bits = 0;
234     else if(p_cfg->fmt & USERIAL_STOPBITS_2)
235         stop_bits = CSTOPB;
236     else
237     {
238         ALOGE("userial vendor open: unsupported stop bits");
239         return -1;
240     }
241 
242     ALOGI("userial vendor open: opening %s", vnd_userial.port_name);
243 
244     if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1)
245     {
246         ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name);
247         return -1;
248     }
249 
250     tcflush(vnd_userial.fd, TCIOFLUSH);
251 
252     tcgetattr(vnd_userial.fd, &vnd_userial.termios);
253     cfmakeraw(&vnd_userial.termios);
254     vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits);
255     tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
256     tcflush(vnd_userial.fd, TCIOFLUSH);
257 
258     tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
259     tcflush(vnd_userial.fd, TCIOFLUSH);
260     tcflush(vnd_userial.fd, TCIOFLUSH);
261 
262     /* set input/output baudrate */
263     cfsetospeed(&vnd_userial.termios, baud);
264     cfsetispeed(&vnd_userial.termios, baud);
265     tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
266 
267 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
268     userial_ioctl_init_bt_wake(vnd_userial.fd);
269 #endif
270 
271     ALOGI("device fd = %d open", vnd_userial.fd);
272 
273     return vnd_userial.fd;
274 }
275 
276 /*******************************************************************************
277 **
278 ** Function        userial_vendor_close
279 **
280 ** Description     Conduct vendor-specific close work
281 **
282 ** Returns         None
283 **
284 *******************************************************************************/
userial_vendor_close(void)285 void userial_vendor_close(void)
286 {
287     int result;
288 
289     if (vnd_userial.fd == -1)
290         return;
291 
292 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
293     /* de-assert bt_wake BEFORE closing port */
294     ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
295 #endif
296 
297     ALOGI("device fd = %d close", vnd_userial.fd);
298     // flush Tx before close to make sure no chars in buffer
299     tcflush(vnd_userial.fd, TCIOFLUSH);
300     if ((result = close(vnd_userial.fd)) < 0)
301         ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result);
302 
303     vnd_userial.fd = -1;
304 }
305 
306 /*******************************************************************************
307 **
308 ** Function        userial_vendor_set_baud
309 **
310 ** Description     Set new baud rate
311 **
312 ** Returns         None
313 **
314 *******************************************************************************/
userial_vendor_set_baud(uint8_t userial_baud)315 void userial_vendor_set_baud(uint8_t userial_baud)
316 {
317     uint32_t tcio_baud;
318 
319     userial_to_tcio_baud(userial_baud, &tcio_baud);
320 
321     cfsetospeed(&vnd_userial.termios, tcio_baud);
322     cfsetispeed(&vnd_userial.termios, tcio_baud);
323     tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
324 }
325 
326 /*******************************************************************************
327 **
328 ** Function        userial_vendor_ioctl
329 **
330 ** Description     ioctl inteface
331 **
332 ** Returns         None
333 **
334 *******************************************************************************/
userial_vendor_ioctl(userial_vendor_ioctl_op_t op,void * p_data)335 void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data)
336 {
337     switch(op)
338     {
339 #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
340         case USERIAL_OP_ASSERT_BT_WAKE:
341             VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##");
342             ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
343             break;
344 
345         case USERIAL_OP_DEASSERT_BT_WAKE:
346             VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##");
347             ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
348             break;
349 
350         case USERIAL_OP_GET_BT_WAKE_STATE:
351             ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data);
352             break;
353 #endif  //  (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
354 
355         default:
356             break;
357     }
358 }
359 
360 /*******************************************************************************
361 **
362 ** Function        userial_set_port
363 **
364 ** Description     Configure UART port name
365 **
366 ** Returns         0 : Success
367 **                 Otherwise : Fail
368 **
369 *******************************************************************************/
userial_set_port(char * p_conf_name,char * p_conf_value,int param)370 int userial_set_port(char *p_conf_name, char *p_conf_value, int param)
371 {
372     strcpy(vnd_userial.port_name, p_conf_value);
373 
374     return 0;
375 }
376 
377