Merge remote-tracking branch 'kraxel/usb.55' into staging
* kraxel/usb.55: usb-host: add trace events for iso xfers usb: fix interface initialization usb: split endpoint init and reset usb-redir: Correctly handle the usb_redir_babble usbredir status ehci: Kick async schedule on wakeup in the non companion case usb-ehci: Fix an assert whenever isoc transfers are used ehci: don't flush cache on doorbell rings. ehci: fix td writeback ehci: fix ehci_qh_do_overlay
This commit is contained in:
commit
fe0cb8ef84
3
hw/usb.h
3
hw/usb.h
@ -145,6 +145,8 @@
|
|||||||
#define USB_ENDPOINT_XFER_INT 3
|
#define USB_ENDPOINT_XFER_INT 3
|
||||||
#define USB_ENDPOINT_XFER_INVALID 255
|
#define USB_ENDPOINT_XFER_INVALID 255
|
||||||
|
|
||||||
|
#define USB_INTERFACE_INVALID 255
|
||||||
|
|
||||||
typedef struct USBBus USBBus;
|
typedef struct USBBus USBBus;
|
||||||
typedef struct USBBusOps USBBusOps;
|
typedef struct USBBusOps USBBusOps;
|
||||||
typedef struct USBPort USBPort;
|
typedef struct USBPort USBPort;
|
||||||
@ -363,6 +365,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p);
|
|||||||
void usb_cancel_packet(USBPacket * p);
|
void usb_cancel_packet(USBPacket * p);
|
||||||
|
|
||||||
void usb_ep_init(USBDevice *dev);
|
void usb_ep_init(USBDevice *dev);
|
||||||
|
void usb_ep_reset(USBDevice *dev);
|
||||||
void usb_ep_dump(USBDevice *dev);
|
void usb_ep_dump(USBDevice *dev);
|
||||||
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
|
struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep);
|
||||||
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
|
uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep);
|
||||||
|
@ -550,7 +550,7 @@ void usb_packet_cleanup(USBPacket *p)
|
|||||||
qemu_iovec_destroy(&p->iov);
|
qemu_iovec_destroy(&p->iov);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_ep_init(USBDevice *dev)
|
void usb_ep_reset(USBDevice *dev)
|
||||||
{
|
{
|
||||||
int ep;
|
int ep;
|
||||||
|
|
||||||
@ -559,7 +559,6 @@ void usb_ep_init(USBDevice *dev)
|
|||||||
dev->ep_ctl.ifnum = 0;
|
dev->ep_ctl.ifnum = 0;
|
||||||
dev->ep_ctl.dev = dev;
|
dev->ep_ctl.dev = dev;
|
||||||
dev->ep_ctl.pipeline = false;
|
dev->ep_ctl.pipeline = false;
|
||||||
QTAILQ_INIT(&dev->ep_ctl.queue);
|
|
||||||
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) {
|
||||||
dev->ep_in[ep].nr = ep + 1;
|
dev->ep_in[ep].nr = ep + 1;
|
||||||
dev->ep_out[ep].nr = ep + 1;
|
dev->ep_out[ep].nr = ep + 1;
|
||||||
@ -567,12 +566,22 @@ void usb_ep_init(USBDevice *dev)
|
|||||||
dev->ep_out[ep].pid = USB_TOKEN_OUT;
|
dev->ep_out[ep].pid = USB_TOKEN_OUT;
|
||||||
dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
|
dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID;
|
||||||
dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
|
dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID;
|
||||||
dev->ep_in[ep].ifnum = 0;
|
dev->ep_in[ep].ifnum = USB_INTERFACE_INVALID;
|
||||||
dev->ep_out[ep].ifnum = 0;
|
dev->ep_out[ep].ifnum = USB_INTERFACE_INVALID;
|
||||||
dev->ep_in[ep].dev = dev;
|
dev->ep_in[ep].dev = dev;
|
||||||
dev->ep_out[ep].dev = dev;
|
dev->ep_out[ep].dev = dev;
|
||||||
dev->ep_in[ep].pipeline = false;
|
dev->ep_in[ep].pipeline = false;
|
||||||
dev->ep_out[ep].pipeline = false;
|
dev->ep_out[ep].pipeline = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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++) {
|
||||||
QTAILQ_INIT(&dev->ep_in[ep].queue);
|
QTAILQ_INIT(&dev->ep_in[ep].queue);
|
||||||
QTAILQ_INIT(&dev->ep_out[ep].queue);
|
QTAILQ_INIT(&dev->ep_out[ep].queue);
|
||||||
}
|
}
|
||||||
|
@ -365,6 +365,7 @@ struct EHCIQueue {
|
|||||||
uint32_t seen;
|
uint32_t seen;
|
||||||
uint64_t ts;
|
uint64_t ts;
|
||||||
int async;
|
int async;
|
||||||
|
int revalidate;
|
||||||
|
|
||||||
/* cached data from guest - needs to be flushed
|
/* cached data from guest - needs to be flushed
|
||||||
* when guest removes an entry (doorbell, handshake sequence)
|
* when guest removes an entry (doorbell, handshake sequence)
|
||||||
@ -775,7 +776,18 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
|
static void ehci_queues_tag_unused_async(EHCIState *ehci)
|
||||||
|
{
|
||||||
|
EHCIQueue *q;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(q, &ehci->aqueues, next) {
|
||||||
|
if (!q->seen) {
|
||||||
|
q->revalidate = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ehci_queues_rip_unused(EHCIState *ehci, int async)
|
||||||
{
|
{
|
||||||
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
|
||||||
uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
|
uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
|
||||||
@ -787,7 +799,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
|
|||||||
q->ts = ehci->last_run_ns;
|
q->ts = ehci->last_run_ns;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!flush && ehci->last_run_ns < q->ts + maxage) {
|
if (ehci->last_run_ns < q->ts + maxage) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ehci_free_queue(q);
|
ehci_free_queue(q);
|
||||||
@ -893,10 +905,11 @@ static void ehci_wakeup(USBPort *port)
|
|||||||
USBPort *companion = s->companion_ports[port->index];
|
USBPort *companion = s->companion_ports[port->index];
|
||||||
if (companion->ops->wakeup) {
|
if (companion->ops->wakeup) {
|
||||||
companion->ops->wakeup(companion);
|
companion->ops->wakeup(companion);
|
||||||
} else {
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_bh_schedule(s->async_bh);
|
qemu_bh_schedule(s->async_bh);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ehci_register_companion(USBBus *bus, USBPort *ports[],
|
static int ehci_register_companion(USBBus *bus, USBPort *ports[],
|
||||||
@ -1246,6 +1259,23 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the qh back to guest physical memory. This step isn't
|
||||||
|
* in the EHCI spec but we need to do it since we don't share
|
||||||
|
* physical memory with our guest VM.
|
||||||
|
*
|
||||||
|
* The first three dwords are read-only for the EHCI, so skip them
|
||||||
|
* when writing back the qh.
|
||||||
|
*/
|
||||||
|
static void ehci_flush_qh(EHCIQueue *q)
|
||||||
|
{
|
||||||
|
uint32_t *qh = (uint32_t *) &q->qh;
|
||||||
|
uint32_t dwords = sizeof(EHCIqh) >> 2;
|
||||||
|
uint32_t addr = NLPTR_GET(q->qhaddr);
|
||||||
|
|
||||||
|
put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
|
||||||
|
}
|
||||||
|
|
||||||
// 4.10.2
|
// 4.10.2
|
||||||
|
|
||||||
static int ehci_qh_do_overlay(EHCIQueue *q)
|
static int ehci_qh_do_overlay(EHCIQueue *q)
|
||||||
@ -1293,8 +1323,7 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
|
|||||||
q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
|
q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK;
|
||||||
q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
|
q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK;
|
||||||
|
|
||||||
put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh,
|
ehci_flush_qh(q);
|
||||||
sizeof(EHCIqh) >> 2);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1600,23 +1629,6 @@ static int ehci_process_itd(EHCIState *ehci,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the qh back to guest physical memory. This step isn't
|
|
||||||
* in the EHCI spec but we need to do it since we don't share
|
|
||||||
* physical memory with our guest VM.
|
|
||||||
*
|
|
||||||
* The first three dwords are read-only for the EHCI, so skip them
|
|
||||||
* when writing back the qh.
|
|
||||||
*/
|
|
||||||
static void ehci_flush_qh(EHCIQueue *q)
|
|
||||||
{
|
|
||||||
uint32_t *qh = (uint32_t *) &q->qh;
|
|
||||||
uint32_t dwords = sizeof(EHCIqh) >> 2;
|
|
||||||
uint32_t addr = NLPTR_GET(q->qhaddr);
|
|
||||||
|
|
||||||
put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This state is the entry point for asynchronous schedule
|
/* This state is the entry point for asynchronous schedule
|
||||||
* processing. Entry here consitutes a EHCI start event state (4.8.5)
|
* processing. Entry here consitutes a EHCI start event state (4.8.5)
|
||||||
*/
|
*/
|
||||||
@ -1632,7 +1644,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async)
|
|||||||
ehci_set_usbsts(ehci, USBSTS_REC);
|
ehci_set_usbsts(ehci, USBSTS_REC);
|
||||||
}
|
}
|
||||||
|
|
||||||
ehci_queues_rip_unused(ehci, async, 0);
|
ehci_queues_rip_unused(ehci, async);
|
||||||
|
|
||||||
/* Find the head of the list (4.9.1.1) */
|
/* Find the head of the list (4.9.1.1) */
|
||||||
for(i = 0; i < MAX_QH; i++) {
|
for(i = 0; i < MAX_QH; i++) {
|
||||||
@ -1717,6 +1729,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
|||||||
EHCIPacket *p;
|
EHCIPacket *p;
|
||||||
uint32_t entry, devaddr;
|
uint32_t entry, devaddr;
|
||||||
EHCIQueue *q;
|
EHCIQueue *q;
|
||||||
|
EHCIqh qh;
|
||||||
|
|
||||||
entry = ehci_get_fetch_addr(ehci, async);
|
entry = ehci_get_fetch_addr(ehci, async);
|
||||||
q = ehci_find_queue_by_qh(ehci, entry, async);
|
q = ehci_find_queue_by_qh(ehci, entry, async);
|
||||||
@ -1734,7 +1747,17 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_dwords(ehci, NLPTR_GET(q->qhaddr),
|
get_dwords(ehci, NLPTR_GET(q->qhaddr),
|
||||||
(uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
|
(uint32_t *) &qh, sizeof(EHCIqh) >> 2);
|
||||||
|
if (q->revalidate && (q->qh.epchar != qh.epchar ||
|
||||||
|
q->qh.epcap != qh.epcap ||
|
||||||
|
q->qh.current_qtd != qh.current_qtd)) {
|
||||||
|
ehci_free_queue(q);
|
||||||
|
q = ehci_alloc_queue(ehci, entry, async);
|
||||||
|
q->seen++;
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
|
q->qh = qh;
|
||||||
|
q->revalidate = 0;
|
||||||
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
|
ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
|
||||||
|
|
||||||
devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
|
devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
|
||||||
@ -2071,6 +2094,7 @@ out:
|
|||||||
static int ehci_state_writeback(EHCIQueue *q)
|
static int ehci_state_writeback(EHCIQueue *q)
|
||||||
{
|
{
|
||||||
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
|
EHCIPacket *p = QTAILQ_FIRST(&q->packets);
|
||||||
|
uint32_t *qtd, addr;
|
||||||
int again = 0;
|
int again = 0;
|
||||||
|
|
||||||
/* Write back the QTD from the QH area */
|
/* Write back the QTD from the QH area */
|
||||||
@ -2078,8 +2102,9 @@ static int ehci_state_writeback(EHCIQueue *q)
|
|||||||
assert(p->qtdaddr == q->qtdaddr);
|
assert(p->qtdaddr == q->qtdaddr);
|
||||||
|
|
||||||
ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
|
ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
|
||||||
put_dwords(q->ehci, NLPTR_GET(p->qtdaddr), (uint32_t *) &q->qh.next_qtd,
|
qtd = (uint32_t *) &q->qh.next_qtd;
|
||||||
sizeof(EHCIqtd) >> 2);
|
addr = NLPTR_GET(p->qtdaddr);
|
||||||
|
put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2);
|
||||||
ehci_free_packet(p);
|
ehci_free_packet(p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2227,7 +2252,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
|
|||||||
*/
|
*/
|
||||||
if (ehci->usbcmd & USBCMD_IAAD) {
|
if (ehci->usbcmd & USBCMD_IAAD) {
|
||||||
/* Remove all unseen qhs from the async qhs queue */
|
/* Remove all unseen qhs from the async qhs queue */
|
||||||
ehci_queues_rip_unused(ehci, async, 1);
|
ehci_queues_tag_unused_async(ehci);
|
||||||
DPRINTF("ASYNC: doorbell request acknowledged\n");
|
DPRINTF("ASYNC: doorbell request acknowledged\n");
|
||||||
ehci->usbcmd &= ~USBCMD_IAAD;
|
ehci->usbcmd &= ~USBCMD_IAAD;
|
||||||
ehci_set_interrupt(ehci, USBSTS_IAA);
|
ehci_set_interrupt(ehci, USBSTS_IAA);
|
||||||
@ -2280,7 +2305,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
|
|||||||
ehci_set_fetch_addr(ehci, async,entry);
|
ehci_set_fetch_addr(ehci, async,entry);
|
||||||
ehci_set_state(ehci, async, EST_FETCHENTRY);
|
ehci_set_state(ehci, async, EST_FETCHENTRY);
|
||||||
ehci_advance_state(ehci, async);
|
ehci_advance_state(ehci, async);
|
||||||
ehci_queues_rip_unused(ehci, async, 0);
|
ehci_queues_rip_unused(ehci, async);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -2557,6 +2582,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
|
|||||||
s->async_bh = qemu_bh_new(ehci_async_bh, s);
|
s->async_bh = qemu_bh_new(ehci_async_bh, s);
|
||||||
QTAILQ_INIT(&s->aqueues);
|
QTAILQ_INIT(&s->aqueues);
|
||||||
QTAILQ_INIT(&s->pqueues);
|
QTAILQ_INIT(&s->pqueues);
|
||||||
|
usb_packet_init(&s->ipacket);
|
||||||
|
|
||||||
qemu_register_reset(ehci_reset, s);
|
qemu_register_reset(ehci_reset, s);
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ static int is_iso_started(USBHostDevice *s, int pid, int ep)
|
|||||||
|
|
||||||
static void clear_iso_started(USBHostDevice *s, int pid, int ep)
|
static void clear_iso_started(USBHostDevice *s, int pid, int ep)
|
||||||
{
|
{
|
||||||
trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
|
trace_usb_host_iso_stop(s->bus_num, s->addr, ep);
|
||||||
get_endp(s, pid, ep)->iso_started = 0;
|
get_endp(s, pid, ep)->iso_started = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ static void set_iso_started(USBHostDevice *s, int pid, int ep)
|
|||||||
{
|
{
|
||||||
struct endp_data *e = get_endp(s, pid, ep);
|
struct endp_data *e = get_endp(s, pid, ep);
|
||||||
|
|
||||||
trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
|
trace_usb_host_iso_start(s->bus_num, s->addr, ep);
|
||||||
if (!e->iso_started) {
|
if (!e->iso_started) {
|
||||||
e->iso_started = 1;
|
e->iso_started = 1;
|
||||||
e->inflight = 0;
|
e->inflight = 0;
|
||||||
@ -319,7 +319,8 @@ static void async_complete(void *opaque)
|
|||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
if (urbs > 2) {
|
if (urbs > 2) {
|
||||||
fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
|
/* indicates possible latency issues */
|
||||||
|
trace_usb_host_iso_many_urbs(s->bus_num, s->addr, urbs);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -352,7 +353,8 @@ static void async_complete(void *opaque)
|
|||||||
urbs++;
|
urbs++;
|
||||||
inflight = change_iso_inflight(s, pid, ep, -1);
|
inflight = change_iso_inflight(s, pid, ep, -1);
|
||||||
if (inflight == 0 && is_iso_started(s, pid, ep)) {
|
if (inflight == 0 && is_iso_started(s, pid, ep)) {
|
||||||
fprintf(stderr, "husb: out of buffers for iso stream\n");
|
/* can be latency issues, or simply end of stream */
|
||||||
|
trace_usb_host_iso_out_of_bufs(s->bus_num, s->addr, ep);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1136,7 +1138,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
|
|||||||
USBDescriptor *d;
|
USBDescriptor *d;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
|
||||||
usb_ep_init(&s->dev);
|
usb_ep_reset(&s->dev);
|
||||||
|
|
||||||
for (i = 0;; i += d->bLength) {
|
for (i = 0;; i += d->bLength) {
|
||||||
if (i+2 >= s->descr_len) {
|
if (i+2 >= s->descr_len) {
|
||||||
@ -1239,7 +1241,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
usb_ep_init(&s->dev);
|
usb_ep_reset(&s->dev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,6 +1328,7 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb_ep_init(&dev->dev);
|
||||||
ret = usb_linux_update_endp_table(dev);
|
ret = usb_linux_update_endp_table(dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1033,6 +1033,8 @@ static int usbredir_handle_status(USBRedirDevice *dev,
|
|||||||
case usb_redir_inval:
|
case usb_redir_inval:
|
||||||
WARNING("got invalid param error from usb-host?\n");
|
WARNING("got invalid param error from usb-host?\n");
|
||||||
return USB_RET_NAK;
|
return USB_RET_NAK;
|
||||||
|
case usb_redir_babble:
|
||||||
|
return USB_RET_BABBLE;
|
||||||
case usb_redir_ioerror:
|
case usb_redir_ioerror:
|
||||||
case usb_redir_timeout:
|
case usb_redir_timeout:
|
||||||
default:
|
default:
|
||||||
|
@ -368,8 +368,10 @@ usb_host_urb_complete(int bus, int addr, void *aurb, int status, int length, int
|
|||||||
usb_host_urb_canceled(int bus, int addr, void *aurb) "dev %d:%d, aurb %p"
|
usb_host_urb_canceled(int bus, int addr, void *aurb) "dev %d:%d, aurb %p"
|
||||||
usb_host_ep_set_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
usb_host_ep_set_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
||||||
usb_host_ep_clear_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
usb_host_ep_clear_halt(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
||||||
usb_host_ep_start_iso(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
usb_host_iso_start(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
||||||
usb_host_ep_stop_iso(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
usb_host_iso_stop(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
||||||
|
usb_host_iso_out_of_bufs(int bus, int addr, int ep) "dev %d:%d, ep %d"
|
||||||
|
usb_host_iso_many_urbs(int bus, int addr, int count) "dev %d:%d, count %d"
|
||||||
usb_host_reset(int bus, int addr) "dev %d:%d"
|
usb_host_reset(int bus, int addr) "dev %d:%d"
|
||||||
usb_host_auto_scan_enabled(void)
|
usb_host_auto_scan_enabled(void)
|
||||||
usb_host_auto_scan_disabled(void)
|
usb_host_auto_scan_disabled(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user