Component Object Model (COM) is an object/component technology that enforces (stringently) a distinction between an object's
interface (what it
can do) from its implementation (how it does it). The problem is, any given object can potentially do everything, or nothing at all. How does one find out?
COM requires that
all interfaces implement a minimum of three methods:
QueryInterface is used to probe an object to see if it
can do something else, while
AddRef and
Release are used to manage the object's lifecycle in memory.
To illustrate how QueryInterface is used, consider what appears to be a normal file. You have a pointer to a file object, and it exposes the usual stuff -- you can read from it, write to it, query its file size, etc. But what if it's a special *kind* of file? For example, it could be a database table. If so, you ought to be able to send it an SQL database query. The file interface lacks this capability -- all it can do is read/write bunches of bytes. So, you invoke QueryInterface, asking if it supports the Database interface. If it does, you can then use that new interface reference to issue the SQL query. (Likewise, Database interfaces aren't necessarily all files either! Consider the case where you have a dedicated database server -- in at least some of the cases, therefore, Database objects can also be network connections. And in the case of JOINs, they could reside entirely in local RAM, with no backing storage at all.)
Hardware devices, unlike software objects, exists purely as singleton objects, so there is no need for
AddRef or
Release. Dropping the final reference to a device will not cause the device to suddenly vanish from your desktop with an audible *fffffPOP!* sound.
But, all devices ought to respond to a command equivalent to
QueryInterface. For example, an MMC card reader
clearly implements mass storage-like attributes and capabilities; thus, it ought to respond to the MassStorage interface. If the peripheral
also supports its own filesystem implementation, as the Commodore disk drives to, then it ought to expose a FileSystem interface. Etc.
These things are determined by labeling each interface with a unique identifier. In COM and in my proposal, 16-byte unique IDs are used. These are 128-bit numbers called UUIDs, and the algorithm for their generation allows for such a high degree of uniqueness that it eliminates any overt need for a central registry authority or database.
Most UUIDs are tied to one of your network card's MAC address (and since those are unique at all times by necessity and by regulation of IEEE, it guarantees UUIDs are also unique). For those cases where it's not, UUIDs are generated via an MD5 cryptographic hash of various pieces of data that you offer it. The odds of me offering the same pieces of data as you are very, very small -- thus, the odds of a collision, while non-zero, comes asymptotically close to zero.
In your example, you said that $12 would cause the device's configuration profile to be sent. I propose $13 to be able to ask the device for whether or not it supports a given interface.
If it does, it will return a successful indication, along with instructions on how to access that facility. The precise manner of how this is done is not yet fleshed out, so I can't go into more details at this time.
If it does not, it just returns a message saying, "No."
By adopting a scheme similar to this, you end up writing
class drivers instead of device drivers as such. Class drivers (a term I borrowed from USB documentation) are basically device drivers that can address a whole class of compatible devices -- devices that willingly adopt a standard interface. HIDDs (Human Input Device Drivers) are class drivers, for example, that allow you to use virtually any USB keyboard or mouse with your computer. One driver module, thousands of peripherals.
This principle is, I think, important, because part of the Kestrel's goal is to allow the programmer the greatest functionality with a minimum of interference from system software and hardware. This is directly in line with how Forth is intended to be used as well. It helps to (sorry) "dispel the user illusion," but does so without sacrificing inherent capability.
Chuck Moore believes, and I vehemently concur, that it's easier to talk directly to the hardware than it is to talk to an operating system interface, provided that interface is standardized and not too complex (or, at least, the complexity is well justified). It saves 100% the code needed to implement the driver,
if only the interface were standardized.
Commodore's serial and GPIB buses were used with this in mind. Devices were intelligent --
very intelligent. The only "driver" that Commodore's kernel had inside it was for the GPIB or serial bus. That's it. Literally all other code either touched hardware directly, OR, it issued
well known and standardized command strings to other GPIB devices on the bus.
The "drivers" for a specific device, therefore, lay inside the peripheral itself, and quite often could run in parallel with the main computer, thus offering a degree of parallelism that PCs couldn't touch until Linux was generally available, decades later. I remember one metric used to guage multitasking on the PC was formatting a floppy disk while doing other things on the screen. The Commodore 8-bit line had the PCs licked in this area since 1977, and the kernel was never designed for multitasking.
Simply send "N" to the disk drive's command channel, and then do something else.
I intend on capitalizing on this with the Kestrel. Maybe not upon first release, but eventually.
Now you know why this SIB is so much of interest to me.
Quote:
What you want to do will require adding more intelligence than anything I have in mind does. I don't think that will make it incompatible with what I have in mind, as long as everything doesn't need to have this intelligence, but I'm afraid I can't contribute much on that part of the discussion unless your let-me-run-this-by-you's also educate me so I can comment. We seem to be well on our way to a good interface spec if it allows this kind of plug-and-play for the things you mention while also allowing the quickly put-together experiments I need to be able to do-- the whole range. If we want others to adopt it, they will have to be able to stop at whatever level of complexity suits them and their needs, and be comfortable with that.
My system does not involve that much overhead. If you prefer to talk directly to SPI devices using their own protocol instead of a sanitized/regularized protocol, that's OK too. There are two approaches:
* Respond
Yes to an interface query with the flag that it is a so-called "native SPI" protocol. Instructions would include which sub-device address to access it with, what SPI mode, what its timing parameters are, etc. In other words, it's just like reading a device's configuration file.
* Respond
No to an interface query, and depend on the driver's innate knowledge of how to access the sub-device.