From 9cd9f6b71c35c0203b7e8997ce9425d0dc6e0f4d Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Thu, 20 Dec 2012 11:33:49 -0600 Subject: [PATCH] alsa: Split into api.c and protocol.c This is the driver model agreed upon for all drivers. As a result of the split, a devc->num_probes field had to be added in order to reduce the interdependence between api.c and protocol.c . Signed-off-by: Alexandru Gagniuc --- hardware/alsa/Makefile.am | 4 +- hardware/alsa/{alsa.c => api.c} | 109 ++++---------------------------- hardware/alsa/protocol.c | 94 +++++++++++++++++++++++++++ hardware/alsa/protocol.h | 55 ++++++++++++++++ 4 files changed, 163 insertions(+), 99 deletions(-) rename hardware/alsa/{alsa.c => api.c} (77%) create mode 100644 hardware/alsa/protocol.c create mode 100644 hardware/alsa/protocol.h diff --git a/hardware/alsa/Makefile.am b/hardware/alsa/Makefile.am index f5f2a453..87c6b50b 100644 --- a/hardware/alsa/Makefile.am +++ b/hardware/alsa/Makefile.am @@ -23,7 +23,9 @@ if HW_ALSA noinst_LTLIBRARIES = libsigrokhwalsa.la libsigrokhwalsa_la_SOURCES = \ - alsa.c + protocol.h \ + protocol.c \ + api.c libsigrokhwalsa_la_CFLAGS = \ -I$(top_srcdir) diff --git a/hardware/alsa/alsa.c b/hardware/alsa/api.c similarity index 77% rename from hardware/alsa/alsa.c rename to hardware/alsa/api.c index 9dad6281..77025c13 100644 --- a/hardware/alsa/alsa.c +++ b/hardware/alsa/api.c @@ -19,23 +19,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -#include +#include "protocol.h" #include "libsigrok.h" #include "libsigrok-internal.h" -/* Message logging helpers with driver-specific prefix string. */ -#define DRIVER_LOG_DOMAIN "alsa: " -#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) -#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args) -#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args) -#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args) -#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) -#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) +#include +#include +#include -#define NUM_PROBES 2 +#define DEFAULT_PROBES 2 #define SAMPLE_WIDTH 16 #define DEFAULT_SAMPLERATE 44100 // #define AUDIO_DEV "plughw:0,0" @@ -57,17 +49,6 @@ static const char *probe_names[] = { SR_PRIV struct sr_dev_driver alsa_driver_info; static struct sr_dev_driver *di = &alsa_driver_info; -/** Private, per-device-instance driver context. */ -struct dev_context { - uint64_t cur_samplerate; - uint64_t limit_samples; - uint64_t num_samples; - snd_pcm_t *capture_handle; - snd_pcm_hw_params_t *hw_params; - struct pollfd *ufds; - void *cb_data; -}; - static int clear_instances(void) { /* TODO */ @@ -118,6 +99,7 @@ static GSList *hw_scan(GSList *options) /* Set the samplerate to a default value for now. */ devc->cur_samplerate = DEFAULT_SAMPLERATE; + devc->num_probes = DEFAULT_PROBES; sdi->priv = devc; sdi->driver = di; @@ -229,7 +211,7 @@ static int hw_info_get(int info_id, const void **data, *data = hwcaps; break; case SR_DI_NUM_PROBES: - *data = GINT_TO_POINTER(NUM_PROBES); + *data = GINT_TO_POINTER(DEFAULT_PROBES); break; case SR_DI_PROBE_NAMES: *data = probe_names; @@ -267,75 +249,6 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, return SR_OK; } -static int 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; - char inbuf[4096]; - int i, x, count, offset, samples_to_get; - uint16_t tmp16; - - (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) * NUM_PROBES); - if (!analog.data) { - sr_err("Failed to malloc sample buffer."); - return FALSE; - } - - offset = 0; - - for (i = 0; i < count; i++) { - for (x = 0; x < NUM_PROBES; x++) { - tmp16 = *(uint16_t *)(inbuf + (i * 4) + (x * 2)); - analog.data[offset++] = (float)tmp16; - } - } - - /* Send a sample packet with the analog values. */ - 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 > 0) { - if (devc->num_samples >= devc->limit_samples) { - sr_info("Requested number of samples reached."); - sdi->driver->dev_acquisition_stop(sdi, cb_data); - } - } - - return TRUE; -} - static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { @@ -374,9 +287,9 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, return SR_ERR; } - sr_dbg("Setting audio channel count to %d.", NUM_PROBES); + sr_dbg("Setting audio channel count to %d.", devc->num_probes); ret = snd_pcm_hw_params_set_channels(devc->capture_handle, - devc->hw_params, NUM_PROBES); + devc->hw_params, devc->num_probes); if (ret < 0) { sr_err("Can't set channel count: %s.", snd_strerror(ret)); return SR_ERR; @@ -430,12 +343,12 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, sr_dbg("Sending SR_DF_META_ANALOG packet."); packet.type = SR_DF_META_ANALOG; packet.payload = &meta; - meta.num_probes = NUM_PROBES; + meta.num_probes = devc->num_probes; sr_session_send(devc->cb_data, &packet); /* Poll every 10ms, or whenever some data comes in. */ sr_source_add(devc->ufds[0].fd, devc->ufds[0].events, 10, - receive_data, (void *)sdi); + alsa_receive_data, (void *)sdi); // g_free(devc->ufds); /* FIXME */ diff --git a/hardware/alsa/protocol.c b/hardware/alsa/protocol.c new file mode 100644 index 00000000..ff6a3f85 --- /dev/null +++ b/hardware/alsa/protocol.c @@ -0,0 +1,94 @@ +/* + * 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 "protocol.h" +#include "libsigrok.h" +#include "libsigrok-internal.h" + +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; + char inbuf[4096]; + int i, x, count, offset, samples_to_get; + uint16_t tmp16; + + (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_probes); + if (!analog.data) { + sr_err("Failed to malloc sample buffer."); + return FALSE; + } + + offset = 0; + + for (i = 0; i < count; i++) { + for (x = 0; x < devc->num_probes; x++) { + tmp16 = *(uint16_t *)(inbuf + (i * 4) + (x * 2)); + analog.data[offset++] = (float)tmp16; + } + } + + /* Send a sample packet with the analog values. */ + 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 > 0) { + if (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 new file mode 100644 index 00000000..c66fc1ec --- /dev/null +++ b/hardware/alsa/protocol.h @@ -0,0 +1,55 @@ +/* + * 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 "libsigrok.h" +#include "libsigrok-internal.h" + +#include +#include + +/* Message logging helpers with driver-specific prefix string. */ +#define DRIVER_LOG_DOMAIN "alsa: " +#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) +#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args) +#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args) +#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args) +#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) +#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) + +/** Private, per-device-instance driver context. */ +struct dev_context { + uint64_t cur_samplerate; + uint64_t limit_samples; + uint64_t num_samples; + uint8_t num_probes; + snd_pcm_t *capture_handle; + snd_pcm_hw_params_t *hw_params; + struct pollfd *ufds; + void *cb_data; +}; + +SR_PRIV int alsa_receive_data(int fd, int revents, void *cb_data); + +#endif /* LIBSIGROK_HARDWARE_ALSA_PROTOCOL_H */