Garth and others who plan on using the serial bus Garth and I designed...
In writing up a design document for the Serbus (serial bus) protocol, I have run into an interesting design problem that I'll need help in resolving.
First, some elementary background (fasten your seatbelts, this will go by fast):
A
peripheral is that box that you plug into the Serbus port.
An
object is a device under the control of the peripheral. Example: an IDE controller allows up to two harddrives, CD-ROM drives, et. al. to be attached. Therefore, an IDE controller would expose two objects to the Serbus implementation.
An
interface is the set of commands that an object responds to. For example, a mouse can offer both button presses and releases as well as position announcements, whereas a keyboard can give
only button presses and releases. However, a keyboard typically has a set of LEDs that can be controlled, while the mouse doesn't.
An
interface ID is a
single byte used on the wire for invoking commands on an object, so that we don't have to waste a lot of bytes for every command or response.
To support bootstrapping the discovery process, the peripheral is itself also an object. This also allows for expanding the bus via switches if necessary. However, this isn't really relavent to my question.
On to the question at hand . . .
A host might send an object the command, "Do you support IDE harddrive commands?" If it does, it'll return a success code with whatever other data needs to be communicated (like interface ID, etc). If it doesn't, a failure code is sent back. Very simple.
The question I have is, how do you prefer to identify interfaces during a query command? There are three approaches, basically:
(1) A central authority can hand out interface identifiers on-demand. This is essentially what IEEE is doing with Ethernet addresses (to sell Ethernet cards, you get blocks of up to 65536 Ethernet IDs at a time). This is also what USB does too.
(2) Microsoft COM demonstrated that using UUIDs is a viable approach for identifying interfaces on objects. The UUID includes the interface author's Ethernet address if available (since it already is guaranteed unique), but if not, it's typically computed as an MD5 cryptographic hash of some other information on the system. Either way, it's a fixed-sized field of 16 bytes, which is statistically unique. They're computed exactly once, and listed in software header files and in print. E.g., a Forth block device might support an interface "named" SB_IForthBootDevice, which could perhaps be mapped to:
Code:
static const char const SB_IForthBootDevice[16] = {
0x10, 0x42, 0xFE, 0x8A, 0x9A, 0x56, 0xBD, 0xD5,
0xFF, 0xA5, 0x21, 0x00, 0x05, 0x22, 0xCD, 0xEA
};
(3) Java and CORBA both demonstrate that textual interface IDs are viable as an approach as well, provided enough hierarchy exists. For example, the Kestrel will be interested in using the first available block storage device as a bootstrap source as well as for the Forth block storage system. Therefore, objects can be queried to see if they support the "com.falvotech.kestrel.storage.rawBlock" interface, and if they do, the first one found is used to boot from.
I really don't have the resources to implement option (1), so my question is, which of (2) or (3) would you prefer? Please try to consider things both as a manufacturer of peripherals as well as a programmer.
Thanks for any feedback you can offer.