]> sigrok.org Git - libsigrok.git/blob - hardware/cem-dt-885x/api.c
68e2f023ddfe3872f2a38b231df29731cabd6940
[libsigrok.git] / hardware / cem-dt-885x / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "protocol.h"
21
22 #define SERIALCOMM "9600/8n1"
23 /* 23ms is the longest interval between tokens. */
24 #define MAX_SCAN_TIME 25 * 1000
25
26 static const int32_t hwopts[] = {
27         SR_CONF_CONN,
28 };
29
30 static const int32_t hwcaps[] = {
31         SR_CONF_SOUNDLEVELMETER,
32         SR_CONF_LIMIT_SAMPLES,
33         SR_CONF_CONTINUOUS,
34 };
35
36
37 SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info;
38 static struct sr_dev_driver *di = &cem_dt_885x_driver_info;
39
40
41 static int init(struct sr_context *sr_ctx)
42 {
43         return std_init(sr_ctx, di, LOG_PREFIX);
44 }
45
46 static GSList *scan(GSList *options)
47 {
48         struct drv_context *drvc;
49         struct dev_context *devc;
50         struct sr_config *src;
51         struct sr_serial_dev_inst *serial;
52         struct sr_dev_inst *sdi;
53         struct sr_probe *probe;
54         GSList *l, *devices;
55         gint64 start;
56         const char *conn;
57         unsigned char c;
58
59         conn = NULL;
60         for (l = options; l; l = l->next) {
61                 src = l->data;
62                 if (src->key == SR_CONF_CONN)
63                         conn = g_variant_get_string(src->data, NULL);
64         }
65         if (!conn)
66                 return NULL;
67
68         if (!(serial = sr_serial_dev_inst_new(conn, SERIALCOMM)))
69                 return NULL;
70
71         if (serial_open(serial, SERIAL_RDONLY | SERIAL_NONBLOCK) != SR_OK)
72                 return NULL;
73
74         devices = NULL;
75         drvc = di->priv;
76         start = g_get_monotonic_time();
77         while (g_get_monotonic_time() - start < MAX_SCAN_TIME) {
78                 if (serial_read(serial, &c, 1) == 1 && c == 0xa5) {
79                         /* Found one. */
80                         if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "CEM",
81                                         "DT-885x", NULL)))
82                                 return NULL;
83
84                         if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
85                                 sr_dbg("Device context malloc failed.");
86                                 return NULL;
87                         }
88
89                         if (!(sdi->conn = sr_serial_dev_inst_new(conn, SERIALCOMM)))
90                                 return NULL;
91
92                         sdi->inst_type = SR_INST_SERIAL;
93                         sdi->priv = devc;
94                         sdi->driver = di;
95                         if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1")))
96                                 return NULL;
97                         sdi->probes = g_slist_append(sdi->probes, probe);
98                         drvc->instances = g_slist_append(drvc->instances, sdi);
99                         devices = g_slist_append(devices, sdi);
100                         break;
101                 }
102                 /* It takes about 1ms for a byte to come in. */
103                 g_usleep(1000);
104         }
105
106         serial_close(serial);
107
108         return devices;
109 }
110
111 static GSList *dev_list(void)
112 {
113         struct drv_context *drvc;
114
115         drvc = di->priv;
116
117         return drvc->instances;
118 }
119
120 static int dev_clear(void)
121 {
122         return std_dev_clear(di, NULL);
123 }
124
125 static int dev_open(struct sr_dev_inst *sdi)
126 {
127         struct sr_serial_dev_inst *serial;
128
129         serial = sdi->conn;
130         if (serial_open(serial, SERIAL_RDWR) != SR_OK)
131                 return SR_ERR;
132
133         sdi->status = SR_ST_ACTIVE;
134
135         return SR_OK;
136 }
137
138 static int dev_close(struct sr_dev_inst *sdi)
139 {
140         struct sr_serial_dev_inst *serial;
141
142         serial = sdi->conn;
143         if (serial && serial->fd != -1) {
144                 serial_close(serial);
145                 sdi->status = SR_ST_INACTIVE;
146         }
147
148         return SR_OK;
149 }
150
151 static int cleanup(void)
152 {
153         return dev_clear();
154 }
155
156 static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi)
157 {
158         struct dev_context *devc;
159
160         if (!sdi)
161                 return SR_ERR_ARG;
162
163         devc = sdi->priv;
164         switch (key) {
165         case SR_CONF_LIMIT_SAMPLES:
166                 *data = g_variant_new_uint64(devc->limit_samples);
167                 break;
168         default:
169                 return SR_ERR_NA;
170         }
171
172         return SR_OK;
173 }
174
175 static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi)
176 {
177         struct dev_context *devc;
178         uint64_t tmp_u64;
179         int ret;
180
181         if (sdi->status != SR_ST_ACTIVE)
182                 return SR_ERR_DEV_CLOSED;
183
184         if (!(devc = sdi->priv)) {
185                 sr_err("sdi->priv was NULL.");
186                 return SR_ERR_BUG;
187         }
188
189         ret = SR_OK;
190         switch (key) {
191         case SR_CONF_LIMIT_SAMPLES:
192                 tmp_u64 = g_variant_get_uint64(data);
193                 devc->limit_samples = tmp_u64;
194                 ret = SR_OK;
195                 break;
196         default:
197                 ret = SR_ERR_NA;
198         }
199
200         return ret;
201 }
202
203 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
204 {
205         int ret;
206
207         (void)sdi;
208
209         ret = SR_OK;
210         switch (key) {
211         case SR_CONF_SCAN_OPTIONS:
212                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
213                                 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
214                 break;
215         case SR_CONF_DEVICE_OPTIONS:
216                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
217                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
218                 break;
219         default:
220                 return SR_ERR_NA;
221         }
222
223         return ret;
224 }
225
226 static int dev_acquisition_start(const struct sr_dev_inst *sdi,
227                                     void *cb_data)
228 {
229         (void)sdi;
230         (void)cb_data;
231
232         if (sdi->status != SR_ST_ACTIVE)
233                 return SR_ERR_DEV_CLOSED;
234
235         /* TODO: configure hardware, reset acquisition state, set up
236          * callbacks and send header packet. */
237
238         return SR_OK;
239 }
240
241 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
242 {
243         (void)cb_data;
244
245         if (sdi->status != SR_ST_ACTIVE)
246                 return SR_ERR_DEV_CLOSED;
247
248         /* TODO: stop acquisition. */
249
250         return SR_OK;
251 }
252
253 SR_PRIV struct sr_dev_driver cem_dt_885x_driver_info = {
254         .name = "cem-dt-885x",
255         .longname = "CEM DT-885x",
256         .api_version = 1,
257         .init = init,
258         .cleanup = cleanup,
259         .scan = scan,
260         .dev_list = dev_list,
261         .dev_clear = dev_clear,
262         .config_get = config_get,
263         .config_set = config_set,
264         .config_list = config_list,
265         .dev_open = dev_open,
266         .dev_close = dev_close,
267         .dev_acquisition_start = dev_acquisition_start,
268         .dev_acquisition_stop = dev_acquisition_stop,
269         .priv = NULL,
270 };