2023年9月24日 星期日

Linux Kernel(25.1)- Gadget Configfs


這篇是gadget_configfs.txt的心得, 透過Dummy HCD的模擬, 就可以不用真的去連USH host才能驗證Gadget了.
首先把Dummy HCD與USB Gadget functions configurable through configf選成built-in了, 方便後面驗證, 下面就直接用例子說明
/ # lsusb 查看目前USB裝置, ID <Vendor ID>:<Device ID>
Bus 001 Device 001: ID 1d6b:0002 可以看到目前只有一組, 1B6D是Linux Foundation, 0002是2.0 root hub

/ # mount -t configfs none /sys/kernel/config/ 要把configfs掛起來才能開始設定gadget
/ # mount
rootfs on / type rootfs (rw,size=40392k,nr_inodes=10098)
tmpfs on /dev type tmpfs (rw,relatime,size=64k,mode=755)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
none on /sys/kernel/config type configfs (rw,relatime)

步驟一(Creating the gadgets) : 每一個Gadget都要建立自己的目錄, 並在其子目錄下做設定, 
我們就約定俗成取成g1吧
格式如下:
	$ mkdir /sys/kernel/config/usb_gadget/<gadget name>
/ # mkdir /sys/kernel/config/usb_gadget/g1 
/ # cd /sys/kernel/config/usb_gadget/g1

每個Gadget都需要有自己的VID與PID, 
格式如下:
	$ echo <VID> > idVendor
	$ echo <PID> > idProduct
/sys/kernel/config/usb_gadget/g1 # echo 0x1d6b > idVendor
/sys/kernel/config/usb_gadget/g1 # echo 0x0104 > idProduct

接著要為每個Gadget設定serial number, manufacturer和product strings
而這些設定會放置在strings底的語系的目錄下, 這裡0x409是英語系
格式如下:
	$ echo <serial number> > strings/0x409/serialnumber
	$ echo <manufacturer> > strings/0x409/manufacturer
	$ echo <product> > strings/0x409/product
/sys/kernel/config/usb_gadget/g1 # mkdir strings/0x409
/sys/kernel/config/usb_gadget/g1 # echo "Brook Technologies" > strings/0x409/manufacturer
/sys/kernel/config/usb_gadget/g1 # echo "Brook's Dummy Storage Gadget" > strings/0x409/product
/sys/kernel/config/usb_gadget/g1 # echo "12345678" > strings/0x409/serialnumber

步驟二(Creating the configurations) : 每個Gadget都會包含許多配置(configurations), 
這些configurations對應的目錄都要被建立,
格式如下:
	$ mkdir configs/<name>.<number>
每個configuration都需要自己的strings與語系, 比如
	$ mkdir configs/c.1/strings/0x409
	$ echo <configuration> > configs/c.1/strings/0x409/configuration
也有一些attributes如MaxPower需要被設定,    
/sys/kernel/config/usb_gadget/g1 # mkdir configs/c.1
/sys/kernel/config/usb_gadget/g1 # mkdir configs/c.1/strings/0x409
/sys/kernel/config/usb_gadget/g1 # echo 'Brook_Gadget' > configs/c.1/strings/0x409/configuration
/sys/kernel/config/usb_gadget/g1 # echo 250 > configs/c.1/MaxPower

步驟三 (Creating the functions) : 每個Gadget都會提供一些function, 每個function都要有對應的目錄
格式如下:
	$ mkdir functions/<name>.<instance name>
name還有對應的attribute可以參考Documentation/ABI/*/configfs-usb-gadget*
以下以mass_storage為範例, 並參考ABI/testing/configfs-usb-gadget-mass-storage
/sys/kernel/config/usb_gadget/g1 # mkdir functions/mass_storage.usb0
Mass Storage Function, version: 2009/09/11
LUN: removable file: (no medium)
/sys/kernel/config/usb_gadget/g1 # ls functions/mass_storage.usb0/
lun.0  stall
/sys/kernel/config/usb_gadget/g1 # ls functions/mass_storage.usb0/lun.0/
cdrom           inquiry_string  removable
file            nofua           ro

參數stall: 必須設為true.
/sys/kernel/config/usb_gadget/g1 # echo 1 > functions/mass_storage.usb0/stall

參數lun.0/removable: 是否可被移除
/sys/kernel/config/usb_gadget/g1 # echo 0 > functions/mass_storage.usb0/lun.0/removable

參數lun.0/ro: 是否唯讀
/sys/kernel/config/usb_gadget/g1 # echo 0 > functions/mass_storage.usb0/lun.0/ro

參數lun.0/file: 如果設定為lun.0/removable=0, 就要提供LUN的備份檔案路徑
/sys/kernel/config/usb_gadget/g1 # dd if=/dev/zero of=/mass.vfat bs=1M count=8
8+0 records in
8+0 records out
8388608 bytes (8.0MB) copied, 0.133141 seconds, 60.1MB/s
/sys/kernel/config/usb_gadget/g1 # mkfs.vfat /mass.vfat
/sys/kernel/config/usb_gadget/g1 # echo '/mass.vfat' > functions/mass_storage.usb0/lun.0/file

步驟四 (Associating the functions with their configurations) : 
格式如下:
	$ ln -s functions/<name>.<instance name> configs/<name>.<number>
    
/sys/kernel/config/usb_gadget/g1 # ln -s functions/mass_storage.usb0 configs/c.1/

步驟五 (Enabling the gadget) : 
基本上enable gadget就是把它跟UDC(USB Device Controller)做綁定. UDC可以在/sys/class/udc/找到
比如我的系統是"dummy_udc.0", 把把他echo 到UDC就可以了
/sys/kernel/config/usb_gadget/g1 # ls /sys/class/udc/
dummy_udc.0
/sys/kernel/config/usb_gadget/g1 # echo dummy_udc.0 > UDC
底下就是長出來的USB Disk了
usb 1-1: new high-speed USB device number 2 using dummy_hcd
usb 1-1: New USB device found, idVendor=1d6b, idProduct=0104, bcdDevice= 5.15
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Brook's Dummy Storage Gadget
usb 1-1: Manufacturer: Brook Technologies
usb 1-1: SerialNumber: 12345678
usb-storage 1-1:1.0: USB Mass Storage device detected
scsi host0: usb-storage 1-1:1.0
scsi 0:0:0:0: Direct-Access     Linux    File-Stor Gadget 0515 PQ: 0 ANSI: 2
sd 0:0:0:0: Power-on or device reset occurred
sd 0:0:0:0: [sda] 16384 512-byte logical blocks: (8.39 MB/8.00 MiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 sda:
sd 0:0:0:0: [sda] Attached SCSI disk

/sys/kernel/config/usb_gadget/g1 # lsusb
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 002: ID 1d6b:0104
下次有機會再多介紹幾個gadget吧

    參考資料:
  • Documentation/usb/gadget_configfs.txt



沒有留言:

張貼留言

熱門文章