On Tue, Jan 25, 2011 at 05:36:58PM -0700, Eric Blake wrote: > * src/qemu/qemu_command.c (qemuBuildCommandLine): Emit smartcard > options. > (qemuAssignDeviceAliases): Assign an alias for smartcards. > (qemuBuildControllerDevStr): Manage the usb-ccid controller. > * tests/qemuxml2argvtest.c (mymain): Add new tests. > * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args: New > file. > * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args: > Likewise. > * tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough.args: > Likewise. > * tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args: > Likewise. > > Notes: > v2: new patch > v3: reject ',' in cert name, alias for host smartcard use, output > usb-ccid controller separate from rest of command line, enforce at > most one smartcard for now > --- > src/qemu/qemu_command.c | 90 +++++++++++++++++++- > .../qemuxml2argv-smartcard-controller.args | 1 + > .../qemuxml2argv-smartcard-host-certificates.args | 1 + > .../qemuxml2argv-smartcard-host.args | 1 + > .../qemuxml2argv-smartcard-passthrough-tcp.args | 1 + > tests/qemuxml2argvtest.c | 13 +++ > 6 files changed, 106 insertions(+), 1 deletions(-) > create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args > create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args > create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args > create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args ACK > > diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c > index 5b65f26..5197ab6 100644 > --- a/src/qemu/qemu_command.c > +++ b/src/qemu/qemu_command.c > @@ -638,6 +638,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags) > if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0) > goto no_memory; > } > + for (i = 0; i < def->nsmartcards ; i++) { > + if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0) > + goto no_memory; > + } > if (def->console) { > if (virAsprintf(&def->console->info.alias, "console%d", i) < 0) > goto no_memory; > @@ -1003,7 +1007,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) > /* Disk controllers (SCSI only for now) */ > for (i = 0; i < def->ncontrollers ; i++) { > /* FDC lives behind the ISA bridge */ > - if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC) > + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC || > + def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID) > continue; Worth updating the comment that 'ccid is a USB device' > > /* First IDE controller lives on the PIIX3 at slot=1, function=1, > @@ -1505,6 +1510,10 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def) > } > break; > > + case VIR_DOMAIN_CONTROLLER_TYPE_CCID: > + virBufferVSprintf(&buf, "usb-ccid,id=ccid%d", def->idx); > + break; > + > /* We always get an IDE controller, whether we want it or not. */ > case VIR_DOMAIN_CONTROLLER_TYPE_IDE: > default: > @@ -3412,6 +3421,85 @@ qemuBuildCommandLine(virConnectPtr conn, > } > } > > + if (def->nsmartcards) { > + /* -device usb-ccid was already emitted along with other > + * controllers. For now, qemu handles only one smartcard. */ > + virDomainSmartcardDefPtr smartcard = def->smartcards[0]; > + char *devstr; > + virBuffer opt = VIR_BUFFER_INITIALIZER; > + int j; > + > + if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) || > + !(qemuCmdFlags & QEMUD_CMD_FLAG_USB_CCID)) { > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("this QEMU binary lacks smartcard support")); > + goto error; > + } > + if (def->nsmartcards > 1 || > + smartcard->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID || > + smartcard->info.addr.ccid.controller != 0 || > + smartcard->info.addr.ccid.slot != 0) { > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("this QEMU binary lacks multiple smartcard " > + "support")); > + virBufferFreeAndReset(&opt); > + goto error; > + } > + > + switch (smartcard->type) { > + case VIR_DOMAIN_SMARTCARD_TYPE_HOST: > + virBufferAddLit(&opt, "ccid-card-emulated,backend=nss-emulated"); > + break; > + case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES: > + virBufferAddLit(&opt, "ccid-card-emulated,backend=certificates"); > + for (j = 0; j < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; j++) { > + if (strchr(smartcard->data.cert.file[j], ',')) { > + virBufferFreeAndReset(&opt); > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, > + _("invalid certificate name: %s"), > + smartcard->data.cert.file[j]); > + goto error; > + } > + virBufferVSprintf(&opt, ",cert%d=%s", j + 1, > + smartcard->data.cert.file[j]); > + } > + if (smartcard->data.cert.database) { > + if (strchr(smartcard->data.cert.database, ',')) { > + virBufferFreeAndReset(&opt); > + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, > + _("invalid database name: %s"), > + smartcard->data.cert.database); > + goto error; > + } > + virBufferVSprintf(&opt, ",database=%s", > + smartcard->data.cert.database); > + } > + break; > + case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: > + virCommandAddArg(cmd, "-chardev"); > + if (!(devstr = qemuBuildChrChardevStr(&smartcard->data.passthru, > + smartcard->info.alias))) { > + virBufferFreeAndReset(&opt); > + goto error; > + } > + virCommandAddArg(cmd, devstr); > + VIR_FREE(devstr); > + > + virBufferVSprintf(&opt, "ccid-card-passthru,chardev=char%s", > + smartcard->info.alias); > + break; > + default: > + qemuReportError(VIR_ERR_INTERNAL_ERROR, > + _("unexpected smartcard type %d"), > + smartcard->type); > + virBufferFreeAndReset(&opt); > + goto error; > + } > + virCommandAddArg(cmd, "-device"); > + virBufferVSprintf(&opt, ",id=%s,bus=ccid0.0", smartcard->info.alias); > + virCommandAddArgBuffer(cmd, &opt); > + } > + > if (!def->nserials) { > /* If we have -device, then we set -nodefault already */ > if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) ACK Daniel -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list