]>
Commit | Line | Data |
---|---|---|
6239c175 UH |
1 | /* |
2 | * This file is part of the sigrok project. | |
3 | * | |
4 | * Copyright (C) 2010 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 <stdlib.h> | |
22 | #include <string.h> | |
23 | #include <sigrok.h> | |
24 | #include "config.h" | |
25 | ||
26 | #define NUM_PROBES 8 | |
27 | #define NUM_TRIGGER_STAGES 4 | |
28 | #define TRIGGER_TYPES "01" | |
29 | ||
30 | /* Software trigger implementation: positive values indicate trigger stage. */ | |
31 | #define TRIGGER_FIRED -1 | |
32 | ||
33 | static int capabilities[] = { | |
34 | HWCAP_LOGIC_ANALYZER, | |
35 | HWCAP_SAMPLERATE, | |
36 | HWCAP_LIMIT_SAMPLES, | |
37 | }; | |
38 | ||
39 | /* Random selection of samplerates this "device" shall support. */ | |
40 | static uint64_t supported_samplerates[] = { | |
41 | KHZ(100), | |
42 | KHZ(500), | |
43 | MHZ(1), | |
44 | MHZ(2), | |
45 | MHZ(12), | |
46 | MHZ(24), | |
47 | 0, | |
48 | }; | |
49 | ||
50 | static struct samplerates samplerates = { | |
51 | KHZ(100), | |
52 | MHZ(24), | |
53 | 0, | |
54 | supported_samplerates, | |
55 | }; | |
56 | ||
57 | /* TODO: All of these should go in a device-specific struct. */ | |
58 | static uint64_t cur_samplerate = 0; | |
59 | static uint64_t limit_samples = 0; | |
60 | // static uint8_t probe_mask = 0; | |
61 | // static uint8_t trigger_mask[NUM_TRIGGER_STAGES] = { 0 }; | |
62 | // static uint8_t trigger_value[NUM_TRIGGER_STAGES] = { 0 }; | |
63 | // static uint8_t trigger_buffer[NUM_TRIGGER_STAGES] = { 0 }; | |
64 | ||
65 | // static int trigger_stage = TRIGGER_FIRED; | |
66 | ||
67 | static int hw_set_configuration(int device_index, int capability, void *value); | |
68 | static void hw_stop_acquisition(int device_index, gpointer session_device_id); | |
69 | ||
70 | #if 0 | |
71 | static int configure_probes(GSList *probes) | |
72 | { | |
73 | struct probe *probe; | |
74 | GSList *l; | |
75 | int probe_bit, stage, i; | |
76 | char *tc; | |
77 | ||
78 | probe_mask = 0; | |
79 | for (i = 0; i < NUM_TRIGGER_STAGES; i++) { | |
80 | trigger_mask[i] = 0; | |
81 | trigger_value[i] = 0; | |
82 | } | |
83 | ||
84 | stage = -1; | |
85 | for (l = probes; l; l = l->next) { | |
86 | probe = (struct probe *)l->data; | |
87 | if (!(probe->enabled)) | |
88 | continue; | |
89 | probe_bit = 1 << (probe->index - 1); | |
90 | probe_mask |= probe_bit; | |
91 | if (!(probe->trigger)) | |
92 | continue; | |
93 | ||
94 | stage = 0; | |
95 | for (tc = probe->trigger; *tc; tc++) { | |
96 | trigger_mask[stage] |= probe_bit; | |
97 | if (*tc == '1') | |
98 | trigger_value[stage] |= probe_bit; | |
99 | stage++; | |
100 | if (stage > NUM_TRIGGER_STAGES) | |
101 | return SIGROK_ERR; | |
102 | } | |
103 | } | |
104 | ||
105 | if (stage == -1) | |
106 | /* | |
107 | * We didn't configure any triggers, make sure acquisition | |
108 | * doesn't wait for any. | |
109 | */ | |
110 | trigger_stage = TRIGGER_FIRED; | |
111 | else | |
112 | trigger_stage = 0; | |
113 | ||
114 | return SIGROK_OK; | |
115 | } | |
116 | #endif | |
117 | ||
118 | static int hw_init(char *deviceinfo) | |
119 | { | |
120 | /* Avoid compiler warning. */ | |
121 | deviceinfo = deviceinfo; | |
122 | ||
123 | /* Nothing needed so far. */ | |
124 | return 1; /* FIXME? */ | |
125 | } | |
126 | ||
127 | static int hw_opendev(int device_index) | |
128 | { | |
129 | /* Avoid compiler warning. */ | |
130 | device_index = device_index; | |
131 | ||
132 | /* Nothing needed so far. */ | |
133 | return SIGROK_OK; | |
134 | } | |
135 | ||
136 | static void hw_closedev(int device_index) | |
137 | { | |
138 | /* Avoid compiler warning. */ | |
139 | device_index = device_index; | |
140 | ||
141 | /* Nothing needed so far. */ | |
142 | } | |
143 | ||
144 | static void hw_cleanup(void) | |
145 | { | |
146 | /* Nothing needed so far. */ | |
147 | } | |
148 | ||
149 | static void *hw_get_device_info(int device_index, int device_info_id) | |
150 | { | |
151 | void *info = NULL; | |
152 | ||
153 | /* Avoid compiler warning. */ | |
154 | device_index = device_index; | |
155 | ||
156 | switch (device_info_id) { | |
157 | case DI_INSTANCE: | |
158 | /// info = sdi; | |
159 | /* TODO */ | |
160 | break; | |
161 | case DI_NUM_PROBES: | |
162 | info = GINT_TO_POINTER(NUM_PROBES); | |
163 | break; | |
164 | case DI_SAMPLERATES: | |
165 | info = &samplerates; | |
166 | break; | |
167 | case DI_TRIGGER_TYPES: | |
168 | info = TRIGGER_TYPES; | |
169 | break; | |
170 | case DI_CUR_SAMPLERATE: | |
171 | info = &cur_samplerate; | |
172 | break; | |
173 | } | |
174 | ||
175 | return info; | |
176 | } | |
177 | ||
178 | static int hw_get_status(int device_index) | |
179 | { | |
180 | /* Avoid compiler warning. */ | |
181 | device_index = device_index; | |
182 | ||
183 | return 0; /* FIXME */ | |
184 | } | |
185 | ||
186 | static int *hw_get_capabilities(void) | |
187 | { | |
188 | return capabilities; | |
189 | } | |
190 | ||
191 | static int hw_set_configuration(int device_index, int capability, void *value) | |
192 | { | |
193 | int ret; | |
194 | ||
195 | /* Avoid compiler warning. */ | |
196 | device_index = device_index; | |
197 | ||
198 | if (capability == HWCAP_SAMPLERATE) { | |
199 | cur_samplerate = *(uint64_t *)value; | |
200 | ret = SIGROK_OK; | |
201 | } else if (capability == HWCAP_PROBECONFIG) { | |
202 | // ret = configure_probes((GSList *) value); | |
203 | ret = SIGROK_ERR; | |
204 | } else if (capability == HWCAP_LIMIT_SAMPLES) { | |
205 | limit_samples = strtoull(value, NULL, 10); | |
206 | ret = SIGROK_OK; | |
207 | } else { | |
208 | ret = SIGROK_ERR; | |
209 | } | |
210 | ||
211 | return ret; | |
212 | } | |
213 | ||
214 | static int hw_start_acquisition(int device_index, gpointer session_device_id) | |
215 | { | |
216 | struct datafeed_packet *packet; | |
217 | struct datafeed_header *header; | |
218 | unsigned char *buf; | |
219 | ||
220 | /* Avoid compiler warning. */ | |
221 | device_index = device_index; | |
222 | ||
223 | packet = malloc(sizeof(struct datafeed_packet)); | |
224 | header = malloc(sizeof(struct datafeed_header)); | |
225 | buf = malloc(2048); | |
226 | if (!packet || !header || !buf) | |
227 | return SIGROK_ERR_MALLOC; | |
228 | ||
229 | /* FIXME */ | |
230 | memset(buf, 0x55, 2048); | |
231 | ||
232 | packet->type = DF_HEADER; | |
233 | packet->length = sizeof(struct datafeed_header); | |
234 | packet->payload = (unsigned char *)header; | |
235 | header->feed_version = 1; | |
236 | gettimeofday(&header->starttime, NULL); | |
237 | header->samplerate = cur_samplerate; | |
238 | header->protocol_id = PROTO_RAW; | |
239 | header->num_probes = NUM_PROBES; | |
240 | session_bus(session_device_id, packet); | |
241 | free(header); | |
242 | free(packet); | |
243 | ||
244 | return SIGROK_OK; | |
245 | } | |
246 | ||
247 | #if 0 | |
248 | void receive_transfer(struct libusb_transfer *transfer) | |
249 | { | |
250 | static int num_samples = 0; | |
251 | static int empty_transfer_count = 0; | |
252 | struct datafeed_packet packet; | |
253 | void *user_data; | |
254 | int cur_buflen, trigger_offset, i; | |
255 | unsigned char *cur_buf, *new_buf; | |
256 | ||
257 | g_message("receive_transfer(): status %d received %d bytes", | |
258 | transfer->status, transfer->actual_length); | |
259 | ||
260 | /* Save incoming transfer before reusing the transfer struct. */ | |
261 | cur_buf = transfer->buffer; | |
262 | cur_buflen = transfer->actual_length; | |
263 | user_data = transfer->user_data; | |
264 | ||
265 | /* Fire off a new request. */ | |
266 | new_buf = g_malloc(4096); | |
267 | transfer->buffer = new_buf; | |
268 | transfer->length = 4096; | |
269 | if (libusb_submit_transfer(transfer) != 0) { | |
270 | /* TODO: Stop session? */ | |
271 | g_warning("eek"); | |
272 | } | |
273 | ||
274 | trigger_offset = 0; | |
275 | if (trigger_stage >= 0) { | |
276 | for (i = 0; i < cur_buflen; i++) { | |
277 | trigger_helper(i, cur_buf, &packet, user_data, | |
278 | &trigger_offset); | |
279 | } | |
280 | } | |
281 | ||
282 | if (trigger_stage == TRIGGER_FIRED) { | |
283 | /* Send the incoming transfer to the session bus. */ | |
284 | packet.type = DF_LOGIC8; | |
285 | packet.length = cur_buflen - trigger_offset; | |
286 | packet.payload = cur_buf + trigger_offset; | |
287 | session_bus(user_data, &packet); | |
288 | free(cur_buf); | |
289 | ||
290 | num_samples += cur_buflen; | |
291 | if ((unsigned int)num_samples > limit_samples) { | |
292 | hw_stop_acquisition(-1, user_data); | |
293 | } | |
294 | } else { | |
295 | /* | |
296 | * TODO: Buffer pre-trigger data in capture | |
297 | * ratio-sized buffer. | |
298 | */ | |
299 | } | |
300 | } | |
301 | #endif | |
302 | ||
303 | /* This stops acquisition on ALL devices, ignoring device_index. */ | |
304 | static void hw_stop_acquisition(int device_index, gpointer session_device_id) | |
305 | { | |
306 | struct datafeed_packet packet; | |
307 | ||
308 | /* QUICK HACK */ | |
309 | device_index = device_index; | |
310 | ||
311 | packet.type = DF_END; | |
312 | session_bus(session_device_id, &packet); | |
313 | ||
314 | /// receive_transfer(NULL); | |
315 | ||
316 | /* TODO: Need to cancel and free any queued up transfers. */ | |
317 | } | |
318 | ||
319 | struct device_plugin demo_plugin_info = { | |
320 | "demo", | |
321 | 1, | |
322 | hw_init, | |
323 | hw_cleanup, | |
324 | hw_opendev, | |
325 | hw_closedev, | |
326 | hw_get_device_info, | |
327 | hw_get_status, | |
328 | hw_get_capabilities, | |
329 | hw_set_configuration, | |
330 | hw_start_acquisition, | |
331 | hw_stop_acquisition, | |
332 | }; |