2 * Copyright (C) 2013 Intel Corporation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 #include "ipc-common.h"
29 static const bthh_callbacks_t *cbacks;
31 static bool interface_ready(void)
33 return cbacks != NULL;
36 static void handle_conn_state(void *buf, uint16_t len, int fd)
38 struct hal_ev_hidhost_conn_state *ev = buf;
40 if (cbacks->connection_state_cb)
41 cbacks->connection_state_cb((bt_bdaddr_t *) ev->bdaddr,
45 static void handle_info(void *buf, uint16_t len, int fd)
47 struct hal_ev_hidhost_info *ev = buf;
50 info.attr_mask = ev->attr;
51 info.sub_class = ev->subclass;
52 info.app_id = ev->app_id;
53 info.vendor_id = ev->vendor;
54 info.product_id = ev->product;
55 info.version = ev->version;
56 info.ctry_code = ev->country;
57 info.dl_len = ev->descr_len;
58 memcpy(info.dsc_list, ev->descr, info.dl_len);
60 if (cbacks->hid_info_cb)
61 cbacks->hid_info_cb((bt_bdaddr_t *) ev->bdaddr, info);
64 static void handle_proto_mode(void *buf, uint16_t len, int fd)
66 struct hal_ev_hidhost_proto_mode *ev = buf;
68 if (cbacks->protocol_mode_cb)
69 cbacks->protocol_mode_cb((bt_bdaddr_t *) ev->bdaddr,
70 ev->status, ev->mode);
73 static void handle_idle_time(void *buf, uint16_t len, int fd)
75 struct hal_ev_hidhost_idle_time *ev = buf;
77 if (cbacks->idle_time_cb)
78 cbacks->idle_time_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
82 static void handle_get_report(void *buf, uint16_t len, int fd)
84 struct hal_ev_hidhost_get_report *ev = buf;
86 if (len != sizeof(*ev) + ev->len) {
87 error("invalid get report event, aborting");
91 if (cbacks->get_report_cb)
92 cbacks->get_report_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
96 static void handle_virtual_unplug(void *buf, uint16_t len, int fd)
98 struct hal_ev_hidhost_virtual_unplug *ev = buf;
100 if (cbacks->virtual_unplug_cb)
101 cbacks->virtual_unplug_cb((bt_bdaddr_t *) ev->bdaddr,
105 static void handle_handshake(void *buf, uint16_t len, int fd)
107 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
108 struct hal_ev_hidhost_handshake *ev = buf;
110 if (cbacks->handshake_cb)
111 cbacks->handshake_cb((bt_bdaddr_t *) ev->bdaddr, ev->status);
116 * handlers will be called from notification thread context,
117 * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
119 static const struct hal_ipc_handler ev_handlers[] = {
120 /* HAL_EV_HIDHOST_CONN_STATE */
121 { handle_conn_state, false, sizeof(struct hal_ev_hidhost_conn_state) },
122 /* HAL_EV_HIDHOST_INFO */
123 { handle_info, false, sizeof(struct hal_ev_hidhost_info) },
124 /* HAL_EV_HIDHOST_PROTO_MODE */
125 { handle_proto_mode, false, sizeof(struct hal_ev_hidhost_proto_mode) },
126 /* HAL_EV_HIDHOST_IDLE_TIME */
127 { handle_idle_time, false, sizeof(struct hal_ev_hidhost_idle_time) },
128 /* HAL_EV_HIDHOST_GET_REPORT */
129 { handle_get_report, true, sizeof(struct hal_ev_hidhost_get_report) },
130 /* HAL_EV_HIDHOST_VIRTUAL_UNPLUG */
131 { handle_virtual_unplug, false,
132 sizeof(struct hal_ev_hidhost_virtual_unplug) },
133 { handle_handshake, false, sizeof(struct hal_ev_hidhost_handshake) },
136 static bt_status_t hidhost_connect(bt_bdaddr_t *bd_addr)
138 struct hal_cmd_hidhost_connect cmd;
142 if (!interface_ready())
143 return BT_STATUS_NOT_READY;
146 return BT_STATUS_PARM_INVALID;
148 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
150 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT,
151 sizeof(cmd), &cmd, NULL, NULL, NULL);
154 static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
156 struct hal_cmd_hidhost_disconnect cmd;
160 if (!interface_ready())
161 return BT_STATUS_NOT_READY;
164 return BT_STATUS_PARM_INVALID;
166 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
168 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT,
169 sizeof(cmd), &cmd, NULL, NULL, NULL);
172 static bt_status_t virtual_unplug(bt_bdaddr_t *bd_addr)
174 struct hal_cmd_hidhost_virtual_unplug cmd;
178 if (!interface_ready())
179 return BT_STATUS_NOT_READY;
182 return BT_STATUS_PARM_INVALID;
184 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
186 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
187 HAL_OP_HIDHOST_VIRTUAL_UNPLUG,
188 sizeof(cmd), &cmd, NULL, NULL, NULL);
191 static bt_status_t set_info(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info)
193 struct hal_cmd_hidhost_set_info cmd;
197 if (!interface_ready())
198 return BT_STATUS_NOT_READY;
201 return BT_STATUS_PARM_INVALID;
203 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
204 cmd.attr = hid_info.attr_mask;
205 cmd.subclass = hid_info.sub_class;
206 cmd.app_id = hid_info.app_id;
207 cmd.vendor = hid_info.vendor_id;
208 cmd.product = hid_info.product_id;
209 cmd.country = hid_info.ctry_code;
210 cmd.descr_len = hid_info.dl_len;
211 memcpy(cmd.descr, hid_info.dsc_list, cmd.descr_len);
213 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
214 sizeof(cmd), &cmd, NULL, NULL, NULL);
217 static bt_status_t get_protocol(bt_bdaddr_t *bd_addr,
218 bthh_protocol_mode_t protocol_mode)
220 struct hal_cmd_hidhost_get_protocol cmd;
224 if (!interface_ready())
225 return BT_STATUS_NOT_READY;
228 return BT_STATUS_PARM_INVALID;
230 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
232 /* type match IPC type */
233 cmd.mode = protocol_mode;
235 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
236 HAL_OP_HIDHOST_GET_PROTOCOL,
237 sizeof(cmd), &cmd, NULL, NULL, NULL);
240 static bt_status_t set_protocol(bt_bdaddr_t *bd_addr,
241 bthh_protocol_mode_t protocol_mode)
243 struct hal_cmd_hidhost_set_protocol cmd;
247 if (!interface_ready())
248 return BT_STATUS_NOT_READY;
251 return BT_STATUS_PARM_INVALID;
253 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
255 /* type match IPC type */
256 cmd.mode = protocol_mode;
258 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
259 HAL_OP_HIDHOST_SET_PROTOCOL,
260 sizeof(cmd), &cmd, NULL, NULL, NULL);
263 static bt_status_t get_report(bt_bdaddr_t *bd_addr,
264 bthh_report_type_t report_type,
268 struct hal_cmd_hidhost_get_report cmd;
272 if (!interface_ready())
273 return BT_STATUS_NOT_READY;
276 return BT_STATUS_PARM_INVALID;
278 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
280 cmd.buf_size = buffer_size;
282 /* type match IPC type */
283 cmd.type = report_type;
285 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT,
286 sizeof(cmd), &cmd, NULL, NULL, NULL);
289 static bt_status_t set_report(bt_bdaddr_t *bd_addr,
290 bthh_report_type_t report_type,
293 uint8_t buf[IPC_MTU];
294 struct hal_cmd_hidhost_set_report *cmd = (void *) buf;
298 if (!interface_ready())
299 return BT_STATUS_NOT_READY;
301 if (!bd_addr || !report)
302 return BT_STATUS_PARM_INVALID;
304 memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
305 cmd->len = strlen(report);
306 memcpy(cmd->data, report, cmd->len);
308 /* type match IPC type */
309 cmd->type = report_type;
311 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
312 sizeof(*cmd) + cmd->len, buf, NULL, NULL, NULL);
315 static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
317 uint8_t buf[IPC_MTU];
318 struct hal_cmd_hidhost_send_data *cmd = (void *) buf;
322 if (!interface_ready())
323 return BT_STATUS_NOT_READY;
325 if (!bd_addr || !data)
326 return BT_STATUS_PARM_INVALID;
328 memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
329 cmd->len = strlen(data);
330 memcpy(cmd->data, data, cmd->len);
332 return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
333 sizeof(*cmd) + cmd->len, buf, NULL, NULL, NULL);
336 static bt_status_t init(bthh_callbacks_t *callbacks)
338 struct hal_cmd_register_module cmd;
343 if (interface_ready())
344 return BT_STATUS_DONE;
346 /* store reference to user callbacks */
349 hal_ipc_register(HAL_SERVICE_ID_HIDHOST, ev_handlers,
350 sizeof(ev_handlers)/sizeof(ev_handlers[0]));
352 cmd.service_id = HAL_SERVICE_ID_HIDHOST;
353 cmd.mode = HAL_MODE_DEFAULT;
356 ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
357 sizeof(cmd), &cmd, NULL, NULL, NULL);
359 if (ret != BT_STATUS_SUCCESS) {
361 hal_ipc_unregister(HAL_SERVICE_ID_HIDHOST);
367 static void cleanup(void)
369 struct hal_cmd_unregister_module cmd;
373 if (!interface_ready())
376 cmd.service_id = HAL_SERVICE_ID_HIDHOST;
378 hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
379 sizeof(cmd), &cmd, NULL, NULL, NULL);
381 hal_ipc_unregister(HAL_SERVICE_ID_HIDHOST);
386 static bthh_interface_t hidhost_if = {
387 .size = sizeof(hidhost_if),
389 .connect = hidhost_connect,
390 .disconnect = disconnect,
391 .virtual_unplug = virtual_unplug,
392 .set_info = set_info,
393 .get_protocol = get_protocol,
394 .set_protocol = set_protocol,
395 .get_report = get_report,
396 .set_report = set_report,
397 .send_data = send_data,
401 bthh_interface_t *bt_get_hidhost_interface(void)