📄 usb-proto.c
字号:
/* Enable interrupt for control endpoint */ *AT91C_UDP_IER = AT91C_UDP_EP0; notify_process(USB_EVENT_RESET);}struct USB_request_st usb_setup_buffer;static voidread_fifo0(unsigned char *buffer, unsigned int length){ unsigned int r; for (r = 0; r < length; r++) { *buffer++ = AT91C_UDP_FDR[0]; }}voidusb_ep0_int(){ unsigned int status; status = AT91C_UDP_CSR[0];#if 0 printf("status: %08x\n", status);#endif if (status & AT91C_UDP_STALLSENT) { /* Acknowledge */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],0, AT91C_UDP_STALLSENT); } if (status & AT91C_UDP_RXSETUP) { usb_ctrl_send_pos = NULL; /* Cancel any pending control data transmission */ if (RXBYTECNT(status) == 8) { read_fifo0((unsigned char*)&usb_setup_buffer, 8); UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0], ((usb_setup_buffer.bmRequestType & 0x80) ? AT91C_UDP_DIR : 0), AT91C_UDP_DIR); usb_ctrl_data_len = 0; if ((usb_setup_buffer.bmRequestType & 0x80) != 0 || usb_setup_buffer.wLength == 0) { usb_endpoint_events[0] |= USB_EP_EVENT_SETUP; notify_process(USB_EVENT_EP(0)); } else { if (usb_setup_buffer.wLength > MAX_CTRL_DATA) { /* stall */ usb_error_stall(); } else { usb_flags |= USB_FLAG_RECEIVING_CTRL; } } } else { usb_error_stall(); } /* Acknowledge SETUP */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],0, AT91C_UDP_RXSETUP); } else if (status & (AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_RX_DATA_BK0)) { puts("IN"); if (usb_flags & USB_FLAG_RECEIVING_CTRL) { unsigned int len; unsigned int left = MAX_CTRL_DATA - usb_ctrl_data_len; len = RXBYTECNT(status); if (len > left) { /* stall */ usb_error_stall(); } else { unsigned char *buf_tmp = usb_ctrl_data_buffer + usb_ctrl_data_len; usb_ctrl_data_len += len; if (usb_ctrl_data_len == usb_setup_buffer.wLength || len < CTRL_EP_SIZE) { usb_flags &= ~USB_FLAG_RECEIVING_CTRL; usb_endpoint_events[0] |= USB_EP_EVENT_SETUP; notify_process(USB_EVENT_EP(0)); } while(len-- > 0) *buf_tmp++ = AT91C_UDP_FDR[0]; } } else { if (RXBYTECNT(status) > 0) { puts("Discarded input"); } } UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],0, AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_RX_DATA_BK0); } if (status & AT91C_UDP_TXCOMP) { /* puts("TX complete"); */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[0],0, AT91C_UDP_TXCOMP); if (usb_flags & USB_FLAG_ADDRESS_PENDING) { *AT91C_UDP_FADDR = AT91C_UDP_FEN | LOW_BYTE(usb_setup_buffer.wValue); *AT91C_UDP_GLBSTATE |= AT91C_UDP_FADDEN; usb_flags &= ~USB_FLAG_ADDRESS_PENDING; printf("Address changed: %d\n", *AT91C_UDP_FADDR & 0x7f); } else { if(usb_ctrl_send_pos) { write_ctrl(); } } }}voidusb_epx_int(){ unsigned int ep_index; /* Handle enabled interrupts */ unsigned int int_status = *AT91C_UDP_ISR & *AT91C_UDP_IMR; for (ep_index = 0; ep_index < NUM_EP-1; ep_index++) { volatile USBEndpoint *ep = &usb_endpoints[ep_index]; unsigned int ep_num = EP_HW_NUM(ep->addr); unsigned int ep_mask; if (ep->addr != 0) { /* skip if not configured */ ep_mask = 1<<ep_num; if (int_status & ep_mask) { unsigned int status; status = AT91C_UDP_CSR[ep_num];#if 0 printf("EP %d status: %08x\n", ep->addr, status);#endif if (status & AT91C_UDP_STALLSENT) { /* Acknowledge */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[ep_num],0, AT91C_UDP_STALLSENT); } if (status & AT91C_UDP_TXCOMP) { UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[ep_num],0, AT91C_UDP_TXCOMP); ep->flags &= ~USB_EP_FLAGS_TRANSMITTING; if (ep->buf_len > 0) { write_buffered_endpoint(ep); /* Tell the application that there's more room in the buffer */ usb_endpoint_events[ep_num] |= USB_EP_EVENT_IN; notify_process(USB_EVENT_EP(ep_num)); } } if (status & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) { unsigned char read_cnt; read_cnt = read_buffered_endpoint(ep); if (read_cnt == 0) { *AT91C_UDP_IDR = 1<<ep_num; ep->flags |= USB_EP_FLAGS_RECV_BLOCKED; } else { if (status & AT91C_UDP_RX_DATA_BK1) { /* Ping-pong */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[ep_num],0, (ep->flags & USB_EP_FLAGS_BANK_1_RECV_NEXT) ? AT91C_UDP_RX_DATA_BK1 : AT91C_UDP_RX_DATA_BK0); ep->flags ^= USB_EP_FLAGS_BANK_1_RECV_NEXT; } else { /* Ping-pong or single buffer */ UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[ep_num],0, AT91C_UDP_RX_DATA_BK0); ep->flags |= USB_EP_FLAGS_BANK_1_RECV_NEXT; } } usb_endpoint_events[ep_num] |= USB_EP_EVENT_OUT; notify_process(ep_mask); } } } }}/* Clear usb events from non-interrupt code */voidusb_clear_events(unsigned events){ /* Disable allUSB events */ *AT91C_AIC_IDCR = (1 << AT91C_ID_UDP); usb_events &= ~events; /* Reenable interrupt */ *AT91C_AIC_IECR = (1 << AT91C_ID_UDP);}voidusb_clear_ep_events(unsigned int ep, unsigned int events){ /* Disable all USB events */ *AT91C_AIC_IDCR = (1 << AT91C_ID_UDP); usb_endpoint_events[ep] &= ~events; /* Reenable interrupt */ *AT91C_AIC_IECR = (1 << AT91C_ID_UDP);}voidusb_set_address(){ usb_flags |= USB_FLAG_ADDRESS_PENDING; /* The actual setting of the address is done when the status packet is sent. */}static voidsetup_endpoint(unsigned char addr, unsigned char *buffer, unsigned int buf_size, unsigned int type) { volatile USBEndpoint *ep; /* Check if the address points to an existing endpoint */ if (EP_INDEX(addr) >= (sizeof(usb_endpoints)/sizeof(usb_endpoints[0]))) { return; } ep = &usb_endpoints[EP_INDEX(addr)]; ep->addr = addr; ep->buf_size_mask = buf_size - 1; ep->buffer = buffer; ep->buf_len = 0; ep->buf_pos = 0; ep->status = 0; *AT91C_UDP_IDR = 1<<EP_HW_NUM(addr); { unsigned int ep_num = EP_HW_NUM(addr); UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[ep_num], type | AT91C_UDP_EPEDS, AT91C_UDP_EPTYPE | AT91C_UDP_EPEDS); } *AT91C_UDP_IER = 1<<EP_HW_NUM(addr);}voidusb_setup_bulk_endpoint(unsigned char addr, unsigned char *buffer, unsigned int buf_size){ setup_endpoint(addr, buffer, buf_size, (addr & 0x80) ? AT91C_UDP_EPTYPE_BULK_IN :AT91C_UDP_EPTYPE_BULK_OUT);}voidusb_setup_interrupt_endpoint(unsigned char addr, unsigned char *buffer, unsigned int buf_size){ setup_endpoint(addr, buffer, buf_size, (addr & 0x80) ? AT91C_UDP_EPTYPE_INT_IN :AT91C_UDP_EPTYPE_INT_OUT);}voidusb_disable_endpoint(unsigned char addr){ /* Check if the address points to an existing endpoint */ if (EP_INDEX(addr) >= (sizeof(usb_endpoints)/sizeof(usb_endpoints[0]))) { return; } *AT91C_UDP_IDR = 1<<EP_HW_NUM(addr); UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[EP_HW_NUM(addr)], 0, AT91C_UDP_EPEDS); usb_endpoints[EP_INDEX(addr)].addr = 0;}static voidinit_ep(volatile USBEndpoint *ctxt){ ctxt->addr = 0; ctxt->buf_size_mask = 0; ctxt->buf_len = 0; ctxt->buf_pos = 0; ctxt->buffer = 0; ctxt->status = 0; ctxt->flags = 0;}voidusb_init_endpoints(){ unsigned int i; for (i = 0; i < NUM_EP-1; i++) { init_ep(&usb_endpoints[i]); }}volatile USBEndpoint*usb_find_endpoint(unsigned char epaddr){ if (EP_INDEX(epaddr) >= NUM_EP - 1) return 0; return &usb_endpoints[EP_INDEX(epaddr)];}voidusb_halt_endpoint(unsigned char ep_addr, unsigned int halt){ *AT91C_UDP_IDR = 1<<EP_HW_NUM(ep_addr); if (halt) { UDP_SET_EP_CTRL_FLAGS(&AT91C_UDP_CSR[EP_HW_NUM(ep_addr)], AT91C_UDP_FORCESTALL, AT91C_UDP_FORCESTALL); usb_endpoints[EP_INDEX(ep_addr)].status |= 0x01; } else { *AT91C_UDP_RSTEP = 1<<EP_HW_NUM(ep_addr); usb_endpoints[EP_INDEX(ep_addr)].status &= ~0x01; } *AT91C_UDP_IER = 1<<EP_HW_NUM(ep_addr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -