Stub more cam function

This commit is contained in:
mailwl 2015-09-25 13:58:33 +03:00
parent ba7ad4c29d
commit 80bcf99622
8 changed files with 277 additions and 27 deletions

View File

@ -21,11 +21,62 @@ namespace CAM {
static const u32 TRANSFER_BYTES = 5 * 1024;
static bool driver_initialized = false;
static bool camera_capture = false;
static FrameRate frame_rate;
static Kernel::SharedPtr<Kernel::Event> completion_event;
static Kernel::SharedPtr<Kernel::Event> interrupt_error_event;
static Kernel::SharedPtr<Kernel::Event> vsync_interrupt_event;
/*
FRAME_RATE_10 = 3,
FRAME_RATE_8_5 = 4,
FRAME_RATE_5 = 5,
*/
/**
* Signal camera Vblank event, if capture started
*/
void SignalVblankInterrupt() {
if(driver_initialized && camera_capture) {
static u32 cicles = 0;
cicles = (cicles+1)%60;
bool signal = true;
switch (frame_rate) {
case FrameRate::FRAME_RATE_30:
case FrameRate::FRAME_RATE_30_TO_5:
case FrameRate::FRAME_RATE_30_TO_10:
signal = (cicles % 2) == 0;
break;
case FrameRate::FRAME_RATE_20:
case FrameRate::FRAME_RATE_20_TO_5:
case FrameRate::FRAME_RATE_20_TO_10:
signal = (cicles % 3) == 0;
break;
case FrameRate::FRAME_RATE_15:
case FrameRate::FRAME_RATE_15_TO_2:
case FrameRate::FRAME_RATE_15_TO_5:
case FrameRate::FRAME_RATE_15_TO_10:
signal = (cicles % 4) == 0;
break;
case FrameRate::FRAME_RATE_10:
signal = (cicles % 6) == 0;
break;
case FrameRate::FRAME_RATE_5:
case FrameRate::FRAME_RATE_8_5:
signal = (cicles % 12) == 0;
break;
}
if (signal)
vsync_interrupt_event->Signal();
}
}
/**
* CAM_U::DriverInitialize service function
@ -98,7 +149,7 @@ void SetTransferLines(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu, lines=%d, width=%d, height=%d",
port, transfer_lines, width, height);
}
@ -146,7 +197,7 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[3] = Kernel::g_handle_table.Create(interrupt_error_event).MoveFrom();
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu", port);
}
/**
@ -168,7 +219,7 @@ void GetVsyncInterruptEvent(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[3] = Kernel::g_handle_table.Create(vsync_interrupt_event).MoveFrom();
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu", port);
}
/**
@ -192,7 +243,7 @@ void SetSize(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%hhu, size=%hhu, context=%hhu",
cam_select, size, context);
}
@ -213,7 +264,7 @@ void Activate(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%hhu",
cam_select);
}
@ -236,7 +287,7 @@ void SetTrimming(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trim=%d", port, trim);
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu, trim=%d", port, trim);
}
/**
@ -264,7 +315,7 @@ void SetTrimmingParamsCenter(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu, trimW=%d, trimH=%d, camW=%d, camH=%d",
port, trimWidth, trimHeight, camWidth, camHeight);
}
@ -289,7 +340,7 @@ void FlipImage(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%hhu, flip=%hhu, context=%hhu",
cam_select, flip, context);
}
@ -297,11 +348,11 @@ void SetFrameRate(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
CameraSelect cam_select = static_cast<CameraSelect>(cmd_buff[1] & 0xFF);
FrameRate frame_rate = static_cast<FrameRate>(cmd_buff[2] & 0xFF);
frame_rate = static_cast<FrameRate>(cmd_buff[2] & 0xFF);
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%hhu, frame_rate=%hhu",
cam_select, frame_rate);
}
@ -345,7 +396,7 @@ void GetTransferBytes(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = TRANSFER_BYTES;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu", port);
}
/**
@ -373,7 +424,7 @@ void SetReceiving(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d",
LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%hhu, image_size=%d, trans_unit=%d",
dest, port, image_size, trans_unit);
}
@ -394,7 +445,11 @@ void StartCapture(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
camera_capture = true;
completion_event->Signal();
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu", port);
}
/**
@ -414,7 +469,9 @@ void StopCapture(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d", port);
camera_capture = false;
LOG_WARNING(Service_CAM, "(STUBBED) called, port=%hhu", port);
}
/**
@ -434,7 +491,73 @@ void PlayShutterSound(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, sound_id=%d", sound_id);
LOG_WARNING(Service_CAM, "(STUBBED) called, sound_id=%hhu", sound_id);
}
/**
* CAM_U::SetPackageParameterWithoutContext service function
*
* This Function setups camera params without context.
*
* Inputs:
* 1 : PackageParameterCameraSelect
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void SetPackageParameterWithoutContext(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
const PackageParameterCameraSelect& params = reinterpret_cast<PackageParameterCameraSelect&>(cmd_buff[1]);
(void)params;
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called");
}
/**
* CAM_U::SetEffect service function
*
* This Function sets the image effect.
*
* Inputs:
* 1 : Camera
* 2 : Effect
* 3 : Context
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void SetEffect(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
CameraSelect cam_select = static_cast<CameraSelect>(cmd_buff[1] & 0xFF);
Effect effect = static_cast<Effect>(cmd_buff[2] & 0xFF);
Context context = static_cast<Context>(cmd_buff[3] & 0xFF);
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%hhu, effect=%hhu, context=%hhu",
cam_select, effect, context);
}
/**
* CAM_U::ClearBuffer service function
*
* This Function clears the buffer on selected port.
*
* Inputs:
* 1 : Port
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void ClearBuffer(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
Port port = static_cast<Port>(cmd_buff[1] & 0xFF);
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_CAM, "(STUBBED) called, port: %hhu", port);
}
void Init() {

View File

@ -11,39 +11,48 @@
namespace Service {
namespace CAM {
enum Port {
enum class Port: u8 {
PORT_NONE = 0,
PORT_CAM1 = 1,
PORT_CAM2 = 2,
PORT_BOTH = PORT_CAM1 | PORT_CAM2
};
enum CameraSelect {
enum class CameraSelect: u8 {
SELECT_NONE = 0,
SELECT_OUT1 = 1,
SELECT_IN1 = 2,
SELECT_OUT2 = 3,
SELECT_OUT2 = 4,
SELECT_IN1_OUT1 = SELECT_OUT1 | SELECT_IN1,
SELECT_OUT1_OUT2 = SELECT_OUT1 | SELECT_OUT2,
SELECT_IN1_OUT2 = SELECT_IN1 | SELECT_OUT2 ,
SELECT_ALL = SELECT_OUT1 | SELECT_IN1 | SELECT_OUT2
};
enum Context {
enum class Effect: u8 {
EFFECT_NONE = 0,
EFFECT_MONO = 1,
EFFECT_SEPIA = 2,
EFFECT_NEGATIVE = 3,
EFFECT_NEGAFILM = 4,
EFFECT_SEPIA01 = 5
};
enum class Context: u8 {
CONTEXT_NONE = 0,
CONTEXT_A = 1,
CONTEXT_B = 2,
CONTEXT_BOTH = CONTEXT_A | CONTEXT_B
};
enum Flip {
enum class Flip: u8 {
FLIP_NONE = 0,
FLIP_HORIZONTAL = 1,
FLIP_VERTICAL = 2,
FLIP_REVERSE = 3
};
enum Size {
enum class Size: u8 {
SIZE_VGA = 0,
SIZE_QVGA = 1,
SIZE_QQVGA = 2,
@ -55,7 +64,7 @@ enum Size {
SIZE_CTR_BOTTOM_LCD = SIZE_QVGA
};
enum FrameRate {
enum class FrameRate: u8 {
FRAME_RATE_15 = 0,
FRAME_RATE_15_TO_5 = 1,
FRAME_RATE_15_TO_2 = 2,
@ -71,12 +80,69 @@ enum FrameRate {
FRAME_RATE_30_TO_10 = 12
};
enum ShutterSoundType {
enum class ShutterSoundType: u8 {
SHUTTER_SOUND_TYPE_NORMAL = 0,
SHUTTER_SOUND_TYPE_MOVIE = 1,
SHUTTER_SOUND_TYPE_MOVIE_END = 2
};
enum class WhiteBalance: u8 {
WHITE_BALANCE_AUTO = 0,
WHITE_BALANCE_3200K = 1,
WHITE_BALANCE_4150K = 2,
WHITE_BALANCE_5200K = 3,
WHITE_BALANCE_6000K = 4,
WHITE_BALANCE_7000K = 5,
WHITE_BALANCE_MAX = 6,
WHITE_BALANCE_NORMAL = WHITE_BALANCE_AUTO,
WHITE_BALANCE_TUNGSTEN = WHITE_BALANCE_3200K,
WHITE_BALANCE_WHITE_FLUORESCENT_LIGHT = WHITE_BALANCE_4150K,
WHITE_BALANCE_DAYLIGHT = WHITE_BALANCE_5200K,
WHITE_BALANCE_CLOUDY = WHITE_BALANCE_6000K,
WHITE_BALANCE_HORIZON = WHITE_BALANCE_6000K,
WHITE_BALANCE_SHADE = WHITE_BALANCE_7000K
};
enum class PhotoMode: u8 {
PHOTO_MODE_NORMAL = 0,
PHOTO_MODE_PORTRAIT = 1,
PHOTO_MODE_LANDSCAPE = 2,
PHOTO_MODE_NIGHTVIEW = 3,
PHOTO_MODE_LETTER0 = 4
};
enum class LensCorrection: u8 {
LENS_CORRECTION_OFF = 0,
LENS_CORRECTION_ON_70 = 1,
LENS_CORRECTION_ON_90 = 2,
LENS_CORRECTION_DARK = LENS_CORRECTION_OFF,
LENS_CORRECTION_NORMAL = LENS_CORRECTION_ON_70,
LENS_CORRECTION_BRIGHT = LENS_CORRECTION_ON_90
};
struct PackageParameterCameraSelect {
enum CameraSelect camera;
s8 exposure;
enum WhiteBalance whiteBalance;
s8 sharpness;
bool autoExposureOn;
bool autoWhiteBalanceOn;
enum FrameRate frameRate;
enum PhotoMode photoMode;
u8 contrast;
enum LensCorrection lensCorrection;
bool noiseFilterOn;
u8 padding;
s16 autoExposureWindowX;
s16 autoExposureWindowY;
s16 autoExposureWindowWidth;
s16 autoExposureWindowHeight;
s16 autoWhiteBalanceWindowX;
s16 autoWhiteBalanceWindowY;
s16 autoWhiteBalanceWindowWidth;
s16 autoWhiteBalanceWindowHeight;
};
void DriverInitialize(Service::Interface* self);
void DriverFinalize(Service::Interface* self);
void GetMaxLines(Service::Interface* self);
@ -95,6 +161,11 @@ void SetReceiving(Service::Interface* self);
void StartCapture(Service::Interface* self);
void StopCapture(Service::Interface* self);
void PlayShutterSound(Service::Interface* self);
void SetPackageParameterWithoutContext(Service::Interface* self);
void SetEffect(Service::Interface* self);
void ClearBuffer(Service::Interface* self);
void SignalVblankInterrupt();
/// Initialize CAM service(s)
void Init();

View File

@ -13,7 +13,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, StartCapture, "StartCapture"},
{0x00020040, StopCapture, "StopCapture"},
{0x00030040, nullptr, "IsBusy"},
{0x00040040, nullptr, "ClearBuffer"},
{0x00040040, ClearBuffer, "ClearBuffer"},
{0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"},
{0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"},
{0x00070102, SetReceiving, "SetReceiving"},
@ -43,7 +43,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x001F00C0, SetSize, "SetSize"},
{0x00200080, SetFrameRate, "SetFrameRate"},
{0x00210080, nullptr, "SetPhotoMode"},
{0x002200C0, nullptr, "SetEffect"},
{0x002200C0, SetEffect, "SetEffect"},
{0x00230080, nullptr, "SetContrast"},
{0x00240080, nullptr, "SetLensCorrection"},
{0x002500C0, nullptr, "SetOutputFormat"},
@ -56,7 +56,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x002C0400, nullptr, "SetStereoCameraCalibrationData"},
{0x00310180, nullptr, "SetImageQualityCalibrationData"},
{0x00320000, nullptr, "GetImageQualityCalibrationData"},
{0x003302C0, nullptr, "SetPackageParameterWithoutContext"},
{0x003302C0, SetPackageParameterWithoutContext, "SetPackageParameterWithoutContext"},
{0x00340140, nullptr, "SetPackageParameterWithContext"},
{0x003501C0, nullptr, "SetPackageParameterWithContextDetail"},
{0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"},

View File

@ -71,7 +71,14 @@ ResultVal<bool> Interface::SyncRequest() {
cmd_buff[1] = 0;
return MakeResult<bool>(false);
} else {
LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
//LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
if(strcmp("TriggerCmdReqQueue", itr->second.name)) {
if(strcmp("FlushDataCache", itr->second.name)) {
if(strcmp("GetHeadphoneStatus", itr->second.name)) {
LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
}
}
}
}
itr->second.func(this);

View File

@ -91,6 +91,16 @@ static void SetInputFormat(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
}
static void GetOutputFormat(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
conversion.output_format = static_cast<OutputFormat>(cmd_buff[1]);
LOG_DEBUG(Service_Y2R, "called output_format=%hhu", conversion.output_format);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = static_cast<u32>(conversion.output_format);
}
static void SetOutputFormat(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@ -216,6 +226,15 @@ static void SetReceiving(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
}
static void GetInputLineWidth(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
LOG_DEBUG(Service_Y2R, "called input_line_width=%u", cmd_buff[1]);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = conversion.input_line_width;
}
static void SetInputLineWidth(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@ -223,6 +242,14 @@ static void SetInputLineWidth(Service::Interface* self) {
cmd_buff[1] = conversion.SetInputLineWidth(cmd_buff[1]).raw;
}
static void GetInputLines(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
LOG_DEBUG(Service_Y2R, "called input_line_number=%u", cmd_buff[1]);
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = conversion.input_lines;
}
static void SetInputLines(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@ -376,6 +403,7 @@ static void DriverFinalize(Service::Interface* self) {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010040, SetInputFormat, "SetInputFormat"},
{0x00030040, SetOutputFormat, "SetOutputFormat"},
{0x00040000, GetOutputFormat, "GetOutputFormat"},
{0x00050040, SetRotation, "SetRotation"},
{0x00070040, SetBlockAlignment, "SetBlockAlignment"},
{0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"},
@ -386,7 +414,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00130102, SetSendingYUYV, "SetSendingYUYV"},
{0x00180102, SetReceiving, "SetReceiving"},
{0x001A0040, SetInputLineWidth, "SetInputLineWidth"},
{0x001B0000, GetInputLineWidth, "GetInputLineWidth"},
{0x001C0040, SetInputLines, "SetInputLines"},
{0x001D0000, GetInputLines, "GetInputLines"},
{0x001E0100, SetCoefficient, "SetCoefficient"},
{0x00200040, SetStandardCoefficient, "SetStandardCoefficient"},
{0x00220040, SetAlpha, "SetAlpha"},

View File

@ -724,6 +724,10 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
timer->Set(initial, interval);
if(initial == 0 && interval == 0) {
timer->signaled = true;
}
return RESULT_SUCCESS;
}

View File

@ -16,6 +16,7 @@
#include "core/memory.h"
#include "core/core_timing.h"
#include "core/hle/service/cam/cam.h"
#include "core/hle/service/gsp_gpu.h"
#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/hid/hid.h"
@ -422,6 +423,10 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
// Check for user input updates
Service::HID::Update();
// VBlank camera
// TODO: rigth framerate
Service::CAM::SignalVblankInterrupt();
// Reschedule recurrent event
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
}

View File

@ -213,6 +213,11 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) {
return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR;
}
// Heap address one to one
if (addr >= HEAP_VADDR && addr < HEAP_VADDR_END) {
return addr;
}
LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr);
// To help with debugging, set bit on address so that it's obviously invalid.
return addr | 0x80000000;
@ -231,6 +236,11 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
return addr - IO_AREA_PADDR + IO_AREA_VADDR;
}
// Heap address one to one
if (addr >= HEAP_VADDR && addr < HEAP_VADDR_END) {
return addr;
}
LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr);
// To help with debugging, set bit on address so that it's obviously invalid.
return addr | 0x80000000;