diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index d71f1f8e67..175db3c855 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -128,7 +128,6 @@ void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer) { auto& usbh = g_fxo->get>(); - std::lock_guard lock(usbh.mutex); if (!usbh.is_init) return; @@ -142,11 +141,17 @@ usb_handler_thread::usb_handler_thread() // look if any device which we could be interested in is actually connected libusb_device** list = nullptr; - ssize_t ndev = libusb_get_device_list(ctx, &list); + ssize_t ndev = libusb_get_device_list(ctx, &list); + + std::array location{}; + + auto get_new_location = [&]() -> const std::array& + { + location[0]++; + return location; + }; bool found_skylander = false; - bool found_ghltar = false; - bool found_turntable = false; bool found_usio = false; for (ssize_t index = 0; index < ndev; index++) @@ -154,20 +159,18 @@ usb_handler_thread::usb_handler_thread() libusb_device_descriptor desc; libusb_get_device_descriptor(list[index], &desc); - // clang-format off auto check_device = [&](const u16 id_vendor, const u16 id_product_min, const u16 id_product_max, const char* s_name) -> bool { if (desc.idVendor == id_vendor && desc.idProduct >= id_product_min && desc.idProduct <= id_product_max) { sys_usbd.success("Found device: %s", s_name); libusb_ref_device(list[index]); - std::shared_ptr usb_dev = std::make_shared(list[index], desc); + std::shared_ptr usb_dev = std::make_shared(list[index], desc, get_new_location()); usb_devices.push_back(usb_dev); return true; } return false; }; - // clang-format on // Portals if (check_device(0x1430, 0x0150, 0x0150, "Skylanders Portal")) @@ -187,15 +190,9 @@ usb_handler_thread::usb_handler_thread() //check_device(0x1415, 0x0020, 0x0020, "SingStar Microphone Wireless"); // TODO: verifiy check_device(0x12BA, 0x0100, 0x0100, "Guitar Hero Guitar"); check_device(0x12BA, 0x0120, 0x0120, "Guitar Hero Drums"); - if (check_device(0x12BA, 0x074B, 0x074B, "Guitar Hero Live Guitar")) - { - found_ghltar = true; - } + check_device(0x12BA, 0x074B, 0x074B, "Guitar Hero Live Guitar"); - if (check_device(0x12BA, 0x0140, 0x0140, "DJ Hero Turntable")) - { - found_turntable = true; - } + check_device(0x12BA, 0x0140, 0x0140, "DJ Hero Turntable"); check_device(0x12BA, 0x0200, 0x020F, "Harmonix Guitar"); check_device(0x12BA, 0x0210, 0x021F, "Harmonix Drums"); check_device(0x12BA, 0x2330, 0x233F, "Harmonix Keyboard"); @@ -242,48 +239,48 @@ usb_handler_thread::usb_handler_thread() if (!found_skylander) { sys_usbd.notice("Adding emulated skylander"); - usb_devices.push_back(std::make_shared()); + usb_devices.push_back(std::make_shared(get_new_location())); } if (!found_usio) { sys_usbd.notice("Adding emulated v406 usio"); - usb_devices.push_back(std::make_shared()); + usb_devices.push_back(std::make_shared(get_new_location())); } if (g_cfg.io.ghltar == ghltar_handler::one_controller || g_cfg.io.ghltar == ghltar_handler::two_controllers) { sys_usbd.notice("Adding emulated GHLtar (1 player)"); - usb_devices.push_back(std::make_shared(0)); + usb_devices.push_back(std::make_shared(0, get_new_location())); } if (g_cfg.io.ghltar == ghltar_handler::two_controllers) { sys_usbd.notice("Adding emulated GHLtar (2 players)"); - usb_devices.push_back(std::make_shared(1)); + usb_devices.push_back(std::make_shared(1, get_new_location())); } if (g_cfg.io.turntable == turntable_handler::one_controller || g_cfg.io.turntable == turntable_handler::two_controllers) { sys_usbd.notice("Adding emulated turntable (1 player)"); - usb_devices.push_back(std::make_shared(0)); + usb_devices.push_back(std::make_shared(0, get_new_location())); } if (g_cfg.io.turntable == turntable_handler::two_controllers) { sys_usbd.notice("Adding emulated turntable (2 players)"); - usb_devices.push_back(std::make_shared(1)); + usb_devices.push_back(std::make_shared(1, get_new_location())); } if (g_cfg.io.buzz == buzz_handler::one_controller || g_cfg.io.buzz == buzz_handler::two_controllers) { sys_usbd.notice("Adding emulated Buzz! buzzer (1-4 players)"); - usb_devices.push_back(std::make_shared(0, 3)); + usb_devices.push_back(std::make_shared(0, 3, get_new_location())); } if (g_cfg.io.buzz == buzz_handler::two_controllers) { // The current buzz emulation piggybacks on the pad input. // Since there can only be 7 pads connected on a PS3 the 8th player is currently not supported sys_usbd.notice("Adding emulated Buzz! buzzer (5-7 players)"); - usb_devices.push_back(std::make_shared(4, 6)); + usb_devices.push_back(std::make_shared(4, 6, get_new_location())); } for (u32 index = 0; index < MAX_SYS_USBD_TRANSFERS; index++) @@ -317,6 +314,7 @@ void usb_handler_thread::operator()() while (thread_ctrl::state() != thread_state::aborting) { // Todo: Hotplug here? + std::lock_guard lock(this->mutex); // Process asynchronous requests that are pending libusb_handle_events_timeout_completed(ctx, &lusb_tv, nullptr); @@ -324,8 +322,6 @@ void usb_handler_thread::operator()() // Process fake transfers if (!fake_transfers.empty()) { - std::lock_guard lock(this->mutex); - u64 timestamp = get_system_time() - Emu.GetPauseTime(); for (auto it = fake_transfers.begin(); it != fake_transfers.end();) @@ -340,7 +336,6 @@ void usb_handler_thread::operator()() continue; } - transfer->result = transfer->expected_result; transfer->count = transfer->expected_count; transfer->fake = false; @@ -596,7 +591,7 @@ error_code sys_usbd_register_extra_ldd(ppu_thread& ppu, u32 handle, vm::ptrget>(); @@ -749,7 +744,7 @@ error_code sys_usbd_receive_event(ppu_thread& ppu, u32 handle, vm::ptr arg1 { ppu.state += cpu_flag::wait; - sys_usbd.trace("sys_usbd_receive_event(handle=%u, arg1=*0x%x, arg2=*0x%x, arg3=*0x%x)", handle, arg1, arg2, arg3); + sys_usbd.trace("sys_usbd_receive_event(handle=0x%x, arg1=*0x%x, arg2=*0x%x, arg3=*0x%x)", handle, arg1, arg2, arg3); auto& usbh = g_fxo->get>(); @@ -851,6 +846,7 @@ error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm:: u32 id_transfer = usbh.get_free_transfer_id(); const auto& pipe = usbh.get_pipe(id_pipe); auto& transfer = usbh.get_transfer(id_transfer); + transfer.busy = true; // Default endpoint is control endpoint if (pipe.endpoint == 0) @@ -869,7 +865,6 @@ error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm:: } pipe.device->control_transfer(request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength, buf_size, buf.get_ptr(), &transfer); - transfer.busy = true; } else { @@ -889,7 +884,6 @@ error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm:: sys_usbd.trace("Write Int(s: %d) :%s", buf_size, datrace); } pipe.device->interrupt_transfer(buf_size, buf.get_ptr(), pipe.endpoint, &transfer); - transfer.busy = true; } if (transfer.fake) @@ -967,11 +961,21 @@ error_code sys_usbd_get_isochronous_transfer_status(ppu_thread& ppu, u32 handle, return CELL_OK; } -error_code sys_usbd_get_device_location(ppu_thread& ppu) +error_code sys_usbd_get_device_location(ppu_thread& ppu, u32 handle, u32 device_handle, vm::ptr location) { ppu.state += cpu_flag::wait; - sys_usbd.todo("sys_usbd_get_device_location()"); + sys_usbd.notice("sys_usbd_get_device_location(handle=0x%x, device_handle=0x%x, location=*0x%x)", handle, device_handle, location); + + auto& usbh = g_fxo->get>(); + + std::lock_guard lock(usbh.mutex); + + if (!usbh.is_init || !usbh.handled_devices.count(device_handle)) + return CELL_EINVAL; + + usbh.handled_devices[device_handle].second->get_location(location.get_ptr()); + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.h b/rpcs3/Emu/Cell/lv2/sys_usbd.h index 3f829cd900..0c2070b2b9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.h +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.h @@ -78,7 +78,7 @@ error_code sys_usbd_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm:: error_code sys_usbd_isochronous_transfer_data(ppu_thread& ppu, u32 handle, u32 id_pipe, vm::ptr iso_request); error_code sys_usbd_get_transfer_status(ppu_thread& ppu, u32 handle, u32 id_transfer, u32 unk1, vm::ptr result, vm::ptr count); error_code sys_usbd_get_isochronous_transfer_status(ppu_thread& ppu, u32 handle, u32 id_transfer, u32 unk1, vm::ptr request, vm::ptr result); -error_code sys_usbd_get_device_location(ppu_thread& ppu); +error_code sys_usbd_get_device_location(ppu_thread& ppu, u32 handle, u32 device_handle, vm::ptr location); error_code sys_usbd_send_event(ppu_thread& ppu); error_code sys_usbd_event_port_send(ppu_thread& ppu, u32 handle, u64 arg1, u64 arg2, u64 arg3); error_code sys_usbd_allocate_memory(ppu_thread& ppu); diff --git a/rpcs3/Emu/Io/Buzz.cpp b/rpcs3/Emu/Io/Buzz.cpp index 40bbcbd950..557c7d03c7 100644 --- a/rpcs3/Emu/Io/Buzz.cpp +++ b/rpcs3/Emu/Io/Buzz.cpp @@ -7,7 +7,8 @@ LOG_CHANNEL(buzz_log); -usb_device_buzz::usb_device_buzz(int first_controller, int last_controller) +usb_device_buzz::usb_device_buzz(int first_controller, int last_controller, const std::array& location) + : usb_device_emulated(location) { this->first_controller = first_controller; this->last_controller = last_controller; diff --git a/rpcs3/Emu/Io/Buzz.h b/rpcs3/Emu/Io/Buzz.h index ef9df8d4c0..314efdce40 100644 --- a/rpcs3/Emu/Io/Buzz.h +++ b/rpcs3/Emu/Io/Buzz.h @@ -8,7 +8,7 @@ class usb_device_buzz : public usb_device_emulated int last_controller; public: - usb_device_buzz(int first_controller, int last_controller); + usb_device_buzz(int first_controller, int last_controller, const std::array& location); ~usb_device_buzz(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/Io/GHLtar.cpp b/rpcs3/Emu/Io/GHLtar.cpp index d0db026d95..2d52c0cd3f 100644 --- a/rpcs3/Emu/Io/GHLtar.cpp +++ b/rpcs3/Emu/Io/GHLtar.cpp @@ -7,7 +7,8 @@ LOG_CHANNEL(ghltar_log); -usb_device_ghltar::usb_device_ghltar(int controller_index) : m_controller_index(controller_index) +usb_device_ghltar::usb_device_ghltar(int controller_index, const std::array& location) + : usb_device_emulated(location), m_controller_index(controller_index) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{0x0200, 0x00, 0x00, 0x00, 0x20, 0x12BA, 0x074B, 0x0100, 0x01, 0x02, 0x00, 0x01}); auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG, UsbDeviceConfiguration{0x0029, 0x01, 0x01, 0x00, 0x80, 0x96})); diff --git a/rpcs3/Emu/Io/GHLtar.h b/rpcs3/Emu/Io/GHLtar.h index 7790da3a27..52c9fd58a5 100644 --- a/rpcs3/Emu/Io/GHLtar.h +++ b/rpcs3/Emu/Io/GHLtar.h @@ -8,7 +8,7 @@ private: int m_controller_index; public: - usb_device_ghltar(int controller_index); + usb_device_ghltar(int controller_index, const std::array& location); ~usb_device_ghltar(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/Io/Skylander.cpp b/rpcs3/Emu/Io/Skylander.cpp index 87887ddf1f..57494a5b1c 100644 --- a/rpcs3/Emu/Io/Skylander.cpp +++ b/rpcs3/Emu/Io/Skylander.cpp @@ -193,7 +193,8 @@ u8 sky_portal::load_skylander(u8* buf, fs::file in_file) return found_slot; } -usb_device_skylander::usb_device_skylander() +usb_device_skylander::usb_device_skylander(const std::array& location) + : usb_device_emulated(location) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{0x0200, 0x00, 0x00, 0x00, 0x20, 0x1430, 0x0150, 0x0100, 0x01, 0x02, 0x00, 0x01}); auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG, UsbDeviceConfiguration{0x0029, 0x01, 0x01, 0x00, 0x80, 0x96})); diff --git a/rpcs3/Emu/Io/Skylander.h b/rpcs3/Emu/Io/Skylander.h index 0002c2500a..da7dc3dfa4 100644 --- a/rpcs3/Emu/Io/Skylander.h +++ b/rpcs3/Emu/Io/Skylander.h @@ -43,7 +43,7 @@ extern sky_portal g_skyportal; class usb_device_skylander : public usb_device_emulated { public: - usb_device_skylander(); + usb_device_skylander(const std::array& location); ~usb_device_skylander(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index 3c65d3a0e0..0f999d9ae3 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -7,7 +7,8 @@ LOG_CHANNEL(turntable_log); -usb_device_turntable::usb_device_turntable(int controller_index) : m_controller_index(controller_index) +usb_device_turntable::usb_device_turntable(int controller_index, const std::array& location) + : usb_device_emulated(location), m_controller_index(controller_index) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{0x0100, 0x00, 0x00, 0x00, 0x40, 0x12BA, 0x0140, 0x0005, 0x01, 0x02, 0x00, 0x01}); auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG, UsbDeviceConfiguration{0x0029, 0x01, 0x01, 0x00, 0x80, 0x19})); diff --git a/rpcs3/Emu/Io/Turntable.h b/rpcs3/Emu/Io/Turntable.h index d816f690d6..1d43cc5875 100644 --- a/rpcs3/Emu/Io/Turntable.h +++ b/rpcs3/Emu/Io/Turntable.h @@ -8,7 +8,7 @@ private: int m_controller_index; public: - usb_device_turntable(int controller_index); + usb_device_turntable(int controller_index, const std::array& location); ~usb_device_turntable(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/Io/usb_device.cpp b/rpcs3/Emu/Io/usb_device.cpp index 4383c5f8c2..e049d2b723 100644 --- a/rpcs3/Emu/Io/usb_device.cpp +++ b/rpcs3/Emu/Io/usb_device.cpp @@ -13,6 +13,16 @@ extern void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer); // ALL DEVICES /////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// +usb_device::usb_device(const std::array& location) +{ + this->location = location; +} + +void usb_device::get_location(u8* location) const +{ + memcpy(location, this->location.data(), 7); +} + void usb_device::read_descriptors() { } @@ -37,11 +47,11 @@ u64 usb_device::get_timestamp() ////////////////////////////////////////////////////////////////// // PASSTHROUGH DEVICE //////////////////////////////////////////// ////////////////////////////////////////////////////////////////// -usb_device_passthrough::usb_device_passthrough(libusb_device* _device, libusb_device_descriptor& desc) - : lusb_device(_device) +usb_device_passthrough::usb_device_passthrough(libusb_device* _device, libusb_device_descriptor& desc, const std::array& location) + : usb_device(location), lusb_device(_device) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{desc.bcdUSB, desc.bDeviceClass, desc.bDeviceSubClass, desc.bDeviceProtocol, desc.bMaxPacketSize0, desc.idVendor, desc.idProduct, - desc.bcdDevice, desc.iManufacturer, desc.iProduct, desc.iSerialNumber, desc.bNumConfigurations}); + desc.bcdDevice, desc.iManufacturer, desc.iProduct, desc.iSerialNumber, desc.bNumConfigurations}); } usb_device_passthrough::~usb_device_passthrough() @@ -136,11 +146,13 @@ void usb_device_passthrough::isochronous_transfer(UsbTransfer* transfer) ////////////////////////////////////////////////////////////////// // EMULATED DEVICE /////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// -usb_device_emulated::usb_device_emulated() +usb_device_emulated::usb_device_emulated(const std::array& location) + : usb_device(location) { } -usb_device_emulated::usb_device_emulated(const UsbDeviceDescriptor& _device) +usb_device_emulated::usb_device_emulated(const UsbDeviceDescriptor& _device, const std::array& location) + : usb_device(location) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, _device); } diff --git a/rpcs3/Emu/Io/usb_device.h b/rpcs3/Emu/Io/usb_device.h index 040d29cccd..3878dd5f56 100644 --- a/rpcs3/Emu/Io/usb_device.h +++ b/rpcs3/Emu/Io/usb_device.h @@ -167,8 +167,11 @@ struct UsbDescriptorNode class usb_device { public: + usb_device(const std::array& location); + virtual bool open_device() = 0; + void get_location(u8* location) const; virtual void read_descriptors(); virtual bool set_configuration(u8 cfg_num); @@ -187,6 +190,7 @@ public: protected: u8 current_config = 1; u8 current_interface = 0; + std::array location{}; protected: static u64 get_timestamp(); @@ -195,7 +199,7 @@ protected: class usb_device_passthrough : public usb_device { public: - usb_device_passthrough(libusb_device* _device, libusb_device_descriptor& desc); + usb_device_passthrough(libusb_device* _device, libusb_device_descriptor& desc, const std::array& location); ~usb_device_passthrough(); bool open_device() override; @@ -214,8 +218,8 @@ protected: class usb_device_emulated : public usb_device { public: - usb_device_emulated(); - usb_device_emulated(const UsbDeviceDescriptor& _device); + usb_device_emulated(const std::array& location); + usb_device_emulated(const UsbDeviceDescriptor& _device, const std::array& location); bool open_device() override; void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/Io/usio.cpp b/rpcs3/Emu/Io/usio.cpp index fb293443b0..7218dcc564 100644 --- a/rpcs3/Emu/Io/usio.cpp +++ b/rpcs3/Emu/Io/usio.cpp @@ -9,7 +9,8 @@ LOG_CHANNEL(usio_log); -usb_device_usio::usb_device_usio() +usb_device_usio::usb_device_usio(const std::array& location) + : usb_device_emulated(location) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{ diff --git a/rpcs3/Emu/Io/usio.h b/rpcs3/Emu/Io/usio.h index df1dbb36a8..d59f4c0047 100644 --- a/rpcs3/Emu/Io/usio.h +++ b/rpcs3/Emu/Io/usio.h @@ -7,7 +7,7 @@ class usb_device_usio : public usb_device_emulated { public: - usb_device_usio(); + usb_device_usio(const std::array& location); ~usb_device_usio(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override;