Revision 806b6024
b/Makefile | ||
---|---|---|
83 | 83 |
obj-y += scsi-disk.o cdrom.o |
84 | 84 |
obj-y += scsi-generic.o |
85 | 85 |
obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o |
86 |
obj-y += usb-serial.o usb-net.o |
|
86 |
obj-y += usb-serial.o usb-net.o usb-bus.o
|
|
87 | 87 |
obj-y += sd.o ssi-sd.o |
88 | 88 |
obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o |
89 | 89 |
obj-y += bt-hci-csr.o |
b/hw/bt-hid.c | ||
---|---|---|
111 | 111 |
bt_l2cap_device_done(&s->btdev); |
112 | 112 |
bt_l2cap_device_init(&s->btdev, net); |
113 | 113 |
|
114 |
s->usbdev->handle_reset(s->usbdev); |
|
114 |
s->usbdev->info->handle_reset(s->usbdev);
|
|
115 | 115 |
s->proto = BT_HID_PROTO_REPORT; |
116 | 116 |
s->state = bt_state_ready; |
117 | 117 |
s->dataother.len = 0; |
... | ... | |
131 | 131 |
p.devep = 1; |
132 | 132 |
p.data = s->dataout.buffer; |
133 | 133 |
p.len = s->dataout.len; |
134 |
s->dataout.len = s->usbdev->handle_data(s->usbdev, &p); |
|
134 |
s->dataout.len = s->usbdev->info->handle_data(s->usbdev, &p);
|
|
135 | 135 |
|
136 | 136 |
return s->dataout.len; |
137 | 137 |
} |
... | ... | |
154 | 154 |
p.devep = 1; |
155 | 155 |
p.data = s->datain.buffer; |
156 | 156 |
p.len = sizeof(s->datain.buffer); |
157 |
s->datain.len = s->usbdev->handle_data(s->usbdev, &p); |
|
157 |
s->datain.len = s->usbdev->info->handle_data(s->usbdev, &p);
|
|
158 | 158 |
|
159 | 159 |
return s->datain.len; |
160 | 160 |
} |
... | ... | |
323 | 323 |
break; |
324 | 324 |
} |
325 | 325 |
s->proto = parameter; |
326 |
s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0, |
|
327 |
NULL); |
|
326 |
s->usbdev->info->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0,
|
|
327 |
NULL);
|
|
328 | 328 |
ret = BT_HS_SUCCESSFUL; |
329 | 329 |
break; |
330 | 330 |
|
... | ... | |
333 | 333 |
ret = BT_HS_ERR_INVALID_PARAMETER; |
334 | 334 |
break; |
335 | 335 |
} |
336 |
s->usbdev->handle_control(s->usbdev, GET_IDLE, 0, 0, 1, |
|
336 |
s->usbdev->info->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
|
|
337 | 337 |
s->control->sdu_out(s->control, 1)); |
338 | 338 |
s->control->sdu_submit(s->control); |
339 | 339 |
break; |
... | ... | |
346 | 346 |
|
347 | 347 |
/* We don't need to know about the Idle Rate here really, |
348 | 348 |
* so just pass it on to the device. */ |
349 |
ret = s->usbdev->handle_control(s->usbdev, |
|
349 |
ret = s->usbdev->info->handle_control(s->usbdev,
|
|
350 | 350 |
SET_IDLE, data[1], 0, 0, NULL) ? |
351 | 351 |
BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER; |
352 | 352 |
/* XXX: Does this generate a handshake? */ |
... | ... | |
450 | 450 |
hid->btdev.device.inquiry_scan = !hid->connected; |
451 | 451 |
|
452 | 452 |
if (hid->connected && !prev) { |
453 |
hid->usbdev->handle_reset(hid->usbdev); |
|
453 |
hid->usbdev->info->handle_reset(hid->usbdev);
|
|
454 | 454 |
hid->proto = BT_HID_PROTO_REPORT; |
455 | 455 |
} |
456 | 456 |
|
... | ... | |
518 | 518 |
bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG); |
519 | 519 |
bt_l2cap_device_done(&hid->btdev); |
520 | 520 |
|
521 |
hid->usbdev->handle_destroy(hid->usbdev); |
|
521 |
hid->usbdev->info->handle_destroy(hid->usbdev);
|
|
522 | 522 |
|
523 | 523 |
qemu_free(hid); |
524 | 524 |
} |
b/hw/usb-bt.c | ||
---|---|---|
617 | 617 |
qemu_free(s); |
618 | 618 |
} |
619 | 619 |
|
620 |
static int usb_bt_initfn(USBDevice *dev) |
|
621 |
{ |
|
622 |
struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev); |
|
623 |
s->dev.speed = USB_SPEED_HIGH; |
|
624 |
return 0; |
|
625 |
} |
|
626 |
|
|
620 | 627 |
USBDevice *usb_bt_init(HCIInfo *hci) |
621 | 628 |
{ |
629 |
USBDevice *dev; |
|
622 | 630 |
struct USBBtState *s; |
623 | 631 |
|
624 | 632 |
if (!hci) |
625 | 633 |
return NULL; |
626 |
s = qemu_mallocz(sizeof(struct USBBtState)); |
|
634 |
dev = usb_create_simple(NULL /* FIXME */, "QEMU BT dongle"); |
|
635 |
s = DO_UPCAST(struct USBBtState, dev, dev); |
|
627 | 636 |
s->dev.opaque = s; |
628 |
s->dev.speed = USB_SPEED_HIGH; |
|
629 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
630 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU BT dongle"); |
|
631 |
|
|
632 |
s->dev.handle_reset = usb_bt_handle_reset; |
|
633 |
s->dev.handle_control = usb_bt_handle_control; |
|
634 |
s->dev.handle_data = usb_bt_handle_data; |
|
635 |
s->dev.handle_destroy = usb_bt_handle_destroy; |
|
636 | 637 |
|
637 | 638 |
s->hci = hci; |
638 | 639 |
s->hci->opaque = s; |
... | ... | |
641 | 642 |
|
642 | 643 |
usb_bt_handle_reset(&s->dev); |
643 | 644 |
|
644 |
return &s->dev; |
|
645 |
return dev; |
|
646 |
} |
|
647 |
|
|
648 |
static struct USBDeviceInfo bt_info = { |
|
649 |
.qdev.name = "QEMU BT dongle", |
|
650 |
.qdev.size = sizeof(struct USBBtState), |
|
651 |
.init = usb_bt_initfn, |
|
652 |
.handle_packet = usb_generic_handle_packet, |
|
653 |
.handle_reset = usb_bt_handle_reset, |
|
654 |
.handle_control = usb_bt_handle_control, |
|
655 |
.handle_data = usb_bt_handle_data, |
|
656 |
.handle_destroy = usb_bt_handle_destroy, |
|
657 |
}; |
|
658 |
|
|
659 |
static void usb_bt_register_devices(void) |
|
660 |
{ |
|
661 |
usb_qdev_register(&bt_info); |
|
645 | 662 |
} |
663 |
device_init(usb_bt_register_devices) |
b/hw/usb-bus.c | ||
---|---|---|
1 |
#include "hw.h" |
|
2 |
#include "usb.h" |
|
3 |
#include "qdev.h" |
|
4 |
|
|
5 |
static struct BusInfo usb_bus_info = { |
|
6 |
.name = "USB", |
|
7 |
.size = sizeof(USBBus), |
|
8 |
}; |
|
9 |
static int next_usb_bus = 0; |
|
10 |
static TAILQ_HEAD(, USBBus) busses = TAILQ_HEAD_INITIALIZER(busses); |
|
11 |
|
|
12 |
USBBus *usb_bus_new(DeviceState *host) |
|
13 |
{ |
|
14 |
USBBus *bus; |
|
15 |
|
|
16 |
bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, NULL)); |
|
17 |
bus->busnr = next_usb_bus++; |
|
18 |
TAILQ_INIT(&bus->free); |
|
19 |
TAILQ_INIT(&bus->used); |
|
20 |
TAILQ_INSERT_TAIL(&busses, bus, next); |
|
21 |
return bus; |
|
22 |
} |
|
23 |
|
|
24 |
USBBus *usb_bus_find(int busnr) |
|
25 |
{ |
|
26 |
USBBus *bus; |
|
27 |
|
|
28 |
if (-1 == busnr) |
|
29 |
return TAILQ_FIRST(&busses); |
|
30 |
TAILQ_FOREACH(bus, &busses, next) { |
|
31 |
if (bus->busnr == busnr) |
|
32 |
return bus; |
|
33 |
} |
|
34 |
return NULL; |
|
35 |
} |
|
36 |
|
|
37 |
static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) |
|
38 |
{ |
|
39 |
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); |
|
40 |
USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base); |
|
41 |
int rc; |
|
42 |
|
|
43 |
pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name); |
|
44 |
dev->info = info; |
|
45 |
rc = dev->info->init(dev); |
|
46 |
return rc; |
|
47 |
} |
|
48 |
|
|
49 |
void usb_qdev_register(USBDeviceInfo *info) |
|
50 |
{ |
|
51 |
info->qdev.bus_info = &usb_bus_info; |
|
52 |
info->qdev.init = usb_qdev_init; |
|
53 |
qdev_register(&info->qdev); |
|
54 |
} |
|
55 |
|
|
56 |
void usb_qdev_register_many(USBDeviceInfo *info) |
|
57 |
{ |
|
58 |
while (info->qdev.name) { |
|
59 |
usb_qdev_register(info); |
|
60 |
info++; |
|
61 |
} |
|
62 |
} |
|
63 |
|
|
64 |
USBDevice *usb_create_simple(USBBus *bus, const char *name) |
|
65 |
{ |
|
66 |
DeviceState *dev; |
|
67 |
|
|
68 |
#if 1 |
|
69 |
/* temporary stopgap until all usb is properly qdev-ified */ |
|
70 |
if (!bus) { |
|
71 |
bus = usb_bus_find(-1); |
|
72 |
if (!bus) |
|
73 |
return NULL; |
|
74 |
fprintf(stderr, "%s: no bus specified, using \"%s\" for \"%s\"\n", |
|
75 |
__FUNCTION__, bus->qbus.name, name); |
|
76 |
} |
|
77 |
#endif |
|
78 |
|
|
79 |
dev = qdev_create(&bus->qbus, name); |
|
80 |
qdev_init(dev); |
|
81 |
return DO_UPCAST(USBDevice, qdev, dev); |
|
82 |
} |
b/hw/usb-hid.c | ||
---|---|---|
846 | 846 |
qemu_free(s); |
847 | 847 |
} |
848 | 848 |
|
849 |
USBDevice *usb_tablet_init(void)
|
|
849 |
static int usb_hid_initfn(USBDevice *dev, int kind)
|
|
850 | 850 |
{ |
851 |
USBHIDState *s; |
|
852 |
|
|
853 |
s = qemu_mallocz(sizeof(USBHIDState)); |
|
851 |
USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev); |
|
854 | 852 |
s->dev.speed = USB_SPEED_FULL; |
855 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
856 |
|
|
857 |
s->dev.handle_reset = usb_mouse_handle_reset; |
|
858 |
s->dev.handle_control = usb_hid_handle_control; |
|
859 |
s->dev.handle_data = usb_hid_handle_data; |
|
860 |
s->dev.handle_destroy = usb_hid_handle_destroy; |
|
861 |
s->kind = USB_TABLET; |
|
853 |
s->kind = kind; |
|
862 | 854 |
/* Force poll routine to be run and grab input the first time. */ |
863 | 855 |
s->changed = 1; |
864 |
|
|
865 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); |
|
866 |
|
|
867 |
return (USBDevice *)s; |
|
856 |
return 0; |
|
868 | 857 |
} |
869 | 858 |
|
870 |
USBDevice *usb_mouse_init(void)
|
|
859 |
static int usb_tablet_initfn(USBDevice *dev)
|
|
871 | 860 |
{ |
872 |
USBHIDState *s; |
|
861 |
return usb_hid_initfn(dev, USB_TABLET); |
|
862 |
} |
|
873 | 863 |
|
874 |
s = qemu_mallocz(sizeof(USBHIDState)); |
|
875 |
s->dev.speed = USB_SPEED_FULL; |
|
876 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
864 |
static int usb_mouse_initfn(USBDevice *dev) |
|
865 |
{ |
|
866 |
return usb_hid_initfn(dev, USB_MOUSE); |
|
867 |
} |
|
877 | 868 |
|
878 |
s->dev.handle_reset = usb_mouse_handle_reset; |
|
879 |
s->dev.handle_control = usb_hid_handle_control; |
|
880 |
s->dev.handle_data = usb_hid_handle_data; |
|
881 |
s->dev.handle_destroy = usb_hid_handle_destroy; |
|
882 |
s->kind = USB_MOUSE; |
|
883 |
/* Force poll routine to be run and grab input the first time. */ |
|
884 |
s->changed = 1; |
|
869 |
static int usb_keyboard_initfn(USBDevice *dev) |
|
870 |
{ |
|
871 |
return usb_hid_initfn(dev, USB_KEYBOARD); |
|
872 |
} |
|
885 | 873 |
|
886 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); |
|
874 |
USBDevice *usb_tablet_init(void) |
|
875 |
{ |
|
876 |
return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet"); |
|
877 |
} |
|
887 | 878 |
|
888 |
return (USBDevice *)s; |
|
879 |
USBDevice *usb_mouse_init(void) |
|
880 |
{ |
|
881 |
return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse"); |
|
889 | 882 |
} |
890 | 883 |
|
891 | 884 |
USBDevice *usb_keyboard_init(void) |
892 | 885 |
{ |
893 |
USBHIDState *s; |
|
894 |
|
|
895 |
s = qemu_mallocz(sizeof(USBHIDState)); |
|
896 |
s->dev.speed = USB_SPEED_FULL; |
|
897 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
898 |
|
|
899 |
s->dev.handle_reset = usb_keyboard_handle_reset; |
|
900 |
s->dev.handle_control = usb_hid_handle_control; |
|
901 |
s->dev.handle_data = usb_hid_handle_data; |
|
902 |
s->dev.handle_destroy = usb_hid_handle_destroy; |
|
903 |
s->kind = USB_KEYBOARD; |
|
904 |
|
|
905 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard"); |
|
906 |
|
|
907 |
return (USBDevice *) s; |
|
886 |
return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard"); |
|
908 | 887 |
} |
909 | 888 |
|
910 | 889 |
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)) |
... | ... | |
914 | 893 |
s->datain_opaque = opaque; |
915 | 894 |
s->datain = datain; |
916 | 895 |
} |
896 |
|
|
897 |
static struct USBDeviceInfo hid_info[] = { |
|
898 |
{ |
|
899 |
.qdev.name = "QEMU USB Tablet", |
|
900 |
.qdev.size = sizeof(USBHIDState), |
|
901 |
.init = usb_tablet_initfn, |
|
902 |
.handle_packet = usb_generic_handle_packet, |
|
903 |
.handle_reset = usb_mouse_handle_reset, |
|
904 |
.handle_control = usb_hid_handle_control, |
|
905 |
.handle_data = usb_hid_handle_data, |
|
906 |
.handle_destroy = usb_hid_handle_destroy, |
|
907 |
},{ |
|
908 |
.qdev.name = "QEMU USB Mouse", |
|
909 |
.qdev.size = sizeof(USBHIDState), |
|
910 |
.init = usb_mouse_initfn, |
|
911 |
.handle_packet = usb_generic_handle_packet, |
|
912 |
.handle_reset = usb_mouse_handle_reset, |
|
913 |
.handle_control = usb_hid_handle_control, |
|
914 |
.handle_data = usb_hid_handle_data, |
|
915 |
.handle_destroy = usb_hid_handle_destroy, |
|
916 |
},{ |
|
917 |
.qdev.name = "QEMU USB Keyboard", |
|
918 |
.qdev.size = sizeof(USBHIDState), |
|
919 |
.init = usb_keyboard_initfn, |
|
920 |
.handle_packet = usb_generic_handle_packet, |
|
921 |
.handle_reset = usb_keyboard_handle_reset, |
|
922 |
.handle_control = usb_hid_handle_control, |
|
923 |
.handle_data = usb_hid_handle_data, |
|
924 |
.handle_destroy = usb_hid_handle_destroy, |
|
925 |
},{ |
|
926 |
/* end of list */ |
|
927 |
} |
|
928 |
}; |
|
929 |
|
|
930 |
static void usb_hid_register_devices(void) |
|
931 |
{ |
|
932 |
usb_qdev_register_many(hid_info); |
|
933 |
} |
|
934 |
device_init(usb_hid_register_devices) |
b/hw/usb-hub.c | ||
---|---|---|
486 | 486 |
port = &s->ports[i]; |
487 | 487 |
dev = port->port.dev; |
488 | 488 |
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) { |
489 |
ret = dev->handle_packet(dev, p); |
|
489 |
ret = dev->info->handle_packet(dev, p);
|
|
490 | 490 |
if (ret != USB_RET_NODEV) { |
491 | 491 |
return ret; |
492 | 492 |
} |
... | ... | |
521 | 521 |
qemu_free(s); |
522 | 522 |
} |
523 | 523 |
|
524 |
USBDevice *usb_hub_init(int nb_ports)
|
|
524 |
static int usb_hub_initfn(USBDevice *dev)
|
|
525 | 525 |
{ |
526 |
USBHubState *s; |
|
526 |
USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
|
|
527 | 527 |
USBHubPort *port; |
528 | 528 |
int i; |
529 | 529 |
|
530 |
if (nb_ports > MAX_PORTS) |
|
531 |
return NULL; |
|
532 |
s = qemu_mallocz(sizeof(USBHubState)); |
|
533 |
s->dev.speed = USB_SPEED_FULL; |
|
534 |
s->dev.handle_packet = usb_hub_handle_packet; |
|
535 |
|
|
536 |
/* generic USB device init */ |
|
537 |
s->dev.handle_reset = usb_hub_handle_reset; |
|
538 |
s->dev.handle_control = usb_hub_handle_control; |
|
539 |
s->dev.handle_data = usb_hub_handle_data; |
|
540 |
s->dev.handle_destroy = usb_hub_handle_destroy; |
|
541 |
|
|
542 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub"); |
|
543 |
|
|
544 |
s->nb_ports = nb_ports; |
|
545 |
for(i = 0; i < s->nb_ports; i++) { |
|
530 |
s->dev.speed = USB_SPEED_FULL, |
|
531 |
s->nb_ports = MAX_PORTS; /* FIXME: make configurable */ |
|
532 |
for (i = 0; i < s->nb_ports; i++) { |
|
546 | 533 |
port = &s->ports[i]; |
547 | 534 |
qemu_register_usb_port(&port->port, s, i, usb_hub_attach); |
548 | 535 |
port->wPortStatus = PORT_STAT_POWER; |
549 | 536 |
port->wPortChange = 0; |
550 | 537 |
} |
551 |
return (USBDevice *)s; |
|
538 |
return 0; |
|
539 |
} |
|
540 |
|
|
541 |
USBDevice *usb_hub_init(int nb_ports) |
|
542 |
{ |
|
543 |
return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub"); |
|
544 |
} |
|
545 |
|
|
546 |
static struct USBDeviceInfo hub_info = { |
|
547 |
.qdev.name = "QEMU USB Hub", |
|
548 |
.qdev.size = sizeof(USBHubState), |
|
549 |
.init = usb_hub_initfn, |
|
550 |
.handle_packet = usb_hub_handle_packet, |
|
551 |
.handle_reset = usb_hub_handle_reset, |
|
552 |
.handle_control = usb_hub_handle_control, |
|
553 |
.handle_data = usb_hub_handle_data, |
|
554 |
.handle_destroy = usb_hub_handle_destroy, |
|
555 |
}; |
|
556 |
|
|
557 |
static void usb_hub_register_devices(void) |
|
558 |
{ |
|
559 |
usb_qdev_register(&hub_info); |
|
552 | 560 |
} |
561 |
device_init(usb_hub_register_devices) |
b/hw/usb-msd.c | ||
---|---|---|
514 | 514 |
qemu_free(s); |
515 | 515 |
} |
516 | 516 |
|
517 |
static int usb_msd_initfn(USBDevice *dev) |
|
518 |
{ |
|
519 |
MSDState *s = DO_UPCAST(MSDState, dev, dev); |
|
520 |
|
|
521 |
s->dev.speed = USB_SPEED_FULL; |
|
522 |
return 0; |
|
523 |
} |
|
524 |
|
|
517 | 525 |
USBDevice *usb_msd_init(const char *filename) |
518 | 526 |
{ |
527 |
USBDevice *dev; |
|
519 | 528 |
MSDState *s; |
520 | 529 |
BlockDriverState *bdrv; |
521 | 530 |
BlockDriver *drv = NULL; |
... | ... | |
548 | 557 |
return NULL; |
549 | 558 |
} |
550 | 559 |
|
551 |
s = qemu_mallocz(sizeof(MSDState)); |
|
552 |
|
|
553 | 560 |
bdrv = bdrv_new("usb"); |
554 | 561 |
if (bdrv_open2(bdrv, filename, 0, drv) < 0) |
555 |
goto fail; |
|
556 |
s->bs = bdrv; |
|
557 |
|
|
558 |
s->dev.speed = USB_SPEED_FULL; |
|
559 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
560 |
|
|
561 |
s->dev.handle_reset = usb_msd_handle_reset; |
|
562 |
s->dev.handle_control = usb_msd_handle_control; |
|
563 |
s->dev.handle_data = usb_msd_handle_data; |
|
564 |
s->dev.handle_destroy = usb_msd_handle_destroy; |
|
562 |
return NULL; |
|
565 | 563 |
|
564 |
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB MSD"); |
|
565 |
s = DO_UPCAST(MSDState, dev, dev); |
|
566 |
s->bs = bdrv; |
|
566 | 567 |
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)", |
567 | 568 |
filename); |
568 | 569 |
|
569 | 570 |
s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s); |
570 | 571 |
usb_msd_handle_reset((USBDevice *)s); |
571 | 572 |
return (USBDevice *)s; |
572 |
fail: |
|
573 |
qemu_free(s); |
|
574 |
return NULL; |
|
575 | 573 |
} |
576 | 574 |
|
577 | 575 |
BlockDriverState *usb_msd_get_bdrv(USBDevice *dev) |
... | ... | |
580 | 578 |
|
581 | 579 |
return s->bs; |
582 | 580 |
} |
581 |
|
|
582 |
static struct USBDeviceInfo msd_info = { |
|
583 |
.qdev.name = "QEMU USB MSD", |
|
584 |
.qdev.size = sizeof(MSDState), |
|
585 |
.init = usb_msd_initfn, |
|
586 |
.handle_packet = usb_generic_handle_packet, |
|
587 |
.handle_reset = usb_msd_handle_reset, |
|
588 |
.handle_control = usb_msd_handle_control, |
|
589 |
.handle_data = usb_msd_handle_data, |
|
590 |
.handle_destroy = usb_msd_handle_destroy, |
|
591 |
}; |
|
592 |
|
|
593 |
static void usb_msd_register_devices(void) |
|
594 |
{ |
|
595 |
usb_qdev_register(&msd_info); |
|
596 |
} |
|
597 |
device_init(usb_msd_register_devices) |
b/hw/usb-musb.c | ||
---|---|---|
590 | 590 |
ep->packey[dir].complete_opaque = ep; |
591 | 591 |
|
592 | 592 |
if (s->port.dev) |
593 |
ret = s->port.dev->handle_packet(s->port.dev, &ep->packey[dir]); |
|
593 |
ret = s->port.dev->info->handle_packet(s->port.dev, &ep->packey[dir]);
|
|
594 | 594 |
else |
595 | 595 |
ret = USB_RET_NODEV; |
596 | 596 |
|
b/hw/usb-net.c | ||
---|---|---|
1432 | 1432 |
qemu_del_vlan_client(s->vc); |
1433 | 1433 |
} |
1434 | 1434 |
|
1435 |
USBDevice *usb_net_init(NICInfo *nd)
|
|
1435 |
static int usb_net_initfn(USBDevice *dev)
|
|
1436 | 1436 |
{ |
1437 |
USBNetState *s; |
|
1438 |
|
|
1439 |
s = qemu_mallocz(sizeof(USBNetState)); |
|
1440 |
s->dev.speed = USB_SPEED_FULL; |
|
1441 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
1437 |
USBNetState *s = DO_UPCAST(USBNetState, dev, dev); |
|
1442 | 1438 |
|
1443 |
s->dev.handle_reset = usb_net_handle_reset; |
|
1444 |
s->dev.handle_control = usb_net_handle_control; |
|
1445 |
s->dev.handle_data = usb_net_handle_data; |
|
1446 |
s->dev.handle_destroy = usb_net_handle_destroy; |
|
1439 |
s->dev.speed = USB_SPEED_FULL; |
|
1447 | 1440 |
|
1448 | 1441 |
s->rndis = 1; |
1449 | 1442 |
s->rndis_state = RNDIS_UNINITIALIZED; |
1443 |
TAILQ_INIT(&s->rndis_resp); |
|
1444 |
|
|
1450 | 1445 |
s->medium = 0; /* NDIS_MEDIUM_802_3 */ |
1451 | 1446 |
s->speed = 1000000; /* 100MBps, in 100Bps units */ |
1452 | 1447 |
s->media_state = 0; /* NDIS_MEDIA_STATE_CONNECTED */; |
1453 | 1448 |
s->filter = 0; |
1454 | 1449 |
s->vendorid = 0x1234; |
1450 |
return 0; |
|
1451 |
} |
|
1452 |
|
|
1453 |
USBDevice *usb_net_init(NICInfo *nd) |
|
1454 |
{ |
|
1455 |
USBDevice *dev; |
|
1456 |
USBNetState *s; |
|
1457 |
|
|
1458 |
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface"); |
|
1459 |
s = DO_UPCAST(USBNetState, dev, dev); |
|
1455 | 1460 |
|
1456 | 1461 |
memcpy(s->mac, nd->macaddr, 6); |
1457 |
TAILQ_INIT(&s->rndis_resp); |
|
1458 | 1462 |
|
1459 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), |
|
1460 |
"QEMU USB Network Interface"); |
|
1461 | 1463 |
s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, |
1462 | 1464 |
usbnet_can_receive, |
1463 | 1465 |
usbnet_receive, |
... | ... | |
1476 | 1478 |
|
1477 | 1479 |
return (USBDevice *) s; |
1478 | 1480 |
} |
1481 |
|
|
1482 |
static struct USBDeviceInfo net_info = { |
|
1483 |
.qdev.name = "QEMU USB Network Interface", |
|
1484 |
.qdev.size = sizeof(USBNetState), |
|
1485 |
.init = usb_net_initfn, |
|
1486 |
.handle_packet = usb_generic_handle_packet, |
|
1487 |
.handle_reset = usb_net_handle_reset, |
|
1488 |
.handle_control = usb_net_handle_control, |
|
1489 |
.handle_data = usb_net_handle_data, |
|
1490 |
.handle_destroy = usb_net_handle_destroy, |
|
1491 |
}; |
|
1492 |
|
|
1493 |
static void usb_net_register_devices(void) |
|
1494 |
{ |
|
1495 |
usb_qdev_register(&net_info); |
|
1496 |
} |
|
1497 |
device_init(usb_net_register_devices) |
b/hw/usb-ohci.c | ||
---|---|---|
754 | 754 |
ohci->usb_packet.len = len; |
755 | 755 |
ohci->usb_packet.complete_cb = ohci_async_complete_packet; |
756 | 756 |
ohci->usb_packet.complete_opaque = ohci; |
757 |
ret = dev->handle_packet(dev, &ohci->usb_packet); |
|
757 |
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
|
|
758 | 758 |
if (ret != USB_RET_NODEV) |
759 | 759 |
break; |
760 | 760 |
} |
... | ... | |
944 | 944 |
ohci->usb_packet.len = len; |
945 | 945 |
ohci->usb_packet.complete_cb = ohci_async_complete_packet; |
946 | 946 |
ohci->usb_packet.complete_opaque = ohci; |
947 |
ret = dev->handle_packet(dev, &ohci->usb_packet); |
|
947 |
ret = dev->info->handle_packet(dev, &ohci->usb_packet);
|
|
948 | 948 |
if (ret != USB_RET_NODEV) |
949 | 949 |
break; |
950 | 950 |
} |
b/hw/usb-serial.c | ||
---|---|---|
524 | 524 |
} |
525 | 525 |
} |
526 | 526 |
|
527 |
static int usb_serial_initfn(USBDevice *dev) |
|
528 |
{ |
|
529 |
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); |
|
530 |
s->dev.speed = USB_SPEED_FULL; |
|
531 |
return 0; |
|
532 |
} |
|
533 |
|
|
527 | 534 |
USBDevice *usb_serial_init(const char *filename) |
528 | 535 |
{ |
536 |
USBDevice *dev; |
|
529 | 537 |
USBSerialState *s; |
530 | 538 |
CharDriverState *cdrv; |
531 | 539 |
unsigned short vendorid = 0x0403, productid = 0x6001; |
... | ... | |
561 | 569 |
return NULL; |
562 | 570 |
} |
563 | 571 |
filename++; |
564 |
s = qemu_mallocz(sizeof(USBSerialState)); |
|
565 | 572 |
|
566 | 573 |
snprintf(label, sizeof(label), "usbserial%d", index++); |
567 | 574 |
cdrv = qemu_chr_open(label, filename, NULL); |
568 | 575 |
if (!cdrv) |
569 |
goto fail; |
|
570 |
s->cs = cdrv; |
|
571 |
qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s); |
|
572 |
|
|
573 |
s->dev.speed = USB_SPEED_FULL; |
|
574 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
575 |
|
|
576 |
s->dev.handle_reset = usb_serial_handle_reset; |
|
577 |
s->dev.handle_control = usb_serial_handle_control; |
|
578 |
s->dev.handle_data = usb_serial_handle_data; |
|
579 |
s->dev.handle_destroy = usb_serial_handle_destroy; |
|
576 |
return NULL; |
|
580 | 577 |
|
578 |
dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Serial"); |
|
579 |
s = DO_UPCAST(USBSerialState, dev, dev); |
|
580 |
s->cs = cdrv; |
|
581 | 581 |
s->vendorid = vendorid; |
582 | 582 |
s->productid = productid; |
583 |
|
|
584 | 583 |
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)", |
585 | 584 |
filename); |
586 | 585 |
|
586 |
qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, |
|
587 |
usb_serial_event, s); |
|
588 |
|
|
587 | 589 |
usb_serial_handle_reset((USBDevice *)s); |
588 | 590 |
return (USBDevice *)s; |
589 |
fail: |
|
590 |
qemu_free(s); |
|
591 |
return NULL; |
|
592 | 591 |
} |
592 |
|
|
593 |
static struct USBDeviceInfo serial_info = { |
|
594 |
.qdev.name = "QEMU USB Serial", |
|
595 |
.qdev.size = sizeof(USBSerialState), |
|
596 |
.init = usb_serial_initfn, |
|
597 |
.handle_packet = usb_generic_handle_packet, |
|
598 |
.handle_reset = usb_serial_handle_reset, |
|
599 |
.handle_control = usb_serial_handle_control, |
|
600 |
.handle_data = usb_serial_handle_data, |
|
601 |
.handle_destroy = usb_serial_handle_destroy, |
|
602 |
}; |
|
603 |
|
|
604 |
static void usb_serial_register_devices(void) |
|
605 |
{ |
|
606 |
usb_qdev_register(&serial_info); |
|
607 |
} |
|
608 |
device_init(usb_serial_register_devices) |
b/hw/usb-uhci.c | ||
---|---|---|
660 | 660 |
USBDevice *dev = port->port.dev; |
661 | 661 |
|
662 | 662 |
if (dev && (port->ctrl & UHCI_PORT_EN)) |
663 |
ret = dev->handle_packet(dev, p); |
|
663 |
ret = dev->info->handle_packet(dev, p);
|
|
664 | 664 |
} |
665 | 665 |
|
666 | 666 |
dprintf("uhci: packet exit. ret %d len %d\n", ret, p->len); |
b/hw/usb-wacom.c | ||
---|---|---|
392 | 392 |
qemu_free(s); |
393 | 393 |
} |
394 | 394 |
|
395 |
USBDevice *usb_wacom_init(void)
|
|
395 |
static int usb_wacom_initfn(USBDevice *dev)
|
|
396 | 396 |
{ |
397 |
USBWacomState *s; |
|
398 |
|
|
399 |
s = qemu_mallocz(sizeof(USBWacomState)); |
|
397 |
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev); |
|
400 | 398 |
s->dev.speed = USB_SPEED_FULL; |
401 |
s->dev.handle_packet = usb_generic_handle_packet; |
|
399 |
return 0; |
|
400 |
} |
|
402 | 401 |
|
403 |
s->dev.handle_reset = usb_wacom_handle_reset;
|
|
404 |
s->dev.handle_control = usb_wacom_handle_control;
|
|
405 |
s->dev.handle_data = usb_wacom_handle_data;
|
|
406 |
s->dev.handle_destroy = usb_wacom_handle_destroy;
|
|
402 |
USBDevice *usb_wacom_init(void)
|
|
403 |
{
|
|
404 |
return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet");
|
|
405 |
}
|
|
407 | 406 |
|
408 |
pstrcpy(s->dev.devname, sizeof(s->dev.devname), |
|
409 |
"QEMU PenPartner Tablet"); |
|
407 |
static struct USBDeviceInfo wacom_info = { |
|
408 |
.qdev.name = "QEMU PenPartner Tablet", |
|
409 |
.qdev.size = sizeof(USBWacomState), |
|
410 |
.init = usb_wacom_initfn, |
|
411 |
.handle_packet = usb_generic_handle_packet, |
|
412 |
.handle_reset = usb_wacom_handle_reset, |
|
413 |
.handle_control = usb_wacom_handle_control, |
|
414 |
.handle_data = usb_wacom_handle_data, |
|
415 |
.handle_destroy = usb_wacom_handle_destroy, |
|
416 |
}; |
|
410 | 417 |
|
411 |
return (USBDevice *) s; |
|
418 |
static void usb_wacom_register_devices(void) |
|
419 |
{ |
|
420 |
usb_qdev_register(&wacom_info); |
|
412 | 421 |
} |
422 |
device_init(usb_wacom_register_devices) |
b/hw/usb.c | ||
---|---|---|
59 | 59 |
index = (s->setup_buf[5] << 8) | s->setup_buf[4]; |
60 | 60 |
|
61 | 61 |
if (s->setup_buf[0] & USB_DIR_IN) { |
62 |
ret = s->handle_control(s, request, value, index, |
|
63 |
s->setup_len, s->data_buf); |
|
62 |
ret = s->info->handle_control(s, request, value, index,
|
|
63 |
s->setup_len, s->data_buf);
|
|
64 | 64 |
if (ret < 0) |
65 | 65 |
return ret; |
66 | 66 |
|
... | ... | |
83 | 83 |
int ret = 0; |
84 | 84 |
|
85 | 85 |
if (p->devep != 0) |
86 |
return s->handle_data(s, p); |
|
86 |
return s->info->handle_data(s, p);
|
|
87 | 87 |
|
88 | 88 |
request = (s->setup_buf[0] << 8) | s->setup_buf[1]; |
89 | 89 |
value = (s->setup_buf[3] << 8) | s->setup_buf[2]; |
... | ... | |
93 | 93 |
case SETUP_STATE_ACK: |
94 | 94 |
if (!(s->setup_buf[0] & USB_DIR_IN)) { |
95 | 95 |
s->setup_state = SETUP_STATE_IDLE; |
96 |
ret = s->handle_control(s, request, value, index, |
|
97 |
s->setup_len, s->data_buf); |
|
96 |
ret = s->info->handle_control(s, request, value, index,
|
|
97 |
s->setup_len, s->data_buf);
|
|
98 | 98 |
if (ret > 0) |
99 | 99 |
return 0; |
100 | 100 |
return ret; |
... | ... | |
126 | 126 |
static int do_token_out(USBDevice *s, USBPacket *p) |
127 | 127 |
{ |
128 | 128 |
if (p->devep != 0) |
129 |
return s->handle_data(s, p); |
|
129 |
return s->info->handle_data(s, p);
|
|
130 | 130 |
|
131 | 131 |
switch(s->setup_state) { |
132 | 132 |
case SETUP_STATE_ACK: |
... | ... | |
179 | 179 |
s->remote_wakeup = 0; |
180 | 180 |
s->addr = 0; |
181 | 181 |
s->state = USB_STATE_DEFAULT; |
182 |
s->handle_reset(s); |
|
182 |
s->info->handle_reset(s);
|
|
183 | 183 |
return 0; |
184 | 184 |
} |
185 | 185 |
|
... | ... | |
225 | 225 |
USBPacket p; |
226 | 226 |
memset(&p, 0, sizeof(p)); |
227 | 227 |
p.pid = msg; |
228 |
dev->handle_packet(dev, &p); |
|
228 |
dev->info->handle_packet(dev, &p);
|
|
229 | 229 |
|
230 | 230 |
/* This _must_ be synchronous */ |
231 | 231 |
} |
b/hw/usb.h | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
|
25 | 25 |
#include "block.h" |
26 |
#include "qdev.h" |
|
26 | 27 |
|
27 | 28 |
#define USB_TOKEN_SETUP 0x2d |
28 | 29 |
#define USB_TOKEN_IN 0x69 /* device -> host */ |
... | ... | |
116 | 117 |
#define USB_ENDPOINT_XFER_BULK 2 |
117 | 118 |
#define USB_ENDPOINT_XFER_INT 3 |
118 | 119 |
|
120 |
typedef struct USBBus USBBus; |
|
119 | 121 |
typedef struct USBPort USBPort; |
120 | 122 |
typedef struct USBDevice USBDevice; |
123 |
typedef struct USBDeviceInfo USBDeviceInfo; |
|
121 | 124 |
typedef struct USBPacket USBPacket; |
122 | 125 |
|
123 | 126 |
/* definition of a USB device */ |
124 | 127 |
struct USBDevice { |
128 |
DeviceState qdev; |
|
129 |
USBDeviceInfo *info; |
|
125 | 130 |
void *opaque; |
126 | 131 |
|
127 |
/* |
|
128 |
* Process USB packet. |
|
132 |
int speed; |
|
133 |
uint8_t addr; |
|
134 |
char devname[32]; |
|
135 |
|
|
136 |
int state; |
|
137 |
uint8_t setup_buf[8]; |
|
138 |
uint8_t data_buf[1024]; |
|
139 |
int remote_wakeup; |
|
140 |
int setup_state; |
|
141 |
int setup_len; |
|
142 |
int setup_index; |
|
143 |
}; |
|
144 |
|
|
145 |
struct USBDeviceInfo { |
|
146 |
DeviceInfo qdev; |
|
147 |
int (*init)(USBDevice *dev); |
|
148 |
|
|
149 |
/* |
|
150 |
* Process USB packet. |
|
129 | 151 |
* Called by the HC (Host Controller). |
130 | 152 |
* |
131 |
* Returns length of the transaction
|
|
153 |
* Returns length of the transaction |
|
132 | 154 |
* or one of the USB_RET_XXX codes. |
133 |
*/
|
|
155 |
*/ |
|
134 | 156 |
int (*handle_packet)(USBDevice *dev, USBPacket *p); |
135 | 157 |
|
136 |
/*
|
|
158 |
/* |
|
137 | 159 |
* Called when device is destroyed. |
138 | 160 |
*/ |
139 | 161 |
void (*handle_destroy)(USBDevice *dev); |
140 | 162 |
|
141 |
int speed; |
|
142 |
|
|
143 |
/* The following fields are used by the generic USB device |
|
144 |
layer. They are here just to avoid creating a new structure |
|
145 |
for them. */ |
|
146 |
|
|
147 | 163 |
/* |
148 | 164 |
* Reset the device |
149 |
*/
|
|
165 |
*/ |
|
150 | 166 |
void (*handle_reset)(USBDevice *dev); |
151 | 167 |
|
152 | 168 |
/* |
... | ... | |
165 | 181 |
* Returns length or one of the USB_RET_ codes. |
166 | 182 |
*/ |
167 | 183 |
int (*handle_data)(USBDevice *dev, USBPacket *p); |
168 |
|
|
169 |
uint8_t addr; |
|
170 |
char devname[32]; |
|
171 |
|
|
172 |
int state; |
|
173 |
uint8_t setup_buf[8]; |
|
174 |
uint8_t data_buf[1024]; |
|
175 |
int remote_wakeup; |
|
176 |
int setup_state; |
|
177 |
int setup_len; |
|
178 |
int setup_index; |
|
179 | 184 |
}; |
180 | 185 |
|
181 | 186 |
typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev); |
... | ... | |
297 | 302 |
uint32_t musb_core_intr_get(MUSBState *s); |
298 | 303 |
void musb_core_intr_clear(MUSBState *s, uint32_t mask); |
299 | 304 |
void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); |
305 |
|
|
306 |
/* usb-bus.c */ |
|
307 |
|
|
308 |
struct USBBus { |
|
309 |
BusState qbus; |
|
310 |
int busnr; |
|
311 |
int nfree; |
|
312 |
int nused; |
|
313 |
TAILQ_HEAD(, USBPort) free; |
|
314 |
TAILQ_HEAD(, USBPort) used; |
|
315 |
TAILQ_ENTRY(USBBus) next; |
|
316 |
}; |
|
317 |
|
|
318 |
USBBus *usb_bus_new(DeviceState *host); |
|
319 |
USBBus *usb_bus_find(int busnr); |
|
320 |
void usb_qdev_register(USBDeviceInfo *info); |
|
321 |
void usb_qdev_register_many(USBDeviceInfo *info); |
|
322 |
USBDevice *usb_create_simple(USBBus *bus, const char *name); |
b/usb-linux.c | ||
---|---|---|
751 | 751 |
s->remote_wakeup = 0; |
752 | 752 |
s->addr = 0; |
753 | 753 |
s->state = USB_STATE_DEFAULT; |
754 |
s->handle_reset(s); |
|
754 |
s->info->handle_reset(s);
|
|
755 | 755 |
return 0; |
756 | 756 |
} |
757 | 757 |
|
... | ... | |
881 | 881 |
return 0; |
882 | 882 |
} |
883 | 883 |
|
884 |
static int usb_host_initfn(USBDevice *dev) |
|
885 |
{ |
|
886 |
return 0; |
|
887 |
} |
|
888 |
|
|
884 | 889 |
static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *prod_name) |
885 | 890 |
{ |
886 | 891 |
int fd = -1, ret; |
887 |
USBHostDevice *dev = NULL; |
|
892 |
USBDevice *d = NULL; |
|
893 |
USBHostDevice *dev; |
|
888 | 894 |
struct usbdevfs_connectinfo ci; |
889 | 895 |
char buf[1024]; |
890 | 896 |
|
891 |
dev = qemu_mallocz(sizeof(USBHostDevice)); |
|
892 |
|
|
893 |
dev->bus_num = bus_num; |
|
894 |
dev->addr = addr; |
|
895 |
|
|
896 | 897 |
printf("husb: open device %d.%d\n", bus_num, addr); |
897 | 898 |
|
898 | 899 |
if (!usb_host_device_path) { |
... | ... | |
908 | 909 |
} |
909 | 910 |
dprintf("husb: opened %s\n", buf); |
910 | 911 |
|
912 |
d = usb_create_simple(NULL /* FIXME */, "USB Host Device"); |
|
913 |
dev = DO_UPCAST(USBHostDevice, dev, d); |
|
914 |
|
|
915 |
dev->bus_num = bus_num; |
|
916 |
dev->addr = addr; |
|
917 |
|
|
911 | 918 |
/* read the device description */ |
912 | 919 |
dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); |
913 | 920 |
if (dev->descr_len <= 0) { |
... | ... | |
925 | 932 |
} |
926 | 933 |
#endif |
927 | 934 |
|
928 |
dev->fd = fd; |
|
929 | 935 |
|
930 | 936 |
/* |
931 | 937 |
* Initial configuration is -1 which makes us claim first |
... | ... | |
953 | 959 |
else |
954 | 960 |
dev->dev.speed = USB_SPEED_HIGH; |
955 | 961 |
|
956 |
dev->dev.handle_packet = usb_host_handle_packet; |
|
957 |
dev->dev.handle_reset = usb_host_handle_reset; |
|
958 |
dev->dev.handle_destroy = usb_host_handle_destroy; |
|
959 |
|
|
960 | 962 |
if (!prod_name || prod_name[0] == '\0') |
961 | 963 |
snprintf(dev->dev.devname, sizeof(dev->dev.devname), |
962 | 964 |
"host:%d.%d", bus_num, addr); |
... | ... | |
972 | 974 |
return (USBDevice *) dev; |
973 | 975 |
|
974 | 976 |
fail: |
975 |
if (dev)
|
|
976 |
qemu_free(dev);
|
|
977 |
|
|
978 |
close(fd); |
|
977 |
if (d) |
|
978 |
qdev_free(&d->qdev);
|
|
979 |
if (fd != -1) |
|
980 |
close(fd);
|
|
979 | 981 |
return NULL; |
980 | 982 |
} |
981 | 983 |
|
984 |
static struct USBDeviceInfo usb_host_dev_info = { |
|
985 |
.qdev.name = "USB Host Device", |
|
986 |
.qdev.size = sizeof(USBHostDevice), |
|
987 |
.init = usb_host_initfn, |
|
988 |
.handle_packet = usb_host_handle_packet, |
|
989 |
.handle_reset = usb_host_handle_reset, |
|
990 |
#if 0 |
|
991 |
.handle_control = usb_host_handle_control, |
|
992 |
.handle_data = usb_host_handle_data, |
|
993 |
#endif |
|
994 |
.handle_destroy = usb_host_handle_destroy, |
|
995 |
}; |
|
996 |
|
|
997 |
static void usb_host_register_devices(void) |
|
998 |
{ |
|
999 |
usb_qdev_register(&usb_host_dev_info); |
|
1000 |
} |
|
1001 |
device_init(usb_host_register_devices) |
|
1002 |
|
|
982 | 1003 |
static int usb_host_auto_add(const char *spec); |
983 | 1004 |
static int usb_host_auto_del(const char *spec); |
984 | 1005 |
|
b/vl.c | ||
---|---|---|
2481 | 2481 |
if (!err) |
2482 | 2482 |
usb_device_add_dev(dev); |
2483 | 2483 |
else |
2484 |
dev->handle_destroy(dev); |
|
2484 |
dev->info->handle_destroy(dev);
|
|
2485 | 2485 |
} |
2486 | 2486 |
|
2487 | 2487 |
static int usb_device_add(const char *devname, int is_hotplug) |
... | ... | |
2567 | 2567 |
dev = port->dev; |
2568 | 2568 |
*lastp = port->next; |
2569 | 2569 |
usb_attach(port, NULL); |
2570 |
dev->handle_destroy(dev); |
|
2570 |
dev->info->handle_destroy(dev);
|
|
2571 | 2571 |
port->next = free_usb_ports; |
2572 | 2572 |
free_usb_ports = port; |
2573 | 2573 |
return 0; |
Also available in: Unified diff