/**
  * @brief  Start The USB OTG Device.
  * @param  hpcd: PCD handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
{ 
  /*  DP Pull-Down is external */
  HAL_PCDEx_SetConnectionState (hpcd, 1);
  
  return HAL_OK;
}
/**
  * @brief  Disconnect the USB device 
  * @param  hpcd: PCD handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
{
  __HAL_LOCK(hpcd); 
  
  /* Disable DP Pull-Down bit*/
  HAL_PCDEx_SetConnectionState(hpcd, 0);
  
  __HAL_UNLOCK(hpcd); 
  return HAL_OK;
}
/**
  * @brief  Connect the USB device 
  * @param  hpcd: PCD handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
{
  __HAL_LOCK(hpcd); 
  
  /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */
   HAL_PCDEx_SetConnectionState(hpcd, 1);
  
  __HAL_UNLOCK(hpcd); 
  return HAL_OK;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
  switch (GPIO_Pin) {
  case GPIO_PIN_5:
    // push SW1, toggle connection
    printf("\r\nSoftware device connection.\r\n");
    connectionState ^= 1;
    HAL_PCDEx_SetConnectionState(hUsbDeviceFS.pData, connectionState);
    break;
  case GPIO_PIN_4:
    break;
  case GPIO_PIN_3:
    break;
  case GPIO_PIN_2:
    break;
  }
}
/**
  * @brief  Start the USB device.
  * @param  hpcd: PCD handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
{ 
  HAL_PCDEx_SetConnectionState (hpcd, 1);

  return HAL_OK;
}
int main(void)
{

  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();

  /* USER CODE BEGIN 2 */
  HAL_PCDEx_SetConnectionState(hUsbDeviceFS.pData, connectionState);// USB Activate
  HAL_Delay(3000);
  printf("Hello world.\r\n");

  uint8_t buf = 0;
  uint8_t cbuf[100];
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

    // USART1 <=> VCP echo test
    if (USB_IS_ACTIVE())
    {
      HAL_Delay(5000);

      printf("\r\nVCP Connected > ");
      fflush(stdout);
      VCP_write("\r\nVCP Connected > ", 18);

      while (USB_IS_ACTIVE())
      {
        // VCP to USART1
        if (VCP_read(&buf, 1) == 1 && buf)
        {
          printf("\033[36m%c\033[0m", buf);
          fflush(stdout);
          VCP_write(&buf, 1);
          buf = 0;
        }

        // USART1 to VCP
        HAL_UART_Receive(&huart1, &buf, 1, 1);
        if (buf)
        {
          sprintf(cbuf, "\033[36m%c\033[0m", buf);
          VCP_write(&cbuf, 10);
          printf("%c", buf);
          fflush(stdout);
          buf = 0;
        }
      }

      printf("\r\nVCP Disconnected.\r\n");
    }
    else
    {
      // [debug] dump device status
      printf("\rdev_state = %d", hUsbDeviceFS.dev_state);
      fflush(stdout);
      HAL_Delay(500);
    }
  }
  /* USER CODE END 3 */

}