psdAbortPipe()
Synopsis
void psdAbortPipe(
struct PsdPipe * pp );
Function
Request cancellation of an outstanding pipe transfer.
Notes
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.
Bugs
If allocation of the temporary cancellation request fails, no
cancellation request is sent and the caller receives no error.
psdAddCfgEntry()
Synopsis
struct PsdIFFContext * psdAddCfgEntry(
struct PsdIFFContext * pic,
APTR formdata );
Function
Add an IFF FORM or data chunk to an existing configuration context.
Result
Resulting configuration context from the internal addition
routine, or NULL on failure.
Notes
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.
psdAddClass()
Synopsis
struct PsdUsbClass * psdAddClass(
STRPTR name,
ULONG vers );
Function
Open a USB class library and register it with Poseidon.
Result
Registered class record, or NULL if the library cannot be opened,
is already registered, or record allocation fails.
Notes
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.
psdAddErrorMsgA()
Synopsis
struct PsdErrorMsg * psdAddErrorMsgA(
UWORD level,
STRPTR origin,
STRPTR fmtstr,
RAWARG fmtdata );
struct PsdErrorMsg * psdAddErrorMsg(
UWORD level,
STRPTR origin,
STRPTR fmtstr,
... );
Function
Append a formatted diagnostic message to Poseidon's error log.
Result
New error-message record, or NULL if logging at this severity is
disabled or a required allocation fails.
Notes
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.
psdAddEventHandler()
Synopsis
APTR psdAddEventHandler(
struct MsgPort *mp, ULONG msgmask)
Function
Subscribe a message port to Poseidon events.
Result
An opaque registration handle, or NULL for a NULL port or allocation
failure. Remove a successful registration with psdRemEventHandler().
Notes
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.
psdAddHardware()
Synopsis
struct PsdHardware * psdAddHardware(
STRPTR name,
ULONG unit );
Function
Open a USB controller and register it with the Poseidon stack.
Result
Initialized controller handle, or NULL if allocation, startup or
controller initialization fails.
Notes
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().
psdAddStringChunk()
Synopsis
BOOL psdAddStringChunk(
APTR pic, ULONG chunkid, CONST_STRPTR contents)
Function
Store a string chunk in a configuration form.
Result
TRUE if the string was stored; FALSE if allocation fails. Failure
while expanding the form buffer can leave the previous chunk removed.
Notes
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.
Bugs
Replacement removes the old chunk before securing expansion memory.
Input sizes and the reserved FORM identifier are not validated.
psdAllocDevice()
Synopsis
struct PsdDevice * psdAllocDevice(
struct PsdHardware * phw );
Function
Allocate and register a device record under a USB controller.
Result
Initialized device record, or NULL on allocation failure.
Notes
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.
psdAllocPipe()
Synopsis
struct PsdPipe * psdAllocPipe(
struct PsdDevice * pd,
struct MsgPort * mp,
struct PsdEndpoint * pep );
Function
Allocate a transfer pipe for a USB device endpoint or endpoint zero.
Result
Allocated pipe, or NULL on invalid input, allocation failure,
unsupported transfer type or controller capability, or failed
endpoint preparation. Release it with psdFreePipe().
Notes
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.
psdAllocRTIsoHandlerA()
Synopsis
APTR psdAllocRTIsoHandlerA(
APTR pep, struct TagItem *taglist)
Function
Register a real-time isochronous endpoint handler with its controller.
Result
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().
Notes
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.
Bugs
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.
psdAllocVec()
Synopsis
APTR psdAllocVec(
ULONG size );
Function
Allocate an aligned block from the Poseidon memory pool.
Result
Allocated block aligned to AROS_WORSTALIGN, or NULL on pool
allocation failure. Release it with psdFreeVec().
Notes
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.
Bugs
The calculation adding the header, alignment padding and optional
debugging area does not check for ULONG overflow.
psdBorrowLocksWait()
Synopsis
ULONG psdBorrowLocksWait(
struct Task *task, ULONG signals)
Function
Temporarily lend the caller's registered Poseidon locks to another
task while waiting for signals, then reclaim them.
Result
The signal mask returned by Wait(signals), after lock reclamation.
This is not a lock-transfer status or a count of transferred locks.
Notes
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.
Bugs
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.
psdCalculatePower()
Synopsis
VOID psdCalculatePower(
APTR phw)
Function
Recalculate the stored power estimates for a hardware device tree.
Result
None. Read device estimates through DA_PowerSupply and DA_PowerDrained.
Notes
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.
Bugs
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.
psdCheckPipe()
Synopsis
APTR psdCheckPipe(
APTR pp)
Function
Test whether a pipe is marked as pending.
Result
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.
Notes
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.
Bugs
The implementation dereferences pp without checking for NULL.
psdClaimAppBindingA()
Synopsis
struct PsdAppBinding * psdClaimAppBindingA(
struct TagItem * tags );
struct PsdAppBinding * psdClaimAppBinding(
TAG tag, ... );
Function
Claim a USB device for an application, bypassing normal class
ownership where the hub accepts the request.
Result
Application-binding handle, or NULL if required attributes are
absent or the hub declines the claim.
Notes
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.
psdClassScan()
Synopsis
void psdClassScan();
Function
Ask USB class drivers to bind devices found by Poseidon.
Notes
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.
psdCloseStream()
Synopsis
VOID psdCloseStream(
APTR pps)
Function
Flush a stream, stop its pipes and release its storage.
Notes
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.
Bugs
Cleanup assumes the configured pipe array and port are usable.
Partially initialized streams can violate that assumption.
psdCopyStr()
Synopsis
STRPTR psdCopyStr(
CONST_STRPTR name );
Function
Allocate a copy of a NUL-terminated string in Poseidon memory.
Result
Newly allocated copy or NULL if allocation fails. Release the
returned string with psdFreeVec().
Notes
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.
psdCopyStrFmtA()
Synopsis
STRPTR psdCopyStrFmtA(
CONST_STRPTR fmtstr, RAWARG fmtdata)
Function
Allocate a string formatted with Exec RawDoFmt().
Result
A NUL-terminated allocated string, or NULL on allocation failure.
Release the result with psdFreeVec().
Notes
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.
psdDebugSemaphores()
Synopsis
VOID psdDebugSemaphores(
)
Function
Log the registered Poseidon semaphore owners, readers and waiters.
Result
None. Output is added to the Poseidon message log.
Notes
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.
psdDelayMS()
Synopsis
void psdDelayMS(
ULONG milli );
Function
Perform a synchronous delay through Poseidon's timer device.
Notes
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.
Bugs
The multiplication by 1000 has no explicit overflow check.
The requested duration is not normalized into seconds here.
psdDoHubMethodA()
Synopsis
IPTR psdDoHubMethodA(
APTR pd, ULONG methodid, IPTR *methoddata)
Function
Dispatch a method to the class bound to a device's parent hub.
Result
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.
Notes
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.
Bugs
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.
psdDoPipe()
Synopsis
LONG psdDoPipe(
struct PsdPipe * pp,
APTR data,
ULONG len );
Function
Submit a pipe transfer and wait for its completion.
Result
IO error code returned by psdWaitPipe() after the transfer, or
UHIOERR_TIMEOUT if the device is disconnected. Zero indicates
successful completion.
Notes
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.
psdEnumerateDevice()
Synopsis
struct PsdDevice * psdEnumerateDevice(
struct PsdPipe * pp );
Function
Assign and query USB device state through an enumeration pipe.
Result
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.
Notes
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.
psdEnumerateHardware()
Synopsis
struct PsdDevice * psdEnumerateHardware(
struct PsdHardware * phw );
Function
Enumerate the root USB device or root hubs of a registered
controller.
Result
Root device established by the enumeration procedure, or NULL if
no root device can be configured.
Notes
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.
psdFindDescriptorA()
Synopsis
APTR psdFindDescriptorA(
APTR pd, APTR pdd, struct TagItem *taglist)
Function
Find the next stored descriptor matching all supplied filters.
Result
A borrowed descriptor handle, or NULL if no further match is found.
Notes
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.
Bugs
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.
psdFindDeviceA()
Synopsis
struct PsdDevice * psdFindDeviceA(
struct PsdDevice * pd,
struct TagItem * tags );
struct PsdDevice * psdFindDevice(
struct PsdDevice * pd,
TAG tag, ... );
Function
Find the next device satisfying all supplied search attributes.
Result
First subsequent matching device, or NULL at the end of traversal.
Notes
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.
psdFindEndpointA()
Synopsis
APTR psdFindEndpointA(
APTR pif, APTR pep, struct TagItem *taglist)
Function
Find the next endpoint matching all supplied filters.
Result
A borrowed endpoint handle, or NULL if no further endpoint matches.
Notes
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.
Bugs
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.
psdFindInterfaceA()
Synopsis
APTR psdFindInterfaceA(
APTR pd, APTR pif, struct TagItem *taglist)
Function
Find the next interface matching all supplied filters.
Result
A borrowed interface handle, or NULL if no further match is found
or a fresh search has no current configuration.
Notes
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.
Bugs
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.
psdFreeDevice()
Synopsis
void psdFreeDevice(
struct PsdDevice * pd );
Function
Remove a device from active enumeration and begin its teardown.
Notes
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.
psdFreePipe()
Synopsis
void psdFreePipe(
struct PsdPipe * pp );
Function
Release a pipe and its associated device reference.
Notes
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.
psdFreeRTIsoHandler()
Synopsis
VOID psdFreeRTIsoHandler(
APTR prt)
Function
Remove a real-time isochronous handler and free its library storage.
Notes
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.
Bugs
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.
psdFreeVec()
Synopsis
void psdFreeVec(
APTR pmem );
Function
Release a block allocated by psdAllocVec().
Notes
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.
psdGetAttrsA()
Synopsis
LONG psdGetAttrsA(
ULONG type,
APTR psdstruct,
struct TagItem * tags );
LONG psdGetAttrs(
ULONG type,
APTR psdstruct,
TAG tag, ... );
Function
Read supported attributes from a Poseidon object or stack state.
Result
Number of recognized attributes read, or -1 when the category
has no pack table.
Notes
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.
psdGetCfgChunk()
Synopsis
APTR psdGetCfgChunk(
struct PsdIFFContext * pic,
ULONG chnkid );
Function
Copy a serialized IFF chunk out of a configuration context.
Result
Allocated copy of the full chunk including its IFF header, or
NULL if the chunk is absent or allocation fails. Free with
psdFreeVec().
Notes
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.
psdGetClsCfg()
Synopsis
struct PsdIFFContext * psdGetClsCfg(
STRPTR owner );
Function
Find the stored configuration context for a class owner.
Result
Internal CLASSDATA context for the matching owner, or NULL if
none is present.
Notes
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.
psdGetForcedBinding()
Synopsis
STRPTR psdGetForcedBinding(
STRPTR devid, STRPTR ifid)
Function
Look up the configured forced class binding for a device or interface.
Result
A borrowed pointer to the stored class name, or NULL if no matching
binding is found. Do not modify or free the returned string.
Notes
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.
psdGetNextDevice()
Synopsis
struct PsdDevice * psdGetNextDevice(
struct PsdDevice * pd );
Function
Return the next device in Poseidon's controller/device lists.
Result
Next device pointer, or NULL when no further device is found.
Notes
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.
psdGetPipeActual()
Synopsis
ULONG psdGetPipeActual(
struct PsdPipe * pp );
Function
Read the actual byte count recorded for a pipe transfer.
Result
Value of the pipe request's iouh_Actual field.
Notes
The function does not wait for completion or validate the pipe
state. Read the count after handling the transfer completion.
psdGetPipeError()
Synopsis
LONG psdGetPipeError(
struct PsdPipe * pp );
Function
Read the IO error recorded for a pipe transfer.
Result
The pipe request's io_Error value, cast to LONG. Zero indicates
no recorded error.
Notes
The function does not wait for completion or validate the pipe
state. Read the error after handling an asynchronous completion.
psdGetStreamError()
Synopsis
LONG psdGetStreamError(
APTR pps)
Function
Return a stream's stored error value.
Result
The stored error value, or -1 for NULL. Zero means no error is stored;
it does not prove transfer completion or successful delivery.
Notes
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.
psdGetStringChunk()
Synopsis
STRPTR psdGetStringChunk(
APTR pic, ULONG chunkid)
Function
Copy the first matching configuration chunk into a string buffer.
Result
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.
Notes
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.
psdGetStringDescriptor()
Synopsis
STRPTR psdGetStringDescriptor(
struct PsdPipe * pp,
UWORD idx );
Function
Read a USB string descriptor and convert it to a C string.
Result
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.
Notes
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.
Bugs
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.
psdGetUsbDevCfg()
Synopsis
struct PsdIFFContext * psdGetUsbDevCfg(
STRPTR owner,
STRPTR devid,
STRPTR ifid );
Function
Find stored class configuration for a device or interface.
Result
Internal class-data IFF context, or NULL if no matching entry
exists.
Notes
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.
psdHubClaimAppBindingA()
Synopsis
APTR psdHubClaimAppBindingA(
struct TagItem *taglist)
Function
Install an application binding on an unbound device.
Result
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().
Notes
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.
psdHubClassScan()
Synopsis
VOID psdHubClassScan(
APTR pd)
Function
Try to bind installed USB classes to a device and request a hub scan.
Result
None. Allocation, configuration and binding failures are not aggregated.
Notes
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.
Bugs
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.
psdHubReleaseDevBinding()
Synopsis
VOID psdHubReleaseDevBinding(
APTR pd)
Function
Remove a device-level binding and invoke its release callback.
Result
None. Callback results are ignored.
Notes
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.
psdHubReleaseIfBinding()
Synopsis
VOID psdHubReleaseIfBinding(
APTR pif)
Function
Remove an interface binding and invoke its class release method.
Result
None. The class method result is ignored.
Notes
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.
psdLoadCfgFromDisk()
Synopsis
BOOL psdLoadCfgFromDisk(
STRPTR filename)
Function
Read a Poseidon preferences file and apply its configuration to the
running stack.
Result
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.
Notes
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.
Bugs
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.
psdLockReadDevice()
Synopsis
void psdLockReadDevice(
struct PsdDevice * pd );
Function
Acquire the shared lock for a Poseidon device.
Notes
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.
psdLockWriteDevice()
Synopsis
void psdLockWriteDevice(
struct PsdDevice * pd );
Function
Acquire the exclusive lock for a Poseidon device.
Notes
Calls pLockSemExcl() on the device's lock. The acquisition may
block, and each acquisition must be balanced with
psdUnlockDevice().
psdMatchStringChunk()
Synopsis
BOOL psdMatchStringChunk(
APTR pic, ULONG chunkid, CONST_STRPTR contents)
Function
Compare a string with the first matching configuration chunk.
Result
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.
Notes
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.
psdNumToStr()
Synopsis
STRPTR psdNumToStr(
UWORD type,
LONG idx,
STRPTR defstr );
Function
Look up a human-readable name for a USB value or enumeration.
Result
Pointer to a static lookup string or the supplied fallback.
The returned pointer is not a new Poseidon allocation.
Notes
The supported categories and mappings are implemented in the
library's lookup tables and switch statement. Callers must not
free a returned table string.
psdOpenStreamA()
Synopsis
APTR psdOpenStreamA(
APTR pep, struct TagItem *taglist)
Function
Create a buffered pipe stream for an endpoint.
Result
A stream handle, or NULL for a NULL endpoint or a detected allocation
failure. Close a successfully created stream with psdCloseStream().
Notes
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.
Bugs
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.
psdParseCfg()
Synopsis
VOID psdParseCfg(
)
Function
Apply the in-memory stack configuration to hardware and USB classes,
then scan devices for class bindings.
Result
None. Failures are not returned to the caller.
Notes
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.
Bugs
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.
psdPipeSetup()
Synopsis
void psdPipeSetup(
struct PsdPipe * pp,
UWORD rt,
UWORD rq,
UWORD val,
UWORD idx );
Function
Set the USB setup request fields on a control pipe.
Notes
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.
psdReadCfg()
Synopsis
BOOL psdReadCfg(
struct PsdIFFContext * pic,
APTR formdata );
Function
Replace a Poseidon configuration context with a serialized IFF
FORM of the same type.
Result
TRUE when the form data was accepted, otherwise FALSE.
Notes
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.
psdReleaseAppBinding()
Synopsis
void psdReleaseAppBinding(
struct PsdAppBinding * pab );
Function
Request release of an application-owned device binding.
Notes
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.
psdReleaseDevBinding()
Synopsis
VOID psdReleaseDevBinding(
APTR pd)
Function
Request release of the current device-level class or application binding.
Result
None. Dispatch and release failures are not reported.
Notes
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.
Bugs
If the parent hub has no device binding or class binding, the request
is silently skipped. Returning does not by itself prove release.
psdReleaseIfBinding()
Synopsis
VOID psdReleaseIfBinding(
APTR pif)
Function
Request release of an interface class binding.
Result
None. Dispatch and release failures are not reported.
Notes
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.
Bugs
If the parent hub has no device binding or class binding, the request
is silently skipped. Returning does not by itself prove release.
psdRemCfgChunk()
Synopsis
BOOL psdRemCfgChunk(
struct PsdIFFContext * pic,
ULONG chnkid );
Function
Remove a chunk by identifier, or clear a form's entire contents.
Result
TRUE when an entry was removed or a context was cleared,
otherwise FALSE.
Notes
The exclusive configuration lock protects modification. Clearing
with identifier zero retains the selected context object while
releasing its subordinate forms and chunks.
psdRemClass()
Synopsis
void psdRemClass(
struct PsdUsbClass * puc );
Function
Unregister and close a previously installed USB class.
Notes
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.
Bugs
EHMB_REMCLASS is queued after the class record is freed. The
event pointer cannot safely be dereferenced by receivers.
psdRemErrorMsg()
Synopsis
void psdRemErrorMsg(
struct PsdErrorMsg * pem );
Function
Remove a Poseidon error-log entry and release its storage.
Notes
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.
Bugs
EHMB_REMERRORMSG is emitted after freeing pem; consumers must
not dereference the event pointer.
psdRemEventHandler()
Synopsis
VOID psdRemEventHandler(
APTR peh)
Function
Remove an event registration and reply to queued port messages.
Notes
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.
Bugs
Drains every message on the port without checking its origin. Use a
dedicated port, not a port shared with another registration or protocol.
psdRemHardware()
Synopsis
void psdRemHardware(
struct PsdHardware * phw );
Function
Shut down a registered USB controller and release its stack state.
Notes
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.
Bugs
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.
psdResumeBindings()
Synopsis
BOOL psdResumeBindings(
APTR pd)
Function
Ask existing class bindings to resume and rescan after a failed callback.
Result
Always TRUE, including for NULL and when a class resume method fails.
The result does not certify that all bindings resumed.
Notes
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.
Bugs
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.
psdResumeDevice()
Synopsis
BOOL psdResumeDevice(
APTR pd)
Function
Request port resume through the parent hub, then resume class bindings.
Result
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.
Notes
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.
Bugs
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.
psdSafeRawDoFmtA()
Synopsis
void psdSafeRawDoFmtA(
STRPTR buf,
ULONG len,
CONST_STRPTR fmtstr,
RAWARG fmtdata );
void psdSafeRawDoFmt(
STRPTR buf,
ULONG len,
CONST_STRPTR fmtstr,
... );
Function
Write formatted text into a caller-provided bounded buffer.
Notes
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.
psdSaveCfgToDisk()
Synopsis
BOOL psdSaveCfgToDisk(
STRPTR filename, BOOL mode)
Function
Write the current configuration to a Poseidon preferences file.
Result
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.
Notes
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.
Bugs
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.
psdSendEvent()
Synopsis
VOID psdSendEvent(
ULONG ehmt, APTR param1, APTR param2)
Function
Queue a notification for each registration selecting an event.
Notes
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.
Bugs
Allocation failure drops the notification for that recipient without
a return status. Delivery is neither all-or-nothing nor guaranteed.
psdSendPipe()
Synopsis
void psdSendPipe(
struct PsdPipe * pp,
APTR data,
ULONG len );
Function
Submit a pipe transfer without waiting for completion.
Notes
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.
psdSetAltInterface()
Synopsis
BOOL psdSetAltInterface(
struct PsdPipe * pp,
struct PsdInterface * pif );
Function
Select an alternate setting of a configured USB interface.
Result
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.
Notes
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.
psdSetAttrsA()
Synopsis
LONG psdSetAttrsA(
ULONG type,
APTR psdstruct,
struct TagItem * tags );
LONG psdSetAttrs(
ULONG type,
APTR psdstruct,
TAG tag, ... );
Function
Change writable attributes of a Poseidon object.
Result
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.
Notes
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.
psdSetClsCfg()
Synopsis
BOOL psdSetClsCfg(
STRPTR owner,
APTR form );
Function
Store or clear class-specific configuration under an owner name.
Result
TRUE on successful creation or update, otherwise FALSE.
Notes
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.
psdSetDeviceConfig()
Synopsis
BOOL psdSetDeviceConfig(
struct PsdPipe * pp,
UWORD cfgnum );
Function
Select a USB device configuration through its control pipe.
Result
TRUE if SET_CONFIGURATION completed without an I/O error;
otherwise FALSE.
Notes
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.
psdSetForcedBinding()
Synopsis
BOOL psdSetForcedBinding(
STRPTR owner, STRPTR devid, STRPTR ifid)
Function
Store or remove the preferred USB class for a device or interface in
the in-memory configuration.
Result
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.
Notes
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.
Bugs
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.
psdSetUsbDevCfg()
Synopsis
BOOL psdSetUsbDevCfg(
STRPTR owner,
STRPTR devid,
STRPTR ifid,
APTR form );
Function
Save device- or interface-specific class configuration.
Result
TRUE when the matching configuration was created or updated,
otherwise FALSE.
Notes
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.
psdSpawnSubTask()
Synopsis
struct Task * psdSpawnSubTask(
STRPTR name,
APTR initpc,
APTR userdata );
Function
Start a Poseidon worker as a process when DOS is available, or
as an Exec task during early startup.
Result
New task pointer, or NULL if argument validation, allocation or
task/process creation fails.
Notes
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.
psdStartRTIso()
Synopsis
LONG psdStartRTIso(
APTR prt)
Function
Ask the controller to start a registered real-time ISO handler.
Result
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.
Notes
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.
Bugs
No running-state guard prevents repeated starts. The device-resume
result is ignored; the returned status belongs to the start command.
psdStopRTIso()
Synopsis
LONG psdStopRTIso(
APTR prt)
Function
Ask the controller to stop a running real-time ISO handler.
Result
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.
Notes
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.
Bugs
No running-state guard prevents unmatched or repeated stops. Each
successful command decrements the busy count, even without a matching
successful start.
psdStreamFlush()
Synopsis
LONG psdStreamFlush(
APTR pps)
Function
Discard pending input or submit buffered output.
Result
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.
Notes
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.
Bugs
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.
psdStreamRead()
Synopsis
LONG psdStreamRead(
APTR pps, APTR buffer, LONG length)
Function
Read bytes from an IN stream.
Result
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.
Notes
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.
Bugs
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.
psdStreamWrite()
Synopsis
LONG psdStreamWrite(
APTR pps, APTR buffer, LONG length)
Function
Write bytes to an OUT stream or accept them into its buffer.
Result
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.
Notes
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.
Bugs
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.
psdSuspendBindings()
Synopsis
BOOL psdSuspendBindings(
APTR pd)
Function
Prepare the device binding and current interface bindings for suspension.
Result
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.
Notes
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.
Bugs
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.
psdSuspendDevice()
Synopsis
BOOL psdSuspendDevice(
APTR pd)
Function
Prepare a device for suspension and request suspension of its hub port.
Result
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.
Notes
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.
Bugs
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.
psdUnbindAll()
Synopsis
VOID psdUnbindAll(
)
Function
Release device and interface bindings throughout the stack.
Notes
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.
Bugs
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.
psdUnlockDevice()
Synopsis
void psdUnlockDevice(
struct PsdDevice * pd );
Function
Release the current task's lock on a Poseidon device.
Notes
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.
psdWaitPipe()
Synopsis
LONG psdWaitPipe(
struct PsdPipe * pp );
Function
Wait for a pending pipe message and return the recorded IO error.
Result
IO error stored in the pipe request; zero indicates success.
Notes
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.
psdWriteCfg()
Synopsis
APTR psdWriteCfg(
struct PsdIFFContext * pic );
Function
Serialize a Poseidon IFF configuration context into an allocated
FORM buffer.
Result
Newly allocated serialized FORM buffer, or NULL when no suitable
root context exists or allocation fails. Free with psdFreeVec().
Notes
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.