mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	cam: use IPCHelper
This commit is contained in:
		
							parent
							
								
									c291db72e7
								
							
						
					
					
						commit
						924292f2cc
					
				
					 1 changed files with 234 additions and 274 deletions
				
			
		|  | @ -55,7 +55,7 @@ struct PortConfig { | ||||||
|     u16 x1; // x-coordinate of ending position for trimming
 |     u16 x1; // x-coordinate of ending position for trimming
 | ||||||
|     u16 y1; // y-coordinate of ending position for trimming
 |     u16 y1; // y-coordinate of ending position for trimming
 | ||||||
| 
 | 
 | ||||||
|     u32 transfer_bytes; |     u16 transfer_bytes; | ||||||
| 
 | 
 | ||||||
|     Kernel::SharedPtr<Kernel::Event> completion_event; |     Kernel::SharedPtr<Kernel::Event> completion_event; | ||||||
|     Kernel::SharedPtr<Kernel::Event> buffer_error_interrupt_event; |     Kernel::SharedPtr<Kernel::Event> buffer_error_interrupt_event; | ||||||
|  | @ -244,9 +244,10 @@ using CameraSet = CommandParamBitSet<3>; | ||||||
| } // namespace
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
| void StartCapture(Service::Interface* self) { | void StartCapture(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 1, 0); | ||||||
|  |     const PortSet port_select(rp.Pop<u32>()); | ||||||
| 
 | 
 | ||||||
|     const PortSet port_select(cmd_buff[1]); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|  | @ -267,21 +268,20 @@ void StartCapture(Service::Interface* self) { | ||||||
|                 LOG_WARNING(Service_CAM, "port %u already started", i); |                 LOG_WARNING(Service_CAM, "port %u already started", i); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StopCapture(Service::Interface* self) { | void StopCapture(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 1, 0); | ||||||
|  |     const PortSet port_select(rp.Pop<u32>()); | ||||||
| 
 | 
 | ||||||
|     const PortSet port_select(cmd_buff[1]); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|  | @ -293,21 +293,20 @@ void StopCapture(Service::Interface* self) { | ||||||
|                 LOG_WARNING(Service_CAM, "port %u already stopped", i); |                 LOG_WARNING(Service_CAM, "port %u already stopped", i); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x2, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IsBusy(Service::Interface* self) { | void IsBusy(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0); | ||||||
|  |     const PortSet port_select(rp.Pop<u32>()); | ||||||
| 
 | 
 | ||||||
|     const PortSet port_select(cmd_buff[1]); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
| 
 | 
 | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         bool is_busy = true; |         bool is_busy = true; | ||||||
|  | @ -315,80 +314,74 @@ void IsBusy(Service::Interface* self) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             is_busy &= ports[i].is_busy; |             is_busy &= ports[i].is_busy; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = is_busy ? 1 : 0; |         rb.Push(is_busy); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x3, 2, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ClearBuffer(Service::Interface* self) { | void ClearBuffer(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x04, 1, 0); | ||||||
|  |     const PortSet port_select(rp.Pop<u32>()); | ||||||
| 
 | 
 | ||||||
|     const PortSet port_select(cmd_buff[1]); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x4, 1, 0); |  | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |  | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); |     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetVsyncInterruptEvent(Service::Interface* self) { | void GetVsyncInterruptEvent(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x05, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = IPC::CopyHandleDesc(); |         rb.PushCopyHandles( | ||||||
|         cmd_buff[3] = Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).MoveFrom(); |             Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).MoveFrom()); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|         cmd_buff[2] = IPC::CopyHandleDesc(); |         rb.PushCopyHandles(0); | ||||||
|         cmd_buff[2] = 0; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x5, 1, 2); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); |     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetBufferErrorInterruptEvent(Service::Interface* self) { | void GetBufferErrorInterruptEvent(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = IPC::CopyHandleDesc(); |         rb.PushCopyHandles( | ||||||
|         cmd_buff[3] = |             Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).MoveFrom()); | ||||||
|             Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).MoveFrom(); |  | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|         cmd_buff[2] = IPC::CopyHandleDesc(); |         rb.PushCopyHandles(0); | ||||||
|         cmd_buff[2] = 0; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); |     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetReceiving(Service::Interface* self) { | void SetReceiving(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x07, 4, 2); | ||||||
| 
 |     const VAddr dest = rp.Pop<u32>(); | ||||||
|     const VAddr dest = cmd_buff[1]; |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[2]); |     const u32 image_size = rp.Pop<u32>(); | ||||||
|     const u32 image_size = cmd_buff[3]; |     const u16 trans_unit = rp.Pop<u16>(); | ||||||
|     const u32 trans_unit = cmd_buff[4] & 0xFFFF; |     rp.PopHandle(); // Handle to destination process. not used
 | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port_id = *port_select.begin(); |         int port_id = *port_select.begin(); | ||||||
|         PortConfig& port = ports[port_id]; |         PortConfig& port = ports[port_id]; | ||||||
|  | @ -403,149 +396,143 @@ void SetReceiving(Service::Interface* self) { | ||||||
|             port.is_pending_receiving = true; |             port.is_pending_receiving = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = IPC::CopyHandleDesc(); |         rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).MoveFrom()); | ||||||
|         cmd_buff[3] = Kernel::g_handle_table.Create(port.completion_event).MoveFrom(); |  | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.PushCopyHandles(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x7, 1, 2); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, addr=0x%X, port_select=%u, image_size=%u, trans_unit=%u", dest, |     LOG_DEBUG(Service_CAM, "called, addr=0x%X, port_select=%u, image_size=%u, trans_unit=%u", dest, | ||||||
|               port_select.m_val, image_size, trans_unit); |               port_select.m_val, image_size, trans_unit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IsFinishedReceiving(Service::Interface* self) { | void IsFinishedReceiving(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = (ports[port].is_receiving || ports[port].is_pending_receiving) ? 0 : 1; |         rb.Push(ports[port].is_receiving || ports[port].is_pending_receiving); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x8, 2, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetTransferLines(Service::Interface* self) { | void SetTransferLines(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x09, 4, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |     const u16 transfer_lines = rp.Pop<u16>(); | ||||||
|     const u32 transfer_lines = cmd_buff[2] & 0xFFFF; |     const u16 width = rp.Pop<u16>(); | ||||||
|     const u32 width = cmd_buff[3] & 0xFFFF; |     const u16 height = rp.Pop<u16>(); | ||||||
|     const u32 height = cmd_buff[4] & 0xFFFF; |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             ports[i].transfer_bytes = transfer_lines * width * 2; |             ports[i].transfer_bytes = transfer_lines * width * 2; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u, lines=%u, width=%u, height=%u", |     LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u, lines=%u, width=%u, height=%u", | ||||||
|                 port_select.m_val, transfer_lines, width, height); |                 port_select.m_val, transfer_lines, width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetMaxLines(Service::Interface* self) { | void GetMaxLines(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0A, 2, 0); | ||||||
|  |     const u16 width = rp.Pop<u16>(); | ||||||
|  |     const u16 height = rp.Pop<u16>(); | ||||||
| 
 | 
 | ||||||
|     const u32 width = cmd_buff[1] & 0xFFFF; |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     const u32 height = cmd_buff[2] & 0xFFFF; |  | ||||||
| 
 | 
 | ||||||
|     // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480
 |     // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480
 | ||||||
|     constexpr u32 MIN_TRANSFER_UNIT = 256; |     constexpr u32 MIN_TRANSFER_UNIT = 256; | ||||||
|     constexpr u32 MAX_BUFFER_SIZE = 2560; |     constexpr u32 MAX_BUFFER_SIZE = 2560; | ||||||
|     if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { |     if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { | ||||||
|         cmd_buff[1] = ERROR_OUT_OF_RANGE.raw; |         rb.Push(ERROR_OUT_OF_RANGE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } else { |     } else { | ||||||
|         u32 lines = MAX_BUFFER_SIZE / width; |         u32 lines = MAX_BUFFER_SIZE / width; | ||||||
|         if (lines > height) { |         if (lines > height) { | ||||||
|             lines = height; |             lines = height; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         ResultCode result = RESULT_SUCCESS; | ||||||
|         while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { |         while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { | ||||||
|             --lines; |             --lines; | ||||||
|             if (lines == 0) { |             if (lines == 0) { | ||||||
|                 cmd_buff[1] = ERROR_OUT_OF_RANGE.raw; |                 result = ERROR_OUT_OF_RANGE; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[2] = lines; |         rb.Push(result); | ||||||
|  |         rb.Push(lines); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); |     LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetTransferBytes(Service::Interface* self) { | void SetTransferBytes(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0B, 4, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |     const u16 transfer_bytes = rp.Pop<u16>(); | ||||||
|     const u32 transfer_bytes = cmd_buff[2] & 0xFFFF; |     const u16 width = rp.Pop<u16>(); | ||||||
|     const u32 width = cmd_buff[3] & 0xFFFF; |     const u16 height = rp.Pop<u16>(); | ||||||
|     const u32 height = cmd_buff[4] & 0xFFFF; |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             ports[i].transfer_bytes = transfer_bytes; |             ports[i].transfer_bytes = transfer_bytes; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xB, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u, bytes=%u, width=%u, height=%u", |     LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u, bytes=%u, width=%u, height=%u", | ||||||
|                 port_select.m_val, transfer_bytes, width, height); |                 port_select.m_val, transfer_bytes, width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetTransferBytes(Service::Interface* self) { | void GetTransferBytes(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0C, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS.raw); | ||||||
|         cmd_buff[2] = ports[port].transfer_bytes; |         rb.Push(ports[port].transfer_bytes); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u", port_select.m_val); |     LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetMaxBytes(Service::Interface* self) { | void GetMaxBytes(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 2, 0); | ||||||
|  |     const u16 width = rp.Pop<u16>(); | ||||||
|  |     const u16 height = rp.Pop<u16>(); | ||||||
| 
 | 
 | ||||||
|     const u32 width = cmd_buff[1] & 0xFFFF; |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     const u32 height = cmd_buff[2] & 0xFFFF; |  | ||||||
| 
 | 
 | ||||||
|     // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480
 |     // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480
 | ||||||
|     constexpr u32 MIN_TRANSFER_UNIT = 256; |     constexpr u32 MIN_TRANSFER_UNIT = 256; | ||||||
|     constexpr u32 MAX_BUFFER_SIZE = 2560; |     constexpr u32 MAX_BUFFER_SIZE = 2560; | ||||||
|     if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { |     if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { | ||||||
|         cmd_buff[1] = ERROR_OUT_OF_RANGE.raw; |         rb.Push(ERROR_OUT_OF_RANGE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } else { |     } else { | ||||||
|         u32 bytes = MAX_BUFFER_SIZE; |         u32 bytes = MAX_BUFFER_SIZE; | ||||||
| 
 | 
 | ||||||
|  | @ -553,63 +540,59 @@ void GetMaxBytes(Service::Interface* self) { | ||||||
|             bytes -= MIN_TRANSFER_UNIT; |             bytes -= MIN_TRANSFER_UNIT; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = bytes; |         rb.Push(bytes); | ||||||
|     } |     } | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xD, 2, 0); |  | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); |     LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetTrimming(Service::Interface* self) { | void SetTrimming(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0E, 2, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |     const bool trim = rp.Pop<bool>(); | ||||||
|     const bool trim = (cmd_buff[2] & 0xFF) != 0; |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             ports[i].is_trimming = trim; |             ports[i].is_trimming = trim; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u, trim=%d", port_select.m_val, trim); |     LOG_DEBUG(Service_CAM, "called, port_select=%u, trim=%d", port_select.m_val, trim); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IsTrimming(Service::Interface* self) { | void IsTrimming(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0F, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = ports[port].is_trimming; |         rb.Push(ports[port].is_trimming); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|  |         rb.Skip(1, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetTrimmingParams(Service::Interface* self) { | void SetTrimmingParams(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x10, 5, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |     const u16 x0 = rp.Pop<u16>(); | ||||||
|     const u16 x0 = static_cast<u16>(cmd_buff[2] & 0xFFFF); |     const u16 y0 = rp.Pop<u16>(); | ||||||
|     const u16 y0 = static_cast<u16>(cmd_buff[3] & 0xFFFF); |     const u16 x1 = rp.Pop<u16>(); | ||||||
|     const u16 x1 = static_cast<u16>(cmd_buff[4] & 0xFFFF); |     const u16 y1 = rp.Pop<u16>(); | ||||||
|     const u16 y1 = static_cast<u16>(cmd_buff[5] & 0xFFFF); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             ports[i].x0 = x0; |             ports[i].x0 = x0; | ||||||
|  | @ -617,49 +600,46 @@ void SetTrimmingParams(Service::Interface* self) { | ||||||
|             ports[i].x1 = x1; |             ports[i].x1 = x1; | ||||||
|             ports[i].y1 = y1; |             ports[i].y1 = y1; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u, x0=%u, y0=%u, x1=%u, y1=%u", port_select.m_val, |     LOG_DEBUG(Service_CAM, "called, port_select=%u, x0=%u, y0=%u, x1=%u, y1=%u", port_select.m_val, | ||||||
|               x0, y0, x1, y1); |               x0, y0, x1, y1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetTrimmingParams(Service::Interface* self) { | void GetTrimmingParams(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x11, 1, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); | ||||||
|     if (port_select.IsSingle()) { |     if (port_select.IsSingle()) { | ||||||
|         int port = *port_select.begin(); |         int port = *port_select.begin(); | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|         cmd_buff[2] = ports[port].x0; |         rb.Push(ports[port].x0); | ||||||
|         cmd_buff[3] = ports[port].y0; |         rb.Push(ports[port].y0); | ||||||
|         cmd_buff[4] = ports[port].x1; |         rb.Push(ports[port].x1); | ||||||
|         cmd_buff[5] = ports[port].y1; |         rb.Push(ports[port].y1); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|  |         rb.Skip(4, false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x11, 5, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); |     LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetTrimmingParamsCenter(Service::Interface* self) { | void SetTrimmingParamsCenter(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x12, 5, 0); | ||||||
| 
 |     const PortSet port_select(rp.Pop<u32>()); | ||||||
|     const PortSet port_select(cmd_buff[1]); |     const u16 trim_w = rp.Pop<u16>(); | ||||||
|     const u16 trim_w = static_cast<u16>(cmd_buff[2] & 0xFFFF); |     const u16 trim_h = rp.Pop<u16>(); | ||||||
|     const u16 trim_h = static_cast<u16>(cmd_buff[3] & 0xFFFF); |     const u16 cam_w = rp.Pop<u16>(); | ||||||
|     const u16 cam_w = static_cast<u16>(cmd_buff[4] & 0xFFFF); |     const u16 cam_h = rp.Pop<u16>(); | ||||||
|     const u16 cam_h = static_cast<u16>(cmd_buff[5] & 0xFFFF); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (port_select.IsValid()) { |     if (port_select.IsValid()) { | ||||||
|         for (int i : port_select) { |         for (int i : port_select) { | ||||||
|             ports[i].x0 = (cam_w - trim_w) / 2; |             ports[i].x0 = (cam_w - trim_w) / 2; | ||||||
|  | @ -667,23 +647,21 @@ void SetTrimmingParamsCenter(Service::Interface* self) { | ||||||
|             ports[i].x1 = ports[i].x0 + trim_w; |             ports[i].x1 = ports[i].x0 + trim_w; | ||||||
|             ports[i].y1 = ports[i].y0 + trim_h; |             ports[i].y1 = ports[i].y0 + trim_h; | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); |         LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, port_select=%u, trim_w=%u, trim_h=%u, cam_w=%u, cam_h=%u", |     LOG_DEBUG(Service_CAM, "called, port_select=%u, trim_w=%u, trim_h=%u, cam_w=%u, cam_h=%u", | ||||||
|               port_select.m_val, trim_w, trim_h, cam_w, cam_h); |               port_select.m_val, trim_w, trim_h, cam_w, cam_h); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Activate(Service::Interface* self) { | void Activate(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x13, 1, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid()) { |     if (camera_select.IsValid()) { | ||||||
|         if (camera_select.m_val == 0) { // deactive all
 |         if (camera_select.m_val == 0) { // deactive all
 | ||||||
|             for (int i = 0; i < 2; ++i) { |             for (int i = 0; i < 2; ++i) { | ||||||
|  | @ -694,10 +672,10 @@ void Activate(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|                 ports[i].is_active = false; |                 ports[i].is_active = false; | ||||||
|             } |             } | ||||||
|             cmd_buff[1] = RESULT_SUCCESS.raw; |             rb.Push(RESULT_SUCCESS); | ||||||
|         } else if (camera_select[0] && camera_select[1]) { |         } else if (camera_select[0] && camera_select[1]) { | ||||||
|             LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); |             LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); | ||||||
|             cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |             rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|         } else { |         } else { | ||||||
|             if (camera_select[0]) { |             if (camera_select[0]) { | ||||||
|                 ActivatePort(0, 0); |                 ActivatePort(0, 0); | ||||||
|  | @ -708,24 +686,22 @@ void Activate(Service::Interface* self) { | ||||||
|             if (camera_select[2]) { |             if (camera_select[2]) { | ||||||
|                 ActivatePort(1, 2); |                 ActivatePort(1, 2); | ||||||
|             } |             } | ||||||
|             cmd_buff[1] = RESULT_SUCCESS.raw; |             rb.Push(RESULT_SUCCESS); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); |         LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u", camera_select.m_val); |     LOG_DEBUG(Service_CAM, "called, camera_select=%u", camera_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SwitchContext(Service::Interface* self) { | void SwitchContext(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x14, 2, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
|     const ContextSet context_select(cmd_buff[2]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsSingle()) { |     if (camera_select.IsValid() && context_select.IsSingle()) { | ||||||
|         int context = *context_select.begin(); |         int context = *context_select.begin(); | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|  | @ -736,26 +712,24 @@ void SwitchContext(Service::Interface* self) { | ||||||
|             cameras[camera].impl->SetFormat(context_config.format); |             cameras[camera].impl->SetFormat(context_config.format); | ||||||
|             cameras[camera].impl->SetResolution(context_config.resolution); |             cameras[camera].impl->SetResolution(context_config.resolution); | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x14, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, context_select=%u", camera_select.m_val, |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|               context_select.m_val); |               context_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FlipImage(Service::Interface* self) { | void FlipImage(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1D, 3, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const Flip flip = static_cast<Flip>(rp.Pop<u8>()); | ||||||
|     const Flip flip = static_cast<Flip>(cmd_buff[2] & 0xFF); |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
|     const ContextSet context_select(cmd_buff[3]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             for (int context : context_select) { |             for (int context : context_select) { | ||||||
|  | @ -765,32 +739,30 @@ void FlipImage(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, flip=%d, context_select=%u", |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, flip=%d, context_select=%u", | ||||||
|               camera_select.m_val, static_cast<int>(flip), context_select.m_val); |               camera_select.m_val, static_cast<int>(flip), context_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetDetailSize(Service::Interface* self) { | void SetDetailSize(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 8, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |  | ||||||
|     Resolution resolution; |     Resolution resolution; | ||||||
|     resolution.width = static_cast<u16>(cmd_buff[2] & 0xFFFF); |     resolution.width = rp.Pop<u16>(); | ||||||
|     resolution.height = static_cast<u16>(cmd_buff[3] & 0xFFFF); |     resolution.height = rp.Pop<u16>(); | ||||||
|     resolution.crop_x0 = static_cast<u16>(cmd_buff[4] & 0xFFFF); |     resolution.crop_x0 = rp.Pop<u16>(); | ||||||
|     resolution.crop_y0 = static_cast<u16>(cmd_buff[5] & 0xFFFF); |     resolution.crop_y0 = rp.Pop<u16>(); | ||||||
|     resolution.crop_x1 = static_cast<u16>(cmd_buff[6] & 0xFFFF); |     resolution.crop_x1 = rp.Pop<u16>(); | ||||||
|     resolution.crop_y1 = static_cast<u16>(cmd_buff[7] & 0xFFFF); |     resolution.crop_y1 = rp.Pop<u16>(); | ||||||
|     const ContextSet context_select(cmd_buff[8]); |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             for (int context : context_select) { |             for (int context : context_select) { | ||||||
|  | @ -800,15 +772,13 @@ void SetDetailSize(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x1E, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, width=%u, height=%u, crop_x0=%u, crop_y0=%u, " |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, width=%u, height=%u, crop_x0=%u, crop_y0=%u, " | ||||||
|                            "crop_x1=%u, crop_y1=%u, context_select=%u", |                            "crop_x1=%u, crop_y1=%u, context_select=%u", | ||||||
|               camera_select.m_val, resolution.width, resolution.height, resolution.crop_x0, |               camera_select.m_val, resolution.width, resolution.height, resolution.crop_x0, | ||||||
|  | @ -816,12 +786,12 @@ void SetDetailSize(Service::Interface* self) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetSize(Service::Interface* self) { | void SetSize(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 3, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const u8 size = rp.Pop<u8>(); | ||||||
|     const u32 size = cmd_buff[2] & 0xFF; |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
|     const ContextSet context_select(cmd_buff[3]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             for (int context : context_select) { |             for (int context : context_select) { | ||||||
|  | @ -831,49 +801,45 @@ void SetSize(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, size=%u, context_select=%u", |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, size=%u, context_select=%u", | ||||||
|               camera_select.m_val, size, context_select.m_val); |               camera_select.m_val, size, context_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetFrameRate(Service::Interface* self) { | void SetFrameRate(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x20, 2, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const FrameRate frame_rate = static_cast<FrameRate>(rp.Pop<u8>()); | ||||||
|     const FrameRate frame_rate = static_cast<FrameRate>(cmd_buff[2] & 0xFF); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid()) { |     if (camera_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             cameras[camera].frame_rate = frame_rate; |             cameras[camera].frame_rate = frame_rate; | ||||||
|             // TODO(wwylele): consider hinting the actual camera with the expected frame rate
 |             // TODO(wwylele): consider hinting the actual camera with the expected frame rate
 | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); |         LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select=%u, frame_rate=%d", |     LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select=%u, frame_rate=%d", | ||||||
|                 camera_select.m_val, static_cast<int>(frame_rate)); |                 camera_select.m_val, static_cast<int>(frame_rate)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetEffect(Service::Interface* self) { | void SetEffect(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x22, 3, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const Effect effect = static_cast<Effect>(rp.Pop<u8>()); | ||||||
|     const Effect effect = static_cast<Effect>(cmd_buff[2] & 0xFF); |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
|     const ContextSet context_select(cmd_buff[3]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             for (int context : context_select) { |             for (int context : context_select) { | ||||||
|  | @ -883,26 +849,24 @@ void SetEffect(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x22, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, effect=%d, context_select=%u", |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, effect=%d, context_select=%u", | ||||||
|               camera_select.m_val, static_cast<int>(effect), context_select.m_val); |               camera_select.m_val, static_cast<int>(effect), context_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetOutputFormat(Service::Interface* self) { | void SetOutputFormat(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x25, 3, 0); | ||||||
| 
 |     const CameraSet camera_select(rp.Pop<u32>()); | ||||||
|     const CameraSet camera_select(cmd_buff[1]); |     const OutputFormat format = static_cast<OutputFormat>(rp.Pop<u8>()); | ||||||
|     const OutputFormat format = static_cast<OutputFormat>(cmd_buff[2] & 0xFF); |     const ContextSet context_select(rp.Pop<u32>()); | ||||||
|     const ContextSet context_select(cmd_buff[3]); |  | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera : camera_select) { |         for (int camera : camera_select) { | ||||||
|             for (int context : context_select) { |             for (int context : context_select) { | ||||||
|  | @ -912,34 +876,32 @@ void SetOutputFormat(Service::Interface* self) { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, | ||||||
|                   context_select.m_val); |                   context_select.m_val); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x25, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called, camera_select=%u, format=%d, context_select=%u", |     LOG_DEBUG(Service_CAM, "called, camera_select=%u, format=%d, context_select=%u", | ||||||
|               camera_select.m_val, static_cast<int>(format), context_select.m_val); |               camera_select.m_val, static_cast<int>(format), context_select.m_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SynchronizeVsyncTiming(Service::Interface* self) { | void SynchronizeVsyncTiming(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x29, 2, 0); | ||||||
|  |     const u8 camera_select1 = rp.Pop<u8>(); | ||||||
|  |     const u8 camera_select2 = rp.Pop<u8>(); | ||||||
| 
 | 
 | ||||||
|     const u32 camera_select1 = cmd_buff[1] & 0xFF; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     const u32 camera_select2 = cmd_buff[2] & 0xFF; |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 |  | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); |  | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |  | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select1=%u, camera_select2=%u", |     LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select1=%u, camera_select2=%u", | ||||||
|                 camera_select1, camera_select2); |                 camera_select1, camera_select2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetStereoCameraCalibrationData(Service::Interface* self) { | void GetStereoCameraCalibrationData(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestBuilder rb = | ||||||
|  |         IPC::RequestParser(Kernel::GetCommandBuffer(), 0x2B, 0, 0).MakeBuilder(17, 0); | ||||||
| 
 | 
 | ||||||
|     // Default values taken from yuriks' 3DS. Valid data is required here or games using the
 |     // Default values taken from yuriks' 3DS. Valid data is required here or games using the
 | ||||||
|     // calibration get stuck in an infinite CPU loop.
 |     // calibration get stuck in an infinite CPU loop.
 | ||||||
|  | @ -958,35 +920,37 @@ void GetStereoCameraCalibrationData(Service::Interface* self) { | ||||||
|     data.imageWidth = 640; |     data.imageWidth = 640; | ||||||
|     data.imageHeight = 480; |     data.imageHeight = 480; | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x2B, 17, 0); |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     rb.PushRaw(data); | ||||||
|     memcpy(&cmd_buff[2], &data, sizeof(data)); |  | ||||||
| 
 | 
 | ||||||
|     LOG_TRACE(Service_CAM, "called"); |     LOG_TRACE(Service_CAM, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetPackageParameterWithoutContext(Service::Interface* self) { | void SetPackageParameterWithoutContext(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x33, 11, 0); | ||||||
| 
 | 
 | ||||||
|     PackageParameterWithoutContext package; |     PackageParameterWithoutContext package; | ||||||
|     std::memcpy(&package, cmd_buff + 1, sizeof(package)); |     rp.PopRaw(package); | ||||||
|  |     rp.Skip(4, false); | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x33, 1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     rb.Push(RESULT_SUCCESS); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called"); |     LOG_WARNING(Service_CAM, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename PackageParameterType, int command_id> | template <typename PackageParameterType, int command_id, int param_length> | ||||||
| static void SetPackageParameter() { | static void SetPackageParameter() { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), command_id, param_length, 0); | ||||||
| 
 | 
 | ||||||
|     PackageParameterType package; |     PackageParameterType package; | ||||||
|     std::memcpy(&package, cmd_buff + 1, sizeof(package)); |     rp.PopRaw(package); | ||||||
|  |     rp.Skip(param_length - (sizeof(PackageParameterType) + 3) / 4, false); | ||||||
| 
 | 
 | ||||||
|     const CameraSet camera_select(static_cast<u32>(package.camera_select)); |     const CameraSet camera_select(static_cast<u32>(package.camera_select)); | ||||||
|     const ContextSet context_select(static_cast<u32>(package.context_select)); |     const ContextSet context_select(static_cast<u32>(package.context_select)); | ||||||
| 
 | 
 | ||||||
|  |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     if (camera_select.IsValid() && context_select.IsValid()) { |     if (camera_select.IsValid() && context_select.IsValid()) { | ||||||
|         for (int camera_id : camera_select) { |         for (int camera_id : camera_select) { | ||||||
|             CameraConfig& camera = cameras[camera_id]; |             CameraConfig& camera = cameras[camera_id]; | ||||||
|  | @ -1002,15 +966,13 @@ static void SetPackageParameter() { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cmd_buff[1] = RESULT_SUCCESS.raw; |         rb.Push(RESULT_SUCCESS); | ||||||
|     } else { |     } else { | ||||||
|         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", package.camera_select, |         LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", package.camera_select, | ||||||
|                   package.context_select); |                   package.context_select); | ||||||
|         cmd_buff[1] = ERROR_INVALID_ENUM_VALUE.raw; |         rb.Push(ERROR_INVALID_ENUM_VALUE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(command_id, 1, 0); |  | ||||||
| 
 |  | ||||||
|     LOG_DEBUG(Service_CAM, "called"); |     LOG_DEBUG(Service_CAM, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1019,36 +981,35 @@ Resolution PackageParameterWithContext::GetResolution() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetPackageParameterWithContext(Service::Interface* self) { | void SetPackageParameterWithContext(Service::Interface* self) { | ||||||
|     SetPackageParameter<PackageParameterWithContext, 0x34>(); |     SetPackageParameter<PackageParameterWithContext, 0x34, 5>(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetPackageParameterWithContextDetail(Service::Interface* self) { | void SetPackageParameterWithContextDetail(Service::Interface* self) { | ||||||
|     SetPackageParameter<PackageParameterWithContextDetail, 0x35>(); |     SetPackageParameter<PackageParameterWithContextDetail, 0x35, 7>(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetSuitableY2rStandardCoefficient(Service::Interface* self) { | void GetSuitableY2rStandardCoefficient(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestBuilder rb = | ||||||
| 
 |         IPC::RequestParser(Kernel::GetCommandBuffer(), 0x36, 0, 0).MakeBuilder(2, 0); | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x36, 2, 0); |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |     rb.Push<u32>(0); | ||||||
|     cmd_buff[2] = 0; |  | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_CAM, "(STUBBED) called"); |     LOG_WARNING(Service_CAM, "(STUBBED) called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlayShutterSound(Service::Interface* self) { | void PlayShutterSound(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x38, 1, 0); | ||||||
|  |     u8 sound_id = rp.Pop<u8>(); | ||||||
| 
 | 
 | ||||||
|     u8 sound_id = cmd_buff[1] & 0xFF; |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x38, 1, 0); |  | ||||||
|     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=%d", sound_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DriverInitialize(Service::Interface* self) { | void DriverInitialize(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestBuilder rb = | ||||||
|  |         IPC::RequestParser(Kernel::GetCommandBuffer(), 0x39, 0, 0).MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|     for (int camera_id = 0; camera_id < NumCameras; ++camera_id) { |     for (int camera_id = 0; camera_id < NumCameras; ++camera_id) { | ||||||
|         CameraConfig& camera = cameras[camera_id]; |         CameraConfig& camera = cameras[camera_id]; | ||||||
|  | @ -1074,14 +1035,14 @@ void DriverInitialize(Service::Interface* self) { | ||||||
|         port.Clear(); |         port.Clear(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x39, 1, 0); |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |  | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_CAM, "called"); |     LOG_DEBUG(Service_CAM, "called"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DriverFinalize(Service::Interface* self) { | void DriverFinalize(Service::Interface* self) { | ||||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); |     IPC::RequestBuilder rb = | ||||||
|  |         IPC::RequestParser(Kernel::GetCommandBuffer(), 0x3A, 0, 0).MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|     CancelReceiving(0); |     CancelReceiving(0); | ||||||
|     CancelReceiving(1); |     CancelReceiving(1); | ||||||
|  | @ -1090,8 +1051,7 @@ void DriverFinalize(Service::Interface* self) { | ||||||
|         camera.impl = nullptr; |         camera.impl = nullptr; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cmd_buff[0] = IPC::MakeHeader(0x3A, 1, 0); |     rb.Push(RESULT_SUCCESS); | ||||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; |  | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_CAM, "called"); |     LOG_DEBUG(Service_CAM, "called"); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue