//
//  bt_spec_avdtp.h
//
//  Bluetooth Protocol Stack - AVDTP(Audio/Video Distribution Transport Protocol) Specification definition
//  Copyright (C) 2017 Toyohiko Togashi tog001@nifty.com
//
//
//  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 3
//  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, see <http://www.gnu.org/licenses/>
//
//
//  Reference:
//      Bluetooth SIG (www.bluetooth.com)
//          Adopted Specifications
//          Protocols
//              AVDTP A/V Distribution Transport 1.3
//
//  Update history
//  ---------- ----- -------------------------------------------
//  2017.03.10 v0.0  First cording
//

#ifndef BT_SPEC_AVDTP_H_
#define BT_SPEC_AVDTP_H_

#include <stdint.h>

union bt_avdtp_signal_PDU_Format {
	uint8_t header;         // TransactionLabel, PacketType, MessageType
	struct {
		uint8_t header;     // TransactionLabel, PacketType, MessageType
		uint8_t body[0];
	}   singlePacket;
	struct {
		uint8_t header;     // TransactionLabel, PacketType, MessageType
		uint8_t NOSP;
		uint8_t bodyStart[0];
	}   startPacket;
	struct {
		uint8_t header;     // TransactionLabel, PacketType, MessageType
		uint8_t bodyContinue[0];
	}   continuePacket;
	struct {
		uint8_t header;     // TransactionLabel, PacketType, MessageType
		uint8_t bodyEnd[0];
	}   endPacket;
} __attribute__ ((packed)) ;

#define AVDTP_HEADER_TransactionLabel_Mask      0b11110000
#define AVDTP_HEADER_PacketType_Mask            0b00001100
#define AVDTP_HEADER_PacketType_SinglePacket    0b00000000
#define AVDTP_HEADER_PacketType_StartPacket     0b00000100
#define AVDTP_HEADER_PacketType_ContinuePacket  0b00001000
#define AVDTP_HEADER_PacketType_EndPacket       0b00001100
#define AVDTP_HEADER_MessageType_Mask           0b00000011
#define AVDTP_HEADER_MessageType_Command        0b00000000
#define AVDTP_HEADER_MessageType_GeneralReject  0b00000001
#define AVDTP_HEADER_MessageType_ResponseAccept 0b00000010
#define AVDTP_HEADER_MessageType_ResponseReject 0b00000011


struct bt_avdtp_serviceCapabilitie {
	uint8_t	serviceCategory;
	uint8_t	LOSC;
	union {
		uint8_t	body[0];
		struct {
			uint8_t	noParam[0];
		}	mediaTransport;
		struct {
			uint8_t	noParam[0];
		}	reporting;
		struct {
			uint8_t	recoveryType;
			uint8_t	MRWS;
			uint8_t	MNMP;
		}	recovery;
		struct {
			uint8_t	mediaType;
			uint8_t	mediaCodecType;
			uint8_t	mediaCodecSpecific[0];
		}	mediaCodec;
		struct {
			uint8_t	CP_TYPE_LSB;
			uint8_t	CP_TYPE_MSB;
			uint8_t	CP_TypeSpecific[0];
		}	contentProtection;
		struct {
			uint8_t	param;		// BackCh, Media, Recovery
		}	headerCompression;
		struct {
			uint8_t	param;		// FRAG
			uint8_t	TSID_media;
			uint8_t	TCID_media;
			uint8_t	TSID_reporting;
			uint8_t	TCID_reporting;
			uint8_t	TSID_recovery;
			uint8_t	TCID_recovery;
		}	multiplexing;
		struct {
			uint8_t	noParam[0];
		} delayReporting;
	};
} __attribute__ ((packed)) ;

#define AVDTP_serviceCapabilitie_HeadSize	2

#define AVDTP_SERVICE_CATEGORY_MediaTransport		0x01
#define AVDTP_SERVICE_CATEGORY_Reporting			0x02
#define AVDTP_SERVICE_CATEGORY_Recovery				0x03
#define AVDTP_SERVICE_CATEGORY_ContentProtection	0x04
#define AVDTP_SERVICE_CATEGORY_HeaderCompression	0x05
#define AVDTP_SERVICE_CATEGORY_Multiplexing			0x06
#define AVDTP_SERVICE_CATEGORY_MediaCodec			0x07
#define AVDTP_SERVICE_CATEGORY_DelayReporting		0x08
#define AVDTP_RECOVERY_TYPE_RFC2733					0x01
#define AVDTP_MediaType_Mask						0xf0
#define AVDTP_MediaType_Audio                       0x00    // Assigned Numbers - Audio/Video
#define AVDTP_MediaType_Video						0x10
#define AVDTP_MediaType_Multimedia					0x20
#define AVDTP_C_TYPE_DTCP                           0x0001
#define AVDTP_C_TYPE_SCMS_T                         0x0002
#define AVDTP_BackCh_Mask							0b10000000	// param
#define AVDTP_BackCh_Available						0b10000000	//
#define AVDTP_BackCh_Not_Available					0b00000000	//
#define AVDTP_Media_Mask							0b01000000	// param
#define AVDTP_Media_Available						0b01000000	//
#define AVDTP_Media_Not_Available					0b00000000	//
#define AVDTP_Recovery_Mask							0b00100000	// param
#define AVDTP_Recovery_Available					0b00100000	//
#define AVDTP_Recovery_Not_Available				0b00000000	//
#define AVDTP_FRAG_Mask								0b10000000	// param
#define AVDTP_FRAG_allow_fragmentation				0b10000000	//
#define AVDTP_FRAG_not_allow_fragmentation			0b00000000	//

struct bt_avdtp_signal {
	uint8_t header;     		// TransactionLabel, PacketType, MessageType
	uint8_t signalIdentifier;   //
	union {
		struct {
			uint8_t	noParam[0];
		}	streamEndPointDiscoveryCommand;
		struct {
			uint8_t	param[0][2];			// [0]:ACP_SEID, InUse   [1]:MediaType, TSEP
		}	streamEndPointDiscoveryResponse;
		struct {
			uint8_t	errorCode;
		}	streamEndPointDiscoveryReject;

		struct {
			uint8_t	param;			// ACP SEID
		}	getCapabilitiesCommand;
		struct {
			struct bt_avdtp_serviceCapabilitie serviceCapabilities[0];
		}	getCapabilitiesResponse;
		struct {
			uint8_t	errorCode;
		}	getCapabilitiesReject;

		struct {
			uint8_t	param;			// ACP SEID
		}	getAllCapabilitiesCommand;
		struct {
			struct bt_avdtp_serviceCapabilitie serviceCapabilities[0];
		}	getAllCapabilitiesResponse;
		struct {
			uint8_t	errorCode;
		}	getAllCapabilitiesReject;

		struct {
			uint8_t	param1;			// ACP SEID
			uint8_t	param2;			// INT SEID
			struct bt_avdtp_serviceCapabilitie serviceCapabilities[0];
		}	setConfigurationCommand;
		struct {
			uint8_t	noParam[0];
		}	setConfigurationResponse;
		struct {
			uint8_t	serviceCategory;
			uint8_t	errorCode;
		}	setConfigurationReject;

		struct {
			uint8_t	param;			// ACP SEID
		}	getConfigurationCommand;
		struct {
			struct bt_avdtp_serviceCapabilitie serviceCapabilities[0];
		}	getConfigurationResponse;
		struct {
			uint8_t	errorCode;
		}	getConfigurationReject;

		struct {
			uint8_t	param;			// ACP SEID
			struct bt_avdtp_serviceCapabilitie serviceCapabilities[0];
		}	reconfigureCommand;
		struct {
			uint8_t	noParam[0];
		}	reconfigureResponse;
		struct {
			uint8_t	serviceCategory;
			uint8_t	errorCode;
		}	reconfigureReject;

		struct {
			uint8_t	param;			// ACP SEID
		}	openStreamCommand;
		struct {
			uint8_t	noParam[0];
		}	openStreamResponse;
		struct {
			uint8_t	errorCode;
		}	openStreamReject;

		struct {
			uint8_t	param[0];		// ACP SEID
		}	startStreamCommand;
		struct {
			uint8_t	noParam[0];
		}	startStreamResponse;
		struct {
			uint8_t	param;			// ACP SEID
			uint8_t	errorCode;
		}	startStreamReject;

		struct {
			uint8_t	param;			// ACP SEID
		}	 closeStreamCommand;
		struct {
			uint8_t	noParam[0];
		}	closeStreamResponse;
		struct {
			uint8_t	errorCode;
		}	closeStreamReject;

		struct {
			uint8_t	param[0];		// ACP SEID
		}	 suspendCommand;
		struct {
			uint8_t	noParam[0];
		}	suspendResponse;
		struct {
			uint8_t	param;			// ACP SEID
			uint8_t	errorCode;
		}	suspendReject;

		struct {
			uint8_t	noParam[0];
		}	 sbortCommand;
		struct {
			uint8_t	noParam[0];
		}	sbortResponse;

		struct {
			uint8_t	param;			// ACP SEID
			uint8_t contentProtectionMethodDependentData[1];
		}	 securityControlCommand;
		struct {
			uint8_t	noParam[0];
			uint8_t contentProtectionMethodDependentData[1];
		}	securityControlResponse;
		struct {
			uint8_t	param;			// ACP SEID
			uint8_t	errorCode;
		}	securityControlReject;

		struct {
			uint8_t	param;			// ACP SEID
			uint8_t Delay_MSB;
			uint8_t Delay_LSB;
		}	 delayReportCommand;
		struct {
			uint8_t	noParam[0];
		}	delayReportResponse;
		struct {
			uint8_t	errorCode;
		}	delayReportReject;

	};
} __attribute__ ((packed)) ;

#define AVDTP_signal_HeadSize	2

#define AVDTP_SignalIdentifier_Mask      0b00111111
#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_DELAYREPORT                0x0D

#define AVDTP_SEID_Mask				0xfc	// 0x01 – 0x3E valid SEID values
#define AVDTP_SEID_Shift			2		//
#define AVDTP_InUse_Mask			0x02	//
#define AVDTP_NotInUse				0x00	//
#define AVDTP_InUse         		0x02	//
#define AVDTP_TSEP_Mask				0x08	//
#define AVDTP_TSEP_isSRC			0x00	//
#define AVDTP_TSEP_isSNK			0x08	//

#define AVDTP_ERROR_CODE_BAD_HEADER_FORMAT			0x01
#define AVDTP_ERROR_CODE_BAD_LENGTH 				0x11	// "All messages" 		The request packet length is not match the assumed length.
#define AVDTP_ERROR_CODE_BAD_ACP_SEID 				0x12 	// "All messages" 		The requested command indicates an invalid ACP SEID (not addressable)
#define AVDTP_ERROR_CODE_SEP_IN_USE 				0x13 	// "Set Configuration" 	The SEP is in use
#define AVDTP_ERROR_CODE_SEP_NOT_IN_USE 			0x14 	// "Reconfigure" 		The SEP is not in use
#define AVDTP_ERROR_CODE_BAD_SERV_CATEGORY 			0x17 	// "Set Configuration, Reconfigure" The value of Service Category in the request packet is not defined in AVDTP.
#define AVDTP_ERROR_CODE_BAD_PAYLOAD_FORMAT 		0x18	// "All messages" 		The requested command has an incorrect payload format (Format errors not specified in this ERROR_CODE)
#define AVDTP_ERROR_CODE_NOT_SUPPORTED_COMMAND 		0x19	// "All messages" 		The requested command is not supported by the device
#define AVDTP_ERROR_CODE_INVALID_CAPABILITIES 		0x1A	// "Reconfigure" 		The reconfigure command is an attempt to reconfigure a transport service capabilities of the SEP. Reconfigure is only permitted for application service capabilities
#define AVDTP_ERROR_CODE_BAD_RECOVERY_TYPE 			0x22	// "Set Configuration" 	The requested Recovery Type is not defined in AVDTP.
#define AVDTP_ERROR_CODE_BAD_MEDIA_TRANSPORT_FORMAT 0x23 	// "Set Configuration" 	The format of Media Transport Capability is not correct.
#define AVDTP_ERROR_CODE_BAD_RECOVERY_FORMAT 		0x25 	// "Set Configuration" 	The format of Recovery Service Capability is not correct.
#define AVDTP_ERROR_CODE_BAD_ROHC_FORMAT 			0x26 	// "Set Configuration" 	The format of Header Compression Service Capability is not correct.
#define AVDTP_ERROR_CODE_BAD_CP_FORMAT 				0x27 	// "Set Configuration" 	The format of Content Protection Service Capability is not correct.
#define AVDTP_ERROR_CODE_BAD_MULTIPLEXING_FORMAT	0x28 	// "Set Configuration" 	The format of Multiplexing Service Capability is not correct.
#define AVDTP_ERROR_CODE_UNSUPPORTED_CONFIGURAION 	0x29 	// "Set Configuration" 	Configuration not supported.
#define AVDTP_ERROR_CODE_BAD_STATE 					0x31 	// "All messages" 		Indicates that the ACP state machine is in an invalid state in order to process the signal. This also includes the situation when an INT receives a request for the same command that it is currently expecting a response for, see 9.11.


struct bt_avdtp_media_packet_PDU_Format {
	uint8_t info1;
	uint8_t info2;
	uint8_t sequenceNumber[2];
	uint8_t timeStamp[4];
	uint8_t SSRC[4];
	uint8_t CSRC[0];
} __attribute__ ((packed)) ;

#define AVDTP_MEDIA_info1_Version_Mask		0b11000000
#define AVDTP_MEDIA_info1_Padding_Mask		0b00100000
#define AVDTP_MEDIA_info1_Extension_Mask	0b00010000
#define AVDTP_MEDIA_info1_CSRCcount_Mask	0b00001111
#define AVDTP_MEDIA_info2_Marker_Mask		0b10000000
#define AVDTP_MEDIA_info2_PayloadType_Mask	0b01111111

enum avdtp_state {
	AVDTP_STATE_IDLE = 0,     // State machine has been initialized
	AVDTP_STATE_CONFIGURED,   // INT has successfully configured an ACP’s stream end-point.
	AVDTP_STATE_OPEN,         // INT and ACP have successfully opened a stream end-point.
	AVDTP_STATE_STREAMING,    // INT and ACP have successfully established a streaming session on a stream end-point.
	AVDTP_STATE_CLOSING,      // INT and ACP are closing a stream end-point.
	AVDTP_STATE_ABORTING      // INT or ACP has requested to abort the stream establishment.
};

#endif // BT_SPEC_AVDTP_H_
