mirror of
https://github.com/switchbrew/libnx.git
synced 2025-07-04 10:32:15 +02:00
Merge branch 'master' of https://github.com/switchbrew/libnx into dev
This commit is contained in:
commit
78ad8a2863
@ -17,7 +17,6 @@ extern "C" {
|
|||||||
|
|
||||||
#include "switch/arm/tls.h"
|
#include "switch/arm/tls.h"
|
||||||
#include "switch/arm/cache.h"
|
#include "switch/arm/cache.h"
|
||||||
#include "switch/arm/atomics.h"
|
|
||||||
#include "switch/arm/counter.h"
|
#include "switch/arm/counter.h"
|
||||||
|
|
||||||
#include "switch/kernel/svc.h"
|
#include "switch/kernel/svc.h"
|
||||||
@ -75,6 +74,7 @@ extern "C" {
|
|||||||
#include "switch/services/usbds.h"
|
#include "switch/services/usbds.h"
|
||||||
#include "switch/services/usbhs.h"
|
#include "switch/services/usbhs.h"
|
||||||
#include "switch/services/hid.h"
|
#include "switch/services/hid.h"
|
||||||
|
#include "switch/services/hidbus.h"
|
||||||
#include "switch/services/hiddbg.h"
|
#include "switch/services/hiddbg.h"
|
||||||
#include "switch/services/hidsys.h"
|
#include "switch/services/hidsys.h"
|
||||||
#include "switch/services/irs.h"
|
#include "switch/services/irs.h"
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file atomics.h
|
|
||||||
* @brief AArch64 atomic operations.
|
|
||||||
* @author plutoo
|
|
||||||
* @copyright libnx Authors
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include "../types.h"
|
|
||||||
|
|
||||||
/// Atomically increments a 32-bit value.
|
|
||||||
static inline u32 atomicIncrement32(u32* p) {
|
|
||||||
return __atomic_fetch_add(p, 1, __ATOMIC_SEQ_CST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atomically decrements a 32-bit value.
|
|
||||||
static inline u32 atomicDecrement32(u32* p) {
|
|
||||||
return __atomic_sub_fetch(p, 1, __ATOMIC_SEQ_CST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atomically increments a 64-bit value.
|
|
||||||
static inline u64 atomicIncrement64(u64* p) {
|
|
||||||
return __atomic_fetch_add(p, 1, __ATOMIC_SEQ_CST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Atomically decrements a 64-bit value.
|
|
||||||
static inline u64 atomicDecrement64(u64* p) {
|
|
||||||
return __atomic_sub_fetch(p, 1, __ATOMIC_SEQ_CST);
|
|
||||||
}
|
|
@ -40,7 +40,7 @@ Result condvarWaitTimeout(CondVar* c, Mutex* m, u64 timeout);
|
|||||||
*/
|
*/
|
||||||
static inline Result condvarWait(CondVar* c, Mutex* m)
|
static inline Result condvarWait(CondVar* c, Mutex* m)
|
||||||
{
|
{
|
||||||
return condvarWaitTimeout(c, m, U64_MAX);
|
return condvarWaitTimeout(c, m, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +188,7 @@ typedef enum {
|
|||||||
TickCountInfo_Core2 = 2, ///< Tick count on core 2.
|
TickCountInfo_Core2 = 2, ///< Tick count on core 2.
|
||||||
TickCountInfo_Core3 = 3, ///< Tick count on core 3.
|
TickCountInfo_Core3 = 3, ///< Tick count on core 3.
|
||||||
|
|
||||||
TickCountInfo_Total = U64_MAX, ///< Tick count on all cores.
|
TickCountInfo_Total = UINT64_MAX, ///< Tick count on all cores.
|
||||||
} TickCountInfo;
|
} TickCountInfo;
|
||||||
|
|
||||||
/// GetInfo InitialProcessIdRange Sub IDs.
|
/// GetInfo InitialProcessIdRange Sub IDs.
|
||||||
|
@ -1003,7 +1003,7 @@ Result appletLockAccessorTryLock(AppletLockAccessor *a, bool *flag);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Lock a LockAccessor.
|
* @brief Lock a LockAccessor.
|
||||||
* @note Similar to \ref appletLockAccessorTryLock, except this uses timeout U64_MAX with the eventWait call, and this uses TryLock repeatedly until the output flag value is true.
|
* @note Similar to \ref appletLockAccessorTryLock, except this uses timeout UINT64_MAX with the eventWait call, and this uses TryLock repeatedly until the output flag value is true.
|
||||||
* @param a LockAccessor object.
|
* @param a LockAccessor object.
|
||||||
*/
|
*/
|
||||||
Result appletLockAccessorLock(AppletLockAccessor *a);
|
Result appletLockAccessorLock(AppletLockAccessor *a);
|
||||||
@ -1095,7 +1095,7 @@ Result appletHolderTerminate(AppletHolder *h);
|
|||||||
/**
|
/**
|
||||||
* @brief Uses cmds GetAppletStateChangedEvent and RequestExit, then waits for the LibraryApplet to exit with the specified timeout. If a timeout occurs, the Terminate cmd is used.
|
* @brief Uses cmds GetAppletStateChangedEvent and RequestExit, then waits for the LibraryApplet to exit with the specified timeout. If a timeout occurs, the Terminate cmd is used.
|
||||||
* @param h AppletHolder object.
|
* @param h AppletHolder object.
|
||||||
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
|
* @param[in] timeout Timeout in nanoseconds. UINT64_MAX for no timeout.
|
||||||
*/
|
*/
|
||||||
Result appletHolderRequestExitOrTerminate(AppletHolder *h, u64 timeout);
|
Result appletHolderRequestExitOrTerminate(AppletHolder *h, u64 timeout);
|
||||||
|
|
||||||
@ -1792,7 +1792,7 @@ Result appletApplicationAreAnyLibraryAppletsLeft(AppletApplication *a, bool *out
|
|||||||
/**
|
/**
|
||||||
* @brief Calls the same func as \ref appletHolderRequestExitOrTerminate with the output IAppletAccessor from the GetCurrentLibraryApplet cmd.
|
* @brief Calls the same func as \ref appletHolderRequestExitOrTerminate with the output IAppletAccessor from the GetCurrentLibraryApplet cmd.
|
||||||
* @param a \ref AppletApplication
|
* @param a \ref AppletApplication
|
||||||
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
|
* @param[in] timeout Timeout in nanoseconds. UINT64_MAX for no timeout.
|
||||||
*/
|
*/
|
||||||
Result appletApplicationRequestExitLibraryAppletOrTerminate(AppletApplication *a, u64 timeout);
|
Result appletApplicationRequestExitLibraryAppletOrTerminate(AppletApplication *a, u64 timeout);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ typedef struct {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close a \ref AsyncValue.
|
* @brief Close a \ref AsyncValue.
|
||||||
* @note When the object is initialized, this uses \ref asyncValueCancel then \ref asyncValueWait with timeout=U64_MAX.
|
* @note When the object is initialized, this uses \ref asyncValueCancel then \ref asyncValueWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref AsyncValue
|
* @param a \ref AsyncValue
|
||||||
*/
|
*/
|
||||||
void asyncValueClose(AsyncValue *a);
|
void asyncValueClose(AsyncValue *a);
|
||||||
@ -35,7 +35,7 @@ void asyncValueClose(AsyncValue *a);
|
|||||||
/**
|
/**
|
||||||
* @brief Waits for the async operation to finish using the specified timeout.
|
* @brief Waits for the async operation to finish using the specified timeout.
|
||||||
* @param a \ref AsyncValue
|
* @param a \ref AsyncValue
|
||||||
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
|
* @param[in] timeout Timeout in nanoseconds. UINT64_MAX for no timeout.
|
||||||
*/
|
*/
|
||||||
Result asyncValueWait(AsyncValue *a, u64 timeout);
|
Result asyncValueWait(AsyncValue *a, u64 timeout);
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ Result asyncValueGetSize(AsyncValue *a, u64 *size);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the value.
|
* @brief Gets the value.
|
||||||
* @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=U64_MAX.
|
* @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref AsyncValue
|
* @param a \ref AsyncValue
|
||||||
* @param[out] buffer Output buffer.
|
* @param[out] buffer Output buffer.
|
||||||
* @param[in] size Output buffer size.
|
* @param[in] size Output buffer size.
|
||||||
@ -77,7 +77,7 @@ Result asyncValueGetErrorContext(AsyncValue *a, ErrorContext *context);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close a \ref AsyncResult.
|
* @brief Close a \ref AsyncResult.
|
||||||
* @note When the object is initialized, this uses \ref asyncResultCancel then \ref asyncResultWait with timeout=U64_MAX.
|
* @note When the object is initialized, this uses \ref asyncResultCancel then \ref asyncResultWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref AsyncResult
|
* @param a \ref AsyncResult
|
||||||
*/
|
*/
|
||||||
void asyncResultClose(AsyncResult *a);
|
void asyncResultClose(AsyncResult *a);
|
||||||
@ -85,13 +85,13 @@ void asyncResultClose(AsyncResult *a);
|
|||||||
/**
|
/**
|
||||||
* @brief Waits for the async operation to finish using the specified timeout.
|
* @brief Waits for the async operation to finish using the specified timeout.
|
||||||
* @param a \ref AsyncResult
|
* @param a \ref AsyncResult
|
||||||
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
|
* @param[in] timeout Timeout in nanoseconds. UINT64_MAX for no timeout.
|
||||||
*/
|
*/
|
||||||
Result asyncResultWait(AsyncResult *a, u64 timeout);
|
Result asyncResultWait(AsyncResult *a, u64 timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the Result.
|
* @brief Gets the Result.
|
||||||
* @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=U64_MAX.
|
* @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref AsyncResult
|
* @param a \ref AsyncResult
|
||||||
*/
|
*/
|
||||||
Result asyncResultGet(AsyncResult *a);
|
Result asyncResultGet(AsyncResult *a);
|
||||||
|
@ -63,7 +63,7 @@ Result audinCaptureBuffer(AudioInBuffer *source, AudioInBuffer **released);
|
|||||||
* @brief Waits for audio capture to finish.
|
* @brief Waits for audio capture to finish.
|
||||||
* @param released AudioInBuffer to receive the first captured buffer after being released.
|
* @param released AudioInBuffer to receive the first captured buffer after being released.
|
||||||
* @param released_count Pointer to receive the number of captured buffers.
|
* @param released_count Pointer to receive the number of captured buffers.
|
||||||
* @param timeout Timeout value, use U64_MAX to wait until all finished.
|
* @param timeout Timeout value, use UINT64_MAX to wait until all finished.
|
||||||
*/
|
*/
|
||||||
Result audinWaitCaptureFinish(AudioInBuffer **released, u32* released_count, u64 timeout);
|
Result audinWaitCaptureFinish(AudioInBuffer **released, u32* released_count, u64 timeout);
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Result audoutPlayBuffer(AudioOutBuffer *source, AudioOutBuffer **released);
|
|||||||
* @brief Waits for audio playback to finish.
|
* @brief Waits for audio playback to finish.
|
||||||
* @param released AudioOutBuffer to receive the first played buffer after being released.
|
* @param released AudioOutBuffer to receive the first played buffer after being released.
|
||||||
* @param released_count Pointer to receive the number of played buffers.
|
* @param released_count Pointer to receive the number of played buffers.
|
||||||
* @param timeout Timeout value, use U64_MAX to wait until all finished.
|
* @param timeout Timeout value, use UINT64_MAX to wait until all finished.
|
||||||
*/
|
*/
|
||||||
Result audoutWaitPlayFinish(AudioOutBuffer **released, u32* released_count, u64 timeout);
|
Result audoutWaitPlayFinish(AudioOutBuffer **released, u32* released_count, u64 timeout);
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ typedef struct SixAxisSensorValues {
|
|||||||
} SixAxisSensorValues;
|
} SixAxisSensorValues;
|
||||||
|
|
||||||
#define JOYSTICK_MAX (0x7FFF)
|
#define JOYSTICK_MAX (0x7FFF)
|
||||||
#define JOYSTICK_MIN (-0x8000)
|
#define JOYSTICK_MIN (-0x7FFF)
|
||||||
|
|
||||||
// End enums and output structs
|
// End enums and output structs
|
||||||
|
|
||||||
|
219
nx/include/switch/services/hidbus.h
Normal file
219
nx/include/switch/services/hidbus.h
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/**
|
||||||
|
* @file hidbus.h
|
||||||
|
* @brief hidbus service IPC wrapper, for using external devices attached to HID controllers. See also: https://switchbrew.org/wiki/HID_services#hidbus
|
||||||
|
* @note Only available on [5.0.0+].
|
||||||
|
* @author yellows8
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../kernel/event.h"
|
||||||
|
#include "../services/hid.h"
|
||||||
|
#include "../sf/service.h"
|
||||||
|
|
||||||
|
/// BusType
|
||||||
|
typedef enum {
|
||||||
|
HidbusBusType_JoyLeftRail = 0, ///< JoyLeftRail
|
||||||
|
HidbusBusType_JoyRightRail = 1, ///< JoyRightRail
|
||||||
|
HidbusBusType_LarkRightRail = 2, ///< [6.0.0+] LarkRightRail (for microphone).
|
||||||
|
} HidbusBusType;
|
||||||
|
|
||||||
|
/// JoyPollingMode
|
||||||
|
typedef enum {
|
||||||
|
HidbusJoyPollingMode_JoyDisableSixAxisPollingData = 0, ///< JoyDisableSixAxisPollingData
|
||||||
|
HidbusJoyPollingMode_JoyEnableSixAxisPollingData = 1, ///< JoyEnableSixAxisPollingData
|
||||||
|
HidbusJoyPollingMode_JoyButtonOnlyPollingData = 2, ///< [6.0.0+] JoyButtonOnlyPollingData
|
||||||
|
} HidbusJoyPollingMode;
|
||||||
|
|
||||||
|
/// BusHandle
|
||||||
|
typedef struct {
|
||||||
|
u32 abstracted_pad_id; ///< AbstractedPadId
|
||||||
|
u8 internal_index; ///< InternalIndex
|
||||||
|
u8 player_number; ///< PlayerNumber
|
||||||
|
u8 bus_type_id; ///< BusTypeId
|
||||||
|
u8 is_valid; ///< IsValid
|
||||||
|
} HidbusBusHandle;
|
||||||
|
|
||||||
|
/// JoyPollingReceivedData
|
||||||
|
typedef struct {
|
||||||
|
u8 data[0x30]; ///< Data.
|
||||||
|
u64 size; ///< Size of data.
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
} HidbusJoyPollingReceivedData;
|
||||||
|
|
||||||
|
/// HidbusDataAccessorHeader
|
||||||
|
typedef struct {
|
||||||
|
Result res; ///< Result.
|
||||||
|
u32 pad; ///< Padding.
|
||||||
|
u8 unused[0x18]; ///< Initialized sysmodule-side, not used by sdknso.
|
||||||
|
u64 latest_entry; ///< Latest entry.
|
||||||
|
u64 total_entries; ///< Total entries.
|
||||||
|
} HidbusDataAccessorHeader;
|
||||||
|
|
||||||
|
/// HidbusJoyDisableSixAxisPollingDataAccessorEntryData
|
||||||
|
typedef struct {
|
||||||
|
u8 data[0x26]; ///< Data.
|
||||||
|
u8 size; ///< Size of data.
|
||||||
|
u8 pad; ///< Padding.
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
} HidbusJoyDisableSixAxisPollingDataAccessorEntryData;
|
||||||
|
|
||||||
|
/// HidbusJoyDisableSixAxisPollingDataAccessorEntry
|
||||||
|
typedef struct {
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
HidbusJoyDisableSixAxisPollingDataAccessorEntryData data; ///< \ref HidbusJoyDisableSixAxisPollingDataAccessorEntryData
|
||||||
|
} HidbusJoyDisableSixAxisPollingDataAccessorEntry;
|
||||||
|
|
||||||
|
/// HidbusJoyEnableSixAxisPollingDataAccessorEntryData
|
||||||
|
typedef struct {
|
||||||
|
u8 data[0x8]; ///< Data.
|
||||||
|
u8 size; ///< Size of data.
|
||||||
|
u8 pad[7]; ///< Padding.
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
} HidbusJoyEnableSixAxisPollingDataAccessorEntryData;
|
||||||
|
|
||||||
|
/// HidbusJoyEnableSixAxisPollingDataAccessorEntry
|
||||||
|
typedef struct {
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
HidbusJoyEnableSixAxisPollingDataAccessorEntryData data; ///< \ref HidbusJoyEnableSixAxisPollingDataAccessorEntryData
|
||||||
|
} HidbusJoyEnableSixAxisPollingDataAccessorEntry;
|
||||||
|
|
||||||
|
/// HidbusJoyButtonOnlyPollingDataAccessorEntryData
|
||||||
|
typedef struct {
|
||||||
|
u8 data[0x2c]; ///< Data.
|
||||||
|
u8 size; ///< Size of data.
|
||||||
|
u8 pad[3]; ///< Padding.
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
} HidbusJoyButtonOnlyPollingDataAccessorEntryData;
|
||||||
|
|
||||||
|
/// HidbusJoyButtonOnlyPollingDataAccessorEntry
|
||||||
|
typedef struct {
|
||||||
|
u64 timestamp; ///< Timestamp.
|
||||||
|
HidbusJoyButtonOnlyPollingDataAccessorEntryData data; ///< \ref HidbusJoyEnableSixAxisPollingDataAccessorEntryData
|
||||||
|
} HidbusJoyButtonOnlyPollingDataAccessorEntry;
|
||||||
|
|
||||||
|
/// HidbusJoyDisableSixAxisPollingDataAccessor
|
||||||
|
typedef struct {
|
||||||
|
HidbusDataAccessorHeader hdr; ///< \ref HidbusDataAccessorHeader
|
||||||
|
HidbusJoyDisableSixAxisPollingDataAccessorEntry entries[0xb]; ///< \ref HidbusJoyDisableSixAxisPollingDataAccessorEntry
|
||||||
|
} HidbusJoyDisableSixAxisPollingDataAccessor;
|
||||||
|
|
||||||
|
/// HidbusJoyEnableSixAxisPollingDataAccessor
|
||||||
|
typedef struct {
|
||||||
|
HidbusDataAccessorHeader hdr; ///< \ref HidbusDataAccessorHeader
|
||||||
|
HidbusJoyEnableSixAxisPollingDataAccessorEntry entries[0xb]; ///< \ref HidbusJoyEnableSixAxisPollingDataAccessorEntry
|
||||||
|
} HidbusJoyEnableSixAxisPollingDataAccessor;
|
||||||
|
|
||||||
|
/// HidbusJoyButtonOnlyPollingDataAccessor
|
||||||
|
typedef struct {
|
||||||
|
HidbusDataAccessorHeader hdr; ///< \ref HidbusDataAccessorHeader
|
||||||
|
HidbusJoyButtonOnlyPollingDataAccessorEntry entries[0xb]; ///< \ref HidbusJoyButtonOnlyPollingDataAccessorEntry
|
||||||
|
} HidbusJoyButtonOnlyPollingDataAccessor;
|
||||||
|
|
||||||
|
/// Common data for HidbusStatusManagerEntry*.
|
||||||
|
typedef struct {
|
||||||
|
u8 flag_x0; ///< Flag.
|
||||||
|
u8 pad[3]; ///< Padding.
|
||||||
|
Result res; ///< Result.
|
||||||
|
u8 device_enabled; ///< Flag indicating whether a device is enabled (\ref hidbusEnableExternalDevice).
|
||||||
|
u8 is_valid; ///< Flag indicating whether this entry is valid.
|
||||||
|
u8 polling_enabled; ///< Flag indicating whether polling is enabled (\ref hidbusEnableJoyPollingReceiveMode).
|
||||||
|
u8 unk_xb; ///< Unknown / padding?
|
||||||
|
u32 polling_mode; ///< \ref HidbusJoyPollingMode
|
||||||
|
} HidbusStatusManagerEntryCommon;
|
||||||
|
|
||||||
|
/// HidbusStatusManagerEntry on 5.x.
|
||||||
|
typedef struct {
|
||||||
|
HidbusStatusManagerEntryCommon common; ///< \ref HidbusStatusManagerEntryCommon
|
||||||
|
u8 unk_x10[0xf0]; ///< Ignored by official sw.
|
||||||
|
} HidbusStatusManagerEntryV5;
|
||||||
|
|
||||||
|
/// HidbusStatusManagerEntry
|
||||||
|
typedef struct {
|
||||||
|
HidbusStatusManagerEntryCommon common; ///< \ref HidbusStatusManagerEntryCommon
|
||||||
|
u8 unk_x10[0x70]; ///< Ignored by official sw.
|
||||||
|
} HidbusStatusManagerEntry;
|
||||||
|
|
||||||
|
/// StatusManager on 5.x.
|
||||||
|
typedef struct {
|
||||||
|
HidbusStatusManagerEntryV5 entries[0x10]; ///< \ref HidbusStatusManagerEntryV5
|
||||||
|
} HidbusStatusManagerV5;
|
||||||
|
|
||||||
|
/// StatusManager
|
||||||
|
typedef struct {
|
||||||
|
HidbusStatusManagerEntry entries[0x13]; ///< \ref HidbusStatusManagerEntry
|
||||||
|
u8 unused[0x680]; ///< Unused.
|
||||||
|
} HidbusStatusManager;
|
||||||
|
|
||||||
|
/// Gets the Service object for the actual hidbus service session. This object must be closed by the user once finished using cmds with this.
|
||||||
|
Result hidbusGetServiceSession(Service* srv_out);
|
||||||
|
|
||||||
|
/// Gets the SharedMemory addr (\ref HidbusStatusManagerV5 on 5.x, otherwise \ref HidbusStatusManager). Only valid when at least one BusHandle is currently initialized (\ref hidbusInitialize).
|
||||||
|
void* hidbusGetSharedmemAddr(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBusHandle
|
||||||
|
* @param[out] handle \ref HidbusBusHandle
|
||||||
|
* @param[out] flag Output flag indicating whether the handle is valid.
|
||||||
|
* @param[in] id \ref HidControllerID
|
||||||
|
* @param[in] bus_type \ref HidbusBusType
|
||||||
|
*/
|
||||||
|
Result hidbusGetBusHandle(HidbusBusHandle *handle, bool *flag, HidControllerID id, HidbusBusType bus_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
*/
|
||||||
|
Result hidbusInitialize(HidbusBusHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finalize
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
*/
|
||||||
|
Result hidbusFinalize(HidbusBusHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EnableExternalDevice
|
||||||
|
* @note This uses \ref hidLaShowControllerFirmwareUpdate if needed.
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
* @param[in] flag Whether to enable the device (true = enable, false = disable). When false, this will internally use \ref hidbusDisableJoyPollingReceiveMode if needed.
|
||||||
|
* @param[in] device_id ExternalDeviceId which must match the connected device. Only used when flag is set.
|
||||||
|
*/
|
||||||
|
Result hidbusEnableExternalDevice(HidbusBusHandle handle, bool flag, u32 device_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SendAndReceive
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
* @param[in] inbuf Input buffer, containing the command data.
|
||||||
|
* @param[in] inbuf_size Input buffer size, must be <0x26.
|
||||||
|
* @param[out] outbuf Output buffer, containing the command reply data.
|
||||||
|
* @param[in] outbuf_size Output buffer max size.
|
||||||
|
* @param[out] out_size Actual output size.
|
||||||
|
*/
|
||||||
|
Result hidbusSendAndReceive(HidbusBusHandle handle, const void* inbuf, size_t inbuf_size, void* outbuf, size_t outbuf_size, u64 *out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EnableJoyPollingReceiveMode
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
* @param[in] inbuf Input buffer, containing the command data.
|
||||||
|
* @param[in] inbuf_size Input buffer size, must be <0x26.
|
||||||
|
* @param[out] workbuf TransferMemory buffer, must be 0x1000-byte aligned. This buffer must not be written to until after \ref hidbusDisableJoyPollingReceiveMode is used.
|
||||||
|
* @param[in] workbuf_size TransferMemory buffer size, must be 0x1000-byte aligned.
|
||||||
|
* @param[in] polling_mode \ref HidbusJoyPollingMode
|
||||||
|
*/
|
||||||
|
Result hidbusEnableJoyPollingReceiveMode(HidbusBusHandle handle, const void* inbuf, size_t inbuf_size, void* workbuf, size_t workbuf_size, HidbusJoyPollingMode polling_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DisableJoyPollingReceiveMode
|
||||||
|
* @note This can also be used via \ref hidbusEnableExternalDevice with flag=false.
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
*/
|
||||||
|
Result hidbusDisableJoyPollingReceiveMode(HidbusBusHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetJoyPollingReceivedData
|
||||||
|
* @param[in] handle \ref HidbusBusHandle
|
||||||
|
* @param[out] recv_data Output array of \ref HidbusJoyPollingReceivedData.
|
||||||
|
* @param[in] count Total entries for the recv_data array. The maximum is 0xa. Official apps use range 0x1-0x9.
|
||||||
|
*/
|
||||||
|
Result hidbusGetJoyPollingReceivedData(HidbusBusHandle handle, HidbusJoyPollingReceivedData *recv_data, s32 count);
|
||||||
|
|
@ -1239,7 +1239,7 @@ Result nsProgressMonitorForDeleteUserSaveDataAllGetProgress(NsProgressMonitorFor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close a \ref NsProgressAsyncResult.
|
* @brief Close a \ref NsProgressAsyncResult.
|
||||||
* @note When the object is initialized, this uses \ref nsProgressAsyncResultCancel then \ref nsProgressAsyncResultWait with timeout=U64_MAX.
|
* @note When the object is initialized, this uses \ref nsProgressAsyncResultCancel then \ref nsProgressAsyncResultWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref NsProgressAsyncResult
|
* @param a \ref NsProgressAsyncResult
|
||||||
*/
|
*/
|
||||||
void nsProgressAsyncResultClose(NsProgressAsyncResult *a);
|
void nsProgressAsyncResultClose(NsProgressAsyncResult *a);
|
||||||
@ -1247,13 +1247,13 @@ void nsProgressAsyncResultClose(NsProgressAsyncResult *a);
|
|||||||
/**
|
/**
|
||||||
* @brief Waits for the async operation to finish using the specified timeout.
|
* @brief Waits for the async operation to finish using the specified timeout.
|
||||||
* @param a \ref NsProgressAsyncResult
|
* @param a \ref NsProgressAsyncResult
|
||||||
* @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout.
|
* @param[in] timeout Timeout in nanoseconds. UINT64_MAX for no timeout.
|
||||||
*/
|
*/
|
||||||
Result nsProgressAsyncResultWait(NsProgressAsyncResult *a, u64 timeout);
|
Result nsProgressAsyncResultWait(NsProgressAsyncResult *a, u64 timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the Result.
|
* @brief Gets the Result.
|
||||||
* @note Prior to using the cmd, this uses \ref nsProgressAsyncResultWait with timeout=U64_MAX.
|
* @note Prior to using the cmd, this uses \ref nsProgressAsyncResultWait with timeout=UINT64_MAX.
|
||||||
* @param a \ref NsProgressAsyncResult
|
* @param a \ref NsProgressAsyncResult
|
||||||
*/
|
*/
|
||||||
Result nsProgressAsyncResultGet(NsProgressAsyncResult *a);
|
Result nsProgressAsyncResultGet(NsProgressAsyncResult *a);
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
|
|
||||||
/// The maximum value of a u64.
|
|
||||||
#define U64_MAX UINT64_MAX
|
|
||||||
|
|
||||||
#ifndef SSIZE_MAX
|
#ifndef SSIZE_MAX
|
||||||
#ifdef SIZE_MAX
|
#ifdef SIZE_MAX
|
||||||
#define SSIZE_MAX ((SIZE_MAX) >> 1)
|
#define SSIZE_MAX ((SIZE_MAX) >> 1)
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "services/audren.h"
|
#include "services/audren.h"
|
||||||
#include "audio/driver.h"
|
#include "audio/driver.h"
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ Result nwindowDequeueBuffer(NWindow* nw, s32* out_slot, NvMultiFence* out_fence)
|
|||||||
|
|
||||||
if (eventActive(&nw->event)) {
|
if (eventActive(&nw->event)) {
|
||||||
do {
|
do {
|
||||||
eventWait(&nw->event, U64_MAX);
|
eventWait(&nw->event, UINT64_MAX);
|
||||||
rc = bqDequeueBuffer(&nw->bq, true, nw->width, nw->height, nw->format, nw->usage, &slot, &fence);
|
rc = bqDequeueBuffer(&nw->bq, true, nw->width, nw->height, nw->format, nw->usage, &slot, &fence);
|
||||||
} while (rc == MAKERESULT(Module_LibnxBinder, LibnxBinderError_WouldBlock));
|
} while (rc == MAKERESULT(Module_LibnxBinder, LibnxBinderError_WouldBlock));
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#include "types.h"
|
#include "../services/service_guard.h"
|
||||||
#include "result.h"
|
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "kernel/event.h"
|
#include "kernel/event.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
@ -8,11 +6,13 @@
|
|||||||
#include "nvidia/fence.h"
|
#include "nvidia/fence.h"
|
||||||
|
|
||||||
static u32 g_ctrl_fd = -1;
|
static u32 g_ctrl_fd = -1;
|
||||||
static u64 g_refCnt;
|
|
||||||
|
|
||||||
static u64 g_NvEventUsedMask;
|
static u64 g_NvEventUsedMask;
|
||||||
static Event g_NvEvents[64];
|
static Event g_NvEvents[64];
|
||||||
|
|
||||||
|
#define nvFenceInitialize nvFenceInit
|
||||||
|
NX_GENERATE_SERVICE_GUARD(nvFence);
|
||||||
|
|
||||||
static int _nvGetEventSlot(void)
|
static int _nvGetEventSlot(void)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
@ -66,35 +66,25 @@ static void _nvFreeEvent(int event_id)
|
|||||||
nvioctlNvhostCtrl_EventUnregister(g_ctrl_fd, event_id);
|
nvioctlNvhostCtrl_EventUnregister(g_ctrl_fd, event_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nvFenceInit(void)
|
Result _nvFenceInitialize(void)
|
||||||
{
|
{
|
||||||
Result rc;
|
return nvOpen(&g_ctrl_fd, "/dev/nvhost-ctrl");
|
||||||
|
|
||||||
if (atomicIncrement64(&g_refCnt) > 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = nvOpen(&g_ctrl_fd, "/dev/nvhost-ctrl");
|
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
g_ctrl_fd = -1;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvFenceExit(void)
|
void _nvFenceCleanup(void)
|
||||||
{
|
{
|
||||||
if (atomicDecrement64(&g_refCnt) == 0) {
|
for (int i = 0; i < 64; i ++)
|
||||||
for (int i = 0; i < 64; i ++)
|
_nvFreeEvent(i);
|
||||||
_nvFreeEvent(i);
|
|
||||||
if (g_ctrl_fd != -1)
|
if (g_ctrl_fd != -1) {
|
||||||
nvClose(g_ctrl_fd);
|
nvClose(g_ctrl_fd);
|
||||||
g_ctrl_fd = -1;
|
g_ctrl_fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _nvFenceEventWaitCommon(Event* event, u32 event_id, s32 timeout_us)
|
static Result _nvFenceEventWaitCommon(Event* event, u32 event_id, s32 timeout_us)
|
||||||
{
|
{
|
||||||
u64 timeout_ns = U64_MAX;
|
u64 timeout_ns = UINT64_MAX;
|
||||||
if (timeout_us >= 0)
|
if (timeout_us >= 0)
|
||||||
timeout_ns = (u64)1000*timeout_us;
|
timeout_ns = (u64)1000*timeout_us;
|
||||||
Result rc = eventWait(event, timeout_ns);
|
Result rc = eventWait(event, timeout_ns);
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "types.h"
|
#include "../services/service_guard.h"
|
||||||
#include "result.h"
|
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
#include "nvidia/ioctl.h"
|
#include "nvidia/ioctl.h"
|
||||||
@ -11,25 +9,21 @@
|
|||||||
#define NUM_TPC_MASKS 1
|
#define NUM_TPC_MASKS 1
|
||||||
|
|
||||||
static u32 g_ctrlgpu_fd = -1;
|
static u32 g_ctrlgpu_fd = -1;
|
||||||
static u64 g_refCnt;
|
|
||||||
|
|
||||||
static nvioctl_gpu_characteristics g_gpu_characteristics;
|
static nvioctl_gpu_characteristics g_gpu_characteristics;
|
||||||
static u32 g_zcull_ctx_size;
|
static u32 g_zcull_ctx_size;
|
||||||
static nvioctl_zcull_info g_zcull_info;
|
static nvioctl_zcull_info g_zcull_info;
|
||||||
static u32 g_tpc_masks[NUM_TPC_MASKS];
|
static u32 g_tpc_masks[NUM_TPC_MASKS];
|
||||||
|
|
||||||
Result nvGpuInit(void)
|
#define nvGpuInitialize nvGpuInit
|
||||||
|
NX_GENERATE_SERVICE_GUARD(nvGpu);
|
||||||
|
|
||||||
|
Result _nvGpuInitialize(void)
|
||||||
{
|
{
|
||||||
Result rc;
|
Result rc;
|
||||||
|
|
||||||
if (atomicIncrement64(&g_refCnt) > 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = nvOpen(&g_ctrlgpu_fd, "/dev/nvhost-ctrl-gpu");
|
rc = nvOpen(&g_ctrlgpu_fd, "/dev/nvhost-ctrl-gpu");
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
g_ctrlgpu_fd = -1;
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = nvioctlNvhostCtrlGpu_GetCharacteristics(g_ctrlgpu_fd, &g_gpu_characteristics);
|
rc = nvioctlNvhostCtrlGpu_GetCharacteristics(g_ctrlgpu_fd, &g_gpu_characteristics);
|
||||||
|
|
||||||
@ -42,18 +36,13 @@ Result nvGpuInit(void)
|
|||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = nvioctlNvhostCtrlGpu_GetTpcMasks(g_ctrlgpu_fd, g_tpc_masks, sizeof(g_tpc_masks));
|
rc = nvioctlNvhostCtrlGpu_GetTpcMasks(g_ctrlgpu_fd, g_tpc_masks, sizeof(g_tpc_masks));
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
nvGpuExit();
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvGpuExit(void)
|
void _nvGpuCleanup(void)
|
||||||
{
|
{
|
||||||
if (atomicDecrement64(&g_refCnt) == 0) {
|
if (g_ctrlgpu_fd != -1) {
|
||||||
if (g_ctrlgpu_fd != -1)
|
nvClose(g_ctrlgpu_fd);
|
||||||
nvClose(g_ctrlgpu_fd);
|
|
||||||
|
|
||||||
g_ctrlgpu_fd = -1;
|
g_ctrlgpu_fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "types.h"
|
#include "../services/service_guard.h"
|
||||||
#include "result.h"
|
|
||||||
#include "arm/atomics.h"
|
|
||||||
#include "arm/cache.h"
|
#include "arm/cache.h"
|
||||||
#include "kernel/svc.h"
|
#include "kernel/svc.h"
|
||||||
#include "services/nv.h"
|
#include "services/nv.h"
|
||||||
@ -9,30 +7,19 @@
|
|||||||
#include "nvidia/map.h"
|
#include "nvidia/map.h"
|
||||||
|
|
||||||
static u32 g_nvmap_fd = -1;
|
static u32 g_nvmap_fd = -1;
|
||||||
static u64 g_refCnt;
|
|
||||||
|
|
||||||
Result nvMapInit(void)
|
#define nvMapInitialize nvMapInit
|
||||||
|
NX_GENERATE_SERVICE_GUARD(nvMap);
|
||||||
|
|
||||||
|
Result _nvMapInitialize(void)
|
||||||
{
|
{
|
||||||
Result rc;
|
return nvOpen(&g_nvmap_fd, "/dev/nvmap");
|
||||||
|
|
||||||
if (atomicIncrement64(&g_refCnt) > 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = nvOpen(&g_nvmap_fd, "/dev/nvmap");
|
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
|
||||||
atomicDecrement64(&g_refCnt);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvMapExit(void)
|
void _nvMapCleanup(void)
|
||||||
{
|
{
|
||||||
if (atomicDecrement64(&g_refCnt) == 0)
|
if (g_nvmap_fd != -1) {
|
||||||
{
|
nvClose(g_nvmap_fd);
|
||||||
if (g_nvmap_fd != -1)
|
|
||||||
nvClose(g_nvmap_fd);
|
|
||||||
|
|
||||||
g_nvmap_fd = -1;
|
g_nvmap_fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ static Result _usbCommsRead(usbCommsInterface *interface, void* buffer, size_t s
|
|||||||
UsbDsReportData reportdata;
|
UsbDsReportData reportdata;
|
||||||
|
|
||||||
//Makes sure endpoints are ready for data-transfer / wait for init if needed.
|
//Makes sure endpoints are ready for data-transfer / wait for init if needed.
|
||||||
rc = usbDsWaitReady(U64_MAX);
|
rc = usbDsWaitReady(UINT64_MAX);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
while(size)
|
while(size)
|
||||||
@ -438,7 +438,7 @@ static Result _usbCommsRead(usbCommsInterface *interface, void* buffer, size_t s
|
|||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
//Wait for the transfer to finish.
|
//Wait for the transfer to finish.
|
||||||
eventWait(&interface->endpoint_out->CompletionEvent, U64_MAX);
|
eventWait(&interface->endpoint_out->CompletionEvent, UINT64_MAX);
|
||||||
eventClear(&interface->endpoint_out->CompletionEvent);
|
eventClear(&interface->endpoint_out->CompletionEvent);
|
||||||
|
|
||||||
rc = usbDsEndpoint_GetReportData(interface->endpoint_out, &reportdata);
|
rc = usbDsEndpoint_GetReportData(interface->endpoint_out, &reportdata);
|
||||||
@ -474,7 +474,7 @@ static Result _usbCommsWrite(usbCommsInterface *interface, const void* buffer, s
|
|||||||
UsbDsReportData reportdata;
|
UsbDsReportData reportdata;
|
||||||
|
|
||||||
//Makes sure endpoints are ready for data-transfer / wait for init if needed.
|
//Makes sure endpoints are ready for data-transfer / wait for init if needed.
|
||||||
rc = usbDsWaitReady(U64_MAX);
|
rc = usbDsWaitReady(UINT64_MAX);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
while(size)
|
while(size)
|
||||||
@ -501,7 +501,7 @@ static Result _usbCommsWrite(usbCommsInterface *interface, const void* buffer, s
|
|||||||
if(R_FAILED(rc))return rc;
|
if(R_FAILED(rc))return rc;
|
||||||
|
|
||||||
//Wait for the transfer to finish.
|
//Wait for the transfer to finish.
|
||||||
eventWait(&interface->endpoint_in->CompletionEvent, U64_MAX);
|
eventWait(&interface->endpoint_in->CompletionEvent, UINT64_MAX);
|
||||||
eventClear(&interface->endpoint_in->CompletionEvent);
|
eventClear(&interface->endpoint_in->CompletionEvent);
|
||||||
|
|
||||||
rc = usbDsEndpoint_GetReportData(interface->endpoint_in, &reportdata);
|
rc = usbDsEndpoint_GetReportData(interface->endpoint_in, &reportdata);
|
||||||
|
@ -254,7 +254,7 @@ Result _appletInitialize(void) {
|
|||||||
//Don't enter this msg-loop when g_appletFocusState is already 1, it will hang when applet was previously initialized in the context of the current process for AppletType_Application.
|
//Don't enter this msg-loop when g_appletFocusState is already 1, it will hang when applet was previously initialized in the context of the current process for AppletType_Application.
|
||||||
if (R_SUCCEEDED(rc) && g_appletFocusState != AppletFocusState_Focused) {
|
if (R_SUCCEEDED(rc) && g_appletFocusState != AppletFocusState_Focused) {
|
||||||
do {
|
do {
|
||||||
eventWait(&g_appletMessageEvent, U64_MAX);
|
eventWait(&g_appletMessageEvent, UINT64_MAX);
|
||||||
|
|
||||||
u32 msg;
|
u32 msg;
|
||||||
rc = _appletReceiveMessage(&msg);
|
rc = _appletReceiveMessage(&msg);
|
||||||
@ -873,7 +873,7 @@ static Result _appletWaitAcquiredSleepLockEvent(void) {
|
|||||||
Event tmpevent={0};
|
Event tmpevent={0};
|
||||||
|
|
||||||
rc = _appletGetAcquiredSleepLockEvent(&tmpevent);
|
rc = _appletGetAcquiredSleepLockEvent(&tmpevent);
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, UINT64_MAX);
|
||||||
eventClose(&tmpevent);
|
eventClose(&tmpevent);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1027,7 +1027,7 @@ static Result _appletWaitLibraryAppletLaunchableEvent(void) {
|
|||||||
if (!eventActive(&g_appletLibraryAppletLaunchableEvent))
|
if (!eventActive(&g_appletLibraryAppletLaunchableEvent))
|
||||||
rc = _appletCmdGetEvent(&g_appletISelfController, &g_appletLibraryAppletLaunchableEvent, false, 9);
|
rc = _appletCmdGetEvent(&g_appletISelfController, &g_appletLibraryAppletLaunchableEvent, false, 9);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&g_appletLibraryAppletLaunchableEvent, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&g_appletLibraryAppletLaunchableEvent, UINT64_MAX);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -1404,7 +1404,7 @@ Result appletLockAccessorLock(AppletLockAccessor *a) {
|
|||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = eventWait(&a->event, U64_MAX);
|
rc = eventWait(&a->event, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, &flag);
|
if (R_SUCCEEDED(rc)) rc = _appletLockAccessorTryLock(a, false, NULL, &flag);
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
} while(!flag);
|
} while(!flag);
|
||||||
@ -1602,7 +1602,7 @@ void appletHolderJoin(AppletHolder *h) {
|
|||||||
LibAppletExitReason res = LibAppletExitReason_Normal;
|
LibAppletExitReason res = LibAppletExitReason_Normal;
|
||||||
u32 desc=0;
|
u32 desc=0;
|
||||||
|
|
||||||
eventWait(&h->StateChangedEvent, U64_MAX);
|
eventWait(&h->StateChangedEvent, UINT64_MAX);
|
||||||
rc = _appletCmdNoIO(&h->s, 30);//GetResult
|
rc = _appletCmdNoIO(&h->s, 30);//GetResult
|
||||||
|
|
||||||
if (R_FAILED(rc)) {
|
if (R_FAILED(rc)) {
|
||||||
@ -1642,7 +1642,7 @@ bool appletHolderWaitInteractiveOut(AppletHolder *h) {
|
|||||||
rc = _appletHolderGetPopInteractiveOutDataEvent(h);
|
rc = _appletHolderGetPopInteractiveOutDataEvent(h);
|
||||||
if (R_FAILED(rc)) return false;
|
if (R_FAILED(rc)) return false;
|
||||||
|
|
||||||
rc = waitMulti(&idx, U64_MAX, waiterForEvent(&h->PopInteractiveOutDataEvent), waiterForEvent(&h->StateChangedEvent));
|
rc = waitMulti(&idx, UINT64_MAX, waiterForEvent(&h->PopInteractiveOutDataEvent), waiterForEvent(&h->StateChangedEvent));
|
||||||
if (R_FAILED(rc)) return false;
|
if (R_FAILED(rc)) return false;
|
||||||
|
|
||||||
return idx==0;
|
return idx==0;
|
||||||
@ -2387,7 +2387,7 @@ void appletApplicationJoin(AppletApplication *a) {
|
|||||||
AppletApplicationExitReason res = AppletApplicationExitReason_Normal;
|
AppletApplicationExitReason res = AppletApplicationExitReason_Normal;
|
||||||
u32 desc=0;
|
u32 desc=0;
|
||||||
|
|
||||||
eventWait(&a->StateChangedEvent, U64_MAX);
|
eventWait(&a->StateChangedEvent, UINT64_MAX);
|
||||||
rc = _appletCmdNoIO(&a->s, 30);//GetResult
|
rc = _appletCmdNoIO(&a->s, 30);//GetResult
|
||||||
|
|
||||||
if (R_FAILED(rc)) {
|
if (R_FAILED(rc)) {
|
||||||
|
@ -22,7 +22,7 @@ static Result _asyncCmdNoInOutBuf(Service* srv, void* buffer, size_t size, u32 c
|
|||||||
void asyncValueClose(AsyncValue *a) {
|
void asyncValueClose(AsyncValue *a) {
|
||||||
if (serviceIsActive(&a->s)) {
|
if (serviceIsActive(&a->s)) {
|
||||||
asyncValueCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
asyncValueCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
||||||
asyncValueWait(a, U64_MAX);
|
asyncValueWait(a, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceClose(&a->s);
|
serviceClose(&a->s);
|
||||||
@ -47,7 +47,7 @@ Result asyncValueGet(AsyncValue *a, void* buffer, size_t size) {
|
|||||||
if (!serviceIsActive(&a->s))
|
if (!serviceIsActive(&a->s))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
Result rc = asyncValueWait(a, U64_MAX);
|
Result rc = asyncValueWait(a, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = _asyncCmdNoInOutBuf(&a->s, buffer, size, 1);
|
if (R_SUCCEEDED(rc)) rc = _asyncCmdNoInOutBuf(&a->s, buffer, size, 1);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ Result asyncValueGetErrorContext(AsyncValue *a, ErrorContext *context) {
|
|||||||
void asyncResultClose(AsyncResult *a) {
|
void asyncResultClose(AsyncResult *a) {
|
||||||
if (serviceIsActive(&a->s)) {
|
if (serviceIsActive(&a->s)) {
|
||||||
asyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
asyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
||||||
asyncResultWait(a, U64_MAX);
|
asyncResultWait(a, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceClose(&a->s);
|
serviceClose(&a->s);
|
||||||
@ -91,7 +91,7 @@ Result asyncResultGet(AsyncResult *a) {
|
|||||||
if (!serviceIsActive(&a->s))
|
if (!serviceIsActive(&a->s))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
Result rc = asyncResultWait(a, U64_MAX);
|
Result rc = asyncResultWait(a, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = _asyncCmdNoIO(&a->s, 0);
|
if (R_SUCCEEDED(rc)) rc = _asyncCmdNoIO(&a->s, 0);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ Result audinCaptureBuffer(AudioInBuffer *source, AudioInBuffer **released) {
|
|||||||
rc = audinAppendAudioInBuffer(source);
|
rc = audinAppendAudioInBuffer(source);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = audinWaitCaptureFinish(released, &released_count, U64_MAX);
|
rc = audinWaitCaptureFinish(released, &released_count, UINT64_MAX);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ Result audoutPlayBuffer(AudioOutBuffer *source, AudioOutBuffer **released) {
|
|||||||
rc = audoutAppendAudioOutBuffer(source);
|
rc = audoutAppendAudioOutBuffer(source);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc))
|
if (R_SUCCEEDED(rc))
|
||||||
rc = audoutWaitPlayFinish(released, &released_count, U64_MAX);
|
rc = audoutWaitPlayFinish(released, &released_count, UINT64_MAX);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ static Result _audrenCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void audrenWaitFrame(void) {
|
void audrenWaitFrame(void) {
|
||||||
eventWait(&g_audrenEvent, U64_MAX);
|
eventWait(&g_audrenEvent, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result _audrenOpenAudioRenderer(Service* srv, Service* srv_out, const AudioRendererParameter* param) {
|
Result _audrenOpenAudioRenderer(Service* srv, Service* srv_out, const AudioRendererParameter* param) {
|
||||||
|
@ -142,7 +142,7 @@ Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_m
|
|||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = _grcGameMovieTrimmerBeginTrim(&trimmer, src_movieid, start, end);
|
if (R_SUCCEEDED(rc)) rc = _grcGameMovieTrimmerBeginTrim(&trimmer, src_movieid, start, end);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&trimevent, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&trimevent, UINT64_MAX);
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = _grcGameMovieTrimmerEndTrim(&trimmer, dst_movieid);
|
if (R_SUCCEEDED(rc)) rc = _grcGameMovieTrimmerEndTrim(&trimmer, dst_movieid);
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ Result grcMovieMakerFinish(GrcMovieMaker *m, s32 width, s32 height, const void*
|
|||||||
|
|
||||||
rc = _grcCmdInU64NoOut(&m->s, m->layer_handle, 22); // RequestOffscreenRecordingFinishReady
|
rc = _grcCmdInU64NoOut(&m->s, m->layer_handle, 22); // RequestOffscreenRecordingFinishReady
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&m->recording_event, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&m->recording_event, UINT64_MAX);
|
||||||
|
|
||||||
if (hosversionAtLeast(7,0,0))
|
if (hosversionAtLeast(7,0,0))
|
||||||
rc = _grcMovieMakerCompleteOffscreenRecordingFinishEx1(m, width, height, userdata, userdata_size, thumbnail, thumbnail_size, entry);
|
rc = _grcMovieMakerCompleteOffscreenRecordingFinishEx1(m, width, height, userdata, userdata_size, thumbnail, thumbnail_size, entry);
|
||||||
@ -342,7 +342,7 @@ Result grcMovieMakerEncodeAudioSample(GrcMovieMaker *m, const void* buffer, size
|
|||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
for (u64 pos=0; size!=0; pos+=out_size, size-=out_size) {
|
for (u64 pos=0; size!=0; pos+=out_size, size-=out_size) {
|
||||||
rc = eventWait(&m->audio_event, U64_MAX);
|
rc = eventWait(&m->audio_event, UINT64_MAX);
|
||||||
if (R_FAILED(rc)) break;
|
if (R_FAILED(rc)) break;
|
||||||
|
|
||||||
rc = _grcMovieMakerEncodeOffscreenLayerAudioSample(m, &bufptr[pos], size, &out_size);
|
rc = _grcMovieMakerEncodeOffscreenLayerAudioSample(m, &bufptr[pos], size, &out_size);
|
||||||
|
571
nx/source/services/hidbus.c
Normal file
571
nx/source/services/hidbus.c
Normal file
@ -0,0 +1,571 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "runtime/hosversion.h"
|
||||||
|
#include "kernel/shmem.h"
|
||||||
|
#include "services/hidbus.h"
|
||||||
|
#include "services/applet.h"
|
||||||
|
#include "applets/hid_la.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Mutex mutex;
|
||||||
|
Event event;
|
||||||
|
HidbusBusHandle handle;
|
||||||
|
void* workbuf;
|
||||||
|
} HidBusDeviceEntry;
|
||||||
|
|
||||||
|
static HidBusDeviceEntry g_hidbusDevices[0x13];
|
||||||
|
|
||||||
|
static Mutex g_hidbusSharedmemMutex, g_hidbusUpdateMutex;
|
||||||
|
static bool g_hidbusUpdateFlag;
|
||||||
|
static u32 g_hidbusSharedmemRefCount;
|
||||||
|
static SharedMemory g_hidbusSharedmem;
|
||||||
|
|
||||||
|
Result hidbusGetServiceSession(Service* srv_out) {
|
||||||
|
if (hosversionBefore(5,0,0))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
return smGetService(srv_out, "hidbus");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidBusVerifyBusHandle(HidbusBusHandle handle) {
|
||||||
|
u8 max_count = hosversionBefore(6,0,0) ? 0x10 : 0x13; // sdknso uses value 0x11 on 5.x, but that's off-by-one with sharedmem because 0x10*sizeof(HidbusStatusManagerEntryV5) == sizeof(sharedmem). Hence, we check for 0x10 instead.
|
||||||
|
|
||||||
|
return handle.internal_index < max_count ? 0 : MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) {
|
||||||
|
return serviceDispatch(srv, cmd_id,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = handle_out,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusGetBusHandle(Service* srv, u32 id, u64 bus_type, bool *flag, HidbusBusHandle *handle) {
|
||||||
|
const struct {
|
||||||
|
u32 id;
|
||||||
|
u32 pad;
|
||||||
|
u64 bus_type;
|
||||||
|
u64 appletResourceUserId;
|
||||||
|
} in = { id, 0, bus_type, appletGetAppletResourceUserId() };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 flag;
|
||||||
|
u8 pad[7];
|
||||||
|
HidbusBusHandle handle;
|
||||||
|
} out;
|
||||||
|
|
||||||
|
Result rc = serviceDispatchInOut(srv, 1, in, out);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (flag) *flag = out.flag & 1;
|
||||||
|
if (handle) *handle = out.handle;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusInBusHandleResIdNoOut(Service* srv, HidbusBusHandle handle, u32 cmd_id) {
|
||||||
|
const struct {
|
||||||
|
HidbusBusHandle handle;
|
||||||
|
u64 appletResourceUserId;
|
||||||
|
} in = { handle, appletGetAppletResourceUserId() };
|
||||||
|
|
||||||
|
return serviceDispatchIn(srv, cmd_id, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusEnableExternalDevice(Service* srv, HidbusBusHandle handle, bool flag, u64 inval) {
|
||||||
|
const struct {
|
||||||
|
u8 flag;
|
||||||
|
u8 pad[7];
|
||||||
|
HidbusBusHandle handle;
|
||||||
|
u64 inval;
|
||||||
|
u64 appletResourceUserId;
|
||||||
|
} in = { flag!=0, {0}, handle, inval, appletGetAppletResourceUserId() };
|
||||||
|
|
||||||
|
return serviceDispatchIn(srv, 5, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusGetExternalDeviceId(Service* srv, HidbusBusHandle handle, u32 *out) {
|
||||||
|
return serviceDispatchInOut(srv, 6, handle, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusSendCommandAsync(Service* srv, HidbusBusHandle handle, const void* buffer, size_t size) {
|
||||||
|
return serviceDispatchIn(srv, 7, handle,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
|
||||||
|
.buffers = { { buffer, size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusGetSendCommandAsynceResult(Service* srv, HidbusBusHandle handle, void* buffer, size_t size, u32 *out_size) {
|
||||||
|
return serviceDispatchInOut(srv, 8, handle, *out_size,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
|
.buffers = { { buffer, size } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusSetEventForSendCommandAsycResult(Service* srv, HidbusBusHandle handle, Event* out_event) {
|
||||||
|
Handle event = INVALID_HANDLE;
|
||||||
|
Result rc = serviceDispatchIn(srv, 9, handle,
|
||||||
|
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
|
||||||
|
.out_handles = &event,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc))
|
||||||
|
eventLoadRemote(out_event, event, false);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusEnableJoyPollingReceiveMode(Service* srv, HidbusBusHandle handle, u32 polling_mode, const void* inbuf, size_t inbuf_size, TransferMemory *tmem) { // [8.0.0+]
|
||||||
|
const struct {
|
||||||
|
u32 size;
|
||||||
|
u32 polling_mode;
|
||||||
|
HidbusBusHandle handle;
|
||||||
|
} in = { tmem->size, polling_mode, handle };
|
||||||
|
|
||||||
|
Result rc = serviceDispatchIn(srv, 11, in,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
|
||||||
|
.buffers = { { inbuf, inbuf_size } },
|
||||||
|
.in_num_handles = 1,
|
||||||
|
.in_handles = { tmem->handle },
|
||||||
|
);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusDisableJoyPollingReceiveMode(Service* srv, HidbusBusHandle handle) {
|
||||||
|
return serviceDispatchIn(srv, 12, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusSetStatusManagerType(Service* srv, u32 inval) { // [6.0.0+]
|
||||||
|
return serviceDispatchIn(srv, 14, inval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Official sw just checks whether a global flag is set, and runs initialization if not set. The code for cleanup is not used. Since we want to actually handle cleanup, use refcounting for sharedmem.
|
||||||
|
static Result _hidbusSharedmemInitialize(Service* srv) {
|
||||||
|
Result rc=0;
|
||||||
|
Handle sharedmem_handle;
|
||||||
|
mutexLock(&g_hidbusSharedmemMutex);
|
||||||
|
if ((g_hidbusSharedmemRefCount++) == 0) {
|
||||||
|
rc = _hidbusCmdGetHandle(srv, &sharedmem_handle, 10); // GetSharedMemoryHandle
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
shmemLoadRemote(&g_hidbusSharedmem, sharedmem_handle, 0x1000, Perm_R);
|
||||||
|
rc = shmemMap(&g_hidbusSharedmem);
|
||||||
|
if (R_FAILED(rc)) shmemClose(&g_hidbusSharedmem);
|
||||||
|
}
|
||||||
|
if (R_FAILED(rc)) g_hidbusSharedmemRefCount--;
|
||||||
|
_hidbusSetStatusManagerType(srv, 0x2); // Official sw ignores errors from this.
|
||||||
|
}
|
||||||
|
mutexUnlock(&g_hidbusSharedmemMutex);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _hidbusSharedmemExit(void) {
|
||||||
|
mutexLock(&g_hidbusSharedmemMutex);
|
||||||
|
if (g_hidbusSharedmemRefCount && (--g_hidbusSharedmemRefCount) == 0) {
|
||||||
|
shmemClose(&g_hidbusSharedmem);
|
||||||
|
}
|
||||||
|
mutexUnlock(&g_hidbusSharedmemMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* hidbusGetSharedmemAddr(void) {
|
||||||
|
return shmemGetAddr(&g_hidbusSharedmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HidbusStatusManagerEntryCommon* _hidbusGetStatusManagerEntryCommon(u8 internal_index) {
|
||||||
|
if (hosversionBefore(6,0,0))
|
||||||
|
return &((HidbusStatusManagerV5*)hidbusGetSharedmemAddr())->entries[internal_index].common;
|
||||||
|
else
|
||||||
|
return &((HidbusStatusManager*)hidbusGetSharedmemAddr())->entries[internal_index].common;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _hidbusGetStatusManagerEntryFlag_x0(u8 internal_index) {
|
||||||
|
return atomic_load_explicit(&_hidbusGetStatusManagerEntryCommon(internal_index)->flag_x0, memory_order_acquire) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hidbusGetStatusManagerEntryRes(u8 internal_index) {
|
||||||
|
return _hidbusGetStatusManagerEntryCommon(internal_index)->res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _hidbusGetStatusManagerEntryDeviceEnabled(u8 internal_index) {
|
||||||
|
return atomic_load_explicit(&_hidbusGetStatusManagerEntryCommon(internal_index)->device_enabled, memory_order_acquire) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _hidbusGetStatusManagerEntryIsValid(u8 internal_index) {
|
||||||
|
return atomic_load_explicit(&_hidbusGetStatusManagerEntryCommon(internal_index)->is_valid, memory_order_acquire) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _hidbusGetStatusManagerEntryPollingEnabled(u8 internal_index) {
|
||||||
|
return atomic_load_explicit(&_hidbusGetStatusManagerEntryCommon(internal_index)->polling_enabled, memory_order_acquire) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HidbusJoyPollingMode _hidbusGetStatusManagerEntryPollingMode(u8 internal_index) {
|
||||||
|
return atomic_load_explicit(&_hidbusGetStatusManagerEntryCommon(internal_index)->polling_mode, memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusGetBusHandle(HidbusBusHandle *handle, bool *flag, HidControllerID id, HidbusBusType bus_type) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = hidbusGetServiceSession(&srv);
|
||||||
|
*flag = 0;
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
|
HidbusBusHandle tmphandle={0};
|
||||||
|
bool tmpflag=0;
|
||||||
|
rc = _hidbusGetBusHandle(&srv, hidControllerIDToOfficial(id), bus_type, &tmpflag, &tmphandle);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (!tmpflag) *flag = tmpflag;
|
||||||
|
else {
|
||||||
|
rc = _hidBusVerifyBusHandle(tmphandle);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*flag = tmpflag;
|
||||||
|
*handle = tmphandle;
|
||||||
|
|
||||||
|
g_hidbusDevices[tmphandle.internal_index].handle = tmphandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusInitialize(HidbusBusHandle handle) {
|
||||||
|
Service srv={0};
|
||||||
|
bool setup_event=1;
|
||||||
|
bool sharedmem_init=0;
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[handle.internal_index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
rc = _hidbusSharedmemInitialize(&srv);
|
||||||
|
if (R_SUCCEEDED(rc)) sharedmem_init = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
rc = _hidbusInBusHandleResIdNoOut(&srv, handle, 3); // Initialize
|
||||||
|
if (R_VALUE(rc) == MAKERESULT(218, 10)) {
|
||||||
|
rc = 0;
|
||||||
|
setup_event = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && setup_event) {
|
||||||
|
eventClose(&entry->event);
|
||||||
|
rc = _hidbusSetEventForSendCommandAsycResult(&srv, handle, &entry->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((R_FAILED(rc) || !setup_event) && sharedmem_init) _hidbusSharedmemExit();
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusFinalize(HidbusBusHandle handle) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[handle.internal_index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))==0) {
|
||||||
|
rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = _hidbusInBusHandleResIdNoOut(&srv, handle, 4); // Finalize
|
||||||
|
eventClose(&entry->event);
|
||||||
|
|
||||||
|
_hidbusSharedmemExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusEnableExternalDevice(HidbusBusHandle handle, bool flag, u32 device_id) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
u64 inval = hosversionBefore(7,0,0) ? 0x38900050018 : 0x3A600050018;
|
||||||
|
u32 index = handle.internal_index;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryIsValid(index)) rc = MAKERESULT(218, 2);
|
||||||
|
if (R_SUCCEEDED(rc)) rc = _hidbusGetStatusManagerEntryRes(index);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (!_hidbusGetStatusManagerEntryFlag_x0(index) && !flag) rc = MAKERESULT(218, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
rc = _hidbusEnableExternalDevice(&srv, handle, flag, inval);
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
// sdknso asserts when rc is MAKERESULT(218, 12), we won't do an equivalent.
|
||||||
|
if (R_VALUE(rc) == MAKERESULT(202, 547) || R_VALUE(rc) == MAKERESULT(108, 426)) {
|
||||||
|
mutexLock(&g_hidbusUpdateMutex);
|
||||||
|
bool updateflag = g_hidbusUpdateFlag;
|
||||||
|
if (!updateflag) g_hidbusUpdateFlag = true;
|
||||||
|
mutexUnlock(&g_hidbusUpdateMutex);
|
||||||
|
if (updateflag) rc = MAKERESULT(218, 2);
|
||||||
|
else {
|
||||||
|
HidLaControllerFirmwareUpdateArg arg;
|
||||||
|
hidLaCreateControllerFirmwareUpdateArg(&arg);
|
||||||
|
arg.enable_force_update = 1;
|
||||||
|
rc = hidLaShowControllerFirmwareUpdate(&arg);
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) rc = R_VALUE(rc) == MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit) ? MAKERESULT(218, 3) : rc;
|
||||||
|
else rc = _hidbusEnableExternalDevice(&srv, handle, flag, inval);
|
||||||
|
|
||||||
|
mutexLock(&g_hidbusUpdateMutex);
|
||||||
|
g_hidbusUpdateFlag = false;
|
||||||
|
mutexUnlock(&g_hidbusUpdateMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (R_SUCCEEDED(rc) && flag) {
|
||||||
|
u32 tmpout=0;
|
||||||
|
rc = _hidbusGetExternalDeviceId(&srv, handle, &tmpout);
|
||||||
|
if (R_SUCCEEDED(rc) && tmpout!=device_id) {
|
||||||
|
rc = hidbusEnableExternalDevice(handle, false, device_id);
|
||||||
|
rc = R_SUCCEEDED(rc) ? MAKERESULT(218, 9) : rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusSendAndReceive(HidbusBusHandle handle, const void* inbuf, size_t inbuf_size, void* outbuf, size_t outbuf_size, u64 *out_size) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
if (inbuf_size >= 0x26) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
u32 index = handle.internal_index;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryDeviceEnabled(index)) rc = MAKERESULT(218, 8);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
eventClear(&entry->event); // This was added with sdknso 6.x+, but we'll do it on 5.x regardless.
|
||||||
|
rc = _hidbusSendCommandAsync(&srv, handle, inbuf, inbuf_size);
|
||||||
|
}
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
eventWait(&entry->event, UINT64_MAX);
|
||||||
|
eventClear(&entry->event);
|
||||||
|
u32 tmpout=0;
|
||||||
|
rc = _hidbusGetSendCommandAsynceResult(&srv, handle, outbuf, outbuf_size, &tmpout);
|
||||||
|
if (R_SUCCEEDED(rc) && out_size) *out_size = tmpout;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusEnableJoyPollingReceiveMode(HidbusBusHandle handle, const void* inbuf, size_t inbuf_size, void* workbuf, size_t workbuf_size, HidbusJoyPollingMode polling_mode) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
if (inbuf_size >= 0x26) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
u32 index = handle.internal_index;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryDeviceEnabled(index)) rc = MAKERESULT(218, 8);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryPollingEnabled(index)) {
|
||||||
|
rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
TransferMemory tmem={0};
|
||||||
|
rc = tmemCreateFromMemory(&tmem, workbuf, workbuf_size, Perm_R);
|
||||||
|
if (R_SUCCEEDED(rc)) rc = _hidbusEnableJoyPollingReceiveMode(&srv, handle, polling_mode, inbuf, inbuf_size, &tmem);
|
||||||
|
if (R_SUCCEEDED(rc)) entry->workbuf = workbuf; // sdknso does this before using the cmd.
|
||||||
|
tmemClose(&tmem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusDisableJoyPollingReceiveMode(HidbusBusHandle handle) {
|
||||||
|
Service srv={0};
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
u32 index = handle.internal_index;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[index];
|
||||||
|
mutexLock(&entry->mutex);
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryDeviceEnabled(index)) rc = MAKERESULT(218, 8);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = hidbusGetServiceSession(&srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = _hidbusDisableJoyPollingReceiveMode(&srv, handle);
|
||||||
|
|
||||||
|
mutexUnlock(&entry->mutex);
|
||||||
|
serviceClose(&srv);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result hidbusGetJoyPollingReceivedData(HidbusBusHandle handle, HidbusJoyPollingReceivedData *recv_data, s32 count) {
|
||||||
|
Result rc = _hidBusVerifyBusHandle(handle);
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
u32 index = handle.internal_index;
|
||||||
|
HidBusDeviceEntry *entry = &g_hidbusDevices[index];
|
||||||
|
if (memcmp(&entry->handle, &handle, sizeof(handle))!=0) rc = MAKERESULT(218, 4);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryDeviceEnabled(index)) rc = MAKERESULT(218, 8);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = _hidbusGetStatusManagerEntryRes(index);
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryFlag_x0(index)) rc = MAKERESULT(218, 8);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && count >= 1) memset(recv_data, 0, sizeof(HidbusJoyPollingReceivedData)*count);
|
||||||
|
if (R_SUCCEEDED(rc) && !_hidbusGetStatusManagerEntryPollingEnabled(index)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
|
if (count > 0xa) count = 0xa;
|
||||||
|
|
||||||
|
HidbusJoyDisableSixAxisPollingDataAccessor *joydisable_accessor = entry->workbuf;
|
||||||
|
HidbusJoyEnableSixAxisPollingDataAccessor *joyenable_accessor = entry->workbuf;
|
||||||
|
HidbusJoyButtonOnlyPollingDataAccessor *joybutton_accessor = entry->workbuf;
|
||||||
|
HidbusDataAccessorHeader *accessor_header;
|
||||||
|
|
||||||
|
HidbusJoyPollingMode polling_mode = _hidbusGetStatusManagerEntryPollingMode(index);
|
||||||
|
if (polling_mode == HidbusJoyPollingMode_JoyDisableSixAxisPollingData) {
|
||||||
|
accessor_header = &joydisable_accessor->hdr;
|
||||||
|
}
|
||||||
|
else if (polling_mode == HidbusJoyPollingMode_JoyEnableSixAxisPollingData) {
|
||||||
|
accessor_header = &joyenable_accessor->hdr;
|
||||||
|
}
|
||||||
|
else if (hosversionAtLeast(6,0,0) && polling_mode == HidbusJoyPollingMode_JoyButtonOnlyPollingData) {
|
||||||
|
accessor_header = &joybutton_accessor->hdr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 total_entries = (s32)atomic_load_explicit(&accessor_header->total_entries, memory_order_acquire);
|
||||||
|
if (total_entries < 0) total_entries = 0;
|
||||||
|
s32 newcount = count < total_entries ? count : total_entries;
|
||||||
|
s32 latest_entry = (s32)atomic_load_explicit(&accessor_header->latest_entry, memory_order_acquire);
|
||||||
|
|
||||||
|
union {
|
||||||
|
HidbusJoyDisableSixAxisPollingDataAccessorEntryData joydisable[0xa];
|
||||||
|
HidbusJoyEnableSixAxisPollingDataAccessorEntryData joyenable[0xa];
|
||||||
|
HidbusJoyButtonOnlyPollingDataAccessorEntryData joybutton[0xa];
|
||||||
|
} tmp_entries;
|
||||||
|
|
||||||
|
if (polling_mode == HidbusJoyPollingMode_JoyDisableSixAxisPollingData) {
|
||||||
|
memset(tmp_entries.joydisable, 0, sizeof(tmp_entries.joydisable));
|
||||||
|
}
|
||||||
|
else if (polling_mode == HidbusJoyPollingMode_JoyEnableSixAxisPollingData) {
|
||||||
|
memset(tmp_entries.joyenable, 0, sizeof(tmp_entries.joyenable));
|
||||||
|
}
|
||||||
|
else if (hosversionAtLeast(6,0,0) && polling_mode == HidbusJoyPollingMode_JoyButtonOnlyPollingData) {
|
||||||
|
memset(tmp_entries.joybutton, 0, sizeof(tmp_entries.joybutton));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (s32 i=0; i<newcount; i++) {
|
||||||
|
s32 entrypos = (((latest_entry + 0xc) - newcount) + i) % 0xb;
|
||||||
|
|
||||||
|
u64 timestamp0=0, timestamp1=0;
|
||||||
|
bool retry=false;
|
||||||
|
if (polling_mode == HidbusJoyPollingMode_JoyDisableSixAxisPollingData) {
|
||||||
|
timestamp0 = atomic_load_explicit(&joydisable_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
memcpy(&tmp_entries.joydisable[newcount-i-1], &joydisable_accessor->entries[entrypos].data, sizeof(HidbusJoyDisableSixAxisPollingDataAccessorEntryData));
|
||||||
|
timestamp1 = atomic_load_explicit(&joydisable_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
|
||||||
|
if (timestamp0 != timestamp1 || (i>0 && joydisable_accessor->entries[entrypos].data.timestamp - tmp_entries.joydisable[newcount-i].timestamp != 1))
|
||||||
|
retry=true;
|
||||||
|
}
|
||||||
|
else if (polling_mode == HidbusJoyPollingMode_JoyEnableSixAxisPollingData) {
|
||||||
|
timestamp0 = atomic_load_explicit(&joyenable_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
memcpy(&tmp_entries.joyenable[newcount-i-1], &joyenable_accessor->entries[entrypos].data, sizeof(HidbusJoyEnableSixAxisPollingDataAccessorEntryData));
|
||||||
|
timestamp1 = atomic_load_explicit(&joyenable_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
|
||||||
|
if (timestamp0 != timestamp1 || (i>0 && joyenable_accessor->entries[entrypos].data.timestamp - tmp_entries.joyenable[newcount-i].timestamp != 1))
|
||||||
|
retry=true;
|
||||||
|
}
|
||||||
|
else if (hosversionAtLeast(6,0,0) && polling_mode == HidbusJoyPollingMode_JoyButtonOnlyPollingData) {
|
||||||
|
timestamp0 = atomic_load_explicit(&joybutton_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
memcpy(&tmp_entries.joybutton[newcount-i-1], &joybutton_accessor->entries[entrypos].data, sizeof(HidbusJoyButtonOnlyPollingDataAccessorEntryData));
|
||||||
|
timestamp1 = atomic_load_explicit(&joybutton_accessor->entries[entrypos].timestamp, memory_order_acquire);
|
||||||
|
|
||||||
|
if (timestamp0 != timestamp1 || (i>0 && joybutton_accessor->entries[entrypos].data.timestamp - tmp_entries.joybutton[newcount-i].timestamp != 1))
|
||||||
|
retry=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry) {
|
||||||
|
total_entries = (s32)atomic_load_explicit(&accessor_header->total_entries, memory_order_acquire);
|
||||||
|
s32 tmpcount = newcount < total_entries ? total_entries : newcount;
|
||||||
|
newcount = tmpcount < count ? tmpcount : count;
|
||||||
|
latest_entry = (s32)atomic_load_explicit(&accessor_header->latest_entry, memory_order_acquire);
|
||||||
|
|
||||||
|
i=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dataready=false;
|
||||||
|
if (polling_mode == HidbusJoyPollingMode_JoyDisableSixAxisPollingData) {
|
||||||
|
dataready = tmp_entries.joydisable[count-1].timestamp != 0;
|
||||||
|
}
|
||||||
|
else if (polling_mode == HidbusJoyPollingMode_JoyEnableSixAxisPollingData) {
|
||||||
|
dataready = tmp_entries.joyenable[count-1].timestamp != 0;
|
||||||
|
}
|
||||||
|
else if (hosversionAtLeast(6,0,0) && polling_mode == HidbusJoyPollingMode_JoyButtonOnlyPollingData) {
|
||||||
|
dataready = tmp_entries.joybutton[count-1].timestamp != 0;
|
||||||
|
}
|
||||||
|
if (!dataready) rc = MAKERESULT(218, 7);
|
||||||
|
if (R_SUCCEEDED(rc)) rc = accessor_header->res;
|
||||||
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
|
for (s32 i=0; i<count; i++) {
|
||||||
|
u8 size=0;
|
||||||
|
|
||||||
|
if (polling_mode == HidbusJoyPollingMode_JoyDisableSixAxisPollingData) {
|
||||||
|
size = tmp_entries.joydisable[i].size;
|
||||||
|
if (size > sizeof(tmp_entries.joydisable[i].data)) return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||||
|
memcpy(recv_data[i].data, tmp_entries.joydisable[i].data, size);
|
||||||
|
recv_data[i].size = size;
|
||||||
|
recv_data[i].timestamp = tmp_entries.joydisable[i].timestamp;
|
||||||
|
}
|
||||||
|
else if (polling_mode == HidbusJoyPollingMode_JoyEnableSixAxisPollingData) {
|
||||||
|
size = tmp_entries.joyenable[i].size;
|
||||||
|
if (size > sizeof(tmp_entries.joyenable[i].data)) return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||||
|
memcpy(recv_data[i].data, tmp_entries.joyenable[i].data, size);
|
||||||
|
recv_data[i].size = size;
|
||||||
|
recv_data[i].timestamp = tmp_entries.joyenable[i].timestamp;
|
||||||
|
}
|
||||||
|
else if (hosversionAtLeast(6,0,0) && polling_mode == HidbusJoyPollingMode_JoyButtonOnlyPollingData) {
|
||||||
|
size = tmp_entries.joybutton[i].size;
|
||||||
|
if (size > sizeof(tmp_entries.joybutton[i].data)) return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||||
|
memcpy(recv_data[i].data, tmp_entries.joybutton[i].data, size);
|
||||||
|
recv_data[i].size = size;
|
||||||
|
recv_data[i].timestamp = tmp_entries.joybutton[i].timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
@ -165,7 +165,7 @@ Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePa
|
|||||||
|
|
||||||
rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, UniquePadId); // *Must* be used before _hiddbgReadSerialFlash.
|
rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, UniquePadId); // *Must* be used before _hiddbgReadSerialFlash.
|
||||||
if (R_SUCCEEDED(rc)) rc = _hiddbgReadSerialFlash(&tmem, offset, size, UniquePadId);
|
if (R_SUCCEEDED(rc)) rc = _hiddbgReadSerialFlash(&tmem, offset, size, UniquePadId);
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(UniquePadId);
|
if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(UniquePadId);
|
||||||
if (R_SUCCEEDED(rc)) memcpy(buffer, tmem.src_addr, size);
|
if (R_SUCCEEDED(rc)) memcpy(buffer, tmem.src_addr, size);
|
||||||
eventClose(&tmpevent);
|
eventClose(&tmpevent);
|
||||||
@ -186,7 +186,7 @@ Result hiddbgWriteSerialFlash(u32 offset, void* buffer, size_t tmem_size, size_t
|
|||||||
|
|
||||||
rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, UniquePadId); // *Must* be used before _hiddbgWriteSerialFlash.
|
rc = hiddbgAcquireOperationEventHandle(&tmpevent, true, UniquePadId); // *Must* be used before _hiddbgWriteSerialFlash.
|
||||||
if (R_SUCCEEDED(rc)) rc = _hiddbgWriteSerialFlash(&tmem, offset, tmem_size, size, UniquePadId);
|
if (R_SUCCEEDED(rc)) rc = _hiddbgWriteSerialFlash(&tmem, offset, tmem_size, size, UniquePadId);
|
||||||
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, U64_MAX);
|
if (R_SUCCEEDED(rc)) rc = eventWait(&tmpevent, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(UniquePadId);
|
if (R_SUCCEEDED(rc)) rc = hiddbgGetOperationResult(UniquePadId);
|
||||||
eventClose(&tmpevent);
|
eventClose(&tmpevent);
|
||||||
tmemClose(&tmem);
|
tmemClose(&tmem);
|
||||||
|
@ -2150,7 +2150,7 @@ Result nsProgressMonitorForDeleteUserSaveDataAllGetProgress(NsProgressMonitorFor
|
|||||||
void nsProgressAsyncResultClose(NsProgressAsyncResult *a) {
|
void nsProgressAsyncResultClose(NsProgressAsyncResult *a) {
|
||||||
if (serviceIsActive(&a->s)) {
|
if (serviceIsActive(&a->s)) {
|
||||||
nsProgressAsyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
nsProgressAsyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event.
|
||||||
nsProgressAsyncResultWait(a, U64_MAX);
|
nsProgressAsyncResultWait(a, UINT64_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
serviceClose(&a->s);
|
serviceClose(&a->s);
|
||||||
@ -2168,7 +2168,7 @@ Result nsProgressAsyncResultGet(NsProgressAsyncResult *a) {
|
|||||||
if (!serviceIsActive(&a->s))
|
if (!serviceIsActive(&a->s))
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
|
||||||
|
|
||||||
Result rc = nsProgressAsyncResultWait(a, U64_MAX);
|
Result rc = nsProgressAsyncResultWait(a, UINT64_MAX);
|
||||||
if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&a->s, 0);
|
if (R_SUCCEEDED(rc)) rc = _nsCmdNoIO(&a->s, 0);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ Result usbHsIfCtrlXfer(UsbHsClientIfSession* s, u8 bmRequestType, u8 bRequest, u
|
|||||||
rc = _usbHsIfCtrlXferAsync(s, bmRequestType, bRequest, wValue, wIndex, wLength, buffer);
|
rc = _usbHsIfCtrlXferAsync(s, bmRequestType, bRequest, wValue, wIndex, wLength, buffer);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
rc = eventWait(&s->eventCtrlXfer, U64_MAX);
|
rc = eventWait(&s->eventCtrlXfer, UINT64_MAX);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
eventClear(&s->eventCtrlXfer);
|
eventClear(&s->eventCtrlXfer);
|
||||||
|
|
||||||
@ -429,7 +429,7 @@ Result usbHsEpPostBuffer(UsbHsClientEpSession* s, void* buffer, u32 size, u32* t
|
|||||||
rc = _usbHsEpPostBufferAsync(s, buffer, size, 0, &xferId);
|
rc = _usbHsEpPostBufferAsync(s, buffer, size, 0, &xferId);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
|
|
||||||
rc = eventWait(&s->eventXfer, U64_MAX);
|
rc = eventWait(&s->eventXfer, UINT64_MAX);
|
||||||
if (R_FAILED(rc)) return rc;
|
if (R_FAILED(rc)) return rc;
|
||||||
eventClear(&s->eventXfer);
|
eventClear(&s->eventXfer);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user