Subject: Re: audio.c parameter sanity check too restrictive
To: None <tech-kern@netbsd.org>
From: Ignatios Souvatzis <is@netbsd.org>
List: tech-kern
Date: 09/01/2001 22:58:22
On Wed, Aug 29, 2001 at 10:15:32PM +0200, Ignatios Souvatzis wrote:
> Hi,
> 
> in the near future I'll add 24bit and 32bit slinear modes to the
> amiga/dev/repulse.c driver. (maybe also ulinear emulation).
> 
> I'll need to enhance the sanity check in audio.c::audio_check_params() 
> [thats about line 2234] for this - any objections?

Here is the actual diff. Somebody should look at it for a moment; I had to
enhance the silence fill function, too.

(Silence fill will now work for any multiple of 8 bits. Maybe I shouldn't
restrict to 8/16/24/32 bits, but I don't know yet how many drivers are
out there that don't check parameters against their capabilities correctly.)

Regards,
	Ignatios

RCS file: /cvsroot/syssrc/sys/dev/audio.c,v
retrieving revision 1.137
diff -u -r1.137 audio.c
--- audio.c     2001/06/03 23:52:51     1.137
+++ audio.c     2001/09/01 21:00:32
@@ -1379,19 +1379,14 @@
        case AUDIO_ENCODING_ADPCM: /* is this right XXX */
        case AUDIO_ENCODING_SLINEAR_LE:
        case AUDIO_ENCODING_SLINEAR_BE:
-               auzero0 = 0;/* fortunately this works for both 8 and 16 bits */
+               auzero0 = 0;/* fortunately this works for any number of bits */
                break;
        case AUDIO_ENCODING_ULINEAR_LE:
        case AUDIO_ENCODING_ULINEAR_BE:
-               if (params->precision == 16) {
-                       nfill = 2;
-                       if (params->encoding == AUDIO_ENCODING_ULINEAR_LE) {
-                               auzero0 = 0;
-                               auzero1 = 0x80;
-                       } else {
-                               auzero0 = 0x80;
-                               auzero1 = 0;
-                       }
+               if (params->precision > 8) {
+                       nfill = (params->precision + NBBY - 1)/ NBBY;
+                       auzero0 = 0x80;
+                       auzero1 = 0;
                } else
                        auzero0 = 0x80;
                break;
@@ -1403,12 +1398,23 @@
        if (nfill == 1) {
                while (--n >= 0)
                        *p++ = auzero0; /* XXX memset */
-       } else /* nfill must be 2 */ {
-               while (n > 1) {
+       } else /* nfill must no longer be 2 */ {
+               if (params->encoding == AUDIO_ENCODING_ULINEAR_LE) {
+                       int k = nfill;
+                       while (--k > 0)
+                               *p++ = auzero1;
+                       n -= nfill - 1;
+               }
+               while (n >= nfill) {
+                       int k;
                        *p++ = auzero0;
-                       *p++ = auzero1;
-                       n -= 2;
+                       while (--k > 0)
+                               *p++ = auzero1;
+
+                       n -= nfill;
                }
+               if (n-- > 0)    /* XXX must be 1 - DIAGNOSTIC check? */
+                       *p++ = auzero0;
        }
 }
 
@@ -2231,7 +2237,9 @@
        case AUDIO_ENCODING_SLINEAR_BE:
        case AUDIO_ENCODING_ULINEAR_LE:
        case AUDIO_ENCODING_ULINEAR_BE:
-               if (p->precision != 8 && p->precision != 16)
+               /* XXX is: our zero-fill can handle any multiple of 8 */
+               if (p->precision !=  8 && p->precision != 16 &&
+                   p->precision != 24 && p->precision != 32)
                        return (EINVAL);
                break;
        case AUDIO_ENCODING_MPEG_L1_STREAM: