git: 9front

Download patch

ref: 03c73d4a7ca63c04b987946eb1f95ac6fdd89530
parent: 7aff8a4587bb1fd6ed694750ce9c9c22d8932ba1
parent: 60e8289f09046cf7f29cff06a2e43ed1f7e6a803
author: cinap_lenrek <cinap_lenrek@localhost>
date: Mon Jun 27 23:51:47 EDT 2011

merge

--- a/sys/src/9/pc/audiohda.c
+++ b/sys/src/9/pc/audiohda.c
@@ -202,8 +202,14 @@
 		Asetleft = 1<<13,
 		Asetright = 1<<12,
 		Asetmute = 1<<7,
-		Aidx = 8,
+		Asetidx = 8,
+		Agetin = 0<<15,
+		Agetout = 1<<15,
+		Agetleft = 1<<13,
+		Agetright = 1<<15,
+		Agetidx = 0,
 		Again = 0,
+		Againmask = 0x7f,
 	Getconvfmt = 0xa,
 	Setconvfmt = 0x2,
 };
@@ -277,9 +283,9 @@
 	uchar *mem;
 	ulong size;
 	
+	Queue *q;
 	ulong *corb;
 	ulong corbsize;
-	
 	ulong *rirb;
 	ulong rirbsize;
 	
@@ -370,6 +376,8 @@
 	"other",
 };
 
+Ctlr *lastcard;
+
 static int
 waitup8(Ctlr *ctlr, int reg, uchar mask, uchar set)
 {
@@ -471,78 +479,74 @@
 	return id;
 }
 
-/* vol is 0...127 or ~0 for 0dB; mute is 0/1 */
-static void
-setoutamp(Widget *w, int mute, uint vol)
+static uint
+getoutamprange(Widget *w)
 {
-	uint q, r;
-	uint zerodb, range;
+	uint r;
+	r = cmd(w->id, Getparm, Outampcap);
+	return (r >> 8) & 0x7f;
+}
 
+static void
+getoutamp(Widget *w, int vol[2])
+{
+	vol[0] = vol[1] = 0;
 	if((w->cap & Woutampcap) == 0)
 		return;
-
-	r = cmd(w->id, Getparm, Outampcap);
-	range = (r >> 8) & 0x7f;
-	zerodb = r & 127;
-
-	q = Asetout | Asetleft | Asetright;
-	if(mute)
-		q |= Asetmute;
-	else if(vol == ~0)
-		q |= zerodb << Again;
-	else if(range > 0)
-		q |= (range * vol / 128) << Again;
-
-	cmd(w->id, Setamp, q);
+	vol[0] = cmd(w->id, Getamp, Agetout | Agetleft) & Againmask;
+	vol[1] = cmd(w->id, Getamp, Agetout | Agetright) & Againmask;
 }
 
+/* vol is 0...range or nil for 0dB; mute is 0/1 */
 static void
-getoutamp(Widget *w, int v[2])
+setoutamp(Widget *w, int mute, int *vol)
 {
-	uint q, r, range;
-	
-	v[0] = 0;
-	v[1] = 0;
-	
+	uint q, r, i;
+	uint zerodb;
+
 	if((w->cap & Woutampcap) == 0)
 		return;
-		
+
 	r = cmd(w->id, Getparm, Outampcap);
-	range = (r >> 8) & 0x7f;
+	zerodb = r & 0x7f;
 	
-	q = (1 << 15) | (1 << 13);
-	r = cmd(w->id, Getamp, q);
-	v[0] = (r & 0x7f) * 128 / range;
-	
-	q = (1 << 15) | (0 << 13);
-	r = cmd(w->id, Getamp, q);
-	v[1] = (r & 0x7f) * 128 / range;
+	for(i=0; i<2; i++){
+		q = Asetout | (i == 0 ? Asetleft : Asetright);
+		if(mute)
+			q |= Asetmute;
+		else if(vol == nil)
+			q |= zerodb << Again;
+		else
+			q |= vol[i] << Again;
+		cmd(w->id, Setamp, q);
+	}
 }
-	
-/* vol is 0...127 or ~0 for 0dB; mute is 0/1; in is widget or nil for all */
+
+/* vol is 0...range or nil for 0dB; mute is 0/1; in is widget or nil for all */
 static void
-setinamp(Widget *w, Widget *in, int mute, uint vol)
+setinamp(Widget *w, Widget *in, int mute, int *vol)
 {
-	uint q, r, i;
-	uint zerodb, range;
+	uint q, r, i, j;
+	uint zerodb;
 
 	if((w->cap & Winampcap) == 0)
 		return;
 
 	r = cmd(w->id, Getparm, Inampcap);
-	range = (r >> 8) & 0x7f;
-	zerodb = r & 127;
-
-	q = Asetin | Asetleft | Asetright;
-	if(mute)
-		q |= Asetmute;
-	else if(vol == ~0)
-		q |= zerodb << Again;
-	else if(range > 0)
-		q |= (range * vol / 128) << Again;
-	for(i=0; i<w->nlist; i++){
-		if(in == nil || w->list[i] == in)
-			cmd(w->id, Setamp, q | (i << Aidx));
+	zerodb = r & 0x7f;
+	
+	for(i=0; i<2; i++){
+		q = Asetin | (i == 0 ? Asetleft : Asetright);
+		if(mute)
+			q |= Asetmute;
+		else if(vol == nil)
+			q |= zerodb << Again;
+		else
+			q |= vol[i] << Again;
+		for(j=0; j<w->nlist; j++){
+			if(in == nil || w->list[j] == in)
+				cmd(w->id, Setamp, q | (j << Asetidx));
+		}
 	}
 }
 
@@ -583,14 +587,14 @@
 	uint i;
 
 	for(w=src->fg->first; w != nil; w=w->next){
-		setoutamp(w, 1, 0);
-		setinamp(w, nil, 1, 0);
+		setoutamp(w, 1, nil);
+		setinamp(w, nil, 1, nil);
 		cmd(w->id, Setstream, 0);
 	}
 	for(w=dst; w != src; w=v){
 		v = w->from;
-		setoutamp(w, 0, ~0);
-		setinamp(v, w, 0, ~0);
+		setoutamp(w, 0, nil);
+		setinamp(v, w, 0, nil);
 		if(v->type == Waout || v->type == Wamix)
 			continue;
 		if(v->nlist == 1)
@@ -599,7 +603,7 @@
 			;
 		cmd(v->id, Setconn, i);
 	}
-	setoutamp(src, 0, ~0);
+	setoutamp(src, 0, nil);
 	cmd(src->id, Setpinctl, Pinctlout);
 	cmd(dst->id, Setstream, (stream << 4) | 0);
 	cmd(dst->id, Setconvfmt, (1 << 14) | (1 << 4) | 1);
@@ -1042,9 +1046,7 @@
 		if(ntok <= 0)
 			continue;
 		if(cistrcmp(tok[0], "pin") == 0 && ntok == 2){
-			qlock(ctlr);
 			connectpin(ctlr, strtoul(tok[1], 0, 0));
-			qunlock(ctlr);
 		}else
 			error(Ebadctl);
 	}
@@ -1099,12 +1101,8 @@
 hdagetvol(Audio *adev, int, int a[2])
 {
 	Ctlr *ctlr = adev->ctlr;
-	
-	if(ctlr->amp == nil)
-		return -1;
-	qlock(ctlr);
-	getoutamp(ctlr->amp, a);
-	qunlock(ctlr);
+	if(ctlr->amp != nil)
+		getoutamp(ctlr->amp, a);
 	return 0;
 }
 
@@ -1112,18 +1110,24 @@
 hdasetvol(Audio *adev, int, int a[2])
 {
 	Ctlr *ctlr = adev->ctlr;
-	
-	if(ctlr->amp == nil)
-		return -1;
-	qlock(ctlr);
-	setoutamp(ctlr->amp, 0, a[0]);
-	qunlock(ctlr);
+	if(ctlr->amp != nil)
+		setoutamp(ctlr->amp, 0, a);
 	return 0;
 }
 
+static void
+fillvoltab(Ctlr *ctlr, Volume *vt)
+{
+	memmove(vt, voltab, sizeof(voltab));
+	if(ctlr->amp != nil)
+		vt[0].range = getoutamprange(ctlr->amp);
+}
+
 static long
 hdavolread(Audio *adev, void *a, long n, vlong)
 {
+	Volume voltab[2];
+	fillvoltab(adev->ctlr, voltab);
 	return genaudiovolread(adev, a, n, 0, voltab, hdagetvol, 0);
 }
 
@@ -1130,6 +1134,8 @@
 static long
 hdavolwrite(Audio *adev, void *a, long n, vlong)
 {
+	Volume voltab[2];
+	fillvoltab(adev->ctlr, voltab);
 	return genaudiovolwrite(adev, a, n, 0, voltab, hdasetvol, 0);
 }
 
@@ -1264,6 +1270,45 @@
 	return nil;
 }
 
+static long
+hdacmdread(Chan *, void *a, long n, vlong)
+{
+	Ctlr *ctlr;
+	
+	ctlr = lastcard;
+	if(ctlr == nil)
+		error(Enodev);
+	if(n & 7)
+		error(Ebadarg);
+	return qread(ctlr->q, a, n);
+}
+
+static long
+hdacmdwrite(Chan *, void *a, long n, vlong)
+{
+	Ctlr *ctlr;
+	ulong *lp;
+	int i;
+	uint w[2];
+	
+	ctlr = lastcard;
+	if(ctlr == nil)
+		error(Enodev);
+	if(n & 3)
+		error(Ebadarg);
+	lp = a;
+	qlock(ctlr);
+	for(i=0; i<n/4; i++){
+		if(hdacmd(ctlr, lp[i], w) < 0){
+			w[0] = 0;
+			w[1] = ~0;
+		}
+		qproduce(ctlr->q, w, sizeof(w));
+	}
+	qunlock(ctlr);
+	return n;
+}
+
 static int
 hdareset(Audio *adev)
 {
@@ -1304,6 +1349,7 @@
 	
 	ctlr->no = adev->ctlrno;
 	ctlr->size = p->mem[0].size;
+	ctlr->q = qopen(256, 0, 0, 0);
 	ctlr->mem = vmap(p->mem[0].bar & ~0x0F, ctlr->size);
 	if(ctlr->mem == nil){
 		print("#A%d: can't map %.8lux\n", ctlr->no, p->mem[0].bar);
@@ -1345,6 +1391,8 @@
 	adev->ctl = hdactl;
 	
 	intrenable(irq, hdainterrupt, adev, tbdf, "hda");
+	lastcard = ctlr;
+	addarchfile("hdacmd", 0664, hdacmdread, hdacmdwrite);
 	
 	return 0;
 }
@@ -1354,3 +1402,4 @@
 {
 	addaudiocard("hda", hdareset);
 }
+
--- a/sys/src/cmd/usb/kb/hid.h
+++ b/sys/src/cmd/usb/kb/hid.h
@@ -10,6 +10,8 @@
 	KbdCSP		= 0x010103,	/* keyboard.boot.hid */
 
 	/* Requests */
+	Getreport = 0x01,
+	Setreport = 0x09,
 	Getproto	= 0x03,
 	Setproto	= 0x0b,
 
@@ -16,6 +18,9 @@
 	/* protocols for SET_PROTO request */
 	Bootproto	= 0,
 	Reportproto	= 1,
+
+	/* protocols for SET_REPORT request */
+	Reportout = 0x0200,
 };
 
 enum {
--- a/sys/src/cmd/usb/kb/kb.c
+++ b/sys/src/cmd/usb/kb/kb.c
@@ -124,6 +124,12 @@
 	return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0);
 }
 
+static int
+setleds(KDev* f, int eid, uchar leds)
+{
+	return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1);
+}
+
 /*
  * Try to recover from a babble error. A port reset is the only way out.
  * BUG: we should be careful not to reset a bundle with several devices.
@@ -537,7 +543,10 @@
 		kd->ep = nil;
 		return;
 	}
-
+	if(setleds(kd, ep->id, 0) < 0){
+		fprint(2, "kb: %s: setleds: %r\n", d->dir);
+		return;
+	}
 	incref(d);
 	proccreate(f, kd, Stack);
 }
--