#include "prx/libSceCamera/libSceCamera.hpp" #include #include #include #include #include using GetU32 = int(APS5_VABI*)(std::int32_t, std::uint32_t, std::uint32_t*, void*); using SetU32 = int(APS5_VABI*)(std::int32_t, std::uint32_t, std::uint32_t, const void*); namespace { constexpr int ErrorParam = static_cast(0x802E0000u); constexpr int ErrorNotInit = static_cast(0x802E0002u); constexpr int ErrorNotOpen = static_cast(0x802E0004u); constexpr int ErrorNotConnected = static_cast(0x802E0010u); constexpr int ErrorFatal = static_cast(0x802E00FFu); constexpr std::uint32_t Channel0 = 1; constexpr std::uint32_t Channel1 = 2; constexpr std::uint32_t ChannelBoth = 3; void Require(bool condition, const char* message) { if (!condition) { std::fprintf(stderr, "Camera settings: %s\n", message); std::abort(); } } CameraConfig SizedConfig() { CameraConfig config; std::memset(&config, 0x5a, sizeof(config)); config.sizeThis = sizeof(CameraConfig); return config; } void CheckBeforeOpen() { std::uint32_t value = 0; CameraConfig config = SizedConfig(); const CameraDeviceInfo info{sizeof(CameraDeviceInfo), 1, 0, 0}; Require(sceCameraGetContrast(1, Channel0, &value, nullptr) == ErrorNotOpen, "a getter before open must report NOT_OPEN"); Require(sceCameraSetContrast(1, Channel0, 1, nullptr) == ErrorNotOpen, "a setter before open must report NOT_OPEN"); Require(sceCameraGetConfig(1, &config) == ErrorNotOpen, "reading the configuration before open must report NOT_OPEN"); Require(sceCameraGetDeviceConfigWithoutHandle(&config) == ErrorNotOpen, "reading the device configuration before open must report NOT_OPEN"); Require(sceCameraGetMmapConnectedCount(&value) == ErrorNotOpen, "the mapped device count before open must report NOT_OPEN"); Require(sceCameraGetDeviceInfo(0, &info) == ErrorNotInit, "device info before open must report NOT_INIT"); Require(sceCameraGetProductInfo(&value) == ErrorNotInit, "product info before open must report NOT_INIT"); Require(sceCameraGetRegistryInfo(&value) == ErrorNotInit, "registry info before open must report NOT_INIT"); } void CheckGetter(GetU32 get, std::uint32_t expected, const char* message) { std::uint32_t value = 0x5a5a5a5a; Require(get(1, Channel1, &value, nullptr) == 0 && value == expected, message); value = 0x5a5a5a5a; std::uint32_t option = 0; Require(get(0, Channel0, &value, nullptr) == ErrorParam, "a getter must reject handle 0"); Require(get(99, Channel0, &value, nullptr) == ErrorNotOpen && value == 0x5a5a5a5a, "a fabricated handle must not read settings"); Require(get(1, 0, &value, nullptr) == ErrorParam, "a getter must reject channel 0"); Require(get(1, ChannelBoth, &value, nullptr) == ErrorParam, "a getter must reject both channels"); Require(get(1, 4, &value, nullptr) == ErrorParam, "a getter must reject channel 4"); Require(get(1, 0xFFFFFFFFu, &value, nullptr) == ErrorParam, "a getter must reject invalid channel"); Require(get(1, Channel0, nullptr, nullptr) == ErrorParam, "a getter must reject a null result"); Require(get(1, Channel0, &value, &option) == ErrorParam, "a getter must reject an option"); Require(value == 0x5a5a5a5a, "a refused getter must not write its result"); } void CheckGetters() { CheckGetter(sceCameraGetAutoWhiteBalance, 0, "automatic white balance must be off"); CheckGetter(sceCameraGetDefectivePixelCancellation, 0, "defective pixel cancellation must be off"); CheckGetter(sceCameraGetLensCorrection, 0, "lens correction must be off"); CheckGetter(sceCameraGetContrast, 32, "the contrast must be 32"); CheckGetter(sceCameraGetSaturation, 64, "the saturation must be 64"); CheckGetter(sceCameraGetSharpness, 1, "the sharpness must be 1"); std::int32_t hue = 0; Require(sceCameraGetHue(1, Channel0, &hue, nullptr) == 0 && hue == 1, "the hue must be 1"); CameraExposureGain exposure{9, 9, 9, 9}; Require(sceCameraGetExposureGain(1, Channel0, &exposure, nullptr) == 0, "the exposure must be readable"); Require(exposure.exposureControl == 0 && exposure.exposure == 20 && exposure.gain == 100 && exposure.mode == 0, "the exposure defaults are wrong"); CameraWhiteBalance balance{9, 9, 9, 9}; Require(sceCameraGetWhiteBalance(1, Channel0, &balance, nullptr) == 0, "the white balance must be readable"); Require(balance.whiteBalanceControl == 0 && balance.gainRed == 768 && balance.gainBlue == 768 && balance.gainGreen == 512, "the white balance defaults are wrong"); CameraGamma gamma; std::memset(&gamma, 0x5a, sizeof(gamma)); Require(sceCameraGetGamma(1, Channel0, &gamma, nullptr) == 0 && gamma.gammaControl == 0 && gamma.value == 4 && gamma.reserved[15] == 0, "the gamma defaults are wrong"); std::uint32_t enable = 9; CameraAutoExposureGainTarget target{sizeof(CameraAutoExposureGainTarget), 0x10}; Require(sceCameraGetAutoExposureGain(1, Channel0, &enable, &target) == 0 && enable == 0, "automatic exposure must be off"); Require(target.sizeThis == 0 && target.target == 0, "the automatic exposure target must be cleared"); target.sizeThis = 4; Require(sceCameraGetAutoExposureGain(1, Channel0, &enable, &target) == ErrorParam, "a target of the wrong size must be rejected"); Require(sceCameraGetAutoExposureGain(1, Channel0, &enable, nullptr) == 0, "automatic exposure must be readable without a target"); } void CheckAttribute() { CameraAttribute attribute; std::memset(&attribute, 0x5a, sizeof(attribute)); attribute.sizeThis = sizeof(CameraAttribute); attribute.channel = Channel1; Require(sceCameraGetAttribute(1, &attribute) == 0, "the attributes must be readable"); Require(attribute.sizeThis == sizeof(CameraAttribute) && attribute.channel == Channel1, "the attribute header must be kept"); Require(attribute.framePosition.x == 0 && attribute.exposureGain.exposure == 83 && attribute.exposureGain.gain == 100, "the attribute exposure is wrong"); Require(attribute.whiteBalance.gainRed == 768 && attribute.whiteBalance.gainGreen == 512 && attribute.gamma.value == 4, "the attribute colour defaults are wrong"); Require(attribute.saturation == 64 && attribute.contrast == 32 && attribute.sharpness == 1 && attribute.hue == 1 && attribute.reserved[3] == 0, "the attribute levels are wrong"); attribute.channel = ChannelBoth; Require(sceCameraGetAttribute(1, &attribute) == ErrorParam, "reading both channels at once must be rejected"); Require(sceCameraSetAttribute(1, &attribute) == ErrorNotConnected, "writing both channels must report NOT_CONNECTED"); attribute.channel = 4; Require(sceCameraSetAttribute(1, &attribute) == ErrorParam, "an unknown channel must be rejected"); attribute.channel = Channel0; attribute.sizeThis = sizeof(CameraAttribute) - 4; Require(sceCameraGetAttribute(1, &attribute) == ErrorParam && sceCameraSetAttribute(1, &attribute) == ErrorParam, "an attribute of the wrong size must be rejected"); Require(sceCameraGetAttribute(1, nullptr) == ErrorParam && sceCameraSetAttribute(1, nullptr) == ErrorParam, "a null attribute must be rejected"); } void CheckSetter(SetU32 set, std::uint32_t largestValue) { std::uint32_t option = 0; Require(set(1, ChannelBoth, largestValue, nullptr) == ErrorNotConnected, "a setter must report NOT_CONNECTED"); Require(set(0, Channel0, 0, nullptr) == ErrorParam, "a setter must reject handle 0"); Require(set(1, 0, 0, nullptr) == ErrorParam, "a setter must reject channel 0"); Require(set(1, 4, 0, nullptr) == ErrorParam, "a setter must reject channel 4"); Require(set(1, 0xFFFFFFFFu, 0, nullptr) == ErrorParam, "a setter must reject invalid channel"); Require(set(1, Channel0, 0, &option) == ErrorParam, "a setter must reject an option"); if (largestValue != UINT32_MAX) Require(set(1, Channel0, largestValue + 1, nullptr) == ErrorParam, "a setter must reject a value past its range"); } void CheckSetters() { CheckSetter(sceCameraSetAutoWhiteBalance, UINT32_MAX); CheckSetter(sceCameraSetContrast, UINT32_MAX); CheckSetter(sceCameraSetSaturation, UINT32_MAX); CheckSetter(sceCameraSetDefectivePixelCancellation, 1); CheckSetter(sceCameraSetDefectivePixelCancellationInternal, 2); CheckSetter(sceCameraSetLensCorrection, 1); CheckSetter(sceCameraSetLensCorrectionInternal, 2); CheckSetter(sceCameraSetSharpness, 10); Require(sceCameraSetHue(1, Channel0, -5, nullptr) == ErrorNotConnected, "a hue change must report NOT_CONNECTED"); const CameraExposureGain exposure{}; const CameraWhiteBalance balance{}; const CameraGamma gamma{}; Require(sceCameraSetExposureGain(1, Channel0, &exposure, nullptr) == ErrorNotConnected, "an exposure change must report NOT_CONNECTED"); Require(sceCameraSetWhiteBalance(1, Channel0, &balance, nullptr) == ErrorNotConnected, "a white balance change must report NOT_CONNECTED"); Require(sceCameraSetGamma(1, Channel0, &gamma, nullptr) == ErrorNotConnected, "a gamma change must report NOT_CONNECTED"); Require(sceCameraSetExposureGain(1, Channel0, nullptr, nullptr) == ErrorParam, "a null exposure must be rejected"); Require(sceCameraSetWhiteBalance(1, Channel0, nullptr, nullptr) == ErrorParam, "a null white balance must be rejected"); Require(sceCameraSetGamma(1, Channel0, nullptr, nullptr) == ErrorParam, "a null gamma must be rejected"); CameraAutoExposureGainTarget target{sizeof(CameraAutoExposureGainTarget), 0x20}; Require(sceCameraSetAutoExposureGain(1, Channel0, 1, &target) == ErrorNotConnected, "the largest exposure target must be accepted"); Require(sceCameraSetAutoExposureGain(1, Channel0, 1, nullptr) == ErrorNotConnected, "automatic exposure without a target must be accepted"); for (const std::uint32_t accepted : {0x0u, 0x2u, 0x4u, 0x6u, 0x8u, 0x10u, 0x12u, 0x14u, 0x16u, 0x20u}) { target.target = accepted; Require(sceCameraSetAutoExposureGain(1, Channel0, 1, &target) == ErrorNotConnected, "a listed exposure target must be accepted"); } for (const std::uint32_t refused : {0x1u, 0xAu, 0xCu, 0xEu, 0x11u, 0x18u, 0x1Au, 0x1Cu, 0x1Eu, 0x22u}) { target.target = refused; Require(sceCameraSetAutoExposureGain(1, Channel0, 1, &target) == ErrorParam, "an unlisted exposure target must be rejected"); } target = {4, 0x10}; Require(sceCameraSetAutoExposureGain(1, Channel0, 1, &target) == ErrorParam, "an exposure target of the wrong size must be rejected"); } void CheckConfig() { CameraConfig config = SizedConfig(); Require(sceCameraGetConfig(1, &config) == 0 && config.configType == 1, "the configuration must be type 1"); for (const CameraConfigExtension& extension : config.extension) { Require(extension.formatLevel[0] == 0 && extension.formatLevel[1] == 4 && extension.formatLevel[3] == 4, "the default formats are wrong"); Require(extension.resolution == 0 && extension.framerate == 60 && extension.width == 0 && extension.baseOption == nullptr, "the default mode is wrong"); } Require(sceCameraSetConfig(1, &config) == ErrorNotConnected, "a new configuration must report NOT_CONNECTED"); Require(sceCameraSetConfigInternal(1, &config) == ErrorNotConnected, "an internal configuration must report NOT_CONNECTED"); config = SizedConfig(); Require(sceCameraGetDeviceConfig(1, &config) == 0 && config.sizeThis == sizeof(CameraConfig) && config.configType == 0, "the device configuration must be empty"); Require(config.extension[1].baseOption == nullptr, "the device configuration must be cleared"); config = SizedConfig(); Require(sceCameraGetDeviceConfigWithoutHandle(&config) == 0 && config.sizeThis == 0 && config.configType == 0, "the handleless device configuration must be cleared"); config = SizedConfig(); config.sizeThis = 96; Require(sceCameraGetConfig(1, &config) == ErrorParam && sceCameraSetConfig(1, &config) == ErrorParam, "a configuration of the wrong size must be rejected"); Require(sceCameraGetDeviceConfig(1, &config) == ErrorParam && sceCameraGetDeviceConfigWithoutHandle(&config) == ErrorParam, "a device configuration of the wrong size must be rejected"); Require(sceCameraGetConfig(0, nullptr) == ErrorParam && sceCameraSetConfigInternal(1, nullptr) == ErrorParam, "a missing configuration must be rejected"); } void CheckDevice() { CameraDeviceInfo info{sizeof(CameraDeviceInfo), 1, 0, 0}; std::array out{}; Require(sceCameraGetDeviceInfo(0, &info) == ErrorNotConnected, "device info must report NOT_CONNECTED"); Require(sceCameraGetDeviceInfo(1, &info) == ErrorParam, "a reserved value other than 0 must be rejected"); info.infoRevision = 2; Require(sceCameraGetDeviceInfo(0, &info) == ErrorParam, "an unknown info revision must be rejected"); Require(sceCameraGetDeviceInfo(0, nullptr) == ErrorParam, "null device info must be rejected"); Require(sceCameraGetProductInfo(out.data()) == ErrorNotConnected && sceCameraGetRegistryInfo(out.data()) == ErrorNotConnected, "product and registry info must report NOT_CONNECTED"); Require(sceCameraGetProductInfo(nullptr) == ErrorParam && sceCameraGetRegistryInfo(nullptr) == ErrorParam, "null product or registry info must be rejected"); std::uint32_t count = 9; Require(sceCameraGetMmapConnectedCount(&count) == 0 && count == 0, "no camera may be mapped"); Require(sceCameraGetMmapConnectedCount(nullptr) == ErrorParam, "a null count must be rejected"); Require(sceCameraGetCalibDataFromDevice() == ErrorNotConnected, "device calibration must report NOT_CONNECTED"); CameraGetCalibrationDataParameter param{sizeof(CameraGetCalibrationDataParameter), 0, 1}; Require(sceCameraGetCalibrationData(¶m, out.data()) == ErrorNotConnected, "calibration data must report NOT_CONNECTED"); Require(sceCameraGetCalibrationData(¶m, nullptr) == ErrorParam && sceCameraGetCalibrationData(nullptr, out.data()) == ErrorParam, "missing calibration arguments must be rejected"); for (const CameraGetCalibrationDataParameter refused : {CameraGetCalibrationDataParameter{8, 0, 0}, CameraGetCalibrationDataParameter{12, 1, 0}, CameraGetCalibrationDataParameter{12, 0, 2}}) { Require(sceCameraGetCalibrationData(&refused, out.data()) == ErrorParam, "a bad calibration request must be rejected"); } Require(sceCameraAudioOpen() == ErrorFatal, "camera audio must fail with FATAL"); } } int main() { CheckBeforeOpen(); Require(sceCameraOpen(0xFF, 0, 0, nullptr) == 1, "the camera must open"); CheckGetters(); CheckAttribute(); CheckSetters(); CheckConfig(); CheckDevice(); Require(sceCameraClose(1) == 0, "the camera must close"); std::uint32_t value = 0; Require(sceCameraGetSharpness(1, Channel0, &value, nullptr) == ErrorNotOpen, "a getter after close must report NOT_OPEN"); return 0; }