// USB Endpoint Interrupt - endpoint 0 is handled here. The // other endpoints are manipulated by the user-callable // functions, and the start-of-frame interrupt. // void usb_gamepad_ISR_USB_COM_vect() { uint8_t intbits; const uint8_t *list; const uint8_t *cfg; uint8_t i, n, len, en; uint8_t bmRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; uint16_t desc_val; const uint8_t *desc_addr; uint8_t desc_length; UENUM = 0; intbits = UEINTX; if (intbits & (1<<RXSTPI)) { bmRequestType = UEDATX; bRequest = UEDATX; wValue = UEDATX; wValue |= (UEDATX << 8); wIndex = UEDATX; wIndex |= (UEDATX << 8); wLength = UEDATX; wLength |= (UEDATX << 8); UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); if (bRequest == GET_DESCRIPTOR) { list = (const uint8_t *)descriptor_list; for (i=0; ; i++) { if (i >= NUM_DESC_LIST) { UECONX = (1<<STALLRQ)|(1<<EPEN); //stall return; } desc_val = pgm_read_word(list); if (desc_val != wValue) { list += sizeof(struct descriptor_list_struct); continue; } list += 2; desc_val = pgm_read_word(list); if (desc_val != wIndex) { list += sizeof(struct descriptor_list_struct)-2; continue; } list += 2; desc_addr = (const uint8_t *)pgm_read_word(list); list += 2; desc_length = pgm_read_byte(list); break; } len = (wLength < 256) ? wLength : 255; if (len > desc_length) len = desc_length; do { // wait for host ready for IN packet do { i = UEINTX; } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); if (i & (1<<RXOUTI)) return; // abort // send IN packet n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; for (i = n; i; i--) { UEDATX = pgm_read_byte(desc_addr++); } len -= n; usb_send_in(); } while (len || n == ENDPOINT0_SIZE); return; } if (bRequest == SET_ADDRESS) { usb_send_in(); usb_wait_in_ready(); UDADDR = wValue | (1<<ADDEN); return; } if (bRequest == SET_CONFIGURATION && bmRequestType == 0) { usb_configuration = wValue; usb_send_in(); cfg = endpoint_config_table; for (i=1; i<5; i++) { UENUM = i; en = pgm_read_byte(cfg++); UECONX = en; if (en) { UECFG0X = pgm_read_byte(cfg++); UECFG1X = pgm_read_byte(cfg++); } } UERST = 0x1E; UERST = 0; return; } if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) { usb_wait_in_ready(); UEDATX = usb_configuration; usb_send_in(); return; } if (bRequest == GET_STATUS) { usb_wait_in_ready(); i = 0; #ifdef SUPPORT_ENDPOINT_HALT if (bmRequestType == 0x82) { UENUM = wIndex; if (UECONX & (1<<STALLRQ)) i = 1; UENUM = 0; } #endif UEDATX = i; UEDATX = 0; usb_send_in(); return; } #ifdef SUPPORT_ENDPOINT_HALT if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) && bmRequestType == 0x02 && wValue == 0) { i = wIndex & 0x7F; if (i >= 1 && i <= MAX_ENDPOINT) { usb_send_in(); UENUM = i; if (bRequest == SET_FEATURE) { UECONX = (1<<STALLRQ)|(1<<EPEN); } else { UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN); UERST = (1 << i); UERST = 0; } return; } } #endif if (wIndex == GAMEPAD1_INTERFACE) { if (bmRequestType == 0xA1) { if (bRequest == HID_GET_REPORT) { usb_wait_in_ready(); send_gamepad1_report(); usb_send_in(); return; } if (bRequest == HID_GET_IDLE) { usb_wait_in_ready(); UEDATX = gamepad1_idle_config; usb_send_in(); return; } if (bRequest == HID_GET_PROTOCOL) { usb_wait_in_ready(); UEDATX = gamepad1_protocol; usb_send_in(); return; } } if (bmRequestType == 0x21) { // we have no out report so this shouldn't happen /* if (bRequest == HID_SET_REPORT) { */ /* usb_wait_receive_out(); */ /* keyboard_leds = UEDATX; */ /* usb_ack_out(); */ /* usb_send_in(); */ /* return; */ /* } */ if (bRequest == HID_SET_IDLE) { gamepad1_idle_config = (wValue >> 8); gamepad1_idle_count = 0; usb_send_in(); return; } if (bRequest == HID_SET_PROTOCOL) { gamepad1_protocol = wValue; usb_send_in(); return; } } }
static inline void endpoint0_isr(void) { uint8_t intbits; const uint8_t *list; const uint8_t *cfg; uint8_t i, n, len, en; uint8_t bmRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; uint16_t desc_val; const uint8_t *desc_addr; uint8_t desc_length; UENUM = 0; intbits = UEINTX; if (intbits & (1<<RXSTPI)) { bmRequestType = UEDATX; bRequest = UEDATX; read_word_lsbfirst(wValue, UEDATX); read_word_lsbfirst(wIndex, UEDATX); read_word_lsbfirst(wLength, UEDATX); UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); if (bRequest == GET_DESCRIPTOR) { list = (const uint8_t *)descriptor_list; for (i=0; ; i++) { if (i >= NUM_DESC_LIST) { UECONX = (1<<STALLRQ)|(1<<EPEN); //stall return; } pgm_read_word_postinc(desc_val, list); if (desc_val != wValue) { list += sizeof(struct descriptor_list_struct)-2; continue; } pgm_read_word_postinc(desc_val, list); if (desc_val != wIndex) { list += sizeof(struct descriptor_list_struct)-4; continue; } pgm_read_word_postinc(desc_addr, list); desc_length = pgm_read_byte(list); break; } len = (wLength < 256) ? wLength : 255; if (len > desc_length) len = desc_length; list = desc_addr; do { // wait for host ready for IN packet do { i = UEINTX; } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); if (i & (1<<RXOUTI)) return; // abort // send IN packet n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; for (i = n; i; i--) { pgm_read_byte_postinc(UEDATX, list); } len -= n; usb_send_in(); } while (len || n == ENDPOINT0_SIZE); return; } if (bRequest == SET_ADDRESS) { usb_send_in(); usb_wait_in_ready(); UDADDR = wValue | (1<<ADDEN); return; } if (bRequest == SET_CONFIGURATION && bmRequestType == 0) { usb_configuration = wValue; debug_flush_timer = 0; usb_send_in(); cfg = endpoint_config_table; for (i=1; i<NUM_ENDPOINTS; i++) { UENUM = i; pgm_read_byte_postinc(en, cfg); UECONX = en; if (en) { pgm_read_byte_postinc(UECFG0X, cfg); pgm_read_byte_postinc(UECFG1X, cfg); } } UERST = 0x1E; UERST = 0; UENUM = DISK_RX_ENDPOINT; UEIENX = (1<<RXOUTE); return; } if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) { usb_wait_in_ready(); UEDATX = usb_configuration; usb_send_in(); return; } if (bRequest == GET_STATUS) { usb_wait_in_ready(); i = 0; if (bmRequestType == 0x82) { UENUM = wIndex; if (UECONX & (1<<STALLRQ)) i = 1; UENUM = 0; } UEDATX = i; UEDATX = 0; usb_send_in(); return; } if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) && bmRequestType == 0x02 && wValue == 0) { i = wIndex & 0x7F; if (i >= 1 && i <= MAX_ENDPOINT) { usb_send_in(); UENUM = i; if (bRequest == SET_FEATURE) { UECONX = (1<<STALLRQ)|(1<<EPEN); } else { UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN); UERST = (1 << i); UERST = 0; if (i == DISK_TX_ENDPOINT) { UEIENX = (1<<TXINE); } } return; } } if (wIndex == KEYBOARD_INTERFACE) { if (bmRequestType == 0xA1) { if (bRequest == HID_GET_REPORT) { usb_wait_in_ready(); UEDATX = keyboard_modifier_keys; UEDATX = 0; for (i=0; i<6; i++) { UEDATX = keyboard_keys[i]; } usb_send_in(); return; } if (bRequest == HID_GET_IDLE) { usb_wait_in_ready(); UEDATX = keyboard_idle_config; usb_send_in(); return; } if (bRequest == HID_GET_PROTOCOL) { usb_wait_in_ready(); UEDATX = keyboard_protocol; usb_send_in(); return; } } if (bmRequestType == 0x21) { if (bRequest == HID_SET_REPORT) { usb_wait_receive_out(); keyboard_leds = UEDATX; usb_ack_out(); usb_send_in(); return; } if (bRequest == HID_SET_IDLE) { keyboard_idle_config = (wValue >> 8); keyboard_idle_count = 0; //usb_wait_in_ready(); usb_send_in(); return; } if (bRequest == HID_SET_PROTOCOL) { keyboard_protocol = wValue; //usb_wait_in_ready(); usb_send_in(); return; } } }