Configurare nod bazat pe CM108
Introducere
Pentru secțiunea principală legată de instalarea și configurarea svxlink, vezi acest link.
Vezi și documentația completă despre HIDRAW la HIDRAW - Raw Access to USB and Bluetooth Human Interface Devices.
Verificări hardware
Verificare recunoaștere chip CM108
Mai întâi trebuie conectate fizic terminalele D+ și D- ale mufei cu pinii test de pe Raspberry Pi. Pentru o imagine a pinilor-test, vezi acest link.
După conectarea fizică (prin lipire) a pinilor D+ și D- în paralel cu port-ul USB 2.0 al plăcii-mamă, trebuie verificat că sistemul recunoaște chip-ul CM108 ca subsistem audio.
Se rulează comanda lsusb:
tom@raspberrypi:~ $ lsusb
În răspunsul sistemului trebuie să se regăsească C-Media Electronics, Inc. USB Audio Device:
tom@raspberrypi:~ $ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0d8c:0012 C-Media Electronics, Inc. USB Audio Device
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Ia aminte la VID și PID (vendor ID și Product ID 0d8c:0012. Aceste informații trebuie folosite la crearea regulilor din udev.
Verificarea se mai poate face și cu comanda cat:
tom@raspberrypi:~ $ cat /proc/asound/cards
0 [Device ]: USB-Audio - USB Audio Device
C-Media Electronics Inc. USB Audio Device at usb-0000:01:00.0-1.3, full speed
Verificare stack HID (Human Interface Device)
O verificare mai detaliată se poate face cu comanda lsusb -v -d VID:PID unde VID și PID sunt vendorID respectiv productID:
tom@rpi-yo3iti:/etc/udev/rules.d $ lsusb -v -d 0d8c:0012
Bus 001 Device 003: ID 0d8c:0012 C-Media Electronics, Inc. USB Audio Device
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0d8c C-Media Electronics, Inc.
idProduct 0x0012
bcdDevice 1.00
iManufacturer 1 C-Media Electronics Inc.
iProduct 2 USB Audio Device
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x00e0
bNumInterfaces 4
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 0x0047
bInCollection 2
baInterfaceNr(0) 1
baInterfaceNr(1) 2
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bNrChannels 2
wChannelConfig 0x0003
Left Front (L)
Right Front (R)
iChannelNames 0
iTerminal 0
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 2
wTerminalType 0x0201 Microphone
bAssocTerminal 0
bNrChannels 1
wChannelConfig 0x0001
Left Front (L)
iChannelNames 0
iTerminal 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 6
wTerminalType 0x0301 Speaker
bAssocTerminal 0
bSourceID 9
iTerminal 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 7
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 10
iTerminal 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 9
bSourceID 1
bControlSize 1
bmaControls(0) 0x01
Mute Control
bmaControls(1) 0x02
Volume Control
bmaControls(2) 0x02
Volume Control
iFeature 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 10
bSourceID 2
bControlSize 1
bmaControls(0) 0x43
Mute Control
Volume Control
Automatic Gain Control
bmaControls(1) 0x00
iFeature 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 1
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 14
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 2 Discrete
tSamFreq[ 0] 48000
tSamFreq[ 1] 44100
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 9
Transfer Type Isochronous
Synch Type Adaptive
Usage Type Data
wMaxPacketSize 0x00c8 1x 200 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 1 Milliseconds
wLockDelay 0x0001
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 7
bDelay 1 frames
wFormatTag 0x0001 PCM
AudioStreaming Interface Descriptor:
bLength 14
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 1
bSubframeSize 2
bBitResolution 16
bSamFreqType 2 Discrete
tSamFreq[ 0] 48000
tSamFreq[ 1] 44100
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 13
Transfer Type Isochronous
Synch Type Synchronous
Usage Type Data
wMaxPacketSize 0x0064 1x 100 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioStreaming Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x01
Sampling Frequency
bLockDelayUnits 0 Undefined
wLockDelay 0x0000
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.00
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 60
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x87 EP 7 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 2
Setarea regulilor în udev
udev este un subsistem Linux pentru gestionarea evenimentelor-dispozitiv. Pentru utilizarea nodurilor bazate pe CM108 prin intermediul HIDRAW, este necesarea crearea unor reguli de gestionare a evenimentelor legate de acest dispozitiv.
Un articol foarte bine scris despre udev poate fi accesat la An introduction to Udev: The Linux subsystem for managing device events. Link-ul este dat și în secțiunea Link-uri externe
Creare fișier reguli
Pentru nodurile realizate cu CM108 trebuie creat un fișier de reguli în udev pentru a încărca modului CM108 ca dispozitiv audio hidraw
# block pulseaudio using the soundcard for SVXLINK
# astea sunt foarte importante
ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="013c", ENV{PULSE_IGNORE}="1"
ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="000c", ENV{PULSE_IGNORE}="1"
ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", ENV{PULSE_IGNORE}="1"
# create a symlink /dev/hidrawX to /dev/cm108gpio
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="013c", SYMLINK+="my_custom_dev_entry", MODE="0666"
# 0d8c:000c
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="000c", SYMLINK+="my_custom_dev_entry", MODE="0666"
# 0d8c:0012 CM108B
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", SYMLINK+="my_custom_dev_entry", MODE="0666"
Secvența ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012" trebuie să corespundă cu informația dată de lsusb.
Eu folosesc doar liniile evidențiate.
În cazul meu, creez un fișier în /etc/udev/rules.d. L-am numit 55-cm108.rules. Numărul de la începutul denumirii asigură prioritatea.
Acest fișier conține:
# block pulseaudio using the soundcard for SVXLINK
# astea sunt foarte importante
ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", ENV{PULSE_IGNORE}="1"
# creez un symlink /dev/hidrawX la /dev/yo3iti
# 0d8c:0012 CM108B
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", SYMLINK+="yo3iti", MODE="0666"
Actualizarea udev se face cu comanda:
tom@raspberrypi:~ $ sudo udevadm control --reload-rules && sudo udevadm trigger
Verificare fișier reguli
Se verifică încărcarea corectă a regulilor prin udevadm info /dev/yo3iti. Vezi liniile cu informațiile ID_VENDOR_FROM_DATABASE și DEVLINKS:
tom@rpi-yo3iti:/etc/udev/rules.d $ udevadm info /dev/yo3iti
P: /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.3/0003:0D8C:0012.0001/hidraw/hidraw0
M: hidraw0
R: 0
U: hidraw
D: c 242:0
N: hidraw0
L: 0
S: yo3iti
E: DEVPATH=/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.3/0003:0D8C:0012.0001/hidraw/hidraw0
E: DEVNAME=/dev/hidraw0
E: MAJOR=242
E: MINOR=0
E: SUBSYSTEM=hidraw
E: USEC_INITIALIZED=5866251
E: ID_VENDOR_FROM_DATABASE=C-Media Electronics, Inc.
E: PULSE_IGNORE=1
E: DEVLINKS=/dev/yo3iti
NOTĂ: comanda completă este udevadm info -a -n /dev/yo3iti care dă informații extrem de detaliate despre tot stack-ul.
Setări svxlink.conf
Izolarea nodului doar în mod Echolink
Nodul poate fi configurat doar pentru conectare la Echolink. Trebuie eliminată intrarea ReflectorLogic din secțiunea [GLOBAL] a fișierului de configurare:
[GLOBAL]
...
LOGICS=SimplexLogic
#,ReflectorLogic
...
TIMESTAMP_FORMAT="%Y-%m-%d %H:%M:%S"
CARD_SAMPLE_RATE=48000
CARD_CHANNELS=1
#LINKS=ReflectorLink
LOCATION_INFO=LocationInfo
Configurarea Tx și Rx
Apoi se modifică secțiunile Rx și Tx cu setările necesare pentru hidraw:
[Rx1]
...
SQL_DET=HIDRAW
HID_DEVICE=/dev/yo3iti
HID_SQL_PIN=VOL_DN
...
[Tx1]
...
PTT_TYPE=Hidraw
HID_DEVICE=/dev/yo3iti
HID_PTT_PIN=GPIO3
...
Unde my_custom_dev_entry e setarea din udev.
Grijă la utilizarea majusculelor pentru SQL_DET și PTT_TYPE
sudo udevadm control --reload-rules && sudo udevadm trigger
Corecție software pentru LED de squelch
LED-ul galben care indică deschiderea și închiderea squelch-ului este conectat la GPIO4 al CM108. Pentru activarea acestui indicator sunt necesari câțiva pași adiționali:
- Compilarea și instalarea utilitarului cm108
- Modificarea
Logic.tcldin/opt/rolink/share/svxlink/events.d/Logic.tcl
Compilarea și instalarea utilitarului cm108
ATENȚIE !!! Ultimele versiuni de nod cu CM108 (versiunea 2.0) nu mai folosesc acest GPIO pentru indicatorul de SQL, deci modificarea Logic.tcl și pașii de mai jos nu mai sunt valabile.
Sursa acestui utilitar se poate descărca de la https://github.com/twilly/cm108.
La compilare cu make all trebuie modificat ușor fișierul Makefile care, în forma de pe github, dă erori de linker. Eu l-am modificat în:
CC=gcc
CFLAGS=-Wall
LDFLAGS=-ludev
#cm108: cm108.o
OBJECTS=cm108.o
all: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o cm108 $(LDFLAGS)
.PHONY: install
install: cm108
sudo cp cm108 /usr/local/bin
# cp 99-cm108-cmedia.rules /etc/udev/rules.d
.PHONY: clean
clean:
rm -f cm108 *.o
Programul trebuie instalat în /usr/local/bin cu make install
Se poate testa prin
tom@rpi-yo3iti:/ $ cm108 -p
VID PID Product Sound ADEVICE HID [ptt]
--- --- ------- ----- ------- ---------
** 0d8c 0012 USB Audio Device /dev/snd/controlC0 /dev/hidraw0
** 0d8c 0012 USB Audio Device /dev/snd/pcmC0D0c plughw:0,0 /dev/hidraw0
** 0d8c 0012 USB Audio Device /dev/snd/pcmC0D0p plughw:0,0 /dev/hidraw0
LED-ul galben pentru squelch se poate testa cu comenzile:
Pentru aprindere:
tom@rpi-yo3iti:/ $ cm108 -H /dev/hidraw0 -P 4 -L 1
Pentru stingere:
tom@rpi-yo3iti:/ $ cm108 -H /dev/hidraw0 -P 4 -L 0
Dacă aceste comenzi funcționează cum trebuie, mai trebuie modificat Logic.tcl pentru a permite aprinderea și stingerea la apăsarea, respectiv eliberarea PTT-ului stației.
Modificarea Logic.tcl
Se editează Logic.tcl din /opt/rolink/share/svxlink/events.d/Logic.tcl:
tom@rpi-yo3iti:~ $ sudo nano /opt/rolink/share/svxlink/events.d/Logic.tcl
Prin adăugarea liniei care apelează executabilul cm108:
#
# Executed each time the squelch is opened or closed
# rx_id - The ID of the RX that the squelch opened/closed on
# is_open - Set to 1 if the squelch is open or 0 if it's closed
#
proc squelch_open {rx_id is_open} {
exec cm108 -H /dev/hidraw0 -P 4 -L $is_open;
variable sql_rx_id;
#puts "The squelch is $is_open on RX $rx_id";
set sql_rx_id $rx_id;
}
Se dă restart la svxlink și apoi se testează funcționarea: LED-ul galben trebuie să se aprindă la apăsarea PTT-ului și să se stingă la eliberarea acestuia.