2 * Copyright (C) 2014 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.
23 #include "hal-utils.h"
27 #include "ipc-common.h"
30 static const btrc_callbacks_t *cbs = NULL;
32 static bool interface_ready(void)
37 static void handle_remote_features(void *buf, uint16_t len, int fd)
39 struct hal_ev_avrcp_remote_features *ev = buf;
41 if (cbs->remote_features_cb)
42 cbs->remote_features_cb((bt_bdaddr_t *) (ev->bdaddr),
46 static void handle_get_play_status(void *buf, uint16_t len, int fd)
48 if (cbs->get_play_status_cb)
49 cbs->get_play_status_cb();
52 static void handle_list_player_attrs(void *buf, uint16_t len, int fd)
54 if (cbs->list_player_app_attr_cb)
55 cbs->list_player_app_attr_cb();
58 static void handle_list_player_values(void *buf, uint16_t len, int fd)
60 struct hal_ev_avrcp_list_player_values *ev = buf;
62 if (cbs->list_player_app_values_cb)
63 cbs->list_player_app_values_cb(ev->attr);
66 static void handle_get_player_values(void *buf, uint16_t len, int fd)
68 struct hal_ev_avrcp_get_player_values *ev = buf;
69 btrc_player_attr_t attrs[4];
72 if (!cbs->get_player_app_value_cb)
75 /* Convert uint8_t array to btrc_player_attr_t array */
76 for (i = 0; i < ev->number; i++)
77 attrs[i] = ev->attrs[i];
79 cbs->get_player_app_value_cb(ev->number, attrs);
82 static void handle_get_player_attrs_text(void *buf, uint16_t len, int fd)
84 struct hal_ev_avrcp_get_player_attrs_text *ev = buf;
85 btrc_player_attr_t attrs[4];
88 if (!cbs->get_player_app_attrs_text_cb)
91 /* Convert uint8_t array to btrc_player_attr_t array */
92 for (i = 0; i < ev->number; i++)
93 attrs[i] = ev->attrs[i];
95 cbs->get_player_app_attrs_text_cb(ev->number, attrs);
98 static void handle_get_player_values_text(void *buf, uint16_t len, int fd)
100 struct hal_ev_avrcp_get_player_values_text *ev = buf;
102 if (cbs->get_player_app_values_text_cb)
103 cbs->get_player_app_values_text_cb(ev->attr, ev->number,
107 static void handle_set_player_value(void *buf, uint16_t len, int fd)
109 struct hal_ev_avrcp_set_player_values *ev = buf;
110 struct hal_avrcp_player_attr_value *attrs;
111 btrc_player_settings_t values;
114 if (!cbs->set_player_app_value_cb)
117 attrs = (struct hal_avrcp_player_attr_value *) ev->attrs;
119 /* Convert to btrc_player_settings_t */
120 values.num_attr = ev->number;
121 for (i = 0; i < ev->number; i++) {
122 values.attr_ids[i] = attrs[i].attr;
123 values.attr_values[i] = attrs[i].value;
126 cbs->set_player_app_value_cb(&values);
129 static void handle_get_element_attrs(void *buf, uint16_t len, int fd)
131 struct hal_ev_avrcp_get_element_attrs *ev = buf;
132 btrc_media_attr_t attrs[BTRC_MAX_APP_SETTINGS];
135 if (!cbs->get_element_attr_cb)
138 /* Convert uint8_t array to btrc_media_attr_t array */
139 for (i = 0; i < ev->number; i++)
140 attrs[i] = ev->attrs[i];
142 cbs->get_element_attr_cb(ev->number, attrs);
145 static void handle_register_notification(void *buf, uint16_t len, int fd)
147 struct hal_ev_avrcp_register_notification *ev = buf;
149 if (cbs->register_notification_cb)
150 cbs->register_notification_cb(ev->event, ev->param);
153 static void handle_volume_changed(void *buf, uint16_t len, int fd)
155 struct hal_ev_avrcp_volume_changed *ev = buf;
157 if (cbs->volume_change_cb)
158 cbs->volume_change_cb(ev->volume, ev->type);
161 static void handle_passthrough_cmd(void *buf, uint16_t len, int fd)
163 struct hal_ev_avrcp_passthrough_cmd *ev = buf;
165 if (cbs->passthrough_cmd_cb)
166 cbs->passthrough_cmd_cb(ev->id, ev->state);
170 * handlers will be called from notification thread context,
171 * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
173 static const struct hal_ipc_handler ev_handlers[] = {
174 /* HAL_EV_AVRCP_REMOTE_FEATURES */
175 { handle_remote_features, false,
176 sizeof(struct hal_ev_avrcp_remote_features) },
177 /* HAL_EV_AVRCP_GET_PLAY_STATUS */
178 { handle_get_play_status, false, 0 },
179 /* HAL_EV_AVRCP_LIST_PLAYER_ATTRS */
180 { handle_list_player_attrs, false, 0 },
181 /* HAL_EV_AVRCP_LIST_PLAYER_VALUES */
182 { handle_list_player_values, false,
183 sizeof(struct hal_ev_avrcp_list_player_values) },
184 /* HAL_EV_AVRCP_GET_PLAYER_VALUES */
185 { handle_get_player_values, true,
186 sizeof(struct hal_ev_avrcp_get_player_values) },
187 /* HAL_EV_AVRCP_GET_PLAYER_ATTRS_TEXT */
188 { handle_get_player_attrs_text, true,
189 sizeof(struct hal_ev_avrcp_get_player_attrs_text) },
190 /* HAL_EV_AVRCP_GET_PLAYER_VALUES_TEXT */
191 { handle_get_player_values_text, true,
192 sizeof(struct hal_ev_avrcp_get_player_values_text) },
193 /* HAL_EV_AVRCP_SET_PLAYER_VALUES */
194 { handle_set_player_value, true,
195 sizeof(struct hal_ev_avrcp_set_player_values) },
196 /* HAL_EV_AVRCP_GET_ELEMENT_ATTRS */
197 { handle_get_element_attrs, true,
198 sizeof(struct hal_ev_avrcp_get_element_attrs) },
199 /* HAL_EV_AVRCP_REGISTER_NOTIFICATION */
200 { handle_register_notification, false,
201 sizeof(struct hal_ev_avrcp_register_notification) },
202 /* HAL_EV_AVRCP_VOLUME_CHANGED */
203 { handle_volume_changed, false,
204 sizeof(struct hal_ev_avrcp_volume_changed) },
205 /* HAL_EV_AVRCP_PASSTHROUGH_CMD */
206 { handle_passthrough_cmd, false,
207 sizeof(struct hal_ev_avrcp_passthrough_cmd) },
210 static bt_status_t init(btrc_callbacks_t *callbacks)
212 struct hal_cmd_register_module cmd;
217 if (interface_ready())
218 return BT_STATUS_DONE;
222 hal_ipc_register(HAL_SERVICE_ID_AVRCP, ev_handlers,
223 sizeof(ev_handlers) / sizeof(ev_handlers[0]));
225 cmd.service_id = HAL_SERVICE_ID_AVRCP;
226 cmd.mode = HAL_MODE_DEFAULT;
229 ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
230 sizeof(cmd), &cmd, NULL, NULL, NULL);
232 if (ret != BT_STATUS_SUCCESS) {
234 hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
240 static bt_status_t get_play_status_rsp(btrc_play_status_t status,
241 uint32_t song_len, uint32_t song_pos)
243 struct hal_cmd_avrcp_get_play_status cmd;
247 if (!interface_ready())
248 return BT_STATUS_NOT_READY;
251 cmd.duration = song_len;
252 cmd.position = song_pos;
254 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAY_STATUS,
255 sizeof(cmd), &cmd, NULL, NULL, NULL);
258 static bt_status_t list_player_app_attr_rsp(int num_attr,
259 btrc_player_attr_t *p_attrs)
262 struct hal_cmd_avrcp_list_player_attrs *cmd = (void *) buf;
267 if (!interface_ready())
268 return BT_STATUS_NOT_READY;
271 return BT_STATUS_PARM_INVALID;
273 len = sizeof(*cmd) + num_attr;
275 return BT_STATUS_PARM_INVALID;
277 cmd->number = num_attr;
278 memcpy(cmd->attrs, p_attrs, num_attr);
280 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
281 HAL_OP_AVRCP_LIST_PLAYER_ATTRS,
282 len, cmd, NULL, NULL, NULL);
285 static bt_status_t list_player_app_value_rsp(int num_val, uint8_t *p_vals)
288 struct hal_cmd_avrcp_list_player_values *cmd = (void *) buf;
293 if (!interface_ready())
294 return BT_STATUS_NOT_READY;
297 return BT_STATUS_PARM_INVALID;
299 len = sizeof(*cmd) + num_val;
302 return BT_STATUS_PARM_INVALID;
304 cmd->number = num_val;
305 memcpy(cmd->values, p_vals, num_val);
307 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
308 HAL_OP_AVRCP_LIST_PLAYER_VALUES,
309 len, cmd, NULL, NULL, NULL);
312 static bt_status_t get_player_app_value_rsp(btrc_player_settings_t *p_vals)
315 struct hal_cmd_avrcp_get_player_attrs *cmd = (void *) buf;
316 size_t len, attrs_len;
321 if (!interface_ready())
322 return BT_STATUS_NOT_READY;
325 return BT_STATUS_PARM_INVALID;
327 attrs_len = p_vals->num_attr *
328 sizeof(struct hal_avrcp_player_attr_value);
329 len = sizeof(*cmd) + attrs_len;
332 return BT_STATUS_PARM_INVALID;
334 cmd->number = p_vals->num_attr;
336 for (i = 0; i < p_vals->num_attr; i++) {
337 cmd->attrs[i].attr = p_vals->attr_ids[i];
338 cmd->attrs[i].value = p_vals->attr_values[i];
341 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
342 HAL_OP_AVRCP_GET_PLAYER_ATTRS,
343 len, cmd, NULL, NULL, NULL);
346 static int write_text(uint8_t *ptr, uint8_t id, uint8_t *text, size_t *len)
348 struct hal_avrcp_player_setting_text *value = (void *) ptr;
349 size_t attr_len = sizeof(*value);
351 if (attr_len + *len > IPC_MTU)
355 value->len = strnlen((const char *) text, BTRC_MAX_ATTR_STR_LEN);
359 if (value->len + *len > IPC_MTU)
360 value->len = IPC_MTU - *len;
362 memcpy(value->text, text, value->len);
366 return attr_len + value->len;
369 static uint8_t write_player_setting_text(uint8_t *ptr, uint8_t num_attr,
370 btrc_player_setting_text_t *p_attrs,
375 for (i = 0; i < num_attr && *len < IPC_MTU; i++) {
378 ret = write_text(ptr, p_attrs[i].id, p_attrs[i].text, len);
388 static bt_status_t get_player_app_attr_text_rsp(int num_attr,
389 btrc_player_setting_text_t *p_attrs)
392 struct hal_cmd_avrcp_get_player_attrs_text *cmd = (void *) buf;
398 if (!interface_ready())
399 return BT_STATUS_NOT_READY;
401 if (num_attr < 0 || num_attr > BTRC_MAX_APP_SETTINGS)
402 return BT_STATUS_PARM_INVALID;
405 ptr = (uint8_t *) &cmd->attrs[0];
406 cmd->number = write_player_setting_text(ptr, num_attr, p_attrs, &len);
408 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
409 HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT,
410 len, cmd, NULL, NULL, NULL);
413 static bt_status_t get_player_app_value_text_rsp(int num_val,
414 btrc_player_setting_text_t *p_vals)
417 struct hal_cmd_avrcp_get_player_values_text *cmd = (void *) buf;
423 if (!interface_ready())
424 return BT_STATUS_NOT_READY;
427 return BT_STATUS_PARM_INVALID;
430 ptr = (uint8_t *) &cmd->values[0];
431 cmd->number = write_player_setting_text(ptr, num_val, p_vals, &len);
433 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
434 HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT,
435 len, cmd, NULL, NULL, NULL);
438 static uint8_t write_element_attr_text(uint8_t *ptr, uint8_t num_attr,
439 btrc_element_attr_val_t *p_attrs,
444 for (i = 0; i < num_attr && *len < IPC_MTU; i++) {
447 ret = write_text(ptr, p_attrs[i].attr_id, p_attrs[i].text, len);
457 static bt_status_t get_element_attr_rsp(uint8_t num_attr,
458 btrc_element_attr_val_t *p_attrs)
461 struct hal_cmd_avrcp_get_element_attrs_text *cmd = (void *) buf;
467 if (!interface_ready())
468 return BT_STATUS_NOT_READY;
471 ptr = (uint8_t *) &cmd->values[0];
472 cmd->number = write_element_attr_text(ptr, num_attr, p_attrs, &len);
474 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
475 HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT,
476 len, cmd, NULL, NULL, NULL);
479 static bt_status_t set_player_app_value_rsp(btrc_status_t rsp_status)
481 struct hal_cmd_avrcp_set_player_attrs_value cmd;
485 if (!interface_ready())
486 return BT_STATUS_NOT_READY;
488 cmd.status = rsp_status;
490 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
491 HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE,
492 sizeof(cmd), &cmd, NULL, NULL, NULL);
495 static bt_status_t play_status_changed_rsp(btrc_notification_type_t type,
496 btrc_play_status_t *play_status)
499 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
502 cmd->event = BTRC_EVT_PLAY_STATUS_CHANGED;
505 memcpy(cmd->data, play_status, cmd->len);
507 len = sizeof(*cmd) + cmd->len;
509 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
510 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
511 len, cmd, NULL, NULL, NULL);
514 static bt_status_t track_change_rsp(btrc_notification_type_t type,
518 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
521 cmd->event = BTRC_EVT_TRACK_CHANGE;
523 cmd->len = sizeof(*track);
524 memcpy(cmd->data, track, cmd->len);
526 len = sizeof(*cmd) + cmd->len;
528 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
529 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
530 len, cmd, NULL, NULL, NULL);
533 static bt_status_t track_reached_end_rsp(btrc_notification_type_t type)
535 struct hal_cmd_avrcp_register_notification cmd;
537 cmd.event = BTRC_EVT_TRACK_REACHED_END;
541 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
542 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
543 sizeof(cmd), &cmd, NULL, NULL, NULL);
546 static bt_status_t track_reached_start_rsp(btrc_notification_type_t type)
548 struct hal_cmd_avrcp_register_notification cmd;
550 cmd.event = BTRC_EVT_TRACK_REACHED_START;
554 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
555 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
556 sizeof(cmd), &cmd, NULL, NULL, NULL);
559 static bt_status_t play_pos_changed_rsp(btrc_notification_type_t type,
563 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
566 cmd->event = BTRC_EVT_PLAY_POS_CHANGED;
568 cmd->len = sizeof(*song_pos);
569 memcpy(cmd->data, song_pos, cmd->len);
571 len = sizeof(*cmd) + cmd->len;
573 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
574 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
575 len, cmd, NULL, NULL, NULL);
578 static bt_status_t settings_changed_rsp(btrc_notification_type_t type,
579 btrc_player_settings_t *player_setting)
582 struct hal_cmd_avrcp_register_notification *cmd = (void *) buf;
583 struct hal_avrcp_player_attr_value *attrs;
584 size_t len, param_len;
587 param_len = player_setting->num_attr * sizeof(*attrs);
588 len = sizeof(*cmd) + param_len;
591 return BT_STATUS_PARM_INVALID;
593 cmd->event = BTRC_EVT_APP_SETTINGS_CHANGED;
595 cmd->len = param_len;
597 attrs = (struct hal_avrcp_player_attr_value *) &cmd->data[0];
598 for (i = 0; i < player_setting->num_attr; i++) {
599 attrs[i].attr = player_setting->attr_ids[i];
600 attrs[i].value = player_setting->attr_values[i];
603 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP,
604 HAL_OP_AVRCP_REGISTER_NOTIFICATION,
605 len, cmd, NULL, NULL, NULL);
608 static bt_status_t register_notification_rsp(btrc_event_id_t event_id,
609 btrc_notification_type_t type,
610 btrc_register_notification_t *p_param)
614 if (!interface_ready())
615 return BT_STATUS_NOT_READY;
618 case BTRC_EVT_PLAY_STATUS_CHANGED:
619 return play_status_changed_rsp(type, &p_param->play_status);
620 case BTRC_EVT_TRACK_CHANGE:
621 return track_change_rsp(type, &p_param->track);
622 case BTRC_EVT_TRACK_REACHED_END:
623 return track_reached_end_rsp(type);
624 case BTRC_EVT_TRACK_REACHED_START:
625 return track_reached_start_rsp(type);
626 case BTRC_EVT_PLAY_POS_CHANGED:
627 return play_pos_changed_rsp(type, &p_param->song_pos);
628 case BTRC_EVT_APP_SETTINGS_CHANGED:
629 return settings_changed_rsp(type, &p_param->player_setting);
631 return BT_STATUS_PARM_INVALID;
635 static bt_status_t set_volume(uint8_t volume)
637 struct hal_cmd_avrcp_set_volume cmd;
641 if (!interface_ready())
642 return BT_STATUS_NOT_READY;
646 return hal_ipc_cmd(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
647 sizeof(cmd), &cmd, NULL, NULL, NULL);
650 static void cleanup(void)
652 struct hal_cmd_unregister_module cmd;
656 if (!interface_ready())
659 cmd.service_id = HAL_SERVICE_ID_AVRCP;
661 hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
662 sizeof(cmd), &cmd, NULL, NULL, NULL);
664 hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
669 static btrc_interface_t iface = {
670 .size = sizeof(iface),
672 .get_play_status_rsp = get_play_status_rsp,
673 .list_player_app_attr_rsp = list_player_app_attr_rsp,
674 .list_player_app_value_rsp = list_player_app_value_rsp,
675 .get_player_app_value_rsp = get_player_app_value_rsp,
676 .get_player_app_attr_text_rsp = get_player_app_attr_text_rsp,
677 .get_player_app_value_text_rsp = get_player_app_value_text_rsp,
678 .get_element_attr_rsp = get_element_attr_rsp,
679 .set_player_app_value_rsp = set_player_app_value_rsp,
680 .register_notification_rsp = register_notification_rsp,
681 .set_volume = set_volume,
685 btrc_interface_t *bt_get_avrcp_interface(void)