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); } } } } }