⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiofs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <thread.h>#include <auth.h>#include <fcall.h>#include <libsec.h>#include "usb.h"#include "usbaudio.h"#include "usbaudioctl.h"int attachok;#define STACKSIZE 16*1024enum{	OPERM	= 0x3,		// mask of all permission types in open mode};typedef struct Fid Fid;typedef struct Audioctldata Audioctldata;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;};enum {	Busy =	0x01,	Open =	0x02,	Eof =		0x04,};struct Fid{	QLock;	int		fid;	Dir	*	dir;	ushort	flags;	short	readers;	void	*	fiddata;		// file specific per-fid data (used for audioctl)	Fid	*	next;};struct Worker{	Fid		*fid;	ushort	tag;	Fcall		*rhdr;	Dir		*dir;	Channel	*eventc;	Worker	*next;};enum {	// Event channel messages for worker	Work =	0x01,	Check =	0x02,	Flush =	0x03,};enum {	Qdir,	Qvolume,	Qaudioctl,	Qaudiostat,	Qaudio,	Qaudioin,	Nqid,};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},[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},};int	messagesize = 4*1024+IOHDRSZ;uchar	mdata[8*1024+IOHDRSZ];uchar	mbuf[8*1024+IOHDRSZ];Fcall	thdr;Fcall	rhdr;Worker *workers;char srvfile[64], mntdir[64], epdata[64], audiofile[64];int mfd[2], p[2];char user[32];char *srvpost;Channel *procchan;Channel *replchan;Fid *fids;Fid*		newfid(int);void		io(void *);void		usage(void);extern char *mntpt;char	*rflush(Fid*), *rauth(Fid*),	*rattach(Fid*), *rwalk(Fid*),	*ropen(Fid*), *rcreate(Fid*),	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),	*rversion(Fid*);char 	*(*fcalls[])(Fid*) = {	[Tflush]		rflush,	[Tversion]		rversion,	[Tauth]		rauth,	[Tattach]		rattach,	[Twalk]		rwalk,	[Topen]		ropen,	[Tcreate]		rcreate,	[Tread]		rread,	[Twrite]		rwrite,	[Tclunk]		rclunk,	[Tremove]	rremove,	[Tstat]		rstat,	[Twstat]		rwstat,};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	Enotowner[] =	"not owner";char	Eisopen[] = 	"file already open for I/O";char	Excl[] = 		"exclusive use file already open";char	Ename[] = 	"illegal name";char	Ebadctl[] =	"unknown control message";intnotifyf(void *, char *s){	if(strncmp(s, "interrupt", 9) == 0)		return 1;	return 0;}voidpost(char *name, char *envname, int srvfd){	int fd;	char buf[32];	fd = create(name, OWRITE, attachok?0666:0600);	if(fd < 0)		return;	sprint(buf, "%d",srvfd);	if(write(fd, buf, strlen(buf)) != strlen(buf))		sysfatal("srv write");	close(fd);	putenv(envname, name);}voidserve(void *){	int i;	ulong t;	if(pipe(p) < 0)		sysfatal("pipe failed");	mfd[0] = p[0];	mfd[1] = p[0];	atnotify(notifyf, 1);	strcpy(user, getuser());	t = time(nil);	for (i = 0; i < Nqid; i++){		dirs[i].uid = user;		dirs[i].gid = user;		dirs[i].muid = user;		dirs[i].atime = t;		dirs[i].mtime = t;	}	if(mntpt == nil){		snprint(mntdir, sizeof(mntdir), "/dev");		mntpt = mntdir;	}	if(debug)		fmtinstall('F', fcallfmt);	procrfork(io, nil, STACKSIZE, RFFDG|RFNAMEG);	close(p[0]);	/* don't deadlock if child fails */	if(srvpost){		sprint(srvfile, "/srv/%s", srvpost);		remove(srvfile);		post(srvfile, "usbaudio", p[1]);	}	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(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(audiofile, "%s/audioin", mntpt);		if(bind(epdata, audiofile, MREPL) < 0)			sysfatal("bind failed");	}	threadexits(nil);}char*rversion(Fid*){	Fid *f;	if(thdr.msize < 256)		return "max messagesize too small";	if(thdr.msize < messagesize)		messagesize = thdr.msize;	rhdr.msize = messagesize;	if(strncmp(thdr.version, "9P2000", 6) != 0)		return "unknown 9P version";	else		rhdr.version = "9P2000";	for(f = fids; f; f = f->next)		if(f->flags & Busy)			rclunk(f);	return nil;}char*rauth(Fid*){	return "usbaudio: no authentication required";}char*rflush(Fid *){	Worker *w;	int waitflush;	do {		waitflush = 0;		for (w = workers; w; w = w->next)			if (w->tag == thdr.oldtag){				waitflush++;				nbsendul(w->eventc, thdr.oldtag << 16 | Flush);			}		if (waitflush)			sleep(50);	} while(waitflush);	if (debug & Dbgproc)		fprint(2, "flush done on tag %d\n", thdr.oldtag);	return 0;}char*rattach(Fid *f){	f->flags |= Busy;	f->dir = &dirs[Qdir];	rhdr.qid = f->dir->qid;	if(attachok == 0 && strcmp(thdr.uname, user) != 0)		return Eperm;	return 0;}static Fid*doclone(Fid *f, int nfid){	Fid *nf;	nf = newfid(nfid);	if(nf->flags & Busy)		return nil;	nf->flags |= Busy;	nf->flags &= ~Open;	nf->dir = f->dir;	return nf;}char*dowalk(Fid *f, char *name){	int t;	if (strcmp(name, ".") == 0)		return nil;	if (strcmp(name, "..") == 0){		f->dir = &dirs[Qdir];		return nil;	}	if(f->dir != &dirs[Qdir])		return Enotexist;	for (t = 1; t < Nqid; t++){		if (t == Qaudio && endpt[Play] < 0)			continue;		if (t == Qaudioin && endpt[Record] < 0)			continue;		if(strcmp(name, dirs[t].name) == 0){			f->dir = &dirs[t];			return nil;		}	}	return Enotexist;}char*rwalk(Fid *f){	Fid *nf;	char *rv;	int i;	Dir *savedir;	if(f->flags & Open)		return Eisopen;	rhdr.nwqid = 0;	nf = nil;	savedir = f->dir;	/* clone if requested */	if(thdr.newfid != thdr.fid){		nf = doclone(f, thdr.newfid);		if(nf == nil)			return "new fid in use";		f = nf;	}	/* if it's just a clone, return */	if(thdr.nwname == 0 && nf != nil)		return nil;	/* walk each element */	rv = nil;	for(i = 0; i < thdr.nwname; i++){		rv = dowalk(f, thdr.wname[i]);		if(rv != nil){			if(nf != nil)					rclunk(nf);			else				f->dir = savedir;			break;		}		rhdr.wqid[i] = f->dir->qid;	}	rhdr.nwqid = i;	/* we only error out if no walk  */	if(i > 0)		rv = nil;	return rv;}Audioctldata *allocaudioctldata(void){	int i, j, k;	Audioctldata *a;	a = emallocz(sizeof(Audioctldata), 1);	for (i = 0; i < 2; i++)		for(j=0; j < Ncontrol; j++)			for(k=0; k < 8; k++)			a->values[i][j][k] = Undef;	return a;}char *ropen(Fid *f){	if(f->flags & Open)		return Eisopen;	if(f->dir == &dirs[Qaudio] || f->dir == &dirs[Qaudioin])		return Eperm;	if(thdr.mode != OREAD && (f->dir->mode & 0x2) == 0)		return Eperm;	qlock(f);	if(f->dir == &dirs[Qaudioctl] && f->fiddata == nil)		f->fiddata = allocaudioctldata();	qunlock(f);	rhdr.iounit = 0;	rhdr.qid = f->dir->qid;	f->flags |= Open;	return nil;}char *rcreate(Fid*){	return Eperm;}intreadtopdir(Fid*, uchar *buf, long off, int cnt, int blen){	int i, m, n;	long pos;	n = 0;	pos = 0;	for (i = 1; i < Nqid; i++){		if (endpt[Play] < 0 && i == Qaudio)			continue;		if (endpt[Record] < 0 && i == Qaudioin)			continue;		m = convD2M(&dirs[i], &buf[n], blen-n);		if(off <= pos){			if(m <= BIT16SZ || m > cnt)				break;			n += m;			cnt -= m;		}		pos += m;	}	return n;}intmakeaudioctldata(Fid *f){	int rec, ctl, i, different;	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;	for (rec = 0; rec < 2; rec++)		for (ctl = 0; ctl < Ncontrol; ctl++) {			c = &controls[rec][ctl];			different = 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;			}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->min != Undef){					p = seprint(p, e, " %ld %ld", c->min, c->max);					if (c->step != Undef)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -