--- Cannot embed stylesheet: [Errno 2] No such file or directory: '../../../aros.css' --->
void psdAbortPipe(
struct PsdPipe * pp );
Request cancellation of an outstanding pipe transfer.
pp - Valid pipe with a possible pending transfer.
The function has no effect unless the pipe message is pending. When pending, it allocates a temporary pipe-like request referring to the original pipe, sends it to the hardware task, waits for the cancellation request to complete and releases the temporary object. It does not wait for or remove the original pipe's completion reply. Call psdWaitPipe() before reusing or releasing the original pipe.
If allocation of the temporary cancellation request fails, no cancellation request is sent and the caller receives no error.
struct PsdIFFContext * psdAddCfgEntry(
struct PsdIFFContext * pic,
APTR formdata );
Add an IFF FORM or data chunk to an existing configuration context.
pic - Parent context, or NULL for the configuration root. formdata - Valid serialized IFF FORM or chunk to incorporate.
Resulting configuration context from the internal addition routine, or NULL on failure.
Takes the configuration write lock, delegates parsing and insertion to pAddCfgChunk(), and marks configuration for checking. Form and chunk replacement rules are those of the internal IFF context implementation, not those of a general-purpose IFF parser.
struct PsdUsbClass * psdAddClass(
STRPTR name,
ULONG vers );
Open a USB class library and register it with Poseidon.
name - Valid class library name or pathname. vers - Minimum version passed to OpenLibrary().
Registered class record, or NULL if the library cannot be opened, is already registered, or record allocation fails.
Attempts the supplied path and progressively shorter path components when opening the library. Rejects duplicate class names. On success, reads class attributes, adds the class to the priority-ordered list and emits EHMB_ADDCLASS. Call psdRemClass() to unregister the class.
struct PsdErrorMsg * psdAddErrorMsgA(
UWORD level,
STRPTR origin,
STRPTR fmtstr,
RAWARG fmtdata );
struct PsdErrorMsg * psdAddErrorMsg(
UWORD level,
STRPTR origin,
STRPTR fmtstr,
... );
Append a formatted diagnostic message to Poseidon's error log.
level - Severity compared with the current logging preferences. origin - Valid source name copied into the error record. fmtstr - RawDoFmt() format string. fmtdata - Matching RawDoFmt() argument stream.
New error-message record, or NULL if logging at this severity is disabled or a required allocation fails.
Applies the configured info, warning, error and failure filters before allocating or formatting a message. Depending on stack flags, the text can also be sent to the kernel log. The record becomes part of the Poseidon message list; callers must not free its fields independently.
APTR psdAddEventHandler( struct MsgPort *mp, ULONG msgmask)
Subscribe a message port to Poseidon events.
mp - Live message port dedicated to this registration.
msgmask - Bitwise OR of EHMF_* masks from <libraries/poseidon.h>.
Zero registers a handler that receives no events.
An opaque registration handle, or NULL for a NULL port or allocation failure. Remove a successful registration with psdRemEventHandler().
Call in task context; registration may wait for a semaphore. The port is retained, not copied or owned. Keep it alive until removal completes and coordinate removal with the receiving task. Each notification is a PsdEventNote message. Read ENA_EventID, ENA_Param1 and ENA_Param2 with psdGetAttrsA(PGA_EVENTNOTE, ...), then ReplyMsg() exactly once. Do not free the message or use it after reply. Parameter pointers do not pin their objects; removal notifications can refer to objects that are no longer safe to dereference. There is no initial state snapshot. Allocation failure can silently drop individual notifications; use events as change notifications, not as a guaranteed transaction log.
struct PsdHardware * psdAddHardware(
STRPTR name,
ULONG unit );
Open a USB controller and register it with the Poseidon stack.
name - Controller device name used for OpenDevice(). unit - Controller device unit number.
Initialized controller handle, or NULL if allocation, startup or controller initialization fails.
Allocates controller state and a dedicated device task, and waits for its initialization signal. Successful registration emits EHMB_ADDHARDWARE. Attached USB devices are not enumerated by this call; use psdEnumerateHardware() afterwards. The returned state belongs to the stack and is released by psdRemHardware().
BOOL psdAddStringChunk( APTR pic, ULONG chunkid, CONST_STRPTR contents)
Store a string chunk in a configuration form.
pic - Valid, non-NULL form handle.
chunkid - Numeric chunk identifier in host byte order; must not be FORM.
contents - Non-NULL, NUL-terminated string. Keep it valid until return.
Its length and allocation overhead must fit in ULONG.
TRUE if the string was stored; FALSE if allocation fails. Failure while expanding the form buffer can leave the previous chunk removed.
Copies the string, including its terminator, into the form. Replaces the first existing chunk with the same identifier. The source is not retained. Uses the configuration write lock and may wait; call in task context. Coordinate form lifetime separately. Does not save preferences, apply configuration or set the configuration recheck request. Use the appropriate configuration operation afterward.
Replacement removes the old chunk before securing expansion memory. Input sizes and the reserved FORM identifier are not validated.
APTR psdAllocCfgForm( ULONG formid)
Allocate an empty, detached configuration form.
formid - Numeric four-character form identifier in host byte order.
An opaque form handle, or NULL if allocation fails.
The form starts with no chunks or child forms and with a four-byte payload for its type identifier. It is tracked separately from the active configuration tree. Allocation alone neither installs configuration nor saves it to disk. Release the form and its contents with psdRemCfgForm(); do not free the handle with psdFreeVec(). Coordinate its lifetime with all users.
struct PsdDevice * psdAllocDevice(
struct PsdHardware * phw );
Allocate and register a device record under a USB controller.
phw - Valid controller owning the new device record.
Initialized device record, or NULL on allocation failure.
Initializes device locks, descriptor/configuration lists, real-time isochronous-handler list, and default device options. Inserts the record into the controller's device list under the Poseidon base write lock. The record is not enumerated or assigned an address by this call.
struct PsdPipe * psdAllocPipe(
struct PsdDevice * pd,
struct MsgPort * mp,
struct PsdEndpoint * pep );
Allocate a transfer pipe for a USB device endpoint or endpoint zero.
pd - Valid Poseidon device with an initialized hardware controller. mp - Message port receiving completed transfers; must not be NULL. pep - Endpoint to address, or NULL for the default control endpoint.
Allocated pipe, or NULL on invalid input, allocation failure, unsupported transfer type or controller capability, or failed endpoint preparation. Release it with psdFreePipe().
The IO request inherits the hardware-controller request template. The function sets device address, endpoint parameters, speed flags, root-port routing and, where required, split-transaction details. Isochronous endpoints require UHCF_ISO. A successful allocation increments the device use count. The caller must retain a valid message port for pending transfers and must not reuse a pending pipe.
APTR psdAllocRTIsoHandlerA( APTR pep, struct TagItem *taglist)
Register a real-time isochronous endpoint handler with its controller.
pep - Live isochronous endpoint. NULL is rejected. taglist - RTA_* attributes, or NULL for defaults.
RTA_InRequestHook, RTA_OutRequestHook - Buffer request hooks for
input or output, using struct IOUsbHWBufferReq.
RTA_InDoneHook, RTA_OutDoneHook - Buffer completion hooks.
RTA_ReleaseHook - Device-removal notification hook, called with the
handler as object and NULL as message.
RTA_OutPrefetchSize - Maximum output prefetch in bytes; default 2048.
A registered handler, or NULL if the endpoint is unsuitable, the controller lacks UHCF_RT_ISO, allocation fails or registration fails. Allocation does not start transfers. Release with psdFreeRTIsoHandler().
Call in task context and coordinate endpoint lifetime. Hook pointers are retained, not copied; keep hook structures, code and associated state valid until the controller no longer uses them. The tag list itself is not retained. No hook is installed by default. Data hooks follow <devices/usbhardware.h>. They may run with interrupts disabled; do not wait, perform DOS I/O or call these lifecycle functions from a data hook. The callback object is controller-private, not the Poseidon handler. Request buffers and completion semantics must satisfy the selected controller; do not release buffers while it can use them. The release hook runs during device removal with the device write lock held. Arrange cleanup without waiting for a task that needs that lock. Registration uses synchronous controller I/O with no reply port and requires quick completion support; there is no library-level timeout.
The endpoint ownership chain is dereferenced without separate validation. Controller quick-I/O support is required by the synchronous calls but is not independently verified here.
APTR psdAllocVec(
ULONG size );
Allocate an aligned block from the Poseidon memory pool.
size - Requested number of usable bytes.
Allocated block aligned to AROS_WORSTALIGN, or NULL on pool allocation failure. Release it with psdFreeVec().
An allocation header immediately preceding the returned pointer records the original pool pointer and requested size. Successful allocations increase the library's allocated-byte counter by size. MEMDEBUG builds reserve an additional 1024-byte overrun area. The requested allocation is not explicitly zero-initialized here.
The calculation adding the header, alignment padding and optional debugging area does not check for ULONG overflow.
ULONG psdBorrowLocksWait( struct Task *task, ULONG signals)
Temporarily lend the caller's registered Poseidon locks to another task while waiting for signals, then reclaim them.
task - Valid, non-NULL cooperating task distinct from the caller.
Keep it alive throughout the wait and lock reclamation.
signals - Exec signal mask for completion. The caller must arrange for
the cooperating operation to signal it.
The signal mask returned by Wait(signals), after lock reclamation. This is not a lock-transfer status or a count of transferred locks.
Used when a cooperating task must access Poseidon state protected by locks held by the caller. Only locks registered with Poseidon's lock implementation participate; ordinary Exec semaphores are unaffected. With no caller-held registered locks, behaves as Wait(signals). The cooperating task must balance its own lock acquisitions and must not consume the caller's borrowed lock counts. Keep all participating lock objects alive until reclamation finishes. Do not use this operation as permission to destroy or replace protected objects. Transfers or temporarily releases exclusive and shared ownership, including recursive counts. A waiting recipient can be moved to the front of a wait queue and its shared request promoted to exclusive. After receiving a signal, restores ownership directly where possible and otherwise reacquires the saved lock counts. Reclamation can block after the requested signal arrives. There is no timeout or cancellation result. A completion signal should represent a point at which the cooperating operation can release its locks.
The recipient task is dereferenced without NULL validation. Transfer bookkeeping allocation can fail without an error result. Some locks can remain with the caller while others have been lent; waiting can then deadlock. Queue reordering or promotion can precede the failed allocation. This function does not guarantee deadlock avoidance or an all-or-nothing transfer.
VOID psdCalculatePower( APTR phw)
Recalculate the stored power estimates for a hardware device tree.
phw - Valid, non-NULL hardware handle. Keep the hardware and its
device topology alive and stable until return.
None. Read device estimates through DA_PowerSupply and DA_PowerDrained.
Visits every root device of this hardware and recursively updates supply and drain estimates in milliamperes. Uses current configurations, self-powered status, power overrides and the suspended flag. The model starts roots at 500 mA, allows 500 mA per downstream connection from self-powered devices, and caps downstream supply from bus-powered devices at 100 mA after accounting for their own demand. Suspended configured devices use a 1 or 3 mA drain estimate. A newly detected deficit sets the low-power flag, logs a warning and sends EHMB_DEVICELOWPW. A resolved deficit clears the flag and logs a message; it does not send a matching recovery event. May wait for the base read lock and perform logging and event allocation. It does not measure current, negotiate power, switch ports or reject configurations. Coordinate concurrent configuration and power-state changes; the read lock does not serialize these stored-value updates.
A NULL hardware pointer is dereferenced without validation. The fixed 500/100 mA model is not a speed-specific USB power budget. Suspended devices stop drain recursion, so descendants can retain old drain values. Self-powered devices report zero upstream drain. Treat these values as implementation estimates, not electrical guarantees.
APTR psdCheckPipe( APTR pp)
Test whether a pipe is marked as pending.
pp - Valid, non-NULL pipe handle.
NULL while the pipe message has type NT_MESSAGE; otherwise pp. A non-NULL result does not mean that the transfer succeeded, and an idle pipe need not have completed a transfer at all.
Does not wait, remove a reply message or inspect transfer status. Use psdWaitPipe() for the normal completion path and inspect its result and the actual byte count before reusing transfer data. Serialize submission, completion and freeing of the pipe with this check. The returned handle is the original pipe, not a new allocation.
The implementation dereferences pp without checking for NULL.
struct PsdAppBinding * psdClaimAppBindingA(
struct TagItem * tags );
struct PsdAppBinding * psdClaimAppBinding(
TAG tag, ... );
Claim a USB device for an application, bypassing normal class ownership where the hub accepts the request.
tags - ABA_* binding attributes, including ABA_Device and
ABA_ReleaseHook; both are required.
Application-binding handle, or NULL if required attributes are absent or the hub declines the claim.
ABA_ForceRelease requests release of existing class bindings before attempting the claim. Root-hub claims are handled locally; downstream devices delegate through the parent hub's class method. On success the binding records the current task and an EHMB_ADDBINDING event is sent. The supplied release hook is called during release; the handle must not be used after that callback.
void psdClassScan();
Ask USB class drivers to bind devices found by Poseidon.
On the first process-driven scan after early task-based startup, releases provisional boot-class bindings before selecting normal drivers. Takes the base read lock and scans root devices through psdHubClassScan(); downstream hub tasks handle their own devices. If no class is registered, reports a warning and returns. No binding count or completion status is returned.
VOID psdCloseStream( APTR pps)
Flush a stream, stop its pipes and release its storage.
pps - Live stream returned by psdOpenStreamA(), or NULL.
NULL is ignored. Call in task context after excluding other users. Flushes first, then aborts, waits for and frees each pipe. Releases internal buffers and an internally created message port. A supplied port and terminator table remain caller-owned. The handle is invalid after return. Close can wait for controller completion. For output, explicitly flush and inspect the result before closing when delivery matters. Close returns no status and ignores flush failure. For input, unread data is discarded.
Cleanup assumes the configured pipe array and port are usable. Partially initialized streams can violate that assumption.
STRPTR psdCopyStr(
CONST_STRPTR name );
Allocate a copy of a NUL-terminated string in Poseidon memory.
name - Valid NUL-terminated string; must not be NULL.
Newly allocated copy or NULL if allocation fails. Release the returned string with psdFreeVec().
The function allocates strlen(name) plus one byte through psdAllocVec() and copies the string with strcpy(). It does not validate the source pointer or bound its length.
STRPTR psdCopyStrFmtA( CONST_STRPTR fmtstr, RAWARG fmtdata)
Allocate a string formatted with Exec RawDoFmt().
fmtstr - Non-NULL RawDoFmt format string.
fmtdata - Argument stream in the format required by RawDoFmt(),
matching fmtstr. Referenced strings must remain valid and unchanged
throughout both formatting passes.
A NUL-terminated allocated string, or NULL on allocation failure. Release the result with psdFreeVec().
Formats once to count output characters and again to fill the buffer. The format and argument data are borrowed and are not retained. RawDoFmt conventions apply, including argument widths and string representations; this is not a printf argument list. The character count, terminator and allocator overhead must fit in ULONG. Count overflow and NULL input pointers are not checked.
VOID psdDebugSemaphores( )
Log the registered Poseidon semaphore owners, readers and waiters.
None. Output is added to the Poseidon message log.
Reports the calling task, then each registered semaphore's name, exclusive and shared counts, owner, waiting tasks and shared-lock counts. It does not acquire, release or repair the reported locks. Messages use informational severity and are suppressed when information logging is disabled. Allocation failure can omit individual messages; there is no complete-output indication. Only registered Poseidon locks are visited, not arbitrary Exec semaphores. Use from task context. Traversal uses Forbid()/Permit(), while logging can allocate memory and perform other system calls. The output is a diagnostic view, not a guaranteed atomic snapshot or a deadlock verdict.
void psdDelayMS(
ULONG milli );
Perform a synchronous delay through Poseidon's timer device.
milli - Requested delay in milliseconds.
The function initializes a private message port using the current task's SIGB_SINGLE signal, copies the library's timer request, sets its time to milli * 1000 microseconds and calls DoIO(). It does not expose a timer error or signal-interruption result.
The multiplication by 1000 has no explicit overflow check. The requested duration is not normalized into seconds here.
IPTR psdDoHubMethodA( APTR pd, ULONG methodid, IPTR *methoddata)
Dispatch a method to the class bound to a device's parent hub.
pd - Device used to select the parent hub class, or NULL. Keep the
device, parent hub and class binding alive until return.
methodid - Method identifier understood by that class.
methoddata - Array of IPTR arguments in the layout required by the
method. Keep the array and referenced objects valid until return
and for any longer lifetime required by that method.
The method result, subject to the return-width defect below. Returns zero without dispatch if pd is NULL, has no parent hub, or the parent has no device binding or class binding. Zero is also a possible method result and does not distinguish these cases.
The argument array is passed unchanged. This function does not insert
the parent hub binding or validate the method identifier, argument count,
argument pointers or target port. The routing device and the objects in
the argument array have distinct roles.
For UCM_HubPowerCyclePort and UCM_HubDisablePort, the supplied hub.class
expects { hub device, one-based port number }. For UCM_HubClassScan it
expects { hub binding }; for UCM_HubClaimAppBinding,
{ hub binding, tag list }; for UCM_HubReleaseIfBinding,
{ hub binding, interface }; and for UCM_HubReleaseDevBinding,
UCM_HubSuspendDevice and UCM_HubResumeDevice, { hub binding, device }.
Takes no device or base lock. The caller must coordinate topology and
binding changes. The class method may block. For the supplied hub.class,
claim, release, suspend and resume requests can wait for its task to
reply. Power-cycle, disable-port and class-scan methods schedule work;
their return does not establish completion of that work.
Prefer the dedicated binding and power-state APIs when they provide the
requested operation; they perform additional bookkeeping and callbacks.
The public result type is IPTR, but this implementation returns LONG. On targets with pointers wider than 32 bits, pointer-valued and other wide results cannot be relied on. In particular, do not obtain an application-binding handle through this dispatcher on such targets; use psdClaimAppBindingA(). The source also uses APTR for methoddata; the public array layout remains IPTR elements.
LONG psdDoPipe(
struct PsdPipe * pp,
APTR data,
ULONG len );
Submit a pipe transfer and wait for its completion.
pp - Allocated pipe that is not already pending. data - Transfer buffer, or NULL for a control request without data. len - Number of bytes to transfer.
IO error code returned by psdWaitPipe() after the transfer, or UHIOERR_TIMEOUT if the device is disconnected. Zero indicates successful completion.
For a connected device, the function requests resume if suspended, sets the data pointer, transfer length and stream ID, and sets the control-request wLength when using endpoint zero. It queues the pipe to the hardware task, updates the device busy count and last activity, then waits for a reply. A disconnected device instead delays for 50 ms, clears the actual length and returns a timeout. The call may block while the transfer is pending.
struct PsdDevice * psdEnumerateDevice(
struct PsdPipe * pp );
Assign and query USB device state through an enumeration pipe.
pp - Valid default-control pipe for a device being enumerated.
Device associated with the pipe, or NULL on an earlier enumeration failure. A non-NULL result does not guarantee that configuration descriptors were read successfully or that a configuration was set.
The procedure acquires the device write lock, performs USB requests to determine speed, address, descriptors and available configurations, and updates the device's parsed state. It saves the pipe flags and NAK timeout and restores them on completion. On the address-assigned failure path, it clears the temporary address and connected flags before returning NULL. Failure to parse configurations is logged but returns the device pointer. The call may block on USB transfers and does not establish a class binding.
struct PsdDevice * psdEnumerateHardware(
struct PsdHardware * phw );
Enumerate the root USB device or root hubs of a registered controller.
phw - Initialized controller handle returned by psdAddHardware().
Root device established by the enumeration procedure, or NULL if no root device can be configured.
Uses a temporary message port and control pipe to reset and probe the controller's root topology. The implementation includes separate USB 2 and SuperSpeed root-hub handling where supported. Unusable probe resources are released along failure paths. The caller can run psdClassScan() after root enumeration to establish suitable class bindings.
struct PsdIFFContext * psdFindCfgForm(
struct PsdIFFContext * pic,
ULONG formid );
Find the first child IFF FORM of a given identifier.
pic - Parent context, or NULL for the configuration root. formid - Identifier of the required child form.
Matching internal IFF context, or NULL if none exists.
The search is restricted to immediate child forms. The function takes and releases the shared configuration lock internally, but the returned context is not copied and may become stale after a concurrent modification. Use psdNextCfgForm() for further matches.
APTR psdFindDescriptorA( APTR pd, APTR pdd, struct TagItem *taglist)
Find the next stored descriptor matching all supplied filters.
pd - Valid device handle.
pdd - NULL to start; otherwise a previous descriptor from this device.
Searching resumes after it.
taglist - Filter list, or NULL for default configuration filtering.
DDA_Config - Configuration handle to match. NULL accepts every
configuration. If omitted, matches the current configuration.
DDA_Interface, DDA_Endpoint - Exact association-pointer matches.
NULL matches an unassociated descriptor, not every association.
DDA_DescriptorType, DDA_CS_SubType, DDA_DescriptorLength - Exact
matches against stored descriptor attributes.
A borrowed descriptor handle, or NULL if no further match is found.
Searches the device's stored descriptor list without issuing USB requests. Unknown tags are ignored. With no current configuration, the default matches descriptors whose configuration pointer is NULL. No lock is taken. Keep the device, cursor and returned objects alive and exclude concurrent list changes. Do not free the result. The tag list is not retained.
DDA_Device, DDA_Name and DDA_DescriptorData are declared but not interpreted as search filters. A NULL device and a foreign continuation descriptor are not validated.
struct PsdDevice * psdFindDeviceA(
struct PsdDevice * pd,
struct TagItem * tags );
struct PsdDevice * psdFindDevice(
struct PsdDevice * pd,
TAG tag, ... );
Find the next device satisfying all supplied search attributes.
pd - Previous device, or NULL to begin at the first device. tags - Matching criteria expressed as DA_* search tags.
First subsequent matching device, or NULL at the end of traversal.
Traverses the same controller/device lists as psdGetNextDevice(). Only search tags handled by this implementation constrain a match; unrecognized tags are ignored. The function takes no base lock; callers requiring a stable result must hold psdLockReadPBase() during traversal.
APTR psdFindEndpointA( APTR pif, APTR pep, struct TagItem *taglist)
Find the next endpoint matching all supplied filters.
pif - Valid interface handle.
pep - NULL to start at the first endpoint; otherwise a previous result
belonging to pif. Searching resumes after that endpoint.
taglist - Filter list, or NULL for no filters.
EA_IsIn - Nonzero for IN, zero for OUT.
EA_EndpointNum, EA_TransferType, EA_MaxPktSize, EA_Interval,
EA_MaxBurst, EA_CompAttributes, EA_BytesPerInterval - Exact matches
against the corresponding stored endpoint attributes.
A borrowed endpoint handle, or NULL if no further endpoint matches.
Searches only this interface's endpoint list. Does not allocate an endpoint, issue USB requests or retain the tag list. Unknown tags are ignored. No lock is taken: keep the interface, cursor and returned object alive and exclude concurrent list changes while traversing. Do not free the result.
EA_Interface, EA_SyncType, EA_UsageType and EA_MaxStreams are declared but are not supported as search filters. A NULL interface and an unrelated continuation cursor are unchecked.
APTR psdFindInterfaceA( APTR pd, APTR pif, struct TagItem *taglist)
Find the next interface matching all supplied filters.
pd - Valid device handle. A fresh search uses its current configuration. pif - NULL to start; otherwise a previous result for this device. taglist - Filter list, or NULL for no filters.
IFA_InterfaceNum, IFA_NumEndpoints, IFA_Class, IFA_SubClass,
IFA_Protocol - Exact matches against stored attributes.
IFA_AlternateNum - Enables alternate-interface searching. Values
through 255 also select that alternate number; larger values
accept any alternate number.
IFA_Binding - Exact binding-pointer match, including NULL.
IFA_InterfaceName, IFA_IDString - Case-sensitive string matches.
Supply valid strings; the corresponding stored string must exist.
A borrowed interface handle, or NULL if no further match is found or a fresh search has no current configuration.
Without IFA_AlternateNum, fresh searches visit main interfaces only. With it, each main interface is followed by its alternates. Resuming from an alternate also enables alternate traversal. Unknown tags are ignored. This call does not select an alternate or issue USB requests. No lock is taken. Keep device, configuration, cursor and results alive and exclude concurrent topology changes while traversing. The result is owned by Poseidon; do not free it. Tag data is not retained.
Resuming after the last alternate can return NULL before visiting later main interfaces. Name filters pass stored pointers to strcmp() without checking for NULL. Other declared interface filters, including IFA_Config and IFA_BindingClass, are not handled.
void psdFreeDevice(
struct PsdDevice * pd );
Remove a device from active enumeration and begin its teardown.
pd - Valid device to retire; NULL is not accepted.
Moves the device to its controller's dead-device list, notifies registered real-time isochronous release hooks, and releases device and interface bindings under the device lock. The internal release routine may defer final reclamation while pipe references remain. Callers must not use the device as an active device after this call.
void psdFreePipe(
struct PsdPipe * pp );
Release a pipe and its associated device reference.
pp - Pipe returned by psdAllocPipe(); NULL has no effect.
When the pipe message is still pending, this function requests an abort and waits for the reply before freeing the pipe. It then tears down the endpoint hardware state, decrements the device use count and frees the pipe. If this was the last reference to a device marked for deferred expunge, the device is also released. The pipe becomes invalid on return. Waiting for a pending transfer may block; the function returns no abort or completion status.
VOID psdFreeRTIsoHandler( APTR prt)
Remove a real-time isochronous handler and free its library storage.
prt - Live handler returned by psdAllocRTIsoHandlerA(), or NULL.
NULL is ignored. Call in task context. Stop a running handler first and serialize this call with all operations using it. Removes the handler from the device list, asks the controller to remove it, then frees its pipe and storage. The handle is invalid after return. Does not stop an active handler, call the release hook or balance a successful start itself. This call has no library-level timeout.
The controller removal result is ignored. Storage is freed even if removal fails, so return does not independently prove that callbacks or controller references have been quiesced.
void psdFreeVec(
APTR pmem );
Release a block allocated by psdAllocVec().
pmem - Block returned by psdAllocVec(), or NULL for no action.
The allocator header immediately before the block supplies the original pooled allocation pointer and the requested byte count. The function decreases the library's allocated-byte counter and frees the original pool block using its original total allocation size, including alignment storage and optional MEMDEBUG space. The pointer becomes invalid on return; non-Poseidon pointers are not accepted.
LONG psdGetAttrsA(
ULONG type,
APTR psdstruct,
struct TagItem * tags );
LONG psdGetAttrs(
ULONG type,
APTR psdstruct,
TAG tag, ... );
Read supported attributes from a Poseidon object or stack state.
type - PGA_* object category selecting the attribute table.
psdstruct - Object of the selected category; PGA_STACK uses the
library's own base state.
tags - Tag list identifying attributes and writable result
addresses; result addresses must be valid.
Number of recognized attributes read, or -1 when the category has no pack table.
Explicit attributes are handled by the selected category's special cases; remaining attributes are read with UnpackStructureTags(). Returned pointers refer to live Poseidon structures and must not be freed or retained beyond their valid lifetime. See libraries/poseidon.h for supported tag identifiers.
APTR psdGetCfgChunk(
struct PsdIFFContext * pic,
ULONG chnkid );
Copy a serialized IFF chunk out of a configuration context.
pic - Context, or NULL for the configuration root. chnkid - Identifier of the requested chunk.
Allocated copy of the full chunk including its IFF header, or NULL if the chunk is absent or allocation fails. Free with psdFreeVec().
Searches under the shared configuration lock and copies the stored chunk into independent memory. Root-context lookup may refresh stored global configuration chunks before reading, so this operation is not strictly read-only. The IFF size field describes payload size; the copy also includes the eight-byte chunk header.
struct PsdIFFContext * psdGetClsCfg(
STRPTR owner );
Find the stored configuration context for a class owner.
owner - Valid class or owner identifier string.
Internal CLASSDATA context for the matching owner, or NULL if none is present.
The returned pointer refers to live configuration storage, not a serialized IFF buffer. It is not caller-owned and should not outlive changes that remove or replace its containing form.
STRPTR psdGetForcedBinding( STRPTR devid, STRPTR ifid)
Look up the configured forced class binding for a device or interface.
devid - Non-NULL, NUL-terminated device ID string.
ifid - NUL-terminated interface ID string, or NULL for a device binding.
Both strings must remain valid until return.
A borrowed pointer to the stored class name, or NULL if no matching binding is found. Do not modify or free the returned string.
May wait for the configuration read lock. Searches only the first matching device form. An interface lookup does not fall back to the device binding. The result describes configuration, not a live binding or proof that the named class is available. The read lock is released before return. Configuration replacement, removal, or buffer reallocation can invalidate the pointer. Exclude concurrent configuration mutation for the lookup and the entire use of the result; copy it while that exclusion remains in effect if a longer-lived value is required.
struct PsdDevice * psdGetNextDevice(
struct PsdDevice * pd );
Return the next device in Poseidon's controller/device lists.
pd - Previous device, or NULL to start with the first controller.
Next device pointer, or NULL when no further device is found.
The function first examines the next node in the current controller's device list. When that list is exhausted, it visits subsequent controllers. With NULL input, it starts at the first controller. It takes no lock; callers must keep the relevant lists stable for the traversal and must not retain a returned pointer beyond the device's valid lifetime.
ULONG psdGetPipeActual(
struct PsdPipe * pp );
Read the actual byte count recorded for a pipe transfer.
pp - Valid Poseidon pipe; NULL is not accepted.
Value of the pipe request's iouh_Actual field.
The function does not wait for completion or validate the pipe state. Read the count after handling the transfer completion.
LONG psdGetPipeError(
struct PsdPipe * pp );
Read the IO error recorded for a pipe transfer.
pp - Valid Poseidon pipe; NULL is not accepted.
The pipe request's io_Error value, cast to LONG. Zero indicates no recorded error.
The function does not wait for completion or validate the pipe state. Read the error after handling an asynchronous completion.
LONG psdGetStreamError( APTR pps)
Return a stream's stored error value.
pps - Live stream, or NULL.
The stored error value, or -1 for NULL. Zero means no error is stored; it does not prove transfer completion or successful delivery.
Does not wait, collect pipe replies, clear the error or acquire the stream semaphore. Read, write and flush reset the value on entry and then record selected errors. Query immediately after the operation under the caller's serialization policy; another operation or an explicit PSA_Error update can replace it.
STRPTR psdGetStringChunk( APTR pic, ULONG chunkid)
Copy the first matching configuration chunk into a string buffer.
pic - Valid, non-NULL form handle. chunkid - Numeric chunk identifier in host byte order.
An allocated copy of the chunk payload, followed by a zero byte. Returns NULL if the chunk is absent or allocation fails. Release the result with psdFreeVec(). An empty stored string returns a non-NULL empty string when allocation succeeds.
Copies the declared payload length, including any embedded NULs. The extra zero byte comes from the cleared allocation. The result remains valid after the form changes or is removed. Uses the configuration read lock and may wait; call in task context. Coordinate form lifetime separately. The form must contain structurally valid chunks; this operation does not validate imported IFF data.
STRPTR psdGetStringDescriptor(
struct PsdPipe * pp,
UWORD idx );
Read a USB string descriptor and convert it to a C string.
pp - Valid device control pipe. idx - USB string-descriptor index to request.
Newly allocated NUL-terminated string, or NULL when a required descriptor request or allocation fails. Release it with psdFreeVec() unless ownership has been transferred explicitly.
The first request for a device also attempts to discover language identifiers and select a language. Subsequent control transfers fetch the descriptor data. The implementation converts characters from the device's UTF-16 string representation to its supported narrow-string form, substituting '?' for code points outside the byte range or below U+0020. It does not preserve arbitrary Unicode input.
When fetching the language-ID array, the second transfer starts two bytes after the beginning of an allocation sized to the descriptor length. A full-length reply can overwrite two bytes beyond that allocation. The string-descriptor transfer also uses the size advertised by the device without bounding the destination against the remaining bytes in its local buffer. Both transfers can overrun their destination allocations.
struct PsdIFFContext * psdGetUsbDevCfg(
STRPTR owner,
STRPTR devid,
STRPTR ifid );
Find stored class configuration for a device or interface.
owner - Class or owner identifier.
devid - Required USB device identification string.
ifid - Optional interface identification string; NULL selects
device-level configuration.
Internal class-data IFF context, or NULL if no matching entry exists.
Searches the device, optional interface and owner configuration forms under the shared configuration lock. The returned pointer refers to mutable internal storage rather than a copied IFF buffer. Call psdWriteCfg() to obtain an independently allocated snapshot.
APTR psdHubClaimAppBindingA( struct TagItem *taglist)
Install an application binding on an unbound device.
taglist - TagItem list describing the application binding.
ABA_Device - Required valid device handle.
ABA_ReleaseHook - Required hook, retained until release. It is called
with the binding handle as the object and ABA_UserData as the message.
ABA_UserData - Value passed to the release hook; defaults to zero.
Keep any referenced data alive until the hook has returned.
ABA_Task - Task pointer stored in the binding; defaults to NULL.
This function does not substitute the current task.
ABA_ForceRelease - Stored flag; does not force release in this function.
An installed binding handle, or NULL if allocation fails, a required attribute is missing, or any device or interface binding already exists. Do not free the handle with psdFreeVec().
This is the hub-side operation. Applications should normally use psdClaimAppBindingA(), which dispatches to the hub owner, handles forced release, records the calling task and sends the binding-added event. The caller must serialize access to the device and its configurations; this function takes no device lock. Tag values are copied, but referenced objects are retained rather than copied. Keep the device, hook and any supplied task pointer valid for the binding lifetime. The tag list itself is not retained. Release through the owning binding path. On release, the hook must finish using the binding before returning; Poseidon then frees it. This function neither emits a binding-added event nor assigns a task name to the binding.
VOID psdHubClassScan( APTR pd)
Try to bind installed USB classes to a device and request a hub scan.
pd - Valid, non-NULL device with a stable configuration and interface
tree. Keep it alive until return.
None. Allocation, configuration and binding failures are not aggregated.
Runs in the owning hub context. Ordinary clients should normally use psdClassScan() to initiate scanning through the stack. Creates a message port and control pipe, takes the base read lock and the device write lock, and may perform USB control transfers and invoke class methods while those locks are held. There is no whole-scan timeout. Allocation failure for the message port or control pipe prevents new binding attempts. An existing device binding or the device's no-class-binding setting skips new binding attempts. Otherwise a forced device class is tried first when no interface binding exists. A configured forced name suppresses ordinary fallback even when that class is absent or refuses. Without that forced-device path, tries unbound interfaces across eligible configurations and alternate settings. Existing interface bindings restrict configuration selection. Forced interface names restrict class selection; otherwise classes are tried in list order. If no interface binds, attempts a device-level binding. Successful bindings update class use counts and send EHMB_ADDBINDING. Configuration and alternate-setting selection can change even when no class binds. Do not retain assumptions about current interface ordering across this call. Finally, if a device class binding exists, invokes UCM_HubClassScan on it, including when new binding attempts were skipped. The supplied hub.class schedules its downstream scan; this call does not wait for that downstream scan to finish.
A NULL device handle is not validated before dereference. Class callbacks run under stack and device locks and can deadlock if they wait for another task requiring those locks. Forced class names are borrowed from configuration storage; concurrent configuration replacement can invalidate them. Coordinate configuration mutation with scanning. Failed attempts do not restore the original configuration or guarantee that all temporary alternate selections were undone.
VOID psdHubReleaseDevBinding( APTR pd)
Remove a device-level binding and invoke its release callback.
pd - Device handle, or NULL to do nothing. Keep a non-NULL device
alive until return.
None. Callback results are ignored.
This is the hub-side operation; ordinary clients should use psdReleaseDevBinding() or psdReleaseAppBinding(). Waits for the device write lock and keeps it held while invoking the release callback. Coordinate device lifetime and avoid callback dependencies on another task that needs this lock. Clears the device binding pointer before the callback. For an application binding, calls its release hook with the binding as the object and its user data as the message, then clears the application-binding flag, frees the binding and sends EHMB_REMBINDING. The hook must not free the binding or retain it after returning. For a class binding, clears the class pointer, calls UCM_ReleaseDeviceBinding, decrements the class use count and sends EHMB_REMBINDING. If no class pointer is present, only the device binding pointer is cleared. Interface bindings are not released here. Release callbacks must complete before return. Do not install a new binding from the callback while this release is still cleaning up.
VOID psdHubReleaseIfBinding( APTR pif)
Remove an interface binding and invoke its class release method.
pif - Interface handle, or NULL to do nothing. Keep a non-NULL
interface, its configuration and its device alive until return.
None. The class method result is ignored.
This is the hub-side operation; ordinary clients should use psdReleaseIfBinding(). Waits for the device write lock and holds it through the class callback. Avoid callback dependencies on another task that needs this lock. If a binding exists, clears the interface binding pointer. If its class is present, also clears the class pointer, calls UCM_ReleaseInterfaceBinding and decrements the class use count. Sends EHMB_REMBINDING for the device whenever a binding was removed, including when no class pointer was present. Does nothing if the interface has no binding. Other interface bindings and the device-level binding are left intact. Stop using the released binding; the class owns its cleanup. This function does not free the interface or its configuration.
BOOL psdLoadCfgFromDisk( STRPTR filename)
Read a Poseidon preferences file and apply its configuration to the running stack.
filename - NUL-terminated DOS path, valid until return. NULL tries
ENV:Sys/poseidon.prefs first, then ENVARC:Sys/poseidon.prefs if
the first attempt returns FALSE.
TRUE after the header and declared payload have been read and configuration application has been attempted. FALSE if DOS cannot be opened, the file cannot be opened, the header is rejected, allocation fails, or the requested bytes cannot be read.
This call performs synchronous file I/O and may add or remove hardware, load or unload classes, and change device bindings through psdParseCfg(). Call from a context that permits DOS I/O and blocking stack operations. The filename is not retained. A reported success updates the saved configuration hash.
Only load trusted, structurally valid Poseidon IFF configuration files. The declared FORM length is used without complete bounds or overflow validation. Malformed lengths can cause invalid memory accesses. The result of psdReadCfg() is ignored. TRUE does not establish that the configuration was imported completely or that all devices and classes were configured. Import failure can leave a partially replaced tree; there is no rollback. A TRUE result also prevents default-path fallback.
void psdLockReadDevice(
struct PsdDevice * pd );
Acquire the shared lock for a Poseidon device.
pd - Valid device whose lock is to be acquired; not NULL.
Calls pLockSemShared() on the device's lock. The acquisition may block, and each acquisition must be balanced with psdUnlockDevice(). The caller must preserve lock ordering when also accessing the global Poseidon base state.
void psdLockReadPBase();
Acquire a shared lock on the Poseidon base state.
The lock protects access to mutable global Poseidon structures, including the hardware, device and class lists. It is acquired through pLockSemShared() and must be released with psdUnlockPBase(). The call may block while an exclusive owner prevents shared access.
void psdLockWriteDevice(
struct PsdDevice * pd );
Acquire the exclusive lock for a Poseidon device.
pd - Valid device whose lock is to be acquired; not NULL.
Calls pLockSemExcl() on the device's lock. The acquisition may block, and each acquisition must be balanced with psdUnlockDevice().
void psdLockWritePBase();
Acquire an exclusive lock on the Poseidon base state.
The function delegates to pLockSemExcl(). It may block until conflicting owners release the lock. The caller must balance the acquisition with psdUnlockPBase() and avoid lock-order inversions when also locking a device or other Poseidon state.
BOOL psdMatchStringChunk( APTR pic, ULONG chunkid, CONST_STRPTR contents)
Compare a string with the first matching configuration chunk.
pic - Valid, non-NULL form handle. chunkid - Numeric chunk identifier in host byte order. contents - Non-NULL, NUL-terminated string to compare.
TRUE for a byte-for-byte, case-sensitive match; FALSE if the chunk is absent or differs. Comparison stops at its first NUL or declared length, and the supplied string must end at that point.
Uses the configuration read lock and may wait; call in task context. Retains neither the string nor a chunk pointer. Coordinate form lifetime separately. This is not validation of serialized IFF data; the form must already contain structurally valid chunks.
struct PsdIFFContext * psdNextCfgForm(
struct PsdIFFContext * pic );
Find the next sibling IFF FORM with the same identifier.
pic - Existing IFF context, typically returned by
psdFindCfgForm(); NULL returns NULL.
Next matching sibling context, or NULL if no further match exists.
The current form ID is reused for the search. The returned context points into mutable configuration state and is not independently reference-counted by this function.
STRPTR psdNumToStr(
UWORD type,
LONG idx,
STRPTR defstr );
Look up a human-readable name for a USB value or enumeration.
type - NTS_* lookup category, such as NTS_IOERR or NTS_LANGID. idx - Numeric value within the selected category. defstr - Fallback string returned when no name is available.
Pointer to a static lookup string or the supplied fallback. The returned pointer is not a new Poseidon allocation.
The supported categories and mappings are implemented in the library's lookup tables and switch statement. Callers must not free a returned table string.
APTR psdOpenStreamA( APTR pep, struct TagItem *taglist)
Create a buffered pipe stream for an endpoint.
pep - Live endpoint with a nonzero maximum packet size. taglist - PSA_* settings, or NULL for defaults.
PSA_MessagePort - Dedicated reply port, owned by the caller. If NULL
or omitted, a port is created for the calling task. The task doing
blocking stream I/O must receive its signals.
PSA_NumPipes - Pipe count; default 4, minimum 1. USB3 stream-ID
availability may further limit the count.
PSA_BufferSize - Per-pipe buffer size; minimum one maximum packet.
Default: 32 packets for IN, 4 for OUT. Allocation products and
overhead must fit in ULONG; overflow is not checked.
PSA_BufferedRead, PSA_ReadAhead, PSA_AllowRuntPackets - Enabled by
default for IN. Plain reads do not support read-ahead or terminators.
PSA_BufferedWrite - Retain incomplete output in the stream; default off.
PSA_NoZeroPktTerm - Suppress the automatic zero-length terminator;
enabled by default for OUT.
PSA_ShortPktTerm - End a buffered read after a non-packet-aligned
received length. A zero-length packet does not meet this test.
PSA_NakTimeout, PSA_NakTimeoutTime - Enable per-pipe NAK timeout and
set its duration in milliseconds. Duration defaults to 5000; the
enable flag defaults off. This is not a whole-operation deadline.
PSA_TermArray - Retained table of eight sorted termination bytes, or
NULL. Repeating the last value pads a shorter set. The terminator
is included in the transfer count. See psdStreamWrite() limitations.
PSA_DoNotWait - Return from buffered reads without waiting for more
data. Does not prevent semaphore waits or hardware submission.
PSA_AbortSigMask - Signals that interrupt supported stream waits.
Observed abort signals are reasserted for the calling task.
PSA_AsyncIO - Leave disabled: read and write have no async transfer path.
PSA_Error - Initial stored error value; normally leave at zero.
PSA_BytesPending, PSA_ActivePipe - Read-only query attributes.
A stream handle, or NULL for a NULL endpoint or a detected allocation failure. Close a successfully created stream with psdCloseStream().
Call in task context. The endpoint determines direction; no endpoint transfer-type check is made here. Port and terminator-table pointers are retained; tag-list storage is not. Keep retained objects valid until close. Do not share the reply port with unrelated traffic. Stream operations use an access semaphore, but the caller must still coordinate port signal ownership, configuration changes and lifetime. Do not change message ports or buffer settings during active I/O.
psdSetAttrsA() return status is ignored during setup. Individual pipe-allocation failures do not make opening fail. A non-NULL stream can contain missing pipes. Failure cleanup can itself enter flush with incomplete arrays or a missing port. Non-NULL is therefore not proof that every resource was initialized successfully.
VOID psdParseCfg( )
Apply the in-memory stack configuration to hardware and USB classes, then scan devices for class bindings.
None. Failures are not returned to the caller.
May block while opening classes, adding or enumerating hardware, removing resources, or scanning bindings. Coordinate the call with other configuration changes and stack lifecycle operations. If no stack configuration form exists, hardware and class reconciliation is skipped. If the form has no hardware entries, existing hardware is preserved. Otherwise hardware absent from the enabled entries is removed. Classes absent from the configured list are removed, except resident classes whose use count is nonzero. Missing classes are opened. Missing enabled hardware is added and enumerated; hardware whose initial enumeration fails is removed again. These operations can invalidate existing device and binding handles. After reconciliation, marks the configuration as read, updates the saved configuration hash, and calls psdClassScan(). When called by a task rather than a process, a configured boot delay may wait for hubs and mass-storage bindings. This call does not save a preferences file.
Application is not transactional. Individual add and remove failures have no aggregate result, and completed changes are not rolled back. Class opening occurs while the configuration read lock is held; a class that waits for another task to modify configuration can deadlock.
void psdPipeSetup(
struct PsdPipe * pp,
UWORD rt,
UWORD rq,
UWORD val,
UWORD idx );
Set the USB setup request fields on a control pipe.
pp - Valid control pipe to configure. rt - bmRequestType field. rq - bRequest field. val - Host-order wValue field. idx - Host-order wIndex field.
The request fields are written into the pipe's setup data. The two 16-bit values are converted to USB little-endian representation with AROS_WORD2LE(). For a control transfer, psdDoPipe() or psdSendPipe() fills wLength from the requested data length. This function does not submit a transfer or validate the request.
BOOL psdReadCfg(
struct PsdIFFContext * pic,
APTR formdata );
Replace a Poseidon configuration context with a serialized IFF FORM of the same type.
pic - Target IFF context, or NULL for the configuration root. formdata - Valid serialized IFF FORM buffer with matching form ID.
TRUE when the form data was accepted, otherwise FALSE.
Takes the configuration write lock, validates the FORM header and form identifier, and rebuilds the context contents. The serialized input is not a PsdIFFContext pointer. No rollback guarantee is established for a failure after partial context modification.
void psdReleaseAppBinding(
struct PsdAppBinding * pab );
Request release of an application-owned device binding.
pab - Binding returned by psdClaimAppBindingA(), or NULL.
For a root hub the implementation invokes the local hub release path. For downstream devices it delegates to the parent hub class through UCM_HubReleaseDevBinding when that hub is bound. The binding release path invokes its registered release hook. No completion or error result is returned.
VOID psdReleaseDevBinding( APTR pd)
Request release of the current device-level class or application binding.
pd - Valid, non-NULL device handle. Keep the device alive until return.
None. Dispatch and release failures are not reported.
Does nothing if the device has no device-level binding. Interface bindings are not released by this call. For a root device, calls psdHubReleaseDevBinding() directly. For a child device, dispatches UCM_HubReleaseDevBinding through its parent hub class. The supplied hub.class waits for the hub task to finish; callbacks and that wait may block without a timeout. The release path can invoke an application release hook or a class release method. Stop using the binding before requesting release. Coordinate device lifetime and competing binding operations with the owner of the device.
If the parent hub has no device binding or class binding, the request is silently skipped. Returning does not by itself prove release.
VOID psdReleaseIfBinding( APTR pif)
Request release of an interface class binding.
pif - Valid, non-NULL interface handle whose configuration and device
remain alive until return.
None. Dispatch and release failures are not reported.
Does nothing unless both an interface binding and its class are present. Other interface bindings and the device-level binding are left intact. For a root device, calls psdHubReleaseIfBinding() directly. Otherwise dispatches UCM_HubReleaseIfBinding through the parent hub class. The supplied hub.class waits for the hub task to finish; the class release callback and that wait may block without a timeout. Stop using the binding before requesting release. Coordinate interface and device lifetime and competing binding operations with their owner.
If the parent hub has no device binding or class binding, the request is silently skipped. Returning does not by itself prove release.
BOOL psdRemCfgChunk(
struct PsdIFFContext * pic,
ULONG chnkid );
Remove a chunk by identifier, or clear a form's entire contents.
pic - Context to modify, or NULL for the configuration root. chnkid - Chunk identifier; zero clears the context's entries.
TRUE when an entry was removed or a context was cleared, otherwise FALSE.
The exclusive configuration lock protects modification. Clearing with identifier zero retains the selected context object while releasing its subordinate forms and chunks.
void psdRemCfgForm(
struct PsdIFFContext * pic );
Remove a configuration FORM and all its nested data.
pic - Context to remove, or NULL to select the configuration root.
Takes the exclusive configuration lock and recursively frees the selected form. Sets the configuration-check flag after removal. References to the removed context and its descendants become invalid. The function returns no status.
void psdRemClass(
struct PsdUsbClass * puc );
Unregister and close a previously installed USB class.
puc - Valid class record returned by psdAddClass().
Removes the class from the global list and tries to release outstanding device and interface bindings before closing the class library and freeing the class record. If the class use count remains nonzero, the release loop retries without a sleep and may run indefinitely. It sends EHMB_REMCLASS without a completion status. The record is invalid after successful teardown.
EHMB_REMCLASS is queued after the class record is freed. The event pointer cannot safely be dereferenced by receivers.
void psdRemErrorMsg(
struct PsdErrorMsg * pem );
Remove a Poseidon error-log entry and release its storage.
pem - Valid error-message record currently linked in the list.
Unlinks the record under Forbid()/Permit(), frees its origin and text, and releases the record. An EHMB_REMERRORMSG event is emitted. The pointer is invalid after this call, and no status is returned.
EHMB_REMERRORMSG is emitted after freeing pem; consumers must not dereference the event pointer.
VOID psdRemEventHandler( APTR peh)
Remove an event registration and reply to queued port messages.
peh - Live registration returned by psdAddEventHandler(), or NULL.
NULL is ignored. Call in task context. Removes the registration under the event semaphore, drains its port with GetMsg()/ReplyMsg(), and frees the registration. No later send can select that registration. The port itself is not deleted. Coordinate with the receiving task before removal. Messages already taken by the consumer are not drained; the consumer must still reply to each exactly once. Do not reuse the registration handle.
Drains every message on the port without checking its origin. Use a dedicated port, not a port shared with another registration or protocol.
void psdRemHardware(
struct PsdHardware * phw );
Shut down a registered USB controller and release its stack state.
phw - Valid controller returned by psdAddHardware().
Releases bindings and retires attached devices, then waits for the controller task to exit. Pending pipe references delay device teardown, but repeated unsuccessful waits can cause the code to clear the device use count and continue. The internal device cleanup releases owned state without freeing the device record. Controller metadata is freed before EHMB_REMHARDWARE is sent. No completion status is returned.
EHMB_REMDEVICE can carry a retired device whose owned state has already been released. EHMB_REMHARDWARE carries the pointer to a freed controller. Event recipients must not dereference either pointer after the associated teardown.
BOOL psdResumeBindings( APTR pd)
Ask existing class bindings to resume and rescan after a failed callback.
pd - Device with a valid current configuration, or NULL. Keep the
device, configuration and bindings alive throughout the call.
Always TRUE, including for NULL and when a class resume method fails. The result does not certify that all bindings resumed.
Requires serialized access to the device and its bindings; this function takes no device lock. Class callbacks, releases and rescanning can block. It neither resumes the hub port nor changes the suspended flag. Sends UCM_AttemptResumeDevice to a device class binding. Application bindings are left alone. A failed class callback requests release of that binding and schedules a stack-wide psdClassScan(). The same handling is applied to the first bound interface in the current configuration. A rescan can create new bindings; it does not guarantee replacement of each released binding.
Interface traversal stops at the first binding, even if its class pointer is absent. Later bound interfaces are not resumed. Failures are not returned and release completion is not checked. A non-NULL device without a current configuration can cause a NULL dereference.
BOOL psdResumeDevice( APTR pd)
Request port resume through the parent hub, then resume class bindings.
pd - Device handle, or NULL. A suspended device must have a valid
current configuration. Keep the device and parent hub alive until
return; serialize competing state changes.
TRUE if the device is already marked active, or if the hub resume method succeeds. FALSE for NULL, an unsupported root-hub resume, a missing parent binding or class, or a failed hub resume method. TRUE does not certify successful resumption of all class bindings.
May block on the device write lock, a hub-task reply, USB control I/O, class callbacks and rescanning. There is no whole-operation timeout. Dispatches UCM_HubResumeDevice while holding the device write lock. The supplied hub.class clears PORT_SUSPEND; after a successful transfer it clears the suspended flag, sends EHMB_DEVRESUMED and waits 30 ms. After the hub method returns successfully, this function releases the lock and calls psdResumeBindings(). The resumed event therefore does not establish that binding callbacks have finished. An already-active device returns immediately without resuming bindings. An active root hub also returns TRUE; resuming a suspended root hub is unsupported.
The binding phase has no usable failure result and only processes the first bound interface. State checks, hub resume and binding callbacks are not one atomic transition.
void psdSafeRawDoFmtA(
STRPTR buf,
ULONG len,
CONST_STRPTR fmtstr,
RAWARG fmtdata );
void psdSafeRawDoFmt(
STRPTR buf,
ULONG len,
CONST_STRPTR fmtstr,
... );
Write formatted text into a caller-provided bounded buffer.
buf - Writable output buffer when len is nonzero. len - Buffer capacity in bytes, including the terminating NUL. fmtstr - Valid RawDoFmt() format string. fmtdata - Matching RawDoFmt() argument stream.
Writes at most len bytes through a bounded RawDoFmt() callback, then sets buf[len - 1] to NUL. With len zero, does nothing. The callback does not report truncation; callers must not infer that the complete formatted result was written.
BOOL psdSaveCfgToDisk( STRPTR filename, BOOL mode)
Write the current configuration to a Poseidon preferences file.
filename - NUL-terminated DOS path, valid until return. NULL writes
both ENVARC:Sys/poseidon.prefs and ENV:Sys/poseidon.prefs, in
that order. Both writes are attempted.
mode - Ignored by this implementation. Pass FALSE.
TRUE if serialization and opening the destination succeeded. FALSE if DOS cannot be opened, serialization fails, or opening fails. With filename NULL, TRUE requires both default-path calls to return TRUE.
Performs synchronous DOS I/O while holding the configuration read lock. Opening an existing destination truncates it. There is no temporary-file replacement or rollback. The filename is not retained. A reported success updates the saved configuration hash.
Write() and Close() results are ignored. TRUE does not establish that the file was written completely or closed successfully. A failed write can leave a truncated file and still mark the configuration as saved. The two default destinations are not updated atomically.
VOID psdSendEvent( ULONG ehmt, APTR param1, APTR param2)
Queue a notification for each registration selecting an event.
ehmt - EHMB_* event number, not an EHMF_* mask. Use a defined event
from <libraries/poseidon.h>; the shift count is not validated.
param1, param2 - Event-specific values copied into each notification.
Pointed-to objects are neither copied nor retained.
Call in task context; allocation and the event semaphore may wait. The call queues messages and returns without waiting for recipients. Each recipient must ReplyMsg() its notification. Replied messages are reclaimed by Poseidon during subsequent event garbage collection. Keep event payload lifetime independent of message delivery. An object address may identify a change without remaining safe to dereference.
Allocation failure drops the notification for that recipient without a return status. Delivery is neither all-or-nothing nor guaranteed.
void psdSendPipe(
struct PsdPipe * pp,
APTR data,
ULONG len );
Submit a pipe transfer without waiting for completion.
pp - Allocated pipe that is not already pending. data - Transfer buffer, or NULL for a control request without data. len - Number of bytes to transfer.
On a connected device, this function requests resume if needed, prepares the IO request and queues the pipe to the hardware task. For a disconnected device, it delays for 50 ms, records UHIOERR_TIMEOUT and replies to the pipe message without queuing the hardware transfer. Both paths increment the device busy count. The buffer and pipe must remain valid and unchanged until their completion message has been received and handled. The function does not return a completion status.
BOOL psdSetAltInterface(
struct PsdPipe * pp,
struct PsdInterface * pif );
Select an alternate setting of a configured USB interface.
pp - Control pipe for the containing device, or NULL to
select the alternate setting only in Poseidon's local state.
pif - Valid interface or alternate interface to activate.
TRUE when the requested setting is already active or the selected path succeeds; otherwise FALSE. With pp set to NULL, TRUE does not confirm any USB transfer or device-side selection.
Locates the main interface and alternate setting and takes the device write lock. A non-NULL pp sends SET_INTERFACE followed by GET_INTERFACE confirmation; with NULL pp the code skips both requests and rearranges the local interface lists. The list linkage changes only on the accepted path. USB errors are reported through Poseidon's log.
LONG psdSetAttrsA(
ULONG type,
APTR psdstruct,
struct TagItem * tags );
LONG psdSetAttrs(
ULONG type,
APTR psdstruct,
TAG tag, ... );
Change writable attributes of a Poseidon object.
type - PGA_* object category selecting the attribute table.
psdstruct - Object to update; required when the category uses
object-specific state.
tags - Attribute/value tag list for the selected category.
The generic path returns the number of attributes processed by PackStructureTags(), or -1 if no pack table is available. PGA_ENDPOINT and PGA_PIPESTREAM return their own processed-tag counts. The generic result does not include every attribute handled explicitly.
Certain device and global configuration tags also update stored configuration records or schedule a power recalculation. Changing an attribute is not equivalent to sending a USB control request unless the corresponding code path explicitly does so. A nonnegative tag count does not guarantee successful resource changes: PIPESTREAM reallocation failures are not reflected in the returned count. Callers must respect object lifetimes and the lock requirements of data shared with other tasks.
BOOL psdSetClsCfg(
STRPTR owner,
APTR form );
Store or clear class-specific configuration under an owner name.
owner - Valid class or owner identifier string. form - Serialized IFFFORM_CLASSDATA, or NULL to clear its contents.
TRUE on successful creation or update, otherwise FALSE.
Finds the matching class configuration by its owner chunk, or creates one if none exists. The function updates configuration change bookkeeping after its write-lock-protected operation. A NULL form creates or preserves an empty CLASSDATA context rather than removing the owning class entry itself. If replacement of an existing CLASSDATA form fails, the routine also attempts the new-entry path. A failed update may therefore leave an additional class configuration entry rather than retaining a unique key.
BOOL psdSetDeviceConfig(
struct PsdPipe * pp,
UWORD cfgnum );
Select a USB device configuration through its control pipe.
pp - Valid default-control pipe for the device. cfgnum - Configuration value to request.
TRUE if SET_CONFIGURATION completed without an I/O error; otherwise FALSE.
Records the new configuration number only after a successful SET_CONFIGURATION transfer. Regardless of transfer success, it resolves the active configuration pointer from the previously stored number. If a matching configuration exists, it may query device status or request remote wakeup. Failure of these later requests does not change the original transfer result; the active configuration pointer may remain NULL.
BOOL psdSetForcedBinding( STRPTR owner, STRPTR devid, STRPTR ifid)
Store or remove the preferred USB class for a device or interface in the in-memory configuration.
owner - NUL-terminated class name to store. NULL or an empty string
removes the forced binding.
devid - Non-NULL, NUL-terminated device ID string.
ifid - NUL-terminated interface ID string, or NULL for a device binding.
Strings must remain valid until return; stored values are copied.
TRUE if the binding was stored, or if removal was requested, including when no matching binding existed. FALSE if storing could not complete. Failure can leave configuration changes in place.
May wait for the configuration write lock. Searches the first matching device form. Interface removal affects all matching interface forms within that device; device removal leaves interface bindings intact. Does not load the named class, verify that it accepts the target, or release and rebind an existing device. Changes remain in memory until saved. A changed configuration hash triggers a configuration-change event; storing a name does not establish a live binding.
Updates are not transactional. Allocation failure can remove a previous value or leave incomplete or duplicate configuration forms. FALSE does not guarantee that the previous binding remains available.
BOOL psdSetUsbDevCfg(
STRPTR owner,
STRPTR devid,
STRPTR ifid,
APTR form );
Save device- or interface-specific class configuration.
owner - Class or owner identifier.
devid - Required USB device identification string.
ifid - Optional interface identification string; NULL selects
device-level configuration.
form - Serialized class-data IFF FORM, or NULL to clear data.
TRUE when the matching configuration was created or updated, otherwise FALSE.
Locates or creates the device configuration and optional interface subform, then associates the owner with its class-data context. Updates take the configuration write lock. The identifiers are used as configuration keys; this call does not modify a live USB device or immediately rebind its interfaces. If updating an existing class-data form fails, the routine falls back to creating a new device configuration entry. Duplicate keys and partially created forms are possible on failure paths.
struct Task * psdSpawnSubTask(
STRPTR name,
APTR initpc,
APTR userdata );
Start a Poseidon worker as a process when DOS is available, or as an Exec task during early startup.
name - Non-NULL task or process name. initpc - Non-NULL entry point for the worker. userdata - Pointer stored as task user data.
New task pointer, or NULL if argument validation, allocation or task/process creation fails.
The DOS path uses CreateNewProcTags() with the configured worker priority and stack size. The early-boot path allocates an Exec task, stack and copied name through an attached memory list and starts it with AddTask(). The returned worker has its own lifetime; this function does not wait for worker initialization or exit.
LONG psdStartRTIso( APTR prt)
Ask the controller to start a registered real-time ISO handler.
prt - Live, stopped handler returned by psdAllocRTIsoHandlerA().
Zero on controller-command success; otherwise the controller I/O error. NULL returns UHIOERR_BADPARAMS. Success is not a completed transfer or a guarantee of error-free future frames.
Call in task context. Serializes neither concurrent lifecycle calls nor attribute changes; the caller must do so. If the device is suspended, attempts to resume it before issuing the start command. Data hooks can run during controller setup. There is no library-level timeout or rollback guarantee for a failed start. Each successful start increments the device busy count. Pair it with one successful psdStopRTIso() before freeing the handler.
No running-state guard prevents repeated starts. The device-resume result is ignored; the returned status belongs to the start command.
LONG psdStopRTIso( APTR prt)
Ask the controller to stop a running real-time ISO handler.
prt - Live handler with one unmatched successful psdStartRTIso().
Zero on controller-command success; otherwise the controller I/O error. NULL returns UHIOERR_BADPARAMS. On failure, do not assume that the controller has stopped accessing callback state or buffers.
Call in task context and serialize lifecycle operations. On success, decrements the device busy count. The registered handler remains allocated and may be started again. There is no library-level timeout; callback and buffer quiescence depend on the controller implementation.
No running-state guard prevents unmatched or repeated stops. Each successful command decrements the busy count, even without a matching successful start.
LONG psdStreamFlush( APTR pps)
Discard pending input or submit buffered output.
pps - Live stream.
TRUE after input cleanup or successful output processing; FALSE if output has no free pipe or its transfer fails. NULL returns -1, which is nonzero: do not treat every nonzero result as success.
Call in task context with exclusive lifetime ownership. Takes the access semaphore and resets the stored error. For IN, aborts and waits for all pipes, recycles ready replies and discards unread data and read offsets. Does not clear the read-ahead option. For OUT, synchronously sends pending bytes using a free pipe. Empty output succeeds only if a free pipe is present. Does not implement PSA_DoNotWait or a stream-level abort wait; there is no whole-call timeout. Query psdGetStreamError() immediately after the operation.
Output pending bytes are cleared even when transfer fails, so an unsent suffix is lost from the stream. Input abort/wait errors are ignored. FALSE caused by no free output pipe leaves the error zero. Flush assumes initialized pipe-array and port storage.
LONG psdStreamRead( APTR pps, APTR buffer, LONG length)
Read bytes from an IN stream.
pps - Live IN stream.
buffer - Writable storage for length bytes. Must remain valid during
the call and while any in-place read still references it.
length - Nonnegative byte capacity. The legacy -1 mode selects all
currently buffered bytes without a capacity check; avoid it.
Other negative values are invalid and are not rejected safely.
Bytes delivered, possibly zero or fewer than requested. Returns -1 for NULL, wrong direction, missing pipe array or detected queue inconsistency. Zero is not an end-of-file indication. Inspect psdGetStreamError() even after a nonnegative or partial result.
Call from the task receiving the stream port signals. Resets the stored error and holds the access semaphore. Buffered reads consume ready packets, optionally stop at an included terminator or a short packet, and may submit read-ahead requests. Zero length can still collect completions or queue read-ahead; it is not necessarily a no-op. PSA_DoNotWait applies only to buffered reads. The plain path uses synchronous pipe I/O and ignores the stream abort mask. A buffered NAK timeout with received bytes is treated as successful data. Other observed errors stop that read and disable read-ahead. An abort signal is reasserted but does not itself set the stream error. There is no whole-call timeout.
The implementation does not validate a non-NULL data buffer. A buffered read can submit directly into the caller buffer. Early return on abort or PSA_DoNotWait does not cancel and join that request. Keep the buffer valid until outstanding reads have been stopped and waited for, for example through a valid stream's flush or close. PSA_AsyncIO skips transfer processing and returns zero after validation. Queue-consistency failures can return -1 with a zero stored error.
LONG psdStreamWrite( APTR pps, APTR buffer, LONG length)
Write bytes to an OUT stream or accept them into its buffer.
pps - Live OUT stream.
buffer - Readable storage for length bytes, valid until return.
length - Nonnegative byte count, or -1 for a NUL-terminated string
whose length fits in LONG. String mode does not send the NUL.
Other negative values are invalid and are not checked safely.
Bytes accepted, including bytes retained for a later flush when buffering is enabled. This is not necessarily a transmitted-byte count. Returns -1 for NULL, wrong direction or missing pipe array. Inspect psdGetStreamError() even after a positive result; failures can follow partial device writes. Retrying the entire payload can duplicate data.
Call from the task receiving the stream port signals. Resets the stored error and holds the access semaphore. Direct transfers are waited for before return; buffered tails are copied into stream storage. An observed abort signal is reasserted, and the active request is aborted and waited for before returning. There is no whole-call timeout. A terminator table limits the accepted prefix through its first matched byte. PSA_DoNotWait does not make writes nonblocking. Use flush to submit remaining buffered output and inspect that result before close.
The implementation does not validate a non-NULL data buffer. The terminator scan can read table element 8 after checking element 7, outside the eight-byte table, and its duplicate-value test differs from the read path. Leave PSA_TermArray NULL for output until corrected. PSA_AsyncIO skips transfer processing and returns zero after validation. Buffered error recovery trusts the controller's actual byte count.
BOOL psdSuspendBindings( APTR pd)
Prepare the device binding and current interface bindings for suspension.
pd - Device with a valid current configuration, or NULL. Keep the
device, configuration and bindings alive throughout the call.
TRUE if traversal finishes without a binding refusing suspension. FALSE for NULL or a rejected suspension request. TRUE does not mean that the hub port has been suspended.
Call in a context that serializes device and binding changes; this function takes no device lock. Class methods and binding release can block. psdSuspendDevice() performs this preparation under a device write lock before asking the hub to suspend the port. Classes advertising UCCA_SupportsSuspend receive UCM_AttemptSuspendDevice. A refusal stops traversal. Classes without that capability are accepted if the device has no active I/O. When GCA_ForceSuspend is enabled and the current configuration advertises remote wakeup, application bindings and busy bindings of classes without suspend support are released. Otherwise an application binding or a busy, unsupported class causes failure. A suspend-capable class may still veto suspension when force mode is enabled. Visits the device binding and every interface in the current configuration. Released binding handles become invalid. This function does not change the port state or the device's suspended flag.
Failure does not undo earlier class suspension or binding releases. Release requests have no status, so TRUE cannot establish that forced release completed. A non-NULL device without a current configuration is invalid and can cause a NULL dereference.
BOOL psdSuspendDevice( APTR pd)
Prepare a device for suspension and request suspension of its hub port.
pd - Valid, non-NULL device with a current configuration. Keep it and
its parent hub alive until return; serialize competing state changes.
TRUE if the device is already marked suspended, or if binding preparation and the dispatched hub method report success. FALSE if preparation or the hub method fails, or a root hub needs suspension. See BUGS for the missing-parent-binding case.
May block on device locks, class callbacks, hub-task replies and USB control transfers. There is no whole-operation timeout. Runs psdSuspendBindings() under the device write lock, then dispatches UCM_HubSuspendDevice under a device read lock. Preparation may release bindings. The supplied hub.class sets PORT_SUSPEND; on successful control transfer it marks the device suspended and sends EHMB_DEVSUSPENDED. This reports command completion, not an independent measurement of power consumption. Root-hub suspension is unsupported unless the suspended flag was already set, in which case the initial state check returns TRUE.
If preparation succeeds but the parent has no device binding or class binding, no hub request is sent and TRUE is still returned. Preparation is not rolled back after a failed port-suspend request. NULL is unsafe: the failure diagnostic dereferences pd. State checks and preparation are not one atomic transition with the subsequent hub call.
VOID psdUnbindAll( )
Release device and interface bindings throughout the stack.
None.
Visits hardware, devices, configurations and interfaces. Requests one release, then restarts traversal from the beginning. Returns after a complete traversal finds no binding. This is not an atomic snapshot or a guarantee that later scans cannot create new bindings. Can invoke class release methods and application release hooks, and can wait for hub tasks. Coordinate stack teardown and exclude concurrent device removal or rebinding before calling. Devices and hardware are not explicitly freed by this function, but release callbacks can have additional effects.
There is no timeout or progress check. If a release leaves its binding in place, the traversal can retry indefinitely. The base read lock is released before each release request; the selected object is not pinned across that interval, so concurrent removal can invalidate it.
void psdUnlockDevice(
struct PsdDevice * pd );
Release the current task's lock on a Poseidon device.
pd - Valid device whose lock is held; not NULL.
Calls pUnlockSem() on the device's lock. The function does not report a completion result. Balance each shared or exclusive device-lock acquisition with its corresponding release.
void psdUnlockPBase();
Release the current task's Poseidon base lock.
Delegates to pUnlockSem() for the shared/exclusive lock state held by the calling task. Each acquisition must be balanced with a corresponding release; this function does not report success or verify a higher-level lock-order contract.
LONG psdWaitPipe(
struct PsdPipe * pp );
Wait for a pending pipe message and return the recorded IO error.
pp - Valid pipe with a message port used for its submission.
IO error stored in the pipe request; zero indicates success.
The function waits on the pipe's message-port signal while the pipe message remains pending. For a replied message, it removes the message from the reply queue and marks it free. Signals seen while waiting are restored for other messages on the port. The device busy count is decremented and last activity updated. Transfer errors contribute to a device dead-count heuristic that can emit EHMB_DEVICEDEAD; improving results can clear the dead flag. Calling this function without a matching submitted transfer is not supported by the bookkeeping in this implementation.
APTR psdWriteCfg(
struct PsdIFFContext * pic );
Serialize a Poseidon IFF configuration context into an allocated FORM buffer.
pic - Context to serialize, or NULL for the configuration root.
Newly allocated serialized FORM buffer, or NULL when no suitable root context exists or allocation fails. Free with psdFreeVec().
The function updates the global configuration fields, marks a configuration check as needed, measures the serialized form and writes it to a new buffer while holding the configuration lock. The serialized FORM contains its IFF size in the header.