void ep_clear_stall(U8 ep_num) { usb_pcb_t *pcb = usb_pcb_get(); pcb->ep_stall &= ~(1 << ep_num); ep_select(ep_num); UECONX |= (1<<STALLRQC); }
void ep_set_stall(U8 ep_num) { usb_pcb_t *pcb = usb_pcb_get(); pcb->ep_stall |= (1 << ep_num); ep_select(ep_num); UECONX |= (1 << STALLRQ); }
void ep_send_zlp(U8 ep_num) { cli(); ep_select(ep_num); while (!TX_FIFO_READY); TX_DATA(); while (!TX_FIFO_READY); sei(); }
void ep_init() { U8 i; // disable and clear all endpoints for (i=0; i<MAX_EPS; i++) { ep_select(i); ep_disable(i); ep_cfg_clear(i); } // reset all the endpoints UERST = 0x7F; UERST = 0; // configure the control endpoint first since that one is needed for enumeration ep_config(EP_CTRL, CONTROL, DIR_OUT, MAX_PACKET_SZ); // set the rx setup interrupt to received the enumeration interrupts ep_select(EP_CTRL); }
/* Clear all USB related interrupts */ void intp_clear_all() { U8 i; USBINT = 0; UDINT = 0; for (i = 0; i < MAX_EPS; i++) { ep_select(i); UEINTX = 0; } }
void ep_drain_fifo(U8 ep) { U8 byte_cnt; usb_pcb_t *pcb = usb_pcb_get(); ep_select(ep); byte_cnt = UEBCX; if (byte_cnt <= (MAX_BUF_SZ - pcb->fifo[ep].len)) { ep_read(ep); pcb->pending_data &= ~(1<<ep); FIFOCON_INT_CLR(); } }
void ep_write(U8 ep_num) { U8 i, ep_size, len; usb_pcb_t *pcb = usb_pcb_get(); ep_select(ep_num); ep_size = ep_size_get(); len = pcb->fifo[ep_num].len; // make sure that the tx fifo is ready to receive the out data if (ep_num == EP_CTRL) { while (!TX_FIFO_READY); } else { while (!RWAL_INT); } for (i=0; i<len; i++) { // check if we've reached the max packet size for the endpoint if (i == ep_size) { // we've filled the max packet size so break and send the data break; } UEDATX = usb_buf_read(ep_num); } if (ep_num == EP_CTRL) { while (!TX_FIFO_READY); } // clearing these two will send the data out TX_IN_INT_CLR(); FIFOCON_INT_CLR(); }
void ep_config(U8 ep_num, U8 type, U8 dir, U8 size) { // init the direction the fifo usb_buf_init(ep_num, dir); // select the endpoint and reset it ep_select(ep_num); UECONX &= ~(1 << EPEN); UECONX |= (1 << EPEN); // set the type, direction, and size UECFG0X |= (type & 0x3) << EPTYPE0; UECFG0X |= dir; UECFG1X |= (size & 0x7) << EPSIZE0; // we're only using single banks for now. double banks can be used on certain EPs only. UECFG1X |= (SINGLE & 0x3) << EPBK0; // alloc memory for the endpoint UECFG1X |= (1 << ALLOC); // spin here until the config is okay while (!(UESTA0X & (1<<CFGOK))); UERST |= (1<<ep_num); UERST &= ~(1<<ep_num); if (ep_num == EP_CTRL) { RX_SETUP_INT_ENB(); RX_OUT_INT_ENB(); } else if (dir == DIR_OUT) { RX_OUT_INT_ENB(); } }
void ep_reset_toggle(U8 ep_num) { ep_select(ep_num); UECONX |= (1<<RSTDT); }