Example #1
0
void usb_core_init(void)
{
    int i;
    if (initialized)
        return;

    usb_drv_init();

    /* class driver init functions should be safe to call even if the driver
     * won't be used. This simplifies other logic (i.e. we don't need to know
     * yet which drivers will be enabled */
    for(i = 0; i < USB_NUM_DRIVERS; i++)
        if(drivers[i].init != NULL)
            drivers[i].init();

    initialized = true;
    usb_state = DEFAULT;
#ifdef HAVE_USB_CHARGING_ENABLE
    usb_no_host = false;
    timeout_register(&usb_no_host_timeout, usb_no_host_callback, HZ*10, 0);
#endif
    logf("usb_core_init() finished");
}
/* UDC ISR function */
void INT_UDC(void)
{
    uint32_t txstat, rxstat;
    int tmp, ep_num;
    
    /* read what caused UDC irq */
    uint32_t intsrc = INT2FLAG & 0x7fffff;
    
    if (intsrc & (1<<1)) /* setup interrupt */
    {
        setup_received();
    }
    else if (intsrc & (1<<2)) /* ep0 in interrupt */
    {
        txstat = TX0STAT; /* read clears flags */
        
        /* TODO handle errors */
        if (txstat & (1<<18)) /* check TxACK flag */
        {
            if (ctrlep[DIR_IN].cnt >= 0)
            {
                /* we still have data to send (or ZLP) */
                ctr_write();
            }
            else
            {
                /* final ack received */
                usb_core_transfer_complete(0,                   /* ep */
                                           USB_DIR_IN,          /* dir */
                                           0,                   /* status */
                                           ctrlep[DIR_IN].len); /* length */
                
                /* release semaphore for blocking transfer */
                if (ctrlep[DIR_IN].block)
                    semaphore_release(&ctrlep[DIR_IN].complete);
            }
        }
    }
    else if (intsrc & (1<<3)) /* ep0 out interrupt */
    {
        rxstat = RX0STAT;

        /* TODO handle errors */
        if (rxstat & (1<<18)) /* RxACK */
        {
            if (ctrlep[DIR_OUT].cnt > 0)
                ctr_read();
            else
                usb_core_transfer_complete(0,                    /* ep */
                                           USB_DIR_OUT,          /* dir */
                                           0,                    /* status */
                                           ctrlep[DIR_OUT].len); /* length */                
        }
    }
    else if (intsrc & (1<<4)) /* usb reset */
    {
        usb_drv_init();
    }
    else if (intsrc & (1<<5)) /* usb resume */
    {
        TX0CON |= (1<<0); /* TxClr */
        TX0CON &= ~(1<<0);
        RX0CON |= (1<<1); /* RxClr */
        RX0CON &= (1<<1);
    }
    else if (intsrc & (1<<6)) /* usb suspend */
    {
    }
    else if (intsrc & (1<<7)) /* usb connect */
    {
    }
    else
    {
        /* lets figure out which ep generated irq */
        tmp = intsrc >> 7;
        for (ep_num=1; ep_num < 15; ep_num++)
        {
            tmp >>= ep_num;
            if (tmp & 0x01)
                break;
        }
        
        if (intsrc & ((1<<8)|(1<<11)|(1<<14)|(1<<17)|(1<<20)))
        {
            /* bulk out */
            rxstat = BOUT_RXSTAT(ep_num);
            
            /* TODO handle errors */
            if (rxstat & (1<<18)) /* RxACK */
            {
                if (endpoints[ep_num].cnt > 0)
                    blk_read(ep_num);
                else
                    usb_core_transfer_complete(ep_num,               /* ep */
                                               USB_DIR_OUT,          /* dir */
                                               0,                    /* status */
                                               endpoints[ep_num].len); /* length */                
            }
        }
        else if (intsrc & ((1<<9)|(1<<12)|(1<<15)|(1<<18)|(1<<21)))
        {
            /* bulk in */
            txstat = BIN_TXSTAT(ep_num);
            
            /* TODO handle errors */
            if (txstat & (1<<18)) /* check TxACK flag */
            {
                if (endpoints[ep_num].cnt >= 0)
                {
                    /* we still have data to send (or ZLP) */
                    blk_write(ep_num);
                }
                else
                {
                    /* final ack received */
                    usb_core_transfer_complete(ep_num,                   /* ep */
                                               USB_DIR_IN,          /* dir */
                                               0,                   /* status */
                                               endpoints[ep_num].len); /* length */
                
                    /* release semaphore for blocking transfer */
                    if (endpoints[ep_num].block)
                        semaphore_release(&endpoints[ep_num].complete);
                }
            }
        }
        else if (intsrc & ((1<<10)|(1<13)|(1<<16)|(1<<19)|(1<<22)))
        {
            /* int in */
            txstat = IIN_TXSTAT(ep_num);

            /* TODO handle errors */
            if (txstat & (1<<18)) /* check TxACK flag */
            {
                if (endpoints[ep_num].cnt >= 0)
                {
                    /* we still have data to send (or ZLP) */
                    int_write(ep_num);
                }
                else
                {
                    /* final ack received */
                    usb_core_transfer_complete(ep_num,                   /* ep */
                                               USB_DIR_IN,          /* dir */
                                               0,                   /* status */
                                               endpoints[ep_num].len); /* length */
                
                    /* release semaphore for blocking transfer */
                    if (endpoints[ep_num].block)
                        semaphore_release(&endpoints[ep_num].complete);
                }
            }
        }
    }
}