2005-11-05 17:22:28 +03:00
|
|
|
/*
|
|
|
|
* QEMU USB emulation
|
|
|
|
*
|
|
|
|
* Copyright (c) 2005 Fabrice Bellard
|
2007-09-17 01:08:06 +04:00
|
|
|
*
|
2008-08-21 23:29:38 +04:00
|
|
|
* 2008 Generic packet handler rewrite by Max Krasnyansky
|
|
|
|
*
|
2005-11-05 17:22:28 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
2007-11-17 20:14:51 +03:00
|
|
|
#include "qemu-common.h"
|
2012-03-07 17:55:18 +04:00
|
|
|
#include "hw/usb.h"
|
2012-12-17 21:20:00 +04:00
|
|
|
#include "qemu/iov.h"
|
2012-02-24 14:03:27 +04:00
|
|
|
#include "trace.h"
|
2005-11-05 17:22:28 +03:00
|
|
|
|
2011-09-01 15:56:37 +04:00
|
|
|
void usb_attach(USBPort *port)
|
2005-11-05 17:22:28 +03:00
|
|
|
{
|
2011-09-01 15:56:37 +04:00
|
|
|
USBDevice *dev = port->dev;
|
|
|
|
|
|
|
|
assert(dev != NULL);
|
|
|
|
assert(dev->attached);
|
2011-09-15 14:10:21 +04:00
|
|
|
assert(dev->state == USB_STATE_NOTATTACHED);
|
2011-09-01 15:56:37 +04:00
|
|
|
port->ops->attach(port);
|
2012-01-06 18:13:34 +04:00
|
|
|
dev->state = USB_STATE_ATTACHED;
|
|
|
|
usb_device_handle_attach(dev);
|
2011-09-01 15:56:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void usb_detach(USBPort *port)
|
|
|
|
{
|
|
|
|
USBDevice *dev = port->dev;
|
|
|
|
|
|
|
|
assert(dev != NULL);
|
2011-09-15 14:10:21 +04:00
|
|
|
assert(dev->state != USB_STATE_NOTATTACHED);
|
2011-09-01 15:56:37 +04:00
|
|
|
port->ops->detach(port);
|
2012-01-06 18:13:34 +04:00
|
|
|
dev->state = USB_STATE_NOTATTACHED;
|
2005-11-05 17:22:28 +03:00
|
|
|
}
|
|
|
|
|
2012-01-06 18:23:10 +04:00
|
|
|
void usb_port_reset(USBPort *port)
|
2011-09-15 14:10:21 +04:00
|
|
|
{
|
|
|
|
USBDevice *dev = port->dev;
|
|
|
|
|
|
|
|
assert(dev != NULL);
|
|
|
|
usb_detach(port);
|
|
|
|
usb_attach(port);
|
2012-01-06 18:23:10 +04:00
|
|
|
usb_device_reset(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_device_reset(USBDevice *dev)
|
|
|
|
{
|
|
|
|
if (dev == NULL || !dev->attached) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dev->remote_wakeup = 0;
|
|
|
|
dev->addr = 0;
|
|
|
|
dev->state = USB_STATE_DEFAULT;
|
|
|
|
usb_device_handle_reset(dev);
|
2011-09-15 14:10:21 +04:00
|
|
|
}
|
|
|
|
|
2013-01-29 15:44:35 +04:00
|
|
|
void usb_wakeup(USBEndpoint *ep, unsigned int stream)
|
2010-12-01 13:32:45 +03:00
|
|
|
{
|
2012-01-17 16:25:46 +04:00
|
|
|
USBDevice *dev = ep->dev;
|
2012-01-20 16:29:53 +04:00
|
|
|
USBBus *bus = usb_bus_from_device(dev);
|
2012-01-17 16:25:46 +04:00
|
|
|
|
2010-12-01 13:32:45 +03:00
|
|
|
if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
|
2011-06-21 13:52:28 +04:00
|
|
|
dev->port->ops->wakeup(dev->port);
|
2010-12-01 13:32:45 +03:00
|
|
|
}
|
2012-01-20 16:29:53 +04:00
|
|
|
if (bus->ops->wakeup_endpoint) {
|
2013-01-29 15:44:35 +04:00
|
|
|
bus->ops->wakeup_endpoint(bus, ep, stream);
|
2012-01-20 16:29:53 +04:00
|
|
|
}
|
2010-12-01 13:32:45 +03:00
|
|
|
}
|
|
|
|
|
2005-11-05 17:22:28 +03:00
|
|
|
/**********************/
|
2008-08-21 23:29:38 +04:00
|
|
|
|
2005-11-05 17:22:28 +03:00
|
|
|
/* generic USB device helpers (you are not forced to use them when
|
|
|
|
writing your USB device driver, but they help handling the
|
2007-09-17 01:08:06 +04:00
|
|
|
protocol)
|
2005-11-05 17:22:28 +03:00
|
|
|
*/
|
|
|
|
|
2011-02-02 19:36:29 +03:00
|
|
|
#define SETUP_STATE_IDLE 0
|
|
|
|
#define SETUP_STATE_SETUP 1
|
|
|
|
#define SETUP_STATE_DATA 2
|
|
|
|
#define SETUP_STATE_ACK 3
|
2012-03-02 16:22:29 +04:00
|
|
|
#define SETUP_STATE_PARAM 4
|
2005-11-05 17:22:28 +03:00
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void do_token_setup(USBDevice *s, USBPacket *p)
|
2008-08-21 23:29:38 +04:00
|
|
|
{
|
|
|
|
int request, value, index;
|
|
|
|
|
2011-07-12 17:22:25 +04:00
|
|
|
if (p->iov.size != 8) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
|
|
|
return;
|
2011-07-12 17:22:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
usb_packet_copy(p, s->setup_buf, p->iov.size);
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 0;
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
|
|
|
|
s->setup_index = 0;
|
|
|
|
|
|
|
|
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
|
|
|
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
|
|
|
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
|
2011-02-02 18:33:13 +03:00
|
|
|
|
2008-08-21 23:29:38 +04:00
|
|
|
if (s->setup_buf[0] & USB_DIR_IN) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_device_handle_control(s, p, request, value, index,
|
|
|
|
s->setup_len, s->data_buf);
|
|
|
|
if (p->status == USB_RET_ASYNC) {
|
|
|
|
s->setup_state = SETUP_STATE_SETUP;
|
|
|
|
}
|
|
|
|
if (p->status != USB_RET_SUCCESS) {
|
|
|
|
return;
|
2011-02-02 19:36:29 +03:00
|
|
|
}
|
2008-08-21 23:29:38 +04:00
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->actual_length < s->setup_len) {
|
|
|
|
s->setup_len = p->actual_length;
|
|
|
|
}
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_state = SETUP_STATE_DATA;
|
|
|
|
} else {
|
2011-02-02 19:46:00 +03:00
|
|
|
if (s->setup_len > sizeof(s->data_buf)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
|
|
|
|
s->setup_len, sizeof(s->data_buf));
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
|
|
|
return;
|
2011-02-02 19:46:00 +03:00
|
|
|
}
|
2008-08-21 23:29:38 +04:00
|
|
|
if (s->setup_len == 0)
|
|
|
|
s->setup_state = SETUP_STATE_ACK;
|
|
|
|
else
|
|
|
|
s->setup_state = SETUP_STATE_DATA;
|
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 8;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void do_token_in(USBDevice *s, USBPacket *p)
|
2005-11-05 17:22:28 +03:00
|
|
|
{
|
2008-08-21 23:29:38 +04:00
|
|
|
int request, value, index;
|
|
|
|
|
2012-01-12 16:23:01 +04:00
|
|
|
assert(p->ep->nr == 0);
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
|
|
|
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
|
|
|
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
|
|
|
|
|
|
|
|
switch(s->setup_state) {
|
|
|
|
case SETUP_STATE_ACK:
|
|
|
|
if (!(s->setup_buf[0] & USB_DIR_IN)) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_device_handle_control(s, p, request, value, index,
|
|
|
|
s->setup_len, s->data_buf);
|
|
|
|
if (p->status == USB_RET_ASYNC) {
|
|
|
|
return;
|
2011-02-02 18:33:13 +03:00
|
|
|
}
|
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 0;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
break;
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
case SETUP_STATE_DATA:
|
|
|
|
if (s->setup_buf[0] & USB_DIR_IN) {
|
|
|
|
int len = s->setup_len - s->setup_index;
|
2011-07-12 17:22:25 +04:00
|
|
|
if (len > p->iov.size) {
|
|
|
|
len = p->iov.size;
|
|
|
|
}
|
|
|
|
usb_packet_copy(p, s->data_buf + s->setup_index, len);
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_index += len;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (s->setup_index >= s->setup_len) {
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_state = SETUP_STATE_ACK;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
}
|
|
|
|
return;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
|
|
|
break;
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
default:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void do_token_out(USBDevice *s, USBPacket *p)
|
2008-08-21 23:29:38 +04:00
|
|
|
{
|
2012-01-12 16:23:01 +04:00
|
|
|
assert(p->ep->nr == 0);
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
switch(s->setup_state) {
|
|
|
|
case SETUP_STATE_ACK:
|
|
|
|
if (s->setup_buf[0] & USB_DIR_IN) {
|
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
|
|
|
/* transfer OK */
|
|
|
|
} else {
|
|
|
|
/* ignore additional output */
|
|
|
|
}
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
break;
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
case SETUP_STATE_DATA:
|
|
|
|
if (!(s->setup_buf[0] & USB_DIR_IN)) {
|
|
|
|
int len = s->setup_len - s->setup_index;
|
2011-07-12 17:22:25 +04:00
|
|
|
if (len > p->iov.size) {
|
|
|
|
len = p->iov.size;
|
|
|
|
}
|
|
|
|
usb_packet_copy(p, s->data_buf + s->setup_index, len);
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_index += len;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (s->setup_index >= s->setup_len) {
|
2008-08-21 23:29:38 +04:00
|
|
|
s->setup_state = SETUP_STATE_ACK;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
}
|
|
|
|
return;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
|
|
|
break;
|
2008-08-21 23:29:38 +04:00
|
|
|
|
|
|
|
default:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
|
|
|
}
|
2005-11-05 17:22:28 +03:00
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void do_parameter(USBDevice *s, USBPacket *p)
|
2012-03-02 16:22:29 +04:00
|
|
|
{
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
int i, request, value, index;
|
2012-03-02 16:22:29 +04:00
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
s->setup_buf[i] = p->parameter >> (i*8);
|
|
|
|
}
|
|
|
|
|
|
|
|
s->setup_state = SETUP_STATE_PARAM;
|
|
|
|
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
|
|
|
|
s->setup_index = 0;
|
|
|
|
|
|
|
|
request = (s->setup_buf[0] << 8) | s->setup_buf[1];
|
|
|
|
value = (s->setup_buf[3] << 8) | s->setup_buf[2];
|
|
|
|
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
|
|
|
|
|
|
|
|
if (s->setup_len > sizeof(s->data_buf)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
|
|
|
|
s->setup_len, sizeof(s->data_buf));
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
|
|
|
return;
|
2012-03-02 16:22:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (p->pid == USB_TOKEN_OUT) {
|
|
|
|
usb_packet_copy(p, s->data_buf, s->setup_len);
|
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_device_handle_control(s, p, request, value, index,
|
|
|
|
s->setup_len, s->data_buf);
|
|
|
|
if (p->status == USB_RET_ASYNC) {
|
|
|
|
return;
|
2012-03-02 16:22:29 +04:00
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->actual_length < s->setup_len) {
|
|
|
|
s->setup_len = p->actual_length;
|
2012-03-02 16:22:29 +04:00
|
|
|
}
|
|
|
|
if (p->pid == USB_TOKEN_IN) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 0;
|
2012-03-02 16:22:29 +04:00
|
|
|
usb_packet_copy(p, s->data_buf, s->setup_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-02 19:36:29 +03:00
|
|
|
/* ctrl complete function for devices which use usb_generic_handle_packet and
|
|
|
|
may return USB_RET_ASYNC from their handle_control callback. Device code
|
|
|
|
which does this *must* call this function instead of the normal
|
|
|
|
usb_packet_complete to complete their async control packets. */
|
|
|
|
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
|
|
|
|
{
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->status < 0) {
|
2011-02-02 19:36:29 +03:00
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (s->setup_state) {
|
|
|
|
case SETUP_STATE_SETUP:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->actual_length < s->setup_len) {
|
|
|
|
s->setup_len = p->actual_length;
|
2011-02-02 19:36:29 +03:00
|
|
|
}
|
|
|
|
s->setup_state = SETUP_STATE_DATA;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 8;
|
2011-02-02 19:36:29 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SETUP_STATE_ACK:
|
|
|
|
s->setup_state = SETUP_STATE_IDLE;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 0;
|
2011-02-02 19:36:29 +03:00
|
|
|
break;
|
|
|
|
|
2012-03-02 16:22:29 +04:00
|
|
|
case SETUP_STATE_PARAM:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->actual_length < s->setup_len) {
|
|
|
|
s->setup_len = p->actual_length;
|
2012-03-02 16:22:29 +04:00
|
|
|
}
|
|
|
|
if (p->pid == USB_TOKEN_IN) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length = 0;
|
2012-03-02 16:22:29 +04:00
|
|
|
usb_packet_copy(p, s->data_buf, s->setup_len);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-02-02 19:36:29 +03:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
usb_packet_complete(s, p);
|
|
|
|
}
|
|
|
|
|
2005-11-05 17:22:28 +03:00
|
|
|
/* XXX: fix overflow */
|
|
|
|
int set_usb_string(uint8_t *buf, const char *str)
|
|
|
|
{
|
|
|
|
int len, i;
|
|
|
|
uint8_t *q;
|
|
|
|
|
|
|
|
q = buf;
|
|
|
|
len = strlen(str);
|
2006-03-11 23:37:58 +03:00
|
|
|
*q++ = 2 * len + 2;
|
2005-11-05 17:22:28 +03:00
|
|
|
*q++ = 3;
|
|
|
|
for(i = 0; i < len; i++) {
|
|
|
|
*q++ = str[i];
|
|
|
|
*q++ = 0;
|
|
|
|
}
|
|
|
|
return q - buf;
|
|
|
|
}
|
2006-08-12 05:04:27 +04:00
|
|
|
|
2012-01-10 19:59:28 +04:00
|
|
|
USBDevice *usb_find_device(USBPort *port, uint8_t addr)
|
|
|
|
{
|
|
|
|
USBDevice *dev = port->dev;
|
|
|
|
|
|
|
|
if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (dev->addr == addr) {
|
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
return usb_device_find_device(dev, addr);
|
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void usb_process_one(USBPacket *p)
|
2012-01-12 17:26:13 +04:00
|
|
|
{
|
|
|
|
USBDevice *dev = p->ep->dev;
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
/*
|
|
|
|
* Handlers expect status to be initialized to USB_RET_SUCCESS, but it
|
|
|
|
* can be USB_RET_NAK here from a previous usb_process_one() call,
|
|
|
|
* or USB_RET_ASYNC from going through usb_queue_one().
|
|
|
|
*/
|
|
|
|
p->status = USB_RET_SUCCESS;
|
|
|
|
|
2012-01-12 17:26:13 +04:00
|
|
|
if (p->ep->nr == 0) {
|
|
|
|
/* control pipe */
|
2012-03-02 16:22:29 +04:00
|
|
|
if (p->parameter) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
do_parameter(dev, p);
|
|
|
|
return;
|
2012-03-02 16:22:29 +04:00
|
|
|
}
|
2012-01-12 17:26:13 +04:00
|
|
|
switch (p->pid) {
|
|
|
|
case USB_TOKEN_SETUP:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
do_token_setup(dev, p);
|
|
|
|
break;
|
2012-01-12 17:26:13 +04:00
|
|
|
case USB_TOKEN_IN:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
do_token_in(dev, p);
|
|
|
|
break;
|
2012-01-12 17:26:13 +04:00
|
|
|
case USB_TOKEN_OUT:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
do_token_out(dev, p);
|
|
|
|
break;
|
2012-01-12 17:26:13 +04:00
|
|
|
default:
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_STALL;
|
2012-01-12 17:26:13 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* data pipe */
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_device_handle_data(dev, p);
|
2012-01-12 17:26:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
static void usb_queue_one(USBPacket *p)
|
|
|
|
{
|
|
|
|
usb_packet_set_state(p, USB_PACKET_QUEUED);
|
|
|
|
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
|
|
|
|
p->status = USB_RET_ASYNC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Hand over a packet to a device for processing. p->status ==
|
2011-05-12 15:20:39 +04:00
|
|
|
USB_RET_ASYNC indicates the processing isn't finished yet, the
|
|
|
|
driver will call usb_packet_complete() when done processing it. */
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
void usb_handle_packet(USBDevice *dev, USBPacket *p)
|
2011-05-12 15:20:39 +04:00
|
|
|
{
|
2012-01-10 20:33:02 +04:00
|
|
|
if (dev == NULL) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_NODEV;
|
|
|
|
return;
|
2012-01-10 20:33:02 +04:00
|
|
|
}
|
2012-01-12 16:23:01 +04:00
|
|
|
assert(dev == p->ep->dev);
|
2012-01-11 15:14:02 +04:00
|
|
|
assert(dev->state == USB_STATE_DEFAULT);
|
2012-03-08 15:27:47 +04:00
|
|
|
usb_packet_check_state(p, USB_PACKET_SETUP);
|
2012-01-12 17:26:13 +04:00
|
|
|
assert(p->ep != NULL);
|
2012-01-11 15:14:02 +04:00
|
|
|
|
usb: Halt ep queue en cancel pending packets on a packet error
For controllers which queue up more then 1 packet at a time, we must halt the
ep queue, and inside the controller code cancel all pending packets on an
error.
There are multiple reasons for this:
1) Guests expect the controllers to halt ep queues on error, so that they
get the opportunity to cancel transfers which the scheduled after the failing
one, before processing continues
2) Not cancelling queued up packets after a failed transfer also messes up
the controller state machine, in the case of EHCI causing the following
assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075
3) For bulk endpoints with pipelining enabled (redirection to a real USB
device), we must cancel all the transfers after this a failed one so that:
a) If they've completed already, they are not processed further causing more
stalls to be reported, originating from the same failed transfer
b) If still in flight, they are cancelled before the guest does
a clear stall, otherwise the guest and device can loose sync!
Note this patch only touches the ehci and uhci controller changes, since AFAIK
no other controllers actually queue up multiple transfer. If I'm wrong on this
other controllers need to be updated too!
Also note that this patch was heavily tested with the ehci code, where I had
a reproducer for a device causing a transfer to fail. The uhci code is not
tested with actually failing transfers and could do with a thorough review!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-08-17 17:24:49 +04:00
|
|
|
/* Submitting a new packet clears halt */
|
|
|
|
if (p->ep->halted) {
|
|
|
|
assert(QTAILQ_EMPTY(&p->ep->queue));
|
|
|
|
p->ep->halted = false;
|
|
|
|
}
|
|
|
|
|
2013-08-27 17:25:24 +04:00
|
|
|
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline || p->stream) {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_process_one(p);
|
|
|
|
if (p->status == USB_RET_ASYNC) {
|
2012-11-17 15:47:15 +04:00
|
|
|
/* hcd drivers cannot handle async for isoc */
|
2012-10-24 20:31:04 +04:00
|
|
|
assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
|
2012-11-17 15:47:15 +04:00
|
|
|
/* using async for interrupt packets breaks migration */
|
|
|
|
assert(p->ep->type != USB_ENDPOINT_XFER_INT ||
|
2013-05-13 03:19:37 +04:00
|
|
|
(dev->flags & (1 << USB_DEV_FLAG_IS_HOST)));
|
2012-01-12 17:26:13 +04:00
|
|
|
usb_packet_set_state(p, USB_PACKET_ASYNC);
|
|
|
|
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
} else if (p->status == USB_RET_ADD_TO_QUEUE) {
|
|
|
|
usb_queue_one(p);
|
2012-01-12 17:26:13 +04:00
|
|
|
} else {
|
usb: Halt ep queue en cancel pending packets on a packet error
For controllers which queue up more then 1 packet at a time, we must halt the
ep queue, and inside the controller code cancel all pending packets on an
error.
There are multiple reasons for this:
1) Guests expect the controllers to halt ep queues on error, so that they
get the opportunity to cancel transfers which the scheduled after the failing
one, before processing continues
2) Not cancelling queued up packets after a failed transfer also messes up
the controller state machine, in the case of EHCI causing the following
assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075
3) For bulk endpoints with pipelining enabled (redirection to a real USB
device), we must cancel all the transfers after this a failed one so that:
a) If they've completed already, they are not processed further causing more
stalls to be reported, originating from the same failed transfer
b) If still in flight, they are cancelled before the guest does
a clear stall, otherwise the guest and device can loose sync!
Note this patch only touches the ehci and uhci controller changes, since AFAIK
no other controllers actually queue up multiple transfer. If I'm wrong on this
other controllers need to be updated too!
Also note that this patch was heavily tested with the ehci code, where I had
a reproducer for a device causing a transfer to fail. The uhci code is not
tested with actually failing transfers and could do with a thorough review!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-08-17 17:24:49 +04:00
|
|
|
/*
|
|
|
|
* When pipelining is enabled usb-devices must always return async,
|
|
|
|
* otherwise packets can complete out of order!
|
|
|
|
*/
|
2013-08-27 17:25:24 +04:00
|
|
|
assert(p->stream || !p->ep->pipeline ||
|
|
|
|
QTAILQ_EMPTY(&p->ep->queue));
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->status != USB_RET_NAK) {
|
2012-09-03 14:33:44 +04:00
|
|
|
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
|
|
|
}
|
2012-01-11 15:14:02 +04:00
|
|
|
}
|
|
|
|
} else {
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_queue_one(p);
|
2011-05-12 15:48:13 +04:00
|
|
|
}
|
2008-08-21 23:29:38 +04:00
|
|
|
}
|
2011-05-12 15:48:13 +04:00
|
|
|
|
2012-10-24 20:14:06 +04:00
|
|
|
void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
|
usb: Halt ep queue en cancel pending packets on a packet error
For controllers which queue up more then 1 packet at a time, we must halt the
ep queue, and inside the controller code cancel all pending packets on an
error.
There are multiple reasons for this:
1) Guests expect the controllers to halt ep queues on error, so that they
get the opportunity to cancel transfers which the scheduled after the failing
one, before processing continues
2) Not cancelling queued up packets after a failed transfer also messes up
the controller state machine, in the case of EHCI causing the following
assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075
3) For bulk endpoints with pipelining enabled (redirection to a real USB
device), we must cancel all the transfers after this a failed one so that:
a) If they've completed already, they are not processed further causing more
stalls to be reported, originating from the same failed transfer
b) If still in flight, they are cancelled before the guest does
a clear stall, otherwise the guest and device can loose sync!
Note this patch only touches the ehci and uhci controller changes, since AFAIK
no other controllers actually queue up multiple transfer. If I'm wrong on this
other controllers need to be updated too!
Also note that this patch was heavily tested with the ehci code, where I had
a reproducer for a device causing a transfer to fail. The uhci code is not
tested with actually failing transfers and could do with a thorough review!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-08-17 17:24:49 +04:00
|
|
|
{
|
|
|
|
USBEndpoint *ep = p->ep;
|
|
|
|
|
2013-08-27 17:25:24 +04:00
|
|
|
assert(p->stream || QTAILQ_FIRST(&ep->queue) == p);
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK);
|
usb: Halt ep queue en cancel pending packets on a packet error
For controllers which queue up more then 1 packet at a time, we must halt the
ep queue, and inside the controller code cancel all pending packets on an
error.
There are multiple reasons for this:
1) Guests expect the controllers to halt ep queues on error, so that they
get the opportunity to cancel transfers which the scheduled after the failing
one, before processing continues
2) Not cancelling queued up packets after a failed transfer also messes up
the controller state machine, in the case of EHCI causing the following
assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075
3) For bulk endpoints with pipelining enabled (redirection to a real USB
device), we must cancel all the transfers after this a failed one so that:
a) If they've completed already, they are not processed further causing more
stalls to be reported, originating from the same failed transfer
b) If still in flight, they are cancelled before the guest does
a clear stall, otherwise the guest and device can loose sync!
Note this patch only touches the ehci and uhci controller changes, since AFAIK
no other controllers actually queue up multiple transfer. If I'm wrong on this
other controllers need to be updated too!
Also note that this patch was heavily tested with the ehci code, where I had
a reproducer for a device causing a transfer to fail. The uhci code is not
tested with actually failing transfers and could do with a thorough review!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-08-17 17:24:49 +04:00
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
if (p->status != USB_RET_SUCCESS ||
|
|
|
|
(p->short_not_ok && (p->actual_length < p->iov.size))) {
|
usb: Halt ep queue en cancel pending packets on a packet error
For controllers which queue up more then 1 packet at a time, we must halt the
ep queue, and inside the controller code cancel all pending packets on an
error.
There are multiple reasons for this:
1) Guests expect the controllers to halt ep queues on error, so that they
get the opportunity to cancel transfers which the scheduled after the failing
one, before processing continues
2) Not cancelling queued up packets after a failed transfer also messes up
the controller state machine, in the case of EHCI causing the following
assert to trigger: "assert(p->qtdaddr == q->qtdaddr)" at hcd-ehci.c:2075
3) For bulk endpoints with pipelining enabled (redirection to a real USB
device), we must cancel all the transfers after this a failed one so that:
a) If they've completed already, they are not processed further causing more
stalls to be reported, originating from the same failed transfer
b) If still in flight, they are cancelled before the guest does
a clear stall, otherwise the guest and device can loose sync!
Note this patch only touches the ehci and uhci controller changes, since AFAIK
no other controllers actually queue up multiple transfer. If I'm wrong on this
other controllers need to be updated too!
Also note that this patch was heavily tested with the ehci code, where I had
a reproducer for a device causing a transfer to fail. The uhci code is not
tested with actually failing transfers and could do with a thorough review!
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-08-17 17:24:49 +04:00
|
|
|
ep->halted = true;
|
|
|
|
}
|
|
|
|
usb_packet_set_state(p, USB_PACKET_COMPLETE);
|
|
|
|
QTAILQ_REMOVE(&ep->queue, p, queue);
|
|
|
|
dev->port->ops->complete(dev->port, p);
|
|
|
|
}
|
|
|
|
|
2011-05-12 15:48:13 +04:00
|
|
|
/* Notify the controller that an async packet is complete. This should only
|
|
|
|
be called for packets previously deferred by returning USB_RET_ASYNC from
|
|
|
|
handle_packet. */
|
|
|
|
void usb_packet_complete(USBDevice *dev, USBPacket *p)
|
|
|
|
{
|
2012-01-12 17:26:13 +04:00
|
|
|
USBEndpoint *ep = p->ep;
|
|
|
|
|
2012-03-08 15:27:47 +04:00
|
|
|
usb_packet_check_state(p, USB_PACKET_ASYNC);
|
2012-10-24 20:14:06 +04:00
|
|
|
usb_packet_complete_one(dev, p);
|
2012-01-12 17:26:13 +04:00
|
|
|
|
2012-10-24 20:14:08 +04:00
|
|
|
while (!QTAILQ_EMPTY(&ep->queue)) {
|
2012-01-12 17:26:13 +04:00
|
|
|
p = QTAILQ_FIRST(&ep->queue);
|
2012-10-24 20:14:08 +04:00
|
|
|
if (ep->halted) {
|
|
|
|
/* Empty the queue on a halt */
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_REMOVE_FROM_QUEUE;
|
2012-10-24 20:14:08 +04:00
|
|
|
dev->port->ops->complete(dev->port, p);
|
|
|
|
continue;
|
|
|
|
}
|
2012-02-28 18:36:06 +04:00
|
|
|
if (p->state == USB_PACKET_ASYNC) {
|
|
|
|
break;
|
|
|
|
}
|
2012-03-08 15:27:47 +04:00
|
|
|
usb_packet_check_state(p, USB_PACKET_QUEUED);
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
usb_process_one(p);
|
|
|
|
if (p->status == USB_RET_ASYNC) {
|
2012-01-12 17:26:13 +04:00
|
|
|
usb_packet_set_state(p, USB_PACKET_ASYNC);
|
|
|
|
break;
|
|
|
|
}
|
2012-10-24 20:14:06 +04:00
|
|
|
usb_packet_complete_one(ep->dev, p);
|
2012-01-12 17:26:13 +04:00
|
|
|
}
|
2011-05-12 15:48:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Cancel an active packet. The packed must have been deferred by
|
|
|
|
returning USB_RET_ASYNC from handle_packet, and not yet
|
|
|
|
completed. */
|
|
|
|
void usb_cancel_packet(USBPacket * p)
|
|
|
|
{
|
2012-01-12 17:26:13 +04:00
|
|
|
bool callback = (p->state == USB_PACKET_ASYNC);
|
|
|
|
assert(usb_packet_is_inflight(p));
|
|
|
|
usb_packet_set_state(p, USB_PACKET_CANCELED);
|
|
|
|
QTAILQ_REMOVE(&p->ep->queue, p, queue);
|
|
|
|
if (callback) {
|
|
|
|
usb_device_cancel_packet(p->ep->dev, p);
|
|
|
|
}
|
2011-05-12 15:48:13 +04:00
|
|
|
}
|
2011-07-12 17:22:25 +04:00
|
|
|
|
|
|
|
|
|
|
|
void usb_packet_init(USBPacket *p)
|
|
|
|
{
|
|
|
|
qemu_iovec_init(&p->iov, 1);
|
|
|
|
}
|
|
|
|
|
2012-03-08 15:27:47 +04:00
|
|
|
static const char *usb_packet_state_name(USBPacketState state)
|
2012-01-12 17:26:13 +04:00
|
|
|
{
|
|
|
|
static const char *name[] = {
|
|
|
|
[USB_PACKET_UNDEFINED] = "undef",
|
|
|
|
[USB_PACKET_SETUP] = "setup",
|
|
|
|
[USB_PACKET_QUEUED] = "queued",
|
|
|
|
[USB_PACKET_ASYNC] = "async",
|
|
|
|
[USB_PACKET_COMPLETE] = "complete",
|
|
|
|
[USB_PACKET_CANCELED] = "canceled",
|
|
|
|
};
|
2012-03-08 15:27:47 +04:00
|
|
|
if (state < ARRAY_SIZE(name)) {
|
|
|
|
return name[state];
|
|
|
|
}
|
|
|
|
return "INVALID";
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_packet_check_state(USBPacket *p, USBPacketState expected)
|
|
|
|
{
|
|
|
|
USBDevice *dev;
|
|
|
|
USBBus *bus;
|
|
|
|
|
|
|
|
if (p->state == expected) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dev = p->ep->dev;
|
|
|
|
bus = usb_bus_from_device(dev);
|
|
|
|
trace_usb_packet_state_fault(bus->busnr, dev->port->path, p->ep->nr, p,
|
|
|
|
usb_packet_state_name(p->state),
|
|
|
|
usb_packet_state_name(expected));
|
|
|
|
assert(!"usb packet state check failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_packet_set_state(USBPacket *p, USBPacketState state)
|
|
|
|
{
|
2012-03-23 16:34:50 +04:00
|
|
|
if (p->ep) {
|
|
|
|
USBDevice *dev = p->ep->dev;
|
|
|
|
USBBus *bus = usb_bus_from_device(dev);
|
|
|
|
trace_usb_packet_state_change(bus->busnr, dev->port->path, p->ep->nr, p,
|
|
|
|
usb_packet_state_name(p->state),
|
|
|
|
usb_packet_state_name(state));
|
|
|
|
} else {
|
|
|
|
trace_usb_packet_state_change(-1, "", -1, p,
|
|
|
|
usb_packet_state_name(p->state),
|
|
|
|
usb_packet_state_name(state));
|
|
|
|
}
|
2012-01-12 17:26:13 +04:00
|
|
|
p->state = state;
|
|
|
|
}
|
|
|
|
|
2013-01-29 15:44:35 +04:00
|
|
|
void usb_packet_setup(USBPacket *p, int pid,
|
|
|
|
USBEndpoint *ep, unsigned int stream,
|
|
|
|
uint64_t id, bool short_not_ok, bool int_req)
|
2011-07-12 17:22:25 +04:00
|
|
|
{
|
2012-01-12 15:51:48 +04:00
|
|
|
assert(!usb_packet_is_inflight(p));
|
2012-04-19 15:07:54 +04:00
|
|
|
assert(p->iov.iov != NULL);
|
2012-08-23 15:30:13 +04:00
|
|
|
p->id = id;
|
2011-07-12 17:22:25 +04:00
|
|
|
p->pid = pid;
|
2012-01-12 16:23:01 +04:00
|
|
|
p->ep = ep;
|
2013-01-29 15:44:35 +04:00
|
|
|
p->stream = stream;
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->status = USB_RET_SUCCESS;
|
|
|
|
p->actual_length = 0;
|
2012-03-02 16:22:29 +04:00
|
|
|
p->parameter = 0;
|
2012-10-24 20:14:09 +04:00
|
|
|
p->short_not_ok = short_not_ok;
|
2012-10-24 20:14:10 +04:00
|
|
|
p->int_req = int_req;
|
usb: Add packet combining functions
Currently we only do pipelining for output endpoints, since to properly
support short-not-ok semantics we can only have one outstanding input
packet. Since the ehci and uhci controllers have a limited per td packet
size guests will split large input transfers to into multiple packets,
and since we don't pipeline these, this comes with a serious performance
penalty.
This patch adds helper functions to (re-)combine packets which belong to 1
transfer at the guest device-driver level into 1 large transger. This can be
used by (redirection) usb-devices to enable pipelining for input endpoints.
This patch will combine packets together until a transfer terminating packet
is encountered. A terminating packet is a packet which meets one or more of
the following conditions:
1) The packet size is *not* a multiple of the endpoint max packet size
2) The packet does *not* have its short-not-ok flag set
3) The packet has its interrupt-on-complete flag set
The short-not-ok flag of the combined packet is that of the terminating packet.
Multiple combined packets may be submitted to the device, if the combined
packets do not have their short-not-ok flag set, enabling true pipelining.
If a combined packet does have its short-not-ok flag set the queue will
wait with submitting further packets to the device until that packet has
completed.
Once enabled in the usb-redir and ehci code, this improves the speed (MB/s)
of a Linux guest reading from a USB mass storage device by a factor of
1.2 - 1.5.
And the main reason why I started working on this, when reading from a pl2303
USB<->serial converter, it combines the previous 4 packets submitted per
device-driver level read into 1 big read, reducing the number of packets / sec
by a factor 4, and it allows to have multiple reads outstanding. This allows
for much better latency tolerance without the pl2303's internal buffer
overflowing (which was happening at 115200 bps, without serial flow control).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-10-31 16:47:09 +04:00
|
|
|
p->combined = NULL;
|
2011-07-12 17:22:25 +04:00
|
|
|
qemu_iovec_reset(&p->iov);
|
2012-01-12 17:26:13 +04:00
|
|
|
usb_packet_set_state(p, USB_PACKET_SETUP);
|
2011-07-12 17:22:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len)
|
|
|
|
{
|
|
|
|
qemu_iovec_add(&p->iov, ptr, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
|
|
|
|
{
|
2013-01-24 18:38:23 +04:00
|
|
|
QEMUIOVector *iov = p->combined ? &p->combined->iov : &p->iov;
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
assert(p->actual_length >= 0);
|
2013-01-24 18:38:23 +04:00
|
|
|
assert(p->actual_length + bytes <= iov->size);
|
2011-07-12 17:22:25 +04:00
|
|
|
switch (p->pid) {
|
|
|
|
case USB_TOKEN_SETUP:
|
|
|
|
case USB_TOKEN_OUT:
|
2013-01-24 18:38:23 +04:00
|
|
|
iov_to_buf(iov->iov, iov->niov, p->actual_length, ptr, bytes);
|
2011-07-12 17:22:25 +04:00
|
|
|
break;
|
|
|
|
case USB_TOKEN_IN:
|
2013-01-24 18:38:23 +04:00
|
|
|
iov_from_buf(iov->iov, iov->niov, p->actual_length, ptr, bytes);
|
2011-07-12 17:22:25 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
|
|
|
|
abort();
|
|
|
|
}
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length += bytes;
|
2011-07-12 17:22:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void usb_packet_skip(USBPacket *p, size_t bytes)
|
|
|
|
{
|
2013-01-24 18:38:23 +04:00
|
|
|
QEMUIOVector *iov = p->combined ? &p->combined->iov : &p->iov;
|
|
|
|
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
assert(p->actual_length >= 0);
|
2013-01-24 18:38:23 +04:00
|
|
|
assert(p->actual_length + bytes <= iov->size);
|
2011-07-12 17:22:25 +04:00
|
|
|
if (p->pid == USB_TOKEN_IN) {
|
2013-01-24 18:38:23 +04:00
|
|
|
iov_memset(iov->iov, iov->niov, p->actual_length, 0, bytes);
|
2011-07-12 17:22:25 +04:00
|
|
|
}
|
usb: split packet result into actual_length + status
Since with the ehci and xhci controllers a single packet can be larger
then maxpacketsize, it is possible for the result of a single packet
to be both having transferred some data as well as the transfer to have
an error.
An example would be an input transfer from a bulk endpoint successfully
receiving 1 or more maxpacketsize packets from the device, followed
by a packet signalling halt.
While already touching all the devices and controllers handle_packet /
handle_data / handle_control code, also change the return type of
these functions to void, solely storing the status in the packet. To
make the code paths for regular versus async packet handling more
uniform.
This patch unfortunately is somewhat invasive, since makeing the qemu
usb core deal with this requires changes everywhere. This patch only
prepares the usb core for this, all the hcd / device changes are done
in such a way that there are no functional changes.
This patch has been tested with uhci and ehci hcds, together with usb-audio,
usb-hid and usb-storage devices, as well as with usb-redir redirection
with a wide variety of real devices.
Note that there is usually no need to directly set packet->actual_length
form devices handle_data callback, as that is done by usb_packet_copy()
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2012-11-01 20:15:01 +04:00
|
|
|
p->actual_length += bytes;
|
2011-07-12 17:22:25 +04:00
|
|
|
}
|
|
|
|
|
2013-01-24 18:38:23 +04:00
|
|
|
size_t usb_packet_size(USBPacket *p)
|
|
|
|
{
|
|
|
|
return p->combined ? p->combined->iov.size : p->iov.size;
|
|
|
|
}
|
|
|
|
|
2011-07-12 17:22:25 +04:00
|
|
|
void usb_packet_cleanup(USBPacket *p)
|
|
|
|
{
|
2012-01-12 15:51:48 +04:00
|
|
|
assert(!usb_packet_is_inflight(p));
|
2011-07-12 17:22:25 +04:00
|
|
|
qemu_iovec_destroy(&p->iov);
|
|
|
|
}
|
2011-08-29 14:49:46 +04:00
|
|
|
|
2012-07-03 12:11:21 +04:00
|
|
|
void usb_ep_reset(USBDevice *dev)
|
2011-08-29 14:49:46 +04:00
|
|
|
{
|
|
|
|
int ep;
|
|
|
|
|
2012-01-12 16:24:22 +04:00
|
|
|
dev->ep_ctl.nr = 0;
|
2011-12-13 18:58:19 +04:00
|
|
|
dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL;
|
|
|
|
dev->ep_ctl.ifnum = 0;
|
2013-09-17 23:44:53 +04:00
|
|
|
dev->ep_ctl.max_packet_size = 64;
|
2013-11-19 17:36:56 +04:00
|
|
|
dev->ep_ctl.max_streams = 0;
|
2011-12-13 18:58:19 +04:00
|
|
|
dev->ep_ctl.dev = dev;
|
2012-03-01 17:39:28 +04:00
|
|
|
dev->ep_ctl.pipeline = false;
|
2011-08-29 14:49:46 +04:00
|
|
|
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
2012-01-12 16:24:22 +04:00
|
|
|
dev->ep_in[ep].nr = ep + 1;
|
|
|
|
dev->ep_out[ep].nr = ep + 1;
|
|
|
|
dev->ep_in[ep].pid = USB_TOKEN_IN;
|
|
|
|
dev->ep_out[ep].pid = USB_TOKEN_OUT;
|
2011-08-29 14:49:46 +04:00
|
|
|
dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
|
|
|
|
dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
|
2012-07-03 12:15:08 +04:00
|
|
|
dev->ep_in[ep].ifnum = USB_INTERFACE_INVALID;
|
|
|
|
dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID;
|
2013-09-17 23:44:53 +04:00
|
|
|
dev->ep_in[ep].max_packet_size = 0;
|
|
|
|
dev->ep_out[ep].max_packet_size = 0;
|
2013-11-19 17:36:56 +04:00
|
|
|
dev->ep_in[ep].max_streams = 0;
|
|
|
|
dev->ep_out[ep].max_streams = 0;
|
2011-12-13 18:58:19 +04:00
|
|
|
dev->ep_in[ep].dev = dev;
|
|
|
|
dev->ep_out[ep].dev = dev;
|
2012-03-01 17:39:28 +04:00
|
|
|
dev->ep_in[ep].pipeline = false;
|
|
|
|
dev->ep_out[ep].pipeline = false;
|
2012-07-03 12:11:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_ep_init(USBDevice *dev)
|
|
|
|
{
|
|
|
|
int ep;
|
|
|
|
|
|
|
|
usb_ep_reset(dev);
|
|
|
|
QTAILQ_INIT(&dev->ep_ctl.queue);
|
|
|
|
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
2012-01-12 17:26:13 +04:00
|
|
|
QTAILQ_INIT(&dev->ep_in[ep].queue);
|
|
|
|
QTAILQ_INIT(&dev->ep_out[ep].queue);
|
2011-08-29 14:49:46 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-29 15:45:25 +04:00
|
|
|
void usb_ep_dump(USBDevice *dev)
|
|
|
|
{
|
|
|
|
static const char *tname[] = {
|
|
|
|
[USB_ENDPOINT_XFER_CONTROL] = "control",
|
|
|
|
[USB_ENDPOINT_XFER_ISOC] = "isoc",
|
|
|
|
[USB_ENDPOINT_XFER_BULK] = "bulk",
|
|
|
|
[USB_ENDPOINT_XFER_INT] = "int",
|
|
|
|
};
|
|
|
|
int ifnum, ep, first;
|
|
|
|
|
|
|
|
fprintf(stderr, "Device \"%s\", config %d\n",
|
|
|
|
dev->product_desc, dev->configuration);
|
|
|
|
for (ifnum = 0; ifnum < 16; ifnum++) {
|
|
|
|
first = 1;
|
|
|
|
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
|
|
|
if (dev->ep_in[ep].type != USB_ENDPOINT_XFER_INVALID &&
|
|
|
|
dev->ep_in[ep].ifnum == ifnum) {
|
|
|
|
if (first) {
|
|
|
|
first = 0;
|
|
|
|
fprintf(stderr, " Interface %d, alternative %d\n",
|
|
|
|
ifnum, dev->altsetting[ifnum]);
|
|
|
|
}
|
2011-08-31 18:09:27 +04:00
|
|
|
fprintf(stderr, " Endpoint %d, IN, %s, %d max\n", ep,
|
|
|
|
tname[dev->ep_in[ep].type],
|
|
|
|
dev->ep_in[ep].max_packet_size);
|
2011-08-29 15:45:25 +04:00
|
|
|
}
|
|
|
|
if (dev->ep_out[ep].type != USB_ENDPOINT_XFER_INVALID &&
|
|
|
|
dev->ep_out[ep].ifnum == ifnum) {
|
|
|
|
if (first) {
|
|
|
|
first = 0;
|
|
|
|
fprintf(stderr, " Interface %d, alternative %d\n",
|
|
|
|
ifnum, dev->altsetting[ifnum]);
|
|
|
|
}
|
2011-08-31 18:09:27 +04:00
|
|
|
fprintf(stderr, " Endpoint %d, OUT, %s, %d max\n", ep,
|
|
|
|
tname[dev->ep_out[ep].type],
|
|
|
|
dev->ep_out[ep].max_packet_size);
|
2011-08-29 15:45:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(stderr, "--\n");
|
|
|
|
}
|
|
|
|
|
2011-08-29 14:49:46 +04:00
|
|
|
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep)
|
|
|
|
{
|
2012-01-12 16:23:01 +04:00
|
|
|
struct USBEndpoint *eps;
|
|
|
|
|
|
|
|
if (dev == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
|
2011-12-13 18:58:19 +04:00
|
|
|
if (ep == 0) {
|
|
|
|
return &dev->ep_ctl;
|
|
|
|
}
|
2011-08-29 14:49:46 +04:00
|
|
|
assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
|
|
|
|
assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
|
|
|
|
return eps + ep - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
return uep->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_ep_set_type(USBDevice *dev, int pid, int ep, uint8_t type)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
uep->type = type;
|
|
|
|
}
|
2011-08-29 14:57:48 +04:00
|
|
|
|
|
|
|
uint8_t usb_ep_get_ifnum(USBDevice *dev, int pid, int ep)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
return uep->ifnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void usb_ep_set_ifnum(USBDevice *dev, int pid, int ep, uint8_t ifnum)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
uep->ifnum = ifnum;
|
|
|
|
}
|
2011-08-31 18:09:27 +04:00
|
|
|
|
|
|
|
void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
|
|
|
|
uint16_t raw)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
int size, microframes;
|
|
|
|
|
|
|
|
size = raw & 0x7ff;
|
|
|
|
switch ((raw >> 11) & 3) {
|
|
|
|
case 1:
|
|
|
|
microframes = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
microframes = 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
microframes = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
uep->max_packet_size = size * microframes;
|
|
|
|
}
|
|
|
|
|
|
|
|
int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
return uep->max_packet_size;
|
|
|
|
}
|
2012-03-01 17:39:28 +04:00
|
|
|
|
2013-11-19 17:36:56 +04:00
|
|
|
void usb_ep_set_max_streams(USBDevice *dev, int pid, int ep, uint8_t raw)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
int MaxStreams;
|
|
|
|
|
|
|
|
MaxStreams = raw & 0x1f;
|
|
|
|
if (MaxStreams) {
|
|
|
|
uep->max_streams = 1 << MaxStreams;
|
|
|
|
} else {
|
|
|
|
uep->max_streams = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int usb_ep_get_max_streams(USBDevice *dev, int pid, int ep)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
return uep->max_streams;
|
|
|
|
}
|
|
|
|
|
2012-03-01 17:39:28 +04:00
|
|
|
void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
uep->pipeline = enabled;
|
|
|
|
}
|
2012-08-28 11:43:18 +04:00
|
|
|
|
2012-12-12 16:40:59 +04:00
|
|
|
void usb_ep_set_halted(USBDevice *dev, int pid, int ep, bool halted)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
uep->halted = halted;
|
|
|
|
}
|
|
|
|
|
2012-08-28 11:43:18 +04:00
|
|
|
USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
|
|
|
|
uint64_t id)
|
|
|
|
{
|
|
|
|
struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
|
|
|
|
USBPacket *p;
|
|
|
|
|
2012-12-14 17:35:39 +04:00
|
|
|
QTAILQ_FOREACH(p, &uep->queue, queue) {
|
2012-08-28 11:43:18 +04:00
|
|
|
if (p->id == id) {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|