]> sigrok.org Git - libsigrok.git/blob - hardware/serial-dmm/api.c
serial-dmm: Add MASTECH MAS345 support.
[libsigrok.git] / hardware / serial-dmm / api.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
6  * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
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 3 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, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <glib.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <errno.h>
28 #include "libsigrok.h"
29 #include "libsigrok-internal.h"
30 #include "protocol.h"
31
32 static const int hwopts[] = {
33         SR_HWOPT_CONN,
34         SR_HWOPT_SERIALCOMM,
35         0,
36 };
37
38 static const int hwcaps[] = {
39         SR_HWCAP_MULTIMETER,
40         SR_HWCAP_LIMIT_SAMPLES,
41         SR_HWCAP_CONTINUOUS,
42         0,
43 };
44
45 static const char *probe_names[] = {
46         "Probe",
47         NULL,
48 };
49
50 SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info;
51 SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info;
52 SR_PRIV struct sr_dev_driver metex_me31_driver_info;
53 SR_PRIV struct sr_dev_driver peaktech_3410_driver_info;
54 SR_PRIV struct sr_dev_driver mastech_mas345_driver_info;
55
56 static struct sr_dev_driver *di_dt4000zc = &digitek_dt4000zc_driver_info;
57 static struct sr_dev_driver *di_tp4000zc = &tekpower_tp4000zc_driver_info;
58 static struct sr_dev_driver *di_me31 = &metex_me31_driver_info;
59 static struct sr_dev_driver *di_3410 = &peaktech_3410_driver_info;
60 static struct sr_dev_driver *di_mas345 = &mastech_mas345_driver_info;
61
62 /* After hw_init() this will point to a device-specific entry (see above). */
63 static struct sr_dev_driver *di = NULL;
64
65 SR_PRIV struct dmm_info dmms[] = {
66         {
67                 "Digitek", "DT4000ZC", "2400/8n1", 2400,
68                 FS9721_PACKET_SIZE, NULL,
69                 sr_fs9721_packet_valid, sr_fs9721_parse,
70                 dmm_details_dt4000zc,
71         },
72         {
73                 "TekPower", "TP4000ZC", "2400/8n1", 2400,
74                 FS9721_PACKET_SIZE, NULL,
75                 sr_fs9721_packet_valid, sr_fs9721_parse,
76                 dmm_details_tp4000zc,
77         },
78         {
79                 "Metex", "ME-31", "600/7n2/rts=0/dtr=1", 600,
80                 METEX14_PACKET_SIZE, sr_metex14_packet_request,
81                 sr_metex14_packet_valid, sr_metex14_parse,
82                 NULL,
83         },
84         {
85                 "Peaktech", "3410", "600/7n2/rts=0/dtr=1", 600,
86                 METEX14_PACKET_SIZE, sr_metex14_packet_request,
87                 sr_metex14_packet_valid, sr_metex14_parse,
88                 NULL,
89         },
90         {
91                 "MASTECH", "MAS345", "600/7n2/rts=0/dtr=1", 600,
92                 METEX14_PACKET_SIZE, sr_metex14_packet_request,
93                 sr_metex14_packet_valid, sr_metex14_parse,
94                 NULL,
95         },
96 };
97
98 /* Properly close and free all devices. */
99 static int clear_instances(void)
100 {
101         struct sr_dev_inst *sdi;
102         struct drv_context *drvc;
103         struct dev_context *devc;
104         GSList *l;
105
106         if (!(drvc = di->priv))
107                 return SR_OK;
108
109         drvc = di->priv;
110         for (l = drvc->instances; l; l = l->next) {
111                 if (!(sdi = l->data))
112                         continue;
113                 if (!(devc = sdi->priv))
114                         continue;
115                 sr_serial_dev_inst_free(devc->serial);
116                 sr_dev_inst_free(sdi);
117         }
118         g_slist_free(drvc->instances);
119         drvc->instances = NULL;
120
121         return SR_OK;
122 }
123
124 static int hw_init(int dmm)
125 {
126         struct drv_context *drvc;
127
128         if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
129                 sr_err("Driver context malloc failed.");
130                 return SR_ERR_MALLOC;
131         }
132
133         if (dmm == DIGITEK_DT4000ZC)
134                 di = di_dt4000zc;
135         if (dmm == TEKPOWER_TP4000ZC)
136                 di = di_tp4000zc;
137         if (dmm == METEX_ME31)
138                 di = di_me31;
139         if (dmm == PEAKTECH_3410)
140                 di = di_3410;
141         if (dmm == MASTECH_MAS345)
142                 di = di_mas345;
143         sr_dbg("Selected '%s' subdriver.", di->name);
144
145         di->priv = drvc;
146
147         return SR_OK;
148 }
149
150 static int hw_init_digitek_dt4000zc(void)
151 {
152         return hw_init(DIGITEK_DT4000ZC);
153 }
154
155 static int hw_init_tekpower_tp4000zc(void)
156 {
157         return hw_init(TEKPOWER_TP4000ZC);
158 }
159
160 static int hw_init_metex_me31(void)
161 {
162         return hw_init(METEX_ME31);
163 }
164
165 static int hw_init_peaktech_3410(void)
166 {
167         return hw_init(PEAKTECH_3410);
168 }
169
170 static int hw_init_mastech_mas345(void)
171 {
172         return hw_init(MASTECH_MAS345);
173 }
174
175 static GSList *scan(const char *conn, const char *serialcomm, int dmm)
176 {
177         struct sr_dev_inst *sdi;
178         struct drv_context *drvc;
179         struct dev_context *devc;
180         struct sr_probe *probe;
181         struct sr_serial_dev_inst *serial;
182         GSList *devices;
183         int dropped, ret;
184         size_t len;
185         uint8_t buf[128];
186
187         if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
188                 return NULL;
189
190         if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
191                 return NULL;
192
193         sr_info("Probing port %s.", conn);
194
195         drvc = di->priv;
196         devices = NULL;
197         serial_flush(serial);
198
199         /*
200          * There's no way to get an ID from the multimeter. It just sends data
201          * periodically, so the best we can do is check if the packets match
202          * the expected format.
203          */
204
205         /* Let's get a bit of data and see if we can find a packet. */
206         len = sizeof(buf);
207
208         /* Request a packet if the DMM requires this. */
209         if (dmms[dmm].packet_request) {
210                 if ((ret = dmms[dmm].packet_request(serial)) < 0) {
211                         sr_err("Failed to request packet: %d.", ret);
212                         return FALSE;
213                 }
214         }
215
216         ret = serial_stream_detect(serial, buf, &len, dmms[dmm].packet_size,
217                                    dmms[dmm].packet_valid, 1000,
218                                    dmms[dmm].baudrate);
219         if (ret != SR_OK)
220                 goto scan_cleanup;
221
222         /*
223          * If we dropped more than two packets worth of data, something is
224          * wrong. We shouldn't quit however, since the dropped bytes might be
225          * just zeroes at the beginning of the stream. Those can occur as a
226          * combination of the nonstandard cable that ships with this device and
227          * the serial port or USB to serial adapter.
228          */
229         dropped = len - dmms[dmm].packet_size;
230         if (dropped > 2 * dmms[dmm].packet_size)
231                 sr_warn("Had to drop too much data.");
232
233         sr_info("Found device on port %s.", conn);
234
235         if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, dmms[dmm].vendor,
236                                     dmms[dmm].device, "")))
237                 goto scan_cleanup;
238
239         if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
240                 sr_err("Device context malloc failed.");
241                 goto scan_cleanup;
242         }
243
244         devc->serial = serial;
245
246         sdi->priv = devc;
247         sdi->driver = di;
248         if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1")))
249                 goto scan_cleanup;
250         sdi->probes = g_slist_append(sdi->probes, probe);
251         drvc->instances = g_slist_append(drvc->instances, sdi);
252         devices = g_slist_append(devices, sdi);
253
254 scan_cleanup:
255         serial_close(serial);
256
257         return devices;
258 }
259
260 static GSList *hw_scan(GSList *options)
261 {
262         struct sr_hwopt *opt;
263         GSList *l, *devices;
264         const char *conn, *serialcomm;
265         int dmm;
266
267         conn = serialcomm = NULL;
268         for (l = options; l; l = l->next) {
269                 opt = l->data;
270                 switch (opt->hwopt) {
271                 case SR_HWOPT_CONN:
272                         conn = opt->value;
273                         break;
274                 case SR_HWOPT_SERIALCOMM:
275                         serialcomm = opt->value;
276                         break;
277                 }
278         }
279         if (!conn)
280                 return NULL;
281
282         if (!strcmp(di->name, "digitek-dt4000zc"))
283                 dmm = 0;
284         if (!strcmp(di->name, "tekpower-tp4000zc"))
285                 dmm = 1;
286         if (!strcmp(di->name, "metex-me31"))
287                 dmm = 2;
288         if (!strcmp(di->name, "peaktech-3410"))
289                 dmm = 3;
290         if (!strcmp(di->name, "mastech-mas345"))
291                 dmm = 4;
292
293         if (serialcomm) {
294                 /* Use the provided comm specs. */
295                 devices = scan(conn, serialcomm, dmm);
296         } else {
297                 /* Try the default. */
298                 devices = scan(conn, dmms[dmm].conn, dmm);
299         }
300
301         return devices;
302 }
303
304 static GSList *hw_dev_list(void)
305 {
306         struct drv_context *drvc;
307
308         drvc = di->priv;
309
310         return drvc->instances;
311 }
312
313 static int hw_dev_open(struct sr_dev_inst *sdi)
314 {
315         struct dev_context *devc;
316
317         if (!(devc = sdi->priv)) {
318                 sr_err("sdi->priv was NULL.");
319                 return SR_ERR_BUG;
320         }
321
322         if (serial_open(devc->serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
323                 return SR_ERR;
324
325         sdi->status = SR_ST_ACTIVE;
326
327         return SR_OK;
328 }
329
330 static int hw_dev_close(struct sr_dev_inst *sdi)
331 {
332         struct dev_context *devc;
333
334         if (!(devc = sdi->priv)) {
335                 sr_err("sdi->priv was NULL.");
336                 return SR_ERR_BUG;
337         }
338
339         if (devc->serial && devc->serial->fd != -1) {
340                 serial_close(devc->serial);
341                 sdi->status = SR_ST_INACTIVE;
342         }
343
344         return SR_OK;
345 }
346
347 static int hw_cleanup(void)
348 {
349         clear_instances();
350
351         return SR_OK;
352 }
353
354 static int hw_info_get(int info_id, const void **data,
355                        const struct sr_dev_inst *sdi)
356 {
357         (void)sdi;
358
359         switch (info_id) {
360         case SR_DI_HWOPTS:
361                 *data = hwopts;
362                 break;
363         case SR_DI_HWCAPS:
364                 *data = hwcaps;
365                 break;
366         case SR_DI_NUM_PROBES:
367                 *data = GINT_TO_POINTER(1);
368                 break;
369         case SR_DI_PROBE_NAMES:
370                 *data = probe_names;
371                 break;
372         default:
373                 return SR_ERR_ARG;
374         }
375
376         return SR_OK;
377 }
378
379 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
380                              const void *value)
381 {
382         struct dev_context *devc;
383
384         if (sdi->status != SR_ST_ACTIVE)
385                 return SR_ERR;
386
387         if (!(devc = sdi->priv)) {
388                 sr_err("sdi->priv was NULL.");
389                 return SR_ERR_BUG;
390         }
391
392         switch (hwcap) {
393         case SR_HWCAP_LIMIT_SAMPLES:
394                 devc->limit_samples = *(const uint64_t *)value;
395                 sr_dbg("Setting sample limit to %" PRIu64 ".",
396                        devc->limit_samples);
397                 break;
398         default:
399                 sr_err("Unknown capability: %d.", hwcap);
400                 return SR_ERR;
401                 break;
402         }
403
404         return SR_OK;
405 }
406
407 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
408                                     void *cb_data)
409 {
410         struct sr_datafeed_packet packet;
411         struct sr_datafeed_header header;
412         struct sr_datafeed_meta_analog meta;
413         struct dev_context *devc;
414         int (*receive_data)(int, int, void *) = NULL;
415
416         if (!(devc = sdi->priv)) {
417                 sr_err("sdi->priv was NULL.");
418                 return SR_ERR_BUG;
419         }
420
421         sr_dbg("Starting acquisition.");
422
423         devc->cb_data = cb_data;
424
425         /*
426          * Reset the number of samples to take. If we've already collected our
427          * quota, but we start a new session, and don't reset this, we'll just
428          * quit without acquiring any new samples.
429          */
430         devc->num_samples = 0;
431
432         /* Send header packet to the session bus. */
433         sr_dbg("Sending SR_DF_HEADER.");
434         packet.type = SR_DF_HEADER;
435         packet.payload = (uint8_t *)&header;
436         header.feed_version = 1;
437         gettimeofday(&header.starttime, NULL);
438         sr_session_send(devc->cb_data, &packet);
439
440         /* Send metadata about the SR_DF_ANALOG packets to come. */
441         sr_dbg("Sending SR_DF_META_ANALOG.");
442         packet.type = SR_DF_META_ANALOG;
443         packet.payload = &meta;
444         meta.num_probes = 1;
445         sr_session_send(devc->cb_data, &packet);
446
447         if (!strcmp(di->name, "digitek-dt4000zc"))
448                 receive_data = digitek_dt4000zc_receive_data;
449         if (!strcmp(di->name, "tekpower-tp4000zc"))
450                 receive_data = tekpower_tp4000zc_receive_data;
451         if (!strcmp(di->name, "metex-me31"))
452                 receive_data = metex_me31_receive_data;
453         if (!strcmp(di->name, "peaktech-3410"))
454                 receive_data = peaktech_3410_receive_data;
455         if (!strcmp(di->name, "mastech-mas345"))
456                 receive_data = mastech_mas345_receive_data;
457
458         /* Poll every 50ms, or whenever some data comes in. */
459         sr_source_add(devc->serial->fd, G_IO_IN, 50,
460                       receive_data, (void *)sdi);
461
462         return SR_OK;
463 }
464
465 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
466 {
467         struct sr_datafeed_packet packet;
468         struct dev_context *devc;
469
470         if (sdi->status != SR_ST_ACTIVE)
471                 return SR_ERR;
472
473         if (!(devc = sdi->priv)) {
474                 sr_err("sdi->priv was NULL.");
475                 return SR_ERR_BUG;
476         }
477
478         sr_dbg("Stopping acquisition.");
479
480         sr_source_remove(devc->serial->fd);
481         hw_dev_close((struct sr_dev_inst *)sdi);
482
483         /* Send end packet to the session bus. */
484         sr_dbg("Sending SR_DF_END.");
485         packet.type = SR_DF_END;
486         sr_session_send(cb_data, &packet);
487
488         return SR_OK;
489 }
490
491 SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info = {
492         .name = "digitek-dt4000zc",
493         .longname = "Digitek DT4000ZC",
494         .api_version = 1,
495         .init = hw_init_digitek_dt4000zc,
496         .cleanup = hw_cleanup,
497         .scan = hw_scan,
498         .dev_list = hw_dev_list,
499         .dev_clear = clear_instances,
500         .dev_open = hw_dev_open,
501         .dev_close = hw_dev_close,
502         .info_get = hw_info_get,
503         .dev_config_set = hw_dev_config_set,
504         .dev_acquisition_start = hw_dev_acquisition_start,
505         .dev_acquisition_stop = hw_dev_acquisition_stop,
506         .priv = NULL,
507 };
508
509 SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info = {
510         .name = "tekpower-tp4000zc",
511         .longname = "TekPower TP4000ZC",
512         .api_version = 1,
513         .init = hw_init_tekpower_tp4000zc,
514         .cleanup = hw_cleanup,
515         .scan = hw_scan,
516         .dev_list = hw_dev_list,
517         .dev_clear = clear_instances,
518         .dev_open = hw_dev_open,
519         .dev_close = hw_dev_close,
520         .info_get = hw_info_get,
521         .dev_config_set = hw_dev_config_set,
522         .dev_acquisition_start = hw_dev_acquisition_start,
523         .dev_acquisition_stop = hw_dev_acquisition_stop,
524         .priv = NULL,
525 };
526
527 SR_PRIV struct sr_dev_driver metex_me31_driver_info = {
528         .name = "metex-me31",
529         .longname = "Metex ME-31",
530         .api_version = 1,
531         .init = hw_init_metex_me31,
532         .cleanup = hw_cleanup,
533         .scan = hw_scan,
534         .dev_list = hw_dev_list,
535         .dev_clear = clear_instances,
536         .dev_open = hw_dev_open,
537         .dev_close = hw_dev_close,
538         .info_get = hw_info_get,
539         .dev_config_set = hw_dev_config_set,
540         .dev_acquisition_start = hw_dev_acquisition_start,
541         .dev_acquisition_stop = hw_dev_acquisition_stop,
542         .priv = NULL,
543 };
544
545 SR_PRIV struct sr_dev_driver peaktech_3410_driver_info = {
546         .name = "peaktech-3410",
547         .longname = "PeakTech 3410",
548         .api_version = 1,
549         .init = hw_init_peaktech_3410,
550         .cleanup = hw_cleanup,
551         .scan = hw_scan,
552         .dev_list = hw_dev_list,
553         .dev_clear = clear_instances,
554         .dev_open = hw_dev_open,
555         .dev_close = hw_dev_close,
556         .info_get = hw_info_get,
557         .dev_config_set = hw_dev_config_set,
558         .dev_acquisition_start = hw_dev_acquisition_start,
559         .dev_acquisition_stop = hw_dev_acquisition_stop,
560         .priv = NULL,
561 };
562
563 SR_PRIV struct sr_dev_driver mastech_mas345_driver_info = {
564         .name = "mastech-mas345",
565         .longname = "MASTECH MAS345",
566         .api_version = 1,
567         .init = hw_init_mastech_mas345,
568         .cleanup = hw_cleanup,
569         .scan = hw_scan,
570         .dev_list = hw_dev_list,
571         .dev_clear = clear_instances,
572         .dev_open = hw_dev_open,
573         .dev_close = hw_dev_close,
574         .info_get = hw_info_get,
575         .dev_config_set = hw_dev_config_set,
576         .dev_acquisition_start = hw_dev_acquisition_start,
577         .dev_acquisition_stop = hw_dev_acquisition_stop,
578         .priv = NULL,
579 };