USB user interface
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1603 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
8738a8d079
commit
a594cfbf3e
@ -290,12 +290,14 @@ ifdef CONFIG_ADLIB
|
|||||||
SOUND_HW += fmopl.o adlib.o
|
SOUND_HW += fmopl.o adlib.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# USB layer
|
||||||
|
VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
|
||||||
|
|
||||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||||
# Hardware support
|
# Hardware support
|
||||||
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
||||||
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
|
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
|
||||||
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
|
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
|
||||||
VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
|
|
||||||
DEFINES += -DHAS_AUDIO
|
DEFINES += -DHAS_AUDIO
|
||||||
endif
|
endif
|
||||||
ifeq ($(TARGET_BASE_ARCH), ppc)
|
ifeq ($(TARGET_BASE_ARCH), ppc)
|
||||||
|
27
hw/pc.c
27
hw/pc.c
@ -42,6 +42,7 @@ static fdctrl_t *floppy_controller;
|
|||||||
static RTCState *rtc_state;
|
static RTCState *rtc_state;
|
||||||
static PITState *pit;
|
static PITState *pit;
|
||||||
static IOAPICState *ioapic;
|
static IOAPICState *ioapic;
|
||||||
|
static USBPort *usb_root_ports[2];
|
||||||
|
|
||||||
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
|
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
|
||||||
{
|
{
|
||||||
@ -625,32 +626,8 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
|
|||||||
cmos_init(ram_size, boot_device, bs_table);
|
cmos_init(ram_size, boot_device, bs_table);
|
||||||
|
|
||||||
if (pci_enabled && usb_enabled) {
|
if (pci_enabled && usb_enabled) {
|
||||||
USBPort *usb_root_ports[2];
|
|
||||||
USBDevice *usb_dev;
|
|
||||||
usb_uhci_init(pci_bus, usb_root_ports);
|
usb_uhci_init(pci_bus, usb_root_ports);
|
||||||
#if 0
|
usb_attach(usb_root_ports[0], vm_usb_hub);
|
||||||
{
|
|
||||||
USBPort *usb_hub1_ports[4];
|
|
||||||
USBPort *usb_hub2_ports[2];
|
|
||||||
/* test: we simulate a USB hub */
|
|
||||||
usb_dev = usb_hub_init(usb_hub1_ports, 4);
|
|
||||||
usb_attach(usb_root_ports[0], usb_dev);
|
|
||||||
|
|
||||||
/* test: we simulate a USB hub */
|
|
||||||
usb_dev = usb_hub_init(usb_hub2_ports, 2);
|
|
||||||
usb_attach(usb_hub1_ports[0], usb_dev);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
/* USB mouse */
|
|
||||||
usb_dev = usb_mouse_init();
|
|
||||||
usb_attach(usb_root_ports[0], usb_dev);
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
/* simulated hub with the host USB devices connected to it */
|
|
||||||
usb_dev = usb_host_hub_init();
|
|
||||||
usb_attach(usb_root_ports[0], usb_dev);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be done after all PCI devices are instanciated */
|
/* must be done after all PCI devices are instanciated */
|
||||||
|
@ -63,7 +63,6 @@
|
|||||||
typedef struct UHCIPort {
|
typedef struct UHCIPort {
|
||||||
USBPort port;
|
USBPort port;
|
||||||
uint16_t ctrl;
|
uint16_t ctrl;
|
||||||
USBDevice *dev; /* connected device */
|
|
||||||
} UHCIPort;
|
} UHCIPort;
|
||||||
|
|
||||||
typedef struct UHCIState {
|
typedef struct UHCIState {
|
||||||
@ -128,8 +127,8 @@ static void uhci_reset(UHCIState *s)
|
|||||||
for(i = 0; i < NB_PORTS; i++) {
|
for(i = 0; i < NB_PORTS; i++) {
|
||||||
port = &s->ports[i];
|
port = &s->ports[i];
|
||||||
port->ctrl = 0x0080;
|
port->ctrl = 0x0080;
|
||||||
if (port->dev)
|
if (port->port.dev)
|
||||||
uhci_attach(&port->port, port->dev);
|
uhci_attach(&port->port, port->port.dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +182,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
/* send reset on the USB bus */
|
/* send reset on the USB bus */
|
||||||
for(i = 0; i < NB_PORTS; i++) {
|
for(i = 0; i < NB_PORTS; i++) {
|
||||||
port = &s->ports[i];
|
port = &s->ports[i];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
dev->handle_packet(dev,
|
dev->handle_packet(dev,
|
||||||
USB_MSG_RESET, 0, 0, NULL, 0);
|
USB_MSG_RESET, 0, 0, NULL, 0);
|
||||||
@ -224,7 +223,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
if (n >= NB_PORTS)
|
if (n >= NB_PORTS)
|
||||||
return;
|
return;
|
||||||
port = &s->ports[n];
|
port = &s->ports[n];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
/* port reset */
|
/* port reset */
|
||||||
if ( (val & UHCI_PORT_RESET) &&
|
if ( (val & UHCI_PORT_RESET) &&
|
||||||
@ -320,7 +319,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
UHCIPort *port = &s->ports[port1->index];
|
UHCIPort *port = &s->ports[port1->index];
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if (port->dev) {
|
if (port->port.dev) {
|
||||||
usb_attach(port1, NULL);
|
usb_attach(port1, NULL);
|
||||||
}
|
}
|
||||||
/* set connect status */
|
/* set connect status */
|
||||||
@ -332,7 +331,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
port->ctrl |= UHCI_PORT_LSDA;
|
port->ctrl |= UHCI_PORT_LSDA;
|
||||||
else
|
else
|
||||||
port->ctrl &= ~UHCI_PORT_LSDA;
|
port->ctrl &= ~UHCI_PORT_LSDA;
|
||||||
port->dev = dev;
|
port->port.dev = dev;
|
||||||
/* send the attach message */
|
/* send the attach message */
|
||||||
dev->handle_packet(dev,
|
dev->handle_packet(dev,
|
||||||
USB_MSG_ATTACH, 0, 0, NULL, 0);
|
USB_MSG_ATTACH, 0, 0, NULL, 0);
|
||||||
@ -346,13 +345,13 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
port->ctrl &= ~UHCI_PORT_EN;
|
port->ctrl &= ~UHCI_PORT_EN;
|
||||||
port->ctrl |= UHCI_PORT_ENC;
|
port->ctrl |= UHCI_PORT_ENC;
|
||||||
}
|
}
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
/* send the detach message */
|
/* send the detach message */
|
||||||
dev->handle_packet(dev,
|
dev->handle_packet(dev,
|
||||||
USB_MSG_DETACH, 0, 0, NULL, 0);
|
USB_MSG_DETACH, 0, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
port->dev = NULL;
|
port->port.dev = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +385,7 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
|
|||||||
#endif
|
#endif
|
||||||
for(i = 0; i < NB_PORTS; i++) {
|
for(i = 0; i < NB_PORTS; i++) {
|
||||||
port = &s->ports[i];
|
port = &s->ports[i];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev && (port->ctrl & UHCI_PORT_EN)) {
|
if (dev && (port->ctrl & UHCI_PORT_EN)) {
|
||||||
ret = dev->handle_packet(dev, pid,
|
ret = dev->handle_packet(dev, pid,
|
||||||
devaddr, devep,
|
devaddr, devep,
|
||||||
|
15
hw/usb.c
15
hw/usb.c
@ -201,7 +201,6 @@ int set_usb_string(uint8_t *buf, const char *str)
|
|||||||
|
|
||||||
typedef struct USBHubPort {
|
typedef struct USBHubPort {
|
||||||
USBPort port;
|
USBPort port;
|
||||||
USBDevice *dev;
|
|
||||||
uint16_t wPortStatus;
|
uint16_t wPortStatus;
|
||||||
uint16_t wPortChange;
|
uint16_t wPortChange;
|
||||||
} USBHubPort;
|
} USBHubPort;
|
||||||
@ -342,7 +341,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
|
|||||||
USBHubPort *port = &s->ports[port1->index];
|
USBHubPort *port = &s->ports[port1->index];
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if (port->dev)
|
if (port->port.dev)
|
||||||
usb_attach(port1, NULL);
|
usb_attach(port1, NULL);
|
||||||
|
|
||||||
port->wPortStatus |= PORT_STAT_CONNECTION;
|
port->wPortStatus |= PORT_STAT_CONNECTION;
|
||||||
@ -351,9 +350,9 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
|
|||||||
port->wPortStatus |= PORT_STAT_LOW_SPEED;
|
port->wPortStatus |= PORT_STAT_LOW_SPEED;
|
||||||
else
|
else
|
||||||
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
|
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
|
||||||
port->dev = dev;
|
port->port.dev = dev;
|
||||||
} else {
|
} else {
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev) {
|
if (dev) {
|
||||||
port->wPortStatus &= ~PORT_STAT_CONNECTION;
|
port->wPortStatus &= ~PORT_STAT_CONNECTION;
|
||||||
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
||||||
@ -361,7 +360,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
|
|||||||
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
||||||
port->wPortChange |= PORT_STAT_C_ENABLE;
|
port->wPortChange |= PORT_STAT_C_ENABLE;
|
||||||
}
|
}
|
||||||
port->dev = NULL;
|
port->port.dev = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,7 +497,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
|
|||||||
if (n >= s->nb_ports)
|
if (n >= s->nb_ports)
|
||||||
goto fail;
|
goto fail;
|
||||||
port = &s->ports[n];
|
port = &s->ports[n];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
switch(value) {
|
switch(value) {
|
||||||
case PORT_SUSPEND:
|
case PORT_SUSPEND:
|
||||||
port->wPortStatus |= PORT_STAT_SUSPEND;
|
port->wPortStatus |= PORT_STAT_SUSPEND;
|
||||||
@ -529,7 +528,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
|
|||||||
if (n >= s->nb_ports)
|
if (n >= s->nb_ports)
|
||||||
goto fail;
|
goto fail;
|
||||||
port = &s->ports[n];
|
port = &s->ports[n];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
switch(value) {
|
switch(value) {
|
||||||
case PORT_ENABLE:
|
case PORT_ENABLE:
|
||||||
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
port->wPortStatus &= ~PORT_STAT_ENABLE;
|
||||||
@ -624,7 +623,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, int pid,
|
|||||||
|
|
||||||
for(i = 0; i < s->nb_ports; i++) {
|
for(i = 0; i < s->nb_ports; i++) {
|
||||||
port = &s->ports[i];
|
port = &s->ports[i];
|
||||||
dev = port->dev;
|
dev = port->port.dev;
|
||||||
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
|
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
|
||||||
ret = dev->handle_packet(dev, pid,
|
ret = dev->handle_packet(dev, pid,
|
||||||
devaddr, devep,
|
devaddr, devep,
|
||||||
|
18
hw/usb.h
18
hw/usb.h
@ -47,6 +47,20 @@
|
|||||||
//#define USB_STATE_CONFIGURED 5
|
//#define USB_STATE_CONFIGURED 5
|
||||||
#define USB_STATE_SUSPENDED 6
|
#define USB_STATE_SUSPENDED 6
|
||||||
|
|
||||||
|
#define USB_CLASS_AUDIO 1
|
||||||
|
#define USB_CLASS_COMM 2
|
||||||
|
#define USB_CLASS_HID 3
|
||||||
|
#define USB_CLASS_PHYSICAL 5
|
||||||
|
#define USB_CLASS_STILL_IMAGE 6
|
||||||
|
#define USB_CLASS_PRINTER 7
|
||||||
|
#define USB_CLASS_MASS_STORAGE 8
|
||||||
|
#define USB_CLASS_HUB 9
|
||||||
|
#define USB_CLASS_CDC_DATA 0x0a
|
||||||
|
#define USB_CLASS_CSCID 0x0b
|
||||||
|
#define USB_CLASS_CONTENT_SEC 0x0d
|
||||||
|
#define USB_CLASS_APP_SPEC 0xfe
|
||||||
|
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||||
|
|
||||||
#define USB_DIR_OUT 0
|
#define USB_DIR_OUT 0
|
||||||
#define USB_DIR_IN 0x80
|
#define USB_DIR_IN 0x80
|
||||||
|
|
||||||
@ -125,6 +139,7 @@ struct USBDevice {
|
|||||||
|
|
||||||
/* USB port on which a device can be connected */
|
/* USB port on which a device can be connected */
|
||||||
struct USBPort {
|
struct USBPort {
|
||||||
|
USBDevice *dev;
|
||||||
void (*attach)(USBPort *port, USBDevice *dev);
|
void (*attach)(USBPort *port, USBDevice *dev);
|
||||||
void *opaque;
|
void *opaque;
|
||||||
int index; /* internal port index, may be used with the opaque */
|
int index; /* internal port index, may be used with the opaque */
|
||||||
@ -143,7 +158,8 @@ USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports);
|
|||||||
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
|
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
|
||||||
|
|
||||||
/* usb-linux.c */
|
/* usb-linux.c */
|
||||||
USBDevice *usb_host_hub_init(void);
|
USBDevice *usb_host_device_open(const char *devname);
|
||||||
|
void usb_host_info(void);
|
||||||
|
|
||||||
/* usb-hid.c */
|
/* usb-hid.c */
|
||||||
USBDevice *usb_mouse_init(void);
|
USBDevice *usb_mouse_init(void);
|
||||||
|
@ -901,7 +901,6 @@ static void do_info_kqemu(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static term_cmd_t term_cmds[] = {
|
static term_cmd_t term_cmds[] = {
|
||||||
{ "help|?", "s?", do_help,
|
{ "help|?", "s?", do_help,
|
||||||
"[cmd]", "show the help" },
|
"[cmd]", "show the help" },
|
||||||
@ -948,6 +947,10 @@ static term_cmd_t term_cmds[] = {
|
|||||||
"", "send system power down event" },
|
"", "send system power down event" },
|
||||||
{ "sum", "ii", do_sum,
|
{ "sum", "ii", do_sum,
|
||||||
"addr size", "compute the checksum of a memory region" },
|
"addr size", "compute the checksum of a memory region" },
|
||||||
|
{ "usb_add", "s", do_usb_add,
|
||||||
|
"device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" },
|
||||||
|
{ "usb_del", "s", do_usb_del,
|
||||||
|
"device", "remove USB device 'bus.addr'" },
|
||||||
{ NULL, NULL, },
|
{ NULL, NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -978,6 +981,10 @@ static term_cmd_t info_cmds[] = {
|
|||||||
"", "show dynamic compiler info", },
|
"", "show dynamic compiler info", },
|
||||||
{ "kqemu", "", do_info_kqemu,
|
{ "kqemu", "", do_info_kqemu,
|
||||||
"", "show kqemu information", },
|
"", "show kqemu information", },
|
||||||
|
{ "usb", "", usb_info,
|
||||||
|
"", "show guest USB devices", },
|
||||||
|
{ "usbhost", "", usb_host_info,
|
||||||
|
"", "show host USB devices", },
|
||||||
{ NULL, NULL, },
|
{ NULL, NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
345
usb-linux.c
345
usb-linux.c
@ -40,9 +40,13 @@ struct usb_ctrltransfer {
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
//#define DEBUG
|
typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
|
||||||
|
int vendor_id, int product_id,
|
||||||
|
const char *product_name, int speed);
|
||||||
|
static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||||
|
const char *devname);
|
||||||
|
|
||||||
#define MAX_DEVICES 8
|
//#define DEBUG
|
||||||
|
|
||||||
#define USBDEVFS_PATH "/proc/bus/usb"
|
#define USBDEVFS_PATH "/proc/bus/usb"
|
||||||
|
|
||||||
@ -51,12 +55,6 @@ typedef struct USBHostDevice {
|
|||||||
int fd;
|
int fd;
|
||||||
} USBHostDevice;
|
} USBHostDevice;
|
||||||
|
|
||||||
typedef struct USBHostHubState {
|
|
||||||
USBDevice *hub_dev;
|
|
||||||
USBPort *hub_ports[MAX_DEVICES];
|
|
||||||
USBDevice *hub_devices[MAX_DEVICES];
|
|
||||||
} USBHostHubState;
|
|
||||||
|
|
||||||
static void usb_host_handle_reset(USBDevice *dev)
|
static void usb_host_handle_reset(USBDevice *dev)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@ -137,29 +135,26 @@ static int usb_host_handle_data(USBDevice *dev, int pid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_host_handle_packet(USBDevice *dev, int pid,
|
|
||||||
uint8_t devaddr, uint8_t devep,
|
|
||||||
uint8_t *data, int len)
|
|
||||||
{
|
|
||||||
return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: exclude high speed devices or implement EHCI */
|
/* XXX: exclude high speed devices or implement EHCI */
|
||||||
static void scan_host_device(USBHostHubState *s, const char *filename)
|
USBDevice *usb_host_device_open(const char *devname)
|
||||||
{
|
{
|
||||||
int fd, interface, ret, i;
|
int fd, interface, ret, i;
|
||||||
USBHostDevice *dev;
|
USBHostDevice *dev;
|
||||||
struct usbdevfs_connectinfo ci;
|
struct usbdevfs_connectinfo ci;
|
||||||
uint8_t descr[1024];
|
uint8_t descr[1024];
|
||||||
|
char buf[1024];
|
||||||
int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
|
int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
|
||||||
|
int bus_num, addr;
|
||||||
|
|
||||||
#ifdef DEBUG
|
if (usb_host_find_device(&bus_num, &addr, devname) < 0)
|
||||||
printf("scanning %s\n", filename);
|
return NULL;
|
||||||
#endif
|
|
||||||
fd = open(filename, O_RDWR);
|
snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
|
||||||
|
bus_num, addr);
|
||||||
|
fd = open(buf, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror(filename);
|
perror(buf);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the config description */
|
/* read the config description */
|
||||||
@ -180,22 +175,31 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
|
|||||||
nb_interfaces = descr[i + 4];
|
nb_interfaces = descr[i + 4];
|
||||||
if (nb_interfaces != 1) {
|
if (nb_interfaces != 1) {
|
||||||
/* NOTE: currently we grab only one interface */
|
/* NOTE: currently we grab only one interface */
|
||||||
|
fprintf(stderr, "usb_host: only one interface supported\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USBDEVFS_DISCONNECT
|
||||||
|
/* earlier Linux 2.4 do not support that */
|
||||||
|
ret = ioctl(fd, USBDEVFS_DISCONNECT);
|
||||||
|
if (ret < 0 && errno != ENODATA) {
|
||||||
|
perror("USBDEVFS_DISCONNECT");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XXX: only grab if all interfaces are free */
|
/* XXX: only grab if all interfaces are free */
|
||||||
interface = 0;
|
interface = 0;
|
||||||
ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
|
ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EBUSY) {
|
if (errno == EBUSY) {
|
||||||
#ifdef DEBUG
|
fprintf(stderr, "usb_host: device already grabbed\n");
|
||||||
printf("%s already grabbed\n", filename);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
perror("USBDEVFS_CLAIMINTERFACE");
|
perror("USBDEVFS_CLAIMINTERFACE");
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
|
ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
|
||||||
@ -205,21 +209,9 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s grabbed\n", filename);
|
printf("host USB device %d.%d grabbed\n", bus_num, addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* find a free slot */
|
|
||||||
for(i = 0; i < MAX_DEVICES; i++) {
|
|
||||||
if (!s->hub_devices[i])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == MAX_DEVICES) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf("too many host devices\n");
|
|
||||||
goto fail;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = qemu_mallocz(sizeof(USBHostDevice));
|
dev = qemu_mallocz(sizeof(USBHostDevice));
|
||||||
if (!dev)
|
if (!dev)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -228,80 +220,259 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
|
|||||||
dev->dev.speed = USB_SPEED_LOW;
|
dev->dev.speed = USB_SPEED_LOW;
|
||||||
else
|
else
|
||||||
dev->dev.speed = USB_SPEED_HIGH;
|
dev->dev.speed = USB_SPEED_HIGH;
|
||||||
dev->dev.handle_packet = usb_host_handle_packet;
|
dev->dev.handle_packet = usb_generic_handle_packet;
|
||||||
|
|
||||||
dev->dev.handle_reset = usb_host_handle_reset;
|
dev->dev.handle_reset = usb_host_handle_reset;
|
||||||
dev->dev.handle_control = usb_host_handle_control;
|
dev->dev.handle_control = usb_host_handle_control;
|
||||||
dev->dev.handle_data = usb_host_handle_data;
|
dev->dev.handle_data = usb_host_handle_data;
|
||||||
|
return (USBDevice *)dev;
|
||||||
s->hub_devices[i] = (USBDevice *)dev;
|
|
||||||
|
|
||||||
/* activate device on hub */
|
|
||||||
usb_attach(s->hub_ports[i], s->hub_devices[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_host_devices(USBHostHubState *s, const char *bus_path)
|
static int get_tag_value(char *buf, int buf_size,
|
||||||
|
const char *str, const char *tag,
|
||||||
|
const char *stopchars)
|
||||||
{
|
{
|
||||||
DIR *d;
|
const char *p;
|
||||||
struct dirent *de;
|
char *q;
|
||||||
char buf[1024];
|
p = strstr(str, tag);
|
||||||
|
if (!p)
|
||||||
|
return -1;
|
||||||
|
p += strlen(tag);
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
q = buf;
|
||||||
|
while (*p != '\0' && !strchr(stopchars, *p)) {
|
||||||
|
if ((q - buf) < (buf_size - 1))
|
||||||
|
*q++ = *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
*q = '\0';
|
||||||
|
return q - buf;
|
||||||
|
}
|
||||||
|
|
||||||
d = opendir(bus_path);
|
static int usb_host_scan(void *opaque, USBScanFunc *func)
|
||||||
if (!d)
|
{
|
||||||
return;
|
FILE *f;
|
||||||
|
char line[1024];
|
||||||
|
char buf[1024];
|
||||||
|
int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
|
||||||
|
int ret;
|
||||||
|
char product_name[512];
|
||||||
|
|
||||||
|
f = fopen(USBDEVFS_PATH "/devices", "r");
|
||||||
|
if (!f) {
|
||||||
|
term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
device_count = 0;
|
||||||
|
bus_num = addr = speed = class_id = product_id = vendor_id = 0;
|
||||||
|
ret = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
de = readdir(d);
|
if (fgets(line, sizeof(line), f) == NULL)
|
||||||
if (!de)
|
|
||||||
break;
|
break;
|
||||||
if (de->d_name[0] != '.') {
|
if (strlen(line) > 0)
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", bus_path, de->d_name);
|
line[strlen(line) - 1] = '\0';
|
||||||
scan_host_device(s, buf);
|
if (line[0] == 'T' && line[1] == ':') {
|
||||||
|
if (device_count) {
|
||||||
|
ret = func(opaque, bus_num, addr, class_id, vendor_id,
|
||||||
|
product_id, product_name, speed);
|
||||||
|
if (ret)
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
|
||||||
|
goto fail;
|
||||||
|
bus_num = atoi(buf);
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
|
||||||
|
goto fail;
|
||||||
|
addr = atoi(buf);
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
|
||||||
|
goto fail;
|
||||||
|
if (!strcmp(buf, "480"))
|
||||||
|
speed = USB_SPEED_HIGH;
|
||||||
|
else if (!strcmp(buf, "1.5"))
|
||||||
|
speed = USB_SPEED_LOW;
|
||||||
|
else
|
||||||
|
speed = USB_SPEED_FULL;
|
||||||
|
product_name[0] = '\0';
|
||||||
|
class_id = 0xff;
|
||||||
|
device_count++;
|
||||||
|
product_id = 0;
|
||||||
|
vendor_id = 0;
|
||||||
|
} else if (line[0] == 'P' && line[1] == ':') {
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
|
||||||
|
goto fail;
|
||||||
|
vendor_id = strtoul(buf, NULL, 16);
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
|
||||||
|
goto fail;
|
||||||
|
product_id = strtoul(buf, NULL, 16);
|
||||||
|
} else if (line[0] == 'S' && line[1] == ':') {
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
|
||||||
|
goto fail;
|
||||||
|
pstrcpy(product_name, sizeof(product_name), buf);
|
||||||
|
} else if (line[0] == 'D' && line[1] == ':') {
|
||||||
|
if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
|
||||||
|
goto fail;
|
||||||
|
class_id = strtoul(buf, NULL, 16);
|
||||||
|
}
|
||||||
|
fail: ;
|
||||||
|
}
|
||||||
|
if (device_count) {
|
||||||
|
ret = func(opaque, bus_num, addr, class_id, vendor_id,
|
||||||
|
product_id, product_name, speed);
|
||||||
|
}
|
||||||
|
the_end:
|
||||||
|
fclose(f);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct FindDeviceState {
|
||||||
|
int vendor_id;
|
||||||
|
int product_id;
|
||||||
|
int bus_num;
|
||||||
|
int addr;
|
||||||
|
} FindDeviceState;
|
||||||
|
|
||||||
|
static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
|
||||||
|
int class_id,
|
||||||
|
int vendor_id, int product_id,
|
||||||
|
const char *product_name, int speed)
|
||||||
|
{
|
||||||
|
FindDeviceState *s = opaque;
|
||||||
|
if (vendor_id == s->vendor_id &&
|
||||||
|
product_id == s->product_id) {
|
||||||
|
s->bus_num = bus_num;
|
||||||
|
s->addr = addr;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the syntax is :
|
||||||
|
'bus.addr' (decimal numbers) or
|
||||||
|
'vendor_id:product_id' (hexa numbers) */
|
||||||
|
static int usb_host_find_device(int *pbus_num, int *paddr,
|
||||||
|
const char *devname)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
int ret;
|
||||||
|
FindDeviceState fs;
|
||||||
|
|
||||||
|
p = strchr(devname, '.');
|
||||||
|
if (p) {
|
||||||
|
*pbus_num = strtoul(devname, NULL, 0);
|
||||||
|
*paddr = strtoul(p + 1, NULL, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p = strchr(devname, ':');
|
||||||
|
if (p) {
|
||||||
|
fs.vendor_id = strtoul(devname, NULL, 16);
|
||||||
|
fs.product_id = strtoul(p + 1, NULL, 16);
|
||||||
|
ret = usb_host_scan(&fs, usb_host_find_device_scan);
|
||||||
|
if (ret) {
|
||||||
|
*pbus_num = fs.bus_num;
|
||||||
|
*paddr = fs.addr;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(d);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_host_buses(USBHostHubState *s)
|
/**********************/
|
||||||
{
|
/* USB host device info */
|
||||||
DIR *d;
|
|
||||||
struct dirent *de;
|
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
d = opendir(USBDEVFS_PATH);
|
struct usb_class_info {
|
||||||
if (!d)
|
int class;
|
||||||
return;
|
const char *class_name;
|
||||||
for(;;) {
|
};
|
||||||
de = readdir(d);
|
|
||||||
if (!de)
|
static const struct usb_class_info usb_class_info[] = {
|
||||||
|
{ USB_CLASS_AUDIO, "Audio"},
|
||||||
|
{ USB_CLASS_COMM, "Communication"},
|
||||||
|
{ USB_CLASS_HID, "HID"},
|
||||||
|
{ USB_CLASS_HUB, "Hub" },
|
||||||
|
{ USB_CLASS_PHYSICAL, "Physical" },
|
||||||
|
{ USB_CLASS_PRINTER, "Printer" },
|
||||||
|
{ USB_CLASS_MASS_STORAGE, "Storage" },
|
||||||
|
{ USB_CLASS_CDC_DATA, "Data" },
|
||||||
|
{ USB_CLASS_APP_SPEC, "Application Specific" },
|
||||||
|
{ USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
|
||||||
|
{ USB_CLASS_STILL_IMAGE, "Still Image" },
|
||||||
|
{ USB_CLASS_CSCID, "Smart Card" },
|
||||||
|
{ USB_CLASS_CONTENT_SEC, "Content Security" },
|
||||||
|
{ -1, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *usb_class_str(uint8_t class)
|
||||||
|
{
|
||||||
|
const struct usb_class_info *p;
|
||||||
|
for(p = usb_class_info; p->class != -1; p++) {
|
||||||
|
if (p->class == class)
|
||||||
break;
|
break;
|
||||||
if (isdigit(de->d_name[0])) {
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", USBDEVFS_PATH, de->d_name);
|
|
||||||
scan_host_devices(s, buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
closedir(d);
|
return p->class_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual hub containing the USB devices of the host */
|
void usb_info_device(int bus_num, int addr, int class_id,
|
||||||
USBDevice *usb_host_hub_init(void)
|
int vendor_id, int product_id,
|
||||||
|
const char *product_name,
|
||||||
|
int speed)
|
||||||
{
|
{
|
||||||
USBHostHubState *s;
|
const char *class_str, *speed_str;
|
||||||
s = qemu_mallocz(sizeof(USBHostHubState));
|
|
||||||
if (!s)
|
switch(speed) {
|
||||||
return NULL;
|
case USB_SPEED_LOW:
|
||||||
s->hub_dev = usb_hub_init(s->hub_ports, MAX_DEVICES);
|
speed_str = "1.5";
|
||||||
if (!s->hub_dev) {
|
break;
|
||||||
free(s);
|
case USB_SPEED_FULL:
|
||||||
return NULL;
|
speed_str = "12";
|
||||||
|
break;
|
||||||
|
case USB_SPEED_HIGH:
|
||||||
|
speed_str = "480";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
speed_str = "?";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
scan_host_buses(s);
|
|
||||||
return s->hub_dev;
|
term_printf(" Device %d.%d, speed %s Mb/s\n",
|
||||||
|
bus_num, addr, speed_str);
|
||||||
|
class_str = usb_class_str(class_id);
|
||||||
|
if (class_str)
|
||||||
|
term_printf(" %s:", class_str);
|
||||||
|
else
|
||||||
|
term_printf(" Class %02x:", class_id);
|
||||||
|
term_printf(" USB device %04x:%04x", vendor_id, product_id);
|
||||||
|
if (product_name[0] != '\0')
|
||||||
|
term_printf(", %s", product_name);
|
||||||
|
term_printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usb_host_info_device(void *opaque, int bus_num, int addr,
|
||||||
|
int class_id,
|
||||||
|
int vendor_id, int product_id,
|
||||||
|
const char *product_name,
|
||||||
|
int speed)
|
||||||
|
{
|
||||||
|
usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
|
||||||
|
product_name, speed);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_host_info(void)
|
||||||
|
{
|
||||||
|
usb_host_scan(NULL, usb_host_info_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
void usb_host_info(void)
|
||||||
|
{
|
||||||
|
term_printf("USB host devices not supported\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: modify configure to compile the right host driver */
|
/* XXX: modify configure to compile the right host driver */
|
||||||
USBDevice *usb_host_hub_init(void)
|
USBDevice *usb_host_device_open(const char *devname)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
145
vl.c
145
vl.c
@ -154,6 +154,8 @@ CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
|||||||
int win2k_install_hack = 0;
|
int win2k_install_hack = 0;
|
||||||
#endif
|
#endif
|
||||||
int usb_enabled = 0;
|
int usb_enabled = 0;
|
||||||
|
USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
|
||||||
|
USBDevice *vm_usb_hub;
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* x86 ISA bus support */
|
/* x86 ISA bus support */
|
||||||
@ -1737,6 +1739,117 @@ static int net_fd_init(NetDriverState *nd, int fd)
|
|||||||
|
|
||||||
#endif /* !_WIN32 */
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* USB devices */
|
||||||
|
|
||||||
|
static int usb_device_add(const char *devname)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
USBDevice *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!vm_usb_hub)
|
||||||
|
return -1;
|
||||||
|
for(i = 0;i < MAX_VM_USB_PORTS; i++) {
|
||||||
|
if (!vm_usb_ports[i]->dev)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == MAX_VM_USB_PORTS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (strstart(devname, "host:", &p)) {
|
||||||
|
dev = usb_host_device_open(p);
|
||||||
|
if (!dev)
|
||||||
|
return -1;
|
||||||
|
} else if (!strcmp(devname, "mouse")) {
|
||||||
|
dev = usb_mouse_init();
|
||||||
|
if (!dev)
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
usb_attach(vm_usb_ports[i], dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usb_device_del(const char *devname)
|
||||||
|
{
|
||||||
|
USBDevice *dev;
|
||||||
|
int bus_num, addr, i;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if (!vm_usb_hub)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
p = strchr(devname, '.');
|
||||||
|
if (!p)
|
||||||
|
return -1;
|
||||||
|
bus_num = strtoul(devname, NULL, 0);
|
||||||
|
addr = strtoul(p + 1, NULL, 0);
|
||||||
|
if (bus_num != 0)
|
||||||
|
return -1;
|
||||||
|
for(i = 0;i < MAX_VM_USB_PORTS; i++) {
|
||||||
|
dev = vm_usb_ports[i]->dev;
|
||||||
|
if (dev && dev->addr == addr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == MAX_VM_USB_PORTS)
|
||||||
|
return -1;
|
||||||
|
usb_attach(vm_usb_ports[i], NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_usb_add(const char *devname)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = usb_device_add(devname);
|
||||||
|
if (ret < 0)
|
||||||
|
term_printf("Could not add USB device '%s'\n", devname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_usb_del(const char *devname)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = usb_device_del(devname);
|
||||||
|
if (ret < 0)
|
||||||
|
term_printf("Could not remove USB device '%s'\n", devname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_info(void)
|
||||||
|
{
|
||||||
|
USBDevice *dev;
|
||||||
|
int i;
|
||||||
|
const char *speed_str;
|
||||||
|
|
||||||
|
if (!vm_usb_hub) {
|
||||||
|
term_printf("USB support not enabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < MAX_VM_USB_PORTS; i++) {
|
||||||
|
dev = vm_usb_ports[i]->dev;
|
||||||
|
if (dev) {
|
||||||
|
term_printf("Hub port %d:\n", i);
|
||||||
|
switch(dev->speed) {
|
||||||
|
case USB_SPEED_LOW:
|
||||||
|
speed_str = "1.5";
|
||||||
|
break;
|
||||||
|
case USB_SPEED_FULL:
|
||||||
|
speed_str = "12";
|
||||||
|
break;
|
||||||
|
case USB_SPEED_HIGH:
|
||||||
|
speed_str = "480";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
speed_str = "?";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
term_printf(" Device %d.%d, speed %s Mb/s\n",
|
||||||
|
0, dev->addr, speed_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* pid file */
|
/* pid file */
|
||||||
|
|
||||||
@ -2989,6 +3102,7 @@ enum {
|
|||||||
QEMU_OPTION_no_kqemu,
|
QEMU_OPTION_no_kqemu,
|
||||||
QEMU_OPTION_win2k_hack,
|
QEMU_OPTION_win2k_hack,
|
||||||
QEMU_OPTION_usb,
|
QEMU_OPTION_usb,
|
||||||
|
QEMU_OPTION_usbdevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QEMUOption {
|
typedef struct QEMUOption {
|
||||||
@ -3063,9 +3177,10 @@ const QEMUOption qemu_options[] = {
|
|||||||
{ "full-screen", 0, QEMU_OPTION_full_screen },
|
{ "full-screen", 0, QEMU_OPTION_full_screen },
|
||||||
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
|
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
|
||||||
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
|
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack },
|
||||||
{ "usb", 0, QEMU_OPTION_usb },
|
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
|
||||||
|
|
||||||
/* temporary options */
|
/* temporary options */
|
||||||
|
{ "usb", 0, QEMU_OPTION_usb },
|
||||||
{ "pci", 0, QEMU_OPTION_pci },
|
{ "pci", 0, QEMU_OPTION_pci },
|
||||||
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
|
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
@ -3239,7 +3354,9 @@ int main(int argc, char **argv)
|
|||||||
int parallel_device_index;
|
int parallel_device_index;
|
||||||
const char *loadvm = NULL;
|
const char *loadvm = NULL;
|
||||||
QEMUMachine *machine;
|
QEMUMachine *machine;
|
||||||
|
char usb_devices[MAX_VM_USB_PORTS][128];
|
||||||
|
int usb_devices_index;
|
||||||
|
|
||||||
#if !defined(CONFIG_SOFTMMU)
|
#if !defined(CONFIG_SOFTMMU)
|
||||||
/* we never want that malloc() uses mmap() */
|
/* we never want that malloc() uses mmap() */
|
||||||
mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
|
mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
|
||||||
@ -3282,6 +3399,8 @@ int main(int argc, char **argv)
|
|||||||
parallel_devices[i][0] = '\0';
|
parallel_devices[i][0] = '\0';
|
||||||
parallel_device_index = 0;
|
parallel_device_index = 0;
|
||||||
|
|
||||||
|
usb_devices_index = 0;
|
||||||
|
|
||||||
nb_tun_fds = 0;
|
nb_tun_fds = 0;
|
||||||
net_if_type = -1;
|
net_if_type = -1;
|
||||||
nb_nics = 1;
|
nb_nics = 1;
|
||||||
@ -3653,6 +3772,17 @@ int main(int argc, char **argv)
|
|||||||
case QEMU_OPTION_usb:
|
case QEMU_OPTION_usb:
|
||||||
usb_enabled = 1;
|
usb_enabled = 1;
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_usbdevice:
|
||||||
|
usb_enabled = 1;
|
||||||
|
if (usb_devices_index >= MAX_VM_USB_PORTS) {
|
||||||
|
fprintf(stderr, "Too many USB devices\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
pstrcpy(usb_devices[usb_devices_index],
|
||||||
|
sizeof(usb_devices[usb_devices_index]),
|
||||||
|
optarg);
|
||||||
|
usb_devices_index++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3818,6 +3948,17 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init USB devices */
|
||||||
|
if (usb_enabled) {
|
||||||
|
vm_usb_hub = usb_hub_init(vm_usb_ports, MAX_VM_USB_PORTS);
|
||||||
|
for(i = 0; i < usb_devices_index; i++) {
|
||||||
|
if (usb_device_add(usb_devices[i]) < 0) {
|
||||||
|
fprintf(stderr, "Warning: could not add USB device %s\n",
|
||||||
|
usb_devices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* init CPU state */
|
/* init CPU state */
|
||||||
env = cpu_init();
|
env = cpu_init();
|
||||||
global_env = env;
|
global_env = env;
|
||||||
|
11
vl.h
11
vl.h
@ -862,6 +862,17 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq);
|
|||||||
|
|
||||||
#include "hw/usb.h"
|
#include "hw/usb.h"
|
||||||
|
|
||||||
|
/* usb ports of the VM */
|
||||||
|
|
||||||
|
#define MAX_VM_USB_PORTS 8
|
||||||
|
|
||||||
|
extern USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
|
||||||
|
extern USBDevice *vm_usb_hub;
|
||||||
|
|
||||||
|
void do_usb_add(const char *devname);
|
||||||
|
void do_usb_del(const char *devname);
|
||||||
|
void usb_info(void);
|
||||||
|
|
||||||
#endif /* defined(QEMU_TOOL) */
|
#endif /* defined(QEMU_TOOL) */
|
||||||
|
|
||||||
/* monitor.c */
|
/* monitor.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user