From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: To: 9fans@cse.psu.edu Subject: Re: usbd - revision (Was: [9fans] USB developments) From: C H Forsyth In-Reply-To: <20040115144342.G25947@cackle.proxima.alt.za> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Date: Thu, 15 Jan 2004 18:01:41 +0000 Topicbox-Message-UUID: ba11e204-eacc-11e9-9e20-41e7f4b1d025 >> i therefore deliberately put enumeration outside the kernel because it is (potentially) >> non-trivial and recursive (so is PCI enumeration but it has >> rather less to do, placing less of a strain on KSTACK). >> >But no more than seven deep, or is that five? Surely we can cope? >Much more importantly, how complex is enumeration as such? In my >extremely limited understanding, it merely needs to return (assign, >in fact) the ID of the device, its type and whether it connected >or disconnected. And, no, I'm not sure :-) I'm asking. Worse, >I'm hoping. But of course I can "just try it". PCI enumeration would probably become more complex for similar reasons when hot-swapping is possible. i'll say a bit more about the original intention, and which parts i now dislike. i observed that the linux and freebsd (and one other i can't mention) usb implementations were rather complex. much of that was related to insisting on enumerating and configuring the devices in the kernel, and there was quite a bit of non-trivial state. in particular, to enumerate, you typically build a tree of devices. if you're only enumerating in the kernel (ie, assigning IDs) then a user-level program will do configuration. that needs to maintain a similar tree. if a hub is removed, you need to delete chunks of substructure but if both kernel and usbd are keeping a tree, they'll update at different times (eg, kernel then usbd). alternatively, they can exchange data to try to keep things in sync, but then there's the potential for races. furthermore, for the purposes of IO through the kernel, the tree structure is irrelevant, since the ID space is actually flat and only endpoints within devices matter. it therefore seemed more straightforward to have the user process build the only copy of the tree (which really is needed for enumeration and hot-plugging/unplugging) and maintain it. it then tells the kernel to enable devices. the kernel provides files it can read to see the status of the root hub. it monitors the state of individual hubs itself, using a process. (ie, usbd is the class/device-specific manager for hubs.) it's easy for usbd to use libthread, and do quite a bit of potentially messy error handling that again i thought would be painful in the kernel. a device-specific device managing process can do device-specific configuration including parsing complex structures like the HID, and it enables endpoints, within the given device directory. the kernel needs to manage only structures for devices and endpoints (which believe me are complex enough), and it does that in response to instructions from user-mode programs. usbd is in control. i was broadly happy with the kernel/user split, and the overall structure. the kernel device is essentially an IO multiplexor and i think that's about right. the kernel doesn't need to know about fancy hub trees or HID descriptors, and that also seems good to me. (for mouse and keyboard there are or were special boot-time modes one could use before usbd could run.) (in fact, usbd could probably devise/check the USB IO schedule too.) at the time i wrote it five or six years ago (!), i had trouble finding USB devices that kept to the spec--or even correct PIIXn implementations-- and decided to do more urgent things. that's one reason that i never supported iso mode (someone else did that and did a lot of work on the driver and usbd). had i realised that i wouldn't really get back to it, i'd have made several more passes over it then. for instance, when i first wrote it, qio.c didn't exist in Plan 9, and i used Stream Blocks instead. i was never very happy with the amount of code in the driver overall, and it was ugly. i did have a quick go at putting Queues in properly but didn't complete it. i was much less happy with the name space. i think it was right that it's flat, an array of devices (rather than attempting to mimic the connection hierarchy which seemed an irrelevant physical detail). the naming within the directories is fussy, though, and the use of physical names (device/endpoint) to access logical things such as printer or ether is troublesome. i thought of allowing a logical name to be created below usb, to refer to an endpoint or endpoints, but not having tried it, i don't know whether that would be better. sometimes a device presents one endpoint for reading and one for writing, but interfaces such as ethermedium expect a single name. there are other peculiar cases.