1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 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 <config.h>
21 #include <libsigrok/libsigrok.h>
22 #include "libsigrok-internal.h"
23 
24 /* * @cond PRIVATE */
25 #define LOG_PREFIX "trigger"
26 /* * @endcond */
27 
28 /**
29  * @file
30  *
31  * Creating, using, or destroying triggers.
32  */
33 
34 /**
35  * @defgroup grp_trigger Trigger handling
36  *
37  * Creating, using, or destroying triggers.
38  *
39  * @{
40  */
41 
42 /**
43  * Create a new trigger.
44  *
45  * The caller is responsible to free the trigger (including all stages and
46  * matches) using sr_trigger_free() once it is no longer needed.
47  *
48  * @param name The trigger name to use. Can be NULL.
49  *
50  * @return A newly allocated trigger.
51  *
52  * @since 0.4.0
53  */
sr_trigger_new(const char * name)54 SR_API struct sr_trigger *sr_trigger_new(const char *name)
55 {
56 	struct sr_trigger *trig;
57 
58 	trig = g_malloc0(sizeof(struct sr_trigger));
59 	if (name)
60 		trig->name = g_strdup(name);
61 
62 	return trig;
63 }
64 
65 /**
66  * Free a previously allocated trigger.
67  *
68  * This will also free any trigger stages/matches in this trigger.
69  *
70  * @param trig The trigger to free. Must not be NULL.
71  *
72  * @since 0.4.0
73  */
sr_trigger_free(struct sr_trigger * trig)74 SR_API void sr_trigger_free(struct sr_trigger *trig)
75 {
76 	struct sr_trigger_stage *stage;
77 	GSList *l;
78 
79 	if (!trig)
80 		return;
81 
82 	for (l = trig->stages; l; l = l->next) {
83 		stage = l->data;
84 
85 		if (stage->matches)
86 			g_slist_free_full(stage->matches, g_free);
87 	}
88 	g_slist_free_full(trig->stages, g_free);
89 
90 	g_free(trig->name);
91 	g_free(trig);
92 }
93 
94 /**
95  * Allocate a new trigger stage and add it to the specified trigger.
96  *
97  * The caller is responsible to free the trigger (including all stages and
98  * matches) using sr_trigger_free() once it is no longer needed.
99  *
100  * @param trig The trigger to add a stage to. Must not be NULL.
101  *
102  * @retval NULL An invalid (NULL) trigger was passed into the function.
103  * @retval other A newly allocated trigger stage (which has also been added
104  * 		 to the list of stages of the specified trigger).
105  *
106  * @since 0.4.0
107  */
sr_trigger_stage_add(struct sr_trigger * trig)108 SR_API struct sr_trigger_stage *sr_trigger_stage_add(struct sr_trigger *trig)
109 {
110 	struct sr_trigger_stage *stage;
111 
112 	if (!trig)
113 		return NULL;
114 
115 	stage = g_malloc0(sizeof(struct sr_trigger_stage));
116 	stage->stage = g_slist_length(trig->stages);
117 	trig->stages = g_slist_append(trig->stages, stage);
118 
119 	return stage;
120 }
121 
122 /**
123  * Allocate a new trigger match and add it to the specified trigger stage.
124  *
125  * The caller is responsible to free the trigger (including all stages and
126  * matches) using sr_trigger_free() once it is no longer needed.
127  *
128  * @param stage The trigger stage to add the match to. Must not be NULL.
129  * @param ch The channel for this trigger match. Must not be NULL. Must be
130  *           either of type SR_CHANNEL_LOGIC or SR_CHANNEL_ANALOG.
131  * @param trigger_match The type of trigger match. Must be a valid trigger
132  *                      type from enum sr_trigger_matches. The trigger type
133  *                      must be valid for the respective channel type as well.
134  * @param value Trigger value.
135  *
136  * @retval SR_OK Success.
137  * @retval SR_ERR_ARG Invalid argument(s) were passed to this functions.
138  *
139  * @since 0.4.0
140  */
sr_trigger_match_add(struct sr_trigger_stage * stage,struct sr_channel * ch,int trigger_match,float value)141 SR_API int sr_trigger_match_add(struct sr_trigger_stage *stage,
142 		struct sr_channel *ch, int trigger_match, float value)
143 {
144 	struct sr_trigger_match *match;
145 
146 	if (!stage || !ch)
147 		return SR_ERR_ARG;
148 
149 	if (ch->type == SR_CHANNEL_LOGIC) {
150 		if (trigger_match != SR_TRIGGER_ZERO &&
151 				trigger_match != SR_TRIGGER_ONE &&
152 				trigger_match != SR_TRIGGER_RISING &&
153 				trigger_match != SR_TRIGGER_FALLING &&
154 				trigger_match != SR_TRIGGER_EDGE) {
155 			sr_err("Invalid trigger match for a logic channel.");
156 			return SR_ERR_ARG;
157 		}
158 	} else if (ch->type == SR_CHANNEL_ANALOG) {
159 		if (trigger_match != SR_TRIGGER_RISING &&
160 				trigger_match != SR_TRIGGER_FALLING &&
161 				trigger_match != SR_TRIGGER_EDGE &&
162 				trigger_match != SR_TRIGGER_OVER &&
163 				trigger_match != SR_TRIGGER_UNDER) {
164 			sr_err("Invalid trigger match for an analog channel.");
165 			return SR_ERR_ARG;
166 		}
167 	} else {
168 		sr_err("Unsupported channel type: %d.", ch->type);
169 		return SR_ERR_ARG;
170 	}
171 
172 	match = g_malloc0(sizeof(struct sr_trigger_match));
173 	match->channel = ch;
174 	match->match = trigger_match;
175 	match->value = value;
176 	stage->matches = g_slist_append(stage->matches, match);
177 
178 	return SR_OK;
179 }
180 
181 /** @} */
182