hci_inject.cc revision 09f31c121df79afe045163e0142dec5c09caa072
1/****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19#define LOG_TAG "bt_hci_inject" 20 21#include <assert.h> 22#include <errno.h> 23#include <utils/Log.h> 24 25#include "bt_hci_bdroid.h" 26#include "bt_types.h" 27#include "hci_inject.h" 28#include "list.h" 29#include "osi.h" 30#include "socket.h" 31#include "thread.h" 32 33typedef enum { 34 HCI_PACKET_COMMAND = 1, 35 HCI_PACKET_ACL_DATA = 2, 36 HCI_PACKET_SCO_DATA = 3, 37 HCI_PACKET_EVENT = 4, 38} hci_packet_t; 39 40typedef struct { 41 socket_t *socket; 42 uint8_t buffer[65536 + 3]; // 2 bytes length prefix, 1 byte type prefix. 43 size_t buffer_size; 44} client_t; 45 46static const port_t LISTEN_PORT = 8873; 47 48static const bt_hc_interface_t *hci; 49static socket_t *listen_socket; 50static thread_t *thread; 51static list_t *clients; 52 53static int hci_packet_to_event(hci_packet_t packet); 54static void accept_ready(socket_t *socket, void *context); 55static void read_ready(socket_t *socket, void *context); 56static void client_free(void *ptr); 57 58bool hci_inject_open(void) { 59 assert(listen_socket == NULL); 60 assert(thread == NULL); 61 assert(clients == NULL); 62 63 hci = bt_hc_get_interface(); 64 65 clients = list_new(client_free); 66 if (!clients) 67 goto error; 68 69 thread = thread_new("hci_inject"); 70 if (!thread) 71 goto error; 72 73 listen_socket = socket_new(); 74 if (!listen_socket) 75 goto error; 76 77 if (!socket_listen(listen_socket, LISTEN_PORT)) 78 goto error; 79 80 socket_register(listen_socket, thread_get_reactor(thread), accept_ready, NULL, NULL); 81 return true; 82 83error:; 84 hci_inject_close(); 85 return false; 86} 87 88void hci_inject_close(void) { 89 socket_free(listen_socket); 90 thread_free(thread); 91 list_free(clients); 92 93 listen_socket = NULL; 94 thread = NULL; 95 clients = NULL; 96} 97 98static int hci_packet_to_event(hci_packet_t packet) { 99 switch (packet) { 100 case HCI_PACKET_COMMAND: 101 return MSG_STACK_TO_HC_HCI_CMD; 102 case HCI_PACKET_ACL_DATA: 103 return MSG_STACK_TO_HC_HCI_ACL; 104 case HCI_PACKET_SCO_DATA: 105 return MSG_STACK_TO_HC_HCI_SCO; 106 default: 107 ALOGE("%s unsupported packet type: %d", __func__, packet); 108 return -1; 109 } 110} 111 112static void accept_ready(socket_t *socket, UNUSED_ATTR void *context) { 113 assert(socket != NULL); 114 assert(socket == listen_socket); 115 116 socket = socket_accept(socket); 117 if (!socket) 118 return; 119 120 client_t *client = (client_t *)calloc(1, sizeof(client_t)); 121 if (!client) { 122 ALOGE("%s unable to allocate memory for client.", __func__); 123 socket_free(socket); 124 return; 125 } 126 127 client->socket = socket; 128 129 if (!list_append(clients, client)) { 130 ALOGE("%s unable to add client to list.", __func__); 131 client_free(client); 132 return; 133 } 134 135 socket_register(socket, thread_get_reactor(thread), read_ready, NULL, client); 136} 137 138static void read_ready(UNUSED_ATTR socket_t *socket, void *context) { 139 assert(bt_hc_cbacks != NULL); 140 assert(socket != NULL); 141 assert(context != NULL); 142 143 client_t *client = (client_t *)context; 144 145 ssize_t ret = socket_read(client->socket, client->buffer + client->buffer_size, sizeof(client->buffer) - client->buffer_size); 146 if (ret == 0 || (ret == -1 && ret != EWOULDBLOCK && ret != EAGAIN)) { 147 list_remove(clients, client); 148 return; 149 } 150 client->buffer_size += ret; 151 152 while (client->buffer_size > 3) { 153 uint8_t *buffer = client->buffer; 154 hci_packet_t packet_type = (hci_packet_t)buffer[0]; 155 size_t packet_len = (buffer[2] << 8) | buffer[1]; 156 size_t frame_len = 3 + packet_len; 157 158 if (client->buffer_size < frame_len) 159 break; 160 161 // TODO(sharvil): validate incoming HCI messages. 162 // TODO(sharvil): once we have an HCI parser, we can eliminate 163 // the 2-byte size field since it will be contained in the packet. 164 165 BT_HDR *buf = (BT_HDR *)bt_hc_cbacks->alloc(packet_len); 166 if (buf) { 167 buf->event = hci_packet_to_event(packet_type); 168 buf->offset = 0; 169 buf->layer_specific = 0; 170 buf->len = packet_len; 171 memcpy(buf->data, buffer + 3, packet_len); 172 hci->transmit_buf(buf, NULL, 0); 173 } else { 174 ALOGE("%s dropping injected packet of length %zu", __func__, packet_len); 175 } 176 177 size_t remainder = client->buffer_size - frame_len; 178 memmove(buffer, buffer + frame_len, remainder); 179 client->buffer_size -= frame_len; 180 } 181} 182 183static void client_free(void *ptr) { 184 if (!ptr) 185 return; 186 187 client_t *client = (client_t *)ptr; 188 socket_free(client->socket); 189} 190