mirror of https://github.com/xqemu/xqemu.git
Merge remote-tracking branch 'kraxel/usb.75' into staging
* kraxel/usb.75: (32 commits) uhci: stop using portio lists usbredir: Add support for buffered bulk input (v2) exynos4210: Add EHCI support usb/ehci: Add SysBus EHCI device for Exynos4210 usb/ehci: Move capsbase and opregbase into SysBus EHCI class usb/ehci: Clean up SysBus and PCI EHCI split xhci: call set-address with dummy usbpacket usb-redir: Add debugging to bufpq save / restore usbredir: Add usbredir_init_endpoints() helper usbredir: Verify we have 32 bits bulk length cap when redirecting to xhci usbredir: Add ep_stopped USBDevice method usbredir: Add USBEP2I and I2USBEP helper macros usbredir: Add an usbredir_stop_ep helper function usb: Add an usb_device_ep_stopped USBDevice method usb: Fix usb_ep_find_packet_by_id hid: Change idle handling to use a timer uhci: Maximize how many frames we catch up when behind uhci: Limit amount of frames processed in one go uhci: Add a QH_VALID define uhci: Fix pending interrupts getting lost on migration ... Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
560c30b1db
|
@ -2851,7 +2851,7 @@ fi
|
|||
|
||||
# check for usbredirparser for usb network redirection support
|
||||
if test "$usb_redir" != "no" ; then
|
||||
if $pkg_config --atleast-version=0.5.3 libusbredirparser-0.5 >/dev/null 2>&1 ; then
|
||||
if $pkg_config --atleast-version=0.6 libusbredirparser-0.5 >/dev/null 2>&1 ; then
|
||||
usb_redir="yes"
|
||||
usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null)
|
||||
usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "arm-misc.h"
|
||||
#include "loader.h"
|
||||
#include "exynos4210.h"
|
||||
#include "usb/hcd-ehci.h"
|
||||
|
||||
#define EXYNOS4210_CHIPID_ADDR 0x10000000
|
||||
|
||||
|
@ -72,6 +73,9 @@
|
|||
/* Display controllers (FIMD) */
|
||||
#define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000
|
||||
|
||||
/* EHCI */
|
||||
#define EXYNOS4210_EHCI_BASE_ADDR 0x12580000
|
||||
|
||||
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
|
||||
0x09, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
@ -338,5 +342,8 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
|
|||
s->irq_table[exynos4210_get_irq(11, 2)],
|
||||
NULL);
|
||||
|
||||
sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR,
|
||||
s->irq_table[exynos4210_get_irq(28, 3)]);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
|
|||
EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
|
||||
EXT_GIC_ID_I2C7 },
|
||||
/* int combiner group 28 */
|
||||
{ EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 },
|
||||
{ EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
|
||||
/* int combiner group 29 */
|
||||
{ EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
|
||||
EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
|
||||
|
|
43
hw/hid.c
43
hw/hid.c
|
@ -71,12 +71,38 @@ static const uint8_t hid_usage_keys[0x100] = {
|
|||
|
||||
bool hid_has_events(HIDState *hs)
|
||||
{
|
||||
return hs->n > 0;
|
||||
return hs->n > 0 || hs->idle_pending;
|
||||
}
|
||||
|
||||
void hid_set_next_idle(HIDState *hs, int64_t curtime)
|
||||
static void hid_idle_timer(void *opaque)
|
||||
{
|
||||
hs->next_idle_clock = curtime + (get_ticks_per_sec() * hs->idle * 4) / 1000;
|
||||
HIDState *hs = opaque;
|
||||
|
||||
hs->idle_pending = true;
|
||||
hs->event(hs);
|
||||
}
|
||||
|
||||
static void hid_del_idle_timer(HIDState *hs)
|
||||
{
|
||||
if (hs->idle_timer) {
|
||||
qemu_del_timer(hs->idle_timer);
|
||||
qemu_free_timer(hs->idle_timer);
|
||||
hs->idle_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void hid_set_next_idle(HIDState *hs)
|
||||
{
|
||||
if (hs->idle) {
|
||||
uint64_t expire_time = qemu_get_clock_ns(vm_clock) +
|
||||
get_ticks_per_sec() * hs->idle * 4 / 1000;
|
||||
if (!hs->idle_timer) {
|
||||
hs->idle_timer = qemu_new_timer_ns(vm_clock, hid_idle_timer, hs);
|
||||
}
|
||||
qemu_mod_timer_ns(hs->idle_timer, expire_time);
|
||||
} else {
|
||||
hid_del_idle_timer(hs);
|
||||
}
|
||||
}
|
||||
|
||||
static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons)
|
||||
|
@ -232,6 +258,8 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
|||
int index;
|
||||
HIDPointerEvent *e;
|
||||
|
||||
hs->idle_pending = false;
|
||||
|
||||
hid_pointer_activate(hs);
|
||||
|
||||
/* When the buffer is empty, return the last event. Relative
|
||||
|
@ -319,6 +347,8 @@ int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
|
|||
|
||||
int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len)
|
||||
{
|
||||
hs->idle_pending = false;
|
||||
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -377,6 +407,8 @@ void hid_reset(HIDState *hs)
|
|||
hs->n = 0;
|
||||
hs->protocol = 1;
|
||||
hs->idle = 0;
|
||||
hs->idle_pending = false;
|
||||
hid_del_idle_timer(hs);
|
||||
}
|
||||
|
||||
void hid_free(HIDState *hs)
|
||||
|
@ -390,6 +422,7 @@ void hid_free(HIDState *hs)
|
|||
qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
|
||||
break;
|
||||
}
|
||||
hid_del_idle_timer(hs);
|
||||
}
|
||||
|
||||
void hid_init(HIDState *hs, int kind, HIDEventFunc event)
|
||||
|
@ -412,9 +445,7 @@ static int hid_post_load(void *opaque, int version_id)
|
|||
{
|
||||
HIDState *s = opaque;
|
||||
|
||||
if (s->idle) {
|
||||
hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
|
||||
}
|
||||
hid_set_next_idle(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
5
hw/hid.h
5
hw/hid.h
|
@ -43,7 +43,8 @@ struct HIDState {
|
|||
int kind;
|
||||
int32_t protocol;
|
||||
uint8_t idle;
|
||||
int64_t next_idle_clock;
|
||||
bool idle_pending;
|
||||
QEMUTimer *idle_timer;
|
||||
HIDEventFunc event;
|
||||
};
|
||||
|
||||
|
@ -52,7 +53,7 @@ void hid_reset(HIDState *hs);
|
|||
void hid_free(HIDState *hs);
|
||||
|
||||
bool hid_has_events(HIDState *hs);
|
||||
void hid_set_next_idle(HIDState *hs, int64_t curtime);
|
||||
void hid_set_next_idle(HIDState *hs);
|
||||
void hid_pointer_activate(HIDState *hs);
|
||||
int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len);
|
||||
int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len);
|
||||
|
|
20
hw/usb.h
20
hw/usb.h
|
@ -307,6 +307,12 @@ typedef struct USBDeviceClass {
|
|||
*/
|
||||
void (*flush_ep_queue)(USBDevice *dev, USBEndpoint *ep);
|
||||
|
||||
/*
|
||||
* Called by the hcd to let the device know the queue for an endpoint
|
||||
* has been unlinked / stopped. Optional may be NULL.
|
||||
*/
|
||||
void (*ep_stopped)(USBDevice *dev, USBEndpoint *ep);
|
||||
|
||||
const char *product_desc;
|
||||
const USBDesc *usb_desc;
|
||||
} USBDeviceClass;
|
||||
|
@ -539,11 +545,23 @@ void usb_device_set_interface(USBDevice *dev, int interface,
|
|||
|
||||
void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep);
|
||||
|
||||
void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep);
|
||||
|
||||
const char *usb_device_get_product_desc(USBDevice *dev);
|
||||
|
||||
const USBDesc *usb_device_get_usb_desc(USBDevice *dev);
|
||||
|
||||
int ehci_create_ich9_with_companions(PCIBus *bus, int slot);
|
||||
|
||||
#endif
|
||||
/* quirks.c */
|
||||
|
||||
/* In bulk endpoints are streaming data sources (iow behave like isoc eps) */
|
||||
#define USB_QUIRK_BUFFER_BULK_IN 0x01
|
||||
/* Bulk pkts in FTDI format, need special handling when combining packets */
|
||||
#define USB_QUIRK_IS_FTDI 0x02
|
||||
|
||||
int usb_get_quirks(uint16_t vendor_id, uint16_t product_id,
|
||||
uint8_t interface_class, uint8_t interface_subclass,
|
||||
uint8_t interface_protocol);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@ common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
|
|||
common-obj-y += libhw.o
|
||||
|
||||
common-obj-$(CONFIG_SMARTCARD) += dev-smartcard-reader.o
|
||||
common-obj-$(CONFIG_USB_REDIR) += redirect.o
|
||||
common-obj-$(CONFIG_USB_REDIR) += redirect.o quirks.o
|
||||
|
||||
common-obj-y += core.o combined-packet.o bus.o desc.o dev-hub.o
|
||||
common-obj-y += host-$(HOST_USB).o dev-bluetooth.o
|
||||
|
|
|
@ -189,6 +189,14 @@ void usb_device_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
|
|||
}
|
||||
}
|
||||
|
||||
void usb_device_ep_stopped(USBDevice *dev, USBEndpoint *ep)
|
||||
{
|
||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
||||
if (klass->ep_stopped) {
|
||||
klass->ep_stopped(dev, ep);
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_qdev_init(DeviceState *qdev)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(qdev);
|
||||
|
|
|
@ -761,7 +761,7 @@ USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
|
|||
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
||||
USBPacket *p;
|
||||
|
||||
while ((p = QTAILQ_FIRST(&uep->queue)) != NULL) {
|
||||
QTAILQ_FOREACH(p, &uep->queue, queue) {
|
||||
if (p->id == id) {
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -501,7 +501,7 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
|
|||
break;
|
||||
case SET_IDLE:
|
||||
hs->idle = (uint8_t) (value >> 8);
|
||||
hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
|
||||
hid_set_next_idle(hs);
|
||||
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
|
||||
hid_pointer_activate(hs);
|
||||
}
|
||||
|
@ -523,16 +523,14 @@ static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
|
|||
switch (p->pid) {
|
||||
case USB_TOKEN_IN:
|
||||
if (p->ep->nr == 1) {
|
||||
int64_t curtime = qemu_get_clock_ns(vm_clock);
|
||||
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
|
||||
hid_pointer_activate(hs);
|
||||
}
|
||||
if (!hid_has_events(hs) &&
|
||||
(!hs->idle || hs->next_idle_clock - curtime > 0)) {
|
||||
if (!hid_has_events(hs)) {
|
||||
p->status = USB_RET_NAK;
|
||||
return;
|
||||
}
|
||||
hid_set_next_idle(hs, curtime);
|
||||
hid_set_next_idle(hs);
|
||||
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
|
||||
len = hid_pointer_poll(hs, buf, p->iov.size);
|
||||
} else if (hs->kind == HID_KEYBOARD) {
|
||||
|
|
|
@ -16,14 +16,8 @@
|
|||
*/
|
||||
|
||||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "qemu/range.h"
|
||||
|
||||
typedef struct EHCIPCIState {
|
||||
PCIDevice pcidev;
|
||||
EHCIState ehci;
|
||||
} EHCIPCIState;
|
||||
|
||||
typedef struct EHCIPCIInfo {
|
||||
const char *name;
|
||||
uint16_t vendor_id;
|
||||
|
@ -33,7 +27,7 @@ typedef struct EHCIPCIInfo {
|
|||
|
||||
static int usb_ehci_pci_initfn(PCIDevice *dev)
|
||||
{
|
||||
EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev);
|
||||
EHCIPCIState *i = PCI_EHCI(dev);
|
||||
EHCIState *s = &i->ehci;
|
||||
uint8_t *pci_conf = dev->config;
|
||||
|
||||
|
@ -83,7 +77,7 @@ static int usb_ehci_pci_initfn(PCIDevice *dev)
|
|||
static void usb_ehci_pci_write_config(PCIDevice *dev, uint32_t addr,
|
||||
uint32_t val, int l)
|
||||
{
|
||||
EHCIPCIState *i = DO_UPCAST(EHCIPCIState, pcidev, dev);
|
||||
EHCIPCIState *i = PCI_EHCI(dev);
|
||||
bool busmaster;
|
||||
|
||||
pci_default_write_config(dev, addr, val, l);
|
||||
|
@ -115,12 +109,8 @@ static void ehci_class_init(ObjectClass *klass, void *data)
|
|||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
EHCIPCIInfo *i = data;
|
||||
|
||||
k->init = usb_ehci_pci_initfn;
|
||||
k->vendor_id = i->vendor_id;
|
||||
k->device_id = i->device_id;
|
||||
k->revision = i->revision;
|
||||
k->class_id = PCI_CLASS_SERIAL_USB;
|
||||
k->config_write = usb_ehci_pci_write_config;
|
||||
k->no_hotplug = 1;
|
||||
|
@ -128,6 +118,24 @@ static void ehci_class_init(ObjectClass *klass, void *data)
|
|||
dc->props = ehci_pci_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo ehci_pci_type_info = {
|
||||
.name = TYPE_PCI_EHCI,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(EHCIPCIState),
|
||||
.abstract = true,
|
||||
.class_init = ehci_class_init,
|
||||
};
|
||||
|
||||
static void ehci_data_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
EHCIPCIInfo *i = data;
|
||||
|
||||
k->vendor_id = i->vendor_id;
|
||||
k->device_id = i->device_id;
|
||||
k->revision = i->revision;
|
||||
}
|
||||
|
||||
static struct EHCIPCIInfo ehci_pci_info[] = {
|
||||
{
|
||||
.name = "usb-ehci",
|
||||
|
@ -150,12 +158,13 @@ static struct EHCIPCIInfo ehci_pci_info[] = {
|
|||
static void ehci_pci_register_types(void)
|
||||
{
|
||||
TypeInfo ehci_type_info = {
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(EHCIPCIState),
|
||||
.class_init = ehci_class_init,
|
||||
.parent = TYPE_PCI_EHCI,
|
||||
.class_init = ehci_data_class_init,
|
||||
};
|
||||
int i;
|
||||
|
||||
type_register_static(&ehci_pci_type_info);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ehci_pci_info); i++) {
|
||||
ehci_type_info.name = ehci_pci_info[i].name;
|
||||
ehci_type_info.class_data = ehci_pci_info + i;
|
||||
|
|
|
@ -16,12 +16,6 @@
|
|||
*/
|
||||
|
||||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
typedef struct EHCISysBusState {
|
||||
SysBusDevice busdev;
|
||||
EHCIState ehci;
|
||||
} EHCISysBusState;
|
||||
|
||||
static const VMStateDescription vmstate_ehci_sysbus = {
|
||||
.name = "ehci-sysbus",
|
||||
|
@ -40,11 +34,12 @@ static Property ehci_sysbus_properties[] = {
|
|||
|
||||
static int usb_ehci_sysbus_initfn(SysBusDevice *dev)
|
||||
{
|
||||
EHCISysBusState *i = FROM_SYSBUS(EHCISysBusState, dev);
|
||||
EHCISysBusState *i = SYS_BUS_EHCI(dev);
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_GET_CLASS(dev);
|
||||
EHCIState *s = &i->ehci;
|
||||
|
||||
s->capsbase = 0x100;
|
||||
s->opregbase = 0x140;
|
||||
s->capsbase = sec->capsbase;
|
||||
s->opregbase = sec->opregbase;
|
||||
s->dma = &dma_context_memory;
|
||||
|
||||
usb_ehci_initfn(s, DEVICE(dev));
|
||||
|
@ -63,16 +58,48 @@ static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
|
|||
dc->props = ehci_sysbus_properties;
|
||||
}
|
||||
|
||||
TypeInfo ehci_xlnx_type_info = {
|
||||
.name = "xlnx,ps7-usb",
|
||||
static const TypeInfo ehci_type_info = {
|
||||
.name = TYPE_SYS_BUS_EHCI,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(EHCISysBusState),
|
||||
.abstract = true,
|
||||
.class_init = ehci_sysbus_class_init,
|
||||
.class_size = sizeof(SysBusEHCIClass),
|
||||
};
|
||||
|
||||
static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
|
||||
|
||||
sec->capsbase = 0x100;
|
||||
sec->opregbase = 0x140;
|
||||
}
|
||||
|
||||
static const TypeInfo ehci_xlnx_type_info = {
|
||||
.name = "xlnx,ps7-usb",
|
||||
.parent = TYPE_SYS_BUS_EHCI,
|
||||
.class_init = ehci_xlnx_class_init,
|
||||
};
|
||||
|
||||
static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
|
||||
|
||||
sec->capsbase = 0x0;
|
||||
sec->opregbase = 0x10;
|
||||
}
|
||||
|
||||
static const TypeInfo ehci_exynos4210_type_info = {
|
||||
.name = TYPE_EXYNOS4210_EHCI,
|
||||
.parent = TYPE_SYS_BUS_EHCI,
|
||||
.class_init = ehci_exynos4210_class_init,
|
||||
};
|
||||
|
||||
static void ehci_sysbus_register_types(void)
|
||||
{
|
||||
type_register_static(&ehci_type_info);
|
||||
type_register_static(&ehci_xlnx_type_info);
|
||||
type_register_static(&ehci_exynos4210_type_info);
|
||||
}
|
||||
|
||||
type_init(ehci_sysbus_register_types)
|
||||
|
|
|
@ -109,12 +109,13 @@
|
|||
|
||||
#define FRAME_TIMER_FREQ 1000
|
||||
#define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ)
|
||||
#define UFRAME_TIMER_NS (FRAME_TIMER_NS / 8)
|
||||
|
||||
#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
|
||||
#define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction
|
||||
#define MAX_QH 100 // Max allowable queue heads in a chain
|
||||
#define MIN_FR_PER_TICK 3 // Min frames to process when catching up
|
||||
#define PERIODIC_ACTIVE 64
|
||||
#define MIN_UFR_PER_TICK 24 /* Min frames to process when catching up */
|
||||
#define PERIODIC_ACTIVE 512 /* Micro-frames */
|
||||
|
||||
/* Internal periodic / asynchronous schedule state machine states
|
||||
*/
|
||||
|
@ -192,6 +193,7 @@ static int ehci_state_executing(EHCIQueue *q);
|
|||
static int ehci_state_writeback(EHCIQueue *q);
|
||||
static int ehci_state_advqueue(EHCIQueue *q);
|
||||
static int ehci_fill_queue(EHCIPacket *p);
|
||||
static void ehci_free_packet(EHCIPacket *p);
|
||||
|
||||
static const char *nr2str(const char **n, size_t len, uint32_t nr)
|
||||
{
|
||||
|
@ -438,6 +440,136 @@ static inline bool ehci_periodic_enabled(EHCIState *s)
|
|||
return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
|
||||
}
|
||||
|
||||
/* Get an array of dwords from main memory */
|
||||
static inline int get_dwords(EHCIState *ehci, uint32_t addr,
|
||||
uint32_t *buf, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ehci->dma) {
|
||||
ehci_raise_irq(ehci, USBSTS_HSE);
|
||||
ehci->usbcmd &= ~USBCMD_RUNSTOP;
|
||||
trace_usb_ehci_dma_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
|
||||
dma_memory_read(ehci->dma, addr, buf, sizeof(*buf));
|
||||
*buf = le32_to_cpu(*buf);
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Put an array of dwords in to main memory */
|
||||
static inline int put_dwords(EHCIState *ehci, uint32_t addr,
|
||||
uint32_t *buf, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ehci->dma) {
|
||||
ehci_raise_irq(ehci, USBSTS_HSE);
|
||||
ehci->usbcmd &= ~USBCMD_RUNSTOP;
|
||||
trace_usb_ehci_dma_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
|
||||
uint32_t tmp = cpu_to_le32(*buf);
|
||||
dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int ehci_get_pid(EHCIqtd *qtd)
|
||||
{
|
||||
switch (get_field(qtd->token, QTD_TOKEN_PID)) {
|
||||
case 0:
|
||||
return USB_TOKEN_OUT;
|
||||
case 1:
|
||||
return USB_TOKEN_IN;
|
||||
case 2:
|
||||
return USB_TOKEN_SETUP;
|
||||
default:
|
||||
fprintf(stderr, "bad token\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ehci_verify_qh(EHCIQueue *q, EHCIqh *qh)
|
||||
{
|
||||
uint32_t devaddr = get_field(qh->epchar, QH_EPCHAR_DEVADDR);
|
||||
uint32_t endp = get_field(qh->epchar, QH_EPCHAR_EP);
|
||||
if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
|
||||
(endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
|
||||
(qh->current_qtd != q->qh.current_qtd) ||
|
||||
(q->async && qh->next_qtd != q->qh.next_qtd) ||
|
||||
(memcmp(&qh->altnext_qtd, &q->qh.altnext_qtd,
|
||||
7 * sizeof(uint32_t)) != 0) ||
|
||||
(q->dev != NULL && q->dev->addr != devaddr)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ehci_verify_qtd(EHCIPacket *p, EHCIqtd *qtd)
|
||||
{
|
||||
if (p->qtdaddr != p->queue->qtdaddr ||
|
||||
(p->queue->async && !NLPTR_TBIT(p->qtd.next) &&
|
||||
(p->qtd.next != qtd->next)) ||
|
||||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd->altnext)) ||
|
||||
p->qtd.token != qtd->token ||
|
||||
p->qtd.bufptr[0] != qtd->bufptr[0]) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ehci_verify_pid(EHCIQueue *q, EHCIqtd *qtd)
|
||||
{
|
||||
int ep = get_field(q->qh.epchar, QH_EPCHAR_EP);
|
||||
int pid = ehci_get_pid(qtd);
|
||||
|
||||
/* Note the pid changing is normal for ep 0 (the control ep) */
|
||||
if (q->last_pid && ep != 0 && pid != q->last_pid) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish executing and writeback a packet outside of the regular
|
||||
fetchqh -> fetchqtd -> execute -> writeback cycle */
|
||||
static void ehci_writeback_async_complete_packet(EHCIPacket *p)
|
||||
{
|
||||
EHCIQueue *q = p->queue;
|
||||
EHCIqtd qtd;
|
||||
EHCIqh qh;
|
||||
int state;
|
||||
|
||||
/* Verify the qh + qtd, like we do when going through fetchqh & fetchqtd */
|
||||
get_dwords(q->ehci, NLPTR_GET(q->qhaddr),
|
||||
(uint32_t *) &qh, sizeof(EHCIqh) >> 2);
|
||||
get_dwords(q->ehci, NLPTR_GET(q->qtdaddr),
|
||||
(uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
|
||||
if (!ehci_verify_qh(q, &qh) || !ehci_verify_qtd(p, &qtd)) {
|
||||
p->async = EHCI_ASYNC_INITIALIZED;
|
||||
ehci_free_packet(p);
|
||||
return;
|
||||
}
|
||||
|
||||
state = ehci_get_state(q->ehci, q->async);
|
||||
ehci_state_executing(q);
|
||||
ehci_state_writeback(q); /* Frees the packet! */
|
||||
if (!(q->qh.token & QTD_TOKEN_HALT)) {
|
||||
ehci_state_advqueue(q);
|
||||
}
|
||||
ehci_set_state(q->ehci, q->async, state);
|
||||
}
|
||||
|
||||
/* packet management */
|
||||
|
||||
static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
|
||||
|
@ -455,17 +587,7 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
|
|||
static void ehci_free_packet(EHCIPacket *p)
|
||||
{
|
||||
if (p->async == EHCI_ASYNC_FINISHED) {
|
||||
EHCIQueue *q = p->queue;
|
||||
int state = ehci_get_state(q->ehci, q->async);
|
||||
/* This is a normal, but rare condition (cancel racing completion) */
|
||||
fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
|
||||
ehci_state_executing(q);
|
||||
ehci_state_writeback(q);
|
||||
if (!(q->qh.token & QTD_TOKEN_HALT)) {
|
||||
ehci_state_advqueue(q);
|
||||
}
|
||||
ehci_set_state(q->ehci, q->async, state);
|
||||
/* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
|
||||
ehci_writeback_async_complete_packet(p);
|
||||
return;
|
||||
}
|
||||
trace_usb_ehci_packet_action(p->queue, p, "free");
|
||||
|
@ -500,6 +622,17 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
|
|||
return q;
|
||||
}
|
||||
|
||||
static void ehci_queue_stopped(EHCIQueue *q)
|
||||
{
|
||||
int endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
|
||||
|
||||
if (!q->last_pid || !q->dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
usb_device_ep_stopped(q->dev, usb_ep_get(q->dev, q->last_pid, endp));
|
||||
}
|
||||
|
||||
static int ehci_cancel_queue(EHCIQueue *q)
|
||||
{
|
||||
EHCIPacket *p;
|
||||
|
@ -507,7 +640,7 @@ static int ehci_cancel_queue(EHCIQueue *q)
|
|||
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
if (p == NULL) {
|
||||
return 0;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
trace_usb_ehci_queue_action(q, "cancel");
|
||||
|
@ -515,6 +648,9 @@ static int ehci_cancel_queue(EHCIQueue *q)
|
|||
ehci_free_packet(p);
|
||||
packets++;
|
||||
} while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
|
||||
|
||||
leave:
|
||||
ehci_queue_stopped(q);
|
||||
return packets;
|
||||
}
|
||||
|
||||
|
@ -526,6 +662,7 @@ static int ehci_reset_queue(EHCIQueue *q)
|
|||
packets = ehci_cancel_queue(q);
|
||||
q->dev = NULL;
|
||||
q->qtdaddr = 0;
|
||||
q->last_pid = 0;
|
||||
return packets;
|
||||
}
|
||||
|
||||
|
@ -634,7 +771,6 @@ static void ehci_attach(USBPort *port)
|
|||
*portsc |= PORTSC_CSC;
|
||||
|
||||
ehci_raise_irq(s, USBSTS_PCD);
|
||||
ehci_commit_irq(s);
|
||||
}
|
||||
|
||||
static void ehci_detach(USBPort *port)
|
||||
|
@ -664,7 +800,6 @@ static void ehci_detach(USBPort *port)
|
|||
*portsc |= PORTSC_CSC;
|
||||
|
||||
ehci_raise_irq(s, USBSTS_PCD);
|
||||
ehci_commit_irq(s);
|
||||
}
|
||||
|
||||
static void ehci_child_detach(USBPort *port, USBDevice *child)
|
||||
|
@ -833,7 +968,15 @@ static uint64_t ehci_opreg_read(void *ptr, hwaddr addr,
|
|||
EHCIState *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
val = s->opreg[addr >> 2];
|
||||
switch (addr) {
|
||||
case FRINDEX:
|
||||
/* Round down to mult of 8, else it can go backwards on migration */
|
||||
val = s->frindex & ~7;
|
||||
break;
|
||||
default:
|
||||
val = s->opreg[addr >> 2];
|
||||
}
|
||||
|
||||
trace_usb_ehci_opreg_read(addr + s->opregbase, addr2str(addr), val);
|
||||
return val;
|
||||
}
|
||||
|
@ -984,7 +1127,8 @@ static void ehci_opreg_write(void *ptr, hwaddr addr,
|
|||
break;
|
||||
|
||||
case FRINDEX:
|
||||
val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */
|
||||
val &= 0x00003fff; /* frindex is 14bits */
|
||||
s->usbsts_frindex = val;
|
||||
break;
|
||||
|
||||
case CONFIGFLAG:
|
||||
|
@ -1017,48 +1161,6 @@ static void ehci_opreg_write(void *ptr, hwaddr addr,
|
|||
*mmio, old);
|
||||
}
|
||||
|
||||
/* Get an array of dwords from main memory */
|
||||
static inline int get_dwords(EHCIState *ehci, uint32_t addr,
|
||||
uint32_t *buf, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ehci->dma) {
|
||||
ehci_raise_irq(ehci, USBSTS_HSE);
|
||||
ehci->usbcmd &= ~USBCMD_RUNSTOP;
|
||||
trace_usb_ehci_dma_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
|
||||
dma_memory_read(ehci->dma, addr, buf, sizeof(*buf));
|
||||
*buf = le32_to_cpu(*buf);
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Put an array of dwords in to main memory */
|
||||
static inline int put_dwords(EHCIState *ehci, uint32_t addr,
|
||||
uint32_t *buf, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ehci->dma) {
|
||||
ehci_raise_irq(ehci, USBSTS_HSE);
|
||||
ehci->usbcmd &= ~USBCMD_RUNSTOP;
|
||||
trace_usb_ehci_dma_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
|
||||
uint32_t tmp = cpu_to_le32(*buf);
|
||||
dma_memory_write(ehci->dma, addr, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the qh back to guest physical memory. This step isn't
|
||||
* in the EHCI spec but we need to do it since we don't share
|
||||
|
@ -1257,6 +1359,9 @@ static void ehci_execute_complete(EHCIQueue *q)
|
|||
if (tbytes) {
|
||||
/* 4.15.1.2 must raise int on a short input packet */
|
||||
ehci_raise_irq(q->ehci, USBSTS_INT);
|
||||
if (q->async) {
|
||||
q->ehci->int_req_by_async = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tbytes = 0;
|
||||
|
@ -1301,22 +1406,11 @@ static int ehci_execute(EHCIPacket *p, const char *action)
|
|||
return -1;
|
||||
}
|
||||
|
||||
p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
|
||||
switch (p->pid) {
|
||||
case 0:
|
||||
p->pid = USB_TOKEN_OUT;
|
||||
break;
|
||||
case 1:
|
||||
p->pid = USB_TOKEN_IN;
|
||||
break;
|
||||
case 2:
|
||||
p->pid = USB_TOKEN_SETUP;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "bad token\n");
|
||||
break;
|
||||
if (!ehci_verify_pid(p->queue, &p->qtd)) {
|
||||
ehci_queue_stopped(p->queue); /* Mark the ep in the prev dir stopped */
|
||||
}
|
||||
|
||||
p->pid = ehci_get_pid(&p->qtd);
|
||||
p->queue->last_pid = p->pid;
|
||||
endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
|
||||
ep = usb_ep_get(p->queue->dev, p->pid, endp);
|
||||
|
||||
|
@ -1551,8 +1645,7 @@ out:
|
|||
|
||||
static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
||||
{
|
||||
EHCIPacket *p;
|
||||
uint32_t entry, devaddr, endp;
|
||||
uint32_t entry;
|
||||
EHCIQueue *q;
|
||||
EHCIqh qh;
|
||||
|
||||
|
@ -1561,7 +1654,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
|||
if (NULL == q) {
|
||||
q = ehci_alloc_queue(ehci, entry, async);
|
||||
}
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
|
||||
q->seen++;
|
||||
if (q->seen > 1) {
|
||||
|
@ -1582,19 +1674,10 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
|||
* The overlay area of the qh should never be changed by the guest,
|
||||
* except when idle, in which case the reset is a nop.
|
||||
*/
|
||||
devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR);
|
||||
endp = get_field(qh.epchar, QH_EPCHAR_EP);
|
||||
if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
|
||||
(endp != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
|
||||
(qh.current_qtd != q->qh.current_qtd) ||
|
||||
(q->async && qh.next_qtd != q->qh.next_qtd) ||
|
||||
(memcmp(&qh.altnext_qtd, &q->qh.altnext_qtd,
|
||||
7 * sizeof(uint32_t)) != 0) ||
|
||||
(q->dev != NULL && q->dev->addr != devaddr)) {
|
||||
if (!ehci_verify_qh(q, &qh)) {
|
||||
if (ehci_reset_queue(q) > 0) {
|
||||
ehci_trace_guest_bug(ehci, "guest updated active QH");
|
||||
}
|
||||
p = NULL;
|
||||
}
|
||||
q->qh = qh;
|
||||
|
||||
|
@ -1604,14 +1687,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
|||
}
|
||||
|
||||
if (q->dev == NULL) {
|
||||
q->dev = ehci_find_device(q->ehci, devaddr);
|
||||
}
|
||||
|
||||
if (p && p->async == EHCI_ASYNC_FINISHED) {
|
||||
/* I/O finished -- continue processing queue */
|
||||
trace_usb_ehci_packet_action(p->queue, p, "complete");
|
||||
ehci_set_state(ehci, async, EST_EXECUTING);
|
||||
goto out;
|
||||
q->dev = ehci_find_device(q->ehci,
|
||||
get_field(q->qh.epchar, QH_EPCHAR_DEVADDR));
|
||||
}
|
||||
|
||||
if (async && (q->qh.epchar & QH_EPCHAR_H)) {
|
||||
|
@ -1762,13 +1839,11 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
|
|||
|
||||
p = QTAILQ_FIRST(&q->packets);
|
||||
if (p != NULL) {
|
||||
if (p->qtdaddr != q->qtdaddr ||
|
||||
(q->async && !NLPTR_TBIT(p->qtd.next) &&
|
||||
(p->qtd.next != qtd.next)) ||
|
||||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
|
||||
p->qtd.bufptr[0] != qtd.bufptr[0]) {
|
||||
if (!ehci_verify_qtd(p, &qtd)) {
|
||||
ehci_cancel_queue(q);
|
||||
ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
|
||||
if (qtd.token & QTD_TOKEN_ACTIVE) {
|
||||
ehci_trace_guest_bug(q->ehci, "guest updated active qTD");
|
||||
}
|
||||
p = NULL;
|
||||
} else {
|
||||
p->qtd = qtd;
|
||||
|
@ -1777,11 +1852,6 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
|
|||
}
|
||||
|
||||
if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
|
||||
if (p != NULL) {
|
||||
/* transfer canceled by guest (clear active) */
|
||||
ehci_cancel_queue(q);
|
||||
p = NULL;
|
||||
}
|
||||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
} else if (p != NULL) {
|
||||
switch (p->async) {
|
||||
|
@ -1797,10 +1867,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
|
|||
ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
|
||||
break;
|
||||
case EHCI_ASYNC_FINISHED:
|
||||
/*
|
||||
* We get here when advqueue moves to a packet which is already
|
||||
* finished, which can happen with packets queued up by fill_queue
|
||||
*/
|
||||
/* Complete executing of the packet */
|
||||
ehci_set_state(q->ehci, q->async, EST_EXECUTING);
|
||||
break;
|
||||
}
|
||||
|
@ -1859,6 +1926,10 @@ static int ehci_fill_queue(EHCIPacket *p)
|
|||
if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
|
||||
break;
|
||||
}
|
||||
if (!ehci_verify_pid(q, &qtd)) {
|
||||
ehci_trace_guest_bug(q->ehci, "guest queued token with wrong pid");
|
||||
break;
|
||||
}
|
||||
p = ehci_alloc_packet(q);
|
||||
p->qtdaddr = qtdaddr;
|
||||
p->qtd = qtd;
|
||||
|
@ -2176,16 +2247,16 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
|
|||
}
|
||||
}
|
||||
|
||||
static void ehci_update_frindex(EHCIState *ehci, int frames)
|
||||
static void ehci_update_frindex(EHCIState *ehci, int uframes)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ehci_enabled(ehci)) {
|
||||
if (!ehci_enabled(ehci) && ehci->pstate == EST_INACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
ehci->frindex += 8;
|
||||
for (i = 0; i < uframes; i++) {
|
||||
ehci->frindex++;
|
||||
|
||||
if (ehci->frindex == 0x00002000) {
|
||||
ehci_raise_irq(ehci, USBSTS_FLR);
|
||||
|
@ -2209,33 +2280,33 @@ static void ehci_frame_timer(void *opaque)
|
|||
int need_timer = 0;
|
||||
int64_t expire_time, t_now;
|
||||
uint64_t ns_elapsed;
|
||||
int frames, skipped_frames;
|
||||
int uframes, skipped_uframes;
|
||||
int i;
|
||||
|
||||
t_now = qemu_get_clock_ns(vm_clock);
|
||||
ns_elapsed = t_now - ehci->last_run_ns;
|
||||
frames = ns_elapsed / FRAME_TIMER_NS;
|
||||
uframes = ns_elapsed / UFRAME_TIMER_NS;
|
||||
|
||||
if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
|
||||
need_timer++;
|
||||
|
||||
if (frames > ehci->maxframes) {
|
||||
skipped_frames = frames - ehci->maxframes;
|
||||
ehci_update_frindex(ehci, skipped_frames);
|
||||
ehci->last_run_ns += FRAME_TIMER_NS * skipped_frames;
|
||||
frames -= skipped_frames;
|
||||
DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
|
||||
if (uframes > (ehci->maxframes * 8)) {
|
||||
skipped_uframes = uframes - (ehci->maxframes * 8);
|
||||
ehci_update_frindex(ehci, skipped_uframes);
|
||||
ehci->last_run_ns += UFRAME_TIMER_NS * skipped_uframes;
|
||||
uframes -= skipped_uframes;
|
||||
DPRINTF("WARNING - EHCI skipped %d uframes\n", skipped_uframes);
|
||||
}
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
for (i = 0; i < uframes; i++) {
|
||||
/*
|
||||
* If we're running behind schedule, we should not catch up
|
||||
* too fast, as that will make some guests unhappy:
|
||||
* 1) We must process a minimum of MIN_FR_PER_TICK frames,
|
||||
* 1) We must process a minimum of MIN_UFR_PER_TICK frames,
|
||||
* otherwise we will never catch up
|
||||
* 2) Process frames until the guest has requested an irq (IOC)
|
||||
*/
|
||||
if (i >= MIN_FR_PER_TICK) {
|
||||
if (i >= MIN_UFR_PER_TICK) {
|
||||
ehci_commit_irq(ehci);
|
||||
if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) {
|
||||
break;
|
||||
|
@ -2245,13 +2316,15 @@ static void ehci_frame_timer(void *opaque)
|
|||
ehci->periodic_sched_active--;
|
||||
}
|
||||
ehci_update_frindex(ehci, 1);
|
||||
ehci_advance_periodic_state(ehci);
|
||||
ehci->last_run_ns += FRAME_TIMER_NS;
|
||||
if ((ehci->frindex & 7) == 0) {
|
||||
ehci_advance_periodic_state(ehci);
|
||||
}
|
||||
ehci->last_run_ns += UFRAME_TIMER_NS;
|
||||
}
|
||||
} else {
|
||||
ehci->periodic_sched_active = 0;
|
||||
ehci_update_frindex(ehci, frames);
|
||||
ehci->last_run_ns += FRAME_TIMER_NS * frames;
|
||||
ehci_update_frindex(ehci, uframes);
|
||||
ehci->last_run_ns += UFRAME_TIMER_NS * uframes;
|
||||
}
|
||||
|
||||
if (ehci->periodic_sched_active) {
|
||||
|
@ -2282,7 +2355,7 @@ static void ehci_frame_timer(void *opaque)
|
|||
/* If we've raised int, we speed up the timer, so that we quickly
|
||||
* notice any new packets queued up in response */
|
||||
if (ehci->int_req_by_async && (ehci->usbsts & USBSTS_INT)) {
|
||||
expire_time = t_now + get_ticks_per_sec() / (FRAME_TIMER_FREQ * 2);
|
||||
expire_time = t_now + get_ticks_per_sec() / (FRAME_TIMER_FREQ * 4);
|
||||
ehci->int_req_by_async = false;
|
||||
} else {
|
||||
expire_time = t_now + (get_ticks_per_sec()
|
||||
|
@ -2330,6 +2403,17 @@ static USBBusOps ehci_bus_ops = {
|
|||
.wakeup_endpoint = ehci_wakeup_endpoint,
|
||||
};
|
||||
|
||||
static void usb_ehci_pre_save(void *opaque)
|
||||
{
|
||||
EHCIState *ehci = opaque;
|
||||
uint32_t new_frindex;
|
||||
|
||||
/* Round down frindex to a multiple of 8 for migration compatibility */
|
||||
new_frindex = ehci->frindex & ~7;
|
||||
ehci->last_run_ns -= (ehci->frindex - new_frindex) * UFRAME_TIMER_NS;
|
||||
ehci->frindex = new_frindex;
|
||||
}
|
||||
|
||||
static int usb_ehci_post_load(void *opaque, int version_id)
|
||||
{
|
||||
EHCIState *s = opaque;
|
||||
|
@ -2380,6 +2464,7 @@ const VMStateDescription vmstate_ehci = {
|
|||
.name = "ehci-core",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 1,
|
||||
.pre_save = usb_ehci_pre_save,
|
||||
.post_load = usb_ehci_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
/* mmio registers */
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "trace.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#ifndef EHCI_DEBUG
|
||||
#define EHCI_DEBUG 0
|
||||
|
@ -248,6 +250,7 @@ struct EHCIQueue {
|
|||
EHCIqh qh; /* copy of current QH (being worked on) */
|
||||
uint32_t qhaddr; /* address QH read from */
|
||||
uint32_t qtdaddr; /* address QTD read from */
|
||||
int last_pid; /* pid of last packet executed */
|
||||
USBDevice *dev;
|
||||
QTAILQ_HEAD(pkts_head, EHCIPacket) packets;
|
||||
};
|
||||
|
@ -321,4 +324,43 @@ extern const VMStateDescription vmstate_ehci;
|
|||
|
||||
void usb_ehci_initfn(EHCIState *s, DeviceState *dev);
|
||||
|
||||
#define TYPE_PCI_EHCI "pci-ehci-usb"
|
||||
#define PCI_EHCI(obj) OBJECT_CHECK(EHCIPCIState, (obj), TYPE_PCI_EHCI)
|
||||
|
||||
typedef struct EHCIPCIState {
|
||||
/*< private >*/
|
||||
PCIDevice pcidev;
|
||||
/*< public >*/
|
||||
|
||||
EHCIState ehci;
|
||||
} EHCIPCIState;
|
||||
|
||||
|
||||
#define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
|
||||
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
|
||||
|
||||
#define SYS_BUS_EHCI(obj) \
|
||||
OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI)
|
||||
#define SYS_BUS_EHCI_CLASS(class) \
|
||||
OBJECT_CLASS_CHECK(SysBusEHCIClass, (class), TYPE_SYS_BUS_EHCI)
|
||||
#define SYS_BUS_EHCI_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(SysBusEHCIClass, (obj), TYPE_SYS_BUS_EHCI)
|
||||
|
||||
typedef struct EHCISysBusState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
EHCIState ehci;
|
||||
} EHCISysBusState;
|
||||
|
||||
typedef struct SysBusEHCIClass {
|
||||
/*< private >*/
|
||||
SysBusDeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
uint16_t capsbase;
|
||||
uint16_t opregbase;
|
||||
} SysBusEHCIClass;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -430,6 +430,23 @@ static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void ohci_stop_endpoints(OHCIState *ohci)
|
||||
{
|
||||
USBDevice *dev;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ohci->num_ports; i++) {
|
||||
dev = ohci->rhport[i].port.dev;
|
||||
if (dev && dev->attached) {
|
||||
usb_device_ep_stopped(dev, &dev->ep_ctl);
|
||||
for (j = 0; j < USB_MAX_ENDPOINTS; j++) {
|
||||
usb_device_ep_stopped(dev, &dev->ep_in[j]);
|
||||
usb_device_ep_stopped(dev, &dev->ep_out[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the controller */
|
||||
static void ohci_reset(void *opaque)
|
||||
{
|
||||
|
@ -478,6 +495,7 @@ static void ohci_reset(void *opaque)
|
|||
usb_cancel_packet(&ohci->usb_packet);
|
||||
ohci->async_td = 0;
|
||||
}
|
||||
ohci_stop_endpoints(ohci);
|
||||
DPRINTF("usb-ohci: Reset %s\n", ohci->name);
|
||||
}
|
||||
|
||||
|
@ -1147,6 +1165,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
|
|||
if (ohci->async_td && addr == ohci->async_td) {
|
||||
usb_cancel_packet(&ohci->usb_packet);
|
||||
ohci->async_td = 0;
|
||||
usb_device_ep_stopped(ohci->usb_packet.ep->dev,
|
||||
ohci->usb_packet.ep);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1227,10 +1247,12 @@ static void ohci_frame_boundary(void *opaque)
|
|||
}
|
||||
|
||||
/* Cancel all pending packets if either of the lists has been disabled. */
|
||||
if (ohci->async_td &&
|
||||
ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
|
||||
usb_cancel_packet(&ohci->usb_packet);
|
||||
ohci->async_td = 0;
|
||||
if (ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
|
||||
if (ohci->async_td) {
|
||||
usb_cancel_packet(&ohci->usb_packet);
|
||||
ohci->async_td = 0;
|
||||
}
|
||||
ohci_stop_endpoints(ohci);
|
||||
}
|
||||
ohci->old_ctl = ohci->ctl;
|
||||
ohci_process_lists(ohci, 0);
|
||||
|
|
|
@ -75,6 +75,11 @@
|
|||
|
||||
#define FRAME_MAX_LOOPS 256
|
||||
|
||||
/* Must be large enough to handle 10 frame delay for initial isoc requests */
|
||||
#define QH_VALID 32
|
||||
|
||||
#define MAX_FRAMES_PER_TICK (QH_VALID / 2)
|
||||
|
||||
#define NB_PORTS 2
|
||||
|
||||
enum {
|
||||
|
@ -166,6 +171,7 @@ struct UHCIState {
|
|||
/* Properties */
|
||||
char *masterbus;
|
||||
uint32_t firstport;
|
||||
uint32_t maxframes;
|
||||
};
|
||||
|
||||
typedef struct UHCI_TD {
|
||||
|
@ -206,9 +212,7 @@ static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td,
|
|||
queue->ep = ep;
|
||||
QTAILQ_INIT(&queue->asyncs);
|
||||
QTAILQ_INSERT_HEAD(&s->queues, queue, next);
|
||||
/* valid needs to be large enough to handle 10 frame delay
|
||||
* for initial isochronous requests */
|
||||
queue->valid = 32;
|
||||
queue->valid = QH_VALID;
|
||||
trace_usb_uhci_queue_add(queue->token);
|
||||
return queue;
|
||||
}
|
||||
|
@ -222,6 +226,7 @@ static void uhci_queue_free(UHCIQueue *queue, const char *reason)
|
|||
async = QTAILQ_FIRST(&queue->asyncs);
|
||||
uhci_async_cancel(async);
|
||||
}
|
||||
usb_device_ep_stopped(queue->ep->dev, queue->ep);
|
||||
|
||||
trace_usb_uhci_queue_del(queue->token, reason);
|
||||
QTAILQ_REMOVE(&s->queues, queue, next);
|
||||
|
@ -433,7 +438,7 @@ static int uhci_post_load(void *opaque, int version_id)
|
|||
|
||||
static const VMStateDescription vmstate_uhci = {
|
||||
.name = "uhci",
|
||||
.version_id = 2,
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.post_load = uhci_post_load,
|
||||
|
@ -451,44 +456,16 @@ static const VMStateDescription vmstate_uhci = {
|
|||
VMSTATE_UINT8(status2, UHCIState),
|
||||
VMSTATE_TIMER(frame_timer, UHCIState),
|
||||
VMSTATE_INT64_V(expire_time, UHCIState, 2),
|
||||
VMSTATE_UINT32_V(pending_int_mask, UHCIState, 3),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
|
||||
static void uhci_port_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
|
||||
addr &= 0x1f;
|
||||
switch(addr) {
|
||||
case 0x0c:
|
||||
s->sof_timing = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
uint32_t val;
|
||||
|
||||
addr &= 0x1f;
|
||||
switch(addr) {
|
||||
case 0x0c:
|
||||
val = s->sof_timing;
|
||||
break;
|
||||
default:
|
||||
val = 0xff;
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
|
||||
addr &= 0x1f;
|
||||
trace_usb_uhci_mmio_writew(addr, val);
|
||||
|
||||
switch(addr) {
|
||||
|
@ -498,7 +475,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||
trace_usb_uhci_schedule_start();
|
||||
s->expire_time = qemu_get_clock_ns(vm_clock) +
|
||||
(get_ticks_per_sec() / FRAME_TIMER_FREQ);
|
||||
qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
|
||||
qemu_mod_timer(s->frame_timer, s->expire_time);
|
||||
s->status &= ~UHCI_STS_HCHALTED;
|
||||
} else if (!(val & UHCI_CMD_RS)) {
|
||||
s->status |= UHCI_STS_HCHALTED;
|
||||
|
@ -537,6 +514,17 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||
if (s->status & UHCI_STS_HCHALTED)
|
||||
s->frnum = val & 0x7ff;
|
||||
break;
|
||||
case 0x08:
|
||||
s->fl_base_addr &= 0xffff0000;
|
||||
s->fl_base_addr |= val & ~0xfff;
|
||||
break;
|
||||
case 0x0a:
|
||||
s->fl_base_addr &= 0x0000ffff;
|
||||
s->fl_base_addr |= (val << 16);
|
||||
break;
|
||||
case 0x0c:
|
||||
s->sof_timing = val & 0xff;
|
||||
break;
|
||||
case 0x10 ... 0x1f:
|
||||
{
|
||||
UHCIPort *port;
|
||||
|
@ -568,12 +556,11 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
|
||||
static uint64_t uhci_port_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
uint32_t val;
|
||||
|
||||
addr &= 0x1f;
|
||||
switch(addr) {
|
||||
case 0x00:
|
||||
val = s->cmd;
|
||||
|
@ -587,6 +574,15 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
|
|||
case 0x06:
|
||||
val = s->frnum;
|
||||
break;
|
||||
case 0x08:
|
||||
val = s->fl_base_addr & 0xffff;
|
||||
break;
|
||||
case 0x0a:
|
||||
val = (s->fl_base_addr >> 16) & 0xffff;
|
||||
break;
|
||||
case 0x0c:
|
||||
val = s->sof_timing;
|
||||
break;
|
||||
case 0x10 ... 0x1f:
|
||||
{
|
||||
UHCIPort *port;
|
||||
|
@ -609,38 +605,6 @@ static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
|
|||
return val;
|
||||
}
|
||||
|
||||
static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
|
||||
addr &= 0x1f;
|
||||
trace_usb_uhci_mmio_writel(addr, val);
|
||||
|
||||
switch(addr) {
|
||||
case 0x08:
|
||||
s->fl_base_addr = val & ~0xfff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
uint32_t val;
|
||||
|
||||
addr &= 0x1f;
|
||||
switch(addr) {
|
||||
case 0x08:
|
||||
val = s->fl_base_addr;
|
||||
break;
|
||||
default:
|
||||
val = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
trace_usb_uhci_mmio_readl(addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/* signal resume if controller suspended */
|
||||
static void uhci_resume (void *opaque)
|
||||
{
|
||||
|
@ -853,7 +817,7 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
|
|||
}
|
||||
|
||||
if (q) {
|
||||
q->valid = 32;
|
||||
q->valid = QH_VALID;
|
||||
}
|
||||
|
||||
/* Is active ? */
|
||||
|
@ -1174,10 +1138,10 @@ static void uhci_bh(void *opaque)
|
|||
static void uhci_frame_timer(void *opaque)
|
||||
{
|
||||
UHCIState *s = opaque;
|
||||
uint64_t t_now, t_last_run;
|
||||
int i, frames;
|
||||
const uint64_t frame_t = get_ticks_per_sec() / FRAME_TIMER_FREQ;
|
||||
|
||||
/* prepare the timer for the next frame */
|
||||
s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
|
||||
s->frame_bytes = 0;
|
||||
s->completions_only = false;
|
||||
qemu_bh_cancel(s->bh);
|
||||
|
||||
|
@ -1191,7 +1155,35 @@ static void uhci_frame_timer(void *opaque)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Complete the previous frame */
|
||||
/* We still store expire_time in our state, for migration */
|
||||
t_last_run = s->expire_time - frame_t;
|
||||
t_now = qemu_get_clock_ns(vm_clock);
|
||||
|
||||
/* Process up to MAX_FRAMES_PER_TICK frames */
|
||||
frames = (t_now - t_last_run) / frame_t;
|
||||
if (frames > s->maxframes) {
|
||||
int skipped = frames - s->maxframes;
|
||||
s->expire_time += skipped * frame_t;
|
||||
s->frnum = (s->frnum + skipped) & 0x7ff;
|
||||
frames -= skipped;
|
||||
}
|
||||
if (frames > MAX_FRAMES_PER_TICK) {
|
||||
frames = MAX_FRAMES_PER_TICK;
|
||||
}
|
||||
|
||||
for (i = 0; i < frames; i++) {
|
||||
s->frame_bytes = 0;
|
||||
trace_usb_uhci_frame_start(s->frnum);
|
||||
uhci_async_validate_begin(s);
|
||||
uhci_process_frame(s);
|
||||
uhci_async_validate_end(s);
|
||||
/* The spec says frnum is the frame currently being processed, and
|
||||
* the guest must look at frnum - 1 on interrupt, so inc frnum now */
|
||||
s->frnum = (s->frnum + 1) & 0x7ff;
|
||||
s->expire_time += frame_t;
|
||||
}
|
||||
|
||||
/* Complete the previous frame(s) */
|
||||
if (s->pending_int_mask) {
|
||||
s->status2 |= s->pending_int_mask;
|
||||
s->status |= UHCI_STS_USBINT;
|
||||
|
@ -1199,32 +1191,17 @@ static void uhci_frame_timer(void *opaque)
|
|||
}
|
||||
s->pending_int_mask = 0;
|
||||
|
||||
/* Start new frame */
|
||||
s->frnum = (s->frnum + 1) & 0x7ff;
|
||||
|
||||
trace_usb_uhci_frame_start(s->frnum);
|
||||
|
||||
uhci_async_validate_begin(s);
|
||||
|
||||
uhci_process_frame(s);
|
||||
|
||||
uhci_async_validate_end(s);
|
||||
|
||||
qemu_mod_timer(s->frame_timer, s->expire_time);
|
||||
qemu_mod_timer(s->frame_timer, t_now + frame_t);
|
||||
}
|
||||
|
||||
static const MemoryRegionPortio uhci_portio[] = {
|
||||
{ 0, 32, 2, .write = uhci_ioport_writew, },
|
||||
{ 0, 32, 2, .read = uhci_ioport_readw, },
|
||||
{ 0, 32, 4, .write = uhci_ioport_writel, },
|
||||
{ 0, 32, 4, .read = uhci_ioport_readl, },
|
||||
{ 0, 32, 1, .write = uhci_ioport_writeb, },
|
||||
{ 0, 32, 1, .read = uhci_ioport_readb, },
|
||||
PORTIO_END_OF_LIST()
|
||||
};
|
||||
|
||||
static const MemoryRegionOps uhci_ioport_ops = {
|
||||
.old_portio = uhci_portio,
|
||||
.read = uhci_port_read,
|
||||
.write = uhci_port_write,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 4,
|
||||
.impl.min_access_size = 2,
|
||||
.impl.max_access_size = 2,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static USBPortOps uhci_port_ops = {
|
||||
|
@ -1311,6 +1288,7 @@ static Property uhci_properties[] = {
|
|||
DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
|
||||
DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
|
||||
DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280),
|
||||
DEFINE_PROP_UINT32("maxframes", UHCIState, maxframes, 128),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
|
|
@ -1177,6 +1177,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
|
|||
XHCISlot *slot;
|
||||
XHCIEPContext *epctx;
|
||||
int i, xferi, killed = 0;
|
||||
USBEndpoint *ep = NULL;
|
||||
assert(slotid >= 1 && slotid <= xhci->numslots);
|
||||
assert(epid >= 1 && epid <= 31);
|
||||
|
||||
|
@ -1192,9 +1193,15 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
|
|||
|
||||
xferi = epctx->next_xfer;
|
||||
for (i = 0; i < TD_QUEUE; i++) {
|
||||
if (epctx->transfers[xferi].packet.ep) {
|
||||
ep = epctx->transfers[xferi].packet.ep;
|
||||
}
|
||||
killed += xhci_ep_nuke_one_xfer(&epctx->transfers[xferi]);
|
||||
xferi = (xferi + 1) % TD_QUEUE;
|
||||
}
|
||||
if (ep) {
|
||||
usb_device_ep_stopped(ep->dev, ep);
|
||||
}
|
||||
return killed;
|
||||
}
|
||||
|
||||
|
@ -1963,13 +1970,18 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
|
|||
if (bsr) {
|
||||
slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
|
||||
} else {
|
||||
USBPacket p;
|
||||
slot->devaddr = xhci->devaddr++;
|
||||
slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slot->devaddr;
|
||||
DPRINTF("xhci: device address is %d\n", slot->devaddr);
|
||||
usb_device_reset(dev);
|
||||
usb_device_handle_control(dev, NULL,
|
||||
usb_packet_setup(&p, USB_TOKEN_OUT,
|
||||
usb_ep_get(dev, USB_TOKEN_OUT, 0),
|
||||
0, false, false);
|
||||
usb_device_handle_control(dev, &p,
|
||||
DeviceOutRequest | USB_REQ_SET_ADDRESS,
|
||||
slot->devaddr, 0, 0, NULL);
|
||||
assert(p.status != USB_RET_ASYNC);
|
||||
}
|
||||
|
||||
res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Prolific PL2303 USB to serial adaptor driver header file
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#define BENQ_VENDOR_ID 0x04a5
|
||||
#define BENQ_PRODUCT_ID_S81 0x4027
|
||||
|
||||
#define PL2303_VENDOR_ID 0x067b
|
||||
#define PL2303_PRODUCT_ID 0x2303
|
||||
#define PL2303_PRODUCT_ID_RSAQ2 0x04bb
|
||||
#define PL2303_PRODUCT_ID_DCU11 0x1234
|
||||
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0
|
||||
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
|
||||
#define PL2303_PRODUCT_ID_ALDIGA 0x0611
|
||||
#define PL2303_PRODUCT_ID_MMX 0x0612
|
||||
#define PL2303_PRODUCT_ID_GPRS 0x0609
|
||||
#define PL2303_PRODUCT_ID_HCR331 0x331a
|
||||
#define PL2303_PRODUCT_ID_MOTOROLA 0x0307
|
||||
|
||||
#define ATEN_VENDOR_ID 0x0557
|
||||
#define ATEN_VENDOR_ID2 0x0547
|
||||
#define ATEN_PRODUCT_ID 0x2008
|
||||
|
||||
#define IODATA_VENDOR_ID 0x04bb
|
||||
#define IODATA_PRODUCT_ID 0x0a03
|
||||
#define IODATA_PRODUCT_ID_RSAQ5 0x0a0e
|
||||
|
||||
#define ELCOM_VENDOR_ID 0x056e
|
||||
#define ELCOM_PRODUCT_ID 0x5003
|
||||
#define ELCOM_PRODUCT_ID_UCSGT 0x5004
|
||||
|
||||
#define ITEGNO_VENDOR_ID 0x0eba
|
||||
#define ITEGNO_PRODUCT_ID 0x1080
|
||||
#define ITEGNO_PRODUCT_ID_2080 0x2080
|
||||
|
||||
#define MA620_VENDOR_ID 0x0df7
|
||||
#define MA620_PRODUCT_ID 0x0620
|
||||
|
||||
#define RATOC_VENDOR_ID 0x0584
|
||||
#define RATOC_PRODUCT_ID 0xb000
|
||||
|
||||
#define TRIPP_VENDOR_ID 0x2478
|
||||
#define TRIPP_PRODUCT_ID 0x2008
|
||||
|
||||
#define RADIOSHACK_VENDOR_ID 0x1453
|
||||
#define RADIOSHACK_PRODUCT_ID 0x4026
|
||||
|
||||
#define DCU10_VENDOR_ID 0x0731
|
||||
#define DCU10_PRODUCT_ID 0x0528
|
||||
|
||||
#define SITECOM_VENDOR_ID 0x6189
|
||||
#define SITECOM_PRODUCT_ID 0x2068
|
||||
|
||||
/* Alcatel OT535/735 USB cable */
|
||||
#define ALCATEL_VENDOR_ID 0x11f7
|
||||
#define ALCATEL_PRODUCT_ID 0x02df
|
||||
|
||||
/* Samsung I330 phone cradle */
|
||||
#define SAMSUNG_VENDOR_ID 0x04e8
|
||||
#define SAMSUNG_PRODUCT_ID 0x8001
|
||||
|
||||
#define SIEMENS_VENDOR_ID 0x11f5
|
||||
#define SIEMENS_PRODUCT_ID_SX1 0x0001
|
||||
#define SIEMENS_PRODUCT_ID_X65 0x0003
|
||||
#define SIEMENS_PRODUCT_ID_X75 0x0004
|
||||
#define SIEMENS_PRODUCT_ID_EF81 0x0005
|
||||
|
||||
#define SYNTECH_VENDOR_ID 0x0745
|
||||
#define SYNTECH_PRODUCT_ID 0x0001
|
||||
|
||||
/* Nokia CA-42 Cable */
|
||||
#define NOKIA_CA42_VENDOR_ID 0x078b
|
||||
#define NOKIA_CA42_PRODUCT_ID 0x1234
|
||||
|
||||
/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */
|
||||
#define CA_42_CA42_VENDOR_ID 0x10b5
|
||||
#define CA_42_CA42_PRODUCT_ID 0xac70
|
||||
|
||||
#define SAGEM_VENDOR_ID 0x079b
|
||||
#define SAGEM_PRODUCT_ID 0x0027
|
||||
|
||||
/* Leadtek GPS 9531 (ID 0413:2101) */
|
||||
#define LEADTEK_VENDOR_ID 0x0413
|
||||
#define LEADTEK_9531_PRODUCT_ID 0x2101
|
||||
|
||||
/* USB GSM cable from Speed Dragon Multimedia, Ltd */
|
||||
#define SPEEDDRAGON_VENDOR_ID 0x0e55
|
||||
#define SPEEDDRAGON_PRODUCT_ID 0x110b
|
||||
|
||||
/* DATAPILOT Universal-2 Phone Cable */
|
||||
#define DATAPILOT_U2_VENDOR_ID 0x0731
|
||||
#define DATAPILOT_U2_PRODUCT_ID 0x2003
|
||||
|
||||
/* Belkin "F5U257" Serial Adapter */
|
||||
#define BELKIN_VENDOR_ID 0x050d
|
||||
#define BELKIN_PRODUCT_ID 0x0257
|
||||
|
||||
/* Alcor Micro Corp. USB 2.0 TO RS-232 */
|
||||
#define ALCOR_VENDOR_ID 0x058F
|
||||
#define ALCOR_PRODUCT_ID 0x9720
|
||||
|
||||
/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
|
||||
#define WS002IN_VENDOR_ID 0x11f6
|
||||
#define WS002IN_PRODUCT_ID 0x2001
|
||||
|
||||
/* Corega CG-USBRS232R Serial Adapter */
|
||||
#define COREGA_VENDOR_ID 0x07aa
|
||||
#define COREGA_PRODUCT_ID 0x002a
|
||||
|
||||
/* Y.C. Cable U.S.A., Inc - USB to RS-232 */
|
||||
#define YCCABLE_VENDOR_ID 0x05ad
|
||||
#define YCCABLE_PRODUCT_ID 0x0fba
|
||||
|
||||
/* "Superial" USB - Serial */
|
||||
#define SUPERIAL_VENDOR_ID 0x5372
|
||||
#define SUPERIAL_PRODUCT_ID 0x2303
|
||||
|
||||
/* Hewlett-Packard LD220-HP POS Pole Display */
|
||||
#define HP_VENDOR_ID 0x03f0
|
||||
#define HP_LD220_PRODUCT_ID 0x3524
|
||||
|
||||
/* Cressi Edy (diving computer) PC interface */
|
||||
#define CRESSI_VENDOR_ID 0x04b8
|
||||
#define CRESSI_EDY_PRODUCT_ID 0x0521
|
||||
|
||||
/* Zeagle dive computer interface */
|
||||
#define ZEAGLE_VENDOR_ID 0x04b8
|
||||
#define ZEAGLE_N2ITION3_PRODUCT_ID 0x0522
|
||||
|
||||
/* Sony, USB data cable for CMD-Jxx mobile phones */
|
||||
#define SONY_VENDOR_ID 0x054c
|
||||
#define SONY_QN3USB_PRODUCT_ID 0x0437
|
||||
|
||||
/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */
|
||||
#define SANWA_VENDOR_ID 0x11ad
|
||||
#define SANWA_PRODUCT_ID 0x0001
|
||||
|
||||
/* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
|
||||
#define ADLINK_VENDOR_ID 0x0b63
|
||||
#define ADLINK_ND6530_PRODUCT_ID 0x6530
|
||||
|
||||
/* SMART USB Serial Adapter */
|
||||
#define SMART_VENDOR_ID 0x0b8c
|
||||
#define SMART_PRODUCT_ID 0x2303
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* USB quirk handling
|
||||
*
|
||||
* Copyright (c) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat Authors:
|
||||
* Hans de Goede <hdegoede@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "quirks.h"
|
||||
#include "hw/usb.h"
|
||||
|
||||
static bool usb_id_match(const struct usb_device_id *ids,
|
||||
uint16_t vendor_id, uint16_t product_id,
|
||||
uint8_t interface_class, uint8_t interface_subclass,
|
||||
uint8_t interface_protocol) {
|
||||
int i;
|
||||
|
||||
for (i = 0; ids[i].vendor_id != -1; i++) {
|
||||
if (ids[i].vendor_id == vendor_id &&
|
||||
ids[i].product_id == product_id &&
|
||||
(ids[i].interface_class == -1 ||
|
||||
(ids[i].interface_class == interface_class &&
|
||||
ids[i].interface_subclass == interface_subclass &&
|
||||
ids[i].interface_protocol == interface_protocol))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int usb_get_quirks(uint16_t vendor_id, uint16_t product_id,
|
||||
uint8_t interface_class, uint8_t interface_subclass,
|
||||
uint8_t interface_protocol)
|
||||
{
|
||||
int quirks = 0;
|
||||
|
||||
if (usb_id_match(usbredir_raw_serial_ids, vendor_id, product_id,
|
||||
interface_class, interface_subclass, interface_protocol)) {
|
||||
quirks |= USB_QUIRK_BUFFER_BULK_IN;
|
||||
}
|
||||
if (usb_id_match(usbredir_ftdi_serial_ids, vendor_id, product_id,
|
||||
interface_class, interface_subclass, interface_protocol)) {
|
||||
quirks |= USB_QUIRK_BUFFER_BULK_IN | USB_QUIRK_IS_FTDI;
|
||||
}
|
||||
|
||||
return quirks;
|
||||
}
|
|
@ -0,0 +1,910 @@
|
|||
/*
|
||||
* USB quirk handling
|
||||
*
|
||||
* Copyright (c) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat Authors:
|
||||
* Hans de Goede <hdegoede@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/* 1 on 1 copy of linux/drivers/usb/serial/ftdi_sio_ids.h */
|
||||
#include "quirks-ftdi-ids.h"
|
||||
/* 1 on 1 copy of linux/drivers/usb/serial/pl2303.h */
|
||||
#include "quirks-pl2303-ids.h"
|
||||
|
||||
struct usb_device_id {
|
||||
int vendor_id;
|
||||
int product_id;
|
||||
int interface_class;
|
||||
int interface_subclass;
|
||||
int interface_protocol;
|
||||
};
|
||||
|
||||
#define USB_DEVICE(vendor, product) \
|
||||
.vendor_id = vendor, .product_id = product, .interface_class = -1,
|
||||
|
||||
#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, iclass, isubclass, iproto) \
|
||||
.vendor_id = vend, .product_id = prod, .interface_class = iclass, \
|
||||
.interface_subclass = isubclass, .interface_protocol = iproto
|
||||
|
||||
static const struct usb_device_id usbredir_raw_serial_ids[] = {
|
||||
/*
|
||||
* Silicon Laboratories CP210x USB to RS232 serial adapter ids
|
||||
* copied from linux/drivers/usb/serial/cp210x.c
|
||||
*
|
||||
* Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
|
||||
*/
|
||||
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
|
||||
{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
|
||||
{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
|
||||
{ USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
|
||||
{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
|
||||
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
|
||||
{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
|
||||
{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
|
||||
{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
|
||||
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
|
||||
{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
|
||||
{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
|
||||
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
|
||||
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
|
||||
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
|
||||
{ USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
|
||||
{ USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */
|
||||
{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
|
||||
{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
|
||||
{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
|
||||
{ USB_DEVICE(0x10C4, 0x8044) }, /* Cygnal Debug Adapter */
|
||||
{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
|
||||
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
|
||||
{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
|
||||
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
|
||||
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
|
||||
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
|
||||
{ USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */
|
||||
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
|
||||
{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
|
||||
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
|
||||
{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
|
||||
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
|
||||
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
|
||||
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
|
||||
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
|
||||
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
|
||||
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
|
||||
{ USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
|
||||
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
|
||||
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
|
||||
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
|
||||
{ USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */
|
||||
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
|
||||
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
|
||||
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
|
||||
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
|
||||
{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
|
||||
{ USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */
|
||||
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
|
||||
{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
|
||||
{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
|
||||
{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
|
||||
{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
|
||||
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
|
||||
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
|
||||
{ USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
|
||||
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
|
||||
{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
|
||||
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
|
||||
{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
|
||||
{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
|
||||
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
|
||||
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
|
||||
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
||||
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
|
||||
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
|
||||
{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
|
||||
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
|
||||
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
|
||||
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
|
||||
{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
|
||||
{ USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
|
||||
{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
|
||||
{ USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
|
||||
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
|
||||
{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
|
||||
{ USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */
|
||||
{ USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */
|
||||
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
|
||||
{ USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */
|
||||
{ USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */
|
||||
{ USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */
|
||||
{ USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */
|
||||
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
|
||||
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
|
||||
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
|
||||
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
|
||||
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
|
||||
{ USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
|
||||
{ USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
|
||||
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
|
||||
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
|
||||
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
|
||||
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
|
||||
{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
|
||||
{ USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
|
||||
{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
|
||||
{ USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
|
||||
{ USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
|
||||
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
|
||||
|
||||
/*
|
||||
* Prolific pl2303 USB to RS232 serial adapter ids
|
||||
* copied from linux/drivers/usb/serial/pl2303.c
|
||||
*
|
||||
* Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Copyright (C) 2003 IBM Corp.
|
||||
*/
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
|
||||
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
|
||||
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
|
||||
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
|
||||
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
|
||||
{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
|
||||
{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
|
||||
{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
|
||||
{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
|
||||
{ USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1) },
|
||||
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65) },
|
||||
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75) },
|
||||
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) },
|
||||
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */
|
||||
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
|
||||
{ USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
|
||||
{ USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
|
||||
{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
|
||||
{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
|
||||
{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
|
||||
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
|
||||
{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
|
||||
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
|
||||
{ USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
|
||||
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
|
||||
{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
|
||||
{ USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
|
||||
|
||||
{ USB_DEVICE(-1, -1) } /* Terminating Entry */
|
||||
};
|
||||
|
||||
static const struct usb_device_id usbredir_ftdi_serial_ids[] = {
|
||||
/*
|
||||
* FTDI USB to RS232 serial adapter ids
|
||||
* copied from linux/drivers/usb/serial/ftdi_sio.c
|
||||
*
|
||||
* Copyright (C) 2009 - 2010
|
||||
* Johan Hovold (jhovold@gmail.com)
|
||||
* Copyright (C) 1999 - 2001
|
||||
* Greg Kroah-Hartman (greg@kroah.com)
|
||||
* Bill Ryder (bryder@sgi.com)
|
||||
* Copyright (C) 2002
|
||||
* Kuba Ober (kuba@mareimbrium.org)
|
||||
*/
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
|
||||
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
|
||||
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SPROG_II) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_633_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_631_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_635_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_URBAN_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_URBAN_1_PID) },
|
||||
{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
|
||||
{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_USBX_707_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
|
||||
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
|
||||
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
|
||||
{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
|
||||
{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_1) },
|
||||
{ USB_DEVICE(FTDI_VID, PROTEGO_R2X0) },
|
||||
{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
|
||||
{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E808_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E809_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80A_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80B_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80C_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80D_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80E_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E80F_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E888_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E889_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88A_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88B_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88C_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88D_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88E_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GUDEADS_E88F_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UR100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_ALC8500_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PYRAMID_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1000PC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_US485_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PICPRO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PCMCIA_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PK1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_RS232MON_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID) },
|
||||
/*
|
||||
* ELV devices:
|
||||
*/
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS550_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_EC3000_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS888_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_TWS550_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FEM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UTP8_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS444PC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_HS485_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UMS100_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_TFD128_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_FM3RX_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_WS777_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
|
||||
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
|
||||
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
|
||||
{ USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) },
|
||||
{ USB_DEVICE(FALCOM_VID, FALCOM_SAMBA_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) },
|
||||
{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
|
||||
{ USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
|
||||
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USPTL4_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_2_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2DR_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR2_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_USOPTL4DR_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_2W_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_485USB9F_4W_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_232USB9M_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_2W_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_485USBTB_4W_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_TTL5USB9M_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_TTL3USB9M_PID) },
|
||||
{ USB_DEVICE(BANDB_VID, BANDB_ZZ_PROG1_USB_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
|
||||
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_YS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y6_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y8_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_IC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_DB9_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_RS232_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_Y9_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
|
||||
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
||||
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
|
||||
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) },
|
||||
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
|
||||
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
|
||||
{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TTUSB_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ECLO_COM_1WIRE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) },
|
||||
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
|
||||
{ USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
|
||||
{ USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID) },
|
||||
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
|
||||
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) },
|
||||
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) },
|
||||
{ USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
|
||||
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
|
||||
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID) },
|
||||
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID) },
|
||||
{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID) },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
|
||||
|
||||
/* Papouch devices based on FTDI chip */
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485_2_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AP485_2_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB422_2_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485S_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB485C_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_LEC_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SB232_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_IRAMP_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK5_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO8x8_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x2_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO10x1_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO30x3_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO60x3_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO2x16_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO3x32_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_DRAK6_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_UPSUSB_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_MU_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_SIMUKEY_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_AD4USB_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMUX_PID) },
|
||||
{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_GMSR_PID) },
|
||||
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
|
||||
{ USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
|
||||
{ USB_DEVICE(ATMEL_VID, STK541_PID) },
|
||||
{ USB_DEVICE(DE_VID, STB_PID) },
|
||||
{ USB_DEVICE(DE_VID, WHT_PID) },
|
||||
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID) },
|
||||
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
|
||||
0xff, 0xff, 0x00) },
|
||||
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
|
||||
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID) },
|
||||
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
|
||||
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, PI_C865_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, PI_C857_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_C866_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_C663_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_C725_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_E517_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_C863_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_E861_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_C867_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_E609_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_E709_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_100F_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1011_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1012_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1013_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1014_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1015_PID) },
|
||||
{ USB_DEVICE(PI_VID, PI_1016_PID) },
|
||||
{ USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
|
||||
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, TI_XDS100V2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) },
|
||||
{ USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
|
||||
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID) },
|
||||
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
|
||||
|
||||
{ USB_DEVICE(-1, -1) } /* Terminating Entry */
|
||||
};
|
||||
|
||||
#undef USB_DEVICE
|
||||
#undef USB_DEVICE_AND_INTERFACE_INFO
|
|
@ -44,18 +44,26 @@
|
|||
#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */
|
||||
#define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
|
||||
#define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
|
||||
#define USBEP2I(usb_ep) (((usb_ep)->pid == USB_TOKEN_IN) ? \
|
||||
((usb_ep)->nr | 0x10) : ((usb_ep)->nr))
|
||||
#define I2USBEP(d, i) (usb_ep_get(&(d)->dev, \
|
||||
((i) & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT, \
|
||||
(i) & 0x0f))
|
||||
|
||||
typedef struct USBRedirDevice USBRedirDevice;
|
||||
|
||||
/* Struct to hold buffered packets (iso or int input packets) */
|
||||
/* Struct to hold buffered packets */
|
||||
struct buf_packet {
|
||||
uint8_t *data;
|
||||
int len;
|
||||
int status;
|
||||
void *free_on_destroy;
|
||||
uint16_t len;
|
||||
uint16_t offset;
|
||||
uint8_t status;
|
||||
QTAILQ_ENTRY(buf_packet)next;
|
||||
};
|
||||
|
||||
struct endp_data {
|
||||
USBRedirDevice *dev;
|
||||
uint8_t type;
|
||||
uint8_t interval;
|
||||
uint8_t interface; /* bInterfaceNumber this ep belongs to */
|
||||
|
@ -64,11 +72,14 @@ struct endp_data {
|
|||
uint8_t iso_error; /* For reporting iso errors to the HC */
|
||||
uint8_t interrupt_started;
|
||||
uint8_t interrupt_error;
|
||||
uint8_t bulk_receiving_enabled;
|
||||
uint8_t bulk_receiving_started;
|
||||
uint8_t bufpq_prefilled;
|
||||
uint8_t bufpq_dropping_packets;
|
||||
QTAILQ_HEAD(, buf_packet) bufpq;
|
||||
int32_t bufpq_size;
|
||||
int32_t bufpq_target_size;
|
||||
USBPacket *pending_async_packet;
|
||||
};
|
||||
|
||||
struct PacketIdQueueEntry {
|
||||
|
@ -102,6 +113,7 @@ struct USBRedirDevice {
|
|||
struct endp_data endpoint[MAX_ENDPOINTS];
|
||||
struct PacketIdQueue cancelled;
|
||||
struct PacketIdQueue already_in_flight;
|
||||
void (*buffered_bulk_in_complete)(USBRedirDevice *, USBPacket *, uint8_t);
|
||||
/* Data for device filtering */
|
||||
struct usb_redir_device_connect_header device_info;
|
||||
struct usb_redir_interface_info_header interface_info;
|
||||
|
@ -129,6 +141,8 @@ static void usbredir_interrupt_receiving_status(void *priv, uint64_t id,
|
|||
*interrupt_receiving_status);
|
||||
static void usbredir_bulk_streams_status(void *priv, uint64_t id,
|
||||
struct usb_redir_bulk_streams_status_header *bulk_streams_status);
|
||||
static void usbredir_bulk_receiving_status(void *priv, uint64_t id,
|
||||
struct usb_redir_bulk_receiving_status_header *bulk_receiving_status);
|
||||
static void usbredir_control_packet(void *priv, uint64_t id,
|
||||
struct usb_redir_control_packet_header *control_packet,
|
||||
uint8_t *data, int data_len);
|
||||
|
@ -141,6 +155,9 @@ static void usbredir_iso_packet(void *priv, uint64_t id,
|
|||
static void usbredir_interrupt_packet(void *priv, uint64_t id,
|
||||
struct usb_redir_interrupt_packet_header *interrupt_header,
|
||||
uint8_t *data, int data_len);
|
||||
static void usbredir_buffered_bulk_packet(void *priv, uint64_t id,
|
||||
struct usb_redir_buffered_bulk_packet_header *buffered_bulk_packet,
|
||||
uint8_t *data, int data_len);
|
||||
|
||||
static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
|
||||
int status);
|
||||
|
@ -314,12 +331,19 @@ static void packet_id_queue_empty(struct PacketIdQueue *q)
|
|||
static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
|
||||
{
|
||||
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
|
||||
int i = USBEP2I(p->ep);
|
||||
|
||||
if (p->combined) {
|
||||
usb_combined_packet_cancel(udev, p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->endpoint[i].pending_async_packet) {
|
||||
assert(dev->endpoint[i].pending_async_packet == p);
|
||||
dev->endpoint[i].pending_async_packet = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
packet_id_queue_add(&dev->cancelled, p->id);
|
||||
usbredirparser_send_cancel_data_packet(dev->parser, p->id);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
|
@ -338,6 +362,11 @@ static void usbredir_fill_already_in_flight_from_ep(USBRedirDevice *dev,
|
|||
{
|
||||
static USBPacket *p;
|
||||
|
||||
/* async handled packets for bulk receiving eps do not count as inflight */
|
||||
if (dev->endpoint[USBEP2I(ep)].bulk_receiving_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(p, &ep->queue, queue) {
|
||||
/* Skip combined packets, except for the first */
|
||||
if (p->combined && p != p->combined->first) {
|
||||
|
@ -385,8 +414,8 @@ static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
|
|||
return p;
|
||||
}
|
||||
|
||||
static void bufp_alloc(USBRedirDevice *dev,
|
||||
uint8_t *data, int len, int status, uint8_t ep)
|
||||
static void bufp_alloc(USBRedirDevice *dev, uint8_t *data, uint16_t len,
|
||||
uint8_t status, uint8_t ep, void *free_on_destroy)
|
||||
{
|
||||
struct buf_packet *bufp;
|
||||
|
||||
|
@ -410,7 +439,9 @@ static void bufp_alloc(USBRedirDevice *dev,
|
|||
bufp = g_malloc(sizeof(struct buf_packet));
|
||||
bufp->data = data;
|
||||
bufp->len = len;
|
||||
bufp->offset = 0;
|
||||
bufp->status = status;
|
||||
bufp->free_on_destroy = free_on_destroy;
|
||||
QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
|
||||
dev->endpoint[EP2I(ep)].bufpq_size++;
|
||||
}
|
||||
|
@ -420,7 +451,7 @@ static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
|
|||
{
|
||||
QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
|
||||
dev->endpoint[EP2I(ep)].bufpq_size--;
|
||||
free(bufp->data);
|
||||
free(bufp->free_on_destroy);
|
||||
g_free(bufp);
|
||||
}
|
||||
|
||||
|
@ -571,19 +602,162 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
|
|||
usbredir_free_bufpq(dev, ep);
|
||||
}
|
||||
|
||||
/*
|
||||
* The usb-host may poll the endpoint faster then our guest, resulting in lots
|
||||
* of smaller bulkp-s. The below buffered_bulk_in_complete* functions combine
|
||||
* data from multiple bulkp-s into a single packet, avoiding bufpq overflows.
|
||||
*/
|
||||
static void usbredir_buffered_bulk_add_data_to_packet(USBRedirDevice *dev,
|
||||
struct buf_packet *bulkp, int count, USBPacket *p, uint8_t ep)
|
||||
{
|
||||
usb_packet_copy(p, bulkp->data + bulkp->offset, count);
|
||||
bulkp->offset += count;
|
||||
if (bulkp->offset == bulkp->len) {
|
||||
/* Store status in the last packet with data from this bulkp */
|
||||
usbredir_handle_status(dev, p, bulkp->status);
|
||||
bufp_free(dev, bulkp, ep);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbredir_buffered_bulk_in_complete_raw(USBRedirDevice *dev,
|
||||
USBPacket *p, uint8_t ep)
|
||||
{
|
||||
struct buf_packet *bulkp;
|
||||
int count;
|
||||
|
||||
while ((bulkp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq)) &&
|
||||
p->actual_length < p->iov.size && p->status == USB_RET_SUCCESS) {
|
||||
count = bulkp->len - bulkp->offset;
|
||||
if (count > (p->iov.size - p->actual_length)) {
|
||||
count = p->iov.size - p->actual_length;
|
||||
}
|
||||
usbredir_buffered_bulk_add_data_to_packet(dev, bulkp, count, p, ep);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbredir_buffered_bulk_in_complete_ftdi(USBRedirDevice *dev,
|
||||
USBPacket *p, uint8_t ep)
|
||||
{
|
||||
const int maxp = dev->endpoint[EP2I(ep)].max_packet_size;
|
||||
uint8_t header[2] = { 0, 0 };
|
||||
struct buf_packet *bulkp;
|
||||
int count;
|
||||
|
||||
while ((bulkp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq)) &&
|
||||
p->actual_length < p->iov.size && p->status == USB_RET_SUCCESS) {
|
||||
if (bulkp->len < 2) {
|
||||
WARNING("malformed ftdi bulk in packet\n");
|
||||
bufp_free(dev, bulkp, ep);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((p->actual_length % maxp) == 0) {
|
||||
usb_packet_copy(p, bulkp->data, 2);
|
||||
memcpy(header, bulkp->data, 2);
|
||||
} else {
|
||||
if (bulkp->data[0] != header[0] || bulkp->data[1] != header[1]) {
|
||||
break; /* Different header, add to next packet */
|
||||
}
|
||||
}
|
||||
|
||||
if (bulkp->offset == 0) {
|
||||
bulkp->offset = 2; /* Skip header */
|
||||
}
|
||||
count = bulkp->len - bulkp->offset;
|
||||
/* Must repeat the header at maxp interval */
|
||||
if (count > (maxp - (p->actual_length % maxp))) {
|
||||
count = maxp - (p->actual_length % maxp);
|
||||
}
|
||||
usbredir_buffered_bulk_add_data_to_packet(dev, bulkp, count, p, ep);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbredir_buffered_bulk_in_complete(USBRedirDevice *dev,
|
||||
USBPacket *p, uint8_t ep)
|
||||
{
|
||||
p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
|
||||
dev->buffered_bulk_in_complete(dev, p, ep);
|
||||
DPRINTF("bulk-token-in ep %02X status %d len %d id %"PRIu64"\n",
|
||||
ep, p->status, p->actual_length, p->id);
|
||||
}
|
||||
|
||||
static void usbredir_handle_buffered_bulk_in_data(USBRedirDevice *dev,
|
||||
USBPacket *p, uint8_t ep)
|
||||
{
|
||||
/* Input bulk endpoint, buffered packet input */
|
||||
if (!dev->endpoint[EP2I(ep)].bulk_receiving_started) {
|
||||
int bpt;
|
||||
struct usb_redir_start_bulk_receiving_header start = {
|
||||
.endpoint = ep,
|
||||
.stream_id = 0,
|
||||
.no_transfers = 5,
|
||||
};
|
||||
/* Round bytes_per_transfer up to a multiple of max_packet_size */
|
||||
bpt = 512 + dev->endpoint[EP2I(ep)].max_packet_size - 1;
|
||||
bpt /= dev->endpoint[EP2I(ep)].max_packet_size;
|
||||
bpt *= dev->endpoint[EP2I(ep)].max_packet_size;
|
||||
start.bytes_per_transfer = bpt;
|
||||
/* No id, we look at the ep when receiving a status back */
|
||||
usbredirparser_send_start_bulk_receiving(dev->parser, 0, &start);
|
||||
usbredirparser_do_write(dev->parser);
|
||||
DPRINTF("bulk receiving started bytes/transfer %u count %d ep %02X\n",
|
||||
start.bytes_per_transfer, start.no_transfers, ep);
|
||||
dev->endpoint[EP2I(ep)].bulk_receiving_started = 1;
|
||||
/* We don't really want to drop bulk packets ever, but
|
||||
having some upper limit to how much we buffer is good. */
|
||||
dev->endpoint[EP2I(ep)].bufpq_target_size = 5000;
|
||||
dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0;
|
||||
}
|
||||
|
||||
if (QTAILQ_EMPTY(&dev->endpoint[EP2I(ep)].bufpq)) {
|
||||
DPRINTF("bulk-token-in ep %02X, no bulkp\n", ep);
|
||||
assert(dev->endpoint[EP2I(ep)].pending_async_packet == NULL);
|
||||
dev->endpoint[EP2I(ep)].pending_async_packet = p;
|
||||
p->status = USB_RET_ASYNC;
|
||||
return;
|
||||
}
|
||||
usbredir_buffered_bulk_in_complete(dev, p, ep);
|
||||
}
|
||||
|
||||
static void usbredir_stop_bulk_receiving(USBRedirDevice *dev, uint8_t ep)
|
||||
{
|
||||
struct usb_redir_stop_bulk_receiving_header stop_bulk = {
|
||||
.endpoint = ep,
|
||||
.stream_id = 0,
|
||||
};
|
||||
if (dev->endpoint[EP2I(ep)].bulk_receiving_started) {
|
||||
usbredirparser_send_stop_bulk_receiving(dev->parser, 0, &stop_bulk);
|
||||
DPRINTF("bulk receiving stopped ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].bulk_receiving_started = 0;
|
||||
}
|
||||
usbredir_free_bufpq(dev, ep);
|
||||
}
|
||||
|
||||
static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
|
||||
uint8_t ep)
|
||||
{
|
||||
struct usb_redir_bulk_packet_header bulk_packet;
|
||||
size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
|
||||
|
||||
DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id);
|
||||
const int maxp = dev->endpoint[EP2I(ep)].max_packet_size;
|
||||
|
||||
if (usbredir_already_in_flight(dev, p->id)) {
|
||||
p->status = USB_RET_ASYNC;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->endpoint[EP2I(ep)].bulk_receiving_enabled) {
|
||||
if (size != 0 && (size % maxp) == 0) {
|
||||
usbredir_handle_buffered_bulk_in_data(dev, p, ep);
|
||||
return;
|
||||
}
|
||||
WARNING("bulk recv invalid size %zd ep %02x, disabling\n", size, ep);
|
||||
assert(dev->endpoint[EP2I(ep)].pending_async_packet == NULL);
|
||||
usbredir_stop_bulk_receiving(dev, ep);
|
||||
dev->endpoint[EP2I(ep)].bulk_receiving_enabled = 0;
|
||||
}
|
||||
|
||||
DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id);
|
||||
|
||||
bulk_packet.endpoint = ep;
|
||||
bulk_packet.length = size;
|
||||
bulk_packet.stream_id = 0;
|
||||
|
@ -720,9 +894,6 @@ static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
|
|||
ERROR("handle_data called for control transfer on ep %02X\n", ep);
|
||||
p->status = USB_RET_NAK;
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
usbredir_handle_iso_data(dev, p, ep);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
if (p->state == USB_PACKET_SETUP && p->pid == USB_TOKEN_IN &&
|
||||
p->ep->pipeline) {
|
||||
|
@ -731,6 +902,9 @@ static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
|
|||
}
|
||||
usbredir_handle_bulk_data(dev, p, ep);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
usbredir_handle_iso_data(dev, p, ep);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (ep & USB_DIR_IN) {
|
||||
usbredir_handle_interrupt_in_data(dev, p, ep);
|
||||
|
@ -752,6 +926,36 @@ static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep)
|
|||
}
|
||||
}
|
||||
|
||||
static void usbredir_stop_ep(USBRedirDevice *dev, int i)
|
||||
{
|
||||
uint8_t ep = I2EP(i);
|
||||
|
||||
switch (dev->endpoint[i].type) {
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
if (ep & USB_DIR_IN) {
|
||||
usbredir_stop_bulk_receiving(dev, ep);
|
||||
}
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
usbredir_stop_iso_stream(dev, ep);
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (ep & USB_DIR_IN) {
|
||||
usbredir_stop_interrupt_receiving(dev, ep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
usbredir_free_bufpq(dev, ep);
|
||||
}
|
||||
|
||||
static void usbredir_ep_stopped(USBDevice *udev, USBEndpoint *uep)
|
||||
{
|
||||
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
|
||||
|
||||
usbredir_stop_ep(dev, USBEP2I(uep));
|
||||
usbredirparser_do_write(dev->parser);
|
||||
}
|
||||
|
||||
static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
|
||||
int config)
|
||||
{
|
||||
|
@ -761,17 +965,7 @@ static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
|
|||
DPRINTF("set config %d id %"PRIu64"\n", config, p->id);
|
||||
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
switch (dev->endpoint[i].type) {
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
usbredir_stop_iso_stream(dev, I2EP(i));
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (i & 0x10) {
|
||||
usbredir_stop_interrupt_receiving(dev, I2EP(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
usbredir_free_bufpq(dev, I2EP(i));
|
||||
usbredir_stop_ep(dev, i);
|
||||
}
|
||||
|
||||
set_config.configuration = config;
|
||||
|
@ -799,17 +993,7 @@ static void usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
|
|||
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
if (dev->endpoint[i].interface == interface) {
|
||||
switch (dev->endpoint[i].type) {
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
usbredir_stop_iso_stream(dev, I2EP(i));
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (i & 0x10) {
|
||||
usbredir_stop_interrupt_receiving(dev, I2EP(i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
usbredir_free_bufpq(dev, I2EP(i));
|
||||
usbredir_stop_ep(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -931,10 +1115,12 @@ static void usbredir_create_parser(USBRedirDevice *dev)
|
|||
dev->parser->interrupt_receiving_status_func =
|
||||
usbredir_interrupt_receiving_status;
|
||||
dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
|
||||
dev->parser->bulk_receiving_status_func = usbredir_bulk_receiving_status;
|
||||
dev->parser->control_packet_func = usbredir_control_packet;
|
||||
dev->parser->bulk_packet_func = usbredir_bulk_packet;
|
||||
dev->parser->iso_packet_func = usbredir_iso_packet;
|
||||
dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
|
||||
dev->parser->buffered_bulk_packet_func = usbredir_buffered_bulk_packet;
|
||||
dev->read_buf = NULL;
|
||||
dev->read_buf_size = 0;
|
||||
|
||||
|
@ -943,6 +1129,7 @@ static void usbredir_create_parser(USBRedirDevice *dev)
|
|||
usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size);
|
||||
usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids);
|
||||
usbredirparser_caps_set_cap(caps, usb_redir_cap_32bits_bulk_length);
|
||||
usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_receiving);
|
||||
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
flags |= usbredirparser_fl_no_hello;
|
||||
|
@ -969,6 +1156,8 @@ static void usbredir_do_attach(void *opaque)
|
|||
if ((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER) && !(
|
||||
usbredirparser_peer_has_cap(dev->parser,
|
||||
usb_redir_cap_ep_info_max_packet_size) &&
|
||||
usbredirparser_peer_has_cap(dev->parser,
|
||||
usb_redir_cap_32bits_bulk_length) &&
|
||||
usbredirparser_peer_has_cap(dev->parser,
|
||||
usb_redir_cap_64bits_ids))) {
|
||||
ERROR("usb-redir-host lacks capabilities needed for use with XHCI\n");
|
||||
|
@ -1051,6 +1240,18 @@ static void usbredir_vm_state_change(void *priv, int running, RunState state)
|
|||
}
|
||||
}
|
||||
|
||||
static void usbredir_init_endpoints(USBRedirDevice *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_ep_init(&dev->dev);
|
||||
memset(dev->endpoint, 0, sizeof(dev->endpoint));
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
dev->endpoint[i].dev = dev;
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbredir_initfn(USBDevice *udev)
|
||||
{
|
||||
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
|
||||
|
@ -1077,9 +1278,7 @@ static int usbredir_initfn(USBDevice *udev)
|
|||
|
||||
packet_id_queue_init(&dev->cancelled, dev, "cancelled");
|
||||
packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight");
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
usbredir_init_endpoints(dev);
|
||||
|
||||
/* We'll do the attach once we receive the speed from the usb-host */
|
||||
udev->auto_attach = 0;
|
||||
|
@ -1169,6 +1368,52 @@ error:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void usbredir_check_bulk_receiving(USBRedirDevice *dev)
|
||||
{
|
||||
int i, j, quirks;
|
||||
|
||||
if (!usbredirparser_peer_has_cap(dev->parser,
|
||||
usb_redir_cap_bulk_receiving)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) {
|
||||
dev->endpoint[i].bulk_receiving_enabled = 0;
|
||||
}
|
||||
for (i = 0; i < dev->interface_info.interface_count; i++) {
|
||||
quirks = usb_get_quirks(dev->device_info.vendor_id,
|
||||
dev->device_info.product_id,
|
||||
dev->interface_info.interface_class[i],
|
||||
dev->interface_info.interface_subclass[i],
|
||||
dev->interface_info.interface_protocol[i]);
|
||||
if (!(quirks & USB_QUIRK_BUFFER_BULK_IN)) {
|
||||
continue;
|
||||
}
|
||||
if (quirks & USB_QUIRK_IS_FTDI) {
|
||||
dev->buffered_bulk_in_complete =
|
||||
usbredir_buffered_bulk_in_complete_ftdi;
|
||||
} else {
|
||||
dev->buffered_bulk_in_complete =
|
||||
usbredir_buffered_bulk_in_complete_raw;
|
||||
}
|
||||
|
||||
for (j = EP2I(USB_DIR_IN); j < MAX_ENDPOINTS; j++) {
|
||||
if (dev->endpoint[j].interface ==
|
||||
dev->interface_info.interface[i] &&
|
||||
dev->endpoint[j].type == USB_ENDPOINT_XFER_BULK &&
|
||||
dev->endpoint[j].max_packet_size != 0) {
|
||||
dev->endpoint[j].bulk_receiving_enabled = 1;
|
||||
/*
|
||||
* With buffering pipelining is not necessary. Also packet
|
||||
* combining and bulk in buffering don't play nice together!
|
||||
*/
|
||||
I2USBEP(dev, j)->pipeline = false;
|
||||
break; /* Only buffer for the first ep of each intf */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* usbredirparser packet complete callbacks
|
||||
*/
|
||||
|
@ -1277,13 +1522,13 @@ static void usbredir_device_connect(void *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
usbredir_check_bulk_receiving(dev);
|
||||
qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
|
||||
}
|
||||
|
||||
static void usbredir_device_disconnect(void *priv)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
int i;
|
||||
|
||||
/* Stop any pending attaches */
|
||||
qemu_del_timer(dev->attach_timer);
|
||||
|
@ -1300,11 +1545,7 @@ static void usbredir_device_disconnect(void *priv)
|
|||
|
||||
/* Reset state so that the next dev connected starts with a clean slate */
|
||||
usbredir_cleanup_device_queues(dev);
|
||||
memset(dev->endpoint, 0, sizeof(dev->endpoint));
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
||||
}
|
||||
usb_ep_init(&dev->dev);
|
||||
usbredir_init_endpoints(dev);
|
||||
dev->interface_info.interface_count = NO_INTERFACE_INFO;
|
||||
dev->dev.addr = 0;
|
||||
dev->dev.speed = 0;
|
||||
|
@ -1320,9 +1561,10 @@ static void usbredir_interface_info(void *priv,
|
|||
|
||||
/*
|
||||
* If we receive interface info after the device has already been
|
||||
* connected (ie on a set_config), re-check the filter.
|
||||
* connected (ie on a set_config), re-check interface dependent things.
|
||||
*/
|
||||
if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
|
||||
usbredir_check_bulk_receiving(dev);
|
||||
if (usbredir_check_filter(dev)) {
|
||||
ERROR("Device no longer matches filter after interface info "
|
||||
"change, disconnecting!\n");
|
||||
|
@ -1354,11 +1596,10 @@ static void usbredir_set_pipeline(USBRedirDevice *dev, struct USBEndpoint *uep)
|
|||
static void usbredir_setup_usb_eps(USBRedirDevice *dev)
|
||||
{
|
||||
struct USBEndpoint *usb_ep;
|
||||
int i, pid;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
||||
pid = (i & 0x10) ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
usb_ep = usb_ep_get(&dev->dev, pid, i & 0x0f);
|
||||
usb_ep = I2USBEP(dev, i);
|
||||
usb_ep->type = dev->endpoint[i].type;
|
||||
usb_ep->ifnum = dev->endpoint[i].interface;
|
||||
usb_ep->max_packet_size = dev->endpoint[i].max_packet_size;
|
||||
|
@ -1424,6 +1665,7 @@ static void usbredir_ep_info(void *priv,
|
|||
return;
|
||||
}
|
||||
usbredir_setup_usb_eps(dev);
|
||||
usbredir_check_bulk_receiving(dev);
|
||||
}
|
||||
|
||||
static void usbredir_configuration_status(void *priv, uint64_t id,
|
||||
|
@ -1514,6 +1756,25 @@ static void usbredir_bulk_streams_status(void *priv, uint64_t id,
|
|||
{
|
||||
}
|
||||
|
||||
static void usbredir_bulk_receiving_status(void *priv, uint64_t id,
|
||||
struct usb_redir_bulk_receiving_status_header *bulk_receiving_status)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
uint8_t ep = bulk_receiving_status->endpoint;
|
||||
|
||||
DPRINTF("bulk recv status %d ep %02X id %"PRIu64"\n",
|
||||
bulk_receiving_status->status, ep, id);
|
||||
|
||||
if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].bulk_receiving_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bulk_receiving_status->status == usb_redir_stall) {
|
||||
DPRINTF("bulk receiving stopped by peer ep %02X\n", ep);
|
||||
dev->endpoint[EP2I(ep)].bulk_receiving_started = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbredir_control_packet(void *priv, uint64_t id,
|
||||
struct usb_redir_control_packet_header *control_packet,
|
||||
uint8_t *data, int data_len)
|
||||
|
@ -1619,7 +1880,7 @@ static void usbredir_iso_packet(void *priv, uint64_t id,
|
|||
}
|
||||
|
||||
/* bufp_alloc also adds the packet to the ep queue */
|
||||
bufp_alloc(dev, data, data_len, iso_packet->status, ep);
|
||||
bufp_alloc(dev, data, data_len, iso_packet->status, ep, data);
|
||||
}
|
||||
|
||||
static void usbredir_interrupt_packet(void *priv, uint64_t id,
|
||||
|
@ -1650,7 +1911,7 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
|
|||
}
|
||||
|
||||
/* bufp_alloc also adds the packet to the ep queue */
|
||||
bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
|
||||
bufp_alloc(dev, data, data_len, interrupt_packet->status, ep, data);
|
||||
} else {
|
||||
/*
|
||||
* We report output interrupt packets as completed directly upon
|
||||
|
@ -1663,6 +1924,52 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
|
|||
}
|
||||
}
|
||||
|
||||
static void usbredir_buffered_bulk_packet(void *priv, uint64_t id,
|
||||
struct usb_redir_buffered_bulk_packet_header *buffered_bulk_packet,
|
||||
uint8_t *data, int data_len)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
uint8_t status, ep = buffered_bulk_packet->endpoint;
|
||||
void *free_on_destroy;
|
||||
int i, len;
|
||||
|
||||
DPRINTF("buffered-bulk-in status %d ep %02X len %d id %"PRIu64"\n",
|
||||
buffered_bulk_packet->status, ep, data_len, id);
|
||||
|
||||
if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_BULK) {
|
||||
ERROR("received buffered-bulk packet for non bulk ep %02X\n", ep);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->endpoint[EP2I(ep)].bulk_receiving_started == 0) {
|
||||
DPRINTF("received buffered-bulk packet on not started ep %02X\n", ep);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Data must be in maxp chunks for buffered_bulk_add_*_data_to_packet */
|
||||
len = dev->endpoint[EP2I(ep)].max_packet_size;
|
||||
status = usb_redir_success;
|
||||
free_on_destroy = NULL;
|
||||
for (i = 0; i < data_len; i += len) {
|
||||
if (len >= (data_len - i)) {
|
||||
len = data_len - i;
|
||||
status = buffered_bulk_packet->status;
|
||||
free_on_destroy = data;
|
||||
}
|
||||
/* bufp_alloc also adds the packet to the ep queue */
|
||||
bufp_alloc(dev, data + i, len, status, ep, free_on_destroy);
|
||||
}
|
||||
|
||||
if (dev->endpoint[EP2I(ep)].pending_async_packet) {
|
||||
USBPacket *p = dev->endpoint[EP2I(ep)].pending_async_packet;
|
||||
dev->endpoint[EP2I(ep)].pending_async_packet = NULL;
|
||||
usbredir_buffered_bulk_in_complete(dev, p, ep);
|
||||
usb_packet_complete(&dev->dev, p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Migration code
|
||||
*/
|
||||
|
@ -1697,6 +2004,7 @@ static int usbredir_post_load(void *priv, int version_id)
|
|||
dev->dev.speedmask = (1 << dev->dev.speed);
|
||||
|
||||
usbredir_setup_usb_eps(dev);
|
||||
usbredir_check_bulk_receiving(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1768,22 +2076,27 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
|
|||
static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
|
||||
{
|
||||
struct endp_data *endp = priv;
|
||||
USBRedirDevice *dev = endp->dev;
|
||||
struct buf_packet *bufp;
|
||||
int remain = endp->bufpq_size;
|
||||
int len, i = 0;
|
||||
|
||||
qemu_put_be32(f, endp->bufpq_size);
|
||||
QTAILQ_FOREACH(bufp, &endp->bufpq, next) {
|
||||
qemu_put_be32(f, bufp->len);
|
||||
len = bufp->len - bufp->offset;
|
||||
DPRINTF("put_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size,
|
||||
len, bufp->status);
|
||||
qemu_put_be32(f, len);
|
||||
qemu_put_be32(f, bufp->status);
|
||||
qemu_put_buffer(f, bufp->data, bufp->len);
|
||||
remain--;
|
||||
qemu_put_buffer(f, bufp->data + bufp->offset, len);
|
||||
i++;
|
||||
}
|
||||
assert(remain == 0);
|
||||
assert(i == endp->bufpq_size);
|
||||
}
|
||||
|
||||
static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
|
||||
{
|
||||
struct endp_data *endp = priv;
|
||||
USBRedirDevice *dev = endp->dev;
|
||||
struct buf_packet *bufp;
|
||||
int i;
|
||||
|
||||
|
@ -1792,9 +2105,13 @@ static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
|
|||
bufp = g_malloc(sizeof(struct buf_packet));
|
||||
bufp->len = qemu_get_be32(f);
|
||||
bufp->status = qemu_get_be32(f);
|
||||
bufp->offset = 0;
|
||||
bufp->data = qemu_oom_check(malloc(bufp->len)); /* regular malloc! */
|
||||
bufp->free_on_destroy = bufp->data;
|
||||
qemu_get_buffer(f, bufp->data, bufp->len);
|
||||
QTAILQ_INSERT_TAIL(&endp->bufpq, bufp, next);
|
||||
DPRINTF("get_bufpq %d/%d len %d status %d\n", i + 1, endp->bufpq_size,
|
||||
bufp->len, bufp->status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1807,6 +2124,23 @@ static const VMStateInfo usbredir_ep_bufpq_vmstate_info = {
|
|||
|
||||
|
||||
/* For endp_data migration */
|
||||
static const VMStateDescription usbredir_bulk_receiving_vmstate = {
|
||||
.name = "usb-redir-ep/bulk-receiving",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(bulk_receiving_started, struct endp_data),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool usbredir_bulk_receiving_needed(void *priv)
|
||||
{
|
||||
struct endp_data *endp = priv;
|
||||
|
||||
return endp->bulk_receiving_started;
|
||||
}
|
||||
|
||||
static const VMStateDescription usbredir_ep_vmstate = {
|
||||
.name = "usb-redir-ep",
|
||||
.version_id = 1,
|
||||
|
@ -1833,6 +2167,14 @@ static const VMStateDescription usbredir_ep_vmstate = {
|
|||
},
|
||||
VMSTATE_INT32(bufpq_target_size, struct endp_data),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.subsections = (VMStateSubsection[]) {
|
||||
{
|
||||
.vmsd = &usbredir_bulk_receiving_vmstate,
|
||||
.needed = usbredir_bulk_receiving_needed,
|
||||
}, {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1994,6 +2336,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data)
|
|||
uc->handle_data = usbredir_handle_data;
|
||||
uc->handle_control = usbredir_handle_control;
|
||||
uc->flush_ep_queue = usbredir_flush_ep_queue;
|
||||
uc->ep_stopped = usbredir_ep_stopped;
|
||||
dc->vmsd = &usbredir_vmstate;
|
||||
dc->props = usbredir_properties;
|
||||
}
|
||||
|
|
|
@ -307,8 +307,6 @@ usb_uhci_frame_loop_stop_idle(void) ""
|
|||
usb_uhci_frame_loop_continue(void) ""
|
||||
usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x"
|
||||
usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x"
|
||||
usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x"
|
||||
usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x"
|
||||
usb_uhci_queue_add(uint32_t token) "token 0x%x"
|
||||
usb_uhci_queue_del(uint32_t token, const char *reason) "token 0x%x: %s"
|
||||
usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
|
||||
|
|
Loading…
Reference in New Issue