// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/service.h"
namespace Service {
namespace CAM {
enum CameraIndex {
OuterRightCamera = 0,
InnerCamera = 1,
OuterLeftCamera = 2,
NumCameras = 3,
};
enum class Effect : u8 {
None = 0,
Mono = 1,
Sepia = 2,
Negative = 3,
Negafilm = 4,
Sepia01 = 5,
};
enum class Flip : u8 {
None = 0,
Horizontal = 1,
Vertical = 2,
Reverse = 3,
};
enum class Size : u8 {
VGA = 0,
QVGA = 1,
QQVGA = 2,
CIF = 3,
QCIF = 4,
DS_LCD = 5,
DS_LCDx4 = 6,
CTR_TOP_LCD = 7,
CTR_BOTTOM_LCD = QVGA,
};
enum class FrameRate : u8 {
Rate_15 = 0,
Rate_15_To_5 = 1,
Rate_15_To_2 = 2,
Rate_10 = 3,
Rate_8_5 = 4,
Rate_5 = 5,
Rate_20 = 6,
Rate_20_To_5 = 7,
Rate_30 = 8,
Rate_30_To_5 = 9,
Rate_15_To_10 = 10,
Rate_20_To_10 = 11,
Rate_30_To_10 = 12,
};
enum class ShutterSoundType : u8 {
Normal = 0,
Movie = 1,
MovieEnd = 2,
};
enum class WhiteBalance : u8 {
BalanceAuto = 0,
Balance3200K = 1,
Balance4150K = 2,
Balance5200K = 3,
Balance6000K = 4,
Balance7000K = 5,
BalanceMax = 6,
BalanceNormal = BalanceAuto,
BalanceTungsten = Balance3200K,
BalanceWhiteFluorescentLight = Balance4150K,
BalanceDaylight = Balance5200K,
BalanceCloudy = Balance6000K,
BalanceHorizon = Balance6000K,
BalanceShade = Balance7000K,
};
enum class PhotoMode : u8 {
Normal = 0,
Portrait = 1,
Landscape = 2,
Nightview = 3,
Letter0 = 4,
};
enum class LensCorrection : u8 {
Off = 0,
On70 = 1,
On90 = 2,
Dark = Off,
Normal = On70,
Bright = On90,
};
enum class Contrast : u8 {
Pattern01 = 1,
Pattern02 = 2,
Pattern03 = 3,
Pattern04 = 4,
Pattern05 = 5,
Pattern06 = 6,
Pattern07 = 7,
Pattern08 = 8,
Pattern09 = 9,
Pattern10 = 10,
Pattern11 = 11,
Low = Pattern05,
Normal = Pattern06,
High = Pattern07,
};
enum class OutputFormat : u8 {
YUV422 = 0,
RGB565 = 1,
};
/// Stereo camera calibration data.
struct StereoCameraCalibrationData {
u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid.
INSERT_PADDING_BYTES(3);
float_le scale; ///< Scale to match the left camera image with the right.
float_le rotationZ; ///< Z axis rotation to match the left camera image with the right.
float_le translationX; ///< X axis translation to match the left camera image with the right.
float_le translationY; ///< Y axis translation to match the left camera image with the right.
float_le rotationX; ///< X axis rotation to match the left camera image with the right.
float_le rotationY; ///< Y axis rotation to match the left camera image with the right.
float_le angleOfViewRight; ///< Right camera angle of view.
float_le angleOfViewLeft; ///< Left camera angle of view.
float_le distanceToChart; ///< Distance between cameras and measurement chart.
float_le distanceCameras; ///< Distance between left and right cameras.
s16_le imageWidth; ///< Image width.
s16_le imageHeight; ///< Image height.
INSERT_PADDING_BYTES(16);
};
static_assert(sizeof(StereoCameraCalibrationData) == 64,
"StereoCameraCalibrationData structure size is wrong");
/**
* Resolution parameters for the camera.
* The native resolution of 3DS camera is 640 * 480. The captured image will be cropped in the
* region [crop_x0, crop_x1] * [crop_y0, crop_y1], and then scaled to size width * height as the
* output image. Note that all cropping coordinates are inclusive.
*/
struct Resolution {
u16 width;
u16 height;
u16 crop_x0;
u16 crop_y0;
u16 crop_x1;
u16 crop_y1;
};
struct PackageParameterWithoutContext {
u8 camera_select;
s8 exposure;
WhiteBalance white_balance;
s8 sharpness;
bool auto_exposure;
bool auto_white_balance;
FrameRate frame_rate;
PhotoMode photo_mode;
Contrast contrast;
LensCorrection lens_correction;
bool noise_filter;
u8 padding;
s16 auto_exposure_window_x;
s16 auto_exposure_window_y;
s16 auto_exposure_window_width;
s16 auto_exposure_window_height;
s16 auto_white_balance_window_x;
s16 auto_white_balance_window_y;
s16 auto_white_balance_window_width;
s16 auto_white_balance_window_height;
};
static_assert(sizeof(PackageParameterWithoutContext) == 28,
"PackageParameterCameraWithoutContext structure size is wrong");
struct PackageParameterWithContext {
u8 camera_select;
u8 context_select;
Flip flip;
Effect effect;
Size size;
INSERT_PADDING_BYTES(3);
Resolution GetResolution();
};
static_assert(sizeof(PackageParameterWithContext) == 8,
"PackageParameterWithContext structure size is wrong");
struct PackageParameterWithContextDetail {
u8 camera_select;
u8 context_select;
Flip flip;
Effect effect;
Resolution resolution;
Resolution GetResolution() {
return resolution;
}
};
static_assert(sizeof(PackageParameterWithContextDetail) == 16,
"PackageParameterWithContextDetail structure size is wrong");
/**
* Starts capturing at the selected port.
* Inputs:
* 0: 0x00010040
* 1: u8 selected port
* Outputs:
* 0: 0x00010040
* 1: ResultCode
*/
void StartCapture(Service::Interface* self);
/**
* Stops capturing from the selected port.
* Inputs:
* 0: 0x00020040
* 1: u8 selected port
* Outputs:
* 0: 0x00020040
* 1: ResultCode
*/
void StopCapture(Service::Interface* self);
/**
* Gets whether the selected port is currently capturing.
* Inputs:
* 0: 0x00030040
* 1: u8 selected port
* Outputs:
* 0: 0x00030080
* 1: ResultCode
* 2: 0 if not capturing, 1 if capturing
*/
void IsBusy(Service::Interface* self);
/**
* Clears the buffer of selected ports.
* Inputs:
* 0: 0x00040040
* 1: u8 selected port
* Outputs:
* 0: 0x00040040
* 2: ResultCode
*/
void ClearBuffer(Service::Interface* self);
/**
* Unknown
* Inputs:
* 0: 0x00050040
* 1: u8 selected port
* Outputs:
* 0: 0x00050042
* 1: ResultCode
* 2: Descriptor: Handle
* 3: Event handle
*/
void GetVsyncInterruptEvent(Service::Interface* self);
/**
* Unknown
* Inputs:
* 0: 0x00060040
* 1: u8 selected port
* Outputs:
* 0: 0x00060042
* 1: ResultCode
* 2: Descriptor: Handle
* 3: Event handle
*/
void GetBufferErrorInterruptEvent(Service::Interface* self);
/**
* Sets the target buffer to receive a frame of image data and starts the transfer. Each camera
* port has its own event to signal the end of the transfer.
*
* Inputs:
* 0: 0x00070102
* 1: Destination address in calling process
* 2: u8 selected port
* 3: Image size (in bytes)
* 4: u16 Transfer unit size (in bytes)
* 5: Descriptor: Handle
* 6: Handle to destination process
* Outputs:
* 0: 0x00070042
* 1: ResultCode
* 2: Descriptor: Handle
* 3: Handle to event signalled when transfer finishes
*/
void SetReceiving(Service::Interface* self);
/**
* Gets whether the selected port finished receiving a frame.
* Inputs:
* 0: 0x00080040
* 1: u8 selected port
* Outputs:
* 0: 0x00080080
* 1: ResultCode
* 2: 0 if not finished, 1 if finished
*/
void IsFinishedReceiving(Service::Interface* self);
/**
* Sets the number of lines the buffer contains.
* Inputs:
* 0: 0x00090100
* 1: u8 selected port
* 2: u16 Number of lines to transfer
* 3: u16 Width
* 4: u16 Height
* Outputs:
* 0: 0x00090040
* 1: ResultCode
* @todo figure out how the "buffer" actually works.
*/
void SetTransferLines(Service::Interface* self);
/**
* Gets the maximum number of lines that fit in the buffer
* Inputs:
* 0: 0x000A0080
* 1: u16 Width
* 2: u16 Height
* Outputs:
* 0: 0x000A0080
* 1: ResultCode
* 2: Maximum number of lines that fit in the buffer
* @todo figure out how the "buffer" actually works.
*/
void GetMaxLines(Service::Interface* self);
/**
* Sets the number of bytes the buffer contains.
* Inputs:
* 0: 0x000B0100
* 1: u8 selected port
* 2: u16 Number of bytes to transfer
* 3: u16 Width
* 4: u16 Height
* Outputs:
* 0: 0x000B0040
* 1: ResultCode
* @todo figure out how the "buffer" actually works.
*/
void SetTransferBytes(Service::Interface* self);
/**
* Gets the number of bytes to the buffer contains.
* Inputs:
* 0: 0x000C0040
* 1: u8 selected port
* Outputs:
* 0: 0x000C0080
* 1: ResultCode
* 2: The number of bytes the buffer contains
* @todo figure out how the "buffer" actually works.
*/
void GetTransferBytes(Service::Interface* self);
/**
* Gets the maximum number of bytes that fit in the buffer.
* Inputs:
* 0: 0x000D0080
* 1: u16 Width
* 2: u16 Height
* Outputs:
* 0: 0x000D0080
* 1: ResultCode
* 2: Maximum number of bytes that fit in the buffer
* @todo figure out how the "buffer" actually works.
*/
void GetMaxBytes(Service::Interface* self);
/**
* Enables or disables trimming.
* Inputs:
* 0: 0x000E0080
* 1: u8 selected port
* 2: u8 bool Enable trimming if true
* Outputs:
* 0: 0x000E0040
* 1: ResultCode
*/
void SetTrimming(Service::Interface* self);
/**
* Gets whether trimming is enabled.
* Inputs:
* 0: 0x000F0040
* 1: u8 selected port
* Outputs:
* 0: 0x000F0080
* 1: ResultCode
* 2: u8 bool Enable trimming if true
*/
void IsTrimming(Service::Interface* self);
/**
* Sets the position to trim.
* Inputs:
* 0: 0x00100140
* 1: u8 selected port
* 2: x start
* 3: y start
* 4: x end (exclusive)
* 5: y end (exclusive)
* Outputs:
* 0: 0x00100040
* 1: ResultCode
*/
void SetTrimmingParams(Service::Interface* self);
/**
* Gets the position to trim.
* Inputs:
* 0: 0x00110040
* 1: u8 selected port
*
* Outputs:
* 0: 0x00110140
* 1: ResultCode
* 2: x start
* 3: y start
* 4: x end (exclusive)
* 5: y end (exclusive)
*/
void GetTrimmingParams(Service::Interface* self);
/**
* Sets the position to trim by giving the width and height. The trimming window is always at the
* center.
* Inputs:
* 0: 0x00120140
* 1: u8 selected port
* 2: s16 Trim width
* 3: s16 Trim height
* 4: s16 Camera width
* 5: s16 Camera height
* Outputs:
* 0: 0x00120040
* 1: ResultCode
*/
void SetTrimmingParamsCenter(Service::Interface* self);
/**
* Selects up to two physical cameras to enable.
* Inputs:
* 0: 0x00130040
* 1: u8 selected camera
* Outputs:
* 0: 0x00130040
* 1: ResultCode
*/
void Activate(Service::Interface* self);
/**
* Switches the context of camera settings.
* Inputs:
* 0: 0x00140080
* 1: u8 selected camera
* 2: u8 selected context
* Outputs:
* 0: 0x00140040
* 1: ResultCode
*/
void SwitchContext(Service::Interface* self);
/**
* Sets flipping of images
* Inputs:
* 0: 0x001D00C0
* 1: u8 selected camera
* 2: u8 Type of flipping to perform (`Flip` enum)
* 3: u8 selected context
* Outputs:
* 0: 0x001D0040
* 1: ResultCode
*/
void FlipImage(Service::Interface* self);
/**
* Sets camera resolution from custom parameters. For more details see the Resolution struct.
* Inputs:
* 0: 0x001E0200
* 1: u8 selected camera
* 2: width
* 3: height
* 4: crop x0
* 5: crop y0
* 6: crop x1
* 7: crop y1
* 8: u8 selected context
* Outputs:
* 0: 0x001E0040
* 1: ResultCode
*/
void SetDetailSize(Service::Interface* self);
/**
* Sets camera resolution from preset resolution parameters.
* Inputs:
* 0: 0x001F00C0
* 1: u8 selected camera
* 2: u8 Camera frame resolution (`Size` enum)
* 3: u8 selected context
* Outputs:
* 0: 0x001F0040
* 1: ResultCode
*/
void SetSize(Service::Interface* self);
/**
* Sets camera framerate.
* Inputs:
* 0: 0x00200080
* 1: u8 selected camera
* 2: u8 Camera framerate (`FrameRate` enum)
* Outputs:
* 0: 0x00200040
* 1: ResultCode
*/
void SetFrameRate(Service::Interface* self);
/**
* Sets effect on the output image
* Inputs:
* 0: 0x002200C0
* 1: u8 selected camera
* 2: u8 image effect (`Effect` enum)
* 3: u8 selected context
* Outputs:
* 0: 0x00220040
* 1: ResultCode
*/
void SetEffect(Service::Interface* self);
/**
* Sets format of the output image
* Inputs:
* 0: 0x002500C0
* 1: u8 selected camera
* 2: u8 image format (`OutputFormat` enum)
* 3: u8 selected context
* Outputs:
* 0: 0x00250040
* 1: ResultCode
*/
void SetOutputFormat(Service::Interface* self);
/**
* Synchronizes the V-Sync timing of two cameras.
* Inputs:
* 0: 0x00290080
* 1: u8 selected camera 1
* 2: u8 selected camera 2
* Outputs:
* 0: 0x00280040
* 1: ResultCode
*/
void SynchronizeVsyncTiming(Service::Interface* self);
/**
* Returns calibration data relating the outside cameras to eachother, for use in AR applications.
*
* Inputs:
* 0: 0x002B0000
* Outputs:
* 0: 0x002B0440
* 1: ResultCode
* 2-17: `StereoCameraCalibrationData` structure with calibration values
*/
void GetStereoCameraCalibrationData(Service::Interface* self);
/**
* Batch-configures context-free settings.
*
* Inputs:
* 0: 0x003302C0
* 1-7: struct PachageParameterWithoutContext
* 8-11: unused
* Outputs:
* 0: 0x00330040
* 1: ResultCode
*/
void SetPackageParameterWithoutContext(Service::Interface* self);
/**
* Batch-configures context-related settings with preset resolution parameters.
*
* Inputs:
* 0: 0x00340140
* 1-2: struct PackageParameterWithContext
* 3-5: unused
* Outputs:
* 0: 0x00340040
* 1: ResultCode
*/
void SetPackageParameterWithContext(Service::Interface* self);
/**
* Batch-configures context-related settings with custom resolution parameters
*
* Inputs:
* 0: 0x003501C0
* 1-4: struct PackageParameterWithContextDetail
* 5-7: unused
* Outputs:
* 0: 0x00350040
* 1: ResultCode
*/
void SetPackageParameterWithContextDetail(Service::Interface* self);
/**
* Unknown
* Inputs:
* 0: 0x00360000
* Outputs:
* 0: 0x00360080
* 1: ResultCode
* 2: ?
*/
void GetSuitableY2rStandardCoefficient(Service::Interface* self);
/**
* Unknown
* Inputs:
* 0: 0x00380040
* 1: u8 Sound ID
* Outputs:
* 0: 0x00380040
* 1: ResultCode
*/
void PlayShutterSound(Service::Interface* self);
/**
* Initializes the camera driver. Must be called before using other functions.
* Inputs:
* 0: 0x00390000
* Outputs:
* 0: 0x00390040
* 1: ResultCode
*/
void DriverInitialize(Service::Interface* self);
/**
* Shuts down the camera driver.
* Inputs:
* 0: 0x003A0000
* Outputs:
* 0: 0x003A0040
* 1: ResultCode
*/
void DriverFinalize(Service::Interface* self);
/// Initialize CAM service(s)
void Init();
/// Shutdown CAM service(s)
void Shutdown();
} // namespace CAM
} // namespace Service