示例#1
0
int a2dp_source_stream_send_media_payload(uint16_t a2dp_cid, uint8_t local_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker){
    avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
    if (!stream_endpoint) {
        log_error("A2DP source: no stream_endpoint with seid %d", local_seid);
        return 0;
    }
    if (a2dp_source_context.avdtp_cid != a2dp_cid){
        log_error("A2DP source: a2dp cid 0x%02x not known, expected 0x%02x", a2dp_cid, a2dp_source_context.avdtp_cid);
        return 0;
    }

    if (stream_endpoint->l2cap_media_cid == 0){
        log_error("A2DP source: no media connection for seid %d", local_seid);
        return 0;
    } 

    int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
    int offset = 0;

    l2cap_reserve_packet_buffer();
    uint8_t * media_packet = l2cap_get_outgoing_buffer();
    //int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
    a2dp_source_setup_media_header(media_packet, size, &offset, marker, stream_endpoint->sequence_number);
    a2dp_source_copy_media_payload(media_packet, size, &offset, storage, num_bytes_to_copy, num_frames);
    stream_endpoint->sequence_number++;
    l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset);
    return size;
}
示例#2
0
static int avdtp_source_stream_send_media_payload(uint8_t local_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker){
    avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
    if (!stream_endpoint) {
        log_error("no stream_endpoint found for seid %d", local_seid);
        return 0;
    }

    if (stream_endpoint->l2cap_media_cid == 0){
        log_error("no media cid found for seid %d", local_seid);
        return 0;
    }        

    int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
    int offset = 0;

    // HACK / PTS requests ERTM although we did not offer it in L2CAP Information Request. Withouth ERTM support, default MTU of 48 will be used, but that's to
    // small for a 44.1kHz/16/8/Stereo/bitpool 53 sbc frame of 119 bytes (+ media info)
    size = 0x290;

    l2cap_reserve_packet_buffer();
    uint8_t * media_packet = l2cap_get_outgoing_buffer();
    //int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
    a2dp_source_setup_media_header(media_packet, size, &offset, marker, stream_endpoint->sequence_number);
    a2dp_source_copy_media_payload(media_packet, size, &offset, storage, num_bytes_to_copy, num_frames);
    stream_endpoint->sequence_number++;
    l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset);
    return size;
}
示例#3
0
int a2dp_max_media_payload_size(uint16_t a2dp_cid, uint8_t local_seid){
    avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
    if (!stream_endpoint) {
        log_error("A2DP source: no stream_endpoint with seid %d", local_seid);
        return 0;
    }
    if (a2dp_source_context.avdtp_cid != a2dp_cid){
        log_error("A2DP source: a2dp cid 0x%02x not known, expected 0x%02x", a2dp_cid, a2dp_source_context.avdtp_cid);
        return 0;
    }

    if (stream_endpoint->l2cap_media_cid == 0){
        log_error("A2DP source: no media connection for seid %d", local_seid);
        return 0;
    }  
    return l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid) - AVDTP_MEDIA_PAYLOAD_HEADER_SIZE;
}
示例#4
0
文件: sdp.c 项目: yourskp/btstack
// we assume that we don't get two requests in a row
static void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
    uint16_t transaction_id;
    SDP_PDU_ID_t pdu_id;
    uint16_t remote_mtu;
    // uint16_t param_len;

    switch (packet_type) {

    case L2CAP_DATA_PACKET:
        pdu_id = (SDP_PDU_ID_t) packet[0];
        transaction_id = READ_NET_16(packet, 1);
        // param_len = READ_NET_16(packet, 3);
        remote_mtu = l2cap_get_remote_mtu_for_local_cid(channel);
        // account for our buffer
        if (remote_mtu > SDP_RESPONSE_BUFFER_SIZE) {
            remote_mtu = SDP_RESPONSE_BUFFER_SIZE;
        }

        // log_info("SDP Request: type %u, transaction id %u, len %u, mtu %u", pdu_id, transaction_id, param_len, remote_mtu);
        switch (pdu_id) {

        case SDP_ServiceSearchRequest:
            sdp_response_size = sdp_handle_service_search_request(packet, remote_mtu);
            break;

        case SDP_ServiceAttributeRequest:
            sdp_response_size = sdp_handle_service_attribute_request(packet, remote_mtu);
            break;

        case SDP_ServiceSearchAttributeRequest:
            sdp_response_size = sdp_handle_service_search_attribute_request(packet, remote_mtu);
            break;

        default:
            sdp_response_size = sdp_create_error_response(transaction_id, 0x0003); // invalid syntax
            break;
        }

        sdp_try_respond();

        break;

    case HCI_EVENT_PACKET:

        switch (packet[0]) {

        case L2CAP_EVENT_INCOMING_CONNECTION:
            if (l2cap_cid) {
                // CONNECTION REJECTED DUE TO LIMITED RESOURCES
                l2cap_decline_connection_internal(channel, 0x04);
                break;
            }
            // accept
            l2cap_cid = channel;
            sdp_response_size = 0;
            l2cap_accept_connection_internal(channel);
            break;

        case L2CAP_EVENT_CHANNEL_OPENED:
            if (packet[2]) {
                // open failed -> reset
                l2cap_cid = 0;
            }
            break;

        case L2CAP_EVENT_CREDITS:
        case DAEMON_EVENT_HCI_PACKET_SENT:
            sdp_try_respond();
            break;

        case L2CAP_EVENT_CHANNEL_CLOSED:
            if (channel == l2cap_cid) {
                // reset
                l2cap_cid = 0;
            }
            break;

        default:
            // other event
            break;
        }
        break;

    default:
        // other packet type
        break;
    }
}