mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
cf0d007fd4
commit
d4d875f2e6
7
repos/libports/lib/mk/vfs_libusb.mk
Normal file
7
repos/libports/lib/mk/vfs_libusb.mk
Normal file
@ -0,0 +1,7 @@
|
||||
SRC_CC = vfs_libusb.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/vfs/libusb
|
||||
|
||||
SHARED_LIB = yes
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
@ -11,5 +11,5 @@ _/src/rom_filter
|
||||
_/src/report_rom
|
||||
_/src/stdcxx
|
||||
_/src/vfs
|
||||
_/src/vfs_libusb
|
||||
_/src/vfs_pipe
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
<rom label="init"/>
|
||||
<rom label="jpeg.lib.so"/>
|
||||
<rom label="vfs.lib.so"/>
|
||||
<rom label="vfs_libusb.lib.so"/>
|
||||
<rom label="vfs_pipe.lib.so"/>
|
||||
<rom label="libc.lib.so"/>
|
||||
<rom label="libm.lib.so"/>
|
||||
|
@ -75,7 +75,11 @@
|
||||
<resource name="RAM" quantum="48M"/>
|
||||
<config ld_verbose="no" enabled="yes" width="640" height="480" format="yuv" fps="15">
|
||||
<vfs>
|
||||
<dir name="dev"> <log/> <inline name="rtc">2018-01-01 00:01</inline> </dir>
|
||||
<dir name="dev">
|
||||
<log/>
|
||||
<inline name="rtc">2018-01-01 00:01</inline>
|
||||
<libusb/>
|
||||
</dir>
|
||||
<dir name="pipe"> <pipe/> </dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc" pipe="/pipe"/>
|
||||
|
9
repos/libports/recipes/src/vfs_libusb/content.mk
Normal file
9
repos/libports/recipes/src/vfs_libusb/content.mk
Normal file
@ -0,0 +1,9 @@
|
||||
MIRROR_FROM_REP_DIR := lib/mk/vfs_libusb.mk src/lib/vfs/libusb
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR) LICENSE
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
||||
|
||||
LICENSE:
|
||||
cp $(GENODE_DIR)/LICENSE $@
|
1
repos/libports/recipes/src/vfs_libusb/hash
Normal file
1
repos/libports/recipes/src/vfs_libusb/hash
Normal file
@ -0,0 +1 @@
|
||||
2022-02-01 a4dec9e3717d7b06e20b057905b2c5e8c0608d93
|
5
repos/libports/recipes/src/vfs_libusb/used_apis
Normal file
5
repos/libports/recipes/src/vfs_libusb/used_apis
Normal file
@ -0,0 +1,5 @@
|
||||
base
|
||||
os
|
||||
so
|
||||
usb_session
|
||||
vfs
|
@ -26,6 +26,7 @@ set build_components {
|
||||
core init timer
|
||||
drivers/usb_host
|
||||
test/smartcard
|
||||
lib/vfs/libusb
|
||||
lib/vfs/pipe
|
||||
}
|
||||
|
||||
@ -91,7 +92,11 @@ append config {
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="dev"> <log/> <inline name="rtc">2018-01-01 00:01</inline> </dir>
|
||||
<dir name="dev">
|
||||
<log/>
|
||||
<inline name="rtc">2018-01-01 00:01</inline>
|
||||
<libusb/>
|
||||
</dir>
|
||||
<dir name="pipe"> <pipe/> </dir>
|
||||
<dir name="ifd-ccid.bundle">
|
||||
<dir name="Contents">
|
||||
@ -116,7 +121,7 @@ set boot_modules {
|
||||
core init timer test-smartcard
|
||||
ld.lib.so pcsc-lite.lib.so ccid.lib.so libusb.lib.so
|
||||
libc.lib.so vfs.lib.so libm.lib.so posix.lib.so
|
||||
Info.plist vfs_pipe.lib.so
|
||||
Info.plist vfs_libusb.lib.so vfs_pipe.lib.so
|
||||
}
|
||||
|
||||
lappend boot_modules [usb_host_drv_binary]
|
||||
|
@ -11,3 +11,9 @@ the application using libusb:
|
||||
</config>
|
||||
|
||||
See also the README file of the USB driver for additional policy attributes.
|
||||
|
||||
The Genode USB connection object resides in a VFS plugin named 'vfs_libusb',
|
||||
which is necessary to handle the 'ack_avail' signal in the libc kernel context.
|
||||
So, an application using libusb needs to have a '<dir name="dev"><libusb/></dev>'
|
||||
node in its VFS configuration and the 'vfs_libusb.lib.so' file loadable at
|
||||
runtime.
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <usb/usb.h>
|
||||
#include <usb_session/connection.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <libc/allocator.h>
|
||||
#include <libc-plugin/plugin.h>
|
||||
@ -36,66 +37,9 @@ static Genode::Env &genode_env()
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
struct Usb_ep
|
||||
{
|
||||
Genode::Entrypoint _ep;
|
||||
pthread_t _pthread;
|
||||
|
||||
void _handle_pthread_registration()
|
||||
{
|
||||
Genode::Thread *myself = Genode::Thread::myself();
|
||||
if (!myself || Libc::pthread_create_from_thread(&_pthread, *myself, &myself)) {
|
||||
Genode::error("cannot register thread for pthread");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Genode::Io_signal_handler<Usb_ep> _pthread_reg_sigh {
|
||||
_ep, *this, &Usb_ep::_handle_pthread_registration };
|
||||
|
||||
Usb_ep(Genode::Env &env, size_t stack_size, char const *name,
|
||||
Genode::Affinity::Location location)
|
||||
: _ep { env, stack_size, name, location }
|
||||
{
|
||||
Genode::Signal_transmitter(_pthread_reg_sigh).submit();
|
||||
}
|
||||
|
||||
Genode::Entrypoint &ep() { return _ep; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Entrypoint for handling 'ack avail' signals from the USB driver.
|
||||
*
|
||||
* The entrypoint is needed because the main thread of an application
|
||||
* using libusb might be blocking on a pthread locking function, which
|
||||
* currently do not dispatch signals while blocking.
|
||||
*/
|
||||
static Genode::Entrypoint &ep()
|
||||
{
|
||||
static Usb_ep instance(genode_env(),
|
||||
2*1024*sizeof(Genode::addr_t),
|
||||
"usb_ack_ep",
|
||||
Genode::Affinity::Location());
|
||||
return instance.ep();
|
||||
}
|
||||
|
||||
|
||||
static Libc::Allocator libc_alloc { };
|
||||
|
||||
|
||||
/*
|
||||
* Prevent modification of packet allocator
|
||||
* by multiple threads.
|
||||
*/
|
||||
static Genode::Mutex &usb_packet_allocator_mutex()
|
||||
{
|
||||
static Genode::Mutex instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
struct Completion : Usb::Completion
|
||||
{
|
||||
struct usbi_transfer *itransfer;
|
||||
@ -111,36 +55,95 @@ struct Usb_device
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Allocator_avl _alloc { &libc_alloc };
|
||||
|
||||
Genode::Io_signal_handler<Usb_device> _state_changed_handler {
|
||||
genode_env().ep(), *this, &Usb_device::_handle_state_changed };
|
||||
|
||||
unsigned _open { 0 };
|
||||
|
||||
void _handle_state_changed()
|
||||
public:
|
||||
|
||||
Usb::Connection *usb_connection;
|
||||
|
||||
Usb::Device_descriptor device_descriptor;
|
||||
Usb::Config_descriptor config_descriptor;
|
||||
char *raw_config_descriptor = nullptr;
|
||||
|
||||
Usb_device(Usb::Connection *usb)
|
||||
: usb_connection(usb)
|
||||
{
|
||||
/*
|
||||
* The handler is installed only to receive state-change signals
|
||||
* from the USB connection using the 'Usb_device' constructor.
|
||||
*/
|
||||
Genode::log("libusb: waiting until device is plugged...");
|
||||
while (!usb_connection->plugged())
|
||||
genode_env().ep().wait_and_dispatch_one_io_signal();
|
||||
Genode::log("libusb: device is plugged");
|
||||
|
||||
usb_connection->config_descriptor(&device_descriptor, &config_descriptor);
|
||||
|
||||
raw_config_descriptor = (char*)malloc(config_descriptor.total_length);
|
||||
|
||||
Usb::Packet_descriptor p =
|
||||
usb_connection->source()->alloc_packet(config_descriptor.total_length);
|
||||
|
||||
p.type = Usb::Packet_descriptor::CTRL;
|
||||
p.control.request = LIBUSB_REQUEST_GET_DESCRIPTOR;
|
||||
p.control.request_type = LIBUSB_ENDPOINT_IN;
|
||||
p.control.value = (LIBUSB_DT_CONFIG << 8) | 0;
|
||||
p.control.index = 0;
|
||||
|
||||
usb_connection->source()->submit_packet(p);
|
||||
|
||||
while (!usb_connection->source()->ack_avail())
|
||||
genode_env().ep().wait_and_dispatch_one_io_signal();
|
||||
|
||||
p = usb_connection->source()->get_acked_packet();
|
||||
|
||||
if (!p.succeded)
|
||||
Genode::error(__PRETTY_FUNCTION__,
|
||||
": could not read raw configuration descriptor");
|
||||
|
||||
if (p.control.actual_size != config_descriptor.total_length)
|
||||
Genode::error(__PRETTY_FUNCTION__,
|
||||
": received configuration descriptor of unexpected size");
|
||||
|
||||
char *packet_content = usb_connection->source()->packet_content(p);
|
||||
Genode::memcpy(raw_config_descriptor, packet_content,
|
||||
config_descriptor.total_length);
|
||||
|
||||
usb_connection->source()->release_packet(p);
|
||||
}
|
||||
|
||||
Genode::Io_signal_handler<Usb_device> _ack_avail_handler {
|
||||
ep(), *this, &Usb_device::_handle_ack_avail };
|
||||
~Usb_device()
|
||||
{
|
||||
free(raw_config_descriptor);
|
||||
}
|
||||
|
||||
void _handle_ack_avail()
|
||||
bool altsetting(int number, int alt_setting)
|
||||
{
|
||||
if (!usb_connection->source()->ready_to_submit())
|
||||
return false;
|
||||
|
||||
Usb::Packet_descriptor p =
|
||||
usb_connection->source()->alloc_packet(0);
|
||||
|
||||
p.type = Usb::Packet_descriptor::ALT_SETTING;
|
||||
p.interface.number = number;
|
||||
p.interface.alt_setting = alt_setting;
|
||||
|
||||
usb_connection->source()->submit_packet(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close() { _open--; }
|
||||
void open() { _open++; }
|
||||
|
||||
void handle_events()
|
||||
{
|
||||
struct libusb_context *ctx = nullptr;
|
||||
|
||||
while (usb_connection.source()->ack_avail()) {
|
||||
while (usb_connection->source()->ack_avail()) {
|
||||
|
||||
Usb::Packet_descriptor p =
|
||||
usb_connection.source()->get_acked_packet();
|
||||
usb_connection->source()->get_acked_packet();
|
||||
|
||||
if (p.type == Usb::Packet_descriptor::ALT_SETTING) {
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
usb_connection.source()->release_packet(p);
|
||||
usb_connection->source()->release_packet(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -153,8 +156,7 @@ struct Usb_device
|
||||
destroy(libc_alloc, completion);
|
||||
|
||||
if (_open == 0) {
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
usb_connection.source()->release_packet(p);
|
||||
usb_connection->source()->release_packet(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -162,15 +164,12 @@ struct Usb_device
|
||||
if (!p.succeded)
|
||||
Genode::error("USB transfer failed: ", (unsigned)p.type);
|
||||
itransfer->transferred = 0;
|
||||
{
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
usb_connection.source()->release_packet(p);
|
||||
}
|
||||
usb_connection->source()->release_packet(p);
|
||||
usbi_signal_transfer_completion(itransfer);
|
||||
continue;
|
||||
}
|
||||
|
||||
char *packet_content = usb_connection.source()->packet_content(p);
|
||||
char *packet_content = usb_connection->source()->packet_content(p);
|
||||
|
||||
struct libusb_transfer *transfer =
|
||||
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
||||
@ -239,15 +238,11 @@ struct Usb_device
|
||||
default:
|
||||
Genode::error(__PRETTY_FUNCTION__,
|
||||
": unsupported transfer type");
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
usb_connection.source()->release_packet(p);
|
||||
usb_connection->source()->release_packet(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
usb_connection.source()->release_packet(p);
|
||||
}
|
||||
usb_connection->source()->release_packet(p);
|
||||
|
||||
usbi_signal_transfer_completion(itransfer);
|
||||
}
|
||||
@ -255,100 +250,38 @@ struct Usb_device
|
||||
if (ctx != nullptr)
|
||||
usbi_signal_event(ctx);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Usb::Connection usb_connection { genode_env(),
|
||||
&_alloc,
|
||||
"usb_device",
|
||||
1024*1024,
|
||||
_state_changed_handler };
|
||||
|
||||
Usb::Device_descriptor device_descriptor;
|
||||
Usb::Config_descriptor config_descriptor;
|
||||
char *raw_config_descriptor = nullptr;
|
||||
|
||||
Usb_device()
|
||||
{
|
||||
Genode::log("libusb: waiting until device is plugged...");
|
||||
while (!usb_connection.plugged())
|
||||
genode_env().ep().wait_and_dispatch_one_io_signal();
|
||||
Genode::log("libusb: device is plugged");
|
||||
|
||||
usb_connection.config_descriptor(&device_descriptor, &config_descriptor);
|
||||
|
||||
raw_config_descriptor = (char*)malloc(config_descriptor.total_length);
|
||||
|
||||
Usb::Packet_descriptor p =
|
||||
usb_connection.source()->alloc_packet(config_descriptor.total_length);
|
||||
|
||||
p.type = Usb::Packet_descriptor::CTRL;
|
||||
p.control.request = LIBUSB_REQUEST_GET_DESCRIPTOR;
|
||||
p.control.request_type = LIBUSB_ENDPOINT_IN;
|
||||
p.control.value = (LIBUSB_DT_CONFIG << 8) | 0;
|
||||
p.control.index = 0;
|
||||
|
||||
usb_connection.source()->submit_packet(p);
|
||||
|
||||
while (!usb_connection.source()->ack_avail())
|
||||
genode_env().ep().wait_and_dispatch_one_io_signal();
|
||||
|
||||
p = usb_connection.source()->get_acked_packet();
|
||||
|
||||
if (!p.succeded)
|
||||
Genode::error(__PRETTY_FUNCTION__,
|
||||
": could not read raw configuration descriptor");
|
||||
|
||||
if (p.control.actual_size != config_descriptor.total_length)
|
||||
Genode::error(__PRETTY_FUNCTION__,
|
||||
": received configuration descriptor of unexpected size");
|
||||
|
||||
char *packet_content = usb_connection.source()->packet_content(p);
|
||||
Genode::memcpy(raw_config_descriptor, packet_content,
|
||||
config_descriptor.total_length);
|
||||
|
||||
usb_connection.source()->release_packet(p);
|
||||
|
||||
usb_connection.tx_channel()->sigh_ack_avail(_ack_avail_handler);
|
||||
}
|
||||
|
||||
~Usb_device()
|
||||
{
|
||||
free(raw_config_descriptor);
|
||||
}
|
||||
|
||||
bool altsetting(int number, int alt_setting)
|
||||
{
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
|
||||
if (!usb_connection.source()->ready_to_submit())
|
||||
return false;
|
||||
|
||||
Usb::Packet_descriptor p =
|
||||
usb_connection.source()->alloc_packet(0);
|
||||
|
||||
p.type = Usb::Packet_descriptor::ALT_SETTING;
|
||||
p.interface.number = number;
|
||||
p.interface.alt_setting = alt_setting;
|
||||
|
||||
usb_connection.source()->submit_packet(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close() { _open--; }
|
||||
void open() { _open++; }
|
||||
};
|
||||
|
||||
static Usb_device *device_instance;
|
||||
|
||||
static int vfs_libusb_fd { -1 };
|
||||
static Usb::Connection *usb_connection { nullptr };
|
||||
static Usb_device *device_instance { nullptr };
|
||||
|
||||
|
||||
/*
|
||||
* This function is called by the VFS plugin on 'open()'
|
||||
* to pass a pointer to the USB connection.
|
||||
*/
|
||||
void libusb_genode_usb_connection(Usb::Connection *usb)
|
||||
{
|
||||
usb_connection = usb;
|
||||
}
|
||||
|
||||
|
||||
static int genode_init(struct libusb_context* ctx)
|
||||
{
|
||||
if (!device_instance) {
|
||||
device_instance = new (libc_alloc) Usb_device;
|
||||
vfs_libusb_fd = open("/dev/libusb", O_RDONLY);
|
||||
if (vfs_libusb_fd == -1) {
|
||||
Genode::error("could not open /dev/libusb");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
device_instance = new (libc_alloc) Usb_device(usb_connection);
|
||||
} else {
|
||||
Genode::error("tried to init genode usb context twice");
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -358,6 +291,9 @@ static void genode_exit(void)
|
||||
if (device_instance) {
|
||||
destroy(libc_alloc, device_instance);
|
||||
device_instance = nullptr;
|
||||
close(vfs_libusb_fd);
|
||||
usb_connection = nullptr;
|
||||
vfs_libusb_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +372,8 @@ static int genode_open(struct libusb_device_handle *dev_handle)
|
||||
if (device_instance)
|
||||
device_instance->open();
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
return usbi_add_pollfd(HANDLE_CTX(dev_handle), vfs_libusb_fd,
|
||||
POLLIN);
|
||||
}
|
||||
|
||||
|
||||
@ -444,6 +381,8 @@ static void genode_close(struct libusb_device_handle *dev_handle)
|
||||
{
|
||||
if (device_instance)
|
||||
device_instance->close();
|
||||
|
||||
usbi_remove_pollfd(HANDLE_CTX(dev_handle), vfs_libusb_fd);
|
||||
}
|
||||
|
||||
|
||||
@ -511,7 +450,7 @@ static int genode_claim_interface(struct libusb_device_handle *dev_handle,
|
||||
Usb_device *usb_device = *(Usb_device**)dev_handle->dev->os_priv;
|
||||
|
||||
try {
|
||||
usb_device->usb_connection.claim_interface(interface_number);
|
||||
usb_device->usb_connection->claim_interface(interface_number);
|
||||
} catch (Usb::Session::Interface_not_found) {
|
||||
Genode::error(__PRETTY_FUNCTION__, ": interface not found");
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
@ -533,7 +472,7 @@ static int genode_release_interface(struct libusb_device_handle *dev_handle,
|
||||
Usb_device *usb_device = *(Usb_device**)dev_handle->dev->os_priv;
|
||||
|
||||
try {
|
||||
usb_device->usb_connection.release_interface(interface_number);
|
||||
usb_device->usb_connection->release_interface(interface_number);
|
||||
} catch (Usb::Session::Interface_not_found) {
|
||||
Genode::error(__PRETTY_FUNCTION__, ": interface not found");
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
@ -564,7 +503,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
|
||||
Usb_device *usb_device = *(Usb_device**)transfer->dev_handle->dev->os_priv;
|
||||
|
||||
if (!usb_device->usb_connection.source()->ready_to_submit())
|
||||
if (!usb_device->usb_connection->source()->ready_to_submit())
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
|
||||
switch (transfer->type) {
|
||||
@ -577,8 +516,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
Usb::Packet_descriptor p;
|
||||
|
||||
try {
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
p = usb_device->usb_connection.source()->alloc_packet(setup->wLength);
|
||||
p = usb_device->usb_connection->source()->alloc_packet(setup->wLength);
|
||||
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
}
|
||||
@ -596,14 +534,14 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
LIBUSB_ENDPOINT_OUT) {
|
||||
|
||||
char *packet_content =
|
||||
usb_device->usb_connection.source()->packet_content(p);
|
||||
usb_device->usb_connection->source()->packet_content(p);
|
||||
|
||||
Genode::memcpy(packet_content,
|
||||
transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE,
|
||||
setup->wLength);
|
||||
}
|
||||
|
||||
usb_device->usb_connection.source()->submit_packet(p);
|
||||
usb_device->usb_connection->source()->submit_packet(p);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
@ -622,8 +560,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
Usb::Packet_descriptor p;
|
||||
|
||||
try {
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
p = usb_device->usb_connection.source()->alloc_packet(transfer->length);
|
||||
p = usb_device->usb_connection->source()->alloc_packet(transfer->length);
|
||||
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
}
|
||||
@ -640,12 +577,12 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
|
||||
if (IS_XFEROUT(transfer)) {
|
||||
char *packet_content =
|
||||
usb_device->usb_connection.source()->packet_content(p);
|
||||
usb_device->usb_connection->source()->packet_content(p);
|
||||
Genode::memcpy(packet_content, transfer->buffer,
|
||||
transfer->length);
|
||||
}
|
||||
|
||||
usb_device->usb_connection.source()->submit_packet(p);
|
||||
usb_device->usb_connection->source()->submit_packet(p);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
@ -659,8 +596,7 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
|
||||
Usb::Packet_descriptor p;
|
||||
try {
|
||||
Genode::Mutex::Guard guard(usb_packet_allocator_mutex());
|
||||
p = usb_device->usb_connection.source()->alloc_packet(total_length);
|
||||
p = usb_device->usb_connection->source()->alloc_packet(total_length);
|
||||
} catch (Usb::Session::Tx::Source::Packet_alloc_failed) {
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
}
|
||||
@ -679,12 +615,12 @@ static int genode_submit_transfer(struct usbi_transfer * itransfer)
|
||||
|
||||
if (IS_XFEROUT(transfer)) {
|
||||
char *packet_content =
|
||||
usb_device->usb_connection.source()->packet_content(p);
|
||||
usb_device->usb_connection->source()->packet_content(p);
|
||||
Genode::memcpy(packet_content, transfer->buffer,
|
||||
transfer->length);
|
||||
}
|
||||
|
||||
usb_device->usb_connection.source()->submit_packet(p);
|
||||
usb_device->usb_connection->source()->submit_packet(p);
|
||||
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
@ -706,6 +642,19 @@ static int genode_cancel_transfer(struct usbi_transfer * itransfer)
|
||||
static void genode_clear_transfer_priv(struct usbi_transfer * itransfer) { }
|
||||
|
||||
|
||||
static int genode_handle_events(struct libusb_context *,
|
||||
struct pollfd *,
|
||||
POLL_NFDS_TYPE, int)
|
||||
{
|
||||
if (device_instance) {
|
||||
device_instance->handle_events();
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
return LIBUSB_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
|
||||
static int genode_handle_transfer_completion(struct usbi_transfer * itransfer)
|
||||
{
|
||||
enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
|
||||
@ -768,7 +717,7 @@ const struct usbi_os_backend genode_usb_raw_backend = {
|
||||
/*.cancel_transfer =*/ genode_cancel_transfer,
|
||||
/*.clear_transfer_priv =*/ genode_clear_transfer_priv,
|
||||
|
||||
/*.handle_events =*/ NULL,
|
||||
/*.handle_events =*/ genode_handle_events,
|
||||
/*.handle_transfer_completion =*/ genode_handle_transfer_completion,
|
||||
|
||||
/*.clock_gettime =*/ genode_clock_gettime,
|
||||
@ -808,3 +757,4 @@ void __attribute__((constructor)) init_libc_libusb(void)
|
||||
{
|
||||
static Plugin plugin;
|
||||
}
|
||||
|
||||
|
4
repos/libports/src/lib/vfs/libusb/target.mk
Normal file
4
repos/libports/src/lib/vfs/libusb/target.mk
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = dummy-vfs_libusb
|
||||
LIBS = vfs_libusb
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
144
repos/libports/src/lib/vfs/libusb/vfs_libusb.cc
Normal file
144
repos/libports/src/lib/vfs/libusb/vfs_libusb.cc
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* \brief libusb file system
|
||||
* \author Christian Prochaska
|
||||
* \date 2022-01-31
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <usb_session/connection.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <vfs/file_system_factory.h>
|
||||
#include <vfs/single_file_system.h>
|
||||
|
||||
|
||||
/*
|
||||
* This function is implemented in the Genode backend
|
||||
* of libusb.
|
||||
*/
|
||||
extern void libusb_genode_usb_connection(Usb::Connection *);
|
||||
|
||||
class Libusb_file_system : public Vfs::Single_file_system
|
||||
{
|
||||
private:
|
||||
|
||||
Vfs::Env &_env;
|
||||
|
||||
class Libusb_vfs_handle : public Single_vfs_handle
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Allocator_avl _alloc_avl;
|
||||
Usb::Connection _usb_connection;
|
||||
|
||||
Genode::Io_signal_handler<Libusb_vfs_handle> _state_changed_handler {
|
||||
_env.ep(), *this, &Libusb_vfs_handle::_handle_state_changed };
|
||||
|
||||
void _handle_state_changed()
|
||||
{
|
||||
/*
|
||||
* The handler is installed only to receive state-change
|
||||
* signals from the USB connection using the 'Usb_device'
|
||||
* constructor.
|
||||
*/
|
||||
}
|
||||
|
||||
Genode::Io_signal_handler<Libusb_vfs_handle> _ack_avail_handler {
|
||||
_env.ep(), *this, &Libusb_vfs_handle::_handle_ack_avail };
|
||||
|
||||
void _handle_ack_avail()
|
||||
{
|
||||
io_progress_response();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Libusb_vfs_handle(Directory_service &ds,
|
||||
File_io_service &fs,
|
||||
Genode::Allocator &alloc,
|
||||
Genode::Env &env)
|
||||
: Single_vfs_handle(ds, fs, alloc, 0),
|
||||
_env(env), _alloc_avl(&alloc),
|
||||
_usb_connection(_env, &_alloc_avl,
|
||||
"usb_device",
|
||||
1024*1024,
|
||||
_state_changed_handler)
|
||||
{
|
||||
_usb_connection.tx_channel()->sigh_ack_avail(_ack_avail_handler);
|
||||
libusb_genode_usb_connection(&_usb_connection);
|
||||
}
|
||||
|
||||
bool read_ready() override
|
||||
{
|
||||
return _usb_connection.source()->ack_avail();
|
||||
}
|
||||
|
||||
Read_result read(char *dst, Vfs::file_size count,
|
||||
Vfs::file_size &out_count) override
|
||||
{
|
||||
return READ_ERR_IO;
|
||||
}
|
||||
|
||||
Write_result write(char const *src, Vfs::file_size count,
|
||||
Vfs::file_size &out_count) override
|
||||
{
|
||||
return WRITE_ERR_IO;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Libusb_file_system(Vfs::Env &env,
|
||||
Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(Vfs::Node_type::CONTINUOUS_FILE, name(),
|
||||
Vfs::Node_rwx::ro(), config),
|
||||
_env(env) { }
|
||||
|
||||
~Libusb_file_system() { }
|
||||
|
||||
static char const *name() { return "libusb"; }
|
||||
char const *type() override { return "libusb"; }
|
||||
|
||||
/*********************************
|
||||
** Directory service interface **
|
||||
*********************************/
|
||||
|
||||
Open_result open(char const *path, unsigned,
|
||||
Vfs::Vfs_handle **out_handle,
|
||||
Genode::Allocator &alloc) override
|
||||
{
|
||||
if (!_single_file(path))
|
||||
return OPEN_ERR_UNACCESSIBLE;
|
||||
|
||||
*out_handle = new (alloc)
|
||||
Libusb_vfs_handle(*this, *this, alloc, _env.env());
|
||||
return OPEN_OK;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct Libusb_factory : Vfs::File_system_factory
|
||||
{
|
||||
Vfs::File_system *create(Vfs::Env &env, Genode::Xml_node node) override
|
||||
{
|
||||
return new (env.alloc()) Libusb_file_system(env, node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern "C" Vfs::File_system_factory *vfs_file_system_factory(void)
|
||||
{
|
||||
static Libusb_factory factory;
|
||||
return &factory;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user