usb: -usbdevice cleanups, storage fix, QOMify ccid.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJaauEhAAoJEEy22O7T6HE44xcP/0adAFXpNaFmdlI4urSOpBWv
 4w3rwbmtfLRoevD8fRH2QK37T8qwc+bAPSN5NVzFAKY4GnFeC7noeRGHNdb1/KgU
 KY7B4lBWHaNh1m/F9ebyS/8SnagrwKWgyaia49DncYeSlvZ/CBUBzx7IjdVMWUYi
 dDj48yK70GzfhDMQUtbiVR3qKH+7ESN1l40cKnbleJrGEQA7V+/JpVaI/z9fxgU0
 rQTMf9OiLJqB8ymwaILWnWyWmw8MMcautaU9NURjGfBVitAX4mL4rWI7rVEcdozi
 jZZwcuN2NtQ6lHDgdIPAA3JOfzw/rp8ApT/VWWIY2YaQir1HydWZscPExfutEv0f
 ys8LsoS5L8SEUXWYJVUfuT1rD+fRUACmjwDzCH9kakL89uD4AnDF1X0SDvuQI4aH
 g+D8E5sRe/3yqosK4XHQNZlmBJ0x1KKNEWrIHjanzh5EcBiEpMJRA7NkmLFV6gsd
 DZf0vwiJNZ6sGwp/7ZpWtOYsyVBGM0Qapc2ooO40qUI88Fl/uzJk6EKYHypm+yud
 APNpdGKyj3JiyOVxSqvDdy7GCZh1QpdfvcFGofjQ44DcjXcG3Drnfg5k85nb/jQg
 pM15+Cvdq4OSg4sRun2PHZK9W8Mt/Tmk5elyC2DopLNnSH8JEOO+GTeLPHjOPOs1
 dH04KChG7zOxOHk6Wt5o
 =siZC
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/usb-20180126-v3-pull-request' into staging

usb: -usbdevice cleanups, storage fix, QOMify ccid.

# gpg: Signature made Fri 26 Jan 2018 08:04:49 GMT
# gpg:                using RSA key 0x4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/usb-20180126-v3-pull-request:
  usb-ccid: convert CCIDCardClass::exitfn() -> unrealize()
  usb-ccid: inline ccid_card_initfn() in ccid_card_realize()
  hw/usb/ccid: Make ccid_card_init() take an error parameter
  usb-storage: Fix share-rw option parsing
  usb: Remove legacy -usbdevice options (host, serial, disk and net)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2018-01-26 13:29:28 +00:00
commit d45091e449
15 changed files with 74 additions and 370 deletions

View File

@ -224,6 +224,7 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
/* handle legacy '-drive if=scsi,...' cmd line args */ /* handle legacy '-drive if=scsi,...' cmd line args */
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
int unit, bool removable, int bootindex, int unit, bool removable, int bootindex,
bool share_rw,
const char *serial, Error **errp) const char *serial, Error **errp)
{ {
const char *driver; const char *driver;
@ -254,6 +255,12 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
object_unparent(OBJECT(dev)); object_unparent(OBJECT(dev));
return NULL; return NULL;
} }
object_property_set_bool(OBJECT(dev), share_rw, "share-rw", &err);
if (err != NULL) {
error_propagate(errp, err);
object_unparent(OBJECT(dev));
return NULL;
}
object_property_set_bool(OBJECT(dev), true, "realized", &err); object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) { if (err != NULL) {
error_propagate(errp, err); error_propagate(errp, err);
@ -288,7 +295,7 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated)
} }
} }
scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo), scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
unit, false, -1, NULL, &error_fatal); unit, false, -1, false, NULL, &error_fatal);
} }
loc_pop(&loc); loc_pop(&loc);
} }

View File

@ -43,7 +43,7 @@ redirect.o-libs = $(USB_REDIR_LIBS)
# usb pass-through # usb pass-through
ifeq ($(CONFIG_USB_LIBUSB)$(CONFIG_USB),yy) ifeq ($(CONFIG_USB_LIBUSB)$(CONFIG_USB),yy)
common-obj-y += host-libusb.o host-legacy.o common-obj-y += host-libusb.o
else else
common-obj-y += host-stub.o common-obj-y += host-stub.o
endif endif

View File

@ -35,6 +35,7 @@
#include "qemu/thread.h" #include "qemu/thread.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "ccid.h" #include "ccid.h"
#include "qapi/error.h"
#define DPRINTF(card, lvl, fmt, ...) \ #define DPRINTF(card, lvl, fmt, ...) \
do {\ do {\
@ -401,10 +402,10 @@ static void card_event_handler(EventNotifier *notifier)
qemu_mutex_unlock(&card->event_list_mutex); qemu_mutex_unlock(&card->event_list_mutex);
} }
static int init_event_notifier(EmulatedState *card) static int init_event_notifier(EmulatedState *card, Error **errp)
{ {
if (event_notifier_init(&card->notifier, false) < 0) { if (event_notifier_init(&card->notifier, false) < 0) {
DPRINTF(card, 2, "event notifier creation failed\n"); error_setg(errp, "ccid-card-emul: event notifier creation failed");
return -1; return -1;
} }
event_notifier_set_handler(&card->notifier, card_event_handler); event_notifier_set_handler(&card->notifier, card_event_handler);
@ -480,7 +481,7 @@ static uint32_t parse_enumeration(char *str,
return ret; return ret;
} }
static int emulated_initfn(CCIDCardState *base) static void emulated_realize(CCIDCardState *base, Error **errp)
{ {
EmulatedState *card = EMULATED_CCID_CARD(base); EmulatedState *card = EMULATED_CCID_CARD(base);
VCardEmulError ret; VCardEmulError ret;
@ -494,8 +495,8 @@ static int emulated_initfn(CCIDCardState *base)
qemu_cond_init(&card->handle_apdu_cond); qemu_cond_init(&card->handle_apdu_cond);
card->reader = NULL; card->reader = NULL;
card->quit_apdu_thread = 0; card->quit_apdu_thread = 0;
if (init_event_notifier(card) < 0) { if (init_event_notifier(card, errp) < 0) {
return -1; return;
} }
card->backend = 0; card->backend = 0;
@ -505,11 +506,11 @@ static int emulated_initfn(CCIDCardState *base)
} }
if (card->backend == 0) { if (card->backend == 0) {
printf("backend must be one of:\n"); error_setg(errp, "backend must be one of:");
for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) { for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) {
printf("%s\n", ptable->name); error_append_hint(errp, "%s\n", ptable->name);
} }
return -1; return;
} }
/* TODO: a passthru backened that works on local machine. third card type?*/ /* TODO: a passthru backened that works on local machine. third card type?*/
@ -517,37 +518,36 @@ static int emulated_initfn(CCIDCardState *base)
if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) { if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) {
ret = emulated_initialize_vcard_from_certificates(card); ret = emulated_initialize_vcard_from_certificates(card);
} else { } else {
printf("%s: you must provide all three certs for" error_setg(errp, "%s: you must provide all three certs for"
" certificates backend\n", TYPE_EMULATED_CCID); " certificates backend", TYPE_EMULATED_CCID);
return -1; return;
} }
} else { } else {
if (card->backend != BACKEND_NSS_EMULATED) { if (card->backend != BACKEND_NSS_EMULATED) {
printf("%s: bad backend specified. The options are:\n%s (default)," error_setg(errp, "%s: bad backend specified. The options are:%s"
" %s.\n", TYPE_EMULATED_CCID, BACKEND_NSS_EMULATED_NAME, " (default), %s.", TYPE_EMULATED_CCID,
BACKEND_CERTIFICATES_NAME); BACKEND_NSS_EMULATED_NAME, BACKEND_CERTIFICATES_NAME);
return -1; return;
} }
if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) { if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) {
printf("%s: unexpected cert parameters to nss emulated backend\n", error_setg(errp, "%s: unexpected cert parameters to nss emulated "
TYPE_EMULATED_CCID); "backend", TYPE_EMULATED_CCID);
return -1; return;
} }
/* default to mirroring the local hardware readers */ /* default to mirroring the local hardware readers */
ret = wrap_vcard_emul_init(NULL); ret = wrap_vcard_emul_init(NULL);
} }
if (ret != VCARD_EMUL_OK) { if (ret != VCARD_EMUL_OK) {
printf("%s: failed to initialize vcard\n", TYPE_EMULATED_CCID); error_setg(errp, "%s: failed to initialize vcard", TYPE_EMULATED_CCID);
return -1; return;
} }
qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread, qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread,
card, QEMU_THREAD_JOINABLE); card, QEMU_THREAD_JOINABLE);
qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread, qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread,
card, QEMU_THREAD_JOINABLE); card, QEMU_THREAD_JOINABLE);
return 0;
} }
static void emulated_exitfn(CCIDCardState *base) static void emulated_unrealize(CCIDCardState *base, Error **errp)
{ {
EmulatedState *card = EMULATED_CCID_CARD(base); EmulatedState *card = EMULATED_CCID_CARD(base);
VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL); VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
@ -581,8 +581,8 @@ static void emulated_class_initfn(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
CCIDCardClass *cc = CCID_CARD_CLASS(klass); CCIDCardClass *cc = CCID_CARD_CLASS(klass);
cc->initfn = emulated_initfn; cc->realize = emulated_realize;
cc->exitfn = emulated_exitfn; cc->unrealize = emulated_unrealize;
cc->get_atr = emulated_get_atr; cc->get_atr = emulated_get_atr;
cc->apdu_from_guest = emulated_apdu_from_guest; cc->apdu_from_guest = emulated_apdu_from_guest;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories); set_bit(DEVICE_CATEGORY_INPUT, dc->categories);

View File

@ -9,11 +9,13 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h"
#include <cacard/vscard_common.h> #include <cacard/vscard_common.h>
#include "chardev/char-fe.h" #include "chardev/char-fe.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "ccid.h" #include "ccid.h"
#include "qapi/error.h"
#define DPRINTF(card, lvl, fmt, ...) \ #define DPRINTF(card, lvl, fmt, ...) \
do { \ do { \
@ -337,29 +339,28 @@ static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
return card->atr; return card->atr;
} }
static int passthru_initfn(CCIDCardState *base) static void passthru_realize(CCIDCardState *base, Error **errp)
{ {
PassthruState *card = PASSTHRU_CCID_CARD(base); PassthruState *card = PASSTHRU_CCID_CARD(base);
card->vscard_in_pos = 0; card->vscard_in_pos = 0;
card->vscard_in_hdr = 0; card->vscard_in_hdr = 0;
if (qemu_chr_fe_backend_connected(&card->cs)) { if (qemu_chr_fe_backend_connected(&card->cs)) {
DPRINTF(card, D_INFO, "initing chardev\n"); error_setg(errp, "ccid-card-passthru: initing chardev");
qemu_chr_fe_set_handlers(&card->cs, qemu_chr_fe_set_handlers(&card->cs,
ccid_card_vscard_can_read, ccid_card_vscard_can_read,
ccid_card_vscard_read, ccid_card_vscard_read,
ccid_card_vscard_event, NULL, card, NULL, true); ccid_card_vscard_event, NULL, card, NULL, true);
ccid_card_vscard_send_init(card); ccid_card_vscard_send_init(card);
} else { } else {
error_report("missing chardev"); error_setg(errp, "missing chardev");
return -1; return;
} }
card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE, card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
card->debug); card->debug);
assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE); assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR)); memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
card->atr_length = sizeof(DEFAULT_ATR); card->atr_length = sizeof(DEFAULT_ATR);
return 0;
} }
static VMStateDescription passthru_vmstate = { static VMStateDescription passthru_vmstate = {
@ -387,7 +388,7 @@ static void passthru_class_initfn(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
CCIDCardClass *cc = CCID_CARD_CLASS(klass); CCIDCardClass *cc = CCID_CARD_CLASS(klass);
cc->initfn = passthru_initfn; cc->realize = passthru_realize;
cc->get_atr = passthru_get_atr; cc->get_atr = passthru_get_atr;
cc->apdu_from_guest = passthru_apdu_from_guest; cc->apdu_from_guest = passthru_apdu_from_guest;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories); set_bit(DEVICE_CATEGORY_INPUT, dc->categories);

View File

@ -28,13 +28,15 @@ typedef struct CCIDCardInfo CCIDCardInfo;
* into the smartcard device (hw/ccid-card-*.c) * into the smartcard device (hw/ccid-card-*.c)
*/ */
typedef struct CCIDCardClass { typedef struct CCIDCardClass {
/*< private >*/
DeviceClass parent_class; DeviceClass parent_class;
/*< public >*/
const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len); const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
void (*apdu_from_guest)(CCIDCardState *card, void (*apdu_from_guest)(CCIDCardState *card,
const uint8_t *apdu, const uint8_t *apdu,
uint32_t len); uint32_t len);
void (*exitfn)(CCIDCardState *card); void (*realize)(CCIDCardState *card, Error **errp);
int (*initfn)(CCIDCardState *card); void (*unrealize)(CCIDCardState *card, Error **errp);
} CCIDCardClass; } CCIDCardClass;
/* /*

View File

@ -1382,31 +1382,6 @@ static void usb_net_instance_init(Object *obj)
&dev->qdev, NULL); &dev->qdev, NULL);
} }
static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
{
Error *local_err = NULL;
USBDevice *dev;
QemuOpts *opts;
int idx;
opts = qemu_opts_parse_noisily(qemu_find_opts("net"), cmdline, false);
if (!opts) {
return NULL;
}
qemu_opt_set(opts, "type", "nic", &error_abort);
qemu_opt_set(opts, "model", "usb", &error_abort);
idx = net_client_init(opts, false, &local_err);
if (local_err) {
error_report_err(local_err);
return NULL;
}
dev = usb_create(bus, "usb-net");
qdev_set_nic_properties(&dev->qdev, &nd_table[idx]);
return dev;
}
static const VMStateDescription vmstate_usb_net = { static const VMStateDescription vmstate_usb_net = {
.name = "usb-net", .name = "usb-net",
.unmigratable = 1, .unmigratable = 1,
@ -1446,7 +1421,6 @@ static const TypeInfo net_info = {
static void usb_net_register_types(void) static void usb_net_register_types(void)
{ {
type_register_static(&net_info); type_register_static(&net_info);
usb_legacy_register(TYPE_USB_NET, "net", usb_net_init);
} }
type_init(usb_net_register_types) type_init(usb_net_register_types)

View File

@ -509,35 +509,6 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
} }
} }
static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
{
USBDevice *dev;
Chardev *cdrv;
char label[32];
static int index;
if (*filename == ':') {
filename++;
} else if (*filename) {
error_report("unrecognized serial USB option %s", filename);
return NULL;
}
if (!*filename) {
error_report("character device specification needed");
return NULL;
}
snprintf(label, sizeof(label), "usbserial%d", index++);
cdrv = qemu_chr_new(label, filename);
if (!cdrv)
return NULL;
dev = usb_create(bus, "usb-serial");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
return dev;
}
static USBDevice *usb_braille_init(USBBus *bus, const char *unused) static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
{ {
USBDevice *dev; USBDevice *dev;
@ -624,7 +595,6 @@ static void usb_serial_register_types(void)
{ {
type_register_static(&usb_serial_dev_type_info); type_register_static(&usb_serial_dev_type_info);
type_register_static(&serial_info); type_register_static(&serial_info);
usb_legacy_register("usb-serial", "serial", usb_serial_init);
type_register_static(&braille_info); type_register_static(&braille_info);
usb_legacy_register("usb-braille", "braille", usb_braille_init); usb_legacy_register("usb-braille", "braille", usb_braille_init);
} }

View File

@ -500,26 +500,6 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
} }
} }
static void ccid_card_exitfn(CCIDCardState *card)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
if (cc->exitfn) {
cc->exitfn(card);
}
}
static int ccid_card_initfn(CCIDCardState *card)
{
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
if (cc->initfn) {
return cc->initfn(card);
}
return 0;
}
static bool ccid_has_pending_answers(USBCCIDState *s) static bool ccid_has_pending_answers(USBCCIDState *s)
{ {
return s->pending_answers_num > 0; return s->pending_answers_num > 0;
@ -1281,41 +1261,52 @@ void ccid_card_card_inserted(CCIDCardState *card)
ccid_on_slot_change(s, true); ccid_on_slot_change(s, true);
} }
static int ccid_card_exit(DeviceState *qdev) static void ccid_card_unrealize(DeviceState *qdev, Error **errp)
{ {
CCIDCardState *card = CCID_CARD(qdev); CCIDCardState *card = CCID_CARD(qdev);
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent); USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent);
USBCCIDState *s = USB_CCID_DEV(dev); USBCCIDState *s = USB_CCID_DEV(dev);
Error *local_err = NULL;
if (ccid_card_inserted(s)) { if (ccid_card_inserted(s)) {
ccid_card_card_removed(card); ccid_card_card_removed(card);
} }
ccid_card_exitfn(card); if (cc->unrealize) {
cc->unrealize(card, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
}
s->card = NULL; s->card = NULL;
return 0;
} }
static int ccid_card_init(DeviceState *qdev) static void ccid_card_realize(DeviceState *qdev, Error **errp)
{ {
CCIDCardState *card = CCID_CARD(qdev); CCIDCardState *card = CCID_CARD(qdev);
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent); USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent);
USBCCIDState *s = USB_CCID_DEV(dev); USBCCIDState *s = USB_CCID_DEV(dev);
int ret = 0; Error *local_err = NULL;
if (card->slot != 0) { if (card->slot != 0) {
warn_report("usb-ccid supports one slot, can't add %d", error_setg(errp, "usb-ccid supports one slot, can't add %d",
card->slot); card->slot);
return -1; return;
} }
if (s->card != NULL) { if (s->card != NULL) {
warn_report("usb-ccid card already full, not adding"); error_setg(errp, "usb-ccid card already full, not adding");
return -1; return;
} }
ret = ccid_card_initfn(card); if (cc->realize) {
if (ret == 0) { cc->realize(card, &local_err);
s->card = card; if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
} }
return ret; s->card = card;
} }
static void ccid_realize(USBDevice *dev, Error **errp) static void ccid_realize(USBDevice *dev, Error **errp)
@ -1477,8 +1468,8 @@ static void ccid_card_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *k = DEVICE_CLASS(klass); DeviceClass *k = DEVICE_CLASS(klass);
k->bus_type = TYPE_CCID_BUS; k->bus_type = TYPE_CCID_BUS;
k->init = ccid_card_init; k->realize = ccid_card_realize;
k->exit = ccid_card_exit; k->unrealize = ccid_card_unrealize;
k->props = ccid_props; k->props = ccid_props;
} }

View File

@ -633,7 +633,8 @@ static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
&usb_msd_scsi_info_storage, NULL); &usb_msd_scsi_info_storage, NULL);
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable, scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
s->conf.bootindex, dev->serial, s->conf.bootindex, s->conf.share_rw,
dev->serial,
errp); errp);
blk_unref(blk); blk_unref(blk);
if (!scsi_dev) { if (!scsi_dev) {
@ -666,63 +667,6 @@ static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
usb_msd_handle_reset(dev); usb_msd_handle_reset(dev);
} }
static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
{
static int nr=0;
Error *err = NULL;
char id[8];
QemuOpts *opts;
DriveInfo *dinfo;
USBDevice *dev;
const char *p1;
char fmt[32];
/* parse -usbdevice disk: syntax into drive opts */
do {
snprintf(id, sizeof(id), "usb%d", nr++);
opts = qemu_opts_create(qemu_find_opts("drive"), id, 1, NULL);
} while (!opts);
p1 = strchr(filename, ':');
if (p1++) {
const char *p2;
if (strstart(filename, "format=", &p2)) {
int len = MIN(p1 - p2, sizeof(fmt));
pstrcpy(fmt, len, p2);
qemu_opt_set(opts, "format", fmt, &error_abort);
} else if (*filename != ':') {
error_report("unrecognized USB mass-storage option %s", filename);
return NULL;
}
filename = p1;
}
if (!*filename) {
error_report("block device specification needed");
return NULL;
}
qemu_opt_set(opts, "file", filename, &error_abort);
qemu_opt_set(opts, "if", "none", &error_abort);
/* create host drive */
dinfo = drive_new(opts, 0);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
}
/* create guest device */
dev = usb_create(bus, "usb-storage");
qdev_prop_set_drive(&dev->qdev, "drive", blk_by_legacy_dinfo(dinfo),
&err);
if (err) {
error_report_err(err);
object_unparent(OBJECT(dev));
return NULL;
}
return dev;
}
static const VMStateDescription vmstate_usb_msd = { static const VMStateDescription vmstate_usb_msd = {
.name = "usb-storage", .name = "usb-storage",
.version_id = 1, .version_id = 1,
@ -855,7 +799,6 @@ static void usb_msd_register_types(void)
type_register_static(&usb_storage_dev_type_info); type_register_static(&usb_storage_dev_type_info);
type_register_static(&msd_info); type_register_static(&msd_info);
type_register_static(&bot_info); type_register_static(&bot_info);
usb_legacy_register("usb-storage", "disk", usb_msd_init);
} }
type_init(usb_msd_register_types) type_init(usb_msd_register_types)

View File

@ -1,144 +0,0 @@
/*
* Linux host USB redirector
*
* Copyright (c) 2005 Fabrice Bellard
*
* Copyright (c) 2008 Max Krasnyansky
* Support for host device auto connect & disconnect
* Major rewrite to support fully async operation
*
* Copyright 2008 TJ <linux@tjworld.net>
* Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
* to the legacy /proc/bus/usb USB device discovery and handling
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/usb.h"
#include "hw/usb/host.h"
/*
* Autoconnect filter
* Format:
* auto:bus:dev[:vid:pid]
* auto:bus.dev[:vid:pid]
*
* bus - bus number (dec, * means any)
* dev - device number (dec, * means any)
* vid - vendor id (hex, * means any)
* pid - product id (hex, * means any)
*
* See 'lsusb' output.
*/
static int parse_filter(const char *spec, struct USBAutoFilter *f)
{
enum { BUS, DEV, VID, PID, DONE };
const char *p = spec;
int i;
f->bus_num = 0;
f->addr = 0;
f->vendor_id = 0;
f->product_id = 0;
for (i = BUS; i < DONE; i++) {
p = strpbrk(p, ":.");
if (!p) {
break;
}
p++;
if (*p == '*') {
continue;
}
switch (i) {
case BUS:
f->bus_num = strtol(p, NULL, 10);
break;
case DEV:
f->addr = strtol(p, NULL, 10);
break;
case VID:
f->vendor_id = strtol(p, NULL, 16);
break;
case PID:
f->product_id = strtol(p, NULL, 16);
break;
}
}
if (i < DEV) {
fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
return -1;
}
return 0;
}
USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
{
struct USBAutoFilter filter;
USBDevice *dev;
char *p;
dev = usb_create(bus, "usb-host");
if (strstr(devname, "auto:")) {
if (parse_filter(devname, &filter) < 0) {
goto fail;
}
} else {
p = strchr(devname, '.');
if (p) {
filter.bus_num = strtoul(devname, NULL, 0);
filter.addr = strtoul(p + 1, NULL, 0);
filter.vendor_id = 0;
filter.product_id = 0;
} else {
p = strchr(devname, ':');
if (p) {
filter.bus_num = 0;
filter.addr = 0;
filter.vendor_id = strtoul(devname, NULL, 16);
filter.product_id = strtoul(p + 1, NULL, 16);
} else {
goto fail;
}
}
}
qdev_prop_set_uint32(&dev->qdev, "hostbus", filter.bus_num);
qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr);
qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id);
qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
return dev;
fail:
object_unparent(OBJECT(dev));
return NULL;
}
static void usb_host_register_types(void)
{
usb_legacy_register("usb-host", "host", usb_host_device_open);
}
type_init(usb_host_register_types)

View File

@ -41,12 +41,6 @@ void hmp_info_usbhost(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "USB host devices not supported\n"); monitor_printf(mon, "USB host devices not supported\n");
} }
/* XXX: modify configure to compile the right host driver */
USBDevice *usb_host_device_open(USBBus *bus, const char *devname)
{
return NULL;
}
bool usb_host_dev_is_scsi_storage(USBDevice *ud) bool usb_host_dev_is_scsi_storage(USBDevice *ud)
{ {
return false; return false;

View File

@ -151,6 +151,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk, SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
int unit, bool removable, int bootindex, int unit, bool removable, int bootindex,
bool share_rw,
const char *serial, Error **errp); const char *serial, Error **errp);
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated); void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated);
void scsi_legacy_handle_cmdline(void); void scsi_legacy_handle_cmdline(void);

View File

@ -466,7 +466,6 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream);
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p); void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p);
/* usb-linux.c */ /* usb-linux.c */
USBDevice *usb_host_device_open(USBBus *bus, const char *devname);
void hmp_info_usbhost(Monitor *mon, const QDict *qdict); void hmp_info_usbhost(Monitor *mon, const QDict *qdict);
bool usb_host_dev_is_scsi_storage(USBDevice *usbdev); bool usb_host_dev_is_scsi_storage(USBDevice *usbdev);

View File

@ -1221,29 +1221,10 @@ Pointer device that uses absolute coordinates (like a touchscreen). This
means QEMU is able to report the mouse position without having to grab the means QEMU is able to report the mouse position without having to grab the
mouse. Also overrides the PS/2 mouse emulation when activated. mouse. Also overrides the PS/2 mouse emulation when activated.
@item disk:[format=@var{format}]:@var{file}
Mass storage device based on file. The optional @var{format} argument
will be used rather than detecting the format. Can be used to specify
@code{format=raw} to avoid interpreting an untrusted format header.
@item host:@var{bus}.@var{addr}
Pass through the host device identified by @var{bus}.@var{addr} (Linux only).
@item host:@var{vendor_id}:@var{product_id}
Pass through the host device identified by @var{vendor_id}:@var{product_id}
(Linux only).
@item serial:[vendorid=@var{vendor_id}][,productid=@var{product_id}]:@var{dev}
Serial converter to host character device @var{dev}, see @code{-serial} for the
available devices.
@item braille @item braille
Braille device. This will use BrlAPI to display the braille output on a real Braille device. This will use BrlAPI to display the braille output on a real
or fake device. or fake device.
@item net:@var{options}
Network adapter that supports CDC ethernet and RNDIS protocols.
@end table @end table
ETEXI ETEXI

15
vl.c
View File

@ -1451,30 +1451,15 @@ static void igd_gfx_passthru(void)
static int usb_device_add(const char *devname) static int usb_device_add(const char *devname)
{ {
USBDevice *dev = NULL; USBDevice *dev = NULL;
#ifndef CONFIG_LINUX
const char *p;
#endif
if (!machine_usb(current_machine)) { if (!machine_usb(current_machine)) {
return -1; return -1;
} }
/* drivers with .usbdevice_name entry in USBDeviceInfo */
dev = usbdevice_create(devname); dev = usbdevice_create(devname);
if (dev)
goto done;
/* the other ones */
#ifndef CONFIG_LINUX
/* only the linux version is qdev-ified, usb-bsd still needs this */
if (strstart(devname, "host:", &p)) {
dev = usb_host_device_open(usb_bus_find(-1), p);
}
#endif
if (!dev) if (!dev)
return -1; return -1;
done:
return 0; return 0;
} }