static void setup_received(void)
{
    static uint32_t setup_data[2];
    
    /* copy setup data from packet */
    setup_data[0] = SETUP1;
    setup_data[1] = SETUP2;

    /* clear all pending control transfers
     * do we need this here?
     */
    
    /* pass setup data to the upper layer */
    usb_core_control_request((struct usb_ctrlrequest*)setup_data);
}
Exemplo n.º 2
0
/* IRQ handler */
void INT_USB_FUNC(void)
{
    int i;
    uint32_t ints = GINTSTS;
    uint32_t epints;
    if (ints & 0x1000)  /* bus reset */
    {
        DCFG = 4;  /* Address 0 */
        reset_endpoints(1);
        usb_core_bus_reset();
    }

    if (ints & 0x2000)  /* enumeration done, we now know the speed */
    {
        /* Set up the maximum packet sizes accordingly */
        uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64;
        DIEPCTL1 = (DIEPCTL1 & ~0x000003FF) | maxpacket;
        DOEPCTL2 = (DOEPCTL2 & ~0x000003FF) | maxpacket;
        DIEPCTL3 = (DIEPCTL3 & ~0x000003FF) | maxpacket;
        DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket;
    }

    if (ints & 0x40000)  /* IN EP event */
        for (i = 0; i < 4; i += i + 1)  // 0, 1, 3
            if ((epints = DIEPINT(i)))
            {
                if (epints & 1)  /* Transfer completed */
                {
                    invalidate_dcache();
                    int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF);
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 0;
                        endpoints[i].done = true;
                        usb_core_transfer_complete(i, USB_DIR_IN, 0, bytes);
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                if (epints & 4)  /* AHB error */
                    panicf("USB: AHB error on IN EP%d", i);
                if (epints & 8)  /* Timeout */
                {
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 1;
                        endpoints[i].done = true;
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                DIEPINT(i) = epints;
            }

    if (ints & 0x80000)  /* OUT EP event */
        for (i = 0; i < USB_NUM_ENDPOINTS; i += 2)
            if ((epints = DOEPINT(i)))
            {
                if (epints & 1)  /* Transfer completed */
                {
                    invalidate_dcache();
                    int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF);
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 0;
                        endpoints[i].done = true;
                        usb_core_transfer_complete(i, USB_DIR_OUT, 0, bytes);
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                if (epints & 4)  /* AHB error */
                    panicf("USB: AHB error on OUT EP%d", i);
                if (epints & 8)  /* SETUP phase done */
                {
                    invalidate_dcache();
                    if (i == 0)
                    {
                        if (ctrlreq.bRequest == 5)
                        {
                            /* Already set the new address here,
                               before passing the packet to the core.
                               See below (usb_drv_set_address) for details. */
                            DCFG = (DCFG & ~0x7F0) | (ctrlreq.wValue << 4);
                        }
                        usb_core_control_request(&ctrlreq);
                    }
                    else panicf("USB: SETUP done on OUT EP%d!?", i);
                }
                /* Make sure EP0 OUT is set up to accept the next request */
                if (!i)
                {
                    DOEPTSIZ0 = 0x20080040;
                    DOEPDMA0 = &ctrlreq;
                    DOEPCTL0 |= 0x84000000;
                }
                DOEPINT(i) = epints;
            }

    GINTSTS = ints;
}
Exemplo n.º 3
0
static void handle_ep_int(int ep, bool out)
{
    unsigned long sts = DEPINT(ep, out);
    struct ep_type *endpoint = &endpoints[ep][out ? DIR_OUT : DIR_IN];

    logf("%s(%d %s): sts = 0x%lx", __func__, ep, out?"OUT":"IN", sts);

    if(sts & DEPINT_ahberr)
        panicf("usb-drv: ahb error on EP%d %s", ep, out ? "OUT" : "IN");

    if(sts & DEPINT_xfercompl)
    {
        discard_dma_buffer_cache();
        if(endpoint->busy)
        {
            endpoint->busy = false;
            endpoint->status = 0;
            /* works even for EP0 */
            int size = (DEPTSIZ(ep, out) & DEPTSIZ_xfersize_bits);
            int transfered = endpoint->size - size;
            if(ep == 0)
            {
                bool is_ack = endpoint->size == 0;
                switch(ep0_state)
                {
                case EP0_WAIT_SETUP:
                    panicf("usb-drv: EP0 completion while waiting for SETUP");
                case EP0_WAIT_DATA_ACK:
                    ep0_state = is_ack ? EP0_WAIT_DATA : EP0_WAIT_ACK;
                    break;
                case EP0_WAIT_ACK:
                case EP0_WAIT_DATA:
                    if((!is_ack && ep0_state == EP0_WAIT_ACK) || (is_ack && ep0_state == EP0_WAIT_DATA))
                        panicf("usb-drv: bad EP0 state");

                    prepare_setup_ep0();
                    break;
                }
            }
            if (!out)
                endpoint->size = size;
            usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, transfered);
            endpoint->done = true;
            semaphore_release(&endpoint->complete);
        }
    }

    if(!out && (sts & DIEPINT_timeout)) {
        if (endpoint->busy)
        {
            endpoint->busy = false;
            endpoint->status = 1;
            endpoint->done = true;
            semaphore_release(&endpoint->complete);
        }
    }

    if(out && (sts & DOEPINT_setup))
    {
        discard_dma_buffer_cache();
        if(ep != 0)
            panicf("usb-drv: setup not on EP0, this is impossible");
        if((DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits) != 0)
        {
            logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits);
            prepare_setup_ep0();
        }
        else
        {
            if(ep0_state == EP0_WAIT_SETUP)
            {
                bool data_phase = ep0_setup_pkt->wLength != 0;
                ep0_state = data_phase ? EP0_WAIT_DATA_ACK : EP0_WAIT_ACK;
            }

            logf("  rt=%x r=%x", ep0_setup_pkt->bRequestType, ep0_setup_pkt->bRequest);

            if(ep0_setup_pkt->bRequestType == USB_TYPE_STANDARD &&
               ep0_setup_pkt->bRequest     == USB_REQ_SET_ADDRESS)
                DCFG = (DCFG & ~bitm(DCFG, devadr)) | (ep0_setup_pkt->wValue << DCFG_devadr_bitp);

            usb_core_control_request(ep0_setup_pkt);
        }
    }

    DEPINT(ep, out) = sts;
}