Enumerating capture ALSA devices and capture from them - c

I am writing a C program where I would like to enumerate all the capture devices in my system (in practice, I know I have three webcams plus the "integrated" microphone), recognize them and start capturing from them all at the same time.
I has some success using snd_device_name_hint() to enumerate all PCM devices and then snd_device_name_get_hint() to determine the "IOID" to see if they support capture. But now, how do I open the related device with snd_pcm_open() so that I can capture? I would like to use the "hw" interface as I do not want to overload the system with many conversion rates, so I would also like to see if there is a method to report the HW supported sampling frequencies.
Thank you!

snd_device_name_hint() can return multiple device names for the same hardware device (e.g., plughw and hw).
It can also returns devices that do not correspond to a single hardware device (such as null, or PulseAudio/Jack/Bluetooth devices).
To enumerate hardware devices, call snd_card_next() and snd_ctl_pcm_next_device() (see the aplay source code for an example).
To check whether a sample rate is supported, call snd_pcm_hw_params_test_rate().

Related

How to manually handle all plugged in USB devices to MacBook

my problem is I want to manually handle how USB devices are handled when they are plugged in. I don't want the operating system to do anything with the plugged in USB devices other than notify me of their type and their ID when they are plugged in. From there I can then select the appropriate driver to apply to it, or manually do something with it with custom code.
I've read this about how MacOS handles USBs, and it says:
If you want your driver selected above others, all you need to do is add key value pairs for the device your driver is for which cause your driver to get a really high score. Usually it's enough to just put keys in for your vendor id/model. However, I think you can override the matching method (device drivers are written in a restricted set of C++) to give your driver a really high score.
I have also found these 3 libraries for getting notified about things in the USB drive:
https://github.com/tessel/node-usb
https://github.com/MadLittleMods/node-usb-detection
https://github.com/node-hid/node-hid
I just am not sure if these libraries will interrupt all USB device handling by the operating system before anything occurs (before any device driver is selected automatically and applied). I would like for nothing to happen except for me to get access to the device and its type in one of the above libraries, but I'm not sure if they will do that.
I don't have much code yet other than this:
var usb = require('usb')
usb.getDeviceList()
But I imagine this would resolve the plugged in devices after the OS has already selected and applied a default driver to it. I want to do something like this:
usb.blockDefaultOSDeviceHandler()
usb.on('device:plugged_in', function(data){
if (data.type == 'keyboard') {
if (data.modelNumber == '123') {
// allow
usb.applyKeyboardDriver('abc', data.modelNumber)
usb.on('keyboard:event', logKeyboardEvent)
} else {
throw new Error('Unrecognized device')
}
}
})
I would hope that the library would interrupt all default behavior by the operating system so I can handle myself what should be done when a USB device is plugged in. A reason is because maybe the USB device is a keyboard and it automatically starts typing in some keys. I would like to know that it is a keyboard, and require a password and a specific driver I have pre-approved for it. Stuff like that.
I would like to get access to any newly plugged in USB device before the operating system applies its default handling rules. And then have the ability to write the code to manually handle what to do with each plugged in device.
If it's only possible in C, then knowing how to do it there would be good instead of node.js.
https://github.com/Arti3DPlayer/USBDeviceSwift
https://github.com/USBGuard/usbguard
How to block/unlock USB port in mac os x programatically without reboot
https://apple.stackexchange.com/questions/59764/how-to-disable-individual-usb-ports-by-script
https://serverfault.com/questions/566687/blocking-usb-through-gpo-in-2008-r2-excluding-certain-users
https://github.com/google/gousb
https://github.com/IntergatedCircuits/USBDevice
The answer is in the Apple documentation on USB devices. Basically you want to override the probe function in a custom driver, have it return the highest score so as to override all other drivers, and implement the driver like normal. Here is some useful documentation on the driver selection and instantiation process.
Before a device—or any service provider—can be used, a driver for it must be found and loaded into the kernel. The I/O Kit defines a flexible, three-phase matching process that narrows a pool of candidate drivers down to one or more drivers. The final candidate (or, if multiple candidates, the m
ost eligible one) is then loaded and given the first opportunity to manage the device or service provider.
...
Each device driver, considered as a loadable kernel extension (KEXT), must define one or more personalities that specify the kinds of devices it can support.
...
Because a driver can contain multiple matching dictionaries, each one defining a different personality for the driver, the same driver code can be loaded for different devices. For purposes of competition, the I/O Kit treats each personality as if it were a driver. If, in any single personality, all of the properties required by the family match, the driver’s code is loaded and given a chance to run for that device.
...
One common property of personalities is the probe score. A probe score is an integer that reflects how well-suited a driver is to drive a particular device. A driver may have an initial probe-score value in its personality and it may implement a probe function that allows it to modify this default value, based on its suitability to drive a device. As with other matching values, probe scores are specific to each family. That’s because once matching proceeds past the class-matching stage, only personalities from the same family compete. For more information on probe scores and what a driver does in the probe function, see Device Probing.
...
At boot time and at any time devices are added or removed, the process of driver matching occurs for each detected device (or other service provider). The process dynamically locates the most suitable driver in /System/Library/Extensions for the device or service.
...
As described in Driver Matching in the chapter Architectural Overview the matching process is triggered when a bus controller driver scans its bus and detects a new device attached to it. For each detected device the controller driver creates a nub. The I/O Kit then initiates the matching process and obtains the values from the device to use in matching (for example, examining the PCI registers). Once a suitable driver is found for the nub, the driver is registered and loaded. That driver, in turn, may create its own nub (possibly through behavior inherited from its family), which initiates the matching process to find a suitable driver.
...
The matching process proceeds as follows:
In the class matching step, the I/O Kit narrows the list of potential drivers by eliminating any drivers of the wrong class for the provider service (that is, the nub). For example, all driver objects that descend from a SCSI class can be ruled out when the search is for a USB driver.
In the passive matching step, the driver’s personality (specified in a driver’s XML information property list) is examined for properties specific to the provider’s family. For example, the personality might specify a particular vendor name.
In the active matching step, the driver’s probe function is called with reference to the nub it is being matched against. This function allows the driver to communicate with the device and verify that it can in fact drive it. The driver returns a probe score that reflects its ability to drive the device. See Device Probing for more information. During active matching, the I/O Kit loads and probes all candidate drivers, then sorts them in order of highest to lowest probe score.
...
The I/O Kit then chooses the remaining driver with the highest probe score and starts it. If the driver successfully starts, it is added to the I/O Registry and any remaining driver candidates are discarded. If it does not start successfully, the driver with the next highest probe score is started, and so on. If more than one driver is in the pool of possible candidates, the more generic driver typically loses out to the more specific driver if both claim to be able to drive the device.
...
The probe score is a signed 32-bit integer initialized to a value specified in the driver’s personality (or to zero if not explicitly initialized).
...
A driver, in its probe function, returns a driver object (IOService *) if the probe was successful and returns zero otherwise. The returned object is usually the driver itself, but the driver can return another driver that is more suited to the provider. The probe score is an in-out parameter, which probe can modify based on what it discovers about the device.
...
After all drivers have probed the device, the one with the highest probe score is attached and its startfunction, which must be implemented by all drivers, is invoked. The start function initializes the device hardware and prepares it for operation. If the driver succeeds in starting, it returns true; the remaining candidate driver instances are discarded and the driver that started successfully continues operating. If the driver cannot initialize the hardware it must leave the hardware in the state it was in when start was invoked and return false. The failing driver is then detached and discarded, and the candidate driver with the next highest probe score is given a chance to start.
This can't be done with Node.js unless (potentially) a C/C++ extension in node is used.

what is the limit value in LINEOUT -TI LCDK C6748

I work in Code Composer Studio Version: 6.0.1.00040 with the card LCDK C6748.
In this card there is LINE_OUT for sampling out audio into speakers.
My question arises, because I encountered some phenomena that look like I reached a limit value when I assigened a value to LINE_OUT:
codec_data.channel[LEFT]= (uint16_t)outputLeft_referenceSignal;
// this union is where I have to "place" the audio sample I create,
// but I suspect outputLeft_referenceSignal exceed the limit value
When it happens it sounds, like a cracked "PACK" in the speakers and then the expected audio signal is not played
The T.I. has complete code examples on how to handle each of the built-in peripherals of the C6847 DSP.
I strongly suggest you start searching/reading the T.I. web site for info on the C6748 DSP
amongst other things, like initializing the DSP, you need to understand the usage of the McASP and the AIC31 peripherals.
It is not a simple write to a I/O address.
If you have setup the above peripherals, please post the relevant code so we can determine the underlying problem.

Device driver classification

So according to 2 books I have on device drivers(for Linux), notable the O'REILLY version("Linux Device Drivers(3rd edition") there are 3 types of device drivers:
Character drivers that read/write on byte of data at a time.
Block drivers which read and write blocks of data(file storage devices).
Network drivers that send and receive frames(for ethernet and wifi these are 48 bit chunks of data).
So where do video and sound drivers fit in? I ask because AFAIK your screen has a bus that sends frames from the motherboard to the monitor and the image on your screen is a memory map(a square array) that is refreshed at a certain number of frames/sec. The sound driver also sends 16-bit(2 byte) frames to the DAC at a sampling rate of 44.1 KHz. Are these character drivers? I would think they would be in a similar category as network drivers as network interfaces, screens, speakers, microphones, and webcams are all devices that read and write frames(an array of bytes).
A more accurate way of describing these types of devices would be to say that:
Character devices deal with streams of data. You can write data to them and read data from them, but you can't skip around. Reading data from them may block if nothing is available. Common character devices include terminals, serial ports, and special devices like /dev/null and /dev/random. This need not be one byte at a time, though: many devices return data as larger frames. (For instance, Linux input devices under /dev/input return data in 32-byte frames, each one representing one event.)
Block devices deal with a fixed block of data. You can read and write data to any location in them you want, as well as mapping them to memory using mmap(). They are often used to represent storage devices (like disks), but can also be used to represent other, more unusual things.
Network devices are a special case. They are more or less exclusively used for devices that actually interface with a network (e.g, Ethernet NICs, wireless network hardware, cell modems, etc). They don't show up in /dev at all.
Both character and block devices can implement special operations that don't fit into the normal framework using ioctl() (e.g, changing the baud rate of a serial port, ejecting a CD, etc), so, to some degree, the decision of which one to use can be somewhat arbitrary. Nevertheless, for the types of devices you're describing:
Audio devices are typically represented as character devices.
The older OSS Linux sound system represented a sound device as /dev/dsp: reading data from it would read PCM data representing microphone input, and writing PCM data to it would play that through the sound card. The more modern ALSA sound system uses a more complex set of devices and formats, but the concept is the same.
Video devices are an unusual situation.
Some simple "framebuffer" video drivers are implemented as a block device such as /dev/fb0. This device represents the image on screen — a 1024x768 screen using 32-bit color would be represented by a 3 MB buffer, for instance — and writing to it changes that image. It's most commonly used by mapping it into memory.
Most modern video devices aren't that simple, though. Many of them are implemented partially as a kernel driver and partially as a X11 device driver which may directly map and write to the video hardware. They may sometimes include an extra character or block device (e.g, some Nvidia graphics cards use a character device /dev/nvidia), but the details of what data is read from or written to this device are largely proprietary.
They are character drivers.
gfx http://www.x.org/wiki/Development/Documentation/HowVideoCardsWork/
audio http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/

C Linux Device Programming - Reading Straight from /Dev

I have been playing with creating sounds using mathematical wave functions in C. The next step in my project is getting user input from a MIDI keyboard controller in order to modulate the waves to different pitches.
My first notion was that this would be relatively simple and that Linux, being Linux, would allow me to read the raw data stream from my device like I would any other file.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
Despite these warnings, I did an experiment. I plugged in the MIDI controller and cat'ed the "/dev/midi1" device file. A steady stream of null characters appeared, and when I pressed a key on the MIDI controller several bytes appeared corresponding to the expected Message Chunks that a MIDI device should output. MIDI Protocol Info
So my questions are:
Why does the cat'ed stream behave this way?
Does this mean that there is a plug and play device driver already installed on my system?
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
Thank you in advanced for sharing your wisdom in these areas.
Why does the cat'ed stream behave this way?
Because that is presumably the raw MIDI data that is being received by the controller. The null bytes are probably some sort of sync tick.
Does this mean that there is a plug and play device driver already installed on my system?
Yes.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
<...>
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
I'm not sure what you're reading or how you're coming to this conclusion, but it's wrong. :) You've already got a perfectly good driver installed for your MIDI controller -- go ahead and use it!
Are you sure you are reading NUL bytes? And not 0xf8 bytes? Because 0xf8 is the MIDI time tick status and is usually sent periodically to keep the instruments in sync. Try reading the device using od:
od -vtx1 /dev/midi1
If you're seeing a bunch of 0xf8, it's okay. If you don't need the tempo information sent by your MIDI controller, either disable it on your controller or ignore those 0xf8 status bytes.
Also, for MIDI, keep in mind that the current MIDI status is usually sent once (to save on bytes) and then the payload bytes follow for as long as needed. For example, the pitch bend status is byte 0xeK (where K is the channel number, i.e. 0 to 15) and its payload is 7 bits of the least significant byte followed by 7 bits of the most significant bytes. Thus, maybe you got a weird controller and you're seeing only repeated payloads of some status, but any controller that's not stupid won't repeat what it doesn't need to.
Now for the driver: have a look at dmesg when you plug in your MIDI controller. Now if your OSS /dev/midi1 appears when you plug in your device (udev is doing this job), and dmesg doesn't shoot any error, you don't need anything else. The MIDI protocol is yet-another-serial-protocol that has a fixed baudrate and transmits/receives bytes. There's nothing complicated about that... just read from or write to the device and you're done.
The only issue is that queuing at some place could result in bad audio latency (if you're using the MIDI commands to control live audio, which I believe is what you're doing). It seems like those devices are mostly made for system exclusive messages, that is, for example, downloading some patch/preset for a synthesizer online and uploading it to the device using MIDI. Latency doesn't really matter in this situation.
Also have a look at the ALSA way of playing with MIDI on Linux.
If you are not developing a new MIDI controller hardware, you shouldn't worry about writing a driver for it. It's the user's concern installing their hardware, and the vendor's obligation to supply the drivers.
Under Linux, you just read the file. Now to interpret and make useful things with the data.

Linux device model: Same device but different drivers

I'm customising Linux for an ARM9 Atmel AT91SAM960 board.
In the device file Atmel named all the USART the same atmel_usart. Of course with id enumeration:
static struct platform_device at91sam9260_uart0_device = {
.name = "atmel_usart",
.id = 1,
.dev = { ...}
}
According to the Linux Device model, all these devices (5 UARTS on a SAM9260) would be bind to the driver named atmel_usart.
I don't want to set a TTYS driver on all UARTS which will be registerd. I have several own drivers which serve for different specialised purposes (LON, RS-485 etc.) I want the control which driver does serve a certain USART. So what could I do:
The Atmel device files are unsatisfiable and I can do it better. So I rename (patch) the devices in the device file. However, in case I want a TTYS driver on UART4 I would be in trouble.
I manipulate (patch) the device file,
so that I'm able the access the
structures platform_device. I could
change their names before I would
register them. But as far as I
understood the idea of the Linux Driver Model,
devices should be
registered early during boot-up but the binding to a driver follows .... later.
I could write a driver, which has an
alias name and which would be binded
to a specific bus_Id ->
atmel_usart.4. Can I really?
What solutions else exist. I want to touch a minimal set of Kernel files but I want all the freedom possible?
Addendum what freedom means to me: I can specify at runtime how the UARTS can be used
with the Atmel-Serial driver (ttyS)
with my own drivers
It means also, that changes to the kernel source are minimal.
I built my own line discipline drivers. You can build them as kernel modules and attach them to the UARTs at runtime. No changes to the Linux source are necessary.
Any funny timing or control stuff can be done through ioctl(). Specifically, I implemented a timing-sensitive RS-485 protocol in this way.
When I did this (Linux 2.6.17) there was no dynamic registration mechanism, so I overwrote the existing line disciplines. The Linux code is (was) pretty straightforward, and I was satisfied that this would be a safe thing to do.
Your problem is quite easily solved. The 5 UART devices are presently registered at kernel startup and their function is locked. This is now how it normally works for PCI or USB devices, right? So what you need to do is pull the device registration out of the startup code and register it dynamically. You can even register/unregister as needed.
at91_register_uart() is being called from your board file for every UART that needs registered. at91_add_device_serial() will then platform_device_register all those you what setup. One solution is to let at91_register_uart() be called for all 5 UARTS, but then remove the call to at91_add_device_serial() from your board. You can then make it an exported function that can be called by your loadable drivers. You can even add an argument to it (int) so that instead of looping on all UARTS, you can select which ones to register individually. You can also mirror this function by making one that unregisters the devices.
NOTE: I think you'll need to always leave one UART dedicated as your console, if you are using one that way. You could probably hide that in the exported function by only allowing index 0->3 as in input and then mapping 0->3 to 0-4, skipping the UART that you want to use for console.

Resources