]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
Sigma: Check state in hw_closedev
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
fc96e6f8 5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6239c175
UH
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdlib.h>
85b5af06 23#include <unistd.h>
6239c175
UH
24#include <string.h>
25#include <sigrok.h>
26#include "config.h"
27
e15f48c2
BV
28#define NUM_PROBES 8
29#define DEMONAME "Demo device"
30/* size of chunks to send through the session bus */
31#define BUFSIZE 4096
85b5af06 32
e15f48c2
BV
33enum {
34 GENMODE_RANDOM,
35 GENMODE_INC,
36};
85b5af06 37
e15f48c2
BV
38struct databag {
39 int pipe_fds[2];
40 uint8_t sample_generator;
41 uint8_t thread_running;
42 uint64_t samples_counter;
43 int device_index;
44 int loop_sleep;
45 gpointer session_device_id;
46};
85b5af06
UH
47
48static GThread *my_thread;
49static int thread_running;
50
6239c175
UH
51static int capabilities[] = {
52 HWCAP_LOGIC_ANALYZER,
e15f48c2 53 HWCAP_PATTERN_MODE,
6239c175 54 HWCAP_LIMIT_SAMPLES,
ba3d481b 55 HWCAP_CONTINUOUS
6239c175
UH
56};
57
02440dd8 58static const char *patternmodes[] = {
e15f48c2
BV
59 "random",
60 "incremental",
02440dd8 61 NULL,
85b5af06
UH
62};
63
64/* List of struct sigrok_device_instance, maintained by opendev()/closedev(). */
65static GSList *device_instances = NULL;
6239c175 66static uint64_t cur_samplerate = 0;
ba3d481b 67static uint64_t limit_samples = -1;
e15f48c2 68static int default_genmode = GENMODE_RANDOM;
6239c175 69
6239c175
UH
70static void hw_stop_acquisition(int device_index, gpointer session_device_id);
71
6239c175
UH
72static int hw_init(char *deviceinfo)
73{
85b5af06
UH
74 struct sigrok_device_instance *sdi;
75
e15f48c2
BV
76 /* Avoid compiler warnings. */
77 deviceinfo = deviceinfo;
85b5af06 78
e15f48c2 79 sdi = sigrok_device_instance_new(0, ST_ACTIVE, DEMONAME, NULL, NULL);
85b5af06
UH
80 if (!sdi)
81 return 0;
e15f48c2 82
85b5af06
UH
83 device_instances = g_slist_append(device_instances, sdi);
84
85 return 1;
6239c175
UH
86}
87
88static int hw_opendev(int device_index)
89{
17e1afcb 90 /* Avoid compiler warnings. */
6239c175
UH
91 device_index = device_index;
92
93 /* Nothing needed so far. */
94 return SIGROK_OK;
95}
96
97static void hw_closedev(int device_index)
98{
17e1afcb 99 /* Avoid compiler warnings. */
6239c175
UH
100 device_index = device_index;
101
102 /* Nothing needed so far. */
103}
104
105static void hw_cleanup(void)
106{
107 /* Nothing needed so far. */
108}
109
110static void *hw_get_device_info(int device_index, int device_info_id)
111{
85b5af06
UH
112 struct sigrok_device_instance *sdi;
113 void *info = NULL;
114
115 if (!(sdi = get_sigrok_device_instance(device_instances, device_index)))
116 return NULL;
117
6239c175
UH
118 switch (device_info_id) {
119 case DI_INSTANCE:
85b5af06 120 info = sdi;
6239c175
UH
121 break;
122 case DI_NUM_PROBES:
123 info = GINT_TO_POINTER(NUM_PROBES);
124 break;
6239c175
UH
125 case DI_CUR_SAMPLERATE:
126 info = &cur_samplerate;
127 break;
e15f48c2
BV
128 case DI_PATTERNMODES:
129 info = &patternmodes;
130 break;
6239c175
UH
131 }
132
133 return info;
134}
135
136static int hw_get_status(int device_index)
137{
17e1afcb 138 /* Avoid compiler warnings. */
6239c175 139 device_index = device_index;
5096c6a6 140
e15f48c2 141 return ST_ACTIVE;
6239c175
UH
142}
143
144static int *hw_get_capabilities(void)
145{
146 return capabilities;
147}
148
149static int hw_set_configuration(int device_index, int capability, void *value)
150{
151 int ret;
85b5af06 152 uint64_t *tmp_u64;
e15f48c2 153 char *stropt;
6239c175 154
17e1afcb 155 /* Avoid compiler warnings. */
6239c175
UH
156 device_index = device_index;
157
e15f48c2 158 if (capability == HWCAP_PROBECONFIG) {
02440dd8 159 /* Nothing to do. */
85b5af06 160 ret = SIGROK_OK;
6239c175 161 } else if (capability == HWCAP_LIMIT_SAMPLES) {
85b5af06
UH
162 tmp_u64 = value;
163 limit_samples = *tmp_u64;
6239c175 164 ret = SIGROK_OK;
e15f48c2
BV
165 } else if (capability == HWCAP_PATTERN_MODE) {
166 stropt = value;
167 if (!strcmp(stropt, "random")) {
168 default_genmode = GENMODE_RANDOM;
169 ret = SIGROK_OK;
170 } else if (!strcmp(stropt, "incremental")) {
171 default_genmode = GENMODE_INC;
172 ret = SIGROK_OK;
173 } else {
174 ret = SIGROK_ERR;
175 }
6239c175
UH
176 } else {
177 ret = SIGROK_ERR;
178 }
179
180 return ret;
181}
182
5096c6a6 183static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06
UH
184{
185 struct databag *mydata = data;
186 uint64_t i;
85b5af06 187
5096c6a6 188 memset(buf, 0, size);
85b5af06
UH
189
190 switch (mydata->sample_generator) {
191 case GENMODE_RANDOM: /* Random */
5096c6a6
UH
192 for (i = 0; i < size; i++)
193 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06
UH
194 break;
195 case GENMODE_INC: /* Simple increment */
5096c6a6 196 for (i = 0; i < size; i++)
85b5af06
UH
197 *(buf + i) = i;
198 break;
199 }
200}
201
202/* Thread function */
203static void thread_func(void *data)
204{
205 struct databag *mydata = data;
206 uint8_t buf[BUFSIZE];
207 uint64_t nb_to_send = 0;
208
209 while (thread_running) {
ba3d481b
OF
210 if (limit_samples)
211 nb_to_send = limit_samples - mydata->samples_counter;
212 else
02440dd8 213 nb_to_send = BUFSIZE; /* Continuous mode */
85b5af06
UH
214
215 if (nb_to_send == 0) {
216 close(mydata->pipe_fds[1]);
217 thread_running = 0;
218 hw_stop_acquisition(mydata->device_index,
219 mydata->session_device_id);
220 } else if (nb_to_send > BUFSIZE) {
221 nb_to_send = BUFSIZE;
222 }
223
224 samples_generator(buf, nb_to_send, data);
225 mydata->samples_counter += nb_to_send;
226
227 write(mydata->pipe_fds[1], &buf, nb_to_send);
228 g_usleep(mydata->loop_sleep);
229 }
230}
231
232/* Callback handling data */
233static int receive_data(int fd, int revents, void *user_data)
234{
235 struct datafeed_packet packet;
85b5af06
UH
236 char c[BUFSIZE];
237 uint64_t z;
238
239 /* Avoid compiler warnings. */
240 revents = revents;
241
242 z = read(fd, &c, BUFSIZE);
243 if (z > 0) {
4c046c6b 244 packet.type = DF_LOGIC;
85b5af06 245 packet.length = z;
4c046c6b 246 packet.unitsize = 1;
85b5af06
UH
247 packet.payload = c;
248 session_bus(user_data, &packet);
249 }
250 return TRUE;
251}
252
6239c175
UH
253static int hw_start_acquisition(int device_index, gpointer session_device_id)
254{
255 struct datafeed_packet *packet;
256 struct datafeed_header *header;
85b5af06 257 struct databag *mydata;
6239c175 258
85b5af06 259 mydata = malloc(sizeof(struct databag));
5096c6a6
UH
260 if (!mydata)
261 return SIGROK_ERR_MALLOC;
85b5af06 262
e15f48c2 263 mydata->sample_generator = default_genmode;
85b5af06
UH
264 mydata->session_device_id = session_device_id;
265 mydata->device_index = device_index;
266 mydata->samples_counter = 0;
267 mydata->loop_sleep = 100000;
268
e15f48c2
BV
269 if (pipe(mydata->pipe_fds))
270 return SIGROK_ERR;
85b5af06 271
85b5af06
UH
272 source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40, receive_data,
273 session_device_id);
274
275 /* Run the demo thread. */
276 g_thread_init(NULL);
277 thread_running = 1;
278 my_thread =
279 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
e15f48c2
BV
280 if (!my_thread)
281 return SIGROK_ERR;
6239c175
UH
282
283 packet = malloc(sizeof(struct datafeed_packet));
284 header = malloc(sizeof(struct datafeed_header));
e15f48c2 285 if (!packet || !header)
6239c175
UH
286 return SIGROK_ERR_MALLOC;
287
6239c175
UH
288 packet->type = DF_HEADER;
289 packet->length = sizeof(struct datafeed_header);
290 packet->payload = (unsigned char *)header;
291 header->feed_version = 1;
292 gettimeofday(&header->starttime, NULL);
293 header->samplerate = cur_samplerate;
294 header->protocol_id = PROTO_RAW;
c2616fb9
DR
295 header->num_logic_probes = NUM_PROBES;
296 header->num_analog_probes = 0;
6239c175
UH
297 session_bus(session_device_id, packet);
298 free(header);
299 free(packet);
300
301 return SIGROK_OK;
302}
303
6239c175
UH
304static void hw_stop_acquisition(int device_index, gpointer session_device_id)
305{
306 struct datafeed_packet packet;
307
17e1afcb 308 /* Avoid compiler warnings. */
6239c175
UH
309 device_index = device_index;
310
85b5af06 311 /* Send last packet. */
6239c175
UH
312 packet.type = DF_END;
313 session_bus(session_device_id, &packet);
6239c175
UH
314}
315
316struct device_plugin demo_plugin_info = {
317 "demo",
318 1,
319 hw_init,
320 hw_cleanup,
321 hw_opendev,
322 hw_closedev,
323 hw_get_device_info,
324 hw_get_status,
325 hw_get_capabilities,
326 hw_set_configuration,
327 hw_start_acquisition,
328 hw_stop_acquisition,
329};