mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-11 21:45:37 +00:00
libusb: don't freeze when device vanishs
Instead of freezing, return corresponding libusb error code if the USB device got disconnected. Therefore, components using the library can continue to work otherwise. Fix genodelabs/genode#5434
This commit is contained in:
parent
76aba79e0b
commit
e113d37958
@ -17,7 +17,6 @@
|
|||||||
#include <base/allocator_avl.h>
|
#include <base/allocator_avl.h>
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
#include <base/tslab.h>
|
#include <base/tslab.h>
|
||||||
#include <base/sleep.h>
|
|
||||||
#include <usb_session/device.h>
|
#include <usb_session/device.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -36,6 +35,8 @@ static int vfs_libusb_fd { -1 };
|
|||||||
|
|
||||||
struct Usb_device
|
struct Usb_device
|
||||||
{
|
{
|
||||||
|
struct No_device {};
|
||||||
|
|
||||||
template <typename URB>
|
template <typename URB>
|
||||||
struct Urb_tpl : URB
|
struct Urb_tpl : URB
|
||||||
{
|
{
|
||||||
@ -169,10 +170,8 @@ void Usb_device::Interface::handle_events()
|
|||||||
/* complete USB request */
|
/* complete USB request */
|
||||||
[this] (Urb &urb, Usb::Tagged_packet::Return_value v)
|
[this] (Urb &urb, Usb::Tagged_packet::Return_value v)
|
||||||
{
|
{
|
||||||
if (v == Usb::Tagged_packet::NO_DEVICE) {
|
if (v == Usb::Tagged_packet::NO_DEVICE)
|
||||||
error("USB device has vanished, will freeze!");
|
throw No_device();
|
||||||
sleep_forever();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != Usb::Tagged_packet::OK)
|
if (v != Usb::Tagged_packet::OK)
|
||||||
error("transfer failed, return value ", (int)v);
|
error("transfer failed, return value ", (int)v);
|
||||||
@ -224,10 +223,8 @@ void Usb_device::handle_events()
|
|||||||
/* complete USB request */
|
/* complete USB request */
|
||||||
[this] (Urb &urb, Usb::Tagged_packet::Return_value v)
|
[this] (Urb &urb, Usb::Tagged_packet::Return_value v)
|
||||||
{
|
{
|
||||||
if (v == Usb::Tagged_packet::NO_DEVICE) {
|
if (v == Usb::Tagged_packet::NO_DEVICE)
|
||||||
error("USB device has vanished, will freeze!");
|
throw No_device();
|
||||||
sleep_forever();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v != Usb::Tagged_packet::OK)
|
if (v != Usb::Tagged_packet::OK)
|
||||||
error("control transfer failed, return value ", (int)v);
|
error("control transfer failed, return value ", (int)v);
|
||||||
@ -366,6 +363,7 @@ static int genode_get_device_descriptor(struct libusb_device *,
|
|||||||
unsigned char* buffer,
|
unsigned char* buffer,
|
||||||
int *host_endian)
|
int *host_endian)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
Usb_device::Urb urb(buffer, sizeof(libusb_device_descriptor),
|
Usb_device::Urb urb(buffer, sizeof(libusb_device_descriptor),
|
||||||
device()._device, LIBUSB_REQUEST_GET_DESCRIPTOR,
|
device()._device, LIBUSB_REQUEST_GET_DESCRIPTOR,
|
||||||
LIBUSB_ENDPOINT_IN, (LIBUSB_DT_DEVICE << 8) | 0, 0,
|
LIBUSB_ENDPOINT_IN, (LIBUSB_DT_DEVICE << 8) | 0, 0,
|
||||||
@ -373,6 +371,9 @@ static int genode_get_device_descriptor(struct libusb_device *,
|
|||||||
device()._wait_for_urb(urb);
|
device()._wait_for_urb(urb);
|
||||||
*host_endian = 0;
|
*host_endian = 0;
|
||||||
return LIBUSB_SUCCESS;
|
return LIBUSB_SUCCESS;
|
||||||
|
} catch(Usb_device::No_device&) {
|
||||||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -382,6 +383,7 @@ static int genode_get_config_descriptor(struct libusb_device *,
|
|||||||
size_t len,
|
size_t len,
|
||||||
int *host_endian)
|
int *host_endian)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
/* read minimal config descriptor */
|
/* read minimal config descriptor */
|
||||||
genode_usb_config_descriptor desc;
|
genode_usb_config_descriptor desc;
|
||||||
Usb_device::Urb cfg(&desc, sizeof(desc), device()._device,
|
Usb_device::Urb cfg(&desc, sizeof(desc), device()._device,
|
||||||
@ -398,6 +400,9 @@ static int genode_get_config_descriptor(struct libusb_device *,
|
|||||||
|
|
||||||
*host_endian = 0;
|
*host_endian = 0;
|
||||||
return desc.total_length;
|
return desc.total_length;
|
||||||
|
} catch(Usb_device::No_device&) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -466,6 +471,7 @@ static int genode_set_interface_altsetting(struct libusb_device_handle* dev_hand
|
|||||||
int interface_number,
|
int interface_number,
|
||||||
int altsetting)
|
int altsetting)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
using P = Usb::Device::Packet_descriptor;
|
using P = Usb::Device::Packet_descriptor;
|
||||||
using Rt = P::Request_type;
|
using Rt = P::Request_type;
|
||||||
|
|
||||||
@ -489,11 +495,15 @@ static int genode_set_interface_altsetting(struct libusb_device_handle* dev_hand
|
|||||||
Usb_device::Interface(device(), (uint8_t) interface_number,
|
Usb_device::Interface(device(), (uint8_t) interface_number,
|
||||||
(uint8_t) altsetting);
|
(uint8_t) altsetting);
|
||||||
return LIBUSB_SUCCESS;
|
return LIBUSB_SUCCESS;
|
||||||
|
} catch(Usb_device::No_device&) {
|
||||||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
struct libusb_transfer *transfer =
|
struct libusb_transfer *transfer =
|
||||||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||||
Usb::Interface::Packet_descriptor::Type type =
|
Usb::Interface::Packet_descriptor::Type type =
|
||||||
@ -550,6 +560,9 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
|||||||
});
|
});
|
||||||
|
|
||||||
return found ? LIBUSB_SUCCESS : LIBUSB_ERROR_NOT_FOUND;
|
return found ? LIBUSB_SUCCESS : LIBUSB_ERROR_NOT_FOUND;
|
||||||
|
} catch (Usb_device::No_device&) {
|
||||||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -565,11 +578,15 @@ static void genode_clear_transfer_priv(struct usbi_transfer * itransfer) { }
|
|||||||
static int genode_handle_events(struct libusb_context *, struct pollfd *,
|
static int genode_handle_events(struct libusb_context *, struct pollfd *,
|
||||||
POLL_NFDS_TYPE, int)
|
POLL_NFDS_TYPE, int)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
libusb_genode_backend_signaling = false;
|
libusb_genode_backend_signaling = false;
|
||||||
device().handle_events();
|
device().handle_events();
|
||||||
device()._interfaces.for_each([&] (Usb_device::Interface &iface) {
|
device()._interfaces.for_each([&] (Usb_device::Interface &iface) {
|
||||||
iface.handle_events(); });
|
iface.handle_events(); });
|
||||||
return LIBUSB_SUCCESS;
|
return LIBUSB_SUCCESS;
|
||||||
|
} catch(Usb_device::No_device&) {
|
||||||
|
return LIBUSB_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user