706 lines · 17.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <thread.h>#include "usb.h"#include "audio.h"#include "audioctl.h" int endpt[2] =		{-1, -1};int interface[2] =	{-1, -1};int featureid[2] =	{-1, -1};int selectorid[2] =	{-1, -1};int mixerid[2] =	{-1, -1};int curalt[2] =		{-1, -1};int buttonendpt =	-1; int id;Dev *ad; Audiocontrol controls[2][Ncontrol] = {	{	[Speed_control] = {		"speed",	0, {0}, 0,	44100,	Undef},	[Mute_control] = {		"mute",		0, {0}, 0,	0,	Undef},	[Volume_control] = {		"volume",	0, {0}, 0,	0,	Undef},	[Bass_control] = {		"bass",		0, {0}, 0,	0,	Undef},	[Mid_control] = {		"mid",		0, {0}, 0,	0,	Undef},	[Treble_control] = {		"treble",	0, {0}, 0,	0,	Undef},	[Equalizer_control] = {		"equalizer",	0, {0}, 0,	0,	Undef},	[Agc_control] = {		"agc",		0, {0}, 0,	0,	Undef},	[Delay_control] = {		"delay",	0, {0}, 0,	0,	Undef},	[Bassboost_control] = {		"bassboost",	0, {0}, 0,	0,	Undef},	[Loudness_control] = {		"loudness",	0, {0}, 0,	0,	Undef},	[Channel_control] = {		"channels",	0, {0}, 0,	2,	Undef},	[Resolution_control] = {	"resolution",	0, {0}, 0,	16,	Undef},//	[Selector_control] = {		"selector",	0, {0}, 0,	0,	Undef},	}, {	[Speed_control] = {		"speed",	0, {0}, 0,	44100,	Undef},	[Mute_control] = {		"mute",		0, {0}, 0,	0,	Undef},	[Volume_control] = {		"volume",	0, {0}, 0,	0,	Undef},	[Bass_control] = {		"bass",		0, {0}, 0,	0,	Undef},	[Mid_control] = {		"mid",		0, {0}, 0,	0,	Undef},	[Treble_control] = {		"treble",	0, {0}, 0,	0,	Undef},	[Equalizer_control] = {		"equalizer",	0, {0}, 0,	0,	Undef},	[Agc_control] = {		"agc",		0, {0}, 0,	0,	Undef},	[Delay_control] = {		"delay",	0, {0}, 0,	0,	Undef},	[Bassboost_control] = {		"bassboost",	0, {0}, 0,	0,	Undef},	[Loudness_control] = {		"loudness",	0, {0}, 0,	0,	Undef},	[Channel_control] = {		"channels",	0, {0}, 0,	2,	Undef},	[Resolution_control] = {	"resolution",	0, {0}, 0,	16,	Undef},//	[Selector_control] = {		"selector",	0, {0}, 0,	0,	Undef},	}}; intsetaudioalt(int rec, Audiocontrol *c, int control){	dprint(2, "setcontrol %s: Set alt %d\n", c->name, control);	curalt[rec] = control;	if(usbcmd(ad, Rh2d|Rstd|Riface, Rsetiface, control, interface[rec], nil, 0) < 0){		dprint(2, "setcontrol: setupcmd %s failed\n", c->name);		return -1;	}	return control;} intfindalt(int rec, int nchan, int res, int speed){	Ep *ep;	Audioalt *a;	Altc *da;	int i, j, k, retval; 	retval = -1;	controls[rec][Channel_control].min = 1000000;	controls[rec][Channel_control].max = 0;	controls[rec][Channel_control].step = Undef;	controls[rec][Resolution_control].min = 1000000;	controls[rec][Resolution_control].max = 0;	controls[rec][Resolution_control].step = Undef;	for(i = 0; i < nelem(ad->usb->ep); i++){		if((ep = ad->usb->ep[i]) == nil)			continue;		if(ep->iface == nil){			fprint(2, "\tno interface\n");			return 0;		}		if(ep->iface->csp != CSP(Claudio, 2, 0))			continue;		if((rec == Play && (ep->addr &  0x80))		|| (rec == Record && (ep->addr &  0x80) == 0))			continue;		for(j = 0; j < 16; j++){			if((da = ep->iface->altc[j]) == nil || (a = da->aux) == nil)				continue;			if(a->nchan < controls[rec][Channel_control].min)				controls[rec][Channel_control].min = a->nchan;			if(a->nchan > controls[rec][Channel_control].max)				controls[rec][Channel_control].max = a->nchan;			if(a->res < controls[rec][Resolution_control].min)				controls[rec][Resolution_control].min = a->res;			if(a->res > controls[rec][Resolution_control].max)				controls[rec][Resolution_control].max = a->res;			controls[rec][Channel_control].settable = 1;			controls[rec][Channel_control].readable = 1;			controls[rec][Resolution_control].settable = 1;			controls[rec][Resolution_control].readable = 1;			controls[rec][Speed_control].settable = 1;			controls[rec][Speed_control].readable = 1;			if(a->nchan == nchan && a->res == res){				if(speed == Undef)					retval = j;				else if(a->caps & (has_discfreq|onefreq)){					for(k = 0; k < nelem(a->freqs); k++){						if(a->freqs[k] == speed){							retval = j;							break;						}					}				}else{					if(speed >= a->minfreq && speed <= a->maxfreq)						retval = j;				}			}		}	}	if(usbdebug && retval < 0)		fprint(2, "findalt(%d, %d, %d, %d) failed\n", rec, nchan, res, speed);	return retval;} intsetspeed(int rec, int speed){	int ps, n, no, dist, i;	Audioalt *a;	Altc *da;	Ep *ep;	uchar buf[3]; 	if(rec == Record && !setrec)		return Undef;	if(curalt[rec] < 0){		fprint(2, "Must set channels and resolution before speed\n");		return Undef;	}	if(endpt[rec] < 0)		sysfatal("endpt[%s] not set", rec?"Record":"Playback");	ep = ad->usb->ep[endpt[rec]];	if(ep->iface == nil)		sysfatal("no interface");	if(curalt[rec] < 0)		sysfatal("curalt[%s] not set", rec?"Record":"Playback");	da = ep->iface->altc[curalt[rec]];	a = da->aux;	if(a->caps & onefreq){		dprint(2, "setspeed %d: onefreq\n", speed);		/* speed not settable, but packet size must still be set */		speed = a->freqs[0];	}else if(a->caps & has_contfreq){		dprint(2, "setspeed %d: contfreq\n", speed);		if(speed < a->minfreq)			speed = a->minfreq;		else if(speed > a->maxfreq)			speed = a->maxfreq;		dprint(2, "Setting continuously variable %s speed to %d\n",				rec?"record":"playback", speed);	}else if(a->caps & has_discfreq){		dprint(2, "setspeed %d: discfreq\n", speed);		dist = 1000000;		no = -1;		for(i = 0; a->freqs[i] > 0; i++)			if(abs(a->freqs[i] - speed) < dist){				dist = abs(a->freqs[i] - speed);				no = i;			}		if(no == -1){			dprint(2, "no = -1\n");			return Undef;		}		speed = a->freqs[no];		dprint(2, "Setting discreetly variable %s speed to %d\n",				rec?"record":"playback", speed);	}else{		dprint(2, "can't happen\n?");		return Undef;	}	if(a->caps & has_setspeed){		dprint(2, "Setting %s speed to %d Hz;", rec?"record":"playback", speed);		buf[0] = speed;		buf[1] = speed >> 8;		buf[2] = speed >> 16;		n = endpt[rec];		if(rec)			n |= 0x80;		if(usbcmd(ad, Rh2d|Rclass|Rep, Rsetcur, sampling_freq_control<<8, n, buf, 3) < 0){			fprint(2, "Error in setupcmd\n");			return Undef;		}		if((n=usbcmd(ad, Rd2h|Rclass|Rep, Rgetcur, sampling_freq_control<<8, n, buf, 3)) < 0){			fprint(2, "Error in setupreq\n");			return Undef;		}		if(n != 3)			fprint(2, "Error in setupreply: %d\n", n);		else{			n = buf[0] | buf[1] << 8 | buf[2] << 16;			if(buf[2] || n == 0){				dprint(2, "Speed out of bounds %d (0x%x)\n", n, n);			}else if(n != speed && ad->usb->vid == 0x077d &&			    (ad->usb->did == 0x0223 || ad->usb->did == 0x07af)){				/* Griffin iMic responds incorrectly to sample rate inquiry */				dprint(2, " reported as %d (iMic bug?);", n);			}else				speed = n;		}		dprint(2, " speed now %d Hz;", speed);	}	ps = ((speed * da->interval + 999) / 1000)		* controls[rec][Channel_control].value[0]		* controls[rec][Resolution_control].value[0]/8;	if(ps > ep->maxpkt){		fprint(2, "%s: setspeed(rec %d, speed %d): packet size %d > "			"maximum packet size %d\n",			argv0, rec, speed, ps, ep->maxpkt);		return Undef;	}	dprint(2, "Configuring %s endpoint for %d Hz\n",				rec?"record":"playback", speed);	epdev[rec] = openep(ad, endpt[rec]);	if(epdev[rec] == nil)		sysfatal("openep rec %d: %r", rec); 	devctl(epdev[rec], "pollival %d", da->interval);	devctl(epdev[rec], "samplesz %ld", controls[rec][Channel_control].value[0] *				controls[rec][Resolution_control].value[0]/8);	devctl(epdev[rec], "hz %d", speed); 	/* NO: the client uses the endpoint file directly	if(opendevdata(epdev[rec], rec ? OREAD : OWRITE) < 0)		sysfatal("openep rec %d: %r", rec);	*/	return speed;} longgetspeed(int rec, int which){	int i, n;	Audioalt *a;	Altc *da;	Ep *ep;	uchar buf[3];	int r; 	if(curalt[rec] < 0){		fprint(2, "Must set channels and resolution before getspeed\n");		return Undef;	}	if(endpt[rec] < 0)		sysfatal("endpt[%s] not set", rec?"Record":"Playback");	dprint(2, "getspeed: endpt[%d] == %d\n", rec, endpt[rec]);	ep = ad->usb->ep[endpt[rec]];	if(ep->iface == nil)		sysfatal("no interface");	if(curalt[rec] < 0)		sysfatal("curalt[%s] not set", rec?"Record":"Playback");	da = ep->iface->altc[curalt[rec]];	a = da->aux;	if(a->caps & onefreq){		dprint(2, "getspeed: onefreq\n");		if(which == Rgetres)			return Undef;		return a->freqs[0];		/* speed not settable */	}	if(a->caps & has_setspeed){		dprint(2, "getspeed: has_setspeed, ask\n");		n = endpt[rec];		if(rec)			n |= 0x80;		r = Rd2h|Rclass|Rep;		if(usbcmd(ad,r,which,sampling_freq_control<<8, n, buf, 3) < 0)			return Undef;		if(n == 3){			if(buf[2]){				dprint(2, "Speed out of bounds\n");				if((a->caps & has_discfreq) && (buf[0] | buf[1] << 8) < 8)					return a->freqs[buf[0] | buf[1] << 8];			}			return buf[0] | buf[1] << 8 | buf[2] << 16;		}		dprint(2, "getspeed: n = %d\n", n);	}	if(a->caps & has_contfreq){		dprint(2, "getspeed: has_contfreq\n");		if(which == Rgetcur)			return controls[rec][Speed_control].value[0];		if(which == Rgetmin)			return a->minfreq;		if(which == Rgetmax)			return a->maxfreq;		if(which == Rgetres)			return 1;	}	if(a->caps & has_discfreq){		dprint(2, "getspeed: has_discfreq\n");		if(which == Rgetcur)			return controls[rec][Speed_control].value[0];		if(which == Rgetmin)			return a->freqs[0];		for(i = 0; i < 8 && a->freqs[i] > 0; i++)			;		if(which == Rgetmax)			return a->freqs[i-1];		if(which == Rgetres)			return Undef;	}	dprint(2, "can't happen\n?");	return Undef;} intsetcontrol(int rec, char *name, long *value){	int i, ctl, m;	byte buf[3];	int type, req, control, index, count;	Audiocontrol *c; 	c = nil;	for(ctl = 0; ctl < Ncontrol; ctl++){		c = &controls[rec][ctl];		if(strcmp(name, c->name) == 0)			break;	}	if(ctl == Ncontrol){		dprint(2, "setcontrol: control not found\n");		return -1;	}	if(c->settable == 0){		dprint(2, "setcontrol: control %d.%d not settable\n", rec, ctl);		if(c->chans){			for(i = 0; i < 8; i++)				if((c->chans & 1 << i) && c->value[i] != value[i])					return -1;			return 0;		}		if(c->value[0] != value[0])			return -1;		return 0;	}	if(c->chans){		value[0] = 0;	// set to average		m = 0;		for(i = 1; i < 8; i++)			if(c->chans & 1 << i){				if(c->min != Undef && value[i] < c->min)					value[i] = c->min;				if(c->max != Undef && value[i] > c->max)					value[i] = c->max;				value[0] += value[i];				m++;			}else				value[i] = Undef;		if(m) value[0] /= m;	}else{		if(c->min != Undef && value[0] < c->min)			value[0] = c->min;		if(c->max != Undef && value[0] > c->max)			value[0] = c->max;	}	req = Rsetcur;	count = 1;	switch(ctl){	default:		dprint(2, "setcontrol: can't happen\n");		return -1;	case Speed_control:		if((rec != Record || setrec) && (value[0] = setspeed(rec, value[0])) < 0)			return -1;		c->value[0] = value[0];		return 0;	case Equalizer_control:		/* not implemented */		return -1;	case Resolution_control:		control = findalt(rec, controls[rec][Channel_control].value[0], value[0], defaultspeed[rec]);		if(control < 0 || setaudioalt(rec, c, control) < 0){			dprint(2, "setcontrol: can't find setting for %s\n", c->name);			return -1;		}		c->value[0] = value[0];		controls[rec][Speed_control].value[0] = defaultspeed[rec];		return 0;	case Volume_control:	case Delay_control:		count = 2;		/* fall through */	case Mute_control:	case Bass_control:	case Mid_control:	case Treble_control:	case Agc_control:	case Bassboost_control:	case Loudness_control:		type = Rh2d|Rclass|Riface;		control = ctl<<8;		index = featureid[rec]<<8;		break;	case Selector_control:		type = Rh2d|Rclass|Riface;		control = 0;		index = selectorid[rec]<<8;		break;	case Channel_control:		control = findalt(rec, value[0], controls[rec][Resolution_control].value[0], defaultspeed[rec]);		if(control < 0 || setaudioalt(rec, c, control) < 0){			dprint(2, "setcontrol: can't find setting for %s\n", c->name);			return -1;		}		c->value[0] = value[0];		controls[rec][Speed_control].value[0] = defaultspeed[rec];		return 0;	}	if(c->chans){		for(i = 1; i < 8; i++)			if(c->chans & 1 << i){				switch(count){				case 2:					buf[1] = value[i] >> 8;				case 1:					buf[0] = value[i];				}				if(usbcmd(ad, type, req, control | i, index, buf, count) < 0){					dprint(2, "setcontrol: setupcmd %s failed\n",						controls[rec][ctl].name);					return -1;				}				c->value[i] = value[i];			}	}else{		switch(count){		case 2:			buf[1] = value[0] >> 8;		case 1:			buf[0] = value[0];		}		if(usbcmd(ad, type, req, control, index, buf, count) < 0){			dprint(2, "setcontrol: setupcmd %s failed\n", c->name);			return -1;		}	}	c->value[0] = value[0];	return 0;} intgetspecialcontrol(int rec, int ctl, int req, long *value){	byte buf[3];	int m, n, i;	int type, control, index, count, signedbyte;	short svalue; 	count = 1;	signedbyte = 0;	switch(ctl){	default:		return Undef;	case Speed_control:		value[0] =  getspeed(rec, req);		return 0;	case Channel_control:	case Resolution_control:		if(req == Rgetmin)			value[0] = controls[rec][ctl].min;		if(req == Rgetmax)			value[0] = controls[rec][ctl].max;		if(req == Rgetres)			value[0] = controls[rec][ctl].step;		if(req == Rgetcur)			value[0] = controls[rec][ctl].value[0];		return 0;	case Volume_control:	case Delay_control:		count = 2;		/* fall through */	case Bass_control:	case Mid_control:	case Treble_control:	case Equalizer_control:		signedbyte = 1;

Lines 1–500 of 706.