[alsa-devel] [PATCH] alsa-lib/tlv: fix handling of raw value ranges
Clemens Ladisch
clemens at ladisch.de
Fri Mar 30 15:51:15 CEST 2012
Benoît Thébaudeau wrote:
> Clemens Ladisch wrote:
>> Benoît Thébaudeau wrote:
>>> Clemens Ladisch wrote:
>> All raw values described by the .info callback, returned by the .get
>> callback, and especially accepted by the .put callback, are valid.
>>
>> The TLV information just _describes_ values, it cannot _restrict_
>> them.
>>
>> If a register has invalid values, the driver must somehow map between
>> raw control values and valid register values.
>
> Now I understand how you see things. But is it an official and absolute ALSA
> rule,
Yes.
> known by everybody,
No.
> that may cause issues if not applied?
Yes.
> The hardware values are:
> 0x00 to 0x70: prohibited
> 0x71 to 0xcf: +15 dB to -79 dB by -1 dB steps
> 0xd0 to 0xfe: prohibited
> 0xff: mute
>
> To respect your rule, the driver would have to implement its own .info/.get/.put
> callbacks, giving the following mapping:
> SW 0x00: HW 0xff: mute
> SW 0x01 to 0x5f: HW 0x71 to 0xcf: +15 dB to -79 dB by -1 dB steps
>
> But why compel the driver to complicate things this way if it can work with
> standard macros and holes in the TLV ranges?
Because it _cannot_ work with standard macros and holes.
> It is also probably the case for many other existing hardware.
>
> Do you think that the solution would be rather to add common kernel ALSA stuff
> to handle such mappings?
Yes.
I'll see if I can cobble together some TLV checking code ...
>>>> As for the patch, while I'm not sure whether it is needed at all,
>>>> I also
>>>> don't quite understand the reason for all the changes.
>>>>
>>>>> --- alsa-lib/src/control/tlv.c
>>>>> +++ alsa-lib/src/control/tlv.c
>>>>> @@ -291,41 +291,37 @@ int snd_tlv_convert_from_dB(unsigned int
>>>>> {
>>>>> switch (tlv[0]) {
>>>>> case SND_CTL_TLVT_DB_RANGE: {
>>>>> + long dbmin, dbmax, prev_submax;
>>>>> unsigned int pos, len;
>>>>> len = int_index(tlv[1]);
>>>>> + if (len < 6 || len > MAX_TLV_RANGE_SIZE)
>>>>> return -EINVAL;
>>>>> pos = 2;
>>>>> + prev_submax = 0;
>>>>> + do {
>>>>
>>>> Why is this not a while loop?
>>>
>>> Because the added "if (len < 6" makes it pointless.
>>
>> Then why did you add the len<6 check? This is, in effect, just the same
>> as the old while condition.
>
> Because it's useless to wait until the end of the loop to return -EINVAL,
It is not necessary to optimize for error cases.
> and with my patch, the after-loop code becomes the fallback case for beyond-
> final-range values, so it avoids adding a weird extra check there.
But why does this force you to use do instead of while?
Regards,
Clemens
More information about the Alsa-devel
mailing list