mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-30 16:20:24 +00:00
Merge branch 'avdtp-source2' into develop
This commit is contained in:
commit
3e3fbf3df6
1289
3rd-party/hxcmod-player/hxcmod.c
vendored
Normal file
1289
3rd-party/hxcmod-player/hxcmod.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
215
3rd-party/hxcmod-player/hxcmod.h
vendored
Normal file
215
3rd-party/hxcmod-player/hxcmod.h
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
|
||||
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
|
||||
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
|
||||
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
|
||||
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//----------------------------------------------------- http://hxc2001.free.fr --//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// File : hxcmod.h
|
||||
// Contains: a tiny mod player
|
||||
//
|
||||
// Written by: Jean François DEL NERO
|
||||
//
|
||||
// Change History (most recent first):
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MODPLAY_DEF
|
||||
#define MODPLAY_DEF
|
||||
|
||||
// Basic type
|
||||
typedef unsigned char muchar;
|
||||
typedef unsigned short muint;
|
||||
typedef short mint;
|
||||
typedef unsigned long mulong;
|
||||
|
||||
#define NUMMAXCHANNELS 32
|
||||
#define MAXNOTES 12*12
|
||||
#define SAMPLE_RATE 44100
|
||||
//
|
||||
// MOD file structures
|
||||
//
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct {
|
||||
muchar name[22];
|
||||
muint length;
|
||||
muchar finetune;
|
||||
muchar volume;
|
||||
muint reppnt;
|
||||
muint replen;
|
||||
} sample;
|
||||
|
||||
typedef struct {
|
||||
muchar sampperiod;
|
||||
muchar period;
|
||||
muchar sampeffect;
|
||||
muchar effect;
|
||||
} note;
|
||||
|
||||
typedef struct {
|
||||
muchar title[20];
|
||||
sample samples[31];
|
||||
muchar length;
|
||||
muchar protracker;
|
||||
muchar patterntable[128];
|
||||
muchar signature[4];
|
||||
muchar speed;
|
||||
} module;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
//
|
||||
// HxCMod Internal structures
|
||||
//
|
||||
typedef struct {
|
||||
char * sampdata;
|
||||
muint sampnum;
|
||||
muint length;
|
||||
muint reppnt;
|
||||
muint replen;
|
||||
mulong samppos;
|
||||
muint period;
|
||||
muchar volume;
|
||||
mulong ticks;
|
||||
muchar effect;
|
||||
muchar parameffect;
|
||||
muint effect_code;
|
||||
|
||||
|
||||
mint decalperiod;
|
||||
mint portaspeed;
|
||||
mint portaperiod;
|
||||
mint vibraperiod;
|
||||
mint Arpperiods[3];
|
||||
muchar ArpIndex;
|
||||
|
||||
mint oldk;
|
||||
muchar volumeslide;
|
||||
|
||||
muchar vibraparam;
|
||||
muchar vibrapointeur;
|
||||
|
||||
muchar finetune;
|
||||
|
||||
muchar cut_param;
|
||||
|
||||
muint patternloopcnt;
|
||||
muint patternloopstartpoint;
|
||||
} channel;
|
||||
|
||||
typedef struct {
|
||||
module song;
|
||||
char * sampledata[31];
|
||||
note * patterndata[128];
|
||||
|
||||
mulong playrate;
|
||||
muint tablepos;
|
||||
muint patternpos;
|
||||
muint patterndelay;
|
||||
muint jump_loop_effect;
|
||||
muchar bpm;
|
||||
mulong patternticks;
|
||||
mulong patterntickse;
|
||||
mulong patternticksaim;
|
||||
mulong sampleticksconst;
|
||||
|
||||
mulong samplenb;
|
||||
|
||||
channel channels[NUMMAXCHANNELS];
|
||||
|
||||
muint number_of_channels;
|
||||
|
||||
muint fullperiod[MAXNOTES * 8];
|
||||
|
||||
muint mod_loaded;
|
||||
|
||||
mint last_r_sample;
|
||||
mint last_l_sample;
|
||||
|
||||
mint stereo;
|
||||
mint stereo_separation;
|
||||
mint bits;
|
||||
mint filter;
|
||||
|
||||
} modcontext;
|
||||
|
||||
//
|
||||
// Player states structures
|
||||
//
|
||||
typedef struct track_state_
|
||||
{
|
||||
unsigned char instrument_number;
|
||||
unsigned short cur_period;
|
||||
unsigned char cur_volume;
|
||||
unsigned short cur_effect;
|
||||
unsigned short cur_parameffect;
|
||||
}track_state;
|
||||
|
||||
typedef struct tracker_state_
|
||||
{
|
||||
int number_of_tracks;
|
||||
int bpm;
|
||||
int speed;
|
||||
int cur_pattern;
|
||||
int cur_pattern_pos;
|
||||
int cur_pattern_table_pos;
|
||||
unsigned int buf_index;
|
||||
track_state tracks[32];
|
||||
}tracker_state;
|
||||
|
||||
typedef struct tracker_state_instrument_
|
||||
{
|
||||
char name[22];
|
||||
int active;
|
||||
}tracker_state_instrument;
|
||||
|
||||
typedef struct tracker_buffer_state_
|
||||
{
|
||||
int nb_max_of_state;
|
||||
int nb_of_state;
|
||||
int cur_rd_index;
|
||||
int sample_step;
|
||||
char name[64];
|
||||
tracker_state_instrument instruments[31];
|
||||
tracker_state * track_state_buf;
|
||||
}tracker_buffer_state;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// HxCMOD Core API:
|
||||
// -------------------------------------------
|
||||
// int hxcmod_init(modcontext * modctx)
|
||||
//
|
||||
// - Initialize the modcontext buffer. Must be called before doing anything else.
|
||||
// Return 1 if success. 0 in case of error.
|
||||
// -------------------------------------------
|
||||
// int hxcmod_load( modcontext * modctx, void * mod_data, int mod_data_size )
|
||||
//
|
||||
// - "Load" a MOD from memory (from "mod_data" with size "mod_data_size").
|
||||
// Return 1 if success. 0 in case of error.
|
||||
// -------------------------------------------
|
||||
// void hxcmod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, tracker_buffer_state * trkbuf )
|
||||
//
|
||||
// - Generate and return the next samples chunk to outbuffer.
|
||||
// nbsample specify the number of stereo 16bits samples you want.
|
||||
// The output format is signed 44100Hz 16-bit Stereo PCM samples.
|
||||
// The output buffer size in byte must be equal to ( nbsample * 2 * 2 ).
|
||||
// The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 is unused.
|
||||
// -------------------------------------------
|
||||
// void hxcmod_unload( modcontext * modctx )
|
||||
// - "Unload" / clear the player status.
|
||||
// -------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int hxcmod_init( modcontext * modctx );
|
||||
int hxcmod_setcfg( modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter);
|
||||
int hxcmod_load( modcontext * modctx, void * mod_data, int mod_data_size );
|
||||
void hxcmod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, tracker_buffer_state * trkbuf );
|
||||
void hxcmod_unload( modcontext * modctx );
|
||||
|
||||
#endif
|
||||
|
3
3rd-party/hxcmod-player/mods/mod.h
vendored
Normal file
3
3rd-party/hxcmod-player/mods/mod.h
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
extern unsigned char mod_data[];
|
||||
extern unsigned int mod_len;
|
||||
extern const char * mod_name;
|
641
3rd-party/hxcmod-player/mods/nao-deceased_by_disease.c
vendored
Normal file
641
3rd-party/hxcmod-player/mods/nao-deceased_by_disease.c
vendored
Normal file
@ -0,0 +1,641 @@
|
||||
#include "mod.h"
|
||||
|
||||
unsigned char mod_data[] = {
|
||||
0x64, 0x65, 0x63, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
|
||||
0x64, 0x69, 0x73, 0x65, 0x61, 0x73, 0x65, 0x00, 0x62, 0x79, 0x20, 0x6e,
|
||||
0x61, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x40, 0x00, 0x08,
|
||||
0x00, 0x40, 0x74, 0x61, 0x6e, 0x78, 0x7a, 0x20, 0x74, 0x6f, 0x20, 0x61,
|
||||
0x73, 0x74, 0x72, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x00,
|
||||
0x02, 0x22, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6c, 0x2d,
|
||||
0x74, 0x72, 0x69, 0x63, 0x6b, 0x20, 0x26, 0x20, 0x64, 0x72, 0x75, 0x6d,
|
||||
0x20, 0x73, 0x6d, 0x70, 0x73, 0x00, 0x00, 0x48, 0x00, 0x40, 0x00, 0x00,
|
||||
0x00, 0x00, 0x69, 0x27, 0x64, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x79,
|
||||
0x6f, 0x75, 0x20, 0x79, 0x6f, 0x75, 0x27, 0x72, 0x65, 0x20, 0x61, 0x00,
|
||||
0x00, 0x08, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6f, 0x6f, 0x6c,
|
||||
0x20, 0x64, 0x75, 0x64, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x79,
|
||||
0x6f, 0x75, 0x20, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x6b, 0x6e, 0x6f, 0x77,
|
||||
0x20, 0x74, 0x68, 0x61, 0x74, 0x21, 0x20, 0x68, 0x65, 0x68, 0x65, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x6f, 0x20, 0x6d,
|
||||
0x79, 0x20, 0x70, 0x61, 0x6c, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x66, 0x72,
|
||||
0x65, 0x65, 0x73, 0x74, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3a, 0x20, 0x77, 0x68, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x66, 0x23, 0x63, 0x6b, 0x20, 0x77, 0x61, 0x73, 0x6e, 0x27, 0x74, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x79, 0x20, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
|
||||
0x65, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6c, 0x69, 0x73, 0x74, 0x3f, 0x21, 0x3f, 0x20, 0x69, 0x74,
|
||||
0x27, 0x73, 0x20, 0x73, 0x70, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x3a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x6c, 0x6c, 0x69, 0x74, 0x65,
|
||||
0x72, 0x61, 0x74, 0x65, 0x20, 0x73, 0x68, 0x69, 0x74, 0x73, 0x21, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x6f, 0x20, 0x6d,
|
||||
0x79, 0x20, 0x70, 0x61, 0x6c, 0x20, 0x6d, 0x69, 0x63, 0x6b, 0x2d, 0x65,
|
||||
0x79, 0x3a, 0x6d, 0x69, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x62, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x77, 0x61, 0x69,
|
||||
0x74, 0x20, 0x75, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x61, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x38, 0x30, 0x30,
|
||||
0x20, 0x64, 0x75, 0x64, 0x6f, 0x21, 0x20, 0x63, 0x79, 0x61, 0x20, 0x6c,
|
||||
0x38, 0x65, 0x72, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x67, 0x72, 0x65, 0x65, 0x74, 0x73, 0x20, 0x66, 0x6c, 0x65,
|
||||
0x63, 0x6b, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x79, 0x20, 0x66,
|
||||
0x61, 0x74, 0x20, 0x61, 0x73, 0x73, 0x20, 0x28, 0x72, 0x61, 0x63, 0x65,
|
||||
0x6b, 0x61, 0x6b, 0x29, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6d, 0x69, 0x71, 0x2c, 0x70, 0x61, 0x74, 0x2c, 0x73, 0x6f,
|
||||
0x62, 0x2c, 0x61, 0x73, 0x74, 0x72, 0x6f, 0x2c, 0x6b, 0x68, 0x64, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x63, 0x6c, 0x61,
|
||||
0x78, 0x6f, 0x6e, 0x28, 0x66, 0x75, 0x6e, 0x6e, 0x79, 0x20, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x29, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x73, 0x79, 0x6e, 0x63, 0x2c, 0x74, 0x63, 0x62, 0x2c, 0x74,
|
||||
0x73, 0x6c, 0x2c, 0x72, 0x65, 0x62, 0x65, 0x6c, 0x73, 0x2c, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x6a, 0x69, 0x6d,
|
||||
0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x6e, 0x75,
|
||||
0x72, 0x73, 0x65, 0x72, 0x79, 0x20, 0x20, 0x73, 0x79, 0x6e, 0x64, 0x69,
|
||||
0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x03, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4d, 0x2e, 0x4b, 0x2e, 0x02, 0x3a, 0x3e, 0x94, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x4c, 0x06, 0x01, 0xac, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x46, 0x05,
|
||||
0x01, 0xfc, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x20, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x93, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x14, 0x00,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x46, 0x05,
|
||||
0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x3f, 0x08, 0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x68, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3,
|
||||
0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3,
|
||||
0x00, 0xb4, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x20, 0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x93, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x14, 0x00, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x46, 0x05,
|
||||
0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x00, 0x00, 0x2c, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x1e, 0xff,
|
||||
0x01, 0xac, 0x2e, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
|
||||
0x00, 0x00, 0x04, 0x81, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x82,
|
||||
0x00, 0x00, 0x0f, 0x08, 0x01, 0xe0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x01, 0xc5, 0x16, 0x0a,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x3a, 0x3e, 0x94, 0x02, 0xd0, 0x46, 0x05, 0x00, 0x00, 0x4c, 0x06,
|
||||
0x01, 0xac, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0xfa, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x03, 0x58, 0x46, 0x05,
|
||||
0x02, 0xfa, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0xac, 0x16, 0x05, 0x03, 0x58, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0xd0, 0x46, 0x05, 0x03, 0x58, 0x0e, 0xd3,
|
||||
0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0xfa, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x00, 0xd6, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x03, 0x58, 0x46, 0x05,
|
||||
0x02, 0xfa, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x80, 0x46, 0x05, 0x03, 0x58, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x20, 0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0xac, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x93, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xd6, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x14, 0x00, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x01, 0xfc, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x3a, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0xd0, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x3f, 0x08,
|
||||
0x01, 0x68, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x68, 0x14, 0x00,
|
||||
0x00, 0x71, 0x20, 0x00, 0x01, 0x7d, 0x46, 0x05, 0x01, 0x68, 0x0e, 0xd3,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xac, 0x46, 0x05,
|
||||
0x01, 0x7d, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0x7d, 0x46, 0x05, 0x01, 0xac, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x94, 0x01, 0xac, 0x46, 0x05, 0x01, 0x7d, 0x0e, 0xd3,
|
||||
0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05,
|
||||
0x01, 0xac, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xac, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x01, 0xe0, 0x46, 0x05, 0x01, 0xac, 0x0e, 0xd3,
|
||||
0x00, 0xb4, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xfc, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x01, 0xe0, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3, 0x00, 0xb4, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3,
|
||||
0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x20,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x00, 0xb4, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x01, 0x68, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x68, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x93,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3, 0x00, 0xb4, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x14, 0x00, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x01, 0xe0, 0x0e, 0xd3, 0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xfc, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xd0, 0x46, 0x05, 0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x80, 0x0e, 0xd3, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0xe0, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x3a, 0x46, 0x05, 0x01, 0xe0, 0x0e, 0xd3,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x80, 0x46, 0x05, 0x01, 0xfc, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x3a, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xd0, 0x46, 0x05,
|
||||
0x02, 0x3a, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x80, 0x46, 0x05, 0x02, 0xd0, 0x0e, 0xd3, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x94, 0x02, 0xd0, 0x46, 0x05, 0x02, 0x80, 0x0e, 0xd3,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x3e, 0x94, 0x03, 0x58, 0x41, 0x0e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x7d, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00,
|
||||
0x02, 0xfa, 0x44, 0x82, 0x00, 0x00, 0x4c, 0x10, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x03, 0x58, 0x01, 0x0e,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x01,
|
||||
0x02, 0xfa, 0x04, 0x82, 0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94,
|
||||
0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0xbe, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, 0x01,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x06, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, 0x01, 0x00, 0xbe, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, 0x10,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0xbe, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x10, 0x01, 0x7d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x10,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x20, 0x01, 0xfc, 0x43, 0x22,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0xbe, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x04, 0x00, 0x01, 0x7d, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x01, 0xfc, 0x03, 0x22,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x93, 0x00, 0x00, 0x06, 0x03,
|
||||
0x00, 0x00, 0x03, 0x22, 0x00, 0xbe, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0x3a, 0x43, 0x22, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x14, 0x00,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x02, 0x3a, 0x03, 0x22, 0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x22, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xa6, 0x43, 0x20,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x03, 0x58, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0xfa, 0x43, 0x20, 0x02, 0xa6, 0x03, 0x20,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x03, 0x58, 0x03, 0x20, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x02, 0xfa, 0x03, 0x20, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0xfa, 0x43, 0x20,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94,
|
||||
0x02, 0xa6, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x3f, 0x08, 0x02, 0x80, 0x43, 0x20, 0x02, 0xfa, 0x03, 0x20,
|
||||
0x01, 0x40, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x00, 0x06, 0x02,
|
||||
0x02, 0xa6, 0x03, 0x20, 0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x01, 0xfc, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x02, 0x80, 0x43, 0x20,
|
||||
0x01, 0xfc, 0x03, 0x20, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x04, 0x00, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0xa6, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x06, 0x01, 0x02, 0xa6, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x02, 0x3a, 0x43, 0x20,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x02, 0x80, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x20, 0x02, 0xfa, 0x43, 0x20, 0x02, 0x3a, 0x03, 0x20,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0xa6, 0x43, 0x20,
|
||||
0x02, 0x80, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0xfa, 0x43, 0x20, 0x02, 0xfa, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x93, 0x02, 0xa6, 0x43, 0x20, 0x02, 0xa6, 0x03, 0x20,
|
||||
0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x02, 0x80, 0x43, 0x20,
|
||||
0x02, 0xfa, 0x03, 0x20, 0x01, 0x1d, 0x14, 0x00, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x02, 0xa6, 0x03, 0x20, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x02, 0x80, 0x03, 0x20,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x01, 0xfc, 0x43, 0x08, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x03, 0x08,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x03, 0x10, 0x01, 0xfc, 0x03, 0x08, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x03, 0x08,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x03, 0x10, 0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x10, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x3e, 0x94,
|
||||
0x03, 0x58, 0x41, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7d, 0x14, 0x00,
|
||||
0x00, 0x71, 0x20, 0x00, 0x02, 0xfa, 0x44, 0x82, 0x00, 0x00, 0x4c, 0x10,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x03, 0x58, 0x01, 0x0e, 0x01, 0x7d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x06, 0x01, 0x02, 0xfa, 0x04, 0x82, 0x01, 0x7d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x94, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0xbe, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x01,
|
||||
0x00, 0x00, 0x06, 0x01, 0x01, 0x7d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x04, 0x00, 0x01, 0x7d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, 0x01,
|
||||
0x00, 0xbe, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x10,
|
||||
0x00, 0x00, 0x06, 0x10, 0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xbe, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x10,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x0c, 0x10, 0x01, 0x7d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x20,
|
||||
0x01, 0xfc, 0x43, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0xbe, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x7d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0xfc, 0x03, 0x22, 0x01, 0x7d, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x93,
|
||||
0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x22, 0x00, 0xbe, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x02, 0x3a, 0x43, 0x22, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x1d, 0x14, 0x00, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x03, 0x22,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x04, 0x00, 0x02, 0x3a, 0x03, 0x22, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x22,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x43, 0x20,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xa6, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x03, 0x58, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x02, 0xfa, 0x43, 0x20,
|
||||
0x02, 0xa6, 0x03, 0x20, 0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x01, 0xfc, 0x43, 0x30, 0x03, 0x58, 0x03, 0x20, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00, 0x02, 0xfa, 0x03, 0x20,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0xfc, 0x03, 0x30, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x03,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0xfa, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2e, 0x94, 0x02, 0xa6, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x3f, 0x08, 0x02, 0x80, 0x43, 0x20,
|
||||
0x02, 0xfa, 0x03, 0x20, 0x01, 0x40, 0x14, 0x00, 0x00, 0x71, 0x20, 0x00,
|
||||
0x00, 0x00, 0x06, 0x02, 0x02, 0xa6, 0x03, 0x20, 0x00, 0x00, 0x06, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x01, 0xac, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x02,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x94,
|
||||
0x01, 0x7d, 0x43, 0x20, 0x01, 0xac, 0x03, 0x20, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x01, 0xfc, 0x43, 0x20,
|
||||
0x01, 0x7d, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xa0, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0xfc, 0x03, 0x20,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x06, 0x01,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0xa0, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x02, 0x3a, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x02, 0x80, 0x43, 0x20, 0x00, 0x00, 0x04, 0x00,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x20, 0x02, 0xfa, 0x43, 0x20,
|
||||
0x02, 0x3a, 0x03, 0x20, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0xa6, 0x43, 0x20, 0x02, 0x80, 0x03, 0x20, 0x01, 0x40, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x02, 0xfa, 0x43, 0x20, 0x02, 0xfa, 0x03, 0x20,
|
||||
0x01, 0x40, 0x16, 0x0a, 0x00, 0x71, 0x2e, 0x93, 0x02, 0xa6, 0x43, 0x20,
|
||||
0x02, 0xa6, 0x03, 0x20, 0x00, 0xa0, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x02, 0x3a, 0x43, 0x20, 0x02, 0xfa, 0x03, 0x20, 0x01, 0x1d, 0x14, 0x00,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00, 0x02, 0xa6, 0x03, 0x20,
|
||||
0x00, 0x00, 0x06, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x02, 0x3a, 0x03, 0x20, 0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a,
|
||||
0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x8f, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00, 0x01, 0xfc, 0x43, 0x08,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10,
|
||||
0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x03, 0x10, 0x01, 0xfc, 0x03, 0x08,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2c, 0x10, 0x00, 0x00, 0x03, 0x10,
|
||||
0x00, 0x00, 0x03, 0x08, 0x01, 0x1d, 0x16, 0x0a, 0x02, 0x3a, 0x30, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x02, 0x3a, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x10,
|
||||
0x01, 0x1d, 0x16, 0x0a, 0x01, 0xac, 0x2c, 0x40, 0x00, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x04, 0x00, 0x01, 0x1d, 0x16, 0x0a, 0x00, 0x71, 0x2b, 0x01,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x8f, 0x16, 0x0a,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x3b, 0xc4, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
|
||||
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xe9, 0xe9, 0xe9, 0xe9,
|
||||
0xe9, 0xe9, 0xe9, 0xe9, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
|
||||
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xc4, 0xc4, 0xc4, 0xc4,
|
||||
0xc4, 0xc4, 0xc4, 0xc4, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0x00, 0x00, 0x66, 0x4e, 0x66, 0x56, 0x48, 0x2a, 0x80, 0x1c, 0xff, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x8d, 0xac, 0xf8, 0x2f, 0x7f, 0x7e, 0x7e, 0x7e,
|
||||
0x7e, 0x7e, 0x5d, 0xbe, 0x72, 0xf6, 0x02, 0x80, 0xda, 0xbb, 0x9f, 0x5a,
|
||||
0x60, 0x3d, 0x2b, 0x3b, 0x2c, 0x1d, 0x0b, 0xc3, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x88, 0x98, 0xc8, 0xd5, 0xcc, 0x1a, 0xc9, 0x0d, 0xe3, 0x00,
|
||||
0x3e, 0x7f, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x67, 0x56,
|
||||
0x07, 0x47, 0x06, 0xda, 0xfb, 0xc8, 0xa9, 0x80, 0x99, 0x80, 0x80, 0x83,
|
||||
0x82, 0x80, 0x80, 0x82, 0x88, 0xaa, 0xb3, 0xc7, 0xf0, 0x2a, 0x43, 0x4e,
|
||||
0x7f, 0x41, 0x7f, 0x22, 0x7f, 0x7e, 0x7e, 0x68, 0x6c, 0x7f, 0x71, 0x11,
|
||||
0x1e, 0x2e, 0x05, 0x21, 0x15, 0x07, 0x24, 0x1e, 0x38, 0x18, 0xfc, 0xdd,
|
||||
0xc6, 0xd2, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa1, 0x80, 0x8a,
|
||||
0xcb, 0xad, 0xda, 0xde, 0xdf, 0x0a, 0x18, 0x19, 0x7e, 0x5b, 0x7f, 0x71,
|
||||
0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x64, 0x61, 0x20, 0x60, 0x13, 0x1d, 0x0e,
|
||||
0xe4, 0xb8, 0xac, 0xb2, 0x80, 0xab, 0x80, 0x85, 0x80, 0x80, 0xae, 0xcd,
|
||||
0xba, 0xfa, 0xc8, 0xce, 0xd3, 0x46, 0xe7, 0x0a, 0xe7, 0xee, 0xfe, 0x10,
|
||||
0xf7, 0x4e, 0x49, 0x5d, 0x68, 0x51, 0x7f, 0x6c, 0x7f, 0x7e, 0x7e, 0x62,
|
||||
0x33, 0x40, 0x4c, 0x12, 0x2a, 0x05, 0x17, 0xeb, 0xf9, 0xc4, 0x80, 0x9f,
|
||||
0xa7, 0x80, 0x80, 0xee, 0x91, 0x9a, 0xa3, 0xd4, 0x83, 0xac, 0xca, 0xdf,
|
||||
0xbc, 0xb2, 0xe3, 0xd9, 0xfc, 0x50, 0x09, 0x54, 0x4e, 0x7f, 0x62, 0x7f,
|
||||
0x62, 0x7f, 0x7e, 0x7e, 0x4c, 0x65, 0x5d, 0x35, 0x2b, 0xff, 0x00, 0xec,
|
||||
0xd1, 0xc3, 0xf1, 0xdf, 0xd1, 0x89, 0xbd, 0xb7, 0x93, 0x8f, 0xe8, 0x80,
|
||||
0xd2, 0xca, 0xb0, 0xe0, 0xc6, 0x07, 0xd0, 0x01, 0x36, 0x28, 0x29, 0x62,
|
||||
0x47, 0x3e, 0x65, 0x3a, 0x04, 0x52, 0x03, 0x3f, 0x34, 0x1f, 0x32, 0x58,
|
||||
0x1b, 0xfd, 0x43, 0x0c, 0x2f, 0x09, 0xfe, 0x1d, 0xea, 0xfd, 0x07, 0xb2,
|
||||
0x2d, 0xad, 0xb3, 0xa2, 0xc5, 0xa5, 0xab, 0xa5, 0xb2, 0x8d, 0xbf, 0x91,
|
||||
0xc1, 0xcb, 0xc1, 0xeb, 0xe4, 0x0f, 0x21, 0x19, 0x74, 0x17, 0x4f, 0x35,
|
||||
0x47, 0x7f, 0x3a, 0x67, 0x75, 0x76, 0x3d, 0x57, 0x4f, 0x36, 0x31, 0xfb,
|
||||
0x00, 0xdb, 0xee, 0xd1, 0xf5, 0xda, 0xac, 0xdc, 0xba, 0xb7, 0xe6, 0xba,
|
||||
0xc6, 0xa6, 0xcf, 0xd3, 0xe2, 0xd0, 0xce, 0xce, 0x07, 0xbb, 0xeb, 0x00,
|
||||
0x07, 0x14, 0x1d, 0x0e, 0x26, 0x17, 0x2a, 0x22, 0x60, 0x36, 0x71, 0x68,
|
||||
0x4f, 0x30, 0x55, 0x15, 0x2a, 0x52, 0x25, 0x1a, 0x25, 0x04, 0x09, 0xc2,
|
||||
0xee, 0xc2, 0xd5, 0xea, 0xe4, 0xb4, 0xeb, 0xc2, 0xc3, 0xca, 0xa5, 0xd4,
|
||||
0x9c, 0xd7, 0xe2, 0xb6, 0x05, 0xc7, 0xda, 0xdb, 0x0d, 0xe5, 0x20, 0x23,
|
||||
0x5b, 0x26, 0x58, 0x3f, 0x4e, 0x47, 0x41, 0x59, 0x49, 0x5c, 0x52, 0x1f,
|
||||
0x61, 0x28, 0x1c, 0x0e, 0xf7, 0xed, 0xe8, 0xd8, 0xf2, 0xaf, 0xf4, 0xc3,
|
||||
0xc5, 0xbe, 0xc9, 0xc2, 0xbe, 0xb5, 0xc7, 0xbe, 0xce, 0xeb, 0xea, 0x09,
|
||||
0xdf, 0x02, 0x12, 0x07, 0xf7, 0x24, 0x01, 0x08, 0x28, 0x18, 0x3e, 0x49,
|
||||
0x44, 0x63, 0x41, 0x2c, 0x46, 0x1f, 0x56, 0x14, 0x18, 0x0f, 0xf6, 0x06,
|
||||
0xdf, 0x00, 0xd0, 0xbd, 0xeb, 0x04, 0xd5, 0xee, 0xe6, 0xdc, 0xd9, 0xbc,
|
||||
0xdd, 0xbe, 0xfc, 0xb7, 0xe7, 0xd6, 0xd6, 0xd9, 0xff, 0xfd, 0xce, 0xff,
|
||||
0xec, 0x02, 0x1d, 0x22, 0x20, 0x20, 0x45, 0x49, 0x60, 0x3f, 0x41, 0x4b,
|
||||
0x34, 0x1a, 0x2f, 0x2a, 0x18, 0xfb, 0x13, 0xf2, 0xdf, 0xd0, 0xe3, 0xdb,
|
||||
0xdb, 0x06, 0x17, 0xf1, 0xed, 0xee, 0xdd, 0xde, 0xed, 0xdb, 0xd7, 0xe7,
|
||||
0xb9, 0x11, 0xdb, 0xe7, 0x0a, 0xe7, 0xe9, 0xd4, 0x06, 0x0c, 0x29, 0xfb,
|
||||
0x1f, 0x0b, 0x33, 0x20, 0xfe, 0x2e, 0x2b, 0x14, 0x16, 0x2a, 0x2c, 0x28,
|
||||
0x3a, 0x1d, 0x1b, 0x24, 0x03, 0x31, 0xe1, 0x06, 0xcd, 0xfd, 0xd1, 0xd5,
|
||||
0xf5, 0xda, 0xe5, 0xc8, 0xcc, 0xd1, 0xee, 0xc7, 0xe7, 0xda, 0xcf, 0xf6,
|
||||
0xcf, 0xfb, 0xe8, 0x26, 0xec, 0x0f, 0xf8, 0x1a, 0x24, 0x37, 0x10, 0x18,
|
||||
0x25, 0x19, 0x20, 0x39, 0x0b, 0x19, 0x1b, 0x1c, 0x10, 0x17, 0x07, 0x21,
|
||||
0x12, 0x03, 0x21, 0xf3, 0x16, 0xec, 0xf5, 0xe6, 0xe8, 0xd6, 0xca, 0xe4,
|
||||
0xf2, 0xd5, 0xe7, 0xef, 0xf9, 0xd3, 0xf9, 0xe3, 0xe8, 0xf0, 0xe5, 0xd7,
|
||||
0xfd, 0x08, 0xf3, 0x14, 0x0b, 0x0d, 0x19, 0x22, 0x0e, 0x07, 0x11, 0x1f,
|
||||
0x12, 0x34, 0x05, 0x2b, 0x11, 0x2c, 0x26, 0x1f, 0x1a, 0x1a, 0x20, 0xf9,
|
||||
0x16, 0xe4, 0xec, 0xe9, 0xdf, 0xe0, 0xed, 0xeb, 0xc5, 0xcc, 0xd3, 0xdd,
|
||||
0xdb, 0xf0, 0x03, 0xf8, 0xdd, 0xee, 0x10, 0xfd, 0x02, 0xf6, 0xff, 0xf3,
|
||||
0x1a, 0x20, 0x05, 0x20, 0x21, 0x1f, 0x1a, 0x13, 0xfd, 0x15, 0x01, 0x13,
|
||||
0x0e, 0xeb, 0x0e, 0x0c, 0x0c, 0x21, 0xed, 0x23, 0xfc, 0x00, 0xe5, 0xe7,
|
||||
0xee, 0xdc, 0xe6, 0xe3, 0xe8, 0xfd, 0xf9, 0x0d, 0x0a, 0x07, 0x0f, 0x07,
|
||||
0xfe, 0x12, 0xe5, 0xf0, 0xef, 0xed, 0xe2, 0xe5, 0xea, 0xe7, 0xf3, 0xfe,
|
||||
0x0c, 0x0b, 0x11, 0x18, 0x21, 0x20, 0x20, 0x0b, 0x1b, 0x19, 0x19, 0x0d,
|
||||
0x0d, 0xf8, 0x01, 0x0b, 0x0a, 0x0c, 0x0a, 0xff, 0x04, 0x0c, 0xec, 0xef,
|
||||
0xfb, 0xdb, 0xe7, 0xd6, 0xd3, 0xf3, 0xd9, 0xf9, 0xdb, 0xe8, 0xf6, 0xf3,
|
||||
0xf3, 0x11, 0xf5, 0x0e, 0xff, 0x10, 0x03, 0x19, 0x0e, 0x21, 0x0f, 0x1e,
|
||||
0x12, 0x20, 0x13, 0x1b, 0x15, 0xf5, 0xfd, 0x04, 0xfe, 0xf7, 0xf1, 0xff,
|
||||
0xed, 0xff, 0x10, 0xf7, 0x02, 0x16, 0xf1, 0x03, 0x03, 0xf7, 0x05, 0x06,
|
||||
0x07, 0x06, 0xed, 0xf7, 0x00, 0x05, 0x13, 0xfb, 0x01, 0x10, 0xea, 0xfd,
|
||||
0xf8, 0xe4, 0xef, 0xe6, 0xef, 0xf6, 0x11, 0x00, 0x00, 0x02, 0x00, 0x06,
|
||||
0x10, 0xfd, 0x0a, 0x0d, 0x00, 0xeb, 0x09, 0x03, 0x09, 0x14, 0x12, 0x05,
|
||||
0xfc, 0x0e, 0x16, 0x1a, 0x18, 0x01, 0x17, 0xfe, 0xf2, 0xf5, 0xea, 0xe7,
|
||||
0xdb, 0xea, 0xea, 0xf7, 0xf0, 0xf9, 0xf9, 0x01, 0x01, 0x0b, 0xf9, 0x07,
|
||||
0xfd, 0xfd, 0x07, 0xf9, 0xfb, 0x02, 0x12, 0x04, 0x04, 0x19, 0x10, 0x09,
|
||||
0x1a, 0x0b, 0xf8, 0x12, 0x03, 0xec, 0x1a, 0xee, 0xfa, 0x13, 0x07, 0x0e,
|
||||
0x05, 0x05, 0x14, 0xf6, 0xfd, 0xf8, 0xdf, 0xf8, 0xf3, 0xe4, 0xfe, 0xfa,
|
||||
0x02, 0x13, 0xf9, 0x0c, 0xf9, 0x10, 0xf7, 0x0d, 0x03, 0x03, 0xf3, 0x03,
|
||||
0x00, 0xeb, 0x03, 0xe3, 0xe5, 0xed, 0xed, 0x0d, 0x07, 0x08, 0x23, 0x21,
|
||||
0x0b, 0x0a, 0x1b, 0x0b, 0x10, 0x03, 0x0b, 0x0a, 0xef, 0xf6, 0x06, 0xfc,
|
||||
0xec, 0xe2, 0x00, 0xf9, 0x09, 0x00, 0x06, 0xf9, 0xf9, 0xf9, 0x01, 0xfa,
|
||||
0x01, 0x05, 0xfa, 0x06, 0x05, 0x10, 0x10, 0x06, 0x06, 0x01, 0x01, 0x06,
|
||||
0x00, 0x0d, 0x10, 0x02, 0xfc, 0xff, 0x05, 0xfe, 0x03, 0xf2, 0xf8, 0xee,
|
||||
0x00, 0xe7, 0x00, 0xf1, 0xf4, 0xf7, 0xf5, 0xfa, 0x01, 0x0f, 0x0a, 0x11,
|
||||
0x0b, 0x0e, 0x0d, 0x13, 0x14, 0x0a, 0x0a, 0x0a, 0x00, 0x07, 0xfc, 0x03,
|
||||
0x00, 0xff, 0xf5, 0xf6, 0xff, 0xf8, 0xfa, 0xfd, 0xef, 0xf6, 0xf7, 0xf8,
|
||||
0xf5, 0xf6, 0x01, 0xf9, 0xfc, 0xf4, 0x03, 0xfe, 0x01, 0x00, 0x02, 0xfc,
|
||||
0xfd, 0x07, 0x0a, 0x02, 0x05, 0x06, 0x09, 0x10, 0x05, 0x0b, 0x14, 0x03,
|
||||
0x06, 0x06, 0x06, 0x09, 0x05, 0xfe, 0xfe, 0xfd, 0xf6, 0xf8, 0xf9, 0xf9,
|
||||
0xfa, 0xfb, 0xfb, 0xfd, 0x01, 0xfa, 0x00, 0x00, 0xf9, 0xfa, 0xfe, 0xff,
|
||||
0xfe, 0xfe, 0x01, 0xff, 0xfe, 0x00, 0x01, 0x00, 0x01, 0x05, 0x00, 0x04,
|
||||
0x08, 0x03, 0x09, 0x03, 0x06, 0x01, 0x09, 0x07, 0x07, 0x03, 0x02, 0xfe,
|
||||
0xff, 0xfe, 0xfe, 0xf9, 0xfa, 0xfa, 0xfd, 0xfb, 0xfc, 0xfd, 0xff, 0xfd,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x15, 0x37, 0x2a, 0x15, 0x16, 0xfa, 0xd6, 0xd6, 0xd8, 0xbc,
|
||||
0xa3, 0x91, 0x85, 0x82, 0x82, 0x84, 0x88, 0x94, 0xaa, 0xc3, 0xe0, 0xfc,
|
||||
0x14, 0x2e, 0x49, 0x5e, 0x6c, 0x74, 0x78, 0x74, 0x6c, 0x62, 0x56, 0x45,
|
||||
0x2e, 0x14, 0xfc, 0xe4, 0xc9, 0xae, 0x93, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8d, 0x9e, 0xb4, 0xc9, 0xdf, 0xf3,
|
||||
0x06, 0x19, 0x2e, 0x45, 0x5b, 0x70, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7c, 0x73, 0x69, 0x5a, 0x48, 0x33, 0x1f, 0x0a, 0xf6, 0xe1, 0xcd,
|
||||
0xb7, 0xa2, 0x8c, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x85, 0x94, 0xa3, 0xae, 0xba, 0xc6, 0xd0, 0xdb, 0xe8, 0xf7,
|
||||
0x02, 0x0c, 0x18, 0x25, 0x32, 0x3e, 0x46, 0x4a, 0x4c, 0x4f, 0x50, 0x4f,
|
||||
0x4e, 0x49, 0x43, 0x3c, 0x36, 0x30, 0x28, 0x21, 0x1a, 0x13, 0x0c, 0x04,
|
||||
0xff, 0xfa, 0xf6, 0xf2, 0xf1, 0xf1, 0xf0, 0xf1, 0xf3, 0xf6, 0xf8, 0x00,
|
||||
0x00, 0xff, 0x99, 0x4e, 0x66, 0x56, 0x48, 0x2a, 0x80, 0x1c, 0xff, 0x80,
|
||||
0x80, 0x80, 0x80, 0x00
|
||||
};
|
||||
|
||||
unsigned int mod_len = 7600;
|
||||
const char * mod_name = "nao-deceased by disease";
|
BIN
3rd-party/hxcmod-player/mods/nao-deceased_by_disease.mod
vendored
Normal file
BIN
3rd-party/hxcmod-player/mods/nao-deceased_by_disease.mod
vendored
Normal file
Binary file not shown.
119
3rd-party/hxcmod-player/readme.txt
vendored
Normal file
119
3rd-party/hxcmod-player/readme.txt
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
Local copy used for A2DP Source demo in BTstack.
|
||||
|
||||
Github repository: https://github.com/jfdelnero/HxCModPlayer
|
||||
Thanks for providing this nice and compact implementation!
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
Original readme.txt
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
|
||||
//----------H----H----X-X-----C--------------2---0----0---0----0---1-1-----------//
|
||||
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
|
||||
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
|
||||
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
|
||||
//-------------------------------------------------------------------------------//
|
||||
//----------------------------------------------------- http://hxc2001.free.fr --//
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HxCMOD player
|
||||
|
||||
The HxCMOD player is a tiny music module player.
|
||||
|
||||
It currently supports the Noisetracker/Soundtracker/Protracker Module Format (*.mod)
|
||||
|
||||
The core (hxcmod.c/hxcmod.h) is designed to have the least external dependency.
|
||||
So it should be usable on almost all OS and systems.
|
||||
You can use the hxcmod.c / hxcmod.h files to add a mod replay support
|
||||
to a demo/game/software.
|
||||
|
||||
You are free to do what you want with this code.
|
||||
(A credit is always appreciated if you include it into your prod ;) )
|
||||
|
||||
The test program is into the win32 folder. Just drag and drop a mod on the main
|
||||
window to load it. Linux & Mac OS X version it planned.
|
||||
|
||||
Please note that this core was "Emscriptened" successfully and is now working in
|
||||
JavaScript with Android, Chrome, Firefox, Edge, Safari browsers and probably
|
||||
with others browsers supporting the Web Audio API support.
|
||||
|
||||
You can test it at this address : http://hxc2001.free.fr/hxcmod/
|
||||
|
||||
A video demo of the native Mod player can be seen on youtube :
|
||||
https://www.youtube.com/watch?v=MEU9FGZzjac
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
HxCMOD Core API
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
int hxcmod_init( modcontext * modctx )
|
||||
|
||||
- Initialize the modcontext buffer. Must be called before doing anything else.
|
||||
Return 1 if success. 0 in case of error.
|
||||
|
||||
int hxcmod_setcfg( modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter);
|
||||
|
||||
- Configure the player :
|
||||
samplerate specify the sample rate. (44100 by default).
|
||||
bits specify the number of bits (16 bits only for the moment).
|
||||
stereo - if non null, the stereo mode is selected (default)
|
||||
stereo_separation - Left/Right channel separation.
|
||||
filter - if non null, the filter is applied (default)
|
||||
|
||||
int hxcmod_load( modcontext * modctx, void * mod_data, int mod_data_size )
|
||||
|
||||
- "Load" a MOD from memory (from "mod_data" with size "mod_data_size").
|
||||
Return 1 if success. 0 in case of error.
|
||||
|
||||
|
||||
void hxcmod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, tracker_buffer_state * trkbuf )
|
||||
|
||||
- Generate and return the next samples chunk to outbuffer.
|
||||
nbsample specify the number of stereo 16bits samples you want.
|
||||
The output format is signed 44100Hz 16-bit Stereo PCM samples.
|
||||
The output buffer size in byte must be equal to ( nbsample * 2 * 2 ).
|
||||
The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 if unused.
|
||||
|
||||
|
||||
void hxcmod_unload( modcontext * modctx )
|
||||
- "Unload" / clear the player status.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
Files on the repository
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
- hxcmod.c / hxcmod.h
|
||||
The HxC core mod replay routines. These files don't have any dependency with others files
|
||||
and can be used into other project.
|
||||
|
||||
- framegenerator.c / framegenerator.h
|
||||
Generate a 640*480 framebuffer from the player status to be displayed in real-time.
|
||||
(not needed by the core)
|
||||
|
||||
- win32/
|
||||
The Windows test software.
|
||||
(linux & Mac version planned)
|
||||
|
||||
- js_emscripten/
|
||||
The Web browser/JavaScript version. (Build with Emscripten)
|
||||
|
||||
- packer/
|
||||
Data compression utility. Used to embed one mod and some graphical stuff into the executable.
|
||||
Not directly used by the core.
|
||||
|
||||
- data/
|
||||
Some packed data files.
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
Jean-François DEL NERO (Jeff) / HxC2001
|
||||
|
||||
Email : jeanfrancoisdelnero <> free.fr
|
||||
|
||||
http://hxc2001.free.fr
|
||||
|
||||
11 July 2015
|
@ -962,6 +962,7 @@ typedef uint8_t sm_key_t[16];
|
||||
#define HCI_EVENT_GOEP_META 0xED
|
||||
#define HCI_EVENT_PBAP_META 0xEE
|
||||
#define HCI_EVENT_HID_META 0xEF
|
||||
#define HCI_EVENT_A2DP_META 0xF0
|
||||
|
||||
// Potential other meta groups
|
||||
// #define HCI_EVENT_BNEP_META 0xxx
|
||||
@ -1258,26 +1259,29 @@ typedef uint8_t sm_key_t[16];
|
||||
/** AVDTP Subevent */
|
||||
|
||||
/**
|
||||
* @format 1H11
|
||||
* @format 1H111
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param signal_identifier
|
||||
* @param status 0 == OK
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_SIGNALING_ACCEPT 0x01
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @format 1H11
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param signal_identifier
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_SIGNALING_REJECT 0x02
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @format 1H11
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param signal_identifier
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT 0x03
|
||||
@ -1285,7 +1289,7 @@ typedef uint8_t sm_key_t[16];
|
||||
/**
|
||||
* @format 1HB1
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param bd_addr
|
||||
* @param status 0 == OK
|
||||
*/
|
||||
@ -1294,14 +1298,14 @@ typedef uint8_t sm_key_t[16];
|
||||
/**
|
||||
* @format 1H
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED 0x05
|
||||
|
||||
/**
|
||||
* @format 1H1111
|
||||
* @param subevent_code
|
||||
* @param handle
|
||||
* @param avdtp_cid
|
||||
* @param seid 0x01 – 0x3E
|
||||
* @param in_use 0-not in use, 1-in use
|
||||
* @param media_type 0-audio, 1-video, 2-multimedia
|
||||
@ -1310,9 +1314,11 @@ typedef uint8_t sm_key_t[16];
|
||||
#define AVDTP_SUBEVENT_SIGNALING_SEP_FOUND 0x06
|
||||
|
||||
/**
|
||||
* @format 1H11111111
|
||||
* @format 1H1111111111
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param acp_seid
|
||||
* @param media_type
|
||||
* @param sampling_frequency_bitmap
|
||||
* @param channel_mode_bitmap
|
||||
@ -1325,9 +1331,11 @@ typedef uint8_t sm_key_t[16];
|
||||
#define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY 0x07
|
||||
|
||||
/**
|
||||
* @format 1H12LV
|
||||
* @format 1H1112LV
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param acp_seid
|
||||
* @param media_type
|
||||
* @param media_codec_type
|
||||
* @param media_codec_information_len
|
||||
@ -1336,9 +1344,11 @@ typedef uint8_t sm_key_t[16];
|
||||
#define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY 0x08
|
||||
|
||||
/**
|
||||
* @format 1H1121111111
|
||||
* @format 1H111121111111
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param acp_seid
|
||||
* @param reconfigure
|
||||
* @param media_type
|
||||
* @param sampling_frequency
|
||||
@ -1353,9 +1363,11 @@ typedef uint8_t sm_key_t[16];
|
||||
#define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION 0x09
|
||||
|
||||
/**
|
||||
* @format 1H112LV
|
||||
* @format 1H11112LV
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param acp_seid
|
||||
* @param reconfigure
|
||||
* @param media_type
|
||||
* @param media_codec_type
|
||||
@ -1365,9 +1377,11 @@ typedef uint8_t sm_key_t[16];
|
||||
#define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x0A
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @format 1H111
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param acp_seid
|
||||
* @param status 0 == OK
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED 0x0B
|
||||
@ -1375,12 +1389,64 @@ typedef uint8_t sm_key_t[16];
|
||||
/**
|
||||
* @format 1H
|
||||
* @param subevent_code
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED 0x0C
|
||||
|
||||
/**
|
||||
* @format 1H12
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param sequence_number
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x0D
|
||||
|
||||
|
||||
/** A2DP Subevent */
|
||||
|
||||
/**
|
||||
* @format 1H111
|
||||
* @param subevent_code
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
* @param remote_seid
|
||||
* @param status
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x01
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_START_ACCEPTED 0x02
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x03
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x04
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_RELEASED 0x05
|
||||
|
||||
/** AVRCP Subevent */
|
||||
|
||||
/**
|
||||
|
@ -85,6 +85,14 @@ static inline uint8_t hci_event_ancs_meta_get_subevent_code(const uint8_t * even
|
||||
static inline uint8_t hci_event_avdtp_meta_get_subevent_code(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/***
|
||||
* @brief Get subevent code for a2dp event
|
||||
* @param event packet
|
||||
* @return subevent_code
|
||||
*/
|
||||
static inline uint8_t hci_event_a2dp_meta_get_subevent_code(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/***
|
||||
* @brief Get subevent code for avrcp event
|
||||
* @param event packet
|
||||
@ -3972,14 +3980,23 @@ static inline hci_con_handle_t ancs_subevent_client_disconnected_get_handle(cons
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_accept_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_accept_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_accept_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
|
||||
* @param event packet
|
||||
@ -3987,7 +4004,7 @@ static inline hci_con_handle_t avdtp_subevent_signaling_accept_get_con_handle(co
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_accept_get_signal_identifier(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field status from event AVDTP_SUBEVENT_SIGNALING_ACCEPT
|
||||
@ -3996,18 +4013,27 @@ static inline uint8_t avdtp_subevent_signaling_accept_get_signal_identifier(cons
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_accept_get_status(const uint8_t * event){
|
||||
return event[6];
|
||||
return event[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_REJECT
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_REJECT
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_reject_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_reject_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_REJECT
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_reject_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_REJECT
|
||||
* @param event packet
|
||||
@ -4015,18 +4041,27 @@ static inline hci_con_handle_t avdtp_subevent_signaling_reject_get_con_handle(co
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_reject_get_signal_identifier(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[6];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_general_reject_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_general_reject_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_general_reject_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
|
||||
* @param event packet
|
||||
@ -4034,16 +4069,16 @@ static inline hci_con_handle_t avdtp_subevent_signaling_general_reject_get_con_h
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_general_reject_get_signal_identifier(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[6];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_connection_established_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_connection_established_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
@ -4066,22 +4101,22 @@ static inline uint8_t avdtp_subevent_signaling_connection_established_get_status
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_connection_released_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_connection_released_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field handle from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND
|
||||
* @param event packet
|
||||
* @return handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_sep_found_get_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_sep_found_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
@ -4122,14 +4157,32 @@ static inline uint8_t avdtp_subevent_signaling_sep_found_get_sep_type(const uint
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_capability_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_capability_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
* @param event packet
|
||||
* @return acp_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_acp_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
* @param event packet
|
||||
@ -4137,7 +4190,7 @@ static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_capabili
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_media_type(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[7];
|
||||
}
|
||||
/**
|
||||
* @brief Get field sampling_frequency_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4146,7 +4199,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_me
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(const uint8_t * event){
|
||||
return event[6];
|
||||
return event[8];
|
||||
}
|
||||
/**
|
||||
* @brief Get field channel_mode_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4155,7 +4208,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_sa
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(const uint8_t * event){
|
||||
return event[7];
|
||||
return event[9];
|
||||
}
|
||||
/**
|
||||
* @brief Get field block_length_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4164,7 +4217,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_ch
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(const uint8_t * event){
|
||||
return event[8];
|
||||
return event[10];
|
||||
}
|
||||
/**
|
||||
* @brief Get field subbands_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4173,7 +4226,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_bl
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(const uint8_t * event){
|
||||
return event[9];
|
||||
return event[11];
|
||||
}
|
||||
/**
|
||||
* @brief Get field allocation_method_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4182,7 +4235,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_su
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(const uint8_t * event){
|
||||
return event[10];
|
||||
return event[12];
|
||||
}
|
||||
/**
|
||||
* @brief Get field min_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4191,7 +4244,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_al
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(const uint8_t * event){
|
||||
return event[11];
|
||||
return event[13];
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
|
||||
@ -4200,18 +4253,36 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_mi
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(const uint8_t * event){
|
||||
return event[12];
|
||||
return event[14];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_capability_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_capability_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
* @param event packet
|
||||
* @return acp_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_acp_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
* @param event packet
|
||||
@ -4219,7 +4290,7 @@ static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_capabi
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_media_type(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[7];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
@ -4228,7 +4299,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_type(const uint8_t * event){
|
||||
return little_endian_read_16(event, 6);
|
||||
return little_endian_read_16(event, 8);
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_information_len from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
@ -4237,7 +4308,7 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get
|
||||
* @note: btstack_type L
|
||||
*/
|
||||
static inline int avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_information_len(const uint8_t * event){
|
||||
return little_endian_read_16(event, 8);
|
||||
return little_endian_read_16(event, 10);
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_information from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
|
||||
@ -4246,18 +4317,36 @@ static inline int avdtp_subevent_signaling_media_codec_other_capability_get_medi
|
||||
* @note: btstack_type V
|
||||
*/
|
||||
static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_information(const uint8_t * event){
|
||||
return &event[10];
|
||||
return &event[12];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return acp_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field reconfigure from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
* @param event packet
|
||||
@ -4265,7 +4354,7 @@ static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_sbc_configur
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[7];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4274,7 +4363,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_media_type(const uint8_t * event){
|
||||
return event[6];
|
||||
return event[8];
|
||||
}
|
||||
/**
|
||||
* @brief Get field sampling_frequency from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4283,7 +4372,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(const uint8_t * event){
|
||||
return little_endian_read_16(event, 7);
|
||||
return little_endian_read_16(event, 9);
|
||||
}
|
||||
/**
|
||||
* @brief Get field channel_mode from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4292,7 +4381,7 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_ge
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(const uint8_t * event){
|
||||
return event[9];
|
||||
return event[11];
|
||||
}
|
||||
/**
|
||||
* @brief Get field num_channels from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4301,7 +4390,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(const uint8_t * event){
|
||||
return event[10];
|
||||
return event[12];
|
||||
}
|
||||
/**
|
||||
* @brief Get field block_length from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4310,7 +4399,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(const uint8_t * event){
|
||||
return event[11];
|
||||
return event[13];
|
||||
}
|
||||
/**
|
||||
* @brief Get field subbands from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4319,7 +4408,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(const uint8_t * event){
|
||||
return event[12];
|
||||
return event[14];
|
||||
}
|
||||
/**
|
||||
* @brief Get field allocation_method from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4328,7 +4417,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(const uint8_t * event){
|
||||
return event[13];
|
||||
return event[15];
|
||||
}
|
||||
/**
|
||||
* @brief Get field min_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4337,7 +4426,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(const uint8_t * event){
|
||||
return event[14];
|
||||
return event[16];
|
||||
}
|
||||
/**
|
||||
* @brief Get field max_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
|
||||
@ -4346,18 +4435,36 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(const uint8_t * event){
|
||||
return event[15];
|
||||
return event[17];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_configuration_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_configuration_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
* @param event packet
|
||||
* @return acp_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_acp_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field reconfigure from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
* @param event packet
|
||||
@ -4365,7 +4472,7 @@ static inline hci_con_handle_t avdtp_subevent_signaling_media_codec_other_config
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_reconfigure(const uint8_t * event){
|
||||
return event[5];
|
||||
return event[7];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
@ -4374,7 +4481,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_g
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_media_type(const uint8_t * event){
|
||||
return event[6];
|
||||
return event[8];
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
@ -4383,7 +4490,7 @@ static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_g
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_type(const uint8_t * event){
|
||||
return little_endian_read_16(event, 7);
|
||||
return little_endian_read_16(event, 9);
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_information_len from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
@ -4392,7 +4499,7 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_
|
||||
* @note: btstack_type L
|
||||
*/
|
||||
static inline int avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_information_len(const uint8_t * event){
|
||||
return little_endian_read_16(event, 9);
|
||||
return little_endian_read_16(event, 11);
|
||||
}
|
||||
/**
|
||||
* @brief Get field media_codec_information from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
|
||||
@ -4401,18 +4508,36 @@ static inline int avdtp_subevent_signaling_media_codec_other_configuration_get_m
|
||||
* @note: btstack_type V
|
||||
*/
|
||||
static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_information(const uint8_t * event){
|
||||
return &event[11];
|
||||
return &event[13];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_streaming_connection_established_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field acp_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return acp_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_streaming_connection_established_get_acp_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field status from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
|
||||
* @param event packet
|
||||
@ -4420,18 +4545,159 @@ static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_g
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_streaming_connection_established_get_status(const uint8_t * event){
|
||||
return event[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_streaming_connection_released_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_streaming_can_send_media_packet_now_get_int_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field sequence_number from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return sequence_number
|
||||
* @note: btstack_type 2
|
||||
*/
|
||||
static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_sequence_number(const uint8_t * event){
|
||||
return little_endian_read_16(event, 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return remote_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_remote_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field status from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t * event){
|
||||
return event[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED
|
||||
* @param event packet
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_start_accepted_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_start_accepted_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_SUSPENDED
|
||||
* @param event packet
|
||||
* @return con_handle
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_streaming_connection_released_get_con_handle(const uint8_t * event){
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_SUSPENDED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_suspended_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAM_RELEASED
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_RELEASED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_released_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field con_handle from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
|
||||
|
134
src/classic/a2dp_sink.c
Normal file
134
src/classic/a2dp_sink.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
#define __BTSTACK_FILE__ "a2dp_sink.c"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack.h"
|
||||
#include "avdtp.h"
|
||||
#include "avdtp_util.h"
|
||||
#include "avdtp_sink.h"
|
||||
#include "a2dp_sink.h"
|
||||
|
||||
static const char * default_a2dp_sink_service_name = "BTstack A2DP Sink Service";
|
||||
static const char * default_a2dp_sink_service_provider_name = "BTstack A2DP Sink Service Provider";
|
||||
|
||||
// static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
||||
uint8_t* attribute;
|
||||
de_create_sequence(service);
|
||||
|
||||
// 0x0000 "Service Record Handle"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
|
||||
|
||||
// 0x0001 "Service Class ID List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AUDIO_SINK);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0004 "Protocol Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t* l2cpProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
|
||||
de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
de_pop_sequence(attribute, l2cpProtocol);
|
||||
|
||||
uint8_t* avProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service
|
||||
de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version
|
||||
}
|
||||
de_pop_sequence(attribute, avProtocol);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0005 "Public Browse Group"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0009 "Bluetooth Profile Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t *a2dProfile = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION);
|
||||
de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103);
|
||||
}
|
||||
de_pop_sequence(attribute, a2dProfile);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
|
||||
// 0x0100 "Service Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
if (service_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_a2dp_sink_service_name), (uint8_t *) default_a2dp_sink_service_name);
|
||||
}
|
||||
|
||||
// 0x0100 "Provider Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102);
|
||||
if (service_provider_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_a2dp_sink_service_provider_name), (uint8_t *) default_a2dp_sink_service_provider_name);
|
||||
}
|
||||
|
||||
// 0x0311 "Supported Features"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
|
||||
}
|
73
src/classic/a2dp_sink.h
Normal file
73
src/classic/a2dp_sink.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* a2dp_sink.h
|
||||
*
|
||||
* Advanced Audio Distribution Transport Profile (A2DP) Sink
|
||||
*
|
||||
* A2DP Sink is a device that accepts streamed media data.
|
||||
*/
|
||||
|
||||
#ifndef __A2DP_SINK_H
|
||||
#define __A2DP_SINK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief A2DP Sink service record.
|
||||
* @param service
|
||||
* @param service_record_handle
|
||||
* @param supported_features 16-bit bitmap, see AVDTP_SINK_SF_* values in avdtp.h
|
||||
* @param service_name
|
||||
* @param service_provider_name
|
||||
*/
|
||||
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __A2DP_SINK_H
|
570
src/classic/a2dp_source.c
Normal file
570
src/classic/a2dp_source.c
Normal file
@ -0,0 +1,570 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
#define __BTSTACK_FILE__ "a2dp_source.c"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack.h"
|
||||
#include "avdtp.h"
|
||||
#include "avdtp_util.h"
|
||||
#include "avdtp_source.h"
|
||||
#include "a2dp_source.h"
|
||||
|
||||
static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service";
|
||||
static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider";
|
||||
static avdtp_context_t a2dp_source_context;
|
||||
|
||||
#define AVDTP_MEDIA_PAYLOAD_HEADER_SIZE 12
|
||||
|
||||
typedef struct {
|
||||
// to app
|
||||
uint32_t fill_audio_ring_buffer_timeout_ms;
|
||||
uint32_t time_audio_data_sent; // ms
|
||||
uint32_t acc_num_missed_samples;
|
||||
uint32_t samples_ready;
|
||||
btstack_timer_source_t fill_audio_ring_buffer_timer;
|
||||
btstack_ring_buffer_t sbc_ring_buffer;
|
||||
btstack_sbc_encoder_state_t sbc_encoder_state;
|
||||
|
||||
int reconfigure;
|
||||
int num_channels;
|
||||
int sampling_frequency;
|
||||
int channel_mode;
|
||||
int block_length;
|
||||
int subbands;
|
||||
int allocation_method;
|
||||
int min_bitpool_value;
|
||||
int max_bitpool_value;
|
||||
avdtp_stream_endpoint_t * local_stream_endpoint;
|
||||
avdtp_sep_t * active_remote_sep;
|
||||
} avdtp_stream_endpoint_context_t;
|
||||
|
||||
static a2dp_state_t app_state = A2DP_IDLE;
|
||||
static avdtp_stream_endpoint_context_t sc;
|
||||
static uint16_t avdtp_cid = 0;
|
||||
static int next_remote_sep_index_to_query = 0;
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
||||
uint8_t* attribute;
|
||||
de_create_sequence(service);
|
||||
|
||||
// 0x0000 "Service Record Handle"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
|
||||
|
||||
// 0x0001 "Service Class ID List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0004 "Protocol Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t* l2cpProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
|
||||
de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
de_pop_sequence(attribute, l2cpProtocol);
|
||||
|
||||
uint8_t* avProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service
|
||||
de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version
|
||||
}
|
||||
de_pop_sequence(attribute, avProtocol);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0005 "Public Browse Group"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0009 "Bluetooth Profile Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t *a2dProfile = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION);
|
||||
de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103);
|
||||
}
|
||||
de_pop_sequence(attribute, a2dProfile);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
|
||||
// 0x0100 "Service Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
if (service_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_a2dp_source_service_name), (uint8_t *) default_a2dp_source_service_name);
|
||||
}
|
||||
|
||||
// 0x0100 "Provider Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102);
|
||||
if (service_provider_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_a2dp_source_service_provider_name), (uint8_t *) default_a2dp_source_service_provider_name);
|
||||
}
|
||||
|
||||
// 0x0311 "Supported Features"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
|
||||
}
|
||||
|
||||
static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){
|
||||
if (!callback) return;
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_ESTABLISHED;
|
||||
little_endian_store_16(event, pos, cid);
|
||||
pos += 2;
|
||||
event[pos++] = local_seid;
|
||||
event[pos++] = remote_seid;
|
||||
event[pos++] = status;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void a2dp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t cid, uint8_t seid){
|
||||
if (!callback) return;
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW;
|
||||
little_endian_store_16(event, pos, cid);
|
||||
pos += 2;
|
||||
event[pos++] = seid;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
uint8_t signal_identifier;
|
||||
uint8_t status;
|
||||
avdtp_sep_t sep;
|
||||
uint8_t int_seid;
|
||||
uint8_t acp_seid;
|
||||
|
||||
switch (packet_type) {
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// inform about pin code request
|
||||
log_info("Pin code request - using '0000'");
|
||||
hci_event_pin_code_request_get_bd_addr(packet, event_addr);
|
||||
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
|
||||
break;
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit test app
|
||||
log_info("\n --- a2dp source --- HCI_EVENT_DISCONNECTION_COMPLETE ---");
|
||||
|
||||
break;
|
||||
case HCI_EVENT_AVDTP_META:
|
||||
switch (packet[2]){
|
||||
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
|
||||
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
|
||||
status = avdtp_subevent_signaling_connection_established_get_status(packet);
|
||||
if (status != 0){
|
||||
log_info(" --- a2dp source --- AVDTP_SUBEVENT_SIGNALING_CONNECTION could not be established, status %d ---", status);
|
||||
break;
|
||||
}
|
||||
sc.active_remote_sep = NULL;
|
||||
next_remote_sep_index_to_query = 0;
|
||||
app_state = A2DP_W2_DISCOVER_SEPS;
|
||||
log_info(" --- a2dp source --- AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", avdtp_cid);
|
||||
avdtp_source_discover_stream_endpoints(avdtp_cid);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
|
||||
status = avdtp_subevent_streaming_connection_established_get_status(packet);
|
||||
avdtp_cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet);
|
||||
int_seid = avdtp_subevent_streaming_connection_established_get_int_seid(packet);
|
||||
acp_seid = avdtp_subevent_streaming_connection_established_get_acp_seid(packet);
|
||||
|
||||
if (status != 0){
|
||||
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---", status);
|
||||
break;
|
||||
}
|
||||
app_state = A2DP_STREAMING_OPENED;
|
||||
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, avdtp_cid, int_seid, acp_seid, 0);
|
||||
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d", avdtp_cid, int_seid, acp_seid);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
|
||||
if (app_state != A2DP_W2_DISCOVER_SEPS) return;
|
||||
sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet);
|
||||
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
|
||||
sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
|
||||
sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
|
||||
log_info(" --- a2dp source --- Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)", sep.seid, sep.in_use, sep.media_type, sep.type);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{
|
||||
if (!sc.local_stream_endpoint) return;
|
||||
uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
|
||||
uint8_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
|
||||
uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
|
||||
uint8_t subbands = avdtp_choose_sbc_subbands(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet));
|
||||
|
||||
uint8_t allocation_method = avdtp_choose_sbc_allocation_method(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet));
|
||||
uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet));
|
||||
uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet));
|
||||
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[0] = (sampling_frequency << 4) | channel_mode;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[1] = (block_length << 4) | (subbands << 2) | allocation_method;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[2] = min_bitpool_value;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[3] = max_bitpool_value;
|
||||
|
||||
sc.local_stream_endpoint->remote_configuration_bitmap = store_bit16(sc.local_stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
|
||||
app_state = A2DP_W2_SET_CONFIGURATION;
|
||||
break;
|
||||
}
|
||||
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
|
||||
log_info(" --- a2dp source --- received non SBC codec. not implemented");
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
|
||||
sc.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
|
||||
sc.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
|
||||
sc.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
|
||||
sc.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet) - 1;
|
||||
sc.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
|
||||
// TODO: deal with reconfigure: avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
|
||||
break;
|
||||
}
|
||||
case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
a2dp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, avdtp_cid, 0);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
|
||||
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
|
||||
status = avdtp_subevent_signaling_accept_get_status(packet);
|
||||
log_info(" --- a2dp source --- Accepted %d", signal_identifier);
|
||||
|
||||
switch (app_state){
|
||||
case A2DP_W2_DISCOVER_SEPS:
|
||||
app_state = A2DP_W2_GET_ALL_CAPABILITIES;
|
||||
sc.active_remote_sep = avdtp_source_remote_sep(avdtp_cid, next_remote_sep_index_to_query++);
|
||||
log_info(" --- a2dp source --- Query get caps for seid %d", sc.active_remote_sep->seid);
|
||||
avdtp_source_get_capabilities(avdtp_cid, sc.active_remote_sep->seid);
|
||||
break;
|
||||
case A2DP_W2_GET_CAPABILITIES:
|
||||
case A2DP_W2_GET_ALL_CAPABILITIES:
|
||||
if (next_remote_sep_index_to_query < avdtp_source_remote_seps_num(avdtp_cid)){
|
||||
sc.active_remote_sep = avdtp_source_remote_sep(avdtp_cid, next_remote_sep_index_to_query++);
|
||||
log_info(" --- a2dp source --- Query get caps for seid %d", sc.active_remote_sep->seid);
|
||||
avdtp_source_get_capabilities(avdtp_cid, sc.active_remote_sep->seid);
|
||||
} else {
|
||||
log_info(" --- a2dp source --- No more remote seps found");
|
||||
app_state = A2DP_IDLE;
|
||||
}
|
||||
break;
|
||||
case A2DP_W2_SET_CONFIGURATION:{
|
||||
if (!sc.local_stream_endpoint) return;
|
||||
app_state = A2DP_W2_GET_CONFIGURATION;
|
||||
avdtp_source_set_configuration(avdtp_cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid, sc.local_stream_endpoint->remote_configuration_bitmap, sc.local_stream_endpoint->remote_configuration);
|
||||
break;
|
||||
}
|
||||
case A2DP_W2_GET_CONFIGURATION:
|
||||
app_state = A2DP_W2_OPEN_STREAM_WITH_SEID;
|
||||
avdtp_source_get_configuration(avdtp_cid, sc.active_remote_sep->seid);
|
||||
break;
|
||||
case A2DP_W2_OPEN_STREAM_WITH_SEID:{
|
||||
app_state = A2DP_W4_OPEN_STREAM_WITH_SEID;
|
||||
btstack_sbc_encoder_init(&sc.sbc_encoder_state, SBC_MODE_STANDARD,
|
||||
sc.block_length, sc.subbands,
|
||||
sc.allocation_method, sc.sampling_frequency,
|
||||
sc.max_bitpool_value);
|
||||
avdtp_source_open_stream(avdtp_cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid);
|
||||
break;
|
||||
}
|
||||
case A2DP_STREAMING_OPENED:
|
||||
if (!a2dp_source_context.a2dp_callback) return;
|
||||
switch (signal_identifier){
|
||||
case AVDTP_SI_START:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_START_ACCEPTED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
break;
|
||||
}
|
||||
case AVDTP_SI_CLOSE:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
log_info("send A2DP_SUBEVENT_STREAM_RELEASED to app");
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
break;
|
||||
}
|
||||
case AVDTP_SI_SUSPEND:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_SUSPENDED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
app_state = A2DP_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case AVDTP_SUBEVENT_SIGNALING_REJECT:
|
||||
app_state = A2DP_IDLE;
|
||||
signal_identifier = avdtp_subevent_signaling_reject_get_signal_identifier(packet);
|
||||
log_info(" --- a2dp source --- Rejected %d", signal_identifier);
|
||||
break;
|
||||
case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT:
|
||||
app_state = A2DP_IDLE;
|
||||
signal_identifier = avdtp_subevent_signaling_general_reject_get_signal_identifier(packet);
|
||||
log_info(" --- a2dp source --- Rejected %d", signal_identifier);
|
||||
break;
|
||||
default:
|
||||
app_state = A2DP_IDLE;
|
||||
log_info(" --- a2dp source --- not implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// other packet type
|
||||
break;
|
||||
}
|
||||
}
|
||||
void a2dp_source_register_packet_handler(btstack_packet_handler_t callback){
|
||||
if (callback == NULL){
|
||||
log_error("a2dp_source_register_packet_handler called with NULL callback");
|
||||
return;
|
||||
}
|
||||
avdtp_source_register_packet_handler(&packet_handler);
|
||||
a2dp_source_context.a2dp_callback = callback;
|
||||
}
|
||||
|
||||
void a2dp_source_init(void){
|
||||
avdtp_source_init(&a2dp_source_context);
|
||||
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
|
||||
}
|
||||
|
||||
uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, media_type);
|
||||
avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type,
|
||||
codec_capabilities, codec_capabilities_len);
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information = media_codec_info;
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_info_len;
|
||||
|
||||
return local_stream_endpoint->sep.seid;
|
||||
}
|
||||
|
||||
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){
|
||||
sc.local_stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
|
||||
if (!sc.local_stream_endpoint){
|
||||
log_error(" no local_stream_endpoint for seid %d", local_seid);
|
||||
return;
|
||||
}
|
||||
avdtp_source_connect(bd_addr);
|
||||
}
|
||||
|
||||
void a2dp_source_disconnect(uint16_t con_handle){
|
||||
avdtp_disconnect(con_handle, &a2dp_source_context);
|
||||
}
|
||||
|
||||
void a2dp_source_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, &a2dp_source_context);
|
||||
}
|
||||
|
||||
void a2dp_source_release_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, &a2dp_source_context);
|
||||
}
|
||||
|
||||
void a2dp_source_pause_stream(uint8_t int_seid){
|
||||
avdtp_suspend_stream(int_seid, &a2dp_source_context);
|
||||
}
|
||||
|
||||
uint8_t a2dp_source_stream_endpoint_ready(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("No stream_endpoint with seid %d", local_seid);
|
||||
return 0;
|
||||
}
|
||||
return (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING);
|
||||
}
|
||||
|
||||
|
||||
static void a2dp_source_setup_media_header(uint8_t * media_packet, int size, int *offset, uint8_t marker, uint16_t sequence_number){
|
||||
if (size < AVDTP_MEDIA_PAYLOAD_HEADER_SIZE){
|
||||
log_error("small outgoing buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t rtp_version = 2;
|
||||
uint8_t padding = 0;
|
||||
uint8_t extension = 0;
|
||||
uint8_t csrc_count = 0;
|
||||
uint8_t payload_type = 0x60;
|
||||
// uint16_t sequence_number = stream_endpoint->sequence_number;
|
||||
uint32_t timestamp = btstack_run_loop_get_time_ms();
|
||||
uint32_t ssrc = 0x11223344;
|
||||
|
||||
// rtp header (min size 12B)
|
||||
int pos = 0;
|
||||
// int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
|
||||
media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
|
||||
media_packet[pos++] = (marker << 1) | payload_type;
|
||||
big_endian_store_16(media_packet, pos, sequence_number);
|
||||
pos += 2;
|
||||
big_endian_store_32(media_packet, pos, timestamp);
|
||||
pos += 4;
|
||||
big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
|
||||
pos += 4;
|
||||
*offset = pos;
|
||||
}
|
||||
|
||||
void a2dp_source_stream_endpoint_request_can_send_now(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("no stream_endpoint for seid %d", local_seid);
|
||||
return;
|
||||
}
|
||||
stream_endpoint->send_stream = 1;
|
||||
avdtp_request_can_send_now_initiator(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
|
||||
int a2dp_max_media_payload_size(uint8_t int_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("no stream_endpoint found for seid %d", int_seid);
|
||||
return 0;
|
||||
}
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
log_error("no media cid found for seid %d", int_seid);
|
||||
return 0;
|
||||
}
|
||||
return l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid) - AVDTP_MEDIA_PAYLOAD_HEADER_SIZE;
|
||||
}
|
||||
|
||||
static void a2dp_source_copy_media_payload(uint8_t * media_packet, int size, int * offset, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames){
|
||||
if (size < num_bytes_to_copy + 1){
|
||||
log_error("small outgoing buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = *offset;
|
||||
media_packet[pos++] = num_frames; // (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
|
||||
memcpy(media_packet + pos, storage, num_bytes_to_copy);
|
||||
pos += num_bytes_to_copy;
|
||||
*offset = pos;
|
||||
}
|
||||
|
||||
int a2dp_source_stream_send_media_payload(uint8_t int_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(int_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("no stream_endpoint found for seid %d", int_seid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
log_error("no media cid found for seid %d", int_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;
|
||||
}
|
125
src/classic/a2dp_source.h
Normal file
125
src/classic/a2dp_source.h
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* a2dp_source.h
|
||||
*
|
||||
* Advanced Audio Distribution Transport Profile (A2DP) Source
|
||||
*
|
||||
* A2DP Source is a device that streames media data.
|
||||
*/
|
||||
|
||||
#ifndef __A2DP_SOURCE_H
|
||||
#define __A2DP_SOURCE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief A2DP Source service record.
|
||||
* @param service
|
||||
* @param service_record_handle
|
||||
* @param supported_features 16-bit bitmap, see AVDTP_SOURCE_SF_* values in avdtp.h
|
||||
* @param service_name
|
||||
* @param service_provider_name
|
||||
*/
|
||||
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
|
||||
|
||||
void a2dp_source_init(void);
|
||||
|
||||
void a2dp_source_register_packet_handler(btstack_packet_handler_t callback);
|
||||
|
||||
uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * codec_configuration, uint16_t codec_configuration_len);
|
||||
|
||||
/**
|
||||
* @brief Open stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_start_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_pause_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Close stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_release_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from device with connection handle.
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void a2dp_source_disconnect(uint16_t avdtp_cid);
|
||||
|
||||
|
||||
// size for media (does not include media header)
|
||||
int a2dp_max_media_payload_size(uint8_t int_seid);
|
||||
|
||||
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid);
|
||||
|
||||
void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid);
|
||||
|
||||
int a2dp_source_stream_send_media_payload(uint8_t int_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __A2DP_SOURCE_H
|
@ -50,13 +50,37 @@
|
||||
#include "avdtp_acceptor.h"
|
||||
#include "avdtp_initiator.h"
|
||||
|
||||
static uint8_t audio_samples_storage[44100*4]; // 1s buffer
|
||||
// static btstack_ring_buffer_t audio_ring_buffer;
|
||||
static int record_id = -1;
|
||||
static uint8_t attribute_value[1000];
|
||||
static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
|
||||
|
||||
static uint8_t sbc_samples_storage[44100*4];
|
||||
// static btstack_ring_buffer_t sbc_ring_buffer;
|
||||
typedef struct {
|
||||
avdtp_connection_t * connection;
|
||||
btstack_packet_handler_t avdtp_callback;
|
||||
avdtp_sep_type_t query_role;
|
||||
btstack_packet_handler_t packet_handler;
|
||||
} avdtp_sdp_query_context_t;
|
||||
|
||||
static avdtp_sdp_query_context_t sdp_query_context;
|
||||
|
||||
static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
|
||||
static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * avdtp_context){
|
||||
sdp_query_context.connection = NULL;
|
||||
avdtp_connection_t * connection = avdtp_connection_for_bd_addr(remote, avdtp_context);
|
||||
if (!connection){
|
||||
connection = avdtp_create_connection(remote, avdtp_context);
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return;
|
||||
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
|
||||
sdp_query_context.connection = connection;
|
||||
sdp_query_context.query_role = query_role;
|
||||
sdp_query_context.avdtp_callback = avdtp_context->avdtp_callback;
|
||||
sdp_query_context.packet_handler = avdtp_context->packet_handler;
|
||||
|
||||
sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
|
||||
void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
if (!stream_endpoint){
|
||||
@ -65,7 +89,6 @@ void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_en
|
||||
}
|
||||
uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_TRANSPORT, 1);
|
||||
stream_endpoint->sep.registered_service_categories = bitmap;
|
||||
printf("registered services AVDTP_MEDIA_TRANSPORT(%d) %02x\n", AVDTP_MEDIA_TRANSPORT, stream_endpoint->sep.registered_service_categories);
|
||||
}
|
||||
|
||||
void avdtp_register_reporting_category(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
@ -122,14 +145,13 @@ void avdtp_register_header_compression_category(avdtp_stream_endpoint_t * stream
|
||||
stream_endpoint->sep.capabilities.header_compression.recovery = recovery;
|
||||
}
|
||||
|
||||
void avdtp_register_media_codec_category(avdtp_stream_endpoint_t * stream_endpoint, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
void avdtp_register_media_codec_category(avdtp_stream_endpoint_t * stream_endpoint, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
if (!stream_endpoint){
|
||||
log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered");
|
||||
return;
|
||||
}
|
||||
uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_CODEC, 1);
|
||||
stream_endpoint->sep.registered_service_categories = bitmap;
|
||||
printf("registered services AVDTP_MEDIA_CODEC(%d) %02x\n", AVDTP_MEDIA_CODEC, stream_endpoint->sep.registered_service_categories);
|
||||
stream_endpoint->sep.capabilities.media_codec.media_type = media_type;
|
||||
stream_endpoint->sep.capabilities.media_codec.media_codec_type = media_codec_type;
|
||||
stream_endpoint->sep.capabilities.media_codec.media_codec_information = media_codec_info;
|
||||
@ -203,14 +225,6 @@ avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type
|
||||
stream_endpoint->sep.seid = context->stream_endpoints_id_counter;
|
||||
stream_endpoint->sep.media_type = media_type;
|
||||
stream_endpoint->sep.type = sep_type;
|
||||
|
||||
memset(audio_samples_storage, 0, sizeof(audio_samples_storage));
|
||||
btstack_ring_buffer_init(&stream_endpoint->audio_ring_buffer, audio_samples_storage, sizeof(audio_samples_storage));
|
||||
|
||||
memset(sbc_samples_storage, 0, sizeof(sbc_samples_storage));
|
||||
btstack_ring_buffer_init(&stream_endpoint->sbc_ring_buffer, sbc_samples_storage, sizeof(sbc_samples_storage));
|
||||
|
||||
|
||||
btstack_linked_list_add(&context->stream_endpoints, (btstack_linked_item_t *) stream_endpoint);
|
||||
return stream_endpoint;
|
||||
}
|
||||
@ -248,8 +262,9 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
|
||||
stream_endpoint->connection = connection;
|
||||
stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);
|
||||
printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection);
|
||||
avdtp_streaming_emit_connection_established(context->avdtp_callback, stream_endpoint->l2cap_media_cid, 0);
|
||||
stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet);
|
||||
log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED, media con handle 0x%02x, l2cap_media_cid 0x%02x", stream_endpoint->media_con_handle, stream_endpoint->l2cap_media_cid);
|
||||
avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, stream_endpoint->sep.seid, connection->remote_seps[stream_endpoint->remote_sep_index].seid, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -257,13 +272,11 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp
|
||||
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
|
||||
if (stream_endpoint->l2cap_media_cid == local_cid){
|
||||
stream_endpoint->l2cap_media_cid = 0;
|
||||
printf(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE\n");
|
||||
log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
|
||||
stream_endpoint->remote_seps_num = 0;
|
||||
memset(stream_endpoint->remote_seps, 0, sizeof(avdtp_sep_t)*MAX_NUM_SEPS);
|
||||
stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
|
||||
stream_endpoint->remote_sep_index = 0;
|
||||
break;
|
||||
}
|
||||
if (stream_endpoint->l2cap_recovery_cid == local_cid){
|
||||
@ -287,6 +300,121 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp
|
||||
}
|
||||
}
|
||||
|
||||
static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(packet_type);
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
des_iterator_t des_list_it;
|
||||
des_iterator_t prot_it;
|
||||
uint32_t avdtp_remote_uuid = 0;
|
||||
uint16_t avdtp_l2cap_psm = 0;
|
||||
uint16_t avdtp_version = 0;
|
||||
|
||||
if (!sdp_query_context.connection) return;
|
||||
|
||||
switch (hci_event_packet_get_type(packet)){
|
||||
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
|
||||
// Handle new SDP record
|
||||
if (sdp_event_query_attribute_byte_get_record_id(packet) != record_id) {
|
||||
record_id = sdp_event_query_attribute_byte_get_record_id(packet);
|
||||
// log_info("SDP Record: Nr: %d", record_id);
|
||||
}
|
||||
|
||||
if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= attribute_value_buffer_size) {
|
||||
attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet);
|
||||
|
||||
if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) {
|
||||
|
||||
switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) {
|
||||
case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST:
|
||||
if (de_get_element_type(attribute_value) != DE_DES) break;
|
||||
for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) {
|
||||
uint8_t * element = des_iterator_get_element(&des_list_it);
|
||||
if (de_get_element_type(element) != DE_UUID) continue;
|
||||
uint32_t uuid = de_get_uuid32(element);
|
||||
switch (uuid){
|
||||
case BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE:
|
||||
if (sdp_query_context.query_role != AVDTP_SOURCE) {
|
||||
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, 0);
|
||||
break;
|
||||
}
|
||||
// log_info("SDP Attribute 0x%04x: AVDTP SOURCE protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
|
||||
avdtp_remote_uuid = uuid;
|
||||
break;
|
||||
case BLUETOOTH_SERVICE_CLASS_AUDIO_SINK:
|
||||
if (sdp_query_context.query_role != AVDTP_SINK) {
|
||||
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, 0);
|
||||
break;
|
||||
}
|
||||
// log_info("SDP Attribute 0x%04x: AVDTP SINK protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
|
||||
avdtp_remote_uuid = uuid;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: {
|
||||
// log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet));
|
||||
|
||||
for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) {
|
||||
uint8_t *des_element;
|
||||
uint8_t *element;
|
||||
uint32_t uuid;
|
||||
|
||||
if (des_iterator_get_type(&des_list_it) != DE_DES) continue;
|
||||
|
||||
des_element = des_iterator_get_element(&des_list_it);
|
||||
des_iterator_init(&prot_it, des_element);
|
||||
element = des_iterator_get_element(&prot_it);
|
||||
|
||||
if (de_get_element_type(element) != DE_UUID) continue;
|
||||
|
||||
uuid = de_get_uuid32(element);
|
||||
switch (uuid){
|
||||
case BLUETOOTH_PROTOCOL_L2CAP:
|
||||
if (!des_iterator_has_more(&prot_it)) continue;
|
||||
des_iterator_next(&prot_it);
|
||||
de_element_get_uint16(des_iterator_get_element(&prot_it), &avdtp_l2cap_psm);
|
||||
break;
|
||||
case BLUETOOTH_PROTOCOL_AVDTP:
|
||||
if (!des_iterator_has_more(&prot_it)) continue;
|
||||
des_iterator_next(&prot_it);
|
||||
de_element_get_uint16(des_iterator_get_element(&prot_it), &avdtp_version);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!avdtp_l2cap_psm) {
|
||||
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
|
||||
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST);
|
||||
break;
|
||||
}
|
||||
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
l2cap_create_channel(sdp_query_context.packet_handler, sdp_query_context.connection->remote_addr, avdtp_l2cap_psm, l2cap_max_mtu(), NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_error("SDP attribute value buffer size exceeded: available %d, required %d", attribute_value_buffer_size, sdp_event_query_attribute_byte_get_attribute_length(packet));
|
||||
}
|
||||
break;
|
||||
|
||||
case SDP_EVENT_QUERY_COMPLETE:
|
||||
log_info("General query done with status %d.", sdp_event_query_complete_get_status(packet));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avdtp_context_t * context){
|
||||
bd_addr_t event_addr;
|
||||
hci_con_handle_t con_handle;
|
||||
@ -297,7 +425,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
btstack_linked_list_t * avdtp_connections = &context->connections;
|
||||
btstack_linked_list_t * stream_endpoints = &context->stream_endpoints;
|
||||
handle_media_data = context->handle_media_data;
|
||||
// printf("avdtp_packet_handler packet type %02x, event %02x \n", packet_type, hci_event_packet_get_type(packet));
|
||||
// log_info("avdtp_packet_handler packet type %02x, event %02x ", packet_type, hci_event_packet_get_type(packet));
|
||||
switch (packet_type) {
|
||||
case L2CAP_DATA_PACKET:
|
||||
connection = avdtp_connection_for_l2cap_signaling_cid(channel, context);
|
||||
@ -325,10 +453,10 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
if (channel == stream_endpoint->l2cap_reporting_cid){
|
||||
// TODO
|
||||
printf("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED\n");
|
||||
log_info("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED");
|
||||
} else if (channel == stream_endpoint->l2cap_recovery_cid){
|
||||
// TODO
|
||||
printf("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED\n");
|
||||
log_info("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED");
|
||||
} else {
|
||||
log_error("avdtp packet handler L2CAP_DATA_PACKET: local cid 0x%02x not found", channel);
|
||||
}
|
||||
@ -341,16 +469,18 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
|
||||
|
||||
connection = avdtp_connection_for_bd_addr(event_addr, context);
|
||||
if (!connection){
|
||||
|
||||
if (!connection || connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED){
|
||||
connection = avdtp_create_connection(event_addr, context);
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
log_info("L2CAP_EVENT_INCOMING_CONNECTION, connection %p, state connection %d", connection, connection->state);
|
||||
l2cap_accept_connection(local_cid);
|
||||
break;
|
||||
}
|
||||
|
||||
stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("L2CAP_EVENT_INCOMING_CONNECTION no streamendpoint found for seid %d\n", connection->query_seid);
|
||||
log_info("L2CAP_EVENT_INCOMING_CONNECTION no streamendpoint found for seid %d", connection->query_seid);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -378,8 +508,8 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
con_handle = l2cap_event_channel_opened_get_handle(packet);
|
||||
local_cid = l2cap_event_channel_opened_get_local_cid(packet);
|
||||
|
||||
// printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
|
||||
// bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet));
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x",
|
||||
bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet));
|
||||
|
||||
if (psm != BLUETOOTH_PROTOCOL_AVDTP) break;
|
||||
|
||||
@ -392,14 +522,14 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
connection->con_handle = con_handle;
|
||||
connection->query_seid = 0;
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_OPENED;
|
||||
printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p\n", connection);
|
||||
avdtp_signaling_emit_connection_established(context->avdtp_callback, con_handle, event_addr, 0);
|
||||
log_info(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p", connection);
|
||||
avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, event_addr, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context);
|
||||
if (!stream_endpoint){
|
||||
printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found");
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found");
|
||||
return;
|
||||
}
|
||||
stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_OPENED, packet, size, context);
|
||||
@ -409,10 +539,10 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
// data: event (8), len(8), channel (16)
|
||||
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
|
||||
connection = avdtp_connection_for_l2cap_signaling_cid(local_cid, context);
|
||||
printf(" -> L2CAP_EVENT_CHANNEL_CLOSED signaling cid 0x%0x\n", local_cid);
|
||||
log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED signaling cid 0x%0x", local_cid);
|
||||
|
||||
if (connection){
|
||||
printf(" -> AVDTP_STREAM_ENDPOINT_IDLE, connection closed\n");
|
||||
log_info(" -> AVDTP_STREAM_ENDPOINT_IDLE, connection closed");
|
||||
btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection);
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, stream_endpoints);
|
||||
@ -437,68 +567,12 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
if (!connection) {
|
||||
stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context);
|
||||
if (!stream_endpoint->connection) break;
|
||||
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND){
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
//send sbc
|
||||
uint8_t rtp_version = 2;
|
||||
uint8_t padding = 0;
|
||||
uint8_t extension = 0;
|
||||
uint8_t csrc_count = 0;
|
||||
uint8_t marker = 0;
|
||||
uint8_t payload_type = 0x60;
|
||||
uint16_t sequence_number = stream_endpoint->sequence_number;
|
||||
uint32_t timestamp = btstack_run_loop_get_time_ms();
|
||||
uint32_t ssrc = 0x11223344;
|
||||
|
||||
// rtp header (min size 12B)
|
||||
int pos = 0;
|
||||
int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
|
||||
uint8_t media_packet[mtu];
|
||||
media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
|
||||
media_packet[pos++] = (marker << 1) | payload_type;
|
||||
big_endian_store_16(media_packet, pos, sequence_number);
|
||||
pos += 2;
|
||||
big_endian_store_32(media_packet, pos, timestamp);
|
||||
pos += 4;
|
||||
big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
|
||||
pos += 4;
|
||||
|
||||
// media payload
|
||||
// sbc_header (size 1B)
|
||||
uint8_t sbc_header_index = pos;
|
||||
pos++;
|
||||
uint8_t fragmentation = 0;
|
||||
uint8_t starting_packet = 0; // set to 1 for the first packet of a fragmented SBC frame
|
||||
uint8_t last_packet = 0; // set to 1 for the last packet of a fragmented SBC frame
|
||||
uint8_t num_frames = 0;
|
||||
|
||||
uint32_t total_sbc_bytes_read = 0;
|
||||
uint8_t sbc_frame_size = 0;
|
||||
// payload
|
||||
while (mtu - 13 - total_sbc_bytes_read >= 120 && btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){
|
||||
uint32_t number_of_bytes_read = 0;
|
||||
btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, &sbc_frame_size, 1, &number_of_bytes_read);
|
||||
btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, media_packet + pos, sbc_frame_size, &number_of_bytes_read);
|
||||
pos += sbc_frame_size;
|
||||
total_sbc_bytes_read += sbc_frame_size;
|
||||
num_frames++;
|
||||
// printf("send sbc frame: timestamp %d, seq. nr %d\n", timestamp, stream_endpoint->sequence_number);
|
||||
}
|
||||
media_packet[sbc_header_index] = (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
|
||||
stream_endpoint->sequence_number++;
|
||||
l2cap_send(stream_endpoint->l2cap_media_cid, media_packet, pos);
|
||||
if (btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND;
|
||||
l2cap_request_can_send_now_event(stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
}
|
||||
connection = stream_endpoint->connection;
|
||||
}
|
||||
avdtp_handle_can_send_now(connection, channel, context);
|
||||
break;
|
||||
default:
|
||||
printf("unknown HCI event type %02x\n", hci_event_packet_get_type(packet));
|
||||
log_info("unknown HCI event type %02x", hci_event_packet_get_type(packet));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -509,8 +583,8 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
}
|
||||
}
|
||||
|
||||
void avdtp_disconnect(uint16_t con_handle, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection) return;
|
||||
if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return;
|
||||
if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return;
|
||||
@ -519,21 +593,25 @@ void avdtp_disconnect(uint16_t con_handle, avdtp_context_t * context){
|
||||
avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_open_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_media_connect: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_media_connect: wrong connection state %d\n", connection->state);
|
||||
if (avdtp_find_remote_sep(connection, acp_seid) == 0xFF){
|
||||
log_error("avdtp_media_connect: no remote sep for seid %d found", acp_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
log_error("avdtp_media_connect: wrong connection state %d", connection->state);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_media_connect: no stream_endpoint with acp seid %d found\n", acp_seid);
|
||||
log_error("avdtp_media_connect: no stream_endpoint with seid %d found", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -548,103 +626,79 @@ void avdtp_open_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t *
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_start_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
if (!connection){
|
||||
printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle);
|
||||
void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("avdtp_start_stream: no stream_endpoint with seid %d found", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_media_connect: wrong connection state %d\n", connection->state);
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
if (!connection){
|
||||
log_error("avdtp_start_stream: no connection for seid %d found",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_media_connect: no stream_endpoint with acp_seid %d found\n", acp_seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
|
||||
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START;
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX || stream_endpoint->start_stream) return;
|
||||
stream_endpoint->start_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_stop_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
if (!connection){
|
||||
printf("avdtp_stop_stream: no connection for handle 0x%02x found\n", con_handle);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_stop_stream: wrong connection state %d\n", connection->state);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
void avdtp_stop_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_stop_stream: no stream_endpoint with acp seid %d found\n", acp_seid);
|
||||
log_error("avdtp_stop_stream: no stream_endpoint with seid %d found", int_seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n");
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
if (!connection){
|
||||
log_error("avdtp_stop_stream: no connection for seid %d found",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return;
|
||||
stream_endpoint->stop_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_abort_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
if (!connection){
|
||||
printf("avdtp_abort_stream: no connection for handle 0x%02x found\n", con_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_abort_stream: wrong connection state %d\n", connection->state);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
void avdtp_abort_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_abort_stream: no stream_endpoint for seid %d found\n", acp_seid);
|
||||
log_error("avdtp_abort_stream: no stream_endpoint with seid %d found", int_seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_CONFIGURED:
|
||||
case AVDTP_STREAM_ENDPOINT_CLOSING:
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
printf(" AVDTP_INITIATOR_W2_STREAMING_ABORT \n");
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_ABORT;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
|
||||
if (!connection){
|
||||
log_error("avdtp_abort_stream: no connection for seid %d found",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->abort_stream) return;
|
||||
stream_endpoint->abort_stream = 1;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_discover_stream_endpoints(uint16_t con_handle, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_suspend_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("avdtp_abort_stream: no stream_endpoint with seid %d found", int_seid);
|
||||
return;
|
||||
}
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
if (!connection){
|
||||
printf("avdtp_discover_stream_endpoints: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_abort_stream: no connection for seid %d found",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return;
|
||||
stream_endpoint->suspend_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
log_error("avdtp_discover_stream_endpoints: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
@ -656,16 +710,16 @@ void avdtp_discover_stream_endpoints(uint16_t con_handle, avdtp_context_t * cont
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
break;
|
||||
default:
|
||||
printf("avdtp_discover_stream_endpoints: wrong state\n");
|
||||
log_error("avdtp_discover_stream_endpoints: wrong state");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void avdtp_get_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_get_capabilities: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_get_capabilities: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
@ -677,10 +731,10 @@ void avdtp_get_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context
|
||||
}
|
||||
|
||||
|
||||
void avdtp_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_get_all_capabilities: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_get_all_capabilities: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
@ -691,10 +745,10 @@ void avdtp_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_con
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_get_configuration(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_get_configuration: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_get_configuration: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
@ -705,10 +759,10 @@ void avdtp_get_configuration(uint16_t con_handle, uint8_t acp_seid, avdtp_contex
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
log_error("avdtp_set_configuration: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_set_configuration: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
@ -716,55 +770,181 @@ void avdtp_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d\n", int_seid);
|
||||
log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
// printf("avdtp_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid);
|
||||
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = int_seid;
|
||||
connection->remote_capabilities_bitmap = configured_services_bitmap;
|
||||
connection->remote_capabilities = configuration;
|
||||
stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
|
||||
stream_endpoint->remote_capabilities = configuration;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_reconfigure: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_reconfigure: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
//TODO: if opened only app capabilities, enable reconfigure for not opened
|
||||
if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
if (!stream_endpoint) return;
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
|
||||
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("avdtp_reconfigure: no initiator stream endpoint for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->remote_sep_index == 0xFF){
|
||||
log_error("avdtp_reconfigure: no associated remote sep");
|
||||
return;
|
||||
}
|
||||
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
connection->remote_capabilities_bitmap = configured_services_bitmap;
|
||||
connection->remote_capabilities = configuration;
|
||||
stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
|
||||
stream_endpoint->remote_capabilities = configuration;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_suspend(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
|
||||
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_suspend: no connection for handle 0x%02x found\n", con_handle);
|
||||
log_error("avdtp_suspend: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return 0;
|
||||
}
|
||||
return connection->remote_seps_num;
|
||||
}
|
||||
|
||||
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
log_error("avdtp_suspend: no connection for signaling cid 0x%02x found", avdtp_cid);
|
||||
return NULL;
|
||||
}
|
||||
return &connection->remote_seps[index];
|
||||
}
|
||||
|
||||
void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size){
|
||||
UNUSED(packet_size);
|
||||
if (storage_size < 4) {
|
||||
log_error("storage must have 4 bytes");
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
|
||||
if (!stream_endpoint) return;
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
|
||||
uint8_t channel_mode = avdtp_choose_sbc_channel_mode(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
|
||||
uint8_t block_length = avdtp_choose_sbc_block_length(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
|
||||
uint8_t subbands = avdtp_choose_sbc_subbands(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet));
|
||||
|
||||
uint8_t allocation_method = avdtp_choose_sbc_allocation_method(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet));
|
||||
uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet));
|
||||
uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet));
|
||||
|
||||
config_storage[0] = (sampling_frequency << 4) | channel_mode;
|
||||
config_storage[1] = (block_length << 4) | (subbands << 2) | allocation_method;
|
||||
config_storage[2] = min_bitpool_value;
|
||||
config_storage[3] = max_bitpool_value;
|
||||
|
||||
stream_endpoint->remote_configuration_bitmap = store_bit16(stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
|
||||
stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
|
||||
stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
stream_endpoint->remote_configuration.media_codec.media_codec_information_len = storage_size;
|
||||
stream_endpoint->remote_configuration.media_codec.media_codec_information = config_storage;
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
uint8_t channel_mode_bitmap = (media_codec[0] & 0x0F) & remote_channel_mode_bitmap;
|
||||
|
||||
uint8_t channel_mode = AVDTP_SBC_STEREO;
|
||||
if (channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO){
|
||||
channel_mode = AVDTP_SBC_JOINT_STEREO;
|
||||
} else if (channel_mode_bitmap & AVDTP_SBC_STEREO){
|
||||
channel_mode = AVDTP_SBC_STEREO;
|
||||
} else if (channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL){
|
||||
channel_mode = AVDTP_SBC_DUAL_CHANNEL;
|
||||
} else if (channel_mode_bitmap & AVDTP_SBC_MONO){
|
||||
channel_mode = AVDTP_SBC_MONO;
|
||||
}
|
||||
return channel_mode;
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
uint8_t allocation_method_bitmap = (media_codec[1] & 0x03) & remote_allocation_method_bitmap;
|
||||
|
||||
uint8_t allocation_method = AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS;
|
||||
if (allocation_method_bitmap & AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS){
|
||||
allocation_method = AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS;
|
||||
} else if (allocation_method_bitmap & AVDTP_SBC_ALLOCATION_METHOD_SNR){
|
||||
allocation_method = AVDTP_SBC_ALLOCATION_METHOD_SNR;
|
||||
}
|
||||
return allocation_method;
|
||||
}
|
||||
|
||||
uint8_t avdtp_stream_endpoint_seid(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
if (!stream_endpoint) return 0;
|
||||
return stream_endpoint->sep.seid;
|
||||
}
|
||||
uint8_t avdtp_choose_sbc_subbands(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_subbands_bitmap){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
uint8_t subbands_bitmap = ((media_codec[1] >> 2) & 0x03) & remote_subbands_bitmap;
|
||||
|
||||
uint8_t subbands = AVDTP_SBC_SUBBANDS_8;
|
||||
if (subbands_bitmap & AVDTP_SBC_SUBBANDS_8){
|
||||
subbands = AVDTP_SBC_SUBBANDS_8;
|
||||
} else if (subbands_bitmap & AVDTP_SBC_SUBBANDS_4){
|
||||
subbands = AVDTP_SBC_SUBBANDS_4;
|
||||
}
|
||||
return subbands;
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_block_length(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_block_length_bitmap){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
uint8_t block_length_bitmap = (media_codec[1] >> 4) & remote_block_length_bitmap;
|
||||
|
||||
uint8_t block_length = AVDTP_SBC_BLOCK_LENGTH_16;
|
||||
if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_16){
|
||||
block_length = AVDTP_SBC_BLOCK_LENGTH_16;
|
||||
} else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_12){
|
||||
block_length = AVDTP_SBC_BLOCK_LENGTH_12;
|
||||
} else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_8){
|
||||
block_length = AVDTP_SBC_BLOCK_LENGTH_8;
|
||||
} else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_4){
|
||||
block_length = AVDTP_SBC_BLOCK_LENGTH_4;
|
||||
}
|
||||
return block_length;
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
uint8_t sampling_frequency_bitmap = (media_codec[0] >> 4) & remote_sampling_frequency_bitmap;
|
||||
|
||||
uint8_t sampling_frequency = AVDTP_SBC_44100;
|
||||
if (sampling_frequency_bitmap & AVDTP_SBC_48000){
|
||||
sampling_frequency = AVDTP_SBC_48000;
|
||||
} else if (sampling_frequency_bitmap & AVDTP_SBC_44100){
|
||||
sampling_frequency = AVDTP_SBC_44100;
|
||||
} else if (sampling_frequency_bitmap & AVDTP_SBC_32000){
|
||||
sampling_frequency = AVDTP_SBC_32000;
|
||||
} else if (sampling_frequency_bitmap & AVDTP_SBC_16000){
|
||||
sampling_frequency = AVDTP_SBC_16000;
|
||||
}
|
||||
return sampling_frequency;
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_max_bitpool_value){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
return btstack_min(media_codec[3], remote_max_bitpool_value);
|
||||
}
|
||||
|
||||
uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_min_bitpool_value){
|
||||
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
|
||||
return btstack_max(media_codec[2], remote_min_bitpool_value);
|
||||
}
|
@ -60,16 +60,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_SEPS 10
|
||||
|
||||
// protocols
|
||||
#define PSM_AVCTP BLUETOOTH_PROTOCOL_AVCTP
|
||||
#define PSM_AVDTP BLUETOOTH_PROTOCOL_AVDTP
|
||||
|
||||
// service classes
|
||||
#define AUDIO_SOURCE_GROUP 0x110A
|
||||
#define AUDIO_SINK_GROUP 0x110B
|
||||
#define ADVANCED_AUDIO_DISTRIBUTION 0X110D
|
||||
|
||||
#define MAX_CSRC_NUM 15
|
||||
|
||||
// Supported Features
|
||||
@ -185,9 +175,10 @@ typedef struct {
|
||||
avdtp_media_type_t media_type;
|
||||
avdtp_media_codec_type_t media_codec_type;
|
||||
uint16_t media_codec_information_len;
|
||||
const uint8_t * media_codec_information;
|
||||
uint8_t * media_codec_information;
|
||||
} adtvp_media_codec_capabilities_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t cp_type;
|
||||
uint16_t cp_type_value_len;
|
||||
@ -292,7 +283,6 @@ typedef enum {
|
||||
|
||||
AVDTP_STREAM_ENDPOINT_OPENED,
|
||||
AVDTP_STREAM_ENDPOINT_STREAMING,
|
||||
AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND,
|
||||
|
||||
AVDTP_STREAM_ENDPOINT_CLOSING,
|
||||
AVDTP_STREAM_ENDPOINT_ABORTING,
|
||||
@ -307,8 +297,6 @@ typedef enum {
|
||||
|
||||
AVDTP_INITIATOR_W2_OPEN_STREAM,
|
||||
|
||||
AVDTP_INITIATOR_W2_STREAMING_START,
|
||||
AVDTP_INITIATOR_W2_STREAMING_STOP,
|
||||
AVDTP_INITIATOR_W2_STREAMING_ABORT,
|
||||
AVDTP_INITIATOR_FRAGMENTATED_COMMAND,
|
||||
AVDTP_INITIATOR_W4_ANSWER
|
||||
@ -349,6 +337,7 @@ typedef struct {
|
||||
|
||||
typedef enum {
|
||||
AVDTP_SIGNALING_CONNECTION_IDLE,
|
||||
AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE,
|
||||
AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED,
|
||||
AVDTP_SIGNALING_CONNECTION_OPENED,
|
||||
AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED
|
||||
@ -389,6 +378,7 @@ typedef struct {
|
||||
|
||||
bd_addr_t remote_addr;
|
||||
hci_con_handle_t con_handle;
|
||||
|
||||
uint16_t l2cap_signaling_cid;
|
||||
avdtp_service_mode_t service_mode;
|
||||
|
||||
@ -408,9 +398,6 @@ typedef struct {
|
||||
uint8_t int_seid;
|
||||
uint8_t acp_seid;
|
||||
|
||||
avdtp_capabilities_t remote_capabilities;
|
||||
uint16_t remote_capabilities_bitmap;
|
||||
|
||||
uint8_t wait_to_send_acceptor;
|
||||
uint8_t wait_to_send_initiator;
|
||||
uint8_t wait_to_send_self;
|
||||
@ -421,14 +408,38 @@ typedef struct {
|
||||
uint8_t reject_service_category;
|
||||
avdtp_signal_identifier_t reject_signal_identifier;
|
||||
uint8_t error_code;
|
||||
|
||||
// store configurations with remote seps
|
||||
avdtp_sep_t remote_seps[MAX_NUM_SEPS];
|
||||
uint8_t remote_seps_num;
|
||||
} avdtp_connection_t;
|
||||
|
||||
typedef enum {
|
||||
A2DP_IDLE,
|
||||
A2DP_CONNECTED,
|
||||
A2DP_W2_DISCOVER_SEPS,
|
||||
A2DP_W2_GET_CAPABILITIES,
|
||||
A2DP_W2_GET_ALL_CAPABILITIES,
|
||||
A2DP_W2_SET_CONFIGURATION,
|
||||
A2DP_W4_GET_CONFIGURATION,
|
||||
A2DP_W4_SET_CONFIGURATION,
|
||||
A2DP_W2_SUSPEND_STREAM_WITH_SEID,
|
||||
A2DP_W2_RECONFIGURE_WITH_SEID,
|
||||
A2DP_W2_OPEN_STREAM_WITH_SEID,
|
||||
A2DP_W4_OPEN_STREAM_WITH_SEID,
|
||||
A2DP_W2_START_STREAM_WITH_SEID,
|
||||
A2DP_W2_ABORT_STREAM_WITH_SEID,
|
||||
A2DP_W2_STOP_STREAM_WITH_SEID,
|
||||
A2DP_W2_GET_CONFIGURATION,
|
||||
A2DP_STREAMING_OPENED
|
||||
} a2dp_state_t;
|
||||
|
||||
typedef struct avdtp_stream_endpoint {
|
||||
btstack_linked_item_t item;
|
||||
|
||||
// original capabilities
|
||||
avdtp_sep_t sep;
|
||||
hci_con_handle_t media_con_handle;
|
||||
uint16_t l2cap_media_cid;
|
||||
uint16_t l2cap_reporting_cid;
|
||||
uint16_t l2cap_recovery_cid;
|
||||
@ -436,27 +447,26 @@ typedef struct avdtp_stream_endpoint {
|
||||
avdtp_stream_endpoint_state_t state;
|
||||
avdtp_acceptor_stream_endpoint_state_t acceptor_config_state;
|
||||
avdtp_initiator_stream_endpoint_state_t initiator_config_state;
|
||||
|
||||
a2dp_state_t a2dp_state;
|
||||
// active connection
|
||||
avdtp_connection_t * connection;
|
||||
// store configurations with remote seps
|
||||
avdtp_sep_t remote_seps[MAX_NUM_SEPS];
|
||||
uint8_t remote_seps_num;
|
||||
|
||||
// currently active remote seid
|
||||
uint8_t remote_sep_index;
|
||||
avdtp_capabilities_t remote_capabilities;
|
||||
uint16_t remote_capabilities_bitmap;
|
||||
|
||||
uint16_t remote_configuration_bitmap;
|
||||
avdtp_capabilities_t remote_configuration;
|
||||
// register request for media L2cap connection release
|
||||
uint8_t media_disconnect;
|
||||
uint8_t media_connect;
|
||||
|
||||
btstack_timer_source_t fill_audio_ring_buffer_timer;
|
||||
uint32_t time_audio_data_sent; // ms
|
||||
uint32_t acc_num_missed_samples;
|
||||
btstack_sbc_encoder_state_t sbc_encoder_state;
|
||||
uint16_t sequence_number;
|
||||
uint8_t start_stream;
|
||||
uint8_t stop_stream;
|
||||
uint8_t send_stream;
|
||||
uint8_t abort_stream;
|
||||
uint8_t suspend_stream;
|
||||
|
||||
btstack_ring_buffer_t audio_ring_buffer;
|
||||
btstack_ring_buffer_t sbc_ring_buffer;
|
||||
uint16_t sequence_number;
|
||||
} avdtp_stream_endpoint_t;
|
||||
|
||||
typedef struct {
|
||||
@ -464,6 +474,7 @@ typedef struct {
|
||||
btstack_linked_list_t stream_endpoints;
|
||||
uint16_t stream_endpoints_id_counter;
|
||||
btstack_packet_handler_t avdtp_callback;
|
||||
btstack_packet_handler_t a2dp_callback;
|
||||
void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
|
||||
btstack_packet_handler_t packet_handler;
|
||||
} avdtp_context_t;
|
||||
@ -474,7 +485,7 @@ void avdtp_register_delay_reporting_category(avdtp_stream_endpoint_t * stream_en
|
||||
void avdtp_register_recovery_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets);
|
||||
void avdtp_register_content_protection_category(avdtp_stream_endpoint_t * stream_endpoint, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len);
|
||||
void avdtp_register_header_compression_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t back_ch, uint8_t media, uint8_t recovery);
|
||||
void avdtp_register_media_codec_category(avdtp_stream_endpoint_t * stream_endpoint, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_register_media_codec_category(avdtp_stream_endpoint_t * stream_endpoint, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_register_multiplexing_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t fragmentation);
|
||||
void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_cid, avdtp_context_t * context);
|
||||
|
||||
@ -482,21 +493,34 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_context_t * context);
|
||||
avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context);
|
||||
|
||||
void avdtp_disconnect(uint16_t con_handle, avdtp_context_t * context);
|
||||
void avdtp_open_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_start_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_stop_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_abort_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_discover_stream_endpoints(uint16_t con_handle, avdtp_context_t * context);
|
||||
void avdtp_get_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_get_configuration(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
|
||||
void avdtp_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
|
||||
void avdtp_suspend(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * context);
|
||||
void avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context);
|
||||
void avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context);
|
||||
void avdtp_stop_stream (uint8_t int_seid, avdtp_context_t * context);
|
||||
void avdtp_abort_stream(uint8_t int_seid, avdtp_context_t * context);
|
||||
void avdtp_suspend_stream(uint8_t int_seid, avdtp_context_t * context);
|
||||
|
||||
void avdtp_source_stream_data_start(uint16_t con_handle);
|
||||
void avdtp_source_stream_data_stop(uint16_t con_handle);
|
||||
void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context);
|
||||
void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
|
||||
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
|
||||
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context);
|
||||
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context);
|
||||
|
||||
void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size);
|
||||
uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap);
|
||||
uint8_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap);
|
||||
|
||||
uint8_t avdtp_choose_sbc_subbands(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_subbands_bitmap);
|
||||
uint8_t avdtp_choose_sbc_block_length(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_block_length_bitmap);
|
||||
uint8_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap);
|
||||
uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_max_bitpool_value);
|
||||
uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_min_bitpool_value);
|
||||
|
||||
uint8_t avdtp_stream_endpoint_seid(avdtp_stream_endpoint_t * stream_endpoint);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static int avdtp_acceptor_validate_msg_length(avdtp_signal_identifier_t signal_i
|
||||
void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t * packet, uint16_t size, int offset, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint;
|
||||
connection->acceptor_transaction_label = connection->signaling_packet.transaction_label;
|
||||
|
||||
|
||||
if (!avdtp_acceptor_validate_msg_length(connection->signaling_packet.signal_identifier, size)) {
|
||||
connection->error_code = BAD_LENGTH;
|
||||
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
|
||||
@ -98,7 +98,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
switch (connection->signaling_packet.signal_identifier){
|
||||
case AVDTP_SI_DISCOVER:
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
printf(" ACP: AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS\n");
|
||||
log_info(" ACP: AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS");
|
||||
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS;
|
||||
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
|
||||
return;
|
||||
@ -114,7 +114,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
connection->query_seid = packet[offset++] >> 2;
|
||||
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->query_seid, context);
|
||||
if (!stream_endpoint){
|
||||
printf(" ACP: cmd %d - RESPONSE REJECT\n", connection->signaling_packet.signal_identifier);
|
||||
log_info(" ACP: cmd %d - RESPONSE REJECT", connection->signaling_packet.signal_identifier);
|
||||
connection->error_code = BAD_ACP_SEID;
|
||||
if (connection->signaling_packet.signal_identifier == AVDTP_SI_OPEN){
|
||||
connection->error_code = BAD_STATE;
|
||||
@ -133,18 +133,18 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
|
||||
case AVDTP_SI_SUSPEND:{
|
||||
int i;
|
||||
printf(" ACP: AVDTP_SI_SUSPEND seids: ");
|
||||
log_info(" ACP: AVDTP_SI_SUSPEND seids: ");
|
||||
connection->num_suspended_seids = 0;
|
||||
|
||||
for (i = offset; i < size; i++){
|
||||
connection->suspended_seids[connection->num_suspended_seids] = packet[i] >> 2;
|
||||
offset++;
|
||||
printf("%d, \n", connection->suspended_seids[connection->num_suspended_seids]);
|
||||
log_info("%d, ", connection->suspended_seids[connection->num_suspended_seids]);
|
||||
connection->num_suspended_seids++;
|
||||
}
|
||||
|
||||
if (connection->num_suspended_seids == 0) {
|
||||
printf(" ACP: CATEGORY RESPONSE REJECT BAD_ACP_SEID\n");
|
||||
log_info(" ACP: CATEGORY RESPONSE REJECT BAD_ACP_SEID");
|
||||
connection->error_code = BAD_ACP_SEID;
|
||||
connection->reject_service_category = connection->query_seid;
|
||||
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
@ -156,7 +156,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
connection->query_seid = connection->suspended_seids[0];
|
||||
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->query_seid, context);
|
||||
if (!stream_endpoint){
|
||||
printf(" ACP: stream_endpoint not found, CATEGORY RESPONSE REJECT BAD_ACP_SEID\n");
|
||||
log_info(" ACP: stream_endpoint not found, CATEGORY RESPONSE REJECT BAD_ACP_SEID");
|
||||
connection->error_code = BAD_ACP_SEID;
|
||||
connection->reject_service_category = connection->query_seid;
|
||||
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
@ -170,7 +170,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
default:
|
||||
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
printf("AVDTP_CMD_MSG signal %d not implemented, general reject\n", connection->signaling_packet.signal_identifier);
|
||||
log_info("AVDTP_CMD_MSG signal %d not implemented, general reject", connection->signaling_packet.signal_identifier);
|
||||
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
|
||||
return;
|
||||
}
|
||||
@ -189,45 +189,41 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE:
|
||||
switch (connection->signaling_packet.signal_identifier){
|
||||
case AVDTP_SI_GET_ALL_CAPABILITIES:
|
||||
printf(" ACP: AVDTP_SI_GET_ALL_CAPABILITIES\n");
|
||||
log_info(" ACP: AVDTP_SI_GET_ALL_CAPABILITIES");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES;
|
||||
break;
|
||||
case AVDTP_SI_GET_CAPABILITIES:
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES;
|
||||
break;
|
||||
case AVDTP_SI_SET_CONFIGURATION:{
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION \n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION ");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION;
|
||||
connection->reject_service_category = 0;
|
||||
|
||||
stream_endpoint->connection = connection;
|
||||
avdtp_sep_t sep;
|
||||
sep.seid = connection->signaling_packet.command[offset++] >> 2;
|
||||
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+offset, packet_size-offset);
|
||||
sep.in_use = 1;
|
||||
|
||||
if (connection->error_code){
|
||||
printf("fire configuration parsing errors \n");
|
||||
log_info("fire configuration parsing errors ");
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
break;
|
||||
}
|
||||
// find or add sep
|
||||
int i;
|
||||
stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
|
||||
for (i=0; i < stream_endpoint->remote_seps_num; i++){
|
||||
if (stream_endpoint->remote_seps[i].seid == sep.seid){
|
||||
stream_endpoint->remote_sep_index = i;
|
||||
}
|
||||
}
|
||||
printf(" ACP .. seid %d, index %d\n", sep.seid, stream_endpoint->remote_sep_index);
|
||||
|
||||
stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid);
|
||||
log_info(" ACP .. seid %d, index %d", sep.seid, stream_endpoint->remote_sep_index);
|
||||
|
||||
if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){
|
||||
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].in_use){
|
||||
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].in_use){
|
||||
// reject if already configured
|
||||
connection->error_code = SEP_IN_USE;
|
||||
// find first registered category and fire the error
|
||||
connection->reject_service_category = 0;
|
||||
int i;
|
||||
for (i = 1; i < 9; i++){
|
||||
if (get_bit16(sep.configured_service_categories, i)){
|
||||
connection->reject_service_category = i;
|
||||
@ -237,29 +233,28 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
} else {
|
||||
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" ACP: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
log_info(" ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
}
|
||||
} else {
|
||||
// add new
|
||||
printf(" ACP: seid %d not found in %p\n", sep.seid, stream_endpoint);
|
||||
stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num;
|
||||
stream_endpoint->remote_seps_num++;
|
||||
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" ACP: add seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
log_info(" ACP: seid %d not found in %p", sep.seid, stream_endpoint);
|
||||
stream_endpoint->remote_sep_index = connection->remote_seps_num;
|
||||
connection->remote_seps_num++;
|
||||
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
log_info(" ACP: add seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
}
|
||||
|
||||
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.configuration.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->con_handle, sep.configuration.media_codec);
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->con_handle, sep.configuration.media_codec);
|
||||
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier, 0);
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, 0);
|
||||
break;
|
||||
}
|
||||
case AVDTP_SI_RECONFIGURE:{
|
||||
@ -268,8 +263,8 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
|
||||
avdtp_sep_t sep;
|
||||
sep.seid = connection->query_seid;
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE seid %d\n", sep.seid);
|
||||
// printf_hexdump(connection->signaling_packet.command, packet_size);
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE seid %d", sep.seid);
|
||||
// log_info_hexdump(connection->signaling_packet.command, packet_size);
|
||||
|
||||
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+offset, packet_size-offset);
|
||||
|
||||
@ -281,76 +276,70 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
}
|
||||
|
||||
// find sep or raise error
|
||||
int i;
|
||||
stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
|
||||
for (i = 0; i < stream_endpoint->remote_seps_num; i++){
|
||||
if (stream_endpoint->remote_seps[i].seid == sep.seid){
|
||||
stream_endpoint->remote_sep_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid);
|
||||
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX){
|
||||
printf(" ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID\n");
|
||||
log_info(" ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_ACP_SEID;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
break;
|
||||
}
|
||||
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" ACP: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
log_info(" ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
|
||||
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.capabilities.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_reconfiguration(context->avdtp_callback, connection->con_handle, sep.capabilities.media_codec);
|
||||
avdtp_signaling_emit_media_codec_sbc_reconfiguration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_reconfiguration(context->avdtp_callback, connection->con_handle, sep.capabilities.media_codec);
|
||||
avdtp_signaling_emit_media_codec_other_reconfiguration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier, 0);
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case AVDTP_SI_GET_CONFIGURATION:
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION;
|
||||
break;
|
||||
case AVDTP_SI_OPEN:
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_CONFIGURED){
|
||||
printf(" ACP: REJECT AVDTP_SI_OPEN, BAD_STATE\n");
|
||||
log_info(" ACP: REJECT AVDTP_SI_OPEN, BAD_STATE");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_STATE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
break;
|
||||
}
|
||||
printf(" ACP: AVDTP_STREAM_ENDPOINT_W2_ANSWER_OPEN_STREAM\n");
|
||||
log_info(" ACP: AVDTP_STREAM_ENDPOINT_W2_ANSWER_OPEN_STREAM");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM;
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED;
|
||||
connection->query_seid = stream_endpoint->sep.seid;
|
||||
break;
|
||||
case AVDTP_SI_START:
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_OPENED){
|
||||
printf(" ACP: REJECT AVDTP_SI_START, BAD_STATE\n");
|
||||
log_info(" ACP: REJECT AVDTP_SI_START, BAD_STATE");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_STATE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
break;
|
||||
}
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM;
|
||||
break;
|
||||
case AVDTP_SI_CLOSE:
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM;
|
||||
break;
|
||||
default:
|
||||
printf(" ACP: AVDTP_SI_CLOSE, bad state %d \n", stream_endpoint->state);
|
||||
log_info(" ACP: AVDTP_SI_CLOSE, bad state %d ", stream_endpoint->state);
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_STATE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
@ -363,12 +352,12 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
case AVDTP_STREAM_ENDPOINT_CLOSING:
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM;
|
||||
break;
|
||||
default:
|
||||
printf(" ACP: AVDTP_SI_ABORT, bad state %d \n", stream_endpoint->state);
|
||||
log_info(" ACP: AVDTP_SI_ABORT, bad state %d ", stream_endpoint->state);
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_STATE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
@ -376,19 +365,19 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
}
|
||||
break;
|
||||
case AVDTP_SI_SUSPEND:
|
||||
printf(" entering AVDTP_SI_SUSPEND\n");
|
||||
log_info(" entering AVDTP_SI_SUSPEND");
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
|
||||
connection->num_suspended_seids--;
|
||||
if (connection->num_suspended_seids <= 0){
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM\n");
|
||||
log_info(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf(" ACP: AVDTP_SI_SUSPEND, bad state \n");
|
||||
log_info(" ACP: AVDTP_SI_SUSPEND, bad state ");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
|
||||
connection->error_code = BAD_STATE;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
@ -399,7 +388,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
//stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_SUSPEND_STREAM;
|
||||
break;
|
||||
default:
|
||||
printf(" ACP: NOT IMPLEMENTED, Reject signal_identifier %02x\n", connection->signaling_packet.signal_identifier);
|
||||
log_info(" ACP: NOT IMPLEMENTED, Reject signal_identifier %02x", connection->signaling_packet.signal_identifier);
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD;
|
||||
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
|
||||
break;
|
||||
@ -410,7 +399,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
}
|
||||
|
||||
if (!request_to_send){
|
||||
printf(" ACP: NOT IMPLEMENTED\n");
|
||||
log_info(" ACP: NOT IMPLEMENTED");
|
||||
}
|
||||
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
@ -488,7 +477,7 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
|
||||
break;
|
||||
}
|
||||
if (sent){
|
||||
printf(" ACP: DONE\n");
|
||||
log_info(" ACP: DONE");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -517,9 +506,9 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
|
||||
pos = avdtp_signaling_create_fragment(cid, &connection->signaling_packet, out_buffer);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
log_info(" ACP: fragmented");
|
||||
} else {
|
||||
printf(" ACP:DONE\n");
|
||||
log_info(" ACP:DONE");
|
||||
}
|
||||
l2cap_send_prepared(cid, pos);
|
||||
break;
|
||||
@ -530,92 +519,89 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
|
||||
pos = avdtp_signaling_create_fragment(cid, &connection->signaling_packet, out_buffer);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
log_info(" ACP: fragmented");
|
||||
} else {
|
||||
printf(" ACP:DONE\n");
|
||||
log_info(" ACP:DONE");
|
||||
}
|
||||
l2cap_send_prepared(cid, pos);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION:
|
||||
printf(" ACP: DONE\n");
|
||||
printf(" -> AVDTP_STREAM_ENDPOINT_CONFIGURED\n");
|
||||
log_info(" ACP: DONE");
|
||||
log_info(" -> AVDTP_STREAM_ENDPOINT_CONFIGURED");
|
||||
stream_endpoint->connection = connection;
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
|
||||
// TODO: use actual config
|
||||
// TODO: consider reconfiguration
|
||||
btstack_sbc_encoder_init(&stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53);
|
||||
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_SET_CONFIGURATION);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE:
|
||||
printf(" ACP: DONE \n");
|
||||
log_info(" ACP: DONE ");
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_RECONFIGURE);
|
||||
break;
|
||||
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:{
|
||||
avdtp_sep_t sep = stream_endpoint->remote_seps[stream_endpoint->remote_sep_index];
|
||||
avdtp_sep_t sep = stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index];
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, trid, sep.configured_service_categories, sep.configuration, AVDTP_SI_GET_CONFIGURATION);
|
||||
l2cap_reserve_packet_buffer();
|
||||
out_buffer = l2cap_get_outgoing_buffer();
|
||||
pos = avdtp_signaling_create_fragment(cid, &connection->signaling_packet, out_buffer);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
log_info(" ACP: fragmented");
|
||||
} else {
|
||||
printf(" ACP:DONE\n");
|
||||
log_info(" ACP:DONE");
|
||||
}
|
||||
l2cap_send_prepared(cid, pos);
|
||||
break;
|
||||
}
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM:
|
||||
printf(" ACP: DONE\n");
|
||||
log_info(" ACP: DONE");
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_OPEN);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM:
|
||||
printf(" ACP: DONE \n");
|
||||
printf(" -> AVDTP_STREAM_ENDPOINT_STREAMING \n");
|
||||
log_info(" ACP: DONE ");
|
||||
log_info(" -> AVDTP_STREAM_ENDPOINT_STREAMING ");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_START);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM:
|
||||
printf(" ACP: DONE\n");
|
||||
log_info(" ACP: DONE");
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_CLOSE);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM:
|
||||
printf(" ACP: DONE\n");
|
||||
log_info(" ACP: DONE");
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_ABORT);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM:
|
||||
printf(" ACP: DONE\n");
|
||||
log_info(" ACP: DONE");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
|
||||
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_SUSPEND);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD:
|
||||
status = 1;
|
||||
printf(" ACP: DONE REJECT\n");
|
||||
log_info(" ACP: DONE REJECT");
|
||||
connection->reject_signal_identifier = 0;
|
||||
avdtp_acceptor_send_response_reject(cid, reject_signal_identifier, trid);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE:
|
||||
status = 1;
|
||||
printf(" ACP: DONE REJECT CATEGORY\n");
|
||||
log_info(" ACP: DONE REJECT CATEGORY");
|
||||
connection->reject_service_category = 0;
|
||||
avdtp_acceptor_send_response_reject_service_category(cid, reject_signal_identifier, reject_service_category, error_code, trid);
|
||||
break;
|
||||
|
||||
case AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE:
|
||||
status = 1;
|
||||
printf(" ACP: DONE REJECT\n");
|
||||
log_info(" ACP: DONE REJECT");
|
||||
connection->reject_signal_identifier = 0;
|
||||
connection->error_code = 0;
|
||||
avdtp_acceptor_send_response_reject_with_error_code(cid, reject_signal_identifier, error_code, trid);
|
||||
break;
|
||||
default:
|
||||
status = 0;
|
||||
printf(" ACP: NOT IMPLEMENTED\n");
|
||||
log_info(" ACP: NOT IMPLEMENTED");
|
||||
sent = 0;
|
||||
}
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier, status);
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, status);
|
||||
|
||||
// check fragmentation
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
|
@ -65,32 +65,6 @@ static int avdtp_initiator_send_signaling_cmd_with_seid(uint16_t cid, avdtp_sign
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
static void avdtp_signaling_emit_media_codec_capability(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
|
||||
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.capabilities.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_capability(callback, con_handle, sep.capabilities.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_capability(callback, con_handle, sep.capabilities.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void avdtp_signaling_emit_media_codec_configuration(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
|
||||
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.capabilities.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(callback, con_handle, sep.capabilities.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_configuration(callback, con_handle, sep.capabilities.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset, avdtp_context_t * context){
|
||||
int status = 0;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
@ -107,25 +81,23 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
if (!stream_endpoint) return;
|
||||
sep.seid = connection->acp_seid;
|
||||
|
||||
printf(" INT: local seid %d, remote seid %d, ident %d \n", connection->int_seid, connection->acp_seid, connection->signaling_packet.signal_identifier);
|
||||
if (stream_endpoint->initiator_config_state != AVDTP_INITIATOR_W4_ANSWER) return;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
|
||||
}
|
||||
|
||||
switch (connection->signaling_packet.message_type){
|
||||
case AVDTP_RESPONSE_ACCEPT_MSG:
|
||||
printf(" INT: AVDTP_RESPONSE_ACCEPT_MSG: ");
|
||||
switch (connection->signaling_packet.signal_identifier){
|
||||
case AVDTP_SI_DISCOVER:{
|
||||
printf("AVDTP_SI_DISCOVER\n");
|
||||
log_info("AVDTP_SI_DISCOVER");
|
||||
if (connection->signaling_packet.transaction_label != connection->initiator_transaction_label){
|
||||
printf(" unexpected transaction label, got %d, expected %d\n", connection->signaling_packet.transaction_label, connection->initiator_transaction_label);
|
||||
log_info(" unexpected transaction label, got %d, expected %d", connection->signaling_packet.transaction_label, connection->initiator_transaction_label);
|
||||
status = BAD_HEADER_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == 3){
|
||||
printf(" ERROR code %02x\n", packet[offset]);
|
||||
log_info(" ERROR code %02x", packet[offset]);
|
||||
status = packet[offset];
|
||||
break;
|
||||
}
|
||||
@ -135,73 +107,90 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
sep.seid = packet[i] >> 2;
|
||||
offset++;
|
||||
if (sep.seid < 0x01 || sep.seid > 0x3E){
|
||||
printf(" invalid sep id\n");
|
||||
log_info(" invalid sep id");
|
||||
status = BAD_ACP_SEID;
|
||||
break;
|
||||
}
|
||||
sep.in_use = (packet[i] >> 1) & 0x01;
|
||||
sep.media_type = (avdtp_media_type_t)(packet[i+1] >> 4);
|
||||
sep.type = (avdtp_sep_type_t)((packet[i+1] >> 3) & 0x01);
|
||||
avdtp_signaling_emit_sep(context->avdtp_callback, connection->con_handle, sep);
|
||||
|
||||
if (avdtp_find_remote_sep(connection, sep.seid) == 0xFF){
|
||||
connection->remote_seps[connection->remote_seps_num++] = sep;
|
||||
}
|
||||
avdtp_signaling_emit_sep(context->avdtp_callback, connection->l2cap_signaling_cid, sep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AVDTP_SI_GET_CAPABILITIES:
|
||||
case AVDTP_SI_GET_ALL_CAPABILITIES:
|
||||
printf("AVDTP_SI_GET(_ALL)_CAPABILITIES\n");
|
||||
log_info("AVDTP_SI_GET(_ALL)_CAPABILITIES int %d, acp %d", connection->int_seid, connection->acp_seid);
|
||||
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+offset, size-offset);
|
||||
avdtp_signaling_emit_media_codec_capability(context->avdtp_callback, connection->con_handle, sep);
|
||||
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.capabilities.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_capability(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_capability(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AVDTP_SI_GET_CONFIGURATION:
|
||||
printf("AVDTP_SI_GET_CONFIGURATION\n");
|
||||
log_info("AVDTP_SI_GET_CONFIGURATION");
|
||||
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, packet+offset, size-offset);
|
||||
|
||||
avdtp_signaling_emit_media_codec_configuration(context->avdtp_callback, connection->con_handle, sep);
|
||||
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.configuration.media_codec.media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
|
||||
break;
|
||||
default:
|
||||
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AVDTP_SI_RECONFIGURE:
|
||||
printf("AVDTP_SI_RECONFIGURE\n");
|
||||
log_info("AVDTP_SI_RECONFIGURE");
|
||||
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+4, connection->signaling_packet.size-4);
|
||||
// TODO check if configuration is supported
|
||||
|
||||
remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid);
|
||||
remote_sep_index = avdtp_find_remote_sep(connection, sep.seid);
|
||||
if (remote_sep_index != 0xFF){
|
||||
stream_endpoint->remote_sep_index = remote_sep_index;
|
||||
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
|
||||
printf(" INT: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
log_info(" INT: update seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
}
|
||||
break;
|
||||
|
||||
case AVDTP_SI_SET_CONFIGURATION:{
|
||||
printf("AVDTP_SI_SET_CONFIGURATION\n");
|
||||
sep.configured_service_categories = connection->remote_capabilities_bitmap;
|
||||
sep.configuration = connection->remote_capabilities;
|
||||
log_info("AVDTP_SI_SET_CONFIGURATION");
|
||||
sep.configured_service_categories = stream_endpoint->remote_capabilities_bitmap;
|
||||
sep.configuration = stream_endpoint->remote_capabilities;
|
||||
sep.in_use = 1;
|
||||
// TODO check if configuration is supported
|
||||
|
||||
// find or add sep
|
||||
remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid);
|
||||
remote_sep_index = avdtp_find_remote_sep(connection, sep.seid);
|
||||
if (remote_sep_index != 0xFF){
|
||||
stream_endpoint->remote_sep_index = remote_sep_index;
|
||||
} else {
|
||||
stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num;
|
||||
stream_endpoint->remote_seps_num++;
|
||||
stream_endpoint->remote_sep_index = connection->remote_seps_num;
|
||||
stream_endpoint->connection->remote_seps_num++;
|
||||
}
|
||||
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" INT: configured remote seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
log_info(" INT: configured remote seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
|
||||
|
||||
// TODO: use actual config
|
||||
// TODO: consider reconfiguration
|
||||
btstack_sbc_encoder_init(&stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53);
|
||||
break;
|
||||
}
|
||||
|
||||
case AVDTP_SI_OPEN:
|
||||
printf("AVDTP_SI_OPEN\n");
|
||||
log_info("AVDTP_SI_OPEN");
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM) {
|
||||
log_error("AVDTP_SI_OPEN in wrong stream endpoint state");
|
||||
return;
|
||||
@ -211,15 +200,16 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
l2cap_create_channel(context->packet_handler, connection->remote_addr, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, NULL);
|
||||
return;
|
||||
case AVDTP_SI_START:
|
||||
printf("AVDTP_SI_START\n");
|
||||
log_info("AVDTP_SI_START");
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_OPENED) {
|
||||
log_error("AVDTP_SI_START in wrong stream endpoint state");
|
||||
return;
|
||||
}
|
||||
log_info("AVDTP_STREAM_ENDPOINT_STREAMING");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
break;
|
||||
case AVDTP_SI_SUSPEND:
|
||||
printf("AVDTP_SI_SUSPEND\n");
|
||||
log_info("AVDTP_SI_SUSPEND");
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_STREAMING) {
|
||||
log_error("AVDTP_SI_SUSPEND in wrong stream endpoint state");
|
||||
return;
|
||||
@ -227,58 +217,54 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
|
||||
break;
|
||||
case AVDTP_SI_CLOSE:
|
||||
printf("AVDTP_SI_CLOSE\n");
|
||||
log_info("AVDTP_SI_CLOSE");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING;
|
||||
break;
|
||||
case AVDTP_SI_ABORT:
|
||||
printf("AVDTP_SI_ABORT\n");
|
||||
log_info("AVDTP_SI_ABORT");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
|
||||
break;
|
||||
default:
|
||||
status = 1;
|
||||
printf(" AVDTP_RESPONSE_ACCEPT_MSG, signal %d not implemented\n", connection->signaling_packet.signal_identifier);
|
||||
log_info(" AVDTP_RESPONSE_ACCEPT_MSG, signal %d not implemented", connection->signaling_packet.signal_identifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->l2cap_signaling_cid, 0, connection->signaling_packet.signal_identifier, status);
|
||||
connection->initiator_transaction_label++;
|
||||
break;
|
||||
case AVDTP_RESPONSE_REJECT_MSG:
|
||||
printf(" AVDTP_RESPONSE_REJECT_MSG signal %d\n", connection->signaling_packet.signal_identifier);
|
||||
avdtp_signaling_emit_reject(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier);
|
||||
log_info(" AVDTP_RESPONSE_REJECT_MSG signal %d", connection->signaling_packet.signal_identifier);
|
||||
avdtp_signaling_emit_reject(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->signaling_packet.signal_identifier);
|
||||
return;
|
||||
case AVDTP_GENERAL_REJECT_MSG:
|
||||
printf(" AVDTP_GENERAL_REJECT_MSG signal %d\n", connection->signaling_packet.signal_identifier);
|
||||
avdtp_signaling_emit_general_reject(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier);
|
||||
log_info(" AVDTP_GENERAL_REJECT_MSG signal %d", connection->signaling_packet.signal_identifier);
|
||||
avdtp_signaling_emit_general_reject(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->signaling_packet.signal_identifier);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
connection->initiator_transaction_label++;
|
||||
connection->int_seid = 0;
|
||||
connection->acp_seid = 0;
|
||||
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->signaling_packet.signal_identifier, status);
|
||||
}
|
||||
|
||||
void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_context_t * context){
|
||||
int sent = 1;
|
||||
|
||||
switch (connection->initiator_connection_state){
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
|
||||
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS\n");
|
||||
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
|
||||
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES\n");
|
||||
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES:
|
||||
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES\n");
|
||||
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION:
|
||||
printf(" INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION\n");
|
||||
log_info(" INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
@ -289,9 +275,8 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
|
||||
if (sent) return;
|
||||
sent = 1;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
|
||||
// printf(" run int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
|
||||
stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid, context);
|
||||
if (!stream_endpoint){
|
||||
@ -301,12 +286,69 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
|
||||
avdtp_initiator_stream_endpoint_state_t stream_endpoint_state = stream_endpoint->initiator_config_state;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W4_ANSWER;
|
||||
|
||||
if (stream_endpoint->start_stream){
|
||||
stream_endpoint->start_stream = 0;
|
||||
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_OPENED){
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label++, connection->acp_seid);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->stop_stream){
|
||||
stream_endpoint->stop_stream = 0;
|
||||
if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED){
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label++, connection->acp_seid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_endpoint->abort_stream){
|
||||
stream_endpoint->abort_stream = 0;
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_CONFIGURED:
|
||||
case AVDTP_STREAM_ENDPOINT_CLOSING:
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label++, connection->acp_seid);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_endpoint->suspend_stream){
|
||||
stream_endpoint->suspend_stream = 0;
|
||||
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING){
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_endpoint->send_stream){
|
||||
stream_endpoint->send_stream = 0;
|
||||
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING){
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
avdtp_streaming_emit_can_send_media_packet_now(context->avdtp_callback, stream_endpoint->l2cap_media_cid, stream_endpoint->sep.seid, stream_endpoint->sequence_number);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (stream_endpoint_state){
|
||||
case AVDTP_INITIATOR_W2_SET_CONFIGURATION:
|
||||
case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{
|
||||
printf(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid);
|
||||
// printf_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
|
||||
log_info(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d", connection->int_seid, connection->acp_seid);
|
||||
// log_info_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
|
||||
connection->signaling_packet.acp_seid = connection->acp_seid;
|
||||
connection->signaling_packet.int_seid = connection->int_seid;
|
||||
|
||||
@ -316,13 +358,13 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
connection->signaling_packet.signal_identifier = AVDTP_SI_RECONFIGURE;
|
||||
}
|
||||
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, connection->signaling_packet.signal_identifier);
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, stream_endpoint->remote_capabilities_bitmap, stream_endpoint->remote_capabilities, connection->signaling_packet.signal_identifier);
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * out_buffer = l2cap_get_outgoing_buffer();
|
||||
uint16_t pos = avdtp_signaling_create_fragment(connection->l2cap_signaling_cid, &connection->signaling_packet, out_buffer);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
|
||||
printf(" INT: fragmented\n");
|
||||
log_info(" INT: fragmented");
|
||||
}
|
||||
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
|
||||
break;
|
||||
@ -333,7 +375,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
uint16_t pos = avdtp_signaling_create_fragment(connection->l2cap_signaling_cid, &connection->signaling_packet, out_buffer);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
|
||||
printf(" INT: fragmented\n");
|
||||
log_info(" INT: fragmented");
|
||||
}
|
||||
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
|
||||
break;
|
||||
@ -341,35 +383,19 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
case AVDTP_INITIATOR_W2_OPEN_STREAM:
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM:
|
||||
printf(" INT: AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM\n");
|
||||
log_info(" INT: AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM");
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
default:
|
||||
sent = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID:
|
||||
printf(" INT: AVDTP_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID\n");
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_STREAMING_START:
|
||||
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_START\n");
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_STREAMING_STOP:
|
||||
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_STOP\n");
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_STREAMING_ABORT:
|
||||
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_ABORT\n");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label, connection->acp_seid);
|
||||
break;
|
||||
default:
|
||||
sent = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// check fragmentation
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
#define __BTSTACK_FILE__ "avdtp_sink.c"
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -51,95 +50,10 @@
|
||||
#include "avdtp_initiator.h"
|
||||
#include "avdtp_acceptor.h"
|
||||
|
||||
static const char * default_avdtp_sink_service_name = "BTstack AVDTP Sink Service";
|
||||
static const char * default_avdtp_sink_service_provider_name = "BTstack AVDTP Sink Service Provider";
|
||||
|
||||
static avdtp_context_t avdtp_sink_context;
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
//static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
|
||||
|
||||
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
||||
uint8_t* attribute;
|
||||
de_create_sequence(service);
|
||||
|
||||
// 0x0000 "Service Record Handle"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
|
||||
|
||||
// 0x0001 "Service Class ID List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, AUDIO_SINK_GROUP);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0004 "Protocol Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t* l2cpProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
|
||||
de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
de_pop_sequence(attribute, l2cpProtocol);
|
||||
|
||||
uint8_t* avProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service
|
||||
de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version
|
||||
}
|
||||
de_pop_sequence(attribute, avProtocol);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0005 "Public Browse Group"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0009 "Bluetooth Profile Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t *a2dProfile = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, ADVANCED_AUDIO_DISTRIBUTION);
|
||||
de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103);
|
||||
}
|
||||
de_pop_sequence(attribute, a2dProfile);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
|
||||
// 0x0100 "Service Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
if (service_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_name), (uint8_t *) default_avdtp_sink_service_name);
|
||||
}
|
||||
|
||||
// 0x0100 "Provider Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102);
|
||||
if (service_provider_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_provider_name), (uint8_t *) default_avdtp_sink_service_provider_name);
|
||||
}
|
||||
|
||||
// 0x0311 "Supported Features"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
|
||||
}
|
||||
|
||||
|
||||
void avdtp_sink_register_media_transport_category(uint8_t seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context);
|
||||
avdtp_register_media_transport_category(stream_endpoint);
|
||||
@ -170,7 +84,7 @@ void avdtp_sink_register_header_compression_category(uint8_t seid, uint8_t back_
|
||||
avdtp_register_header_compression_category(stream_endpoint, back_ch, media, recovery);
|
||||
}
|
||||
|
||||
void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_sink_context);
|
||||
avdtp_register_media_codec_category(stream_endpoint, media_type, media_codec_type, media_codec_info, media_codec_info_len);
|
||||
}
|
||||
@ -198,7 +112,7 @@ void avdtp_sink_init(void){
|
||||
avdtp_sink_context.stream_endpoints = NULL;
|
||||
avdtp_sink_context.connections = NULL;
|
||||
avdtp_sink_context.stream_endpoints_id_counter = 0;
|
||||
// TODO: assign dummy handlers;
|
||||
avdtp_sink_context.packet_handler = packet_handler;
|
||||
|
||||
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
|
||||
}
|
||||
@ -223,60 +137,55 @@ void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback){
|
||||
avdtp_sink_context.avdtp_callback = callback;
|
||||
}
|
||||
|
||||
void avdtp_sink_connect(bd_addr_t bd_addr){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_bd_addr(bd_addr, &avdtp_sink_context);
|
||||
if (!connection){
|
||||
connection = avdtp_create_connection(bd_addr, &avdtp_sink_context);
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return;
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
l2cap_create_channel(packet_handler, connection->remote_addr, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, NULL);
|
||||
void avdtp_sink_connect(bd_addr_t remote){
|
||||
avdtp_connect(remote, AVDTP_SOURCE, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_disconnect(uint16_t con_handle){
|
||||
avdtp_disconnect(con_handle, &avdtp_sink_context);
|
||||
void avdtp_sink_disconnect(uint16_t avdtp_cid){
|
||||
avdtp_disconnect(avdtp_cid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_open_stream(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_open_stream(avdtp_cid, int_seid, acp_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_start_stream(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_stop_stream(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_stop_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_abort_stream(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_abort_stream(uint8_t int_seid){
|
||||
avdtp_abort_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_discover_stream_endpoints(uint16_t con_handle){
|
||||
avdtp_discover_stream_endpoints(con_handle, &avdtp_sink_context);
|
||||
void avdtp_sink_suspend(uint8_t int_seid){
|
||||
avdtp_suspend_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_capabilities(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid){
|
||||
avdtp_discover_stream_endpoints(avdtp_cid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_all_capabilities(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){
|
||||
avdtp_get_capabilities(avdtp_cid, acp_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_configuration(con_handle, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){
|
||||
avdtp_get_all_capabilities(avdtp_cid, acp_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_set_configuration(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context);
|
||||
void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid){
|
||||
avdtp_get_configuration(avdtp_cid, acp_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_reconfigure(con_handle, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context);
|
||||
void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_set_configuration(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_reconfigure(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_suspend(con_handle, acp_seid, &avdtp_sink_context);
|
||||
}
|
@ -55,15 +55,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* API_START */
|
||||
/**
|
||||
* @brief AVDTP Sink service record.
|
||||
* @param service
|
||||
* @param service_record_handle
|
||||
* @param supported_features 16-bit bitmap, see AVDTP_SINK_SF_* values in avdtp.h
|
||||
* @param service_name
|
||||
* @param service_provider_name
|
||||
*/
|
||||
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
|
||||
|
||||
/**
|
||||
* @brief Set up AVDTP Sink device.
|
||||
@ -80,7 +71,7 @@ void avdtp_sink_register_recovery_category(uint8_t seid, uint8_t maximum_recover
|
||||
void avdtp_sink_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery);
|
||||
void avdtp_sink_register_multiplexing_category(uint8_t seid, uint8_t fragmentation);
|
||||
|
||||
void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_sink_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len);
|
||||
|
||||
/**
|
||||
@ -98,82 +89,79 @@ void avdtp_sink_connect(bd_addr_t bd_addr);
|
||||
void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
|
||||
/**
|
||||
* @brief Disconnect from device with connection handle.
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_disconnect(uint16_t con_handle);
|
||||
void avdtp_sink_disconnect(uint16_t avdtp_cid);
|
||||
|
||||
/**
|
||||
* @brief Discover stream endpoints
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_discover_stream_endpoints(uint16_t con_handle);
|
||||
void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid);
|
||||
|
||||
/**
|
||||
* @brief Get capabilities
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Get all capabilities
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Set configuration
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
|
||||
/**
|
||||
* @brief Reconfigure stream
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
|
||||
/**
|
||||
* @brief Get configuration
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Suspend stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open stream
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_start_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Abort stream
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_sink_abort_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_stop_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @brief Suspend stream
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_sink_suspend(uint8_t local_seid);
|
||||
|
||||
/* API_END */
|
||||
|
||||
|
@ -51,137 +51,52 @@
|
||||
#include "avdtp_util.h"
|
||||
#include "avdtp_source.h"
|
||||
|
||||
#include "btstack_ring_buffer.h"
|
||||
|
||||
static const char * default_avdtp_source_service_name = "BTstack AVDTP Source Service";
|
||||
static const char * default_avdtp_source_service_provider_name = "BTstack AVDTP Source Service Provider";
|
||||
|
||||
static avdtp_context_t avdtp_source_context;
|
||||
static avdtp_context_t * avdtp_source_context;
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
|
||||
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){
|
||||
uint8_t* attribute;
|
||||
de_create_sequence(service);
|
||||
|
||||
// 0x0000 "Service Record Handle"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
|
||||
|
||||
// 0x0001 "Service Class ID List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, AUDIO_SOURCE_GROUP);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0004 "Protocol Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t* l2cpProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
|
||||
de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP);
|
||||
}
|
||||
de_pop_sequence(attribute, l2cpProtocol);
|
||||
|
||||
uint8_t* avProtocol = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service
|
||||
de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version
|
||||
}
|
||||
de_pop_sequence(attribute, avProtocol);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0005 "Public Browse Group"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
// 0x0009 "Bluetooth Profile Descriptor List"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
|
||||
attribute = de_push_sequence(service);
|
||||
{
|
||||
uint8_t *a2dProfile = de_push_sequence(attribute);
|
||||
{
|
||||
de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, ADVANCED_AUDIO_DISTRIBUTION);
|
||||
de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103);
|
||||
}
|
||||
de_pop_sequence(attribute, a2dProfile);
|
||||
}
|
||||
de_pop_sequence(service, attribute);
|
||||
|
||||
|
||||
// 0x0100 "Service Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
|
||||
if (service_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_avdtp_source_service_name), (uint8_t *) default_avdtp_source_service_name);
|
||||
}
|
||||
|
||||
// 0x0100 "Provider Name"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102);
|
||||
if (service_provider_name){
|
||||
de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name);
|
||||
} else {
|
||||
de_add_data(service, DE_STRING, strlen(default_avdtp_source_service_provider_name), (uint8_t *) default_avdtp_source_service_provider_name);
|
||||
}
|
||||
|
||||
// 0x0311 "Supported Features"
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311);
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
|
||||
}
|
||||
|
||||
|
||||
void avdtp_source_register_media_transport_category(uint8_t seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_media_transport_category(stream_endpoint);
|
||||
}
|
||||
|
||||
void avdtp_source_register_reporting_category(uint8_t seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_reporting_category(stream_endpoint);
|
||||
}
|
||||
|
||||
void avdtp_source_register_delay_reporting_category(uint8_t seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_delay_reporting_category(stream_endpoint);
|
||||
}
|
||||
|
||||
void avdtp_source_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_recovery_category(stream_endpoint, maximum_recovery_window_size, maximum_number_media_packets);
|
||||
}
|
||||
|
||||
void avdtp_source_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_content_protection_category(stream_endpoint, cp_type, cp_type_value, cp_type_value_len);
|
||||
}
|
||||
|
||||
void avdtp_source_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_header_compression_category(stream_endpoint, back_ch, media, recovery);
|
||||
}
|
||||
|
||||
void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_media_codec_category(stream_endpoint, media_type, media_codec_type, media_codec_info, media_codec_info_len);
|
||||
}
|
||||
|
||||
void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
|
||||
avdtp_register_multiplexing_category(stream_endpoint, fragmentation);
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){
|
||||
return avdtp_create_stream_endpoint(sep_type, media_type, &avdtp_source_context);
|
||||
return avdtp_create_stream_endpoint(sep_type, media_type, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){
|
||||
@ -189,232 +104,83 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){
|
||||
log_error("avdtp_source_register_packet_handler called with NULL callback");
|
||||
return;
|
||||
}
|
||||
avdtp_source_context.avdtp_callback = callback;
|
||||
avdtp_source_context->avdtp_callback = callback;
|
||||
}
|
||||
|
||||
void avdtp_source_connect(bd_addr_t bd_addr){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_bd_addr(bd_addr, &avdtp_source_context);
|
||||
if (!connection){
|
||||
connection = avdtp_create_connection(bd_addr, &avdtp_source_context);
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return;
|
||||
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
|
||||
l2cap_create_channel(packet_handler, connection->remote_addr, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, NULL);
|
||||
void avdtp_source_connect(bd_addr_t remote){
|
||||
avdtp_connect(remote, AVDTP_SINK, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_disconnect(uint16_t con_handle){
|
||||
avdtp_disconnect(con_handle, &avdtp_source_context);
|
||||
avdtp_disconnect(con_handle, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_open_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_open_stream(con_handle, acp_seid, &avdtp_source_context);
|
||||
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_open_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_start_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_start_stream(con_handle, acp_seid, &avdtp_source_context);
|
||||
void avdtp_source_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_stop_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_stop_stream(con_handle, acp_seid, &avdtp_source_context);
|
||||
void avdtp_source_stop_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_abort_stream(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_abort_stream(con_handle, acp_seid, &avdtp_source_context);
|
||||
void avdtp_source_abort_stream(uint8_t int_seid){
|
||||
avdtp_abort_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_suspend(uint8_t int_seid){
|
||||
avdtp_suspend_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_discover_stream_endpoints(uint16_t con_handle){
|
||||
avdtp_discover_stream_endpoints(con_handle, &avdtp_source_context);
|
||||
avdtp_discover_stream_endpoints(con_handle, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_get_capabilities(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_capabilities(con_handle, acp_seid, &avdtp_source_context);
|
||||
avdtp_get_capabilities(con_handle, acp_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_all_capabilities(con_handle, acp_seid, &avdtp_source_context);
|
||||
avdtp_get_all_capabilities(con_handle, acp_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_get_configuration(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_get_configuration(con_handle, acp_seid, &avdtp_source_context);
|
||||
avdtp_get_configuration(con_handle, acp_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_set_configuration(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, &avdtp_source_context);
|
||||
avdtp_set_configuration(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_reconfigure(con_handle, acp_seid, configured_services_bitmap, configuration, &avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_suspend(uint16_t con_handle, uint8_t acp_seid){
|
||||
avdtp_suspend(con_handle, acp_seid, &avdtp_source_context);
|
||||
void avdtp_source_reconfigure(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
|
||||
avdtp_reconfigure(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_source_context);
|
||||
}
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
avdtp_packet_handler(packet_type, channel, packet, size, &avdtp_source_context);
|
||||
avdtp_packet_handler(packet_type, channel, packet, size, avdtp_source_context);
|
||||
}
|
||||
|
||||
|
||||
/* streaming part */
|
||||
#define NUM_CHANNELS 2
|
||||
#define SAMPLE_RATE 44100
|
||||
#define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS)
|
||||
#define LATENCY 300 // ms
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265
|
||||
#endif
|
||||
#define TABLE_SIZE_441HZ 100
|
||||
|
||||
typedef struct {
|
||||
int16_t source[TABLE_SIZE_441HZ];
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
} paTestData;
|
||||
|
||||
static uint32_t fill_audio_ring_buffer_timeout = 50; //ms
|
||||
static paTestData sin_data;
|
||||
|
||||
static void fill_audio_ring_buffer(void *userData, int num_samples_to_write, avdtp_stream_endpoint_t * stream_endpoint){
|
||||
paTestData *data = (paTestData*)userData;
|
||||
int count = 0;
|
||||
while (btstack_ring_buffer_bytes_free(&stream_endpoint->audio_ring_buffer) >= BYTES_PER_AUDIO_SAMPLE && count < num_samples_to_write){
|
||||
uint8_t write_data[BYTES_PER_AUDIO_SAMPLE];
|
||||
*(int16_t*)&write_data[0] = data->source[data->left_phase];
|
||||
*(int16_t*)&write_data[2] = data->source[data->right_phase];
|
||||
|
||||
btstack_ring_buffer_write(&stream_endpoint->audio_ring_buffer, write_data, BYTES_PER_AUDIO_SAMPLE);
|
||||
count++;
|
||||
|
||||
data->left_phase += 1;
|
||||
if (data->left_phase >= TABLE_SIZE_441HZ){
|
||||
data->left_phase -= TABLE_SIZE_441HZ;
|
||||
}
|
||||
data->right_phase += 1;
|
||||
if (data->right_phase >= TABLE_SIZE_441HZ){
|
||||
data->right_phase -= TABLE_SIZE_441HZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_sbc_ring_buffer(uint8_t * sbc_frame, int sbc_frame_size, avdtp_stream_endpoint_t * stream_endpoint){
|
||||
if (btstack_ring_buffer_bytes_free(&stream_endpoint->sbc_ring_buffer) >= sbc_frame_size ){
|
||||
// printf(" fill_sbc_ring_buffer\n");
|
||||
uint8_t size_buffer = sbc_frame_size;
|
||||
btstack_ring_buffer_write(&stream_endpoint->sbc_ring_buffer, &size_buffer, 1);
|
||||
btstack_ring_buffer_write(&stream_endpoint->sbc_ring_buffer, sbc_frame, sbc_frame_size);
|
||||
} else {
|
||||
printf("No space in sbc buffer\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void avdtp_source_stream_endpoint_run(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
// performe sbc encoding
|
||||
int total_num_bytes_read = 0;
|
||||
int num_audio_samples_to_read = btstack_sbc_encoder_num_audio_frames();
|
||||
int audio_bytes_to_read = num_audio_samples_to_read * BYTES_PER_AUDIO_SAMPLE;
|
||||
|
||||
// printf("run: audio_bytes_to_read: %d\n", audio_bytes_to_read);
|
||||
// printf(" audio buf, bytes available: %d\n", btstack_ring_buffer_bytes_available(&stream_endpoint->audio_ring_buffer));
|
||||
// printf(" sbc buf, bytes free: %d\n", btstack_ring_buffer_bytes_free(&stream_endpoint->sbc_ring_buffer));
|
||||
|
||||
while (btstack_ring_buffer_bytes_available(&stream_endpoint->audio_ring_buffer) >= audio_bytes_to_read
|
||||
&& btstack_ring_buffer_bytes_free(&stream_endpoint->sbc_ring_buffer) >= 120){ // TODO use real value
|
||||
|
||||
uint32_t number_of_bytes_read = 0;
|
||||
uint8_t pcm_frame[256*BYTES_PER_AUDIO_SAMPLE];
|
||||
btstack_ring_buffer_read(&stream_endpoint->audio_ring_buffer, pcm_frame, audio_bytes_to_read, &number_of_bytes_read);
|
||||
// printf(" num audio bytes read %d\n", number_of_bytes_read);
|
||||
btstack_sbc_encoder_process_data((int16_t *) pcm_frame);
|
||||
|
||||
uint16_t sbc_frame_bytes = 119; //btstack_sbc_encoder_sbc_buffer_length();
|
||||
|
||||
total_num_bytes_read += number_of_bytes_read;
|
||||
fill_sbc_ring_buffer(btstack_sbc_encoder_sbc_buffer(), sbc_frame_bytes, stream_endpoint);
|
||||
}
|
||||
// schedule sending
|
||||
if (total_num_bytes_read != 0){
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND;
|
||||
avdtp_request_can_send_now_self(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_fill_audio_ring_buffer_timeout_handler(btstack_timer_source_t * timer){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = btstack_run_loop_get_timer_context(timer);
|
||||
btstack_run_loop_set_timer(&stream_endpoint->fill_audio_ring_buffer_timer, fill_audio_ring_buffer_timeout); // 2 seconds timeout
|
||||
btstack_run_loop_add_timer(&stream_endpoint->fill_audio_ring_buffer_timer);
|
||||
uint32_t now = btstack_run_loop_get_time_ms();
|
||||
|
||||
uint32_t update_period_ms = fill_audio_ring_buffer_timeout;
|
||||
if (stream_endpoint->time_audio_data_sent > 0){
|
||||
update_period_ms = now - stream_endpoint->time_audio_data_sent;
|
||||
}
|
||||
uint32_t num_samples = (update_period_ms * 44100) / 1000;
|
||||
stream_endpoint->acc_num_missed_samples += (update_period_ms * 44100) % 1000;
|
||||
|
||||
if (stream_endpoint->acc_num_missed_samples >= 1000){
|
||||
num_samples++;
|
||||
stream_endpoint->acc_num_missed_samples -= 1000;
|
||||
}
|
||||
|
||||
fill_audio_ring_buffer(&sin_data, num_samples, stream_endpoint);
|
||||
stream_endpoint->time_audio_data_sent = now;
|
||||
|
||||
avdtp_source_stream_endpoint_run(stream_endpoint);
|
||||
//
|
||||
}
|
||||
|
||||
static void test_fill_audio_ring_buffer_timer_start(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
btstack_run_loop_remove_timer(&stream_endpoint->fill_audio_ring_buffer_timer);
|
||||
btstack_run_loop_set_timer_handler(&stream_endpoint->fill_audio_ring_buffer_timer, test_fill_audio_ring_buffer_timeout_handler);
|
||||
btstack_run_loop_set_timer_context(&stream_endpoint->fill_audio_ring_buffer_timer, stream_endpoint);
|
||||
btstack_run_loop_set_timer(&stream_endpoint->fill_audio_ring_buffer_timer, fill_audio_ring_buffer_timeout); // 50 ms timeout
|
||||
btstack_run_loop_add_timer(&stream_endpoint->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
static void test_fill_audio_ring_buffer_timer_stop(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
btstack_run_loop_remove_timer(&stream_endpoint->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
void avdtp_source_stream_data_start(uint16_t con_handle){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(con_handle, &avdtp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint found for 0x%02x", con_handle);
|
||||
void avdtp_source_init(avdtp_context_t * avdtp_context){
|
||||
if (!avdtp_context){
|
||||
log_error("avdtp_source_context is NULL");
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_STREAMING){
|
||||
printf("stream_endpoint in wrong state %d\n", stream_endpoint->state);
|
||||
return;
|
||||
}
|
||||
|
||||
test_fill_audio_ring_buffer_timer_start(stream_endpoint);
|
||||
}
|
||||
|
||||
void avdtp_source_stream_data_stop(uint16_t con_handle){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(con_handle, &avdtp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
log_error("no stream_endpoint found");
|
||||
return;
|
||||
}
|
||||
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_STREAMING) return;
|
||||
// TODO: initialize randomly sequence number
|
||||
stream_endpoint->sequence_number = 0;
|
||||
test_fill_audio_ring_buffer_timer_stop(stream_endpoint);
|
||||
}
|
||||
|
||||
void avdtp_source_init(void){
|
||||
avdtp_source_context.stream_endpoints = NULL;
|
||||
avdtp_source_context.connections = NULL;
|
||||
avdtp_source_context.stream_endpoints_id_counter = 0;
|
||||
avdtp_source_context.packet_handler = packet_handler;
|
||||
|
||||
/* initialise sinusoidal wavetable */
|
||||
int i;
|
||||
for (i=0; i<TABLE_SIZE_441HZ; i++){
|
||||
sin_data.source[i] = sin(((double)i/(double)TABLE_SIZE_441HZ) * M_PI * 2.)*32767;
|
||||
}
|
||||
sin_data.left_phase = sin_data.right_phase = 0;
|
||||
avdtp_source_context = avdtp_context;
|
||||
avdtp_source_context->stream_endpoints = NULL;
|
||||
avdtp_source_context->connections = NULL;
|
||||
avdtp_source_context->stream_endpoints_id_counter = 0;
|
||||
avdtp_source_context->packet_handler = packet_handler;
|
||||
|
||||
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
|
||||
}
|
||||
|
||||
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){
|
||||
return avdtp_remote_seps_num(avdtp_cid, avdtp_source_context);
|
||||
}
|
||||
|
||||
avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index){
|
||||
return avdtp_remote_sep(avdtp_cid, index, avdtp_source_context);
|
||||
}
|
||||
|
@ -54,27 +54,17 @@ extern "C" {
|
||||
|
||||
/* API_START */
|
||||
|
||||
/**
|
||||
* @brief AVDTP Source service record.
|
||||
* @param service
|
||||
* @param service_record_handle
|
||||
* @param supported_features 16-bit bitmap, see AVDTP_SOURCE_SF_* values in avdtp.h
|
||||
* @param service_name
|
||||
* @param service_provider_name
|
||||
*/
|
||||
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
|
||||
|
||||
void avdtp_source_register_media_transport_category(uint8_t seid);
|
||||
void avdtp_source_register_reporting_category(uint8_t seid);
|
||||
void avdtp_source_register_delay_reporting_category(uint8_t seid);
|
||||
void avdtp_source_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets);
|
||||
void avdtp_source_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len);
|
||||
void avdtp_source_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery);
|
||||
void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len);
|
||||
void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation);
|
||||
|
||||
|
||||
void avdtp_source_init(void);
|
||||
void avdtp_source_init(avdtp_context_t * avdtp_context);
|
||||
void avdtp_source_register_packet_handler(btstack_packet_handler_t callback);
|
||||
|
||||
/**
|
||||
@ -83,90 +73,86 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback);
|
||||
*/
|
||||
void avdtp_source_connect(bd_addr_t bd_addr);
|
||||
|
||||
void avdtp_source_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
|
||||
/**
|
||||
* @brief Disconnect from device with connection handle.
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_disconnect(uint16_t con_handle);
|
||||
void avdtp_source_disconnect(uint16_t avdtp_cid);
|
||||
|
||||
/**
|
||||
* @brief Discover stream endpoints
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_discover_stream_endpoints(uint16_t con_handle);
|
||||
void avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid);
|
||||
|
||||
/**
|
||||
* @brief Get capabilities
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_get_capabilities(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Get all capabilities
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Set configuration
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
void avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
|
||||
/**
|
||||
* @brief Reconfigure stream
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
void avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
|
||||
|
||||
/**
|
||||
* @brief Get configuration
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
*/
|
||||
void avdtp_source_get_configuration(uint16_t con_handle, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Suspend stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_suspend(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Open stream
|
||||
* @param con_handle
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_open_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_source_start_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_start_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Abort stream
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_source_abort_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_source_abort_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_stop_stream(uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param con_handle
|
||||
* @param seid
|
||||
* @brief Suspend stream
|
||||
* @param local_seid
|
||||
*/
|
||||
void avdtp_source_stop_stream(uint16_t con_handle, uint8_t acp_seid);
|
||||
void avdtp_source_suspend(uint8_t local_seid);
|
||||
|
||||
|
||||
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);
|
||||
|
||||
void avdtp_source_stream_data_start(uint16_t con_handle);
|
||||
void avdtp_source_stream_data_stop(uint16_t con_handle);
|
||||
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid);
|
||||
avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index);
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -59,9 +59,8 @@ void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint)
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
|
||||
stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
|
||||
stream_endpoint->media_disconnect = 0;
|
||||
stream_endpoint->remote_seps_num = 0;
|
||||
stream_endpoint->sep.in_use = 0;
|
||||
memset(stream_endpoint->remote_seps, 0, sizeof(stream_endpoint->remote_seps));
|
||||
stream_endpoint->remote_sep_index = 0;
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * avdtp_stream_endpoint_for_seid(uint16_t seid, avdtp_context_t * context){
|
||||
@ -87,17 +86,6 @@ avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avdtp_connection_t * avdtp_connection_for_con_handle(hci_con_handle_t con_handle, avdtp_context_t * context){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &context->connections);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it);
|
||||
if (connection->con_handle != con_handle) continue;
|
||||
return connection;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &context->connections);
|
||||
@ -144,8 +132,10 @@ avdtp_stream_endpoint_t * avdtp_stream_endpoint_associated_with_acp_seid(uint16_
|
||||
btstack_linked_list_iterator_init(&it, &context->stream_endpoints);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it);
|
||||
|
||||
if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){
|
||||
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){
|
||||
if (!stream_endpoint->connection) continue;
|
||||
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){
|
||||
return stream_endpoint;
|
||||
}
|
||||
}
|
||||
@ -190,7 +180,7 @@ int avdtp_read_signaling_header(avdtp_signaling_packet_t * signaling_header, uin
|
||||
break;
|
||||
case AVDTP_CONTINUE_PACKET:
|
||||
if (signaling_header->num_packets <= 0) {
|
||||
printf(" ERROR: wrong num fragmented packets\n");
|
||||
log_info(" ERROR: wrong num fragmented packets\n");
|
||||
break;
|
||||
}
|
||||
signaling_header->num_packets--;
|
||||
@ -254,7 +244,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
|
||||
if (category == AVDTP_SERVICE_CATEGORY_INVALID_0 ||
|
||||
(category == AVDTP_SERVICE_CATEGORY_INVALID_FF && connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE)){
|
||||
printf(" ERROR: BAD SERVICE CATEGORY %d\n", category);
|
||||
log_info(" ERROR: BAD SERVICE CATEGORY %d\n", category);
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = BAD_SERV_CATEGORY;
|
||||
return 1;
|
||||
@ -262,7 +252,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
|
||||
if (connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE){
|
||||
if (category != AVDTP_CONTENT_PROTECTION && category != AVDTP_MEDIA_CODEC){
|
||||
printf(" ERROR: REJECT CATEGORY, INVALID_CAPABILITIES\n");
|
||||
log_info(" ERROR: REJECT CATEGORY, INVALID_CAPABILITIES\n");
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = INVALID_CAPABILITIES;
|
||||
return 1;
|
||||
@ -272,7 +262,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
switch(category){
|
||||
case AVDTP_MEDIA_TRANSPORT:
|
||||
if (cap_len != 0){
|
||||
printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n");
|
||||
log_info(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n");
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = BAD_MEDIA_TRANSPORT_FORMAT;
|
||||
return 1;
|
||||
@ -281,7 +271,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
case AVDTP_REPORTING:
|
||||
case AVDTP_DELAY_REPORTING:
|
||||
if (cap_len != 0){
|
||||
printf(" ERROR: REJECT CATEGORY, BAD_LENGTH\n");
|
||||
log_info(" ERROR: REJECT CATEGORY, BAD_LENGTH\n");
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = BAD_LENGTH;
|
||||
return 1;
|
||||
@ -289,7 +279,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
break;
|
||||
case AVDTP_RECOVERY:
|
||||
if (cap_len < 3){
|
||||
printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n");
|
||||
log_info(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n");
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = BAD_RECOVERY_FORMAT;
|
||||
return 1;
|
||||
@ -297,7 +287,7 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
|
||||
break;
|
||||
case AVDTP_CONTENT_PROTECTION:
|
||||
if (cap_len < 2){
|
||||
printf(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n");
|
||||
log_info(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n");
|
||||
connection->reject_service_category = category;
|
||||
connection->error_code = BAD_CP_FORMAT;
|
||||
return 1;
|
||||
@ -327,8 +317,7 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
|
||||
if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0;
|
||||
int processed_cap_len = 0;
|
||||
int rfa = 0;
|
||||
//printf(" size %d, cat size %d\n", size, cap_len);
|
||||
|
||||
|
||||
while (pos < size){
|
||||
if (cap_len > size - pos){
|
||||
connection->reject_service_category = category;
|
||||
@ -398,8 +387,6 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
|
||||
category = (avdtp_service_category_t)packet[pos++];
|
||||
cap_len = packet[pos++];
|
||||
if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0;
|
||||
//printf("category %d, pos %d + 2 + %d -> %d\n", category, old_pos, cap_len, pos + cap_len);
|
||||
//printf_hexdump(packet+old_pos, size-old_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,10 +424,6 @@ void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uin
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("registered_service_categories: 0x%02x\n", registered_service_categories);
|
||||
|
||||
// printf("command before packing:\n");
|
||||
// printf_hexdump(signaling_packet->command, signaling_packet->size);
|
||||
for (i = 1; i < 9; i++){
|
||||
int registered_category = get_bit16(registered_service_categories, i);
|
||||
if (!registered_category && (identifier == AVDTP_SI_SET_CONFIGURATION || identifier == AVDTP_SI_RECONFIGURE)){
|
||||
@ -451,13 +434,10 @@ void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uin
|
||||
}
|
||||
if (registered_category){
|
||||
// service category
|
||||
// printf("pack service category: %d\n", i);
|
||||
signaling_packet->command[signaling_packet->size++] = i;
|
||||
signaling_packet->size += avdtp_pack_service_capabilities(signaling_packet->command+signaling_packet->size, sizeof(signaling_packet->command)-signaling_packet->size, capabilities, (avdtp_service_category_t)i, pack_all_capabilities);
|
||||
}
|
||||
}
|
||||
// printf("command after packing:\n");
|
||||
// printf_hexdump(signaling_packet->command, signaling_packet->size);
|
||||
|
||||
signaling_packet->signal_identifier = identifier;
|
||||
signaling_packet->transaction_label = transaction_label;
|
||||
@ -465,17 +445,13 @@ void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uin
|
||||
|
||||
int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer) {
|
||||
int mtu = l2cap_get_remote_mtu_for_local_cid(cid);
|
||||
// hack for test
|
||||
// int mtu = 6;
|
||||
int data_len = 0;
|
||||
|
||||
uint16_t offset = signaling_packet->offset;
|
||||
uint16_t pos = 1;
|
||||
// printf(" avdtp_signaling_create_fragment offset %d, packet type %d\n", signaling_packet->offset, signaling_packet->packet_type);
|
||||
|
||||
if (offset == 0){
|
||||
if (signaling_packet->size <= mtu - 2){
|
||||
// printf(" AVDTP_SINGLE_PACKET\n");
|
||||
signaling_packet->packet_type = AVDTP_SINGLE_PACKET;
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = signaling_packet->size;
|
||||
@ -485,21 +461,17 @@ int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * sig
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = mtu - 3;
|
||||
signaling_packet->offset = data_len;
|
||||
// printf(" AVDTP_START_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
} else {
|
||||
int remaining_bytes = signaling_packet->size - offset;
|
||||
if (remaining_bytes <= mtu - 1){
|
||||
//signaling_packet->fragmentation = 1;
|
||||
signaling_packet->packet_type = AVDTP_END_PACKET;
|
||||
data_len = remaining_bytes;
|
||||
signaling_packet->offset = 0;
|
||||
// printf(" AVDTP_END_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
} else{
|
||||
signaling_packet->packet_type = AVDTP_CONTINUE_PACKET;
|
||||
data_len = mtu - 1;
|
||||
signaling_packet->offset += data_len;
|
||||
// printf(" AVDTP_CONTINUE_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
}
|
||||
out_buffer[0] = avdtp_header(signaling_packet->transaction_label, signaling_packet->packet_type, signaling_packet->message_type);
|
||||
@ -509,14 +481,14 @@ int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * sig
|
||||
}
|
||||
|
||||
|
||||
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status){
|
||||
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t status){
|
||||
if (!callback) return;
|
||||
uint8_t event[12];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
reverse_bd_addr(addr,&event[pos]);
|
||||
pos += 6;
|
||||
@ -524,27 +496,44 @@ void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callba
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status){
|
||||
void avdtp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, uint16_t sequence_number){
|
||||
if (!callback) return;
|
||||
uint8_t event[6];
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = seid;
|
||||
little_endian_store_16(event, pos, sequence_number);
|
||||
pos += 2;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status){
|
||||
if (!callback) return;
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = acp_seid;
|
||||
event[pos++] = status;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
|
||||
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep){
|
||||
if (!callback) return;
|
||||
uint8_t event[9];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_FOUND;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = sep.seid;
|
||||
event[pos++] = sep.in_use;
|
||||
@ -553,55 +542,60 @@ void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_ha
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier, uint8_t status){
|
||||
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier, uint8_t status){
|
||||
if (!callback) return;
|
||||
uint8_t event[7];
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = identifier;
|
||||
event[pos++] = status;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){
|
||||
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier){
|
||||
if (!callback) return;
|
||||
uint8_t event[6];
|
||||
uint8_t event[7];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_REJECT;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = identifier;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){
|
||||
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier){
|
||||
if (!callback) return;
|
||||
uint8_t event[6];
|
||||
uint8_t event[7];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = identifier;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
uint8_t event[13];
|
||||
uint8_t event[15];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = acp_seid;
|
||||
event[pos++] = media_codec.media_type;
|
||||
event[pos++] = media_codec.media_codec_information[0] >> 4;
|
||||
event[pos++] = media_codec.media_codec_information[0] & 0x0F;
|
||||
@ -613,15 +607,17 @@ void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t ca
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
uint8_t event[109];
|
||||
uint8_t event[111];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = acp_seid;
|
||||
event[pos++] = media_codec.media_type;
|
||||
little_endian_store_16(event, pos, media_codec.media_codec_type);
|
||||
pos += 2;
|
||||
@ -635,16 +631,18 @@ void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
|
||||
static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
|
||||
if (!callback) return;
|
||||
uint8_t event[14+2];
|
||||
uint8_t event[16+2];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = acp_seid;
|
||||
event[pos++] = reconfigure;
|
||||
|
||||
uint8_t num_channels = 0;
|
||||
@ -713,25 +711,26 @@ static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 0);
|
||||
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, int_seid, acp_seid, media_codec, 0);
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 1);
|
||||
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, int_seid, acp_seid, media_codec, 1);
|
||||
}
|
||||
|
||||
static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
|
||||
uint8_t event[110];
|
||||
static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
|
||||
uint8_t event[112];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION;
|
||||
little_endian_store_16(event, pos, con_handle);
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
|
||||
event[pos++] = int_seid;
|
||||
event[pos++] = acp_seid;
|
||||
event[pos++] = reconfigure;
|
||||
|
||||
event[pos++] = media_codec.media_type;
|
||||
@ -748,14 +747,14 @@ static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 0);
|
||||
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, int_seid, acp_seid, media_codec, 0);
|
||||
}
|
||||
|
||||
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
|
||||
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
|
||||
if (!callback) return;
|
||||
avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 1);
|
||||
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, int_seid, acp_seid, media_codec, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -773,14 +772,27 @@ void avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l
|
||||
}
|
||||
|
||||
uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){
|
||||
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == seid){
|
||||
if (!stream_endpoint->connection) return 0xFF;
|
||||
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == seid){
|
||||
return stream_endpoint->remote_sep_index;
|
||||
}
|
||||
int i;
|
||||
for (i=0; i < stream_endpoint->remote_seps_num; i++){
|
||||
if (stream_endpoint->remote_seps[i].seid == seid){
|
||||
for (i=0; i < stream_endpoint->connection->remote_seps_num; i++){
|
||||
if (stream_endpoint->connection->remote_seps[i].seid == seid){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid){
|
||||
if (!connection) return 0xFF;
|
||||
int i;
|
||||
for (i = 0; i < connection->remote_seps_num; i++){
|
||||
if (connection->remote_seps[i].seid == remote_seid){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ extern "C" {
|
||||
#define AVDTP_INVALID_SEP_INDEX 0xff
|
||||
|
||||
avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_t * context);
|
||||
avdtp_connection_t * avdtp_connection_for_con_handle(hci_con_handle_t con_handle, avdtp_context_t * context);
|
||||
avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context);
|
||||
avdtp_stream_endpoint_t * avdtp_stream_endpoint_for_l2cap_cid(uint16_t l2cap_cid, avdtp_context_t * context);
|
||||
avdtp_stream_endpoint_t * avdtp_stream_endpoint_with_seid(uint8_t seid, avdtp_context_t * context);
|
||||
@ -74,20 +73,20 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
|
||||
void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t configuration, uint8_t identifier);
|
||||
int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer);
|
||||
|
||||
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status);
|
||||
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status);
|
||||
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep);
|
||||
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier, uint8_t status);
|
||||
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier);
|
||||
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier);
|
||||
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t status);
|
||||
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status);
|
||||
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep);
|
||||
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier, uint8_t status);
|
||||
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
|
||||
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
|
||||
void avdtp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint16_t sequence_number);
|
||||
|
||||
|
||||
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec);
|
||||
|
||||
void avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid);
|
||||
void avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid);
|
||||
@ -96,6 +95,7 @@ void avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l
|
||||
uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t acp_seid);
|
||||
|
||||
void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint);
|
||||
uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
2
test/avdtp/.gitignore
vendored
2
test/avdtp/.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
avdtp_source_test
|
||||
avdtp_source_demo
|
||||
avdtp_sink_test
|
||||
portaudio_test
|
||||
sine_encode_decode_test
|
||||
|
@ -28,6 +28,8 @@ COMMON += \
|
||||
sdp_server.c \
|
||||
sdp_util.c \
|
||||
wav_util.c \
|
||||
sdp_server.c \
|
||||
sdp_client.c \
|
||||
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wunused-variable -Wunused-parameter -Werror
|
||||
CFLAGS += -I.
|
||||
@ -35,6 +37,8 @@ CFLAGS += -I${BTSTACK_ROOT}/src
|
||||
CFLAGS += -I${BTSTACK_ROOT}/src/classic
|
||||
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/include -D OI_DEBUG
|
||||
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/include
|
||||
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/hxcmod-player
|
||||
CFLAGS += -I${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods
|
||||
CFLAGS += -I${BTSTACK_ROOT}/platform/posix
|
||||
CFLAGS += -I${BTSTACK_ROOT}/platform/embedded
|
||||
CFLAGS += -I${BTSTACK_ROOT}/port/libusb
|
||||
@ -46,6 +50,8 @@ VPATH += ${BTSTACK_ROOT}/platform/libusb
|
||||
VPATH += ${BTSTACK_ROOT}/port/libusb
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods
|
||||
|
||||
# use pkg-config for libusb
|
||||
CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
|
||||
@ -63,42 +69,50 @@ SBC_ENCODER += \
|
||||
${BTSTACK_ROOT}/src/classic/btstack_sbc_bludroid.c \
|
||||
${BTSTACK_ROOT}/src/classic/hfp_msbc.c \
|
||||
|
||||
AVDTP_SINK += \
|
||||
AVDTP += \
|
||||
avdtp_util.c \
|
||||
avdtp.c \
|
||||
avdtp_initiator.c \
|
||||
avdtp_acceptor.c \
|
||||
avdtp_source.c \
|
||||
avdtp_sink.c \
|
||||
a2dp_source.c \
|
||||
a2dp_sink.c \
|
||||
btstack_ring_buffer.c \
|
||||
|
||||
AVDTP_TESTS = avdtp_source_test avdtp_sink_test portaudio_test sine_encode_decode_ring_buffer_test sine_encode_decode_test sine_encode_decode_performance_test
|
||||
HXCMOD_PLAYER = \
|
||||
${BTSTACK_ROOT}/3rd-party/hxcmod-player/hxcmod.c \
|
||||
${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods/nao-deceased_by_disease.c \
|
||||
|
||||
AVDTP_TESTS = avdtp_source_demo avdtp_sink_test portaudio_test
|
||||
#sine_encode_decode_ring_buffer_test sine_encode_decode_test sine_encode_decode_performance_test
|
||||
|
||||
CORE_OBJ = $(CORE:.c=.o)
|
||||
COMMON_OBJ = $(COMMON:.c=.o)
|
||||
SBC_DECODER_OBJ = $(SBC_DECODER:.c=.o)
|
||||
SBC_ENCODER_OBJ = $(SBC_ENCODER:.c=.o)
|
||||
AVDTP_SINK_OBJ = $(AVDTP_SINK:.c=.o)
|
||||
AVDTP_OBJ = $(AVDTP:.c=.o)
|
||||
HXCMOD_PLAYER_OBJ = $(HXCMOD_PLAYER:.c=.o)
|
||||
|
||||
all: ${AVDTP_TESTS}
|
||||
|
||||
avdtp_sink_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_SINK_OBJ} avdtp_sink_test.o
|
||||
avdtp_sink_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} avdtp_sink_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
avdtp_source_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_SINK_OBJ} avdtp_source_test.o
|
||||
avdtp_source_demo: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} ${HXCMOD_PLAYER_OBJ} avdtp_source_demo.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
portaudio_test: btstack_util.o hci_dump.o wav_util.o btstack_ring_buffer.o portaudio_test.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
|
||||
sine_encode_decode_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_SINK_OBJ} sine_encode_decode_test.c
|
||||
sine_encode_decode_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} sine_encode_decode_test.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sine_encode_decode_ring_buffer_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_SINK_OBJ} sine_encode_decode_ring_buffer_test.c
|
||||
sine_encode_decode_ring_buffer_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} sine_encode_decode_ring_buffer_test.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
sine_encode_decode_performance_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_SINK_OBJ} sine_encode_decode_performance_test.c
|
||||
sine_encode_decode_performance_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} sine_encode_decode_performance_test.c
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "l2cap.h"
|
||||
#include "stdin_support.h"
|
||||
#include "avdtp_sink.h"
|
||||
#include "a2dp_sink.h"
|
||||
|
||||
#include "btstack_sbc.h"
|
||||
#include "wav_util.h"
|
||||
@ -133,13 +134,13 @@ typedef struct {
|
||||
} avdtp_media_codec_configuration_sbc_t;
|
||||
|
||||
// mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
|
||||
// pts:
|
||||
static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
|
||||
// mac 2013: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
|
||||
// pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
|
||||
// mac 2013:
|
||||
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
|
||||
|
||||
// bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1};
|
||||
|
||||
static uint16_t con_handle = 0;
|
||||
static uint16_t avdtp_cid = 0;
|
||||
static uint8_t sdp_avdtp_sink_service_buffer[150];
|
||||
static avdtp_sep_t sep;
|
||||
|
||||
@ -442,8 +443,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
case HCI_EVENT_AVDTP_META:
|
||||
switch (packet[2]){
|
||||
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
|
||||
con_handle = avdtp_subevent_signaling_connection_established_get_con_handle(packet);
|
||||
printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, con handle 0x%02x ---\n", con_handle);
|
||||
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
|
||||
printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", avdtp_cid);
|
||||
break;
|
||||
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
|
||||
if (app_state != AVDTP_APPLICATION_W2_DISCOVER_SEPS) return;
|
||||
@ -477,7 +478,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
sbc_configuration.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
|
||||
sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
|
||||
dump_sbc_configuration(sbc_configuration);
|
||||
|
||||
// // TODO: use actual config
|
||||
// btstack_sbc_encoder_init(&local_stream_endpoint->sbc_encoder_state, SBC_MODE_STANDARD, 16, 8, 2, 44100, 53);
|
||||
|
||||
if (sbc_configuration.reconfigure){
|
||||
close_media_processing();
|
||||
init_media_processing(sbc_configuration);
|
||||
@ -486,6 +489,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
|
||||
break;
|
||||
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
|
||||
printf(" received non SBC codec. not implemented\n");
|
||||
break;
|
||||
@ -528,19 +533,19 @@ static void show_usage(void){
|
||||
printf("---\n");
|
||||
}
|
||||
|
||||
static const uint8_t media_sbc_codec_capabilities[] = {
|
||||
static uint8_t media_sbc_codec_capabilities[] = {
|
||||
0xFF,//(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
|
||||
2, 53
|
||||
};
|
||||
|
||||
static const uint8_t media_sbc_codec_configuration[] = {
|
||||
static uint8_t media_sbc_codec_configuration[] = {
|
||||
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
|
||||
2, 53
|
||||
};
|
||||
|
||||
static const uint8_t media_sbc_codec_reconfiguration[] = {
|
||||
static uint8_t media_sbc_codec_reconfiguration[] = {
|
||||
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_SNR,
|
||||
2, 53
|
||||
@ -560,23 +565,23 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect not implemented\n");
|
||||
avdtp_sink_disconnect(con_handle);
|
||||
avdtp_sink_disconnect(avdtp_cid);
|
||||
break;
|
||||
case 'd':
|
||||
app_state = AVDTP_APPLICATION_W2_DISCOVER_SEPS;
|
||||
avdtp_sink_discover_stream_endpoints(con_handle);
|
||||
avdtp_sink_discover_stream_endpoints(avdtp_cid);
|
||||
break;
|
||||
case 'g':
|
||||
app_state = AVDTP_APPLICATION_W2_GET_CAPABILITIES;
|
||||
avdtp_sink_get_capabilities(con_handle, sep.seid);
|
||||
avdtp_sink_get_capabilities(avdtp_cid, sep.seid);
|
||||
break;
|
||||
case 'a':
|
||||
app_state = AVDTP_APPLICATION_W2_GET_ALL_CAPABILITIES;
|
||||
avdtp_sink_get_all_capabilities(con_handle, sep.seid);
|
||||
avdtp_sink_get_all_capabilities(avdtp_cid, sep.seid);
|
||||
break;
|
||||
case 'f':
|
||||
app_state = AVDTP_APPLICATION_W2_GET_CONFIGURATION;
|
||||
avdtp_sink_get_configuration(con_handle, sep.seid);
|
||||
avdtp_sink_get_configuration(avdtp_cid, sep.seid);
|
||||
break;
|
||||
case 's':
|
||||
app_state = AVDTP_APPLICATION_W2_SET_CONFIGURATION;
|
||||
@ -585,7 +590,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_configuration);
|
||||
remote_configuration.media_codec.media_codec_information = media_sbc_codec_configuration;
|
||||
avdtp_sink_set_configuration(con_handle, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
|
||||
avdtp_sink_set_configuration(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
|
||||
break;
|
||||
case 'R':
|
||||
app_state = AVDTP_APPLICATION_W2_RECONFIGURE_WITH_SEID;
|
||||
@ -594,27 +599,28 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_reconfiguration);
|
||||
remote_configuration.media_codec.media_codec_information = media_sbc_codec_reconfiguration;
|
||||
avdtp_sink_reconfigure(con_handle, sep.seid, remote_configuration_bitmap, remote_configuration);
|
||||
avdtp_sink_reconfigure(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
|
||||
break;
|
||||
case 'o':
|
||||
app_state = AVDTP_APPLICATION_W2_OPEN_STREAM_WITH_SEID;
|
||||
avdtp_sink_open_stream(con_handle, sep.seid);
|
||||
avdtp_sink_open_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
|
||||
break;
|
||||
case 'm':
|
||||
printf("AVDTP_APPLICATION_W2_START_STREAM_WITH_SEID \n");
|
||||
app_state = AVDTP_APPLICATION_W2_START_STREAM_WITH_SEID;
|
||||
avdtp_sink_start_stream(con_handle, sep.seid);
|
||||
avdtp_sink_start_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
case 'A':
|
||||
app_state = AVDTP_APPLICATION_W2_ABORT_STREAM_WITH_SEID;
|
||||
avdtp_sink_abort_stream(con_handle, sep.seid);
|
||||
avdtp_sink_abort_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
case 'S':
|
||||
app_state = AVDTP_APPLICATION_W2_STOP_STREAM_WITH_SEID;
|
||||
avdtp_sink_stop_stream(con_handle, sep.seid);
|
||||
avdtp_sink_stop_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
case 'P':
|
||||
app_state = AVDTP_APPLICATION_W2_SUSPEND_STREAM_WITH_SEID;
|
||||
avdtp_sink_suspend(con_handle, sep.seid);
|
||||
avdtp_sink_suspend(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
|
425
test/avdtp/avdtp_source_demo.c
Normal file
425
test/avdtp/avdtp_source_demo.c
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (C) 2016 BlueKitchen GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holders nor the names of
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* 4. Any redistribution, use, or modification is done solely for
|
||||
* personal benefit and not for any commercial purpose or for
|
||||
* monetary gain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
|
||||
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Please inquire about commercial licensing options at
|
||||
* contact@bluekitchen-gmbh.com
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack_config.h"
|
||||
#include "btstack_debug.h"
|
||||
#include "btstack_event.h"
|
||||
#include "btstack_memory.h"
|
||||
#include "btstack_run_loop.h"
|
||||
#include "gap.h"
|
||||
#include "hci.h"
|
||||
#include "hci_cmd.h"
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "stdin_support.h"
|
||||
#include "avdtp_source.h"
|
||||
#include "a2dp_source.h"
|
||||
|
||||
#include "btstack_sbc.h"
|
||||
#include "sbc_encoder.h"
|
||||
#include "avdtp_util.h"
|
||||
#include "hxcmod.h"
|
||||
#include "mod.h"
|
||||
|
||||
#define NUM_CHANNELS 2
|
||||
#define A2DP_SAMPLE_RATE 44100
|
||||
#define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS)
|
||||
#define FILL_AUDIO_BUFFER_TIMEOUT_MS 10
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265
|
||||
#endif
|
||||
#define TABLE_SIZE_441HZ 100
|
||||
|
||||
typedef struct {
|
||||
int left_phase;
|
||||
int right_phase;
|
||||
} paTestData;
|
||||
|
||||
typedef enum {
|
||||
STREAM_SINE,
|
||||
STREAM_MOD
|
||||
} stream_data_source_t;
|
||||
|
||||
static uint8_t media_sbc_codec_capabilities[] = {
|
||||
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
|
||||
2, 53
|
||||
};
|
||||
|
||||
static const int16_t sine_int16[] = {
|
||||
0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557,
|
||||
19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466,
|
||||
31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738,
|
||||
31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886,
|
||||
19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057,
|
||||
0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557,
|
||||
-19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466,
|
||||
-31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738,
|
||||
-31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886,
|
||||
-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
|
||||
};
|
||||
|
||||
static char * device_name = "A2DP Source BTstack";
|
||||
|
||||
// mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
|
||||
// pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
|
||||
// mac 2013: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
|
||||
// phone 2013: static bd_addr_t remote = {0xD8, 0xBB, 0x2C, 0xDF, 0xF0, 0xF2};
|
||||
// minijambox:
|
||||
static bd_addr_t remote = {0x00, 0x21, 0x3c, 0xac, 0xf7, 0x38};
|
||||
// head phones: static bd_addr_t remote = {0x00, 0x18, 0x09, 0x28, 0x50, 0x18};
|
||||
// bt dongle: -u 02-04-01
|
||||
// static bd_addr_t remote = {0x00, 0x15, 0x83, 0x5F, 0x9D, 0x46};
|
||||
|
||||
|
||||
static uint8_t sdp_avdtp_source_service_buffer[150];
|
||||
static uint8_t media_sbc_codec_configuration[4];
|
||||
|
||||
typedef struct {
|
||||
uint16_t a2dp_cid;
|
||||
uint8_t local_seid;
|
||||
|
||||
uint32_t time_audio_data_sent; // ms
|
||||
uint32_t acc_num_missed_samples;
|
||||
uint32_t samples_ready;
|
||||
btstack_timer_source_t fill_audio_buffer_timer;
|
||||
uint8_t streaming;
|
||||
|
||||
int max_media_payload_size;
|
||||
|
||||
uint8_t sbc_storage[1030];
|
||||
uint16_t sbc_storage_count;
|
||||
uint8_t sbc_ready_to_send;
|
||||
|
||||
} a2dp_media_sending_context_t;
|
||||
|
||||
static a2dp_media_sending_context_t media_tracker;
|
||||
|
||||
static paTestData sin_data;
|
||||
|
||||
static int hxcmod_initialized = 0;
|
||||
static modcontext mod_context;
|
||||
static tracker_buffer_state trkbuf;
|
||||
|
||||
static uint8_t local_seid = 0;
|
||||
stream_data_source_t data_source = STREAM_SINE;
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void a2dp_fill_audio_buffer_timer_start(a2dp_media_sending_context_t * context);
|
||||
static void a2dp_fill_audio_buffer_timer_stop(a2dp_media_sending_context_t * context);
|
||||
static void a2dp_fill_audio_buffer_timer_pause(a2dp_media_sending_context_t * context);
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
switch (packet_type) {
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
case HCI_EVENT_A2DP_META:
|
||||
switch (packet[2]){
|
||||
case A2DP_SUBEVENT_STREAM_ESTABLISHED:
|
||||
media_tracker.local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
|
||||
media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_ESTABLISHED, a2dp_cid 0x%02x, local seid %d, remote seid %d\n",
|
||||
media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAM_START_ACCEPTED:
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
if (!a2dp_source_stream_endpoint_ready(media_tracker.local_seid)) break;
|
||||
a2dp_fill_audio_buffer_timer_start(&media_tracker);
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_START_ACCEPTED, local seid %d\n", media_tracker.local_seid);
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:{
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
|
||||
int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
|
||||
int bytes_in_storage = media_tracker.sbc_storage_count;
|
||||
uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
|
||||
|
||||
a2dp_source_stream_send_media_payload(media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
|
||||
media_tracker.sbc_storage_count = 0;
|
||||
media_tracker.sbc_ready_to_send = 0;
|
||||
break;
|
||||
}
|
||||
case A2DP_SUBEVENT_STREAM_SUSPENDED:
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_SUSPENDED, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_fill_audio_buffer_timer_pause(&media_tracker);
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAM_RELEASED:
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_RELEASED, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_fill_audio_buffer_timer_stop(&media_tracker);
|
||||
break;
|
||||
default:
|
||||
printf(" --- application --- not implemented\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// other packet type
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_usage(void){
|
||||
bd_addr_t iut_address;
|
||||
gap_local_bd_addr(iut_address);
|
||||
printf("\n--- Bluetooth AVDTP SOURCE Test Console %s ---\n", bd_addr_to_str(iut_address));
|
||||
printf("c - create connection to addr %s\n", bd_addr_to_str(remote));
|
||||
printf("C - disconnect\n");
|
||||
printf("x - start streaming sine\n");
|
||||
if (hxcmod_initialized){
|
||||
printf("z - start streaming '%s'\n", mod_name);
|
||||
}
|
||||
printf("p - pause streaming\n");
|
||||
printf("X - stop streaming\n");
|
||||
printf("Ctrl-c - exit\n");
|
||||
printf("---\n");
|
||||
}
|
||||
|
||||
static void produce_sine_audio(int16_t * pcm_buffer, void *user_data, int num_samples_to_write){
|
||||
paTestData *data = (paTestData*)user_data;
|
||||
int count;
|
||||
for (count = 0; count < num_samples_to_write ; count++){
|
||||
pcm_buffer[count * 2] = sine_int16[data->left_phase];
|
||||
pcm_buffer[count * 2 + 1] = sine_int16[data->right_phase];
|
||||
|
||||
data->left_phase += 1;
|
||||
if (data->left_phase >= TABLE_SIZE_441HZ){
|
||||
data->left_phase -= TABLE_SIZE_441HZ;
|
||||
}
|
||||
data->right_phase += 1;
|
||||
if (data->right_phase >= TABLE_SIZE_441HZ){
|
||||
data->right_phase -= TABLE_SIZE_441HZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
|
||||
hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
|
||||
}
|
||||
|
||||
static void produce_audio(int16_t * pcm_buffer, int num_samples){
|
||||
switch (data_source){
|
||||
case STREAM_SINE:
|
||||
produce_sine_audio(pcm_buffer, &sin_data, num_samples);
|
||||
break;
|
||||
case STREAM_MOD:
|
||||
produce_mod_audio(pcm_buffer, num_samples);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
|
||||
// perform sbc encodin
|
||||
int total_num_bytes_read = 0;
|
||||
int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
|
||||
while (context->samples_ready >= num_audio_samples_per_sbc_buffer
|
||||
&& (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
|
||||
|
||||
uint8_t pcm_frame[256*BYTES_PER_AUDIO_SAMPLE];
|
||||
|
||||
produce_audio((int16_t *) pcm_frame, num_audio_samples_per_sbc_buffer);
|
||||
btstack_sbc_encoder_process_data((int16_t *) pcm_frame);
|
||||
|
||||
uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
|
||||
uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
|
||||
|
||||
total_num_bytes_read += num_audio_samples_per_sbc_buffer;
|
||||
memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
|
||||
context->sbc_storage_count += sbc_frame_size;
|
||||
context->samples_ready -= num_audio_samples_per_sbc_buffer;
|
||||
}
|
||||
return total_num_bytes_read;
|
||||
}
|
||||
|
||||
static void avdtp_fill_audio_buffer_timeout_handler(btstack_timer_source_t * timer){
|
||||
log_info("timer");
|
||||
a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
|
||||
btstack_run_loop_set_timer(&context->fill_audio_buffer_timer, FILL_AUDIO_BUFFER_TIMEOUT_MS);
|
||||
btstack_run_loop_add_timer(&context->fill_audio_buffer_timer);
|
||||
uint32_t now = btstack_run_loop_get_time_ms();
|
||||
|
||||
uint32_t update_period_ms = FILL_AUDIO_BUFFER_TIMEOUT_MS;
|
||||
if (context->time_audio_data_sent > 0){
|
||||
update_period_ms = now - context->time_audio_data_sent;
|
||||
}
|
||||
|
||||
uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000;
|
||||
context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000;
|
||||
|
||||
while (context->acc_num_missed_samples >= 1000){
|
||||
num_samples++;
|
||||
context->acc_num_missed_samples -= 1000;
|
||||
}
|
||||
context->time_audio_data_sent = now;
|
||||
context->samples_ready += num_samples;
|
||||
|
||||
if (!context->sbc_ready_to_send){
|
||||
fill_sbc_audio_buffer(context);
|
||||
}
|
||||
|
||||
if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
|
||||
// schedule sending
|
||||
context->sbc_ready_to_send = 1;
|
||||
a2dp_source_stream_endpoint_request_can_send_now(context->local_seid);
|
||||
}
|
||||
}
|
||||
|
||||
static void a2dp_fill_audio_buffer_timer_start(a2dp_media_sending_context_t * context){
|
||||
context->max_media_payload_size = a2dp_max_media_payload_size(context->local_seid);
|
||||
context->sbc_storage_count = 0;
|
||||
context->sbc_ready_to_send = 0;
|
||||
context->streaming = 1;
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_buffer_timer);
|
||||
btstack_run_loop_set_timer_handler(&context->fill_audio_buffer_timer, avdtp_fill_audio_buffer_timeout_handler);
|
||||
btstack_run_loop_set_timer_context(&context->fill_audio_buffer_timer, context);
|
||||
btstack_run_loop_set_timer(&context->fill_audio_buffer_timer, FILL_AUDIO_BUFFER_TIMEOUT_MS);
|
||||
btstack_run_loop_add_timer(&context->fill_audio_buffer_timer);
|
||||
}
|
||||
|
||||
static void a2dp_fill_audio_buffer_timer_stop(a2dp_media_sending_context_t * context){
|
||||
context->time_audio_data_sent = 0;
|
||||
context->acc_num_missed_samples = 0;
|
||||
context->samples_ready = 0;
|
||||
context->streaming = 1;
|
||||
context->sbc_storage_count = 0;
|
||||
context->sbc_ready_to_send = 0;
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_buffer_timer);
|
||||
}
|
||||
|
||||
static void a2dp_fill_audio_buffer_timer_pause(a2dp_media_sending_context_t * context){
|
||||
// context->time_audio_data_sent = 0;
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_buffer_timer);
|
||||
}
|
||||
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
UNUSED(ds);
|
||||
UNUSED(callback_type);
|
||||
|
||||
int cmd = btstack_stdin_read();
|
||||
|
||||
switch (cmd){
|
||||
case 'c':
|
||||
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(remote));
|
||||
a2dp_source_establish_stream(remote, local_seid);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect not implemented\n");
|
||||
a2dp_source_disconnect(media_tracker.a2dp_cid);
|
||||
break;
|
||||
case 'x':
|
||||
printf("Stream sine, local seid %d\n", media_tracker.local_seid);
|
||||
data_source = STREAM_SINE;
|
||||
a2dp_source_start_stream(media_tracker.local_seid);
|
||||
break;
|
||||
case 'z':
|
||||
printf("Stream mode, local seid %d\n", media_tracker.local_seid);
|
||||
data_source = STREAM_MOD;
|
||||
a2dp_source_start_stream(media_tracker.local_seid);
|
||||
break;
|
||||
case 'p':
|
||||
printf("Pause stream, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_source_pause_stream(media_tracker.local_seid);
|
||||
break;
|
||||
case 'X':
|
||||
printf("Close stream, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_source_release_stream(media_tracker.local_seid);
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
UNUSED(argc);
|
||||
(void)argv;
|
||||
|
||||
/* Register for HCI events */
|
||||
hci_event_callback_registration.callback = &packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
|
||||
l2cap_init();
|
||||
// Initialize AVDTP Sink
|
||||
a2dp_source_init();
|
||||
a2dp_source_register_packet_handler(&packet_handler);
|
||||
|
||||
//#ifndef SMG_BI
|
||||
local_seid = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration));
|
||||
|
||||
// Initialize SDP
|
||||
sdp_init();
|
||||
memset(sdp_avdtp_source_service_buffer, 0, sizeof(sdp_avdtp_source_service_buffer));
|
||||
a2dp_source_create_sdp_record(sdp_avdtp_source_service_buffer, 0x10002, 1, NULL, NULL);
|
||||
sdp_register_service(sdp_avdtp_source_service_buffer);
|
||||
|
||||
gap_set_local_name(device_name);
|
||||
gap_discoverable_control(1);
|
||||
gap_set_class_of_device(0x200408);
|
||||
|
||||
hxcmod_initialized = hxcmod_init(&mod_context);
|
||||
if (hxcmod_initialized){
|
||||
hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1);
|
||||
hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
|
||||
printf("loaded mod '%s', size %u\n", mod_name, mod_len);
|
||||
}
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
btstack_stdin_setup(stdin_process);
|
||||
return 0;
|
||||
}
|
1
test/pts/.gitignore
vendored
1
test/pts/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
avdtp_source_test
|
||||
ancs_client
|
||||
ble_central_test
|
||||
ble_central_test.h
|
||||
|
@ -1,32 +1,49 @@
|
||||
# Makefile for libusb based PTS tests
|
||||
BTSTACK_ROOT = ../..
|
||||
|
||||
|
||||
CORE += \
|
||||
btstack_memory.c \
|
||||
btstack_linked_list.c \
|
||||
btstack_memory_pool.c \
|
||||
btstack_run_loop.c \
|
||||
btstack_util.c \
|
||||
main.c \
|
||||
stdin_support.c \
|
||||
main.c \
|
||||
stdin_support.c \
|
||||
|
||||
|
||||
COMMON += \
|
||||
hci.c \
|
||||
hci_cmd.c \
|
||||
hci_dump.c \
|
||||
l2cap.c \
|
||||
l2cap_signaling.c \
|
||||
hci_transport_h2_libusb.c \
|
||||
btstack_run_loop_posix.c \
|
||||
btstack_link_key_db_fs.c \
|
||||
le_device_db_fs.c \
|
||||
wav_util.c \
|
||||
hci_transport_h2_libusb.c \
|
||||
btstack_run_loop_posix.c \
|
||||
btstack_link_key_db_fs.c \
|
||||
le_device_db_fs.c \
|
||||
wav_util.c \
|
||||
sdp_util.c \
|
||||
sdp_server.c \
|
||||
sdp_server.c \
|
||||
|
||||
SBC_DECODER += \
|
||||
${BTSTACK_ROOT}/src/classic/btstack_sbc_plc.c \
|
||||
${BTSTACK_ROOT}/src/classic/btstack_sbc_bludroid.c \
|
||||
|
||||
SBC_ENCODER += \
|
||||
${BTSTACK_ROOT}/src/classic/btstack_sbc_bludroid.c \
|
||||
${BTSTACK_ROOT}/src/classic/hfp_msbc.c \
|
||||
|
||||
AVDTP += \
|
||||
avdtp_util.c \
|
||||
avdtp.c \
|
||||
avdtp_initiator.c \
|
||||
avdtp_acceptor.c \
|
||||
avdtp_source.c \
|
||||
btstack_ring_buffer.c \
|
||||
|
||||
include ${BTSTACK_ROOT}/example/Makefile.inc
|
||||
include ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/Makefile.inc
|
||||
include ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/Makefile.inc
|
||||
|
||||
CFLAGS += -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wunused-variable -Wunused-parameter -Werror
|
||||
CFLAGS += -I.
|
||||
@ -44,31 +61,34 @@ VPATH += ${BTSTACK_ROOT}/src/classic
|
||||
VPATH += ${BTSTACK_ROOT}/platform/posix
|
||||
VPATH += ${BTSTACK_ROOT}/platform/libusb
|
||||
VPATH += ${BTSTACK_ROOT}/port/libusb
|
||||
# VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
|
||||
# VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/srce
|
||||
VPATH += ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/srce
|
||||
|
||||
# use pkg-config for libusb
|
||||
CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
|
||||
LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
|
||||
# hard coded flags for libusb in /usr/local/lib
|
||||
# CFLAGS += -I/usr/local/include
|
||||
# LDFLAGS += -L/usr/local/lib -lusb-1.0
|
||||
|
||||
# use pkg-config for portaudio
|
||||
# CFLAGS += $(shell pkg-config portaudio-2.0 --cflags)
|
||||
# LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
|
||||
# hard coded flags for portaudio in /usr/local/lib
|
||||
# CFLAGS += -I/usr/local/include
|
||||
# LDFLAGS += -L/sw/lib -lportaudio -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,Carbon
|
||||
CFLAGS += $(shell pkg-config portaudio-2.0 --cflags) -DHAVE_PORTAUDIO
|
||||
LDFLAGS += $(shell pkg-config portaudio-2.0 --libs)
|
||||
|
||||
CORE_OBJ = $(CORE:.c=.o)
|
||||
COMMON_OBJ = $(COMMON:.c=.o)
|
||||
SBC_DECODER_OBJ = $(SBC_DECODER:.c=.o)
|
||||
SBC_ENCODER_OBJ = $(SBC_ENCODER:.c=.o)
|
||||
AVDTP_OBJ = $(AVDTP:.c=.o)
|
||||
|
||||
EXAMPLES = iopt ble_peripheral_test ble_central_test l2cap_test classic_test bnep_test hsp_ag_test hsp_hs_test sco_loopback le_data_channel
|
||||
EXAMPLES = le_data_channel
|
||||
EXAMPLES = avdtp_source_test le_data_channel
|
||||
|
||||
all: ${EXAMPLES}
|
||||
|
||||
# compile .gatt descriptions
|
||||
avdtp_source_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SM_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} avdtp_source_test.o
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
ble_peripheral_test.h: ble_peripheral_test.gatt
|
||||
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
|
||||
|
||||
ble_central_test.h: ble_central_test.gatt
|
||||
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
|
||||
|
||||
@ -101,4 +121,6 @@ sco_loopback: ${CORE_OBJ} ${COMMON_OBJ} sco_loopback.c
|
||||
|
||||
iopt: ${CORE_OBJ} ${COMMON_OBJ} pan.o hsp_ag.o hsp_hs.o hfp_ag.o hfp_hf.o hfp_gsm_model.o iopt.c hfp.o ${SDP_CLIENT}
|
||||
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf *.pyc *.o $(AVDTP_TESTS) *.dSYM *_test *.wav *.sbc ${BTSTACK_ROOT}/port/libusb/*.o
|
@ -54,9 +54,10 @@
|
||||
#include "hci_dump.h"
|
||||
#include "l2cap.h"
|
||||
#include "stdin_support.h"
|
||||
#include "avdtp_source.h"
|
||||
|
||||
#include "btstack_sbc.h"
|
||||
#include "avdtp.h"
|
||||
#include "avdtp_source.h"
|
||||
#include "avdtp_util.h"
|
||||
|
||||
typedef struct {
|
||||
@ -112,7 +113,7 @@ static const char * avdtp_si_name[] = {
|
||||
"AVDTP_SI_GET_CAPABILITIES",
|
||||
"AVDTP_SI_SET_CONFIGURATION",
|
||||
"AVDTP_SI_GET_CONFIGURATION",
|
||||
"AVDTP_SI_RECONFIGURE,"
|
||||
"AVDTP_SI_RECONFIGURE",
|
||||
"AVDTP_SI_OPEN",
|
||||
"AVDTP_SI_START",
|
||||
"AVDTP_SI_CLOSE",
|
||||
@ -455,7 +456,7 @@ int btstack_main(int argc, const char * argv[]){
|
||||
// Initialize SDP
|
||||
sdp_init();
|
||||
memset(sdp_avdtp_source_service_buffer, 0, sizeof(sdp_avdtp_source_service_buffer));
|
||||
a2dp_sink_create_sdp_record(sdp_avdtp_source_service_buffer, 0x10002, 1, NULL, NULL);
|
||||
a2dp_source_create_sdp_record(sdp_avdtp_source_service_buffer, 0x10002, 1, NULL, NULL);
|
||||
sdp_register_service(sdp_avdtp_source_service_buffer);
|
||||
|
||||
gap_set_local_name("BTstack A2DP Source Test");
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import math
|
||||
import sys
|
||||
|
||||
SAMPLES = 100
|
||||
VALUES_PER_LINE = 10
|
||||
|
||||
print ('''
|
||||
// input signal: pre-computed sine wave, 160 Hz at 16000 kHz
|
||||
static const int16_t sine_int16[] = {''')
|
||||
items = 0
|
||||
for sample in range(SAMPLES):
|
||||
angle = (sample * 360.0) / SAMPLES
|
||||
sine = math.sin(math.radians(angle))
|
||||
rescaled = int(round(sine * 32767))
|
||||
print ("%6d, " % rescaled),
|
||||
items += 1
|
||||
if items == VALUES_PER_LINE:
|
||||
items = 0
|
||||
print
|
||||
print( "};")
|
@ -11,6 +11,7 @@ import btstack_parser as parser
|
||||
meta_events = [
|
||||
'ANCS',
|
||||
'AVDTP',
|
||||
'A2DP',
|
||||
'AVRCP',
|
||||
'GOEP',
|
||||
'HFP',
|
||||
|
50
tool/sine_table_generator.py
Executable file
50
tool/sine_table_generator.py
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
import math
|
||||
import sys
|
||||
|
||||
# 1HZ == 1 sine
|
||||
# sample rate at 44100Hz, sine at 441Hz -> 441 sines in 44100 samples -> 44100/441 samples/sine
|
||||
|
||||
sine_array = '''
|
||||
// input signal: pre-computed int16 sine wave, {sine_sample_rate} Hz at {sine_frequency} Hz
|
||||
static const int16_t sine_int16[] = {{'''
|
||||
|
||||
VALUES_PER_LINE = 10
|
||||
sine_sample_rate = 44100
|
||||
sine_frequency = 441
|
||||
|
||||
if __name__ == "__main__":
|
||||
usage = '''
|
||||
Usage: ./sine_table.py sine_frequency sine_sample_rate
|
||||
'''
|
||||
|
||||
if (len(sys.argv) < 3):
|
||||
print(usage)
|
||||
sys.exit(1)
|
||||
|
||||
sine_frequency = int(sys.argv[1])
|
||||
sine_sample_rate = int(sys.argv[2])
|
||||
|
||||
if sine_frequency <= 0:
|
||||
print(usage)
|
||||
sys.exit(1)
|
||||
|
||||
if sine_sample_rate <= 0:
|
||||
print(usage)
|
||||
sys.exit(1)
|
||||
|
||||
sine_num_samples = sine_sample_rate/sine_frequency
|
||||
|
||||
print(sine_array.format(sine_sample_rate=sine_sample_rate, sine_frequency=sine_frequency))
|
||||
items = 0
|
||||
for sample in range(0,sine_num_samples):
|
||||
items = items + 1
|
||||
angle = (sample * 360.0) / sine_num_samples
|
||||
sine = math.sin(math.radians(angle))
|
||||
rescaled = int(round(sine * 32767))
|
||||
print ("%6d, " % rescaled),
|
||||
if items == VALUES_PER_LINE:
|
||||
items = 0
|
||||
print
|
||||
|
||||
print( "};")
|
Loading…
x
Reference in New Issue
Block a user