mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
virt/lx_emul: add usb_client.c
This registers C-API USB-client device handle (i.e., USB::Connection) as Linux 'usb_device' and probes all the initialized drivers. issue #4958
This commit is contained in:
parent
5eff895f9d
commit
3925c7ec60
13
repos/dde_linux/src/include/lx_emul/usb_client.h
Normal file
13
repos/dde_linux/src/include/lx_emul/usb_client.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <genode_c_api/usb_client.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *lx_emul_usb_client_register_device(genode_usb_client_handle_t handle, char const *label);
|
||||||
|
void lx_emul_usb_client_unregister_device(genode_usb_client_handle_t handle, void *data);
|
||||||
|
int lx_emul_usb_client_set_configuration(genode_usb_client_handle_t, void *data, unsigned long config);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
139
repos/dde_linux/src/lib/lx_emul/virt/usb_client.c
Normal file
139
repos/dde_linux/src/lib/lx_emul/virt/usb_client.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#include <linux/usb.h>
|
||||||
|
#include <linux/usb/hcd.h>
|
||||||
|
|
||||||
|
#include <lx_emul/usb_client.h>
|
||||||
|
|
||||||
|
static struct hc_driver _hc_driver = { };
|
||||||
|
|
||||||
|
struct meta_data
|
||||||
|
{
|
||||||
|
struct usb_hcd *hcd;
|
||||||
|
struct device *sysdev;
|
||||||
|
struct usb_device *udev;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void *lx_emul_usb_client_register_device(genode_usb_client_handle_t handle, char const *label)
|
||||||
|
{
|
||||||
|
struct meta_data *meta;
|
||||||
|
int err;
|
||||||
|
struct genode_usb_device_descriptor dev_descr;
|
||||||
|
struct genode_usb_config_descriptor conf_descr;
|
||||||
|
|
||||||
|
err = genode_usb_client_config_descriptor(handle, &dev_descr, &conf_descr);
|
||||||
|
if (err) {
|
||||||
|
printk("error: failed to read config descriptor\n");
|
||||||
|
return NULL;;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta = (struct meta_data *)kmalloc(sizeof(struct meta_data), GFP_KERNEL);
|
||||||
|
if (!meta) return NULL;
|
||||||
|
|
||||||
|
meta->sysdev = (struct device*)kzalloc(sizeof(struct device), GFP_KERNEL);
|
||||||
|
if (!meta->sysdev) goto sysdev;
|
||||||
|
|
||||||
|
device_initialize(meta->sysdev);
|
||||||
|
|
||||||
|
meta->hcd = (struct usb_hcd *)kzalloc(sizeof(struct usb_hcd), GFP_KERNEL);
|
||||||
|
if (!meta->hcd) goto hcd;
|
||||||
|
|
||||||
|
/* hcd->self is usb_bus */
|
||||||
|
meta->hcd->driver = &_hc_driver;
|
||||||
|
meta->hcd->self.bus_name = "usbbus";
|
||||||
|
meta->hcd->self.sysdev = meta->sysdev;
|
||||||
|
|
||||||
|
meta->udev = usb_alloc_dev(NULL, &meta->hcd->self, 0);
|
||||||
|
if (!meta->udev) {
|
||||||
|
printk("error: could not allocate udev for %s\n", label);
|
||||||
|
goto udev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* usb_alloc_dev sets parent to bus->controller if first argument is NULL */
|
||||||
|
meta->hcd->self.controller = (struct device *)handle;
|
||||||
|
|
||||||
|
memcpy(&meta->udev->descriptor, &dev_descr, sizeof(struct usb_device_descriptor));
|
||||||
|
meta->udev->devnum = dev_descr.num;
|
||||||
|
meta->udev->speed = (enum usb_device_speed)dev_descr.speed;
|
||||||
|
meta->udev->authorized = 1;
|
||||||
|
meta->udev->bus_mA = 900; /* set to maximum USB3.0 */
|
||||||
|
meta->udev->state = USB_STATE_NOTATTACHED;
|
||||||
|
|
||||||
|
dev_set_name(&meta->udev->dev, "%s", label);
|
||||||
|
|
||||||
|
err = usb_new_device(meta->udev);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
printk("error: usb_new_device failed %d\n", err);
|
||||||
|
goto new_device;
|
||||||
|
}
|
||||||
|
return meta;
|
||||||
|
|
||||||
|
new_device:
|
||||||
|
usb_put_dev(meta->udev);
|
||||||
|
udev:
|
||||||
|
kfree(meta->hcd);
|
||||||
|
hcd:
|
||||||
|
kfree(meta->sysdev);
|
||||||
|
sysdev:
|
||||||
|
kfree(meta);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lx_emul_usb_client_unregister_device(genode_usb_client_handle_t handle, void *data)
|
||||||
|
{
|
||||||
|
struct meta_data *meta = (struct meta_data *)data;
|
||||||
|
|
||||||
|
usb_disconnect(&meta->udev);
|
||||||
|
usb_put_dev(meta->udev);
|
||||||
|
kfree(meta->hcd);
|
||||||
|
kobject_put(&meta->sysdev->kobj);
|
||||||
|
kfree(meta->sysdev);
|
||||||
|
kfree(meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define for_each_claimed_interface(udev, num, intf) \
|
||||||
|
for (num = 0, intf = udev->actconfig->interface[num]; \
|
||||||
|
num < udev->actconfig->desc.bNumInterfaces; \
|
||||||
|
intf = udev->actconfig->interface[++num]) \
|
||||||
|
if (!usb_interface_claimed(intf)) continue; else
|
||||||
|
|
||||||
|
|
||||||
|
int lx_emul_usb_client_set_configuration(genode_usb_client_handle_t handle, void *data, unsigned long config)
|
||||||
|
{
|
||||||
|
struct meta_data *meta = (struct meta_data *)data;
|
||||||
|
struct usb_device *udev = meta->udev;
|
||||||
|
unsigned i = 0;
|
||||||
|
struct usb_interface *intf;
|
||||||
|
|
||||||
|
/* release claimed interfaces at session */
|
||||||
|
for_each_claimed_interface(udev, i, intf) {
|
||||||
|
genode_usb_client_release_interface(handle, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release claimed interfaces at driver, 'usb_driver_release_interface' may
|
||||||
|
* release more than one interface
|
||||||
|
*/
|
||||||
|
for_each_claimed_interface(udev, i, intf) {
|
||||||
|
usb_driver_release_interface(to_usb_driver(intf->dev.driver), intf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set unconfigured (internal reset in host driver) first */
|
||||||
|
usb_set_configuration(meta->udev, 0);
|
||||||
|
return usb_set_configuration(meta->udev, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void * hcd_buffer_alloc(struct usb_bus * bus, size_t size, gfp_t mem_flags, dma_addr_t * dma)
|
||||||
|
{
|
||||||
|
return kmalloc(size, GFP_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hcd_buffer_free(struct usb_bus * bus, size_t size, void * addr, dma_addr_t dma)
|
||||||
|
{
|
||||||
|
kfree(addr);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user