Home | History | Annotate | Download | only in usbaudio
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "usb_profile"
     18 /*#define LOG_NDEBUG 0*/
     19 
     20 #include "format.h"
     21 
     22 #include <tinyalsa/asoundlib.h>
     23 
     24 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
     25 
     26 /*
     27  * Maps from bit position in pcm_mask to AUDIO_ format constants.
     28  */
     29 static audio_format_t const format_value_map[] = {
     30     AUDIO_FORMAT_PCM_8_BIT,           /* 00 - SNDRV_PCM_FORMAT_S8 */
     31     AUDIO_FORMAT_PCM_8_BIT,           /* 01 - SNDRV_PCM_FORMAT_U8 */
     32     AUDIO_FORMAT_PCM_16_BIT,          /* 02 - SNDRV_PCM_FORMAT_S16_LE */
     33     AUDIO_FORMAT_INVALID,             /* 03 - SNDRV_PCM_FORMAT_S16_BE */
     34     AUDIO_FORMAT_INVALID,             /* 04 - SNDRV_PCM_FORMAT_U16_LE */
     35     AUDIO_FORMAT_INVALID,             /* 05 - SNDRV_PCM_FORMAT_U16_BE */
     36     AUDIO_FORMAT_INVALID,             /* 06 - SNDRV_PCM_FORMAT_S24_LE */
     37     AUDIO_FORMAT_INVALID,             /* 07 - SNDRV_PCM_FORMAT_S24_BE */
     38     AUDIO_FORMAT_INVALID,             /* 08 - SNDRV_PCM_FORMAT_U24_LE */
     39     AUDIO_FORMAT_INVALID,             /* 09 - SNDRV_PCM_FORMAT_U24_BE */
     40     AUDIO_FORMAT_PCM_32_BIT,          /* 10 - SNDRV_PCM_FORMAT_S32_LE */
     41     AUDIO_FORMAT_INVALID,             /* 11 - SNDRV_PCM_FORMAT_S32_BE */
     42     AUDIO_FORMAT_INVALID,             /* 12 - SNDRV_PCM_FORMAT_U32_LE */
     43     AUDIO_FORMAT_INVALID,             /* 13 - SNDRV_PCM_FORMAT_U32_BE */
     44     AUDIO_FORMAT_PCM_FLOAT,           /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
     45     AUDIO_FORMAT_INVALID,             /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
     46     AUDIO_FORMAT_INVALID,             /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
     47     AUDIO_FORMAT_INVALID,             /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
     48     AUDIO_FORMAT_INVALID,             /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
     49     AUDIO_FORMAT_INVALID,             /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
     50     AUDIO_FORMAT_INVALID,             /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
     51     AUDIO_FORMAT_INVALID,             /* 21 - SNDRV_PCM_FORMAT_A_LAW */
     52     AUDIO_FORMAT_INVALID,             /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
     53     AUDIO_FORMAT_INVALID,             /* 23 - SNDRV_PCM_FORMAT_MPEG */
     54     AUDIO_FORMAT_INVALID,             /* 24 - SNDRV_PCM_FORMAT_GSM */
     55     AUDIO_FORMAT_INVALID,             /* 25 -> 30 (not assigned) */
     56     AUDIO_FORMAT_INVALID,
     57     AUDIO_FORMAT_INVALID,
     58     AUDIO_FORMAT_INVALID,
     59     AUDIO_FORMAT_INVALID,
     60     AUDIO_FORMAT_INVALID,
     61     AUDIO_FORMAT_INVALID,             /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
     62     AUDIO_FORMAT_PCM_24_BIT_PACKED,   /* 32 - SNDRV_PCM_FORMAT_S24_3LE */
     63     AUDIO_FORMAT_INVALID,             /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
     64     AUDIO_FORMAT_INVALID,             /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
     65     AUDIO_FORMAT_INVALID,             /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
     66     AUDIO_FORMAT_INVALID,             /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
     67     AUDIO_FORMAT_INVALID,             /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
     68     AUDIO_FORMAT_INVALID,             /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
     69     AUDIO_FORMAT_INVALID,             /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
     70     AUDIO_FORMAT_INVALID,             /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
     71     AUDIO_FORMAT_INVALID,             /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
     72     AUDIO_FORMAT_INVALID,             /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
     73     AUDIO_FORMAT_INVALID,             /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
     74     AUDIO_FORMAT_INVALID,             /* 44 - SNDRV_PCM_FORMAT_G723_24 */
     75     AUDIO_FORMAT_INVALID,             /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
     76     AUDIO_FORMAT_INVALID,             /* 46 - SNDRV_PCM_FORMAT_G723_40 */
     77     AUDIO_FORMAT_INVALID,             /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
     78     AUDIO_FORMAT_INVALID,             /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
     79     AUDIO_FORMAT_INVALID              /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
     80 };
     81 
     82 audio_format_t get_format_for_mask(struct pcm_mask* mask)
     83 {
     84     int num_slots = sizeof(mask->bits) / sizeof(mask->bits[0]);
     85     int bits_per_slot = sizeof(mask->bits[0]) * 8;
     86 
     87     int table_size = sizeof(format_value_map) / sizeof(format_value_map[0]);
     88 
     89     int slot_index, bit_index, table_index;
     90     table_index = 0;
     91     int num_written = 0;
     92     for (slot_index = 0; slot_index < num_slots; slot_index++) {
     93         unsigned bit_mask = 1;
     94         for (bit_index = 0; bit_index < bits_per_slot; bit_index++) {
     95             /* don't return b-bit formats even if they are supported */
     96             if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
     97                 /* just return the first one */
     98                 return table_index < table_size
     99                            ? format_value_map[table_index]
    100                            : AUDIO_FORMAT_INVALID;
    101             }
    102             bit_mask <<= 1;
    103             table_index++;
    104         }
    105     }
    106 
    107     return AUDIO_FORMAT_INVALID;
    108 }
    109 
    110 /*
    111  * Maps from bit position in pcm_mask to PCM_ format constants.
    112  */
    113 int8_t const pcm_format_value_map[50] = {
    114     PCM_FORMAT_S8,          /* 00 - SNDRV_PCM_FORMAT_S8 */
    115     PCM_FORMAT_INVALID,     /* 01 - SNDRV_PCM_FORMAT_U8 */
    116     PCM_FORMAT_S16_LE,      /* 02 - SNDRV_PCM_FORMAT_S16_LE */
    117     PCM_FORMAT_INVALID,     /* 03 - SNDRV_PCM_FORMAT_S16_BE */
    118     PCM_FORMAT_INVALID,     /* 04 - SNDRV_PCM_FORMAT_U16_LE */
    119     PCM_FORMAT_INVALID,     /* 05 - SNDRV_PCM_FORMAT_U16_BE */
    120     PCM_FORMAT_S24_3LE,     /* 06 - SNDRV_PCM_FORMAT_S24_LE */
    121     PCM_FORMAT_INVALID,     /* 07 - SNDRV_PCM_FORMAT_S24_BE */
    122     PCM_FORMAT_INVALID,     /* 08 - SNDRV_PCM_FORMAT_U24_LE */
    123     PCM_FORMAT_INVALID,     /* 09 - SNDRV_PCM_FORMAT_U24_BE */
    124     PCM_FORMAT_S32_LE,      /* 10 - SNDRV_PCM_FORMAT_S32_LE */
    125     PCM_FORMAT_INVALID,     /* 11 - SNDRV_PCM_FORMAT_S32_BE */
    126     PCM_FORMAT_INVALID,     /* 12 - SNDRV_PCM_FORMAT_U32_LE */
    127     PCM_FORMAT_INVALID,     /* 13 - SNDRV_PCM_FORMAT_U32_BE */
    128     PCM_FORMAT_INVALID,     /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
    129     PCM_FORMAT_INVALID,     /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
    130     PCM_FORMAT_INVALID,     /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
    131     PCM_FORMAT_INVALID,     /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
    132     PCM_FORMAT_INVALID,     /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
    133     PCM_FORMAT_INVALID,     /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
    134     PCM_FORMAT_INVALID,     /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
    135     PCM_FORMAT_INVALID,     /* 21 - SNDRV_PCM_FORMAT_A_LAW */
    136     PCM_FORMAT_INVALID,     /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
    137     PCM_FORMAT_INVALID,     /* 23 - SNDRV_PCM_FORMAT_MPEG */
    138     PCM_FORMAT_INVALID,     /* 24 - SNDRV_PCM_FORMAT_GSM */
    139     PCM_FORMAT_INVALID,     /* 25 -> 30 (not assigned) */
    140     PCM_FORMAT_INVALID,
    141     PCM_FORMAT_INVALID,
    142     PCM_FORMAT_INVALID,
    143     PCM_FORMAT_INVALID,
    144     PCM_FORMAT_INVALID,
    145     PCM_FORMAT_INVALID,     /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
    146     PCM_FORMAT_S24_3LE,     /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
    147     PCM_FORMAT_INVALID,     /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
    148     PCM_FORMAT_INVALID,     /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
    149     PCM_FORMAT_INVALID,     /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
    150     PCM_FORMAT_INVALID,     /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
    151     PCM_FORMAT_INVALID,     /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
    152     PCM_FORMAT_INVALID,     /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
    153     PCM_FORMAT_INVALID,     /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
    154     PCM_FORMAT_INVALID,     /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
    155     PCM_FORMAT_INVALID,     /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
    156     PCM_FORMAT_INVALID,     /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
    157     PCM_FORMAT_INVALID,     /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
    158     PCM_FORMAT_INVALID,     /* 44 - SNDRV_PCM_FORMAT_G723_24 */
    159     PCM_FORMAT_INVALID,     /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
    160     PCM_FORMAT_INVALID,     /* 46 - SNDRV_PCM_FORMAT_G723_40 */
    161     PCM_FORMAT_INVALID,     /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
    162     PCM_FORMAT_INVALID,     /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
    163     PCM_FORMAT_INVALID      /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
    164 };
    165 
    166 /*
    167  * Scans the provided format mask and returns the first non-8 bit sample
    168  * format supported by the devices.
    169  */
    170 enum pcm_format get_pcm_format_for_mask(struct pcm_mask* mask)
    171 {
    172     int num_slots = ARRAY_SIZE(mask->bits);
    173     int bits_per_slot = sizeof(mask->bits[0]) * 8;
    174 
    175     int table_size = ARRAY_SIZE(pcm_format_value_map);
    176 
    177     int slot_index, bit_index, table_index;
    178     table_index = 0;
    179     int num_written = 0;
    180     for (slot_index = 0; slot_index < num_slots && table_index < table_size; slot_index++) {
    181         unsigned bit_mask = 1;
    182         for (bit_index = 0; bit_index < bits_per_slot && table_index < table_size; bit_index++) {
    183             /* skip any 8-bit formats */
    184             if (table_index >= 2 && (mask->bits[slot_index] & bit_mask) != 0) {
    185                 /* just return the first one which will be at least 16-bit */
    186                 return (int)pcm_format_value_map[table_index];
    187             }
    188             bit_mask <<= 1;
    189             table_index++;
    190         }
    191     }
    192 
    193     return PCM_FORMAT_INVALID;
    194 }
    195