Commit a594cfbf3e1a38bc6f3908d7d0903d41e8ea9da8

Authored by bellard
1 parent 8738a8d0

USB user interface


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1603 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -290,12 +290,14 @@ ifdef CONFIG_ADLIB @@ -290,12 +290,14 @@ ifdef CONFIG_ADLIB
290 SOUND_HW += fmopl.o adlib.o 290 SOUND_HW += fmopl.o adlib.o
291 endif 291 endif
292 292
  293 +# USB layer
  294 +VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o
  295 +
293 ifeq ($(TARGET_BASE_ARCH), i386) 296 ifeq ($(TARGET_BASE_ARCH), i386)
294 # Hardware support 297 # Hardware support
295 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) 298 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
296 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o 299 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
297 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o 300 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
298 -VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o  
299 DEFINES += -DHAS_AUDIO 301 DEFINES += -DHAS_AUDIO
300 endif 302 endif
301 ifeq ($(TARGET_BASE_ARCH), ppc) 303 ifeq ($(TARGET_BASE_ARCH), ppc)
@@ -42,6 +42,7 @@ static fdctrl_t *floppy_controller; @@ -42,6 +42,7 @@ static fdctrl_t *floppy_controller;
42 static RTCState *rtc_state; 42 static RTCState *rtc_state;
43 static PITState *pit; 43 static PITState *pit;
44 static IOAPICState *ioapic; 44 static IOAPICState *ioapic;
  45 +static USBPort *usb_root_ports[2];
45 46
46 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) 47 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
47 { 48 {
@@ -625,32 +626,8 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, @@ -625,32 +626,8 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
625 cmos_init(ram_size, boot_device, bs_table); 626 cmos_init(ram_size, boot_device, bs_table);
626 627
627 if (pci_enabled && usb_enabled) { 628 if (pci_enabled && usb_enabled) {
628 - USBPort *usb_root_ports[2];  
629 - USBDevice *usb_dev;  
630 usb_uhci_init(pci_bus, usb_root_ports); 629 usb_uhci_init(pci_bus, usb_root_ports);
631 -#if 0  
632 - {  
633 - USBPort *usb_hub1_ports[4];  
634 - USBPort *usb_hub2_ports[2];  
635 - /* test: we simulate a USB hub */  
636 - usb_dev = usb_hub_init(usb_hub1_ports, 4);  
637 - usb_attach(usb_root_ports[0], usb_dev);  
638 -  
639 - /* test: we simulate a USB hub */  
640 - usb_dev = usb_hub_init(usb_hub2_ports, 2);  
641 - usb_attach(usb_hub1_ports[0], usb_dev);  
642 - }  
643 -#endif  
644 -#if 0  
645 - /* USB mouse */  
646 - usb_dev = usb_mouse_init();  
647 - usb_attach(usb_root_ports[0], usb_dev);  
648 -#endif  
649 -#if 1  
650 - /* simulated hub with the host USB devices connected to it */  
651 - usb_dev = usb_host_hub_init();  
652 - usb_attach(usb_root_ports[0], usb_dev);  
653 -#endif 630 + usb_attach(usb_root_ports[0], vm_usb_hub);
654 } 631 }
655 632
656 /* must be done after all PCI devices are instanciated */ 633 /* must be done after all PCI devices are instanciated */
hw/usb-uhci.c
@@ -63,7 +63,6 @@ @@ -63,7 +63,6 @@
63 typedef struct UHCIPort { 63 typedef struct UHCIPort {
64 USBPort port; 64 USBPort port;
65 uint16_t ctrl; 65 uint16_t ctrl;
66 - USBDevice *dev; /* connected device */  
67 } UHCIPort; 66 } UHCIPort;
68 67
69 typedef struct UHCIState { 68 typedef struct UHCIState {
@@ -128,8 +127,8 @@ static void uhci_reset(UHCIState *s) @@ -128,8 +127,8 @@ static void uhci_reset(UHCIState *s)
128 for(i = 0; i < NB_PORTS; i++) { 127 for(i = 0; i < NB_PORTS; i++) {
129 port = &s->ports[i]; 128 port = &s->ports[i];
130 port->ctrl = 0x0080; 129 port->ctrl = 0x0080;
131 - if (port->dev)  
132 - uhci_attach(&port->port, port->dev); 130 + if (port->port.dev)
  131 + uhci_attach(&port->port, port->port.dev);
133 } 132 }
134 } 133 }
135 134
@@ -183,7 +182,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) @@ -183,7 +182,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
183 /* send reset on the USB bus */ 182 /* send reset on the USB bus */
184 for(i = 0; i < NB_PORTS; i++) { 183 for(i = 0; i < NB_PORTS; i++) {
185 port = &s->ports[i]; 184 port = &s->ports[i];
186 - dev = port->dev; 185 + dev = port->port.dev;
187 if (dev) { 186 if (dev) {
188 dev->handle_packet(dev, 187 dev->handle_packet(dev,
189 USB_MSG_RESET, 0, 0, NULL, 0); 188 USB_MSG_RESET, 0, 0, NULL, 0);
@@ -224,7 +223,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val) @@ -224,7 +223,7 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
224 if (n >= NB_PORTS) 223 if (n >= NB_PORTS)
225 return; 224 return;
226 port = &s->ports[n]; 225 port = &s->ports[n];
227 - dev = port->dev; 226 + dev = port->port.dev;
228 if (dev) { 227 if (dev) {
229 /* port reset */ 228 /* port reset */
230 if ( (val & UHCI_PORT_RESET) && 229 if ( (val & UHCI_PORT_RESET) &&
@@ -320,7 +319,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -320,7 +319,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
320 UHCIPort *port = &s->ports[port1->index]; 319 UHCIPort *port = &s->ports[port1->index];
321 320
322 if (dev) { 321 if (dev) {
323 - if (port->dev) { 322 + if (port->port.dev) {
324 usb_attach(port1, NULL); 323 usb_attach(port1, NULL);
325 } 324 }
326 /* set connect status */ 325 /* set connect status */
@@ -332,7 +331,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -332,7 +331,7 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
332 port->ctrl |= UHCI_PORT_LSDA; 331 port->ctrl |= UHCI_PORT_LSDA;
333 else 332 else
334 port->ctrl &= ~UHCI_PORT_LSDA; 333 port->ctrl &= ~UHCI_PORT_LSDA;
335 - port->dev = dev; 334 + port->port.dev = dev;
336 /* send the attach message */ 335 /* send the attach message */
337 dev->handle_packet(dev, 336 dev->handle_packet(dev,
338 USB_MSG_ATTACH, 0, 0, NULL, 0); 337 USB_MSG_ATTACH, 0, 0, NULL, 0);
@@ -346,13 +345,13 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -346,13 +345,13 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
346 port->ctrl &= ~UHCI_PORT_EN; 345 port->ctrl &= ~UHCI_PORT_EN;
347 port->ctrl |= UHCI_PORT_ENC; 346 port->ctrl |= UHCI_PORT_ENC;
348 } 347 }
349 - dev = port->dev; 348 + dev = port->port.dev;
350 if (dev) { 349 if (dev) {
351 /* send the detach message */ 350 /* send the detach message */
352 dev->handle_packet(dev, 351 dev->handle_packet(dev,
353 USB_MSG_DETACH, 0, 0, NULL, 0); 352 USB_MSG_DETACH, 0, 0, NULL, 0);
354 } 353 }
355 - port->dev = NULL; 354 + port->port.dev = NULL;
356 } 355 }
357 } 356 }
358 357
@@ -386,7 +385,7 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid, @@ -386,7 +385,7 @@ static int uhci_broadcast_packet(UHCIState *s, uint8_t pid,
386 #endif 385 #endif
387 for(i = 0; i < NB_PORTS; i++) { 386 for(i = 0; i < NB_PORTS; i++) {
388 port = &s->ports[i]; 387 port = &s->ports[i];
389 - dev = port->dev; 388 + dev = port->port.dev;
390 if (dev && (port->ctrl & UHCI_PORT_EN)) { 389 if (dev && (port->ctrl & UHCI_PORT_EN)) {
391 ret = dev->handle_packet(dev, pid, 390 ret = dev->handle_packet(dev, pid,
392 devaddr, devep, 391 devaddr, devep,
hw/usb.c
@@ -201,7 +201,6 @@ int set_usb_string(uint8_t *buf, const char *str) @@ -201,7 +201,6 @@ int set_usb_string(uint8_t *buf, const char *str)
201 201
202 typedef struct USBHubPort { 202 typedef struct USBHubPort {
203 USBPort port; 203 USBPort port;
204 - USBDevice *dev;  
205 uint16_t wPortStatus; 204 uint16_t wPortStatus;
206 uint16_t wPortChange; 205 uint16_t wPortChange;
207 } USBHubPort; 206 } USBHubPort;
@@ -342,7 +341,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev) @@ -342,7 +341,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
342 USBHubPort *port = &s->ports[port1->index]; 341 USBHubPort *port = &s->ports[port1->index];
343 342
344 if (dev) { 343 if (dev) {
345 - if (port->dev) 344 + if (port->port.dev)
346 usb_attach(port1, NULL); 345 usb_attach(port1, NULL);
347 346
348 port->wPortStatus |= PORT_STAT_CONNECTION; 347 port->wPortStatus |= PORT_STAT_CONNECTION;
@@ -351,9 +350,9 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev) @@ -351,9 +350,9 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
351 port->wPortStatus |= PORT_STAT_LOW_SPEED; 350 port->wPortStatus |= PORT_STAT_LOW_SPEED;
352 else 351 else
353 port->wPortStatus &= ~PORT_STAT_LOW_SPEED; 352 port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
354 - port->dev = dev; 353 + port->port.dev = dev;
355 } else { 354 } else {
356 - dev = port->dev; 355 + dev = port->port.dev;
357 if (dev) { 356 if (dev) {
358 port->wPortStatus &= ~PORT_STAT_CONNECTION; 357 port->wPortStatus &= ~PORT_STAT_CONNECTION;
359 port->wPortChange |= PORT_STAT_C_CONNECTION; 358 port->wPortChange |= PORT_STAT_C_CONNECTION;
@@ -361,7 +360,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev) @@ -361,7 +360,7 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
361 port->wPortStatus &= ~PORT_STAT_ENABLE; 360 port->wPortStatus &= ~PORT_STAT_ENABLE;
362 port->wPortChange |= PORT_STAT_C_ENABLE; 361 port->wPortChange |= PORT_STAT_C_ENABLE;
363 } 362 }
364 - port->dev = NULL; 363 + port->port.dev = NULL;
365 } 364 }
366 } 365 }
367 } 366 }
@@ -498,7 +497,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value, @@ -498,7 +497,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
498 if (n >= s->nb_ports) 497 if (n >= s->nb_ports)
499 goto fail; 498 goto fail;
500 port = &s->ports[n]; 499 port = &s->ports[n];
501 - dev = port->dev; 500 + dev = port->port.dev;
502 switch(value) { 501 switch(value) {
503 case PORT_SUSPEND: 502 case PORT_SUSPEND:
504 port->wPortStatus |= PORT_STAT_SUSPEND; 503 port->wPortStatus |= PORT_STAT_SUSPEND;
@@ -529,7 +528,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value, @@ -529,7 +528,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
529 if (n >= s->nb_ports) 528 if (n >= s->nb_ports)
530 goto fail; 529 goto fail;
531 port = &s->ports[n]; 530 port = &s->ports[n];
532 - dev = port->dev; 531 + dev = port->port.dev;
533 switch(value) { 532 switch(value) {
534 case PORT_ENABLE: 533 case PORT_ENABLE:
535 port->wPortStatus &= ~PORT_STAT_ENABLE; 534 port->wPortStatus &= ~PORT_STAT_ENABLE;
@@ -624,7 +623,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, int pid, @@ -624,7 +623,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, int pid,
624 623
625 for(i = 0; i < s->nb_ports; i++) { 624 for(i = 0; i < s->nb_ports; i++) {
626 port = &s->ports[i]; 625 port = &s->ports[i];
627 - dev = port->dev; 626 + dev = port->port.dev;
628 if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) { 627 if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
629 ret = dev->handle_packet(dev, pid, 628 ret = dev->handle_packet(dev, pid,
630 devaddr, devep, 629 devaddr, devep,
hw/usb.h
@@ -47,6 +47,20 @@ @@ -47,6 +47,20 @@
47 //#define USB_STATE_CONFIGURED 5 47 //#define USB_STATE_CONFIGURED 5
48 #define USB_STATE_SUSPENDED 6 48 #define USB_STATE_SUSPENDED 6
49 49
  50 +#define USB_CLASS_AUDIO 1
  51 +#define USB_CLASS_COMM 2
  52 +#define USB_CLASS_HID 3
  53 +#define USB_CLASS_PHYSICAL 5
  54 +#define USB_CLASS_STILL_IMAGE 6
  55 +#define USB_CLASS_PRINTER 7
  56 +#define USB_CLASS_MASS_STORAGE 8
  57 +#define USB_CLASS_HUB 9
  58 +#define USB_CLASS_CDC_DATA 0x0a
  59 +#define USB_CLASS_CSCID 0x0b
  60 +#define USB_CLASS_CONTENT_SEC 0x0d
  61 +#define USB_CLASS_APP_SPEC 0xfe
  62 +#define USB_CLASS_VENDOR_SPEC 0xff
  63 +
50 #define USB_DIR_OUT 0 64 #define USB_DIR_OUT 0
51 #define USB_DIR_IN 0x80 65 #define USB_DIR_IN 0x80
52 66
@@ -125,6 +139,7 @@ struct USBDevice { @@ -125,6 +139,7 @@ struct USBDevice {
125 139
126 /* USB port on which a device can be connected */ 140 /* USB port on which a device can be connected */
127 struct USBPort { 141 struct USBPort {
  142 + USBDevice *dev;
128 void (*attach)(USBPort *port, USBDevice *dev); 143 void (*attach)(USBPort *port, USBDevice *dev);
129 void *opaque; 144 void *opaque;
130 int index; /* internal port index, may be used with the opaque */ 145 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); @@ -143,7 +158,8 @@ USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports);
143 void usb_uhci_init(PCIBus *bus, USBPort **usb_ports); 158 void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
144 159
145 /* usb-linux.c */ 160 /* usb-linux.c */
146 -USBDevice *usb_host_hub_init(void); 161 +USBDevice *usb_host_device_open(const char *devname);
  162 +void usb_host_info(void);
147 163
148 /* usb-hid.c */ 164 /* usb-hid.c */
149 USBDevice *usb_mouse_init(void); 165 USBDevice *usb_mouse_init(void);
monitor.c
@@ -901,7 +901,6 @@ static void do_info_kqemu(void) @@ -901,7 +901,6 @@ static void do_info_kqemu(void)
901 #endif 901 #endif
902 } 902 }
903 903
904 -  
905 static term_cmd_t term_cmds[] = { 904 static term_cmd_t term_cmds[] = {
906 { "help|?", "s?", do_help, 905 { "help|?", "s?", do_help,
907 "[cmd]", "show the help" }, 906 "[cmd]", "show the help" },
@@ -948,6 +947,10 @@ static term_cmd_t term_cmds[] = { @@ -948,6 +947,10 @@ static term_cmd_t term_cmds[] = {
948 "", "send system power down event" }, 947 "", "send system power down event" },
949 { "sum", "ii", do_sum, 948 { "sum", "ii", do_sum,
950 "addr size", "compute the checksum of a memory region" }, 949 "addr size", "compute the checksum of a memory region" },
  950 + { "usb_add", "s", do_usb_add,
  951 + "device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" },
  952 + { "usb_del", "s", do_usb_del,
  953 + "device", "remove USB device 'bus.addr'" },
951 { NULL, NULL, }, 954 { NULL, NULL, },
952 }; 955 };
953 956
@@ -978,6 +981,10 @@ static term_cmd_t info_cmds[] = { @@ -978,6 +981,10 @@ static term_cmd_t info_cmds[] = {
978 "", "show dynamic compiler info", }, 981 "", "show dynamic compiler info", },
979 { "kqemu", "", do_info_kqemu, 982 { "kqemu", "", do_info_kqemu,
980 "", "show kqemu information", }, 983 "", "show kqemu information", },
  984 + { "usb", "", usb_info,
  985 + "", "show guest USB devices", },
  986 + { "usbhost", "", usb_host_info,
  987 + "", "show host USB devices", },
981 { NULL, NULL, }, 988 { NULL, NULL, },
982 }; 989 };
983 990
usb-linux.c
@@ -40,9 +40,13 @@ struct usb_ctrltransfer { @@ -40,9 +40,13 @@ struct usb_ctrltransfer {
40 void *data; 40 void *data;
41 }; 41 };
42 42
43 -//#define DEBUG 43 +typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
  44 + int vendor_id, int product_id,
  45 + const char *product_name, int speed);
  46 +static int usb_host_find_device(int *pbus_num, int *paddr,
  47 + const char *devname);
44 48
45 -#define MAX_DEVICES 8 49 +//#define DEBUG
46 50
47 #define USBDEVFS_PATH "/proc/bus/usb" 51 #define USBDEVFS_PATH "/proc/bus/usb"
48 52
@@ -51,12 +55,6 @@ typedef struct USBHostDevice { @@ -51,12 +55,6 @@ typedef struct USBHostDevice {
51 int fd; 55 int fd;
52 } USBHostDevice; 56 } USBHostDevice;
53 57
54 -typedef struct USBHostHubState {  
55 - USBDevice *hub_dev;  
56 - USBPort *hub_ports[MAX_DEVICES];  
57 - USBDevice *hub_devices[MAX_DEVICES];  
58 -} USBHostHubState;  
59 -  
60 static void usb_host_handle_reset(USBDevice *dev) 58 static void usb_host_handle_reset(USBDevice *dev)
61 { 59 {
62 #if 0 60 #if 0
@@ -137,29 +135,26 @@ static int usb_host_handle_data(USBDevice *dev, int pid, @@ -137,29 +135,26 @@ static int usb_host_handle_data(USBDevice *dev, int pid,
137 } 135 }
138 } 136 }
139 137
140 -static int usb_host_handle_packet(USBDevice *dev, int pid,  
141 - uint8_t devaddr, uint8_t devep,  
142 - uint8_t *data, int len)  
143 -{  
144 - return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);  
145 -}  
146 -  
147 /* XXX: exclude high speed devices or implement EHCI */ 138 /* XXX: exclude high speed devices or implement EHCI */
148 -static void scan_host_device(USBHostHubState *s, const char *filename) 139 +USBDevice *usb_host_device_open(const char *devname)
149 { 140 {
150 int fd, interface, ret, i; 141 int fd, interface, ret, i;
151 USBHostDevice *dev; 142 USBHostDevice *dev;
152 struct usbdevfs_connectinfo ci; 143 struct usbdevfs_connectinfo ci;
153 uint8_t descr[1024]; 144 uint8_t descr[1024];
  145 + char buf[1024];
154 int descr_len, dev_descr_len, config_descr_len, nb_interfaces; 146 int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
  147 + int bus_num, addr;
155 148
156 -#ifdef DEBUG  
157 - printf("scanning %s\n", filename);  
158 -#endif  
159 - fd = open(filename, O_RDWR); 149 + if (usb_host_find_device(&bus_num, &addr, devname) < 0)
  150 + return NULL;
  151 +
  152 + snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
  153 + bus_num, addr);
  154 + fd = open(buf, O_RDWR);
160 if (fd < 0) { 155 if (fd < 0) {
161 - perror(filename);  
162 - return; 156 + perror(buf);
  157 + return NULL;
163 } 158 }
164 159
165 /* read the config description */ 160 /* read the config description */
@@ -180,22 +175,31 @@ static void scan_host_device(USBHostHubState *s, const char *filename) @@ -180,22 +175,31 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
180 nb_interfaces = descr[i + 4]; 175 nb_interfaces = descr[i + 4];
181 if (nb_interfaces != 1) { 176 if (nb_interfaces != 1) {
182 /* NOTE: currently we grab only one interface */ 177 /* NOTE: currently we grab only one interface */
  178 + fprintf(stderr, "usb_host: only one interface supported\n");
  179 + goto fail;
  180 + }
  181 +
  182 +#ifdef USBDEVFS_DISCONNECT
  183 + /* earlier Linux 2.4 do not support that */
  184 + ret = ioctl(fd, USBDEVFS_DISCONNECT);
  185 + if (ret < 0 && errno != ENODATA) {
  186 + perror("USBDEVFS_DISCONNECT");
183 goto fail; 187 goto fail;
184 } 188 }
  189 +#endif
  190 +
185 /* XXX: only grab if all interfaces are free */ 191 /* XXX: only grab if all interfaces are free */
186 interface = 0; 192 interface = 0;
187 ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface); 193 ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
188 if (ret < 0) { 194 if (ret < 0) {
189 if (errno == EBUSY) { 195 if (errno == EBUSY) {
190 -#ifdef DEBUG  
191 - printf("%s already grabbed\n", filename);  
192 -#endif 196 + fprintf(stderr, "usb_host: device already grabbed\n");
193 } else { 197 } else {
194 perror("USBDEVFS_CLAIMINTERFACE"); 198 perror("USBDEVFS_CLAIMINTERFACE");
195 } 199 }
196 fail: 200 fail:
197 close(fd); 201 close(fd);
198 - return; 202 + return NULL;
199 } 203 }
200 204
201 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); 205 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
@@ -205,21 +209,9 @@ static void scan_host_device(USBHostHubState *s, const char *filename) @@ -205,21 +209,9 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
205 } 209 }
206 210
207 #ifdef DEBUG 211 #ifdef DEBUG
208 - printf("%s grabbed\n", filename); 212 + printf("host USB device %d.%d grabbed\n", bus_num, addr);
209 #endif 213 #endif
210 214
211 - /* find a free slot */  
212 - for(i = 0; i < MAX_DEVICES; i++) {  
213 - if (!s->hub_devices[i])  
214 - break;  
215 - }  
216 - if (i == MAX_DEVICES) {  
217 -#ifdef DEBUG  
218 - printf("too many host devices\n");  
219 - goto fail;  
220 -#endif  
221 - }  
222 -  
223 dev = qemu_mallocz(sizeof(USBHostDevice)); 215 dev = qemu_mallocz(sizeof(USBHostDevice));
224 if (!dev) 216 if (!dev)
225 goto fail; 217 goto fail;
@@ -228,80 +220,259 @@ static void scan_host_device(USBHostHubState *s, const char *filename) @@ -228,80 +220,259 @@ static void scan_host_device(USBHostHubState *s, const char *filename)
228 dev->dev.speed = USB_SPEED_LOW; 220 dev->dev.speed = USB_SPEED_LOW;
229 else 221 else
230 dev->dev.speed = USB_SPEED_HIGH; 222 dev->dev.speed = USB_SPEED_HIGH;
231 - dev->dev.handle_packet = usb_host_handle_packet; 223 + dev->dev.handle_packet = usb_generic_handle_packet;
232 224
233 dev->dev.handle_reset = usb_host_handle_reset; 225 dev->dev.handle_reset = usb_host_handle_reset;
234 dev->dev.handle_control = usb_host_handle_control; 226 dev->dev.handle_control = usb_host_handle_control;
235 dev->dev.handle_data = usb_host_handle_data; 227 dev->dev.handle_data = usb_host_handle_data;
  228 + return (USBDevice *)dev;
  229 +}
236 230
237 - s->hub_devices[i] = (USBDevice *)dev;  
238 -  
239 - /* activate device on hub */  
240 - usb_attach(s->hub_ports[i], s->hub_devices[i]); 231 +static int get_tag_value(char *buf, int buf_size,
  232 + const char *str, const char *tag,
  233 + const char *stopchars)
  234 +{
  235 + const char *p;
  236 + char *q;
  237 + p = strstr(str, tag);
  238 + if (!p)
  239 + return -1;
  240 + p += strlen(tag);
  241 + while (isspace(*p))
  242 + p++;
  243 + q = buf;
  244 + while (*p != '\0' && !strchr(stopchars, *p)) {
  245 + if ((q - buf) < (buf_size - 1))
  246 + *q++ = *p;
  247 + p++;
  248 + }
  249 + *q = '\0';
  250 + return q - buf;
241 } 251 }
242 252
243 -static void scan_host_devices(USBHostHubState *s, const char *bus_path) 253 +static int usb_host_scan(void *opaque, USBScanFunc *func)
244 { 254 {
245 - DIR *d;  
246 - struct dirent *de; 255 + FILE *f;
  256 + char line[1024];
247 char buf[1024]; 257 char buf[1024];
248 -  
249 - d = opendir(bus_path);  
250 - if (!d)  
251 - return; 258 + int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
  259 + int ret;
  260 + char product_name[512];
  261 +
  262 + f = fopen(USBDEVFS_PATH "/devices", "r");
  263 + if (!f) {
  264 + term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
  265 + return 0;
  266 + }
  267 + device_count = 0;
  268 + bus_num = addr = speed = class_id = product_id = vendor_id = 0;
  269 + ret = 0;
252 for(;;) { 270 for(;;) {
253 - de = readdir(d);  
254 - if (!de) 271 + if (fgets(line, sizeof(line), f) == NULL)
255 break; 272 break;
256 - if (de->d_name[0] != '.') {  
257 - snprintf(buf, sizeof(buf), "%s/%s", bus_path, de->d_name);  
258 - scan_host_device(s, buf); 273 + if (strlen(line) > 0)
  274 + line[strlen(line) - 1] = '\0';
  275 + if (line[0] == 'T' && line[1] == ':') {
  276 + if (device_count) {
  277 + ret = func(opaque, bus_num, addr, class_id, vendor_id,
  278 + product_id, product_name, speed);
  279 + if (ret)
  280 + goto the_end;
  281 + }
  282 + if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
  283 + goto fail;
  284 + bus_num = atoi(buf);
  285 + if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
  286 + goto fail;
  287 + addr = atoi(buf);
  288 + if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
  289 + goto fail;
  290 + if (!strcmp(buf, "480"))
  291 + speed = USB_SPEED_HIGH;
  292 + else if (!strcmp(buf, "1.5"))
  293 + speed = USB_SPEED_LOW;
  294 + else
  295 + speed = USB_SPEED_FULL;
  296 + product_name[0] = '\0';
  297 + class_id = 0xff;
  298 + device_count++;
  299 + product_id = 0;
  300 + vendor_id = 0;
  301 + } else if (line[0] == 'P' && line[1] == ':') {
  302 + if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
  303 + goto fail;
  304 + vendor_id = strtoul(buf, NULL, 16);
  305 + if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
  306 + goto fail;
  307 + product_id = strtoul(buf, NULL, 16);
  308 + } else if (line[0] == 'S' && line[1] == ':') {
  309 + if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
  310 + goto fail;
  311 + pstrcpy(product_name, sizeof(product_name), buf);
  312 + } else if (line[0] == 'D' && line[1] == ':') {
  313 + if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
  314 + goto fail;
  315 + class_id = strtoul(buf, NULL, 16);
259 } 316 }
  317 + fail: ;
  318 + }
  319 + if (device_count) {
  320 + ret = func(opaque, bus_num, addr, class_id, vendor_id,
  321 + product_id, product_name, speed);
260 } 322 }
261 - closedir(d); 323 + the_end:
  324 + fclose(f);
  325 + return ret;
262 } 326 }
263 327
264 -static void scan_host_buses(USBHostHubState *s) 328 +typedef struct FindDeviceState {
  329 + int vendor_id;
  330 + int product_id;
  331 + int bus_num;
  332 + int addr;
  333 +} FindDeviceState;
  334 +
  335 +static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
  336 + int class_id,
  337 + int vendor_id, int product_id,
  338 + const char *product_name, int speed)
265 { 339 {
266 - DIR *d;  
267 - struct dirent *de;  
268 - char buf[1024]; 340 + FindDeviceState *s = opaque;
  341 + if (vendor_id == s->vendor_id &&
  342 + product_id == s->product_id) {
  343 + s->bus_num = bus_num;
  344 + s->addr = addr;
  345 + return 1;
  346 + } else {
  347 + return 0;
  348 + }
  349 +}
269 350
270 - d = opendir(USBDEVFS_PATH);  
271 - if (!d)  
272 - return;  
273 - for(;;) {  
274 - de = readdir(d);  
275 - if (!de)  
276 - break;  
277 - if (isdigit(de->d_name[0])) {  
278 - snprintf(buf, sizeof(buf), "%s/%s", USBDEVFS_PATH, de->d_name);  
279 - scan_host_devices(s, buf); 351 +/* the syntax is :
  352 + 'bus.addr' (decimal numbers) or
  353 + 'vendor_id:product_id' (hexa numbers) */
  354 +static int usb_host_find_device(int *pbus_num, int *paddr,
  355 + const char *devname)
  356 +{
  357 + const char *p;
  358 + int ret;
  359 + FindDeviceState fs;
  360 +
  361 + p = strchr(devname, '.');
  362 + if (p) {
  363 + *pbus_num = strtoul(devname, NULL, 0);
  364 + *paddr = strtoul(p + 1, NULL, 0);
  365 + return 0;
  366 + }
  367 + p = strchr(devname, ':');
  368 + if (p) {
  369 + fs.vendor_id = strtoul(devname, NULL, 16);
  370 + fs.product_id = strtoul(p + 1, NULL, 16);
  371 + ret = usb_host_scan(&fs, usb_host_find_device_scan);
  372 + if (ret) {
  373 + *pbus_num = fs.bus_num;
  374 + *paddr = fs.addr;
  375 + return 0;
280 } 376 }
281 } 377 }
282 - closedir(d); 378 + return -1;
283 } 379 }
284 380
285 -/* virtual hub containing the USB devices of the host */  
286 -USBDevice *usb_host_hub_init(void) 381 +/**********************/
  382 +/* USB host device info */
  383 +
  384 +struct usb_class_info {
  385 + int class;
  386 + const char *class_name;
  387 +};
  388 +
  389 +static const struct usb_class_info usb_class_info[] = {
  390 + { USB_CLASS_AUDIO, "Audio"},
  391 + { USB_CLASS_COMM, "Communication"},
  392 + { USB_CLASS_HID, "HID"},
  393 + { USB_CLASS_HUB, "Hub" },
  394 + { USB_CLASS_PHYSICAL, "Physical" },
  395 + { USB_CLASS_PRINTER, "Printer" },
  396 + { USB_CLASS_MASS_STORAGE, "Storage" },
  397 + { USB_CLASS_CDC_DATA, "Data" },
  398 + { USB_CLASS_APP_SPEC, "Application Specific" },
  399 + { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
  400 + { USB_CLASS_STILL_IMAGE, "Still Image" },
  401 + { USB_CLASS_CSCID, "Smart Card" },
  402 + { USB_CLASS_CONTENT_SEC, "Content Security" },
  403 + { -1, NULL }
  404 +};
  405 +
  406 +static const char *usb_class_str(uint8_t class)
287 { 407 {
288 - USBHostHubState *s;  
289 - s = qemu_mallocz(sizeof(USBHostHubState));  
290 - if (!s)  
291 - return NULL;  
292 - s->hub_dev = usb_hub_init(s->hub_ports, MAX_DEVICES);  
293 - if (!s->hub_dev) {  
294 - free(s);  
295 - return NULL; 408 + const struct usb_class_info *p;
  409 + for(p = usb_class_info; p->class != -1; p++) {
  410 + if (p->class == class)
  411 + break;
296 } 412 }
297 - scan_host_buses(s);  
298 - return s->hub_dev; 413 + return p->class_name;
  414 +}
  415 +
  416 +void usb_info_device(int bus_num, int addr, int class_id,
  417 + int vendor_id, int product_id,
  418 + const char *product_name,
  419 + int speed)
  420 +{
  421 + const char *class_str, *speed_str;
  422 +
  423 + switch(speed) {
  424 + case USB_SPEED_LOW:
  425 + speed_str = "1.5";
  426 + break;
  427 + case USB_SPEED_FULL:
  428 + speed_str = "12";
  429 + break;
  430 + case USB_SPEED_HIGH:
  431 + speed_str = "480";
  432 + break;
  433 + default:
  434 + speed_str = "?";
  435 + break;
  436 + }
  437 +
  438 + term_printf(" Device %d.%d, speed %s Mb/s\n",
  439 + bus_num, addr, speed_str);
  440 + class_str = usb_class_str(class_id);
  441 + if (class_str)
  442 + term_printf(" %s:", class_str);
  443 + else
  444 + term_printf(" Class %02x:", class_id);
  445 + term_printf(" USB device %04x:%04x", vendor_id, product_id);
  446 + if (product_name[0] != '\0')
  447 + term_printf(", %s", product_name);
  448 + term_printf("\n");
  449 +}
  450 +
  451 +static int usb_host_info_device(void *opaque, int bus_num, int addr,
  452 + int class_id,
  453 + int vendor_id, int product_id,
  454 + const char *product_name,
  455 + int speed)
  456 +{
  457 + usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
  458 + product_name, speed);
  459 + return 0;
  460 +}
  461 +
  462 +void usb_host_info(void)
  463 +{
  464 + usb_host_scan(NULL, usb_host_info_device);
299 } 465 }
300 466
301 #else 467 #else
302 468
  469 +void usb_host_info(void)
  470 +{
  471 + term_printf("USB host devices not supported\n");
  472 +}
  473 +
303 /* XXX: modify configure to compile the right host driver */ 474 /* XXX: modify configure to compile the right host driver */
304 -USBDevice *usb_host_hub_init(void) 475 +USBDevice *usb_host_device_open(const char *devname)
305 { 476 {
306 return NULL; 477 return NULL;
307 } 478 }
@@ -154,6 +154,8 @@ CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; @@ -154,6 +154,8 @@ CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
154 int win2k_install_hack = 0; 154 int win2k_install_hack = 0;
155 #endif 155 #endif
156 int usb_enabled = 0; 156 int usb_enabled = 0;
  157 +USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
  158 +USBDevice *vm_usb_hub;
157 159
158 /***********************************************************/ 160 /***********************************************************/
159 /* x86 ISA bus support */ 161 /* x86 ISA bus support */
@@ -1738,6 +1740,117 @@ static int net_fd_init(NetDriverState *nd, int fd) @@ -1738,6 +1740,117 @@ static int net_fd_init(NetDriverState *nd, int fd)
1738 #endif /* !_WIN32 */ 1740 #endif /* !_WIN32 */
1739 1741
1740 /***********************************************************/ 1742 /***********************************************************/
  1743 +/* USB devices */
  1744 +
  1745 +static int usb_device_add(const char *devname)
  1746 +{
  1747 + const char *p;
  1748 + USBDevice *dev;
  1749 + int i;
  1750 +
  1751 + if (!vm_usb_hub)
  1752 + return -1;
  1753 + for(i = 0;i < MAX_VM_USB_PORTS; i++) {
  1754 + if (!vm_usb_ports[i]->dev)
  1755 + break;
  1756 + }
  1757 + if (i == MAX_VM_USB_PORTS)
  1758 + return -1;
  1759 +
  1760 + if (strstart(devname, "host:", &p)) {
  1761 + dev = usb_host_device_open(p);
  1762 + if (!dev)
  1763 + return -1;
  1764 + } else if (!strcmp(devname, "mouse")) {
  1765 + dev = usb_mouse_init();
  1766 + if (!dev)
  1767 + return -1;
  1768 + } else {
  1769 + return -1;
  1770 + }
  1771 + usb_attach(vm_usb_ports[i], dev);
  1772 + return 0;
  1773 +}
  1774 +
  1775 +static int usb_device_del(const char *devname)
  1776 +{
  1777 + USBDevice *dev;
  1778 + int bus_num, addr, i;
  1779 + const char *p;
  1780 +
  1781 + if (!vm_usb_hub)
  1782 + return -1;
  1783 +
  1784 + p = strchr(devname, '.');
  1785 + if (!p)
  1786 + return -1;
  1787 + bus_num = strtoul(devname, NULL, 0);
  1788 + addr = strtoul(p + 1, NULL, 0);
  1789 + if (bus_num != 0)
  1790 + return -1;
  1791 + for(i = 0;i < MAX_VM_USB_PORTS; i++) {
  1792 + dev = vm_usb_ports[i]->dev;
  1793 + if (dev && dev->addr == addr)
  1794 + break;
  1795 + }
  1796 + if (i == MAX_VM_USB_PORTS)
  1797 + return -1;
  1798 + usb_attach(vm_usb_ports[i], NULL);
  1799 + return 0;
  1800 +}
  1801 +
  1802 +void do_usb_add(const char *devname)
  1803 +{
  1804 + int ret;
  1805 + ret = usb_device_add(devname);
  1806 + if (ret < 0)
  1807 + term_printf("Could not add USB device '%s'\n", devname);
  1808 +}
  1809 +
  1810 +void do_usb_del(const char *devname)
  1811 +{
  1812 + int ret;
  1813 + ret = usb_device_del(devname);
  1814 + if (ret < 0)
  1815 + term_printf("Could not remove USB device '%s'\n", devname);
  1816 +}
  1817 +
  1818 +void usb_info(void)
  1819 +{
  1820 + USBDevice *dev;
  1821 + int i;
  1822 + const char *speed_str;
  1823 +
  1824 + if (!vm_usb_hub) {
  1825 + term_printf("USB support not enabled\n");
  1826 + return;
  1827 + }
  1828 +
  1829 + for(i = 0; i < MAX_VM_USB_PORTS; i++) {
  1830 + dev = vm_usb_ports[i]->dev;
  1831 + if (dev) {
  1832 + term_printf("Hub port %d:\n", i);
  1833 + switch(dev->speed) {
  1834 + case USB_SPEED_LOW:
  1835 + speed_str = "1.5";
  1836 + break;
  1837 + case USB_SPEED_FULL:
  1838 + speed_str = "12";
  1839 + break;
  1840 + case USB_SPEED_HIGH:
  1841 + speed_str = "480";
  1842 + break;
  1843 + default:
  1844 + speed_str = "?";
  1845 + break;
  1846 + }
  1847 + term_printf(" Device %d.%d, speed %s Mb/s\n",
  1848 + 0, dev->addr, speed_str);
  1849 + }
  1850 + }
  1851 +}
  1852 +
  1853 +/***********************************************************/
1741 /* pid file */ 1854 /* pid file */
1742 1855
1743 static char *pid_filename; 1856 static char *pid_filename;
@@ -2989,6 +3102,7 @@ enum { @@ -2989,6 +3102,7 @@ enum {
2989 QEMU_OPTION_no_kqemu, 3102 QEMU_OPTION_no_kqemu,
2990 QEMU_OPTION_win2k_hack, 3103 QEMU_OPTION_win2k_hack,
2991 QEMU_OPTION_usb, 3104 QEMU_OPTION_usb,
  3105 + QEMU_OPTION_usbdevice,
2992 }; 3106 };
2993 3107
2994 typedef struct QEMUOption { 3108 typedef struct QEMUOption {
@@ -3063,9 +3177,10 @@ const QEMUOption qemu_options[] = { @@ -3063,9 +3177,10 @@ const QEMUOption qemu_options[] = {
3063 { "full-screen", 0, QEMU_OPTION_full_screen }, 3177 { "full-screen", 0, QEMU_OPTION_full_screen },
3064 { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, 3178 { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
3065 { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, 3179 { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
3066 - { "usb", 0, QEMU_OPTION_usb }, 3180 + { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
3067 3181
3068 /* temporary options */ 3182 /* temporary options */
  3183 + { "usb", 0, QEMU_OPTION_usb },
3069 { "pci", 0, QEMU_OPTION_pci }, 3184 { "pci", 0, QEMU_OPTION_pci },
3070 { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, 3185 { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
3071 { NULL }, 3186 { NULL },
@@ -3239,7 +3354,9 @@ int main(int argc, char **argv) @@ -3239,7 +3354,9 @@ int main(int argc, char **argv)
3239 int parallel_device_index; 3354 int parallel_device_index;
3240 const char *loadvm = NULL; 3355 const char *loadvm = NULL;
3241 QEMUMachine *machine; 3356 QEMUMachine *machine;
3242 - 3357 + char usb_devices[MAX_VM_USB_PORTS][128];
  3358 + int usb_devices_index;
  3359 +
3243 #if !defined(CONFIG_SOFTMMU) 3360 #if !defined(CONFIG_SOFTMMU)
3244 /* we never want that malloc() uses mmap() */ 3361 /* we never want that malloc() uses mmap() */
3245 mallopt(M_MMAP_THRESHOLD, 4096 * 1024); 3362 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
@@ -3282,6 +3399,8 @@ int main(int argc, char **argv) @@ -3282,6 +3399,8 @@ int main(int argc, char **argv)
3282 parallel_devices[i][0] = '\0'; 3399 parallel_devices[i][0] = '\0';
3283 parallel_device_index = 0; 3400 parallel_device_index = 0;
3284 3401
  3402 + usb_devices_index = 0;
  3403 +
3285 nb_tun_fds = 0; 3404 nb_tun_fds = 0;
3286 net_if_type = -1; 3405 net_if_type = -1;
3287 nb_nics = 1; 3406 nb_nics = 1;
@@ -3653,6 +3772,17 @@ int main(int argc, char **argv) @@ -3653,6 +3772,17 @@ int main(int argc, char **argv)
3653 case QEMU_OPTION_usb: 3772 case QEMU_OPTION_usb:
3654 usb_enabled = 1; 3773 usb_enabled = 1;
3655 break; 3774 break;
  3775 + case QEMU_OPTION_usbdevice:
  3776 + usb_enabled = 1;
  3777 + if (usb_devices_index >= MAX_VM_USB_PORTS) {
  3778 + fprintf(stderr, "Too many USB devices\n");
  3779 + exit(1);
  3780 + }
  3781 + pstrcpy(usb_devices[usb_devices_index],
  3782 + sizeof(usb_devices[usb_devices_index]),
  3783 + optarg);
  3784 + usb_devices_index++;
  3785 + break;
3656 } 3786 }
3657 } 3787 }
3658 } 3788 }
@@ -3818,6 +3948,17 @@ int main(int argc, char **argv) @@ -3818,6 +3948,17 @@ int main(int argc, char **argv)
3818 } 3948 }
3819 } 3949 }
3820 3950
  3951 + /* init USB devices */
  3952 + if (usb_enabled) {
  3953 + vm_usb_hub = usb_hub_init(vm_usb_ports, MAX_VM_USB_PORTS);
  3954 + for(i = 0; i < usb_devices_index; i++) {
  3955 + if (usb_device_add(usb_devices[i]) < 0) {
  3956 + fprintf(stderr, "Warning: could not add USB device %s\n",
  3957 + usb_devices[i]);
  3958 + }
  3959 + }
  3960 + }
  3961 +
3821 /* init CPU state */ 3962 /* init CPU state */
3822 env = cpu_init(); 3963 env = cpu_init();
3823 global_env = env; 3964 global_env = env;
@@ -862,6 +862,17 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq); @@ -862,6 +862,17 @@ int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq);
862 862
863 #include "hw/usb.h" 863 #include "hw/usb.h"
864 864
  865 +/* usb ports of the VM */
  866 +
  867 +#define MAX_VM_USB_PORTS 8
  868 +
  869 +extern USBPort *vm_usb_ports[MAX_VM_USB_PORTS];
  870 +extern USBDevice *vm_usb_hub;
  871 +
  872 +void do_usb_add(const char *devname);
  873 +void do_usb_del(const char *devname);
  874 +void usb_info(void);
  875 +
865 #endif /* defined(QEMU_TOOL) */ 876 #endif /* defined(QEMU_TOOL) */
866 877
867 /* monitor.c */ 878 /* monitor.c */