]> sigrok.org Git - libsigrok.git/blob - hardware/mastech-va18b/api.c
sr: Unfinished Mastech VA18B (DMM) support.
[libsigrok.git] / hardware / mastech-va18b / api.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
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 #include <stdlib.h>
22 #include "sigrok.h"
23 #include "sigrok-internal.h"
24
25 #define MIN_NUM_SAMPLES 1
26
27 struct context {
28         uint64_t limit_samples;
29         uint64_t limit_msec; /* TODO: Implement. */
30         uint64_t num_samples;
31         void *session_dev_id;
32 };
33
34 static const int hwcaps[] = {
35         SR_HWCAP_OSCILLOSCOPE,
36         SR_HWCAP_LIMIT_SAMPLES,
37         // SR_HWCAP_LIMIT_MSEC,
38         // SR_HWCAP_CONTINUOUS,
39         0,
40 };
41
42 static const char *probe_names[] = {
43         "Probe",
44         NULL,
45 };
46
47 static GSList *dev_insts = NULL;
48
49 /* Function prototypes. */
50 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
51
52 static int hw_init(const char *devinfo)
53 {
54         struct sr_dev_inst *sdi;
55         struct context *ctx;
56         int devcnt = 0;
57
58         /* Avoid compiler warnings. */
59         (void)devinfo; /* TODO: This specifies the serial port to use. */
60
61         if (!(ctx = g_try_malloc0(sizeof(struct context)))) {
62                 sr_err("va18b: %s: ctx malloc failed.", __func__);
63                 return 0;
64         }
65
66         ctx->limit_samples = 0;
67         ctx->limit_msec = 0;
68         ctx->num_samples = 0;
69         ctx->session_dev_id = NULL;
70
71         if (!(sdi = sr_dev_inst_new(devcnt, SR_ST_ACTIVE,
72                                     "Mastech", "VA18B", ""))) {
73                 sr_err("va18b: %s: sr_dev_inst_new returned NULL.", __func__);
74                 return 0;
75         }
76
77         sdi->priv = ctx;
78         dev_insts = g_slist_append(dev_insts, sdi);
79
80         devcnt = 1;
81
82         return devcnt;
83 }
84
85 static int hw_dev_open(int dev_index)
86 {
87         /* Avoid compiler warnings. */
88         (void)dev_index;
89
90         /* TODO. */
91
92         return SR_OK;
93 }
94
95 static int hw_dev_close(int dev_index)
96 {
97         /* Avoid compiler warnings. */
98         (void)dev_index;
99
100         /* TODO. */
101
102         return SR_OK;
103 }
104
105 static int hw_cleanup(void)
106 {
107         GSList *l;
108         struct sr_dev_inst *sdi;
109         struct context *ctx;
110
111         /* Properly close and free all devices. */
112         for (l = dev_insts; l; l = l->next) {
113                 if (!(sdi = l->data)) {
114                         /* Log error, but continue cleaning up the rest. */
115                         sr_err("va18b: %s: sdi was NULL, continuing.",
116                                __func__);
117                         continue;
118                 }
119                 if (!(ctx = sdi->priv)) {
120                         /* Log error, but continue cleaning up the rest. */
121                         sr_err("va18b: %s: sdi->priv was NULL, continuing.",
122                                __func__);
123                         continue;
124                 }
125
126                 /* TODO. */
127
128                 sr_dev_inst_free(sdi);
129         }
130
131         g_slist_free(dev_insts);
132         dev_insts = NULL;
133
134         return SR_OK;
135 }
136
137 static const void *hw_dev_info_get(int dev_index, int dev_info_id)
138 {
139         struct sr_dev_inst *sdi;
140         struct context *ctx;
141         const void *info;
142         uint64_t tmp;
143         int tmpint;
144
145         if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
146                 sr_err("va18b: %s: sdi was NULL.", __func__);
147                 return NULL;
148         }
149
150         if (!(ctx = sdi->priv)) {
151                 sr_err("va18b: %s: sdi->priv was NULL.", __func__);
152                 return NULL;
153         }
154
155         sr_spew("va18b: %s: dev_index %d, dev_info_id %d.", __func__,
156                 dev_index, dev_info_id);
157
158         switch (dev_info_id) {
159         case SR_DI_INST:
160                 info = sdi;
161                 sr_spew("va18b: %s: Returning sdi.", __func__);
162                 break;
163         case SR_DI_NUM_PROBES:
164                 tmpint = 1;
165                 info = (int *)tmpint;
166                 sr_spew("va18b: %s: Returning number of probes: 1.", __func__);
167                 break;
168         case SR_DI_PROBE_NAMES:
169                 info = probe_names;
170                 sr_spew("va18b: %s: Returning probenames.", __func__);
171                 break;
172         case SR_DI_CUR_SAMPLERATE:
173                 /* FIXME */
174                 tmp = 1;
175                 info = (uint64_t *)&tmp;
176                 sr_spew("va18b: %s: Returning samplerate: %" PRIu64 "Hz.",
177                         __func__, tmp);
178                 break;
179         default:
180                 /* Unknown device info ID, return NULL. */
181                 sr_err("va18b: %s: Unknown device info ID: %d.",
182                        __func__, dev_info_id);
183                 info = NULL;
184                 break;
185         }
186
187         return info;
188 }
189
190 static int hw_dev_status_get(int dev_index)
191 {
192         struct sr_dev_inst *sdi;
193
194         if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
195                 sr_err("va18b: %s: sdi was NULL, device not found.", __func__);
196                 return SR_ST_NOT_FOUND;
197         }
198
199         sr_dbg("va18b: Returning status: %d.", sdi->status);
200
201         return sdi->status;
202 }
203
204 static const int *hw_hwcap_get_all(void)
205 {
206         sr_spew("va18b: Returning list of device capabilities.");
207
208         return hwcaps;
209 }
210
211 static int hw_dev_config_set(int dev_index, int hwcap, const void *value)
212 {
213         struct sr_dev_inst *sdi;
214         struct context *ctx;
215
216         if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
217                 sr_err("va18b: %s: sdi was NULL.", __func__);
218                 return SR_ERR_BUG;
219         }
220
221         if (!(ctx = sdi->priv)) {
222                 sr_err("va18b: %s: sdi->priv was NULL.", __func__);
223                 return SR_ERR_BUG;
224         }
225
226         sr_spew("va18b: %s: dev_index %d, hwcap %d.", __func__,
227                 dev_index, hwcap);
228
229         switch (hwcap) {
230         case SR_HWCAP_PROBECONFIG:
231                 /* TODO: Required? */
232                 break;
233         case SR_HWCAP_LIMIT_MSEC:
234                 if (*(const uint64_t *)value == 0) {
235                         sr_err("va18b: %s: LIMIT_MSEC can't be 0.", __func__);
236                         return SR_ERR;
237                 }
238                 ctx->limit_msec = *(const uint64_t *)value;
239                 sr_dbg("va18b: Setting LIMIT_MSEC to %" PRIu64 ".",
240                        ctx->limit_msec);
241                 break;
242         case SR_HWCAP_LIMIT_SAMPLES:
243                 if (*(const uint64_t *)value < MIN_NUM_SAMPLES) {
244                         sr_err("va18b: %s: LIMIT_SAMPLES too small.", __func__);
245                         return SR_ERR;
246                 }
247                 ctx->limit_samples = *(const uint64_t *)value;
248                 sr_dbg("va18b: Setting LIMIT_SAMPLES to %" PRIu64 ".",
249                        ctx->limit_samples);
250                 break;
251         default:
252                 /* Unknown capability, return SR_ERR. */
253                 sr_err("va18b: %s: Unknown capability: %d.", __func__, hwcap);
254                 return SR_ERR;
255                 break;
256         }
257
258         return SR_OK;
259 }
260
261 static int receive_data(int fd, int revents, void *cb_data)
262 {
263         struct sr_dev_inst *sdi;
264         struct sr_datafeed_packet packet;
265         struct sr_datafeed_analog analog;
266         struct context *ctx;
267         int num_probes;
268
269         /* Avoid compiler warnings. */
270         (void)fd;
271         (void)revents;
272
273         if (!(sdi = cb_data)) {
274                 sr_err("va18b: %s: cb_data was NULL.", __func__);
275                 return FALSE;
276         }
277
278         if (!(ctx = sdi->priv)) {
279                 sr_err("va18b: %s: sdi->priv was NULL.", __func__);
280                 return FALSE;
281         }
282
283         sr_dbg("va18b: Sending SR_DF_ANALOG packet with 1 sample.");
284         /* TODO: timestamp. */
285         num_probes = 1;
286         packet.type = SR_DF_ANALOG;
287         packet.payload = &analog;
288         analog.num_samples = 1;
289         analog.mq = SR_MQ_VOLTAGE;
290         analog.unit = SR_UNIT_VOLT;
291         /* TODO: Check alloc return value. */
292         analog.data = g_try_malloc(analog.num_samples * sizeof(float) * num_probes);
293         analog.data[0] = rand() % 42; /* Transmit dummy data for now. */
294         sr_session_send(ctx->session_dev_id, &packet);
295
296         ctx->num_samples++;
297
298         /* Support for SR_HWCAP_LIMIT_SAMPLES. */
299         if (ctx->limit_samples > 0 && ctx->num_samples > ctx->limit_samples) {
300                 hw_dev_acquisition_stop(0 /* FIXME? */, cb_data);
301                 return FALSE;
302         }
303
304         return TRUE;
305 }
306
307 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
308 {
309         struct sr_datafeed_packet packet;
310         struct sr_datafeed_header header;
311         struct sr_datafeed_meta_analog meta;
312         struct sr_dev_inst *sdi;
313         struct context *ctx;
314
315         if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
316                 sr_err("va18b: %s: sdi was NULL.", __func__);
317                 return SR_ERR_BUG;
318         }
319
320         if (!(ctx = sdi->priv)) {
321                 sr_err("va18b: %s: sdi->priv was NULL.", __func__);
322                 return SR_ERR_BUG;
323         }
324
325         sr_dbg("va18b: Starting acquisition.");
326
327         ctx->session_dev_id = cb_data;
328
329         /* Send header packet to the session bus. */
330         sr_dbg("va18b: Sending SR_DF_HEADER.");
331         packet.type = SR_DF_HEADER;
332         packet.payload = (uint8_t *)&header;
333         header.feed_version = 1;
334         gettimeofday(&header.starttime, NULL);
335         sr_session_send(ctx->session_dev_id, &packet);
336
337         /* Send metadata about the SR_DF_ANALOG packets to come. */
338         sr_dbg("va18b: Sending SR_DF_META_ANALOG.");
339         packet.type = SR_DF_META_ANALOG;
340         packet.payload = &meta;
341         meta.num_probes = 1;
342         sr_session_send(ctx->session_dev_id, &packet);
343
344         /* Hook up a dummy handler to receive data from the device. */
345         sr_source_add(-1, G_IO_IN, 0, receive_data, sdi);
346
347         return SR_OK;
348 }
349
350 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
351 {
352         struct sr_datafeed_packet packet;
353
354         /* Avoid compiler warnings. */
355         (void)dev_index;
356
357         sr_dbg("va18b: Stopping acquisition.");
358
359         /* Send end packet to the session bus. */
360         sr_dbg("va18b: Sending SR_DF_END.");
361         packet.type = SR_DF_END;
362         sr_session_send(cb_data, &packet);
363
364         return SR_OK;
365 }
366
367 SR_PRIV struct sr_dev_driver mastech_va18b_driver_info = {
368         .name = "mastech-va18b",
369         .longname = "Mastech VA18B",
370         .api_version = 1,
371         .init = hw_init,
372         .cleanup = hw_cleanup,
373         .dev_open = hw_dev_open,
374         .dev_close = hw_dev_close,
375         .dev_info_get = hw_dev_info_get,
376         .dev_status_get = hw_dev_status_get,
377         .hwcap_get_all = hw_hwcap_get_all,
378         .dev_config_set = hw_dev_config_set,
379         .dev_acquisition_start = hw_dev_acquisition_start,
380         .dev_acquisition_stop = hw_dev_acquisition_stop,
381 };