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 
36 typedef 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 
43 typedef 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 
49 static const port_t LISTEN_PORT = 8873;
50 
51 static const hci_inject_t interface;
52 static const hci_t *hci;
53 static const allocator_t *buffer_allocator;
54 static socket_t *listen_socket;
55 static thread_t *thread;
56 static list_t *clients;
57 
58 static int hci_packet_to_event(hci_packet_t packet);
59 static void accept_ready(socket_t *socket, void *context);
60 static void read_ready(socket_t *socket, void *context);
61 static void client_free(void *ptr);
62 
hci_inject_open(const hci_t * hci_interface)63 bool 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 
89 error:;
90   interface.close();
91   return false;
92 }
93 
hci_inject_close(void)94 void 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 
hci_packet_to_event(hci_packet_t packet)104 static 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 
accept_ready(socket_t * socket,UNUSED_ATTR void * context)118 static 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 
read_ready(UNUSED_ATTR socket_t * socket,void * context)144 static 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(BT_HDR_SIZE + 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 
client_free(void * ptr)188 static 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 
197 static const hci_inject_t interface = {
198   hci_inject_open,
199   hci_inject_close
200 };
201 
hci_inject_get_interface()202 const hci_inject_t *hci_inject_get_interface() {
203   buffer_allocator = buffer_allocator_get_interface();
204   return &interface;
205 }
206