btdrv: Added support for the new 12.0.0 cmds.

This commit is contained in:
yellows8 2021-04-16 16:46:45 -04:00
parent 0d32a2c0d5
commit 2e2cf43cf5
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
3 changed files with 372 additions and 0 deletions

View File

@ -225,6 +225,15 @@ typedef struct {
} data; } data;
} BtdrvHidReportEventInfoBufferData; } BtdrvHidReportEventInfoBufferData;
/// Data for \ref btdrvGetAudioEventInfo. The data stored here depends on the \ref BtdrvAudioEventType.
typedef union {
struct {
u32 status; ///< Status: 0 = AV connection closed, 1 = AV connection opened, 2 = failed to open AV connection.
BtdrvAddress addr; ///< Device address.
u8 pad[2]; ///< Padding
} connection; ///< ::BtdrvAudioEventType_Connection
} BtdrvAudioEventInfo;
/// CircularBuffer /// CircularBuffer
typedef struct { typedef struct {
Mutex mutex; Mutex mutex;
@ -1083,6 +1092,163 @@ Result btdrvSetBleScanParameter(u16 unk0, u16 unk1);
*/ */
Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr); Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr);
/**
* @brief IsBluetoothEnabled
* @note Only available on [12.0.0+].
* @param[out] out Output flag.
*/
Result btdrvIsBluetoothEnabled(bool *out);
/**
* @brief AcquireAudioEvent
* @note Only available on [12.0.0+].
* @param[out] out_event Output Event.
* @param[in] autoclear Event autoclear.
*/
Result btdrvAcquireAudioEvent(Event* out_event, bool autoclear);
/**
* @brief GetAudioEventInfo
* @note Only available on [12.0.0+].
* @param[out] buffer Output buffer, see \ref BtdrvAudioEventInfo.
* @param[in] size Output buffer size.
* @param[out] type \ref BtdrvAudioEventType.
*/
Result btdrvGetAudioEventInfo(void* buffer, size_t size, BtdrvAudioEventType *type);
/**
* @brief OpenAudioConnection
* @note Only available on [12.0.0+].
* @param[in] addr \ref BtdrvAddress
*/
Result btdrvOpenAudioConnection(BtdrvAddress addr);
/**
* @brief CloseAudioConnection
* @note Only available on [12.0.0+].
* @param[in] addr \ref BtdrvAddress
*/
Result btdrvCloseAudioConnection(BtdrvAddress addr);
/**
* @brief OpenAudioOut
* @note Only available on [12.0.0+].
* @param[in] addr \ref BtdrvAddress
* @param[out] audio_handle Audio handle.
*/
Result btdrvOpenAudioOut(BtdrvAddress addr, u32 *audio_handle);
/**
* @brief CloseAudioOut
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
*/
Result btdrvCloseAudioOut(u32 audio_handle);
/**
* @brief StartAudioOut
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[in] pcm_param \ref BtdrvPcmParameter
* @param[in] in_latency Input latency in nanoseconds.
* @param[out] out_latency Output latency in nanoseconds.
* @param[out] out1 Unknown output.
*/
Result btdrvStartAudioOut(u32 audio_handle, const BtdrvPcmParameter *pcm_param, s64 in_latency, s64 *out_latency, u64 *out1);
/**
* @brief StopAudioOut
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
*/
Result btdrvStopAudioOut(u32 audio_handle);
/**
* @brief GetAudioOutState
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[out] out \ref BtdrvAudioOutState
*/
Result btdrvGetAudioOutState(u32 audio_handle, BtdrvAudioOutState *out);
/**
* @brief GetAudioOutFeedingCodec
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[out] out \ref BtdrvAudioCodec
*/
Result btdrvGetAudioOutFeedingCodec(u32 audio_handle, BtdrvAudioCodec *out);
/**
* @brief GetAudioOutFeedingParameter
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[out] out \ref BtdrvPcmParameter
*/
Result btdrvGetAudioOutFeedingParameter(u32 audio_handle, BtdrvPcmParameter *out);
/**
* @brief AcquireAudioOutStateChangedEvent
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[out] out_event Output Event.
* @param[in] autoclear Event autoclear.
*/
Result btdrvAcquireAudioOutStateChangedEvent(u32 audio_handle, Event* out_event, bool autoclear);
/**
* @brief AcquireAudioOutBufferAvailableEvent
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[out] out_event Output Event.
* @param[in] autoclear Event autoclear.
*/
Result btdrvAcquireAudioOutBufferAvailableEvent(u32 audio_handle, Event* out_event, bool autoclear);
/**
* @brief SendAudioData
* @note Only available on [12.0.0+].
* @param[in] audio_handle Audio handle from \ref btdrvOpenAudioOut.
* @param[in] buffer Input buffer.
* @param[in] size Input buffer size.
* @param[out] Output transferred size. This is always either 0 (error occured) or the buffer size.
*/
Result btdrvSendAudioData(u32 audio_handle, const void* buffer, size_t size, u64 *transferred_size);
/**
* @brief AcquireAudioControlInputStateChangedEvent
* @note Only available on [12.0.0+].
* @param[out] out_event Output Event.
* @param[in] autoclear Event autoclear.
*/
Result btdrvAcquireAudioControlInputStateChangedEvent(Event* out_event, bool autoclear);
/**
* @brief GetAudioControlInputState
* @note Only available on [12.0.0+].
* @param[out] states Output array of \ref BtdrvAudioControlButtonState.
* @param[in] count Size of the states array in entries, the maximum is 0xF.
* @param[out] total_out Total output entries.
*/
Result btdrvGetAudioControlInputState(BtdrvAudioControlButtonState *states, s32 count, s32 *total_out);
/**
* @brief AcquireAudioConnectionStateChangedEvent
* @note Only available on [12.0.0+].
* @param[out] out_event Output Event.
* @param[in] autoclear Event autoclear.
*/
Result btdrvAcquireAudioConnectionStateChangedEvent(Event* out_event, bool autoclear);
/**
* @brief GetConnectedAudioDevice
* @note Only available on [12.0.0+].
* @param[out] addrs Output array of \ref BtdrvAddress.
* @param[in] count Size of the addrs array in entries, the maximum is 0x8.
* @param[out] total_out Total output entries.
*/
Result btdrvGetConnectedAudioDevice(BtdrvAddress *addrs, s32 count, s32 *total_out);
/** /**
* @brief IsManufacturingMode * @brief IsManufacturingMode
* @note Only available on [5.0.0+]. * @note Only available on [5.0.0+].

View File

@ -73,6 +73,23 @@ typedef enum {
BtdrvFatalReason_Enable = 7, ///< Only for \ref BtdrvEventInfo: triggered after enabling bluetooth, depending on the value of a global state field. BtdrvFatalReason_Enable = 7, ///< Only for \ref BtdrvEventInfo: triggered after enabling bluetooth, depending on the value of a global state field.
} BtdrvFatalReason; } BtdrvFatalReason;
/// AudioEventType
typedef enum {
BtdrvAudioEventType_None = 0, ///< None
BtdrvAudioEventType_Connection = 1, ///< Connection
} BtdrvAudioEventType;
/// AudioOutState
typedef enum {
BtdrvAudioOutState_Stopped = 0, ///< Stopped
BtdrvAudioOutState_Started = 1, ///< Started
} BtdrvAudioOutState;
/// AudioCodec
typedef enum {
BtdrvAudioCodec_Pcm = 0, ///< Raw PCM
} BtdrvAudioCodec;
/// Address /// Address
typedef struct { typedef struct {
u8 address[0x6]; ///< Address u8 address[0x6]; ///< Address
@ -220,3 +237,15 @@ typedef struct {
u8 data[0x200]; ///< BtdrvLeEventInfo::data u8 data[0x200]; ///< BtdrvLeEventInfo::data
} BtdrvBleClientGattOperationInfo; } BtdrvBleClientGattOperationInfo;
/// PcmParameter
typedef struct {
u32 unk_x0; ///< Must be 0-3. Controls number of channels: 0 = mono, non-zero = stereo.
s32 sample_rate; ///< Sample rate. Must be one of the following: 16000, 32000, 44100, 48000.
u32 bits_per_sample; ///< Bits per sample. Must be 8 or 16.
} BtdrvPcmParameter;
/// AudioControlButtonState
typedef struct {
u8 unk_x0[0x10]; ///< Unknown
} BtdrvAudioControlButtonState;

View File

@ -99,6 +99,10 @@ static Result _btdrvCmdNoInOutBool(bool *out, u32 cmd_id) {
return rc; return rc;
} }
static Result _btdrvCmdInU32OutU32(u32 inval, u32 *out, u32 cmd_id) {
return serviceDispatchInOut(&g_btdrvSrv, cmd_id, inval, *out);
}
static Result _btdrvCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) { static Result _btdrvCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) {
Handle tmp_handle = INVALID_HANDLE; Handle tmp_handle = INVALID_HANDLE;
Result rc = 0; Result rc = 0;
@ -108,6 +112,18 @@ static Result _btdrvCmdGetEvent(Event* out_event, bool autoclear, u32 cmd_id) {
return rc; return rc;
} }
static Result _btdrvCmdInU32OutEvent(u32 inval, Event* out_event, bool autoclear, u32 cmd_id) {
Handle tmp_handle = INVALID_HANDLE;
Result rc = serviceDispatchIn(&g_btdrvSrv, cmd_id, inval,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &tmp_handle,
);
if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear);
return rc;
}
static Result _btdrvCmdInBufPtrFixed(const void* buffer, size_t size, u32 cmd_id) { static Result _btdrvCmdInBufPtrFixed(const void* buffer, size_t size, u32 cmd_id) {
return serviceDispatch(&g_btdrvSrv, cmd_id, return serviceDispatch(&g_btdrvSrv, cmd_id,
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize },
@ -1125,6 +1141,167 @@ Result btdrvMoveToSecondaryPiconet(BtdrvAddress addr) {
return _btdrvCmdInAddrNoOut(addr, 99); return _btdrvCmdInAddrNoOut(addr, 99);
} }
Result btdrvIsBluetoothEnabled(bool *out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdNoInOutBool(out, 100);
}
Result btdrvAcquireAudioEvent(Event* out_event, bool autoclear) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdGetEvent(out_event, autoclear, 128);
}
Result btdrvGetAudioEventInfo(void* buffer, size_t size, BtdrvAudioEventType *type) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u32 tmp=0;
Result rc = _btdrvCmdOutU32OutBuf(buffer, size, &tmp, 129);
if (R_SUCCEEDED(rc) && type) *type = tmp;
return rc;
}
Result btdrvOpenAudioConnection(BtdrvAddress addr) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInAddrNoOut(addr, 130);
}
Result btdrvCloseAudioConnection(BtdrvAddress addr) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInAddrNoOut(addr, 131);
}
Result btdrvOpenAudioOut(BtdrvAddress addr, u32 *audio_handle) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_btdrvSrv, 132, addr, *audio_handle);
}
Result btdrvCloseAudioOut(u32 audio_handle) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInU32NoOut(audio_handle, 133);
}
Result btdrvAcquireAudioOutStateChangedEvent(u32 audio_handle, Event* out_event, bool autoclear) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInU32OutEvent(audio_handle, out_event, autoclear, 134);
}
Result btdrvStartAudioOut(u32 audio_handle, const BtdrvPcmParameter *pcm_param, s64 in_latency, s64 *out_latency, u64 *out1) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u32 audio_handle;
BtdrvPcmParameter pcm_param;
s64 latency;
} in = { audio_handle, *pcm_param, in_latency };
struct {
s64 latency;
u64 out1;
} out;
Result rc = serviceDispatchInOut(&g_btdrvSrv, 135, in, out);
if (R_SUCCEEDED(rc)) {
if (out_latency) *out_latency = out.latency;
if (out1) *out1 = out.out1;
}
return rc;
}
Result btdrvStopAudioOut(u32 audio_handle) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInU32NoOut(audio_handle, 136);
}
Result btdrvGetAudioOutState(u32 audio_handle, BtdrvAudioOutState *out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u32 tmp=0;
Result rc = _btdrvCmdInU32OutU32(audio_handle, &tmp, 137);
if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc;
}
Result btdrvGetAudioOutFeedingCodec(u32 audio_handle, BtdrvAudioCodec *out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u32 tmp=0;
Result rc = _btdrvCmdInU32OutU32(audio_handle, &tmp, 138);
if (R_SUCCEEDED(rc) && out) *out = tmp;
return rc;
}
Result btdrvGetAudioOutFeedingParameter(u32 audio_handle, BtdrvPcmParameter *out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_btdrvSrv, 139, audio_handle, *out);
}
Result btdrvAcquireAudioOutBufferAvailableEvent(u32 audio_handle, Event* out_event, bool autoclear) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdInU32OutEvent(audio_handle, out_event, autoclear, 140);
}
Result btdrvSendAudioData(u32 audio_handle, const void* buffer, size_t size, u64 *transferred_size) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_btdrvSrv, 141, audio_handle, *transferred_size,
.buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In },
.buffers = { { buffer, size } },
);
}
Result btdrvAcquireAudioControlInputStateChangedEvent(Event* out_event, bool autoclear) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdGetEvent(out_event, autoclear, 142);
}
Result btdrvGetAudioControlInputState(BtdrvAudioControlButtonState *states, s32 count, s32 *total_out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdOutU32OutBuf(states, count*sizeof(BtdrvAudioControlButtonState), (u32*)total_out, 143);
}
Result btdrvAcquireAudioConnectionStateChangedEvent(Event* out_event, bool autoclear) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdGetEvent(out_event, autoclear, 144);
}
Result btdrvGetConnectedAudioDevice(BtdrvAddress *addrs, s32 count, s32 *total_out) {
if (hosversionBefore(12,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _btdrvCmdOutU32OutBuf(addrs, count*sizeof(BtdrvAddress), (u32*)total_out, 145);
}
Result btdrvIsManufacturingMode(bool *out) { Result btdrvIsManufacturingMode(bool *out) {
if (hosversionBefore(5,0,0)) if (hosversionBefore(5,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);