From: Anthony Liguori <anthony@codemonkey.ws>
To: Alon Levy <alevy@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 06/20] usb-ccid: review fixes (v15-v16)
Date: Thu, 03 Feb 2011 10:48:03 -0600 [thread overview]
Message-ID: <4D4ADC43.90709@codemonkey.ws> (raw)
In-Reply-To: <1296678500-19497-7-git-send-email-alevy@redhat.com>
On 02/02/2011 02:28 PM, Alon Levy wrote:
> I'll fold it before submitting the version to be applied, but
> I hope keeping it as a separate patch will make reviewing easier.
>
Hrm, can you just send out the new patches? It's actually harder to
review like this.
Regards,
Anthony Liguori
> Behavioral changes:
> * fix abort on client answer after card remove
> * enable migration
> * remove side affect code from asserts
> * return consistent self-powered state
> * mask out reserved bits in ccid_set_parameters
> * add missing abRFU in SetParameters (no affect on linux guest)
>
> whitefixes / comments / consts defines:
> * remove stale comment
> * remove ccid_print_pending_answers if no DEBUG_CCID
> * replace printf's with DPRINTF, remove DEBUG_CCID, add verbosity defines
> * use error_report
> * update copyright (most of the code is not original)
> * reword known bug comment
> * add missing closing quote in comment
> * add missing whitespace on one line
> * s/CCID_SetParameter/CCID_SetParameters/
> * add comments
> * use define for max packet size
>
> Comment for "return consistent self-powered state":
>
> the Configuration Descriptor bmAttributes claims we are self powered,
> but we were returning not self powered to USB_REQ_GET_STATUS control message.
>
> In practice, this message is not sent by a linux 2.6.35.10-74.fc14.x86_64
> guest (not tested on other guests), unless you issue lsusb -v as root (for
> example).
>
> Signed-off-by: Alon Levy<alevy@redhat.com>
> ---
> hw/ccid.h | 7 +++
> hw/usb-ccid.c | 115 ++++++++++++++++++++++++++++-----------------------------
> 2 files changed, 63 insertions(+), 59 deletions(-)
>
> diff --git a/hw/ccid.h b/hw/ccid.h
> index af59070..f5dcfae 100644
> --- a/hw/ccid.h
> +++ b/hw/ccid.h
> @@ -6,11 +6,16 @@
> typedef struct CCIDCardState CCIDCardState;
> typedef struct CCIDCardInfo CCIDCardInfo;
>
> +/* state of the CCID Card device (i.e. hw/ccid-card-*.c)
> + */
> struct CCIDCardState {
> DeviceState qdev;
> uint32_t slot; // For future use with multiple slot reader.
> };
>
> +/* callbacks to be used by the CCID device (hw/usb-ccid.c) to call
> + * into the smartcard device (hw/ccid-card-*.c)
> + */
> struct CCIDCardInfo {
> DeviceInfo qdev;
> void (*print)(Monitor *mon, CCIDCardState *card, int indent);
> @@ -20,6 +25,8 @@ struct CCIDCardInfo {
> int (*initfn)(CCIDCardState *card);
> };
>
> +/* API for smartcard calling the CCID device (used by hw/ccid-card-*.c)
> + */
> void ccid_card_send_apdu_to_guest(CCIDCardState *card, uint8_t* apdu, uint32_t len);
> void ccid_card_card_removed(CCIDCardState *card);
> void ccid_card_card_inserted(CCIDCardState *card);
> diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
> index 58f69a6..09e39ac 100644
> --- a/hw/usb-ccid.c
> +++ b/hw/usb-ccid.c
> @@ -1,15 +1,18 @@
> /*
> * CCID Device emulation
> *
> - * Based on usb-serial.c:
> + * Written by Alon Levy, with contributions from Robert Relyea.
> + *
> + * Based on usb-serial.c, see it's copyright and attributions below.
> + *
> + * This code is licenced under the GNU LGPL, version 2 or later.
> + *
> + * -------
> + *
> + * usb-serial.c copyright and attribution:
> * Copyright (c) 2006 CodeSourcery.
> * Copyright (c) 2008 Samuel Thibault<samuel.thibault@ens-lyon.org>
> * Written by Paul Brook, reused for FTDI by Samuel Thibault,
> - * Reused for CCID by Alon Levy.
> - * Contributed to by Robert Relyea
> - * Copyright (c) 2010 Red Hat.
> - *
> - * This code is licenced under the LGPL.
> */
>
> /* References:
> @@ -19,22 +22,16 @@
> * Specification for Integrated Circuit(s) Cards Interface Devices
> *
> * Endianess note: from the spec (1.3)
> - * "Fields that are larger than a byte are stored in little endian
> + * "Fields that are larger than a byte are stored in little endian"
> *
> * KNOWN BUGS
> * 1. remove/insert can sometimes result in removed state instead of inserted.
> * This is a result of the following:
> - * symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This happens
> - * when we send a too short packet, seen in uhci-usb.c, resulting from
> - * a urb requesting SPD and us returning a smaller packet.
> + * symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This can happen
> + * when a short packet is sent, as seen in uhci-usb.c, resulting from a urb
> + * from the guest requesting SPD and us returning a smaller packet.
> * Not sure which messages trigger this.
> *
> - * Migration note:
> - *
> - * All the VMStateDescription's are left here for future use, but
> - * not enabled right now since there is no support for USB migration.
> - *
> - * To enable define ENABLE_MIGRATION
> */
>
> #include "qemu-common.h"
> @@ -44,11 +41,14 @@
>
> #include "hw/ccid.h"
>
> -//#define DEBUG_CCID
> -
> #define DPRINTF(s, lvl, fmt, ...) \
> do { if (lvl<= s->debug) { printf("usb-ccid: " fmt , ## __VA_ARGS__); } } while (0)
>
> +#define D_WARN 1
> +#define D_INFO 2
> +#define D_MORE_INFO 3
> +#define D_VERBOSE 4
> +
> #define CCID_DEV_NAME "usb-ccid"
>
> /* The two options for variable sized buffers:
> @@ -64,6 +64,8 @@ do { if (lvl<= s->debug) { printf("usb-ccid: " fmt , ## __VA_ARGS__); } } while
> #define InterfaceOutClass ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
> #define InterfaceInClass ((USB_DIR_IN |USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8)
>
> +#define CCID_MAX_PACKET_SIZE 64
> +
> #define CCID_CONTROL_ABORT 0x1
> #define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x2
> #define CCID_CONTROL_GET_DATA_RATES 0x3
> @@ -209,11 +211,12 @@ typedef struct __attribute__ ((__packed__)) CCID_IccPowerOff {
> uint16_t abRFU;
> } CCID_IccPowerOff;
>
> -typedef struct __attribute__ ((__packed__)) CCID_SetParameter {
> +typedef struct __attribute__ ((__packed__)) CCID_SetParameters {
> CCID_Header hdr;
> uint8_t bProtocolNum;
> + uint16_t abRFU;
> uint8_t abProtocolDataStructure[0];
> -} CCID_SetParameter;
> +} CCID_SetParameters;
>
> typedef struct CCID_Notify_Slot_Change {
> uint8_t bMessageType; /* CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange */
> @@ -278,10 +281,6 @@ struct USBCCIDState {
> uint16_t migration_target_port;
> };
>
> -/* Slot specific variables. We emulate a single slot card reader.
> - */
> -
> -
> /* CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
> * "USB Device Framework", section 9.6.1, in the Universal Serial Bus
> * Specification.
> @@ -416,7 +415,8 @@ static const uint8_t qemu_ccid_config_descriptor[] = {
> /* u8 ep_bEndpointAddress; IN Endpoint 1 */
> 0x80 | CCID_INT_IN_EP,
> 0x03, /* u8 ep_bmAttributes; Interrupt */
> - 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
> + /* u16 ep_wMaxPacketSize; */
> + CCID_MAX_PACKET_SIZE& 0xff, (CCID_MAX_PACKET_SIZE>> 8),
> 0xff, /* u8 ep_bInterval; */
>
> /* Bulk-In endpoint */
> @@ -455,32 +455,31 @@ static void ccid_clear_pending_answers(USBCCIDState *s)
>
> static void ccid_print_pending_answers(USBCCIDState *s)
> {
> -#ifdef DEBUG_CCID
> Answer *answer;
> int i, count;
>
> - printf("usb-ccid: pending answers:");
> + DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
> if (!ccid_has_pending_answers(s)) {
> - printf(" empty\n");
> + DPRINTF(s, D_VERBOSE, " empty\n");
> return;
> }
> for (i = s->pending_answers_start, count=s->pending_answers_num ;
> count> 0; count--, i++) {
> answer =&s->pending_answers[i % PENDING_ANSWERS_NUM];
> if (count == 1) {
> - printf("%d:%d\n", answer->slot, answer->seq);
> + DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
> } else {
> - printf("%d:%d,", answer->slot, answer->seq);
> + DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
> }
> }
> -#endif
> }
>
> static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
> {
> Answer* answer;
>
> - assert(s->pending_answers_num++< PENDING_ANSWERS_NUM);
> + assert(s->pending_answers_num< PENDING_ANSWERS_NUM);
> + s->pending_answers_num++;
> answer =&s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
> answer->slot = hdr->bSlot;
> answer->seq = hdr->bSeq;
> @@ -492,7 +491,8 @@ static void ccid_remove_pending_answer(USBCCIDState *s,
> {
> Answer *answer;
>
> - assert(s->pending_answers_num--> 0);
> + assert(s->pending_answers_num> 0);
> + s->pending_answers_num--;
> answer =&s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
> *slot = answer->slot;
> *seq = answer->seq;
> @@ -528,16 +528,16 @@ static void* ccid_reserve_recv_buf(USBCCIDState* s, uint16_t len)
> {
> BulkIn* bulk_in;
>
> - DPRINTF(s, 4, "%s: QUEUE: reserve %d bytes\n", __func__, len);
> + DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
>
> /* look for an existing element */
> if (len> BULK_IN_BUF_SIZE) {
> - printf("usb-ccid.c: %s: len larger then max (%d>%d). discarding message.\n",
> + DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). discarding message.\n",
> __func__, len, BULK_IN_BUF_SIZE);
> return NULL;
> }
> if (s->bulk_in_pending_num>= BULK_IN_PENDING_NUM) {
> - printf("usb-ccid.c: %s: No free bulk_in buffers. discarding message.\n",
> + DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. discarding message.\n",
> __func__);
> return NULL;
> }
> @@ -576,7 +576,7 @@ static int ccid_handle_control(USBDevice *dev, int request, int value,
> DPRINTF(s, 1, "got control %x, value %x\n",request, value);
> switch (request) {
> case DeviceRequest | USB_REQ_GET_STATUS:
> - data[0] = (0<< USB_DEVICE_SELF_POWERED) |
> + data[0] = (1<< USB_DEVICE_SELF_POWERED) |
> (dev->remote_wakeup<< USB_DEVICE_REMOTE_WAKEUP);
> data[1] = 0x00;
> ret = 2;
> @@ -709,7 +709,7 @@ static uint8_t ccid_calc_status(USBCCIDState *s)
> bmCommandStatus
> */
> uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus<< 6);
> - DPRINTF(s, 4, "status = %d\n", ret);
> + DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
> return ret;
> }
>
> @@ -770,11 +770,9 @@ static void ccid_write_data_block(
> p->b.hdr.bSeq = seq;
> p->b.bStatus = ccid_calc_status(s);
> p->b.bError = s->bError;
> -#ifdef DEBUG_CCID
> if (p->b.bError) {
> - DPRINTF(s, 4, "error %d", p->b.bError);
> + DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
> }
> -#endif
> memcpy(p->abData, data, len);
> ccid_reset_error_status(s);
> }
> @@ -805,12 +803,12 @@ static void ccid_write_data_block_atr(USBCCIDState* s, CCID_Header* recv)
>
> static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
> {
> - CCID_SetParameter *ph = (CCID_SetParameter *) recv;
> + CCID_SetParameters *ph = (CCID_SetParameters *) recv;
> uint32_t len = 0;
> - if (ph->bProtocolNum == 0) {
> + if ((ph->bProtocolNum& 3) == 0) {
> len = 5;
> }
> - if (ph->bProtocolNum == 1) {
> + if ((ph->bProtocolNum& 3) == 1) {
> len = 7;
> }
> if (len == 0) {
> @@ -884,7 +882,7 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
> if (s->card) {
> s->cardinfo->apdu_from_guest(s->card, recv->abData, len);
> } else {
> - printf("warning: discarded apdu\n");
> + DPRINTF(s, D_WARN, "warning: discarded apdu\n");
> }
> }
>
> @@ -901,15 +899,15 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
> ccid_header = (CCID_Header*)s->bulk_out_data;
> memcpy(s->bulk_out_data + s->bulk_out_pos, p->data, p->len);
> s->bulk_out_pos += p->len;
> - if (p->len == 64) {
> - DPRINTF(s, 4, "usb-ccid: bulk_in: expecting more packets (%d/%d)\n",
> + if (p->len == CCID_MAX_PACKET_SIZE) {
> + DPRINTF(s, D_VERBOSE, "usb-ccid: bulk_in: expecting more packets (%d/%d)\n",
> p->len, ccid_header->dwLength);
> return 0;
> }
> if (s->bulk_out_pos< 10) {
> DPRINTF(s, 1, "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n", __func__);
> } else {
> - DPRINTF(s, 3, "%s %x\n", __func__, ccid_header->bMessageType);
> + DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
> switch (ccid_header->bMessageType) {
> case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
> ccid_write_slot_status(s, ccid_header);
> @@ -965,7 +963,7 @@ static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, uint8_t *data, int len)
> {
> int ret = 0;
>
> - assert(len>0);
> + assert(len> 0);
> ccid_bulk_in_get(s);
> if (s->current_bulk_in != NULL) {
> ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos, len);
> @@ -978,7 +976,7 @@ static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, uint8_t *data, int len)
> ret = USB_RET_NAK; /* return when device has no data - usb 2.0 spec Table 8-4 */
> }
> if (ret> 0) {
> - DPRINTF(s, 3, "%s: %d/%d req/act to guest (BULK_IN)\n", __func__, len, ret);
> + DPRINTF(s, D_MORE_INFO, "%s: %d/%d req/act to guest (BULK_IN)\n", __func__, len, ret);
> }
> if (ret != USB_RET_NAK&& ret< len) {
> DPRINTF(s, 1, "%s: returning short (EREMOTEIO) %d< %d\n", __func__, ret, len);
> @@ -1015,7 +1013,7 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p)
> ret = 2;
> s->notify_slot_change = false;
> s->bmSlotICCState&= ~SLOT_0_CHANGED_MASK;
> - DPRINTF(s, 2, "handle_data: int_in: notify_slot_change %X, requested len %d\n",
> + DPRINTF(s, D_INFO, "handle_data: int_in: notify_slot_change %X, requested len %d\n",
> s->bmSlotICCState, len);
> }
> break;
> @@ -1146,7 +1144,11 @@ void ccid_card_card_error(CCIDCardState *card, uint64_t error)
> DPRINTF(s, 1, "VSC_Error: %lX\n", s->last_answer_error);
> /* TODO: these error's should be more verbose and propogated to the guest.
> * */
> - ccid_write_data_block_answer(s, NULL, 0);
> + /* we flush all pending answers on CardRemove message in ccid-card-passthru,
> + * so check that first to not trigger abort */
> + if (ccid_has_pending_answers(s)) {
> + ccid_write_data_block_answer(s, NULL, 0);
> + }
> }
>
> void ccid_card_card_inserted(CCIDCardState *card)
> @@ -1184,12 +1186,12 @@ static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
> int ret = 0;
>
> if (card->slot != 0) {
> - fprintf(stderr, "Warning: usb-ccid supports one slot, can't add %d",
> + error_report("Warning: usb-ccid supports one slot, can't add %d",
> card->slot);
> return -1;
> }
> if (s->card != NULL) {
> - fprintf(stderr, "Warning: usb-ccid card already full, not adding\n");
> + error_report("Warning: usb-ccid card already full, not adding\n");
> return -1;
> }
> ret = info->initfn ? info->initfn(card) : ret;
> @@ -1233,7 +1235,6 @@ static int ccid_initfn(USBDevice *dev)
> return 0;
> }
>
> -#ifdef ENABLE_MIGRATION
> static int ccid_post_load(void *opaque, int version_id)
> {
> USBCCIDState *s = opaque;
> @@ -1325,7 +1326,6 @@ static VMStateDescription ccid_vmstate = {
> VMSTATE_END_OF_LIST()
> }
> };
> -#endif // ENABLE_MIGRATION
>
> static struct USBDeviceInfo ccid_info = {
> .product_desc = "QEMU USB CCID",
> @@ -1342,12 +1342,9 @@ static struct USBDeviceInfo ccid_info = {
> DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
> DEFINE_PROP_END_OF_LIST(),
> },
> -#ifdef ENABLE_MIGRATION
> .qdev.vmsd =&ccid_vmstate,
> -#endif
> };
>
> -
> static void ccid_register_devices(void)
> {
> usb_qdev_register(&ccid_info);
>
next prev parent reply other threads:[~2011-02-03 16:55 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-02 20:28 [Qemu-devel] [PATCH 00/20] usb-ccid (v16) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 01/20] qdev: add print_options callback Alon Levy
2011-02-03 16:39 ` Anthony Liguori
2011-02-03 20:54 ` Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 02/20] qdev: add data pointer to Property Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 03/20] qdev-properties: add PROP_TYPE_ENUM Alon Levy
2011-02-03 16:44 ` Anthony Liguori
2011-02-03 20:59 ` Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 04/20] qdev-properties: parse_enum: don't cast a void* Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 05/20] usb-ccid: add CCID bus Alon Levy
2011-02-03 16:46 ` Anthony Liguori
2011-02-03 18:53 ` Alon Levy
2011-02-03 19:29 ` Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 06/20] usb-ccid: review fixes (v15-v16) Alon Levy
2011-02-03 16:48 ` Anthony Liguori [this message]
2011-02-03 18:53 ` Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 07/20] introduce libcacard/vscard_common.h Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 08/20] libcacard/vscard_common.h update (v15->v16) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 09/20] ccid: add passthru card device Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 10/20] ccid-card-passthru: review fixes (v15->v16) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 11/20] libcacard: initial commit after coding style fixes Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 12/20] libcacard: fixes from review (v15->v16) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 13/20] ccid: add ccid-card-emulated device (v2) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 14/20] ccid-card-emulated: use PROP_TYPE_ENUM for backend Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 15/20] ccid-card-emulated: review fixes (v15->v16) Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 16/20] ccid: add docs Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 17/20] ccid: configure: add --enable/disable and nss only disable Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 18/20] ccid: add qdev description strings Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 19/20] smartcard, configure: add --enable-smartcard-nss, report only nss Alon Levy
2011-02-02 20:28 ` [Qemu-devel] [PATCH 20/20] smartcard,configure: " Alon Levy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D4ADC43.90709@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=alevy@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.