dde_linux: usb support extra data and zero config

- Vendor devices add addtional data to the config descriptor, read and
  added to the usb session
- allow '0' configuration within the usb session

issue #3822
This commit is contained in:
Sebastian Sumpf 2020-12-02 09:28:20 +01:00 committed by Norman Feske
parent 537472e9af
commit 36eeab6df2
6 changed files with 90 additions and 21 deletions

View File

@ -441,13 +441,12 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
usb_host_config *config = _device->udev->actconfig;
if (!config)
return;
for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) {
if (usb_interface_claimed(config->interface[i])) {
error("There are interfaces claimed, won't set configuration");
return;
if (config) {
for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) {
if (usb_interface_claimed(config->interface[i])) {
error("There are interfaces claimed, won't set configuration");
return;
}
}
}
@ -816,6 +815,29 @@ class Usb::Session_component : public Session_rpc_object,
interface_descr->active = true;
}
bool interface_extra(unsigned index, unsigned alt_setting,
Interface_extra *interface_data)
{
if (!_device)
throw Device_not_found();
usb_interface *iface = _device->interface(index);
if (!iface)
throw Interface_not_found();
Genode::uint8_t length = iface->altsetting[alt_setting].extralen;
if (length == 0) return false;
if (length > sizeof(Interface_extra::data))
length = sizeof(Interface_extra::data);
Genode::memcpy(interface_data->data, iface->altsetting[alt_setting].extra,
length);
interface_data->length = length;
return true;
}
void endpoint_descriptor(unsigned interface_num,
unsigned alt_setting,
unsigned endpoint_num,

View File

@ -1742,11 +1742,14 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, const cha
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
return *(const volatile u32 __force *) addr;
u32 val = *(const volatile u32 __force *) addr;
iormb();
return val;
}
static inline void __raw_writel(u32 b, volatile void __iomem *addr)
{
iowmb();
*(volatile u32 __force *) addr = b;
}

View File

@ -452,13 +452,12 @@ class Usb::Worker : public Genode::Weak_object<Usb::Worker>
{
usb_host_config *config = _device->udev->actconfig;
if (!config)
return;
for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) {
if (usb_interface_claimed(config->interface[i])) {
error("There are interfaces claimed, won't set configuration");
return;
if (config) {
for (unsigned i = 0; i < config->desc.bNumInterfaces; i++) {
if (usb_interface_claimed(config->interface[i])) {
error("There are interfaces claimed, won't set configuration");
return;
}
}
}
@ -836,6 +835,29 @@ class Usb::Session_component : public Session_rpc_object,
interface_descr->active = true;
}
bool interface_extra(unsigned index, unsigned alt_setting,
Interface_extra *interface_data)
{
if (!_device)
throw Device_not_found();
usb_interface *iface = _device->interface(index);
if (!iface)
throw Interface_not_found();
Genode::uint8_t length = iface->altsetting[alt_setting].extralen;
if (length == 0) return false;
if (length > sizeof(Interface_extra::data))
length = sizeof(Interface_extra::data);
Genode::memcpy(interface_data->data, iface->altsetting[alt_setting].extra,
length);
interface_data->length = length;
return true;
}
void endpoint_descriptor(unsigned interface_num,
unsigned alt_setting,
unsigned endpoint_num,

View File

@ -22,6 +22,7 @@ namespace Usb {
struct Interface_descriptor;
struct Endpoint_descriptor;
struct String;
struct Interface_extra;
}
namespace Usb {
@ -193,9 +194,19 @@ struct Usb::Interface_descriptor
* Genode extensions (POD only)
*/
bool active = false;
} __attribute__((packed));
/**
* Vendor specific data
*/
struct Usb::Interface_extra
{
Genode::uint8_t length;
Genode::uint8_t data[32];
};
/**
* USB hardware endpoint descriptor
*/

View File

@ -80,10 +80,16 @@ class Usb::Session_client : public Genode::Rpc_client<Session>
call<Rpc_iface_descr>(index, alt_setting, interface_descr);
}
bool interface_extra(unsigned index, unsigned alt_setting,
Interface_extra *interface_data) override
{
return call<Rpc_iface_extra>(index, alt_setting, interface_data);
}
void endpoint_descriptor(unsigned interface_num,
unsigned alt_setting,
unsigned endpoint_num,
Endpoint_descriptor *endpoint_descr) override
unsigned alt_setting,
unsigned endpoint_num,
Endpoint_descriptor *endpoint_descr) override
{
call<Rpc_ep_descr>(interface_num, alt_setting, endpoint_num, endpoint_descr);
}

View File

@ -182,6 +182,9 @@ struct Usb::Session : public Genode::Session
virtual void interface_descriptor(unsigned index, unsigned alt_setting,
Interface_descriptor *interface_descr) = 0;
virtual bool interface_extra(unsigned index, unsigned alt_setting,
Interface_extra *interface_data) = 0;
/**
* Return endpoint for interface index/alternate setting tuple
*/
@ -208,6 +211,8 @@ struct Usb::Session : public Genode::Session
GENODE_RPC(Rpc_alt_settings, unsigned, alt_settings, unsigned);
GENODE_RPC_THROW(Rpc_iface_descr, void, interface_descriptor, GENODE_TYPE_LIST(Device_not_found,
Interface_not_found), unsigned, unsigned, Interface_descriptor *);
GENODE_RPC_THROW(Rpc_iface_extra, bool, interface_extra, GENODE_TYPE_LIST(Device_not_found,
Interface_not_found), unsigned, unsigned, Interface_extra *);
GENODE_RPC_THROW(Rpc_ep_descr, void, endpoint_descriptor, GENODE_TYPE_LIST(Device_not_found,
Interface_not_found), unsigned, unsigned, unsigned, Endpoint_descriptor *);
GENODE_RPC_THROW(Rpc_claim_interface, void, claim_interface, GENODE_TYPE_LIST(Interface_not_found,
@ -215,8 +220,8 @@ struct Usb::Session : public Genode::Session
GENODE_RPC_THROW(Rpc_release_interface, void, release_interface, GENODE_TYPE_LIST(Interface_not_found),
unsigned);
GENODE_RPC_INTERFACE(Rpc_plugged, Rpc_sigh_state_change, Rpc_tx_cap, Rpc_config_descr,
Rpc_iface_descr, Rpc_ep_descr, Rpc_alt_settings, Rpc_claim_interface,
Rpc_release_interface);
Rpc_iface_descr, Rpc_iface_extra, Rpc_ep_descr, Rpc_alt_settings,
Rpc_claim_interface, Rpc_release_interface);
};
#endif /* _INCLUDE__USB_SESSION__USB_SESSION_H_ */