Is it possible to get information about a busy Alsa device? - alsa

Currently I am attempting to get information about an Alsa device by calling the snd_pcm_open function then passing that to snd_pcm_info to get information about the device. I plan specifically to get the channel information from snd_pcm_query_chmaps. The error code I am getting is: Device or resource busy. I was curious if there was another way to get this information or somehow open the pcm in a way that it won't ever be "busy" from other applications. How would I get this information, if at all possible, in a way that will work even if the device is busy?
The relevant snippet of my code is
snd_pcm_t* pcm;
int err;
if ((err = snd_pcm_open(&pcm, name, SND_PCM_STREAM_PLAYBACK, 0)) == 0 || (err = snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0)) == 0) {
snd_pcm_info_t* pcm_info;
if (snd_pcm_info_malloc(&pcm_info) == 0) {
if (snd_pcm_info(pcm, pcm_info) == 0) {
printf("Card number: %d\n", snd_pcm_info_get_card(pcm_info));
printf("Device number: %d\n", snd_pcm_info_get_device(pcm_info));
printf("Subdevice number: %d\n", snd_pcm_info_get_subdevice(pcm_info));
}
snd_pcm_info_free(pcm_info);
}
snd_pcm_close(pcm);
} else {
printf("Erroring opening PCM device with error: %s\n", snd_strerror(err));
}

To get information about a PCM device without opening it, open the control device of its card and call snd_ctl_pcm_info(). (See the aplay source code for how to use it.)
The channel map information is provided in the TLV information of some mixer controls; use the snd_pcm_query_chmaps_from_hw() helper function to read it.

Related

pcap_set_rfmon return 0 as success but the interface is not set to monitor mode

I'm trying to write a small program which set my network interface to monitor mode using C, the function pcap_set_rfmon returns 0 as success but the interface is still in mange mode. I'm sure my network card supports Monitor mode because i have checked using ng-airmon and iwconfig wlp3s0 mode monitor the wlp3s0 is my network interface's name.
Here's my code:
#include <pcap.h>
main()
{
char error_buffer[PCAP_ERRBUF_SIZE];
pcap_t *handle = pcap_create("wlp3s0", error_buffer);
int result = pcap_set_rfmon(handle, 1);
if (result != 0)
{
printf("failed to set pcap rfmon");
}
}
Since the code output nothing and just returns 0, i don't know what has gone wrong and where to look at, can you guys tell me what i should check or something is missing
To quote the documentation for pcap_set_rfmon():
pcap_set_rfmon() sets whether monitor mode should be set on a capture handle when the handle is activated. ...
I've emphasized part of that - "when the handle is activated". All pcap_set_rfmon() does is set a flag in the pcap_t to indicate that, when the program calls pcap_activate(), the adapter would be put in monitor mode (if pcap_activate() succeeds).
You aren't calling pcap_activate(), so nothing happens.
You will also have to keep the pcap_t open - even a program that does
#include <pcap.h>
main()
{
char error_buffer[PCAP_ERRBUF_SIZE];
pcap_t *handle;
int result;
handle = pcap_create("wlp3s0", error_buffer);
if (handle == NULL)
{
printf("failed to create a handle: %s\n",
error_buffer);
return 2;
}
result = pcap_set_rfmon(handle, 1);
if (result != 0)
{
printf("failed to set pcap rfmon: %s (%s)\n",
pcap_statustostr(result),
pcap_geterr(handle));
return 2;
}
result = pcap_activate(handle);
{
printf("failed to activate handle: %s (%s)\n",
pcap_statustostr(result),
pcap_geterr(handle));
return 2;
}
}
will just let the adapter revert to managed mode when it exits. You will need to add something such as
for (;;)
pause();
at the end of main(), so the program doesn't exit unless you interrupt or terminate it.
(Note: I added more error checking and reporting to the program. This Is A Good Thing, as it means that, if something doesn't work, the program will give a detailed error report, helping you - or whoever you ask for help - try to fix the problem, rather than just silently failing or, if pcap_create() fails, crashing.)

Faking an input device for testing purpose

What I want to do
I'm writing a daemon which listen to the input devices for keys presses and send signals via D-Bus. The main goal is to manage audio volume and screen backlight level by requesting changes or informing about changes.
I use libevdev to handle the input device events.
I wrote a function for opening an input device located at a specified path:
Device device_open(const char *path);
That function works well, but while I'm writing unit tests for it, I wanted to create file fixtures with different properties (existence of the file, read access, etc.) to check the error handling of my function and memory management (as I store data in a structure).
What I have already done
But testing it with a real input device (located at /dev/input/event*) needs root access rights. Setting read access for everyone on /dev/input/event* files works but seems risky to me. Executing my tests as root is worse !
Creating a device using mknod works but needs to be done as root.
I also tried to use character special files (because input devices are one of those) allowing read for everyone (like /dev/random, /dev/zero, /dev/null and even the terminal device i'm currently using: /dev/tty2).
But those devices does not handles ioctl requests needed by libevdev: EVIOCGBIT is the first request returning an error "Inappropriate ioctl for device".
What I'm looking for
I want to be able to create device files as a regular user (the user executing the unit tests). Then, by setting access rights I should be able to test my function behavior for different kinds of file (read only, no read allowed, bad device type, etc.).
If it appears to be impossible, I will certainly refactor my function using private helpers. But how to do it. Any examples ?
Thanks.
Edit: I tried to express better my needs.
Create a group for users who are allowed to access the device, and an udev rule to set the ownership of that input event device to that group.
I use teensy (system) group:
sudo groupadd -r teensy
and add each user into it using e.g.
sudo usermod -a -g teensy my-user-name
or whatever graphical user interface I have available.
By managing which users and service daemons belong to the teensy group, you can easily manage the access to the devices.
For my Teensy microcontrollers (that have native USB, and I use for HID testing), I have the following /lib/udev/rules.d/49-teensy.rules:
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789A]?", ENV{MTP_NO_PROBE}="1"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789ABCD]?", GROUP:="teensy", MODE:="0660"
KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789B]?", GROUP:="teensy", MODE:="0660"
You only need the third line (SUBSYSTEMS=="usb", one) for HID devices, though. Make sure the idVendor and idProduct match your USB HID device. You can use lsusb to list the currently connected USB devices vendor and product numbers. The matching uses glob patterns, just like file names.
After adding the above, don't forget running sudo udevadm control --reload-rules && sudo udevadm trigger to reload the rules. Next time you plug in your USB HID device, all members of your group (teensy in the above) can access it directly.
Note that by default in most distributions, udev also creates persistent symlinks in /dev/input/by-id/ using the USB device type and serial. In my case, one of my Teensy LC's (serial 4298820) with a combined keyboard-mouse-joystic device provides /dev/input/by-id/usb-Teensyduino_Keyboard_Mouse_Joystick_4298820-event-kbd for the keyboard event device, /dev/input/by-id/usb-Teensyduino_Keyboard_Mouse_Joystick_4298820-if01-event-mouse for the mouse event device, and /dev/input/by-id/usb-Teensyduino_Keyboard_Mouse_Joystick_4298820-if03-event-joystick and /dev/input/by-id/usb-Teensyduino_Keyboard_Mouse_Joystick_4298820-if04-event-joystick for the two joystick interfaces.
(By "persistent", I do not mean these symlinks always exist; I mean that whenever that particular device is plugged in, the symlink of exactly that name exists, and points to the actual Linux input event character device.)
The Linux uinput device can be used to implement a virtual input event device using a simple privileged daemon.
The process to create a new virtual USB input event device goes as follows.
Open /dev/uinput for writing (or reading and writing):
fd = open("/dev/uinput", O_RDWR);
if (fd == -1) {
fprintf(stderr, "Cannot open /dev/uinput: %s.\n", strerror(errno));
exit(EXIT_FAILURE);
}
The above requires superuser privileges. However, immediately after opening the device, you can drop all privileges, and have your daemon/service run as a dedicated user instead.
Use the UI_SET_EVBIT ioctl for each event type allowed.
You will want to allow at least EV_SYN; and EV_KEY for keyboards and mouse buttons, and EV_REL for mouse movement, and so on.
if (ioctl(fd, UI_SET_EVBIT, EV_SYN) == -1 ||
ioctl(fd, UI_SET_EVBIT, EV_KEY) == -1 ||
ioctl(fd, UI_SET_EVBIT, EV_REL) == -1) {
fprintf(stderr, "Uinput event types not allowed: %s.\n", strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
I personally use a static constant array with the codes, for easier management.
Use the UI_SET_KEYBIT ioctl for each key code the device may emit, and UI_SET_RELBIT ioctl for each relative movement code (mouse code). For example, to allow space, left mouse button, horizontal and vertical mouse movement, and mouse wheel:
if (ioctl(fd, UI_SET_KEYBIT, KEY_SPACE) == -1 ||
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) == -1 ||
ioctl(fd, UI_SET_RELBIT, REL_X) == -1 ||
ioctl(fd, UI_SET_RELBIT, REL_Y) == -1 ||
ioctl(fd, UI_SET_RELBIT, REL_WHEEL) == -1) {
fprintf(stderr, "Uinput event types not allowed: %s.\n", strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
Again, static const arrays (one for UI_SET_KEYBIT and one for UI_SET_RELBIT codes) is much easier to maintain.
Define a struct uinput_user_dev, and write it to the device.
If you have name containing the device name string, vendor and product with the USB vendor and product ID numbers, version with a version number (0 is fine), use
struct uinput_user_dev dev;
memset(&dev, 0, sizeof dev);
strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);
dev.id.bustype = BUS_USB;
dev.id.vendor = vendor;
dev.id.product = product;
dev.id.version = version;
if (write(fd, &dev, sizeof dev) != sizeof dev) {
fprintf(stderr, "Cannot write an uinput device description: %s.\n", strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
Later kernels have an ioctl to do the same thing (apparently being involved in systemd development causes this kind of drain bamage);
struct uinput_setup dev;
memset(&dev, 0, sizeof dev);
strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);
dev.id.bustype = BUS_USB;
dev.id.vendor = vendor;
dev.id.product = product;
dev.id.version = version;
if (ioctl(fd, UI_DEV_SETUP, &dev) == -1) {
fprintf(stderr, "Cannot write an uinput device description: %s.\n", strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
The idea seems to be that instead of using the former, you can try the latter first, and if it fails, do the former instead. You know, because a single interface might some day not be enough. (That's what the documentation and commit say, anyway.)
I might sound a bit cranky, here, but that's just because I do subscribe to both the Unix philosophy and the KISS principle (or minimalist approach), and see such warts completely unnecessary. And too often coming from the same loosely related group of developers. Ahem. No personal insult intended; I just think they are doing poor job.
Create the virtual device, by issuing an UI_DEV_CREATE ioctl:
if (ioctl(fd, UI_DEV_CREATE) == -1) {
fprintf(stderr, "Cannot create the virtual uinput device: %s.\n", strerror(errno));
close(fd);
exit(EXIT_FAILURE);
}
At this point, the kernel will construct the device, provide the corresponding event to the udev daemon, and the udev daemon will construct the device node and symlink(s) according to its configuration. All this will take a bit of time -- a fraction of a second in the real world, but enough that trying to emit events immediately might cause some of them to be lost.
Emit the input events (struct input_event) by writing to the uinput device.
You can write one or more struct input_events at a time, and should never see short writes (unless you try to write a partial event structure). Partial event structures are completely ignored. (See drivers/input/misc/uinput.c:uinput_write() uinput_inject_events() for how the kernel handles such writes.)
Many actions consists of more than one struct input_event. For example, you might move the mouse diagonally (emitting both { .type == EV_REL, .code == REL_X, .value = xdelta } and { .type == EV_REL, .code == REL_Y, .value = ydelta } for that single movement). The synchronization events ({ .type == EV_SYN, .code == 0, .value == 0 }) are used as a sentinel or separator, denoting the end of related events.
Because of this, you'll need to append an { .type == EV_SYN, .code == 0, .value == 0 } input event after each individual action (mouse movement, key press, key release, and so on). Think of it as the equivalent of a newline, for line-buffered input.
For example, the following code moves the mouse diagonally down right by a single pixel.
struct input_event event[3];
memset(event, 0, sizeof event);
event[0].type = EV_REL;
event[0].code = REL_X;
event[0].value = +1; /* Right */
event[1].type = EV_REL;
event[1].code = REL_Y;
event[1].value = +1; /* Down */
event[2].type = EV_SYN;
event[2].code = 0;
event[2].value = 0;
if (write(fd, event, sizeof event) != sizeof event)
fprintf(stderr, "Failed to inject mouse movement event.\n");
The failure case is not fatal; it only means the events were not injected (although I don't see how that could happen in current kernels; better be defensive, just in case). You can simply retry the same again, or ignore the failure (but letting the user know, so they can investigate, if it ever happens). So log it or output a warning, but no need for it to cause the daemon/service to exit.
Destroy the device:
ioctl(fd, UI_DEV_DESTROY);
close(fd);
The device does get automatically destroyed when the last duplicate of the original opened descriptor gets closed, but I recommend doing it explicitly as above.
Putting steps 1-5 in a function, you get something like
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
static const unsigned int allow_event_type[] = {
EV_KEY,
EV_SYN,
EV_REL,
};
#define ALLOWED_EVENT_TYPES (sizeof allow_event_type / sizeof allow_event_type[0])
static const unsigned int allow_key_code[] = {
KEY_SPACE,
BTN_LEFT,
BTN_MIDDLE,
BTN_RIGHT,
};
#define ALLOWED_KEY_CODES (sizeof allow_key_code / sizeof allow_key_code[0])
static const unsigned int allow_rel_code[] = {
REL_X,
REL_Y,
REL_WHEEL,
};
#define ALLOWED_REL_CODES (sizeof allow_rel_code / sizeof allow_rel_code[0])
static int uinput_open(const char *name, const unsigned int vendor, const unsigned int product, const unsigned int version)
{
struct uinput_user_dev dev;
int fd;
size_t i;
if (!name || strlen(name) < 1 || strlen(name) >= UINPUT_MAX_NAME_SIZE) {
errno = EINVAL;
return -1;
}
fd = open("/dev/uinput", O_RDWR);
if (fd == -1)
return -1;
memset(&dev, 0, sizeof dev);
strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE);
dev.id.bustype = BUS_USB;
dev.id.vendor = vendor;
dev.id.product = product;
dev.id.version = version;
do {
for (i = 0; i < ALLOWED_EVENT_TYPES; i++)
if (ioctl(fd, UI_SET_EVBIT, allow_event_type[i]) == -1)
break;
if (i < ALLOWED_EVENT_TYPES)
break;
for (i = 0; i < ALLOWED_KEY_CODES; i++)
if (ioctl(fd, UI_SET_KEYBIT, allow_key_code[i]) == -1)
break;
if (i < ALLOWED_KEY_CODES)
break;
for (i = 0; i < ALLOWED_REL_CODES; i++)
if (ioctl(fd, UI_SET_RELBIT, allow_rel_code[i]) == -1)
break;
if (i < ALLOWED_REL_CODES)
break;
if (write(fd, &dev, sizeof dev) != sizeof dev)
break;
if (ioctl(fd, UI_DEV_CREATE) == -1)
break;
/* Success. */
return fd;
} while (0);
/* FAILED: */
{
const int saved_errno = errno;
close(fd);
errno = saved_errno;
return -1;
}
}
static void uinput_close(const int fd)
{
ioctl(fd, UI_DEV_DESTROY);
close(fd);
}
which seem to work fine, and requires no libraries (other than the standard C library).
It is important to realize that the Linux input subsystem, including uinput and struct input_event, are binary interfaces to the Linux kernel, and therefore will be kept backwards compatible (except for pressing technical reasons, like security issues or serious conflicts with other parts of the kernel). (The desire to wrap everything under the freedesktop.org or systemd umbrella is not one.)

Streaming audio file in C on linux

I have a .au audio file and am reading it in parts using fread. However when i write this to /dev/audio there is no sound being played. Do I need to do something or is the system supposed to play back as soon as I write to /dev/audio. I am not getting any errors.
player = open("/dev/audio", O_WRONLY, 0);
if (player < 0)
{
perror("Opening /dev/audio failed\n");
exit(1);
}
while(1)
{
//code to read from the file writes to buf 1000 bytes per read
//fread(buf,1000, 1, audioFile); //server side
write(player, buf, 1000);
}
The issue seems to be with Ubuntu. I tried the same on a Gentoo installation in my lab and the sound can be heard

Why is pcap_datalink() always returning 1 (Ethernet), even on wireless device?

I'm having an issue where by pcap_datalink() is always returning 1. To my understanding this is LINKTYPE_ETHERNET. But, the device I am using is a wireless card and in my case en0.
This is stopping me from putting the card into monitor mode, and stopping my WLAN filters from working. I've tried to run this on both OSX and Linux with the same results. I also run as root.
Here's the part of my code that's causing the problem. For the example, assume dev is set to en0 (wireless device on Mac).
#include <stdio.h>
#include <pcap.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pcap_t *pcap_h;
char *dev, errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
struct pcap_pkthdr header;
const u_char *packet;
if(argc < 2)
{
printf("Usage: %s device\n", argv[0]);
exit(EXIT_FAILURE);
}
dev = argv[1];
if((pcap_h = pcap_create(dev, errbuf)) == NULL)
{
printf("pcap_create() failed: %s\n", errbuf);
exit(EXIT_FAILURE);
}
if(pcap_can_set_rfmon(pcap_h) == 0)
{
printf("Monitor mode can not be set.\n");
}
if(pcap_set_rfmon(pcap_h, 1) != 0)
{
printf("Failed to set monitor mode.\n");
exit(EXIT_FAILURE);
}
if(pcap_activate(pcap_h) != 0)
{
printf("pcap_activate() failed\n");
exit(EXIT_FAILURE);
}
/*
* Compile a filter to sniff 802.11 probe requests
* Filter: type mgt subtype probe-req
*/
if(pcap_compile(pcap_h, &fp, "type mgt subtype probe-req", 0, PCAP_NETMASK_UNKNOWN) == -1)
{
printf("pcap_compile() failed: %s\n", pcap_geterr(pcap_h));
exit(EXIT_FAILURE);
}
/*
* Set the compiled filter
*/
if(pcap_setfilter(pcap_h, &fp) == -1)
{
printf("pcap_setfilter() failed: %s\n", pcap_geterr(pcap_h));
exit(EXIT_FAILURE);
}
pcap_freecode(&fp);
packet = pcap_next(pcap_h, &header);
printf("Header: %d\n", header.len);
pcap_close(pcap_h);
return 0;
}
Any idea's why pcap_datalink() is always returning 1?
Edit
Updated code, and added pcap_set_rfmon() before the call to pcap_activate(). I get an error:
pcap_compile() failed: 802.11 link-layer types supported only on 802.11
Are you shure this is what's is stopping you from putting the card into monitor mode, and stopping your WLAN filters from working, or do you do this call to pcap_datalink() as a check trying to pinpoint the issue?
Be aware that, from PCAP-LINKTYPE(7):
For a live capture or ``savefile'', libpcap supplies, as the
return value of the pcap_datalink(3PCAP) routine, a value that
indicates the type of link-layer header at the beginning of the
packets it provides. This is not necessarily the type of link-layer
header that the packets being captured have on the network from
which they're being captured; for example, packets from an IEEE 802.11
network might be provided by libpcap with Ethernet headers that
the network adapter or the network adapter driver generates from the
802.11 headers.
So I would not take this LINKTYPE_ETHERNET / DLT_EN10MB return value as the sure indication of a problem here.
EDIT:
Also, pcap_set_rfmon() is supposed to be call before the handle is activated, which is not visible in your code.
pcap is rather touchy about the order things should be done. Have a look at the man pages for pcap_can_set_rfmon and pcap_set_rfmon.
The order should be:
pcap_create
pcap_can_set_rfmon
pcap_set_rfmon (if so far so good)
then and only then, pcap_activate

Streaming engines best practice in C

LANG: C / ENV: Linux
I am developing a streaming engine, for now I am able to start, stop and pause the stream, but seeking is the operation that's giving me a lot of headache, I already asked a question here before and fixed some issues inside the code from the answers.
Using lseek() function, I am passing the open streaming file descriptor as first argument, plus I am using UDP for transmitting, something like the following code:
transport_fd = open(tsfile, O_RDONLY);
int offset = 1024;
off_t offsetIndicator;
if ((offsetIndicator=lseek(transport_fd, offset, SEEK_CUR))<0) printf("Error seeking\n");
Whenever I try to seek while streaming, the streaming stops and the pictures hangs.
Is there anything I should pay attention to?, i.e: like attempting to sleep() or nanosleep() after seeking into the file in order for the changes to take effect.
I couldn't find examples, papers or realted articles for best practices in such engines.
EDIT:
After testing, it seems like the file continued to stream but receiving devices on the network didn't catch the stream connection anymore, and calculating the time it took to finish after subtract seeking time, the stream seems to be finished normally.
CODE SNIPPET:
while (!completed)
{
while (/* Comparing conditions */ && !completed)
{
if (seekLck == 1) // seekLck is a semaphore to test seek signal from father process initiated by 0
{
int offset = 1024;
off_t offsetIndicator;
if ((offsetIndicator=lseek(transport_fd, offset, SEEK_CUR))<0)
printf("Error seeking\n");
nanosleep(&nano_sleep_packet, 0); //Try to sleep to see if it is still hanging, didn't work
seekLck = 0;
}
len = read(transport_fd, send_buf, packet_size);
if(len < 0) {
fprintf(stderr, "File read error \n");
completed = 1;
}
else if (len == 0)
{
fprintf(stderr, "Sent done\n");
completed = 1;
}
else
{
sent = sendto(sockfdstr, send_buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if(sent <= 0)
{
perror("send(): error ");
completed = 1;
}
}
}
nanosleep(&nano_sleep_packet, 0);
}
close(transport_fd);
close(sockfdstr);
free(send_buf);
printf("cleaning up\n");
return 0;
}
The main question was "Why isn't the file being streamed (Played) even when lseek() is working fine?"...
Actually nothing was wrong from the server side, but even though, the clients weren't able to continue streaming after losing the frame count (streaming ffmpeg frames, clients are getting the stream from a video scrambler).
What worked for me in this situation is getting the socket parameter and killing (in a clean way) the process that needs to be seeked in while holding the stream position, after that start a totally new stream from the seek position with the same socket parameter so it replaces the old one.
I hope this will help someone out there especially that there's no much documentation about those stuff.

Resources