The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 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.c |
| 22 | * |
| 23 | * Description: Contains open/read/write/close functions on serial port |
| 24 | * |
| 25 | ******************************************************************************/ |
| 26 | |
| 27 | #define LOG_TAG "bt_userial" |
| 28 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 29 | #include <assert.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 30 | #include <errno.h> |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 31 | #include <fcntl.h> |
| 32 | #include <pthread.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 33 | #include <stdio.h> |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 34 | #include <sys/eventfd.h> |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 35 | #include <sys/prctl.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 36 | #include <sys/socket.h> |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 37 | #include <utils/Log.h> |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 38 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 39 | #include "bt_hci_bdroid.h" |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 40 | #include "bt_utils.h" |
| 41 | #include "bt_vendor_lib.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 42 | #include "userial.h" |
| 43 | #include "utils.h" |
Sharvil Nanavati | f3b23f2 | 2014-06-15 13:36:45 -0700 | [diff] [blame] | 44 | #include "vendor.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 45 | |
| 46 | /****************************************************************************** |
| 47 | ** Constants & Macros |
| 48 | ******************************************************************************/ |
| 49 | |
| 50 | #ifndef USERIAL_DBG |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 51 | #define USERIAL_DBG TRUE |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 52 | #endif |
| 53 | |
| 54 | #if (USERIAL_DBG == TRUE) |
| 55 | #define USERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);} |
| 56 | #else |
| 57 | #define USERIALDBG(param, ...) {} |
| 58 | #endif |
| 59 | |
| 60 | #define MAX_SERIAL_PORT (USERIAL_PORT_3 + 1) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 61 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 62 | // The set of events one can send to the userial read thread. |
| 63 | // Note that the values must be >= 0x8000000000000000 to guarantee delivery |
| 64 | // of the message (see eventfd(2) for details on blocking behaviour). |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 65 | enum { |
Sharvil Nanavati | 5055c9d | 2014-06-24 00:39:06 -0700 | [diff] [blame] | 66 | USERIAL_RX_EXIT = 0x8000000000000000ULL |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 67 | }; |
| 68 | |
| 69 | /****************************************************************************** |
| 70 | ** Externs |
| 71 | ******************************************************************************/ |
| 72 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 73 | /****************************************************************************** |
| 74 | ** Local type definitions |
| 75 | ******************************************************************************/ |
| 76 | |
| 77 | typedef struct |
| 78 | { |
| 79 | int fd; |
| 80 | uint8_t port; |
| 81 | pthread_t read_thread; |
| 82 | BUFFER_Q rx_q; |
| 83 | HC_BT_HDR *p_rx_hdr; |
| 84 | } tUSERIAL_CB; |
| 85 | |
| 86 | /****************************************************************************** |
| 87 | ** Static variables |
| 88 | ******************************************************************************/ |
| 89 | |
| 90 | static tUSERIAL_CB userial_cb; |
| 91 | static volatile uint8_t userial_running = 0; |
| 92 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 93 | /***************************************************************************** |
| 94 | ** Socket signal functions to wake up userial_read_thread for termination |
| 95 | ** |
| 96 | ** creating an unnamed pair of connected sockets |
| 97 | ** - signal_fds[0]: join fd_set in select call of userial_read_thread |
| 98 | ** - signal_fds[1]: trigger from userial_close |
| 99 | *****************************************************************************/ |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 100 | static int event_fd = -1; |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 101 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 102 | static inline int add_event_fd(fd_set *set) { |
| 103 | if (event_fd == -1) { |
| 104 | event_fd = eventfd(0, 0); |
| 105 | if (event_fd == -1) { |
| 106 | ALOGE("%s unable to create event fd: %s", __func__, strerror(errno)); |
| 107 | return -1; |
| 108 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 109 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 110 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 111 | FD_SET(event_fd, set); |
| 112 | return event_fd; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 113 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 114 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 115 | static inline void send_event(uint64_t event_id) { |
| 116 | assert(event_fd != -1); |
| 117 | eventfd_write(event_fd, event_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 118 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 119 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 120 | static inline uint64_t read_event() { |
| 121 | assert(event_fd != -1); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 122 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 123 | uint64_t value = 0; |
| 124 | eventfd_read(event_fd, &value); |
| 125 | return value; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 126 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 127 | |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 128 | static inline bool is_event_available(fd_set *set) { |
| 129 | assert(event_fd != -1); |
| 130 | return !!FD_ISSET(event_fd, set); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 131 | } |
| 132 | |
| 133 | /******************************************************************************* |
| 134 | ** |
| 135 | ** Function select_read |
| 136 | ** |
| 137 | ** Description check if fd is ready for reading and listen for termination |
| 138 | ** signal. need to use select in order to avoid collision |
| 139 | ** between read and close on the same fd |
| 140 | ** |
| 141 | ** Returns -1: termination |
| 142 | ** >=0: numbers of bytes read back from fd |
| 143 | ** |
| 144 | *******************************************************************************/ |
| 145 | static int select_read(int fd, uint8_t *pbuf, int len) |
| 146 | { |
| 147 | fd_set input; |
| 148 | int n = 0, ret = -1; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 149 | |
| 150 | while (userial_running) |
| 151 | { |
| 152 | /* Initialize the input fd set */ |
| 153 | FD_ZERO(&input); |
Sharvil Nanavati | 5055c9d | 2014-06-24 00:39:06 -0700 | [diff] [blame] | 154 | FD_SET(fd, &input); |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 155 | int fd_max = add_event_fd(&input); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 156 | fd_max = fd_max > fd ? fd_max : fd; |
| 157 | |
| 158 | /* Do the select */ |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 159 | n = TEMP_FAILURE_RETRY(select(fd_max+1, &input, NULL, NULL, NULL)); |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 160 | if(is_event_available(&input)) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 161 | { |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 162 | uint64_t event = read_event(); |
| 163 | switch (event) { |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 164 | case USERIAL_RX_EXIT: |
| 165 | USERIALDBG("RX termination"); |
| 166 | return -1; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 167 | } |
| 168 | } |
| 169 | |
| 170 | if (n > 0) |
| 171 | { |
| 172 | /* We might have input */ |
| 173 | if (FD_ISSET(fd, &input)) |
| 174 | { |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 175 | ret = TEMP_FAILURE_RETRY(read(fd, pbuf, (size_t)len)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 176 | if (0 == ret) |
| 177 | ALOGW( "read() returned 0!" ); |
| 178 | |
| 179 | return ret; |
| 180 | } |
| 181 | } |
| 182 | else if (n < 0) |
| 183 | ALOGW( "select() Failed"); |
| 184 | else if (n == 0) |
| 185 | ALOGW( "Got a select() TIMEOUT"); |
| 186 | |
| 187 | } |
| 188 | |
| 189 | return ret; |
| 190 | } |
| 191 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 192 | static void *userial_read_thread(void *arg) |
| 193 | { |
| 194 | int rx_length = 0; |
| 195 | HC_BT_HDR *p_buf = NULL; |
| 196 | uint8_t *p; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 197 | UNUSED(arg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 198 | |
| 199 | USERIALDBG("Entering userial_read_thread()"); |
| 200 | prctl(PR_SET_NAME, (unsigned long)"userial_read", 0, 0, 0); |
| 201 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 202 | userial_running = 1; |
| 203 | |
Zhihai Xu | 690401a | 2013-09-13 19:31:18 -0700 | [diff] [blame] | 204 | raise_priority_a2dp(TASK_HIGH_USERIAL_READ); |
| 205 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 206 | while (userial_running) |
| 207 | { |
| 208 | if (bt_hc_cbacks) |
| 209 | { |
Loic Poulain | 535e24b | 2014-04-04 10:05:05 +0200 | [diff] [blame] | 210 | p_buf = (HC_BT_HDR *) bt_hc_cbacks->alloc( |
| 211 | BT_HC_HDR_SIZE + HCI_MAX_FRAME_SIZE + 1); /* H4 HDR = 1 */ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 212 | } |
| 213 | else |
| 214 | p_buf = NULL; |
| 215 | |
| 216 | if (p_buf != NULL) |
| 217 | { |
| 218 | p_buf->offset = 0; |
| 219 | p_buf->layer_specific = 0; |
| 220 | |
| 221 | p = (uint8_t *) (p_buf + 1); |
Chris Manton | d1e6922 | 2014-09-15 08:48:35 -0700 | [diff] [blame] | 222 | int userial_fd = userial_cb.fd; |
| 223 | if (userial_fd != -1) |
| 224 | rx_length = select_read(userial_fd, p, HCI_MAX_FRAME_SIZE + 1); |
| 225 | else |
| 226 | rx_length = 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 227 | } |
| 228 | else |
| 229 | { |
| 230 | rx_length = 0; |
| 231 | utils_delay(100); |
| 232 | ALOGW("userial_read_thread() failed to gain buffers"); |
| 233 | continue; |
| 234 | } |
| 235 | |
| 236 | |
| 237 | if (rx_length > 0) |
| 238 | { |
| 239 | p_buf->len = (uint16_t)rx_length; |
| 240 | utils_enqueue(&(userial_cb.rx_q), p_buf); |
Sharvil Nanavati | dd28edb | 2014-07-17 00:53:01 -0700 | [diff] [blame] | 241 | bthc_rx_ready(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 242 | } |
| 243 | else /* either 0 or < 0 */ |
| 244 | { |
| 245 | ALOGW("select_read return size <=0:%d, exiting userial_read_thread",\ |
| 246 | rx_length); |
| 247 | /* if we get here, we should have a buffer */ |
Sungjun Park | f072b98 | 2014-07-25 18:42:28 -0700 | [diff] [blame] | 248 | if (bt_hc_cbacks) |
| 249 | bt_hc_cbacks->dealloc(p_buf); |
| 250 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 251 | /* negative value means exit thread */ |
| 252 | break; |
| 253 | } |
| 254 | } /* for */ |
| 255 | |
| 256 | userial_running = 0; |
| 257 | USERIALDBG("Leaving userial_read_thread()"); |
| 258 | pthread_exit(NULL); |
| 259 | |
| 260 | return NULL; // Compiler friendly |
| 261 | } |
| 262 | |
| 263 | |
| 264 | /***************************************************************************** |
| 265 | ** Userial API Functions |
| 266 | *****************************************************************************/ |
| 267 | |
Sharvil Nanavati | bbe0c30 | 2014-04-26 00:58:15 -0700 | [diff] [blame] | 268 | bool userial_init(void) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 269 | { |
| 270 | USERIALDBG("userial_init"); |
| 271 | memset(&userial_cb, 0, sizeof(tUSERIAL_CB)); |
| 272 | userial_cb.fd = -1; |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 273 | utils_queue_init(&userial_cb.rx_q); |
Sharvil Nanavati | bbe0c30 | 2014-04-26 00:58:15 -0700 | [diff] [blame] | 274 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 275 | } |
| 276 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 277 | bool userial_open(userial_port_t port) { |
| 278 | if (port >= MAX_SERIAL_PORT) { |
| 279 | ALOGE("%s serial port %d > %d (max).", __func__, port, MAX_SERIAL_PORT); |
| 280 | return false; |
| 281 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 282 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 283 | if (userial_running) { |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 284 | userial_close(); |
| 285 | utils_delay(50); |
| 286 | } |
| 287 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 288 | // Call in to the vendor-specific library to open the serial port. |
| 289 | int fd_array[CH_MAX]; |
Chris Manton | 2172d0a | 2014-09-03 09:40:10 -0700 | [diff] [blame] | 290 | for (int i = 0; i < CH_MAX; i++) |
| 291 | fd_array[i] = -1; |
| 292 | |
Sharvil Nanavati | f3b23f2 | 2014-06-15 13:36:45 -0700 | [diff] [blame] | 293 | int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 294 | |
Chris Manton | 2172d0a | 2014-09-03 09:40:10 -0700 | [diff] [blame] | 295 | if (num_ports != 1) { |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 296 | ALOGE("%s opened wrong number of ports: got %d, expected 1.", __func__, num_ports); |
| 297 | goto error; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 298 | } |
| 299 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 300 | userial_cb.fd = fd_array[0]; |
| 301 | if (userial_cb.fd == -1) { |
| 302 | ALOGE("%s unable to open serial port.", __func__); |
| 303 | goto error; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 304 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 305 | |
| 306 | userial_cb.port = port; |
| 307 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 308 | if (pthread_create(&userial_cb.read_thread, NULL, userial_read_thread, NULL)) { |
| 309 | ALOGE("%s unable to spawn read thread.", __func__); |
| 310 | goto error; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 311 | } |
| 312 | |
Sharvil Nanavati | bbe0c30 | 2014-04-26 00:58:15 -0700 | [diff] [blame] | 313 | return true; |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 314 | |
| 315 | error: |
Sharvil Nanavati | f3b23f2 | 2014-06-15 13:36:45 -0700 | [diff] [blame] | 316 | vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 317 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 318 | } |
| 319 | |
Sharvil Nanavati | bbe0c30 | 2014-04-26 00:58:15 -0700 | [diff] [blame] | 320 | uint16_t userial_read(uint16_t msg_id, uint8_t *p_buffer, uint16_t len) |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 321 | { |
| 322 | uint16_t total_len = 0; |
| 323 | uint16_t copy_len = 0; |
| 324 | uint8_t *p_data = NULL; |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 325 | UNUSED(msg_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 326 | |
| 327 | do |
| 328 | { |
| 329 | if(userial_cb.p_rx_hdr != NULL) |
| 330 | { |
| 331 | p_data = ((uint8_t *)(userial_cb.p_rx_hdr + 1)) + \ |
| 332 | (userial_cb.p_rx_hdr->offset); |
| 333 | |
| 334 | if((userial_cb.p_rx_hdr->len) <= (len - total_len)) |
| 335 | copy_len = userial_cb.p_rx_hdr->len; |
| 336 | else |
| 337 | copy_len = (len - total_len); |
| 338 | |
| 339 | memcpy((p_buffer + total_len), p_data, copy_len); |
| 340 | |
| 341 | total_len += copy_len; |
| 342 | |
| 343 | userial_cb.p_rx_hdr->offset += copy_len; |
| 344 | userial_cb.p_rx_hdr->len -= copy_len; |
| 345 | |
| 346 | if(userial_cb.p_rx_hdr->len == 0) |
| 347 | { |
| 348 | if (bt_hc_cbacks) |
Sharvil Nanavati | 75e8f41 | 2014-06-24 17:02:30 -0700 | [diff] [blame] | 349 | bt_hc_cbacks->dealloc(userial_cb.p_rx_hdr); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 350 | |
| 351 | userial_cb.p_rx_hdr = NULL; |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | if(userial_cb.p_rx_hdr == NULL) |
| 356 | { |
| 357 | userial_cb.p_rx_hdr=(HC_BT_HDR *)utils_dequeue(&(userial_cb.rx_q)); |
| 358 | } |
| 359 | } while ((userial_cb.p_rx_hdr != NULL) && (total_len < len)); |
| 360 | |
| 361 | return total_len; |
| 362 | } |
| 363 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 364 | uint16_t userial_write(uint16_t msg_id, const uint8_t *p_data, uint16_t len) { |
Mike J. Chen | 5cd8bff | 2014-01-31 18:16:59 -0800 | [diff] [blame] | 365 | UNUSED(msg_id); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 366 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 367 | uint16_t total = 0; |
| 368 | while (len) { |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 369 | ssize_t ret = TEMP_FAILURE_RETRY(write(userial_cb.fd, p_data + total, len)); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 370 | switch (ret) { |
| 371 | case -1: |
| 372 | ALOGE("%s error writing to serial port: %s", __func__, strerror(errno)); |
| 373 | return total; |
| 374 | case 0: // don't loop forever in case write returns 0. |
| 375 | return total; |
| 376 | default: |
| 377 | total += ret; |
| 378 | len -= ret; |
| 379 | break; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 380 | } |
| 381 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 382 | |
| 383 | return total; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 384 | } |
| 385 | |
Chris Manton | 11aa94d | 2014-08-15 09:04:00 -0700 | [diff] [blame] | 386 | void userial_close_reader(void) { |
| 387 | // Join the reader thread if it is still running. |
| 388 | if (userial_running) { |
| 389 | send_event(USERIAL_RX_EXIT); |
| 390 | int result = pthread_join(userial_cb.read_thread, NULL); |
| 391 | USERIALDBG("%s Joined userial reader thread: %d", __func__, result); |
| 392 | if (result) |
| 393 | ALOGE("%s failed to join reader thread: %d", __func__, result); |
| 394 | return; |
| 395 | } |
| 396 | ALOGW("%s Already closed userial reader thread", __func__); |
| 397 | } |
| 398 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 399 | void userial_close(void) { |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 400 | assert(bt_hc_cbacks != NULL); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 401 | |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 402 | // Join the reader thread if it's still running. |
| 403 | if (userial_running) { |
Sharvil Nanavati | 29abb0e | 2014-04-27 14:34:50 -0700 | [diff] [blame] | 404 | send_event(USERIAL_RX_EXIT); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 405 | int result = pthread_join(userial_cb.read_thread, NULL); |
| 406 | if (result) |
| 407 | ALOGE("%s failed to join reader thread: %d", __func__, result); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 408 | } |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 409 | |
| 410 | // Ask the vendor-specific library to close the serial port. |
Sharvil Nanavati | f3b23f2 | 2014-06-15 13:36:45 -0700 | [diff] [blame] | 411 | vendor_send_command(BT_VND_OP_USERIAL_CLOSE, NULL); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 412 | |
| 413 | // Free all buffers still waiting in the RX queue. |
| 414 | // TODO: use list data structure and clean this up. |
| 415 | void *buf; |
| 416 | while ((buf = utils_dequeue(&userial_cb.rx_q)) != NULL) |
Sharvil Nanavati | 75e8f41 | 2014-06-24 17:02:30 -0700 | [diff] [blame] | 417 | bt_hc_cbacks->dealloc(buf); |
Sharvil Nanavati | d9fd65e | 2014-04-26 10:40:30 -0700 | [diff] [blame] | 418 | |
| 419 | userial_cb.fd = -1; |
| 420 | } |