Beispiel #1
0
static void
work(void *a)
{
	Channel *portc;
	char *fn;
	Hub *h;
	int i;

	portc = a;
	threadsetname("work");
	hubs = nil;
	/*
	 * Receive requests for root hubs
	 */
	while((fn = recvp(portc)) != nil){
		dprint(2, "%s: %s starting\n", argv0, fn);
		h = newhub(fn, nil);
		if(h == nil)
			fprint(2, "%s: %s: newhub failed: %r\n", argv0, fn);
		free(fn);
	}
	/*
	 * Enumerate (and acknowledge after first enumeration).
	 * Do NOT perform enumeration concurrently for the same
	 * controller. new devices attached respond to a default
	 * address (0) after reset, thus enumeration has to work
	 * one device at a time at least before addresses have been
	 * assigned.
	 * Do not use hub interrupt endpoint because we
	 * have to poll the root hub(s) in any case.
	 */
	for(;;){
Again:
		for(h = hubs; h != nil; h = h->next)
			for(i = 1; i <= h->nport; i++)
				if(enumhub(h, i) < 0){
					/* changes in hub list; repeat */
					goto Again;
				}
		if(portc != nil){
			sendp(portc, nil);
			portc = nil;
		}
		sleep(pollms);
		if(mustdump)
			dump();
	}
}
Beispiel #2
0
int
startdev(Port *pp)
{
	Dev *d;
	Usbdev *ud;
	Devtab *dt;
	Sarg *sa;
	Channel *rc;

	d = pp->dev;
	assert(d);
	ud = d->usb;
	assert(ud != nil);

	writeinfo(d);

	if(ud->class == Clhub){
		/*
		 * Hubs are handled directly by this process avoiding
		 * concurrent operation so that at most one device
		 * has the config address in use.
		 * We cancel kernel debug for these eps. too chatty.
		 */
		pp->hub = newhub(d->dir, d);
		if(pp->hub == nil)
			fprint(2, "%s: %s: %r\n", argv0, d->dir);
		else
			fprint(2, "usb/hub... ");
		if(usbdebug > 1)
			devctl(d, "debug 0");	/* polled hubs are chatty */
		return pp->hub == nil ? -1 : 0;
	}

	for(dt = devtab; dt->name != nil; dt++)
		if(devmatch(dt, ud))
			break;
	/*
	 * From here on the device is for the driver.
	 * When we return pp->dev contains a Dev just for us
	 * with only the ctl open. Both devs are released on the last closedev:
	 * driver's upon I/O errors and ours upon port dettach.
	 */
	if(dt->name == nil){
		dprint(2, "%s: no configured entry for %s (csp %#08lx)\n",
			argv0, d->dir, ud->csp);
		close(d->dfd);
		d->dfd = -1;
		return 0;
	}
	sa = emallocz(sizeof(Sarg), 1);
	sa->pp = pp;
	sa->dt = dt;
	rc = sa->rc = chancreate(sizeof(uint32_t), 1);
	procrfork(startdevproc, sa, Stack, RFNOTEG);
	if(recvul(rc) != 0)
		free(sa);
	chanfree(rc);
	fprint(2, "usb/%s... ", dt->name);

	sleep(Spawndelay);		/* in case we re-spawn too fast */
	return 0;
}