/* Hand over a packet to a device for processing. Return value USB_RET_ASYNC indicates the processing isn't finished yet, the driver will call usb_packet_complete() when done processing it. */ int usb_handle_packet(USBDevice *dev, USBPacket *p) { int ret; if (dev == NULL) { return USB_RET_NODEV; } assert(dev == p->ep->dev); assert(dev->state == USB_STATE_DEFAULT); usb_packet_check_state(p, USB_PACKET_SETUP); assert(p->ep != NULL); if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } else { p->result = ret; usb_packet_set_state(p, USB_PACKET_COMPLETE); } } else { ret = USB_RET_ASYNC; usb_packet_set_state(p, USB_PACKET_QUEUED); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } return ret; }
/* 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) { USBEndpoint *ep = p->ep; int ret; usb_packet_check_state(p, USB_PACKET_ASYNC); assert(QTAILQ_FIRST(&ep->queue) == p); usb_packet_set_state(p, USB_PACKET_COMPLETE); QTAILQ_REMOVE(&ep->queue, p, queue); dev->port->ops->complete(dev->port, p); while (!QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); if (p->state == USB_PACKET_ASYNC) { break; } usb_packet_check_state(p, USB_PACKET_QUEUED); ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); break; } p->result = ret; usb_packet_set_state(p, USB_PACKET_COMPLETE); QTAILQ_REMOVE(&ep->queue, p, queue); dev->port->ops->complete(dev->port, p); } }
/* 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) { USBEndpoint *ep = p->ep; int ret; usb_packet_check_state(p, USB_PACKET_ASYNC); usb_packet_complete_one(dev, p); while (!QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); if (ep->halted) { /* Empty the queue on a halt */ p->result = USB_RET_REMOVE_FROM_QUEUE; dev->port->ops->complete(dev->port, p); continue; } if (p->state == USB_PACKET_ASYNC) { break; } usb_packet_check_state(p, USB_PACKET_QUEUED); ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); break; } p->result = ret; usb_packet_complete_one(ep->dev, p); } }
/* Hand over a packet to a device for processing. Return value USB_RET_ASYNC indicates the processing isn't finished yet, the driver will call usb_packet_complete() when done processing it. */ int usb_handle_packet(USBDevice *dev, USBPacket *p) { int ret; if (dev == NULL) { return USB_RET_NODEV; } assert(dev == p->ep->dev); assert(dev->state == USB_STATE_DEFAULT); usb_packet_check_state(p, USB_PACKET_SETUP); assert(p->ep != NULL); /* Submitting a new packet clears halt */ if (p->ep->halted) { assert(QTAILQ_EMPTY(&p->ep->queue)); p->ep->halted = false; } if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) { ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { assert(p->ep->type != USB_ENDPOINT_XFER_ISOC); usb_packet_set_state(p, USB_PACKET_ASYNC); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } else if (ret == USB_RET_ADD_TO_QUEUE) { usb_packet_set_state(p, USB_PACKET_QUEUED); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); ret = USB_RET_ASYNC; } else { /* * When pipelining is enabled usb-devices must always return async, * otherwise packets can complete out of order! */ assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue)); if (ret != USB_RET_NAK) { p->result = ret; usb_packet_set_state(p, USB_PACKET_COMPLETE); } } } else { ret = USB_RET_ASYNC; usb_packet_set_state(p, USB_PACKET_QUEUED); QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue); } return ret; }
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) { assert(!usb_packet_is_inflight(p)); p->pid = pid; p->ep = ep; p->result = 0; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); }
/* 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) { 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); } }
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id) { assert(!usb_packet_is_inflight(p)); assert(p->iov.iov != NULL); p->id = id; p->pid = pid; p->ep = ep; p->result = 0; p->parameter = 0; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); }
static void __usb_packet_complete(USBDevice *dev, USBPacket *p) { USBEndpoint *ep = p->ep; assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK); if (p->result < 0) { ep->halted = true; } usb_packet_set_state(p, USB_PACKET_COMPLETE); QTAILQ_REMOVE(&ep->queue, p, queue); dev->port->ops->complete(dev->port, p); }
void usb_packet_complete_one(USBDevice *dev, USBPacket *p) { USBEndpoint *ep = p->ep; assert(QTAILQ_FIRST(&ep->queue) == p); assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK); if (p->result < 0 || (p->short_not_ok && (p->result < p->iov.size))) { ep->halted = true; } usb_packet_set_state(p, USB_PACKET_COMPLETE); QTAILQ_REMOVE(&ep->queue, p, queue); dev->port->ops->complete(dev->port, p); }
void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, bool short_not_ok, bool int_req) { assert(!usb_packet_is_inflight(p)); assert(p->iov.iov != NULL); p->id = id; p->pid = pid; p->ep = ep; p->result = 0; p->parameter = 0; p->short_not_ok = short_not_ok; p->int_req = int_req; p->combined = NULL; qemu_iovec_reset(&p->iov); usb_packet_set_state(p, USB_PACKET_SETUP); }
/* 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) { USBEndpoint *ep = p->ep; int ret; usb_packet_check_state(p, USB_PACKET_ASYNC); assert(QTAILQ_FIRST(&ep->queue) == p); __usb_packet_complete(dev, p); while (!ep->halted && !QTAILQ_EMPTY(&ep->queue)) { p = QTAILQ_FIRST(&ep->queue); if (p->state == USB_PACKET_ASYNC) { break; } usb_packet_check_state(p, USB_PACKET_QUEUED); ret = usb_process_one(p); if (ret == USB_RET_ASYNC) { usb_packet_set_state(p, USB_PACKET_ASYNC); break; } p->result = ret; __usb_packet_complete(ep->dev, p); } }