1 /******************************************************************************
3 * Copyright (C) 2014 Google, Inc.
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 #define LOG_TAG "bt_hci_inject"
23 #include <utils/Log.h>
25 #include "bt_hci_bdroid.h"
27 #include "hci_inject.h"
34 HCI_PACKET_COMMAND = 1,
35 HCI_PACKET_ACL_DATA = 2,
36 HCI_PACKET_SCO_DATA = 3,
42 uint8_t buffer[65536 + 3]; // 2 bytes length prefix, 1 byte type prefix.
46 static const port_t LISTEN_PORT = 8873;
48 static const bt_hc_interface_t *hci;
49 static socket_t *listen_socket;
50 static thread_t *thread;
51 static list_t *clients;
53 static int hci_packet_to_event(hci_packet_t packet);
54 static void accept_ready(socket_t *socket, void *context);
55 static void read_ready(socket_t *socket, void *context);
56 static void client_free(void *ptr);
58 bool hci_inject_open(void) {
59 assert(listen_socket == NULL);
60 assert(thread == NULL);
61 assert(clients == NULL);
63 hci = bt_hc_get_interface();
65 thread = thread_new("hci_inject");
69 clients = list_new(client_free);
73 listen_socket = socket_new();
77 if (!socket_listen(listen_socket, LISTEN_PORT))
80 socket_register(listen_socket, thread_get_reactor(thread), NULL, accept_ready, NULL);
88 void hci_inject_close(void) {
89 socket_free(listen_socket);
98 static int hci_packet_to_event(hci_packet_t 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;
107 ALOGE("%s unsupported packet type: %d", __func__, packet);
112 static void accept_ready(socket_t *socket, UNUSED_ATTR void *context) {
113 assert(socket != NULL);
114 assert(socket == listen_socket);
116 socket = socket_accept(socket);
120 client_t *client = (client_t *)calloc(1, sizeof(client_t));
122 ALOGE("%s unable to allocate memory for client.", __func__);
127 client->socket = socket;
129 if (!list_append(clients, client)) {
130 ALOGE("%s unable to add client to list.", __func__);
135 socket_register(socket, thread_get_reactor(thread), client, read_ready, NULL);
138 static void read_ready(UNUSED_ATTR socket_t *socket, void *context) {
139 assert(bt_hc_cbacks != NULL);
140 assert(socket != NULL);
141 assert(context != NULL);
143 client_t *client = (client_t *)context;
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);
150 client->buffer_size += ret;
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;
158 if (client->buffer_size < frame_len)
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.
165 BT_HDR *buf = (BT_HDR *)bt_hc_cbacks->alloc(packet_len);
167 buf->event = hci_packet_to_event(packet_type);
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);
174 ALOGE("%s dropping injected packet of length %zu", __func__, packet_len);
177 size_t remainder = client->buffer_size - frame_len;
178 memmove(buffer, buffer + frame_len, remainder);
179 client->buffer_size -= frame_len;
183 static void client_free(void *ptr) {
187 client_t *client = (client_t *)ptr;
188 socket_free(client->socket);