Merge pull request #1340 from tannewt/hid_to_cdc
Add concurrent host and device example
This commit is contained in:
		
							
								
								
									
										28
									
								
								examples/host/hid_to_cdc/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								examples/host/hid_to_cdc/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.5)
 | 
			
		||||
 | 
			
		||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 | 
			
		||||
 | 
			
		||||
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 | 
			
		||||
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
 | 
			
		||||
 | 
			
		||||
project(${PROJECT})
 | 
			
		||||
 | 
			
		||||
# Checks this example is valid for the family and initializes the project
 | 
			
		||||
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
 | 
			
		||||
 | 
			
		||||
add_executable(${PROJECT})
 | 
			
		||||
 | 
			
		||||
# Example source
 | 
			
		||||
target_sources(${PROJECT} PUBLIC
 | 
			
		||||
        ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
 | 
			
		||||
        ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
# Example include
 | 
			
		||||
target_include_directories(${PROJECT} PUBLIC
 | 
			
		||||
        ${CMAKE_CURRENT_SOURCE_DIR}/src
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
# Configure compilation flags and libraries for the example... see the corresponding function
 | 
			
		||||
# in hw/bsp/FAMILY/family.cmake for details.
 | 
			
		||||
family_configure_device_example(${PROJECT})
 | 
			
		||||
							
								
								
									
										20
									
								
								examples/host/hid_to_cdc/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								examples/host/hid_to_cdc/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
include ../../../tools/top.mk
 | 
			
		||||
include ../../make.mk
 | 
			
		||||
 | 
			
		||||
INC += \
 | 
			
		||||
	src \
 | 
			
		||||
	$(TOP)/hw \
 | 
			
		||||
 | 
			
		||||
# Example source
 | 
			
		||||
EXAMPLE_SOURCE += $(wildcard src/*.c)
 | 
			
		||||
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
 | 
			
		||||
 | 
			
		||||
CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
 | 
			
		||||
 | 
			
		||||
SRC_C += \
 | 
			
		||||
	src/class/hid/hid_host.c \
 | 
			
		||||
	src/host/hub.c \
 | 
			
		||||
	src/host/usbh.c \
 | 
			
		||||
	src/host/usbh_control.c
 | 
			
		||||
 | 
			
		||||
include ../../rules.mk
 | 
			
		||||
							
								
								
									
										2
									
								
								examples/host/hid_to_cdc/only.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								examples/host/hid_to_cdc/only.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
board:mimxrt1060_evk
 | 
			
		||||
board:mimxrt1064_evk
 | 
			
		||||
							
								
								
									
										315
									
								
								examples/host/hid_to_cdc/src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								examples/host/hid_to_cdc/src/main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,315 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * The MIT License (MIT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2019 Ha Thach (tinyusb.org)
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// This example runs both host and device concurrently. The USB host looks for
 | 
			
		||||
// any HID device with reports that are 8 bytes long and then assumes they are
 | 
			
		||||
// keyboard reports. It translates the keypresses of the reports to ASCII and
 | 
			
		||||
// transmits it over CDC to the device's host.
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "bsp/board.h"
 | 
			
		||||
#include "tusb.h"
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// MACRO CONSTANT TYPEDEF PROTYPES
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
// uncomment if you are using colemak layout
 | 
			
		||||
// #define KEYBOARD_COLEMAK
 | 
			
		||||
 | 
			
		||||
#ifdef KEYBOARD_COLEMAK
 | 
			
		||||
const uint8_t colemak[128] = {
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0, 22,
 | 
			
		||||
  9  , 23,  7,  0, 24, 17,  8, 12,
 | 
			
		||||
  0  , 14, 28, 51,  0, 19, 21, 10,
 | 
			
		||||
  15 ,  0,  0,  0, 13,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0, 18,  0,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0,  0,
 | 
			
		||||
  0  ,  0,  0,  0,  0,  0,  0,  0
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint8_t const keycode2ascii[128][2] =  { HID_KEYCODE_TO_ASCII };
 | 
			
		||||
 | 
			
		||||
/* Blink pattern
 | 
			
		||||
 * - 250 ms  : device not mounted
 | 
			
		||||
 * - 1000 ms : device mounted
 | 
			
		||||
 * - 2500 ms : device is suspended
 | 
			
		||||
 */
 | 
			
		||||
enum  {
 | 
			
		||||
  BLINK_NOT_MOUNTED = 250,
 | 
			
		||||
  BLINK_MOUNTED = 1000,
 | 
			
		||||
  BLINK_SUSPENDED = 2500,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
 | 
			
		||||
 | 
			
		||||
void led_blinking_task(void);
 | 
			
		||||
void cdc_task(void);
 | 
			
		||||
 | 
			
		||||
/*------------- MAIN -------------*/
 | 
			
		||||
int main(void)
 | 
			
		||||
{
 | 
			
		||||
  board_init();
 | 
			
		||||
  tusb_init();
 | 
			
		||||
 | 
			
		||||
  while (1)
 | 
			
		||||
  {
 | 
			
		||||
    tud_task(); // tinyusb device task
 | 
			
		||||
    tuh_task(); // tinyusb host task
 | 
			
		||||
    led_blinking_task();
 | 
			
		||||
 | 
			
		||||
    cdc_task();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// Device callbacks
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
// Invoked when device is mounted
 | 
			
		||||
void tud_mount_cb(void)
 | 
			
		||||
{
 | 
			
		||||
  blink_interval_ms = BLINK_MOUNTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when device is unmounted
 | 
			
		||||
void tud_umount_cb(void)
 | 
			
		||||
{
 | 
			
		||||
  blink_interval_ms = BLINK_NOT_MOUNTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when usb bus is suspended
 | 
			
		||||
// remote_wakeup_en : if host allow us  to perform remote wakeup
 | 
			
		||||
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
 | 
			
		||||
void tud_suspend_cb(bool remote_wakeup_en)
 | 
			
		||||
{
 | 
			
		||||
  (void) remote_wakeup_en;
 | 
			
		||||
  blink_interval_ms = BLINK_SUSPENDED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when usb bus is resumed
 | 
			
		||||
void tud_resume_cb(void)
 | 
			
		||||
{
 | 
			
		||||
  blink_interval_ms = BLINK_MOUNTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// Host callbacks
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
// Invoked when device with hid interface is mounted
 | 
			
		||||
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
 | 
			
		||||
// can be used to parse common/simple enough descriptor.
 | 
			
		||||
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
 | 
			
		||||
// therefore report_desc = NULL, desc_len = 0
 | 
			
		||||
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
 | 
			
		||||
{
 | 
			
		||||
  (void)desc_report;
 | 
			
		||||
  (void)desc_len;
 | 
			
		||||
  uint16_t vid, pid;
 | 
			
		||||
  tuh_vid_pid_get(dev_addr, &vid, &pid);
 | 
			
		||||
 | 
			
		||||
  printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
 | 
			
		||||
  printf("VID = %04x, PID = %04x\r\n", vid, pid);
 | 
			
		||||
 | 
			
		||||
  // Receive any report and treat it like a keyboard.
 | 
			
		||||
  // tuh_hid_report_received_cb() will be invoked when report is available
 | 
			
		||||
  if ( !tuh_hid_receive_report(dev_addr, instance) )
 | 
			
		||||
  {
 | 
			
		||||
    printf("Error: cannot request to receive report\r\n");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when device with hid interface is un-mounted
 | 
			
		||||
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
 | 
			
		||||
{
 | 
			
		||||
  printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// keycodes from last report to check if key is holding or newly pressed
 | 
			
		||||
uint8_t last_keycodes[6] = {0};
 | 
			
		||||
 | 
			
		||||
// look up new key in previous keys
 | 
			
		||||
static inline bool key_in_last_report(const uint8_t key_arr[6], uint8_t keycode)
 | 
			
		||||
{
 | 
			
		||||
  for(uint8_t i=0; i<6; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (key_arr[i] == keycode) return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when received report from device via interrupt endpoint
 | 
			
		||||
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
 | 
			
		||||
{
 | 
			
		||||
  if (len != 8)
 | 
			
		||||
  {
 | 
			
		||||
    char ch_num;
 | 
			
		||||
 | 
			
		||||
    tud_cdc_write_str("incorrect report len: ");
 | 
			
		||||
 | 
			
		||||
    if ( len > 10 )
 | 
			
		||||
    {
 | 
			
		||||
      ch_num = '0' + (len / 10);
 | 
			
		||||
      tud_cdc_write(&ch_num, 1);
 | 
			
		||||
      len = len % 10;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ch_num = '0' + len;
 | 
			
		||||
    tud_cdc_write(&ch_num, 1);
 | 
			
		||||
 | 
			
		||||
    tud_cdc_write_str("\r\n");
 | 
			
		||||
    tud_cdc_write_flush();
 | 
			
		||||
 | 
			
		||||
    // Don't request a new report for a wrong sized endpoint.
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint8_t const modifiers = report[0];
 | 
			
		||||
  bool flush = false;
 | 
			
		||||
 | 
			
		||||
  for (int i = 2; i < 8; i++)
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t keycode = report[i];
 | 
			
		||||
 | 
			
		||||
    if (keycode)
 | 
			
		||||
    {
 | 
			
		||||
      if ( key_in_last_report(last_keycodes, keycode) )
 | 
			
		||||
      {
 | 
			
		||||
        // exist in previous report means the current key is holding
 | 
			
		||||
        // do nothing
 | 
			
		||||
      }else
 | 
			
		||||
      {
 | 
			
		||||
        // not existed in previous report means the current key is pressed
 | 
			
		||||
        // Only print keycodes 0 - 128.
 | 
			
		||||
        if (keycode < 128)
 | 
			
		||||
        {
 | 
			
		||||
          // remap the key code for Colemak layout so @tannewt can type.
 | 
			
		||||
          #ifdef KEYBOARD_COLEMAK
 | 
			
		||||
          uint8_t colemak_key_code = colemak[keycode];
 | 
			
		||||
          if (colemak_key_code != 0) keycode = colemak_key_code;
 | 
			
		||||
          #endif
 | 
			
		||||
 | 
			
		||||
          bool const is_shift = modifiers & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
 | 
			
		||||
          char c = keycode2ascii[keycode][is_shift ? 1 : 0];
 | 
			
		||||
          if (c)
 | 
			
		||||
          {
 | 
			
		||||
            if (c == '\n') tud_cdc_write("\r", 1);
 | 
			
		||||
            tud_cdc_write(&c, 1);
 | 
			
		||||
            flush = true;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flush) tud_cdc_write_flush();
 | 
			
		||||
 | 
			
		||||
  // save current report
 | 
			
		||||
  memcpy(last_keycodes, report+2, 6);
 | 
			
		||||
 | 
			
		||||
  // continue to request to receive report
 | 
			
		||||
  if ( !tuh_hid_receive_report(dev_addr, instance) )
 | 
			
		||||
  {
 | 
			
		||||
    printf("Error: cannot request to receive report\r\n");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// USB CDC
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
void cdc_task(void)
 | 
			
		||||
{
 | 
			
		||||
  // connected() check for DTR bit
 | 
			
		||||
  // Most but not all terminal client set this when making connection
 | 
			
		||||
  // if ( tud_cdc_connected() )
 | 
			
		||||
  {
 | 
			
		||||
    // connected and there are data available
 | 
			
		||||
    if ( tud_cdc_available() )
 | 
			
		||||
    {
 | 
			
		||||
      // read datas
 | 
			
		||||
      char buf[64];
 | 
			
		||||
      uint32_t count = tud_cdc_read(buf, sizeof(buf));
 | 
			
		||||
      (void) count;
 | 
			
		||||
 | 
			
		||||
      // Echo back
 | 
			
		||||
      // Note: Skip echo by commenting out write() and write_flush()
 | 
			
		||||
      // for throughput test e.g
 | 
			
		||||
      //    $ dd if=/dev/zero of=/dev/ttyACM0 count=10000
 | 
			
		||||
      tud_cdc_write(buf, count);
 | 
			
		||||
      tud_cdc_write_flush();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when cdc when line state changed e.g connected/disconnected
 | 
			
		||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
 | 
			
		||||
{
 | 
			
		||||
  (void) itf;
 | 
			
		||||
  (void) rts;
 | 
			
		||||
 | 
			
		||||
  // TODO set some indicator
 | 
			
		||||
  if ( dtr )
 | 
			
		||||
  {
 | 
			
		||||
    // Terminal connected
 | 
			
		||||
  }else
 | 
			
		||||
  {
 | 
			
		||||
    // Terminal disconnected
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when CDC interface received data from host
 | 
			
		||||
void tud_cdc_rx_cb(uint8_t itf)
 | 
			
		||||
{
 | 
			
		||||
  (void) itf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// BLINKING TASK
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
void led_blinking_task(void)
 | 
			
		||||
{
 | 
			
		||||
  static uint32_t start_ms = 0;
 | 
			
		||||
  static bool led_state = false;
 | 
			
		||||
 | 
			
		||||
  // Blink every interval ms
 | 
			
		||||
  if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
 | 
			
		||||
  start_ms += blink_interval_ms;
 | 
			
		||||
 | 
			
		||||
  board_led_write(led_state);
 | 
			
		||||
  led_state = 1 - led_state; // toggle
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										163
									
								
								examples/host/hid_to_cdc/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								examples/host/hid_to_cdc/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The MIT License (MIT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2019 Ha Thach (tinyusb.org)
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _TUSB_CONFIG_H_
 | 
			
		||||
#define _TUSB_CONFIG_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
// COMMON CONFIGURATION
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// defined by board.mk
 | 
			
		||||
#ifndef CFG_TUSB_MCU
 | 
			
		||||
  #error CFG_TUSB_MCU must be defined
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// RHPort number used for device can be defined by board.mk, default to port 0
 | 
			
		||||
#ifndef BOARD_DEVICE_RHPORT_NUM
 | 
			
		||||
  #define BOARD_DEVICE_RHPORT_NUM     0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// RHPort number used for device can be defined by board.mk, default to port 1
 | 
			
		||||
#ifndef BOARD_HOST_RHPORT_NUM
 | 
			
		||||
  #define BOARD_HOST_RHPORT_NUM     1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// RHPort max operational speed can defined by board.mk
 | 
			
		||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
 | 
			
		||||
#ifndef BOARD_DEVICE_RHPORT_SPEED
 | 
			
		||||
  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
 | 
			
		||||
      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
 | 
			
		||||
      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
 | 
			
		||||
    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
 | 
			
		||||
  #else
 | 
			
		||||
    #define BOARD_DEVICE_RHPORT_SPEED   OPT_MODE_FULL_SPEED
 | 
			
		||||
  #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// RHPort max operational speed can defined by board.mk
 | 
			
		||||
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
 | 
			
		||||
#ifndef BOARD_HOST_RHPORT_SPEED
 | 
			
		||||
  #if TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX, OPT_MCU_MIMXRT10XX, OPT_MCU_NUC505) ||\
 | 
			
		||||
      TU_CHECK_MCU(OPT_MCU_CXD56, OPT_MCU_SAMX7X, OPT_MCU_BCM2711) ||\
 | 
			
		||||
      TU_CHECK_MCU(OPT_MCU_FT90X, OPT_MCU_FT93X)
 | 
			
		||||
    #define BOARD_HOST_RHPORT_SPEED   OPT_MODE_HIGH_SPEED
 | 
			
		||||
  #else
 | 
			
		||||
    #define BOARD_HOST_RHPORT_SPEED   OPT_MODE_FULL_SPEED
 | 
			
		||||
  #endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Device mode with rhport and speed defined by board.mk
 | 
			
		||||
#if   BOARD_DEVICE_RHPORT_NUM == 0
 | 
			
		||||
  #define CFG_TUSB_RHPORT0_MODE     (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
 | 
			
		||||
#elif BOARD_DEVICE_RHPORT_NUM == 1
 | 
			
		||||
  #define CFG_TUSB_RHPORT1_MODE     (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
 | 
			
		||||
#else
 | 
			
		||||
  #error "Incorrect RHPort configuration"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Device mode with rhport and speed defined by board.mk
 | 
			
		||||
#if   BOARD_HOST_RHPORT_NUM == 0
 | 
			
		||||
  #define CFG_TUSB_RHPORT0_MODE     (OPT_MODE_HOST | BOARD_HOST_RHPORT_SPEED)
 | 
			
		||||
#elif BOARD_HOST_RHPORT_NUM == 1
 | 
			
		||||
  #define CFG_TUSB_RHPORT1_MODE     (OPT_MODE_HOST | BOARD_HOST_RHPORT_SPEED)
 | 
			
		||||
#else
 | 
			
		||||
  #error "Incorrect RHPort configuration"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This example doesn't use an RTOS
 | 
			
		||||
#ifndef CFG_TUSB_OS
 | 
			
		||||
#define CFG_TUSB_OS               OPT_OS_NONE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
 | 
			
		||||
// #define CFG_TUSB_DEBUG           0
 | 
			
		||||
 | 
			
		||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
 | 
			
		||||
 * Tinyusb use follows macros to declare transferring memory so that they can be put
 | 
			
		||||
 * into those specific section.
 | 
			
		||||
 * e.g
 | 
			
		||||
 * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
 | 
			
		||||
 * - CFG_TUSB_MEM_ALIGN   : __attribute__ ((aligned(4)))
 | 
			
		||||
 */
 | 
			
		||||
#ifndef CFG_TUSB_MEM_SECTION
 | 
			
		||||
#define CFG_TUSB_MEM_SECTION
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef CFG_TUSB_MEM_ALIGN
 | 
			
		||||
#define CFG_TUSB_MEM_ALIGN          __attribute__ ((aligned(4)))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
// DEVICE CONFIGURATION
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
 | 
			
		||||
#define CFG_TUD_ENDPOINT0_SIZE    64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//------------- CLASS -------------//
 | 
			
		||||
#define CFG_TUD_CDC              1
 | 
			
		||||
#define CFG_TUD_MSC              0
 | 
			
		||||
#define CFG_TUD_HID              0
 | 
			
		||||
#define CFG_TUD_MIDI             0
 | 
			
		||||
#define CFG_TUD_VENDOR           0
 | 
			
		||||
 | 
			
		||||
// CDC FIFO size of TX and RX
 | 
			
		||||
#define CFG_TUD_CDC_RX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
 | 
			
		||||
#define CFG_TUD_CDC_TX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
 | 
			
		||||
 | 
			
		||||
// CDC Endpoint transfer buffer size, more is faster
 | 
			
		||||
#define CFG_TUD_CDC_EP_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
// HOST CONFIGURATION
 | 
			
		||||
//--------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// Size of buffer to hold descriptors and other data used for enumeration
 | 
			
		||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
 | 
			
		||||
 | 
			
		||||
#define CFG_TUH_HUB                 1
 | 
			
		||||
#define CFG_TUH_CDC                 0
 | 
			
		||||
#define CFG_TUH_MSC                 0
 | 
			
		||||
#define CFG_TUH_VENDOR              0
 | 
			
		||||
 | 
			
		||||
// max device support (excluding hub device)
 | 
			
		||||
#define CFG_TUH_DEVICE_MAX          (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
 | 
			
		||||
 | 
			
		||||
//------------- HID -------------//
 | 
			
		||||
#define CFG_TUH_HID                  4
 | 
			
		||||
#define CFG_TUH_HID_EPIN_BUFSIZE    64
 | 
			
		||||
#define CFG_TUH_HID_EPOUT_BUFSIZE   64
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _TUSB_CONFIG_H_ */
 | 
			
		||||
							
								
								
									
										266
									
								
								examples/host/hid_to_cdc/src/usb_descriptors.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								examples/host/hid_to_cdc/src/usb_descriptors.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,266 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * The MIT License (MIT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2019 Ha Thach (tinyusb.org)
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "tusb.h"
 | 
			
		||||
 | 
			
		||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
 | 
			
		||||
 * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
 | 
			
		||||
 *
 | 
			
		||||
 * Auto ProductID layout's Bitmap:
 | 
			
		||||
 *   [MSB]         HID | MSC | CDC          [LSB]
 | 
			
		||||
 */
 | 
			
		||||
#define _PID_MAP(itf, n)  ( (CFG_TUD_##itf) << (n) )
 | 
			
		||||
#define USB_PID           (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
 | 
			
		||||
                           _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
 | 
			
		||||
 | 
			
		||||
#define USB_VID   0xCafe
 | 
			
		||||
#define USB_BCD   0x0200
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// Device Descriptors
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
tusb_desc_device_t const desc_device =
 | 
			
		||||
{
 | 
			
		||||
  .bLength            = sizeof(tusb_desc_device_t),
 | 
			
		||||
  .bDescriptorType    = TUSB_DESC_DEVICE,
 | 
			
		||||
  .bcdUSB             = USB_BCD,
 | 
			
		||||
 | 
			
		||||
  // Use Interface Association Descriptor (IAD) for CDC
 | 
			
		||||
  // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
 | 
			
		||||
  .bDeviceClass       = TUSB_CLASS_MISC,
 | 
			
		||||
  .bDeviceSubClass    = MISC_SUBCLASS_COMMON,
 | 
			
		||||
  .bDeviceProtocol    = MISC_PROTOCOL_IAD,
 | 
			
		||||
 | 
			
		||||
  .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
 | 
			
		||||
 | 
			
		||||
  .idVendor           = USB_VID,
 | 
			
		||||
  .idProduct          = USB_PID,
 | 
			
		||||
  .bcdDevice          = 0x0100,
 | 
			
		||||
 | 
			
		||||
  .iManufacturer      = 0x01,
 | 
			
		||||
  .iProduct           = 0x02,
 | 
			
		||||
  .iSerialNumber      = 0x03,
 | 
			
		||||
 | 
			
		||||
  .bNumConfigurations = 0x01
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Invoked when received GET DEVICE DESCRIPTOR
 | 
			
		||||
// Application return pointer to descriptor
 | 
			
		||||
uint8_t const * tud_descriptor_device_cb(void)
 | 
			
		||||
{
 | 
			
		||||
  return (uint8_t const *) &desc_device;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// Configuration Descriptor
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  ITF_NUM_CDC = 0,
 | 
			
		||||
  ITF_NUM_CDC_DATA,
 | 
			
		||||
  ITF_NUM_MSC,
 | 
			
		||||
  ITF_NUM_TOTAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
 | 
			
		||||
  // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
 | 
			
		||||
  // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
 | 
			
		||||
  #define EPNUM_CDC_NOTIF   0x81
 | 
			
		||||
  #define EPNUM_CDC_OUT     0x02
 | 
			
		||||
  #define EPNUM_CDC_IN      0x82
 | 
			
		||||
 | 
			
		||||
#elif CFG_TUSB_MCU == OPT_MCU_SAMG  || CFG_TUSB_MCU ==  OPT_MCU_SAMX7X
 | 
			
		||||
  // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
 | 
			
		||||
  //    e.g EP1 OUT & EP1 IN cannot exist together
 | 
			
		||||
  #define EPNUM_CDC_NOTIF   0x81
 | 
			
		||||
  #define EPNUM_CDC_OUT     0x02
 | 
			
		||||
  #define EPNUM_CDC_IN      0x83
 | 
			
		||||
 | 
			
		||||
#elif CFG_TUSB_MCU == OPT_MCU_CXD56
 | 
			
		||||
  // CXD56 doesn't support a same endpoint number with different direction IN and OUT
 | 
			
		||||
  //    e.g EP1 OUT & EP1 IN cannot exist together
 | 
			
		||||
  // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
 | 
			
		||||
  // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
 | 
			
		||||
  #define EPNUM_CDC_NOTIF   0x83
 | 
			
		||||
  #define EPNUM_CDC_OUT     0x02
 | 
			
		||||
  #define EPNUM_CDC_IN      0x81
 | 
			
		||||
 | 
			
		||||
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
 | 
			
		||||
  // FT9XX doesn't support a same endpoint number with different direction IN and OUT
 | 
			
		||||
  //    e.g EP1 OUT & EP1 IN cannot exist together
 | 
			
		||||
  #define EPNUM_CDC_NOTIF   0x81
 | 
			
		||||
  #define EPNUM_CDC_OUT     0x02
 | 
			
		||||
  #define EPNUM_CDC_IN      0x83
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
  #define EPNUM_CDC_NOTIF   0x81
 | 
			
		||||
  #define EPNUM_CDC_OUT     0x02
 | 
			
		||||
  #define EPNUM_CDC_IN      0x82
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define CONFIG_TOTAL_LEN    (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
 | 
			
		||||
 | 
			
		||||
// full speed configuration
 | 
			
		||||
uint8_t const desc_fs_configuration[] =
 | 
			
		||||
{
 | 
			
		||||
  // Config number, interface count, string index, total length, attribute, power in mA
 | 
			
		||||
  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
 | 
			
		||||
 | 
			
		||||
  // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
 | 
			
		||||
  TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if TUD_OPT_HIGH_SPEED
 | 
			
		||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
 | 
			
		||||
 | 
			
		||||
// high speed configuration
 | 
			
		||||
uint8_t const desc_hs_configuration[] =
 | 
			
		||||
{
 | 
			
		||||
  // Config number, interface count, string index, total length, attribute, power in mA
 | 
			
		||||
  TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
 | 
			
		||||
 | 
			
		||||
  // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
 | 
			
		||||
  TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// other speed configuration
 | 
			
		||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
 | 
			
		||||
 | 
			
		||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
 | 
			
		||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
 | 
			
		||||
{
 | 
			
		||||
  .bLength            = sizeof(tusb_desc_device_qualifier_t),
 | 
			
		||||
  .bDescriptorType    = TUSB_DESC_DEVICE_QUALIFIER,
 | 
			
		||||
  .bcdUSB             = USB_BCD,
 | 
			
		||||
 | 
			
		||||
  .bDeviceClass       = TUSB_CLASS_MISC,
 | 
			
		||||
  .bDeviceSubClass    = MISC_SUBCLASS_COMMON,
 | 
			
		||||
  .bDeviceProtocol    = MISC_PROTOCOL_IAD,
 | 
			
		||||
 | 
			
		||||
  .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
 | 
			
		||||
  .bNumConfigurations = 0x01,
 | 
			
		||||
  .bReserved          = 0x00
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
 | 
			
		||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
 | 
			
		||||
// device_qualifier descriptor describes information about a high-speed capable device that would
 | 
			
		||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
 | 
			
		||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
 | 
			
		||||
{
 | 
			
		||||
  return (uint8_t const*) &desc_device_qualifier;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
 | 
			
		||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
 | 
			
		||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
 | 
			
		||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
 | 
			
		||||
{
 | 
			
		||||
  (void) index; // for multiple configurations
 | 
			
		||||
 | 
			
		||||
  // if link speed is high return fullspeed config, and vice versa
 | 
			
		||||
  // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
 | 
			
		||||
  memcpy(desc_other_speed_config,
 | 
			
		||||
         (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
 | 
			
		||||
         CONFIG_TOTAL_LEN);
 | 
			
		||||
 | 
			
		||||
  desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
 | 
			
		||||
 | 
			
		||||
  return desc_other_speed_config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // highspeed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
 | 
			
		||||
// Application return pointer to descriptor
 | 
			
		||||
// Descriptor contents must exist long enough for transfer to complete
 | 
			
		||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
 | 
			
		||||
{
 | 
			
		||||
  (void) index; // for multiple configurations
 | 
			
		||||
 | 
			
		||||
#if TUD_OPT_HIGH_SPEED
 | 
			
		||||
  // Although we are highspeed, host may be fullspeed.
 | 
			
		||||
  return (tud_speed_get() == TUSB_SPEED_HIGH) ?  desc_hs_configuration : desc_fs_configuration;
 | 
			
		||||
#else
 | 
			
		||||
  return desc_fs_configuration;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
// String Descriptors
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 | 
			
		||||
// array of pointer to string descriptors
 | 
			
		||||
char const* string_desc_arr [] =
 | 
			
		||||
{
 | 
			
		||||
  (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
 | 
			
		||||
  "TinyUSB",                     // 1: Manufacturer
 | 
			
		||||
  "TinyUSB Device",              // 2: Product
 | 
			
		||||
  "123456789012",                // 3: Serials, should use chip ID
 | 
			
		||||
  "TinyUSB CDC",                 // 4: CDC Interface
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint16_t _desc_str[32];
 | 
			
		||||
 | 
			
		||||
// Invoked when received GET STRING DESCRIPTOR request
 | 
			
		||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
 | 
			
		||||
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
 | 
			
		||||
{
 | 
			
		||||
  (void) langid;
 | 
			
		||||
 | 
			
		||||
  uint8_t chr_count;
 | 
			
		||||
 | 
			
		||||
  if ( index == 0)
 | 
			
		||||
  {
 | 
			
		||||
    memcpy(&_desc_str[1], string_desc_arr[0], 2);
 | 
			
		||||
    chr_count = 1;
 | 
			
		||||
  }else
 | 
			
		||||
  {
 | 
			
		||||
    // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
 | 
			
		||||
    // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
 | 
			
		||||
 | 
			
		||||
    if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
 | 
			
		||||
 | 
			
		||||
    const char* str = string_desc_arr[index];
 | 
			
		||||
 | 
			
		||||
    // Cap at max char
 | 
			
		||||
    chr_count = (uint8_t) strlen(str);
 | 
			
		||||
    if ( chr_count > 31 ) chr_count = 31;
 | 
			
		||||
 | 
			
		||||
    // Convert ASCII string into UTF-16
 | 
			
		||||
    for(uint8_t i=0; i<chr_count; i++)
 | 
			
		||||
    {
 | 
			
		||||
      _desc_str[1+i] = str[i];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // first byte is length (including header), second byte is string type
 | 
			
		||||
  _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
 | 
			
		||||
 | 
			
		||||
  return _desc_str;
 | 
			
		||||
}
 | 
			
		||||
@@ -7,5 +7,8 @@ JLINK_DEVICE = MIMXRT1062xxx6A
 | 
			
		||||
# For flash-pyocd target
 | 
			
		||||
PYOCD_TARGET = mimxrt1060
 | 
			
		||||
 | 
			
		||||
BOARD_DEVICE_RHPORT_NUM = 1
 | 
			
		||||
BOARD_HOST_RHPORT_NUM = 0
 | 
			
		||||
 | 
			
		||||
# flash using pyocd
 | 
			
		||||
flash: flash-pyocd
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,8 @@ JLINK_DEVICE = MIMXRT1064xxx6A
 | 
			
		||||
# For flash-pyocd target
 | 
			
		||||
PYOCD_TARGET = mimxrt1064
 | 
			
		||||
 | 
			
		||||
BOARD_DEVICE_RHPORT_NUM = 1
 | 
			
		||||
BOARD_HOST_RHPORT_NUM = 0
 | 
			
		||||
 | 
			
		||||
# flash using pyocd
 | 
			
		||||
flash: flash-pyocd
 | 
			
		||||
 
 | 
			
		||||
@@ -98,13 +98,9 @@ void board_init(void)
 | 
			
		||||
  CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
 | 
			
		||||
  CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
 | 
			
		||||
 | 
			
		||||
  // USB1
 | 
			
		||||
//  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
 | 
			
		||||
//  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
 | 
			
		||||
 | 
			
		||||
  USBPHY_Type* usb_phy;
 | 
			
		||||
 | 
			
		||||
  // RT105x RT106x have dual USB controller. TODO support USB2
 | 
			
		||||
  // RT105x RT106x have dual USB controller.
 | 
			
		||||
#ifdef USBPHY1
 | 
			
		||||
  usb_phy = USBPHY1;
 | 
			
		||||
#else
 | 
			
		||||
@@ -122,6 +118,27 @@ void board_init(void)
 | 
			
		||||
  phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
 | 
			
		||||
  phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
 | 
			
		||||
  usb_phy->TX = phytx;
 | 
			
		||||
 | 
			
		||||
  // RT105x RT106x have dual USB controller.
 | 
			
		||||
#ifdef USBPHY2
 | 
			
		||||
  // USB1
 | 
			
		||||
  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
 | 
			
		||||
  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
 | 
			
		||||
 | 
			
		||||
  usb_phy = USBPHY2;
 | 
			
		||||
 | 
			
		||||
  // Enable PHY support for Low speed device + LS via FS Hub
 | 
			
		||||
  usb_phy->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK;
 | 
			
		||||
 | 
			
		||||
  // Enable all power for normal operation
 | 
			
		||||
  usb_phy->PWD = 0;
 | 
			
		||||
 | 
			
		||||
  // TX Timing
 | 
			
		||||
  phytx = usb_phy->TX;
 | 
			
		||||
  phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
 | 
			
		||||
  phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
 | 
			
		||||
  usb_phy->TX = phytx;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------------------------+
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,13 @@ CFLAGS += \
 | 
			
		||||
  -DXIP_BOOT_HEADER_ENABLE=1 \
 | 
			
		||||
  -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX
 | 
			
		||||
 | 
			
		||||
ifdef BOARD_DEVICE_RHPORT_NUM
 | 
			
		||||
CFLAGS += -DBOARD_DEVICE_RHPORT_NUM=$(BOARD_DEVICE_RHPORT_NUM)
 | 
			
		||||
endif
 | 
			
		||||
ifdef BOARD_HOST_RHPORT_NUM
 | 
			
		||||
CFLAGS += -DBOARD_HOST_RHPORT_NUM=$(BOARD_HOST_RHPORT_NUM)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# mcu driver cause following warnings
 | 
			
		||||
CFLAGS += -Wno-error=unused-parameter -Wno-error=implicit-fallthrough=
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1106,7 +1106,10 @@ enum
 | 
			
		||||
    {'8'   , 0      }, /* 0x60 */ \
 | 
			
		||||
    {'9'   , 0      }, /* 0x61 */ \
 | 
			
		||||
    {'0'   , 0      }, /* 0x62 */ \
 | 
			
		||||
    {'0'   , 0      }, /* 0x63 */ \
 | 
			
		||||
    {'.'   , 0      }, /* 0x63 */ \
 | 
			
		||||
    {0     , 0      }, /* 0x64 */ \
 | 
			
		||||
    {0     , 0      }, /* 0x65 */ \
 | 
			
		||||
    {0     , 0      }, /* 0x66 */ \
 | 
			
		||||
    {'='   , '='    }, /* 0x67 */ \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user