/* * 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. Load more
/* * 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}, } }; int setaudioalt(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; } int findalt(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; } int setspeed(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; } long getspeed(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; } int setcontrol(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; } int getspecialcontrol(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;