]> sigrok.org Git - libsigrok.git/blob - src/std.c
Don't set _POSIX_C_SOURCE for VXI/RPC related files.
[libsigrok.git] / src / std.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 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 /** @file
22   * Standard API helper functions.
23   * @internal
24   */
25
26 #include <glib.h>
27 #include <libsigrok/libsigrok.h>
28 #include "libsigrok-internal.h"
29 #include "scpi.h"
30
31 #define LOG_PREFIX "std"
32
33 /**
34  * Standard sr_driver_init() API helper.
35  *
36  * This function can be used to simplify most driver's init() API callback.
37  *
38  * It creates a new 'struct drv_context' (drvc), assigns sr_ctx to it, and
39  * then 'drvc' is assigned to the 'struct sr_dev_driver' (di) that is passed.
40  *
41  * @param sr_ctx The libsigrok context to assign.
42  * @param di The driver instance to use.
43  * @param[in] prefix A driver-specific prefix string used for log messages.
44  *
45  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
46  */
47 SR_PRIV int std_init(struct sr_context *sr_ctx, struct sr_dev_driver *di,
48                      const char *prefix)
49 {
50         struct drv_context *drvc;
51
52         if (!di) {
53                 sr_err("%s: Invalid driver, cannot initialize.", prefix);
54                 return SR_ERR_ARG;
55         }
56
57         drvc = g_malloc0(sizeof(struct drv_context));
58         drvc->sr_ctx = sr_ctx;
59         drvc->instances = NULL;
60         di->context = drvc;
61
62         return SR_OK;
63 }
64
65 /**
66  * Standard API helper for sending an SR_DF_HEADER packet.
67  *
68  * This function can be used to simplify most driver's
69  * dev_acquisition_start() API callback.
70  *
71  * @param sdi The device instance to use.
72  * @param prefix A driver-specific prefix string used for log messages.
73  *               Must not be NULL. An empty string is allowed.
74  *
75  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
76  *         SR_ERR upon other errors.
77  */
78 SR_PRIV int std_session_send_df_header(const struct sr_dev_inst *sdi,
79                                        const char *prefix)
80 {
81         int ret;
82         struct sr_datafeed_packet packet;
83         struct sr_datafeed_header header;
84
85         if (!prefix) {
86                 sr_err("Invalid prefix.");
87                 return SR_ERR_ARG;
88         }
89
90         sr_dbg("%s: Starting acquisition.", prefix);
91
92         /* Send header packet to the session bus. */
93         sr_dbg("%s: Sending SR_DF_HEADER packet.", prefix);
94         packet.type = SR_DF_HEADER;
95         packet.payload = (uint8_t *)&header;
96         header.feed_version = 1;
97         gettimeofday(&header.starttime, NULL);
98
99         if ((ret = sr_session_send(sdi, &packet)) < 0) {
100                 sr_err("%s: Failed to send header packet: %d.", prefix, ret);
101                 return ret;
102         }
103
104         return SR_OK;
105 }
106
107 #ifdef HAVE_LIBSERIALPORT
108
109 /**
110  * Standard serial driver dev_open() helper.
111  *
112  * This function can be used to implement the dev_open() driver API
113  * callback in drivers that use a serial port. The port is opened
114  * with the SERIAL_RDWR flag.
115  *
116  * If the open succeeded, the status field of the given sdi is set
117  * to SR_ST_ACTIVE.
118  *
119  * @retval SR_OK Success.
120  * @retval SR_ERR Serial port open failed.
121  */
122 SR_PRIV int std_serial_dev_open(struct sr_dev_inst *sdi)
123 {
124         struct sr_serial_dev_inst *serial;
125
126         serial = sdi->conn;
127         if (serial_open(serial, SERIAL_RDWR) != SR_OK)
128                 return SR_ERR;
129
130         sdi->status = SR_ST_ACTIVE;
131
132         return SR_OK;
133 }
134
135 /**
136  * Standard serial driver dev_close() helper.
137  *
138  * This function can be used to implement the dev_close() driver API
139  * callback in drivers that use a serial port.
140  *
141  * After closing the port, the status field of the given sdi is set
142  * to SR_ST_INACTIVE.
143  *
144  * @retval SR_OK Success.
145  */
146 SR_PRIV int std_serial_dev_close(struct sr_dev_inst *sdi)
147 {
148         struct sr_serial_dev_inst *serial;
149
150         serial = sdi->conn;
151         if (serial && sdi->status == SR_ST_ACTIVE) {
152                 serial_close(serial);
153                 sdi->status = SR_ST_INACTIVE;
154         }
155
156         return SR_OK;
157 }
158
159 /**
160  * Standard sr_session_stop() API helper.
161  *
162  * This function can be used to simplify most (serial port based) driver's
163  * dev_acquisition_stop() API callback.
164  *
165  * @param sdi The device instance for which acquisition should stop.
166  *            Must not be NULL.
167  * @param cb_data Opaque 'cb_data' pointer. Must not be NULL.
168  * @param dev_close_fn Function pointer to the driver's dev_close().
169  *                        Must not be NULL.
170  * @param serial The serial device instance (struct serial_dev_inst *).
171  *               Must not be NULL.
172  * @param[in] prefix A driver-specific prefix string used for log messages.
173  *               Must not be NULL. An empty string is allowed.
174  *
175  * @retval SR_OK Success.
176  * @retval SR_ERR_ARG Invalid arguments.
177  * @retval SR_ERR_DEV_CLOSED Device is closed.
178  * @retval SR_ERR Other errors.
179  */
180 SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi,
181                         void *cb_data, dev_close_callback dev_close_fn,
182                         struct sr_serial_dev_inst *serial, const char *prefix)
183 {
184         int ret;
185         struct sr_datafeed_packet packet;
186
187         if (!prefix) {
188                 sr_err("Invalid prefix.");
189                 return SR_ERR_ARG;
190         }
191
192         if (sdi->status != SR_ST_ACTIVE) {
193                 sr_err("%s: Device inactive, can't stop acquisition.", prefix);
194                 return SR_ERR_DEV_CLOSED;
195         }
196
197         sr_dbg("%s: Stopping acquisition.", prefix);
198
199         if ((ret = serial_source_remove(sdi->session, serial)) < 0) {
200                 sr_err("%s: Failed to remove source: %d.", prefix, ret);
201                 return ret;
202         }
203
204         if ((ret = dev_close_fn(sdi)) < 0) {
205                 sr_err("%s: Failed to close device: %d.", prefix, ret);
206                 return ret;
207         }
208
209         /* Send SR_DF_END packet to the session bus. */
210         sr_dbg("%s: Sending SR_DF_END packet.", prefix);
211         packet.type = SR_DF_END;
212         packet.payload = NULL;
213         if ((ret = sr_session_send(cb_data, &packet)) < 0) {
214                 sr_err("%s: Failed to send SR_DF_END packet: %d.", prefix, ret);
215                 return ret;
216         }
217
218         return SR_OK;
219 }
220
221 #endif
222
223 /**
224  * Standard driver dev_clear() helper.
225  *
226  * Clear driver, this means, close all instances.
227  *
228  * This function can be used to implement the dev_clear() driver API
229  * callback. dev_close() is called before every sr_dev_inst is cleared.
230  *
231  * The only limitation is driver-specific device contexts (sdi->priv).
232  * These are freed, but any dynamic allocation within structs stored
233  * there cannot be freed.
234  *
235  * @param driver The driver which will have its instances released.
236  * @param clear_private If not NULL, this points to a function called
237  * with sdi->priv as argument. The function can then clear any device
238  * instance-specific resources kept there. It must also clear the struct
239  * pointed to by sdi->priv.
240  *
241  * @return SR_OK on success.
242  */
243 SR_PRIV int std_dev_clear(const struct sr_dev_driver *driver,
244                 std_dev_clear_callback clear_private)
245 {
246         struct drv_context *drvc;
247         struct sr_dev_inst *sdi;
248         GSList *l;
249         int ret;
250
251         if (!(drvc = driver->context))
252                 /* Driver was never initialized, nothing to do. */
253                 return SR_OK;
254
255         ret = SR_OK;
256         for (l = drvc->instances; l; l = l->next) {
257                 if (!(sdi = l->data)) {
258                         ret = SR_ERR_BUG;
259                         continue;
260                 }
261                 if (driver->dev_close)
262                         driver->dev_close(sdi);
263
264                 if (sdi->conn) {
265 #ifdef HAVE_LIBSERIALPORT
266                         if (sdi->inst_type == SR_INST_SERIAL)
267                                 sr_serial_dev_inst_free(sdi->conn);
268 #endif
269 #ifdef HAVE_LIBUSB_1_0
270                         if (sdi->inst_type == SR_INST_USB)
271                                 sr_usb_dev_inst_free(sdi->conn);
272 #endif
273                         if (sdi->inst_type == SR_INST_SCPI)
274                                 sr_scpi_free(sdi->conn);
275                         if (sdi->inst_type == SR_INST_MODBUS)
276                                 sr_modbus_free(sdi->conn);
277                 }
278                 if (clear_private)
279                         /* The helper function is responsible for freeing
280                          * its own sdi->priv! */
281                         clear_private(sdi->priv);
282                 else
283                         g_free(sdi->priv);
284
285                 sr_dev_inst_free(sdi);
286         }
287
288         g_slist_free(drvc->instances);
289         drvc->instances = NULL;
290
291         return ret;
292 }