]> sigrok.org Git - libsigrok.git/blame - hardware/alsa/protocol.c
zeroplus-logic-cube: fix samplerate setting
[libsigrok.git] / hardware / alsa / protocol.c
CommitLineData
9cd9f6b7
AG
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
9cd9f6b7
AG
23#include "libsigrok.h"
24#include "libsigrok-internal.h"
721ecf3d 25#include "protocol.h"
9cd9f6b7 26
65faa197
AG
27/*
28 * There is no way to get a list of supported samplerates from ALSA. We could
29 * use the 'plughw' interface of ALSA, in which case any format and/or
30 * samplerate conversion would be performed by ALSA. However, we are interested
31 * in the hardware capabilities, and have the infrastructure in sigrok to do so.
32 * We therefore use the 'hw' interface. The downside is that the code gets a
33 * little bulkier, as we have to keep track of the hardware capabilities, and
34 * only use those that the hardware supports. Case in point, ALSA will not give
35 * us a list of capabilities; we have to test for each one individually. Hence,
36 * we keep lists of the capabilities we are interested in.
37 */
38static const unsigned int rates[] = {
39 5512,
40 8000,
41 11025,
21d3d4ee 42 12000,
65faa197
AG
43 16000,
44 22050,
21d3d4ee 45 24000,
65faa197
AG
46 32000,
47 44100,
48 48000,
49 64000,
50 88200,
51 96000,
52 176400,
53 192000,
21d3d4ee
UH
54 384000,
55 768000, /* Yes, there are sound cards that go this high. */
65faa197
AG
56};
57
6944b2d0
AG
58static void alsa_scan_handle_dev(GSList **devices,
59 const char *cardname, const char *alsaname,
60 struct sr_dev_driver *di,
61 snd_pcm_info_t *pcminfo)
62{
63 struct drv_context *drvc = NULL;
64 struct sr_dev_inst *sdi = NULL;
65 struct dev_context *devc = NULL;
66 struct sr_probe *probe;
67 int ret;
65faa197
AG
68 unsigned int i, offset, channels, minrate, maxrate, rate;
69 uint64_t hwrates[ARRAY_SIZE(rates)];
70 uint64_t *devrates = NULL;
6944b2d0
AG
71 snd_pcm_t *temp_handle = NULL;
72 snd_pcm_hw_params_t *hw_params = NULL;
721ecf3d 73 char p_name[32];
6944b2d0
AG
74
75 drvc = di->priv;
76
77 /*
65faa197
AG
78 * Get hardware parameters:
79 * The number of channels, for example, are our sigrok probes. Getting
80 * this information needs a detour. We need to open the device, then
81 * query it and/or test different parameters. A side-effect of is that
82 * we create a snd_pcm_hw_params_t object. We take advantage of the
6944b2d0
AG
83 * situation, and pass this object in our dev_context->hw_params,
84 * eliminating the need to free() it and malloc() it later.
85 */
86 ret = snd_pcm_open(&temp_handle, alsaname, SND_PCM_STREAM_CAPTURE, 0);
87 if (ret < 0) {
88 sr_err("Cannot open device: %s.", snd_strerror(ret));
89 goto scan_error_cleanup;
90 }
91
92 ret = snd_pcm_hw_params_malloc(&hw_params);
93 if (ret < 0) {
94 sr_err("Error allocating hardware parameter structure: %s.",
95 snd_strerror(ret));
96 goto scan_error_cleanup;
97 }
98
99 ret = snd_pcm_hw_params_any(temp_handle, hw_params);
100 if (ret < 0) {
101 sr_err("Error initializing hardware parameter structure: %s.",
102 snd_strerror(ret));
103 goto scan_error_cleanup;
104 }
105
106 snd_pcm_hw_params_get_channels_max(hw_params, &channels);
107
65faa197
AG
108 /*
109 * We need to test if each samplerate between min and max is supported.
110 * Unfortunately, ALSA won't just throw a list at us.
111 */
112 snd_pcm_hw_params_get_rate_min(hw_params, &minrate, 0);
113 snd_pcm_hw_params_get_rate_max(hw_params, &maxrate, 0);
721ecf3d 114 for (i = 0, offset = 0; i < ARRAY_SIZE(rates); i++) {
65faa197
AG
115 rate = rates[i];
116 if (rate < minrate)
117 continue;
118 if (rate > maxrate)
119 break;
120 ret = snd_pcm_hw_params_test_rate(temp_handle, hw_params,
121 rate, 0);
122 if (ret >= 0)
123 hwrates[offset++] = rate;
124 }
125 hwrates[offset++] = 0;
126
52ba6e05
UH
127 if ((ret = snd_pcm_close(temp_handle)) < 0)
128 sr_err("Failed to close device: %s.", snd_strerror(ret));
6944b2d0
AG
129 temp_handle = NULL;
130
131 /*
65faa197 132 * Now we are done querying the hardware parameters.
721ecf3d
UH
133 * If we made it here, we know everything we want to know, and it's
134 * time to create our sigrok device.
6944b2d0
AG
135 */
136 sr_info("Device %s has %d channels.", alsaname, channels);
137 if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "ALSA:",
138 cardname, snd_pcm_info_get_name(pcminfo)))) {
721ecf3d 139 sr_err("Failed to create device instance.");
6944b2d0
AG
140 goto scan_error_cleanup;
141 }
142 if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
143 sr_err("Device context malloc failed.");
144 goto scan_error_cleanup;
145 }
65faa197
AG
146 if (!(devrates = g_try_malloc(offset * sizeof(uint64_t)))) {
147 sr_err("Samplerate list malloc failed.");
148 goto scan_error_cleanup;
149 }
6944b2d0
AG
150
151 devc->hwdev = g_strdup(alsaname);
152 devc->num_probes = channels;
153 devc->hw_params = hw_params;
65faa197
AG
154 memcpy(devrates, hwrates, offset * sizeof(uint64_t));
155 devc->supp_rates.list = devrates;
156
6944b2d0
AG
157 sdi->priv = devc;
158 sdi->driver = di;
159
160 for (i = 0; i < devc->num_probes; i++) {
6944b2d0
AG
161 snprintf(p_name, sizeof(p_name), "Ch_%d", i);
162 if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, p_name)))
163 goto scan_error_cleanup;
164 sdi->probes = g_slist_append(sdi->probes, probe);
165 }
166
167 drvc->instances = g_slist_append(drvc->instances, sdi);
168 *devices = g_slist_append(*devices, sdi);
169 return;
170
171scan_error_cleanup:
172 if (devc) {
173 if (devc->hwdev)
721ecf3d 174 g_free(devc->hwdev);
6944b2d0
AG
175 g_free(devc);
176 }
65faa197
AG
177 if (devrates)
178 g_free(devrates);
6944b2d0
AG
179 if (sdi)
180 sr_dev_inst_free(sdi);
181 if (hw_params)
182 snd_pcm_hw_params_free(hw_params);
183 if (temp_handle)
52ba6e05
UH
184 if ((ret = snd_pcm_close(temp_handle)) < 0) {
185 sr_err("Failed to close device: %s.",
186 snd_strerror(ret));
187 }
6944b2d0
AG
188}
189
190/**
721ecf3d
UH
191 * Scan all alsa devices, and translate them to sigrok devices.
192 *
193 * Each alsa device (not alsa card) gets its own sigrok device.
6944b2d0 194 *
6944b2d0
AG
195 * For example,
196 * hw:1,0 == sigrok device 0
197 * hw:1,1 == sigrok device 1
198 * hw:2,0 == sigrok device 2
199 * hw:2,1 == sigrok device 3
200 * hw:2,2 == sigrok device 4
201 * [...]
721ecf3d 202 *
6944b2d0 203 * We don't currently look at alsa subdevices. We only use subdevice 0.
721ecf3d 204 * Every input device will have its own channels (left, right, etc). Each of
6944b2d0
AG
205 * those channels gets mapped to a different sigrok probe. A device with 4
206 * channels will have 4 probes from sigrok's perspective.
207 */
208SR_PRIV GSList *alsa_scan(GSList *options, struct sr_dev_driver *di)
209{
210 GSList *devices = NULL;
211 snd_ctl_t *handle;
212 int card, ret, dev;
213 snd_ctl_card_info_t *info;
214 snd_pcm_info_t *pcminfo;
721ecf3d
UH
215 const char *cardname;
216 char hwcard[32], hwdev[32];
217
6944b2d0
AG
218 /* TODO */
219 (void)options;
220
52ba6e05 221 if ((ret = snd_ctl_card_info_malloc(&info)) < 0) {
3d6de074 222 sr_dbg("Failed to malloc card info: %s.", snd_strerror(ret));
6944b2d0
AG
223 return NULL;
224 }
52ba6e05 225 if ((ret = snd_pcm_info_malloc(&pcminfo) < 0)) {
3d6de074 226 sr_dbg("Cannot malloc pcm info: %s.", snd_strerror(ret));
6944b2d0
AG
227 return NULL;
228 }
229
230 card = -1;
231 while (snd_card_next(&card) >= 0 && card >= 0) {
6944b2d0
AG
232 snprintf(hwcard, sizeof(hwcard), "hw:%d", card);
233 if ((ret = snd_ctl_open(&handle, hwcard, 0)) < 0) {
3d6de074 234 sr_dbg("Cannot open (%d): %s.", card, snd_strerror(ret));
6944b2d0
AG
235 continue;
236 }
237 if ((ret = snd_ctl_card_info(handle, info)) < 0) {
3d6de074 238 sr_dbg("Cannot get hardware info (%d): %s.",
6944b2d0 239 card, snd_strerror(ret));
52ba6e05 240 if ((ret = snd_ctl_close(handle)) < 0) {
3d6de074 241 sr_dbg("Cannot close device (%d): %s.",
52ba6e05
UH
242 card, snd_strerror(ret));
243 }
6944b2d0
AG
244 continue;
245 }
246 dev = -1;
247 while (snd_ctl_pcm_next_device(handle, &dev) >= 0 && dev >= 0) {
6944b2d0
AG
248 snprintf(hwdev, sizeof(hwdev), "%s,%d", hwcard, dev);
249 /*
250 * TODO: We always use subdevice 0, but we have yet to
251 * explore the possibilities opened up by other
252 * subdevices. Most hardware only has subdevice 0.
253 */
254 snd_pcm_info_set_device(pcminfo, dev);
255 snd_pcm_info_set_subdevice(pcminfo, 0);
256 snd_pcm_info_set_stream(pcminfo,
257 SND_PCM_STREAM_CAPTURE);
258 if ((ret = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
3d6de074 259 sr_dbg("Cannot get device info (%s): %s.",
52ba6e05 260 hwdev, snd_strerror(ret));
6944b2d0
AG
261 continue;
262 }
263
264 cardname = snd_ctl_card_info_get_name(info);
721ecf3d 265 sr_info("card %d: %s [%s], device %d: %s [%s]",
6944b2d0
AG
266 card, snd_ctl_card_info_get_id(info), cardname,
267 dev, snd_pcm_info_get_id(pcminfo),
268 snd_pcm_info_get_name(pcminfo));
269
270 alsa_scan_handle_dev(&devices, cardname, hwdev,
271 di, pcminfo);
272 }
52ba6e05 273 if ((ret = snd_ctl_close(handle)) < 0) {
3d6de074 274 sr_dbg("Cannot close device (%d): %s.",
52ba6e05
UH
275 card, snd_strerror(ret));
276 }
6944b2d0
AG
277 }
278
279 snd_pcm_info_free(pcminfo);
280 snd_ctl_card_info_free(info);
281
282 return devices;
283}
284
285/*
286 * Helper to be used with g_slist_free_full(); for properly freeing an alsa
287 * dev instance.
288 */
289SR_PRIV void alsa_dev_inst_clear(struct sr_dev_inst *sdi)
290{
291 struct dev_context *devc;
292
293 if (!(devc = sdi->priv))
294 return;
295
296 snd_pcm_hw_params_free(devc->hw_params);
65faa197 297 g_free((void*)devc->supp_rates.list);
6944b2d0
AG
298 sr_dev_inst_free(sdi);
299}
300
721ecf3d
UH
301/**
302 * Set the samplerate of the ALSA device.
65faa197
AG
303 *
304 * Changes the samplerate of the given ALSA device if the specified samplerate
305 * is supported by the hardware.
721ecf3d 306 *
65faa197
AG
307 * The new samplerate is recorded, but it is not applied to the hardware. The
308 * samplerate is applied to the hardware only when acquisition is started via
309 * dev_acquisition_start(), and cannot be changed during acquisition. To change
310 * the samplerate, several steps are needed:
721ecf3d 311 *
65faa197
AG
312 * 1) If acquisition is running, it must first be stopped.
313 * 2) dev_config_set() must be called with the new samplerate.
314 * 3) When starting a new acquisition, the new samplerate is applied.
721ecf3d 315 *
65faa197
AG
316 */
317SR_PRIV int alsa_set_samplerate(const struct sr_dev_inst *sdi,
721ecf3d 318 uint64_t newrate)
65faa197
AG
319{
320 struct dev_context *devc;
321 size_t i;
322 uint64_t rate = 0;
323
324 if (!(devc = sdi->priv))
325 return SR_ERR_ARG;
326
327 i = 0;
328 do {
329 if (newrate == devc->supp_rates.list[i]) {
330 rate = newrate;
331 break;
332 }
333 } while (devc->supp_rates.list[i++] != 0);
334
335 if (!rate) {
a1b9a9bf 336 sr_err("Sample rate %" PRIu64 " not supported.", newrate);
65faa197
AG
337 return SR_ERR_ARG;
338 }
339
340 devc->cur_samplerate = rate;
341 return SR_OK;
342}
343
9cd9f6b7
AG
344SR_PRIV int alsa_receive_data(int fd, int revents, void *cb_data)
345{
346 struct sr_dev_inst *sdi;
347 struct dev_context *devc;
348 struct sr_datafeed_packet packet;
349 struct sr_datafeed_analog analog;
729850c9 350 int16_t inbuf[4096];
9cd9f6b7 351 int i, x, count, offset, samples_to_get;
729850c9 352 int16_t tmp16;
721ecf3d 353 const float s16norm = 1 / (float)(1 << 15);
9cd9f6b7
AG
354
355 (void)fd;
356 (void)revents;
357
358 sdi = cb_data;
359 devc = sdi->priv;
360
361 memset(&analog, 0, sizeof(struct sr_datafeed_analog));
362 memset(inbuf, 0, sizeof(inbuf));
363
364 samples_to_get = MIN(4096 / 4, devc->limit_samples);
365
366 sr_spew("Getting %d samples from audio device.", samples_to_get);
367 count = snd_pcm_readi(devc->capture_handle, inbuf, samples_to_get);
368
369 if (count < 0) {
370 sr_err("Failed to read samples: %s.", snd_strerror(count));
371 return FALSE;
372 } else if (count != samples_to_get) {
373 sr_spew("Only got %d/%d samples.", count, samples_to_get);
374 }
375
376 analog.data = g_try_malloc0(count * sizeof(float) * devc->num_probes);
377 if (!analog.data) {
378 sr_err("Failed to malloc sample buffer.");
379 return FALSE;
380 }
381
382 offset = 0;
729850c9
AG
383 /*
384 * It's impossible to know what voltage levels the soundcard handles.
385 * Some handle 0 dBV rms, some 0dBV peak-to-peak, +4dbmW (600 ohm), etc
386 * Each of these corresponds to a different voltage, and there is no
387 * mechanism to determine this voltage. The best solution is to send all
388 * audio data as a normalized float, and let the frontend or user worry
389 * about the calibration.
390 */
391 for (i = 0; i < count; i += devc->num_probes) {
9cd9f6b7 392 for (x = 0; x < devc->num_probes; x++) {
721ecf3d 393 tmp16 = inbuf[i + x];
729850c9 394 analog.data[offset++] = tmp16 * s16norm;
9cd9f6b7
AG
395 }
396 }
397
398 /* Send a sample packet with the analog values. */
69e19dd7 399 analog.probes = sdi->probes;
9cd9f6b7
AG
400 analog.num_samples = count;
401 analog.mq = SR_MQ_VOLTAGE; /* FIXME */
402 analog.unit = SR_UNIT_VOLT; /* FIXME */
403 packet.type = SR_DF_ANALOG;
404 packet.payload = &analog;
405 sr_session_send(devc->cb_data, &packet);
406
407 g_free(analog.data);
408
409 devc->num_samples += count;
410
411 /* Stop acquisition if we acquired enough samples. */
35e199da
UH
412 if (devc->limit_samples && devc->num_samples >= devc->limit_samples) {
413 sr_info("Requested number of samples reached.");
414 sdi->driver->dev_acquisition_stop(sdi, cb_data);
9cd9f6b7
AG
415 }
416
417 return TRUE;
418}