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

댓글 없음 :