Implement cdc:CHK service
This commit is contained in:
parent
cb9d682f65
commit
a30628058c
@ -79,6 +79,7 @@ extern "C" {
|
||||
#include <3ds/services/loader.h>
|
||||
#include <3ds/services/y2r.h>
|
||||
#include <3ds/services/mcuhwc.h>
|
||||
#include <3ds/services/cdcchk.h>
|
||||
|
||||
#include <3ds/gpu/gx.h>
|
||||
#include <3ds/gpu/gpu.h>
|
||||
|
90
libctru/include/3ds/services/cdcchk.h
Normal file
90
libctru/include/3ds/services/cdcchk.h
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @file cdcchk.h
|
||||
* @brief CODEC Hardware Check service.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
/// I2S line enumeration
|
||||
typedef enum {
|
||||
CODEC_I2S_LINE_1, ///< Primary I2S line, used by DSP/Mic (configurable)/GBA sound controller.
|
||||
CODEC_I2S_LINE_2, ///< Secondary I2S line, used by CSND hardware.
|
||||
} CodecI2sLine;
|
||||
|
||||
/// Initializes CDCCHK.
|
||||
Result cdcChkInit(void);
|
||||
|
||||
/// Exits CDCCHK.
|
||||
void cdcChkExit(void);
|
||||
|
||||
/**
|
||||
* @brief Gets a pointer to the current cdc:CHK session handle.
|
||||
* @return A pointer to the current cdc:CHK session handle.
|
||||
*/
|
||||
Handle *cdcChkGetSessionHandle(void);
|
||||
|
||||
/**
|
||||
* @brief Reads multiple registers from the CODEC, using the old
|
||||
* SPI hardware interface and a 4MHz baudrate.
|
||||
* @param pageId CODEC Page ID.
|
||||
* @param initialRegAddr Address of the CODEC register to start with.
|
||||
* @param[out] outData Where to write the read data to.
|
||||
* @param size Number of registers to read (bytes to read, max. 64).
|
||||
*/
|
||||
Result CDCCHK_ReadRegisters1(u8 pageId, u8 initialRegAddr, void *outData, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Reads multiple registers from the CODEC, using the new
|
||||
* SPI hardware interface and a 16MHz baudrate.
|
||||
* @param pageId CODEC Page ID.
|
||||
* @param initialRegAddr Address of the CODEC register to start with.
|
||||
* @param[out] outData Where to read the data to.
|
||||
* @param size Number of registers to read (bytes to read, max. 64).
|
||||
*/
|
||||
Result CDCCHK_ReadRegisters2(u8 pageId, u8 initialRegAddr, void *outData, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Writes multiple registers to the CODEC, using the old
|
||||
* SPI hardware interface and a 4MHz baudrate.
|
||||
* @param pageId CODEC Page ID.
|
||||
* @param initialRegAddr Address of the CODEC register to start with.
|
||||
* @param data Where to read the data to write from.
|
||||
* @param size Number of registers to write (bytes to read, max. 64).
|
||||
*/
|
||||
Result CDCCHK_WriteRegisters1(u8 pageId, u8 initialRegAddr, const void *data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Writes multiple registers to the CODEC, using the new
|
||||
* SPI hardware interface and a 16MHz baudrate.
|
||||
* @param pageId CODEC Page ID.
|
||||
* @param initialRegAddr Address of the CODEC register to start with.
|
||||
* @param data Where to read the data to write from.
|
||||
* @param size Number of registers to write (bytes to read, max. 64).
|
||||
*/
|
||||
Result CDCCHK_WriteRegisters2(u8 pageId, u8 initialRegAddr, const void *data, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Reads a single register from the NTR PMIC.
|
||||
* @param[out] outData Where to read the data to (1 byte).
|
||||
* @param regAddr Register address.
|
||||
* @note The NTR PMIC is emulated by the CODEC hardware and sends
|
||||
* IRQs to the MCU when relevant.
|
||||
*/
|
||||
Result CDCCHK_ReadNtrPmicRegister(u8 *outData, u8 regAddr);
|
||||
|
||||
/**
|
||||
* @brief Writes a single register from the NTR PMIC.
|
||||
* @param regAddr Register address.
|
||||
* @param data Data to write (1 byte).
|
||||
* @note The NTR PMIC is emulated by the CODEC hardware and sends
|
||||
* IRQs to the MCU when relevant.
|
||||
*/
|
||||
Result CDCCHK_WriteNtrPmicRegister(u8 regAddr, u8 data);
|
||||
|
||||
/**
|
||||
* @brief Sets the DAC volume level for the specified I2S line.
|
||||
* @param i2sLine I2S line to set the volume for.
|
||||
* @param volume Volume level (-128 to 0).
|
||||
*/
|
||||
Result CDCCHK_SetI2sVolume(CodecI2sLine i2sLine, s8 volume);
|
162
libctru/source/services/cdcchk.c
Normal file
162
libctru/source/services/cdcchk.c
Normal file
@ -0,0 +1,162 @@
|
||||
#include <string.h>
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/result.h>
|
||||
#include <3ds/svc.h>
|
||||
#include <3ds/srv.h>
|
||||
#include <3ds/synchronization.h>
|
||||
#include <3ds/ipc.h>
|
||||
#include <3ds/services/cdcchk.h>
|
||||
|
||||
static Handle cdcChkHandle;
|
||||
static int cdcChkRefCount;
|
||||
|
||||
Result cdcChkInit(void)
|
||||
{
|
||||
if (AtomicPostIncrement(&cdcChkRefCount))
|
||||
return 0;
|
||||
|
||||
Result res = srvGetServiceHandle(&cdcChkHandle, "cdc:CHK");
|
||||
if (R_FAILED(res))
|
||||
AtomicDecrement(&cdcChkRefCount);
|
||||
return res;
|
||||
}
|
||||
|
||||
void cdcChkExit(void)
|
||||
{
|
||||
if (AtomicDecrement(&cdcChkRefCount))
|
||||
return;
|
||||
svcCloseHandle(cdcChkHandle);
|
||||
}
|
||||
|
||||
Handle *cdcChkGetSessionHandle(void)
|
||||
{
|
||||
return &cdcChkHandle;
|
||||
}
|
||||
|
||||
Result CDCCHK_ReadRegisters1(u8 pageId, u8 initialRegAddr, void *outData, size_t size)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 *staticbufs = getThreadStaticBuffers();
|
||||
|
||||
u32 staticbufBackup[2];
|
||||
memcpy(staticbufBackup, staticbufs, 8);
|
||||
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(size, 0);
|
||||
staticbufs[1] = (u32)outData;
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(1, 3, 0); // 0x100C0
|
||||
cmdbuf[1] = pageId;
|
||||
cmdbuf[2] = initialRegAddr;
|
||||
cmdbuf[3] = size;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
memcpy(staticbufs, staticbufBackup, 8);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_ReadRegisters2(u8 pageId, u8 initialRegAddr, void *outData, size_t size)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
u32 *staticbufs = getThreadStaticBuffers();
|
||||
|
||||
u32 staticbufBackup[2];
|
||||
memcpy(staticbufBackup, staticbufs, 8);
|
||||
|
||||
staticbufs[0] = IPC_Desc_StaticBuffer(size, 0);
|
||||
staticbufs[1] = (u32)outData;
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(2, 3, 0); // 0x200C0
|
||||
cmdbuf[1] = pageId;
|
||||
cmdbuf[2] = initialRegAddr;
|
||||
cmdbuf[3] = size;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
memcpy(staticbufs, staticbufBackup, 8);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_WriteRegisters1(u8 pageId, u8 initialRegAddr, const void *data, size_t size)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(3, 3, 2); // 0x300C2
|
||||
cmdbuf[1] = pageId;
|
||||
cmdbuf[2] = initialRegAddr;
|
||||
cmdbuf[3] = size;
|
||||
cmdbuf[4] = IPC_Desc_StaticBuffer(size, 0);
|
||||
cmdbuf[5] = (u32)data;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_WriteRegisters2(u8 pageId, u8 initialRegAddr, const void *data, size_t size)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(4, 3, 2); // 0x400C2
|
||||
cmdbuf[1] = pageId;
|
||||
cmdbuf[2] = initialRegAddr;
|
||||
cmdbuf[3] = size;
|
||||
cmdbuf[4] = IPC_Desc_StaticBuffer(size, 0);
|
||||
cmdbuf[5] = (u32)data;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_ReadNtrPmicRegister(u8 *outData, u8 regAddr)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(5, 1, 0); // 0x50040
|
||||
cmdbuf[1] = regAddr;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
if (R_SUCCEEDED(ret))
|
||||
{
|
||||
*outData = (u8)cmdbuf[2];
|
||||
ret = cmdbuf[1];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_WriteNtrPmicRegister(u8 regAddr, u8 data)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(6, 2, 0); // 0x60080
|
||||
cmdbuf[1] = regAddr;
|
||||
cmdbuf[2] = data;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
||||
|
||||
Result CDCCHK_SetI2sVolume(CodecI2sLine i2sLine, s8 volume)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(7, 2, 0); // 0x70080
|
||||
cmdbuf[1] = (u32)i2sLine;
|
||||
cmdbuf[2] = volume;
|
||||
|
||||
ret = svcSendSyncRequest(cdcChkHandle);
|
||||
|
||||
return R_SUCCEEDED(ret) ? cmdbuf[1] : ret;
|
||||
}
|
Loading…
Reference in New Issue
Block a user