понедельник, 16 сентября 2013 г.

BeagleBone Black - USB Device Gadget - Ethernet, Serial, Mass Storage

Как вы уже заметили из заголовка сегодня мы будем использовать USB Device свойства МП AM3359. Вообще на самом деле оба порта USB могут работать в режиме OTG, но для упрощения схемотехники один из них сделан так чтобы работать в режиме Device, а второй в режиме Host. Если с режимом Host в ОС Linux всё более или менее понятно, то с режимом Device есть некоторые особенности.


Введение
Как уже я рассказывал в статье про загрузку МП AM3359, при подключении USB кабеля устройство эмулирует сетевую карту. Так вот существует возможность подобной эмуляции и для ОС Linux. Как отмечалось выше USB может работать в двух режимах:
в режиме Host драйвер USB ожидает подключения, и в соответствии с идентификатором подключённого устройства выбирает драйвер;
в режиме Device в зависимости от выбранного драйвера, USB блок определяется под соответствующим идентификатором и работает в определённом режиме приёма-передачи. Я не буду вдаваться глубоко в теорию, об этом вам расскажет оригинальный мануал на МП, а также вводная информация о протоколе, откуда вы можете подчерпнуть полезны ссылок на документацию. Вместо этого я лишь коротко опишу основные положения касательно практической части применения USB Device для платы BeagleBone Black.

Настройка ядра
Для того чтобы воспользоватся подобным функционалом его необходимо включить в ядре Linux. Поэтому перейдём к настройкам ядра:

# cd kernel/kernel; make -j9 ARCH=arm CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi- menuconfig

После в появившемся меню необходимо активировать следующие пункты:
Symbol: USB_GADGET [=y]
  Prompt: USB Gadget Support
    Defined at drivers/usb/gadget/Kconfig:16
    Depends on: USB_SUPPORT
    Location:
      -> Kernel configuration
        -> Device Drivers
          -> USB support (USB_SUPPORT [=y])

Для поддержки USB Gadget, без которого собственно у нас ничего не заработает.
Prompt: Driver Mode
    Defined at drivers/usb/musb/Kconfig:68
    Depends on: USB_SUPPORT && USB_MUSB_HDRC
    Location:
      -> Kernel configuration
        -> Device Drivers
          -> USB support (USB_SUPPORT [=y])
            -> Inventra Highspeed Dual Role Controller (TI, ADI, ...) 

Для поддержки 2 режимного контроллера в ядре Linux.
Symbol: USB_G_MASS_STORAGE_CDC [=m]
  Prompt: CDC ACM + Mass Storage configuration
    Defined at drivers/usb/gadget/Kconfig:814
    Depends on: <choice> && BLOCK
    Location:
      -> Kernel configuration
        -> Device Drivers
          -> USB support (USB_SUPPORT [=y])
            -> USB Gadget Support (USB_GADGET [=y])
              -> USB Gadget Drivers (<choice> [=m])
              -> USB Gadget Drivers (<choice> [=m])

Выбрать для поддержки CDC и Mass Storage профиля.
Symbol: USB_ETH [=m]
   Prompt: Ethernet Gadget (with CDC Ethernet support)
     Defined at drivers/usb/gadget/Kconfig:628
     Depends on: <choice> && NET
     Location:
       -> Kernel configuration
         -> Device Drivers
           -> USB support (USB_SUPPORT [=y])
             -> USB Gadget Support (USB_GADGET [=y])
               -> USB Gadget Drivers (<choice> [=m])

А это для поддержки Ethernet соединения
Symbol: USB_G_SERIAL [=m]
    Type  : tristate
    Prompt: Serial Gadget (with CDC ACM and CDC OBEX support)
      Defined at drivers/usb/gadget/Kconfig:751
      Depends on: <choice>
      Location:
        -> Device Drivers
          -> USB support (USB_SUPPORT [=y])
            -> USB Gadget Support (USB_GADGET [=y])
              -> USB Gadget Drivers (<choice> [=m])
     Selects: USB_LIBCOMPOSITE [=m]

Для поддержки последовательного порта

Также можно добавить и другие профили которые находятся в том же меню конфигурации.

После вышеуказанных настроек необходимо собрать ядро Linux и установить его в соответствии со статьей про установку ядра, а также не забыть установить модули ядра (это отмечалось в статье про установку базовой системы). Итак ядро готово к использованию USB Device режима, теперь можно рассмотреть всё это с практической части.

Модуль g_serial.ko
Модуль отвечающий за последовательный порт. Информация о модуле:

# modinfo g_serial
filename:       /lib/modules/3.8.13-00715-g836d639/kernel/drivers/usb/gadget/g_serial.ko
license:        GPL
author:         David Brownell
author:         Al Borchers
description:    Gadget Serial v2.4
license:        GPL
author:         Felipe Balbi
srcversion:     A7058FBDCF3A5E10C147597
depends:        libcomposite
intree:         Y
vermagic:       3.8.13-00715-g836d639 SMP mod_unload modversions ARMv7 thumb2 p2v8 
parm:           idVendor:USB Vendor ID (ushort)
parm:           idProduct:USB Product ID (ushort)
parm:           bcdDevice:USB Device version (BCD) (ushort)
parm:           iSerialNumber:SerialNumber string (charp)
parm:           iManufacturer:USB Manufacturer string (charp)
parm:           iProduct:USB Product string (charp)
parm:           use_acm:Use CDC ACM, default=yes (bool)
parm:           use_obex:Use CDC OBEX, default=no (bool)
parm:           n_ports:number of ports to create, default=1 (uint)

Модуль прост в использовании:

# modprobe g_serial

После подключения модуля в списке USB устройств ПК появится последовательный порт:

$ lsusb
...
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 011: ID 0525:a4a7 Netchip Technology, Inc. Linux-USB Serial Gadget (CDC ACM mode)
Bus 002 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
...

Также появится сообщение о его подключении в dmesg:

[ 8056.520011] usb 2-1.1: New USB device found, idVendor=0525, idProduct=a4a7
[ 8056.520014] usb 2-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 8056.520017] usb 2-1.1: Product: Gadget Serial v2.4
[ 8056.520020] usb 2-1.1: Manufacturer: Linux 3.8.13-00715-g836d639 with musb-hdrc
[ 8056.520151] usb 2-1.1: usb_probe_device
[ 8056.520155] usb 2-1.1: configuration #2 chosen from 1 choice
[ 8056.520539] usb 2-1.1: adding 2-1.1:2.0 (config #2, interface 0)
[ 8056.520703] cdc_acm 2-1.1:2.0: usb_probe_interface
[ 8056.520709] cdc_acm 2-1.1:2.0: usb_probe_interface - got id
[ 8056.520713] cdc_acm 2-1.1:2.0: This device cannot do calls on its own. It is not a modem.
[ 8056.520761] cdc_acm 2-1.1:2.0: ttyACM0: USB ACM device
[ 8056.521129] usb 2-1.1: adding 2-1.1:2.1 (config #2, interface 1)

К порту можно подключится. Также будет сообщение и от ядра Linux в BeagleBone Black:

[ 1391.712610]  gadget: high-speed config #2: CDC ACM config
[ 1391.712634]  gadget: activate acm ttyGS0



Видео примера работы этого гаджета:


Модуль g_mass_storage.ko
Модуль отвечающий за Mass Storage, или по русски за класс USB - накопитель.
Вот информация о модуле:

# modinfo g_mass_storage
filename:       /lib/modules/3.8.13-00715-g836d639/kernel/drivers/usb/gadget/g_mass_storage.ko
license:        GPL
author:         Michal Nazarewicz
description:    Mass Storage Gadget
srcversion:     64711342A1DEA234CA40760
depends:        libcomposite
intree:         Y
vermagic:       3.8.13-00715-g836d639 SMP mod_unload modversions ARMv7 thumb2 p2v8 
parm:           num_buffers:Number of pipeline buffers (uint)
parm:           idVendor:USB Vendor ID (ushort)
parm:           idProduct:USB Product ID (ushort)
parm:           bcdDevice:USB Device version (BCD) (ushort)
parm:           iSerialNumber:SerialNumber string (charp)
parm:           iManufacturer:USB Manufacturer string (charp)
parm:           iProduct:USB Product string (charp)
parm:           file:names of backing files or devices (array of charp)
parm:           ro:true to force read-only (array of bool)
parm:           removable:true to simulate removable media (array of bool)
parm:           cdrom:true to simulate CD-ROM instead of disk (array of bool)
parm:           nofua:true to ignore SCSI WRITE(10,12) FUA bit (array of bool)
parm:           luns:number of LUNs (uint)
parm:           stall:false to prevent bulk stalls (bool)

Модуль чуть сложнее в использовании (для примера возьмём первый раздел нашей карты памяти, где находится U-Boot и MLO):

# modprobe g_mass_storage file=/dev/mmcblk0p1

Аргумент file служит для указания файла, устройства. При подключении в списках устройств появится носитель:

$ lsusb
...
Bus 002 Device 021: ID 0525:a4a5 Netchip Technology, Inc. Pocketbook Pro 903
Bus 002 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
...

А также будет сообщение в dmesg:

[ 9810.048424] usb 2-1.1: New USB device found, idVendor=0525, idProduct=a4a5
[ 9810.048425] usb 2-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 9810.048427] usb 2-1.1: Product: Mass Storage Gadget
[ 9810.048428] usb 2-1.1: Manufacturer: Linux 3.8.13-00715-g836d639 with musb-hdrc
[ 9810.048517] usb 2-1.1: usb_probe_device
[ 9810.048519] usb 2-1.1: configuration #1 chosen from 1 choice
[ 9810.048804] usb 2-1.1: adding 2-1.1:1.0 (config #1, interface 0)
[ 9810.049007] usb-storage 2-1.1:1.0: usb_probe_interface
[ 9810.049011] usb-storage 2-1.1:1.0: usb_probe_interface - got id
[ 9810.049051] usb-storage 2-1.1:1.0: Quirks match for vid 0525 pid a4a5: 10000
[ 9810.049083] scsi7 : usb-storage 2-1.1:1.0
[ 9811.048546] scsi 7:0:0:0: Direct-Access     Linux    File-CD Gadget   0308 PQ: 0 ANSI: 2
[ 9811.048797] sd 7:0:0:0: Attached scsi generic sg2 type 0
[ 9811.049864] sd 7:0:0:0: [sdb] 102400 512-byte logical blocks: (52.4 MB/50.0 MiB)
[ 9811.153779] sd 7:0:0:0: [sdb] Write Protect is off
[ 9811.153785] sd 7:0:0:0: [sdb] Mode Sense: 0f 00 00 00
[ 9811.256998] sd 7:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 9811.467991]  sdb:
[ 9811.675818] sd 7:0:0:0: [sdb] Attached SCSI disk

Устройство будет доступно как обыкновенный диск, также будет сообщение в BeagleBone Black:

[ 3150.257963]  gadget: high-speed config #1: Linux File-Backed Storage
[ 3150.257993]  gadget: set_config: interface 0 (Mass Storage Function) requested delayed status

Видео:


Модуль g_ether.ko
Этот модуль отвечает за эмуляцию RNDIS/Ethernet устройств. Вот информация по этому модулю:

# modinfo g_ether       
filename:       /lib/modules/3.8.13-00715-g836d639/kernel/drivers/usb/gadget/g_ether.ko
license:        GPL
author:         David Brownell, Benedikt Spanger
description:    RNDIS/Ethernet Gadget
srcversion:     DCB8F1700BB1E7FA244B25B
depends:        libcomposite
intree:         Y
vermagic:       3.8.13-00715-g836d639 SMP mod_unload modversions ARMv7 thumb2 p2v8 
parm:           qmult:queue length multiplier at high/super speed (uint)
parm:           dev_addr:Device Ethernet Address (charp)
parm:           host_addr:Host Ethernet Address (charp)
parm:           idVendor:USB Vendor ID (ushort)
parm:           idProduct:USB Product ID (ushort)
parm:           bcdDevice:USB Device version (BCD) (ushort)
parm:           iSerialNumber:SerialNumber string (charp)
parm:           iManufacturer:USB Manufacturer string (charp)
parm:           iProduct:USB Product string (charp)
parm:           use_eem:use CDC EEM mode (bool)

Использование аналогично g_serial:

# modprobe g_ether

При подключении будет отображён тип и класс устройства:

nis@jane ~ $ lsusb
...
Bus 002 Device 029: ID 0525:a4a2 Netchip Technology, Inc. Linux-USB Ethernet/RNDIS Gadget
Bus 002 Device 005: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC
...

В dmesg, будет же сообщение о новом сетевом интерфейсе, который можно использовать:

[10434.976282] usb 2-1.1: New USB device found, idVendor=0525, idProduct=a4a2
[10434.976285] usb 2-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[10434.976288] usb 2-1.1: Product: RNDIS/Ethernet Gadget
[10434.976290] usb 2-1.1: Manufacturer: Linux 3.8.13-00715-g836d639 with musb-hdrc
[10434.976434] usb 2-1.1: usb_probe_device
[10434.976438] usb 2-1.1: configuration #1 chosen from 2 choices
[10434.976656] usb 2-1.1: adding 2-1.1:1.0 (config #1, interface 0)
[10435.007888] cdc_eem 2-1.1:1.0: usb_probe_interface
[10435.007894] cdc_eem 2-1.1:1.0: usb_probe_interface - got id
[10435.008415] cdc_eem 2-1.1:1.0 usb0: register 'cdc_eem' at usb-0000:00:1d.0-1.1, CDC EEM Device, 4a:86:24:76:9d:1f
[10435.008441] usbcore: registered new interface driver cdc_eem
[10435.023835] usbcore: registered new interface driver cdc_subset

В утилите ifconfig ПК можно будет обнаружить новое сетевое устройство (на логе оно уже настроено):

$ ifconfig
...
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.7.1  netmask 255.255.255.0  broadcast 192.168.7.255
        inet6 fe80::4886:24ff:fe76:9d1f  prefixlen 64  scopeid 0x20<link>
        ether 4a:86:24:76:9d:1f  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1  bytes 96 (96.0 B)
        TX errors 8  dropped 0 overruns 0  carrier 0  collisions 0

Это также относится и к BeagleBone Black в dmesg который будет отображено сообщение о сетевом устройстве:

[ 3776.973806]  gadget: high-speed config #1: CDC Ethernet (EEM)
[ 3776.973818]  gadget: init eem
[ 3776.973827]  gadget: activate eem

ifconfig также показывает новое сетевое соединение (на логе оно ещё не настроено):

# ifconfig -a
...
usb0: flags=4098<BROADCAST,MULTICAST>  mtu 1500
        ether 72:ed:a4:27:d3:56  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Активируем соединение:

# ifconfig usb0 192.168.7.2 up

После чего можно проверить с ПК как плата отвечает на запросы (ping):

$ ping 192.168.7.2
PING 192.168.7.2 (192.168.7.2) 56(84) bytes of data.
64 bytes from 192.168.7.2: icmp_seq=1 ttl=64 time=0.447 ms
64 bytes from 192.168.7.2: icmp_seq=2 ttl=64 time=0.196 ms
^C
--- 192.168.7.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.196/0.321/0.447/0.126 ms

Так и в обратном направлении с платы на ПК:

# ping 192.168.7.1
PING 192.168.7.1 (192.168.7.1) 56(84) bytes of data.
64 bytes from 192.168.7.1: icmp_seq=1 ttl=64 time=0.271 ms
64 bytes from 192.168.7.1: icmp_seq=2 ttl=64 time=0.260 ms
64 bytes from 192.168.7.1: icmp_seq=3 ttl=64 time=0.306 ms
^C
--- 192.168.7.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.260/0.279/0.306/0.019 ms

Т.к. это обыкновенная с точки зрения пользователя сетевая карта, то её можно настроить в соответствии с мануалом по настройке сети в Gentoo Linux.

При подготовке мануала использовалась оригинальная документация на Linux Kernel, а также мануалы от свободного общества https://developer.ridgerun.com по настройке сети в МП Ti Davinchi DM365, данные с различных форумов посвящённых встраиваемой электронике.