static int ehci_execute(EHCIQueue *q)

{

    USBDevice *dev;

    int ret;

    int endp;

    int devadr;



    if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {

        fprintf(stderr, "Attempting to execute inactive QH\n");

        return USB_RET_PROCERR;

    }



    q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;

    if (q->tbytes > BUFF_SIZE) {

        fprintf(stderr, "Request for more bytes than allowed\n");

        return USB_RET_PROCERR;

    }



    q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;

    switch(q->pid) {

        case 0: q->pid = USB_TOKEN_OUT; break;

        case 1: q->pid = USB_TOKEN_IN; break;

        case 2: q->pid = USB_TOKEN_SETUP; break;

        default: fprintf(stderr, "bad token\n"); break;

    }



    if (ehci_init_transfer(q) != 0) {

        return USB_RET_PROCERR;

    }



    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);

    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);



    ret = USB_RET_NODEV;



    usb_packet_setup(&q->packet, q->pid, devadr, endp);

    usb_packet_map(&q->packet, &q->sgl);



    

    dev = ehci_find_device(q->ehci, q->packet.devaddr);

    ret = usb_handle_packet(dev, &q->packet);

    DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "

            "(total %d) endp %x ret %d\n",

            q->qhaddr, q->qh.next, q->qtdaddr, q->pid,

            q->packet.iov.size, q->tbytes, endp, ret);



    if (ret > BUFF_SIZE) {

        fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");

        return USB_RET_PROCERR;

    }



    return ret;

}
