/**
 * This function will handle system sof event.
 *
 * @param device the usb device object.
 *
 * @return RT_EOK on successful.
 */
static rt_err_t _class_sof_handler(udevice_t device, uclass_t cls)
{
    rt_uint32_t level;
    rt_size_t size;
    static rt_uint32_t frame_count = 0;
    cdc_eps_t eps;

    if(vcom_connected != RT_TRUE) return -RT_ERROR;
    
    eps = (cdc_eps_t)cls->eps;
    if (frame_count ++ == 5)
    {
        rt_size_t mps = eps->ep_in->ep_desc->wMaxPacketSize;

        /* reset the frame counter */
        frame_count = 0;

        size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
        if(size == 0) return -RT_EFULL;

        size = size > mps ? mps : size;
        
        level = rt_hw_interrupt_disable();
        rt_ringbuffer_get(&tx_ringbuffer, eps->ep_in->buffer, size);
        rt_hw_interrupt_enable(level);                     
        
        /* send data to host */
        dcd_ep_write(device->dcd, eps->ep_in, eps->ep_in->buffer, size);
    }

    return RT_EOK;
}
/*******************************************************************************
* Function Name  : Handle_USBAsynchXfer.
* Description    : send data to USB.
* Input          : None.
* Return         : none.
*******************************************************************************/
void Handle_USBAsynchXfer (void)
{
  rt_uint32_t level;
  rt_uint32_t remain;
  
  if(USB_Tx_State != 1)
  {
  	level = rt_hw_interrupt_disable();
	  remain = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
    
    if(remain == 0) 
    {
      USB_Tx_State = 0;
	  rt_hw_interrupt_enable(level);
      return;
    }
    
    if (remain > VIRTUAL_COM_PORT_DATA_SIZE)
    {
      remain = VIRTUAL_COM_PORT_DATA_SIZE;	
    }
	rt_ringbuffer_get(&tx_ringbuffer, tx_buf, remain);
	rt_hw_interrupt_enable(level);

    USB_Tx_State = 1; 
    UserToPMABufferCopy(tx_buf, ENDP1_TXADDR, remain);
    SetEPTxCount(ENDP1, remain);
    SetEPTxValid(ENDP1); 
  }  
}
/*******************************************************************************
* Function Name  : EP1_IN_Callback
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void EP1_IN_Callback (void)
{
  rt_uint32_t level;
  rt_uint32_t remain;

  if (USB_Tx_State == 1)
  {
	  level = rt_hw_interrupt_disable();
	  remain = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
	  if (remain == 0) 
	    {
	      USB_Tx_State = 0;
		  rt_hw_interrupt_enable(level);
		  return;
	    }
	    else
	    {
	    	if (remain > VIRTUAL_COM_PORT_DATA_SIZE)
	    	{
				remain = VIRTUAL_COM_PORT_DATA_SIZE;
			}
	        /* although vcom_in_sending is set in SOF handler in the very
	         * beginning, we have to guarantee the state is right when start
	         * sending. There is at least one extreme case where we have finished the
	         * last IN transaction but the vcom_in_sending is RT_FALSE.
	         *
	         * Ok, what the extreme case is: pour data into vcom in loop. Open
	         * terminal on the PC, you will see the data. Then close it. So the
	         * data will be sent to the PC in the back. When the buffer of the PC
	         * driver is full. It will not send IN packet to the board and you will
	         * have no chance to clear vcom_in_sending in this function. The data
	         * will fill into the ringbuffer until it is full, and we will reset
	         * the state machine and clear vcom_in_sending. When you open the
	         * terminal on the PC again. The IN packet will appear on the line and
	         * we will, eventually, reach here with vcom_in_sending is clear.
	         */
	        vcom_in_sending = RT_TRUE;
	        rt_ringbuffer_get(&tx_ringbuffer, tx_buf, remain);
	        rt_hw_interrupt_enable(level);

	        /* send data to host */
			UserToPMABufferCopy(tx_buf, ENDP1_TXADDR, remain);
	        SetEPTxCount(ENDP1, remain);
	        SetEPTxValid(ENDP1); 

	        //return RT_EOK;
	    }
  	}

}
static int _vcom_getc(struct rt_serial_device *serial)
{
    int result;
    rt_uint8_t ch;
    rt_uint32_t level;

    result = -1;

    level = rt_hw_interrupt_disable();
    if (RT_RINGBUFFER_SIZE(&rx_ringbuffer))
    {
        rt_ringbuffer_getchar(&rx_ringbuffer, &ch);
        result = ch;
    }
    rt_hw_interrupt_enable(level);

    return result;
}
Exemple #5
0
/**
 * This function will handle cdc bulk in endpoint request.
 *
 * @param device the usb device object.
 * @param size request size.
 *
 * @return RT_EOK.
 */
static rt_err_t _ep_in_handler(udevice_t device, rt_size_t size)
{
    rt_uint32_t level;
    rt_size_t length;

    rt_size_t mps = ep_in->ep_desc->wMaxPacketSize;
    size = RT_RINGBUFFER_SIZE(&tx_ringbuffer);
    if(size == 0) return RT_EOK;

    length = size > mps ? mps : size;

    level = rt_hw_interrupt_disable();
    rt_ringbuffer_get(&tx_ringbuffer, ep_in->buffer, length);
    rt_hw_interrupt_enable(level);

    /* send data to host */
    dcd_ep_write(device->dcd, ep_in, ep_in->buffer, length);

    return RT_EOK;
}