mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
sys_usbd: Implemented sys_usbd_unregister_extra_ldd()
This commit is contained in:
parent
da0c9c2ce9
commit
c85775922e
@ -186,4 +186,23 @@ namespace fmt
|
||||
const u8* buf;
|
||||
usz len;
|
||||
};
|
||||
|
||||
struct string_hash
|
||||
{
|
||||
using hash_type = std::hash<std::string_view>;
|
||||
using is_transparent = void;
|
||||
|
||||
std::size_t operator()(const char* str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string_view str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string const& str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_sysc
|
||||
null_func,//BIND_SYSC(sys_usbd_...), //555 (0x22B)
|
||||
BIND_SYSC(sys_usbd_get_device_speed), //556 (0x22C)
|
||||
null_func,//BIND_SYSC(sys_usbd_...), //557 (0x22D)
|
||||
null_func,//BIND_SYSC(sys_usbd_...), //558 (0x22E)
|
||||
BIND_SYSC(sys_usbd_unregister_extra_ldd), //558 (0x22E)
|
||||
BIND_SYSC(sys_usbd_register_extra_ldd), //559 (0x22F)
|
||||
null_func,//BIND_SYSC(sys_...), //560 (0x230) ROOT
|
||||
null_func,//BIND_SYSC(sys_...), //561 (0x231) ROOT
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/system_utils.hpp"
|
||||
#include "Emu/Cell/lv2/sys_process.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <span>
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Utilities/File.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
@ -218,26 +219,7 @@ public:
|
||||
static bool vfs_unmount(std::string_view vpath);
|
||||
|
||||
private:
|
||||
struct string_hash
|
||||
{
|
||||
using hash_type = std::hash<std::string_view>;
|
||||
using is_transparent = void;
|
||||
|
||||
std::size_t operator()(const char* str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string_view str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
std::size_t operator()(std::string const& str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, lv2_fs_mount_info, string_hash, std::equal_to<>> map;
|
||||
std::unordered_map<std::string, lv2_fs_mount_info, fmt::string_hash, std::equal_to<>> map;
|
||||
};
|
||||
|
||||
struct lv2_fs_object
|
||||
|
@ -48,7 +48,6 @@ void fmt_class_string<libusb_transfer>::format(std::string& out, u64 arg)
|
||||
|
||||
struct UsbLdd
|
||||
{
|
||||
std::string name;
|
||||
u16 id_vendor{};
|
||||
u16 id_product_min{};
|
||||
u16 id_product_max{};
|
||||
@ -86,8 +85,8 @@ public:
|
||||
void transfer_complete(libusb_transfer* transfer);
|
||||
|
||||
// LDDs handling functions
|
||||
u32 add_ldd(vm::ptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max);
|
||||
void check_devices_vs_ldds();
|
||||
bool add_ldd(std::string_view product, u16 id_vendor, u16 id_product_min, u16 id_product_max);
|
||||
bool remove_ldd(std::string_view product);
|
||||
|
||||
// Pipe functions
|
||||
u32 open_pipe(u32 device_handle, u8 endpoint);
|
||||
@ -131,7 +130,7 @@ private:
|
||||
u32 pipe_counter = 0x10; // Start at 0x10 only for tracing purposes
|
||||
|
||||
// List of device drivers
|
||||
std::vector<UsbLdd> ldds;
|
||||
std::unordered_map<std::string, UsbLdd, fmt::string_hash, std::equal_to<>> ldds;
|
||||
|
||||
// List of pipes
|
||||
std::map<u32, UsbPipe> open_pipes;
|
||||
@ -523,17 +522,64 @@ void usb_handler_thread::transfer_complete(struct libusb_transfer* transfer)
|
||||
sys_usbd.trace("Transfer complete(0x%x): %s", usbd_transfer->transfer_id, *transfer);
|
||||
}
|
||||
|
||||
u32 usb_handler_thread::add_ldd(vm::ptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max)
|
||||
bool usb_handler_thread::add_ldd(std::string_view product, u16 id_vendor, u16 id_product_min, u16 id_product_max)
|
||||
{
|
||||
UsbLdd new_ldd;
|
||||
new_ldd.name.resize(slen_product);
|
||||
memcpy(new_ldd.name.data(), s_product.get_ptr(), slen_product);
|
||||
new_ldd.id_vendor = id_vendor;
|
||||
new_ldd.id_product_min = id_product_min;
|
||||
new_ldd.id_product_max = id_product_max;
|
||||
ldds.push_back(new_ldd);
|
||||
if (ldds.try_emplace(std::string(product), id_vendor, id_product_min, id_product_max).second)
|
||||
{
|
||||
for (const auto& dev : usb_devices)
|
||||
{
|
||||
if (dev->assigned_number)
|
||||
continue;
|
||||
|
||||
return ::size32(ldds); // TODO: to check
|
||||
if (dev->device._device.idVendor == id_vendor && dev->device._device.idProduct >= id_product_min && dev->device._device.idProduct <= id_product_max)
|
||||
{
|
||||
if (!dev->open_device())
|
||||
{
|
||||
sys_usbd.error("Failed to open device for LDD(VID:0x%04x PID:0x%04x)", dev->device._device.idVendor, dev->device._device.idProduct);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev->read_descriptors();
|
||||
dev->assigned_number = dev_counter++; // assign current dev_counter, and atomically increment
|
||||
|
||||
sys_usbd.notice("Ldd device matchup for <%s>, assigned as handled_device=0x%x", product, dev->assigned_number);
|
||||
|
||||
handled_devices.emplace(dev->assigned_number, std::pair(UsbInternalDevice{0x00, narrow<u8>(dev->assigned_number), 0x02, 0x40}, dev));
|
||||
send_message(SYS_USBD_ATTACH, dev->assigned_number);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usb_handler_thread::remove_ldd(std::string_view product)
|
||||
{
|
||||
if (const auto iterator = ldds.find(product); iterator != ldds.end())
|
||||
{
|
||||
for (const auto& dev : usb_devices)
|
||||
{
|
||||
if (!dev->assigned_number)
|
||||
continue;
|
||||
|
||||
if (dev->device._device.idVendor == iterator->second.id_vendor && dev->device._device.idProduct >= iterator->second.id_product_min && dev->device._device.idProduct <= iterator->second.id_product_max)
|
||||
{
|
||||
if (handled_devices.erase(dev->assigned_number))
|
||||
{
|
||||
sys_usbd.notice("Ldd device matchup for <%s>, removed 0x%x from handled_devices", iterator->first, dev->assigned_number);
|
||||
send_message(SYS_USBD_DETACH, dev->assigned_number);
|
||||
dev->assigned_number = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldds.erase(iterator);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 usb_handler_thread::open_pipe(u32 device_handle, u8 endpoint)
|
||||
@ -557,35 +603,6 @@ const UsbPipe& usb_handler_thread::get_pipe(u32 pipe_id) const
|
||||
return ::at32(open_pipes, pipe_id);
|
||||
}
|
||||
|
||||
void usb_handler_thread::check_devices_vs_ldds()
|
||||
{
|
||||
for (const auto& dev : usb_devices)
|
||||
{
|
||||
if (dev->assigned_number)
|
||||
continue;
|
||||
|
||||
for (const auto& ldd : ldds)
|
||||
{
|
||||
if (dev->device._device.idVendor == ldd.id_vendor && dev->device._device.idProduct >= ldd.id_product_min && dev->device._device.idProduct <= ldd.id_product_max)
|
||||
{
|
||||
if (!dev->open_device())
|
||||
{
|
||||
sys_usbd.error("Failed to open device for LDD(VID:0x%04x PID:0x%04x)", dev->device._device.idVendor, dev->device._device.idProduct);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev->read_descriptors();
|
||||
dev->assigned_number = dev_counter++; // assign current dev_counter, and atomically increment
|
||||
|
||||
sys_usbd.success("Ldd device matchup for <%s>, assigned as handled_device=0x%x", ldd.name, dev->assigned_number);
|
||||
|
||||
handled_devices.emplace(dev->assigned_number, std::pair(UsbInternalDevice{0x00, narrow<u8>(dev->assigned_number), 0x02, 0x40}, dev));
|
||||
send_message(SYS_USBD_ATTACH, dev->assigned_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_handler_thread::get_event(vm::ptr<u64>& arg1, vm::ptr<u64>& arg2, vm::ptr<u64>& arg3)
|
||||
{
|
||||
if (!usbd_events.empty())
|
||||
@ -754,12 +771,11 @@ error_code sys_usbd_get_device_list(ppu_thread& ppu, u32 handle, vm::ptr<UsbInte
|
||||
return not_an_error(i_tocopy);
|
||||
}
|
||||
|
||||
error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::ptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max)
|
||||
error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_usbd.warning("sys_usbd_register_extra_ldd(handle=0x%x, s_product=%s, slen_product=%d, id_vendor=0x%04x, id_product_min=0x%04x, id_product_max=0x%04x)", handle, s_product, slen_product, id_vendor,
|
||||
id_product_min, id_product_max);
|
||||
sys_usbd.trace("sys_usbd_register_extra_ldd(handle=0x%x, s_product=%s, slen_product=%d, id_vendor=0x%04x, id_product_min=0x%04x, id_product_max=0x%04x)", handle, s_product, slen_product, id_vendor, id_product_min, id_product_max);
|
||||
|
||||
auto& usbh = g_fxo->get<named_thread<usb_handler_thread>>();
|
||||
|
||||
@ -767,10 +783,32 @@ error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::ptr<char
|
||||
if (!usbh.is_init)
|
||||
return CELL_EINVAL;
|
||||
|
||||
s32 res = usbh.add_ldd(s_product, slen_product, id_vendor, id_product_min, id_product_max);
|
||||
usbh.check_devices_vs_ldds();
|
||||
std::string_view product{s_product.get_ptr(), slen_product};
|
||||
|
||||
return not_an_error(res); // To check
|
||||
if (usbh.add_ldd(product, id_vendor, id_product_min, id_product_max))
|
||||
return CELL_OK;
|
||||
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
error_code sys_usbd_unregister_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_usbd.trace("sys_usbd_unregister_extra_ldd(handle=0x%x, s_product=%s, slen_product=%d)", handle, s_product, slen_product);
|
||||
|
||||
auto& usbh = g_fxo->get<named_thread<usb_handler_thread>>();
|
||||
|
||||
std::lock_guard lock(usbh.mutex);
|
||||
if (!usbh.is_init)
|
||||
return CELL_EINVAL;
|
||||
|
||||
std::string_view product{s_product.get_ptr(), slen_product};
|
||||
|
||||
if (usbh.remove_ldd(product))
|
||||
return CELL_OK;
|
||||
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
error_code sys_usbd_get_descriptor_size(ppu_thread& ppu, u32 handle, u32 device_handle)
|
||||
@ -812,37 +850,39 @@ error_code sys_usbd_get_descriptor(ppu_thread& ppu, u32 handle, u32 device_handl
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
// This function is used for psp(cellUsbPspcm), dongles in ps3 arcade cabinets(PS3A-USJ), ps2 cam(eyetoy), generic usb camera?(sample_usb2cam)
|
||||
error_code sys_usbd_register_ldd(ppu_thread& ppu, u32 handle, vm::ptr<char> s_product, u16 slen_product)
|
||||
// This function is used for psp(cellUsbPspcm), ps3 arcade usj io(PS3A-USJ), ps2 cam(eyetoy), generic usb camera?(sample_usb2cam)
|
||||
error_code sys_usbd_register_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
std::string_view product{s_product.get_ptr(), slen_product};
|
||||
|
||||
// slightly hacky way of getting Namco GCon3 gun to work.
|
||||
// The register_ldd appears to be a more promiscuous mode function, where all device 'inserts' would be presented to the cellUsbd for Probing.
|
||||
// Unsure how many more devices might need similar treatment (i.e. just a compare and force VID/PID add), or if it's worth adding a full promiscuous
|
||||
// capability
|
||||
if (s_product.get_ptr() == "guncon3"sv)
|
||||
// Unsure how many more devices might need similar treatment (i.e. just a compare and force VID/PID add), or if it's worth adding a full promiscuous capability
|
||||
static const std::unordered_map<std::string, UsbLdd, fmt::string_hash, std::equal_to<>> predefined_ldds
|
||||
{
|
||||
sys_usbd.warning("sys_usbd_register_ldd(handle=0x%x, s_product=%s, slen_product=0x%x) -> Redirecting to sys_usbd_register_extra_ldd", handle, s_product, slen_product);
|
||||
sys_usbd_register_extra_ldd(ppu, handle, s_product, slen_product, 0x0B9A, 0x0800, 0x0800);
|
||||
}
|
||||
else if (s_product.get_ptr() == "PS3A-USJ"sv)
|
||||
{"guncon3", {0x0B9A, 0x0800, 0x0800}},
|
||||
{"PS3A-USJ", {0x0B9A, 0x0900, 0x0910}}
|
||||
};
|
||||
|
||||
if (const auto iterator = predefined_ldds.find(product); iterator != predefined_ldds.end())
|
||||
{
|
||||
// Arcade IO boards
|
||||
sys_usbd.warning("sys_usbd_register_ldd(handle=0x%x, s_product=%s, slen_product=0x%x) -> Redirecting to sys_usbd_register_extra_ldd", handle, s_product, slen_product);
|
||||
sys_usbd_register_extra_ldd(ppu, handle, s_product, slen_product, 0x0B9A, 0x0900, 0x0910);
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_usbd.todo("sys_usbd_register_ldd(handle=0x%x, s_product=%s, slen_product=0x%x)", handle, s_product, slen_product);
|
||||
sys_usbd.trace("sys_usbd_register_ldd(handle=0x%x, s_product=%s, slen_product=%d) -> Redirecting to sys_usbd_register_extra_ldd()", handle, s_product, slen_product);
|
||||
return sys_usbd_register_extra_ldd(ppu, handle, s_product, slen_product, iterator->second.id_vendor, iterator->second.id_product_min, iterator->second.id_product_max);
|
||||
}
|
||||
|
||||
sys_usbd.todo("sys_usbd_register_ldd(handle=0x%x, s_product=%s, slen_product=%d)", handle, s_product, slen_product);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_usbd_unregister_ldd(ppu_thread&)
|
||||
error_code sys_usbd_unregister_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product)
|
||||
{
|
||||
sys_usbd.todo("sys_usbd_unregister_ldd()");
|
||||
return CELL_OK;
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_usbd.trace("sys_usbd_unregister_ldd(handle=0x%x, s_product=%s, slen_product=%d) -> Redirecting to sys_usbd_unregister_extra_ldd()", handle, s_product, slen_product);
|
||||
|
||||
return sys_usbd_unregister_extra_ldd(ppu, handle, s_product, slen_product);
|
||||
}
|
||||
|
||||
// TODO: determine what the unknown params are
|
||||
@ -999,7 +1039,7 @@ error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm::
|
||||
|
||||
if (sys_usbd.trace && request)
|
||||
{
|
||||
sys_usbd.trace("RequestType:0x%x, Request:0x%x, wValue:0x%x, wIndex:0x%x, wLength:0x%x", request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength);
|
||||
sys_usbd.trace("RequestType:0x%02x, Request:0x%02x, wValue:0x%04x, wIndex:0x%04x, wLength:0x%04x", request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength);
|
||||
|
||||
if ((request->bmRequestType & 0x80) == 0 && buf && buf_size != 0)
|
||||
sys_usbd.trace("Control sent:\n%s", fmt::buf_to_hexstring(buf.get_ptr(), buf_size));
|
||||
|
@ -66,8 +66,8 @@ error_code sys_usbd_finalize(ppu_thread& ppu, u32 handle);
|
||||
error_code sys_usbd_get_device_list(ppu_thread& ppu, u32 handle, vm::ptr<UsbInternalDevice> device_list, u32 max_devices);
|
||||
error_code sys_usbd_get_descriptor_size(ppu_thread& ppu, u32 handle, u32 device_handle);
|
||||
error_code sys_usbd_get_descriptor(ppu_thread& ppu, u32 handle, u32 device_handle, vm::ptr<void> descriptor, u32 desc_size);
|
||||
error_code sys_usbd_register_ldd(ppu_thread& ppu, u32 handle, vm::ptr<char> s_product, u16 slen_product);
|
||||
error_code sys_usbd_unregister_ldd(ppu_thread& ppu);
|
||||
error_code sys_usbd_register_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product);
|
||||
error_code sys_usbd_unregister_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product);
|
||||
error_code sys_usbd_open_pipe(ppu_thread& ppu, u32 handle, u32 device_handle, u32 unk1, u64 unk2, u64 unk3, u32 endpoint, u64 unk4);
|
||||
error_code sys_usbd_open_default_pipe(ppu_thread& ppu, u32 handle, u32 device_handle);
|
||||
error_code sys_usbd_close_pipe(ppu_thread& ppu, u32 handle, u32 pipe_handle);
|
||||
@ -84,4 +84,5 @@ error_code sys_usbd_event_port_send(ppu_thread& ppu, u32 handle, u64 arg1, u64 a
|
||||
error_code sys_usbd_allocate_memory(ppu_thread& ppu);
|
||||
error_code sys_usbd_free_memory(ppu_thread& ppu);
|
||||
error_code sys_usbd_get_device_speed(ppu_thread& ppu);
|
||||
error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::ptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max);
|
||||
error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product, u16 id_vendor, u16 id_product_min, u16 id_product_max);
|
||||
error_code sys_usbd_unregister_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr<char> s_product, u16 slen_product);
|
||||
|
Loading…
Reference in New Issue
Block a user