diff --git a/repos/dde_linux/src/include/lx_emul/usb_client.h b/repos/dde_linux/src/include/lx_emul/usb_client.h
new file mode 100644
index 0000000000..66c60eb5c6
--- /dev/null
+++ b/repos/dde_linux/src/include/lx_emul/usb_client.h
@@ -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
diff --git a/repos/dde_linux/src/lib/lx_emul/virt/usb_client.c b/repos/dde_linux/src/lib/lx_emul/virt/usb_client.c
new file mode 100644
index 0000000000..bb6efb3741
--- /dev/null
+++ b/repos/dde_linux/src/lib/lx_emul/virt/usb_client.c
@@ -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);
+}