// see pic18_usb.h for documentation int1 usb_flush_in(int8 endpoint, int16 len, USB_DTS_BIT tgl) { unsigned int8 i; debug_usb(debug_putc,"\r\nPUT %X %U %LU",endpoint, tgl, len); if (usb_tbe(endpoint)) { EP_BDxCNT_I(endpoint)=len; debug_display_ram(len, EP_BDxADR_I(endpoint)); #if USB_IGNORE_TX_DTS i=0x80; #else if (tgl == USB_DTS_TOGGLE) { i = EP_BDxST_I(endpoint); if (bit_test(i,6)) tgl = USB_DTS_DATA0; //was DATA1, goto DATA0 else tgl = USB_DTS_DATA1; //was DATA0, goto DATA1 } else if (tgl == USB_DTS_USERX) { i = EP_BDxST_O(endpoint); if (bit_test(i,6)) tgl = USB_DTS_DATA1; else tgl = USB_DTS_DATA0; } if (tgl == USB_DTS_DATA1) i=0xC8; //DATA1, UOWN else //if (tgl == USB_DTS_DATA0) i=0x88; //DATA0, UOWN #endif //set BC8 and BC9 if (bit_test(len,8)) {bit_set(i,0);} if (bit_test(len,9)) {bit_set(i,1);} debug_usb(debug_putc, " %X", i); EP_BDxST_I(endpoint) = i;//save changes //putc('!'); return(1); } else { //putc('_'); debug_usb(debug_putc,"\r\nPUT ERR"); } return(0); }
void usb_isr_rst(void) { debug_usb(debug_putc,"R"); UEIR = 0; UIR = 0; UEIE = 0x9F; UIE = STANDARD_INTS & ~__USB_UIF_ACTIVE; UADDR = 0; usb_disable_endpoints(); usb_token_reset(); UEP(0) = ENDPT_CONTROL | 0x10; while (UIR_TRN) { usb_clear_trn(); } UCON_PKTDIS = 0; //SIE token and packet processing enabled usb_init_ep0_setup(); usb_state = USB_STATE_DEFAULT; //put usb mcu into default state }
// SOF interrupt not handled. user must add this depending on application void usb_isr_sof(void) { debug_usb(debug_putc, "\r\nSOF"); //UIR_SOF = 0; UIR &= ~(1 << BIT_SOF); }
void usb_isr_uerr(void) { #if USB_USE_ERROR_COUNTER int ints; #endif debug_usb(debug_putc,"E %X ",UEIR); #if USB_USE_ERROR_COUNTER ints=UEIR & UEIE; //mask off the flags with the ones that are enabled if ( bit_test(ints,0) ) { //increment pid_error counter debug_usb(debug_putc,"PID "); ERROR_COUNTER[0]++; } if ( bit_test(ints,1) ) { //increment crc5 error counter debug_usb(debug_putc,"CRC5 "); ERROR_COUNTER[1]++; } if ( bit_test(ints,2) ) { //increment crc16 error counter debug_usb(debug_putc,"CRC16 "); ERROR_COUNTER[2]++; } if ( bit_test(ints,3) ) { //increment dfn8 error counter debug_usb(debug_putc,"DFN8 "); ERROR_COUNTER[3]++; } if ( bit_test(ints,4) ) { //increment bto error counter debug_usb(debug_putc,"BTO "); ERROR_COUNTER[4]++; } if ( bit_test(ints,7) ) { //increment bts error counter debug_usb(debug_putc,"BTS "); ERROR_COUNTER[5]++; } #endif UEIR = 0; //UIR_UERR = 0; UIR &= ~(1 << BIT_UERR); }
void ep0_init(void) { debug_usb("ep0_init\r\n"); init_dfu(); ep0_state = WAIT_SETUP; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)&SetupBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE | BDS_DAT0 | BDS_DTSEN; EP_IN_BD(0).Stat.uc = BDS_UCPU; UEP0 = EPINEN_EN | EPOUTEN_EN | EPHSHK_EN; }
void usb_isr_uidle(void) { debug_usb(debug_putc, "I"); UIE_ACTV = 1; //enable activity interrupt flag. (we are now suspended until we get an activity interrupt. nice) //UIR_IDLE = 0; //clear idle interrupt flag UIR &= ~(1 << BIT_IDLE); UCON_SUSPND = 1; //set suspend. we are now suspended }
// see usb_hw_layer.h for documentation void usb_task(void) { #if defined(USB_ISR_POLLING) if (interrupt_active(INT_USB)) { usb_isr(); } #endif if (usb_attached()) { if (UCON_USBEN==0) { debug_usb(debug_putc, "\r\n\nUSB TASK: ATTACH"); usb_attach(); } } else { if (UCON_USBEN==1) { debug_usb(debug_putc, "\r\n\nUSB TASK: DE-ATTACH"); usb_detach(); } } if ((usb_state == USB_STATE_ATTACHED)&&(!UCON_SE0)) { UIR=0; UIE=0; #if !defined(USB_ISR_POLLING) enable_interrupts(INT_USB); enable_interrupts(GLOBAL); #endif UIE=__USB_UIF_IDLE | __USB_UIF_RESET; //enable IDLE and RESET USB ISR usb_state=USB_STATE_POWERED; debug_usb(debug_putc, "\r\n\nUSB TASK: POWERED"); } }
void usb_isr_activity(void) { debug_usb(debug_putc, "A"); UCON_SUSPND = 0; //turn off low power suspending UIE_ACTV = 0; //clear activity interupt enabling while(UIR_ACTV) { //UIR_ACTV = 0; UIR &= ~(1 << BIT_ACTV); } }
void usb_isr_stall(void) { debug_usb(debug_putc, "S"); if (bit_test(UEP(0),0)) { usb_init_ep0_setup(); bit_clear(UEP(0), 0); } //UIR_STALL = 0; UIR &= ~(1 << BIT_STALL); }
// see pic18_usb.h for documentation void usb_flush_out(int8 endpoint, USB_DTS_BIT tgl) { unsigned int8 i; unsigned int16 len; #if USB_IGNORE_RX_DTS if (tgl == USB_DTS_STALL) { debug_usb(debug_putc, '*'); EP_BDxCNT_O(endpoint) = 0x84; EP_BDxST_I(endpoint) = 0x84; return; } else i=0x80; #else i = EP_BDxST_O(endpoint); if (tgl == USB_DTS_TOGGLE) { if (bit_test(i,6)) tgl = USB_DTS_DATA0; //was DATA1, goto DATA0 else tgl = USB_DTS_DATA1; //was DATA0, goto DATA1 } if (tgl == USB_DTS_STALL) { i = 0x84; EP_BDxST_I(endpoint) = 0x84; //stall both in and out endpoints } else if (tgl == USB_DTS_DATA1) i = 0xC8; //DATA1, UOWN else //if (tgl == USB_DTS_DATA0) i = 0x88; //DATA0, UOWN #endif //bit_clear(__usb_kbhit_status,endpoint); len = usb_ep_rx_size[endpoint]; EP_BDxCNT_O(endpoint) = len; if (bit_test(len,8)) {bit_set(i,0);} if (bit_test(len,9)) {bit_set(i,1);} EP_BDxST_O(endpoint) = i; }
// see usb_hw_layer.h for documentation int1 usb_put_packet(unsigned int8 endpoint, unsigned int8 * ptr, unsigned int16 len, USB_DTS_BIT tgl) { unsigned int8 * buff_add; if (usb_tbe(endpoint)) { buff_add = EP_BDxADR_I(endpoint); memcpy(buff_add, ptr, len); return(usb_flush_in(endpoint, len, tgl)); } else { //putc('-'); //printf("%X", EP_BDxST_I(endpoint)); debug_usb(debug_putc,"\r\nPUT ERR"); } return(0); }
void usb_isr(void) { unsigned int8 TRNAttempts; clear_interrupt(INT_USB); if (usb_state == USB_STATE_DETACHED) return; //should never happen, though if (UIR) { debug_usb(debug_putc,"\r\n\n[%X] ",UIR); //activity detected. (only enable after sleep) if (UIR_ACTV && UIE_ACTV) {usb_isr_activity();} if (UCON_SUSPND) return; if (UIR_STALL && UIE_STALL) {usb_isr_stall();} //a stall handshake was sent if (UIR_UERR && UIE_UERR) {usb_isr_uerr();} //error has been detected if (UIR_URST && UIE_URST) {usb_isr_rst();} //usb reset has been detected if (UIR_IDLE && UIE_IDLE) {usb_isr_uidle();} //idle time, we can go to sleep if (UIR_SOF && UIE_SOF) {usb_isr_sof();} TRNAttempts = 0; do { if (UIR_TRN && UIE_TRN) { USTATCopy = U1STAT; usb_clear_trn(); usb_isr_tok_dne(); } else break; } while (TRNAttempts++ < 4); } }
u8 ep0_usb_std_request(void) { // hack to avoid register allocation bug in sdcc static u8 unknown_request; unknown_request = FALSE; if (SetupBuffer.request_type != STANDARD) { return FALSE; } switch (SetupBuffer.bRequest) { case CLEAR_FEATURE: debug_usb("CLEAR_FEATURE\n"); // TODO not implemented break; case GET_CONFIGURATION: debug_usb("GET_CONFIGURATION\n"); sourceData = &GET_ACTIVE_CONFIGURATION(); num_bytes_to_be_send = 1; break; case GET_DESCRIPTOR: debug_usb("GET_DESCRIPTOR\n"); switch (SetupBuffer.bDescType) { case DEVICE_DESCRIPTOR: debug_usb("device\n"); sourceData = (u8 *) device_descriptor; num_bytes_to_be_send = device_descriptor->bLength; break; case CONFIGURATION_DESCRIPTOR: debug_usb("configuration\n"); sourceData = configuration_descriptor[SetupBuffer.bDescIndex]; num_bytes_to_be_send = ((USB_Configuration_Descriptor*) sourceData)->wTotalLength; break; case STRING_DESCRIPTOR: debug_usb("string\n"); sourceData = string_descriptor[SetupBuffer.bDescIndex]; num_bytes_to_be_send = sourceData[0]; break; default: debug_usb("unknown\n"); // This is required to stall the DEVICE_QUALIFIER request unknown_request = TRUE; break; } break; case GET_INTERFACE: debug_usb("GET_INTERFACE\n"); // TODO not implemented break; case GET_STATUS: debug_usb("GET_STATUS\n"); // TODO not implemented break; case SET_ADDRESS: debug_usb("SET_ADDRESS\n"); SET_DEVICE_STATE(ADDRESS_PENDING_STATE) ; break; case SET_CONFIGURATION: debug_usb("SET_CONFIGURATION\n"); // is this configuration valid ? if (device_descriptor->bNumConfigurations >= SetupBuffer.bConfigurationValue) { coming_cfg = SetupBuffer.bConfigurationValue; SET_DEVICE_STATE(CONFIGURATION_PENDING_STATE); } else // invalid configuration { debug_usb("invalid configuration\n"); // Reply with a request error (STALL) unknown_request = TRUE; } break; case SET_FEATURE: debug_usb("SET_FEATURE\n"); // TODO not implemented break; case SET_INTERFACE: debug_usb("SET_INTERFACE\n"); // TODO not implemented break; // case SYNCH_FRAME: // only for isochronous synchronization // break; default: unknown_request = TRUE; break; } return !unknown_request; }
void ep0_setup(void) { debug_usb("ep0_setup\n"); ep0_state = WAIT_SETUP; num_bytes_to_be_send = 0; if (ep0_usb_std_request()) { UCONbits.PKTDIS = 0; if (SetupBuffer.data_transfer_direction == DEVICE_TO_HOST) { ep0_state = WAIT_IN; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)&SetupBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE; EP_IN_BD(0).ADR = (u8 __data *)InBuffer; if (SetupBuffer.wLength < num_bytes_to_be_send) { num_bytes_to_be_send = SetupBuffer.wLength; } debug2_usb("bytes to send: %d\r\n", num_bytes_to_be_send); fill_in_buffer(0, &sourceData, EP0_BUFFER_SIZE, &num_bytes_to_be_send); EP_IN_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; } else // HOST_TO_DEVICE { ep0_state = WAIT_OUT; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)InBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; EP_IN_BD(0).Cnt = 0; EP_IN_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; } } else if (ep0_dfu_request()) { UCONbits.PKTDIS = 0; if (SetupBuffer.data_transfer_direction == DEVICE_TO_HOST) { ep0_state = WAIT_DFU_IN; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)&SetupBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE; EP_IN_BD(0).ADR = (u8 __data *)InBuffer; if (SetupBuffer.wLength < num_bytes_to_be_send) { num_bytes_to_be_send = SetupBuffer.wLength; } debug2_usb("bytes to send: %d\n", num_bytes_to_be_send); // debug2("2: %x\n", sourceData[0]); fill_in_buffer(0, &sourceData, EP0_BUFFER_SIZE, &num_bytes_to_be_send); EP_IN_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; } else // HOST_TO_DEVICE { ep0_state = WAIT_DFU_OUT; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)InBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; EP_IN_BD(0).Cnt = 0; EP_IN_BD(0).Stat.uc = BDS_USIE | BDS_DAT1 | BDS_DTSEN; } } else { debug_usb("unknown request\n"); UCONbits.PKTDIS = 0; EP_OUT_BD(0).Cnt = EP0_BUFFER_SIZE; EP_OUT_BD(0).ADR = (u8 __data *)&SetupBuffer; EP_OUT_BD(0).Stat.uc = BDS_USIE | BDS_BSTALL; EP_IN_BD(0).Stat.uc = BDS_USIE | BDS_BSTALL; } }
void usb_isr_tok_dne(void) { unsigned int8 en; en = USTATCopy>>3; debug_usb(debug_putc, "T "); debug_usb(debug_putc, "%X ", USTATCopy); if (USTATCopy == USTAT_OUT_SETUP_E0) { //new out or setup token in the buffer int8 pidKey; debug_usb(debug_putc,"%X ", EP_BDxST_O(0)); pidKey = EP_BDxST_O(0) & 0x3C; //save PID EP_BDxST_O(0) &= 0x43; //clear pid, prevent bdstal/pid confusion if (pidKey == USB_PIC_PID_SETUP) { if ((EP_BDxST_I(0) & 0x80) != 0x00) EP_BDxST_I(0)=0; // return the in buffer to us (dequeue any pending requests) debug_usb(debug_putc,"(%U) ", EP_BDxCNT_O(0)); debug_display_ram(EP_BDxCNT_O(0), usb_ep0_rx_buffer); usb_isr_tok_setup_dne(); UCON_PKTDIS=0; // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit //if setup_0_tx_size==0xFF - stall ep0 (unhandled request) (see usb_request_stall()) //if setup_0_tx_size==0xFE - get EP0OUT ready for a data packet, leave EP0IN alone (see usb_request_get_data()) //else setup_0_tx_size=size of response, get EP0OUT ready for a setup packet, mark EPOIN ready for transmit (see usb_request_send_response()) if (__setup_0_tx_size == 0xFF) usb_flush_out(0, USB_DTS_STALL); else { usb_flush_out(0, USB_DTS_TOGGLE); if (__setup_0_tx_size != 0xFE) usb_flush_in(0 ,__setup_0_tx_size, USB_DTS_USERX); } //why was this here? //UCON_PKTDIS=0; // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit } else if (pidKey == USB_PIC_PID_OUT) { usb_isr_tok_out_dne(0); usb_flush_out(0, USB_DTS_TOGGLE); if ((__setup_0_tx_size!=0xFE) && (__setup_0_tx_size!=0xFF)) { usb_flush_in(0,__setup_0_tx_size,USB_DTS_DATA1); //send response (usually a 0len) } } else { debug_usb(debug_putc, "!!! "); } } else if (USTATCopy == USTAT_IN_E0) { //pic -> host transfer completed //EP_BDxST_I(0) = EP_BDxST_I(0) & 0xC3; //clear up any BDSTAL confusion __setup_0_tx_size = 0xFF; usb_isr_tok_in_dne(0); if (__setup_0_tx_size!=0xFF) usb_flush_in(0, __setup_0_tx_size, USB_DTS_TOGGLE); else { //usb_init_ep0_setup(); //REMOVED JUN/9/2009 } } else { if (!bit_test(USTATCopy, 2)) { //EP_BDxST_O(en) = EP_BDxST_O(en) & 0xC3; //clear up any BDSTAL confusion usb_isr_tok_out_dne(en); } else { //EP_BDxST_I(en) = EP_BDxST_I(en) & 0xC3; //clear up any BDSTAL confusion usb_isr_tok_in_dne(en); } } }