/******************************************************************************* ** ** Function avrc_bld_app_setting_text_rsp ** ** Description This function builds the Get Application Settings Attribute Text ** or Get Application Settings Value Text response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_app_setting_text_rsp (tAVRC_GET_APP_ATTR_TXT_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len, len_left; UINT8 xx; tAVRC_STS sts = AVRC_STS_NO_ERROR; UINT8 num_added = 0; if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR0("avrc_bld_app_setting_text_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ len_left = GKI_get_buf_size(p_pkt) - BT_HDR_SIZE - p_pkt->offset - p_pkt->len; BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if (len_left < (p_rsp->p_attrs[xx].str_len + 4)) { AVRC_TRACE_ERROR3("avrc_bld_app_setting_text_rsp out of room (str_len:%d, left:%d)", xx, p_rsp->p_attrs[xx].str_len, len_left); p_rsp->num_attr = num_added; sts = AVRC_STS_INTERNAL_ERR; break; } if ( !p_rsp->p_attrs[xx].str_len || !p_rsp->p_attrs[xx].p_str ) { AVRC_TRACE_ERROR1("avrc_bld_app_setting_text_rsp NULL attr text[%d]", xx); continue; } UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].charset_id); UINT8_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].p_str, p_rsp->p_attrs[xx].str_len); (*p_count)++; num_added++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return sts; }
/******************************************************************************* ** ** Function avrc_bld_get_elem_attrs_rsp ** ** Description This function builds the Get Element Attributes ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; AVRC_TRACE_API0("avrc_bld_get_elem_attrs_rsp"); if (!p_rsp->p_attrs) { AVRC_TRACE_ERROR0("avrc_bld_get_elem_attrs_rsp NULL parameter"); return AVRC_STS_BAD_PARAM; } /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ BE_STREAM_TO_UINT16(len, p_data); p_count = p_data; if (len == 0) { *p_count = 0; p_data++; } else { p_data = p_start + p_pkt->len; } for (xx=0; xx<p_rsp->num_attr; xx++) { if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR2("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id); continue; } if ( !p_rsp->p_attrs[xx].name.p_str ) { p_rsp->p_attrs[xx].name.str_len = 0; } UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len); ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); (*p_count)++; } len = p_data - p_count; UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function llcp_sdp_add_sdreq ** ** Description Add Service Discovery Request into SNL PDU ** ** ** Returns void ** *******************************************************************************/ static void llcp_sdp_add_sdreq (UINT8 tid, char *p_name) { UINT8 *p; UINT16 name_len = (UINT16) strlen (p_name); p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + llcp_cb.sdp_cb.p_snl->len; UINT8_TO_BE_STREAM (p, LLCP_SDREQ_TYPE); UINT8_TO_BE_STREAM (p, (1 + name_len)); UINT8_TO_BE_STREAM (p, tid); ARRAY_TO_BE_STREAM (p, p_name, name_len); llcp_cb.sdp_cb.p_snl->len += LLCP_SDREQ_MIN_LEN + name_len; }
/******************************************************************************* ** ** Function bta_hl_compose_supported_feature_list ** ** Description This function is called to compose a data sequence from ** the supported feature element list struct pointer ** ** Returns the length of the data sequence ** *******************************************************************************/ int bta_hl_compose_supported_feature_list( UINT8 *p, UINT16 num_elem, const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list) { UINT16 xx, str_len, seq_len; UINT8 *p_head = p; for (xx = 0; xx < num_elem; xx++, p_elem_list++) { UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); seq_len=7; str_len=0; if (p_elem_list->p_mdep_desp) { str_len = strlen(p_elem_list->p_mdep_desp)+1; seq_len += str_len+2; /* todo add a # symbol for 2 */ } *p++ = (UINT8) seq_len; UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); UINT8_TO_BE_STREAM (p, p_elem_list->mdep_id); UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); UINT16_TO_BE_STREAM (p, p_elem_list->data_type); UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); UINT8_TO_BE_STREAM (p, p_elem_list->mdep_role); if (str_len) { UINT8_TO_BE_STREAM (p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); UINT8_TO_BE_STREAM (p, str_len); ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len); } } return(p - p_head); }
/******************************************************************************* ** ** Function avrc_bld_notify_rsp ** ** Description This function builds the Notification response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; UINT8 *p_len; UINT16 len = 0; UINT8 xx; tAVRC_STS status = AVRC_STS_NO_ERROR; AVRC_TRACE_API0("avrc_bld_notify_rsp"); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ p_data += 2; UINT8_TO_BE_STREAM(p_data, p_rsp->event_id); switch (p_rsp->event_id) { case AVRC_EVT_PLAY_STATUS_CHANGE: /* 0x01 */ /* p_rsp->param.play_status >= AVRC_PLAYSTATE_STOPPED is always TRUE */ if ((p_rsp->param.play_status <= AVRC_PLAYSTATE_REV_SEEK) || (p_rsp->param.play_status == AVRC_PLAYSTATE_ERROR) ) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.play_status); len = 2; } else { AVRC_TRACE_ERROR0("bad play state"); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_TRACK_CHANGE: /* 0x02 */ ARRAY_TO_BE_STREAM(p_data, p_rsp->param.track, AVRC_UID_SIZE); len = (UINT8)(AVRC_UID_SIZE + 1); break; case AVRC_EVT_TRACK_REACHED_END: /* 0x03 */ case AVRC_EVT_TRACK_REACHED_START: /* 0x04 */ len = 1; break; case AVRC_EVT_PLAY_POS_CHANGED: /* 0x05 */ UINT32_TO_BE_STREAM(p_data, p_rsp->param.play_pos); len = 5; break; case AVRC_EVT_BATTERY_STATUS_CHANGE: /* 0x06 */ if (AVRC_IS_VALID_BATTERY_STATUS(p_rsp->param.battery_status)) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.battery_status); len = 2; } else { AVRC_TRACE_ERROR0("bad battery status"); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_SYSTEM_STATUS_CHANGE: /* 0x07 */ if (AVRC_IS_VALID_SYSTEM_STATUS(p_rsp->param.system_status)) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.system_status); len = 2; } else { AVRC_TRACE_ERROR0("bad system status"); status = AVRC_STS_BAD_PARAM; } break; case AVRC_EVT_APP_SETTING_CHANGE: /* 0x08 */ if (p_rsp->param.player_setting.num_attr > AVRC_MAX_APP_SETTINGS) p_rsp->param.player_setting.num_attr = AVRC_MAX_APP_SETTINGS; if (p_rsp->param.player_setting.num_attr > 0) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.num_attr); len = 2; for (xx=0; xx<p_rsp->param.player_setting.num_attr; xx++) { if (avrc_is_valid_player_attrib_value(p_rsp->param.player_setting.attr_id[xx], p_rsp->param.player_setting.attr_value[xx])) { UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]); UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]); } else { AVRC_TRACE_ERROR0("bad player app seeting attribute or value"); status = AVRC_STS_BAD_PARAM; break; } len += 2; } } else status = AVRC_STS_BAD_PARAM; break; default: status = AVRC_STS_BAD_PARAM; AVRC_TRACE_ERROR0("unknown event_id"); } UINT16_TO_BE_STREAM(p_len, len); p_pkt->len = (p_data - p_start); return status; }
/******************************************************************************* ** ** Function NDEF_MsgAddWktAc ** ** Description This function adds Alternative Carrier Record. ** ** Returns NDEF_OK if all OK ** *******************************************************************************/ tNDEF_STATUS NDEF_MsgAddWktAc (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, UINT8 cps, char *p_carrier_data_ref_str, UINT8 aux_data_ref_count, char *p_aux_data_ref_str[]) { tNDEF_STATUS status; UINT32 payload_len; UINT8 ref_str_len, xx; UINT8 *p_rec, *p; /* get payload length first */ /* CPS, length of carrier data ref, carrier data ref, Aux data reference count */ payload_len = 3 + (UINT8)strlen (p_carrier_data_ref_str); for (xx = 0; xx < aux_data_ref_count; xx++) { /* Aux Data Reference length (1 byte) */ payload_len += 1 + (UINT8)strlen (p_aux_data_ref_str[xx]); } /* reserve memory for payload */ status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, NDEF_TNF_WKT, ac_rec_type, AC_REC_TYPE_LEN, NULL, 0, NULL, payload_len); if (status == NDEF_OK) { /* get AC record added at the end */ p_rec = NDEF_MsgGetLastRecInMsg (p_msg); /* get start pointer of reserved payload */ p = NDEF_RecGetPayload (p_rec, &payload_len); /* Get a pointer to the payload or NULL (for none) which is valid */ if (p) { /* Add Carrier Power State */ UINT8_TO_BE_STREAM (p, cps); /* Carrier Data Reference length */ ref_str_len = (UINT8)strlen (p_carrier_data_ref_str); UINT8_TO_BE_STREAM (p, ref_str_len); /* Carrier Data Reference */ ARRAY_TO_BE_STREAM (p, p_carrier_data_ref_str, ref_str_len); /* Aux Data Reference Count */ UINT8_TO_BE_STREAM (p, aux_data_ref_count); for (xx = 0; xx < aux_data_ref_count; xx++) { /* Aux Data Reference length (1 byte) */ ref_str_len = (UINT8)strlen (p_aux_data_ref_str[xx]); UINT8_TO_BE_STREAM (p, ref_str_len); /* Aux Data Reference */ ARRAY_TO_BE_STREAM (p, p_aux_data_ref_str[xx], ref_str_len); } } } return (status); }