.. | .. |
---|
1 | 1 | /****************************************************************************** |
---|
2 | 2 | * |
---|
3 | | - * Copyright (C) 2019-2027 AIC Corporation |
---|
| 3 | + * Copyright (C) 2019-2021 Aicsemi Corporation |
---|
4 | 4 | * |
---|
5 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
---|
6 | 6 | * you may not use this file except in compliance with the License. |
---|
.. | .. |
---|
23 | 23 | * Description: Contains vendor-specific userial functions |
---|
24 | 24 | * |
---|
25 | 25 | ******************************************************************************/ |
---|
26 | | - |
---|
| 26 | +#undef NDEBUG |
---|
27 | 27 | #define LOG_TAG "bt_userial_vendor" |
---|
28 | 28 | |
---|
29 | 29 | #include <utils/Log.h> |
---|
.. | .. |
---|
31 | 31 | #include <fcntl.h> |
---|
32 | 32 | #include <errno.h> |
---|
33 | 33 | #include <stdio.h> |
---|
34 | | -#include <string.h> |
---|
35 | | -#include "bt_vendor_aicbt.h" |
---|
| 34 | +#include <sys/eventfd.h> |
---|
36 | 35 | #include "userial.h" |
---|
37 | 36 | #include "userial_vendor.h" |
---|
38 | | -#include <unistd.h> |
---|
| 37 | +#include "aic_socket.h" |
---|
| 38 | +#include <cutils/sockets.h> |
---|
| 39 | +#include "upio.h" |
---|
39 | 40 | |
---|
| 41 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 42 | +#include "sbc.h" |
---|
| 43 | +#ifdef CONFIG_SCO_MSBC_PLC |
---|
| 44 | +#include "sbcplc.h" |
---|
| 45 | +unsigned char indices0[] = {0xad, 0x0, 0x0, 0xc5, 0x0, 0x0, 0x0, 0x0, 0x77, 0x6d, |
---|
| 46 | + 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, |
---|
| 47 | + 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, |
---|
| 48 | + 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, |
---|
| 49 | + 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00}; //padding at the end |
---|
| 50 | +#endif |
---|
| 51 | +#endif |
---|
40 | 52 | /****************************************************************************** |
---|
41 | 53 | ** Constants & Macros |
---|
42 | 54 | ******************************************************************************/ |
---|
43 | 55 | |
---|
44 | 56 | #ifndef VNDUSERIAL_DBG |
---|
45 | | -#define VNDUSERIAL_DBG FALSE |
---|
| 57 | +#define VNDUSERIAL_DBG TRUE |
---|
46 | 58 | #endif |
---|
47 | 59 | |
---|
48 | 60 | #if (VNDUSERIAL_DBG == TRUE) |
---|
.. | .. |
---|
53 | 65 | |
---|
54 | 66 | #define VND_PORT_NAME_MAXLEN 256 |
---|
55 | 67 | |
---|
| 68 | +#ifndef BT_CHIP_HW_FLOW_CTRL_ON |
---|
| 69 | +#define BT_CHIP_HW_FLOW_CTRL_ON TRUE |
---|
| 70 | +#endif |
---|
| 71 | + |
---|
| 72 | +/****************************************************************************** |
---|
| 73 | +** Extern functions |
---|
| 74 | +******************************************************************************/ |
---|
| 75 | +extern char aicbt_transtype; |
---|
| 76 | +extern void Heartbeat_cleanup(); |
---|
| 77 | +extern void Heartbeat_init(); |
---|
| 78 | +extern int AIC_btservice_init(); |
---|
| 79 | + |
---|
56 | 80 | /****************************************************************************** |
---|
57 | 81 | ** Local type definitions |
---|
58 | 82 | ******************************************************************************/ |
---|
| 83 | +#if !defined(EFD_SEMAPHORE) |
---|
| 84 | +# define EFD_SEMAPHORE (1 << 0) |
---|
| 85 | +#endif |
---|
| 86 | + |
---|
| 87 | +#define AIC_DATA_RECEIVED 1 |
---|
| 88 | +#define AIC_DATA_SEND 0 |
---|
| 89 | +struct aic_object_t { |
---|
| 90 | + int fd; // the file descriptor to monitor for events. |
---|
| 91 | + void *context; // a context that's passed back to the *_ready functions.. |
---|
| 92 | + pthread_mutex_t lock; // protects the lifetime of this object and all variables. |
---|
| 93 | + |
---|
| 94 | + void (*read_ready)(void *context); // function to call when the file descriptor becomes readable. |
---|
| 95 | + void (*write_ready)(void *context); // function to call when the file descriptor becomes writeable. |
---|
| 96 | +}; |
---|
59 | 97 | |
---|
60 | 98 | /* vendor serial control block */ |
---|
61 | 99 | typedef struct { |
---|
62 | 100 | int fd; /* fd to Bluetooth device */ |
---|
| 101 | + int uart_fd[2]; |
---|
| 102 | + int signal_fd[2]; |
---|
| 103 | + int epoll_fd; |
---|
| 104 | + int cpoll_fd; |
---|
| 105 | + int event_fd; |
---|
63 | 106 | struct termios termios; /* serial terminal of BT port */ |
---|
64 | 107 | char port_name[VND_PORT_NAME_MAXLEN]; |
---|
| 108 | + pthread_t thread_socket_id; |
---|
| 109 | + pthread_t thread_uart_id; |
---|
| 110 | + pthread_t thread_coex_id; |
---|
| 111 | + bool thread_running; |
---|
| 112 | + |
---|
| 113 | + RTB_QUEUE_HEAD *recv_data; |
---|
| 114 | + RTB_QUEUE_HEAD *send_data; |
---|
| 115 | + RTB_QUEUE_HEAD *data_order; |
---|
| 116 | + volatile bool btdriver_state; |
---|
65 | 117 | } vnd_userial_cb_t; |
---|
66 | 118 | |
---|
| 119 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 120 | + |
---|
| 121 | +enum esco_coding_format { |
---|
| 122 | + ESCO_CODING_FORMAT_ULAW = 0x00, |
---|
| 123 | + ESCO_CODING_FORMAT_ALAW = 0x01, |
---|
| 124 | + ESCO_CODING_FORMAT_CVSD = 0x02, |
---|
| 125 | + ESCO_CODING_FORMAT_TRANSPNT = 0x03, |
---|
| 126 | + ESCO_CODING_FORMAT_LINEAR = 0x04, // PCM raw data |
---|
| 127 | + ESCO_CODING_FORMAT_MSBC = 0x05, |
---|
| 128 | + ESCO_CODING_FORMAT_VS = 0xFF, |
---|
| 129 | +}; |
---|
| 130 | + |
---|
| 131 | +enum esco_data_path { |
---|
| 132 | + ESCO_DATA_PATH_HCI = 0x00, |
---|
| 133 | + ESCO_DATA_PATH_PCM = 0x01, |
---|
| 134 | + ESCO_DATA_PATH_TEST = 0xFF, |
---|
| 135 | +}; |
---|
| 136 | + |
---|
| 137 | +struct coding_format_t { |
---|
| 138 | + uint8_t coding_format; |
---|
| 139 | + uint8_t reserved[4]; |
---|
| 140 | +} __attribute__ ((packed)); |
---|
| 141 | + |
---|
| 142 | +struct esco_para_t { |
---|
| 143 | + uint32_t transmit_bandwidth; |
---|
| 144 | + uint32_t receive_bandwidth; |
---|
| 145 | + struct coding_format_t transmit_coding_format; |
---|
| 146 | + struct coding_format_t receive_coding_format; |
---|
| 147 | + uint16_t transmit_codec_frame_size; |
---|
| 148 | + uint16_t receive_codec_frame_size; |
---|
| 149 | + uint32_t input_bandwidth; |
---|
| 150 | + uint32_t output_bandwidth; |
---|
| 151 | + struct coding_format_t input_coding_format; |
---|
| 152 | + struct coding_format_t output_coding_format; |
---|
| 153 | + uint16_t input_coded_data_size; |
---|
| 154 | + uint16_t output_coded_data_size; |
---|
| 155 | + uint8_t input_pcm_data_format; |
---|
| 156 | + uint8_t output_pcm_data_format; |
---|
| 157 | + uint8_t input_pcm_sample_payload_msb_pos; |
---|
| 158 | + uint8_t output_pcm_sample_payload_msb_pos; |
---|
| 159 | + uint8_t input_data_path; |
---|
| 160 | + uint8_t output_data_path; |
---|
| 161 | + uint8_t input_transport_unit_size; |
---|
| 162 | + uint8_t output_transport_unit_size; |
---|
| 163 | + uint16_t max_latency; |
---|
| 164 | + uint16_t packet_types; |
---|
| 165 | + uint8_t retransmission_effort; |
---|
| 166 | +} __attribute__ ((packed)); |
---|
| 167 | + |
---|
| 168 | +struct codec_para_t { |
---|
| 169 | + uint8_t input_format; |
---|
| 170 | + uint8_t input_channels; |
---|
| 171 | + uint8_t input_bits; |
---|
| 172 | + uint16_t input_rate; |
---|
| 173 | + uint8_t output_format; |
---|
| 174 | + uint8_t output_channels; |
---|
| 175 | + uint8_t output_bits; |
---|
| 176 | + uint16_t output_rate; |
---|
| 177 | +} __attribute__ ((packed)); |
---|
| 178 | + |
---|
| 179 | +uint16_t btui_msbc_h2[] = {0x0801,0x3801,0xc801,0xf801}; |
---|
| 180 | +typedef struct { |
---|
| 181 | + pthread_mutex_t sco_recv_mutex; |
---|
| 182 | + pthread_cond_t sco_recv_cond; |
---|
| 183 | + pthread_mutex_t sco_send_mutex; |
---|
| 184 | + pthread_t thread_socket_sco_id; |
---|
| 185 | + pthread_t thread_recv_sco_id; |
---|
| 186 | + pthread_t thread_send_sco_id; |
---|
| 187 | + uint16_t sco_handle; |
---|
| 188 | + bool thread_sco_running; |
---|
| 189 | + bool thread_recv_sco_running; |
---|
| 190 | + bool thread_send_sco_running; |
---|
| 191 | + uint16_t voice_settings; |
---|
| 192 | + RTB_QUEUE_HEAD *recv_sco_data; |
---|
| 193 | + RTB_QUEUE_HEAD *send_sco_data; |
---|
| 194 | + unsigned char enc_data[480]; |
---|
| 195 | + unsigned int current_pos; |
---|
| 196 | + uint16_t sco_packet_len; |
---|
| 197 | + struct esco_para_t esco_para; |
---|
| 198 | + struct codec_para_t codec_para; |
---|
| 199 | + int ctrl_fd, data_fd; |
---|
| 200 | + sbc_t sbc_dec, sbc_enc; |
---|
| 201 | + uint32_t pcm_enc_seq; |
---|
| 202 | + int8_t pcm_dec_seq; |
---|
| 203 | + uint32_t pcm_dec_frame; |
---|
| 204 | + int signal_fd[2]; |
---|
| 205 | +} sco_cb_t; |
---|
| 206 | +#endif |
---|
| 207 | + |
---|
| 208 | +/****************************************************************************** |
---|
| 209 | +** Static functions |
---|
| 210 | +******************************************************************************/ |
---|
| 211 | +static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length); |
---|
| 212 | +static uint16_t h5_int_transmit_data_cb(serial_data_type_t type, uint8_t *data, uint16_t length) ; |
---|
| 213 | +extern void AIC_btservice_destroyed(); |
---|
| 214 | +static uint16_t h4_int_transmit_data(uint8_t *data, uint16_t total_length); |
---|
| 215 | +static int close_state = -1; |
---|
67 | 216 | /****************************************************************************** |
---|
68 | 217 | ** Static variables |
---|
69 | 218 | ******************************************************************************/ |
---|
70 | | - |
---|
| 219 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 220 | +static sco_cb_t sco_cb = { |
---|
| 221 | + .codec_para = { |
---|
| 222 | + .input_channels = 1, |
---|
| 223 | + .input_bits = 16, |
---|
| 224 | + .input_rate = 8000, |
---|
| 225 | + .output_channels = 1, |
---|
| 226 | + .output_bits = 16, |
---|
| 227 | + .output_rate = 8000, |
---|
| 228 | + }, |
---|
| 229 | +}; |
---|
| 230 | +#endif |
---|
71 | 231 | static vnd_userial_cb_t vnd_userial; |
---|
| 232 | +static const hci_h5_t *h5_int_interface; |
---|
| 233 | +static int packet_recv_state = AICBT_PACKET_IDLE; |
---|
| 234 | +static unsigned int packet_bytes_need = 0; |
---|
| 235 | +static serial_data_type_t current_type = 0; |
---|
| 236 | +static struct aic_object_t aic_socket_object; |
---|
| 237 | +static struct aic_object_t aic_coex_object; |
---|
| 238 | +static unsigned char h4_read_buffer[2048] = {0}; |
---|
| 239 | +static int h4_read_length = 0; |
---|
| 240 | + |
---|
| 241 | +static int coex_packet_recv_state = AICBT_PACKET_IDLE; |
---|
| 242 | +static int coex_packet_bytes_need = 0; |
---|
| 243 | +static serial_data_type_t coex_current_type = 0; |
---|
| 244 | +static unsigned char coex_resvered_buffer[2048] = {0}; |
---|
| 245 | +static int coex_resvered_length = 0; |
---|
| 246 | + |
---|
| 247 | +#ifdef AIC_HANDLE_EVENT |
---|
| 248 | +static int received_packet_state = AICBT_PACKET_IDLE; |
---|
| 249 | +static unsigned int received_packet_bytes_need = 0; |
---|
| 250 | +static serial_data_type_t recv_packet_current_type = 0; |
---|
| 251 | +static unsigned char received_resvered_header[2048] = {0}; |
---|
| 252 | +static int received_resvered_length = 0; |
---|
| 253 | +static aicbt_version_t aicbt_version; |
---|
| 254 | +static aicbt_lescn_t aicbt_adv_con; |
---|
| 255 | +#endif |
---|
| 256 | + |
---|
| 257 | +static aic_parse_manager_t *aic_parse_manager = NULL; |
---|
| 258 | + |
---|
| 259 | +static hci_h5_callbacks_t h5_int_callbacks = { |
---|
| 260 | + .h5_int_transmit_data_cb = h5_int_transmit_data_cb, |
---|
| 261 | + .h5_data_ready_cb = h5_data_ready_cb, |
---|
| 262 | +}; |
---|
| 263 | + |
---|
| 264 | +static const uint8_t hci_preamble_sizes[] = { |
---|
| 265 | + COMMAND_PREAMBLE_SIZE, |
---|
| 266 | + ACL_PREAMBLE_SIZE, |
---|
| 267 | + SCO_PREAMBLE_SIZE, |
---|
| 268 | + EVENT_PREAMBLE_SIZE |
---|
| 269 | +}; |
---|
72 | 270 | |
---|
73 | 271 | /***************************************************************************** |
---|
74 | 272 | ** Helper Functions |
---|
.. | .. |
---|
143 | 341 | { |
---|
144 | 342 | uint32_t bt_wake_state; |
---|
145 | 343 | |
---|
146 | | -#if (BT_WAKE_USERIAL_LDISC==TRUE) |
---|
147 | | - int ldisc = N_AICBT_HCI; /* acibt sleep mode support line discipline */ |
---|
148 | | - |
---|
149 | | - /* attempt to load enable discipline driver */ |
---|
150 | | - if (ioctl(vnd_userial.fd, TIOCSETD, &ldisc) < 0) { |
---|
151 | | - VNDUSERIALDBG("USERIAL_Open():fd %d, TIOCSETD failed: error %d for ldisc: %d", |
---|
152 | | - fd, errno, ldisc); |
---|
153 | | - } |
---|
154 | | -#endif |
---|
155 | | - |
---|
156 | 344 | /* assert BT_WAKE through ioctl */ |
---|
157 | 345 | ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); |
---|
158 | 346 | ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state); |
---|
.. | .. |
---|
165 | 353 | /***************************************************************************** |
---|
166 | 354 | ** Userial Vendor API Functions |
---|
167 | 355 | *****************************************************************************/ |
---|
| 356 | +static void userial_send_hw_error() |
---|
| 357 | +{ |
---|
| 358 | + unsigned char p_buf[100]; |
---|
| 359 | + int length; |
---|
| 360 | + p_buf[0] = HCIT_TYPE_EVENT;//event |
---|
| 361 | + p_buf[1] = HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT;//firmwre event log |
---|
| 362 | + p_buf[3] = 0x01;// host log opcode |
---|
| 363 | + length = sprintf((char *)&p_buf[4], "host stack: userial error \n"); |
---|
| 364 | + p_buf[2] = length + 2;//len |
---|
| 365 | + length = length + 1 + 4; |
---|
| 366 | + userial_recv_rawdata_hook(p_buf,length); |
---|
| 367 | + |
---|
| 368 | + length = 4; |
---|
| 369 | + p_buf[0] = HCIT_TYPE_EVENT;//event |
---|
| 370 | + p_buf[1] = HCI_HARDWARE_ERROR_EVT;//hardware error |
---|
| 371 | + p_buf[2] = 0x01;//len |
---|
| 372 | + p_buf[3] = USERIAL_HWERR_CODE_AIC;//userial error code |
---|
| 373 | + userial_recv_rawdata_hook(p_buf,length); |
---|
| 374 | +} |
---|
168 | 375 | |
---|
169 | 376 | /******************************************************************************* |
---|
170 | 377 | ** |
---|
.. | .. |
---|
175 | 382 | ** Returns None |
---|
176 | 383 | ** |
---|
177 | 384 | *******************************************************************************/ |
---|
178 | | -void userial_vendor_init(void) |
---|
| 385 | +void userial_vendor_init(char *bt_device_node) |
---|
179 | 386 | { |
---|
| 387 | +#ifdef AIC_HANDLE_EVENT |
---|
| 388 | + memset(&aicbt_adv_con, 0, sizeof(aicbt_lescn_t)); |
---|
| 389 | +#endif |
---|
| 390 | + memset(&vnd_userial, 0, sizeof(vnd_userial_cb_t)); |
---|
180 | 391 | vnd_userial.fd = -1; |
---|
| 392 | + char value[100]; |
---|
181 | 393 | snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \ |
---|
182 | | - BLUETOOTH_UART_DEVICE_PORT); |
---|
| 394 | + bt_device_node); |
---|
| 395 | + if (aicbt_transtype & AICBT_TRANS_H5) { |
---|
| 396 | + h5_int_interface = hci_get_h5_int_interface(); |
---|
| 397 | + h5_int_interface->h5_int_init(&h5_int_callbacks); |
---|
| 398 | + } |
---|
| 399 | + aic_parse_manager = NULL; |
---|
| 400 | + property_get("persist.vendor.bluetooth.aiccoex", value, "true"); |
---|
| 401 | + if (strncmp(value, "true", 4) == 0) { |
---|
| 402 | + aic_parse_manager = aic_parse_manager_get_interface(); |
---|
| 403 | + aic_parse_manager->aic_parse_init(); |
---|
| 404 | + } |
---|
| 405 | + vnd_userial.data_order = RtbQueueInit(); |
---|
| 406 | + vnd_userial.recv_data = RtbQueueInit(); |
---|
| 407 | + vnd_userial.send_data = RtbQueueInit(); |
---|
| 408 | + |
---|
| 409 | + //reset coex gloable variables |
---|
| 410 | + coex_packet_recv_state = AICBT_PACKET_IDLE; |
---|
| 411 | + coex_packet_bytes_need = 0; |
---|
| 412 | + coex_current_type = 0; |
---|
| 413 | + coex_resvered_length = 0; |
---|
| 414 | + |
---|
| 415 | +#ifdef AIC_HANDLE_EVENT |
---|
| 416 | + //reset handle event gloable variables |
---|
| 417 | + received_packet_state = AICBT_PACKET_IDLE; |
---|
| 418 | + received_packet_bytes_need = 0; |
---|
| 419 | + recv_packet_current_type = 0; |
---|
| 420 | + received_resvered_length = 0; |
---|
| 421 | +#endif |
---|
| 422 | + |
---|
| 423 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 424 | + sco_cb.recv_sco_data = RtbQueueInit(); |
---|
| 425 | + sco_cb.send_sco_data = RtbQueueInit(); |
---|
| 426 | + pthread_mutex_init(&sco_cb.sco_recv_mutex, NULL); |
---|
| 427 | + pthread_cond_init(&sco_cb.sco_recv_cond, NULL); |
---|
| 428 | + pthread_mutex_init(&sco_cb.sco_send_mutex, NULL); |
---|
| 429 | + memset(&sco_cb.sbc_enc, 0, sizeof(sbc_t)); |
---|
| 430 | + sbc_init_msbc(&sco_cb.sbc_enc, 0L); |
---|
| 431 | + sco_cb.sbc_enc.endian = SBC_LE; |
---|
| 432 | + memset(&sco_cb.sbc_dec, 0, sizeof(sbc_t)); |
---|
| 433 | + sbc_init_msbc(&sco_cb.sbc_dec, 0L); |
---|
| 434 | + sco_cb.sbc_dec.endian = SBC_LE; |
---|
| 435 | +#endif |
---|
183 | 436 | } |
---|
| 437 | + |
---|
184 | 438 | |
---|
185 | 439 | /******************************************************************************* |
---|
186 | 440 | ** |
---|
.. | .. |
---|
265 | 519 | userial_ioctl_init_bt_wake(vnd_userial.fd); |
---|
266 | 520 | #endif |
---|
267 | 521 | |
---|
| 522 | + vnd_userial.btdriver_state = true; |
---|
268 | 523 | ALOGI("device fd = %d open", vnd_userial.fd); |
---|
269 | 524 | |
---|
270 | 525 | return vnd_userial.fd; |
---|
| 526 | +} |
---|
| 527 | + |
---|
| 528 | +static void userial_socket_close(void) |
---|
| 529 | +{ |
---|
| 530 | + int result; |
---|
| 531 | + |
---|
| 532 | + if ((vnd_userial.uart_fd[0] > 0) && (result = close(vnd_userial.uart_fd[0])) < 0) |
---|
| 533 | + ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.uart_fd[0], result); |
---|
| 534 | + |
---|
| 535 | + if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_DEL, vnd_userial.uart_fd[1], NULL) == -1) |
---|
| 536 | + ALOGE("%s unable to unregister fd %d from epoll set: %s", __func__, vnd_userial.uart_fd[1], strerror(errno)); |
---|
| 537 | + |
---|
| 538 | + if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_DEL, vnd_userial.signal_fd[1], NULL) == -1) |
---|
| 539 | + ALOGE("%s unable to unregister signal fd %d from epoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno)); |
---|
| 540 | + |
---|
| 541 | + if ((vnd_userial.uart_fd[1] > 0) && (result = close(vnd_userial.uart_fd[1])) < 0) |
---|
| 542 | + ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.uart_fd[1], result); |
---|
| 543 | + |
---|
| 544 | + if (vnd_userial.thread_socket_id != -1){ |
---|
| 545 | + if ((result = pthread_join(vnd_userial.thread_socket_id, NULL)) < 0) |
---|
| 546 | + ALOGE("%s vnd_userial.thread_socket_id pthread_join_failed", __func__); |
---|
| 547 | + else { |
---|
| 548 | + vnd_userial.thread_socket_id = -1; |
---|
| 549 | + ALOGD("%s vnd_userial.thread_socket_id pthread_join_success", __func__); |
---|
| 550 | + } |
---|
| 551 | + } |
---|
| 552 | + if (vnd_userial.epoll_fd > 0) |
---|
| 553 | + close(vnd_userial.epoll_fd); |
---|
| 554 | + |
---|
| 555 | + if ((vnd_userial.signal_fd[0] > 0) && (result = close(vnd_userial.signal_fd[0])) < 0) |
---|
| 556 | + ALOGE( "%s (signal fd[0]:%d) FAILED result:%d", __func__, vnd_userial.signal_fd[0], result); |
---|
| 557 | + if ((vnd_userial.signal_fd[1] > 0) && (result = close(vnd_userial.signal_fd[1])) < 0) |
---|
| 558 | + ALOGE( "%s (signal fd[1]:%d) FAILED result:%d", __func__, vnd_userial.signal_fd[1], result); |
---|
| 559 | + |
---|
| 560 | + vnd_userial.epoll_fd = -1; |
---|
| 561 | + vnd_userial.uart_fd[0] = -1; |
---|
| 562 | + vnd_userial.uart_fd[1] = -1; |
---|
| 563 | + vnd_userial.signal_fd[0] = -1; |
---|
| 564 | + vnd_userial.signal_fd[1] = -1; |
---|
| 565 | +} |
---|
| 566 | + |
---|
| 567 | +static void userial_uart_close(void) |
---|
| 568 | +{ |
---|
| 569 | + int result; |
---|
| 570 | + if ((vnd_userial.fd > 0) && (result = close(vnd_userial.fd)) < 0) |
---|
| 571 | + ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.fd, result); |
---|
| 572 | + if (vnd_userial.thread_uart_id != -1) |
---|
| 573 | + pthread_join(vnd_userial.thread_uart_id, NULL); |
---|
| 574 | +} |
---|
| 575 | + |
---|
| 576 | +static void userial_coex_close(void) |
---|
| 577 | +{ |
---|
| 578 | + int result; |
---|
| 579 | + |
---|
| 580 | + if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_DEL, vnd_userial.event_fd, NULL) == -1) |
---|
| 581 | + ALOGE("%s unable to unregister fd %d from cpoll set: %s", __func__, vnd_userial.event_fd, strerror(errno)); |
---|
| 582 | + |
---|
| 583 | + if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_DEL, vnd_userial.signal_fd[1], NULL) == -1) |
---|
| 584 | + ALOGE("%s unable to unregister fd %d from cpoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno)); |
---|
| 585 | + |
---|
| 586 | + if ((result = close(vnd_userial.event_fd)) < 0) |
---|
| 587 | + ALOGE( "%s (fd:%d) FAILED result:%d", __func__, vnd_userial.event_fd, result); |
---|
| 588 | + |
---|
| 589 | + close(vnd_userial.cpoll_fd); |
---|
| 590 | + if (vnd_userial.thread_coex_id != -1){ |
---|
| 591 | + if (pthread_join(vnd_userial.thread_coex_id, NULL) != 0) { |
---|
| 592 | + ALOGE("%s vnd_userial.thread_coex_id pthread_join_failed", __func__); |
---|
| 593 | + } else { |
---|
| 594 | + vnd_userial.thread_coex_id = -1; |
---|
| 595 | + ALOGD("%s vnd_userial.thread_coex_id pthread_join_success", __func__); |
---|
| 596 | + } |
---|
| 597 | + } |
---|
| 598 | + vnd_userial.cpoll_fd = -1; |
---|
| 599 | + vnd_userial.event_fd = -1; |
---|
| 600 | +} |
---|
| 601 | + |
---|
| 602 | +void userial_send_close_signal(void) |
---|
| 603 | +{ |
---|
| 604 | + unsigned char close_signal = 1; |
---|
| 605 | + ssize_t ret; |
---|
| 606 | + AIC_NO_INTR(ret = write(vnd_userial.signal_fd[0], &close_signal, 1)); |
---|
| 607 | +} |
---|
| 608 | + |
---|
| 609 | +void userial_quene_close(void) |
---|
| 610 | +{ |
---|
| 611 | + RtbQueueFree(vnd_userial.data_order); |
---|
| 612 | + RtbQueueFree(vnd_userial.recv_data); |
---|
| 613 | + RtbQueueFree(vnd_userial.send_data); |
---|
| 614 | +} |
---|
| 615 | + |
---|
| 616 | +void close_with_hci_reset(void) |
---|
| 617 | +{ |
---|
| 618 | + uint8_t hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 }; |
---|
| 619 | + int i = 0; |
---|
| 620 | + ALOGD("%s, start send hci reset command", __func__); |
---|
| 621 | + upio_set(UPIO_BT_WAKE, UPIO_DEASSERT, 1); |
---|
| 622 | + upio_set(UPIO_BT_WAKE, UPIO_ASSERT, 1); |
---|
| 623 | + h4_int_transmit_data(hci_reset, sizeof(hci_reset)); |
---|
| 624 | + close_state = 0; |
---|
| 625 | + for (i = 0; i < 5; i++) { |
---|
| 626 | + if (close_state == 1) { |
---|
| 627 | + ALOGD("%s, hci reset done", __func__); |
---|
| 628 | + upio_set(UPIO_BT_WAKE, UPIO_DEASSERT, 1); |
---|
| 629 | + close_state = -1; |
---|
| 630 | + return; |
---|
| 631 | + } |
---|
| 632 | + usleep(100000); |
---|
| 633 | + } |
---|
| 634 | + upio_set(UPIO_BT_WAKE, UPIO_DEASSERT, 1); |
---|
| 635 | + ALOGD("%s, send hci reset command timeout", __func__); |
---|
271 | 636 | } |
---|
272 | 637 | |
---|
273 | 638 | /******************************************************************************* |
---|
.. | .. |
---|
281 | 646 | *******************************************************************************/ |
---|
282 | 647 | void userial_vendor_close(void) |
---|
283 | 648 | { |
---|
284 | | - int result; |
---|
| 649 | + close_with_hci_reset(); |
---|
285 | 650 | |
---|
286 | 651 | if (vnd_userial.fd == -1) |
---|
287 | 652 | return; |
---|
288 | 653 | |
---|
| 654 | + if ((aicbt_transtype & AICBT_TRANS_UART) && (aicbt_transtype & AICBT_TRANS_H5)) { |
---|
289 | 655 | #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) |
---|
290 | | - /* de-assert bt_wake BEFORE closing port */ |
---|
291 | | - ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); |
---|
| 656 | + /* de-assert bt_wake BEFORE closing port */ |
---|
| 657 | + ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); |
---|
292 | 658 | #endif |
---|
| 659 | + //h5_int_interface->h5_int_cleanup(); |
---|
293 | 660 | |
---|
294 | | - ALOGI("device fd = %d close", vnd_userial.fd); |
---|
295 | | - // flush Tx before close to make sure no chars in buffer |
---|
296 | | - tcflush(vnd_userial.fd, TCIOFLUSH); |
---|
297 | | - if ((result = close(vnd_userial.fd)) < 0) |
---|
298 | | - ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result); |
---|
| 661 | + } |
---|
| 662 | + |
---|
| 663 | + vnd_userial.thread_running = false; |
---|
| 664 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 665 | + if (sco_cb.thread_sco_running) { |
---|
| 666 | + sco_cb.thread_sco_running = false; |
---|
| 667 | + unsigned char close_signal = 1; |
---|
| 668 | + ssize_t ret; |
---|
| 669 | + AIC_NO_INTR(ret = write(sco_cb.signal_fd[0], &close_signal, 1)); |
---|
| 670 | + pthread_join(sco_cb.thread_socket_sco_id, NULL); |
---|
| 671 | + } |
---|
| 672 | +#endif |
---|
| 673 | + Heartbeat_cleanup(); |
---|
| 674 | + AIC_btservice_destroyed(); |
---|
| 675 | + userial_send_close_signal(); |
---|
| 676 | + userial_uart_close(); |
---|
| 677 | + userial_coex_close(); |
---|
| 678 | + userial_socket_close(); |
---|
| 679 | + userial_quene_close(); |
---|
| 680 | + if ((aicbt_transtype & AICBT_TRANS_UART) && (aicbt_transtype & AICBT_TRANS_H5)) { |
---|
| 681 | + h5_int_interface->h5_int_cleanup(); |
---|
| 682 | + } |
---|
299 | 683 | |
---|
300 | 684 | vnd_userial.fd = -1; |
---|
| 685 | + vnd_userial.btdriver_state = false; |
---|
| 686 | + if (aic_parse_manager) { |
---|
| 687 | + aic_parse_manager->aic_parse_cleanup(); |
---|
| 688 | + } |
---|
| 689 | + aic_parse_manager = NULL; |
---|
| 690 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 691 | + sbc_finish(&sco_cb.sbc_enc); |
---|
| 692 | + sbc_finish(&sco_cb.sbc_dec); |
---|
| 693 | +#endif |
---|
| 694 | + ALOGD("%s finish", __func__); |
---|
301 | 695 | } |
---|
302 | 696 | |
---|
303 | 697 | /******************************************************************************* |
---|
.. | .. |
---|
331 | 725 | *******************************************************************************/ |
---|
332 | 726 | void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data) |
---|
333 | 727 | { |
---|
| 728 | + AIC_UNUSED(p_data); |
---|
334 | 729 | switch (op) { |
---|
335 | 730 | #if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE) |
---|
336 | 731 | case USERIAL_OP_ASSERT_BT_WAKE: |
---|
337 | | - VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##"); |
---|
| 732 | + VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake##"); |
---|
338 | 733 | ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL); |
---|
339 | 734 | break; |
---|
340 | 735 | |
---|
341 | 736 | case USERIAL_OP_DEASSERT_BT_WAKE: |
---|
342 | | - VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##"); |
---|
| 737 | + VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake##"); |
---|
343 | 738 | ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL); |
---|
344 | 739 | break; |
---|
345 | 740 | |
---|
.. | .. |
---|
365 | 760 | *******************************************************************************/ |
---|
366 | 761 | int userial_set_port(char *p_conf_name, char *p_conf_value, int param) |
---|
367 | 762 | { |
---|
| 763 | + AIC_UNUSED(p_conf_name); |
---|
| 764 | + AIC_UNUSED(param); |
---|
368 | 765 | strcpy(vnd_userial.port_name, p_conf_value); |
---|
369 | 766 | |
---|
370 | 767 | return 0; |
---|
371 | 768 | } |
---|
372 | 769 | |
---|
| 770 | +/******************************************************************************* |
---|
| 771 | +** |
---|
| 772 | +** Function userial_vendor_set_hw_fctrl |
---|
| 773 | +** |
---|
| 774 | +** Description Conduct vendor-specific close work |
---|
| 775 | +** |
---|
| 776 | +** Returns None |
---|
| 777 | +** |
---|
| 778 | +*******************************************************************************/ |
---|
| 779 | +void userial_vendor_set_hw_fctrl(uint8_t hw_fctrl) |
---|
| 780 | +{ |
---|
| 781 | + struct termios termios_old; |
---|
| 782 | + |
---|
| 783 | + if (vnd_userial.fd == -1) { |
---|
| 784 | + ALOGE("vnd_userial.fd is -1"); |
---|
| 785 | + return; |
---|
| 786 | + } |
---|
| 787 | + |
---|
| 788 | + tcgetattr(vnd_userial.fd, &termios_old); |
---|
| 789 | + if (hw_fctrl) { |
---|
| 790 | + if (termios_old.c_cflag & CRTSCTS) { |
---|
| 791 | + BTVNDDBG("userial_vendor_set_hw_fctrl already hw flowcontrol on"); |
---|
| 792 | + return; |
---|
| 793 | + } else { |
---|
| 794 | + termios_old.c_cflag |= CRTSCTS; |
---|
| 795 | + tcsetattr(vnd_userial.fd, TCSANOW, &termios_old); |
---|
| 796 | + BTVNDDBG("userial_vendor_set_hw_fctrl set hw flowcontrol on"); |
---|
| 797 | + } |
---|
| 798 | + } else { |
---|
| 799 | + if (termios_old.c_cflag & CRTSCTS) { |
---|
| 800 | + termios_old.c_cflag &= ~CRTSCTS; |
---|
| 801 | + tcsetattr(vnd_userial.fd, TCSANOW, &termios_old); |
---|
| 802 | + return; |
---|
| 803 | + } else { |
---|
| 804 | + ALOGI("userial_vendor_set_hw_fctrl set hw flowcontrol off"); |
---|
| 805 | + return; |
---|
| 806 | + } |
---|
| 807 | + } |
---|
| 808 | +} |
---|
| 809 | + |
---|
| 810 | +static uint16_t h4_int_transmit_data(uint8_t *data, uint16_t total_length) { |
---|
| 811 | + assert(data != NULL); |
---|
| 812 | + assert(total_length > 0); |
---|
| 813 | + |
---|
| 814 | + uint16_t length = total_length; |
---|
| 815 | + uint16_t transmitted_length = 0; |
---|
| 816 | + while (length > 0 && vnd_userial.btdriver_state) { |
---|
| 817 | + ssize_t ret = write(vnd_userial.fd, data + transmitted_length, length); |
---|
| 818 | + switch (ret) { |
---|
| 819 | + case -1: |
---|
| 820 | + ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno)); |
---|
| 821 | + goto done; |
---|
| 822 | + case 0: |
---|
| 823 | + // If we wrote nothing, don't loop more because we |
---|
| 824 | + // can't go to infinity or beyond, ohterwise H5 can resend data |
---|
| 825 | + ALOGE("%s, ret %zd", __func__, ret); |
---|
| 826 | + goto done; |
---|
| 827 | + default: |
---|
| 828 | + transmitted_length += ret; |
---|
| 829 | + length -= ret; |
---|
| 830 | + break; |
---|
| 831 | + } |
---|
| 832 | + } |
---|
| 833 | + |
---|
| 834 | +done: |
---|
| 835 | + return transmitted_length; |
---|
| 836 | +} |
---|
| 837 | + |
---|
| 838 | +static void userial_enqueue_coex_rawdata(unsigned char *buffer, int length, bool is_recved) |
---|
| 839 | +{ |
---|
| 840 | + AIC_BUFFER *skb_data = RtbAllocate(length, 0); |
---|
| 841 | + AIC_BUFFER *skb_type = RtbAllocate(1, 0); |
---|
| 842 | + memcpy(skb_data->Data, buffer, length); |
---|
| 843 | + skb_data->Length = length; |
---|
| 844 | + if (is_recved) { |
---|
| 845 | + *skb_type->Data = AIC_DATA_RECEIVED; |
---|
| 846 | + skb_type->Length = 1; |
---|
| 847 | + RtbQueueTail(vnd_userial.recv_data, skb_data); |
---|
| 848 | + RtbQueueTail(vnd_userial.data_order, skb_type); |
---|
| 849 | + } else { |
---|
| 850 | + *skb_type->Data = AIC_DATA_SEND; |
---|
| 851 | + skb_type->Length = 1; |
---|
| 852 | + RtbQueueTail(vnd_userial.send_data, skb_data); |
---|
| 853 | + RtbQueueTail(vnd_userial.data_order, skb_type); |
---|
| 854 | + } |
---|
| 855 | + |
---|
| 856 | + if (eventfd_write(vnd_userial.event_fd, 1) == -1) { |
---|
| 857 | + ALOGE("%s unable to write for coex event fd.", __func__); |
---|
| 858 | + } |
---|
| 859 | +} |
---|
| 860 | + |
---|
| 861 | +#ifdef AIC_HANDLE_EVENT |
---|
| 862 | +static void userial_send_cmd_to_controller(unsigned char *recv_buffer, int total_length) |
---|
| 863 | +{ |
---|
| 864 | + if (aicbt_transtype & AICBT_TRANS_H4) { |
---|
| 865 | + h4_int_transmit_data(recv_buffer, total_length); |
---|
| 866 | + } else { |
---|
| 867 | + h5_int_interface->h5_send_cmd(DATA_TYPE_COMMAND, &recv_buffer[1], (total_length - 1)); |
---|
| 868 | + } |
---|
| 869 | + userial_enqueue_coex_rawdata(recv_buffer, total_length, false); |
---|
| 870 | +} |
---|
| 871 | +#endif |
---|
| 872 | + |
---|
| 873 | +static void userial_send_acl_to_controller(unsigned char *recv_buffer, int total_length) |
---|
| 874 | +{ |
---|
| 875 | + if (aicbt_transtype & AICBT_TRANS_H4) { |
---|
| 876 | + h4_int_transmit_data(recv_buffer, total_length); |
---|
| 877 | + } else { |
---|
| 878 | + h5_int_interface->h5_send_acl_data(DATA_TYPE_ACL, &recv_buffer[1], (total_length - 1)); |
---|
| 879 | + } |
---|
| 880 | + userial_enqueue_coex_rawdata(recv_buffer, total_length, false); |
---|
| 881 | +} |
---|
| 882 | + |
---|
| 883 | +static void userial_send_sco_to_controller(unsigned char *recv_buffer, int total_length) |
---|
| 884 | +{ |
---|
| 885 | + if (aicbt_transtype & AICBT_TRANS_H4) { |
---|
| 886 | + h4_int_transmit_data(recv_buffer, total_length); |
---|
| 887 | + } else { |
---|
| 888 | + h5_int_interface->h5_send_sco_data(DATA_TYPE_SCO, &recv_buffer[1], (total_length - 1)); |
---|
| 889 | + } |
---|
| 890 | + userial_enqueue_coex_rawdata(recv_buffer, total_length, false); |
---|
| 891 | +} |
---|
| 892 | + |
---|
| 893 | + |
---|
| 894 | +static int userial_coex_recv_data_handler(unsigned char *recv_buffer, int total_length) |
---|
| 895 | +{ |
---|
| 896 | + serial_data_type_t type = 0; |
---|
| 897 | + unsigned char *p_data = recv_buffer; |
---|
| 898 | + int length = total_length; |
---|
| 899 | + HC_BT_HDR *p_buf; |
---|
| 900 | + uint8_t boundary_flag; |
---|
| 901 | + uint16_t len, handle, acl_length, l2cap_length; |
---|
| 902 | + switch (coex_packet_recv_state) { |
---|
| 903 | + case AICBT_PACKET_IDLE: |
---|
| 904 | + coex_packet_bytes_need = 1; |
---|
| 905 | + while(length) { |
---|
| 906 | + type = p_data[0]; |
---|
| 907 | + length--; |
---|
| 908 | + p_data++; |
---|
| 909 | + assert((type > DATA_TYPE_COMMAND) && (type <= DATA_TYPE_EVENT)); |
---|
| 910 | + if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) { |
---|
| 911 | + ALOGE("%s invalid data type: %d", __func__, type); |
---|
| 912 | + if (!length) |
---|
| 913 | + return total_length; |
---|
| 914 | + |
---|
| 915 | + continue; |
---|
| 916 | + } |
---|
| 917 | + break; |
---|
| 918 | + } |
---|
| 919 | + coex_current_type = type; |
---|
| 920 | + coex_packet_recv_state = AICBT_PACKET_TYPE; |
---|
| 921 | + //fall through |
---|
| 922 | + |
---|
| 923 | + case AICBT_PACKET_TYPE: |
---|
| 924 | + if (coex_current_type == DATA_TYPE_ACL) { |
---|
| 925 | + coex_packet_bytes_need = 4; |
---|
| 926 | + } else if (coex_current_type == DATA_TYPE_EVENT) { |
---|
| 927 | + coex_packet_bytes_need = 2; |
---|
| 928 | + } else { |
---|
| 929 | + coex_packet_bytes_need = 3; |
---|
| 930 | + } |
---|
| 931 | + coex_resvered_length = 0; |
---|
| 932 | + coex_packet_recv_state = AICBT_PACKET_HEADER; |
---|
| 933 | + //fall through |
---|
| 934 | + |
---|
| 935 | + case AICBT_PACKET_HEADER: |
---|
| 936 | + if (length >= coex_packet_bytes_need) { |
---|
| 937 | + memcpy(&coex_resvered_buffer[coex_resvered_length], p_data, coex_packet_bytes_need); |
---|
| 938 | + coex_resvered_length += coex_packet_bytes_need; |
---|
| 939 | + length -= coex_packet_bytes_need; |
---|
| 940 | + p_data += coex_packet_bytes_need; |
---|
| 941 | + } else { |
---|
| 942 | + memcpy(&coex_resvered_buffer[coex_resvered_length], p_data, length); |
---|
| 943 | + coex_resvered_length += length; |
---|
| 944 | + coex_packet_bytes_need -= length; |
---|
| 945 | + length = 0; |
---|
| 946 | + return total_length; |
---|
| 947 | + } |
---|
| 948 | + coex_packet_recv_state = AICBT_PACKET_CONTENT; |
---|
| 949 | + |
---|
| 950 | + if (coex_current_type == DATA_TYPE_ACL) { |
---|
| 951 | + coex_packet_bytes_need = *(uint16_t *)&coex_resvered_buffer[2]; |
---|
| 952 | + } else if (coex_current_type == DATA_TYPE_EVENT){ |
---|
| 953 | + coex_packet_bytes_need = coex_resvered_buffer[1]; |
---|
| 954 | + } else { |
---|
| 955 | + coex_packet_bytes_need = coex_resvered_buffer[2]; |
---|
| 956 | + } |
---|
| 957 | + //fall through |
---|
| 958 | + |
---|
| 959 | + case AICBT_PACKET_CONTENT: |
---|
| 960 | + if (length >= coex_packet_bytes_need) { |
---|
| 961 | + memcpy(&coex_resvered_buffer[coex_resvered_length], p_data, coex_packet_bytes_need); |
---|
| 962 | + length -= coex_packet_bytes_need; |
---|
| 963 | + p_data += coex_packet_bytes_need; |
---|
| 964 | + coex_resvered_length += coex_packet_bytes_need; |
---|
| 965 | + coex_packet_bytes_need = 0; |
---|
| 966 | + } else { |
---|
| 967 | + memcpy(&coex_resvered_buffer[coex_resvered_length], p_data, length); |
---|
| 968 | + coex_resvered_length += length; |
---|
| 969 | + coex_packet_bytes_need -= length; |
---|
| 970 | + length = 0; |
---|
| 971 | + return total_length; |
---|
| 972 | + } |
---|
| 973 | + coex_packet_recv_state = AICBT_PACKET_END; |
---|
| 974 | + //fall through |
---|
| 975 | + |
---|
| 976 | + case AICBT_PACKET_END: |
---|
| 977 | + { |
---|
| 978 | + len = BT_HC_HDR_SIZE + coex_resvered_length; |
---|
| 979 | + uint8_t packet[len]; |
---|
| 980 | + p_buf = (HC_BT_HDR *) packet; |
---|
| 981 | + p_buf->offset = 0; |
---|
| 982 | + p_buf->layer_specific = 0; |
---|
| 983 | + p_buf->len = coex_resvered_length; |
---|
| 984 | + memcpy((uint8_t *)(p_buf + 1), coex_resvered_buffer, coex_resvered_length); |
---|
| 985 | + switch (coex_current_type) { |
---|
| 986 | + case DATA_TYPE_EVENT: |
---|
| 987 | + p_buf->event = MSG_HC_TO_STACK_HCI_EVT; |
---|
| 988 | + if (aic_parse_manager) |
---|
| 989 | + aic_parse_manager->aic_parse_internal_event_intercept(coex_resvered_buffer); |
---|
| 990 | + break; |
---|
| 991 | + |
---|
| 992 | + case DATA_TYPE_ACL: |
---|
| 993 | + p_buf->event = MSG_HC_TO_STACK_HCI_ACL; |
---|
| 994 | + handle = *(uint16_t *)coex_resvered_buffer; |
---|
| 995 | + acl_length = *(uint16_t *)&coex_resvered_buffer[2]; |
---|
| 996 | + l2cap_length = *(uint16_t *)&coex_resvered_buffer[4]; |
---|
| 997 | + boundary_flag = AIC_GET_BOUNDARY_FLAG(handle); |
---|
| 998 | + if (aic_parse_manager) |
---|
| 999 | + aic_parse_manager->aic_parse_l2cap_data(coex_resvered_buffer, 0); |
---|
| 1000 | + break; |
---|
| 1001 | + |
---|
| 1002 | + case DATA_TYPE_SCO: |
---|
| 1003 | + p_buf->event = MSG_HC_TO_STACK_HCI_SCO; |
---|
| 1004 | + break; |
---|
| 1005 | + |
---|
| 1006 | + default: |
---|
| 1007 | + p_buf->event = MSG_HC_TO_STACK_HCI_ERR; |
---|
| 1008 | + break; |
---|
| 1009 | + } |
---|
| 1010 | + aic_btsnoop_capture(p_buf, true); |
---|
| 1011 | + } |
---|
| 1012 | + break; |
---|
| 1013 | + |
---|
| 1014 | + default: |
---|
| 1015 | + break; |
---|
| 1016 | + } |
---|
| 1017 | + |
---|
| 1018 | + coex_packet_recv_state = AICBT_PACKET_IDLE; |
---|
| 1019 | + coex_packet_bytes_need = 0; |
---|
| 1020 | + coex_current_type = 0; |
---|
| 1021 | + coex_resvered_length = 0; |
---|
| 1022 | + |
---|
| 1023 | + return (total_length - length); |
---|
| 1024 | +} |
---|
| 1025 | + |
---|
| 1026 | +static void userial_coex_send_data_handler(unsigned char *send_buffer, int total_length) |
---|
| 1027 | +{ |
---|
| 1028 | + serial_data_type_t type = 0; |
---|
| 1029 | + type = send_buffer[0]; |
---|
| 1030 | + int length = total_length; |
---|
| 1031 | + HC_BT_HDR *p_buf; |
---|
| 1032 | + uint8_t boundary_flag; |
---|
| 1033 | + uint16_t len, handle, acl_length, l2cap_length; |
---|
| 1034 | + |
---|
| 1035 | + len = BT_HC_HDR_SIZE + (length - 1); |
---|
| 1036 | + uint8_t packet[len]; |
---|
| 1037 | + p_buf = (HC_BT_HDR *) packet; |
---|
| 1038 | + p_buf->offset = 0; |
---|
| 1039 | + p_buf->layer_specific = 0; |
---|
| 1040 | + p_buf->len = total_length -1; |
---|
| 1041 | + memcpy((uint8_t *)(p_buf + 1), &send_buffer[1], length - 1); |
---|
| 1042 | + |
---|
| 1043 | + switch (type) { |
---|
| 1044 | + case DATA_TYPE_COMMAND: |
---|
| 1045 | + p_buf->event = MSG_STACK_TO_HC_HCI_CMD; |
---|
| 1046 | + if (aic_parse_manager) |
---|
| 1047 | + aic_parse_manager->aic_parse_command(&send_buffer[1]); |
---|
| 1048 | + break; |
---|
| 1049 | + |
---|
| 1050 | + case DATA_TYPE_ACL: |
---|
| 1051 | + p_buf->event = MSG_STACK_TO_HC_HCI_ACL; |
---|
| 1052 | + handle = *(uint16_t *)&send_buffer[1]; |
---|
| 1053 | + acl_length = *(uint16_t *)&send_buffer[3]; |
---|
| 1054 | + l2cap_length = *(uint16_t *)&send_buffer[5]; |
---|
| 1055 | + boundary_flag = AIC_GET_BOUNDARY_FLAG(handle); |
---|
| 1056 | + if (aic_parse_manager) |
---|
| 1057 | + aic_parse_manager->aic_parse_l2cap_data(&send_buffer[1], 1); |
---|
| 1058 | + |
---|
| 1059 | + break; |
---|
| 1060 | + |
---|
| 1061 | + case DATA_TYPE_SCO: |
---|
| 1062 | + p_buf->event = MSG_STACK_TO_HC_HCI_SCO; |
---|
| 1063 | + break; |
---|
| 1064 | + default: |
---|
| 1065 | + p_buf->event = 0; |
---|
| 1066 | + ALOGE("%s invalid data type: %d", __func__, type); |
---|
| 1067 | + break; |
---|
| 1068 | + } |
---|
| 1069 | + aic_btsnoop_capture(p_buf, false); |
---|
| 1070 | +} |
---|
| 1071 | + |
---|
| 1072 | +static void userial_coex_handler(void *context) |
---|
| 1073 | +{ |
---|
| 1074 | + AIC_UNUSED(context); |
---|
| 1075 | + AIC_BUFFER *skb_data; |
---|
| 1076 | + AIC_BUFFER *skb_type; |
---|
| 1077 | + eventfd_t value; |
---|
| 1078 | + unsigned int read_length = 0; |
---|
| 1079 | + eventfd_read(vnd_userial.event_fd, &value); |
---|
| 1080 | + if (!value && !vnd_userial.thread_running) { |
---|
| 1081 | + return; |
---|
| 1082 | + } |
---|
| 1083 | + |
---|
| 1084 | + while (!RtbQueueIsEmpty(vnd_userial.data_order)) { |
---|
| 1085 | + read_length = 0; |
---|
| 1086 | + skb_type = RtbDequeueHead(vnd_userial.data_order); |
---|
| 1087 | + if (skb_type) { |
---|
| 1088 | + if (*(skb_type->Data) == AIC_DATA_RECEIVED) { |
---|
| 1089 | + skb_data = RtbDequeueHead(vnd_userial.recv_data); |
---|
| 1090 | + if (skb_data) { |
---|
| 1091 | + do { |
---|
| 1092 | + read_length += userial_coex_recv_data_handler((skb_data->Data + read_length), (skb_data->Length - read_length)); |
---|
| 1093 | + } while(read_length < skb_data->Length); |
---|
| 1094 | + RtbFree(skb_data); |
---|
| 1095 | + } |
---|
| 1096 | + } else { |
---|
| 1097 | + skb_data = RtbDequeueHead(vnd_userial.send_data); |
---|
| 1098 | + if (skb_data) { |
---|
| 1099 | + userial_coex_send_data_handler(skb_data->Data, skb_data->Length); |
---|
| 1100 | + RtbFree(skb_data); |
---|
| 1101 | + } |
---|
| 1102 | + } |
---|
| 1103 | + RtbFree(skb_type); |
---|
| 1104 | + } |
---|
| 1105 | + } |
---|
| 1106 | +} |
---|
| 1107 | + |
---|
| 1108 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 1109 | +//receive sco encode or non-encode data over hci, we need to decode msbc data to pcm, and send it to sco audio hal |
---|
| 1110 | +static void *userial_recv_sco_thread(void *arg) |
---|
| 1111 | +{ |
---|
| 1112 | + AIC_UNUSED(arg); |
---|
| 1113 | + AIC_BUFFER *skb_sco_data; |
---|
| 1114 | + unsigned char dec_data[480]; |
---|
| 1115 | + unsigned char pcm_data[960]; |
---|
| 1116 | + int index = 0; |
---|
| 1117 | + //uint16_t sco_packet_len = 60; |
---|
| 1118 | + uint8_t *p_data = NULL; |
---|
| 1119 | + int res = 0; |
---|
| 1120 | + size_t writen = 0; |
---|
| 1121 | + prctl(PR_SET_NAME, (unsigned long)"userial_recv_sco_thread", 0, 0, 0); |
---|
| 1122 | + sco_cb.pcm_dec_seq = -1; |
---|
| 1123 | + sco_cb.pcm_dec_frame = 0; |
---|
| 1124 | +#ifdef CONFIG_SCO_MSBC_PLC |
---|
| 1125 | + unsigned char plc_data[480]; |
---|
| 1126 | + struct PLC_State plc_state; |
---|
| 1127 | + InitPLC(&plc_state); |
---|
| 1128 | +#endif |
---|
| 1129 | + /* |
---|
| 1130 | + FILE *file; |
---|
| 1131 | + unsigned char enc_data[60]; |
---|
| 1132 | + file = fopen("/data/misc/bluedroid/sco_capture.raw", "rb"); |
---|
| 1133 | + FILE *file2; |
---|
| 1134 | + file2 = fopen("/data/misc/bluedroid/sco_capture.pcm", "wb"); |
---|
| 1135 | + if (!file) { |
---|
| 1136 | + ALOGE("Unable to create file"); |
---|
| 1137 | + return NULL; |
---|
| 1138 | + } |
---|
| 1139 | + */ |
---|
| 1140 | + //RtbEmptyQueue(sco_cb.recv_sco_data); |
---|
| 1141 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 1142 | + while (RtbGetQueueLen(sco_cb.recv_sco_data) > 60) { |
---|
| 1143 | + AIC_BUFFER *sco_data = RtbDequeueHead(sco_cb.recv_sco_data); |
---|
| 1144 | + if (sco_data) |
---|
| 1145 | + RtbFree(sco_data); |
---|
| 1146 | + } |
---|
| 1147 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 1148 | + |
---|
| 1149 | + ALOGD("userial_recv_sco_thread start"); |
---|
| 1150 | + while (sco_cb.thread_recv_sco_running) { |
---|
| 1151 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 1152 | + while (RtbQueueIsEmpty(sco_cb.recv_sco_data) && sco_cb.thread_sco_running) { |
---|
| 1153 | + pthread_cond_wait(&sco_cb.sco_recv_cond, &sco_cb.sco_recv_mutex); |
---|
| 1154 | + } |
---|
| 1155 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 1156 | + skb_sco_data = RtbDequeueHead(sco_cb.recv_sco_data); |
---|
| 1157 | + if (!skb_sco_data) |
---|
| 1158 | + continue; |
---|
| 1159 | + p_data = skb_sco_data->Data; |
---|
| 1160 | + |
---|
| 1161 | + switch (sco_cb.codec_para.input_format) { |
---|
| 1162 | + case ESCO_CODING_FORMAT_LINEAR: // PCM raw data |
---|
| 1163 | + case ESCO_CODING_FORMAT_CVSD: // Cvsd codec |
---|
| 1164 | + res = Skt_Send_noblock(sco_cb.data_fd, p_data, sco_cb.sco_packet_len); |
---|
| 1165 | + if (res < 0) { |
---|
| 1166 | + ALOGE("userial_recv_sco_thread, send noblock error"); |
---|
| 1167 | + } |
---|
| 1168 | + break; |
---|
| 1169 | + case ESCO_CODING_FORMAT_MSBC: { |
---|
| 1170 | + /* |
---|
| 1171 | + //if (fwrite(skb_sco_data->Data, 1, 60, file) != 60) { |
---|
| 1172 | + //ALOGE("Error capturing sample"); |
---|
| 1173 | + //} |
---|
| 1174 | + if (fread(enc_data, 1, 60, file) > 0) { |
---|
| 1175 | + ALOGD("userial_recv_sco_thread, fread data"); |
---|
| 1176 | + res = sbc_decode(&sco_cb.sbc_dec, &enc_data[2], 58, dec_data, 240, &writen); |
---|
| 1177 | + } else { |
---|
| 1178 | + fseek(file, 0L, SEEK_SET); |
---|
| 1179 | + if (fread(enc_data, 1, 60, file) > 0) { |
---|
| 1180 | + res = sbc_decode(&sco_cb.sbc_dec, &enc_data[2], 58, dec_data, 240, &writen); |
---|
| 1181 | + } |
---|
| 1182 | + } */ |
---|
| 1183 | + uint8_t seq = (p_data[1] >> 4) & 0x0F; |
---|
| 1184 | + uint32_t last_dec_frame = sco_cb.pcm_dec_frame; |
---|
| 1185 | + if (sco_cb.pcm_dec_seq == -1) { |
---|
| 1186 | + uint8_t step = 0; |
---|
| 1187 | + sco_cb.pcm_dec_seq = (int8_t)seq; |
---|
| 1188 | + step += (seq & 0x03)/2; |
---|
| 1189 | + step += ((seq >> 2) & 0x03) / 2; |
---|
| 1190 | + sco_cb.pcm_dec_frame += step; |
---|
| 1191 | + } else { |
---|
| 1192 | + do { |
---|
| 1193 | + sco_cb.pcm_dec_seq = (uint8_t)((btui_msbc_h2[(++sco_cb.pcm_dec_frame) % 4] >> 12) & 0x0F); |
---|
| 1194 | + if (sco_cb.pcm_dec_frame - last_dec_frame > 100) { |
---|
| 1195 | + // fix package loss. |
---|
| 1196 | + ALOGE("lost frame: %d, may use the plc function", (sco_cb.pcm_dec_frame - last_dec_frame)); |
---|
| 1197 | + break; |
---|
| 1198 | + } |
---|
| 1199 | + } while (sco_cb.pcm_dec_seq != seq); |
---|
| 1200 | + |
---|
| 1201 | + if ((last_dec_frame + 1) != sco_cb.pcm_dec_frame) { |
---|
| 1202 | +#ifdef CONFIG_SCO_MSBC_PLC |
---|
| 1203 | + uint8_t lost_frame = sco_cb.pcm_dec_frame - last_dec_frame - 1; |
---|
| 1204 | + int i = 0; |
---|
| 1205 | + for (i = 0; i < lost_frame; i++) { |
---|
| 1206 | + sbc_decode(&sco_cb.sbc_dec, indices0, 58, dec_data, 240, &writen); |
---|
| 1207 | + PLC_bad_frame(&plc_state, (short*)dec_data, (short*)plc_data); |
---|
| 1208 | + memcpy(&pcm_data[240 * index], plc_data, 240); |
---|
| 1209 | + index = (index + 1) % 4; |
---|
| 1210 | + if (index == 0) { |
---|
| 1211 | + Skt_Send_noblock(sco_cb.data_fd, pcm_data, 960); |
---|
| 1212 | + } |
---|
| 1213 | + } |
---|
| 1214 | +#endif |
---|
| 1215 | + } |
---|
| 1216 | + } |
---|
| 1217 | + |
---|
| 1218 | + res = sbc_decode(&sco_cb.sbc_dec, (p_data + 2), 58, dec_data, 240, &writen); |
---|
| 1219 | + if (res > 0) { |
---|
| 1220 | +#ifdef CONFIG_SCO_MSBC_PLC |
---|
| 1221 | + PLC_good_frame(&plc_state, (short*)dec_data, (short*)plc_data); |
---|
| 1222 | + memcpy(&pcm_data[240 * index], plc_data, 240); |
---|
| 1223 | +#else |
---|
| 1224 | + memcpy(&pcm_data[240 * index], dec_data, 240); |
---|
| 1225 | +#endif |
---|
| 1226 | + //if (fwrite(dec_data, 240, 1, file2) != 240) { |
---|
| 1227 | + // ALOGE("Error capturing sample"); |
---|
| 1228 | + //} |
---|
| 1229 | + index = (index + 1) % 4; |
---|
| 1230 | + if (index == 0) { |
---|
| 1231 | + Skt_Send_noblock(sco_cb.data_fd, pcm_data, 960); |
---|
| 1232 | + } |
---|
| 1233 | + } else { |
---|
| 1234 | + ALOGE("msbc decode fail! May use PLC function"); |
---|
| 1235 | +#ifdef CONFIG_SCO_MSBC_PLC |
---|
| 1236 | + sbc_decode(&sco_cb.sbc_dec, indices0, 58, dec_data, 240, &writen); |
---|
| 1237 | + PLC_bad_frame(&plc_state, (short*)dec_data, (short*)plc_data); |
---|
| 1238 | + memcpy(&pcm_data[240 * index], plc_data, 240); |
---|
| 1239 | + index = (index + 1) % 4; |
---|
| 1240 | + if (index == 0) { |
---|
| 1241 | + Skt_Send_noblock(sco_cb.data_fd, pcm_data, 960); |
---|
| 1242 | + } |
---|
| 1243 | +#endif |
---|
| 1244 | + } |
---|
| 1245 | + } |
---|
| 1246 | + break; |
---|
| 1247 | + default: |
---|
| 1248 | + ALOGE("Unsupport coding format: 0x%02X", sco_cb.codec_para.input_format); |
---|
| 1249 | + break; |
---|
| 1250 | + } |
---|
| 1251 | + RtbFree(skb_sco_data); |
---|
| 1252 | + } |
---|
| 1253 | + ALOGD("userial_recv_sco_thread exit"); |
---|
| 1254 | + RtbEmptyQueue(sco_cb.recv_sco_data); |
---|
| 1255 | + return NULL; |
---|
| 1256 | +} |
---|
| 1257 | + |
---|
| 1258 | +static void *userial_send_sco_thread(void *arg) |
---|
| 1259 | +{ |
---|
| 1260 | + AIC_UNUSED(arg); |
---|
| 1261 | + unsigned char enc_data[240]; |
---|
| 1262 | + unsigned char pcm_data[960 * 2]; |
---|
| 1263 | + unsigned char send_data[240]; |
---|
| 1264 | + int writen = 0; |
---|
| 1265 | + int num_read; |
---|
| 1266 | + prctl(PR_SET_NAME, (unsigned long)"userial_send_sco_thread", 0, 0, 0); |
---|
| 1267 | + sco_cb.pcm_enc_seq = 0; |
---|
| 1268 | + int i; |
---|
| 1269 | + int need_read = sco_cb.sco_packet_len; |
---|
| 1270 | + |
---|
| 1271 | + if (sco_cb.codec_para.output_format == ESCO_CODING_FORMAT_MSBC) |
---|
| 1272 | + need_read = 240; |
---|
| 1273 | + |
---|
| 1274 | + /* |
---|
| 1275 | + FILE *file; |
---|
| 1276 | + file = fopen("/data/misc/bluedroid/sco_playback.raw", "rb"); |
---|
| 1277 | + if (!file) { |
---|
| 1278 | + ALOGE("Unable to create file"); |
---|
| 1279 | + return NULL; |
---|
| 1280 | + } |
---|
| 1281 | + */ |
---|
| 1282 | + //when start sco send thread, first send 6 sco data to controller |
---|
| 1283 | + if (sco_cb.codec_para.output_format == ESCO_CODING_FORMAT_CVSD) { |
---|
| 1284 | + memset(pcm_data, 0, (48*6)); |
---|
| 1285 | + for (i = 0; i < 6; i++) { |
---|
| 1286 | + send_data[0] = DATA_TYPE_SCO; |
---|
| 1287 | + send_data[3] = 48; |
---|
| 1288 | + *(uint16_t *)&send_data[1] = sco_cb.sco_handle; |
---|
| 1289 | + memcpy(&send_data[4], &pcm_data[i*48], 48); |
---|
| 1290 | + userial_send_sco_to_controller(send_data, 52); |
---|
| 1291 | + } |
---|
| 1292 | + } |
---|
| 1293 | + ALOGD("userial_send_sco_thread start"); |
---|
| 1294 | + while (sco_cb.thread_send_sco_running) { |
---|
| 1295 | + num_read = Skt_Read(sco_cb.data_fd, pcm_data, need_read, &sco_cb.thread_send_sco_running); |
---|
| 1296 | + if (!num_read) |
---|
| 1297 | + continue; |
---|
| 1298 | + |
---|
| 1299 | + switch (sco_cb.codec_para.output_format) { |
---|
| 1300 | + case ESCO_CODING_FORMAT_LINEAR: |
---|
| 1301 | + send_data[0] = DATA_TYPE_SCO; |
---|
| 1302 | + send_data[3] = sco_cb.sco_packet_len; |
---|
| 1303 | + *(uint16_t *)&send_data[1] = sco_cb.sco_handle; |
---|
| 1304 | + memcpy(&send_data[4], &pcm_data[0], sco_cb.sco_packet_len); |
---|
| 1305 | + userial_send_sco_to_controller(send_data, sco_cb.sco_packet_len + 4); |
---|
| 1306 | + break; |
---|
| 1307 | + case ESCO_CODING_FORMAT_CVSD: |
---|
| 1308 | + for (i = 0; i < 5; i++) { |
---|
| 1309 | + send_data[0] = DATA_TYPE_SCO; |
---|
| 1310 | + send_data[3] = 48; |
---|
| 1311 | + *(uint16_t *)&send_data[1] = sco_cb.sco_handle; |
---|
| 1312 | + memcpy(&send_data[4], &pcm_data[i*48], 48); |
---|
| 1313 | + userial_send_sco_to_controller(send_data, 52); |
---|
| 1314 | + } |
---|
| 1315 | + break; |
---|
| 1316 | + case ESCO_CODING_FORMAT_MSBC: |
---|
| 1317 | + if (sbc_encode(&sco_cb.sbc_enc, &pcm_data[0], 240, &enc_data[2], 58, (ssize_t *)&writen) <= 0) { |
---|
| 1318 | + ALOGE("sbc encode error!"); |
---|
| 1319 | + } else { |
---|
| 1320 | + *(uint16_t*)(&(enc_data[0])) = btui_msbc_h2[sco_cb.pcm_enc_seq % 4]; |
---|
| 1321 | + sco_cb.pcm_enc_seq++; |
---|
| 1322 | + enc_data[59] = 0x00; //padding |
---|
| 1323 | + } |
---|
| 1324 | + |
---|
| 1325 | + send_data[0] = DATA_TYPE_SCO; |
---|
| 1326 | + send_data[3] = sco_cb.sco_packet_len; |
---|
| 1327 | + *(uint16_t *)&send_data[1] = sco_cb.sco_handle; |
---|
| 1328 | + memcpy(&send_data[4], &enc_data[0], sco_cb.sco_packet_len); |
---|
| 1329 | + userial_send_sco_to_controller(send_data, sco_cb.sco_packet_len + 4); |
---|
| 1330 | + break; |
---|
| 1331 | + default: |
---|
| 1332 | + ALOGE("%s(%d), unsupport coding format: 0x%02X", __func__, __LINE__, sco_cb.codec_para.output_format); |
---|
| 1333 | + break; |
---|
| 1334 | + } |
---|
| 1335 | + } |
---|
| 1336 | + ALOGD("userial_send_sco_thread exit"); |
---|
| 1337 | + return NULL; |
---|
| 1338 | +} |
---|
| 1339 | + |
---|
| 1340 | +static void userial_sco_send_socket_stop() |
---|
| 1341 | +{ |
---|
| 1342 | + ALOGD("%s", __func__); |
---|
| 1343 | + pthread_mutex_lock(&sco_cb.sco_send_mutex); |
---|
| 1344 | + if (sco_cb.thread_send_sco_running) { |
---|
| 1345 | + sco_cb.thread_send_sco_running = false; |
---|
| 1346 | + } else { |
---|
| 1347 | + pthread_mutex_unlock(&sco_cb.sco_send_mutex); |
---|
| 1348 | + return; |
---|
| 1349 | + } |
---|
| 1350 | + pthread_mutex_unlock(&sco_cb.sco_send_mutex); |
---|
| 1351 | + |
---|
| 1352 | + if (sco_cb.thread_send_sco_id != -1) { |
---|
| 1353 | + pthread_join(sco_cb.thread_send_sco_id, NULL); |
---|
| 1354 | + sco_cb.thread_send_sco_id = -1; |
---|
| 1355 | + } |
---|
| 1356 | +} |
---|
| 1357 | + |
---|
| 1358 | +static void userial_sco_recv_socket_stop() |
---|
| 1359 | +{ |
---|
| 1360 | + ALOGD("%s", __func__); |
---|
| 1361 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 1362 | + if (sco_cb.thread_recv_sco_running) { |
---|
| 1363 | + sco_cb.thread_recv_sco_running = false; |
---|
| 1364 | + pthread_cond_signal(&sco_cb.sco_recv_cond); |
---|
| 1365 | + } else { |
---|
| 1366 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 1367 | + return; |
---|
| 1368 | + |
---|
| 1369 | + } |
---|
| 1370 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 1371 | + |
---|
| 1372 | + if (sco_cb.thread_recv_sco_id != -1) { |
---|
| 1373 | + pthread_join(sco_cb.thread_recv_sco_id, NULL); |
---|
| 1374 | + sco_cb.thread_recv_sco_id = -1; |
---|
| 1375 | + } |
---|
| 1376 | + |
---|
| 1377 | +} |
---|
| 1378 | + |
---|
| 1379 | +static void userial_sco_socket_stop() |
---|
| 1380 | +{ |
---|
| 1381 | + ALOGD("%s", __func__); |
---|
| 1382 | + userial_sco_send_socket_stop(); |
---|
| 1383 | + userial_sco_recv_socket_stop(); |
---|
| 1384 | + if (sco_cb.ctrl_fd > 0) { |
---|
| 1385 | + close(sco_cb.ctrl_fd); |
---|
| 1386 | + sco_cb.ctrl_fd = -1; |
---|
| 1387 | + } |
---|
| 1388 | + |
---|
| 1389 | + if (sco_cb.data_fd > 0) { |
---|
| 1390 | + close(sco_cb.data_fd); |
---|
| 1391 | + sco_cb.data_fd = -1; |
---|
| 1392 | + } |
---|
| 1393 | + RtbEmptyQueue(sco_cb.recv_sco_data); |
---|
| 1394 | +} |
---|
| 1395 | + |
---|
| 1396 | +static void userial_sco_ctrl_skt_handle() |
---|
| 1397 | +{ |
---|
| 1398 | + uint8_t cmd = 0, ack = 0;; |
---|
| 1399 | + int result = Skt_Read(sco_cb.ctrl_fd, &cmd, 1, NULL); |
---|
| 1400 | + |
---|
| 1401 | + if (result == 0) { |
---|
| 1402 | + userial_sco_socket_stop(); |
---|
| 1403 | + return; |
---|
| 1404 | + } |
---|
| 1405 | + |
---|
| 1406 | + ALOGD("%s, cmd: %d", __func__, cmd); |
---|
| 1407 | + switch (cmd) { |
---|
| 1408 | + case SCO_CTRL_CMD_CHECK_READY: |
---|
| 1409 | + break; |
---|
| 1410 | + |
---|
| 1411 | + case SCO_CTRL_CMD_OUT_START: |
---|
| 1412 | + { |
---|
| 1413 | + pthread_attr_t thread_attr; |
---|
| 1414 | + pthread_attr_init(&thread_attr); |
---|
| 1415 | + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); |
---|
| 1416 | + sco_cb.thread_send_sco_running = true; |
---|
| 1417 | + if (pthread_create(&sco_cb.thread_send_sco_id, &thread_attr, userial_send_sco_thread, NULL) != 0 ) { |
---|
| 1418 | + ALOGE("pthread_create : %s", strerror(errno)); |
---|
| 1419 | + } |
---|
| 1420 | + } |
---|
| 1421 | + break; |
---|
| 1422 | + |
---|
| 1423 | + case SCO_CTRL_CMD_IN_START: |
---|
| 1424 | + { |
---|
| 1425 | + pthread_attr_t thread_attr; |
---|
| 1426 | + pthread_attr_init(&thread_attr); |
---|
| 1427 | + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); |
---|
| 1428 | + sco_cb.thread_recv_sco_running = true; |
---|
| 1429 | + if (pthread_create(&sco_cb.thread_recv_sco_id, &thread_attr, userial_recv_sco_thread, NULL) != 0 ) { |
---|
| 1430 | + ALOGE("pthread_create : %s", strerror(errno)); |
---|
| 1431 | + } |
---|
| 1432 | + } |
---|
| 1433 | + break; |
---|
| 1434 | + |
---|
| 1435 | + case SCO_CTRL_CMD_OUT_STOP: |
---|
| 1436 | + userial_sco_send_socket_stop(); |
---|
| 1437 | + break; |
---|
| 1438 | + |
---|
| 1439 | + case SCO_CTRL_CMD_IN_STOP: |
---|
| 1440 | + userial_sco_recv_socket_stop(); |
---|
| 1441 | + break; |
---|
| 1442 | + |
---|
| 1443 | + case SCO_CTRL_CMD_SUSPEND: |
---|
| 1444 | + break; |
---|
| 1445 | + |
---|
| 1446 | + case SCO_CTRL_GET_AUDIO_CONFIG: |
---|
| 1447 | + ack = sco_cb.codec_para.input_format; |
---|
| 1448 | + Skt_Send(sco_cb.ctrl_fd, (uint8_t *)&sco_cb.codec_para, sizeof(struct codec_para_t)); |
---|
| 1449 | + break; |
---|
| 1450 | + |
---|
| 1451 | + case SCO_CTRL_CMD_CLOSE: |
---|
| 1452 | + userial_sco_socket_stop(); |
---|
| 1453 | + break; |
---|
| 1454 | + |
---|
| 1455 | + default: |
---|
| 1456 | + break; |
---|
| 1457 | + } |
---|
| 1458 | +} |
---|
| 1459 | + |
---|
| 1460 | +static void *userial_socket_sco_thread(void *arg) |
---|
| 1461 | +{ |
---|
| 1462 | + AIC_UNUSED(arg); |
---|
| 1463 | + struct sockaddr_un addr, remote; |
---|
| 1464 | + //socklen_t alen; |
---|
| 1465 | + socklen_t len = sizeof(struct sockaddr_un); |
---|
| 1466 | + fd_set read_set, active_set; |
---|
| 1467 | + int result, max_fd; |
---|
| 1468 | + int s_ctrl = socket(AF_LOCAL, SOCK_STREAM, 0); |
---|
| 1469 | + if (s_ctrl < 0) { |
---|
| 1470 | + ALOGE("ctrl socket create fail"); |
---|
| 1471 | + return NULL; |
---|
| 1472 | + } |
---|
| 1473 | + |
---|
| 1474 | + int s_data = socket(AF_LOCAL, SOCK_STREAM, 0); |
---|
| 1475 | + if (s_data < 0) { |
---|
| 1476 | + ALOGE("data socket create fail"); |
---|
| 1477 | + close(s_ctrl); |
---|
| 1478 | + return NULL; |
---|
| 1479 | + } |
---|
| 1480 | + |
---|
| 1481 | + prctl(PR_SET_NAME, (unsigned long)"userial_socket_sco_thread", 0, 0, 0); |
---|
| 1482 | + |
---|
| 1483 | + if ((socketpair(AF_UNIX, SOCK_STREAM, 0, sco_cb.signal_fd)) < 0) { |
---|
| 1484 | + ALOGE("%s, errno : %s", __func__, strerror(errno)); |
---|
| 1485 | + goto socket_close; |
---|
| 1486 | + } |
---|
| 1487 | + |
---|
| 1488 | + if (socket_local_server_bind(s_ctrl, SCO_CTRL_PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0) { |
---|
| 1489 | + ALOGE("ctrl socket failed to create (%s)", strerror(errno)); |
---|
| 1490 | + goto signal_close; |
---|
| 1491 | + } |
---|
| 1492 | + |
---|
| 1493 | + if (listen(s_ctrl, 5) < 0) { |
---|
| 1494 | + ALOGE("userial_socket_sco_thread, listen ctrl socket error : %s", strerror(errno)); |
---|
| 1495 | + goto signal_close; |
---|
| 1496 | + } |
---|
| 1497 | + |
---|
| 1498 | + if (socket_local_server_bind(s_data, SCO_DATA_PATH, ANDROID_SOCKET_NAMESPACE_ABSTRACT) < 0) { |
---|
| 1499 | + ALOGE("data socket failed to create (%s)", strerror(errno)); |
---|
| 1500 | + goto signal_close; |
---|
| 1501 | + } |
---|
| 1502 | + |
---|
| 1503 | + if (listen(s_data, 5) < 0) { |
---|
| 1504 | + ALOGE("userial_socket_sco_thread, listen data socket error : %s", strerror(errno)); |
---|
| 1505 | + goto signal_close; |
---|
| 1506 | + } |
---|
| 1507 | + |
---|
| 1508 | + ALOGD("userial_socket_sco_thread"); |
---|
| 1509 | + FD_ZERO(&read_set); |
---|
| 1510 | + FD_ZERO(&active_set); |
---|
| 1511 | + FD_SET(s_ctrl, &active_set); |
---|
| 1512 | + FD_SET(s_data, &active_set); |
---|
| 1513 | + FD_SET(sco_cb.signal_fd[1], &active_set); |
---|
| 1514 | + max_fd = MAX(s_ctrl, s_data); |
---|
| 1515 | + max_fd = MAX(max_fd, sco_cb.signal_fd[1]) + 1; |
---|
| 1516 | + while (sco_cb.thread_sco_running) { |
---|
| 1517 | + read_set = active_set; |
---|
| 1518 | + result = select(max_fd, &read_set, NULL, NULL, NULL); |
---|
| 1519 | + if (result == 0) { |
---|
| 1520 | + ALOGE("select timeout"); |
---|
| 1521 | + continue; |
---|
| 1522 | + } |
---|
| 1523 | + if (result < 0) { |
---|
| 1524 | + if (errno != EINTR) |
---|
| 1525 | + ALOGE("select failed %d (%s)", errno, strerror(errno)); |
---|
| 1526 | + if (errno != EBADF) |
---|
| 1527 | + continue; |
---|
| 1528 | + } |
---|
| 1529 | + if (FD_ISSET(s_ctrl, &read_set)) { |
---|
| 1530 | + if (sco_cb.ctrl_fd > 0) { |
---|
| 1531 | + ALOGE("Already has connect a control fd: %d", sco_cb.ctrl_fd); |
---|
| 1532 | + FD_SET(sco_cb.ctrl_fd, &read_set); |
---|
| 1533 | + close(sco_cb.ctrl_fd); |
---|
| 1534 | + } |
---|
| 1535 | + AIC_NO_INTR(sco_cb.ctrl_fd = accept(s_ctrl, (struct sockaddr *)&remote, &len)); |
---|
| 1536 | + if (sco_cb.ctrl_fd == -1) { |
---|
| 1537 | + ALOGE("sock accept failed (%s)", strerror(errno)); |
---|
| 1538 | + continue; |
---|
| 1539 | + } |
---|
| 1540 | + const int size = (512); |
---|
| 1541 | + setsockopt(sco_cb.ctrl_fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size)); |
---|
| 1542 | + FD_SET(sco_cb.ctrl_fd, &active_set); |
---|
| 1543 | + max_fd = (MAX(max_fd, sco_cb.ctrl_fd)) + 1; |
---|
| 1544 | + } |
---|
| 1545 | + |
---|
| 1546 | + if (FD_ISSET(s_data, &read_set)) { |
---|
| 1547 | + if (sco_cb.data_fd > 0) { |
---|
| 1548 | + ALOGE("Already has connect a control fd: %d", sco_cb.data_fd); |
---|
| 1549 | + close(sco_cb.data_fd); |
---|
| 1550 | + } |
---|
| 1551 | + AIC_NO_INTR(sco_cb.data_fd = accept(s_data, (struct sockaddr *)&remote, &len)); |
---|
| 1552 | + if (sco_cb.data_fd == -1) { |
---|
| 1553 | + ALOGE("socket accept failed (%s)", strerror(errno)); |
---|
| 1554 | + continue; |
---|
| 1555 | + } |
---|
| 1556 | + const int size = (30 * 960); |
---|
| 1557 | + int ret = setsockopt(sco_cb.data_fd, SOL_SOCKET, SO_RCVBUF, (char*)&size, (int)sizeof(size)); |
---|
| 1558 | + ret = setsockopt(sco_cb.data_fd, SOL_SOCKET, SO_SNDBUF, (char*)&size, (int)sizeof(size)); |
---|
| 1559 | + } |
---|
| 1560 | + |
---|
| 1561 | + if (sco_cb.ctrl_fd > 0 && FD_ISSET(sco_cb.ctrl_fd, &read_set)) { |
---|
| 1562 | + userial_sco_ctrl_skt_handle(); |
---|
| 1563 | + } |
---|
| 1564 | + } |
---|
| 1565 | + |
---|
| 1566 | + userial_sco_socket_stop(); |
---|
| 1567 | +signal_close: |
---|
| 1568 | + close(sco_cb.signal_fd[0]); |
---|
| 1569 | + close(sco_cb.signal_fd[1]); |
---|
| 1570 | +socket_close: |
---|
| 1571 | + close(s_ctrl); |
---|
| 1572 | + close(s_data); |
---|
| 1573 | + |
---|
| 1574 | + memset(&addr, 0, sizeof(addr)); |
---|
| 1575 | + strcpy((addr.sun_path + 1), SCO_DATA_PATH); |
---|
| 1576 | + addr.sun_path[0] = 0; |
---|
| 1577 | + unlink(addr.sun_path); |
---|
| 1578 | + |
---|
| 1579 | + memset(&addr, 0, sizeof(addr)); |
---|
| 1580 | + strcpy((addr.sun_path + 1), SCO_CTRL_PATH); |
---|
| 1581 | + addr.sun_path[0] = 0; |
---|
| 1582 | + unlink(addr.sun_path); |
---|
| 1583 | + ALOGD("userial_socket_sco_thread exit"); |
---|
| 1584 | + return NULL; |
---|
| 1585 | +} |
---|
| 1586 | +#endif |
---|
| 1587 | + |
---|
| 1588 | +#ifdef AIC_HANDLE_CMD |
---|
| 1589 | +static void userial_handle_cmd(unsigned char *recv_buffer, int total_length) |
---|
| 1590 | +{ |
---|
| 1591 | + AIC_UNUSED(total_length); |
---|
| 1592 | + uint16_t opcode = *(uint16_t*)recv_buffer; |
---|
| 1593 | + uint16_t scan_int, scan_win; |
---|
| 1594 | + static uint16_t voice_settings; |
---|
| 1595 | + char prop_value[100]; |
---|
| 1596 | + switch (opcode) { |
---|
| 1597 | + case HCI_BLE_WRITE_SCAN_PARAMS : |
---|
| 1598 | + scan_int = *(uint16_t*)&recv_buffer[4]; |
---|
| 1599 | + scan_win = *(uint16_t*)&recv_buffer[6]; |
---|
| 1600 | + if (scan_win > 20){ |
---|
| 1601 | + if ((scan_int/scan_win) > 2) { |
---|
| 1602 | + *(uint16_t*)&recv_buffer[4] = (scan_int * 20) / scan_win; |
---|
| 1603 | + *(uint16_t*)&recv_buffer[6] = 20; |
---|
| 1604 | + } else { |
---|
| 1605 | + *(uint16_t*)&recv_buffer[4] = 40; |
---|
| 1606 | + *(uint16_t*)&recv_buffer[6] = 20; |
---|
| 1607 | + } |
---|
| 1608 | + } else if (scan_win == scan_int) { |
---|
| 1609 | + *(uint16_t*)&recv_buffer[4] = (scan_int * 5) & 0xFE; |
---|
| 1610 | + } else if ((scan_int/scan_win) <= 2) { |
---|
| 1611 | + *(uint16_t*)&recv_buffer[4] = (scan_int * 3) & 0xFE; |
---|
| 1612 | + } |
---|
| 1613 | + break; |
---|
| 1614 | + |
---|
| 1615 | + case HCI_LE_SET_EXTENDED_SCAN_PARAMETERS: |
---|
| 1616 | + scan_int = *(uint16_t*)&recv_buffer[7]; |
---|
| 1617 | + scan_win = *(uint16_t*)&recv_buffer[9]; |
---|
| 1618 | + if (scan_win > 20){ |
---|
| 1619 | + if ((scan_int/scan_win) > 2) { |
---|
| 1620 | + *(uint16_t*)&recv_buffer[7] = (scan_int * 20) / scan_win; |
---|
| 1621 | + *(uint16_t*)&recv_buffer[9] = 20; |
---|
| 1622 | + } else { |
---|
| 1623 | + *(uint16_t*)&recv_buffer[7] = 40; |
---|
| 1624 | + *(uint16_t*)&recv_buffer[9] = 20; |
---|
| 1625 | + } |
---|
| 1626 | + } else if (scan_win == scan_int) { |
---|
| 1627 | + *(uint16_t*)&recv_buffer[7] = (scan_int * 5) & 0xFE; |
---|
| 1628 | + } else if ((scan_int/scan_win) <= 2) { |
---|
| 1629 | + *(uint16_t*)&recv_buffer[9] = (scan_int * 3) & 0xFE; |
---|
| 1630 | + } |
---|
| 1631 | + break; |
---|
| 1632 | + |
---|
| 1633 | + case HCI_WRITE_VOICE_SETTINGS : |
---|
| 1634 | + voice_settings = *(uint16_t*)&recv_buffer[3]; |
---|
| 1635 | + if (aicbt_transtype & AICBT_TRANS_USB) { |
---|
| 1636 | + userial_vendor_usb_ioctl(SET_ISO_CFG, &voice_settings); |
---|
| 1637 | + } |
---|
| 1638 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 1639 | + sco_cb.voice_settings = voice_settings; |
---|
| 1640 | +#endif |
---|
| 1641 | + break; |
---|
| 1642 | + |
---|
| 1643 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 1644 | + case HCI_SETUP_ESCO_CONNECTION : |
---|
| 1645 | + ALOGD("%s, HCI_SETUP_ESCO_CONNECTION", __func__); |
---|
| 1646 | + sco_cb.voice_settings = *(uint16_t*)&recv_buffer[15]; |
---|
| 1647 | + if (sco_cb.voice_settings & 0x0003) { |
---|
| 1648 | + sco_cb.codec_para.input_format = ESCO_CODING_FORMAT_MSBC; |
---|
| 1649 | + sco_cb.codec_para.output_format = ESCO_CODING_FORMAT_MSBC; |
---|
| 1650 | + sco_cb.codec_para.input_rate = 16000; |
---|
| 1651 | + sco_cb.codec_para.output_rate = 16000; |
---|
| 1652 | + } else { |
---|
| 1653 | + sco_cb.codec_para.input_format = ESCO_CODING_FORMAT_LINEAR; |
---|
| 1654 | + sco_cb.codec_para.output_format = ESCO_CODING_FORMAT_LINEAR; |
---|
| 1655 | + sco_cb.codec_para.input_rate = 8000; |
---|
| 1656 | + sco_cb.codec_para.output_rate = 8000; |
---|
| 1657 | + } |
---|
| 1658 | + sco_cb.ctrl_fd = -1; |
---|
| 1659 | + sco_cb.data_fd = -1; |
---|
| 1660 | + break; |
---|
| 1661 | + |
---|
| 1662 | + case HCI_ENH_SETUP_ESCO_CONNECTION: |
---|
| 1663 | + ALOGD("%s, HCI_ENH_SETUP_ESCO_CONNECTION", __func__); |
---|
| 1664 | + memcpy(&sco_cb.esco_para, &recv_buffer[5], sizeof(sco_cb.esco_para)); |
---|
| 1665 | + |
---|
| 1666 | + switch (sco_cb.esco_para.transmit_coding_format.coding_format) { |
---|
| 1667 | + case ESCO_CODING_FORMAT_ULAW: |
---|
| 1668 | + case ESCO_CODING_FORMAT_ALAW: |
---|
| 1669 | + case ESCO_CODING_FORMAT_CVSD: |
---|
| 1670 | + if (sco_cb.esco_para.output_coding_format.coding_format == ESCO_CODING_FORMAT_LINEAR) |
---|
| 1671 | + sco_cb.codec_para.output_format = ESCO_CODING_FORMAT_LINEAR; |
---|
| 1672 | + else |
---|
| 1673 | + sco_cb.codec_para.output_format = sco_cb.esco_para.transmit_coding_format.coding_format; |
---|
| 1674 | + sco_cb.codec_para.output_rate = 8000; |
---|
| 1675 | + break; |
---|
| 1676 | + case ESCO_CODING_FORMAT_MSBC: // stack bugs |
---|
| 1677 | + sco_cb.esco_para.transmit_coding_format.coding_format = ESCO_CODING_FORMAT_TRANSPNT; |
---|
| 1678 | + case ESCO_CODING_FORMAT_TRANSPNT: |
---|
| 1679 | + sco_cb.codec_para.output_format = ESCO_CODING_FORMAT_MSBC; |
---|
| 1680 | + sco_cb.codec_para.output_rate = 16000; |
---|
| 1681 | + break; |
---|
| 1682 | + default: |
---|
| 1683 | + ALOGD("Unsupport transmit coding format"); |
---|
| 1684 | + break; |
---|
| 1685 | + } |
---|
| 1686 | + |
---|
| 1687 | + switch (sco_cb.esco_para.receive_coding_format.coding_format) { |
---|
| 1688 | + case ESCO_CODING_FORMAT_ULAW: |
---|
| 1689 | + case ESCO_CODING_FORMAT_ALAW: |
---|
| 1690 | + case ESCO_CODING_FORMAT_CVSD: |
---|
| 1691 | + if (sco_cb.esco_para.input_coding_format.coding_format == ESCO_CODING_FORMAT_LINEAR) |
---|
| 1692 | + sco_cb.codec_para.input_format = ESCO_CODING_FORMAT_LINEAR; |
---|
| 1693 | + else |
---|
| 1694 | + sco_cb.codec_para.input_format = sco_cb.esco_para.receive_coding_format.coding_format; |
---|
| 1695 | + sco_cb.codec_para.input_rate = 8000; |
---|
| 1696 | + break; |
---|
| 1697 | + case ESCO_CODING_FORMAT_MSBC: // stack bugs |
---|
| 1698 | + sco_cb.esco_para.receive_coding_format.coding_format = ESCO_CODING_FORMAT_TRANSPNT; |
---|
| 1699 | + case ESCO_CODING_FORMAT_TRANSPNT: |
---|
| 1700 | + sco_cb.codec_para.input_format = ESCO_CODING_FORMAT_MSBC; |
---|
| 1701 | + sco_cb.codec_para.input_rate = 16000; |
---|
| 1702 | + break; |
---|
| 1703 | + default: |
---|
| 1704 | + ALOGD("Unsupport receive coding format"); |
---|
| 1705 | + break; |
---|
| 1706 | + } |
---|
| 1707 | + |
---|
| 1708 | + sco_cb.esco_para.input_data_path = ESCO_DATA_PATH_HCI; // input data path, set to VOHCI |
---|
| 1709 | + sco_cb.esco_para.output_data_path = ESCO_DATA_PATH_HCI; // output data path, set to VOHCI |
---|
| 1710 | + memcpy(&recv_buffer[5], &sco_cb.esco_para, sizeof(sco_cb.esco_para)); |
---|
| 1711 | + |
---|
| 1712 | + sco_cb.ctrl_fd = -1; |
---|
| 1713 | + sco_cb.data_fd = -1; |
---|
| 1714 | + break; |
---|
| 1715 | +#endif |
---|
| 1716 | + |
---|
| 1717 | + case HCI_SET_EVENT_MASK: |
---|
| 1718 | + ALOGD("set event mask, it should bt stack init, set coex bt on"); |
---|
| 1719 | + if (aic_parse_manager) { |
---|
| 1720 | + aic_parse_manager->aic_set_bt_on(1); |
---|
| 1721 | + } |
---|
| 1722 | + Heartbeat_init(); |
---|
| 1723 | + break; |
---|
| 1724 | + |
---|
| 1725 | + case HCI_ACCEPT_CONNECTION_REQUEST: |
---|
| 1726 | + property_get("persist.vendor.bluetooth.prefferedrole", prop_value, "none"); |
---|
| 1727 | + if (strcmp(prop_value, "none") != 0) { |
---|
| 1728 | + int role = recv_buffer[9]; |
---|
| 1729 | + if (role == 0x01 && (strcmp(prop_value, "master") == 0)) |
---|
| 1730 | + recv_buffer[9] = 0x00; |
---|
| 1731 | + else if (role == 0x00 && (strcmp(prop_value, "slave") == 0)) |
---|
| 1732 | + recv_buffer[9] = 0x01; |
---|
| 1733 | + } |
---|
| 1734 | + break; |
---|
| 1735 | + |
---|
| 1736 | + case HCI_BLE_WRITE_ADV_PARAMS: |
---|
| 1737 | + if (aicbt_version.hci_version> HCI_PROTO_VERSION_4_2) { |
---|
| 1738 | + break; |
---|
| 1739 | + } |
---|
| 1740 | + aicbt_adv_con.adverting_type = recv_buffer[7]; |
---|
| 1741 | + property_get("persist.vendor.aicbtadvdisable", prop_value, "false"); |
---|
| 1742 | + if (aicbt_adv_con.adverting_type == 0x00 && (strcmp(prop_value, "true") == 0)) { |
---|
| 1743 | + recv_buffer[7] = 0x03; |
---|
| 1744 | + aicbt_adv_con.adverting_type = 0x03; |
---|
| 1745 | + } |
---|
| 1746 | + break; |
---|
| 1747 | + |
---|
| 1748 | + case HCI_BLE_WRITE_ADV_ENABLE: |
---|
| 1749 | + if (aicbt_version.hci_version > HCI_PROTO_VERSION_4_2) { |
---|
| 1750 | + break; |
---|
| 1751 | + } |
---|
| 1752 | + if (recv_buffer[3] == 0x01) { |
---|
| 1753 | + aicbt_adv_con.adverting_start = TRUE; |
---|
| 1754 | + } else if (recv_buffer[3] == 0x00) { |
---|
| 1755 | + aicbt_adv_con.adverting_type = 0; |
---|
| 1756 | + aicbt_adv_con.adverting_enable = FALSE; |
---|
| 1757 | + aicbt_adv_con.adverting_start = FALSE; |
---|
| 1758 | + } |
---|
| 1759 | + break; |
---|
| 1760 | + |
---|
| 1761 | + case HCI_BLE_CREATE_LL_CONN: |
---|
| 1762 | + if (aicbt_version.hci_version > HCI_PROTO_VERSION_4_2) { |
---|
| 1763 | + break; |
---|
| 1764 | + } |
---|
| 1765 | + if (aicbt_adv_con.adverting_enable && |
---|
| 1766 | + ((aicbt_adv_con.adverting_type == 0x00) || |
---|
| 1767 | + (aicbt_adv_con.adverting_type == 0x01) || |
---|
| 1768 | + (aicbt_adv_con.adverting_type == 0x04))) { |
---|
| 1769 | + uint8_t disable_adv_cmd[5] = {0x01, 0x0A, 0x20, 0x01, 0x00}; |
---|
| 1770 | + aicbt_adv_con.adverting_enable = FALSE; |
---|
| 1771 | + userial_send_cmd_to_controller(disable_adv_cmd, 5); |
---|
| 1772 | + } |
---|
| 1773 | + break; |
---|
| 1774 | + |
---|
| 1775 | + default: |
---|
| 1776 | + break; |
---|
| 1777 | + } |
---|
| 1778 | +} |
---|
| 1779 | +#endif |
---|
| 1780 | + |
---|
| 1781 | + |
---|
| 1782 | +//This recv data from bt process. The data type only have ACL/SCO/COMMAND |
---|
| 1783 | +// direction BT HOST ----> CONTROLLER |
---|
| 1784 | +static void userial_recv_H4_rawdata(void *context) |
---|
| 1785 | +{ |
---|
| 1786 | + AIC_UNUSED(context); |
---|
| 1787 | + serial_data_type_t type = 0; |
---|
| 1788 | + ssize_t bytes_read; |
---|
| 1789 | + uint16_t opcode; |
---|
| 1790 | + uint16_t transmitted_length = 0; |
---|
| 1791 | + //unsigned char *buffer = NULL; |
---|
| 1792 | + |
---|
| 1793 | + switch (packet_recv_state) { |
---|
| 1794 | + case AICBT_PACKET_IDLE: |
---|
| 1795 | + packet_bytes_need = 1; |
---|
| 1796 | + do { |
---|
| 1797 | + AIC_NO_INTR(bytes_read = read(vnd_userial.uart_fd[1], &type, 1)); |
---|
| 1798 | + if (bytes_read == -1) { |
---|
| 1799 | + ALOGE("%s, state = %d, read error %s", __func__, packet_recv_state, strerror(errno)); |
---|
| 1800 | + return; |
---|
| 1801 | + } |
---|
| 1802 | + if (!bytes_read && packet_bytes_need) { |
---|
| 1803 | + ALOGE("%s, state = %d, bytes_read 0", __func__, packet_recv_state); |
---|
| 1804 | + return; |
---|
| 1805 | + } |
---|
| 1806 | + |
---|
| 1807 | + if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) { |
---|
| 1808 | + ALOGE("%s invalid data type: %d", __func__, type); |
---|
| 1809 | + assert((type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO)); |
---|
| 1810 | + } else { |
---|
| 1811 | + packet_bytes_need -= bytes_read; |
---|
| 1812 | + packet_recv_state = AICBT_PACKET_TYPE; |
---|
| 1813 | + current_type = type; |
---|
| 1814 | + h4_read_buffer[0] = type; |
---|
| 1815 | + } |
---|
| 1816 | + } while(packet_bytes_need); |
---|
| 1817 | + // fall through |
---|
| 1818 | + |
---|
| 1819 | + case AICBT_PACKET_TYPE: |
---|
| 1820 | + packet_bytes_need = hci_preamble_sizes[HCI_PACKET_TYPE_TO_INDEX(current_type)]; |
---|
| 1821 | + h4_read_length = 0; |
---|
| 1822 | + packet_recv_state = AICBT_PACKET_HEADER; |
---|
| 1823 | + // fall through |
---|
| 1824 | + |
---|
| 1825 | + case AICBT_PACKET_HEADER: |
---|
| 1826 | + do { |
---|
| 1827 | + AIC_NO_INTR(bytes_read = read(vnd_userial.uart_fd[1], &h4_read_buffer[h4_read_length + 1], packet_bytes_need)); |
---|
| 1828 | + if (bytes_read == -1) { |
---|
| 1829 | + ALOGE("%s, state = %d, read error %s", __func__, packet_recv_state, strerror(errno)); |
---|
| 1830 | + return; |
---|
| 1831 | + } |
---|
| 1832 | + if (!bytes_read && packet_bytes_need) { |
---|
| 1833 | + ALOGE("%s, state = %d, bytes_read 0, type : %d", __func__, packet_recv_state, current_type); |
---|
| 1834 | + return; |
---|
| 1835 | + } |
---|
| 1836 | + packet_bytes_need -= bytes_read; |
---|
| 1837 | + h4_read_length += bytes_read; |
---|
| 1838 | + }while(packet_bytes_need); |
---|
| 1839 | + packet_recv_state = AICBT_PACKET_CONTENT; |
---|
| 1840 | + |
---|
| 1841 | + if (current_type == DATA_TYPE_ACL) { |
---|
| 1842 | + packet_bytes_need = *(uint16_t *)&h4_read_buffer[COMMON_DATA_LENGTH_INDEX]; |
---|
| 1843 | + } else if (current_type == DATA_TYPE_EVENT) { |
---|
| 1844 | + packet_bytes_need = h4_read_buffer[EVENT_DATA_LENGTH_INDEX]; |
---|
| 1845 | + } else { |
---|
| 1846 | + packet_bytes_need = h4_read_buffer[COMMON_DATA_LENGTH_INDEX]; |
---|
| 1847 | + } |
---|
| 1848 | + // fall through |
---|
| 1849 | + |
---|
| 1850 | + case AICBT_PACKET_CONTENT: |
---|
| 1851 | + while(packet_bytes_need) { |
---|
| 1852 | + AIC_NO_INTR(bytes_read = read(vnd_userial.uart_fd[1], &h4_read_buffer[h4_read_length + 1], packet_bytes_need)); |
---|
| 1853 | + if (bytes_read == -1) { |
---|
| 1854 | + ALOGE("%s, state = %d, read error %s", __func__, packet_recv_state, strerror(errno)); |
---|
| 1855 | + return; |
---|
| 1856 | + } |
---|
| 1857 | + if (!bytes_read) { |
---|
| 1858 | + ALOGE("%s, state = %d, bytes_read 0", __func__, packet_recv_state); |
---|
| 1859 | + return; |
---|
| 1860 | + } |
---|
| 1861 | + |
---|
| 1862 | + packet_bytes_need -= bytes_read; |
---|
| 1863 | + h4_read_length += bytes_read; |
---|
| 1864 | + } |
---|
| 1865 | + packet_recv_state = AICBT_PACKET_END; |
---|
| 1866 | + // fall through |
---|
| 1867 | + |
---|
| 1868 | + case AICBT_PACKET_END: |
---|
| 1869 | + switch (current_type) { |
---|
| 1870 | + case DATA_TYPE_COMMAND: |
---|
| 1871 | +#ifdef AIC_HANDLE_CMD |
---|
| 1872 | + userial_handle_cmd(&h4_read_buffer[1], h4_read_length); |
---|
| 1873 | +#endif |
---|
| 1874 | + if (aicbt_transtype & AICBT_TRANS_H4) { |
---|
| 1875 | + h4_int_transmit_data(h4_read_buffer, (h4_read_length + 1)); |
---|
| 1876 | + } else { |
---|
| 1877 | + opcode = *(uint16_t *)&h4_read_buffer[1]; |
---|
| 1878 | + if (opcode == HCI_VSC_H5_INIT) { |
---|
| 1879 | + h5_int_interface->h5_send_sync_cmd(opcode, NULL, h4_read_length); |
---|
| 1880 | + } else { |
---|
| 1881 | + transmitted_length = h5_int_interface->h5_send_cmd(type, &h4_read_buffer[1], h4_read_length); |
---|
| 1882 | + } |
---|
| 1883 | + } |
---|
| 1884 | + userial_enqueue_coex_rawdata(h4_read_buffer,(h4_read_length + 1), false); |
---|
| 1885 | + break; |
---|
| 1886 | + |
---|
| 1887 | + case DATA_TYPE_ACL: |
---|
| 1888 | + userial_send_acl_to_controller(h4_read_buffer, (h4_read_length + 1)); |
---|
| 1889 | + break; |
---|
| 1890 | + |
---|
| 1891 | + case DATA_TYPE_SCO: |
---|
| 1892 | + userial_send_sco_to_controller(h4_read_buffer, (h4_read_length + 1)); |
---|
| 1893 | + break; |
---|
| 1894 | + |
---|
| 1895 | + default: |
---|
| 1896 | + ALOGE("%s invalid data type: %d", __func__, current_type); |
---|
| 1897 | + userial_enqueue_coex_rawdata(h4_read_buffer,(h4_read_length + 1), false); |
---|
| 1898 | + break; |
---|
| 1899 | + } |
---|
| 1900 | + break; |
---|
| 1901 | + |
---|
| 1902 | + default: |
---|
| 1903 | + break; |
---|
| 1904 | + } |
---|
| 1905 | + |
---|
| 1906 | + packet_recv_state = AICBT_PACKET_IDLE; |
---|
| 1907 | + packet_bytes_need = 0; |
---|
| 1908 | + current_type = 0; |
---|
| 1909 | + h4_read_length = 0; |
---|
| 1910 | +} |
---|
| 1911 | + |
---|
| 1912 | +static uint16_t h5_int_transmit_data_cb(serial_data_type_t type, uint8_t *data, uint16_t length) { |
---|
| 1913 | + assert(data != NULL); |
---|
| 1914 | + assert(length > 0); |
---|
| 1915 | + |
---|
| 1916 | + if (type != DATA_TYPE_H5) { |
---|
| 1917 | + ALOGE("%s invalid data type: %d", __func__, type); |
---|
| 1918 | + return 0; |
---|
| 1919 | + } |
---|
| 1920 | + |
---|
| 1921 | + uint16_t transmitted_length = 0; |
---|
| 1922 | + while (length > 0 && vnd_userial.btdriver_state) { |
---|
| 1923 | + ssize_t ret = write(vnd_userial.fd, data + transmitted_length, length); |
---|
| 1924 | + switch (ret) { |
---|
| 1925 | + case -1: |
---|
| 1926 | + ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno)); |
---|
| 1927 | + goto done; |
---|
| 1928 | + |
---|
| 1929 | + case 0: |
---|
| 1930 | + // If we wrote nothing, don't loop more because we |
---|
| 1931 | + // can't go to infinity or beyond, ohterwise H5 can resend data |
---|
| 1932 | + ALOGE("%s, ret %zd", __func__, ret); |
---|
| 1933 | + goto done; |
---|
| 1934 | + |
---|
| 1935 | + default: |
---|
| 1936 | + transmitted_length += ret; |
---|
| 1937 | + length -= ret; |
---|
| 1938 | + break; |
---|
| 1939 | + } |
---|
| 1940 | + } |
---|
| 1941 | + |
---|
| 1942 | +done: |
---|
| 1943 | + return transmitted_length; |
---|
| 1944 | + |
---|
| 1945 | +} |
---|
| 1946 | + |
---|
| 1947 | +#ifdef AIC_HANDLE_EVENT |
---|
| 1948 | +static void userial_handle_event(unsigned char *recv_buffer, int total_length) |
---|
| 1949 | +{ |
---|
| 1950 | + AIC_UNUSED(total_length); |
---|
| 1951 | + uint8_t event; |
---|
| 1952 | + uint8_t *p_data = recv_buffer; |
---|
| 1953 | + event = p_data[0]; |
---|
| 1954 | + switch (event) { |
---|
| 1955 | + case HCI_COMMAND_COMPLETE_EVT: |
---|
| 1956 | + { |
---|
| 1957 | + uint16_t opcode = *((uint16_t*)&p_data[3]); |
---|
| 1958 | + uint8_t *stream = &p_data[6]; |
---|
| 1959 | + if (opcode == HCI_READ_LOCAL_VERSION_INFO) { |
---|
| 1960 | + STREAM_TO_UINT8(aicbt_version.hci_version, stream); |
---|
| 1961 | + STREAM_TO_UINT16(aicbt_version.hci_revision, stream); |
---|
| 1962 | + STREAM_TO_UINT8(aicbt_version.lmp_version, stream); |
---|
| 1963 | + STREAM_TO_UINT16(aicbt_version.manufacturer, stream); |
---|
| 1964 | + STREAM_TO_UINT16(aicbt_version.lmp_subversion, stream); |
---|
| 1965 | + } else if (opcode == HCI_BLE_WRITE_ADV_ENABLE){ |
---|
| 1966 | + if (aicbt_version.hci_version > HCI_PROTO_VERSION_4_2) { |
---|
| 1967 | + break; |
---|
| 1968 | + } |
---|
| 1969 | + if (aicbt_adv_con.adverting_start &&(p_data[5] == HCI_SUCCESS)) { |
---|
| 1970 | + aicbt_adv_con.adverting_enable = TRUE; |
---|
| 1971 | + aicbt_adv_con.adverting_start = FALSE; |
---|
| 1972 | + } |
---|
| 1973 | + } else if (opcode == HCI_RESET) { |
---|
| 1974 | + if (close_state == 0) { |
---|
| 1975 | + ALOGD("hci reset event received before serial close"); |
---|
| 1976 | + close_state = 1; |
---|
| 1977 | + } |
---|
| 1978 | + } |
---|
| 1979 | + } |
---|
| 1980 | + break; |
---|
| 1981 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 1982 | + case HCI_ESCO_CONNECTION_COMP_EVT: { |
---|
| 1983 | + ALOGD("%s, HCI_ESCO_CONNECTION_COMP_EVT", __func__); |
---|
| 1984 | + if (p_data[2] != 0) { |
---|
| 1985 | + sco_cb.thread_sco_running = false; |
---|
| 1986 | + sco_cb.thread_recv_sco_running = false; |
---|
| 1987 | + sco_cb.thread_send_sco_running = false; |
---|
| 1988 | + sco_cb.data_fd = -1; |
---|
| 1989 | + sco_cb.ctrl_fd = -1; |
---|
| 1990 | + } else { |
---|
| 1991 | + sco_cb.sco_handle = *((uint16_t *)&p_data[3]); |
---|
| 1992 | + pthread_attr_t thread_attr; |
---|
| 1993 | + pthread_attr_init(&thread_attr); |
---|
| 1994 | + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); |
---|
| 1995 | + sco_cb.thread_sco_running = true; |
---|
| 1996 | + sco_cb.thread_recv_sco_running = false; |
---|
| 1997 | + sco_cb.thread_send_sco_running = false; |
---|
| 1998 | + sco_cb.data_fd = -1; |
---|
| 1999 | + sco_cb.ctrl_fd = -1; |
---|
| 2000 | + if (pthread_create(&sco_cb.thread_socket_sco_id, &thread_attr, userial_socket_sco_thread, NULL)!= 0 ) { |
---|
| 2001 | + ALOGE("pthread_create : %s", strerror(errno)); |
---|
| 2002 | + } |
---|
| 2003 | + |
---|
| 2004 | + RtbEmptyQueue(sco_cb.recv_sco_data); |
---|
| 2005 | + switch (sco_cb.codec_para.input_format) { |
---|
| 2006 | + case ESCO_CODING_FORMAT_LINEAR: |
---|
| 2007 | + sco_cb.sco_packet_len = 120; // Get from esco data package, how decide it dynamic? |
---|
| 2008 | + break; |
---|
| 2009 | + case ESCO_CODING_FORMAT_CVSD: |
---|
| 2010 | + sco_cb.sco_packet_len = 240; // every 5 cvsd packets form a sco pcm data |
---|
| 2011 | + break; |
---|
| 2012 | + case ESCO_CODING_FORMAT_MSBC: |
---|
| 2013 | + sco_cb.sco_packet_len = 60; |
---|
| 2014 | + break; |
---|
| 2015 | + default: |
---|
| 2016 | + ALOGE("%s(%d), unsupport coding format: 0x%02X", __func__, __LINE__, sco_cb.codec_para.input_format); |
---|
| 2017 | + break; |
---|
| 2018 | + } |
---|
| 2019 | + sco_cb.current_pos = 0; |
---|
| 2020 | + } |
---|
| 2021 | + |
---|
| 2022 | + ALOGD("userial_handle_event sco_handle: %d", sco_cb.sco_handle); |
---|
| 2023 | + } |
---|
| 2024 | + break; |
---|
| 2025 | + |
---|
| 2026 | + case HCI_DISCONNECTION_COMP_EVT: { |
---|
| 2027 | + if ((*((uint16_t *)&p_data[3])) == sco_cb.sco_handle) { |
---|
| 2028 | + sco_cb.sco_handle = 0; |
---|
| 2029 | + RtbEmptyQueue(sco_cb.recv_sco_data); |
---|
| 2030 | + if (sco_cb.thread_sco_running) { |
---|
| 2031 | + sco_cb.thread_sco_running = false; |
---|
| 2032 | + unsigned char close_signal = 1; |
---|
| 2033 | + ssize_t ret; |
---|
| 2034 | + AIC_NO_INTR(ret = write(sco_cb.signal_fd[0], &close_signal, 1)); |
---|
| 2035 | + } |
---|
| 2036 | + } |
---|
| 2037 | + } |
---|
| 2038 | + break; |
---|
| 2039 | +#endif |
---|
| 2040 | + default : |
---|
| 2041 | + break; |
---|
| 2042 | + } |
---|
| 2043 | +} |
---|
| 2044 | + |
---|
| 2045 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 2046 | +static void userial_enqueue_recv_sco_data(unsigned char *recv_buffer, int total_length) |
---|
| 2047 | +{ |
---|
| 2048 | + AIC_UNUSED(total_length); |
---|
| 2049 | + uint8_t sco_length; |
---|
| 2050 | + uint8_t *p_data = recv_buffer; |
---|
| 2051 | + AIC_BUFFER *skb_sco_data; |
---|
| 2052 | + int i; |
---|
| 2053 | + uint16_t sco_handle = (*((uint16_t *)p_data)) & 0x0FFF; |
---|
| 2054 | + uint8_t packet_flag = (uint8_t)((sco_handle >> 12) & 0x0003); |
---|
| 2055 | + uint16_t current_pos = sco_cb.current_pos; |
---|
| 2056 | + uint16_t sco_packet_len = sco_cb.sco_packet_len; |
---|
| 2057 | + |
---|
| 2058 | + if (sco_handle == sco_cb.sco_handle) { |
---|
| 2059 | + sco_length = p_data[SCO_PREAMBLE_SIZE - 1]; |
---|
| 2060 | + p_data += SCO_PREAMBLE_SIZE; |
---|
| 2061 | + |
---|
| 2062 | + switch (sco_cb.codec_para.input_format) { |
---|
| 2063 | + case ESCO_CODING_FORMAT_LINEAR: // PCM raw data |
---|
| 2064 | + skb_sco_data = RtbAllocate(sco_length, 0); |
---|
| 2065 | + memcpy(skb_sco_data->Data, p_data, sco_length); |
---|
| 2066 | + RtbAddTail(skb_sco_data, sco_length); |
---|
| 2067 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 2068 | + RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data); |
---|
| 2069 | + pthread_cond_signal(&sco_cb.sco_recv_cond); |
---|
| 2070 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 2071 | + return; |
---|
| 2072 | + case ESCO_CODING_FORMAT_CVSD: // CVSD codec |
---|
| 2073 | + case ESCO_CODING_FORMAT_MSBC: // MSBC codec |
---|
| 2074 | + if (packet_flag != 0x00) |
---|
| 2075 | + ALOGE("sco data receive wrong packet_flag : %d", packet_flag); |
---|
| 2076 | + if (current_pos) { |
---|
| 2077 | + if ((sco_packet_len - current_pos) <= sco_length) { |
---|
| 2078 | + memcpy(&sco_cb.enc_data[current_pos], p_data, (sco_packet_len - current_pos)); |
---|
| 2079 | + skb_sco_data = RtbAllocate(sco_packet_len, 0); |
---|
| 2080 | + memcpy(skb_sco_data->Data, sco_cb.enc_data, sco_packet_len); |
---|
| 2081 | + RtbAddTail(skb_sco_data, sco_packet_len); |
---|
| 2082 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 2083 | + RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data); |
---|
| 2084 | + pthread_cond_signal(&sco_cb.sco_recv_cond); |
---|
| 2085 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 2086 | + sco_cb.current_pos = 0; |
---|
| 2087 | + p_data += (sco_packet_len - current_pos); |
---|
| 2088 | + sco_length -= (sco_packet_len - current_pos); |
---|
| 2089 | + } else { |
---|
| 2090 | + memcpy(&sco_cb.enc_data[current_pos], p_data, sco_length); |
---|
| 2091 | + sco_cb.current_pos += sco_length; |
---|
| 2092 | + return; |
---|
| 2093 | + } |
---|
| 2094 | + } |
---|
| 2095 | + break; |
---|
| 2096 | + default: |
---|
| 2097 | + ALOGE("%s(%d), unsupport coding format: 0x%02X", __func__, __LINE__, sco_cb.codec_para.input_format); |
---|
| 2098 | + return; |
---|
| 2099 | + } |
---|
| 2100 | + |
---|
| 2101 | + switch (sco_cb.codec_para.input_format) { |
---|
| 2102 | + case ESCO_CODING_FORMAT_CVSD: // Cvsd codec |
---|
| 2103 | + for (i = 0; i < (sco_length/sco_packet_len); i++) { |
---|
| 2104 | + skb_sco_data = RtbAllocate(sco_packet_len, 0); |
---|
| 2105 | + memcpy(skb_sco_data->Data, p_data + i*sco_packet_len, sco_packet_len); |
---|
| 2106 | + RtbAddTail(skb_sco_data, sco_packet_len); |
---|
| 2107 | + RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data); |
---|
| 2108 | + } |
---|
| 2109 | + if ((sco_length/sco_packet_len)) { |
---|
| 2110 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 2111 | + pthread_cond_signal(&sco_cb.sco_recv_cond); |
---|
| 2112 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 2113 | + } |
---|
| 2114 | + i = (sco_length % sco_packet_len); |
---|
| 2115 | + current_pos = sco_length - i; |
---|
| 2116 | + if (i) { |
---|
| 2117 | + memcpy(sco_cb.enc_data, p_data + current_pos, i); |
---|
| 2118 | + sco_cb.current_pos = i; |
---|
| 2119 | + } |
---|
| 2120 | + break; |
---|
| 2121 | + case ESCO_CODING_FORMAT_MSBC: |
---|
| 2122 | + for (i = 0; i < sco_length; i++) { |
---|
| 2123 | + if ((p_data[i] == 0x01) && ((p_data[i+1] & 0x0f) == 0x08) && (p_data[i+2] == 0xAD)) { |
---|
| 2124 | + if ((sco_length - i) < sco_packet_len) { |
---|
| 2125 | + memcpy(sco_cb.enc_data, &p_data[i], (sco_length - i)); |
---|
| 2126 | + sco_cb.current_pos = sco_length - i; |
---|
| 2127 | + return; |
---|
| 2128 | + } else { |
---|
| 2129 | + memcpy(sco_cb.enc_data, &p_data[i], sco_packet_len); //complete msbc data |
---|
| 2130 | + skb_sco_data = RtbAllocate(sco_packet_len, 0); |
---|
| 2131 | + memcpy(skb_sco_data->Data, sco_cb.enc_data, sco_packet_len); |
---|
| 2132 | + RtbAddTail(skb_sco_data, sco_packet_len); |
---|
| 2133 | + pthread_mutex_lock(&sco_cb.sco_recv_mutex); |
---|
| 2134 | + RtbQueueTail(sco_cb.recv_sco_data, skb_sco_data); |
---|
| 2135 | + pthread_cond_signal(&sco_cb.sco_recv_cond); |
---|
| 2136 | + pthread_mutex_unlock(&sco_cb.sco_recv_mutex); |
---|
| 2137 | + sco_cb.current_pos = 0; |
---|
| 2138 | + i += (sco_packet_len - 1); |
---|
| 2139 | + } |
---|
| 2140 | + } |
---|
| 2141 | + } |
---|
| 2142 | + break; |
---|
| 2143 | + default: |
---|
| 2144 | + ALOGE("%s(%d), unsupport coding format: 0x%02X", __func__, __LINE__, sco_cb.codec_para.input_format); |
---|
| 2145 | + break; |
---|
| 2146 | + } |
---|
| 2147 | + } |
---|
| 2148 | +} |
---|
| 2149 | +#endif |
---|
| 2150 | + |
---|
| 2151 | +static int userial_handle_recv_data(unsigned char *recv_buffer, unsigned int total_length) |
---|
| 2152 | +{ |
---|
| 2153 | + serial_data_type_t type = 0; |
---|
| 2154 | + unsigned char *p_data = recv_buffer; |
---|
| 2155 | + unsigned int length = total_length; |
---|
| 2156 | + uint8_t event; |
---|
| 2157 | + |
---|
| 2158 | + if (!length){ |
---|
| 2159 | + ALOGE("%s, length is 0, return immediately", __func__); |
---|
| 2160 | + return total_length; |
---|
| 2161 | + } |
---|
| 2162 | + switch (received_packet_state) { |
---|
| 2163 | + case AICBT_PACKET_IDLE: |
---|
| 2164 | + received_packet_bytes_need = 1; |
---|
| 2165 | + while(length) { |
---|
| 2166 | + type = p_data[0]; |
---|
| 2167 | + length--; |
---|
| 2168 | + p_data++; |
---|
| 2169 | + if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) { |
---|
| 2170 | + ALOGE("%s invalid data type: %d", __func__, type); |
---|
| 2171 | + assert((type > DATA_TYPE_COMMAND) && (type <= DATA_TYPE_EVENT)); |
---|
| 2172 | + if (!length) |
---|
| 2173 | + return total_length; |
---|
| 2174 | + |
---|
| 2175 | + continue; |
---|
| 2176 | + } |
---|
| 2177 | + break; |
---|
| 2178 | + } |
---|
| 2179 | + recv_packet_current_type = type; |
---|
| 2180 | + received_packet_state = AICBT_PACKET_TYPE; |
---|
| 2181 | + //fall through |
---|
| 2182 | + |
---|
| 2183 | + case AICBT_PACKET_TYPE: |
---|
| 2184 | + received_packet_bytes_need = hci_preamble_sizes[HCI_PACKET_TYPE_TO_INDEX(recv_packet_current_type)]; |
---|
| 2185 | + received_resvered_length = 0; |
---|
| 2186 | + received_packet_state = AICBT_PACKET_HEADER; |
---|
| 2187 | + //fall through |
---|
| 2188 | + |
---|
| 2189 | + case AICBT_PACKET_HEADER: |
---|
| 2190 | + if (length >= received_packet_bytes_need) { |
---|
| 2191 | + memcpy(&received_resvered_header[received_resvered_length], p_data, received_packet_bytes_need); |
---|
| 2192 | + received_resvered_length += received_packet_bytes_need; |
---|
| 2193 | + length -= received_packet_bytes_need; |
---|
| 2194 | + p_data += received_packet_bytes_need; |
---|
| 2195 | + } else { |
---|
| 2196 | + memcpy(&received_resvered_header[received_resvered_length], p_data, length); |
---|
| 2197 | + received_resvered_length += length; |
---|
| 2198 | + received_packet_bytes_need -= length; |
---|
| 2199 | + length = 0; |
---|
| 2200 | + return total_length; |
---|
| 2201 | + } |
---|
| 2202 | + received_packet_state = AICBT_PACKET_CONTENT; |
---|
| 2203 | + |
---|
| 2204 | + if (recv_packet_current_type == DATA_TYPE_ACL) { |
---|
| 2205 | + received_packet_bytes_need = *(uint16_t *)&received_resvered_header[2]; |
---|
| 2206 | + } else if (recv_packet_current_type == DATA_TYPE_EVENT){ |
---|
| 2207 | + received_packet_bytes_need = received_resvered_header[1]; |
---|
| 2208 | + } else { |
---|
| 2209 | + received_packet_bytes_need = received_resvered_header[2]; |
---|
| 2210 | + } |
---|
| 2211 | + //fall through |
---|
| 2212 | + |
---|
| 2213 | + case AICBT_PACKET_CONTENT: |
---|
| 2214 | + if (recv_packet_current_type == DATA_TYPE_EVENT) { |
---|
| 2215 | + event = received_resvered_header[0]; |
---|
| 2216 | + |
---|
| 2217 | + if (event == HCI_COMMAND_COMPLETE_EVT) { |
---|
| 2218 | + if (received_resvered_length == 2) { |
---|
| 2219 | + if (length >= 1) { |
---|
| 2220 | + *p_data = 1; |
---|
| 2221 | + } |
---|
| 2222 | + } |
---|
| 2223 | + } else if (event == HCI_COMMAND_STATUS_EVT) { |
---|
| 2224 | + if (received_resvered_length < 4) { |
---|
| 2225 | + unsigned int act_len = 4 - received_resvered_length; |
---|
| 2226 | + if (length >= act_len) { |
---|
| 2227 | + *(p_data + act_len -1) = 1; |
---|
| 2228 | + } |
---|
| 2229 | + } |
---|
| 2230 | + } |
---|
| 2231 | + } |
---|
| 2232 | + if (length >= received_packet_bytes_need) { |
---|
| 2233 | + memcpy(&received_resvered_header[received_resvered_length], p_data, received_packet_bytes_need); |
---|
| 2234 | + length -= received_packet_bytes_need; |
---|
| 2235 | + p_data += received_packet_bytes_need; |
---|
| 2236 | + received_resvered_length += received_packet_bytes_need; |
---|
| 2237 | + received_packet_bytes_need = 0; |
---|
| 2238 | + } else { |
---|
| 2239 | + memcpy(&received_resvered_header[received_resvered_length], p_data, length); |
---|
| 2240 | + received_resvered_length += length; |
---|
| 2241 | + received_packet_bytes_need -= length; |
---|
| 2242 | + length = 0; |
---|
| 2243 | + return total_length; |
---|
| 2244 | + } |
---|
| 2245 | + received_packet_state = AICBT_PACKET_END; |
---|
| 2246 | + //fall through |
---|
| 2247 | + |
---|
| 2248 | + case AICBT_PACKET_END: |
---|
| 2249 | + switch (recv_packet_current_type) { |
---|
| 2250 | + case DATA_TYPE_EVENT : |
---|
| 2251 | + userial_handle_event(received_resvered_header, received_resvered_length); |
---|
| 2252 | + break; |
---|
| 2253 | +#ifdef CONFIG_SCO_OVER_HCI |
---|
| 2254 | + case DATA_TYPE_SCO : |
---|
| 2255 | + userial_enqueue_recv_sco_data(received_resvered_header, received_resvered_length); |
---|
| 2256 | + break; |
---|
| 2257 | +#endif |
---|
| 2258 | + default : |
---|
| 2259 | + |
---|
| 2260 | + break; |
---|
| 2261 | + } |
---|
| 2262 | + break; |
---|
| 2263 | + |
---|
| 2264 | + default: |
---|
| 2265 | + break; |
---|
| 2266 | + } |
---|
| 2267 | + |
---|
| 2268 | + received_packet_state = AICBT_PACKET_IDLE; |
---|
| 2269 | + received_packet_bytes_need = 0; |
---|
| 2270 | + recv_packet_current_type = 0; |
---|
| 2271 | + received_resvered_length = 0; |
---|
| 2272 | + |
---|
| 2273 | + return (total_length - length); |
---|
| 2274 | +} |
---|
| 2275 | +#endif |
---|
| 2276 | + |
---|
| 2277 | +static void h5_data_ready_cb(serial_data_type_t type, unsigned int total_length) |
---|
| 2278 | +{ |
---|
| 2279 | + unsigned char buffer[1028] = {0}; |
---|
| 2280 | + int length = 0; |
---|
| 2281 | + length = h5_int_interface->h5_int_read_data(&buffer[1], total_length); |
---|
| 2282 | + if (length == -1) { |
---|
| 2283 | + ALOGE("%s, error read length", __func__); |
---|
| 2284 | + assert(length != -1); |
---|
| 2285 | + } |
---|
| 2286 | + buffer[0] = type; |
---|
| 2287 | + length++; |
---|
| 2288 | + uint16_t transmitted_length = 0; |
---|
| 2289 | + unsigned int real_length = length; |
---|
| 2290 | +#ifdef AIC_HANDLE_EVENT |
---|
| 2291 | + unsigned int read_length = 0; |
---|
| 2292 | + do { |
---|
| 2293 | + read_length += userial_handle_recv_data(buffer + read_length, real_length - read_length); |
---|
| 2294 | + } while (vnd_userial.thread_running && read_length < total_length); |
---|
| 2295 | +#endif |
---|
| 2296 | + |
---|
| 2297 | + while (length > 0) { |
---|
| 2298 | + ssize_t ret; |
---|
| 2299 | + AIC_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, length)); |
---|
| 2300 | + switch (ret) { |
---|
| 2301 | + case -1: |
---|
| 2302 | + ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno)); |
---|
| 2303 | + goto done; |
---|
| 2304 | + case 0: |
---|
| 2305 | + // If we wrote nothing, don't loop more because we |
---|
| 2306 | + // can't go to infinity or beyond |
---|
| 2307 | + goto done; |
---|
| 2308 | + default: |
---|
| 2309 | + transmitted_length += ret; |
---|
| 2310 | + length -= ret; |
---|
| 2311 | + break; |
---|
| 2312 | + } |
---|
| 2313 | + } |
---|
| 2314 | +done: |
---|
| 2315 | + if (real_length) |
---|
| 2316 | + userial_enqueue_coex_rawdata(buffer, real_length, true); |
---|
| 2317 | + return; |
---|
| 2318 | +} |
---|
| 2319 | + |
---|
| 2320 | +//This recv data from driver which is sent or recv by the controller. The data type have ACL/SCO/EVENT |
---|
| 2321 | +// direction CONTROLLER -----> BT HOST |
---|
| 2322 | +static void userial_recv_uart_rawdata(unsigned char *buffer, unsigned int total_length) |
---|
| 2323 | +{ |
---|
| 2324 | + unsigned int length = total_length; |
---|
| 2325 | + uint16_t transmitted_length = 0; |
---|
| 2326 | +#ifdef AIC_HANDLE_EVENT |
---|
| 2327 | + unsigned int read_length = 0; |
---|
| 2328 | + do { |
---|
| 2329 | + read_length += userial_handle_recv_data(buffer + read_length, total_length - read_length); |
---|
| 2330 | + } while(read_length < total_length); |
---|
| 2331 | +#endif |
---|
| 2332 | + while (length > 0 && vnd_userial.thread_running) { |
---|
| 2333 | + ssize_t ret; |
---|
| 2334 | + AIC_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, length)); |
---|
| 2335 | + switch (ret) { |
---|
| 2336 | + case -1: |
---|
| 2337 | + ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno)); |
---|
| 2338 | + goto done; |
---|
| 2339 | + case 0: |
---|
| 2340 | + // If we wrote nothing, don't loop more because we |
---|
| 2341 | + // can't go to infinity or beyond |
---|
| 2342 | + goto done; |
---|
| 2343 | + default: |
---|
| 2344 | + transmitted_length += ret; |
---|
| 2345 | + length -= ret; |
---|
| 2346 | + break; |
---|
| 2347 | + } |
---|
| 2348 | + } |
---|
| 2349 | +done: |
---|
| 2350 | + if (total_length) |
---|
| 2351 | + userial_enqueue_coex_rawdata(buffer, total_length, true); |
---|
| 2352 | + return; |
---|
| 2353 | +} |
---|
| 2354 | + |
---|
| 2355 | +void userial_recv_rawdata_hook(unsigned char *buffer, unsigned int total_length) |
---|
| 2356 | +{ |
---|
| 2357 | + uint16_t transmitted_length = 0; |
---|
| 2358 | + unsigned int real_length = total_length; |
---|
| 2359 | + |
---|
| 2360 | + while (vnd_userial.thread_running && (total_length > 0)) { |
---|
| 2361 | + ssize_t ret; |
---|
| 2362 | + AIC_NO_INTR(ret = write(vnd_userial.uart_fd[1], buffer + transmitted_length, total_length)); |
---|
| 2363 | + switch (ret) { |
---|
| 2364 | + case -1: |
---|
| 2365 | + ALOGE("In %s, error writing to the uart serial port: %s", __func__, strerror(errno)); |
---|
| 2366 | + goto done; |
---|
| 2367 | + case 0: |
---|
| 2368 | + // If we wrote nothing, don't loop more because we |
---|
| 2369 | + // can't go to infinity or beyond |
---|
| 2370 | + goto done; |
---|
| 2371 | + default: |
---|
| 2372 | + transmitted_length += ret; |
---|
| 2373 | + total_length -= ret; |
---|
| 2374 | + break; |
---|
| 2375 | + } |
---|
| 2376 | + } |
---|
| 2377 | + done: |
---|
| 2378 | + if (real_length && vnd_userial.thread_running) |
---|
| 2379 | + userial_enqueue_coex_rawdata(buffer, real_length, true); |
---|
| 2380 | + return; |
---|
| 2381 | + |
---|
| 2382 | +} |
---|
| 2383 | + |
---|
| 2384 | +static void *userial_recv_socket_thread(void *arg) |
---|
| 2385 | +{ |
---|
| 2386 | + AIC_UNUSED(arg); |
---|
| 2387 | + struct epoll_event events[64]; |
---|
| 2388 | + int j; |
---|
| 2389 | + while (vnd_userial.thread_running) { |
---|
| 2390 | + int ret; |
---|
| 2391 | + do { |
---|
| 2392 | + ret = epoll_wait(vnd_userial.epoll_fd, events, 32, 500); |
---|
| 2393 | + } while(vnd_userial.thread_running && ret == -1 && errno == EINTR); |
---|
| 2394 | + |
---|
| 2395 | + if (ret == -1) { |
---|
| 2396 | + ALOGE("%s error in epoll_wait: %s", __func__, strerror(errno)); |
---|
| 2397 | + } |
---|
| 2398 | + for (j = 0; j < ret; ++j) { |
---|
| 2399 | + struct aic_object_t *object = (struct aic_object_t *)events[j].data.ptr; |
---|
| 2400 | + if (events[j].data.ptr == NULL) |
---|
| 2401 | + continue; |
---|
| 2402 | + else { |
---|
| 2403 | + if (events[j].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && object->read_ready) |
---|
| 2404 | + object->read_ready(object->context); |
---|
| 2405 | + if (events[j].events & EPOLLOUT && object->write_ready) |
---|
| 2406 | + object->write_ready(object->context); |
---|
| 2407 | + } |
---|
| 2408 | + } |
---|
| 2409 | + } |
---|
| 2410 | + //vnd_userial.thread_socket_id = -1; |
---|
| 2411 | + ALOGD("%s exit", __func__); |
---|
| 2412 | + return NULL; |
---|
| 2413 | +} |
---|
| 2414 | + |
---|
| 2415 | +static void *userial_recv_uart_thread(void *arg) |
---|
| 2416 | +{ |
---|
| 2417 | + AIC_UNUSED(arg); |
---|
| 2418 | + struct pollfd pfd[2]; |
---|
| 2419 | + pfd[0].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP; |
---|
| 2420 | + pfd[0].fd = vnd_userial.signal_fd[1]; |
---|
| 2421 | + pfd[1].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP; |
---|
| 2422 | + pfd[1].fd = vnd_userial.fd; |
---|
| 2423 | + int ret; |
---|
| 2424 | + unsigned char read_buffer[2056] = {0}; |
---|
| 2425 | + ssize_t bytes_read; |
---|
| 2426 | + while (vnd_userial.thread_running) { |
---|
| 2427 | + do { |
---|
| 2428 | + ret = poll(pfd, 2, 500); |
---|
| 2429 | + } while (ret == -1 && errno == EINTR && vnd_userial.thread_running); |
---|
| 2430 | + |
---|
| 2431 | + //exit signal is always at first index |
---|
| 2432 | + if (pfd[0].revents && !vnd_userial.thread_running) { |
---|
| 2433 | + ALOGD("receive exit signal and stop thread"); |
---|
| 2434 | + return NULL; |
---|
| 2435 | + } |
---|
| 2436 | + |
---|
| 2437 | + if (pfd[1].revents & POLLIN) { |
---|
| 2438 | + AIC_NO_INTR(bytes_read = read(vnd_userial.fd, read_buffer, sizeof(read_buffer))); |
---|
| 2439 | + if (!bytes_read) |
---|
| 2440 | + continue; |
---|
| 2441 | + if (bytes_read < 0) { |
---|
| 2442 | + ALOGE("%s, read fail, error : %s", __func__, strerror(errno)); |
---|
| 2443 | + continue; |
---|
| 2444 | + } |
---|
| 2445 | + |
---|
| 2446 | + if (aicbt_transtype & AICBT_TRANS_H5) { |
---|
| 2447 | + h5_int_interface->h5_recv_msg(read_buffer, bytes_read); |
---|
| 2448 | + } else { |
---|
| 2449 | + userial_recv_uart_rawdata(read_buffer, bytes_read); |
---|
| 2450 | + } |
---|
| 2451 | + } |
---|
| 2452 | + |
---|
| 2453 | + if (pfd[1].revents & (POLLERR|POLLHUP)) { |
---|
| 2454 | + ALOGE("%s poll error, fd : %d", __func__, vnd_userial.fd); |
---|
| 2455 | + vnd_userial.btdriver_state = false; |
---|
| 2456 | + close(vnd_userial.fd); |
---|
| 2457 | + userial_send_hw_error(); |
---|
| 2458 | + return NULL; |
---|
| 2459 | + } |
---|
| 2460 | + if (ret < 0) { |
---|
| 2461 | + ALOGE("%s : error (%d)", __func__, ret); |
---|
| 2462 | + continue; |
---|
| 2463 | + } |
---|
| 2464 | + } |
---|
| 2465 | + vnd_userial.thread_uart_id = -1; |
---|
| 2466 | + ALOGD("%s exit", __func__); |
---|
| 2467 | + return NULL; |
---|
| 2468 | +} |
---|
| 2469 | + |
---|
| 2470 | +static void *userial_coex_thread(void *arg) |
---|
| 2471 | +{ |
---|
| 2472 | + AIC_UNUSED(arg); |
---|
| 2473 | + struct epoll_event events[64]; |
---|
| 2474 | + int j; |
---|
| 2475 | + while(vnd_userial.thread_running) { |
---|
| 2476 | + int ret; |
---|
| 2477 | + do { |
---|
| 2478 | + ret = epoll_wait(vnd_userial.cpoll_fd, events, 64, 500); |
---|
| 2479 | + } while (ret == -1 && errno == EINTR && vnd_userial.thread_running); |
---|
| 2480 | + if (ret == -1) { |
---|
| 2481 | + ALOGE("%s error in epoll_wait: %s", __func__, strerror(errno)); |
---|
| 2482 | + } |
---|
| 2483 | + for (j = 0; j < ret; ++j) { |
---|
| 2484 | + struct aic_object_t *object = (struct aic_object_t *)events[j].data.ptr; |
---|
| 2485 | + if (events[j].data.ptr == NULL) |
---|
| 2486 | + continue; |
---|
| 2487 | + else { |
---|
| 2488 | + if (events[j].events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && object->read_ready) |
---|
| 2489 | + object->read_ready(object->context); |
---|
| 2490 | + if (events[j].events & EPOLLOUT && object->write_ready) |
---|
| 2491 | + object->write_ready(object->context); |
---|
| 2492 | + } |
---|
| 2493 | + } |
---|
| 2494 | + } |
---|
| 2495 | + // vnd_userial.thread_coex_id = -1; |
---|
| 2496 | + ALOGD("%s exit", __func__); |
---|
| 2497 | + return NULL; |
---|
| 2498 | +} |
---|
| 2499 | + |
---|
| 2500 | +int userial_socket_open() |
---|
| 2501 | +{ |
---|
| 2502 | + int ret = 0; |
---|
| 2503 | + struct epoll_event event; |
---|
| 2504 | + if ((ret = socketpair(AF_UNIX, SOCK_STREAM, 0, vnd_userial.uart_fd)) < 0) { |
---|
| 2505 | + ALOGE("%s, errno : %s", __func__, strerror(errno)); |
---|
| 2506 | + return ret; |
---|
| 2507 | + } |
---|
| 2508 | + |
---|
| 2509 | + if ((ret = socketpair(AF_UNIX, SOCK_STREAM, 0, vnd_userial.signal_fd)) < 0) { |
---|
| 2510 | + ALOGE("%s, errno : %s", __func__, strerror(errno)); |
---|
| 2511 | + return ret; |
---|
| 2512 | + } |
---|
| 2513 | + |
---|
| 2514 | + vnd_userial.epoll_fd = epoll_create(64); |
---|
| 2515 | + if (vnd_userial.epoll_fd == -1) { |
---|
| 2516 | + ALOGE("%s unable to create epoll instance: %s", __func__, strerror(errno)); |
---|
| 2517 | + return -1; |
---|
| 2518 | + } |
---|
| 2519 | + |
---|
| 2520 | + aic_socket_object.fd = vnd_userial.uart_fd[1]; |
---|
| 2521 | + aic_socket_object.read_ready = userial_recv_H4_rawdata; |
---|
| 2522 | + memset(&event, 0, sizeof(event)); |
---|
| 2523 | + event.events |= EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR; |
---|
| 2524 | + event.data.ptr = (void *)&aic_socket_object; |
---|
| 2525 | + if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_ADD, vnd_userial.uart_fd[1], &event) == -1) { |
---|
| 2526 | + ALOGE("%s unable to register fd %d to epoll set: %s", __func__, vnd_userial.uart_fd[1], strerror(errno)); |
---|
| 2527 | + close(vnd_userial.epoll_fd); |
---|
| 2528 | + vnd_userial.epoll_fd = -1; |
---|
| 2529 | + return -1; |
---|
| 2530 | + } |
---|
| 2531 | + |
---|
| 2532 | + event.data.ptr = NULL; |
---|
| 2533 | + if (epoll_ctl(vnd_userial.epoll_fd, EPOLL_CTL_ADD, vnd_userial.signal_fd[1], &event) == -1) { |
---|
| 2534 | + ALOGE("%s unable to register signal fd %d to epoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno)); |
---|
| 2535 | + close(vnd_userial.epoll_fd); |
---|
| 2536 | + vnd_userial.epoll_fd = -1; |
---|
| 2537 | + return -1; |
---|
| 2538 | + } |
---|
| 2539 | + pthread_attr_t thread_attr; |
---|
| 2540 | + pthread_attr_init(&thread_attr); |
---|
| 2541 | + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); |
---|
| 2542 | + vnd_userial.thread_running = true; |
---|
| 2543 | + if (pthread_create(&vnd_userial.thread_socket_id, &thread_attr, userial_recv_socket_thread, NULL) != 0) { |
---|
| 2544 | + ALOGE("pthread_create : %s", strerror(errno)); |
---|
| 2545 | + close(vnd_userial.epoll_fd); |
---|
| 2546 | + vnd_userial.epoll_fd = -1; |
---|
| 2547 | + vnd_userial.thread_socket_id = -1; |
---|
| 2548 | + return -1; |
---|
| 2549 | + } |
---|
| 2550 | + |
---|
| 2551 | + |
---|
| 2552 | + if (pthread_create(&vnd_userial.thread_uart_id, &thread_attr, userial_recv_uart_thread, NULL) != 0) { |
---|
| 2553 | + ALOGE("pthread_create : %s", strerror(errno)); |
---|
| 2554 | + close(vnd_userial.epoll_fd); |
---|
| 2555 | + vnd_userial.thread_running = false; |
---|
| 2556 | + pthread_join(vnd_userial.thread_socket_id, NULL); |
---|
| 2557 | + vnd_userial.thread_socket_id = -1; |
---|
| 2558 | + return -1; |
---|
| 2559 | + } |
---|
| 2560 | + |
---|
| 2561 | + vnd_userial.cpoll_fd = epoll_create(64); |
---|
| 2562 | + assert (vnd_userial.cpoll_fd != -1); |
---|
| 2563 | + |
---|
| 2564 | + vnd_userial.event_fd = eventfd(10, EFD_NONBLOCK); |
---|
| 2565 | + assert(vnd_userial.event_fd != -1); |
---|
| 2566 | + if (vnd_userial.event_fd != -1) { |
---|
| 2567 | + aic_coex_object.fd = vnd_userial.event_fd; |
---|
| 2568 | + aic_coex_object.read_ready = userial_coex_handler; |
---|
| 2569 | + memset(&event, 0, sizeof(event)); |
---|
| 2570 | + event.events |= EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR; |
---|
| 2571 | + event.data.ptr = (void *)&aic_coex_object; |
---|
| 2572 | + if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_ADD, vnd_userial.event_fd, &event) == -1) { |
---|
| 2573 | + ALOGE("%s unable to register fd %d to cpoll set: %s", __func__, vnd_userial.event_fd, strerror(errno)); |
---|
| 2574 | + assert(false); |
---|
| 2575 | + } |
---|
| 2576 | + |
---|
| 2577 | + event.data.ptr = NULL; |
---|
| 2578 | + if (epoll_ctl(vnd_userial.cpoll_fd, EPOLL_CTL_ADD, vnd_userial.signal_fd[1], &event) == -1) { |
---|
| 2579 | + ALOGE("%s unable to register fd %d to cpoll set: %s", __func__, vnd_userial.signal_fd[1], strerror(errno)); |
---|
| 2580 | + assert(false); |
---|
| 2581 | + } |
---|
| 2582 | + |
---|
| 2583 | + if (pthread_create(&vnd_userial.thread_coex_id, &thread_attr, userial_coex_thread, NULL) != 0) { |
---|
| 2584 | + ALOGE("pthread create coex : %s", strerror(errno)); |
---|
| 2585 | + vnd_userial.thread_coex_id = -1; |
---|
| 2586 | + assert(false); |
---|
| 2587 | + } |
---|
| 2588 | + } |
---|
| 2589 | + |
---|
| 2590 | + AIC_btservice_init(); |
---|
| 2591 | + ret = vnd_userial.uart_fd[0]; |
---|
| 2592 | + return ret; |
---|
| 2593 | +} |
---|
| 2594 | + |
---|
| 2595 | +int userial_vendor_usb_ioctl(int operation, void *param) |
---|
| 2596 | +{ |
---|
| 2597 | + int retval; |
---|
| 2598 | + ALOGD("aic userial_vendor_usb_ioctl %d", operation); |
---|
| 2599 | + retval = ioctl(vnd_userial.fd, operation, param); |
---|
| 2600 | + if (retval == -1) |
---|
| 2601 | + ALOGE("%s: error: %d : %s", __func__,errno, strerror(errno)); |
---|
| 2602 | + return retval; |
---|
| 2603 | +} |
---|
| 2604 | + |
---|
| 2605 | +int userial_vendor_usb_open(void) |
---|
| 2606 | +{ |
---|
| 2607 | + if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1) { |
---|
| 2608 | + ALOGE("%s: unable to open %s: %s", __func__, vnd_userial.port_name, strerror(errno)); |
---|
| 2609 | + return -1; |
---|
| 2610 | + } |
---|
| 2611 | + |
---|
| 2612 | + vnd_userial.btdriver_state = true; |
---|
| 2613 | + ALOGI("device fd = %d open", vnd_userial.fd); |
---|
| 2614 | + |
---|
| 2615 | + return vnd_userial.fd; |
---|
| 2616 | +} |
---|
| 2617 | + |
---|
| 2618 | +void userial_set_bt_interface_state(int bt_on) |
---|
| 2619 | +{ |
---|
| 2620 | + if (aic_parse_manager) { |
---|
| 2621 | + aic_parse_manager->aic_set_bt_on(bt_on); |
---|
| 2622 | + } |
---|
| 2623 | +} |
---|
| 2624 | + |
---|