/******************************************************************************* ** ** Function NDEF_MsgAddWktErr ** ** Description This function adds Error Record. ** ** Returns NDEF_OK if all OK ** *******************************************************************************/ tNDEF_STATUS NDEF_MsgAddWktErr (UINT8 *p_msg, UINT32 max_size, UINT32 *p_cur_size, UINT8 error_reason, UINT32 error_data ) { tNDEF_STATUS status; UINT8 payload[5], *p; UINT32 payload_len; p = payload; UINT8_TO_BE_STREAM (p, error_reason); if (error_reason == 0x02) { UINT32_TO_BE_STREAM (p, error_data); payload_len = 5; } else { UINT8_TO_BE_STREAM (p, error_data); payload_len = 2; } status = NDEF_MsgAddRec (p_msg, max_size, p_cur_size, NDEF_TNF_WKT, err_rec_type, ERR_REC_TYPE_LEN, NULL, 0, payload, payload_len); return (status); }
/******************************************************************************* ** ** Function avrc_bld_get_play_status_rsp ** ** Description This function builds the Get Play Status ** response. ** ** Returns AVRC_STS_NO_ERROR, if the response is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API0("avrc_bld_get_play_status_rsp"); p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* add fixed lenth - song len(4) + song position(4) + status(1) */ UINT16_TO_BE_STREAM(p_data, 9); UINT32_TO_BE_STREAM(p_data, p_rsp->song_len); UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos); UINT8_TO_BE_STREAM(p_data, p_rsp->play_status); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** 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 avrc_bld_vol_change_notfn ** ** Description This function builds the register notification for volume change. ** ** Returns AVRC_STS_NO_ERROR, if the command is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_vol_change_notfn(BT_HDR * p_pkt) { UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_vol_change"); /* get the existing length, if any, and also the num attributes */ // Set the notify value p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ /* add fixed length 5 -*/ UINT16_TO_BE_STREAM(p_data, 5); UINT8_TO_BE_STREAM(p_data,AVRC_EVT_VOLUME_CHANGE); UINT32_TO_BE_STREAM(p_data, 0); p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** Function avrc_bld_get_element_attr_cmd ** ** Description This function builds the Get Element Attribute command. ** ** Returns AVRC_STS_NO_ERROR, if the command is built successfully ** Otherwise, the error code. ** *******************************************************************************/ static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, BT_HDR *p_pkt) { int i; UINT8 *p_data, *p_start; AVRC_TRACE_API("avrc_bld_get_element_attr_cmd num_attr: %d", p_cmd->num_attr); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ /* add length */ UINT16_TO_BE_STREAM(p_data, 8 + 1 /* id + attr count */ + p_cmd->num_attr * sizeof(UINT32)); /* Identifier 0x0 (PLAYING) */ UINT64_TO_BE_STREAM(p_data, (UINT64)(0)); /* Attribute count */ UINT8_TO_BE_STREAM(p_data, p_cmd->num_attr); for (i=0; i<p_cmd->num_attr; i++){ AVRC_TRACE_API("avrc_bld_get_element_attr_cmd attr_id: %d", p_cmd->attrs[i]); UINT32_TO_BE_STREAM(p_data, p_cmd->attrs[i]); } p_pkt->len = (p_data - p_start); return AVRC_STS_NO_ERROR; }
/******************************************************************************* ** ** 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 pan_register_with_sdp ** ** Description ** ** Returns ** *******************************************************************************/ UINT32 pan_register_with_sdp (UINT16 uuid, UINT8 sec_mask, char *p_name, char *p_desc) { UINT32 sdp_handle; UINT16 browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; UINT16 security = 0; UINT8 availability; UINT32 proto_len = (UINT32)pan_proto_elem_data[1]; /* Create a record */ sdp_handle = SDP_CreateRecord (); if (sdp_handle == 0) { PAN_TRACE_ERROR0 ("PAN_SetRole - could not create SDP record"); return 0; } /* Service Class ID List */ SDP_AddServiceClassIdList (sdp_handle, 1, &uuid); /* Add protocol element sequence from the constant string */ SDP_AddAttribute (sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST, DATA_ELE_SEQ_DESC_TYPE, proto_len, (UINT8 *)(pan_proto_elem_data+2)); // btla-specific ++ #if 0 availability = 0xFF; SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_AVAILABILITY, UINT_DESC_TYPE, 1, &availability); #endif // btla-specific -- /* Language base */ SDP_AddLanguageBaseAttrIDList (sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID); /* Profile descriptor list */ SDP_AddProfileDescriptorList (sdp_handle, uuid, PAN_PROFILE_VERSION); /* Service Name */ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, (UINT8) (strlen(p_name) + 1), (UINT8 *)p_name); /* Service description */ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, (UINT8) (strlen(p_desc) + 1), (UINT8 *)p_desc); /* Security description */ if (sec_mask) { UINT16_TO_BE_FIELD(&security, 0x0001); } SDP_AddAttribute (sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2, (UINT8 *)&security); #if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE) if (uuid == UUID_SERVCLASS_NAP) { UINT16 NetAccessType = 0x0005; /* Ethernet */ UINT32 NetAccessRate = 0x0001312D0; /* 10Mb/sec */ UINT8 array[10], *p; /* Net access type. */ p = array; UINT16_TO_BE_STREAM (p, NetAccessType); SDP_AddAttribute (sdp_handle, ATTR_ID_NET_ACCESS_TYPE, UINT_DESC_TYPE, 2, array); /* Net access rate. */ p = array; UINT32_TO_BE_STREAM (p, NetAccessRate); SDP_AddAttribute (sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4, array); /* Register with Security Manager for the specific security level */ if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_NAP, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_NAP, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU"); } } #endif #if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE) if (uuid == UUID_SERVCLASS_GN) { if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_GN, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_GN, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for GN"); } } #endif #if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE) if (uuid == UUID_SERVCLASS_PANU) { if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU)) || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_PANU, sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU))) { PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU"); } } #endif /* Make the service browsable */ SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_list); return sdp_handle; }
/******************************************************************************* ** ** Function AVDT_SendReport ** ** Description ** ** ** ** Returns ** *******************************************************************************/ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type, tAVDT_REPORT_DATA *p_data) { tAVDT_SCB *p_scb; UINT16 result = AVDT_BAD_PARAMS; BT_HDR *p_pkt; tAVDT_TC_TBL *p_tbl; UINT8 *p, *plen, *pm1, *p_end; #if AVDT_MULTIPLEXING == TRUE UINT8 *p_al = NULL, u; #endif UINT32 ssrc; UINT16 len; /* map handle to scb && verify parameters */ if (((p_scb = avdt_scb_by_hdl(handle)) != NULL) && (p_scb->p_ccb != NULL) && (((type == AVDT_RTCP_PT_SR) && (p_scb->cs.tsep == AVDT_TSEP_SRC)) || ((type == AVDT_RTCP_PT_RR) && (p_scb->cs.tsep == AVDT_TSEP_SNK)) || (type == AVDT_RTCP_PT_SDES)) ) { result = AVDT_NO_RESOURCES; /* build SR - assume fit in one packet */ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb); if ((p_tbl->state == AVDT_AD_ST_OPEN) && (p_pkt = (BT_HDR *)GKI_getbuf(p_tbl->peer_mtu)) != NULL) { p_pkt->offset = L2CAP_MIN_OFFSET; p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; #if AVDT_MULTIPLEXING == TRUE if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) { /* Adaptation Layer header later */ p_al = p; p += 2; } #endif pm1 = p; *p++ = AVDT_MEDIA_OCTET1 | 1; *p++ = type; /* save the location for length */ plen = p; p += 2; ssrc = avdt_scb_gen_ssrc(p_scb); UINT32_TO_BE_STREAM(p, ssrc); switch (type) { case AVDT_RTCP_PT_SR: /* Sender Report */ *pm1 = AVDT_MEDIA_OCTET1; UINT32_TO_BE_STREAM(p, p_data->sr.ntp_sec); UINT32_TO_BE_STREAM(p, p_data->sr.ntp_frac); UINT32_TO_BE_STREAM(p, p_data->sr.rtp_time); UINT32_TO_BE_STREAM(p, p_data->sr.pkt_count); UINT32_TO_BE_STREAM(p, p_data->sr.octet_count); break; case AVDT_RTCP_PT_RR: /* Receiver Report */ *p++ = p_data->rr.frag_lost; AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); p_data->rr.packet_lost &= 0xFFFFFF; AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost); UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd); UINT32_TO_BE_STREAM(p, p_data->rr.jitter); UINT32_TO_BE_STREAM(p, p_data->rr.lsr); UINT32_TO_BE_STREAM(p, p_data->rr.dlsr); break; case AVDT_RTCP_PT_SDES: /* Source Description */ *p++ = AVDT_RTCP_SDES_CNAME; len = strlen((char *)p_data->cname); if (len > AVDT_MAX_CNAME_SIZE) { len = AVDT_MAX_CNAME_SIZE; } *p++ = (UINT8)len; BCM_STRNCPY_S((char *)p, len + 1, (char *)p_data->cname, len + 1); p += len; break; } p_end = p; len = p - pm1 - 1; UINT16_TO_BE_STREAM(plen, len); #if AVDT_MULTIPLEXING == TRUE if (p_scb->curr_cfg.psc_mask & AVDT_PSC_MUX) { /* Adaptation Layer header */ p = p_al; len++; UINT16_TO_BE_STREAM(p_al, len ); /* TSID, no-fragment bit and coding of length(9-bit length field) */ u = *p; *p = (p_scb->curr_cfg.mux_tsid_report << 3) | AVDT_ALH_LCODE_9BITM0; if (u) { *p |= AVDT_ALH_LCODE_9BITM1; } } #endif /* set the actual payload length */ p_pkt->len = p_end - p; /* send the packet */ if (L2CAP_DW_FAILED != avdt_ad_write_req(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb, p_pkt)) { result = AVDT_SUCCESS; } } } return result; }