mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-18 23:40:11 +00:00
DM USB: xHCI: enable Flat Mode Hub emulation support.
Flat Mode for hub emulation means DM emulates USB devices under hub but hide hub itself. Under this design the Guest OS cannot see any emulated hub. So in the perspective of Guest OS, all the emulated devices are under root hub. This patch is used to enable feature as mentioned above. And please NOTE, it is the initial version of hub flat Mode hub emulation, there are one limitation: only one physical hub is supported. If second physical hub is connected, the connect and disconnect behavior in second hub may affect the function of first emulated hub. The USB HUB device model should be the final long term solution, but it is very complex. Use flat mode HUB emulation as the short term solution first to support some USB touch devices which integrated internal HUB. Signed-off-by: Liang Yang <liang3.yang@intel.com> Reviewed-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com> Tracked-On: #1243
This commit is contained in:
@@ -95,7 +95,7 @@
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "xHCI: "
|
||||
#define XHCI_MAX_DEVS 8 /* 4 USB3 + 4 USB2 devs */
|
||||
#define XHCI_MAX_DEVS 20 /* 10 root hub + 10 external hub */
|
||||
#define XHCI_MAX_SLOTS 64 /* min allowed by Windows drivers */
|
||||
|
||||
/*
|
||||
@@ -394,6 +394,7 @@ struct pci_xhci_vdev {
|
||||
#define VPORT_ASSIGNED (1)
|
||||
#define VPORT_CONNECTED (2)
|
||||
#define VPORT_EMULATED (3)
|
||||
#define VPORT_HUB_CONNECTED (4)
|
||||
|
||||
/* helpers for get port mapping information */
|
||||
#define VPORT_NUM(state) (state & 0xFF)
|
||||
@@ -479,6 +480,27 @@ static struct pci_xhci_option_elem xhci_option_table[] = {
|
||||
{"cap", pci_xhci_parse_extcap}
|
||||
};
|
||||
|
||||
static enum usb_native_dev_type
|
||||
pci_xhci_get_dev_type(struct pci_xhci_vdev *xdev, void *dev_data)
|
||||
{
|
||||
uint16_t port, bus;
|
||||
struct usb_native_devinfo *di;
|
||||
|
||||
assert(dev_data);
|
||||
|
||||
di = dev_data;
|
||||
if (usb_get_parent_dev_type(di->priv_data, &bus, &port) == USB_HUB) {
|
||||
if (VPORT_STATE(xdev->port_map_tbl[bus][port]) ==
|
||||
VPORT_HUB_CONNECTED) {
|
||||
di->port += PORT_HUB_BASE;
|
||||
return USB_VALID_SUB_DEV;
|
||||
} else
|
||||
return USB_INVALID_SUB_DEV;
|
||||
}
|
||||
|
||||
return USB_DEV;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
||||
{
|
||||
@@ -487,6 +509,9 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
||||
int vport_start, vport_end;
|
||||
int port;
|
||||
int need_intr = 1;
|
||||
enum usb_native_dev_type type;
|
||||
int state;
|
||||
int rc;
|
||||
|
||||
xdev = hci_data;
|
||||
|
||||
@@ -501,12 +526,37 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
||||
UPRINTF(LDBG, "%04x:%04x %d-%d connecting.\r\n",
|
||||
di->vid, di->pid, di->bus, di->port);
|
||||
|
||||
if (VPORT_STATE(xdev->port_map_tbl[di->bus][di->port]) ==
|
||||
VPORT_FREE) {
|
||||
UPRINTF(LDBG, "%04x:%04x %d-%d doesn't belong to this vm, bye."
|
||||
"\r\n", di->vid, di->pid, di->bus, di->port);
|
||||
type = pci_xhci_get_dev_type(xdev, di);
|
||||
if (type == USB_DEV) {
|
||||
if (VPORT_STATE(xdev->port_map_tbl[di->bus][di->port]) ==
|
||||
VPORT_FREE) {
|
||||
UPRINTF(LDBG, "%04x:%04x %d-%d doesn't belong to this"
|
||||
" vm, bye.\r\n", di->vid, di->pid,
|
||||
di->bus, di->port);
|
||||
goto errout;
|
||||
}
|
||||
} else if (type == USB_INVALID_SUB_DEV)
|
||||
return 0;
|
||||
|
||||
state = VPORT_STATE(xdev->port_map_tbl[di->bus][di->port]);
|
||||
if (state == VPORT_CONNECTED || state == VPORT_EMULATED ||
|
||||
state == VPORT_HUB_CONNECTED) {
|
||||
UPRINTF(LFTL, "do not support multiple hubs currently, reject "
|
||||
"device %d-%d\r\n", di->bus, di->port);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
rc = usb_dev_is_hub(di->priv_data);
|
||||
if (rc == USB_HUB) {
|
||||
xdev->port_map_tbl[di->bus][di->port] =
|
||||
VPORT_NUM_STATE(VPORT_HUB_CONNECTED, 0);
|
||||
return 0;
|
||||
} else if (rc == USB_TYPE_INVALID) {
|
||||
UPRINTF(LWRN, "usb_dev_is_hub failed\r\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
UPRINTF(LDBG, "%04x:%04x %d-%d belong to this vm.\r\n", di->vid,
|
||||
di->pid, di->bus, di->port);
|
||||
|
||||
@@ -593,8 +643,6 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
|
||||
if (xdev->slots[slot] == edev)
|
||||
break;
|
||||
|
||||
assert(slot < XHCI_MAX_SLOTS);
|
||||
|
||||
status = VPORT_STATE(xdev->port_map_tbl[di.bus][di.port]);
|
||||
assert(status == VPORT_EMULATED || status == VPORT_CONNECTED);
|
||||
xdev->port_map_tbl[di.bus][di.port] = VPORT_NUM_STATE(VPORT_ASSIGNED,
|
||||
|
Reference in New Issue
Block a user