mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 04:22:50 +02:00
usbcomms: add async API
This commit is contained in:
parent
dca4fb772a
commit
51fce6e4c3
@ -26,6 +26,9 @@ void usbCommsExit(void);
|
||||
/// Sets whether to throw a fatal error in usbComms{Read/Write}* on failure, or just return the transferred size. By default (false) the latter is used.
|
||||
void usbCommsSetErrorHandling(bool flag);
|
||||
|
||||
///@name Synchronous API
|
||||
///@{
|
||||
|
||||
/// Read data with the default interface.
|
||||
size_t usbCommsRead(void* buffer, size_t size);
|
||||
|
||||
@ -37,3 +40,31 @@ size_t usbCommsReadEx(void* buffer, size_t size, u32 interface);
|
||||
|
||||
/// Same as usbCommsWrite except with the specified interface.
|
||||
size_t usbCommsWriteEx(const void* buffer, size_t size, u32 interface);
|
||||
|
||||
///@}
|
||||
|
||||
///@name Asynchronous API
|
||||
///@{
|
||||
|
||||
/// Retrieve event used for read completion with the given interface.
|
||||
Event *usbCommsGetReadCompletionEvent(u32 interface);
|
||||
|
||||
/// Start an asynchronous read. The completion event will be signaled when the read completes.
|
||||
/// The buffer must be page-aligned and no larger than one page.
|
||||
Result usbCommsReadAsync(void *buffer, size_t size, u32 *urbId, u32 interface);
|
||||
|
||||
/// Complete an asynchronous read, clearing the completion event, and return the amount of data which was read.
|
||||
Result usbCommsGetReadResult(u32 urbId, u32 *transferredSize, u32 interface);
|
||||
|
||||
|
||||
/// Retrieve event used for write completion with the given interface.
|
||||
Event *usbCommsGetWriteCompletionEvent(u32 interface);
|
||||
|
||||
/// Start an asynchronous write. The completion event will be signaled when the write completes.
|
||||
/// The buffer must be page-aligned and no larger than one page.
|
||||
Result usbCommsWriteAsync(void *buffer, size_t size, u32 *urbId, u32 interface);
|
||||
|
||||
/// Complete an asynchronous write, clearing the completion event, and return the amount of data which was written.
|
||||
Result usbCommsGetWriteResult(u32 urbId, u32 *transferredSize, u32 interface);
|
||||
|
||||
///@}
|
||||
|
@ -462,6 +462,28 @@ static Result _usbCommsRead(usbCommsInterface *interface, void* buffer, size_t s
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _usbCommsReadAsync(usbCommsInterface *interface, void *buffer, size_t size, u32 *urbId)
|
||||
{
|
||||
if (((uintptr_t)buffer) & 0xfff)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
// Start a host->device transfer.
|
||||
return usbDsEndpoint_PostBufferAsync(interface->endpoint_out, buffer, size, urbId);
|
||||
}
|
||||
|
||||
static Result _usbCommsGetReadResult(usbCommsInterface *interface, u32 urbId, u32 *transferredSize)
|
||||
{
|
||||
Result rc=0;
|
||||
UsbDsReportData reportdata;
|
||||
|
||||
eventClear(&interface->endpoint_out->CompletionEvent);
|
||||
|
||||
rc = usbDsEndpoint_GetReportData(interface->endpoint_out, &reportdata);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
return usbDsParseReportData(&reportdata, urbId, NULL, transferredSize);
|
||||
}
|
||||
|
||||
static Result _usbCommsWrite(usbCommsInterface *interface, const void* buffer, size_t size, size_t *transferredSize)
|
||||
{
|
||||
Result rc=0;
|
||||
@ -525,6 +547,28 @@ static Result _usbCommsWrite(usbCommsInterface *interface, const void* buffer, s
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _usbCommsWriteAsync(usbCommsInterface *interface, void *buffer, size_t size, u32 *urbId)
|
||||
{
|
||||
if (((uintptr_t)buffer) & 0xfff)
|
||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
// Start a device->host transfer.
|
||||
return usbDsEndpoint_PostBufferAsync(interface->endpoint_in, buffer, size, urbId);
|
||||
}
|
||||
|
||||
static Result _usbCommsGetWriteResult(usbCommsInterface *interface, u32 urbId, u32 *transferredSize)
|
||||
{
|
||||
Result rc=0;
|
||||
UsbDsReportData reportdata;
|
||||
|
||||
eventClear(&interface->endpoint_in->CompletionEvent);
|
||||
|
||||
rc = usbDsEndpoint_GetReportData(interface->endpoint_in, &reportdata);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
return usbDsParseReportData(&reportdata, urbId, NULL, transferredSize);
|
||||
}
|
||||
|
||||
size_t usbCommsReadEx(void* buffer, size_t size, u32 interface)
|
||||
{
|
||||
size_t transferredSize=0;
|
||||
@ -562,6 +606,63 @@ size_t usbCommsRead(void* buffer, size_t size)
|
||||
return usbCommsReadEx(buffer, size, 0);
|
||||
}
|
||||
|
||||
Event *usbCommsGetReadCompletionEvent(u32 interface)
|
||||
{
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return NULL;
|
||||
|
||||
rwlockReadLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockReadUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return NULL;
|
||||
return &inter->endpoint_out->CompletionEvent;
|
||||
}
|
||||
|
||||
Result usbCommsReadAsync(void *buffer, size_t size, u32 *urbId, u32 interface)
|
||||
{
|
||||
Result rc;
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsRead);
|
||||
|
||||
rwlockReadLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockReadUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsRead);
|
||||
|
||||
rwlockWriteLock(&inter->lock_out);
|
||||
rc = _usbCommsReadAsync(inter, buffer, size, urbId);
|
||||
rwlockWriteUnlock(&inter->lock_out);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result usbCommsGetReadResult(u32 urbId, u32 *transferredSize, u32 interface)
|
||||
{
|
||||
Result rc;
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsRead);
|
||||
|
||||
rwlockReadLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockReadUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsRead);
|
||||
|
||||
rwlockWriteLock(&inter->lock_out);
|
||||
rc = _usbCommsGetReadResult(inter, urbId, transferredSize);
|
||||
rwlockWriteUnlock(&inter->lock_out);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
size_t usbCommsWriteEx(const void* buffer, size_t size, u32 interface)
|
||||
{
|
||||
size_t transferredSize=0;
|
||||
@ -599,3 +700,59 @@ size_t usbCommsWrite(const void* buffer, size_t size)
|
||||
return usbCommsWriteEx(buffer, size, 0);
|
||||
}
|
||||
|
||||
Event *usbCommsGetWriteCompletionEvent(u32 interface)
|
||||
{
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return NULL;
|
||||
|
||||
rwlockWriteLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockWriteUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return NULL;
|
||||
return &inter->endpoint_in->CompletionEvent;
|
||||
}
|
||||
|
||||
Result usbCommsWriteAsync(void *buffer, size_t size, u32 *urbId, u32 interface)
|
||||
{
|
||||
Result rc;
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsWrite);
|
||||
|
||||
rwlockWriteLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockWriteUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsWrite);
|
||||
|
||||
rwlockWriteLock(&inter->lock_in);
|
||||
rc = _usbCommsWriteAsync(inter, buffer, size, urbId);
|
||||
rwlockWriteUnlock(&inter->lock_in);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result usbCommsGetWriteResult(u32 urbId, u32 *transferredSize, u32 interface)
|
||||
{
|
||||
Result rc;
|
||||
usbCommsInterface *inter = &g_usbCommsInterfaces[interface];
|
||||
bool initialized;
|
||||
|
||||
if (interface >= TOTAL_INTERFACES) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsWrite);
|
||||
|
||||
rwlockWriteLock(&inter->lock);
|
||||
initialized = inter->initialized;
|
||||
rwlockWriteUnlock(&inter->lock);
|
||||
|
||||
if (!initialized) return MAKERESULT(Module_Libnx, LibnxError_BadUsbCommsWrite);
|
||||
|
||||
rwlockWriteLock(&inter->lock_in);
|
||||
rc = _usbCommsGetWriteResult(inter, urbId, transferredSize);
|
||||
rwlockWriteUnlock(&inter->lock_in);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user