레이블이 IF-USB인 게시물을 표시합니다. 모든 게시물 표시
레이블이 IF-USB인 게시물을 표시합니다. 모든 게시물 표시

1/09/2021

Android USB 설정 및 USB Type C

 1. USB Device Tree 설정분석 


USB OTG Device Tree 관련내용 


Chapter 14 Connectivity Subsystem



  • USB 분석이유 
USB Device Tree를 다시 분석하는 이유는 USB Type-C가 지원이 되면서, HW 구조가 변경이 되어 개인적으로 이 부분을 정확히 이해하려고 한다. 
i.MX8QXP의 EVM의 경우 아래와 같이 사용하고 있지만, 현재 OTG1/2만 사용하고자 하면 이 구조를 변경을 해야한다. 
  1. OTG1: OTG 사용   
  2. OTG2/OTG3: USB Type-C  (USB 2.0 과 USB 3.0 동시 필요)

USB 3.0 TypeC 의 경우 Cadence 것을 가져다 쓰며, 아래와 같이 AMBA에서 APB/AXI4로 연결하여 사용되어지고 있다. 
중간에 MUX에 의해 Host or Device 선택되어지면, 이는 OTG에 의해서 결정될 것이다. 
(참고로 USB 2.0 OTG의 경우, 대체적으로 dwc or hdrc )

14.12.2 Functional Description





변경하고자 하는 HW
OTG1 과 OTG2만 USB 2.0 사용할 경우 재미있는 것은 상위 OTG1/2만 사용할 경우 OTG가 잘동작하지 않아 이를 HW로 ID 핀으로 Device or Host 설정을 한 후 사용예정 


$ vi ./vendor/nxp-opensource/kernel_imx/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi

/*
    USB OTG일 경우  i.MX series는 /sys file에 ci_hdrc.0 만 생성되며, ci_hdrc.1 은 찾아볼수 없음 
    i.MX8은 i.MX6 다르게, OTG Hardware는 두개지만 내부적 OTG2는 USB3를 위해서으로 분할되어 있음
    
    Device Tree 주소와 같이 보자 
    
  2.2.2 Connectivity Memory Maps
     5B28_0000 : LPCG USB3           (현재 미사용 추측) 
     5B27_0000 : LPCG USB2           (현재 미사용 추측)
     5B16_0000 : USB3_PHY3P0  (OTG3/2) 
     5B12_0000 : USB3         (OTG3/2) 
     5B11_0000 : USB3_CTRL    (OTG3/2) 
     5B10_0000 : USBOH_PHY    (OTG1)
     5B0F_0000 : USBOH_PL301         (현재 미사용 추측)
     5B0D_0000 : USBOH_OTG    (OTG1) 
*/

  https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
  
	usbotg1: usb@5b0d0000 {
		compatible = "fsl,imx8qm-usb", "fsl,imx7ulp-usb",
			"fsl,imx27-usb";
		reg = <0x5b0d0000 0x200>;
		interrupt-parent = <&gic>;
		interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
		fsl,usbphy = <&usbphy1>;
		fsl,usbmisc = <&usbmisc1 0>;
		clocks = <&usb2_lpcg 0>;
		ahb-burst-config = <0x0>;
		tx-burst-size-dword = <0x10>;
		rx-burst-size-dword = <0x10>;
		power-domains = <&pd IMX_SC_R_USB_0>;
		status = "disabled";
	};

/*
    Datasheet를 보면, OTG Hardware는 2개가 다른 곳에 있으며, 이 것을 OTG1/2 분할 해서 사용해야 할 것같다.  
    구성은 좀 재미있으며, Datasheet를 비교해봐도 i.MX6와 완전다르다 
    
OTG1의 구성을 세부적으로 Datasheet와 같이 분석 
    
  14.10.3.1.1 Configuration, Control and Status Register Set 구성 (5B0D_0000 : USBOH_OTG )  
       - UOG1 (OTG1) : 3개다 동일 offset 이며, 공통 OTG 기능 목적으로 사용되는 것으로 추측 
       - UOG2 (OTG2)
       - UH   (USB Host)
      USB Core RegisterUSB Non Core Register가 구분               
      
  14.10.4 USB Non-Core Memory Map/Register Definition        (5B0D_0000 : USBOH_OTG )
      Non Core Register들로 추가적으로 의존적인 부분이라고 하는데, 공유목적으로 분리사용하는것으로 추측
        - 5b0d0200 : USBNC_OTG1_CTRL1  Non-Core Control
        - 5b0d1200 : USBNC_OTG2_CTRL1         
        - 5b0d2200 : USBNC_UH_CTRL1        
        ** usbmisc 사용    
        
  14.10.5 USB Core Memory Map/Register Definition      (5B0D_0000 : USBOH_OTG )
       USB Core Register들은 USB Core Function Control과 독립적인 기능역할을 해서 분리 
        상위 14.10.3.1.1 Configuration, Control and Status Register Set 과 동일         
*/
  https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/usb/usbmisc-imx.txt

	usbmisc1: usbmisc@5b0d0200 {
		#index-cells = <1>;
		compatible = "fsl,imx7ulp-usbmisc", "fsl,imx6q-usbmisc";
		reg = <0x5b0d0200 0x200>;
	};

  https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt
  
	usbphy1: usbphy@5b100000 {
		compatible = "fsl,imx8qm-usbphy", "fsl,imx7ulp-usbphy",
			"fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
		reg = <0x5b100000 0x1000>;
		clocks = <&usb2_lpcg 1>;
		power-domains = <&pd IMX_SC_R_USB_0_PHY>;
		status = "disabled";
	};
        
/* 
OTG3/2의 구성분석 
   
    USB OTG2는 내부적으로 보면 USB3.0 OTG Controller 위해 존재하며, 상위 OTG1 과 OTG3 Device Driver 완전 다르다. 
    EVM은 사용 상위 OTG2의 Controller가 14.12.6.33 USB2 Port Status and Control (PORTSC1USB2)  존재하는데, 
    EVM을 보면, USB-C Type에 위해서 사용되며, USB 2.0 Phy(OTG) 와 USB 3.0 Phy 때문에 사용한 것으로 파악  
    
    관련내용 14.12.1.1 Features Reference Manual
    - 전압도 12V 와 5V로 구조로 분리되어 동작 (추후 시간이되면, USB3.0 회로구성을 다시 한번 세부 분석해야겠음)
    - 현재 아래는 USB Type-C 사용할때 3.0 와 2.0을 같이 사용하기 위한 전용 Controller로 생각되며, 
      처음 OTG1/2만 사용할 경우 필요 없을 것이라고 생각했지만, 분석 후 아래의 otg3도 같이 사용할 필요할 것으로 파악. 
*/

	usb3phynop1: usb3-phy {
		compatible = "usb-nop-xceiv";
		clocks = <&usb3_lpcg 4>;
		clock-names = "main_clk";
		power-domains = <&pd IMX_SC_R_USB_2_PHY>;
		status = "disabled";
	};

/*     
OTG3/2의 구성을 세부적으로 Datasheet와 Driver 같이 분석 
   
  14.12.6.1 Core Registers Memory map   (5B12_0000 : USB3       0x5B130000,  0x5B140000)
      USB Core Register들은 USB Core Function Control과 독립적인 기능역할을 해서 분리
        - 5B120058 :  OTGCTRL1     Core Control
        - 5B12005C :  OTGCTRL2
        
        - 5B130480 :  PORTSC1USB2  xhci_regs
        - 5B130490 :  PORTSC1USB3  xhci_regs 
   
  14.12.7.1 Non-Core Registers Memory map (5B11_0000 : USB3_CTRL )     
      Non Core Register들로 추가적으로 의존적인 부분이라고 하는데, 공유목적으로 분리사용하는것으로 추측
  
  https://mjmwired.net/kernel/Documentation/devicetree/bindings/usb/cdns-usb3.txt
  
     ./drivers/usb/cdns3/core.c (현재 상위 USB3 PHY 주소는 아래 정의됨)
        /*
         * Request memory region
         * region-0: nxp wrap registers  : 0x5B110000  none_core_regs           USB3_CTRL 
         * region-1: xHCI                : 0x5B130000  xhci_regs  (core_regs)   USB3 
         * region-2: Peripheral          : 0x5B140000  dev_regs   (core_regs)   USB3 
         * region-3: PHY registers       : 0x5B160000  phy_regs                 USB3_PHY3P0 
         * region-4: OTG registers       : 0x5B120000  otg_regs   (core_regs)   USB3 
         */
         
*/

	usbotg3: usb3@5b110000 {
		compatible = "Cadence,usb3";
		reg = <0x5B110000 0x10000>,
			<0x5B130000 0x10000>,
			<0x5B140000 0x10000>,
			<0x5B160000 0x40000>,
			<0x5B120000 0x10000>;
		interrupt-parent = <&gic>;
		interrupts = <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&usb3_lpcg 1>,
			 <&usb3_lpcg 0>,
			 <&usb3_lpcg 5>,
			 <&usb3_lpcg 2>,
			 <&usb3_lpcg 3>;
		clock-names = "usb3_lpm_clk", "usb3_bus_clk", "usb3_aclk",
			"usb3_ipg_clk", "usb3_core_pclk";
		assigned-clocks = <&clk IMX_SC_R_USB_2 IMX_SC_PM_CLK_PER>,
				  <&clk IMX_SC_R_USB_2 IMX_SC_PM_CLK_MISC>,
				  <&clk IMX_SC_R_USB_2 IMX_SC_PM_CLK_MST_BUS>;
		assigned-clock-rates = <125000000>, <12000000>, <250000000>;
		power-domains = <&pd IMX_SC_R_USB_2>;
		cdns3,usbphy = <&usb3phynop1>;
		status = "disabled";
	};


  • USB Type C 연결구조 및 USB PD 구조 
USB Type C의 경우 아래와 같이 USB2.0 (Unshielded) 과 USB3.0 (Shielded,CBTU02043) 으로 나뉘어진다. 
USB PD(Power Delivery)는 아래의 PTN5150A에 의해서 CC(Configuration Channel) 설정되며, 내부에 Current도 설정가능하므로 추후 다시 한번 살펴보자. 




OTG1/2관련내용 
Device Tree 요약하면 OTG1 설정 과 OTG3 설정(OTG2가 포함) 두개를 다 사용시 자동적으로 OTG1/2를 Switch된다고하며, OTG3를 써야 OTG2도 동작가능


OTG3 관련내용 CDNS-USB3 사용 

$ vi ./vendor/nxp-opensource/kernel_imx/arch/arm64/boot/dts/freescale/imx8x-mek.dtsi
//상위 설정에서 disable 된 것을 okay 재정의하고, USB OTG1,3 관련 세부설정 

&usbphy1 {
	status = "okay";
};

&usbotg1 {
	vbus-supply = <&reg_usb_otg1_vbus>;
	srp-disable;
	hnp-disable;
	adp-disable;
	power-active-high;
	disable-over-current;
	status = "okay";
};

&usb3phynop1 {
	status = "okay";
};

/*
  ptn5110으로 12V/5V 로 USB PD가 지원되는 것으로 보이며, USB Type C (USB3.0) 일 경우 필요 
*/

&usbotg3 {
	dr_mode = "otg";
	extcon = <&ptn5110>;
	status = "okay";
};


  • USB PD(Power Delivery) 구조 
20V 와 5V Switch로 인하여 CC1/CC2 결정과 내부 Current 결정 


PTN5110/PTN5150A (상위 그림참조) 
CC(Configuration Channel) Logic 이라고하며, 두개의 CC1/CC2를 제공 
USB PD를 위해서 12V 와 5V 선택가능한것으로 보이며, 각 Current도 조절가능 각각의 12V/5V Switch는 별도필요

반드시 참조 

기타용어 
  • OCP (Over Current Protection)
  • OPP (Over Power Protection)
  • OVP (Over Voltage Protection)
  • SCP (Short Circuit Protection)
  • OTP (Over Temperature Protection)
  • BOP (Brown Out Protection)


1.1 Kernel Config 분석방법 

Android에서 제공하는 Kernel Config 옵션이 많이 부족한것 같아 관련부분을 점검해보기로 하고, 아래와 같이 Android Config를 설정한 후 
ARM용으로 menuconfig를 실행하여 설정을 비교하기로 하였으며, menuconfig에서 빠진 내용들을 확인했다. 

$ export ARCH=arm64
//$ export CROSS_COMPILE=aarch64-linux-gnu-
//$ export AARCH64_GCC_CROSS_COMPILE=/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-
//$ export AARCH32_GCC_CROSS_COMPILE=/opt/gcc-arm-8.3-2019.03-x86_64-arm-eabi/bin/arm-eabi-
$ make imx_v8_android_defconfig      //이 설정 값 기반으로 .config을 새로 생성 
$ make menuconfig

$ cp .config org_cofig
$ make menuconfig
$ diff .config org_cofig // 비교 후 수정사항을 상위 defconfig에 추가 

$ vi out/target/product/mek_8q/obj/KERNEL_OBJ/.config
$ diff .config out/target/product/mek_8q/obj/KERNEL_OBJ/.config

$ make mrproper  // 내가 설정한 부분 전체 삭제



1.2 Kernel Config 설정 및 확인 


USB OTG 이해 및 USB Gadget의 KERNEL CONFIG 관련내용 



#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USBIP_CORE is not set
CONFIG_USB_CDNS3=y
CONFIG_USB_CDNS3_GADGET=y
CONFIG_USB_CDNS3_HOST=y
CONFIG_USB_MUSB_HDRC=y
# CONFIG_USB_MUSB_HOST is not set
# CONFIG_USB_MUSB_GADGET is not set
CONFIG_USB_MUSB_DUAL_ROLE=y
......
CONFIG_USB_LIBCOMPOSITE=y
CONFIG_USB_F_ACM=y
CONFIG_USB_F_SS_LB=y
CONFIG_USB_U_SERIAL=y
CONFIG_USB_U_ETHER=y
CONFIG_USB_U_AUDIO=y
CONFIG_USB_F_SERIAL=y
CONFIG_USB_F_OBEX=y
CONFIG_USB_F_NCM=y
CONFIG_USB_F_ECM=y
CONFIG_USB_F_EEM=y
CONFIG_USB_F_SUBSET=y
CONFIG_USB_F_RNDIS=y
CONFIG_USB_F_MASS_STORAGE=y
CONFIG_USB_F_FS=y
CONFIG_USB_F_UAC1=y
CONFIG_USB_F_UAC1_LEGACY=y
CONFIG_USB_F_UAC2=y
CONFIG_USB_F_UVC=y
CONFIG_USB_F_MIDI=y
CONFIG_USB_F_HID=y
CONFIG_USB_F_ACC=y
CONFIG_USB_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS_F_UAC1=y
CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y
CONFIG_USB_CONFIGFS_F_UAC2=y
CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
# CONFIG_USB_CONFIGFS_F_PRINTER is not set
CONFIG_USB_ZERO=m
# CONFIG_USB_ZERO_HNPTEST is not set
CONFIG_USB_AUDIO=m
# CONFIG_GADGET_UAC1 is not set
CONFIG_USB_ETH=m
CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_ETH_EEM is not set
# CONFIG_USB_G_NCM is not set
# CONFIG_USB_GADGETFS is not set            //필요할 것이라고 생각했는데, 판단미스 
# CONFIG_USB_FUNCTIONFS is not set          //필요할 것이라고 생각했는데, 판단미스
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
# CONFIG_USB_G_ACM_MS is not set
# CONFIG_USB_G_MULTI is not set
# CONFIG_USB_G_HID is not set
# CONFIG_USB_G_DBGP is not set
# CONFIG_USB_G_WEBCAM is not set
# CONFIG_USB_RAW_GADGET is not set
# CONFIG_TYPEC is not set
CONFIG_USB_ROLE_SWITCH=y


2. Android init.usb.rc (USB Gadget 수정)  


Android init.rc 문법 

Android에서는 init.rc 문법기반으로 Gadget ConfigFS 기반로 쉽게 USB Gadget들의 상태를 변경가능

  • USB Gadget(Device) 모드 설정 
Chip Vendor init.usb.rc 설정으로 실제 저장되는 곳은 /vendor/etc/init/hw/init.freescale.usb.rc 
$ vi ./device/fsl/imx8q/mek_8q/init.usb.rc
on early-boot
# USG Config FS을 이용하여 직접 init.rc에서 Gadget을 설정가능 
    mount configfs none /config
    mkdir /config/usb_gadget/g1 0770
    mkdir /config/usb_gadget/g1/strings/0x409 0770
    write /config/usb_gadget/g1/bcdUSB 0x0200
    write /config/usb_gadget/g1/idVendor 0x18d1
    write /config/usb_gadget/g1/bcdDevice 0x0440
    write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}
    write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}
    write /config/usb_gadget/g1/strings/0x409/product ${ro.product.model}
    mkdir /config/usb_gadget/g1/functions/mass_storage.0
    mkdir /config/usb_gadget/g1/functions/accessory.gs2
    mkdir /config/usb_gadget/g1/functions/audio_source.gs3
    mkdir /config/usb_gadget/g1/functions/rndis.gs4
    mkdir /config/usb_gadget/g1/functions/midi.gs5
    mkdir /config/usb_gadget/g1/functions/ffs.adb
    mkdir /config/usb_gadget/g1/functions/ffs.mtp
    mkdir /config/usb_gadget/g1/functions/ffs.ptp
    mkdir /config/usb_gadget/g1/configs/b.1 0770
    mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770
    write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1
    write /config/usb_gadget/g1/os_desc/qw_sign "MSFT100"
# USB adb  설정 
    mkdir /dev/usb-ffs 0775 shell shell
    mkdir /dev/usb-ffs/adb 0770 shell shell
    mount functionfs adb /dev/usb-ffs/adb rmode=0770,fmode=0660,uid=2000,gid=2000
# USB mtp/ptp device 설정         
    mkdir /dev/usb-ffs/mtp 0770 mtp mtp
    mkdir /dev/usb-ffs/ptp 0770 mtp mtp
    mount functionfs mtp /dev/usb-ffs/mtp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1
    mount functionfs ptp /dev/usb-ffs/ptp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1
#
# USB Android property 설정 
#   
   setprop sys.usb.mtp.device_type 3  
  
  # vendor.usb.config 설정하며, USB OTG의 주소 ( Device Tree에서 반드시 확인)   
  # ls /sys/class/udc/ 로 확인가능  
  # otg3 는 현재 Device Tree에서 별도의 Driver로 사용하며, USB3 용  (*hdrc* 가 아님)
  # gadget-cdns3 or 5b110000.usb3 (otg3)
    #setprop vendor.usb.config "5b110000.usb3"  
  #   
  # vendor.usb.config 설정하며, USB OTG의 주소 ( Device Tree에서 반드시 확인)   
  # ls /sys/class/udc/ 로 확인가능  
  # ci_hdrc.0 or 5b0d0000.usb (otg1 ,OTG1/2로 동시사용가능)
  #          
    setprop vendor.usb.config "5b0d0000.usb"
     or
    setprop vendor.usb.config "ci_hdrc.0"      
# Kernel의 libcomposite 관련부분 미사용     
    write /sys/module/libcomposite/parameters/disable_l1_for_hs "y"
# 최종 adb    
    symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1

on boot
    setprop sys.usb.configfs 2
    #jhlee (추가후 RNDIS Window 10 존재하나, Window 10에서 미인식 )
    #setprop sys.usb.controller "ci_hdrc.0"
    #setprop sys.usb.config rndis,adb
    #setprop sys.usb.configfs 1    
    #setprop sys.usb.configfs 2

  • Android system/core의 init*.rc 내용 
Android에서제공하는 property 상태에 따라 USB Gadget 설정이 변경되며, 이를 확인 
$ vi system/core/rootdir/init.usb.configfs.rc
  https://android.googlesource.com/platform/system/core/+/master/rootdir/init.usb.configfs.rc
  
//sys.usb.config=adb && property:sys.usb.configfs=0 값에 따라 변경   
$ vi system/core/rootdir/init.usb.rc 
  https://android.googlesource.com/platform/system/core/+/master/rootdir/init.usb.rc

현재 /sys/class/android_usb/android0/enable를 이용하여 방법은 이용을 해보지 못했는데, 
/sys/class/android_usb/android0은 존재하지만, 내부에 enable이 현재 생성되지 않음 



  • USB Gadget TEST 방법 
  https://www.kernel.org/doc/html/latest/usb/gadget-testing.html


  • USB Gadget RNDIS 설정시 ip route 와 iptable 설정 


2.1 Android USB Gadget 설정확인 


  • USB Gadget ConfigFS 관련부분 확인 
Android Board에서 Gadget ConfigFS와 설정된 기능 
$ ls -l /config/usb_gadget/g1/
total 0
-rw-r--r--  1 root root 4096 2021-01-05 07:12 UDC
-rw-r--r--  1 root root 4096 1970-01-01 00:00 bDeviceClass
-rw-r--r--  1 root root 4096 1970-01-01 00:00 bDeviceProtocol
-rw-r--r--  1 root root 4096 1970-01-01 00:00 bDeviceSubClass
-rw-r--r--  1 root root 4096 2021-01-01 07:26 bMaxPacketSize0
-rw-r--r--  1 root root 4096 1970-01-01 00:00 bcdDevice
-rw-r--r--  1 root root 4096 1970-01-01 00:00 bcdUSB
drwxr-xr-x  3 root root    0 1970-01-01 00:00 configs
-rw-r--r--  1 root root 4096 2021-01-01 07:26 driver_match_existing_only
drwxr-xr-x 10 root root    0 2021-01-01 05:16 functions
-rw-r--r--  1 root root 4096 1970-01-01 00:00 idProduct
-rw-r--r--  1 root root 4096 1970-01-01 00:00 idVendor
drwxr-xr-x  2 root root    0 1970-01-01 00:00 os_desc
drwxr-xr-x  3 root root    0 1970-01-01 00:00 strings

//상위 RNDIS 설정된 부분이 나오지 않아 Kernel Config 수정  
$ ls /config/usb_gadget/g1/functions/  
accessory.gs2    ffs.adb ffs.ptp        midi.gs5
audio_source.gs3 ffs.mtp mass_storage.0

//KERNEL CONFIG 추가설정
CONFIG_USB_NET_DRIVERS=y
CONFIG_USB_ETH_RNDIS=y

//Kernel Config 수정 후 USB Gadget RNDIS 확인 
$ ls /config/usb_gadget/g1/functions/ 
accessory.gs2    ffs.adb ffs.ptp        midi.gs5
audio_source.gs3 ffs.mtp mass_storage.0 rndis.gs4 

$ ls /sys/module/libcomposite  //현재 미존재하지만, RNDIS 동작확인 


Window 10 RNDIS 미인식문제 (Window 7은 문제없음)

  • Android Property 관련사항 확인 
getprop를 이용하여 현재 설정된 값들을 확인하고 강제로 변경하여 테스트 
$ getprop | grep usb
[init.svc.usb-hal-1-1]: [running]
[init.svc.usbd]: [stopped]
[persist.sys.usb.config]: [adb]
[ro.audio.usb.period_us]: [20000]
[ro.boottime.usb-hal-1-1]: [13786733000]
[ro.boottime.usbd]: [14657327000]
[sys.usb.config]: [adb]
[sys.usb.configfs]: [2]
[sys.usb.controller]: [ci_hdrc.0]
[sys.usb.ffs.ready]: [1]
[sys.usb.mtp.device_type]: [3]
[vendor.usb.config]: [ci_hdrc.0]

//상위의 init.usb.configfs.rc 중 adbd stop  
$ setprop sys.usb.configfs 1
$ setprop sys.usb.config none
$ setprop sys.usb.configfs 2

//상위의 init.usb.rc 중 rndis,adb 이용을 위해서 강제 기능 테스트 
$ setprop sys.usb.configfs 1
$ setprop sys.usb.config rndis,adb
$ setprop sys.usb.configfs 2

//상위의 init.usb.rc 중 midi,adb 이용을 위해서 강제 기능 테스트 
$ setprop sys.usb.configfs 1
$ setprop sys.usb.config midi,adb
$ setprop sys.usb.configfs 2

//상위와 같이 직접 변경하면 아래와 같이 Error 발생하여, init.usb.rc 반영하기로 결정   
init: processing action (sys.usb.config=rndis,adb && sys.usb.configfs=1) from (/init.usb.configfs.rc:131)
init: processing action (sys.usb.config=rndis,adb && sys.usb.configfs=1 && sys.usb.ffs.ready=1) from (/init.usb.configfs.rc:134)
init: Command 'write /config/usb_gadget/g1/UDC ${sys.usb.controller}' action=sys.usb.config=rndis,adb && sys.usb.configfs=1 && sys.usb.ffs.ready=1 (/init.usb.configfs.rc:139) took 0ms and failed: Unable to write to file '/config/usb_gadget/g1/UDC': Unable to write file contents: Device or resource busy

  • Android i.MX USB 관련사항 점검
i.MX8QXP 와 i.MX6를 비교를 하면 차이나며, 관련부분을 좀 더 분석해야할 것으로 생각됨
// OTG1 관련부분의 hdrc가 1개 확인
$ su
# find /sys -name  *hdrc*     
/sys/class/udc/ci_hdrc.0
/sys/devices/platform/bus@5b000000/5b0d0000.usb/ci_hdrc.0
/sys/devices/platform/bus@5b000000/5b0d0000.usb/ci_hdrc.0/udc/ci_hdrc.0
/sys/bus/platform/devices/ci_hdrc.0
/sys/bus/platform/drivers/musb-hdrc
/sys/bus/platform/drivers/ci_hdrc
/sys/bus/platform/drivers/ci_hdrc/ci_hdrc.0
/sys/bus/pci/drivers/ci_hdrc_pci
/sys/module/musb_hdrc

// OTG3,2 cdns 관련부분확인 
# find /sys -name  *cdn*
/sys/devices/platform/bus@5b000000/5b110000.usb3/xhci-cdns3
/sys/bus/platform/drivers/cdns-mhdp-imx
/sys/bus/platform/drivers/sdhci-cdns
/sys/bus/platform/drivers/cdns-usb3
/sys/bus/platform/drivers/imx-cdnhdmi
/sys/firmware/devicetree/base/bus@5b000000/usb3@5b110000/cdns3,usbphy
/sys/module/cdns3

# lsusb -t
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 003: ID 0525:a4a1
Bus 002 Device 001: ID 1d6b:0003

// USB Host에 연결된 Device 확인 (lsusb의 옵션이 제대로 안됨) 
# ls /sys/bus/usb/devices/  
1-0:1.0 1-1 1-1:1.0 1-1:1.1 2-0:1.0 usb1 usb2

# cat /sys/bus/usb/devices/1-1/idProduct
a4a1

# cat /sys/bus/usb/devices/usb1/uevent //usb1이 OTG1 일것이라고 생각했는데, OTG3 이 Host 역할 
MAJOR=189
MINOR=0
DEVNAME=bus/usb/001/001
DEVTYPE=usb_device
DRIVER=usb
OF_NAME=usb3
OF_FULLNAME=/bus@5b000000/usb3@5b110000
OF_COMPATIBLE_0=Cadence,usb3
OF_COMPATIBLE_N=1
PRODUCT=1d6b/2/504
TYPE=9/0/1
BUSNUM=001
DEVNUM=001

# exit
$


11/22/2020

USB OTG (Gadget Config FS) 사용법

1. USB Gadget Config FS 사용법 


USB Gadget Config File System은 기존의 Legacy Gadget 처럼 Kernel Module 만 올리면 되는 것이 아니라, 
USB Gadget Config File System을 Mount를 한 후 User에서 필요한 USB Device에 관해서 Descriptor 정보 와 Function을 연결하는 방식이다. 
물론 Composite Device도 지원가능하며, 이를 위해서 Multi Function 기능사용해야한다.

Python기반의 USB Gadget 관리

1.1  USB Kernel 설정 후 빌드 및 확인

  • USB OTG 사용시 Gadget 관련 Kernel 설정 및 확인 
USB Gadget에 관련된 Kernel 설정은 아래의 링크로 확인하고 관련 기능 확인 
  https://ahyuo79.blogspot.com/2020/11/usb-device-gadget-cdc.html

  • USB Gadget Kernel API
Gadget의 세부적인 구현을 하려면 반드시 알아야함  

1.2  USB Device 와  USB Function 구조 파악 

기존의 USB Legacy 와 크게 다르지 않으므로, 중략 


USB Legacy Gadget 사용법


  • USB Gadget Config FS 의 구조 와 Functions 구조 
  1. Configuration Descriptor  
  2. Interface Descriptor -> Function (USB Device) ==> Class Driver (USB Host 와 연결)
    1. included Endpoint Descriptors

https://training.ti.com/sites/default/files/docs/USB-M6-USB-in-Device-Mode.pdf

USB Gadget Config File system mount 후 아래와 같이 설정 

https://training.ti.com/sites/default/files/docs/USB-M6-USB-in-Device-Mode.pdf


2. USB Gadget Config FS 사용법 


상위 그림처럼 Kernel Config에서 설정 후  /sys/kernel/config/usb_gadget 을 mount 후 직접 USB Device 설정 및 
USB Function 부분 연결가능하며, 동작도 역시 Legacy USB Gadget 가 거의 동일하게 동작한다.  


2.1 USB Serial (g_serial 과 동일)

설정방법만 소개하고 테스트 방법 및 사용법은 기존 Legacy와 크게 다르지 않다 

  • USB Serial (ACM) 예제 
상위 g_serial 과 동일하게 동작하며, 테스트 방법도 동일 
# Check Kernel Config about Gadget and ConfigFS 
$ mount -t configfs none /sys/kernel/config
$ cd /sys/kernel/config/usb_gadget

# Create g1/g2/g3 Gadget(USB Device) STEP1
$ mkdir g1

# Set USB Device Descriptor STEP2
$ cd g1
$ ls
UDC              bMaxPacketSize0  functions        strings
bDeviceClass     bcdDevice        idProduct
bDeviceProtocol  bcdUSB           idVendor
bDeviceSubClass  configs          os_desc

$ echo "0x1d6b" > idVendor
$ echo "0x0104" > idProduct

# Create/Set USB Device Descriptor about String STEP2
$ mkdir strings/0x409
$ ls strings/0x409/
manufacturer  product       serialnumber

$ echo "0123456789" > strings/0x409/serialnumber
$ echo "Foo Inc." > strings/0x409/manufacturer
$ echo "Bar Gadget" > strings/0x409/product


# Create/Set USB Config Descriptor STEP3 
$ mkdir configs/c.1
$ ls configs/c.1
MaxPower      bmAttributes  strings

# Set USB Config Descriptor for String STEP3 
$ mkdir configs/c.1/strings/0x409
$ ls configs/c.1/strings/0x409/
configuration

# Set USB Config Descriptor for String STEP4 
$ echo "CDC ACM" > configs/c.1/strings/0x409/configuration

# Create USB Interface Descriptor (Functions)  STEP5,6 
# USB Host              /dev/ttyACMx
# USB Device (Gadget)   /dev/ttymxc4  (need g_serial)   CONFIG_USB_G_SERIAL  
$ mkdir functions/acm.GS0

# Link USB Interface Descriptor (Functions)  STEP5,6 
$ ln -s functions/acm.GS0 configs/c.1

# Check USB Gadget 의 UDC name 파악 
# i.MX의 경우 현재 USB OTG 설정은 다음과 같이 Device Tree에서 설정 
#  ci_hdrc.0 : Device  
#  ci_hdrc.1:  Host    
# TI는 musb-hdrc.0/1로 사용 
# 각 AP마다 이름이 다르며, Device Tree의 설정같이 봐야함 (아래의 UDC에 정의하면 동작함) 
$ ls /sys/class/udc/
ci_hdrc.0

# Activate USB-CDC ACM Device 동작  (Host에서 ACM, USB Serial 확인가능) 
$ echo "ci_hdrc.0" > UDC


$ find /sys -name *hdrc*  //OTG1 (ci_hdrc.0) , OTG2 (ci_hdrc.1) 검색 
/sys/kernel/debug/ci_hdrc.1
/sys/kernel/debug/ci_hdrc.0
/sys/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1
/sys/devices/soc0/soc/2100000.aips-bus/2184000.usb/ci_hdrc.0
/sys/devices/soc0/soc/2100000.aips-bus/2184000.usb/ci_hdrc.0/udc/ci_hdrc.0
/sys/class/udc/ci_hdrc.0
/sys/bus/platform/devices/ci_hdrc.0
/sys/bus/platform/devices/ci_hdrc.1
/sys/bus/platform/drivers/ci_hdrc
/sys/bus/platform/drivers/ci_hdrc/ci_hdrc.0
/sys/bus/platform/drivers/ci_hdrc/ci_hdrc.1

$ cat /sys/bus/platform/devices/ci_hdrc.0/uevent
DRIVER=ci_hdrc
MODALIAS=platform:ci_hdrc

$ cat /sys/bus/platform/devices/ci_hdrc.1/uevent
DRIVER=ci_hdrc
MODALIAS=platform:ci_hdrc

https://elixir.bootlin.com/linux/v4.9/ident/ci_hdrc

UVC Gadget 설정방법 
  https://developer.ridgerun.com/wiki/index.php?title=How_to_use_the_UVC_gadget_driver_in_Linux

Gadget Config FS 관련설정참고
  https://www.kernel.org/doc/Documentation/usb/gadget_configfs.txt
  https://www.kernel.org/doc/Documentation/usb/gadget-testing.txt
  https://www.kernel.org/doc/Documentation/filesystems/configfs/configfs.txt 


2.2 다른 설정 (상위와 거의 동일함)


상위구조처럼 생성한 후 Function 이름만 아래와 같이 변경해서 사용하면된다.

NameDriverDescriptionDocumentation
acmAbstract Control Model (CDC ACM)ACM serial link, works with Windows/Linux (use Documentation/usb/linux-cdc-acm.inf)Documentation/usb/gadget_serial.txt
gserGeneric serial bulk in/outThe function talks to the Linux-USB generic serial driver
obexObject Exchange Model (CDC OBEX)Needs an user space OBEX server
rndisRNDISMicrosoft "Remote NDIS" (RNDIS) Ethernet protocol (use Documentation/usb/linux.inf)
ecmEthernet Control Model (CDC ECM)Ethernet Control Model
eemEthernet Emulation Model (EEM)Newer USB Ethernet standard that is somewhat simpler than CDC ECM
ncmNetwork Control Model (CDC NCM)Advanced protocol for Ethernet
ffsFunction filesystem (FunctionFS)Allows to implement USB functions from user-space (e.g. for MTP)Documentation/usb/functionfs.txt
mass_storageMass storageExports a regular file or block device as USB Mass Storage disk driveDocumentation/usb/mass-storage.txt
hidHID functionGeneric emulation of USB Human Interface Devices (HID)Documentation/usb/gadget_hid.txt


USB Gadget Config FS 예제 및 Function 부분 자세히 설명 
  https://developer.toradex.com/knowledge-base/usb-device-mode-linux

2.3 Gadget Config FS 와 libusg 사용 

상위 설정을 Shell Script가 아닌 C로 작성하여 사용방법 



Android USB Config FS 관련초기설정 

Android udev 처럼 uevent 관리


3. Window RNDIS 관련문제사항 

추후 필요없는 부분 삭제 

11/18/2020

USB OTG (Gadget) Legacy 사용법

1. USB Legacy Gadget 사용법 

Kernel에서 기존부터 제공하는 Legacy Gadget 으로 Kernel의 Gadget Module Driver를 Load를 하면 쉽게 사용하는 방법이다. 

Legacy를 사용하기 위해서는 각 Kernel Legacy Gadget Driver들을 반드시 Module로 만들어서 사용해야한다.



1.1  USB Kernel 설정 후 빌드 및 확인

  • USB OTG 사용시 Gadget 관련 Kernel 설정 및 확인 
USB Gadget에 관련된 Kernel 설정은 아래의 링크로 확인하고 관련 기능 확인 
  https://ahyuo79.blogspot.com/2020/11/usb-device-gadget-cdc.html

  • USB Gadget Kernel API
Gadget의 세부적인 구현을 하려면 반드시 알아야함  
  https://ahyuo79.blogspot.com/2014/11/usb-host-gadget-debug-2.html


1.2  USB Device 와  USB Function 구조 파악 


내부적으로 보면 , Legacy Gadget Driver 역시 Kernel 의 USB Function을 사용하므로 관련소스를 보면 이해하기가 쉽다 


  • USB Device Descriptor 구조 

  1. Configuration Descriptor  
  2. Interface Descriptor -> Function (USB Device) ==> Class Driver (USB Host 와 연결)
    1. included Endpoint Descriptors

Gadget Legacy Driver 역시 내부적으로 각 Function 들과 연결되어 동작되어짐 

https://training.ti.com/sites/default/files/docs/USB-M6-USB-in-Device-Mode.pdf


2. USB Legacy Gadget Module 사용 


기본적인 사용법은 각 사용할 Module 찾아 Module을 올리면 기본적으로 동작된다. 
다만 확인해야 할 사항이 현재 UDC가 사용가능하는 것을 확인해야하고, 더불어 UDC가 사용중이면, 사용 중인 Module Driver를 제거를 한 후 다른 Module를 사용해야한다.

두 개의 기능을 동시에 사용하고 싶다면 Composite Device 을 Kernel에서 설정을 해야하며, 제한적으로 사용가능하다. 


  • 에러사항
보통 gadget을 사용중이거나, kernel에서 udc를 별도로 설정을 안했을 경우 
$ modprobe g_serial
udc-core: couldn't find an available UDC - added [g_serial] to list of pending drivers

$ lsmod   // 현재 사용중인 다른 gadget 확인 or USB Gadget ConfigFS에서 설정한 것 해제 



  • USB Legacy Gadget의 공통 Parameter 및 설정방법 
ParameterPurposeType
idVendorUSB Vendor ID(ushort)
idProductUSB Product ID(ushort)
bcdDeviceUSB Device version(BCD) (ushort)
iSerialNumberSerialNumber string(charp)
iManufacturerUSB Manufacturer string(charp)
iProductProduct string(charp)

$ vi /etc/modprobe.d/options  // modprobe usbserial vendor=0x0525 product=0xA4A6
....
options usbserial vendor=0x0525 product=0xA4A6
...

  • 반드시 필독 (아래 이외의 UVC 와 UVA g_printer  사용)
TI-USB와 다른 AP와 별차이가 없으며 쉽게 설명  
  https://training.ti.com/sites/default/files/docs/USB-M6-USB-in-Device-Mode.pdf

  • USB 모든 Gadget 기본 TET 방법 
USB Device Gadget Function기준으로 테스트 방법 


2.1 g_serial (ACM)

USB to Serial 가장 많이 사용이 되며, 동작역시 쉽게된다. 

  • USB Device 설정 
# CONFIG_USB_G_SERIAL 
# USB Gadget Driver (Device의 /dev/ttyGS0 -> Host의 ACM) 실제연결
$ modprobe g_serial
g_serial gadget: Gadget Serial v2.4
g_serial gadget: g_serial ready
g_serial gadget: high-speed config #2: CDC ACM config

  1. USB Device: ttyGS0 생성 
  2. USB Host: ttyACMx  

  • USB Device 에서 USB Host 통신확인 
Host에서 간단히 TEST Message 확인 및 socat으로 다른 /dev/ttyx 와 /dev/ttyGS0 연결
$ ls /dev/ttyGS0    // 생성확인 
/dev/ttyGS0
$ cat /sys/class/tty/ttyGS0/dev
246:0

// Host에서 USB Serial로 연결 후 Baudrate를 맘대로 변경해도 다 됨 (기본 115200) 설정 후 테스트  
$ echo "Test " > /dev/ttyGS0
$ cat /dev/ttyGS0

  https://www.kernel.org/doc/Documentation/usb/gadget_serial.txt
  https://linux-sunxi.org/USB_Gadget/Serial


2.2 g_ether (RNDIS/ECM)

Kernel 설정 및 USB Host 지원상황에 따라 USB CDC 가 달라지며, 각각 독립적인 Network이 구성되며, 각 Route Table 역시 확인해봐야한다. 

  • USB Device 설정 
$ modprobe g_ether
using random self ethernet address
using random host ethernet address
usb0: HOST MAC a2:3a:fa:76:8c:18
usb0: MAC 4a:1e:02:84:f1:3f
using random self ethernet address
using random host ethernet address
g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
g_ether gadget: g_ether ready
g_ether gadget: high-speed config #2: RNDIS

or 

$ modprobe g_ether idVendor=0x1234 idProduct=0xabcd bcdDevice=0x0304 \
iSerialNumber=sn7890 iManufacturer=myCom iProduct=demo

  • USB Device Network 설정 
아래와 같이 강제로 usb0을 up 시키거나, 자동으로 잡도록 /etc/network/interface or /etc/systemd/network/xxx.network 로 설정 

$ ifconfig usb0 up
$ ifconfig usb0
usb0      Link encap:Ethernet  HWaddr 4A:1E:02:84:F1:3F
          inet6 addr: fe80::481e:2ff:fe84:f13f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

$ ifconfig usb0 192.168.5.7



  • USB Host Network 설정 
USB Host 의 경우 usb0으로 잡혀도 route table이 link-local로 잡혀 제대로 통신이 되지 않는다. 
그러므로 별도로 route table를 설정해줘야 한다. 

$ ifconfig usb0 192.168.5.11 

// Route Table에 현재 설정한 부분이 link-local로 되며, 등록이 안됨
$ route
...
link-local      0.0.0.0         255.255.0.0     U     204    0        0 usb0
..
// 직접 Route Table에 추가 
$ sudo route add -net 192.168.5.0 netmask 255.255.255.0 usb0
....
192.168.5.0     0.0.0.0         255.255.255.0   U     0      0        0 usb0

  • USB Device 와 Host  검증 
최종테스트 Host 와 Device 사이에 ping으로 테스트 진행하며,  ifconfig에서 Packet이 전송되었는지를 반드시 확인하자 

$ ifconfig usb0        //USB Device 
usb0      Link encap:Ethernet  HWaddr 4A:1E:02:84:F1:3F
          inet addr:192.168.5.7  Bcast:192.168.5.255  Mask:255.255.255.0
          inet6 addr: fe80::b4fe:8fff:fe61:d00d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

$ ifconfig usb0        //USB Host  
usb0      Link encap:Ethernet  HWaddr A2:3A:FA:76:8C:18
          inet addr:192.168.5.11  Bcast:192.168.5.255  Mask:255.255.255.0
          inet6 addr: fe80::b4fe:8fff:fe61:d00d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

좀 더 속도 및 세부적으로 검증하고자 하면, iperf 를 이용하여 세부검증을 하자. 



2.3 g_mass_storage (MASS STORAGE)

일반적으로 내부 Partition을 연결하거나 File을 연결하여 사용하면 된다. 
내부 파일을 연결시에는 Image를 만들어서 연결해도 상관이 없지만, FAT로 Format 후 사용하자. 

Window에서 인식하기 위해서  File or Device FAT or NTFS 로 format을 해야함

$ modprobe g_mass_storage file=/dev/mmcblk0p3   
Mass Storage Function, version: 2009/09/11
LUN: removable file: (no medium)
LUN: file: /dev/mmcblk0p3
Number of LUNs=1
g_mass_storage gadget: Mass Storage Gadget, version: 2009/09/11
g_mass_storage gadget: userspace failed to provide iSerialNumber
g_mass_storage gadget: g_mass_storage ready
g_mass_storage gadget: high-speed config #1: Linux File-Backed Storage

11/15/2020

USB OTG (Gadget) 이해 및 설정

1. USB Gadget 기능 및 기본이해

오래전 부터 USB 2.0 부터 OTG가 많이지원이 되면서 Host 와 Peripheral Mode로 동시에 사용가능하도록 지원가능 했다. (정확히 하면, USB 2.0 전에 나옴)
그리고, Linux Kernel에서는 USB의 Peripheral , 즉 USB Device Mode를 지원하기 위해서 USB Gadget이라는 이름으로 Driver를 제공을 하고 이를 지원을 해서 사용했지만,
매번 사용만 하고 크게 정리하지 않아 이번 기회에 정리를 하고자 한다. 


USB Host 와 Gadget 기본 
  https://ahyuo79.blogspot.com/2014/11/usb-driver.html

USB Device Descriptor 기본구조 이해 
  https://ahyuo79.blogspot.com/2014/10/usb-device-descriptor.html

USB Interface Descriptor 와 USB Class driver 연결
  https://ahyuo79.blogspot.com/2014/11/class-descriptor.html

1.1 USB OTG의 기능 

USB OTG는 USB 2.0에서나온 기술로 On-The-Go 약어로 Host 와 Device를 동시에 사용할 수 있는 기술이다.

이 기술내에는 몇가지 지원되는 Protocol이 있으며, 관련 Protocol은 Wiki에서 찾아볼 수 있다.


  • USB Peripherals 

기본적인 USB Device로 VBUS 5V로 들어온 것을 Regulator로 3.3V 변경 

https://www.maximintegrated.com/en/design/technical-documents/tutorials/1/1822.html

  • USB OTG Tranceiver 
상위 USB Device와 다르게 두가지 역할(Host or Device) 를 위해 구성 추가되어진다. 
  1. Host or Deivce에 따라 변경가능한 Pull-up/down Tranciever 저항 (D+/D-) 
  2. 아래 A-DEVICE(Host)처럼 Vbus 5V를 모니터할 기능 (HNP 참고, C-DETECT)
  3. 아래 B-DEVICE(Device)처럼 Vbus Pulse 가능과 모니터 가능 (SNP 참고, SRP[B] )
  4. 5번째 Pin인 ID Input Pin이  아래의 ASIC에서 Output로 변경가능


https://www.maximintegrated.com/en/design/technical-documents/tutorials/1/1822.html



USB Host가 되는 법

  1. 15K pulldown resitors on D+/D- 와 Power 공급
  2. Send SOF(Start of Frame) Packets
  3. Send SETUP,IN, and OUT Packets
  4. Schedule transfers within USB 1ms frames
  5. Signal USB reset
  6. Provide USB power management
추가적으로 OTG에서는 Host 와 Device의 두개의 역할을 하므로, 회로적으로 별도의 Protocol들이 지원해야하는데, HNP 와 SNP 이다. (5Pin이 지원되는 Cable 사용)


  • Host Negotiation Protocol (HNP)
OTG dual-role device는 Host 혹은 Device로 동작이 가능하며 초기에 A-DEVICE는 Host , B-DEVICE는 Device로 동작하는 것이라면, 
USB가 연결되는 즉시, OTG의 각각의 Role은 변경될 수 있다. 5번째 ID Pin을 Host에서 GND로 연결하면, 이를 Host로 동작한다.
OTG가 Host or Device로 결정되려고 하면 반드시 필수 

https://www.maximintegrated.com/en/design/technical-documents/tutorials/1/1822.html


  • Session Request Protocol (SRP)
HNP 다음으로, B-DEVICE(Device)는 A-DEVICE(HOST)에게 Vbus power를 요청한 USB Host 와 Device의 Session이 시작되어지며,
기본조건은 상위 HNP가 동작한 후 Host가 Vbus Power 결정된 후 사용되어진다고 하며, Power Consumption에서 중요하다고 한다. 

https://www.maximintegrated.com/en/design/technical-documents/tutorials/1/1822.html


  • Attach Detection Protocol (ADP)
재미있는 기능같은데, OTG Host or Device가 USB power가 없는 상태에서 붙는 것을 결정한다고 하는데, 상위 HNP 구조와 다르게 동작할 것으로 생각된다.
또다른 Device 붙었는지 알기 위해서 주기적으로 USB의 Capacitance를 측정한다고 하며, 큰 값이 측정되며, A-Device(Host)로 Power 공급을 한다고 하며, 
그 이후에는 상위와 같이 SRP를 사용한다고 한다. 



USB 의 관련전체 


1.2  USB Host 와 Device 기본동작구조 

USB Host 와 Device 기본동작구조이지만, libusb 사용했을 경우 이며, 만약 USB Host에 Kernel Driver 존재하면 VFS를 걸치지 않고 바로 Control 


https://elinux.org/images/1/17/USB_Debugging_and_Profiling_Techniques.pdf


  • libusb 구조 
VFS(Virtual Filesystem)을 이용하지만, device filesystem으로 접근하여 연결함 


1.3 USB Gadget에 관련 File System

아래의 USB Gadget File system은 전부 Kernel에서 기본으로 지원동작가능하며, 지원되는 File system의 발전된 부분을 알아야 한다.

  • GadgetFS 
2003년에 Gadget FS로 처음 도입되었으며, 기본적으로 User space에서 동작하는 Gadget driver를 구현가능하도록 
Kernel 의 Interface로 이를 지원하며 User space에서 App기반으로 USB Gadget과 USB Host 부분을 구현가능하다.

아래의 그림과 같이 Gadget FS 와 User Space 연결되어 동작되므로 Kernel의 Linux headerGadget Filesystem mount 가 필요하다.  

https://elinux.org/images/e/ef/USB_Gadget_Configfs_API_0.pdf


  • GadgetFS 를 이용한 User App 사용시 Kernel Header 사용  
User space에서는 Gadget File system mount가 된 상태에서 동작가능 
// User App에서 Gadget Filesystem Mount 필요
$ mkdir /dev/gadget
$ mount -t gadgetfs gadgetfs /dev/gadget

// User App에서  Device 의 경우 Kernel의 Header 필요
#include <linux/types.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadgetfs.h>

//User App에서 Host 의 경우 Kernel의 Header 필요 
#include <linux/usbdevice_fs.h>
#include <linux/usb/ch9.h>

  https://blog.soutade.fr/post/2016/07/create-your-own-usb-gadget-with-gadgetfs.html

상위 기능은 요즘 거의 사용되지 않는 것으로 보인다. 쉽게 작성하려면 역시 libusb를 사용 

  • FunctionFS
2010년에 도입이 되었으며, Kernel 에서 Gadget Function 들을 제공하고 있으며, 이 기능은 USB Device의 기본동작가능하며, 
이를 기반으로 Composite USB Device도 작성도 가능하다. 
또한 여기서 끝나지 않고 Kernel의 Gadget Function User Space Gadget Function 조합도 가능하다고 하지만, 뭔가가 부족하다고 하니
지속적으로 사용해봐야 알겠다.

  • USB Gadget ConfigFS
가장 나중에 도입된 기능으로, User space에서 Config FS를 이용하여 USB Device의 Descriptor를 정의 및 설정 과 수정가능하며, 
내부적으로 FunctionFS의 기능을 쉽게 설정으로 연결하여 사용가능할 뿐 더러 더불어 Composite USB Driver도 생성가능 하다 




2.  Uboot / Linux Kernel 의 OTG 관련 설정 

Linux or Uboot에서 OTG 관련설정을 이해하도록 하며, 보통 Device Tree 부터 이해를 해야한다. 
Linux or Uboot 둘 다 요즘 동일한 Device Tree를 사용하기 때문에 , 설정을 이해하고 관련 Kernel Config를 알아 두자. 


Uboot Source로 Gadget 역시 Kernel 구조와 비슷하게 변경중

Uboot 의 Sandbox 지원 및 Sandbox 관련내용

UBoot Custodians 

Uboot Manual 


2.1  USB OTG 의 Device Tree 설정 

일반적으로 USB OTG를 사용할 경우 Device or Host가 동시에 동작이 되지만, 대부분 안정성을 위해서 하나로 설정하여 사용하기도 한다. 

Device Tree 문법설명 

아래의 설정은 USB의 레귤레이터 과 Pin 선언 설정부분이며, 즉 전원관련부분이다,
OTG를 Host를 사용할 경우, 전원공급을 해줘야 하며,  Peripheral (Device)로 사용할 경우 전원이 불필요하므로, 이를 GPIO로 On/off를 제어  

$ vi kernel-source/arch/arm/boot/dts/imx6sx-sdb.dtsi
......

regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <0>;
                
                reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
                        compatible = "regulator-fixed";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb_otg1>;
                        regulator-name = "usb_otg1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
                        enable-active-high;
                };

                reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
                        compatible = "regulator-fixed";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb_otg2>;
                        regulator-name = "usb_otg2_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
                        enable-active-high;
                };
         ....
/*
- enable-active-high	: Polarity of "enable-gpio" GPIO is active HIGH.
			  Default is active LOW.
  https://www.kernel.org/doc/Documentation/devicetree/bindings/regulator/gpio-regulator.txt         
*/
       }




실제 OTG의 동작모드를 설정하며, 각 OTG의 Protocol 옵션 사용여부 설정한다. 더불어 Phy Chip의 저항역시 설정. 

$ vi kernel-source/arch/arm/boot/dts/imx6sx-sdb.dtsi
....
/*
   USB OTG1 Peripheral Mode 가 아닌 OTG Mode (Dual Mode)          
 - dr_mode: tells Dual-Role USB controllers that we want to work on a particular mode. 
            Valid arguments are "host", "peripheral" and "otg". In case this attribute isn't
			passed via DT, USB DRD controllers should default to OTG.   
            
    아래와 같이 srp/hnp/adp는 peripheral에서 사용하는 기능이며, OTG로 사용시 disable 함 
    
 - hnp-disable: tells OTG controllers we want to disable OTG HNP,
                       normally HNP is the basic function of real OTG except you want it to be a srp-capable only B device.
 - srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is	optional for OTG device.
 - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is	optional for OTG device.
            
   https://www.kernel.org/doc/Documentation/devicetree/bindings/usb/generic.txt 
*/

&usbotg1 {
        vbus-supply = <&reg_usb_otg1_vbus>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usb_otg1_id>;
        srp-disable;
        hnp-disable;
        adp-disable;
        status = "okay";
};

/*
   USB OTG2 Host Mode (Dual Mode)
   dr_mode  Host Only 로만 변경 
*/
&usbotg2 {
        vbus-supply = <&reg_usb_otg2_vbus>;
        dr_mode = "host";
        status = "okay";
};

/*
 USB Phy 1, 2 
- fsl,tx-cal-45-dn-ohms: Integer [30-55]. Resistance (in ohms) of switchable
  high-speed trimming resistor connected in parallel with the 45 ohm resistor
  that terminates the DN output signal. Default: 45
- fsl,tx-cal-45-dp-ohms: Integer [30-55]. Resistance (in ohms) of switchable
  high-speed trimming resistor connected in parallel with the 45 ohm resistor
  that terminates the DP output signal. Default: 45
- fsl,tx-d-cal: Integer [79-119]. Current trimming value (as a percentage) of the 17.78mA TX reference current. Default: 100
  https://www.kernel.org/doc/Documentation/devicetree/bindings/phy/mxs-usb-phy.txt 
*/
&usbphy1 {
        fsl,tx-d-cal = <106>;
};

&usbphy2 {
        fsl,tx-d-cal = <106>;
};


2.2 Linux Kernel Gadget 설정 

Linux Kernel에서 Host는 많이 봐왔기 때문에 관련부분은 생략하고 , USB Device Mode로 동작될 때 사용되는 Gadget의 구조를 파악하자. 

  • Linux Kernel Gadget 기본구조 
아래의 구조의 이해는 User Interface에서 사용할때, 관련동작이 이해하기사 
kernel/drivers/usb/gadget/
kernel/drivers/usb/gadget/function/
kernel/drivers/usb/gadget/legacy/
kernel/drivers/usb/gadget/udc/

TI USB Gadget 구조 참조 
  https://e2e.ti.com/support/processors/f/791/t/825474


** Kernel Config FS 설정확인 후 USB Config 설정가능

  > File systems > Pseudo filesystems  Gadget Support
 [*] /proc file system support
 [*]   Sysctl support (/proc/sys)
 [*]   Enable /proc page monitoring 
 [ ] Include /proc/<pid>/task/<tid>/children file 
 -*- sysfs file system support  
 [*] Tmpfs virtual memory file system support (former shm fs) 
 [ ]   Tmpfs POSIX Access Control Lists
 [ ]   Tmpfs extended attributes
 -*- Userspace-driven configuration filesystem                       #CONFIG_CONFIGFS_FS 


** Kernel USB Gadget / Legacy / Function Config
 Device Drivers > USB support > USB Gadget Support
 [ ]   Debugging messages (DEVELOPMENT)                                   #CONFIG_USB_GADGET_DEBUG                               
 [ ]   Debugging information files (DEVELOPMENT)                          #CONFIG_USB_GADGET_DEBUG_FILES                           
 [ ]   Debugging information files in debugfs (DEVELOPMENT)               #CONFIG_USB_GADGET_DEBUG_FS  
 (2)   Maximum VBUS Power usage (2-500 mA)                                #CONFIG_USB_GADGET_VBUS_DRAW 
 (2)   Number of storage pipeline buffers                                 #CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS   
 [ ]   Serial gadget console support                                      #CONFIG_U_SERIAL_CONSOLE 
       USB Peripheral Controller  --->       // 별도서브메뉴로,  아래참조 drivers/usb/gadget/udc/Kconfig                    
 <*>   USB Gadget functions configurable through configfs         #CONFIG_USB_CONFIGFS , USB Gadget ConfigFS 
 [*]     Generic serial bulk in/out                                       #CONFIG_USB_CONFIGFS_SERIAL , CONFIG_USB_CONFIGFS_xx선택   
 [*]     Abstract Control Model (CDC ACM)                                 #CONFIG_USB_CONFIGFS_ACM   
 [*]     Object Exchange Model (CDC OBEX)                                 #CONFIG_USB_CONFIGFS_OBEX  
 [*]     Network Control Model (CDC NCM)                                  #CONFIG_USB_CONFIGFS_NCM   
 [*]     Ethernet Control Model (CDC ECM)                                 #CONFIG_USB_CONFIGFS_ECM  
 [*]     Ethernet Control Model (CDC ECM) subset                          #CONFIG_USB_CONFIGFS_ECM_SUBSET 
 [*]     RNDIS                                                            #CONFIG_USB_CONFIGFS_RNDIS  
 [*]     Ethernet Emulation Model (EEM)                                   #CONFIG_USB_CONFIGFS_EEM  
 [*]     Mass storage                                                     #CONFIG_USB_CONFIGFS_MASS_STORAGE  
 [*] UTP over Storage Gadget                                                 
 [*]     Loopback and sourcesink function (for testing)                   #CONFIG_USB_CONFIGFS_F_LB_SS 
 [*]     Function filesystem (FunctionFS)                            #CONFIG_USB_CONFIGFS_F_FS  , FunctionFS  
 [ ]     HID function                                                     #CONFIG_USB_CONFIGFS_F_HID 
 [ ]     Printer function                                                 #CONFIG_USB_CONFIGFS_F_PRINTER  
 <m>   USB Gadget precomposed configurations // 아래부터,아래참조 drivers/usb/gadget/legacy/Kconfig               
 <m>     Gadget Zero (DEVELOPMENT)                                        #CONFIG_USB_ZERO      
 <m>     Ethernet Gadget (with CDC Ethernet support)                      #CONFIG_USB_ETH
 [*] RNDIS support                                                        #CONFIG_USB_ETH_RNDIS  
 [ ] Ethernet Emulation Model (EEM) support                               #CONFIG_USB_ETH_EEM 
 <m>     Network Control Model (NCM) support                              #CONFIG_USB_G_NCM 
 <m>     Gadget Filesystem                                              #CONFIG_USB_GADGETFS , GadgetFS
 <m>     Function Filesystem                                            #CONFIG_USB_FUNCTIONFS   
 [ ] Include configuration with CDC ECM (Ethernet)                             #CONFIG_USB_FUNCTIONFS_ETH 
 [ ] Include configuration with RNDIS (Ethernet)                               #CONFIG_USB_FUNCTIONFS_RNDIS 
 -*- Include 'pure' configuration                                         #CONFIG_USB_FUNCTIONFS_GENERIC 
 <m>     Mass Storage Gadget                                              #CONFIG_USB_MASS_STORAGE  
 <m>     Serial Gadget (with CDC ACM and CDC OBEX support)                #CONFIG_USB_G_SERIAL 
 < >     Printer Gadget                                                   #CONFIG_USB_G_PRINTER 
 < >     CDC Composite Device (Ethernet and ACM)                          #CONFIG_USB_CDC_COMPOSITE 
 < >     CDC Composite Device (ACM and mass storage)                      #CONFIG_USB_G_ACM_MS 
 <m>     Multifunction Composite Gadget                                   #CONFIG_USB_G_MULTI
 [*] RNDIS + CDC Serial + Storage configuration                                   #CONFIG_USB_G_MULTI_RNDIS
 [ ] CDC Ethernet + CDC Serial + Storage configuration                            #CONFIG_USB_G_MULTI_CDC
 < >     HID Gadget                                                       #CONFIG_USB_G_HID 
 < >     EHCI Debug Device Gadget                                         #CONFIG_USB_G_DBGP  

Kernel USB Gadget/Function/Legacy Config  참조 
  https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/Kconfig
  https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/legacy/Kconfig


  • CONFIG_USB_LIBCOMPOSITE 과 Gadget Function 기능
  1. CONFIG_CONFIGFS_FS 
  2. CONFIG_USB_GADGET 
  3. 상위 두개 선택시 자동 선택되며, 2개이상의 다중 USB Gadget Function 위해 사용
  4. 이 기능은 CONFIGFS의 FUNCTION 설정일 뿐이지 실제 Device가 아님
예를들면, RNDIS 필요하다면, 
  1. FUNCTION 설정 (CONFIG_USB_F_RNDIS)
  2. CONFIG_USB_ETH_RNDIS도 필요

libcomposite (CONFIG_USB_LIBCOMPOSITE) 관련사용법 
  https://wiki.tizen.org/USB/Linux_USB_Layers/Configfs_Composite_Gadget

libcomposite USB Gadget Function 의 경우 USB Gadget 선택시 자동선택 
  https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/Kconfig


** UDC (USB Device Controller) Config
 > Device Drivers > USB support > USB Gadget Support > USB Peripheral Controller
 <m> Freescale Highspeed USB DR Peripheral Controller                     #CONFIG_USB_FSL_USB2
 < > Faraday FUSB300 USB Peripheral Controller
 < > Faraday FOTG210 USB Peripheral Controller 
 < > Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver
 < > Renesas R8A66597 USB Peripheral Controller 
 < > PXA 27x 
 < > Marvell USB2.0 Device Controller 
 < > MARVELL PXA2128 USB 3.0 controller
 < > Synopsys USB 2.0 Device controller
 < > Renesas M66592 USB Peripheral Controller
 < > Broadcom USB3.0 device controller IP driver(BDC)
 < > PLX NET2272  
 < > Xilinx USB Driver 
 < > Dummy HCD (DEVELOPMENT)

USB Gadget UDC Config 
  https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/udc/Kconfig

USB Kernel Config


3. USB Gadget 설정기능확인  

기본으로 sys file system으로 설정된 UDC 와 설정된 Kernel Module들을 확인하자.
더불어 Kernel Debug가 지원되면 관련부분도 설정하여 살펴보자.
 
  • USB 의 UDC (USB Device Controller) 확인 
상위에 설정한 UDC의 기능정보 확인 및 이름확인
# UDC의 이름 확인 각 Chip Maker마다 이름이 다름 TI musb 이며 or 주소로도 표시됨 
# 상위 Device Tree에서 OTG 1은 OTG (ci_hdrc.0) 사용 , OTG 2는 Host Only (ci_hdrc.1) 
$ ls /sys/class/udc
ci_hdrc.0

# Chip Maker 마다 UDC에서 제공되는 기능으로 전부 다를 수 있음 
$ ls /sys/class/udc/ci_hdrc.0
a_alt_hnp_support  device             is_selfpowered     srp
a_hnp_support      function           maximum_speed      state
b_hnp_enable       is_a_peripheral    power              subsystem
current_speed      is_otg             soft_connect       uevent

# UDC의 Device 상태 
$ ls /sys/class/udc/ci_hdrc.0/device/
driver           modalias         subsystem
driver_override  power            udc
gadget           role             uevent

# UDC의 Device 미사용상태 (udevd 사용) 
$ cat /sys/class/udc/ci_hdrc.0/uevent
USB_UDC_NAME=2184000.usb

# UDC의 Device 미사용상태 
$ cat /sys/class/udc/ci_hdrc.0/current_speed
UNKNOWN

# UDC의 Device Legacy로 g_ether 설정상태 (속도확인가능) 
$ cat /sys/class/udc/ci_hdrc.0/current_speed
high-speed

# UDC의 Device Legacy로 g_ether 설정상태 (udevd 추후 함께 사용)
$ cat /sys/class/udc/ci_hdrc.0/uevent
DRIVER=g_ether
USB_UDC_NAME=2184000.usb
USB_UDC_DRIVER=g_ether

상위 (Kernel Device Tree의 otg1 -> ci_hdrc.0)
ci_hdrc.x 의 관련정보이며, chip vendor와 kernel version 마다 이름은 다를 수 있음 (주의)
  https://www.kernel.org/doc/html/latest/usb/chipidea.html

  • USB Kernel Module 관련사항
현재 Function은 Module로 생성하지 않았으며, legcay 역시 내부적으로 Function을 호출하여 사용하고 동작한다. 
# 각 usb gadget module 확인 (상위 Kernel에서 Module로 안했다면 없음) 
$ ls /lib/modules/$(uname -r)/kernel/drivers/usb/gadget/
legacy  udc

$ ls /lib/modules/$(uname -r)/kernel/drivers/usb/gadget/legacy
g_acm_ms.ko        g_ffs.ko           g_ncm.ko           gadgetfs.ko
g_cdc.ko           g_mass_storage.ko  g_serial.ko
g_ether.ko         g_multi.ko         g_zero.ko

$ ls /lib/modules/$(uname -r)/kernel/drivers/usb/gadget/udc
fsl_usb2_udc.ko


  • Kernel Debug On
USB Gadget Config FS로 설정한 상태로 확인 
# Kernel Debug 기능이 동작이 되어야 하며, 상위 UDC 이름으로  간단히 Debug 
# mount -t debugfs none /sys/kernel/debug  , 자동 mount 함  (CONFIG_DEBUG_FS)
# https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/ch09s07.html
# 

$ ls /sys/kernel/debug/ci_hdrc.0
device     port_test  qheads     registers  requests   role

$ cat /sys/kernel/debug/ci_hdrc.0/role
gadget

$ cat /sys/kernel/debug/ci_hdrc.0/device
speed             = 3
max_speed         = 3
is_otg            = 0
is_a_peripheral   = 0
b_hnp_enable      = 0
a_hnp_support     = 0
a_alt_hnp_support = 0
name              = 2184000.usb
gadget function   = g1
gadget max speed  = 5