AROS

The Amiga Research OS


(C) Copyright 1996 AROS - The Amiga Research OS


Chapter 6. Hardware Independent Device Driver - HIDD

6.1 Introduction

This is a *preliminary* document. It's neither complete nor correct. It's purpose is to offer a basis for discussion not to put things into concrete

The AmigaOS is built on the Amiga's custom chips. This is a fact which is eventually discovered when you hit the rather tight limits they impose and try to circumvent them by adding new hardware. For the new hardware, you also need a device driver. But sometimes, the applications can't be made to use this new driver because the old one is compiled in or, even worse, the OS refuses to use anything besides the built in driver or, even more worse, the OS doesn't use a driver to access this chip at all.

AROS was designed to be a portable OS and be compatible to the old AmigaOS. But we had to design something which lessens these burdens without becoming incompatible or loosing too much speed. So we developed the idea of the HIDD - the Hardware Independent Device Driver.

6.2 Features

HIDDs offer a consistent API for everything one could want to do with a device. Here is a quick overview:

The complete life cycle of a HIDD is like this:

  1. The OS boots. HIDDs on external cards and in the ROM get installed by the OS in the global list of all available HIDDs. Also the OS searches for HIDDs installed on the harddisk.

  2. The OS reads the extended romtags from all HIDDs and puts that information in the global list of all available HIDDs.

  3. Some application asks for a list with the informations about all HIDDs or a specific type of HIDD.

  4. The application loads the HIDD and the config plugin. This makes the HIDD initialize some internal data structures but not always the hardware because a HIDD might be the driver for several kinds of different hardwares which are all available. Thus it must be configured first.

  5. The application asks for the current config of the HIDD. If the config plugin has its own GUI, the application displays it. Otherwise, the application displays the information in an own window. For this, the application queries the config plugin for all available modes.

  6. The app reads the config from the config plugin, then reads the list of available modes for this config (ie. what can be changed in the current config) and displays this. Then the user can select some mode, the app changes the config and starts over.

  7. When the user presses ok, the application or config plugin closes the window/GUI. The Ok or Apply button must be ghosted as long as the HIDD says that the configuration is not ok. The application can now expunge the config plugin. If a HIDD supports saving its config, it must do so.

  8. When the device is explicitly activated or used for the first time (eg. data is written to it), it will use the configuration to initialize the hardware.

  9. The user can deactivate the device and change the config if the HIDD permits that.

6.3 The HIDD Support API

ULONG HIDD_FindHIDD (struct TagItem * tags, Class ** hiddArray)
Get a list of HIDDs with the specified attributes. The HIDDs must match all attribute/value pairs in tags. Note that this is a normal function and not a method.

ULONG HIDDM_Class_Get(struct TagItem * AttrList)
Use this method on the class on a HIDD to get the static attributes (eg. HIDDA_Type, HIDDA_SubType, etc).

You can then use the HIDD API to query the devices for their infos. Use FreeVec() to dispose the array. HIDDV_FindHIDD_All as type gives the complete list of all known HIDDs.

6.4 The HIDD API

HIDDs are BOOPSI objects which support the Exec Device API.

LONG OM_SET (struct TagItem * AttrList)
Change some attributes of a HIDD.

The return code is 0 in case of success or != 0 in case of an error. If the return code is > 0, then it's the number of the offending tag in the list, if it's < 0, then it's an error code. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert this error code into a string.

LONG OM_GET (Tag AttrID, IPTR * Storage)
Query a single attribute from the HIDD in general (eg. its name and version) and the current status. You can only query attributes which are gettable.

The return code is 0 in case of success or < 0 in case of an error. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert the error code into a string.

LONG OM_MGET (struct TagItem * AttrList)
Query one or more attributes from the HIDD in general (eg. its name and version) and the current status. You can only query attributes which are gettable. The ti_Data fields of AttrList must be pointers of the type which is expected for the respective attribute.

The return code is 0 in case of success or != 0 in case of an error. If the return code is > 0, then it's the number of the offending tag in the list, if it's < 0, then it's an error code. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert this error code into a string.

LONG HIDDM_BeginIO (struct IORequest *)
Initiate a device operation. See the Exec Device API for details.

LONG HIDDM_AbortIO (struct IORequest *)
Abort a running device operation. See the Exec Device API for details.

HIDDT_Config HIDDM_LoadConfigPlugin (APTR PluginData)
Tells the HIDD to load its configuration plugin. This method returns a pointer to the plugin. PluginData is a pointer with plugin specific data. For details, look into the manual for the HIDD.

6.5 The HIDD Config Plugin API

LONG OM_SET (struct TagItem * AttrList)
Change some attributes of a HIDD Config Plugin (HIDD CP).

The return code is 0 in case of success or != 0 in case of an error. If the return code is > 0, then it's the number of the offending tag in the list, if it's < 0, then it's an error code. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert this error code into a string.

Note that changing attributes changes only the HIDD CP, never the HIDD itself. When the HIDD CP tells you that the current config works, then you can copy the config to the HIDD.

LONG OM_GET (Tag AttrID, IPTR * Storage)
Query a single attribute from the HIDD CP. You can only query attributes which are gettable.

The return code is 0 in case of success or < 0 in case of an error. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert the error code into a string.

LONG OM_MGET (struct TagItem * AttrList)
Query one or more attributes from the HIDD CP. You can only query attributes which are gettable. The ti_Data fields of AttrList must be pointers of the type which is expected for the respective attribute.

The return code is 0 in case of success or != 0 in case of an error. If the return code is > 0, then it's the number of the offending tag in the list, if it's < 0, then it's an error code. You can use HIDDM_ValueToString() with the special tag HIDDA_ErrorCode to convert this error code into a string.

struct TagItem * AttrList HIDDM_QueryConfig (void)
Ask the HIDD CP about its current configuration. The AttrList should be built in such a way that one can go back to the current config by loading the device for the first time and use OM_SET with this AttrList or by disabling it and use OM_SET. A typical use of this will be to save this list to a file and load it next time when one needs to configure the HIDD.

The current configuration of the HIDD CP is a copy of the HIDDs current configuration when the HIDD CP is created. Then you can change it and the HIDD CP will act as if the HIDD itself had changed. When you are done, you can apply the changes to the HIDD itself (aka Ok or Apply) or just forget about them (aka Cancel).

Tip: If you write a HIDD, then you can use the power of BOOPSI and TagItem lists to create this list. Pass this method to the superclass first and then attach your local taglist with TAG_MORE. Or you can filter the taglist of the superclass and build your own taglist (and dispose the taglist of the superclass by HIDDM_FreeConfig()).

void HIDDM_FreeConfig (struct TagItem * AttrList)
Dispose the list of attributes which you got by HIDDM_QueryConfig().

struct TagItem * HIDDM_QueryModeList (void)
Ask the HIDD CP about the currently available modes.

The taglist consists of tags which have the types BOOL, HIDDT_Limit (a min and max value), HIDDT_List (a list with string/value pairs or one-of-many selection) or HIDDT_OptionList (same as HIDDT_List but for some-of-many selection. The result is passed as a bitfield).

HIDD CPs which supply their own GUI don't need to support this tag (but most will because you need something like this internally anyway).

void HIDDM_FreeModeList (struct TagItem * AttrList)
Dispose the list of attributes which you got by HIDDM_QueryModeList().

ULONG HIDDM_Apply (void)
Apply the current config to the HIDD. If you dispose the HIDD CP, then all changes will be lost.

ULONG HIDDM_SaveConfig (STRPTR filename)
Save the current config in the specified file. If filename is NULL then save the current config as default. This might not result in writing a file to the harddisk if the hardware has a FlashROM or EEPROM.

ULONG HIDDM_LoadConfig (STRPTR filename)
Load the config from the specified file or the last saved defaults if filename is NULL. Some devices will read the defaults from an EEPROM so this will not always generate disc access.

STRPTR HIDDM_ValueToString (Tag tag, IPTR value)
Convert the value value for the tag tag into a human readable string. The string returned must not be written to or be freed.

HIDD CPs which supply their own GUI don't need to support this tag (but most will because you need something like this internally anyway).

The application will use this value to generate the visual feedback in its GUI.

IPTR HIDDM_StringToValue (Tag tag, STRPTR string)
Convert the string string for the tag tag back into a value.

HIDD CPs which supply their own GUI don't need to support this tag (but most will because you need something like this internally anyway).

Also note that a HIDD can ask that you return exactly the string which was passed to you by HIDDM_ValueToString() (ie. the string must have the same address).

STRPTR HIDDM_GetTagName (Tag tag)
Return a human readble string with the name for a tag. For example a serial HIDD with the tag HIDDV_Serial_BPSRate might return "BPS rate". The application will use this to generate its GUI.

ULONG HIDDM_GetTagType (Tag tag)
Return the type of an attribute. Examples are HIDDV_TagType_ULONG, HIDDV_TagType_STRPTR, HIDDV_TagType_Other (ie. something special). This can be used to generate a general GUI for a HIDD or to load and save attributess of a HIDD. Always remember that a HIDD can have many more attributes than this document describes. A HIDD can store private data in a taglist which it needs to configure itself but which should be invisible to the user.

6.5.1 Common tags for all HIDDs

HIDDA_Type,ULONG,G
This is the basic type of the HIDD (eg. HIDDV_Type_Serial for serial HIDDs, HIDDV_Type_Parallel for parallel HIDDs or HIDDV_Type_Graphics for graphical HIDDs).

HIDDA_SubType,ULONG,G
This is a more specific type. If HIDDA_Type is HIDDV_Type_Serial, then this is a bitfield with one or more bits of HIDDV_Type_Serial_RS232 or HIDDV_Type_Serial_RS488 set.

HIDDA_Producer,ULONG,G
The ID of the producer as handed out by Amiga International.

HIDDA_Name,STRPTR,G
The name of this device (eg. serial.device).

HIDDA_HardwareName,STRPTR,G
The name of the hardware (eg. "Builtin Serial Port", "COM1", "CyberVision/3D", etc.). Note that you must initialize some HIDDs before you can query this attribute because some HIDDs work with more than one type of hardware.

HIDDA_Active,BOOL,ISG
Tells if the device is active or (de-)activates it when set.

HIDDA_Status,ULONG,G
The current status of a HIDD. This is a set of bits which show if the init of the hardware was successful, if the device is active or if the device is ready to be activated.

HIDDA_ErrorCode,LONG,G
In case of an error, you can ask for the error code and use this code in HIDDM_ValueToString() to get a string with the meaning of the error. This is mostly used when the HIDD tells you that it doesn't like a certain tag in a taglist. When this happens, you can query this code to find out what the HIDD doesn't like about the tag.

Note that you can supply this tag when you try to create or change attributes of a HIDD. If you do this, you must still pass a pointer to LONG to NewObject() or SetAttrs(). In case of an error, it will be filled with the error code.

HIDDA_Locking,ULONG,G
Tells which kinds of locking the HIDD supports. Can be read from the class and from an existing HIDD. The possible values are:

HIDDV_Lock_None
No locking is supported. Note that some HIDDs have a kind of hidden locking: They can't be created more than once. The second attempt to create such a HIDD will just fail with the error HIDDV_Error_UniqueObject. Also note that this can also mean that no locking is necessary.

HIDDV_Lock_Shared
Shared and exclusive locking are supported (several tasks can access the HIDD simultanously). This doesn't mean that it makes sense when several tasks access the HIDD at the same time, only that it is possible.

HIDDV_Lock_Exclusive
Only one task can access the HIDD at any one time. Note that a HIDD which can't exist more than once should not use this kind of locking but just fail on the second attempt to create it.

6.5.2 Common tags for all HIDD CPs

HIDDA_HasOwnGUI,BOOL,G
Ask the HIDD CP if it has its own GUI for configuration.

HIDDA_ShowGUI,BOOL,ISG
Make the GUI of the HIDD CP visible or hide it or ask if it's visible right now. If you hide the GUI and dispose the HIDD CP, then the changes the user made will be lost.

HIDDA_UseScreen,struct Screen *,ISG
Tell the HIDD CP to open the GUI on this screen.

HIDDA_AppMsgPort,struct MsgPort *,ISG
When the HIDD CP has its own GUI, this GUI runs independent of the application. You can supply a message port to synchronise your application with the GUI of the HIDD CP. Some HIDD CPs will also use this to talk to the application.

6.5.3 Tags and methods for some HIDDs

IPTR HIDDM_Lock(ULONG mode)
Try to get access to the HIDD if you opened it in shared mode. The values for mode are HIDDV_Lock_Exclusive and HIDDV_Lock_Shared. You can add the flag HIDDV_Lock_Try. HIDDV_Lock_Exclusive means that you want the HIDD for your own. If someone else has a lock on the HIDD, this will block unless HIDDV_Lock_Try is set. HIDDV_Lock_Shared will only block if no exclusive locks exist and HIDDV_Lock_Try is not set.

If HIDDV_Lock_Try is not set, this will block until the HIDD can be locked as you wish.

The method will return FALSE if the lock could not be established. It will return something else if the lock could be established.

Note that some HIDDs don't support locking. Use HIDDM_Class_Get() to find out which do and which don't at runtime and read the documentation for the HIDDs.

void HIDDM_Unlock(IPTR lock)
Unlock the HIDD. lock must contain what you got back from HIDDM_Lock().


prev up next

If you have comments or suggestions, email me at digulla@aros.fh-konstanz.de. 24. Jul 1999