usbhs: Use an user-specified buffer for tmem, etc.

This commit is contained in:
yellows8 2023-02-01 14:00:33 -05:00
parent 7549d3b124
commit 174b5066a5
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 22 additions and 15 deletions

View File

@ -103,10 +103,9 @@ typedef struct {
typedef struct {
Service s;
Event eventXfer; ///< [2.0.0+] Signaled when PostBufferAsync finishes.
TransferMemory tmem;
u32 maxUrbCount;
u64 max_reports;
bool tmem_initialized;
void* ringbuf;
struct usb_endpoint_descriptor desc;
} UsbHsClientEpSession;
@ -237,10 +236,18 @@ Result usbHsIfResetDevice(UsbHsClientIfSession* s);
void usbHsEpClose(UsbHsClientEpSession* s);
/// Gets the Xfer Event which is signaled when PostBufferAsync finishes. This is only valid for [2.0.0+]. If using \ref eventWait with this, then \ref eventClear should be used if the event was signaled (since the autoclear is false).
static inline Event* usbHsEpGetXferEvent(UsbHsClientEpSession* s) {
NX_CONSTEXPR Event* usbHsEpGetXferEvent(UsbHsClientEpSession* s) {
return &s->eventXfer;
}
/// Gets the buffer size to use with \ref usbHsEpShareReportRing.
NX_CONSTEXPR u32 usbHsEpGetReportRingSize(UsbHsClientEpSession* s) {
u64 max_reports = s->maxUrbCount * 0x21;
u32 size = sizeof(UsbHsRingHeader) + max_reports*sizeof(UsbHsXferReport);
size = (size+0xFFF) & ~0xFFF;
return size;
}
/**
* @brief Starts an async data transfer with the specified endpoint. The Event from \ref usbHsEpGetXferEvent can be used to determine when the transfer finished. If you don't need async, \ref usbHsEpPostBuffer can be used instead.
* @note Only available on [2.0.0+].
@ -299,6 +306,8 @@ Result usbHsEpCreateSmmuSpace(UsbHsClientEpSession* s, void* buffer, u32 size);
/**
* @brief This creates TransferMemory which is used to read \ref UsbHsXferReport when \ref usbHsEpGetXferReport is used, instead of using the service cmd.
* @note Only available on [4.0.0+].
* @param buffer Buffer, must be 0x1000-byte aligned.
* @param[in] size Buffer size, \ref usbHsEpGetReportRingSize can be used to calculate this.
*/
Result usbHsEpShareReportRing(UsbHsClientEpSession* s);
Result usbHsEpShareReportRing(UsbHsClientEpSession* s, void* buffer, size_t size);

View File

@ -377,7 +377,6 @@ void usbHsEpClose(UsbHsClientEpSession* s) {
serviceAssumeDomain(&s->s);
serviceClose(&s->s);
eventClose(&s->eventXfer);
tmemClose(&s->tmem);
memset(s, 0, sizeof(UsbHsClientEpSession));
}
@ -420,7 +419,7 @@ Result usbHsEpGetXferReport(UsbHsClientEpSession* s, UsbHsXferReport* reports, u
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (!s->tmem_initialized) {
if (s->ringbuf == NULL) {
serviceAssumeDomain(&s->s);
return serviceDispatchInOut(&s->s, 5, max_reports, *count,
.buffer_attrs = { (hosversionBefore(3,0,0) ? SfBufferAttr_HipcMapAlias : SfBufferAttr_HipcAutoSelect) | SfBufferAttr_Out },
@ -430,7 +429,7 @@ Result usbHsEpGetXferReport(UsbHsClientEpSession* s, UsbHsXferReport* reports, u
u32 total=0;
UsbHsRingHeader *hdr = (UsbHsRingHeader*)s->tmem.src_addr;
UsbHsRingHeader *hdr = (UsbHsRingHeader*)s->ringbuf;
UsbHsXferReport *ring_reports = (UsbHsXferReport*)(hdr+1);
memset(reports, 0, max_reports*sizeof(UsbHsXferReport));
@ -515,26 +514,25 @@ Result usbHsEpCreateSmmuSpace(UsbHsClientEpSession* s, void* buffer, u32 size) {
return serviceDispatchIn(&s->s, 7, in);
}
Result usbHsEpShareReportRing(UsbHsClientEpSession* s) {
Result usbHsEpShareReportRing(UsbHsClientEpSession* s, void* buffer, size_t size) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
if (s->tmem_initialized)
if (s->ringbuf)
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
s->max_reports = s->maxUrbCount * 0x21;
u32 size = sizeof(UsbHsRingHeader) + s->max_reports*sizeof(UsbHsXferReport);
size = (size+0xFFF) & ~0xFFF;
Result rc = tmemCreate(&s->tmem, size, Perm_Rw);
TransferMemory tmem={};
Result rc = tmemCreateFromMemory(&tmem, buffer, size, Perm_Rw);
if (R_FAILED(rc)) return rc;
serviceAssumeDomain(&s->s);
rc = serviceDispatchIn(&s->s, 8, size,
.in_num_handles = 1,
.in_handles = { s->tmem.handle },
.in_handles = { tmem.handle },
);
if (R_FAILED(rc)) tmemClose(&s->tmem);
else s->tmem_initialized = true;
tmemClose(&tmem);
if (R_SUCCEEDED(rc)) s->ringbuf = buffer;
return rc;
}