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