Dependency Issues with ALSA (libao and sndfile) - c

I have written a small program to play PCM audio files using a reference from github with slight modifications for my application. The program is compiling fine, but I am having a few runtime issues regarding dependencies and ALSA devices.
The errors I am receiving are:
ERROR: Failed to load plugin /usr/lib/x86_64-linux-gnu/ao/plugins-4/libsndio.so => dlopen() failed
ERROR: Failed to load plugin /usr/lib/x86_64-linux-gnu/ao/plugins-4/libnas.so => dlopen() failed
ao_alsa WARNING: Unable to open surround playback. Trying default device...
ALSA lib pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
ao_alsa ERROR: Unable to open ALSA device 'default' for playback => No such file or directory
I have been researching many different solutions and none seem to be working, including adding a line to the alsa.conf file in /etc/modprobe.d (however, these solutions suggest adding a line in reference to intel when I am using an AMD setup.
Here is the full code:
/*
*
* ao_example.c
*
* Written by Stan Seibert - July 2001
*
* Legal Terms:
*
* This source file is released into the public domain. It is
* distributed without any warranty; without even the implied
* warranty * of merchantability or fitness for a particular
* purpose.
*
* Function:
*
* This program opens the default driver and plays a 440 Hz tone for
* one second.
*
* Compilation command line (for Linux systems):
*
* gcc -o ao_example ao_example.c -lao -ldl -lm -lsndfile
*
*/
#include <stdio.h>
#include <string.h>
#include <ao/ao.h>
#include <math.h>
#include <sndfile.h>
#define BUF_SIZE 4096
static void clean(ao_device *device, SNDFILE *file){
ao_close(device);
sf_close(file);
ao_shutdown();
}
int main(int argc, char **argv)
{
ao_device *device;
ao_sample_format format;
unsigned long count;
int default_driver;
short *buffer;
int buf_size;
int sample;
int i;
//FILE *fp;
SF_INFO sfinfo;
if (argc != 2){
printf("usage: %s <filename>\n", argv[0]);
exit(1);
}
/* -- Initialize -- */
fprintf(stderr, "libao example program\n");
SNDFILE *fp = sf_open(argv[1], SFM_READ, &sfinfo);
// fp = fopen(argv[1], "rb");
if (fp == NULL){
printf("Cannot open %s.\n", argv[1]);
exit(1);
}
printf("samples: %d\n", sfinfo.frames);
printf("sample rate: %d\n", sfinfo.samplerate);
printf("Channels: %d\n", sfinfo.channels);
ao_initialize();
/* -- Setup for default driver -- */
default_driver = ao_default_driver_id();
switch(sfinfo.format & SF_FORMAT_SUBMASK){
case SF_FORMAT_PCM_16:
format.bits = 16;
break;
case SF_FORMAT_PCM_24:
format.bits = 24;
break;
case SF_FORMAT_PCM_32:
format.bits = 32;
break;
case SF_FORMAT_PCM_S8:
format.bits = 8;
break;
case SF_FORMAT_PCM_U8:
format.bits = 8;
break;
default:
format.bits = 24;
break;
}
format.channels = sfinfo.channels;
format.rate = sfinfo.samplerate;
format.byte_format = AO_FMT_LITTLE;
// format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
// memset(&format, 0, sizeof(format));
// format.bits = 24;
// format.channels = 16;
// format.rate = 48000;
// format.byte_format = AO_FMT_LITTLE;
/* -- Open driver -- */
device = ao_open_live(default_driver, &format, NULL /* no options */);
if (device == NULL) {
fprintf(stderr, "Error opening device.\n");
return 1;
}
// fseek(fp, 0, SEEK_END);
// count = ftell(fp);
// fseek(fp, 0, SEEK_SET);
// // printf("count: %ld\n", count);
buffer = calloc(BUF_SIZE, sizeof(short));
while(1){
int read = sf_read_short(fp, buffer, BUF_SIZE);
if (ao_play(device, (char *) buffer, (uint_32)(read * sizeof(short))) == 0){
printf("ao_play: failed\n");
clean(device, fp);
break;
}
}
clean(device, fp);
return 0;
}
I hope someone else has had the same trouble and can shed light on the solution. Thank you.

To summarise the discussion:
The problem does not seem to lie within the code per se but in the libao configuration.
According to the libao documentation, the library tries to determine a default driver as follows:
In the absence of configuration files to explicit identify a default
driver, the library will try to detect a suitable default driver. It
does this by testing every available live output driver (using
ao_plugin_test()) and finding the driver with the highest priority
(see the ao_info struct) that works. Drivers with priority 0, such as
the null and file output drivers, are never selected as the default.
The error messages indicate that several drivers including nas, sndio and alsa are tried. Choosing the driver manually with ao_driver_id(...) instead of using ao_default_driver_id() fixes the issue.
Further problems with opening the device with ao_open_live(...) can be investigated by getting the corresponding error number with printf("errno %d\n", errno);. The output can be interpreted as follows:
AO_ENODRIVER (1) - No driver corresponds to driver_id.
AO_ENOTLIVE (3) - This driver is not a live output device.
AO_EBADOPTION (4) - A valid option key has an invalid value.
AO_EOPENDEVICE (5) - Cannot open the device (for example, if /dev/dsp cannot be opened for writing).
AO_EFAIL (100) - Any other cause of failure.
Besides that debugging can be enabled in the ~/.libao configuration file to get further information.

Here is the lsmod output:
Module Size Used by
rfcomm 81920 4
cmac 16384 2
algif_hash 16384 1
algif_skcipher 16384 1
af_alg 28672 6 algif_hash,algif_skcipher
bnep 24576 2
nls_iso8859_1 16384 1
hid_logitech_hidpp 45056 0
input_leds 16384 0
joydev 24576 0
hid_logitech_dj 28672 0
hid_generic 16384 0
snd_hda_codec_realtek 131072 1
snd_hda_codec_generic 81920 1 snd_hda_codec_realtek
ledtrig_audio 16384 1 snd_hda_codec_generic
snd_hda_codec_hdmi 61440 1
snd_hda_intel 53248 4
edac_mce_amd 32768 0
snd_intel_dspcfg 28672 1 snd_hda_intel
iwlmvm 393216 0
snd_hda_codec 139264 4 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec_realtek
snd_hda_core 94208 5 snd_hda_codec_generic,snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_hda_codec_realtek
mac80211 905216 1 iwlmvm
snd_hwdep 20480 1 snd_hda_codec
snd_pcm 114688 4 snd_hda_codec_hdmi,snd_hda_intel,snd_hda_codec,snd_hda_core
amdgpu 5218304 11
libarc4 16384 1 mac80211
snd_seq_midi 20480 0
snd_seq_midi_event 16384 1 snd_seq_midi
kvm 712704 0
snd_rawmidi 36864 1 snd_seq_midi
snd_seq 69632 2 snd_seq_midi,snd_seq_midi_event
crct10dif_pclmul 16384 1
snd_seq_device 16384 3 snd_seq,snd_seq_midi,snd_rawmidi
ghash_clmulni_intel 16384 0
iwlwifi 352256 1 iwlmvm
snd_timer 40960 2 snd_seq,snd_pcm
aesni_intel 372736 3
iommu_v2 20480 1 amdgpu
crypto_simd 16384 1 aesni_intel
gpu_sched 36864 1 amdgpu
cryptd 24576 3 crypto_simd,ghash_clmulni_intel
glue_helper 16384 1 aesni_intel
usbhid 57344 1 hid_logitech_dj
ttm 102400 1 amdgpu
wmi_bmof 16384 0
hid 135168 4 usbhid,hid_generic,hid_logitech_dj,hid_logitech_hidpp
rapl 20480 0
drm_kms_helper 217088 1 amdgpu
efi_pstore 16384 0
cfg80211 778240 3 iwlmvm,iwlwifi,mac80211
cec 53248 1 drm_kms_helper
rc_core 61440 1 cec
snd 94208 19 snd_hda_codec_generic,snd_seq,snd_seq_device,snd_hda_codec_hdmi,snd_hwdep,snd_hda_intel,snd_hda_codec,snd_hda_codec_realtek,snd_timer,snd_pcm,snd_rawmidi
fb_sys_fops 16384 1 drm_kms_helper
syscopyarea 16384 1 drm_kms_helper
sysfillrect 16384 1 drm_kms_helper
sysimgblt 16384 1 drm_kms_helper
k10temp 16384 0
ccp 98304 0
soundcore 16384 1 snd
btusb 57344 0
btrtl 24576 1 btusb
btbcm 16384 1 btusb
btintel 28672 1 btusb
mac_hid 16384 0
bluetooth 581632 31 btrtl,btintel,btbcm,bnep,btusb,rfcomm
ecdh_generic 16384 1 bluetooth
ecc 32768 1 ecdh_generic
sch_fq_codel 20480 3
hwmon_vid 16384 0
parport_pc 45056 0
ppdev 24576 0
lp 20480 0
drm 552960 9 gpu_sched,drm_kms_helper,amdgpu,ttm
parport 65536 3 parport_pc,lp,ppdev
ip_tables 32768 0
x_tables 49152 1 ip_tables
autofs4 45056 2
crc32_pclmul 16384 0
xhci_pci 20480 0
nvme 49152 2
i2c_piix4 28672 0
igb 221184 0
ahci 40960 0
libahci 36864 1 ahci
xhci_pci_renesas 20480 1 xhci_pci
i2c_algo_bit 16384 2 igb,amdgpu
nvme_core 114688 4 nvme
dca 16384 1 igb
wmi 32768 1 wmi_bmof
video 49152 0
and here is the aplay -L output:
default
Playback/recording through the PulseAudio sound server
surround21
2.1 Surround output to Front and Subwoofer speakers
surround40
4.0 Surround output to Front and Rear speakers
surround41
4.1 Surround output to Front, Rear and Subwoofer speakers
surround50
5.0 Surround output to Front, Center and Rear speakers
surround51
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71
7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
null
Discard all samples (playback) or generate zero samples (capture)
samplerate
Rate Converter Plugin Using Samplerate Library
speexrate
Rate Converter Plugin Using Speex Resampler
jack
JACK Audio Connection Kit
oss
Open Sound System
pulse
PulseAudio Sound Server
upmix
Plugin for channel upmix (4,6,8)
vdownmix
Plugin for channel downmix (stereo) with a simple spacialization
hdmi:CARD=Generic,DEV=0
HD-Audio Generic, HDMI 0
HDMI Audio Output
hdmi:CARD=Generic,DEV=1
HD-Audio Generic, HDMI 1
HDMI Audio Output
hdmi:CARD=Generic,DEV=2
HD-Audio Generic, HDMI 2
HDMI Audio Output
dmix:CARD=Generic,DEV=3
HD-Audio Generic, HDMI 0
Direct sample mixing device
dmix:CARD=Generic,DEV=7
HD-Audio Generic, HDMI 1
Direct sample mixing device
dmix:CARD=Generic,DEV=8
HD-Audio Generic, HDMI 2
Direct sample mixing device
dsnoop:CARD=Generic,DEV=3
HD-Audio Generic, HDMI 0
Direct sample snooping device
dsnoop:CARD=Generic,DEV=7
HD-Audio Generic, HDMI 1
Direct sample snooping device
dsnoop:CARD=Generic,DEV=8
HD-Audio Generic, HDMI 2
Direct sample snooping device
hw:CARD=Generic,DEV=3
HD-Audio Generic, HDMI 0
Direct hardware device without any conversions
hw:CARD=Generic,DEV=7
HD-Audio Generic, HDMI 1
Direct hardware device without any conversions
hw:CARD=Generic,DEV=8
HD-Audio Generic, HDMI 2
Direct hardware device without any conversions
plughw:CARD=Generic,DEV=3
HD-Audio Generic, HDMI 0
Hardware device with all software conversions
plughw:CARD=Generic,DEV=7
HD-Audio Generic, HDMI 1
Hardware device with all software conversions
plughw:CARD=Generic,DEV=8
HD-Audio Generic, HDMI 2
Hardware device with all software conversions
usbstream:CARD=Generic
HD-Audio Generic
USB Stream Output
sysdefault:CARD=Generic_1
HD-Audio Generic, ALC1220 Analog
Default Audio Device
front:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
Front speakers
surround21:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
4.0 Surround output to Front and Rear speakers
surround41:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
dmix:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
Direct sample mixing device
dsnoop:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
Direct sample snooping device
hw:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
Direct hardware device without any conversions
plughw:CARD=Generic_1,DEV=0
HD-Audio Generic, ALC1220 Analog
Hardware device with all software conversions
usbstream:CARD=Generic_1
HD-Audio Generic
USB Stream Output

Related

ESP IDF: Task never leaves vTaskDelay()

I am building a system that creates a WLAN AP over which the end user can Connect/disconnect the ESP to another AP ( For example a router) by posting a JSON String to a URL. In APSTA mode. When this is done a bool "_STA_START" is set to true. And the login parameters are saved in _STA_WIFI_SSID and _STA_WIFI_PASS.
I encounter a problem when writing the Task that manages the esp as Station. When the vTaskDelay() is called the code in the vTask_Manage_STA_Connection() just stops running. If I delete the statement. The code runs very fast until it casues a stack overflow and resets the esp.
start_Manage_STA_Connection() is called in main.c after I initialise the esp as Access Point.
Right now I see on the monitor that the loop in the vTask_Manage_STA_Connection runs a single time.
Below you can find my Tasks.c and Task.h
Task.h
#ifndef INCLUDE
#define INCLUDE
#include "config.h"
#endif
#ifndef INCLUDE_WLAN_STA
#define INCLUDE_WLAN_STA
#include "WLAN_STA.h"
#endif
// Dimensions the buffer that the task being created will use as its stack.
// NOTE: This is the number of words the stack will hold, not the number of
// bytes. For example, if each stack item is 32-bits, and this is set to 100,
// then 400 bytes (100 * 32-bits) will be allocated.
#define STACK_SIZE 2048
/// #brief Starts a Task to Manage the STA Connection
/// #param pvParameters
void vTask_Manage_STA_Connection( void * pvParameters );
/// #brief Calls vTask_Manage_STA_Connection in main.c
/// #param
void start_Manage_STA_Connection( void );
Tasks.c
#include "Tasks.h"
static const char *TAG_Manage_STA = "Manage STA Connection";
// Task to be created.
void vTask_Manage_STA_Connection(void *pvParameters)
{
for (;;)
{
// Task code goes here.
if (_STA_START == true)
{
ESP_LOGI(TAG_Manage_STA, "Connecting to Station...");
wifi_init_sta(
_STA_WIFI_SSID,
_STA_WIFI_PASS);
_STA_START = false;
}
ESP_LOGI(TAG_Manage_STA, "Managing STA Connection...");
vTaskDelay(100/portTICK_PERIOD_MS);
}
}
// Function that creates a task.
void start_Manage_STA_Connection(void)
{
static uint8_t ucParameterToPass;
TaskHandle_t xHandle = NULL;
// Create the task pinned to core 0, storing the handle. Note that the passed parameter ucParameterToPass
// must exist for the lifetime of the task, so in this case is declared static. If it was just an
// an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
// the new task attempts to access it.
xTaskCreatePinnedToCore(vTask_Manage_STA_Connection,
"Manage_STA_Connection",
STACK_SIZE,
&ucParameterToPass,
(configMAX_PRIORITIES-1),
&xHandle, 0);
configASSERT(xHandle);
// Use the handle to delete the task.
if (xHandle != NULL)
{
vTaskDelete(xHandle);
}
}
The Monitor Output:
I (0) cpu_start: App cpu up.
I (388) cpu_start: Pro cpu start user code
I (388) cpu_start: cpu freq: 160000000
I (388) cpu_start: Application information:
I (392) cpu_start: Project name: wifi_softAP
I (398) cpu_start: App version: 1
I (402) cpu_start: Compile time: Dec 5 2022 11:50:36
I (408) cpu_start: ELF file SHA256: 3597702b82953470...
I (414) cpu_start: ESP-IDF: v4.4.2
I (419) heap_init: Initializing. RAM available for dynamic allocation:
I (426) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (432) heap_init: At 3FFB7508 len 00028AF8 (162 KiB): DRAM
I (438) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (445) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (451) heap_init: At 400944E0 len 0000BB20 (46 KiB): IRAM
I (459) spi_flash: detected chip: gd
I (462) spi_flash: flash io: dio
I (467) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (559) MAIN: ESP_WIFI_MODE_AP/STA
I (569) WLAN AP: Wifi Loop Started
I (579) wifi:wifi driver task: 3ffc0378, prio:23, stack:6656, core=0
I (579) system_api: Base MAC address is not set
I (579) system_api: read default base MAC address from EFUSE
I (609) wifi:wifi firmware version: eeaa27d
I (609) wifi:wifi certification version: v7.0
I (609) wifi:config NVS flash: enabled
I (609) wifi:config nano formating: disabled
I (609) wifi:Init data frame dynamic rx buffer num: 32
I (619) wifi:Init management frame dynamic rx buffer num: 32
I (619) wifi:Init management short buffer num: 32
I (629) wifi:Init dynamic tx buffer num: 32
I (629) wifi:Init static rx buffer size: 1600
I (629) wifi:Init static rx buffer num: 10
I (639) wifi:Init dynamic rx buffer num: 32
I (639) wifi_init: rx ba win: 6
I (649) wifi_init: tcpip mbox: 32
I (649) wifi_init: udp mbox: 6
I (649) wifi_init: tcp mbox: 6
I (659) wifi_init: tcp tx win: 5744
I (659) wifi_init: tcp rx win: 5744
I (669) wifi_init: tcp mss: 1440
I (669) wifi_init: WiFi IRAM OP enabled
I (669) wifi_init: WiFi RX IRAM OP enabled
I (689) phy_init: phy_version 4670,719f9f6,Feb 18 2021,17:07:07
I (789) wifi:mode : sta (30:ae:a4:80:4e:88) + softAP (30:ae:a4:80:4e:89)
I (789) wifi:enable tsf
I (789) wifi:Total power save buffer number: 16
I (789) wifi:Init max length of beacon: 752/752
I (789) wifi:Init max length of beacon: 752/752
I (799) WLAN AP: Error: Unknown AP Exception
I (799) WLAN AP: wifi_init_softap finished. SSID:myssid password:mypassword channel:4
I (799) WLAN AP: Access point started!
I (819) Manage STA Connection: Managing STA Connection...
I (91529) wifi:new:<1,1>, old:<1,1>, ap:<1,1>, sta:<0,0>, prof:1
I (91529) wifi:station: 1c:bf:ce:ca:79:de join, AID=1, bgn, 40U
I (91549) WLAN AP: station 1c:bf:ce:ca:79:de join, AID=1
I (91559) esp_netif_lwip: DHCP server assigned IP to a station, IP is: 192.168.5.2
I (91559) AP Webserver: Starting webserver
I (91559) AP Webserver: Starting server on port: '80'
I (91569) AP Webserver: Registering URI handlers
W (95189) wifi:<ba-add>idx:2 (ifx:1, 1c:bf:ce:ca:79:de), tid:0, ssn:190, winSize:64

Error while checking audio capture device

Hello I am trying to check if a Beaglebone AI is getting correctly I2S from a TIDA-1454 so if I try to arecord test.wav I get:
debian#beaglebone:/etc$ arecord -d 10 ALSA lib
pcm_dsnoop.c:638:(snd_pcm_dsnoop_open) unable to open slave arecord:
main:828: audio open error: No such file or directory
But the card is detected since i get this output from arecord -l:
**** List of CAPTURE Hardware Devices ****
card 1: PCM5102a [PCM5102a], device 0: davinci-mcasp.0-pcm5102a-hifi pcm5102a-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
or arecord -L:
debian#beaglebone:/var/lib/cloud9$ arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
onboard
onboard_capture_left
onboard_playback_left
onboard_capture_right
onboard_playback_right
plug_onboard_capture_left
plug_onboard_playback_left
default
sysdefault:CARD=PCM5102a
PCM5102a,
Default Audio Device
dmix:CARD=PCM5102a,DEV=0
PCM5102a,
Direct sample mixing device
dsnoop:CARD=PCM5102a,DEV=0
PCM5102a,
Direct sample snooping device
hw:CARD=PCM5102a,DEV=0
PCM5102a,
Direct hardware device without any conversions
plughw:CARD=PCM5102a,DEV=0
PCM5102a,
Hardware device with all software conversions
and ALSA configuration:
pcm.onboard{
type hw
card 0
}
ctl.onboard {
type hw
card 0
}
### Dsnoop splited channels
pcm.onboard_capture_left {
type dsnoop
ipc_key 32
slave {
pcm "onboard"
channels 2
rate 48000
format S32_LE
}
bindings.0 0
}
pcm.onboard_playback_left {
type dmix
ipc_key 33
slave {
pcm "onboard"
channels 2
}
bindings.0 0
}
pcm.onboard_capture_right {
type dsnoop
ipc_key 32
slave {
pcm "onboard"
channels 2
rate 48000
format S32_LE
}
bindings.0 1
}
pcm.onboard_playback_right {
type dmix
ipc_key 33
slave {
pcm "onboard"
channels 2
}
bindings.0 1
}
### PLUGS ##
### used with darkice
### device = plug:plug_onboard_left
pcm.plug_onboard_capture_left{
type plug
slave.pcm "onboard_capture_left"
}
pcm.plug_onboard_playback_left{
type plug
slave.pcm "onboard_playback_left"
}
pcm.!default {
type asym
playback.pcm "plug_onboard_playback_left"
capture.pcm "plug_onboard_capture_left"
}
So what can it be the problem?
When recording you should tell alsa what device to use:
**** List of CAPTURE Hardware Devices ****
card 1: PCM5102a [PCM5102a], device 0: davinci-mcasp.0-pcm5102a-hifi >pcm5102a-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
Your device address is : hw:1,0 (card 1, device 0 )
So :
arecord --device="hw:1,0" test.wav
He should ask you for the format, for instance:
Available format:
- S8
- S16_LE
Then you can add the format :
arecord --device="hw:1,0" -f S16_LE test.wav

Slave PCM not usable when using ALSA multi plugin

I am trying to use the multi ALSA plugin to copy my desktop audio to the Loopback device created by snd-aloop. However, when I try to use the .asoundrc below, I get this error:
> aplay -vv test.wav
Playing WAVE 'test.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo
ALSA lib pcm_params.c:2226:(snd1_pcm_hw_refine_slave) Slave PCM not usable
aplay: set_params:1314: Broken configuration for this PCM: no configurations available
.asoundrc:
pcm.both {
type multi
slaves.a.pcm "dmixer"
slaves.b.pcm "loop"
slaves.a.channels 2
slaves.b.channels 2
bindings.0 { slave a; channel 0; }
bindings.1 { slave a; channel 1; }
bindings.2 { slave b; channel 0; }
bindings.3 { slave b; channel 1; }
}
pcm.dmixer {
type dmix
ipc_key 1231
ipc_perm 0666
slave.pcm "hw:PCH,0"
slave.channels 2
slave.rate 48000
slave.format S32_LE
bindings {
0 0
1 1
}
}
pcm.loop {
type dmix
ipc_key 29637
slave {
pcm "hw:Loopback,0"
rate 48000
format S32_LE
channels 2
period_size 1024
buffer_size 9182
}
}
pcm.hubcap {
type plug
slave {
pcm "hw:Loopback,1,0"
rate 48000
format S32_LE
}
}
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "both"
ttable [
[ 1 0 1 0 ]
[ 0 1 0 1 ]
]
}
capture.pcm "plug:dsnoop"
}
defaults.pcm.surround21.card off
defaults.pcm.surround21.device off
defaults.pcm.surround40.card off
defaults.pcm.surround40.device off
defaults.pcm.surround41.card off
defaults.pcm.surround41.device off
defaults.pcm.surround50.card off
defaults.pcm.surround50.device off
defaults.pcm.surround51.card off
defaults.pcm.surround51.device off
defaults.pcm.surround71.card off
defaults.pcm.surround71.device off
Things to note:
When I remove both dmixes, it works fine.
In the multi plugin, when I change both slaves to the same pcm, it works fine for that one pcm.
Ex.
...
type multi
slaves.a.pcm "dmixer"
slaves.b.pcm "dmixer"
...
Try setting slave.period_size 1024 in pcm.dmixer block.

Why does the read with lsusb fails?

I need to read the response from a control unit of a motor. After the write of a command beginning with ?, the motor unit should respond with some text. I.e. on ?MSG it should report its status. But when I try to read the status the unit sends nothing and the request ends with a timeout.
The code is pretty straightforward and uses libusb. The program detaches all active drivers from the device, attaches itself to the device, transfers the command ?MSG and waits for response. After that it detaches and ends.
Why there is no response? Is there any error in code or is it an issue of the motor unit? I am sure that commands are sent and received by the unit as the motor moves, for example, on PSET1=4000
#include <assert.h>
#include <string.h>
#define VENDOR_ID 0x0483
#define PRODUCT_ID 0x5740
#define BULK_EP_IN 0x03
#define BULK_EP_OUT 0x81 // From computer to control unit
#define INTERFACE_IN 0
#define INTERFACE_OUT 1
#define BUF_SIZE 64
int main()
{
libusb_context *ctx;
libusb_device_handle *dev_handle;
int r = 0;
int actual, length, received;
char cmd[] = "?MSG\r\n";
char buffer[BUF_SIZE];
length = strlen(cmd);
r = libusb_init(&ctx);
assert(r == 0);
/* Set verbosity level to 3, as suggested in the documentation */
libusb_set_debug(ctx, 3);
/* Get device handle */
dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID);
assert(dev_handle != NULL);
/* Find out if kernel driver is attached on IN iface */
if(libusb_kernel_driver_active(dev_handle, INTERFACE_IN) == 1) {
printf("Kernel Driver Active\n");
assert(libusb_detach_kernel_driver(dev_handle, INTERFACE_IN) == 0);
printf("Kernel Driver Detached!\n");
}
if(libusb_kernel_driver_active(dev_handle, INTERFACE_OUT) == 1) {
printf("Kernel Driver Active\n");
assert(libusb_detach_kernel_driver(dev_handle, INTERFACE_OUT) == 0);
printf("Kernel Driver Detached!\n");
}
/* Claim IN interface of device */
r = libusb_claim_interface(dev_handle, INTERFACE_IN);
assert(r >= 0);
/* claim OUT interface of device */
r = libusb_claim_interface(dev_handle, INTERFACE_OUT);
assert(r >= 0);
/* Transfer commands */
r = libusb_bulk_transfer(dev_handle, BULK_EP_IN, (unsigned char *)cmd, length, &actual, 0);
assert(r == 0 && actual > 0 && actual == length);
printf("Written %s\n",cmd);
/* Now read response */
if (cmd[0] == '?') {
char buffer[BUF_SIZE] = "";
int received = 0;
do {
int i;
r = libusb_bulk_transfer(dev_handle, BULK_EP_OUT, (unsigned char *)buffer, BUF_SIZE, &received, 1000);
if(r == LIBUSB_ERROR_TIMEOUT) {
printf("Timeout\n");
} else {
assert(r == 0);
}
for(i = 0; i<BUF_SIZE;i++)
printf("%c",buffer[i]);
} while (received != 0);
}
/* Release devices */
r = libusb_release_interface(dev_handle, INTERFACE_IN);
assert(r == 0);
r = libusb_release_interface(dev_handle, INTERFACE_OUT);
assert(r == 0);
/* Clean */
libusb_close(dev_handle);
libusb_exit(ctx);
}
Here is a description of the device with sudo lsusb --verbose in case it's important:
Bus 003 Device 003: ID 0483:5740 STMicroelectronics STM32F407
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 2 Communications
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x5740 STM32F407
bcdDevice 1.00
iManufacturer 1 STMicroelectronics
iProduct 2 STR75x Virtual COM Port
iSerial 3 Demo 1.000
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 67
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 255
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Device Status: 0x0001
Self Powered
You can communicate with the device by the RS-232 protocol, because it provides a virtual COM port which is a CDC ACM class. The kernel driver is cdc_acm.
iManufacturer 1 STMicroelectronics
iProduct 2 STR75x Virtual COM Port
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x00
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
So you can communicate with the device by sending RS-232 commands to /dev/ttyACMx (or /dev/ttyUSBx) (replace x with the number on your system)
To check this you can use a terminal program like PuTTY,... 5 Linux / Unix Commands For Connecting To The Serial Console. You have to figure out the correct COM port settings (baud rate, parity, start/stop bits, etc.)
There are several RS-232 libraries, see C: cross-platform RS-232 serial library?
Check the dmesg output after plugin in the device to see which driver is used.

Intel Galileo bare metal UART

I want to program a little "hello world" bare metal application on the Intel Galileo board. Using UEFI to print out text (to UART-1) works well, of course, but I want to access the UART "manually", without any help from UEFI.
In QEMU my code works well:
.h file
#define COM1_PORT (0x03F8)
#define UART_PORT (COM1_PORT)
enum uart_port_offs_t
{ // DLAB RW
THR = 0, // 0 W Transmitter Holding Buffer
RBR = 0, // 0 R Receiver Buffer
DLL = 0, // 1 RW Divisor Latch Low Byte
IER = 1, // 0 RW Interrupt Enable Register
DLH = 1, // 1 RW Divisor Latch High Byte
IIR = 2, // - R Interrupt Identification Register
FCR = 2, // - RW FIFO Control Register
LCR = 3, // - RW Line Control Register
MCR = 4, // - RW Modem Control Register
LSR = 5, // - R Line Status Register
MSR = 6, // - R Modem Status Register
SR = 7, // - RW Scratch Register
};
.c file
void uart_init(void)
{
outb(UART_PORT + IER, 0x00); // Disable all interrupts
outb(UART_PORT + LCR, LCR_DLAB);
outb(UART_PORT + DLL, BAUD_LL); // Set divisor (lo byte)
outb(UART_PORT + DLH, BAUD_HL); // (hi byte)
outb(UART_PORT + LCR, LCR_WORD_BITS_8 | LCR_PAR_NONE | LCR_STOP_BITS_1);
outb(UART_PORT + FCR, FCR_ENABLE | FCR_CLR_RECV | FCR_CLR_SEND | FCR_TRIGGER_16);
outb(UART_PORT + MCR, MCR_DSR | MCR_RTS | MCR_AUX2);
}
ssize_t uart_write(const char *buf, size_t len)
{
size_t written = 0;
while (written < len) {
while (!is_output_empty()) {
asm volatile ("pause");
}
outb(UART_PORT + THR, buf[written]);
++written;
}
return written;
}
main
SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Exiting EFI boot services ...\r\n");
SystemTable->BootServices->ExitBootServices(ImageHandle, map_key);
uart_init();
while (1) {
const char s[] = "UART\r\n";
uart_write(s, sizeof (s) - 1);
}
The specs did not help me very much. I guess that the UARTs on the Intel Galileo board don't use/emulate the normal/legacy COM ports 3F8h, 2F8h, 3E8h, or 2E8h.
Can anyone tell me what I am doing wrong, or even post a minimal bare metal hello world example?
I assume you are aiming at the serial port that is the "audio-like" connector on the Intel Galileo board.
Here are a few resources that should help:
Galileo schematic
Intel Quark SoC X1000 datasheet
Intel Galileo IO Mapping
Sergey's blog entry about Configuring the Serial Port for Galileo
Intel Quark Board Support Package downloads, including
Board Support Package Sources (currently ver.1.0.0)
Intel Quark SoC X1000 UEFI Firmware Writer’s Guide
Things to note about this UART:
This serial port comes out of the QUARK chip as UART1 (see the schematics).
There are a few GPIOs that you may need to manipulate (see Sergey's blog for doing this in Linux):
gpio4: This GPIO controls level shifter for UART signals and some other signals connected to Quark SoC, such as SPI and fast I/O. Writing '1' to this GPIO enables level shifter.
gpio40: This GPIO controls multiplexer for pin 0. Writing '0' to this GPIO connects pin 0 to UART's RxD (receive data) signal.
gpio41: This GPIO controls multiplexer for pin 1. Writing '0' to this GPIO connects pin 1 to UART's TxD (transmit data) signal.
Check the chapter 18 (High Speed UART) in the Quark datasheet for what to put in the UART registers:
Registers DLH, DLL specify the baud rate
Decide whether you want the DMA mode (chapter 18.3.1), the FIFO-interrupt mode (chapter 18.3.2), or the FIFO-polling mode (chapter 18.3.3). The latter is simpler but less effective, IMHO. The former requires you to configure DMA properly as well.
Since there is quite a bit to read for chapter 18 (~67 pages of useful information), I'm not going to retype all that here, please read the datasheet and configure the registers accordingly.
General notes:
For bare-metal approach first make sure that your boot procedure is correct, configuring all the clocking options, GPIO default modes and values, timers if any, etc. For Boot checklist read chapter 4.12 in X1000 UEFI Firmware Writer’s Guide (~18 things to do to boot this chip). After that I'd verify it with a simple "LED blinking" application on a GPIO.
Tinkering with 3F8h and similar ports is not going to help on "bare metal" of this SoC. You need to deal with the registers directly, or find and use appropriate library or framework (maybe UEFI BIOS?).
Programming sources for the particular platform should be a good read for examples.
For example, in Board Support Package Sources for Intel Quark the archive Quark_EDKII_v1.0.0.tar.gz is the UEFI source code for Quark/Galileo. It there, the Serial.c and Serial.h files might just be what you are looking for:
Quark_EDKII_v1.0.0/QuarkSocPkg/QuarkSouthCluster/Uart/Dxe/Serial.*

Resources