Skip to content

Commit a8b10fe

Browse files
committed
Keep A2DP configuration check in codec files
In order to simplify error handling, the check function stops on first error. Now, the D-Bus API for codec selection returns human readable error message describing the cause of error.
1 parent 5f2bdc0 commit a8b10fe

File tree

13 files changed

+406
-242
lines changed

13 files changed

+406
-242
lines changed

src/a2dp-aac.c

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,43 @@ static int a2dp_aac_configuration_select(
552552
return 0;
553553
}
554554

555+
static int a2dp_aac_configuration_check(
556+
const struct a2dp_codec *codec,
557+
const void *configuration) {
558+
559+
const a2dp_aac_t *conf = configuration;
560+
a2dp_aac_t conf_v = *conf;
561+
562+
/* validate configuration against BlueALSA capabilities */
563+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
564+
&conf_v, sizeof(conf_v)) != 0)
565+
return A2DP_CHECK_ERR_SIZE;
566+
567+
switch (conf_v.object_type) {
568+
case AAC_OBJECT_TYPE_MPEG2_AAC_LC:
569+
case AAC_OBJECT_TYPE_MPEG4_AAC_LC:
570+
case AAC_OBJECT_TYPE_MPEG4_AAC_LTP:
571+
case AAC_OBJECT_TYPE_MPEG4_AAC_SCA:
572+
break;
573+
default:
574+
debug("AAC: Invalid object type: %#x", conf->object_type);
575+
return A2DP_CHECK_ERR_OBJECT_TYPE;
576+
}
577+
578+
const uint16_t conf_frequency = AAC_GET_FREQUENCY(conf_v);
579+
if (a2dp_sampling_lookup(a2dp_aac_samplings, conf_frequency) == NULL) {
580+
debug("AAC: Invalid sampling frequency: %#x", AAC_GET_FREQUENCY(*conf));
581+
return A2DP_CHECK_ERR_SAMPLING;
582+
}
583+
584+
if (a2dp_channel_mode_lookup(a2dp_aac_channels, conf_v.channels) == NULL) {
585+
debug("AAC: Invalid channel mode: %#x", conf->channels);
586+
return A2DP_CHECK_ERR_CHANNEL_MODE;
587+
}
588+
589+
return A2DP_CHECK_OK;
590+
}
591+
555592
static int a2dp_aac_transport_init(struct ba_transport *t) {
556593

557594
const struct a2dp_channel_mode *chm;
@@ -630,11 +667,10 @@ struct a2dp_codec a2dp_aac_source = {
630667
AAC_INIT_BITRATE(320000)
631668
},
632669
.capabilities_size = sizeof(a2dp_aac_t),
633-
.channels[0] = a2dp_aac_channels,
634-
.samplings[0] = a2dp_aac_samplings,
635670
.init = a2dp_aac_source_init,
636671
.capabilities_filter = a2dp_aac_capabilities_filter,
637672
.configuration_select = a2dp_aac_configuration_select,
673+
.configuration_check = a2dp_aac_configuration_check,
638674
.transport_init = a2dp_aac_transport_init,
639675
.transport_start = a2dp_aac_source_transport_start,
640676
.enabled = true,
@@ -691,11 +727,10 @@ struct a2dp_codec a2dp_aac_sink = {
691727
AAC_INIT_BITRATE(320000)
692728
},
693729
.capabilities_size = sizeof(a2dp_aac_t),
694-
.channels[0] = a2dp_aac_channels,
695-
.samplings[0] = a2dp_aac_samplings,
696730
.init = a2dp_aac_sink_init,
697731
.capabilities_filter = a2dp_aac_capabilities_filter,
698732
.configuration_select = a2dp_aac_configuration_select,
733+
.configuration_check = a2dp_aac_configuration_check,
699734
.transport_init = a2dp_aac_transport_init,
700735
.transport_start = a2dp_aac_sink_transport_start,
701736
.enabled = true,

src/a2dp-aptx-hd.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,31 @@ static int a2dp_aptx_hd_configuration_select(
313313
return 0;
314314
}
315315

316+
static int a2dp_aptx_hd_configuration_check(
317+
const struct a2dp_codec *codec,
318+
const void *configuration) {
319+
320+
const a2dp_aptx_hd_t *conf = configuration;
321+
a2dp_aptx_hd_t conf_v = *conf;
322+
323+
/* validate configuration against BlueALSA capabilities */
324+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
325+
&conf_v, sizeof(conf_v)) != 0)
326+
return A2DP_CHECK_ERR_SIZE;
327+
328+
if (a2dp_sampling_lookup(a2dp_aptx_hd_samplings, conf_v.aptx.frequency) == NULL) {
329+
debug("apt-X HD: Invalid sampling frequency: %#x", conf->aptx.frequency);
330+
return A2DP_CHECK_ERR_SAMPLING;
331+
}
332+
333+
if (a2dp_channel_mode_lookup(a2dp_aptx_hd_channels, conf_v.aptx.channel_mode) == NULL) {
334+
debug("apt-X HD: Invalid channel mode: %#x", conf->aptx.channel_mode);
335+
return A2DP_CHECK_ERR_CHANNEL_MODE;
336+
}
337+
338+
return A2DP_CHECK_OK;
339+
}
340+
316341
static int a2dp_aptx_hd_transport_init(struct ba_transport *t) {
317342

318343
const struct a2dp_channel_mode *chm;
@@ -361,10 +386,9 @@ struct a2dp_codec a2dp_aptx_hd_source = {
361386
APTX_SAMPLING_FREQ_48000,
362387
},
363388
.capabilities_size = sizeof(a2dp_aptx_hd_t),
364-
.channels[0] = a2dp_aptx_hd_channels,
365-
.samplings[0] = a2dp_aptx_hd_samplings,
366389
.init = a2dp_aptx_hd_source_init,
367390
.configuration_select = a2dp_aptx_hd_configuration_select,
391+
.configuration_check = a2dp_aptx_hd_configuration_check,
368392
.transport_init = a2dp_aptx_hd_transport_init,
369393
.transport_start = a2dp_aptx_hd_source_transport_start,
370394
};
@@ -392,9 +416,8 @@ struct a2dp_codec a2dp_aptx_hd_sink = {
392416
APTX_SAMPLING_FREQ_48000,
393417
},
394418
.capabilities_size = sizeof(a2dp_aptx_hd_t),
395-
.channels[0] = a2dp_aptx_hd_channels,
396-
.samplings[0] = a2dp_aptx_hd_samplings,
397419
.configuration_select = a2dp_aptx_hd_configuration_select,
420+
.configuration_check = a2dp_aptx_hd_configuration_check,
398421
.transport_init = a2dp_aptx_hd_transport_init,
399422
.transport_start = a2dp_aptx_hd_sink_transport_start,
400423
};

src/a2dp-aptx.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,31 @@ static int a2dp_aptx_configuration_select(
276276
return 0;
277277
}
278278

279+
static int a2dp_aptx_configuration_check(
280+
const struct a2dp_codec *codec,
281+
const void *configuration) {
282+
283+
const a2dp_aptx_t *conf = configuration;
284+
a2dp_aptx_t conf_v = *conf;
285+
286+
/* validate configuration against BlueALSA capabilities */
287+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
288+
&conf_v, sizeof(conf_v)) != 0)
289+
return A2DP_CHECK_ERR_SIZE;
290+
291+
if (a2dp_sampling_lookup(a2dp_aptx_samplings, conf_v.frequency) == NULL) {
292+
debug("apt-X: Invalid sampling frequency: %#x", conf->frequency);
293+
return A2DP_CHECK_ERR_SAMPLING;
294+
}
295+
296+
if (a2dp_channel_mode_lookup(a2dp_aptx_channels, conf_v.channel_mode) == NULL) {
297+
debug("apt-X: Invalid channel mode: %#x", conf->channel_mode);
298+
return A2DP_CHECK_ERR_CHANNEL_MODE;
299+
}
300+
301+
return A2DP_CHECK_OK;
302+
}
303+
279304
static int a2dp_aptx_transport_init(struct ba_transport *t) {
280305

281306
const struct a2dp_channel_mode *chm;
@@ -324,10 +349,9 @@ struct a2dp_codec a2dp_aptx_source = {
324349
APTX_SAMPLING_FREQ_48000,
325350
},
326351
.capabilities_size = sizeof(a2dp_aptx_t),
327-
.channels[0] = a2dp_aptx_channels,
328-
.samplings[0] = a2dp_aptx_samplings,
329352
.init = a2dp_aptx_source_init,
330353
.configuration_select = a2dp_aptx_configuration_select,
354+
.configuration_check = a2dp_aptx_configuration_check,
331355
.transport_init = a2dp_aptx_transport_init,
332356
.transport_start = a2dp_aptx_source_transport_start,
333357
};
@@ -355,9 +379,8 @@ struct a2dp_codec a2dp_aptx_sink = {
355379
APTX_SAMPLING_FREQ_48000,
356380
},
357381
.capabilities_size = sizeof(a2dp_aptx_t),
358-
.channels[0] = a2dp_aptx_channels,
359-
.samplings[0] = a2dp_aptx_samplings,
360382
.configuration_select = a2dp_aptx_configuration_select,
383+
.configuration_check = a2dp_aptx_configuration_check,
361384
.transport_init = a2dp_aptx_transport_init,
362385
.transport_start = a2dp_aptx_sink_transport_start,
363386
};

src/a2dp-faststream.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,40 @@ static int a2dp_faststream_configuration_select(
289289
return 0;
290290
}
291291

292+
static int a2dp_faststream_configuration_check(
293+
const struct a2dp_codec *codec,
294+
const void *configuration) {
295+
296+
const a2dp_faststream_t *conf = configuration;
297+
a2dp_faststream_t conf_v = *conf;
298+
299+
/* validate configuration against BlueALSA capabilities */
300+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
301+
&conf_v, sizeof(conf_v)) != 0)
302+
return A2DP_CHECK_ERR_SIZE;
303+
304+
switch (conf_v.direction) {
305+
case FASTSTREAM_DIRECTION_MUSIC:
306+
case FASTSTREAM_DIRECTION_VOICE:
307+
break;
308+
default:
309+
debug("FastStream: Invalid direction: %#x", conf->direction);
310+
return A2DP_CHECK_ERR_DIRECTIONS;
311+
}
312+
313+
if (a2dp_sampling_lookup(a2dp_faststream_samplings_voice, conf_v.frequency_voice) == NULL) {
314+
debug("FastStream: Invalid voice sampling frequency: %#x", conf->frequency_voice);
315+
return A2DP_CHECK_ERR_SAMPLING_VOICE;
316+
}
317+
318+
if (a2dp_sampling_lookup(a2dp_faststream_samplings_music, conf_v.frequency_music) == NULL) {
319+
debug("FastStream: Invalid music sampling frequency: %#x", conf->frequency_music);
320+
return A2DP_CHECK_ERR_SAMPLING_MUSIC;
321+
}
322+
323+
return A2DP_CHECK_OK;
324+
}
325+
292326
static int a2dp_faststream_transport_init(struct ba_transport *t) {
293327

294328
if (t->a2dp.configuration.faststream.direction & FASTSTREAM_DIRECTION_MUSIC) {
@@ -356,10 +390,9 @@ struct a2dp_codec a2dp_faststream_source = {
356390
FASTSTREAM_SAMPLING_FREQ_VOICE_16000,
357391
},
358392
.capabilities_size = sizeof(a2dp_faststream_t),
359-
.samplings[0] = a2dp_faststream_samplings_music,
360-
.samplings[1] = a2dp_faststream_samplings_voice,
361393
.init = a2dp_faststream_source_init,
362394
.configuration_select = a2dp_faststream_configuration_select,
395+
.configuration_check = a2dp_faststream_configuration_check,
363396
.transport_init = a2dp_faststream_transport_init,
364397
.transport_start = a2dp_faststream_source_transport_start,
365398
};
@@ -392,9 +425,8 @@ struct a2dp_codec a2dp_faststream_sink = {
392425
FASTSTREAM_SAMPLING_FREQ_VOICE_16000,
393426
},
394427
.capabilities_size = sizeof(a2dp_faststream_t),
395-
.samplings[0] = a2dp_faststream_samplings_music,
396-
.samplings[1] = a2dp_faststream_samplings_voice,
397428
.configuration_select = a2dp_faststream_configuration_select,
429+
.configuration_check = a2dp_faststream_configuration_check,
398430
.transport_init = a2dp_faststream_transport_init,
399431
.transport_start = a2dp_faststream_sink_transport_start,
400432
};

src/a2dp-lc3plus.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,42 @@ static int a2dp_lc3plus_configuration_select(
590590
return 0;
591591
}
592592

593+
static int a2dp_lc3plus_configuration_check(
594+
const struct a2dp_codec *codec,
595+
const void *configuration) {
596+
597+
const a2dp_lc3plus_t *conf = configuration;
598+
a2dp_lc3plus_t conf_v = *conf;
599+
600+
/* validate configuration against BlueALSA capabilities */
601+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
602+
&conf_v, sizeof(conf_v)) != 0)
603+
return A2DP_CHECK_ERR_SIZE;
604+
605+
switch (conf_v.frame_duration) {
606+
case LC3PLUS_FRAME_DURATION_025:
607+
case LC3PLUS_FRAME_DURATION_050:
608+
case LC3PLUS_FRAME_DURATION_100:
609+
break;
610+
default:
611+
debug("LC3plus: Invalid frame duration: %#x", conf->frame_duration);
612+
return A2DP_CHECK_ERR_FRAME_DURATION;
613+
}
614+
615+
if (a2dp_channel_mode_lookup(a2dp_lc3plus_channels, conf_v.channels) == NULL) {
616+
debug("LC3plus: Invalid channel mode: %#x", conf->channels);
617+
return A2DP_CHECK_ERR_CHANNEL_MODE;
618+
}
619+
620+
uint16_t conf_frequency = LC3PLUS_GET_FREQUENCY(conf_v);
621+
if (a2dp_sampling_lookup(a2dp_lc3plus_samplings, conf_frequency) == NULL) {
622+
debug("LC3plus: Invalid sampling frequency: %#x", LC3PLUS_GET_FREQUENCY(*conf));
623+
return A2DP_CHECK_ERR_SAMPLING;
624+
}
625+
626+
return A2DP_CHECK_OK;
627+
}
628+
593629
static int a2dp_lc3plus_transport_init(struct ba_transport *t) {
594630

595631
const struct a2dp_channel_mode *chm;
@@ -639,10 +675,9 @@ struct a2dp_codec a2dp_lc3plus_source = {
639675
LC3PLUS_SAMPLING_FREQ_96000)
640676
},
641677
.capabilities_size = sizeof(a2dp_lc3plus_t),
642-
.channels[0] = a2dp_lc3plus_channels,
643-
.samplings[0] = a2dp_lc3plus_samplings,
644678
.init = a2dp_lc3plus_source_init,
645679
.configuration_select = a2dp_lc3plus_configuration_select,
680+
.configuration_check = a2dp_lc3plus_configuration_check,
646681
.transport_init = a2dp_lc3plus_transport_init,
647682
.transport_start = a2dp_lc3plus_source_transport_start,
648683
};
@@ -669,9 +704,8 @@ struct a2dp_codec a2dp_lc3plus_sink = {
669704
LC3PLUS_SAMPLING_FREQ_96000)
670705
},
671706
.capabilities_size = sizeof(a2dp_lc3plus_t),
672-
.channels[0] = a2dp_lc3plus_channels,
673-
.samplings[0] = a2dp_lc3plus_samplings,
674707
.configuration_select = a2dp_lc3plus_configuration_select,
708+
.configuration_check = a2dp_lc3plus_configuration_check,
675709
.transport_init = a2dp_lc3plus_transport_init,
676710
.transport_start = a2dp_lc3plus_sink_transport_start,
677711
};

src/a2dp-ldac.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,31 @@ static int a2dp_ldac_configuration_select(
368368
return 0;
369369
}
370370

371+
static int a2dp_ldac_configuration_check(
372+
const struct a2dp_codec *codec,
373+
const void *configuration) {
374+
375+
const a2dp_ldac_t *conf = configuration;
376+
a2dp_ldac_t conf_v = *conf;
377+
378+
/* validate configuration against BlueALSA capabilities */
379+
if (a2dp_filter_capabilities(codec, &codec->capabilities,
380+
&conf_v, sizeof(conf_v)) != 0)
381+
return A2DP_CHECK_ERR_SIZE;
382+
383+
if (a2dp_sampling_lookup(a2dp_ldac_samplings, conf_v.frequency) == NULL) {
384+
debug("LDAC: Invalid sampling frequency: %#x", conf->frequency);
385+
return A2DP_CHECK_ERR_SAMPLING;
386+
}
387+
388+
if (a2dp_channel_mode_lookup(a2dp_ldac_channels, conf_v.channel_mode) == NULL) {
389+
debug("LDAC: Invalid channel mode: %#x", conf->channel_mode);
390+
return A2DP_CHECK_ERR_CHANNEL_MODE;
391+
}
392+
393+
return A2DP_CHECK_OK;
394+
}
395+
371396
static int a2dp_ldac_transport_init(struct ba_transport *t) {
372397

373398
const struct a2dp_channel_mode *chm;
@@ -420,10 +445,9 @@ struct a2dp_codec a2dp_ldac_source = {
420445
LDAC_SAMPLING_FREQ_96000,
421446
},
422447
.capabilities_size = sizeof(a2dp_ldac_t),
423-
.channels[0] = a2dp_ldac_channels,
424-
.samplings[0] = a2dp_ldac_samplings,
425448
.init = a2dp_ldac_source_init,
426449
.configuration_select = a2dp_ldac_configuration_select,
450+
.configuration_check = a2dp_ldac_configuration_check,
427451
.transport_init = a2dp_ldac_transport_init,
428452
.transport_start = a2dp_ldac_source_transport_start,
429453
};
@@ -453,9 +477,8 @@ struct a2dp_codec a2dp_ldac_sink = {
453477
LDAC_SAMPLING_FREQ_96000,
454478
},
455479
.capabilities_size = sizeof(a2dp_ldac_t),
456-
.channels[0] = a2dp_ldac_channels,
457-
.samplings[0] = a2dp_ldac_samplings,
458480
.configuration_select = a2dp_ldac_configuration_select,
481+
.configuration_check = a2dp_ldac_configuration_check,
459482
.transport_init = a2dp_ldac_transport_init,
460483
.transport_start = a2dp_ldac_sink_transport_start,
461484
};

0 commit comments

Comments
 (0)