/* 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); 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_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); } }
/* 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; }