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#include <assert.h>
20
21#include "osi/include/allocator.h"
22#include "bt_types.h"
23#include "buffer_allocator.h"
24#include "hcidefs.h"
25#include "hcimsgs.h"
26#include "hci_internals.h"
27#include "hci_layer.h"
28#include "hci_packet_factory.h"
29
30static const allocator_t *buffer_allocator;
31
32static BT_HDR *make_packet(size_t data_size);
33static BT_HDR *make_command_no_params(uint16_t opcode);
34static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out);
35
36// Interface functions
37
38static BT_HDR *make_reset(void) {
39  return make_command_no_params(HCI_RESET);
40}
41
42static BT_HDR *make_read_buffer_size(void) {
43  return make_command_no_params(HCI_READ_BUFFER_SIZE);
44}
45
46static BT_HDR *make_host_buffer_size(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count) {
47  uint8_t *stream;
48  const uint8_t parameter_size = 2 + 1 + 2 + 2; // from each of the parameters
49  BT_HDR *packet = make_command(HCI_HOST_BUFFER_SIZE, parameter_size, &stream);
50
51  UINT16_TO_STREAM(stream, acl_size);
52  UINT8_TO_STREAM(stream, sco_size);
53  UINT16_TO_STREAM(stream, acl_count);
54  UINT16_TO_STREAM(stream, sco_count);
55  return packet;
56}
57
58static BT_HDR *make_read_local_version_info(void) {
59  return make_command_no_params(HCI_READ_LOCAL_VERSION_INFO);
60}
61
62static BT_HDR *make_read_bd_addr(void) {
63  return make_command_no_params(HCI_READ_BD_ADDR);
64}
65
66static BT_HDR *make_read_local_supported_commands(void) {
67  return make_command_no_params(HCI_READ_LOCAL_SUPPORTED_CMDS);
68}
69
70static BT_HDR *make_read_local_extended_features(uint8_t page_number) {
71  uint8_t *stream;
72  const uint8_t parameter_size = 1;
73  BT_HDR *packet = make_command(HCI_READ_LOCAL_EXT_FEATURES, parameter_size, &stream);
74
75  UINT8_TO_STREAM(stream, page_number);
76  return packet;
77}
78
79static BT_HDR *make_write_simple_pairing_mode(uint8_t mode) {
80  uint8_t *stream;
81  const uint8_t parameter_size = 1;
82  BT_HDR *packet = make_command(HCI_WRITE_SIMPLE_PAIRING_MODE, parameter_size, &stream);
83
84  UINT8_TO_STREAM(stream, mode);
85  return packet;
86}
87
88static BT_HDR *make_write_secure_connections_host_support(uint8_t mode) {
89  uint8_t *stream;
90  const uint8_t parameter_size = 1;
91  BT_HDR *packet = make_command(HCI_WRITE_SECURE_CONNS_SUPPORT, parameter_size, &stream);
92
93  UINT8_TO_STREAM(stream, mode);
94  return packet;
95}
96
97static BT_HDR *make_set_event_mask(const bt_event_mask_t *event_mask) {
98  uint8_t *stream;
99  uint8_t parameter_size = sizeof(bt_event_mask_t);
100  BT_HDR *packet = make_command(HCI_SET_EVENT_MASK, parameter_size, &stream);
101
102  ARRAY8_TO_STREAM(stream, event_mask->as_array);
103  return packet;
104}
105
106static BT_HDR *make_ble_write_host_support(uint8_t supported_host, uint8_t simultaneous_host) {
107  uint8_t *stream;
108  const uint8_t parameter_size = 1 + 1;
109  BT_HDR *packet = make_command(HCI_WRITE_LE_HOST_SUPPORT, parameter_size, &stream);
110
111  UINT8_TO_STREAM(stream, supported_host);
112  UINT8_TO_STREAM(stream, simultaneous_host);
113  return packet;
114}
115
116static BT_HDR *make_ble_read_white_list_size(void) {
117  return make_command_no_params(HCI_BLE_READ_WHITE_LIST_SIZE);
118}
119
120static BT_HDR *make_ble_read_buffer_size(void) {
121  return make_command_no_params(HCI_BLE_READ_BUFFER_SIZE);
122}
123
124static BT_HDR *make_ble_read_supported_states(void) {
125  return make_command_no_params(HCI_BLE_READ_SUPPORTED_STATES);
126}
127
128static BT_HDR *make_ble_read_local_supported_features(void) {
129  return make_command_no_params(HCI_BLE_READ_LOCAL_SPT_FEAT);
130}
131
132static BT_HDR *make_ble_read_resolving_list_size(void) {
133  return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
134}
135
136static BT_HDR *make_ble_read_suggested_default_data_length(void) {
137    return make_command_no_params(HCI_BLE_READ_DEFAULT_DATA_LENGTH);
138}
139
140static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
141  uint8_t *stream;
142  uint8_t parameter_size = sizeof(bt_event_mask_t);
143  BT_HDR *packet = make_command(HCI_BLE_SET_EVENT_MASK, parameter_size, &stream);
144
145  ARRAY8_TO_STREAM(stream, event_mask->as_array);
146  return packet;
147}
148
149// Internal functions
150
151static BT_HDR *make_command_no_params(uint16_t opcode) {
152  return make_command(opcode, 0, NULL);
153}
154
155static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out) {
156  BT_HDR *packet = make_packet(HCI_COMMAND_PREAMBLE_SIZE + parameter_size);
157
158  uint8_t *stream = packet->data;
159  UINT16_TO_STREAM(stream, opcode);
160  UINT8_TO_STREAM(stream, parameter_size);
161
162  if (stream_out != NULL)
163    *stream_out = stream;
164
165  return packet;
166}
167
168static BT_HDR *make_packet(size_t data_size) {
169  BT_HDR *ret = (BT_HDR *)buffer_allocator->alloc(sizeof(BT_HDR) + data_size);
170  assert(ret);
171  ret->event = 0;
172  ret->offset = 0;
173  ret->layer_specific = 0;
174  ret->len = data_size;
175  return ret;
176}
177
178static const hci_packet_factory_t interface = {
179  make_reset,
180  make_read_buffer_size,
181  make_host_buffer_size,
182  make_read_local_version_info,
183  make_read_bd_addr,
184  make_read_local_supported_commands,
185  make_read_local_extended_features,
186  make_write_simple_pairing_mode,
187  make_write_secure_connections_host_support,
188  make_set_event_mask,
189  make_ble_write_host_support,
190  make_ble_read_white_list_size,
191  make_ble_read_buffer_size,
192  make_ble_read_supported_states,
193  make_ble_read_local_supported_features,
194  make_ble_read_resolving_list_size,
195  make_ble_read_suggested_default_data_length,
196  make_ble_set_event_mask
197};
198
199const hci_packet_factory_t *hci_packet_factory_get_interface() {
200  buffer_allocator = buffer_allocator_get_interface();
201  return &interface;
202}
203