static void bt_hid_notify_proto_mode(struct hid_device *dev, uint8_t *buf, int len) { struct hal_ev_hidhost_proto_mode ev; char address[18]; ba2str(&dev->dst, address); DBG("device %s", address); memset(&ev, 0, sizeof(ev)); bdaddr2android(&dev->dst, ev.bdaddr); if (buf[0] == HID_MSG_DATA) { ev.status = HAL_HIDHOST_STATUS_OK; if (buf[1] == HID_PROTO_REPORT) ev.mode = HAL_HIDHOST_REPORT_PROTOCOL; else if (buf[1] == HID_PROTO_BOOT) ev.mode = HAL_HIDHOST_BOOT_PROTOCOL; else ev.mode = HAL_HIDHOST_UNSUPPORTED_PROTOCOL; } else { ev.status = buf[0]; ev.mode = HAL_HIDHOST_UNSUPPORTED_PROTOCOL; } ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_PROTO_MODE, sizeof(ev), &ev); }
static int handle_register_notification_cmd(struct avrcp *session, uint8_t transaction, uint8_t event, uint32_t interval, void *user_data) { struct avrcp_device *dev = user_data; struct hal_ev_avrcp_register_notification ev; DBG(""); /* TODO: Add any missing events supported by Android */ switch (event) { case AVRCP_EVENT_STATUS_CHANGED: case AVRCP_EVENT_TRACK_CHANGED: case AVRCP_EVENT_PLAYBACK_POS_CHANGED: break; default: return -EINVAL; } ev.event = event; ev.param = interval; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_REGISTER_NOTIFICATION, sizeof(ev), &ev); push_request(dev, AVRCP_REGISTER_NOTIFICATION, event, transaction); return -EAGAIN; }
static bool handle_register_notification_rsp(struct avrcp *session, int err, uint8_t code, uint8_t event, uint8_t *params, void *user_data) { struct avrcp_device *dev = user_data; struct hal_ev_avrcp_volume_changed ev; if (err < 0) { error("AVRCP: %s", strerror(-err)); return false; } if (code != AVC_CTYPE_INTERIM && code != AVC_CTYPE_CHANGED) return false; if (event != AVRCP_EVENT_VOLUME_CHANGED) return false; ev.type = code; ev.volume = params[0] & 0x7f; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_VOLUME_CHANGED, sizeof(ev), &ev); if (code == AVC_CTYPE_INTERIM) return true; avrcp_register_notification(dev->session, event, 0); return false; }
static gboolean set_volume_rsp(struct avctp *conn, uint8_t code, uint8_t subunit, uint8_t *operands, size_t operand_count, void *user_data) { struct hal_ev_avrcp_volume_changed ev; uint8_t *params; if (code != AVC_CTYPE_ACCEPTED) { ev.volume = 0; ev.type = code; goto done; } if (operands == NULL || operand_count < 7) return FALSE; params = &operands[7]; ev.volume = params[0] & 0x7F; ev.type = code; done: ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_VOLUME_CHANGED, sizeof(ev), &ev); return FALSE; }
static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state) { struct hal_ev_a2dp_conn_state ev; char address[18]; if (dev->state == state) return; dev->state = state; ba2str(&dev->dst, address); DBG("device %s state %u", address, state); bdaddr2android(&dev->dst, ev.bdaddr); ev.state = state; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_CONN_STATE, sizeof(ev), &ev); if (state != HAL_A2DP_STATE_DISCONNECTED) return; bt_avrcp_disconnect(&dev->dst); a2dp_device_remove(dev); }
static void send_app_reg_notify(struct health_app *app, uint8_t state) { struct hal_ev_health_app_reg_state ev; DBG(""); ev.id = app->id; ev.state = state; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HEALTH, HAL_EV_HEALTH_APP_REG_STATE, sizeof(ev), &ev); }
static int handle_get_play_status_cmd(struct avrcp *session, uint8_t transaction, void *user_data) { struct avrcp_device *dev = user_data; DBG(""); ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_GET_PLAY_STATUS, 0, NULL); push_request(dev, AVRCP_GET_PLAY_STATUS, 0, transaction); return -EAGAIN; }
static bool handle_rewind(struct avrcp *session, bool pressed, void *user_data) { struct hal_ev_avrcp_passthrough_cmd ev; DBG("pressed %s", pressed ? "true" : "false"); ev.id = AVC_REWIND; ev.state = pressed; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_PASSTHROUGH_CMD, sizeof(ev), &ev); return true; }
static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf, int len) { struct hal_ev_hidhost_get_report *ev; int ev_len; char address[18]; ba2str(&dev->dst, address); DBG("device %s", address); ev_len = sizeof(*ev); if (!((buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_INPUT)) || (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_OUTPUT)) || (buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) { ev = g_malloc0(ev_len); ev->status = buf[0]; bdaddr2android(&dev->dst, ev->bdaddr); goto send; } /* * Report porotocol mode reply contains id after hdr, in boot * protocol mode id doesn't exist */ ev_len += (dev->boot_dev) ? (len - 1) : (len - 2); ev = g_malloc0(ev_len); ev->status = HAL_HIDHOST_STATUS_OK; bdaddr2android(&dev->dst, ev->bdaddr); /* * Report porotocol mode reply contains id after hdr, in boot * protocol mode id doesn't exist */ if (dev->boot_dev) { ev->len = len - 1; memcpy(ev->data, buf + 1, ev->len); } else { ev->len = len - 2; memcpy(ev->data, buf + 2, ev->len); } send: ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_GET_REPORT, ev_len, ev); g_free(ev); }
static int avrcp_device_add_session(struct avrcp_device *dev, int fd, uint16_t imtu, uint16_t omtu) { struct hal_ev_avrcp_remote_features ev; char address[18]; dev->session = avrcp_new(fd, imtu, omtu, dev->version); if (!dev->session) return -EINVAL; avrcp_set_destroy_cb(dev->session, disconnect_cb, dev); avrcp_set_passthrough_handlers(dev->session, passthrough_handlers, dev); avrcp_register_player(dev->session, &control_ind, &control_cfm, dev); dev->queue = g_queue_new(); ba2str(&dev->dst, address); /* FIXME: get the real name of the device */ avrcp_init_uinput(dev->session, "bluetooth", address); bdaddr2android(&dev->dst, ev.bdaddr); ev.features = HAL_AVRCP_FEATURE_NONE; DBG("version 0x%02x", dev->version); if (dev->version < 0x0103) goto done; ev.features |= HAL_AVRCP_FEATURE_METADATA; if (dev->version < 0x0104) goto done; ev.features |= HAL_AVRCP_FEATURE_ABSOLUTE_VOLUME; avrcp_get_capabilities(dev->session, CAP_EVENTS_SUPPORTED); done: ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_REMOTE_FEATURES, sizeof(ev), &ev); return 0; }
static void bt_hid_notify_state(struct hid_device *dev, uint8_t state) { struct hal_ev_hidhost_conn_state ev; char address[18]; if (dev->state == state) return; dev->state = state; ba2str(&dev->dst, address); DBG("device %s state %u", address, state); bdaddr2android(&dev->dst, ev.bdaddr); ev.state = state; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_CONN_STATE, sizeof(ev), &ev); }
static void bt_audio_notify_state(struct a2dp_setup *setup, uint8_t state) { struct hal_ev_a2dp_audio_state ev; char address[18]; if (setup->state == state) return; setup->state = state; ba2str(&setup->dev->dst, address); DBG("device %s state %u", address, state); bdaddr2android(&setup->dev->dst, ev.bdaddr); ev.state = state; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_AUDIO_STATE, sizeof(ev), &ev); }
static void bt_hid_set_info(struct hid_device *dev) { struct hal_ev_hidhost_info ev; DBG(""); bdaddr2android(&dev->dst, ev.bdaddr); ev.attr = 0; /* TODO: Check what is this field */ ev.subclass = dev->subclass; ev.app_id = 0; /* TODO: Check what is this field */ ev.vendor = dev->vendor; ev.product = dev->product; ev.version = dev->version; ev.country = dev->country; ev.descr_len = dev->rd_size; memset(ev.descr, 0, sizeof(ev.descr)); memcpy(ev.descr, dev->rd_data, ev.descr_len); ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_INFO, sizeof(ev), &ev); }
static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state, uint8_t status) { struct hal_ev_pan_ctrl_state ev; DBG(""); ev.state = state; ev.local_role = local_role; ev.status = status; memset(ev.name, 0, sizeof(ev.name)); if (local_role == HAL_PAN_ROLE_NAP) memcpy(ev.name, BNEP_BRIDGE, sizeof(BNEP_BRIDGE)); else if (local_role == HAL_PAN_ROLE_PANU) memcpy(ev.name, dev->iface, sizeof(dev->iface)); ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev), &ev); }
static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state) { struct hal_ev_pan_conn_state ev; char addr[18]; if (dev->conn_state == state) return; dev->conn_state = state; ba2str(&dev->dst, addr); DBG("device %s state %u", addr, state); bdaddr2android(&dev->dst, ev.bdaddr); ev.state = state; ev.local_role = local_role; ev.remote_role = dev->role; ev.status = HAL_STATUS_SUCCESS; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev), &ev); if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED) pan_device_remove(dev); }
static void bt_hid_notify_virtual_unplug(struct hid_device *dev, uint8_t *buf, int len) { struct hal_ev_hidhost_virtual_unplug ev; char address[18]; ba2str(&dev->dst, address); DBG("device %s", address); bdaddr2android(&dev->dst, ev.bdaddr); ev.status = HAL_HIDHOST_GENERAL_ERROR; /* Wait either channels to HUP */ if (dev->intr_io && dev->ctrl_io) { g_io_channel_shutdown(dev->intr_io, TRUE, NULL); g_io_channel_shutdown(dev->ctrl_io, TRUE, NULL); bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING); ev.status = HAL_HIDHOST_STATUS_OK; } ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_VIRTUAL_UNPLUG, sizeof(ev), &ev); }
static int handle_get_element_attrs_cmd(struct avrcp *session, uint8_t transaction, uint64_t uid, uint8_t number, uint32_t *attrs, void *user_data) { struct avrcp_device *dev = user_data; uint8_t buf[IPC_MTU]; struct hal_ev_avrcp_get_element_attrs *ev = (void *) buf; int i; DBG(""); ev->number = number; /* Set everything in case of empty list */ if (ev->number == 0) { for (i = 0; i < HAL_AVRCP_MEDIA_ATTR_DURATION; i++) { /* Skip 0x00 as the attributes start with 0x01 */ ev->attrs[i] = i + 1; } ev->number = i; goto done; } for (i = 0; i < number; i++) ev->attrs[i] = attrs[i]; done: ipc_send_notif(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_EV_AVRCP_GET_ELEMENT_ATTRS, sizeof(*ev) + ev->number, ev); push_request(dev, AVRCP_GET_ELEMENT_ATTRIBUTES, 0, transaction); return -EAGAIN; }