Cannot set GPIO pins in FT230X in Centos - c

I have LEDs connected to CBx pins of FT230X. I am using libftdi v1.2 to set FT230X CBx pins. I am tried both 2 bitbang modes: BITMODE_BITBANG and BITMODE_CBUS, but without any result.
My code is somewhere about follow:
#include <ftdi.h>
#include <err.h>
int main(int argc, char *argv[])
{
struct ftdi_context ftdi;
unsigned char x;
/* Initialize and find device */
if (ftdi_init(&ftdi) < 0)
err(1, "ftdi_init");
if (ftdi_usb_open(&ftdi, 0x0403, 0x6015) < 0)
err(2, "can't open device");
/* Enable bitbang */
if (ftdi_set_bitmode(&ftdi, 0xff, BITMODE_BITBANG) < 0)
err(3, "can't enable bitbang mode");
/* Write Yellow */
x=0x00;
if (ftdi_write_data(&ftdi, &x, 1) < 0)
err(5, "can't write");
sleep(3);
/* Write Red */
x=0x01;
if (ftdi_write_data(&ftdi, &x, 1) < 0)
err(5, "can't write");
sleep(3);
/* Write Green */
x=0x02;
if (ftdi_write_data(&ftdi, &x, 1) < 0)
err(5, "can't write");
sleep(3);
/* Close device */
ftdi_usb_close(&ftdi);
ftdi_deinit(&ftdi);
return 0;
}
It should be noted that the same code (exclude product id = 0x6013) works properly for FT4232H.

I resolved my problem. As I mentioned, I need to set CBx pins on FT230X. For this case in the FT230X should be enabled BITMODE_CBUS mode in EEPROM.
In BITMODE_CBUS mode, as it described in bitbang_cbus.c example of libftdi, to set these CBx pins should be used only ftdi_set_bitmode() function.
Wherein in the second parameter (bitmask) the top nibble controls input/output and the bottom nibble controls the state of the lines set to output.

Related

Mouse event handling in Linux?

I have an event handling code that reads Linux's /dev/input/ for my touchpad and prints result on the basis of which button is pressed/released.
Although. as of now my code is waiting on a button press while running on terminal. My next step is to run this event handling thread along with another thread (not event based). If I continue handling event by reading input at terminal, I will not be able to execute other threads as a part of my main() as main() keeps on waiting for the button press:
int main(int argc, char** argv)
{
*Mouse event handling code here*
return 0;
}
Is there a different approach like reading interrupts instead? Or can I still take this approach and make amends in my code to make this work as a part of a thread (like can I make my thread to wait on these inputs as arguments)?
If you make the event device descriptors nonblocking (by opening them with the O_NONBLOCK flag), you can very easily use `poll() to wait until one of them has events you can read.
Consider the following example program, example.c:
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/input.h>
#include <termios.h>
#include <poll.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
/* Maximum number of input sources, including the terminal. */
#ifndef MAX_INPUTS
#define MAX_INPUTS 32
#endif
/* Maximum wait for events, in milliseconds (1000 ms = 1 second). */
#ifndef INTERVAL_MS
#define INTERVAL_MS 100
#endif
int main(int argc, char *argv[])
{
unsigned char keys[16];
struct input_event event;
struct termios config, oldconfig;
struct pollfd src[MAX_INPUTS];
size_t srcs, i, done;
ssize_t n;
int arg, nsrcs;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "Standard input is not a terminal.\n");
return EXIT_FAILURE;
}
/* Save old terminal configuration. */
if (tcgetattr(STDIN_FILENO, &oldconfig) == -1 ||
tcgetattr(STDIN_FILENO, &config) == -1) {
fprintf(stderr, "Cannot get terminal settings: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
/* Set new terminal configuration. */
config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK);
config.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN | TOSTOP);
config.c_cc[VMIN] = 0;
config.c_cc[VTIME] = 0;
config.c_cc[VSTART] = 0;
config.c_cc[VSTOP] = 0;
if (tcsetattr(STDIN_FILENO, TCSANOW, &config) == -1) {
const int saved_errno = errno;
tcsetattr(STDIN_FILENO, TCSANOW, &oldconfig);
fprintf(stderr, "Cannot set terminal settings: %s.\n", strerror(saved_errno));
return EXIT_FAILURE;
}
/* The very first input source is the terminal. */
src[0].fd = STDIN_FILENO;
src[0].events = POLLIN;
src[0].revents = 0;
srcs = 1;
/* Add input devices from command line. */
for (arg = 1; arg < argc; arg++) {
int fd;
fd = open(argv[arg], O_RDONLY | O_NOCTTY | O_NONBLOCK);
if (fd == -1) {
fprintf(stderr, "Skipping input device %s: %s.\n", argv[arg], strerror(errno));
continue;
}
if (srcs >= MAX_INPUTS) {
fprintf(stderr, "Too many event sources.\n");
return EXIT_FAILURE;
}
/* Optional: Grab input device, so only we receive its events. */
ioctl(fd, EVIOCGRAB, 1);
src[srcs].fd = fd;
src[srcs].events = POLLIN;
src[srcs].revents = 0;
srcs++;
}
printf("Ready. Press Q to exit.\n");
fflush(stdout);
done = 0;
while (!done) {
nsrcs = poll(src, srcs, INTERVAL_MS);
if (nsrcs == -1) {
if (errno == EINTR)
continue;
fprintf(stderr, "poll(): %s.\n", strerror(errno));
break;
}
/* Terminal is not an input source. */
if (src[0].revents & POLLIN) {
n = read(src[0].fd, keys, sizeof keys);
if (n > 0) {
for (i = 0; i < n; i++) {
if (keys[i] == 'q' || keys[i] == 'Q')
done = 1;
if (keys[i] >= 32 && keys[i] <= 126)
printf("Key '%c' = 0x%02x = %u pressed\n", keys[i], keys[i], keys[i]);
else
if (keys[i])
printf("Key '\\%03o' = 0x%02x = %u pressed\n", keys[i], keys[i], keys[i]);
else
printf("NUL key (0) pressed\n");
}
fflush(stdout);
}
src[0].revents = 0;
}
/* Check the other input sources. */
for (i = 1; i < srcs; i++) {
if (src[i].revents & POLLIN) {
while (1) {
n = read(src[i].fd, &event, sizeof event);
if (n != sizeof event)
break;
if (event.type == EV_KEY && event.code == BTN_LEFT) {
if (event.value > 0)
printf("Left mouse button pressed\n");
else
printf("Left mouse button released\n");
}
if (event.type == EV_KEY && event.code == BTN_RIGHT) {
if (event.value > 0)
printf("Right mouse button pressed\n");
else
printf("Right mouse button released\n");
}
}
fflush(stdout);
}
src[i].revents = 0;
}
}
/* Close input devices. */
for (i = 1; i < srcs; i++)
close(src[i].fd);
/* Restore terminal settings. */
tcsetattr(src[0].fd, TCSAFLUSH, &oldconfig);
printf("All done.\n");
return EXIT_SUCCESS;
}
Compile it using e.g.
gcc -Wall -O2 example.c -o example
and run it using e.g.
sudo ./example /dev/input/event5
where /dev/input/event5 is a mouse event device. Note that you can read /sys/class/input/event5/device/name to find out the name of the device (as far as the kernel knows it; these are the same names evtest shows when run as root).
If you are not sure, you can always run
for N in /sys/class/input/event*/device/name ; do
DEV="${N%%/device/name}" ; DEV="/dev/${DEV##/sys/class/}" ;
NAME="$(cat "$N" 2>/dev/null)" ;
printf "%s: %s\n" "$DEV" "$NAME" ;
done
in a Bash or Dash or a POSIX shell, to see what event devices you can try.
The example program above must be run from a terminal or console, because it also takes input from the terminal. It sets the terminal into nonblocking non-canonical mode, where it can receive individual keypresses. Do note that some keypresses, like cursor and function keys, are actually several characters long, beginning with an ESC (\033).
It is also common to split that input event loop into a separate thread. It is just a dozen or so lines more, but the "problem" then becomes how the separate thread informs the main (or other) threads that new input events/commands have arrived. The non-blocking poll() approach above is usually easier to implement in a very robust, straightforward manner.
My simple poll. the event routine attempt to get data from the two non blocking fds, one for mouse and one for keyboard. The event routine returns -1 or device busy when not ready, anything error below that is trapped by event. The if statement here tries fmd, mouse, first, then fkd next. A return less than one or zero means data not ready, the thread sleeps.
if( ( ( imd = event(fmd,&ie) ) <=0)&& ( ( ikd = event(fkd,&ie)) <= 0))
{
usleep(TIMEOUT);
continue;
}

How to record sound in buffer using ALSA [duplicate]

I'm begining to learn linux and ALSA and I was wondering if there is a way to store the sound I record from a microphone a directly to the buffer. I read here http://www.linuxjournal.com/article/6735?page=0,2 how to make my recording program. But what I need is a little more complex. I need to record sound untill I hit a key. The reason I need this is because I'm messing with a RaspberryPI(debian on it) and to see if I could turn it into a sound monitoring/detecting device.
My main problem is now that when I try to use it to record (./Rec >name.raw ) it does nothing. It just ouputs an empty .raw file.
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <termios.h>
#include <alsa/asoundlib.h>
struct termios stdin_orig; // Structure to save parameters
void term_reset() {
tcsetattr(STDIN_FILENO,TCSANOW,&stdin_orig);
tcsetattr(STDIN_FILENO,TCSAFLUSH,&stdin_orig);
}
void term_nonblocking() {
struct termios newt;
tcgetattr(STDIN_FILENO, &stdin_orig);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking
newt = stdin_orig;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
atexit(term_reset);
}
int main() {
int key=0;
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* One channel (mono) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* 16000 bits/second sampling rate */
val = 16000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 2048 frames. */
frames = 2048;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 1 channels */
buffer = (char *) malloc(size);
while (key == 0)
{
rc = snd_pcm_readi(handle, buffer, frames);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
}
else if (rc != (int)frames)
{
fprintf(stderr, "short read, read %d frames\n", rc);
}
rc = write(1, buffer, size);
if (rc != size)
fprintf(stderr, "short write: wrote %d bytes\n", rc);
key = getchar();
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
Here is how I did that with python. Tested to work on my desktop Debian with USB Plantronics headphones. You need to install python-qt4 and python-pyaudio packages for this to work.
Also, you'll need to set your input device to microphone. In GNOME I switched both input and output devices via System Tools -> System Settings -> Sound. If you have Raspbian, not Debian on your Raspberry, as I do, it's gonna be tougher, cause there's LXDE instead of GNOME. You can use alsamixer and F6 button there to set audio cards, but the problem is that ALSA is low-level interface, while most Linuxes use some sound server on top of it, such as PulseAudio or JACK. You'll need some luck/spent time to make sure you switched input/output device to your mic/headphones.
If you use Jack microphone, plugged in through Jack input of your Raspberry Pi, note that Raspberry's Jack is input only, so you won't be able to play back your recordings and need some USB headphones to listen to your wav.
Personally, I feel that ALSA is very poorly documented (I suppose it's intentional job security) and I don't like to deal with it.
import pyaudio
import wave
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# This is Qt part: we create a window, which has a "stop" flag.
# Stop flag defaults to False, but is set to True, when you press a key.
# Value of that flag is checked in main loop and loop exits when flag is True.
app = QApplication(sys.argv)
class MyWindow(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.stop = False
def keyPressEvent(self, event):
print "keyPressedEvent caught!"
self.stop = True
window = MyWindow()
window.show()
# This is sound processing part: we create an input stream to read from microphone.
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(2),
channels = 2,
rate=44100,
input=True,
output=False,
frames_per_buffer=1024)
# This is main loop: we iteratively poll audio and gui: audio data are stored in output_buffer,
# whereas gui is checked for stop flag value (if keyPressedEvent happened, flag will be set
# to True and break our main loop).
output_buffer = ""
while True:
app.processEvents()
data = stream.read(1024)
output_buffer += data
if window.stop: break
stream.stop_stream()
stream.close()
# Here we output contents of output_buffer as .wav file
output_wav = wave.open("output.wav", 'w')
output_wav.setparams((2, 2, 44100, len(output_buffer),"NONE","not compressed"))
output_wav.writeframesraw(output_buffer)
p.terminate()
This code shows you how to capture from ALSA in C++ in a while loop :
https://github.com/flatmax/gtkiostream/blob/master/test/ALSACaptureTest.C#L95
You can alter the loop there to record forever, replace :
while (N>0){
with
while (1){
Now you'll need some extra code. Firstly to read a character non-blocking add this to the top of the file :
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define ngetc(c) (read (0, (c), 1))
ngetc is a non-blocking read from stdin. It returns -1 when nothing is read. It returns > 1 when you press the enter key.
So finally putting this all together, change :
while (N>0){
with
while (1){
int enter=ngetc(&ch);
if (enter>0)
break;

How to record sound in buffer using ALSA

I'm begining to learn linux and ALSA and I was wondering if there is a way to store the sound I record from a microphone a directly to the buffer. I read here http://www.linuxjournal.com/article/6735?page=0,2 how to make my recording program. But what I need is a little more complex. I need to record sound untill I hit a key. The reason I need this is because I'm messing with a RaspberryPI(debian on it) and to see if I could turn it into a sound monitoring/detecting device.
My main problem is now that when I try to use it to record (./Rec >name.raw ) it does nothing. It just ouputs an empty .raw file.
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <termios.h>
#include <alsa/asoundlib.h>
struct termios stdin_orig; // Structure to save parameters
void term_reset() {
tcsetattr(STDIN_FILENO,TCSANOW,&stdin_orig);
tcsetattr(STDIN_FILENO,TCSAFLUSH,&stdin_orig);
}
void term_nonblocking() {
struct termios newt;
tcgetattr(STDIN_FILENO, &stdin_orig);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // non-blocking
newt = stdin_orig;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
atexit(term_reset);
}
int main() {
int key=0;
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0) {
fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
/* One channel (mono) */
snd_pcm_hw_params_set_channels(handle, params, 1);
/* 16000 bits/second sampling rate */
val = 16000;
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
/* Set period size to 2048 frames. */
frames = 2048;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 2; /* 2 bytes/sample, 1 channels */
buffer = (char *) malloc(size);
while (key == 0)
{
rc = snd_pcm_readi(handle, buffer, frames);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(handle);
}
else if (rc < 0)
{
fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
}
else if (rc != (int)frames)
{
fprintf(stderr, "short read, read %d frames\n", rc);
}
rc = write(1, buffer, size);
if (rc != size)
fprintf(stderr, "short write: wrote %d bytes\n", rc);
key = getchar();
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
Here is how I did that with python. Tested to work on my desktop Debian with USB Plantronics headphones. You need to install python-qt4 and python-pyaudio packages for this to work.
Also, you'll need to set your input device to microphone. In GNOME I switched both input and output devices via System Tools -> System Settings -> Sound. If you have Raspbian, not Debian on your Raspberry, as I do, it's gonna be tougher, cause there's LXDE instead of GNOME. You can use alsamixer and F6 button there to set audio cards, but the problem is that ALSA is low-level interface, while most Linuxes use some sound server on top of it, such as PulseAudio or JACK. You'll need some luck/spent time to make sure you switched input/output device to your mic/headphones.
If you use Jack microphone, plugged in through Jack input of your Raspberry Pi, note that Raspberry's Jack is input only, so you won't be able to play back your recordings and need some USB headphones to listen to your wav.
Personally, I feel that ALSA is very poorly documented (I suppose it's intentional job security) and I don't like to deal with it.
import pyaudio
import wave
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
# This is Qt part: we create a window, which has a "stop" flag.
# Stop flag defaults to False, but is set to True, when you press a key.
# Value of that flag is checked in main loop and loop exits when flag is True.
app = QApplication(sys.argv)
class MyWindow(QWidget):
def __init__(self):
super(QWidget, self).__init__()
self.stop = False
def keyPressEvent(self, event):
print "keyPressedEvent caught!"
self.stop = True
window = MyWindow()
window.show()
# This is sound processing part: we create an input stream to read from microphone.
p = pyaudio.PyAudio()
stream = p.open(format = p.get_format_from_width(2),
channels = 2,
rate=44100,
input=True,
output=False,
frames_per_buffer=1024)
# This is main loop: we iteratively poll audio and gui: audio data are stored in output_buffer,
# whereas gui is checked for stop flag value (if keyPressedEvent happened, flag will be set
# to True and break our main loop).
output_buffer = ""
while True:
app.processEvents()
data = stream.read(1024)
output_buffer += data
if window.stop: break
stream.stop_stream()
stream.close()
# Here we output contents of output_buffer as .wav file
output_wav = wave.open("output.wav", 'w')
output_wav.setparams((2, 2, 44100, len(output_buffer),"NONE","not compressed"))
output_wav.writeframesraw(output_buffer)
p.terminate()
This code shows you how to capture from ALSA in C++ in a while loop :
https://github.com/flatmax/gtkiostream/blob/master/test/ALSACaptureTest.C#L95
You can alter the loop there to record forever, replace :
while (N>0){
with
while (1){
Now you'll need some extra code. Firstly to read a character non-blocking add this to the top of the file :
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define ngetc(c) (read (0, (c), 1))
ngetc is a non-blocking read from stdin. It returns -1 when nothing is read. It returns > 1 when you press the enter key.
So finally putting this all together, change :
while (N>0){
with
while (1){
int enter=ngetc(&ch);
if (enter>0)
break;

Cannot open /dev/dsp

I am trying to learn audio recording, so I compiled The following code that I found online , but for some reason I cannot open /dev/dsp. I tried killing pulseaudio, but it re-opens as soon as I killall it. I really don't know what I am doing; I've been struggling for the latter part of the week. Please help.
I also tried chmod o+rw /dev/dsp
/*
* parrot.c
* Program to illustrate /dev/dsp device
* Records several seconds of sound, then echoes it back.
* Runs until Control-C is pressed.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#define LENGTH 3 /* how many seconds of speech to store */
#define RATE 8000 /* the sampling rate */
#define SIZE 8 /* sample size: 8 or 16 bits */
#define CHANNELS 1 /* 1 = mono 2 = stereo */
/* this buffer holds the digitized audio */
unsigned char buf[LENGTH*RATE*SIZE*CHANNELS/8];
int main()
{
int fd; /* sound device file descriptor */
int arg; /* argument for ioctl calls */
int status; /* return status of system calls */
/* open sound device */
fd = open("/dev/dsp", O_RDWR);
if (fd < 0) {
perror("open of /dev/dsp failed");
exit(1);
}
/* set sampling parameters */
arg = SIZE; /* sample size */
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_BITS ioctl failed");
if (arg != SIZE)
perror("unable to set sample size");
arg = CHANNELS; /* mono or stereo */
status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_CHANNELS ioctl failed");
if (arg != CHANNELS)
perror("unable to set number of channels");
arg = RATE; /* sampling rate */
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
if (status == -1)
perror("SOUND_PCM_WRITE_WRITE ioctl failed");
while (1) { /* loop until Control-C */
printf("Say something:\n");
status = read(fd, buf, sizeof(buf)); /* record some sound */
if (status != sizeof(buf))
perror("read wrong number of bytes");
printf("You said:\n");
status = write(fd, buf, sizeof(buf)); /* play it back */
if (status != sizeof(buf))
perror("wrote wrong number of bytes");
/* wait for playback to complete before recording again */
status = ioctl(fd, SOUND_PCM_SYNC, 0);
if (status == -1)
perror("SOUND_PCM_SYNC ioctl failed");
}
}
See, /dev/dsp was used on older versions of ubuntu linux. It's no longer available in newer versions of ubuntu. I think it was gone with 10.04. Things changed from 10.10.
From one of the websites:
10.10 Maverick finally disabled the very old OSS drivers (which provided /dev/dsp, so the padsp wrapper is the easiest way to handle if it you can't select ALSA or PulseAudio directly.
See this http://manpages.ubuntu.com/manpages/hardy/man1/padsp.1.html

ioctl giving Invalid Argument

I want to send a opened file descriptor between two different programs. So I am using ioctl with named pipes to do so. But there I am getting "Invalid argument" error for ioctl().
#include <stropts.h>
#include "accesories.c"
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#define MSGSIZ 63
char *fifo = "fifo";
int send_err(int fd, int errcode, const char *msg)
{
int n;
if ((n = strlen(msg)) > 0)
if (write(fd, msg, n) != n) /* send the error message */
return(-1);
if (errcode >= 0)
errcode = -1; /* must be negative */
if (send_fd(fd, errcode) < 0)
return(-1);
return(0);
}
int send_fd(int fd, int fd_to_send)
{
char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
buf[0] = 0; /* null byte flag to recv_fd() */
if (fd_to_send < 0) {
buf[1] = -fd_to_send; /* nonzero status means error */
if (buf[1] == 0)
buf[1] = 1; /* -256, etc. would screw up protocol */
} else {
buf[1] = 0; /* zero status means OK */
}
//printf("From the write %d\n",buf[0]);
if (write(fd, buf, 2) != 2)
return(-1);
if (fd_to_send >= 0)
if (ioctl(fd, I_SENDFD, fd_to_send) < 0)
{
printf("Eroor ::: %s\n",strerror(errno));
return(-1);
}
return(0);
}
int main(int argc, char const *argv[])
{
int fd, j, nwrite;
char msgbuf[MSGSIZ+1];
int fd_to_send;
if((fd_to_send = open("vi",O_RDONLY)) < 0)
printf("vi open failed");
if(argc < 2)
{
fprintf(stderr, "Usage: sendmessage msg ... \n");
exit(1);
}
/* open fifo with O_NONBLOCK set */
if((fd = open(fifo, O_WRONLY | O_NONBLOCK)) < 0)
printf("fifo open failed");
/* send messages */
for (j = 1; j < argc; j++)
{
if(strlen(argv[j]) > MSGSIZ)
{
fprintf(stderr, "message too long %s\n", argv[j]);
continue;
}
strcpy(msgbuf, argv[j]);
if((nwrite = write(fd, msgbuf, 6)) == -1)
printf("message write failed");
}
printf("From send_fd %d \n",send_fd(fd,fd_to_send));
exit(0);
}
The file accessories .h only contain some common include files nothing else.
First I am sending a simple message and then calling send_fd which is first sending a 2 byte message and then have to send file descriptor using ioctl(). But it is not.
It looks like linux doesn't support I_SENDFD. The comments indicate that I_SENDFD is in the documentation, but is not actually supported, and results in the error message you encountered. The wikipedia entry for STREAMS states the linux kernel does not have any support for streams. The wikipedia entry does point to a couple of third-party packages that could be used to add streams support, but LiS has not been ported to the 2.6 kernel, and OpenSS7 hasn't had any active development in 4 years.
However, linux does support something similar. This mechanism uses a special message type SCM_RIGHTS to deliver a file descriptor over a UNIX domain socket with sendmsg and obtained from recvmsg. Examples can be found with a simple web search, a complete example seems to be from the book The Linux Programming Interface, with source for sending and receiving.

Resources