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