]> sigrok.org Git - libsigrok.git/blob - hardware/tondaj-sl-814/api.c
GPL headers: Use correct project name.
[libsigrok.git] / hardware / tondaj-sl-814 / api.c
1 /*
2  * This file is part of the libsigrok 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 <fcntl.h>
22 #include <glib.h>
23 #include "libsigrok.h"
24 #include "libsigrok-internal.h"
25 #include "protocol.h"
26
27 #define SERIALCOMM "9600/8e1"
28
29 static const int32_t hwopts[] = {
30         SR_CONF_CONN,
31         SR_CONF_SERIALCOMM,
32 };
33
34 static const int32_t hwcaps[] = {
35         SR_CONF_SOUNDLEVELMETER,
36         SR_CONF_LIMIT_SAMPLES,
37         SR_CONF_CONTINUOUS,
38 };
39
40 SR_PRIV struct sr_dev_driver tondaj_sl_814_driver_info;
41 static struct sr_dev_driver *di = &tondaj_sl_814_driver_info;
42
43 /* Properly close and free all devices. */
44 static int clear_instances(void)
45 {
46         struct sr_dev_inst *sdi;
47         struct drv_context *drvc;
48         struct dev_context *devc;
49         GSList *l;
50
51         if (!(drvc = di->priv))
52                 return SR_OK;
53
54         for (l = drvc->instances; l; l = l->next) {
55                 if (!(sdi = l->data))
56                         continue;
57                 if (!(devc = sdi->priv))
58                         continue;
59                 sr_serial_dev_inst_free(devc->serial);
60                 sr_dev_inst_free(sdi);
61         }
62
63         g_slist_free(drvc->instances);
64         drvc->instances = NULL;
65
66         return SR_OK;
67 }
68
69 static int hw_init(struct sr_context *sr_ctx)
70 {
71         return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
72 }
73
74 static GSList *hw_scan(GSList *options)
75 {
76         struct drv_context *drvc;
77         struct dev_context *devc;
78         struct sr_dev_inst *sdi;
79         struct sr_config *src;
80         struct sr_probe *probe;
81         GSList *devices, *l;
82         const char *conn, *serialcomm;
83
84         drvc = di->priv;
85         drvc->instances = NULL;
86
87         devices = NULL;
88
89         conn = serialcomm = NULL;
90         for (l = options; l; l = l->next) {
91                 if (!(src = l->data)) {
92                         sr_err("Invalid option data, skipping.");
93                         continue;
94                 }
95                 switch (src->key) {
96                 case SR_CONF_CONN:
97                         conn = g_variant_get_string(src->data, NULL);
98                         break;
99                 case SR_CONF_SERIALCOMM:
100                         serialcomm  = g_variant_get_string(src->data, NULL);
101                         break;
102                 default:
103                         sr_err("Unknown option %d, skipping.", src->key);
104                         break;
105                 }
106         }
107         if (!conn)
108                 return NULL;
109         if (!serialcomm)
110                 serialcomm = SERIALCOMM;
111
112         if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Tondaj",
113                                     "SL-814", NULL))) {
114                 sr_err("Failed to create device instance.");
115                 return NULL;
116         }
117
118         if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
119                 sr_err("Device context malloc failed.");
120                 return NULL;
121         }
122
123         if (!(devc->serial = sr_serial_dev_inst_new(conn, serialcomm)))
124                 return NULL;
125
126         if (serial_open(devc->serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
127                 return NULL;
128
129         sdi->priv = devc;
130         sdi->driver = di;
131         probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1");
132         if (!probe) {
133                 sr_err("Failed to create probe.");
134                 return NULL;
135         }
136         sdi->probes = g_slist_append(sdi->probes, probe);
137         drvc->instances = g_slist_append(drvc->instances, sdi);
138         devices = g_slist_append(devices, sdi);
139
140         return devices;
141 }
142
143 static GSList *hw_dev_list(void)
144 {
145         return ((struct drv_context *)(di->priv))->instances;
146 }
147
148 static int hw_dev_open(struct sr_dev_inst *sdi)
149 {
150         struct dev_context *devc;
151
152         devc = sdi->priv;
153
154         if (serial_open(devc->serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
155                 return SR_ERR;
156
157         sdi->status = SR_ST_ACTIVE;
158
159         return SR_OK;
160 }
161
162 static int hw_dev_close(struct sr_dev_inst *sdi)
163 {
164         struct dev_context *devc;
165
166         devc = sdi->priv;
167
168         if (devc->serial && devc->serial->fd != -1) {
169                 serial_close(devc->serial);
170                 sdi->status = SR_ST_INACTIVE;
171         }
172
173         return SR_OK;
174 }
175
176 static int hw_cleanup(void)
177 {
178         clear_instances();
179
180         return SR_OK;
181 }
182
183 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
184 {
185         struct dev_context *devc;
186
187         if (sdi->status != SR_ST_ACTIVE) {
188                 sr_err("Device inactive, can't set config options.");
189                 return SR_ERR;
190         }
191
192         devc = sdi->priv;
193
194         switch (id) {
195         case SR_CONF_LIMIT_SAMPLES:
196                 devc->limit_samples = g_variant_get_uint64(data);
197                 sr_dbg("Setting sample limit to %" PRIu64 ".",
198                        devc->limit_samples);
199                 break;
200         default:
201                 return SR_ERR_NA;
202         }
203
204         return SR_OK;
205 }
206
207 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
208 {
209
210         (void)sdi;
211
212         switch (key) {
213         case SR_CONF_SCAN_OPTIONS:
214                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
215                                 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
216                 break;
217         case SR_CONF_DEVICE_OPTIONS:
218                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
219                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
220                 break;
221         default:
222                 return SR_ERR_NA;
223         }
224
225         return SR_OK;
226 }
227
228 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
229                                     void *cb_data)
230 {
231         struct dev_context *devc;
232
233         devc = sdi->priv;
234         devc->cb_data = cb_data;
235
236         /* Send header packet to the session bus. */
237         std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
238
239         /* Poll every 500ms, or whenever some data comes in. */
240         sr_source_add(devc->serial->fd, G_IO_IN, 500,
241                       tondaj_sl_814_receive_data, (void *)sdi);
242
243         return SR_OK;
244 }
245
246 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
247 {
248         return std_hw_dev_acquisition_stop_serial(sdi, cb_data, hw_dev_close,
249                ((struct dev_context *)(sdi->priv))->serial, DRIVER_LOG_DOMAIN);
250 }
251
252 SR_PRIV struct sr_dev_driver tondaj_sl_814_driver_info = {
253         .name = "tondaj-sl-814",
254         .longname = "Tondaj SL-814",
255         .api_version = 1,
256         .init = hw_init,
257         .cleanup = hw_cleanup,
258         .scan = hw_scan,
259         .dev_list = hw_dev_list,
260         .dev_clear = clear_instances,
261         .config_get = NULL,
262         .config_set = config_set,
263         .config_list = config_list,
264         .dev_open = hw_dev_open,
265         .dev_close = hw_dev_close,
266         .dev_acquisition_start = hw_dev_acquisition_start,
267         .dev_acquisition_stop = hw_dev_acquisition_stop,
268         .priv = NULL,
269 };