From 7e7b7fb7d323f7600958bf29025ca089a15829e3 Mon Sep 17 00:00:00 2001 From: Bert Vermeulen Date: Sat, 19 Apr 2014 13:37:53 +0200 Subject: [PATCH] Removed ALSA driver. This driver has been unmaintained for years, and was never good code to begin with. It's also questionable whether it was ever useful, particularly with the demo driver now supporting various analog signalling. --- Makefile.am | 6 - configure.ac | 19 +- hardware/alsa/api.c | 348 --------------------------------- hardware/alsa/protocol.c | 402 --------------------------------------- hardware/alsa/protocol.h | 52 ----- 5 files changed, 1 insertion(+), 826 deletions(-) delete mode 100644 hardware/alsa/api.c delete mode 100644 hardware/alsa/protocol.c delete mode 100644 hardware/alsa/protocol.h diff --git a/Makefile.am b/Makefile.am index 481bbe3c..4023778b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -105,12 +105,6 @@ libsigrok_la_SOURCES += \ hardware/agilent-dmm/agilent-dmm.h \ hardware/agilent-dmm/sched.c endif -if HW_ALSA -libsigrok_la_SOURCES += \ - hardware/alsa/protocol.h \ - hardware/alsa/protocol.c \ - hardware/alsa/api.c -endif if HW_APPA_55II libsigrok_la_SOURCES += \ hardware/appa-55ii/protocol.h \ diff --git a/configure.ac b/configure.ac index 5d76c16f..f8db30c7 100644 --- a/configure.ac +++ b/configure.ac @@ -89,11 +89,6 @@ AC_ARG_ENABLE(agilent-dmm, AC_HELP_STRING([--enable-agilent-dmm], [HW_AGILENT_DMM="$enableval"], [HW_AGILENT_DMM=$HW_ENABLED_DEFAULT]) -AC_ARG_ENABLE(alsa, AC_HELP_STRING([--enable-alsa], - [enable ALSA driver support [default=yes]]), - [HW_ALSA="$enableval"], - [HW_ALSA=$HW_ENABLED_DEFAULT]) - AC_ARG_ENABLE(appa-55ii, AC_HELP_STRING([--enable-appa-55ii], [enable APPA 55II support [default=yes]]), [HW_APPA_55II="$enableval"], @@ -387,12 +382,6 @@ PKG_CHECK_MODULES([libudev], [libudev >= 151], SR_PKGLIBS="$SR_PKGLIBS libudev"], [HW_LINK_MSO19="no"]) -# ALSA is only needed for some hardware drivers. Disable them if not found. -PKG_CHECK_MODULES([alsa], [alsa >= 1.0], - [CFLAGS="$CFLAGS $alsa_CFLAGS"; LIBS="$LIBS $alsa_LIBS"; - SR_PKGLIBS="$SR_PKGLIBS alsa"], - [HW_ALSA="no"]) - # The Check unit testing framework is optional. Disable if not found. PKG_CHECK_MODULES([check], [check >= 0.9.4], [have_check="yes"; CFLAGS="$CFLAGS $check_CFLAGS"; @@ -416,11 +405,6 @@ if test "x$HW_AGILENT_DMM" = "xyes"; then AC_DEFINE(HAVE_HW_AGILENT_DMM, 1, [Agilent DMM support]) fi -AM_CONDITIONAL(HW_ALSA, test x$HW_ALSA = xyes) -if test "x$HW_ALSA" = "xyes"; then - AC_DEFINE(HAVE_HW_ALSA, 1, [ALSA driver support]) -fi - AM_CONDITIONAL(HW_APPA_55II, test x$HW_APPA_55II = xyes) if test "x$HW_APPA_55II" = "xyes"; then AC_DEFINE(HAVE_HW_APPA_55II, 1, [APPA 55II support]) @@ -628,7 +612,7 @@ echo "Detected libraries:" echo # Note: This only works for libs with pkg-config integration. -for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.10" "libserialport >= 0.1.0" "librevisa >= 0.0.20130812" "libusb-1.0 >= 1.0.16" "libftdi >= 0.16" "libudev >= 151" "alsa >= 1.0" "check >= 0.9.4"; do +for lib in "glib-2.0 >= 2.32.0" "libzip >= 0.10" "libserialport >= 0.1.0" "librevisa >= 0.0.20130812" "libusb-1.0 >= 1.0.16" "libftdi >= 0.16" "libudev >= 151" "check >= 0.9.4"; do optional="OPTIONAL" if test "x$lib" = "xglib-2.0 >= 2.32.0"; then optional="REQUIRED"; fi if test "x$lib" = "xlibzip >= 0.10"; then optional="REQUIRED"; fi @@ -643,7 +627,6 @@ done echo -e "\nEnabled hardware drivers:\n" echo " - agilent-dmm..................... $HW_AGILENT_DMM" -echo " - alsa............................ $HW_ALSA" echo " - appa-55ii....................... $HW_APPA_55II" echo " - asix-sigma...................... $HW_ASIX_SIGMA" echo " - atten-pps3xxx................... $HW_ATTEN_PPS3XXX" diff --git a/hardware/alsa/api.c b/hardware/alsa/api.c deleted file mode 100644 index 82af3d0e..00000000 --- a/hardware/alsa/api.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011 Daniel Ribeiro - * Copyright (C) 2012 Uwe Hermann - * Copyright (C) 2012 Alexandru Gagniuc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "protocol.h" - -static const int32_t hwcaps[] = { - SR_CONF_SAMPLERATE, - SR_CONF_LIMIT_SAMPLES, - SR_CONF_CONTINUOUS, -}; - -SR_PRIV struct sr_dev_driver alsa_driver_info; -static struct sr_dev_driver *di = &alsa_driver_info; - -static void clear_helper(void *priv) -{ - struct dev_context *devc; - - devc = priv; - - snd_pcm_hw_params_free(devc->hw_params); - devc->hw_params = NULL; - - g_free((void *)devc->samplerates); - devc->samplerates = NULL; -} - -static int dev_clear(void) -{ - return std_dev_clear(di, clear_helper); -} - -static int init(struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - -static GSList *scan(GSList *options) -{ - return alsa_scan(options, di); -} - -static GSList *dev_list(void) -{ - return ((struct drv_context *)(di->priv))->instances; -} - -static int dev_open(struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - int ret; - - devc = sdi->priv; - - if (!(devc->hwdev)) { - sr_err("devc->hwdev was NULL."); - return SR_ERR_BUG; - } - - sr_dbg("Opening audio device '%s' for stream capture.", devc->hwdev); - ret = snd_pcm_open(&devc->capture_handle, devc->hwdev, - SND_PCM_STREAM_CAPTURE, 0); - if (ret < 0) { - sr_err("Can't open audio device: %s.", snd_strerror(ret)); - return SR_ERR; - } - - sr_dbg("Initializing hardware parameter structure."); - ret = snd_pcm_hw_params_any(devc->capture_handle, devc->hw_params); - if (ret < 0) { - sr_err("Can't initialize hardware parameter structure: %s.", - snd_strerror(ret)); - return SR_ERR; - } - - sdi->status = SR_ST_ACTIVE; - - return SR_OK; -} - -static int dev_close(struct sr_dev_inst *sdi) -{ - int ret; - struct dev_context *devc; - - devc = sdi->priv; - - if (devc->capture_handle) { - sr_dbg("Closing PCM device."); - if ((ret = snd_pcm_close(devc->capture_handle)) < 0) - sr_err("Failed to close device: %s.", - snd_strerror(ret)); - devc->capture_handle = NULL; - sdi->status = SR_ST_INACTIVE; - } else { - sr_dbg("No capture handle, no need to close audio device."); - } - - return SR_OK; -} - -static int cleanup(void) -{ - return dev_clear(); -} - -static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - switch (id) { - case SR_CONF_SAMPLERATE: - devc = sdi->priv; - *data = g_variant_new_uint64(devc->cur_samplerate); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - - (void)cg; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - - switch (id) { - case SR_CONF_SAMPLERATE: - alsa_set_samplerate(sdi, g_variant_get_uint64(data)); - break; - case SR_CONF_LIMIT_SAMPLES: - devc->limit_samples = g_variant_get_uint64(data); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) -{ - struct dev_context *devc; - GVariant *gvar; - GVariantBuilder gvb; - int i; - - (void)cg; - - switch (key) { - case SR_CONF_DEVICE_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, - hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); - break; - case SR_CONF_SAMPLERATE: - if (!sdi || !sdi->priv) - return SR_ERR_ARG; - devc = sdi->priv; - if (!devc->samplerates) { - sr_err("Instance did not contain a samplerate list."); - return SR_ERR_ARG; - } - for (i = 0; devc->samplerates[i]; i++) - ; - g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); - gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), - devc->samplerates, i, sizeof(uint64_t)); - g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar); - *data = g_variant_builder_end(&gvb); - break; - default: - return SR_ERR_NA; - } - - return SR_OK; -} - -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) -{ - struct dev_context *devc; - int count, ret; - char *endianness; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - devc = sdi->priv; - devc->cb_data = cb_data; - devc->num_samples = 0; - - sr_dbg("Setting audio access type to RW/interleaved."); - ret = snd_pcm_hw_params_set_access(devc->capture_handle, - devc->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (ret < 0) { - sr_err("Can't set audio access type: %s.", snd_strerror(ret)); - return SR_ERR; - } - - /* FIXME: Hardcoded for 16bits. */ - if (SND_PCM_FORMAT_S16 == SND_PCM_FORMAT_S16_LE) - endianness = "little endian"; - else - endianness = "big endian"; - sr_dbg("Setting audio sample format to signed 16bit (%s).", endianness); - ret = snd_pcm_hw_params_set_format(devc->capture_handle, - devc->hw_params, - SND_PCM_FORMAT_S16); - if (ret < 0) { - sr_err("Can't set audio sample format: %s.", snd_strerror(ret)); - return SR_ERR; - } - - sr_dbg("Setting audio samplerate to %" PRIu64 "Hz.", - devc->cur_samplerate); - ret = snd_pcm_hw_params_set_rate(devc->capture_handle, devc->hw_params, - (unsigned int)devc->cur_samplerate, 0); - if (ret < 0) { - sr_err("Can't set audio sample rate: %s.", snd_strerror(ret)); - return SR_ERR; - } - - sr_dbg("Setting audio channel count to %d.", devc->num_channels); - ret = snd_pcm_hw_params_set_channels(devc->capture_handle, - devc->hw_params, devc->num_channels); - if (ret < 0) { - sr_err("Can't set channel count: %s.", snd_strerror(ret)); - return SR_ERR; - } - - sr_dbg("Setting audio parameters."); - ret = snd_pcm_hw_params(devc->capture_handle, devc->hw_params); - if (ret < 0) { - sr_err("Can't set parameters: %s.", snd_strerror(ret)); - return SR_ERR; - } - - sr_dbg("Preparing audio interface for use."); - ret = snd_pcm_prepare(devc->capture_handle); - if (ret < 0) { - sr_err("Can't prepare audio interface for use: %s.", - snd_strerror(ret)); - return SR_ERR; - } - - count = snd_pcm_poll_descriptors_count(devc->capture_handle); - if (count < 1) { - sr_err("Unable to obtain poll descriptors count."); - return SR_ERR; - } - - if (!(devc->ufds = g_try_malloc(count * sizeof(struct pollfd)))) { - sr_err("Failed to malloc ufds."); - return SR_ERR_MALLOC; - } - - sr_spew("Getting %d poll descriptors.", count); - ret = snd_pcm_poll_descriptors(devc->capture_handle, devc->ufds, count); - if (ret < 0) { - sr_err("Unable to obtain poll descriptors: %s.", - snd_strerror(ret)); - g_free(devc->ufds); - return SR_ERR; - } - - /* Send header packet to the session bus. */ - std_session_send_df_header(cb_data, LOG_PREFIX); - - /* Poll every 10ms, or whenever some data comes in. */ - sr_source_add(devc->ufds[0].fd, devc->ufds[0].events, 10, - alsa_receive_data, (void *)sdi); - - // g_free(devc->ufds); /* FIXME */ - - return SR_OK; -} - -static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) -{ - struct sr_datafeed_packet packet; - struct dev_context *devc; - - devc = sdi->priv; - devc->cb_data = cb_data; - - sr_source_remove(devc->ufds[0].fd); - - /* Send end packet to the session bus. */ - sr_dbg("Sending SR_DF_END packet."); - packet.type = SR_DF_END; - sr_session_send(cb_data, &packet); - - return SR_OK; -} - -SR_PRIV struct sr_dev_driver alsa_driver_info = { - .name = "alsa", - .longname = "ALSA driver", - .api_version = 1, - .init = init, - .cleanup = cleanup, - .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, - .config_get = config_get, - .config_set = config_set, - .config_list = config_list, - .dev_open = dev_open, - .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, - .dev_acquisition_stop = dev_acquisition_stop, - .priv = NULL, -}; diff --git a/hardware/alsa/protocol.c b/hardware/alsa/protocol.c deleted file mode 100644 index 6975d2fb..00000000 --- a/hardware/alsa/protocol.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011 Daniel Ribeiro - * Copyright (C) 2012 Uwe Hermann - * Copyright (C) 2012 Alexandru Gagniuc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "protocol.h" - -/* - * There is no way to get a list of supported samplerates from ALSA. We could - * use the 'plughw' interface of ALSA, in which case any format and/or - * samplerate conversion would be performed by ALSA. However, we are interested - * in the hardware capabilities, and have the infrastructure in sigrok to do so. - * We therefore use the 'hw' interface. The downside is that the code gets a - * little bulkier, as we have to keep track of the hardware capabilities, and - * only use those that the hardware supports. Case in point, ALSA will not give - * us a list of capabilities; we have to test for each one individually. Hence, - * we keep lists of the capabilities we are interested in. - */ -static const unsigned int rates[] = { - 5512, - 8000, - 11025, - 12000, - 16000, - 22050, - 24000, - 32000, - 44100, - 48000, - 64000, - 88200, - 96000, - 176400, - 192000, - 384000, - 768000, /* Yes, there are sound cards that go this high. */ -}; - -static void alsa_scan_handle_dev(GSList **devices, - const char *cardname, const char *alsaname, - struct sr_dev_driver *di, - snd_pcm_info_t *pcminfo) -{ - struct drv_context *drvc = NULL; - struct sr_dev_inst *sdi = NULL; - struct dev_context *devc = NULL; - struct sr_channel *ch; - int ret; - unsigned int i, offset, channels, minrate, maxrate, rate; - uint64_t hwrates[ARRAY_SIZE(rates)]; - uint64_t *devrates = NULL; - snd_pcm_t *temp_handle = NULL; - snd_pcm_hw_params_t *hw_params = NULL; - char p_name[32]; - - drvc = di->priv; - - /* - * Get hardware parameters: - * The number of channels, for example, are our sigrok channels. Getting - * this information needs a detour. We need to open the device, then - * query it and/or test different parameters. A side-effect of is that - * we create a snd_pcm_hw_params_t object. We take advantage of the - * situation, and pass this object in our dev_context->hw_params, - * eliminating the need to free() it and malloc() it later. - */ - ret = snd_pcm_open(&temp_handle, alsaname, SND_PCM_STREAM_CAPTURE, 0); - if (ret < 0) { - sr_err("Cannot open device: %s.", snd_strerror(ret)); - goto scan_error_cleanup; - } - - ret = snd_pcm_hw_params_malloc(&hw_params); - if (ret < 0) { - sr_err("Error allocating hardware parameter structure: %s.", - snd_strerror(ret)); - goto scan_error_cleanup; - } - - ret = snd_pcm_hw_params_any(temp_handle, hw_params); - if (ret < 0) { - sr_err("Error initializing hardware parameter structure: %s.", - snd_strerror(ret)); - goto scan_error_cleanup; - } - - snd_pcm_hw_params_get_channels_max(hw_params, &channels); - - /* - * We need to test if each samplerate between min and max is supported. - * Unfortunately, ALSA won't just throw a list at us. - */ - snd_pcm_hw_params_get_rate_min(hw_params, &minrate, 0); - snd_pcm_hw_params_get_rate_max(hw_params, &maxrate, 0); - for (i = 0, offset = 0; i < ARRAY_SIZE(rates); i++) { - rate = rates[i]; - if (rate < minrate) - continue; - if (rate > maxrate) - break; - ret = snd_pcm_hw_params_test_rate(temp_handle, hw_params, - rate, 0); - if (ret >= 0) - hwrates[offset++] = rate; - } - hwrates[offset++] = 0; - - if ((ret = snd_pcm_close(temp_handle)) < 0) - sr_err("Failed to close device: %s.", snd_strerror(ret)); - temp_handle = NULL; - - /* - * Now we are done querying the hardware parameters. - * If we made it here, we know everything we want to know, and it's - * time to create our sigrok device. - */ - sr_info("Device %s has %d channels.", alsaname, channels); - if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "ALSA:", - cardname, snd_pcm_info_get_name(pcminfo)))) { - sr_err("Failed to create device instance."); - goto scan_error_cleanup; - } - if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) { - sr_err("Device context malloc failed."); - goto scan_error_cleanup; - } - if (!(devrates = g_try_malloc(offset * sizeof(uint64_t)))) { - sr_err("Samplerate list malloc failed."); - goto scan_error_cleanup; - } - - devc->hwdev = g_strdup(alsaname); - devc->num_channels = channels; - devc->hw_params = hw_params; - memcpy(devrates, hwrates, offset * sizeof(uint64_t)); - devc->samplerates = devrates; - - sdi->priv = devc; - sdi->driver = di; - - for (i = 0; i < devc->num_channels; i++) { - snprintf(p_name, sizeof(p_name), "Ch_%d", i); - if (!(ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, p_name))) - goto scan_error_cleanup; - sdi->channels = g_slist_append(sdi->channels, ch); - } - - drvc->instances = g_slist_append(drvc->instances, sdi); - *devices = g_slist_append(*devices, sdi); - return; - -scan_error_cleanup: - if (devc) { - if (devc->hwdev) - g_free(devc->hwdev); - g_free(devc); - } - if (devrates) - g_free(devrates); - if (sdi) - sr_dev_inst_free(sdi); - if (hw_params) - snd_pcm_hw_params_free(hw_params); - if (temp_handle) - if ((ret = snd_pcm_close(temp_handle)) < 0) { - sr_err("Failed to close device: %s.", - snd_strerror(ret)); - } -} - -/** - * Scan all alsa devices, and translate them to sigrok devices. - * - * Each alsa device (not alsa card) gets its own sigrok device. - * - * For example, - * hw:1,0 == sigrok device 0 - * hw:1,1 == sigrok device 1 - * hw:2,0 == sigrok device 2 - * hw:2,1 == sigrok device 3 - * hw:2,2 == sigrok device 4 - * [...] - * - * We don't currently look at alsa subdevices. We only use subdevice 0. - * Every input device will have its own channels (left, right, etc). Each of - * those channels gets mapped to a different sigrok channel. A device with 4 - * channels will have 4 channels from sigrok's perspective. - */ -SR_PRIV GSList *alsa_scan(GSList *options, struct sr_dev_driver *di) -{ - GSList *devices = NULL; - snd_ctl_t *handle; - int card, ret, dev; - snd_ctl_card_info_t *info; - snd_pcm_info_t *pcminfo; - const char *cardname; - char hwcard[32], hwdev[32]; - - /* TODO */ - (void)options; - - if ((ret = snd_ctl_card_info_malloc(&info)) < 0) { - sr_dbg("Failed to malloc card info: %s.", snd_strerror(ret)); - return NULL; - } - if ((ret = snd_pcm_info_malloc(&pcminfo) < 0)) { - sr_dbg("Cannot malloc pcm info: %s.", snd_strerror(ret)); - return NULL; - } - - card = -1; - while (snd_card_next(&card) >= 0 && card >= 0) { - snprintf(hwcard, sizeof(hwcard), "hw:%d", card); - if ((ret = snd_ctl_open(&handle, hwcard, 0)) < 0) { - sr_dbg("Cannot open (%d): %s.", card, snd_strerror(ret)); - continue; - } - if ((ret = snd_ctl_card_info(handle, info)) < 0) { - sr_dbg("Cannot get hardware info (%d): %s.", - card, snd_strerror(ret)); - if ((ret = snd_ctl_close(handle)) < 0) { - sr_dbg("Cannot close device (%d): %s.", - card, snd_strerror(ret)); - } - continue; - } - dev = -1; - while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) { - snprintf(hwdev, sizeof(hwdev), "%s,%d", hwcard, dev); - /* - * TODO: We always use subdevice 0, but we have yet to - * explore the possibilities opened up by other - * subdevices. Most hardware only has subdevice 0. - */ - snd_pcm_info_set_device(pcminfo, dev); - snd_pcm_info_set_subdevice(pcminfo, 0); - snd_pcm_info_set_stream(pcminfo, - SND_PCM_STREAM_CAPTURE); - if ((ret = snd_ctl_pcm_info(handle, pcminfo)) < 0) { - sr_dbg("Cannot get device info (%s): %s.", - hwdev, snd_strerror(ret)); - continue; - } - - cardname = snd_ctl_card_info_get_name(info); - sr_info("card %d: %s [%s], device %d: %s [%s]", - card, snd_ctl_card_info_get_id(info), cardname, - dev, snd_pcm_info_get_id(pcminfo), - snd_pcm_info_get_name(pcminfo)); - - alsa_scan_handle_dev(&devices, cardname, hwdev, - di, pcminfo); - } - if ((ret = snd_ctl_close(handle)) < 0) { - sr_dbg("Cannot close device (%d): %s.", - card, snd_strerror(ret)); - } - } - - snd_pcm_info_free(pcminfo); - snd_ctl_card_info_free(info); - - return devices; -} - -/** - * Set the samplerate of the ALSA device. - * - * Changes the samplerate of the given ALSA device if the specified samplerate - * is supported by the hardware. - * - * The new samplerate is recorded, but it is not applied to the hardware. The - * samplerate is applied to the hardware only when acquisition is started via - * dev_acquisition_start(), and cannot be changed during acquisition. To change - * the samplerate, several steps are needed: - * - * 1) If acquisition is running, it must first be stopped. - * 2) dev_config_set() must be called with the new samplerate. - * 3) When starting a new acquisition, the new samplerate is applied. - * - */ -SR_PRIV int alsa_set_samplerate(const struct sr_dev_inst *sdi, - uint64_t newrate) -{ - struct dev_context *devc; - size_t i; - uint64_t rate = 0; - - if (!(devc = sdi->priv)) - return SR_ERR_ARG; - - i = 0; - do { - if (newrate == devc->samplerates[i]) { - rate = newrate; - break; - } - } while (devc->samplerates[i++] != 0); - - if (!rate) { - sr_err("Sample rate %" PRIu64 " not supported.", newrate); - return SR_ERR_ARG; - } - - devc->cur_samplerate = rate; - return SR_OK; -} - -SR_PRIV int alsa_receive_data(int fd, int revents, void *cb_data) -{ - struct sr_dev_inst *sdi; - struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_analog analog; - int16_t inbuf[4096]; - int i, x, count, offset, samples_to_get; - int16_t tmp16; - const float s16norm = 1 / (float)(1 << 15); - - (void)fd; - (void)revents; - - sdi = cb_data; - devc = sdi->priv; - - memset(&analog, 0, sizeof(struct sr_datafeed_analog)); - memset(inbuf, 0, sizeof(inbuf)); - - samples_to_get = MIN(4096 / 4, devc->limit_samples); - - sr_spew("Getting %d samples from audio device.", samples_to_get); - count = snd_pcm_readi(devc->capture_handle, inbuf, samples_to_get); - - if (count < 0) { - sr_err("Failed to read samples: %s.", snd_strerror(count)); - return FALSE; - } else if (count != samples_to_get) { - sr_spew("Only got %d/%d samples.", count, samples_to_get); - } - - analog.data = g_try_malloc0(count * sizeof(float) * devc->num_channels); - if (!analog.data) { - sr_err("Failed to malloc sample buffer."); - return FALSE; - } - - offset = 0; - /* - * It's impossible to know what voltage levels the soundcard handles. - * Some handle 0 dBV rms, some 0dBV peak-to-peak, +4dbmW (600 ohm), etc - * Each of these corresponds to a different voltage, and there is no - * mechanism to determine this voltage. The best solution is to send all - * audio data as a normalized float, and let the frontend or user worry - * about the calibration. - */ - for (i = 0; i < count; i += devc->num_channels) { - for (x = 0; x < devc->num_channels; x++) { - tmp16 = inbuf[i + x]; - analog.data[offset++] = tmp16 * s16norm; - } - } - - /* Send a sample packet with the analog values. */ - analog.channels = sdi->channels; - analog.num_samples = count; - analog.mq = SR_MQ_VOLTAGE; /* FIXME */ - analog.unit = SR_UNIT_VOLT; /* FIXME */ - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(devc->cb_data, &packet); - - g_free(analog.data); - - devc->num_samples += count; - - /* Stop acquisition if we acquired enough samples. */ - if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - } - - return TRUE; -} diff --git a/hardware/alsa/protocol.h b/hardware/alsa/protocol.h deleted file mode 100644 index 465ebbaa..00000000 --- a/hardware/alsa/protocol.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the libsigrok project. - * - * Copyright (C) 2011 Daniel Ribeiro - * Copyright (C) 2012 Uwe Hermann - * Copyright (C) 2012 Alexandru Gagniuc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef LIBSIGROK_HARDWARE_ALSA_PROTOCOL_H -#define LIBSIGROK_HARDWARE_ALSA_PROTOCOL_H - -#include -#include -#include "libsigrok.h" -#include "libsigrok-internal.h" - -#define LOG_PREFIX "alsa" - -/** Private, per-device-instance driver context. */ -struct dev_context { - uint64_t cur_samplerate; - uint64_t limit_samples; - uint64_t num_samples; - uint8_t num_channels; - uint64_t *samplerates; - char *hwdev; - snd_pcm_t *capture_handle; - snd_pcm_hw_params_t *hw_params; - struct pollfd *ufds; - void *cb_data; -}; - -SR_PRIV GSList *alsa_scan(GSList *options, struct sr_dev_driver *di); -SR_PRIV int alsa_set_samplerate(const struct sr_dev_inst *sdi, - uint64_t newrate); -SR_PRIV int alsa_receive_data(int fd, int revents, void *cb_data); - -#endif