rpcsx/rpcs3/Emu/Cell/Modules/cellMouse.cpp

376 lines
9.1 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "Emu/System.h"
2016-03-21 20:43:03 +01:00
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
2014-08-23 22:40:04 +02:00
2016-03-21 20:43:03 +01:00
#include "Emu/Io/MouseHandler.h"
2018-08-04 14:37:32 +02:00
#include "Utilities/sema.h"
2014-09-03 18:33:30 +02:00
#include "cellMouse.h"
2016-05-13 15:55:34 +02:00
extern logs::channel sys_io;
2015-07-09 17:30:37 +02:00
s32 cellMouseInit(u32 max_connect)
{
sys_io.warning("cellMouseInit(max_connect=%d)", max_connect);
2018-06-07 09:59:27 +02:00
auto handler = fxm::get<MouseHandlerBase>();
2016-03-21 20:43:03 +01:00
2018-06-07 09:59:27 +02:00
if (handler)
{
2016-03-21 20:43:03 +01:00
return CELL_MOUSE_ERROR_ALREADY_INITIALIZED;
}
2018-06-07 09:59:27 +02:00
if (max_connect == 0 || max_connect > CELL_MAX_MICE)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
handler = fxm::import<MouseHandlerBase>(Emu.GetCallbacks().get_mouse_handler);
2017-06-03 04:42:34 +02:00
handler->Init(std::min(max_connect, 7u));
2018-06-07 09:59:27 +02:00
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseClearBuf(u32 port_no)
{
sys_io.trace("cellMouseClearBuf(port_no=%d)", port_no);
2016-03-21 20:43:03 +01:00
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
2018-06-07 09:59:27 +02:00
if (port_no >= CELL_MAX_MICE)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
2018-06-07 09:59:27 +02:00
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_NO_DEVICE;
}
handler->GetDataList(port_no).clear();
handler->GetTabletDataList(port_no).clear();
MouseRawData& raw_data = handler->GetRawData(port_no);
raw_data.len = 0;
for (int i = 0; i < CELL_MOUSE_MAX_CODES; i++)
{
raw_data.data[i] = 0;
}
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseEnd()
{
2016-03-21 20:43:03 +01:00
sys_io.notice("cellMouseEnd()");
2016-03-21 20:43:03 +01:00
if (!fxm::remove<MouseHandlerBase>())
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
{
sys_io.trace("cellMouseGetInfo(info=*0x%x)", info);
2016-03-21 20:43:03 +01:00
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
2018-06-07 09:59:27 +02:00
if (!info)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
2016-03-21 20:43:03 +01:00
const MouseInfo& current_info = handler->GetInfo();
info->max_connect = current_info.max_connect;
info->now_connect = current_info.now_connect;
info->info = current_info.info;
for (u32 i=0; i<CELL_MAX_MICE; i++) info->vendor_id[i] = current_info.vendor_id[i];
for (u32 i=0; i<CELL_MAX_MICE; i++) info->product_id[i] = current_info.product_id[i];
for (u32 i=0; i<CELL_MAX_MICE; i++) info->status[i] = current_info.status[i];
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr<CellMouseInfoTablet> info)
{
sys_io.trace("cellMouseInfoTabletMode(port_no=%d, info=*0x%x)", port_no, info);
2016-03-21 20:43:03 +01:00
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
2018-06-07 09:59:27 +02:00
// only check for port_no here. Tests show that valid ports lead to ERROR_FATAL with disconnected devices regardless of info
if (port_no >= CELL_MAX_MICE)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
2018-06-07 09:59:27 +02:00
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_FATAL;
}
if (!info)
{
return CELL_EFAULT; // we don't get CELL_MOUSE_ERROR_INVALID_PARAMETER here :thonkang:
}
info->is_supported = current_info.tablet_is_supported[port_no];
info->mode = current_info.mode[port_no];
// TODO: decr returns CELL_ENOTSUP ... How should we handle this?
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
{
sys_io.trace("cellMouseGetData(port_no=%d, data=*0x%x)", port_no, data);
2016-03-21 20:43:03 +01:00
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
2016-03-21 20:43:03 +01:00
2018-06-07 09:59:27 +02:00
if (port_no >= CELL_MAX_MICE || !data)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
2018-08-04 14:37:32 +02:00
semaphore_lock lock(handler->mutex);
2018-06-07 09:59:27 +02:00
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_NO_DEVICE;
}
2018-06-07 09:59:27 +02:00
// TODO: check if (current_info.mode[port_no] != CELL_MOUSE_INFO_TABLET_MOUSE_MODE) has any impact
2018-08-04 14:37:32 +02:00
MouseDataList& data_list = handler->GetDataList(port_no);
if (data_list.size() == 0)
{
*data = {};
return CELL_OK;
}
const MouseData current_data = data_list.front();
data->update = current_data.update;
data->buttons = current_data.buttons;
data->x_axis = current_data.x_axis;
data->y_axis = current_data.y_axis;
data->wheel = current_data.wheel;
data->tilt = current_data.tilt;
2018-08-04 14:37:32 +02:00
data_list.pop_front();
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
{
2018-06-07 09:59:27 +02:00
sys_io.warning("cellMouseGetDataList(port_no=%d, data=0x%x)", port_no, data);
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
if (port_no >= CELL_MAX_MICE || !data)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
2018-08-04 14:37:32 +02:00
semaphore_lock lock(handler->mutex);
2018-06-07 09:59:27 +02:00
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_NO_DEVICE;
2018-06-07 09:59:27 +02:00
}
// TODO: check if (current_info.mode[port_no] != CELL_MOUSE_INFO_TABLET_MOUSE_MODE) has any impact
auto& list = handler->GetDataList(port_no);
data->list_num = std::min((u32)CELL_MOUSE_MAX_DATA_LIST_NUM, (u32)list.size());
int i = 0;
for (auto it = list.begin(); it != list.end() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++it, ++i)
{
2018-06-07 09:59:27 +02:00
data->list[i].update = it->update;
data->list[i].buttons = it->buttons;
data->list[i].x_axis = it->x_axis;
data->list[i].y_axis = it->y_axis;
data->list[i].wheel = it->wheel;
data->list[i].tilt = it->tilt;
}
2018-06-07 09:59:27 +02:00
2018-08-04 14:37:32 +02:00
list.clear();
2018-06-07 09:59:27 +02:00
return CELL_OK;
}
2015-07-09 17:30:37 +02:00
s32 cellMouseSetTabletMode(u32 port_no, u32 mode)
{
2018-06-07 09:59:27 +02:00
sys_io.warning("cellMouseSetTabletMode(port_no=%d, mode=%d)", port_no, mode);
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
// only check for port_no here. Tests show that valid ports lead to ERROR_FATAL with disconnected devices regardless of info
if (port_no >= CELL_MAX_MICE)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_FATAL;
}
if (mode != CELL_MOUSE_INFO_TABLET_MOUSE_MODE && mode != CELL_MOUSE_INFO_TABLET_TABLET_MODE)
{
return CELL_EINVAL; // lol... why not CELL_MOUSE_ERROR_INVALID_PARAMETER. Sony is drunk
}
current_info.mode[port_no] = mode;
// TODO: decr returns CELL_ENOTSUP ... How should we handle this?
return CELL_OK;
}
2018-06-07 09:59:27 +02:00
s32 cellMouseGetTabletDataList(u32 port_no, vm::ptr<CellMouseTabletDataList> data)
{
2018-06-07 09:59:27 +02:00
sys_io.warning("cellMouseGetTabletDataList(port_no=%d, data=0x%x)", port_no, data);
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
if (port_no >= CELL_MAX_MICE || !data)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
{
return CELL_MOUSE_ERROR_NO_DEVICE;
}
// TODO: decr tests show that CELL_MOUSE_ERROR_DATA_READ_FAILED is returned when a mouse is connected
// TODO: check if (current_info.mode[port_no] != CELL_MOUSE_INFO_TABLET_TABLET_MODE) has any impact
auto& list = handler->GetTabletDataList(port_no);
data->list_num = std::min((u32)CELL_MOUSE_MAX_DATA_LIST_NUM, (u32)list.size());
int i = 0;
for (auto it = list.begin(); it != list.end() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++it, ++i)
{
data->list[i].len = it->len;
it->len = 0;
for (int k = 0; k < CELL_MOUSE_MAX_CODES; k++)
{
data->list[i].data[k] = it->data[k];
it->data[k] = 0;
}
}
return CELL_OK;
}
2016-03-21 20:43:03 +01:00
s32 cellMouseGetRawData(u32 port_no, vm::ptr<CellMouseRawData> data)
{
2018-06-07 09:59:27 +02:00
sys_io.warning("cellMouseGetRawData(port_no=%d, data=*0x%x)", port_no, data);
2016-03-21 20:43:03 +01:00
const auto handler = fxm::get<MouseHandlerBase>();
if (!handler)
{
2016-03-21 20:43:03 +01:00
return CELL_MOUSE_ERROR_UNINITIALIZED;
}
2018-06-07 09:59:27 +02:00
if (port_no >= CELL_MAX_MICE || !data)
{
return CELL_MOUSE_ERROR_INVALID_PARAMETER;
}
const MouseInfo& current_info = handler->GetInfo();
if (port_no >= handler->GetMice().size() || current_info.status[port_no] != CELL_MOUSE_STATUS_CONNECTED)
2016-03-21 20:43:03 +01:00
{
return CELL_MOUSE_ERROR_NO_DEVICE;
}
2018-06-07 09:59:27 +02:00
// TODO: decr tests show that CELL_MOUSE_ERROR_DATA_READ_FAILED is returned when a mouse is connected
// TODO: check if (current_info.mode[port_no] != CELL_MOUSE_INFO_TABLET_MOUSE_MODE) has any impact
MouseRawData& current_data = handler->GetRawData(port_no);
data->len = current_data.len;
current_data.len = 0;
for (int i = 0; i < CELL_MOUSE_MAX_CODES; i++)
{
data->data[i] = current_data.data[i];
current_data.data[i] = 0;
}
return CELL_OK;
}
2014-09-03 18:33:30 +02:00
void cellMouse_init()
{
REG_FUNC(sys_io, cellMouseInit);
REG_FUNC(sys_io, cellMouseClearBuf);
REG_FUNC(sys_io, cellMouseEnd);
REG_FUNC(sys_io, cellMouseGetInfo);
REG_FUNC(sys_io, cellMouseInfoTabletMode);
REG_FUNC(sys_io, cellMouseGetData);
REG_FUNC(sys_io, cellMouseGetDataList);
REG_FUNC(sys_io, cellMouseSetTabletMode);
REG_FUNC(sys_io, cellMouseGetTabletDataList);
REG_FUNC(sys_io, cellMouseGetRawData);
2014-09-03 18:33:30 +02:00
}