]> sigrok.org Git - libsigrok.git/blob - hardware/alsa/protocol.c
alsa: Split into api.c and protocol.c
[libsigrok.git] / hardware / alsa / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2011 Daniel Ribeiro <drwyrm@gmail.com>
5  * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
6  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 #include "protocol.h"
24 #include "libsigrok.h"
25 #include "libsigrok-internal.h"
26
27 SR_PRIV int alsa_receive_data(int fd, int revents, void *cb_data)
28 {
29         struct sr_dev_inst *sdi;
30         struct dev_context *devc;
31         struct sr_datafeed_packet packet;
32         struct sr_datafeed_analog analog;
33         char inbuf[4096];
34         int i, x, count, offset, samples_to_get;
35         uint16_t tmp16;
36
37         (void)fd;
38         (void)revents;
39
40         sdi = cb_data;
41         devc = sdi->priv;
42
43         memset(&analog, 0, sizeof(struct sr_datafeed_analog));
44         memset(inbuf, 0, sizeof(inbuf));
45
46         samples_to_get = MIN(4096 / 4, devc->limit_samples);
47
48         sr_spew("Getting %d samples from audio device.", samples_to_get);
49         count = snd_pcm_readi(devc->capture_handle, inbuf, samples_to_get);
50
51         if (count < 0) {
52                 sr_err("Failed to read samples: %s.", snd_strerror(count));
53                 return FALSE;
54         } else if (count != samples_to_get) {
55                 sr_spew("Only got %d/%d samples.", count, samples_to_get);
56         }
57
58         analog.data = g_try_malloc0(count * sizeof(float) * devc->num_probes);
59         if (!analog.data) {
60                 sr_err("Failed to malloc sample buffer.");
61                 return FALSE;
62         }
63
64         offset = 0;
65
66         for (i = 0; i < count; i++) {
67                 for (x = 0; x < devc->num_probes; x++) {
68                         tmp16 = *(uint16_t *)(inbuf + (i * 4) + (x * 2));
69                         analog.data[offset++] = (float)tmp16;
70                 }
71         }
72
73         /* Send a sample packet with the analog values. */
74         analog.num_samples = count;
75         analog.mq = SR_MQ_VOLTAGE; /* FIXME */
76         analog.unit = SR_UNIT_VOLT; /* FIXME */
77         packet.type = SR_DF_ANALOG;
78         packet.payload = &analog;
79         sr_session_send(devc->cb_data, &packet);
80
81         g_free(analog.data);
82
83         devc->num_samples += count;
84
85         /* Stop acquisition if we acquired enough samples. */
86         if (devc->limit_samples > 0) {
87                 if (devc->num_samples >= devc->limit_samples) {
88                         sr_info("Requested number of samples reached.");
89                         sdi->driver->dev_acquisition_stop(sdi, cb_data);
90                 }
91         }
92
93         return TRUE;
94 }