+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/soundcard.h>
-#include <sys/time.h>
-#include <oss-redir.h>
-
-int main(void)
-{
- int fd, sz, fsz, i, tmp, n, l, have_data=0, nfrag;
- int caps, idx;
-
- int sd, sl=0, sp;
-
- unsigned char data[500000], *dp = data;
-
- struct buffmem_desc imemd, omemd;
- caddr_t buf;
- struct timeval tim;
-
- unsigned char *op;
-
- struct audio_buf_info info;
-
- int frag = 0xffff000c; /* Max # periods of 2^13=8k bytes */\r
-
- fd_set writeset;
-
- if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1) {
- perror("/dev/dsp");
- exit(-1);
- }
- tmp = 48000;
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_SPEED, &tmp) < 0) {
- perror("SNDCTL_DSP_SPEED\n");
- exit(EXIT_FAILURE);
- }
- printf("Speed set to %d\n", tmp);
-
- sl = sp = 0;
- if ((sd=open("smpl", O_RDONLY, 0)) >= 0) {
- sl = read(sd, data, sizeof(data));
- printf("%d bytes read from file.\n", sl);
- close(sd);
- } else
- perror("smpl");
-
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0) {
- perror("/dev/dsp");
- fprintf(stderr, "Sorry but your sound driver is too old\n");
- exit(EXIT_FAILURE);
- }
- if (!(caps & DSP_CAP_TRIGGER) ||
- !(caps & DSP_CAP_MMAP))
- {
- fprintf(stderr, "Sorry but your soundcard can't do this\n");
- exit(EXIT_FAILURE);
- }
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0)
- perror("SNDCTL_DSP_SETFRAGMENT");
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
- perror("SNDCTL_DSP_GETOSPACE");
- exit(EXIT_FAILURE);
- }
- sz = info.fragstotal * info.fragsize;
- fsz = info.fragsize;
- printf("info.fragstotal = %i\n", info.fragstotal);
- printf("info.fragsize = %i\n", info.fragsize);
- printf("info.periods = %i\n", info.fragments);
- printf("info.bytes = %i\n", info.bytes);
- if ((buf=mmap(NULL, sz, PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED) {
- perror("mmap (write)");
- exit(-1);
- }
- printf("mmap (out) returned %08x\n", buf);
- op=buf;
-
- tmp = 0;
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
- perror("SNDCTL_DSP_SETTRIGGER");
- exit(EXIT_FAILURE);
- }
- printf("Trigger set to %08x\n", tmp);
-
- tmp = PCM_ENABLE_OUTPUT;
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
- perror("SNDCTL_DSP_SETTRIGGER");
- exit(EXIT_FAILURE);
- }
- printf("Trigger set to %08x\n", tmp);
-
- nfrag = 0;
- for (idx=0; idx<40; idx++) {
- struct count_info count;
- int p, l, extra;
-
- FD_ZERO(&writeset);
- FD_SET(fd, &writeset);
-
- tim.tv_sec = 10;
- tim.tv_usec= 0;
-
- select(fd+1, NULL, &writeset, NULL, NULL);
- if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOPTR, &count) < 0) {
- perror("GETOPTR");
- exit(EXIT_FAILURE);
- }
- nfrag += count.blocks;
-#ifdef VERBOSE
- printf("Total: %09d, Period: %03d, Ptr: %06d", count.bytes, nfrag, count.ptr);\r
- fflush(stdout);
-#endif
- count.ptr = (count.ptr/fsz)*fsz;
-
-#ifdef VERBOSE
- printf(" memcpy(%6d, %4d)\n", (dp-data), fsz);
- fflush(stdout);
-#endif
-
-/*
- * Set few bytes in the beginning of next period too.\r
- */
- if ((count.ptr+fsz+16) < sz) /* Last period? */
- extra = 16;
- else
- extra = 0;
-
- memcpy(op+count.ptr, dp, fsz+extra);
-
- dp += fsz;
- if (dp > (data+sl-fsz))
- dp = data;
- }
-
- close(fd);
-
- printf("second open test:\n");
- if ((fd=oss_pcm_open("/dev/dsp", O_RDWR, 0))==-1) {
- perror("/dev/dsp");
- exit(-1);
- }
- close(fd);
- printf("second open test passed\n");
-
- exit(0);
-}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/soundcard.h>
+#include <sys/time.h>
+#include <oss-redir.h>
+
+#define VERBOSE 1
+
+//static char data[500000];
+static int verbose;
+static char *device = "/dev/dsp";
+static int rate = 48000;
+static int channels = 2;
+static int omode = O_RDWR;
+static int frag = 0xffff000c; /* Max # periods of 2^13=8k bytes */\r
+static int fd;
+static audio_buf_info ospace;
+static audio_buf_info ispace;
+static int bufsize;
+static int fragsize;
+static char *wbuf, *rbuf;
+
+static void help(void)
+{
+ printf(
+"Usage: mmap_test [OPTION]...\n"
+"-h,--help help\n"
+"-D,--device playback device\n"
+"-r,--rate stream rate in Hz\n"
+"-c,--channels count of channels in stream\n"
+"-f,--frequency sine wave frequency in Hz\n"
+"-b,--buffer ring buffer size in us\n"
+"-p,--period period size in us\n"
+"-m,--method transfer method (read/write/duplex)\n"
+"-v,--verbose show the PCM setup parameters\n"
+"\n");
+}
+
+static void set_params(void)
+{
+ int caps;
+
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SPEED, &rate) < 0) {
+ perror("SNDCTL_DSP_SPEED\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Rate set to %d\n", rate);
+
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) {
+ perror("SNDCTL_DSP_CHANNELS\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Channels set to %d\n", channels);
+
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) < 0) {
+ perror("/dev/dsp");
+ fprintf(stderr, "Sorry but your sound driver is too old\n");
+ exit(EXIT_FAILURE);
+ }
+ if (!(caps & DSP_CAP_TRIGGER) ||
+ !(caps & DSP_CAP_MMAP))
+ {
+ fprintf(stderr, "Sorry but your soundcard can't do this\n");
+ exit(EXIT_FAILURE);
+ }
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0)
+ perror("SNDCTL_DSP_SETFRAGMENT");
+ bufsize = fragsize = -1;
+ if (omode == O_RDWR || omode == O_WRONLY) {
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOSPACE, &ospace) < 0) {
+ perror("SNDCTL_DSP_GETOSPACE");
+ exit(EXIT_FAILURE);
+ }
+ bufsize = ospace.fragstotal * ospace.fragsize;
+ fragsize = ospace.fragsize;
+ printf("ospace.fragstotal = %i\n", ospace.fragstotal);
+ printf("ospace.fragsize = %i\n", ospace.fragsize);
+ printf("ospace.periods = %i\n", ospace.fragments);
+ printf("ospace.bytes = %i\n", ospace.bytes);
+ if ((wbuf=mmap(NULL, bufsize, PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED) {
+ perror("mmap (write)");
+ exit(-1);
+ }
+ printf("mmap (out) returned %p\n", wbuf);
+ }
+ if (omode == O_RDWR || omode == O_RDONLY) {
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETISPACE, &ispace) < 0) {
+ perror("SNDCTL_DSP_GETISPACE");
+ if (omode == O_RDWR) {
+ omode = O_WRONLY;
+ fprintf(stderr, "Falling to write only mode\n");
+ } else {
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (omode != O_WRONLY) {
+ if (bufsize < 0) {
+ bufsize = ispace.fragstotal * ispace.fragsize;
+ fragsize = ispace.fragsize;
+ }
+ printf("ispace.fragstotal = %i\n", ispace.fragstotal);
+ printf("ispace.fragsize = %i\n", ispace.fragsize);
+ printf("ispace.periods = %i\n", ispace.fragments);
+ printf("ispace.bytes = %i\n", ispace.bytes);
+ if ((rbuf=mmap(NULL, bufsize, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0))==MAP_FAILED) {
+ perror("mmap (read)");
+ exit(-1);
+ }
+ printf("mmap (in) returned %p\n", rbuf);
+ }
+ }
+}
+
+static void set_trigger(void)
+{
+ int tmp;
+
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
+ perror("SNDCTL_DSP_SETTRIGGER");
+ exit(EXIT_FAILURE);
+ }
+ printf("Trigger set to %08x\n", tmp);
+
+ if (omode == O_RDWR)
+ tmp = PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT;
+ else if (omode == O_RDONLY)
+ tmp = PCM_ENABLE_INPUT;
+ else if (omode == O_WRONLY)
+ tmp = PCM_ENABLE_OUTPUT;
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
+ perror("SNDCTL_DSP_SETTRIGGER");
+ exit(EXIT_FAILURE);
+ }
+ printf("Trigger set to %08x\n", tmp);
+}
+
+int main(int argc, char *argv[])
+{
+ int morehelp = 0;
+ int nfrag, idx;
+ struct timeval tim;
+ fd_set writeset, readset;
+ struct option long_option[] =
+ {
+ {"help", 0, NULL, 'h'},
+ {"device", 1, NULL, 'D'},
+ {"verbose", 1, NULL, 'v'},
+ {"omode", 1, NULL, 'M'},
+ {"rate", 1, NULL, 'r'},
+ {"channels", 1, NULL, 'c'},
+ {"frag", 1, NULL, 'F'},
+ {NULL, 0, NULL, 0},
+ };
+
+ morehelp = 0;
+ while (1) {
+ int c;
+ if ((c = getopt_long(argc, argv, "hD:M:r:c:F:v", long_option, NULL)) < 0)
+ break;
+ switch (c) {
+ case 'h':
+ morehelp++;
+ break;
+ case 'D':
+ device = strdup(optarg);
+ break;
+ case 'M':
+ if (!strcmp(optarg, "read"))
+ omode = O_RDONLY;
+ else if (!strcmp(optarg, "write"))
+ omode = O_WRONLY;
+ else
+ omode = O_RDWR;
+ break;
+ case 'r':
+ rate = atoi(optarg);
+ break;
+ case 'c':
+ channels = atoi(optarg);
+ break;
+ case 'F':
+ frag = atoi(optarg);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ }
+ }
+
+ if (morehelp) {
+ help();
+ return 0;
+ }
+
+ if ((fd=oss_pcm_open(device, O_RDWR, 0))==-1) {
+ perror("/dev/dsp");
+ exit(-1);
+ }
+
+ set_params();
+ set_trigger();
+
+
+ nfrag = 0;
+ for (idx=0; idx<40; idx++) {
+ struct count_info count;
+ int res;
+
+ FD_ZERO(&writeset);
+ FD_SET(fd, &writeset);
+
+ tim.tv_sec = 10;
+ tim.tv_usec= 0;
+
+ res = select(fd+1, NULL, &writeset, NULL, &tim);
+#ifdef VERBOSE
+ printf("Select returned: %03d\n", res);
+ fflush(stdout);
+#endif
+ if (oss_pcm_ioctl(fd, SNDCTL_DSP_GETOPTR, &count) < 0) {
+ perror("GETOPTR");
+ exit(EXIT_FAILURE);
+ }
+ nfrag += count.blocks;
+#ifdef VERBOSE
+ printf("Total: %09d, Period: %03d, Ptr: %06d\n", count.bytes, nfrag, count.ptr);
+ fflush(stdout);
+#endif
+ }
+
+ close(fd);
+
+ exit(0);
+}