aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBandan Das <bsd@redhat.com>2018-07-20 17:40:16 -0400
committerGerd Hoffmann <kraxel@redhat.com>2018-08-21 10:27:59 +0200
commit47bff13cea8dd3e6ae869c3203723d93bd734637 (patch)
tree849466abc8cf1dec6563187e23458410dd735c6b /hw
parent7c48b95df47458d10726d6dca0c4c33eb5eace40 (diff)
downloadqemu-47bff13cea8dd3e6ae869c3203723d93bd734637.zip
qemu-47bff13cea8dd3e6ae869c3203723d93bd734637.tar.gz
qemu-47bff13cea8dd3e6ae869c3203723d93bd734637.tar.bz2
dev-mtp: add support for canceling transaction
The initiator can choose to cancel an ongoing request which is specified by bRequest=0x64. If such a request arrives, free up any pending state Signed-off-by: Bandan Das <bsd@redhat.com> Message-id: 20180720214020.22897-2-bsd@redhat.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb/dev-mtp.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1ded7ac..c40b0de 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -82,6 +82,7 @@ enum mtp_code {
FMT_ASSOCIATION = 0x3001,
/* event codes */
+ EVT_CANCEL_TRANSACTION = 0x4001,
EVT_OBJ_ADDED = 0x4002,
EVT_OBJ_REMOVED = 0x4003,
EVT_OBJ_INFO_CHANGED = 0x4007,
@@ -1551,14 +1552,35 @@ static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
int length, uint8_t *data)
{
int ret;
+ MTPState *s = USB_MTP(dev);
+ uint16_t *event = (uint16_t *)data;
- ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
- if (ret >= 0) {
- return;
+ switch (request) {
+ case ClassInterfaceOutRequest | 0x64:
+ if (*event == EVT_CANCEL_TRANSACTION) {
+ g_free(s->result);
+ s->result = NULL;
+ usb_mtp_data_free(s->data_in);
+ s->data_in = NULL;
+ if (s->write_pending) {
+ g_free(s->dataset.filename);
+ s->write_pending = false;
+ }
+ usb_mtp_data_free(s->data_out);
+ s->data_out = NULL;
+ } else {
+ p->status = USB_RET_STALL;
+ }
+ break;
+ default:
+ ret = usb_desc_handle_control(dev, p, request,
+ value, index, length, data);
+ if (ret >= 0) {
+ return;
+ }
}
trace_usb_mtp_stall(dev->addr, "unknown control request");
- p->status = USB_RET_STALL;
}
static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)