//----------------------------------------------------------------------------- void usb_svc_setconfiguration_hook(USB_DRV_INFO drv_info, HANDLE hnd) { USB_DRIVER_DATA* drv_data = drv_info->drv_data; unsigned char cfgnum = hnd->src.as_int; TRACE_USB(" SetCfg(%d)", cfgnum); // If the configuration number if non-zero, the device enters the // Configured state if (cfgnum != 0) { drv_data->usb_state = USBST_DEVICE_CONFIGURED; } // If the configuration number is zero, the device goes back to the Address // state else { drv_data->usb_state = USBST_DEVICE_ADDRESS; // Abort all transfers for(int i= 1; i<USB_NUMENDPOINTS; i++) { usb_hal_ept_reset(drv_info, i); } } drv_data->device.cfgnum = cfgnum; }
void usb_cdc_acm_interface::RequestHandler(const void* drv, const USBGenericRequest *pRequest, HANDLE hnd) { /* Check request code */ switch (pRequest->bRequest) { case CDCRequest_SET_LINE_CODING: TRACE1_USB(" sLineCoding"); if (hnd->tsk_read(&lineCoding, sizeof(lineCoding), USB_SETUP_READ_TOUT)==RES_OK) { //read OK TRACE_USB(" rate=%d", lineCoding.dwDTERate); set_line_coding(drv); usb_svc_send_control_status(hnd); } break; case CDCRequest_GET_LINE_CODING: TRACE1_USB(" gLineCoding"); hnd->tsk_write(&lineCoding, sizeof(lineCoding), USB_SETUP_WRITE_TOUT); break; case CDCRequest_SET_CONTROL_LINE_STATE: { TRACE_USB("sControlLineState(%02x) ", pRequest->wValue); bControlLineState = (uint8_t)pRequest->wValue; set_control_line_state(drv); usb_svc_send_control_status(hnd); break; } default: TRACE_USB(" Unknown cdc acm request(%d)", pRequest->bRequest); usb_svc_stall(hnd); break; } }
void usb_svc_stall_hook(USB_DRV_INFO drv_info, HANDLE hnd) { unsigned char eptnum = hnd->mode.as_bytes[0]; Endpoint *endpoint = &drv_info->drv_data->endpoints[eptnum]; eptnum |= 0x80; // ENDPOINT_DIRECTION_IN // Check that endpoint is in Idle state if (endpoint->state != ENDPOINT_STATE_IDLE) { TRACE_USB(" Stall(%d): locked", eptnum); } else { TRACE_USB(" Stall(%d)", eptnum); usb_hal_stall(drv_info->hw_base, eptnum); } }
//----------------------------------------------------------------------------- void usb_svc_unhalt_hook(USB_DRV_INFO drv_info, HANDLE hnd) { USB_DRIVER_DATA* drv_data = drv_info->drv_data; Udp* pUDP = drv_info->hw_base; unsigned char eptnum = hnd->src.as_int; Endpoint *endpoint = &drv_data->endpoints[eptnum]; TRACE_USB(" Unhalt(%d)", eptnum); if (endpoint->state == ENDPOINT_STATE_HALTED) { // Return endpoint to Idle state endpoint->state = ENDPOINT_STATE_IDLE; // Clear FORCESTALL flag CLEAR_CSR(&pUDP->UDP_CSR[eptnum], UDP_CSR_FORCESTALL); // Reset Endpoint Fifos, beware this is a 2 steps operation pUDP->UDP_RST_EP |= 1 << eptnum; pUDP->UDP_RST_EP &= ~(1 << eptnum); } }
//----------------------------------------------------------------------------- void usb_svc_halt_hook(USB_DRV_INFO drv_info, HANDLE hnd) { USB_DRIVER_DATA* drv_data = drv_info->drv_data; Udp* pUDP = drv_info->hw_base; unsigned int eptnum = hnd->src.as_int; Endpoint *endpoint = &drv_data->endpoints[eptnum]; TRACE_USB(" Halt%d", eptnum); // Check that endpoint is enabled and not already in Halt state if (endpoint->state >= ENDPOINT_STATE_IDLE) { // Abort the current transfer if necessary usb_drv_end_transfers(endpoint, USBD_STATUS_ABORTED); // Put endpoint into Halt state SET_CSR(&pUDP->UDP_CSR[eptnum], UDP_CSR_FORCESTALL); endpoint->state = ENDPOINT_STATE_HALTED; // Enable the endpoint interrupt pUDP->UDP_IER |= 1 << eptnum; } }
//----------------------------------------------------------------------------- void usb_svc_setaddress_hook(USB_DRV_INFO drv_info, HANDLE hnd) { USB_DRIVER_DATA* drv_data = drv_info->drv_data; Udp* pUDP = drv_info->hw_base; unsigned char address = hnd->src.as_int; TRACE_USB(" SetAddr(%d)", address); // Set address pUDP->UDP_FADDR = UDP_FADDR_FEN | address; // If the address is 0, the device returns to the Default state if (address == 0) { pUDP->UDP_GLB_STAT = 0; drv_data->usb_state = USBST_DEVICE_DEFAULT; } // If the address is non-zero, the device enters the Address state else { pUDP->UDP_GLB_STAT = UDP_GLB_STAT_FADDEN; drv_data->usb_state = USBST_DEVICE_ADDRESS; } }
void usbdrv_thread(USB_DRV_INFO drv_info) { CHandle helper; CHandle req_hnd; USBGenericRequest request; bool requested = false; unsigned int sig=0; ALLOCATE_SIGNAL(USB_DRIVER_SIG); helper.tsk_safe_open(drv_info->info.drv_index, 0); helper.tsk_start_command(NULL, 0); req_hnd.tsk_safe_open(drv_info->info.drv_index, USB_DRV_MODE(EPT_0, EPT_0)); while(1) { sig |= tsk_get_signal(SIGNAL_ANY); // 2) get waiting clients if(sig & helper.signal) { HANDLE client; sig ^= helper.signal; helper.res &= ~FLG_SIGNALED; client = (HANDLE)helper.dst.as_voidptr; if(client) { RES_CODE res; res = ((USB_API_FUNC)client->src.as_voidptr)(drv_info, client); if(res & FLG_SIGNALED) { tsk_HND_SET_STATUS(client, res); } } helper.tsk_start_command(NULL, 0); } if(sig & req_hnd.signal) { sig ^= req_hnd.signal; req_hnd.res &= ~FLG_SIGNALED; #if USB_ENABLE_DEVICE TRACE1_USB(" | req:"); if(req_hnd.res == RES_OK) { drv_info->drv_data->device.RequestHandler(drv_info, &request, &req_hnd); } else #endif { TRACE_USB(" res %x", req_hnd.res); tsk_sleep(5); } requested = false; } if(!requested) { #if USB_ENABLE_HOST if(sig == USB_DRIVER_SIG) { if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_CON) { do { sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig); sig &= ~OTG_H_SIG_CON; } while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig)); //wait 1s for connect for(int retries =0; retries <10; ++retries) { if(drv_info->drv_data->otg_flags & USB_OTG_FLG_HOST_RST) break; sig = tsk_wait_signal(USB_DRIVER_SIG, 100); if (sig) break; } if( !(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RST)) { usb_api_otg_off(drv_info, NULL); } } if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RST) { do { sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig); sig &= ~OTG_H_SIG_RST; } while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig)); if(drv_info->drv_data->otg_flags & USB_OTG_FLG_HOST_RST) { RES_CODE res; // Reset requested for(int retries =0; retries <3; ++retries) { tsk_sleep(100); res = usb_host_reset_bus(drv_info, &req_hnd); if( res == RES_OK) break; } // if(res != RES_OK) // usb_api_otg_off(drv_info, NULL); } } if(drv_info->drv_data->otg_h_sig & OTG_H_SIG_RESUME) { do { sig = atomic_fetch((volatile int*)&drv_info->drv_data->otg_h_sig); sig &= ~OTG_H_SIG_RESUME; } while(atomic_store((volatile int*)&drv_info->drv_data->otg_h_sig, sig)); usb_hal_host_resume(drv_info); } sig = 0; } if(drv_info->drv_data->otg_flags & USB_OTG_FLG_DEV_OK) { req_hnd.mode.as_ushort[1] = drv_info->drv_data->drv_state_cnt; #endif req_hnd.tsk_start_read(&request, 8); TRACE_USB_NAME(drv_info); TRACE1_USB(" st req:"); requested = true; #if USB_ENABLE_HOST } #endif } } }
//void NAKEDFUNC usb_irq_service(void) void usb_irq_service(void) { //ISR_ENTRY(); // End interrupt if we are not attached to USB bus //*AT91C_PIOA_SODR = PIN_LED; //TRACE_ALL("@"); if (ISCLEARED(usb_device_state,USB_STATE_ATTACHED)) goto end_of_irq; unsigned char endpoint; unsigned int status = pUDP->UDP_ISR & pUDP->UDP_IMR & ISR_MASK; while( status != 0) { // Start Of Frame (SOF) if (ISSET(status, AT91C_UDP_SOFINT)) { TRACE_USB("SOF "); // Acknowledge interrupt SET(pUDP->UDP_ICR, AT91C_UDP_SOFINT); CLEAR(status, AT91C_UDP_SOFINT); } // Suspend if (ISSET(status,AT91C_UDP_RXSUSP)) { TRACE_USB("Susp "); if (ISCLEARED(usb_device_state,USB_STATE_SUSPENDED)) { // The device enters the Suspended state // MCK + UDPCK must be off // Pull-Up must be connected // Transceiver must be disabled // Enable wakeup SET(pUDP->UDP_IER, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM); // Acknowledge interrupt SET(pUDP->UDP_ICR, AT91C_UDP_RXSUSP); // Set suspended state SET(usb_device_state,USB_STATE_SUSPENDED); // Disable transceiver SET(pUDP->UDP_TXVC, AT91C_UDP_TXVDIS); // Disable master clock AT91C_BASE_PMC->PMC_PCDR |= (1 << AT91C_ID_UDP); // Disable peripheral clock for USB AT91C_BASE_PMC->PMC_SCDR |= AT91C_PMC_UDP; } } // Resume else if (ISSET(status, AT91C_UDP_WAKEUP) || ISSET(status, AT91C_UDP_RXRSM)) { TRACE_USB("Resm "); // The device enters Configured state // MCK + UDPCK must be on // Pull-Up must be connected // Transceiver must be enabled // Powered state // Enable master clock AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_UDP); // Enable peripheral clock for USB AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; // Default state if (ISSET(usb_device_state,USB_STATE_DEFAULT)) { // Enable transceiver CLEAR(pUDP->UDP_TXVC, AT91C_UDP_TXVDIS); } CLEAR(usb_device_state, USB_STATE_SUSPENDED); SET(pUDP->UDP_ICR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP); SET(pUDP->UDP_IDR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM); } // End of bus reset else if (ISSET(status, AT91C_UDP_ENDBUSRES)) { TRACE_USB("\n\n\nEoBres "); // Initialize UDP peripheral device usb_bus_reset_handler(); // Flush and enable the Suspend interrupt SET(pUDP->UDP_ICR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP); // Acknowledge end of bus reset interrupt SET(pUDP->UDP_ICR, AT91C_UDP_ENDBUSRES); } // Endpoint interrupts else { while (status != 0) { // Get endpoint index endpoint = last_set_bit(status); usb_endpoint_handler(endpoint); CLEAR(pUDP->UDP_ICR, (1 << endpoint)); CLEAR(status, 1 << endpoint); } } status = pUDP->UDP_ISR & pUDP->UDP_IMR & ISR_MASK; // Mask unneeded interrupts if (ISCLEARED(usb_device_state,DEFAULT_STATE)) { status &= AT91C_UDP_ENDBUSRES | AT91C_UDP_SOFINT; } } // end while status != 0 end_of_irq: *AT91C_AIC_EOICR = 1; // ACK interrupt end *AT91C_AIC_ICCR = 1 << AT91C_ID_UDP; // clear interrupt on the interrupt controller //ISR_EXIT(); }