/** * 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; }
/** * 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; }