160 lines · 3.1 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include "usb.h" typedef struct Parg Parg; enum {	Ndevs = 32,	Arglen = 500,	Nargs = 64,	Stack = 16 * 1024,}; struct Parg {	char*	args;	Dev*	dev;	int 	(*f)(Dev*,int,char**);	Channel*rc;}; static voidworkproc(void *a){	Parg *pa;	char args[Arglen];	char *argv[Nargs];	int argc;	Channel *rc;	Dev *d;	int (*f)(Dev*,int,char**); 	pa = a;	threadsetname("workproc %s", pa->dev->dir);	strecpy(args, args+sizeof(args), pa->args);	/* don't leak */	d = pa->dev;	f = pa->f;	rc = pa->rc;	free(pa->args);	free(pa);	argc = tokenize(args, argv, nelem(argv)-1);	argv[argc] = nil;	if(f(d, argc, argv) < 0){		closedev(d);		fprint(2, "%s: devmain: %r\n", argv0);		sendul(rc, -1);		threadexits("devmain: %r");	}	sendul(rc, 0);	threadexits(nil);	} intmatchdevcsp(char *info, void *a){	char sbuf[40];	int *csps; 	csps = a;	for(; *csps != 0; csps++){		snprint(sbuf, sizeof(sbuf), "csp %#08ux", *csps);		if(strstr(info, sbuf) != nil)			return 0;	}	return -1;} intfinddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs){	int fd, i, n, nd, nr;	char *nm;	char dbuf[512], fbuf[40];	Dir *d; 	fd = open("/dev/usb", OREAD);	if(fd < 0)		sysfatal("/dev/usb: %r");	nd = dirreadall(fd, &d);	close(fd);	if(nd < 2)		sysfatal("/dev/usb: no devs");	for(i = n = 0; i < nd && n < ndirs; i++){		nm = d[i].name;		if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil)			continue;		snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm);		fd = open(fbuf, OREAD);		if(fd < 0)			continue;	/* may be gone */		nr = read(fd, dbuf, sizeof(dbuf)-1);		close(fd);		if(nr < 0)			continue;		dbuf[nr] = 0;		if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil)			if(matchf(dbuf, farg) == 0)				dirs[n++] = smprint("/dev/usb/%s", nm);	}	free(d);	if(usbdebug > 1)		for(nd = 0; nd < n; nd++)			fprint(2, "finddevs: %s\n", dirs[nd]);	return n;} voidstartdevs(char *args, char *argv[], int argc, int (*mf)(char*, void*),	void *ma, int (*df)(Dev*, int, char**)){	int i, ndirs, ndevs;	char *dirs[Ndevs];	char **dp;	Parg *parg;	Dev *dev;	Channel *rc; 	if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)		sysfatal("#u: %r"); 	if(argc > 0){		ndirs = argc;		dp = argv;	}else{		dp = dirs;		ndirs = finddevs(mf, ma, dp, Ndevs);		if(ndirs == nelem(dirs))			fprint(2, "%s: too many devices\n", argv0);	}	ndevs = 0;	rc = chancreate(sizeof(ulong), 0);	if(rc == nil)		sysfatal("no memory");	for(i = 0; i < ndirs; i++){		fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]);		dev = opendev(dp[i]);		if(dev == nil)			fprint(2, "%s: %s: %r\n", argv0, dp[i]);		else if(configdev(dev) < 0){			fprint(2, "%s: %s: config: %r\n", argv0, dp[i]);			closedev(dev);		}else{			dprint(2, "%s: %U", argv0, dev);			parg = emallocz(sizeof(Parg), 0);			parg->args = estrdup(args);			parg->dev = dev;			parg->rc = rc;			parg->f = df;			proccreate(workproc, parg, Stack);			if(recvul(rc) == 0)				ndevs++;		}		if(dp != argv)			free(dirs[i]);	}	chanfree(rc);	if(ndevs == 0)		sysfatal("no unhandled devices found");}