hci_inject.cc revision 3e59b5b6f2ce1295e3e2711afcd2cdf0dd7e22b6
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 <string.h> 24 25#include "osi/include/allocator.h" 26#include "bt_types.h" 27#include "buffer_allocator.h" 28#include "hci_inject.h" 29#include "hci_layer.h" 30#include "osi/include/list.h" 31#include "osi/include/osi.h" 32#include "osi/include/log.h" 33#include "osi/include/socket.h" 34#include "osi/include/thread.h" 35 36typedef enum { 37 HCI_PACKET_COMMAND = 1, 38 HCI_PACKET_ACL_DATA = 2, 39 HCI_PACKET_SCO_DATA = 3, 40 HCI_PACKET_EVENT = 4, 41} hci_packet_t; 42 43typedef struct { 44 socket_t *socket; 45 uint8_t buffer[65536 + 3]; // 2 bytes length prefix, 1 byte type prefix. 46 size_t buffer_size; 47} client_t; 48 49static const port_t LISTEN_PORT = 8873; 50 51static const hci_inject_t interface; 52static const hci_t *hci; 53static const allocator_t *buffer_allocator; 54static socket_t *listen_socket; 55static thread_t *thread; 56static list_t *clients; 57 58static int hci_packet_to_event(hci_packet_t packet); 59static void accept_ready(socket_t *socket, void *context); 60static void read_ready(socket_t *socket, void *context); 61static void client_free(void *ptr); 62 63bool hci_inject_open(const hci_t *hci_interface) { 64 assert(listen_socket == NULL); 65 assert(thread == NULL); 66 assert(clients == NULL); 67 assert(hci_interface != NULL); 68 69 hci = hci_interface; 70 71 thread = thread_new("hci_inject"); 72 if (!thread) 73 goto error; 74 75 clients = list_new(client_free); 76 if (!clients) 77 goto error; 78 79 listen_socket = socket_new(); 80 if (!listen_socket) 81 goto error; 82 83 if (!socket_listen(listen_socket, LISTEN_PORT)) 84 goto error; 85 86 socket_register(listen_socket, thread_get_reactor(thread), NULL, accept_ready, NULL); 87 return true; 88 89error:; 90 interface.close(); 91 return false; 92} 93 94void hci_inject_close(void) { 95 socket_free(listen_socket); 96 list_free(clients); 97 thread_free(thread); 98 99 listen_socket = NULL; 100 thread = NULL; 101 clients = NULL; 102} 103 104static int hci_packet_to_event(hci_packet_t packet) { 105 switch (packet) { 106 case HCI_PACKET_COMMAND: 107 return MSG_STACK_TO_HC_HCI_CMD; 108 case HCI_PACKET_ACL_DATA: 109 return MSG_STACK_TO_HC_HCI_ACL; 110 case HCI_PACKET_SCO_DATA: 111 return MSG_STACK_TO_HC_HCI_SCO; 112 default: 113 LOG_ERROR("%s unsupported packet type: %d", __func__, packet); 114 return -1; 115 } 116} 117 118static void accept_ready(socket_t *socket, UNUSED_ATTR void *context) { 119 assert(socket != NULL); 120 assert(socket == listen_socket); 121 122 socket = socket_accept(socket); 123 if (!socket) 124 return; 125 126 client_t *client = (client_t *)osi_calloc(sizeof(client_t)); 127 if (!client) { 128 LOG_ERROR("%s unable to allocate memory for client.", __func__); 129 socket_free(socket); 130 return; 131 } 132 133 client->socket = socket; 134 135 if (!list_append(clients, client)) { 136 LOG_ERROR("%s unable to add client to list.", __func__); 137 client_free(client); 138 return; 139 } 140 141 socket_register(socket, thread_get_reactor(thread), client, read_ready, NULL); 142} 143 144static void read_ready(UNUSED_ATTR socket_t *socket, void *context) { 145 assert(socket != NULL); 146 assert(context != NULL); 147 148 client_t *client = (client_t *)context; 149 150 ssize_t ret = socket_read(client->socket, client->buffer + client->buffer_size, sizeof(client->buffer) - client->buffer_size); 151 if (ret == 0 || (ret == -1 && ret != EWOULDBLOCK && ret != EAGAIN)) { 152 list_remove(clients, client); 153 return; 154 } 155 client->buffer_size += ret; 156 157 while (client->buffer_size > 3) { 158 uint8_t *buffer = client->buffer; 159 hci_packet_t packet_type = (hci_packet_t)buffer[0]; 160 size_t packet_len = (buffer[2] << 8) | buffer[1]; 161 size_t frame_len = 3 + packet_len; 162 163 if (client->buffer_size < frame_len) 164 break; 165 166 // TODO(sharvil): validate incoming HCI messages. 167 // TODO(sharvil): once we have an HCI parser, we can eliminate 168 // the 2-byte size field since it will be contained in the packet. 169 170 BT_HDR *buf = (BT_HDR *)buffer_allocator->alloc(packet_len); 171 if (buf) { 172 buf->event = hci_packet_to_event(packet_type); 173 buf->offset = 0; 174 buf->layer_specific = 0; 175 buf->len = packet_len; 176 memcpy(buf->data, buffer + 3, packet_len); 177 hci->transmit_downward(buf->event, buf); 178 } else { 179 LOG_ERROR("%s dropping injected packet of length %zu", __func__, packet_len); 180 } 181 182 size_t remainder = client->buffer_size - frame_len; 183 memmove(buffer, buffer + frame_len, remainder); 184 client->buffer_size -= frame_len; 185 } 186} 187 188static void client_free(void *ptr) { 189 if (!ptr) 190 return; 191 192 client_t *client = (client_t *)ptr; 193 socket_free(client->socket); 194 osi_free(client); 195} 196 197static const hci_inject_t interface = { 198 hci_inject_open, 199 hci_inject_close 200}; 201 202const hci_inject_t *hci_inject_get_interface() { 203 buffer_allocator = buffer_allocator_get_interface(); 204 return &interface; 205} 206