aboutsummaryrefslogtreecommitdiff
path: root/apps/systemcmds/mixer/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/systemcmds/mixer/mixer.c')
-rw-r--r--apps/systemcmds/mixer/mixer.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/apps/systemcmds/mixer/mixer.c b/apps/systemcmds/mixer/mixer.c
new file mode 100644
index 000000000..c5adf8dbf
--- /dev/null
+++ b/apps/systemcmds/mixer/mixer.c
@@ -0,0 +1,342 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file Mixer utility.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <systemlib/mixer.h>
+#include <drivers/drv_mixer.h>
+#include <uORB/topics/actuator_controls.h>
+
+__EXPORT int mixer_main(int argc, char *argv[]);
+
+static void usage(void);
+static void load(const char *devname, const char *fname);
+static void save(const char *devname, const char *fname);
+static void show(const char *devname);
+
+enum Operation {
+ LOAD,
+ SAVE,
+ SHOW,
+ NONE
+};
+
+int
+mixer_main(int argc, char *argv[])
+{
+ const char *devname = NULL;
+ const char *fname = NULL;
+ int ch;
+ enum Operation todo = NONE;
+
+ if (argc < 2)
+ usage();
+ if (!strcmp(argv[1], "load")) {
+ todo = LOAD;
+ } else if (!strcmp(argv[1], "save")) {
+ todo = SAVE;
+ } else if (!strcmp(argv[1], "show")) {
+ todo = SHOW;
+ } else {
+ usage();
+ }
+
+ while ((ch = getopt(argc, argv, "d:f:")) != EOF) {
+ switch (ch) {
+ case 'd':
+ devname = optarg;
+ break;
+ case 'f':
+ fname = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ switch (todo) {
+ case LOAD:
+ if ((devname == NULL) || (fname == NULL))
+ usage();
+ load(devname, fname);
+ break;
+
+ case SAVE:
+ if ((devname == NULL) || (fname == NULL))
+ usage();
+ save(devname, fname);
+ break;
+
+ case SHOW:
+ if (devname == NULL)
+ usage();
+ show(devname);
+ break;
+ default:
+ exit(1);
+ }
+ return 0;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, " mixer {load|save|show} -d <device> [-f <filename>]\n");
+ exit(1);
+}
+
+static void
+load(const char *devname, const char *fname)
+{
+ int defs = -1;
+ int dev = -1;
+ unsigned num_mixers = 0;
+ int ret, result = 1;
+ struct MixMixer *mixer;
+
+ /* open the device */
+ if ((dev = open(devname, 0)) < 0) {
+ fprintf(stderr, "can't open %s\n", devname);
+ goto out;
+ }
+
+ /* open the definition file */
+ if ((defs = open(fname, O_RDONLY)) < 0) {
+ fprintf(stderr, "can't open %s\n", fname);
+ goto out;
+ }
+
+ /* find out how many mixers the device supports */
+ ioctl(dev, MIXERIOCGETMIXERCOUNT, (unsigned long)&num_mixers);
+ if (num_mixers < 1) {
+ fprintf(stderr, "can't get mixer count from %s\n", devname);
+ goto out;
+ }
+
+ /* send mixers to the device */
+ for (unsigned i = 0; i < num_mixers; i++) {
+ ret = mixer_load(defs, &mixer);
+ if (ret < 0)
+ goto out;
+
+ /* end of file? */
+ if (ret == 0)
+ break;
+
+ /* sanity check the mixer */
+ if (mixer_check(mixer, NUM_ACTUATOR_CONTROLS)) {
+ fprintf(stderr, "mixer %u fails sanity check\n", i);
+ goto out;
+ }
+
+ /* send the mixer to the device */
+ ret = ioctl(dev, MIXERIOCSETMIXER(i), (unsigned long)mixer);
+ if (ret < 0)
+ goto out;
+
+ free(mixer);
+ mixer = NULL;
+ }
+
+ printf("mixer: loaded %d mixers to %s\n", num_mixers, devname);
+ result = 0;
+
+out:
+ /* free the mixers array */
+ if (mixer != NULL)
+ free(mixer);
+ if (defs != -1)
+ close(defs);
+ if (dev != -1)
+ close(dev);
+
+ exit(result);
+}
+
+static int
+getmixer(int dev, unsigned mixer_number, struct MixInfo **mip)
+{
+ struct MixInfo *mi = *mip;
+ int ret;
+
+ /* first-round initialisation */
+ if (mi == NULL) {
+ mi->num_controls = 0;
+ mi = (struct MixInfo *)malloc(MIXINFO_SIZE(mi->num_controls));
+ }
+
+ /* loop trying to get the next mixer until the buffer is big enough */
+ do {
+ /* try to get the mixer into the buffer as it stands */
+ ret = ioctl(dev, MIXERIOCGETMIXER(mixer_number), (unsigned long)mi);
+ if (ret < 0) {
+ fprintf(stderr, "MIXERIOCGETMIXER error\n");
+ return -1;
+ }
+
+ /* did the mixer fit? */
+ if (mi->mixer.control_count <= mi->num_controls)
+ break;
+
+ /* re-allocate to suit */
+ mi->num_controls = mi->mixer.control_count;
+ mi = (struct MixInfo *)realloc(mi, MIXINFO_SIZE(mi->num_controls));
+
+ /* oops, blew up the heap */
+ if (mi == NULL)
+ return -1;
+
+ } while(true);
+
+ *mip = mi;
+ return 0;
+}
+
+static void
+save(const char *devname, const char *fname)
+{
+ struct MixInfo *mi = NULL;
+ int defs = -1;
+ int dev = -1;
+ unsigned num_mixers = 0;
+ int ret, result = 1;
+
+ /* open the device */
+ if ((dev = open(devname, 0)) < 0) {
+ fprintf(stderr, "can't open %s\n", devname);
+ goto out;
+ }
+
+ /* find out how many mixers the device supports */
+ ioctl(dev, MIXERIOCGETMIXERCOUNT, (unsigned long)&num_mixers);
+ if (num_mixers < 1) {
+ fprintf(stderr, "can't get mixer count from %s\n", devname);
+ goto out;
+ }
+
+ /* open the definition file */
+ if ((defs = open(fname, O_WRONLY | O_CREAT)) < 0) {
+ fprintf(stderr, "can't open %s\n", fname);
+ goto out;
+ }
+
+ /* get mixers from the device and save them */
+ for (unsigned i = 0; i < num_mixers; i++) {
+
+ ret = getmixer(dev, i, &mi);
+ if (ret < 0)
+ goto out;
+
+ ret = mixer_save(defs, &mi->mixer);
+ if (ret < 0)
+ goto out;
+ }
+
+ result = 0;
+
+out:
+ /* free the mixinfo */
+ if (mi != NULL)
+ free(mi);
+ if (defs != -1)
+ close(defs);
+ if (dev != -1)
+ close(dev);
+
+ exit(result);
+}
+
+static void
+show(const char *devname)
+{
+ struct MixInfo *mi;
+ int dev = -1;
+ unsigned num_mixers = 0;
+ int ret;
+
+ /* open the device */
+ if ((dev = open(devname, 0)) < 0) {
+ fprintf(stderr, "can't open %s\n", devname);
+ goto out;
+ }
+
+ /* find out how many mixers the device supports */
+ ioctl(dev, MIXERIOCGETMIXERCOUNT, (unsigned long)&num_mixers);
+ if (num_mixers < 1) {
+ fprintf(stderr, "can't get mixer count from %s\n", devname);
+ goto out;
+ }
+
+ /* get mixers from the device and print them */
+ for (unsigned i = 0; i < num_mixers; i++) {
+
+ ret = getmixer(dev, i, &mi);
+ if (ret < 0)
+ goto out;
+
+ printf("mixer %d : %d controls\n", i, mi->mixer.control_count);
+ printf(" -ve scale +ve scale offset low limit high limit");
+ printf("output %f %f %f %f %f\n",
+ mi->mixer.output_scaler.negative_scale,
+ mi->mixer.output_scaler.positive_scale,
+ mi->mixer.output_scaler.offset,
+ mi->mixer.output_scaler.lower_limit,
+ mi->mixer.output_scaler.upper_limit);
+ for (unsigned j = 0; j < mi->mixer.control_count; j++) {
+ printf("%d: %f %f %f %f %f\n",
+ mi->mixer.control_scaler[j].negative_scale,
+ mi->mixer.control_scaler[j].positive_scale,
+ mi->mixer.control_scaler[j].offset,
+ mi->mixer.control_scaler[j].lower_limit,
+ mi->mixer.control_scaler[j].upper_limit);
+ }
+ }
+
+out:
+ /* free the mixinfo */
+ if (mi != NULL)
+ free(mi);
+ if (dev != -1)
+ close(dev);
+ exit(0);
+}