Beispiel #1
0
//-----------------------------------------------------------------------------
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;
}
Beispiel #2
0
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;

    }

}
Beispiel #3
0
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);
    }

}
Beispiel #4
0
//-----------------------------------------------------------------------------
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);
    }
}
Beispiel #5
0
//-----------------------------------------------------------------------------
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;
    }
}
Beispiel #6
0
//-----------------------------------------------------------------------------
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;
    }
}
Beispiel #7
0
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
		}

    }

}
Beispiel #8
0
//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();   
}