Updated usbhs comments and store the interface ID in UsbHsClientIfSession. Added: usbHsIfSetInterface, usbHsIfGetInterface, usbHsIfGetAlternateInterface, usbHsIfGetCurrentFrame, and usbHsIfResetDevice.

This commit is contained in:
yellows8 2018-11-29 21:15:29 -05:00
parent 83dfc58adb
commit 2049ff081d
2 changed files with 183 additions and 3 deletions

View File

@ -87,6 +87,7 @@ typedef struct {
Service s;
Event event0; ///< Unknown.
Event eventCtrlXfer; ///< [2.0.0+] Signaled when CtrlXferAsync finishes.
s32 ID;
UsbHsInterface inf; ///< Initialized with the input interface from \ref usbHsAcquireUsbIf, then the first 0x1B8-bytes are overwritten with the cmd output (data before pathstr).
} UsbHsClientIfSession;
@ -105,7 +106,7 @@ void usbHsExit(void);
Event* usbHsGetInterfaceStateChangeEvent(void);
/**
* @brief Returns an array of all \ref UsbHsInterface. Internally this loads the same interfaces as \ref usbHsQueryAvailableInterfaces, followed by \ref usbHsQueryAcquiredInterfaces.
* @brief Returns an array of all \ref UsbHsInterface. Internally this loads the same interfaces as \ref usbHsQueryAvailableInterfaces, followed by \ref usbHsQueryAcquiredInterfaces. However, ID in \ref UsbHsInterface is set to -1, hence the output from this should not be used with \ref usbHsAcquireUsbIf.
* @param[in] filter \ref UsbHsInterfaceFilter.
* @param[out] interfaces Array of output interfaces.
* @param[in] interfaces_maxsize Max byte-size of the interfaces buffer.
@ -147,7 +148,7 @@ Result usbHsCreateInterfaceAvailableEvent(Event* event, bool autoclear, u8 index
Result usbHsDestroyInterfaceAvailableEvent(Event* event, u8 index);
/**
* @brief Acquires/opens the specified interface.
* @brief Acquires/opens the specified interface. This returns an error if the interface was already acquired by another process.
* @param[in] s The service object.
* @param[in] interface Interface to use.
*/
@ -158,3 +159,32 @@ Result usbHsAcquireUsbIf(UsbHsClientIfSession* s, UsbHsInterface *interface);
/// Closes the specified interface session.
void usbHsIfClose(UsbHsClientIfSession* s);
/**
* @brief Selects an interface.
* @param[in] s The service object.
* @param[out] inf The output interface info. If NULL, the output is stored within s instead.
* @param[in] id ID
*/
Result usbHsIfSetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id);
/**
* @brief Gets an interface.
* @param[in] s The service object.
* @param[out] inf The output interface info. If NULL, the output is stored within s instead.
*/
Result usbHsIfGetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf);
/**
* @brief Gets an alternate interface.
* @param[in] s The service object.
* @param[out] inf The output interface info. If NULL, the output is stored within s instead.
* @param[in] id ID
*/
Result usbHsIfGetAlternateInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id);
/// On 1.0.0 this is stubbed, just returns 0 with out=0.
Result usbHsIfGetCurrentFrame(UsbHsClientIfSession* s, u32* out);
/// Resets the device: has the same affect as unplugging the device and plugging it back in.
Result usbHsIfResetDevice(UsbHsClientIfSession* s);

View File

@ -297,6 +297,7 @@ Result usbHsAcquireUsbIf(UsbHsClientIfSession* s, UsbHsInterface *interface) {
memset(s, 0, sizeof(UsbHsClientIfSession));
memcpy(&s->inf, interface, sizeof(UsbHsInterface));
s->ID = interface->inf.ID;
struct {
u64 magic;
@ -310,7 +311,7 @@ Result usbHsAcquireUsbIf(UsbHsClientIfSession* s, UsbHsInterface *interface) {
raw->magic = SFCI_MAGIC;
raw->cmd_id = kernelAbove200() ? 7 : 6;
raw->ID = interface->inf.ID;
raw->ID = s->ID;
Result rc = serviceIpcDispatch(&g_usbHsSrv);
@ -352,3 +353,152 @@ void usbHsIfClose(UsbHsClientIfSession* s) {
memset(s, 0, sizeof(UsbHsClientIfSession));
}
static Result _usbHsIfGetInf(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
if (inf==NULL) inf = &s->inf.inf;
struct {
u64 magic;
u64 cmd_id;
u8 id;
} *raw;
ipcAddRecvBuffer(&c, inf, sizeof(UsbHsInterfaceInfo), BufferType_Normal);
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
raw->id = id;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result usbHsIfSetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id) {
return _usbHsIfGetInf(s, inf, id, 1);
}
Result usbHsIfGetAlternateInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf, u8 id) {
return _usbHsIfGetInf(s, inf, id, 3);
}
Result usbHsIfGetInterface(UsbHsClientIfSession* s, UsbHsInterfaceInfo* inf) {
IpcCommand c;
ipcInitialize(&c);
if (inf==NULL) inf = &s->inf.inf;
struct {
u64 magic;
u64 cmd_id;
} *raw;
ipcAddRecvBuffer(&c, inf, sizeof(UsbHsInterfaceInfo), BufferType_Normal);
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}
Result usbHsIfGetCurrentFrame(UsbHsClientIfSession* s, u32* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = kernelAbove200() ? 4 : 5;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u32 out;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->out;
}
return rc;
}
Result usbHsIfResetDevice(UsbHsClientIfSession* s) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
Result rc = serviceIpcDispatch(&s->s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
}