genode/repos/os/include/usb_session/usb_session.h
Stefan Kalkowski 7ec08af6d9 usb: session renewal & new client API
Replace the USB session API by one that provides a devices ROM only,
which contains information about all USB devices available for this client,
as well as methods to acquire and release a single device.

The acquisition of an USB device returns the capability to a device session
that includes a packet stream buffer to communicate control transfers
in between the client and the USB host controller driver. Moreover,
additional methods to acquire and release an USB interface can be used.

The acquisition of an USB interface returns the capability to an interface
session that includes a packet stream buffer to communicate either
bulk, interrupt, or isochronous transfers in between the client and the
USB host controller driver.

This commit implements the API changes in behalf of the Genode C API's
USB server and client side. Addtionally, it provides Usb::Device,
Usb::Interface, and Usb::Endpoint utilities that can be used by native
C++ clients to use the new API and hide the sophisticated packet stream API.

The adaptations necessary target the following areas:

* lx_emul layer for USB host and client side
* Linux USB host controller driver port for PC
* Linux USB client ports: usb_hid_drv and usb_net_drv, additionally
  reduce the Linux tasks used inside these drivers
* Native usb_block_drv
* black_hole component
* Port of libusb, including smartcard and usb_webcam driver depending on it
* Port of Qemu XHCI model library, including vbox5 & vbox6 depending on it
* Adapt all run-scripts and drivers_interactive recipes to work
  with the new policy rules of the USB host controller driver

Fix genodelabs/genode#5021
2024-04-12 12:57:30 +02:00

232 lines
5.5 KiB
C++

/**
* \brief USB session for USB clients (mainly device drivers)
* \author Stefan Kalkowski
* \author Sebastian Sumpf
* \date 2014-12-08
*/
/*
* Copyright (C) 2014-2024 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.
*/
#ifndef _INCLUDE__USB_SESSION__USB_SESSION_H_
#define _INCLUDE__USB_SESSION__USB_SESSION_H_
#include <base/rpc_args.h>
#include <os/packet_stream.h>
#include <packet_stream_tx/packet_stream_tx.h>
#include <rom_session/capability.h>
#include <session/session.h>
#include <usb_session/capability.h>
namespace Usb {
using namespace Genode;
struct Tagged_packet;
struct Interface_session;
struct Device_session;
class Session;
}
struct Usb::Tagged_packet : Genode::Packet_descriptor
{
/*
* At least on ARM the minimal alignment for distinct
* DMA-capable USB URBs shall meet a maximum cache-line
* size of 128 bytes
*/
enum Alignment { PACKET_ALIGNMENT = 7 };
/**
* Payload location within the packet stream
*/
struct Payload
{
off_t offset;
size_t bytes;
};
struct Tag {
unsigned long value;
} tag { ~0UL };
enum Return_value {
UNHANDLED, NO_DEVICE, INVALID, TIMEOUT, HALT, OK
} return_value { UNHANDLED };
Tagged_packet(off_t offset = 0, size_t size = 0)
: Genode::Packet_descriptor(offset, size) {}
Tagged_packet(Payload p, Tag tag)
:
Genode::Packet_descriptor(p.offset, p.bytes),
tag(tag) {}
};
struct Usb::Interface_session : Interface
{
struct Packet_descriptor : Tagged_packet
{
enum Type {
BULK, IRQ, ISOC, FLUSH
} type { FLUSH };
uint8_t index { 0 };
size_t payload_return_size { 0 };
using Tagged_packet::Tagged_packet;
};
enum { TX_QUEUE_SIZE = 64 };
using Tx_policy = Packet_stream_policy<Packet_descriptor,
TX_QUEUE_SIZE, TX_QUEUE_SIZE, char>;
using Tx = Packet_stream_tx::Channel<Tx_policy>;
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, tx_cap);
GENODE_RPC_INTERFACE(Rpc_tx_cap);
};
struct Usb::Device_session : Interface
{
struct Packet_descriptor : Tagged_packet
{
enum Request : uint8_t {
GET_STATUS = 0x00,
CLEAR_FEATURE = 0x01,
SET_FEATURE = 0x03,
SET_ADDRESS = 0x05,
GET_DESCRIPTOR = 0x06,
SET_DESCRIPTOR = 0x07,
GET_CONFIGURATION = 0x08,
SET_CONFIGURATION = 0x09,
GET_INTERFACE = 0x0a,
SET_INTERFACE = 0x0b,
SYNCH_FRAME = 0x0c,
SET_SEL = 0x30,
SET_ISOCH_DELAY = 0x31,
};
uint8_t request { GET_STATUS };
enum Recipient { DEVICE, IFACE, ENDP, OTHER };
enum Type { STANDARD, CLASS, VENDOR, RESERVED };
enum Direction { OUT, IN };
struct Request_type : Register<8>
{
struct R : Bitfield<0, 5> { };
struct T : Bitfield<5, 2> { };
struct D : Bitfield<7, 1> { };
static access_t value(Recipient r, Type t, Direction d)
{
access_t ret = 0;
R::set(ret, r);
T::set(ret, t);
D::set(ret, d);
return ret;
}
};
Request_type::access_t request_type { 0 };
uint16_t value { 0 };
uint16_t index { 0 };
size_t payload_return_size { 0 };
size_t timeout { 0 };
using Tagged_packet::Tagged_packet;
};
enum { TX_QUEUE_SIZE = 8, TX_BUFFER_SIZE = 4096 };
using Tx_policy = Packet_stream_policy<Packet_descriptor,
TX_QUEUE_SIZE, TX_QUEUE_SIZE, char>;
using Tx = Packet_stream_tx::Channel<Tx_policy>;
/*********************
** RPC declaration **
*********************/
GENODE_RPC_THROW(Rpc_acquire_interface, Interface_capability,
acquire_interface,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
uint8_t, size_t);
GENODE_RPC(Rpc_release_interface, void, release_interface,
Interface_capability);
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, tx_cap);
GENODE_RPC_INTERFACE(Rpc_acquire_interface, Rpc_release_interface,
Rpc_tx_cap);
};
struct Usb::Session : public Genode::Session
{
/**
* \noapi
*/
static const char *service_name() { return "Usb"; }
static constexpr unsigned CAP_QUOTA = 8;
static constexpr unsigned RAM_QUOTA = 512 * 1024;
virtual ~Session() {}
using Device_name = String<64>;
/**
* Request ROM session containing information about available devices.
*
* \return capability to ROM dataspace
*/
virtual Rom_session_capability devices_rom() = 0;
/**
* Acquire device known by unique 'name'
*/
virtual Device_capability acquire_device(Device_name const &name) = 0;
/**
* Acquire the first resp. single device of this session
*/
virtual Device_capability acquire_single_device() = 0;
/**
* Release all resources regarding the given 'device' session
*/
virtual void release_device(Device_capability device) = 0;
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_devices_rom, Rom_session_capability, devices_rom);
GENODE_RPC_THROW(Rpc_acquire_device, Device_capability, acquire_device,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps),
Device_name const &);
GENODE_RPC_THROW(Rpc_acquire_single_device, Device_capability,
acquire_single_device,
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps));
GENODE_RPC(Rpc_release_device, void, release_device, Device_capability);
GENODE_RPC_INTERFACE(Rpc_devices_rom, Rpc_acquire_device,
Rpc_acquire_single_device, Rpc_release_device);
};
#endif /* _INCLUDE__USB_SESSION__USB_SESSION_H_ */