#include #include #include int avr_usb_ep_size[] = { 8, 16, 32, 64, 128, 256, 512, 0 }; int usb_ll_ep_find_size_index(int minSize){ int n; for (n=0;n<7;n++){ if (avr_usb_ep_size[n] >= minSize){ return n; }; }; // In Case no useful size available, we try a fall back of 32bytes return 0x02; }; /** * @brief select endpoint to be handled by the usb_ll_endpoint_X functions * @param endpoint Number of endpoint * @return 0 on Success */ int usb_ll_endpoint_select(uint8_t endpoint){ UENUM = endpoint; return 0; }; /** * @brief read up to bytes from endpoint fifo * usb_ll_endpoint_select(..) must have been called before * @param buffer Pointer to buffer to write data to * @param len maximum buffer size * @return number of bytes that have been read from hardware */ int usb_ll_endpoint_read(uint8_t *buffer,int len){ int p = 0; while (UEBCX && (p < len)){ buffer[p++] = UEDATX; }; return p; }; /** * @brief write up to bytes to endpoint fifo * usb_ll_endpoint_select(..) must have been called before * @param buffer Pointer to buffer to read data from * @param len buffer size * @return number of bytes that have been written to hardware */ int usb_ll_endpoint_write(uint8_t *buffer,int len){ int p = 0; int epsize = avr_usb_ep_size[ (UECFG1X>>EPSIZE0)&0x07 ]; while ((p < len) && (UEBCX < epsize) ){ UEDATX = buffer[p++]; }; return p; }; void usb_irq_endpoint_txin(uint8_t endpoint) { uint8_t ep_type; usb_ll_endpoint_select( endpoint ); ep_type = (UECFG0X >> EPTYPE0) & 0x03; if ( (endpoint == 0) && (usb_device._addr_setup)){ if (usb_device.endpoints[ endpoint ].buffer){ usb_device.endpoints[ endpoint ].buffer = NULL; } else { //UDADDR = usb_device._addr_setup; UDADDR |= _BV(ADDEN); usb_device._addr_setup = 0; usb_device.state.Address = 1; }; } else if (usb_device.endpoints[ endpoint ].buffer){ int nSend = usb_device.endpoints[ endpoint ].blen - usb_device.endpoints[ endpoint ].bpos; int nSent = usb_ll_endpoint_write( &(usb_device.endpoints[ endpoint ].buffer[ usb_device.endpoints[ endpoint ].bpos ]), nSend); usb_device.endpoints[ endpoint ].bpos += nSent; } else { if (ep_type == USB_EP_CONTROL){ usb_ll_clear_irq( USB_IRQ_TXIN ); usb_ll_disable_irq( USB_IRQ_TXIN ); usb_ll_disable_irq( USB_IRQ_RXOUT ); } else { usb_ll_disable_irq( USB_IRQ_TXIN ); }; return; }; switch (ep_type){ case USB_EP_CONTROL: usb_ll_clear_irq( USB_IRQ_TXIN ); break; case USB_EP_INTERRUPT: case USB_EP_BULK: case USB_EP_ISOCHRONOUS: if (UEBCX){ usb_ll_clear_irq( USB_IRQ_TXIN ); UEINTX &= ~_BV(FIFOCON); } else { usb_ll_disable_irq( USB_IRQ_TXIN ); }; break; }; }; void usb_irq_endpoint_rxout(uint8_t endpoint) { uint8_t ep_type; usb_ll_endpoint_select( endpoint ); ep_type = (UECFG0X >> EPTYPE0) & 0x03; if ((ep_type == USB_EP_CONTROL)&&((usb_device.endpoints[ endpoint ].request->bmRequestType & 0x80)) ){ usb_device.endpoints[ endpoint ].buffer = NULL; } else if (usb_device.endpoints[ endpoint ].buffer){ int nToRead = usb_device.endpoints[ endpoint ].blen - usb_device.endpoints[ endpoint ].bpos; int nRead = usb_ll_endpoint_read( &(usb_device.endpoints[ endpoint ].buffer[ usb_device.endpoints[ endpoint ].bpos ]), nToRead); usb_device.endpoints[ endpoint ].bpos += nRead; } else { usb_ll_disable_irq( USB_IRQ_RXOUT ); return; }; switch (ep_type){ case USB_EP_CONTROL: usb_ll_clear_irq( USB_IRQ_RXOUT ); break; case USB_EP_INTERRUPT: case USB_EP_BULK: case USB_EP_ISOCHRONOUS: if (!UEBCX){ usb_ll_clear_irq( USB_IRQ_RXOUT ); UEINTX &= ~_BV(FIFOCON); } else { usb_ll_disable_irq( USB_IRQ_RXOUT ); }; break; }; }; void usb_irq_endpoint_nakin(uint8_t endpoint){ uint8_t ep_type; usb_ll_endpoint_select( endpoint ); ep_type = (UECFG0X >> EPTYPE0) & 0x03; if (ep_type == USB_EP_CONTROL){ if (!(usb_device.endpoints[ endpoint ].request->bmRequestType & 0x80 )) { usb_ll_clear_irq( USB_IRQ_TXIN ); usb_ll_disable_irq( USB_IRQ_RXOUT ); }; }; usb_ll_clear_irq( USB_IRQ_NAKIN ); }; void usb_irq_endpoint_setup (uint8_t endpoint){ usb_ll_endpoint_t* ep = &(usb_device.endpoints[endpoint]); int n; if (ep && ep->request){ n = usb_ll_endpoint_read( (uint8_t*)ep->request, sizeof( usb_device_request_t ) ); if (n == sizeof( usb_device_request_t )){ if (usb_ll_setup_request( endpoint, ep->request ) < 0){ avr_usb_endpoint_stall_request(); }; }; }; usb_ll_clear_irq( USB_IRQ_SETUP ); }; void usb_ll_endpoint_disable(int endpoint){ if (endpoint >= MAX_ENDPOINTS) return; usb_ll_endpoint_select(endpoint); UEIENX = 0; UECONX &= ~_BV(EPEN); UECFG0X = 0x00; UECFG1X = 0x00; if (usb_device.endpoints[endpoint].request){ usb_ll_disable_irq( USB_IRQ_SETUP ); free(usb_device.endpoints[endpoint].request); }; usb_device.endpoints[endpoint].cb_setup = NULL; usb_endpoint_unset_buffer( endpoint ); usb_device.endpoints[endpoint].desc = NULL; }; void usb_ll_endpoint_enable (struct usb_standard_endpoint_descriptor* descriptor){ int nEP; if (!descriptor) return; nEP = descriptor->bEndpointAddress & 0x07; if (nEP > MAX_ENDPOINTS) return; usb_ll_endpoint_select(nEP); UECONX &= ~_BV(EPEN); UECONX |= _BV(EPEN); UERST |= _BV(nEP); UERST &= ~_BV(nEP); UEIENX = 0; usb_device.endpoints[nEP].desc = descriptor; UECFG0X = ((descriptor->bEndpointAddress & 0x80) ? 0x01 : 0x00) | ((descriptor->bmAttributes & 0x03) << EPTYPE0); UECFG1X = (usb_ll_ep_find_size_index( descriptor->wMaxPacketSize ) << 4); UECFG1X |= _BV(ALLOC); if ((UECFG0X & (_BV(EPTYPE1)|_BV(EPTYPE0))) == 0){ usb_device.endpoints[nEP].request = malloc( sizeof(usb_device_request_t ) ); usb_ll_enable_irq( USB_IRQ_SETUP ); } else { }; if (UESTA0X & _BV(CFGOK)){ return; } else { return; }; };