/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <netinet/in.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <glib.h>
#include <dbus/dbus.h>
#include "log.h"
#include "../src/manager.h"
#include "../src/adapter.h"
#include "../src/device.h"
#include "device.h"
#include "manager.h"
#include "control.h"
#include "avdtp.h"
#include "glib-helper.h"
#include "btio.h"
#include "sink.h"
#include "source.h"
#include <bluetooth/l2cap.h>
#define AVDTP_PSM 25
#define MAX_SEID 0x3E
#define AVDTP_DISCOVER 0x01
#define AVDTP_GET_CAPABILITIES 0x02
#define AVDTP_SET_CONFIGURATION 0x03
#define AVDTP_GET_CONFIGURATION 0x04
#define AVDTP_RECONFIGURE 0x05
#define AVDTP_OPEN 0x06
#define AVDTP_START 0x07
#define AVDTP_CLOSE 0x08
#define AVDTP_SUSPEND 0x09
#define AVDTP_ABORT 0x0A
#define AVDTP_SECURITY_CONTROL 0x0B
#define AVDTP_GET_ALL_CAPABILITIES 0x0C
#define AVDTP_DELAY_REPORT 0x0D
#define AVDTP_PKT_TYPE_SINGLE 0x00
#define AVDTP_PKT_TYPE_START 0x01
#define AVDTP_PKT_TYPE_CONTINUE 0x02
#define AVDTP_PKT_TYPE_END 0x03
#define AVDTP_MSG_TYPE_COMMAND 0x00
#define AVDTP_MSG_TYPE_GEN_REJECT 0x01
#define AVDTP_MSG_TYPE_ACCEPT 0x02
#define AVDTP_MSG_TYPE_REJECT 0x03
#define REQ_TIMEOUT 4
#define ABORT_TIMEOUT 2
#define DISCONNECT_TIMEOUT 1
#define STREAM_TIMEOUT 20
#if __BYTE_ORDER == __LITTLE_ENDIAN
struct avdtp_common_header {
uint8_t message_type:2;
uint8_t packet_type:2;
uint8_t transaction:4;
} __attribute__ ((packed));
struct avdtp_single_header {
uint8_t message_type:2;
uint8_t packet_type:2;
uint8_t transaction:4;
uint8_t signal_id:6;
uint8_t rfa0:2;
} __attribute__ ((packed));
struct avdtp_start_header {
uint8_t message_type:2;
uint8_t packet_type:2;
uint8_t transaction:4;
uint8_t no_of_packets;
uint8_t signal_id:6;
uint8_t rfa0:2;
} __attribute__ ((packed));
struct avdtp_continue_header {
uint8_t message_type:2;
uint8_t packet_type:2;
uint8_t transaction:4;
} __attribute__ ((packed));
struct seid_info {
uint8_t rfa0:1;
uint8_t inuse:1;
uint8_t seid:6;
uint8_t rfa2:3;
uint8_t type:1;
uint8_t media_type:4;
} __attribute__ ((packed));
struct seid {
uint8_t rfa0:2;
uint8_t seid:6;
} __attribute__ ((packed));
#elif __BYTE_ORDER == __BIG_ENDIAN
struct avdtp_common_header {
uint8_t transaction:4;
uint8_t packet_type:2;
uint8_t message_type:2;
} __attribute__ ((packed));
struct avdtp_single_header {
uint8_t transaction:4;
uint8_t packet_type:2;
uint8_t message_type:2;
uint8_t rfa0:2;
uint8_t signal_id:6;
} __attribute__ ((packed));
struct avdtp_start_header {
uint8_t transaction:4;
uint8_t packet_type:2;
uint8_t message_type:2;
uint8_t no_of_packets;
uint8_t rfa0:2;
uint8_t signal_id:6;
} __attribute__ ((packed));
struct avdtp_continue_header {
uint8_t transaction:4;
uint8_t packet_type:2;
uint8_t message_type:2;
} __attribute__ ((packed));
struct seid_info {
uint8_t seid:6;
uint8_t inuse:1;
uint8_t rfa0:1;
uint8_t media_type:4;
uint8_t type:1;
uint8_t rfa2:3;
} __attribute__ ((packed));
struct seid {
uint8_t seid:6;
uint8_t rfa0:2;
} __attribute__ ((packed));
#else
#error "Unknown byte order"
#endif
/* packets */
struct discover_resp {
struct seid_info seps[0];
} __attribute__ ((packed));
struct getcap_resp {
uint8_t caps[0];
} __attribute__ ((packed));
struct start_req {
struct seid first_seid;
struct seid other_seids[0];
} __attribute__ ((packed));
struct suspend_req {
struct seid first_seid;
struct seid other_seids[0];
} __attribute__ ((packed));
struct seid_rej {
uint8_t error;
} __attribute__ ((packed));
struct conf_rej {
uint8_t category;
uint8_t error;
} __attribute__ ((packed));
#if __BYTE_ORDER == __LITTLE_ENDIAN
struct seid_req {
uint8_t rfa0:2;
uint8_t acp_seid:6;
} __attribute__ ((packed));
struct setconf_req {
uint8_t rfa0:2;
uint8_t acp_seid:6;
uint8_t rfa1:2;
uint8_t int_seid:6;
uint8_t caps[0];
} __attribute__ ((packed));
struct stream_rej {
uint8_t rfa0:2;
uint8_t acp_seid:6;
uint8_t error;
} __attribute__ ((packed));
struct reconf_req {
uint8_t rfa0:2;
uint8_t acp_seid:6;
uint8_t serv_cap;
uint8_t serv_cap_len;
uint8_t caps[0];
} __attribute__ ((packed));
struct delay_req {
uint8_t rfa0:2;
uint8_t acp_seid:6;
uint16_t delay;
} __attribute__ ((packed));
#elif __BYTE_ORDER == __BIG_ENDIAN
struct seid_req {
uint8_t acp_seid:6;
uint8_t rfa0:2;
} __attribute__ ((packed));
struct setconf_req {
uint8_t acp_seid:6;
uint8_t rfa0:2;
uint8_t int_seid:6;
uint8_t rfa1:2;
uint8_t caps[0];
} __attribute__ ((packed));
struct stream_rej {
uint8_t acp_seid:6;
uint8_t rfa0:2;
uint8_t error;
} __attribute__ ((packed));
struct reconf_req {
uint8_t acp_seid:6;
uint8_t rfa0:2;
uint8_t serv_cap;
uint8_t serv_cap_len;
uint8_t caps[0];
} __attribute__ ((packed));
struct delay_req {
uint8_t acp_seid:6;
uint8_t rfa0:2;
uint16_t delay;
} __attribute__ ((packed));
#else
#error "Unknown byte order"
#endif
struct in_buf {
gboolean active;
int no_of_packets;
uint8_t transaction;
uint8_t message_type;
uint8_t signal_id;
uint8_t buf[1024];
uint8_t data_size;
};
struct pending_req {
uint8_t transaction;
uint8_t signal_id;
void *data;
size_t data_size;
struct avdtp_stream *stream; /* Set if the request targeted a stream */
guint timeout;
};
struct avdtp_remote_sep {
uint8_t seid;
uint8_t type;
uint8_t media_type;
struct avdtp_service_capability *codec;
gboolean delay_reporting;
GSList *caps; /* of type struct avdtp_service_capability */
struct avdtp_stream *stream;
};
struct avdtp_server {
bdaddr_t src;
uint16_t version;
GIOChannel *io;
GSList *seps;
GSList *sessions;
};
struct avdtp_local_sep {
avdtp_state_t state;
struct avdtp_stream *stream;
struct seid_info info;
uint8_t codec;
gboolean delay_reporting;
GSList *caps;
struct avdtp_sep_ind *ind;
struct avdtp_sep_cfm *cfm;
void *user_data;
struct avdtp_server *server;
};
struct stream_callback {
avdtp_stream_state_cb cb;
void *user_data;
unsigned int id;
};
struct avdtp_state_callback {
avdtp_session_state_cb cb;
void *user_data;
unsigned int id;
};
struct avdtp_stream {
GIOChannel *io;
uint16_t imtu;
uint16_t omtu;
struct avdtp *session;
struct avdtp_local_sep *lsep;
uint8_t rseid;
GSList *caps;
GSList *callbacks;
struct avdtp_service_capability *codec;
guint io_id; /* Transport GSource ID */
guint timer; /* Waiting for other side to close or open
* the transport channel */
gboolean open_acp; /* If we are in ACT role for Open */
gboolean close_int; /* If we are in INT role for Close */
gboolean abort_int; /* If we are in INT role for Abort */
guint idle_timer;
gboolean delay_reporting;
uint16_t delay; /* AVDTP 1.3 Delay Reporting feature */
};
/* Structure describing an AVDTP connection between two devices */
struct avdtp {
int ref;
int free_lock;
uint16_t version;
struct avdtp_server *server;
bdaddr_t dst;
avdtp_session_state_t state;
/* True if the session should be automatically disco