[Spice-commits] Branch 'usb-ccid' - hw/usb-ccid.c Makefile.objs
Alon Levy
alon at kemper.freedesktop.org
Tue Jul 6 09:21:42 PDT 2010
Makefile.objs | 2 -
hw/usb-ccid.c | 82 ++++++++++++++++++++++++++++++++++++----------------------
2 files changed, 52 insertions(+), 32 deletions(-)
New commits:
commit 1f9345369aaa1146088028c037094109e5c1f26f
Author: Alon Levy <alevy at redhat.com>
Date: Tue Jul 6 19:21:25 2010 +0300
usb-ccid: missing makefile, support multipacket bulk_out (packet size hardcoded to 64 bytes)
diff --git a/Makefile.objs b/Makefile.objs
index 1250d98..4075b95 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -72,7 +72,7 @@ common-obj-y += eeprom93xx.o
common-obj-y += scsi-disk.o cdrom.o
common-obj-y += scsi-generic.o scsi-bus.o
common-obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-common-obj-y += usb-serial.o usb-net.o usb-bus.o
+common-obj-y += usb-serial.o usb-ccid.o usb-net.o usb-bus.o
common-obj-$(CONFIG_SSI) += ssi.o
common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
common-obj-$(CONFIG_SD) += sd.o
diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c
index a59049d..acf5901 100644
--- a/hw/usb-ccid.c
+++ b/hw/usb-ccid.c
@@ -10,6 +10,13 @@
* This code is licenced under the LGPL.
*/
+/* TODO
+ *
+ * Discard additional answers
+ * Don't change answer while sending a multiple packet BULK_IN (answer_len > single_packet_len == 64)
+ *
+ */
+
#include "qemu-common.h"
#include "qemu-error.h"
#include "usb.h"
@@ -111,7 +118,7 @@ typedef struct __attribute__ ((__packed__)) {
typedef struct __attribute__ ((__packed__)) {
CCID_BULK_IN b;
uint8_t bChainParameter;
- // here starts the data part
+ uint8_t abData[0];
} CCID_DataBlock;
// 6.1.4 PC_to_RDR_XfrBlock
@@ -119,7 +126,7 @@ typedef struct __attribute__ ((__packed__)) {
CCID_Header hdr;
uint8_t bBWI; // Block Waiting Timeout
uint16_t wLevelParameter;
- // here starts the data part
+ uint8_t abData[0];
} CCID_XferBlock;
typedef struct __attribute__ ((__packed__)) {
@@ -508,7 +515,7 @@ static void ccid_write_data_block(USBCCIDState* s, uint8_t slot, uint8_t seq,
p->b.hdr.bSeq = seq;
p->b.bStatus = 0;
p->b.bError = 0;
- memcpy((char*)p+sizeof(*p), data, len);
+ memcpy(p->abData, data, len);
}
static void ccid_write_data_block_answer(USBCCIDState* s, const uint8_t* data, uint32_t len)
@@ -546,20 +553,56 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock* recv)
}
s->answer_slot = recv->hdr.bSlot;
s->answer_seq = recv->hdr.bSeq;
+ printf("usb-ccid: apdu_from_guest %d: len %d\n", recv->hdr.bSeq, recv->hdr.dwLength);
scr_msg_header.type = SCard_APDU;
scr_msg_header.nLength = recv->hdr.dwLength;
qemu_chr_write(s->cs, (uint8_t*)&scr_msg_header, sizeof(SCRMsgHeader));
- qemu_chr_write(s->cs, (uint8_t*)recv + sizeof(*recv), recv->hdr.dwLength);
+ qemu_chr_write(s->cs, recv->abData, recv->hdr.dwLength);
+}
+
+static void usb_ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+{
+ static uint8_t data[70000]; // TODO - set to correct max size of packet.
+ static uint32_t len = 0;
+ static CCID_Header* ccid_header = (CCID_Header*)data;
+
+ memcpy(data + len, p->data, p->len);
+ len += p->len;
+ if (p->len == 64) {
+ printf("usb-ccid: bulk_in: expecting more packets (%d/%d)\n",
+ len, ccid_header->dwLength);
+ return;
+ }
+ if (len < 10) {
+ DPRINTF("handle_data: bad USB_TOKEN_OUT length, should be at least 10 bytes\n");
+ } else {
+ switch (ccid_header->bMessageType) {
+ case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
+ ccid_write_slot_status(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
+ // We need to send an ATR back
+ ccid_write_data_block_atr(s, ccid_header);
+ break;
+ case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
+ ccid_on_apdu_from_guest(s, (CCID_XferBlock*)data);
+ break;
+ default:
+ DPRINTF("handle_data: ERROR: unhandled message type %Xh\n",
+ ccid_header->bMessageType);
+ break;
+ }
+ }
+ len = 0;
}
static int usb_ccid_handle_data(USBDevice *dev, USBPacket *p)
{
USBCCIDState *s = (USBCCIDState *)dev;
int ret = 0;
+ int first_len;
uint8_t *data = p->data;
int len = p->len;
- int first_len;
- CCID_Header* ccid_header;
#ifdef DEBUG_CCID
//int i;
#endif
@@ -579,28 +622,7 @@ static int usb_ccid_handle_data(USBDevice *dev, USBPacket *p)
switch (p->pid) {
case USB_TOKEN_OUT:
- // translate CCID to a APDU request, or handle here.
- // right now all is handled here. (development only)
- if (len < 10) {
- DPRINTF("handle_data: bad USB_TOKEN_OUT length, should be at least 10 bytes\n");
- } else {
- ccid_header = (CCID_Header*)data;
- switch (ccid_header->bMessageType) {
- case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
- ccid_write_slot_status(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
- // We need to send an ATR back
- ccid_write_data_block_atr(s, ccid_header);
- break;
- case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
- ccid_on_apdu_from_guest(s, (CCID_XferBlock*)data);
- break;
- default:
- DPRINTF("handle_data: unhandled message type %d\n",
- ccid_header->bMessageType);
- }
- }
+ usb_ccid_handle_bulk_out(s, p);
break;
case USB_TOKEN_IN:
@@ -675,13 +697,11 @@ static void usb_ccid_read(void *opaque, const uint8_t *buf, int size)
const uint8_t* data = readbuf + sizeof(SCRMsgHeader);
uint32_t available = size + readpos;
- printf("usb-ccid: chardev read %d\n", size);
+ assert(readpos + size <= sizeof(readbuf));
memcpy(readbuf + readpos, buf, size);
readpos += size;
if (available - sizeof(SCRMsgHeader) < scr_msg_header->nLength) {
- printf("usb-ccid: chardev read short, missing %ld\n",
- scr_msg_header->nLength + sizeof(SCRMsgHeader) - available);
return;
}
More information about the Spice-commits
mailing list