|
@@ -14,7 +14,7 @@ int attachok;
|
|
|
|
|
|
enum
|
|
|
{
|
|
|
- OPERM = 0x3, // mask of all permission types in open mode
|
|
|
+ OPERM = 0x3, /* mask of all permission types in open mode */
|
|
|
};
|
|
|
|
|
|
typedef struct Fid Fid;
|
|
@@ -23,41 +23,41 @@ typedef struct Worker Worker;
|
|
|
|
|
|
struct Audioctldata
|
|
|
{
|
|
|
- long offoff; // offset of the offset for audioctl
|
|
|
- long values[2][Ncontrol][8]; // last values transmitted
|
|
|
- char * s;
|
|
|
- int ns;
|
|
|
+ long offoff; /* offset of the offset for audioctl */
|
|
|
+ long values[2][Ncontrol][8]; /* last values transmitted */
|
|
|
+ char *s;
|
|
|
+ int ns;
|
|
|
};
|
|
|
|
|
|
enum {
|
|
|
Busy = 0x01,
|
|
|
Open = 0x02,
|
|
|
- Eof = 0x04,
|
|
|
+ Eof = 0x04,
|
|
|
};
|
|
|
|
|
|
struct Fid
|
|
|
{
|
|
|
QLock;
|
|
|
- int fid;
|
|
|
- Dir * dir;
|
|
|
+ int fid;
|
|
|
+ Dir *dir;
|
|
|
ushort flags;
|
|
|
short readers;
|
|
|
- void * fiddata; // file specific per-fid data (used for audioctl)
|
|
|
- Fid * next;
|
|
|
+ void *fiddata; /* file specific per-fid data (used for audioctl) */
|
|
|
+ Fid *next;
|
|
|
};
|
|
|
|
|
|
struct Worker
|
|
|
{
|
|
|
- Fid *fid;
|
|
|
+ Fid *fid;
|
|
|
ushort tag;
|
|
|
- Fcall *rhdr;
|
|
|
- Dir *dir;
|
|
|
+ Fcall *rhdr;
|
|
|
+ Dir *dir;
|
|
|
Channel *eventc;
|
|
|
Worker *next;
|
|
|
};
|
|
|
|
|
|
enum {
|
|
|
- // Event channel messages for worker
|
|
|
+ /* Event channel messages for worker */
|
|
|
Work = 0x01,
|
|
|
Check = 0x02,
|
|
|
Flush = 0x03,
|
|
@@ -75,12 +75,12 @@ enum {
|
|
|
|
|
|
Dir dirs[] = {
|
|
|
/* Note: Qaudio{in} used as mount point for /dev/usb/%d/ep%ddata only */
|
|
|
-[Qdir] = {0,0,{Qdir, 0,QTDIR},0555|DMDIR,0,0,0, ".", nil,nil,nil},
|
|
|
-[Qvolume] = {0,0,{Qvolume, 0,QTFILE},0666,0,0,0, "volume", nil,nil,nil},
|
|
|
+[Qdir] = {0,0,{Qdir, 0,QTDIR},0555|DMDIR,0,0,0, ".", nil,nil,nil},
|
|
|
+[Qvolume] = {0,0,{Qvolume, 0,QTFILE},0666,0,0,0, "volume", nil,nil,nil},
|
|
|
[Qaudioctl] = {0,0,{Qaudioctl, 0,QTFILE},0666,0,0,0, "audioctl",nil,nil,nil},
|
|
|
-[Qaudiostat] = {0,0,{Qaudiostat, 0,QTFILE},0666,0,0,0, "audiostat",nil,nil,nil},
|
|
|
-[Qaudio] = {0,0,{Qaudio, 0,QTFILE},0222,0,0,0, "audio", nil,nil,nil},
|
|
|
-[Qaudioin] = {0,0,{Qaudioin, 0,QTFILE},0444,0,0,0, "audioin", nil,nil,nil},
|
|
|
+[Qaudiostat] = {0,0,{Qaudiostat,0,QTFILE},0666,0,0,0, "audiostat",nil,nil,nil},
|
|
|
+[Qaudio] = {0,0,{Qaudio, 0,QTFILE},0222,0,0,0, "audio", nil,nil,nil},
|
|
|
+[Qaudioin] = {0,0,{Qaudioin, 0,QTFILE},0444,0,0,0, "audioin", nil,nil,nil},
|
|
|
};
|
|
|
|
|
|
int messagesize = 4*1024+IOHDRSZ;
|
|
@@ -115,30 +115,30 @@ char *rflush(Fid*), *rauth(Fid*),
|
|
|
*rversion(Fid*);
|
|
|
|
|
|
char *(*fcalls[])(Fid*) = {
|
|
|
- [Tflush] rflush,
|
|
|
- [Tversion] rversion,
|
|
|
+ [Tflush] rflush,
|
|
|
+ [Tversion] rversion,
|
|
|
[Tauth] rauth,
|
|
|
- [Tattach] rattach,
|
|
|
+ [Tattach] rattach,
|
|
|
[Twalk] rwalk,
|
|
|
[Topen] ropen,
|
|
|
- [Tcreate] rcreate,
|
|
|
+ [Tcreate] rcreate,
|
|
|
[Tread] rread,
|
|
|
- [Twrite] rwrite,
|
|
|
- [Tclunk] rclunk,
|
|
|
+ [Twrite] rwrite,
|
|
|
+ [Tclunk] rclunk,
|
|
|
[Tremove] rremove,
|
|
|
[Tstat] rstat,
|
|
|
- [Twstat] rwstat,
|
|
|
+ [Twstat] rwstat,
|
|
|
};
|
|
|
|
|
|
-char Eperm[] = "permission denied";
|
|
|
+char Eperm[] = "permission denied";
|
|
|
char Enotdir[] = "not a directory";
|
|
|
char Enoauth[] = "no authentication in ramfs";
|
|
|
char Enotexist[] = "file does not exist";
|
|
|
-char Einuse[] = "file in use";
|
|
|
-char Eexist[] = "file exists";
|
|
|
+char Einuse[] = "file in use";
|
|
|
+char Eexist[] = "file exists";
|
|
|
char Enotowner[] = "not owner";
|
|
|
char Eisopen[] = "file already open for I/O";
|
|
|
-char Excl[] = "exclusive use file already open";
|
|
|
+char Excl[] = "exclusive use file already open";
|
|
|
char Ename[] = "illegal name";
|
|
|
char Ebadctl[] = "unknown control message";
|
|
|
|
|
@@ -206,13 +206,15 @@ serve(void *)
|
|
|
if(mount(p[1], -1, mntpt, MBEFORE, "") < 0)
|
|
|
sysfatal("mount failed");
|
|
|
if (endpt[Play] >= 0){
|
|
|
- sprint(epdata, "#U/usb%d/%d/ep%ddata", ad->ctlrno, ad->id, endpt[Play]);
|
|
|
+ sprint(epdata, "#U/usb%d/%d/ep%ddata", ad->ctlrno, ad->id,
|
|
|
+ endpt[Play]);
|
|
|
sprint(audiofile, "%s/audio", mntpt);
|
|
|
if(bind(epdata, audiofile, MREPL) < 0)
|
|
|
sysfatal("bind failed");
|
|
|
}
|
|
|
if (endpt[Record] >= 0){
|
|
|
- sprint(epdata, "#U/usb%d/%d/ep%ddata", ad->ctlrno, ad->id, endpt[Record]);
|
|
|
+ sprint(epdata, "#U/usb%d/%d/ep%ddata", ad->ctlrno, ad->id,
|
|
|
+ endpt[Record]);
|
|
|
sprint(audiofile, "%s/audioin", mntpt);
|
|
|
if(bind(epdata, audiofile, MREPL) < 0)
|
|
|
sysfatal("bind failed");
|
|
@@ -376,7 +378,7 @@ allocaudioctldata(void)
|
|
|
for (i = 0; i < 2; i++)
|
|
|
for(j=0; j < Ncontrol; j++)
|
|
|
for(k=0; k < 8; k++)
|
|
|
- a->values[i][j][k] = Undef;
|
|
|
+ a->values[i][j][k] = Undef;
|
|
|
return a;
|
|
|
}
|
|
|
|
|
@@ -431,44 +433,50 @@ readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
|
|
|
return n;
|
|
|
}
|
|
|
|
|
|
+enum { Chunk = 1024, };
|
|
|
+
|
|
|
int
|
|
|
makeaudioctldata(Fid *f)
|
|
|
{
|
|
|
- int rec, ctl, i, different;
|
|
|
+ int rec, ctl, i, diff;
|
|
|
+ long *actls; /* 8 of them */
|
|
|
char *p, *e;
|
|
|
Audiocontrol *c;
|
|
|
Audioctldata *a;
|
|
|
|
|
|
if ((a = f->fiddata) == nil)
|
|
|
sysfatal("fiddata");
|
|
|
- if ((p = a->s) == nil){
|
|
|
- p = emalloc(1024);
|
|
|
- a->s = p;
|
|
|
- }
|
|
|
- e = p + 1024;
|
|
|
+ if ((p = a->s) == nil)
|
|
|
+ a->s = p = emalloc(Chunk);
|
|
|
+ e = p + Chunk - 1; /* e must point *at* last byte, not *after* */
|
|
|
for (rec = 0; rec < 2; rec++)
|
|
|
for (ctl = 0; ctl < Ncontrol; ctl++) {
|
|
|
c = &controls[rec][ctl];
|
|
|
- different = 0;
|
|
|
+ actls = a->values[rec][ctl];
|
|
|
+ diff = 0;
|
|
|
if (c->chans){
|
|
|
for (i = 1; i < 8; i++)
|
|
|
- if ((c->chans & 1<<i) && c->value[i] != a->values[rec][ctl][i])
|
|
|
- different = 1;
|
|
|
+ if ((c->chans & 1<<i) &&
|
|
|
+ c->value[i] != actls[i])
|
|
|
+ diff = 1;
|
|
|
}else
|
|
|
- if (c->value[0] != a->values[rec][ctl][0])
|
|
|
- different = 1;
|
|
|
- if (different){
|
|
|
- p = seprint(p, e, "%s %s %A", c->name, rec?"in":"out", c);
|
|
|
- memmove(a->values[rec][ctl], c->value, sizeof c->value);
|
|
|
+ if (c->value[0] != actls[0])
|
|
|
+ diff = 1;
|
|
|
+ if (diff){
|
|
|
+ p = seprint(p, e, "%s %s %A", c->name,
|
|
|
+ rec? "in": "out", c);
|
|
|
+ memmove(actls, c->value, sizeof c->value);
|
|
|
if (c->min != Undef){
|
|
|
- p = seprint(p, e, " %ld %ld", c->min, c->max);
|
|
|
+ p = seprint(p, e, " %ld %ld", c->min,
|
|
|
+ c->max);
|
|
|
if (c->step != Undef)
|
|
|
- p = seprint(p, e, " %ld", c->step);
|
|
|
+ p = seprint(p, e, " %ld",
|
|
|
+ c->step);
|
|
|
}
|
|
|
p = seprint(p, e, "\n");
|
|
|
}
|
|
|
}
|
|
|
- assert(strlen(a->s) < 1024);
|
|
|
+ assert(strlen(a->s) < Chunk);
|
|
|
a->ns = p - a->s;
|
|
|
return a->ns;
|
|
|
}
|
|
@@ -476,14 +484,14 @@ makeaudioctldata(Fid *f)
|
|
|
void
|
|
|
readproc(void *x)
|
|
|
{
|
|
|
- Fcall *rhdr;
|
|
|
+ int n, cnt;
|
|
|
+ ulong event;
|
|
|
+ vlong off;
|
|
|
+ uchar *mdata;
|
|
|
Audioctldata *a;
|
|
|
+ Fcall *rhdr;
|
|
|
Fid *f;
|
|
|
- uchar *mdata;
|
|
|
- int n, cnt;
|
|
|
- long off;
|
|
|
Worker *w;
|
|
|
- ulong event;
|
|
|
|
|
|
w = x;
|
|
|
mdata = emalloc(8*1024+IOHDRSZ);
|
|
@@ -502,7 +510,8 @@ readproc(void *x)
|
|
|
event = recvul(w->eventc);
|
|
|
qlock(f);
|
|
|
if (debug & Dbgproc)
|
|
|
- fprint(2, "readproc unblocked fid %d %lld\n", f->fid, f->dir->qid.path);
|
|
|
+ fprint(2, "readproc unblocked fid %d %lld\n",
|
|
|
+ f->fid, f->dir->qid.path);
|
|
|
switch (event & 0xffff) {
|
|
|
case Work:
|
|
|
sysfatal("readproc phase error");
|
|
@@ -513,7 +522,8 @@ readproc(void *x)
|
|
|
case Flush:
|
|
|
if ((event >> 16) == rhdr->tag) {
|
|
|
if (debug & Dbgproc)
|
|
|
- fprint(2, "readproc flushing fid %d, tag %d\n", f->fid, rhdr->tag);
|
|
|
+ fprint(2, "readproc flushing fid %d, tag %d\n",
|
|
|
+ f->fid, rhdr->tag);
|
|
|
goto flush;
|
|
|
}
|
|
|
continue;
|
|
@@ -549,13 +559,13 @@ flush:
|
|
|
char*
|
|
|
rread(Fid *f)
|
|
|
{
|
|
|
- long off;
|
|
|
int i, n, cnt, rec;
|
|
|
+ vlong off;
|
|
|
char *p;
|
|
|
- static char buf[1024];
|
|
|
Audiocontrol *c;
|
|
|
Audioctldata *a;
|
|
|
Worker *w;
|
|
|
+ static char buf[1024];
|
|
|
|
|
|
rhdr.count = 0;
|
|
|
off = thdr.offset;
|
|
@@ -578,26 +588,37 @@ rread(Fid *f)
|
|
|
for (rec = 0; rec < 2; rec++){
|
|
|
c = &controls[rec][Volume_control];
|
|
|
if (c->readable){
|
|
|
- i = snprint(p, n, "audio %s %ld\n", rec?"in":"out", (c->min != Undef) ?
|
|
|
- 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]);
|
|
|
- p+=i; n-=i;
|
|
|
+ i = snprint(p, n, "audio %s %ld\n",
|
|
|
+ rec? "in": "out", (c->min != Undef?
|
|
|
+ 100*(c->value[0]-c->min)/(c->max-c->min):
|
|
|
+ c->value[0]));
|
|
|
+ p += i;
|
|
|
+ n -= i;
|
|
|
}
|
|
|
c = &controls[rec][Treble_control];
|
|
|
if (c->readable){
|
|
|
- i = snprint(p, n, "treb %s %ld\n", rec?"in":"out", (c->min != Undef) ?
|
|
|
- 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]);
|
|
|
- p+=i; n-=i;
|
|
|
+ i = snprint(p, n, "treb %s %ld\n",
|
|
|
+ rec? "in": "out", (c->min != Undef?
|
|
|
+ 100*(c->value[0]-c->min)/(c->max-c->min):
|
|
|
+ c->value[0]));
|
|
|
+ p += i;
|
|
|
+ n -= i;
|
|
|
}
|
|
|
c = &controls[rec][Bass_control];
|
|
|
if (c->readable){
|
|
|
- i = snprint(p, n, "bass %s %ld\n", rec?"in":"out", (c->min != Undef) ?
|
|
|
- 100*(c->value[0]-c->min)/(c->max-c->min) : c->value[0]);
|
|
|
- p+=i; n-=i;
|
|
|
+ i = snprint(p, n, "bass %s %ld\n",
|
|
|
+ rec? "in": "out", (c->min != Undef?
|
|
|
+ 100*(c->value[0]-c->min)/(c->max-c->min):
|
|
|
+ c->value[0]));
|
|
|
+ p += i;
|
|
|
+ n -= i;
|
|
|
}
|
|
|
c = &controls[rec][Speed_control];
|
|
|
if (c->readable){
|
|
|
- i = snprint(p, n, "speed %s %ld\n", rec?"in":"out", c->value[0]);
|
|
|
- p+=i; n-=i;
|
|
|
+ i = snprint(p, n, "speed %s %ld\n",
|
|
|
+ rec? "in": "out", c->value[0]);
|
|
|
+ p += i;
|
|
|
+ n -= i;
|
|
|
}
|
|
|
}
|
|
|
n = sizeof buf - n;
|
|
@@ -689,27 +710,32 @@ rwrite(Fid *f)
|
|
|
thdr.data[cnt] = '\0';
|
|
|
nlines = getfields(thdr.data, lines, 2*Ncontrol, 1, "\n");
|
|
|
for(i = 0; i < nlines; i++){
|
|
|
- if (debug) fprint(2, "line: %s\n", lines[i]);
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "line: %s\n", lines[i]);
|
|
|
nf = tokenize(lines[i], fields, 4);
|
|
|
if (nf == 0)
|
|
|
continue;
|
|
|
- if (nf == 3){
|
|
|
- if (strcmp(fields[1], "in") == 0 || strcmp(fields[1], "record") == 0)
|
|
|
+ if (nf == 3)
|
|
|
+ if (strcmp(fields[1], "in") == 0 ||
|
|
|
+ strcmp(fields[1], "record") == 0)
|
|
|
rec = 1;
|
|
|
- else if (strcmp(fields[1], "out") == 0 || strcmp(fields[1], "playback") == 0)
|
|
|
+ else if (strcmp(fields[1], "out") == 0 ||
|
|
|
+ strcmp(fields[1], "playback") == 0)
|
|
|
rec = 0;
|
|
|
else {
|
|
|
- if (debug) fprint(2, "bad1\n");
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "bad1\n");
|
|
|
return Ebadctl;
|
|
|
}
|
|
|
- }else if (nf == 2)
|
|
|
+ else if (nf == 2)
|
|
|
rec = 0;
|
|
|
else {
|
|
|
- if (debug) fprint(2, "bad2 %d\n", nf);
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "bad2 %d\n", nf);
|
|
|
return Ebadctl;
|
|
|
}
|
|
|
c = nil;
|
|
|
- if (strcmp(fields[0], "audio") == 0) /* special case */
|
|
|
+ if (strcmp(fields[0], "audio") == 0) /* special case */
|
|
|
fields[0] = "volume";
|
|
|
for (ctl = 0; ctl < Ncontrol; ctl++){
|
|
|
c = &controls[rec][ctl];
|
|
@@ -717,38 +743,55 @@ rwrite(Fid *f)
|
|
|
break;
|
|
|
}
|
|
|
if (ctl == Ncontrol){
|
|
|
- if (debug) fprint(2, "bad3\n");
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "bad3\n");
|
|
|
return Ebadctl;
|
|
|
}
|
|
|
- if (f->dir == &dirs[Qvolume] && ctl != Speed_control && c->min != Undef && c->max != Undef){
|
|
|
- nnf = tokenize(fields[nf-1], subfields, nelem(subfields));
|
|
|
+ if (f->dir == &dirs[Qvolume] && ctl != Speed_control &&
|
|
|
+ c->min != Undef && c->max != Undef){
|
|
|
+ nnf = tokenize(fields[nf-1], subfields,
|
|
|
+ nelem(subfields));
|
|
|
if (nnf <= 0 || nnf > 8){
|
|
|
- if (debug) fprint(2, "bad4\n");
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "bad4\n");
|
|
|
return Ebadctl;
|
|
|
}
|
|
|
p = buf;
|
|
|
for (i = 0; i < nnf; i++){
|
|
|
value = strtol(subfields[i], nil, 0);
|
|
|
- value = ((100 - value) * c->min + value * c->max) / 100;
|
|
|
- if (debug) {
|
|
|
+ value = ((100 - value)*c->min +
|
|
|
+ value*c->max) / 100;
|
|
|
+ if (debug)
|
|
|
if (p == buf)
|
|
|
fprint(2, "rwrite: %s %s '%ld",
|
|
|
- c->name, rec?"record":"playback", value);
|
|
|
+ c->name, rec?
|
|
|
+ "record":
|
|
|
+ "playback",
|
|
|
+ value);
|
|
|
else
|
|
|
fprint(2, " %ld", value);
|
|
|
- }
|
|
|
if (p == buf)
|
|
|
- p = seprint(p, buf+sizeof buf, "0x%p %s %s '%ld",
|
|
|
- replchan, c->name, rec?"record":"playback", value);
|
|
|
+ p = seprint(p, buf+sizeof buf,
|
|
|
+ "0x%p %s %s '%ld",
|
|
|
+ replchan, c->name, rec?
|
|
|
+ "record": "playback",
|
|
|
+ value);
|
|
|
else
|
|
|
- p = seprint(p, buf+sizeof buf, " %ld", value);
|
|
|
+ p = seprint(p, buf+sizeof buf,
|
|
|
+ " %ld", value);
|
|
|
}
|
|
|
- if (debug) fprint(2, "'\n");
|
|
|
- seprint(p, buf+sizeof buf, "'");
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "'\n");
|
|
|
+ seprint(p, buf+sizeof buf-1, "'");
|
|
|
chanprint(controlchan, buf);
|
|
|
} else {
|
|
|
- if (debug) fprint(2, "rwrite: %s %s %q", c->name, rec?"record":"playback", fields[nf-1]);
|
|
|
- chanprint(controlchan, "0x%p %s %s %q", replchan, c->name, rec?"record":"playback", fields[nf-1]);
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "rwrite: %s %s %q", c->name,
|
|
|
+ rec? "record": "playback",
|
|
|
+ fields[nf-1]);
|
|
|
+ chanprint(controlchan, "0x%p %s %s %q",
|
|
|
+ replchan, c->name, rec? "record":
|
|
|
+ "playback", fields[nf-1]);
|
|
|
}
|
|
|
p = recvp(replchan);
|
|
|
if (p){
|
|
@@ -775,7 +818,7 @@ rclunk(Fid *f)
|
|
|
|
|
|
qlock(f);
|
|
|
f->flags &= ~(Open|Busy);
|
|
|
- assert (f->readers ==0);
|
|
|
+ assert(f->readers ==0);
|
|
|
if (f->fiddata){
|
|
|
a = f->fiddata;
|
|
|
if (a->s)
|
|
@@ -799,9 +842,9 @@ rstat(Fid *f)
|
|
|
Audioctldata *a;
|
|
|
|
|
|
if (f->dir == &dirs[Qaudio] && endpt[Play] < 0)
|
|
|
- return Enotexist;
|
|
|
+ return Enotexist;
|
|
|
if (f->dir == &dirs[Qaudioin] && endpt[Record] < 0)
|
|
|
- return Enotexist;
|
|
|
+ return Enotexist;
|
|
|
if (f->dir == &dirs[Qaudioctl]){
|
|
|
qlock(f);
|
|
|
if (f->fiddata == nil)
|
|
@@ -830,9 +873,9 @@ newfid(int fid)
|
|
|
|
|
|
ff = nil;
|
|
|
for(f = fids; f; f = f->next)
|
|
|
- if(f->fid == fid){
|
|
|
+ if(f->fid == fid)
|
|
|
return f;
|
|
|
- }else if(ff == nil && (f->flags & Busy) == 0)
|
|
|
+ else if(ff == nil && (f->flags & Busy) == 0)
|
|
|
ff = f;
|
|
|
if(ff == nil){
|
|
|
ff = emallocz(sizeof *ff, 1);
|
|
@@ -870,7 +913,8 @@ io(void *)
|
|
|
if(n < 0){
|
|
|
rerrstr(e, sizeof e);
|
|
|
if (strcmp(e, "interrupted") == 0){
|
|
|
- if (debug) fprint(2, "read9pmsg interrupted\n");
|
|
|
+ if (debug)
|
|
|
+ fprint(2, "read9pmsg interrupted\n");
|
|
|
continue;
|
|
|
}
|
|
|
return;
|