2 Copyright © 2013-2016, The AROS Development Team. All rights reserved.
6 #include <aros/debug.h>
9 #include <utility/hooks.h>
10 #include <utility/tagitem.h>
11 #include <proto/exec.h>
12 #include <proto/oop.h>
13 #include <proto/utility.h>
15 #include "hiddclass_intern.h"
17 /*****************************************************************************************
20 --background_hwclass--
26 This class is a base class for all hardware subsystems in AROS. Its
27 main purpose is to manage hardware drivers.
29 A "subsystem" is a kind of devices, e. g. keyboards, mice, etc. This
30 class stores information about existing device instances and can provide
31 this information to user's software.
33 A typical subsystem class should be a singletone. This greatly simplifies
36 *****************************************************************************************/
38 #define IS_HW_ATTR(attr, idx) ((idx = attr - HWAttrBase) < num_HW_Attrs)
40 /*****************************************************************************************
52 Query human-readable description of the class. E. g. "Keyboards".
64 *****************************************************************************************/
65 /*****************************************************************************************
77 Return TRUE if the subsystem is currently in use by some driver(s)
90 *****************************************************************************************/
92 OOP_Object
*HW__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
94 struct Library
*UtilityBase
= CSD(cl
)->cs_UtilityBase
;
96 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
99 struct HWData
*data
= OOP_INST_DATA(cl
, o
);
101 NEWLIST(&data
->drivers
);
102 InitSemaphore(&data
->driver_lock
);
104 data
->name
= (const char *)GetTagData(aHW_ClassName
,
105 (IPTR
)"Unknown hardware",
111 void HW__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
113 struct HWData
*data
= OOP_INST_DATA(cl
, o
);
116 if (IS_HW_ATTR(msg
->attrID
, idx
))
121 *msg
->storage
= (IPTR
)data
->name
;
125 *msg
->storage
= IsListEmpty(&data
->drivers
) ? FALSE
: TRUE
;
129 OOP_DoSuperMethod(cl
, o
, &msg
->mID
);
132 /*****************************************************************************************
138 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHW_AddHardwareDriver *Msg);
140 OOP_Object *HW_AddDriver(OOP_Object *obj, OOP_Class *driverClass,
141 struct TagItem *tags);
147 Creates a hardware driver object and registers it in the subsystem.
150 obj - A subsystem object to operate on.
151 driverClass - A pointer to OOP class of the driver. In order to create an object
152 of some previously registered public class, use
153 oop.library/OOP_FindClass().
154 tags - An optional taglist which will be passed to driver class' New() method.
157 A pointer to driver object or NULL in case of failure.
160 Do not dispose the returned object yourself, use HW_RemoveDriver() for it.
167 moHW_RemHardwareDriver
171 *****************************************************************************************/
173 OOP_Object
*HW__HW__AddDriver(OOP_Class
*cl
, OOP_Object
*o
,
174 struct pHW_AddDriver
*msg
)
176 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
177 struct HWData
*data
= OOP_INST_DATA(cl
, o
);
178 OOP_Object
*drv
= NULL
;
179 struct DriverNode
*dn
;
181 D(bug("[HW] Adding Driver class 0x%p\n", msg
->driverClass
));
183 if (msg
->driverClass
!= NULL
)
185 // Get some extra memory for driver node
186 dn
= AllocPooled(CSD(cl
)->MemPool
, sizeof(struct DriverNode
));
189 drv
= OOP_NewObject(msg
->driverClass
, NULL
, msg
->tags
);
193 FreePooled(CSD(cl
)->MemPool
, dn
, sizeof(struct DriverNode
));
194 D(bug("[HW] Driver did not initialize\n"));
198 if (HW_SetUpDriver(o
, drv
))
200 /* Add the driver to the end of drivers list */
201 dn
->driverObject
= drv
;
202 ObtainSemaphore(&data
->driver_lock
);
203 ADDTAIL(&data
->drivers
, dn
);
204 ReleaseSemaphore(&data
->driver_lock
);
209 OOP_DisposeObject(drv
);
215 /*****************************************************************************************
221 void OOP_DoMethod(OOP_Object *obj, struct pHW_RemoveDriver *Msg);
223 void HW_RemoveDriver(OOP_Object *obj, OOP_Object *driver);
229 Unregisters and disposes hardware driver object.
232 obj - A subsystem object from which the driver should be removed.
233 driver - A pointer to a driver object, returned by HW_AddDriver().
236 TRUE if removal successful or FALSE upon failure.
239 The base class returns FALSE only if the driver is not registered
240 in the subsystem. However, subclasses implementing actual subsystems
241 can add their own checks, for example whether the driver currently
242 owns some objects which are in use, and thus cannot be disposed.
253 *****************************************************************************************/
255 BOOL
HW__HW__RemoveDriver(OOP_Class
*cl
, OOP_Object
*o
,
256 struct pHW_RemoveDriver
*msg
)
258 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
259 struct HWData
*data
= OOP_INST_DATA(cl
, o
);
260 struct DriverNode
*dn
= NULL
, *next
= NULL
, *rem
= NULL
;
262 D(bug("[HW] Removing hardware driver %p\n", msg
->driverObject
));
264 /* Get exclusive lock on driver list */
265 ObtainSemaphore(&data
->driver_lock
);
266 ForeachNodeSafe(&data
->drivers
, dn
, next
)
268 if (dn
->driverObject
== msg
->driverObject
)
270 Remove((struct Node
*)dn
);
274 ReleaseSemaphore(&data
->driver_lock
);
276 /* If driver removed, rem contains pointer to removed DriverNode */
279 HW_CleanUpDriver(o
, rem
->driverObject
);
282 OOP_DisposeObject(rem
->driverObject
);
283 /* And free memory for DriverNode */
284 FreePooled(CSD(cl
)->MemPool
, rem
, sizeof(struct DriverNode
));
287 D(bug("[HW] Mgr::RemHardwareDriver() %s\n", rem
? "succeeded" : "failed"));
289 return rem
? TRUE
: FALSE
;
292 /*****************************************************************************************
298 void OOP_DoMethod(OOP_Object *obj, struct pHW_EnumDrivers *Msg);
300 void HW_EnumDrivers(OOP_Object *obj, struct Hook *callback, APTR hookMsg);
306 Enumerates all installed driver in the subsystem.
309 obj - A subsystem object to query.
310 callback - A user-supplied hook which will be called for every driver.
311 hookMsg - A user-defined data to be passed to the hook.
313 The hook will be called with the following parameters:
314 AROS_UFHA(struct Hook *, hook , A0)
315 - A pointer to hook structure itself
316 AROS_UFHA(OOP_Object * , driverObject, A2)
317 - A device driver object
318 AROS_UFHA(APTR , message , A1)
321 The hook should return FALSE in order to continue enumeration
322 or TRUE in order to stop it.
336 The function uses internal semaphore locking. Because of this,
337 it is illegal to attempt to add or remove drivers within the hook.
339 *****************************************************************************************/
341 void HW__HW__EnumDrivers(OOP_Class
*cl
, OOP_Object
*o
, struct pHW_EnumDrivers
*msg
)
343 struct HWData
*data
= OOP_INST_DATA(cl
, o
);
344 struct DriverNode
*dn
;
346 /* Lock driver list for shared use */
347 ObtainSemaphoreShared(&data
->driver_lock
);
349 /* For every driver in the system... */
350 ForeachNode(&data
->drivers
, dn
)
353 * Explicit cast to BOOL makes it possible to declare the hook as
354 * returning BOOL, not IPTR. BOOL is 16-bit wide, so higher bits
355 * of result may carry random trash.
357 BOOL stop
= CALLHOOKPKT(msg
->callback
, dn
->driverObject
, msg
->hookMsg
);
363 ReleaseSemaphore(&data
->driver_lock
);
366 /*****************************************************************************************
372 void OOP_DoMethod(OOP_Object *obj, struct pHW_SetUpDriver *Msg);
374 void HW_SetUpDriver(OOP_Object *obj, OOP_Object *driverObject);
380 Performs subsystem-specific setup after driver object creation.
381 This method is intended to be used only by subclasses of CLID_HW.
384 obj - A subsystem object.
385 driverObject - Device driver object.
388 TRUE if setup completed successfully and FALSE in case of error.
389 If this method returns error, the driver object will be disposed
390 and moHW_AddDriver method will fail.
393 In base class this method does nothing and always returns TRUE.
404 *****************************************************************************************/
406 BOOL
HW__HW__SetUpDriver(OOP_Class
*cl
, OOP_Object
*o
, struct pHW_SetUpDriver
*msg
)
408 /* By default we have nothing to do here */
412 /*****************************************************************************************
418 void OOP_DoMethod(OOP_Object *obj, struct pHW_CleanUpDriver *Msg);
420 void HW_CleanUpDriver(OOP_Object *obj, OOP_Object *driverObject);
426 Performs subsystem-specific cleanup before driver object disposal.
427 This method is intended to be used only by subclasses of CLID_HW.
430 obj - A subsystem object.
431 driverObject - Device driver object.
437 In base class this method does nothing.
448 *****************************************************************************************/
450 void HW__HW__CleanUpDriver(OOP_Class
*cl
, OOP_Object
*o
, struct pHW_CleanUpDriver
*msg
)
452 /* By default we have nothing to do here */