libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
alsa.c
Go to the documentation of this file.
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2011 Daniel Ribeiro <drwyrm@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /* Note: This driver doesn't compile, analog support in sigrok is WIP. */
22 
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <alsa/asoundlib.h>
27 #include "sigrok.h"
28 #include "sigrok-internal.h"
29 
30 #define NUM_PROBES 2
31 #define SAMPLE_WIDTH 16
32 #define AUDIO_DEV "plughw:0,0"
33 
35  uint8_t att;
36  uint8_t res; /* Needs to be a power of 2, FIXME */
37  uint16_t val; /* Max hardware ADC width is 16bits */
38 };
39 
41  uint8_t num_probes; /* Max hardware probes is 256 */
43 };
44 
45 static int hwcaps[] = {
49 };
50 
51 /* TODO: Which probe names/numbers to use? */
52 static const char *probe_names[NUM_PROBES + 1] = {
53  "0",
54  "1",
55  NULL,
56 };
57 
58 static GSList *dev_insts = NULL;
59 
60 /* Private, per-device-instance driver context. */
61 struct context {
62  uint64_t cur_rate;
63  uint64_t limit_samples;
64  snd_pcm_t *capture_handle;
65  snd_pcm_hw_params_t *hw_params;
67 };
68 
69 static int hw_init(const char *devinfo)
70 {
71  struct sr_dev_inst *sdi;
72  struct context *ctx;
73 
74  /* Avoid compiler warnings. */
75  (void)devinfo;
76 
77  if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
78  sr_err("alsa: %s: ctx malloc failed", __func__);
79  return 0;
80  }
81 
82  if (!(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "alsa", NULL, NULL))) {
83  sr_err("alsa: %s: sdi was NULL", __func__);
84  goto free_ctx;
85  }
86 
87  sdi->priv = ctx;
88 
89  dev_insts = g_slist_append(dev_insts, sdi);
90 
91  return 1;
92 
93 free_ctx:
94  g_free(ctx);
95  return 0;
96 }
97 
98 static int hw_dev_open(int dev_index)
99 {
100  struct sr_dev_inst *sdi;
101  struct context *ctx;
102  int ret;
103 
104  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
105  return SR_ERR;
106  ctx = sdi->priv;
107 
108  ret = snd_pcm_open(&ctx->capture_handle, AUDIO_DEV,
109  SND_PCM_STREAM_CAPTURE, 0);
110  if (ret < 0) {
111  sr_err("alsa: can't open audio device %s (%s)", AUDIO_DEV,
112  snd_strerror(ret));
113  return SR_ERR;
114  }
115 
116  ret = snd_pcm_hw_params_malloc(&ctx->hw_params);
117  if (ret < 0) {
118  sr_err("alsa: can't allocate hardware parameter structure (%s)",
119  snd_strerror(ret));
120  return SR_ERR;
121  }
122 
123  ret = snd_pcm_hw_params_any(ctx->capture_handle, ctx->hw_params);
124  if (ret < 0) {
125  sr_err("alsa: can't initialize hardware parameter structure "
126  "(%s)", snd_strerror(ret));
127  return SR_ERR;
128  }
129 
130  return SR_OK;
131 }
132 
133 static int hw_dev_close(int dev_index)
134 {
135  struct sr_dev_inst *sdi;
136  struct context *ctx;
137 
138  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
139  sr_err("alsa: %s: sdi was NULL", __func__);
140  return SR_ERR_BUG;
141  }
142 
143  if (!(ctx = sdi->priv)) {
144  sr_err("alsa: %s: sdi->priv was NULL", __func__);
145  return SR_ERR_BUG;
146  }
147 
148  // TODO: Return values of snd_*?
149  if (ctx->hw_params)
150  snd_pcm_hw_params_free(ctx->hw_params);
151  if (ctx->capture_handle)
152  snd_pcm_close(ctx->capture_handle);
153 
154  return SR_OK;
155 }
156 
157 static int hw_cleanup(void)
158 {
159  struct sr_dev_inst *sdi;
160 
161  if (!(sdi = sr_dev_inst_get(dev_insts, 0))) {
162  sr_err("alsa: %s: sdi was NULL", __func__);
163  return SR_ERR_BUG;
164  }
165 
166  sr_dev_inst_free(sdi);
167 
168  return SR_OK;
169 }
170 
171 static void *hw_dev_info_get(int dev_index, int dev_info_id)
172 {
173  struct sr_dev_inst *sdi;
174  struct context *ctx;
175  void *info = NULL;
176 
177  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
178  return NULL;
179  ctx = sdi->priv;
180 
181  switch (dev_info_id) {
182  case SR_DI_INST:
183  info = sdi;
184  break;
185  case SR_DI_NUM_PROBES:
186  info = GINT_TO_POINTER(NUM_PROBES);
187  break;
188  case SR_DI_PROBE_NAMES:
189  info = probe_names;
190  break;
192  info = &ctx->cur_rate;
193  break;
194  // case SR_DI_PROBE_TYPE:
195  // info = GINT_TO_POINTER(SR_PROBE_TYPE_ANALOG);
196  // break;
197  }
198 
199  return info;
200 }
201 
202 static int hw_dev_status_get(int dev_index)
203 {
204  /* Avoid compiler warnings. */
205  dev_index = dev_index;
206 
207  return SR_ST_ACTIVE;
208 }
209 
210 static int *hw_hwcap_get_all(void)
211 {
212  return hwcaps;
213 }
214 
215 static int hw_dev_config_set(int dev_index, int hwcap, void *value)
216 {
217  struct sr_dev_inst *sdi;
218  struct context *ctx;
219 
220  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
221  return SR_ERR;
222  ctx = sdi->priv;
223 
224  switch (hwcap) {
226  return SR_OK;
227  case SR_HWCAP_SAMPLERATE:
228  ctx->cur_rate = *(uint64_t *)value;
229  return SR_OK;
231  ctx->limit_samples = *(uint64_t *)value;
232  return SR_OK;
233  default:
234  return SR_ERR;
235  }
236 }
237 
238 static int receive_data(int fd, int revents, void *cb_data)
239 {
240  struct sr_dev_inst *sdi = cb_data;
241  struct context *ctx = sdi->priv;
242  struct sr_datafeed_packet packet;
243  struct sr_analog_sample *sample;
244  unsigned int sample_size = sizeof(struct sr_analog_sample) +
245  (NUM_PROBES * sizeof(struct sr_analog_probe));
246  char *outb;
247  char inb[4096];
248  int i, x, count;
249 
250  fd = fd;
251  revents = revents;
252 
253  do {
254  memset(inb, 0, sizeof(inb));
255  count = snd_pcm_readi(ctx->capture_handle, inb,
256  MIN(4096 / 4, ctx->limit_samples));
257  if (count < 1) {
258  sr_err("alsa: Failed to read samples");
259  return FALSE;
260  }
261 
262  if (!(outb = g_try_malloc(sample_size * count))) {
263  sr_err("alsa: %s: outb malloc failed", __func__);
264  return FALSE;
265  }
266 
267  for (i = 0; i < count; i++) {
268  sample = (struct sr_analog_sample *)
269  (outb + (i * sample_size));
270  sample->num_probes = NUM_PROBES;
271 
272  for (x = 0; x < NUM_PROBES; x++) {
273  sample->probes[x].val =
274  *(uint16_t *)(inb + (i * 4) + (x * 2));
275  sample->probes[x].val &= ((1 << 16) - 1);
276  sample->probes[x].res = 16;
277  }
278  }
279 
280  packet.type = SR_DF_ANALOG;
281  packet.length = count * sample_size;
282  packet.unitsize = sample_size;
283  packet.payload = outb;
284  sr_session_send(sdi, &packet);
285  g_free(outb);
286  ctx->limit_samples -= count;
287 
288  } while (ctx->limit_samples > 0);
289 
290  packet.type = SR_DF_END;
291  sr_session_send(sdi, &packet);
292 
293  return TRUE;
294 }
295 
296 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
297 {
298  struct sr_dev_inst *sdi;
299  struct context *ctx;
300  struct sr_datafeed_packet packet;
301  struct sr_datafeed_header header;
302  struct pollfd *ufds;
303  int count;
304  int ret;
305 
306  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
307  return SR_ERR;
308  ctx = sdi->priv;
309 
310  ret = snd_pcm_hw_params_set_access(ctx->capture_handle,
311  ctx->hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
312  if (ret < 0) {
313  sr_err("alsa: can't set access type (%s)", snd_strerror(ret));
314  return SR_ERR;
315  }
316 
317  /* FIXME: Hardcoded for 16bits */
318  ret = snd_pcm_hw_params_set_format(ctx->capture_handle,
319  ctx->hw_params, SND_PCM_FORMAT_S16_LE);
320  if (ret < 0) {
321  sr_err("alsa: can't set sample format (%s)", snd_strerror(ret));
322  return SR_ERR;
323  }
324 
325  ret = snd_pcm_hw_params_set_rate_near(ctx->capture_handle,
326  ctx->hw_params, (unsigned int *)&ctx->cur_rate, 0);
327  if (ret < 0) {
328  sr_err("alsa: can't set sample rate (%s)", snd_strerror(ret));
329  return SR_ERR;
330  }
331 
332  ret = snd_pcm_hw_params_set_channels(ctx->capture_handle,
333  ctx->hw_params, NUM_PROBES);
334  if (ret < 0) {
335  sr_err("alsa: can't set channel count (%s)", snd_strerror(ret));
336  return SR_ERR;
337  }
338 
339  ret = snd_pcm_hw_params(ctx->capture_handle, ctx->hw_params);
340  if (ret < 0) {
341  sr_err("alsa: can't set parameters (%s)", snd_strerror(ret));
342  return SR_ERR;
343  }
344 
345  ret = snd_pcm_prepare(ctx->capture_handle);
346  if (ret < 0) {
347  sr_err("alsa: can't prepare audio interface for use (%s)",
348  snd_strerror(ret));
349  return SR_ERR;
350  }
351 
352  count = snd_pcm_poll_descriptors_count(ctx->capture_handle);
353  if (count < 1) {
354  sr_err("alsa: Unable to obtain poll descriptors count");
355  return SR_ERR;
356  }
357 
358  if (!(ufds = g_try_malloc(count * sizeof(struct pollfd)))) {
359  sr_err("alsa: %s: ufds malloc failed", __func__);
360  return SR_ERR_MALLOC;
361  }
362 
363  ret = snd_pcm_poll_descriptors(ctx->capture_handle, ufds, count);
364  if (ret < 0) {
365  sr_err("alsa: Unable to obtain poll descriptors (%s)",
366  snd_strerror(ret));
367  g_free(ufds);
368  return SR_ERR;
369  }
370 
371  ctx->session_dev_id = cb_data;
372  sr_source_add(ufds[0].fd, ufds[0].events, 10, receive_data, sdi);
373 
374  packet.type = SR_DF_HEADER;
375  packet.length = sizeof(struct sr_datafeed_header);
376  packet.payload = (unsigned char *)&header;
377  header.feed_version = 1;
378  gettimeofday(&header.starttime, NULL);
379  header.samplerate = ctx->cur_rate;
380  header.num_analog_probes = NUM_PROBES;
381  header.num_logic_probes = 0;
382  header.protocol_id = SR_PROTO_RAW;
383  sr_session_send(cb_data, &packet);
384  g_free(ufds);
385 
386  return SR_OK;
387 }
388 
389 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
390 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
391 {
392  /* Avoid compiler warnings. */
393  (void)dev_index;
394  (void)cb_data;
395 
396  return SR_OK;
397 }
398 
400  .name = "alsa",
401  .longname = "ALSA driver",
402  .api_version = 1,
403  .init = hw_init,
404  .cleanup = hw_cleanup,
405  .dev_open = hw_dev_open,
406  .dev_close = hw_dev_close,
407  .dev_info_get = hw_dev_info_get,
408  .dev_status_get = hw_dev_status_get,
409  .hwcap_get_all = hw_hwcap_get_all,
410  .dev_config_set = hw_dev_config_set,
411  .dev_acquisition_start = hw_dev_acquisition_start,
412  .dev_acquisition_stop = hw_dev_acquisition_stop,
413 };
snd_pcm_t * capture_handle
Definition: alsa.c:64
char * name
Definition: sigrok.h:389
The device supports continuous sampling, i.e.
Definition: sigrok.h:311
Definition: alsa.c:61
int dev_index
Definition: demo.c:74
struct sr_analog_probe probes[]
Definition: alsa.c:42
snd_pcm_hw_params_t * hw_params
Definition: alsa.c:65
uint8_t num_probes
Definition: alsa.c:41
The device supports setting a sample number limit, i.e.
Definition: sigrok.h:304
void * priv
Definition: sigrok.h:330
uint8_t att
Definition: alsa.c:35
SR_PRIV int sr_source_add(int fd, int events, int timeout, sr_receive_data_callback_t cb, void *cb_data)
Definition: hwdriver.c:317
void * session_dev_id
TODO.
Definition: alsa.c:66
#define SR_PRIV
Definition: sigrok.h:133
#define SR_OK
Definition: sigrok.h:82
SR_PRIV struct sr_dev_inst * sr_dev_inst_get(GSList *dev_insts, int dev_index)
Definition: hwdriver.c:184
#define SR_ERR_BUG
Definition: sigrok.h:86
uint64_t cur_rate
Definition: alsa.c:62
SR_PRIV struct sr_dev_inst * sr_dev_inst_new(int index, int status, const char *vendor, const char *model, const char *version)
Definition: hwdriver.c:163
The device supports setting/changing its samplerate.
Definition: sigrok.h:262
The device supports setting a probe mask.
Definition: sigrok.h:266
SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi)
Definition: hwdriver.c:199
SR_PRIV struct sr_dev_driver alsa_driver_info
Definition: alsa.c:399
uint8_t res
Definition: alsa.c:36
#define SR_ERR_MALLOC
Definition: sigrok.h:84
uint16_t val
Definition: alsa.c:37
#define SR_ERR
Definition: sigrok.h:83
uint64_t limit_samples
The current sampling limit (in number of samples).
Definition: alsa.c:63
SR_PRIV int sr_session_send(struct sr_dev *dev, struct sr_datafeed_packet *packet)
Send a packet to whatever is listening on the datafeed bus.
Definition: session.c:435
SR_PRIV int sr_err(const char *format,...)
Definition: log.c:253
#define AUDIO_DEV
Definition: alsa.c:32
#define NUM_PROBES
Definition: alsa.c:30