1f7c85330SMatthias Ringwald /* 2f7c85330SMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3f7c85330SMatthias Ringwald * 4f7c85330SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5f7c85330SMatthias Ringwald * modification, are permitted provided that the following conditions 6f7c85330SMatthias Ringwald * are met: 7f7c85330SMatthias Ringwald * 8f7c85330SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10f7c85330SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12f7c85330SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13f7c85330SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14f7c85330SMatthias Ringwald * contributors may be used to endorse or promote products derived 15f7c85330SMatthias Ringwald * from this software without specific prior written permission. 16f7c85330SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17f7c85330SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18f7c85330SMatthias Ringwald * monetary gain. 19f7c85330SMatthias Ringwald * 20f7c85330SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21f7c85330SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22f7c85330SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23f7c85330SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24f7c85330SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25f7c85330SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26f7c85330SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27f7c85330SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28f7c85330SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29f7c85330SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30f7c85330SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f7c85330SMatthias Ringwald * SUCH DAMAGE. 32f7c85330SMatthias Ringwald * 33f7c85330SMatthias Ringwald * Please inquire about commercial licensing options at 34f7c85330SMatthias Ringwald * [email protected] 35f7c85330SMatthias Ringwald * 36f7c85330SMatthias Ringwald */ 37f7c85330SMatthias Ringwald 38f7c85330SMatthias Ringwald /* 39f7c85330SMatthias Ringwald * sco_demo_util.c - send/receive test data via SCO, used by hfp_*_demo and hsp_*_demo 40f7c85330SMatthias Ringwald */ 41f7c85330SMatthias Ringwald 422ec72fbbSMilanka Ringwald #include <stdio.h> 432ec72fbbSMilanka Ringwald 44f7c85330SMatthias Ringwald #include "sco_demo_util.h" 45fcb08cdbSMilanka Ringwald #include "btstack_debug.h" 4635fd3fb9SMatthias Ringwald #include "classic/btstack_sbc.h" 4735fd3fb9SMatthias Ringwald #include "classic/btstack_cvsd_plc.h" 4835fd3fb9SMatthias Ringwald #include "classic/hfp_msbc.h" 4935fd3fb9SMatthias Ringwald #include "classic/hfp.h" 50fcb08cdbSMilanka Ringwald 5135fd3fb9SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 52fbc7c9f2SMilanka Ringwald #include "wav_util.h" 5335fd3fb9SMatthias Ringwald #endif 54fbc7c9f2SMilanka Ringwald 55c4e666bcSMatthias Ringwald #ifdef HAVE_PORTAUDIO 56c4e666bcSMatthias Ringwald #include <portaudio.h> 57c4e666bcSMatthias Ringwald #include "btstack_ring_buffer.h" 58c4e666bcSMatthias Ringwald #endif 59c4e666bcSMatthias Ringwald 60c4e666bcSMatthias Ringwald 61c4e666bcSMatthias Ringwald // test modes 62f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_SINE 0 63f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_ASCII 1 64f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_COUNTER 2 651a919128SMatthias Ringwald #define SCO_DEMO_MODE_55 3 661a919128SMatthias Ringwald #define SCO_DEMO_MODE_00 4 67*463c9c89SMatthias Ringwald #define SCO_DEMO_MODE_MICROPHONE 5 68f7c85330SMatthias Ringwald 69f7c85330SMatthias Ringwald // SCO demo configuration 70fcb08cdbSMilanka Ringwald #define SCO_DEMO_MODE SCO_DEMO_MODE_SINE 71c4e666bcSMatthias Ringwald 72c4e666bcSMatthias Ringwald // number of sco packets until 'report' on console 73f7c85330SMatthias Ringwald #define SCO_REPORT_PERIOD 100 74f7c85330SMatthias Ringwald 75c4e666bcSMatthias Ringwald // length and name of wav file on disc 76c4e666bcSMatthias Ringwald #define SCO_WAV_DURATION_IN_SECONDS 15 778b29cfc6SMatthias Ringwald #define SCO_WAV_FILENAME "sco_input.wav" 78c4e666bcSMatthias Ringwald 79c4e666bcSMatthias Ringwald // name of sbc test files 80d5e5f834SMatthias Ringwald #define SCO_MSBC_OUT_FILENAME "sco_output.msbc" 812308e108SMilanka Ringwald #define SCO_MSBC_IN_FILENAME "sco_input.msbc" 82220eb563SMilanka Ringwald 83c4e666bcSMatthias Ringwald // pre-buffer for CVSD and mSBC - also defines latency 84c4e666bcSMatthias Ringwald #define SCO_CVSD_PA_PREBUFFER_MS 50 85c4e666bcSMatthias Ringwald #define SCO_MSBC_PA_PREBUFFER_MS 50 868b29cfc6SMatthias Ringwald 87c4e666bcSMatthias Ringwald // constants 88c4e666bcSMatthias Ringwald #define NUM_CHANNELS 1 89c4e666bcSMatthias Ringwald #define CVSD_BYTES_PER_FRAME (2*NUM_CHANNELS) 90c4e666bcSMatthias Ringwald #define CVSD_SAMPLE_RATE 8000 91c4e666bcSMatthias Ringwald #define MSBC_SAMPLE_RATE 16000 92c4e666bcSMatthias Ringwald #define MSBC_BYTES_PER_FRAME (2*NUM_CHANNELS) 93f7c85330SMatthias Ringwald 94*463c9c89SMatthias Ringwald #if defined(HAVE_PORTAUDIO) && (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE || SCO_DEMO_MODE_MICROPHONE) 95f7c85330SMatthias Ringwald #define USE_PORTAUDIO 96c4e666bcSMatthias Ringwald #define CVSD_PA_PREBUFFER_BYTES (SCO_CVSD_PA_PREBUFFER_MS * CVSD_SAMPLE_RATE/1000 * CVSD_BYTES_PER_FRAME) 97c4e666bcSMatthias Ringwald #define MSBC_PA_PREBUFFER_BYTES (SCO_MSBC_PA_PREBUFFER_MS * MSBC_SAMPLE_RATE/1000 * MSBC_BYTES_PER_FRAME) 98f7c85330SMatthias Ringwald #endif 99f7c85330SMatthias Ringwald 100f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 101*463c9c89SMatthias Ringwald static PaStream * pa_output_stream; 102*463c9c89SMatthias Ringwald static int pa_output_started = 0; 103*463c9c89SMatthias Ringwald static int pa_output_paused = 0; 104*463c9c89SMatthias Ringwald static uint8_t pa_output_ring_buffer_storage[2*MSBC_PA_PREBUFFER_BYTES]; 105*463c9c89SMatthias Ringwald static btstack_ring_buffer_t pa_output_ring_buffer; 106f7c85330SMatthias Ringwald #endif 107f7c85330SMatthias Ringwald 108fcb08cdbSMilanka Ringwald static int dump_data = 1; 109fcb08cdbSMilanka Ringwald static int count_sent = 0; 110fcb08cdbSMilanka Ringwald static int count_received = 0; 111c4e666bcSMatthias Ringwald static int negotiated_codec = -1; 1121a919128SMatthias Ringwald static int phase = 0; 113c4e666bcSMatthias Ringwald static int num_audio_frames = 0; 114c4e666bcSMatthias Ringwald 115c4e666bcSMatthias Ringwald static btstack_sbc_decoder_state_t decoder_state; 116c4e666bcSMatthias Ringwald static btstack_cvsd_plc_state_t cvsd_plc_state; 117c4e666bcSMatthias Ringwald static int num_samples_to_write; 118fcb08cdbSMilanka Ringwald 119d5e5f834SMatthias Ringwald FILE * msbc_file_in; 120d5e5f834SMatthias Ringwald FILE * msbc_file_out; 1217294d009SMatthias Ringwald 122f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 123d6a06398SMatthias Ringwald 12435fd3fb9SMatthias Ringwald // input signal: pre-computed sine wave, 160 Hz at 16000 kHz 125c4e666bcSMatthias Ringwald static const int16_t sine_int16_at_16000hz[] = { 12635fd3fb9SMatthias Ringwald 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 12735fd3fb9SMatthias Ringwald 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 12835fd3fb9SMatthias Ringwald 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 12935fd3fb9SMatthias Ringwald 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 13035fd3fb9SMatthias Ringwald 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 13135fd3fb9SMatthias Ringwald 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 13235fd3fb9SMatthias Ringwald -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 13335fd3fb9SMatthias Ringwald -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 13435fd3fb9SMatthias Ringwald -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 13535fd3fb9SMatthias Ringwald -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 13635fd3fb9SMatthias Ringwald }; 13735fd3fb9SMatthias Ringwald 138c4e666bcSMatthias Ringwald // ony use every second value from 16khz table 139c4e666bcSMatthias Ringwald static void sco_demo_sine_wave_int16_at_8000_hz(int num_samples, int16_t * data){ 14035fd3fb9SMatthias Ringwald int i; 14135fd3fb9SMatthias Ringwald for (i=0; i < num_samples; i++){ 142c4e666bcSMatthias Ringwald data[i] = sine_int16_at_16000hz[phase++]; 14335fd3fb9SMatthias Ringwald phase++; 144c4e666bcSMatthias Ringwald if (phase >= (sizeof(sine_int16_at_16000hz) / sizeof(int16_t))){ 14535fd3fb9SMatthias Ringwald phase = 0; 14635fd3fb9SMatthias Ringwald } 14735fd3fb9SMatthias Ringwald } 14835fd3fb9SMatthias Ringwald } 14935fd3fb9SMatthias Ringwald 15035fd3fb9SMatthias Ringwald static void sco_demo_fill_audio_frame(void){ 15135fd3fb9SMatthias Ringwald if (!hfp_msbc_can_encode_audio_frame_now()) return; 15235fd3fb9SMatthias Ringwald int num_samples = hfp_msbc_num_audio_samples_per_frame(); 15335fd3fb9SMatthias Ringwald int16_t sample_buffer[num_samples]; 154c4e666bcSMatthias Ringwald sco_demo_sine_wave_int16_at_8000_hz(num_samples, sample_buffer); 15535fd3fb9SMatthias Ringwald hfp_msbc_encode_audio_frame(sample_buffer); 15635fd3fb9SMatthias Ringwald num_audio_frames++; 15735fd3fb9SMatthias Ringwald } 158dbb41bfeSMilanka Ringwald 159c4e666bcSMatthias Ringwald #ifdef SCO_WAV_FILENAME 160dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 161c4e666bcSMatthias Ringwald static int portaudio_callback( const void *inputBuffer, void *outputBuffer, 162dbb41bfeSMilanka Ringwald unsigned long framesPerBuffer, 163dbb41bfeSMilanka Ringwald const PaStreamCallbackTimeInfo* timeInfo, 164dbb41bfeSMilanka Ringwald PaStreamCallbackFlags statusFlags, 165dbb41bfeSMilanka Ringwald void *userData ) { 166dbb41bfeSMilanka Ringwald (void) timeInfo; /* Prevent unused variable warnings. */ 167dbb41bfeSMilanka Ringwald (void) statusFlags; 168dbb41bfeSMilanka Ringwald (void) inputBuffer; 1693963d036SMatthias Ringwald (void) userData; 170dbb41bfeSMilanka Ringwald 171c4e666bcSMatthias Ringwald // config based on codec 172c4e666bcSMatthias Ringwald int bytes_to_copy; 173c4e666bcSMatthias Ringwald int prebuffer_bytes; 174c4e666bcSMatthias Ringwald switch (negotiated_codec){ 175c4e666bcSMatthias Ringwald case HFP_CODEC_MSBC: 176c4e666bcSMatthias Ringwald bytes_to_copy = framesPerBuffer * MSBC_BYTES_PER_FRAME; 177c4e666bcSMatthias Ringwald prebuffer_bytes = MSBC_PA_PREBUFFER_BYTES; 178c4e666bcSMatthias Ringwald break; 179c4e666bcSMatthias Ringwald case HFP_CODEC_CVSD: 180c4e666bcSMatthias Ringwald bytes_to_copy = framesPerBuffer * CVSD_BYTES_PER_FRAME; 181c4e666bcSMatthias Ringwald prebuffer_bytes = CVSD_PA_PREBUFFER_BYTES; 182c4e666bcSMatthias Ringwald break; 183c4e666bcSMatthias Ringwald default: 184c4e666bcSMatthias Ringwald bytes_to_copy = framesPerBuffer * 2; // assume 1 channel / 16 bit audio samples 185c4e666bcSMatthias Ringwald prebuffer_bytes = 0xfffffff; 186c4e666bcSMatthias Ringwald break; 187dbb41bfeSMilanka Ringwald } 188dbb41bfeSMilanka Ringwald 189c4e666bcSMatthias Ringwald // fill with silence while paused 190*463c9c89SMatthias Ringwald if (pa_output_paused){ 191*463c9c89SMatthias Ringwald if (btstack_ring_buffer_bytes_available(&pa_output_ring_buffer) < prebuffer_bytes){ 192c4e666bcSMatthias Ringwald memset(outputBuffer, 0, bytes_to_copy); 193c4e666bcSMatthias Ringwald return 0; 194dbb41bfeSMilanka Ringwald } else { 195c4e666bcSMatthias Ringwald // resume playback 196*463c9c89SMatthias Ringwald pa_output_paused = 0; 197dbb41bfeSMilanka Ringwald } 198c4e666bcSMatthias Ringwald } 199c4e666bcSMatthias Ringwald 200c4e666bcSMatthias Ringwald // get data from ringbuffer 201c4e666bcSMatthias Ringwald uint32_t bytes_read = 0; 202*463c9c89SMatthias Ringwald btstack_ring_buffer_read(&pa_output_ring_buffer, outputBuffer, bytes_to_copy, &bytes_read); 203c4e666bcSMatthias Ringwald bytes_to_copy -= bytes_read; 204c4e666bcSMatthias Ringwald 205c4e666bcSMatthias Ringwald // fill with 0 if not enough 206c4e666bcSMatthias Ringwald if (bytes_to_copy){ 207c4e666bcSMatthias Ringwald memset(outputBuffer + bytes_read, 0, bytes_to_copy); 208*463c9c89SMatthias Ringwald pa_output_paused = 1; 209c4e666bcSMatthias Ringwald } 210dbb41bfeSMilanka Ringwald return 0; 211dbb41bfeSMilanka Ringwald } 2128b29cfc6SMatthias Ringwald 213c4e666bcSMatthias Ringwald static void portaudio_start(void){ 214*463c9c89SMatthias Ringwald if (!pa_output_started){ 215dbb41bfeSMilanka Ringwald /* -- start stream -- */ 216*463c9c89SMatthias Ringwald PaError err = Pa_StartStream(pa_output_stream); 217dbb41bfeSMilanka Ringwald if (err != paNoError){ 218dbb41bfeSMilanka Ringwald printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 219dbb41bfeSMilanka Ringwald return; 220dbb41bfeSMilanka Ringwald } 221*463c9c89SMatthias Ringwald pa_output_started = 1; 222*463c9c89SMatthias Ringwald pa_output_paused = 1; 223dbb41bfeSMilanka Ringwald } 224c4e666bcSMatthias Ringwald } 225c4e666bcSMatthias Ringwald 226c4e666bcSMatthias Ringwald // return 1 if ok 227c4e666bcSMatthias Ringwald static int portaudio_initialize(int sample_rate){ 228c4e666bcSMatthias Ringwald PaError err; 229c4e666bcSMatthias Ringwald PaStreamParameters outputParameters; 230c4e666bcSMatthias Ringwald 231c4e666bcSMatthias Ringwald /* -- initialize PortAudio -- */ 232c4e666bcSMatthias Ringwald printf("PortAudio: Initialize\n"); 233c4e666bcSMatthias Ringwald err = Pa_Initialize(); 234c4e666bcSMatthias Ringwald if( err != paNoError ) return 0; 235c4e666bcSMatthias Ringwald /* -- setup input and output -- */ 236c4e666bcSMatthias Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 237c4e666bcSMatthias Ringwald outputParameters.channelCount = NUM_CHANNELS; 238c4e666bcSMatthias Ringwald outputParameters.sampleFormat = paInt16; 239c4e666bcSMatthias Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 240c4e666bcSMatthias Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 241c4e666bcSMatthias Ringwald /* -- setup stream -- */ 242c4e666bcSMatthias Ringwald printf("PortAudio: Open stream\n"); 243c4e666bcSMatthias Ringwald err = Pa_OpenStream( 244c4e666bcSMatthias Ringwald &stream, 245c4e666bcSMatthias Ringwald NULL, // &inputParameters, 246c4e666bcSMatthias Ringwald &outputParameters, 247c4e666bcSMatthias Ringwald sample_rate, 248c4e666bcSMatthias Ringwald 0, 249c4e666bcSMatthias Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 250c4e666bcSMatthias Ringwald portaudio_callback, 251c4e666bcSMatthias Ringwald NULL ); 252c4e666bcSMatthias Ringwald if (err != paNoError){ 253c4e666bcSMatthias Ringwald printf("Error opening portaudio stream: \"%s\"\n", Pa_GetErrorText(err)); 254c4e666bcSMatthias Ringwald return 0; 255c4e666bcSMatthias Ringwald } 256*463c9c89SMatthias Ringwald memset(pa_output_ring_buffer_storage, 0, sizeof(pa_output_ring_buffer_storage)); 257*463c9c89SMatthias Ringwald btstack_ring_buffer_init(&pa_output_ring_buffer, pa_output_ring_buffer_storage, sizeof(pa_output_ring_buffer_storage)); 258*463c9c89SMatthias Ringwald pa_output_started = 0; 259c4e666bcSMatthias Ringwald return 1; 260c4e666bcSMatthias Ringwald } 261c4e666bcSMatthias Ringwald #endif 262c4e666bcSMatthias Ringwald 263c4e666bcSMatthias Ringwald 264c4e666bcSMatthias Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 265c4e666bcSMatthias Ringwald UNUSED(context); 266c4e666bcSMatthias Ringwald UNUSED(sample_rate); 267c4e666bcSMatthias Ringwald 268c4e666bcSMatthias Ringwald // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels); 269c4e666bcSMatthias Ringwald #ifdef HAVE_PORTAUDIO 270c4e666bcSMatthias Ringwald portaudio_start(); 271*463c9c89SMatthias Ringwald btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2); 2729ec2630cSMatthias Ringwald #else 2739ec2630cSMatthias Ringwald UNUSED(num_channels); 274dbb41bfeSMilanka Ringwald #endif 275dbb41bfeSMilanka Ringwald 276fcb08cdbSMilanka Ringwald if (!num_samples_to_write) return; 277fcb08cdbSMilanka Ringwald 278fcb08cdbSMilanka Ringwald num_samples = btstack_min(num_samples, num_samples_to_write); 279fcb08cdbSMilanka Ringwald num_samples_to_write -= num_samples; 280fcb08cdbSMilanka Ringwald 281fbc7c9f2SMilanka Ringwald wav_writer_write_int16(num_samples, data); 282fcb08cdbSMilanka Ringwald 283fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 284fcb08cdbSMilanka Ringwald sco_demo_close(); 285fcb08cdbSMilanka Ringwald } 286fcb08cdbSMilanka Ringwald } 287fcb08cdbSMilanka Ringwald 288fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){ 289c4e666bcSMatthias Ringwald printf("SCO Demo: Init mSBC\n"); 290c4e666bcSMatthias Ringwald 291c4e666bcSMatthias Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, MSBC_SAMPLE_RATE); 292fbc7c9f2SMilanka Ringwald btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL); 293fcb08cdbSMilanka Ringwald 294c4e666bcSMatthias Ringwald num_samples_to_write = MSBC_SAMPLE_RATE * SCO_WAV_DURATION_IN_SECONDS; 295220eb563SMilanka Ringwald 296220eb563SMilanka Ringwald hfp_msbc_init(); 297220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 298973d7173SMatthias Ringwald 299d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME 300d5e5f834SMatthias Ringwald msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb"); 301d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in); 302d5e5f834SMatthias Ringwald #endif 3037294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME 304d5e5f834SMatthias Ringwald msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb"); 305d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out); 3067294d009SMatthias Ringwald #endif 307dbb41bfeSMilanka Ringwald 308dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 309c4e666bcSMatthias Ringwald portaudio_initialize(MSBC_SAMPLE_RATE); 310dbb41bfeSMilanka Ringwald #endif 311fcb08cdbSMilanka Ringwald } 312fcb08cdbSMilanka Ringwald 313fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){ 314fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 315d5e5f834SMatthias Ringwald if (msbc_file_in){ 316d5e5f834SMatthias Ringwald // log incoming mSBC data for testing 317d5e5f834SMatthias Ringwald fwrite(packet+3, size-3, 1, msbc_file_in); 318d5e5f834SMatthias Ringwald } 319fcb08cdbSMilanka Ringwald } 320dbb41bfeSMilanka Ringwald btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3); 321fcb08cdbSMilanka Ringwald } 322fcb08cdbSMilanka Ringwald 323fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){ 324c4e666bcSMatthias Ringwald printf("SCO Demo: Init CVSD\n"); 325c4e666bcSMatthias Ringwald 326c4e666bcSMatthias Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, CVSD_SAMPLE_RATE); 327fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_init(&cvsd_plc_state); 328c4e666bcSMatthias Ringwald 329c4e666bcSMatthias Ringwald num_samples_to_write = CVSD_SAMPLE_RATE * SCO_WAV_DURATION_IN_SECONDS; 330dbb41bfeSMilanka Ringwald 331dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 332c4e666bcSMatthias Ringwald portaudio_initialize(CVSD_SAMPLE_RATE); 333dbb41bfeSMilanka Ringwald #endif 334fbc7c9f2SMilanka Ringwald } 335fbc7c9f2SMilanka Ringwald 336fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){ 337dbb41bfeSMilanka Ringwald if (!num_samples_to_write) return; 338c4e666bcSMatthias Ringwald int16_t audio_frame_out[255]; // 3391f8694ccSMatthias Ringwald 3401f8694ccSMatthias Ringwald if (size > sizeof(audio_frame_out)){ 3411f8694ccSMatthias Ringwald printf("sco_demo_receive_CVSD: SCO packet larger than local output buffer - dropping data.\n"); 3421f8694ccSMatthias Ringwald return; 3431f8694ccSMatthias Ringwald } 344c4e666bcSMatthias Ringwald const int audio_bytes_read = size - 3; 345c4e666bcSMatthias Ringwald const int num_samples = audio_bytes_read / CVSD_BYTES_PER_FRAME; 346fcb08cdbSMilanka Ringwald const int samples_to_write = btstack_min(num_samples, num_samples_to_write); 347379d044eSMilanka Ringwald 348c4e666bcSMatthias Ringwald #if 0 349fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out); 350c4e666bcSMatthias Ringwald #else 351c4e666bcSMatthias Ringwald memcpy(audio_frame_out, packet+3, audio_bytes_read); 352c4e666bcSMatthias Ringwald #endif 353379d044eSMilanka Ringwald 354c4e666bcSMatthias Ringwald wav_writer_write_int16(samples_to_write, audio_frame_out); 355fcb08cdbSMilanka Ringwald num_samples_to_write -= samples_to_write; 356fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 357fcb08cdbSMilanka Ringwald sco_demo_close(); 358fcb08cdbSMilanka Ringwald } 359dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 360c4e666bcSMatthias Ringwald portaudio_start(); 361*463c9c89SMatthias Ringwald btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read); 362dbb41bfeSMilanka Ringwald #endif 363fcb08cdbSMilanka Ringwald } 364fcb08cdbSMilanka Ringwald 3658b29cfc6SMatthias Ringwald #endif 3664a96141eSMatthias Ringwald #endif 3678b29cfc6SMatthias Ringwald 368fcb08cdbSMilanka Ringwald void sco_demo_close(void){ 369c4e666bcSMatthias Ringwald printf("SCO demo close\n"); 370fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 37126463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 372fbc7c9f2SMilanka Ringwald wav_writer_close(); 37326463303SMilanka Ringwald printf("SCO demo statistics: "); 37426463303SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 37526463303SMilanka Ringwald printf("Used mSBC with PLC, number of processed frames: \n - %d good frames, \n - %d zero frames, \n - %d bad frames.", decoder_state.good_frames_nr, decoder_state.zero_frames_nr, decoder_state.bad_frames_nr); 37626463303SMilanka Ringwald } else { 37726463303SMilanka Ringwald printf("Used CVSD with PLC, number of proccesed frames: \n - %d good frames, \n - %d bad frames.", cvsd_plc_state.good_frames_nr, cvsd_plc_state.bad_frames_nr); 37826463303SMilanka Ringwald } 37926463303SMilanka Ringwald #endif 38026463303SMilanka Ringwald 381dbb41bfeSMilanka Ringwald #ifdef HAVE_PORTAUDIO 382*463c9c89SMatthias Ringwald if (pa_output_started){ 383c4e666bcSMatthias Ringwald printf("PortAudio: Stop Stream\n"); 384*463c9c89SMatthias Ringwald PaError err = Pa_StopStream(pa_output_stream); 385dbb41bfeSMilanka Ringwald if (err != paNoError){ 386dbb41bfeSMilanka Ringwald printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err)); 387dbb41bfeSMilanka Ringwald return; 388dbb41bfeSMilanka Ringwald } 389*463c9c89SMatthias Ringwald pa_output_started = 0; 390c4e666bcSMatthias Ringwald printf("PortAudio: Close Stream\n"); 391*463c9c89SMatthias Ringwald err = Pa_CloseStream(pa_output_stream); 392dbb41bfeSMilanka Ringwald if (err != paNoError){ 393dbb41bfeSMilanka Ringwald printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err)); 394dbb41bfeSMilanka Ringwald return; 395dbb41bfeSMilanka Ringwald } 396dbb41bfeSMilanka Ringwald 397c4e666bcSMatthias Ringwald printf("PortAudio: Terminate\n"); 398dbb41bfeSMilanka Ringwald err = Pa_Terminate(); 399dbb41bfeSMilanka Ringwald if (err != paNoError){ 400dbb41bfeSMilanka Ringwald printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err)); 401dbb41bfeSMilanka Ringwald return; 402dbb41bfeSMilanka Ringwald } 403dbb41bfeSMilanka Ringwald } 404dbb41bfeSMilanka Ringwald #endif 405fcb08cdbSMilanka Ringwald 406c4e666bcSMatthias Ringwald #ifdef SCO_WAV_FILENAME 407613518d1SMilanka Ringwald #if 0 408fcb08cdbSMilanka Ringwald printf("SCO Demo: closing wav file\n"); 409220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 4106e046a36SMatthias Ringwald wav_writer_state_t * writer_state = &wav_writer_state; 411fcb08cdbSMilanka Ringwald if (!writer_state->wav_file) return; 412fcb08cdbSMilanka Ringwald rewind(writer_state->wav_file); 4132afeea7fSMilanka Ringwald write_wav_header(writer_state->wav_file, writer_state->total_num_samples, btstack_sbc_decoder_num_channels(&decoder_state), btstack_sbc_decoder_sample_rate(&decoder_state),2); 414fcb08cdbSMilanka Ringwald fclose(writer_state->wav_file); 415fcb08cdbSMilanka Ringwald writer_state->wav_file = NULL; 416fcb08cdbSMilanka Ringwald } 417613518d1SMilanka Ringwald #endif 418fcb08cdbSMilanka Ringwald #endif 419c4e666bcSMatthias Ringwald 420c4e666bcSMatthias Ringwald negotiated_codec = -1; 421c4e666bcSMatthias Ringwald 422fcb08cdbSMilanka Ringwald #endif 423fcb08cdbSMilanka Ringwald } 424fcb08cdbSMilanka Ringwald 425fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){ 426fcb08cdbSMilanka Ringwald if (negotiated_codec == codec) return; 427fcb08cdbSMilanka Ringwald negotiated_codec = codec; 428fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 42917cd946eSMatthias Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 430220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 431fcb08cdbSMilanka Ringwald sco_demo_init_mSBC(); 432fcb08cdbSMilanka Ringwald } else { 433fcb08cdbSMilanka Ringwald sco_demo_init_CVSD(); 434fcb08cdbSMilanka Ringwald } 435fcb08cdbSMilanka Ringwald #endif 436fcb08cdbSMilanka Ringwald #endif 437fcb08cdbSMilanka Ringwald } 438fcb08cdbSMilanka Ringwald 439f7c85330SMatthias Ringwald void sco_demo_init(void){ 440f7c85330SMatthias Ringwald 441f7c85330SMatthias Ringwald // status 442f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 443f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO 444f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, audio output via portaudio.\n"); 445f7c85330SMatthias Ringwald #else 446f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, hexdump received data.\n"); 447f7c85330SMatthias Ringwald #endif 448f7c85330SMatthias Ringwald #endif 449f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 450f7c85330SMatthias Ringwald printf("SCO Demo: Sending ASCII blocks, print received data.\n"); 451f7c85330SMatthias Ringwald #endif 452f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 453f7c85330SMatthias Ringwald printf("SCO Demo: Sending counter value, hexdump received data.\n"); 454f7c85330SMatthias Ringwald #endif 455f7c85330SMatthias Ringwald 456c4e666bcSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 457c4e666bcSMatthias Ringwald hci_set_sco_voice_setting(0x60); // linear, unsigned, 16-bit, CVSD 458c4e666bcSMatthias Ringwald #else 459f7c85330SMatthias Ringwald hci_set_sco_voice_setting(0x03); // linear, unsigned, 8-bit, transparent 4607294d009SMatthias Ringwald #endif 461f7c85330SMatthias Ringwald 462f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 463f7c85330SMatthias Ringwald phase = 'a'; 464f7c85330SMatthias Ringwald #endif 465f7c85330SMatthias Ringwald } 466f7c85330SMatthias Ringwald 4671a919128SMatthias Ringwald void sco_report(void); 4681a919128SMatthias Ringwald void sco_report(void){ 4694a96141eSMatthias Ringwald printf("SCO: sent %u, received %u\n", count_sent, count_received); 4704a96141eSMatthias Ringwald } 471f7c85330SMatthias Ringwald 472f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){ 473f7c85330SMatthias Ringwald 474f7c85330SMatthias Ringwald if (!sco_handle) return; 475f7c85330SMatthias Ringwald 476c4e666bcSMatthias Ringwald int sco_packet_length = hci_get_sco_packet_length(); 477c4e666bcSMatthias Ringwald int sco_payload_length = sco_packet_length - 3; 478f7c85330SMatthias Ringwald 479f7c85330SMatthias Ringwald hci_reserve_packet_buffer(); 480f7c85330SMatthias Ringwald uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); 481f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 482220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 483220eb563SMilanka Ringwald 484c4e666bcSMatthias Ringwald // overwrite 485c4e666bcSMatthias Ringwald sco_payload_length = 24; 486c4e666bcSMatthias Ringwald sco_packet_length = sco_payload_length + 3; 487c4e666bcSMatthias Ringwald 488220eb563SMilanka Ringwald if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){ 489220eb563SMilanka Ringwald log_error("mSBC stream is empty."); 490220eb563SMilanka Ringwald } 491220eb563SMilanka Ringwald hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length); 492d5e5f834SMatthias Ringwald if (msbc_file_out){ 493d76591efSMatthias Ringwald // log outgoing mSBC data for testing 494d5e5f834SMatthias Ringwald fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out); 495d76591efSMatthias Ringwald } 4967294d009SMatthias Ringwald 497220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 498220eb563SMilanka Ringwald } else { 499c4e666bcSMatthias Ringwald const int audio_samples_per_packet = sco_payload_length / CVSD_BYTES_PER_FRAME; 500c4e666bcSMatthias Ringwald sco_demo_sine_wave_int16_at_8000_hz(audio_samples_per_packet, (int16_t *) (sco_packet+3)); 501220eb563SMilanka Ringwald } 5021a919128SMatthias Ringwald #endif 503f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 504c4e666bcSMatthias Ringwald memset(&sco_packet[3], phase++, sco_payload_length); 505f7c85330SMatthias Ringwald if (phase > 'z') phase = 'a'; 5061a919128SMatthias Ringwald #endif 5071a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 50838b2eaafSMatthias Ringwald int j; 509c4e666bcSMatthias Ringwald for (j=0;j<sco_payload_length;j++){ 51038b2eaafSMatthias Ringwald sco_packet[3+j] = phase++; 511f7c85330SMatthias Ringwald } 512f7c85330SMatthias Ringwald #endif 5131a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 5141a919128SMatthias Ringwald int j; 515c4e666bcSMatthias Ringwald for (j=0;j<sco_payload_length;j++){ 5161a919128SMatthias Ringwald // sco_packet[3+j] = j & 1 ? 0x35 : 0x53; 5171a919128SMatthias Ringwald sco_packet[3+j] = 0x55; 5181a919128SMatthias Ringwald } 5191a919128SMatthias Ringwald #endif 5201a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_00 5211a919128SMatthias Ringwald int j; 522c4e666bcSMatthias Ringwald for (j=0;j<sco_payload_length;j++){ 5231a919128SMatthias Ringwald sco_packet[3+j] = 0x00; 5241a919128SMatthias Ringwald } 5251a919128SMatthias Ringwald // additional hack 5261a919128SMatthias Ringwald // big_endian_store_16(sco_packet, 5, phase++); 5271a919128SMatthias Ringwald (void) phase; 528f7c85330SMatthias Ringwald #endif 529220eb563SMilanka Ringwald 530c4e666bcSMatthias Ringwald // set handle + flags 531c4e666bcSMatthias Ringwald little_endian_store_16(sco_packet, 0, sco_handle); 532c4e666bcSMatthias Ringwald // set len 533c4e666bcSMatthias Ringwald sco_packet[2] = sco_payload_length; 534c4e666bcSMatthias Ringwald // finally send packet 535f7c85330SMatthias Ringwald hci_send_sco_packet_buffer(sco_packet_length); 536f7c85330SMatthias Ringwald 537f7c85330SMatthias Ringwald // request another send event 538f7c85330SMatthias Ringwald hci_request_sco_can_send_now_event(); 539f7c85330SMatthias Ringwald 5404a96141eSMatthias Ringwald count_sent++; 5411a919128SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_55 5424a96141eSMatthias Ringwald if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report(); 5431a919128SMatthias Ringwald #endif 544f7c85330SMatthias Ringwald } 545f7c85330SMatthias Ringwald 546f7c85330SMatthias Ringwald /** 547f7c85330SMatthias Ringwald * @brief Process received data 548f7c85330SMatthias Ringwald */ 5491a919128SMatthias Ringwald #define ANSI_COLOR_RED "\x1b[31m" 5501a919128SMatthias Ringwald #define ANSI_COLOR_GREEN "\x1b[32m" 5511a919128SMatthias Ringwald #define ANSI_COLOR_YELLOW "\x1b[33m" 5521a919128SMatthias Ringwald #define ANSI_COLOR_BLUE "\x1b[34m" 5531a919128SMatthias Ringwald #define ANSI_COLOR_MAGENTA "\x1b[35m" 5541a919128SMatthias Ringwald #define ANSI_COLOR_CYAN "\x1b[36m" 5551a919128SMatthias Ringwald #define ANSI_COLOR_RESET "\x1b[0m" 5561a919128SMatthias Ringwald 557f7c85330SMatthias Ringwald void sco_demo_receive(uint8_t * packet, uint16_t size){ 558f7c85330SMatthias Ringwald 559fcb08cdbSMilanka Ringwald dump_data = 1; 5608b29cfc6SMatthias Ringwald 5614a96141eSMatthias Ringwald count_received++; 5621a919128SMatthias Ringwald static uint32_t packets = 0; 5631a919128SMatthias Ringwald static uint32_t crc_errors = 0; 5641a919128SMatthias Ringwald static uint32_t data_received = 0; 5651a919128SMatthias Ringwald static uint32_t byte_errors = 0; 5664a96141eSMatthias Ringwald 5671a919128SMatthias Ringwald data_received += size - 3; 5681a919128SMatthias Ringwald packets++; 5691a919128SMatthias Ringwald if (data_received > 100000){ 5701a919128SMatthias Ringwald printf("Summary: data %07u, packets %04u, packet with crc errors %0u, byte errors %04u\n", data_received, packets, crc_errors, byte_errors); 5711a919128SMatthias Ringwald crc_errors = 0; 5721a919128SMatthias Ringwald byte_errors = 0; 5731a919128SMatthias Ringwald data_received = 0; 5741a919128SMatthias Ringwald packets = 0; 5751a919128SMatthias Ringwald } 5764a96141eSMatthias Ringwald 5774a96141eSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 5788b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 579c4e666bcSMatthias Ringwald switch (negotiated_codec){ 580c4e666bcSMatthias Ringwald case HFP_CODEC_MSBC: 581fcb08cdbSMilanka Ringwald sco_demo_receive_mSBC(packet, size); 582c4e666bcSMatthias Ringwald break; 583c4e666bcSMatthias Ringwald case HFP_CODEC_CVSD: 584fcb08cdbSMilanka Ringwald sco_demo_receive_CVSD(packet, size); 585c4e666bcSMatthias Ringwald break; 586c4e666bcSMatthias Ringwald default: 587c4e666bcSMatthias Ringwald break; 5888b29cfc6SMatthias Ringwald } 589dbb41bfeSMilanka Ringwald dump_data = 0; 5908b29cfc6SMatthias Ringwald #endif 5914a96141eSMatthias Ringwald #endif 5928b29cfc6SMatthias Ringwald 593b3f76298SMilanka Ringwald if (packet[1] & 0x30){ 5941a919128SMatthias Ringwald crc_errors++; 5951a919128SMatthias Ringwald // printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4); 5961a919128SMatthias Ringwald // printf_hexdump(&packet[3], size-3); 597f7c85330SMatthias Ringwald return; 598f7c85330SMatthias Ringwald } 5998b29cfc6SMatthias Ringwald if (dump_data){ 600f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 6011a919128SMatthias Ringwald printf("data: "); 602f7c85330SMatthias Ringwald int i; 603f7c85330SMatthias Ringwald for (i=3;i<size;i++){ 604f7c85330SMatthias Ringwald printf("%c", packet[i]); 605f7c85330SMatthias Ringwald } 606f7c85330SMatthias Ringwald printf("\n"); 6078b29cfc6SMatthias Ringwald dump_data = 0; 6081a919128SMatthias Ringwald #endif 6091a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 6101a919128SMatthias Ringwald // colored hexdump with expected 6111a919128SMatthias Ringwald static uint8_t expected_byte = 0; 6121a919128SMatthias Ringwald int i; 6131a919128SMatthias Ringwald printf("data: "); 6141a919128SMatthias Ringwald for (i=3;i<size;i++){ 6151a919128SMatthias Ringwald if (packet[i] != expected_byte){ 6161a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 6171a919128SMatthias Ringwald } else { 6181a919128SMatthias Ringwald printf("%02x ", packet[i]); 6191a919128SMatthias Ringwald } 6201a919128SMatthias Ringwald expected_byte = packet[i]+1; 6211a919128SMatthias Ringwald } 6221a919128SMatthias Ringwald printf("\n"); 6231a919128SMatthias Ringwald #endif 624a11bf416SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE == SCO_DEMO_MODE_00 6251a919128SMatthias Ringwald int i; 6261a919128SMatthias Ringwald int contains_error = 0; 6271a919128SMatthias Ringwald for (i=3;i<size;i++){ 6281a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 6291a919128SMatthias Ringwald contains_error = 1; 6301a919128SMatthias Ringwald byte_errors++; 6311a919128SMatthias Ringwald } 6321a919128SMatthias Ringwald } 6331a919128SMatthias Ringwald if (contains_error){ 6341a919128SMatthias Ringwald printf("data: "); 6351a919128SMatthias Ringwald for (i=0;i<3;i++){ 6361a919128SMatthias Ringwald printf("%02x ", packet[i]); 6371a919128SMatthias Ringwald } 6381a919128SMatthias Ringwald for (i=3;i<size;i++){ 6391a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 6401a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 6411a919128SMatthias Ringwald } else { 6421a919128SMatthias Ringwald printf("%02x ", packet[i]); 6431a919128SMatthias Ringwald } 6441a919128SMatthias Ringwald } 6451a919128SMatthias Ringwald printf("\n"); 6461a919128SMatthias Ringwald } 647f7c85330SMatthias Ringwald #endif 6488b29cfc6SMatthias Ringwald } 649f7c85330SMatthias Ringwald } 650