]>
Commit | Line | Data |
---|---|---|
ff7f7f73 GS |
1 | /* |
2 | * This file is part of the libsigrok project. | |
3 | * | |
4 | * Copyright (C) 2019-2023 Gerhard Sittig <gerhard.sittig@gmx.net> | |
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 | /* | |
21 | * This input module reads data values from an input stream, and sends | |
22 | * the corresponding samples to the sigrok session feed which form the | |
23 | * respective waveform, pretending that a logic analyzer had captured | |
24 | * wire traffic. This allows to feed data to protocol decoders which | |
25 | * were recorded by different means (COM port redirection, pcap(3) | |
26 | * recordings, 3rd party bus analyzers). It can also simplify the | |
27 | * initial creation of protocol decoders by generating synthetic | |
28 | * input data, before real world traffic captures become available. | |
29 | * | |
30 | * This input module "assumes ideal traffic" and absence of protocol | |
31 | * errors. Does _not_ inject error conditions, instead generates valid | |
32 | * bit patterns by naively filling blanks to decorate the payload data | |
33 | * which the input file provides. To yield a stream of samples which | |
34 | * successfully decodes at the recipient's, and upper layer decoders | |
35 | * will see valid data which corresponds to the file's content. Edge | |
36 | * positions and minute timnig details are not adjustable either in | |
37 | * this module (no support for setup or hold times or slew rates etc). | |
38 | * The goal is not to emulate a protocol with all its possibilities to | |
39 | * the fullest detail. The module's purpose is to simplify the import | |
40 | * of values while no capture of the wire traffic was available. | |
41 | * | |
42 | * There are several approaches to using the input module: | |
43 | * - Input data can be a mere bytes sequence. While attributes can get | |
44 | * specified by means of input module options. This is the fastest | |
45 | * approach to accessing raw data that's externally made available. | |
46 | * - An optional leading magic literal supports automatic file type | |
47 | * detection, and obsoletes the -I input module selection. Unwanted | |
48 | * automatic detection is possible but very unlikely. The magic text | |
49 | * was chosen such that its occurance at the very start of payload | |
50 | * data is extremely unlikely, and is easy to work around should the | |
51 | * situation happen. Of course specifying input module options does | |
52 | * necessitate the selection of the input module. | |
53 | * - When the file type magic is present, an optional header section | |
54 | * can follow, and can carry parameters which obsolete the necessity | |
55 | * to specify input module options. The choice of header section | |
56 | * boundaries again reduces the likelyhood of false detection. When | |
57 | * input module options were specified, they take precedence over | |
58 | * input stream content. | |
59 | * - The payload of the input stream (the protocol values) can take | |
60 | * the form of a mere bytes sequence where every byte is a value | |
61 | * (this is the default). Or values can be represented in textual | |
62 | * format when either an input module option or the header section | |
63 | * specify that the input is text. Individual protocol handlers can | |
64 | * also prefer one format over another, while file content and | |
65 | * module options take precedence as usual. Some protocols may not | |
66 | * usefully be described by values only, or may involve values and | |
67 | * numbers larger than a byte, which essentially makes text format | |
68 | * a non-option for these situations. | |
69 | * - The text format supports coments which silently get discarded. | |
70 | * As well as pseudo comments which can affect the interpretation | |
71 | * of the input text, and/or can control properties of protocols | |
72 | * that exceed the mere submission of values. Think chip-select or | |
73 | * ACK/NAK slots or similar. | |
74 | * - It's understood that the text format is more expensive to process, | |
75 | * but is also more versatile. It's assumed that the 'protocoldata' | |
76 | * input format is used for small or mid size capture lengths. The | |
77 | * input module enables quick access to data that became available | |
78 | * by other means. For higher fidelity of real world traffic and for | |
79 | * long captures the native format should be preferred. For error | |
80 | * injection the VCD format might be a better match. | |
81 | * - It should be obvious that raw bytes or input data in text form, | |
82 | * as well as header fields can either be the content of a file on | |
83 | * disk, or can be part of a pipe input. Either the earlier process | |
84 | * in the pipe which provides the values, or an intermediate filter | |
85 | * in the pipe, can provide the decoration. | |
86 | * $ ./gen-values.sh | sigrok-cli -i - ... | |
87 | * $ ./gen-values.sh | cat header - | sigrok-cli -i - ... | |
88 | * - Since the input format supports automatic detection as well as | |
89 | * parameter specs by means of input module options as well as in | |
90 | * file content, the format lends itself equally well to pipelined | |
91 | * or scripted as well as interactive use in different applications. | |
92 | * For pipelines, the header as well as the values (as well as any | |
93 | * mix of these pieces) can be kept in separate locations. Generators | |
94 | * need not provide all of the input stream in a single invocation. | |
95 | * - As a matter of convenience, especially when targetting upper layer | |
96 | * protocol decoders, users need not construct "correctly configured" | |
97 | * from the lower protocol's perspective) waveforms on the wire. | |
98 | * Instead "naive" waveforms which match the decoders' default options | |
99 | * can be used, which eliminates the need to configure non-default | |
100 | * options in decoders (and redundantly do the same thing in the | |
101 | * input module, just to have them match again). | |
102 | * $ ./gen-values.sh | sigrok-cli \ | |
103 | * -i - -I protocoldata:protocol=uart:bitrate=57600:frameformat=8e2 \ | |
104 | * -P uart:parity=even:baudrate=57600 | |
105 | * $ ./gen-values.sh | sigrok-cli \ | |
106 | * -i - -I protocoldata:protocol=uart -P uart,midi | |
107 | * | |
108 | * Example invocations: | |
109 | * | |
110 | * $ sigrok-cli -I protocoldata --show | |
111 | * | |
112 | * $ echo "Hello sigrok protocol values!" | \ | |
113 | * sigrok-cli \ | |
114 | * -I protocoldata:protocol=uart -i - \ | |
115 | * -P uart:format=ascii -A uart=rx-data | |
116 | * | |
117 | * $ sigrok-cli -i file.bin -P uart -A uart=rx-data | |
118 | * $ sigrok-cli -i file.txt -P uart:rx=rxtx -A uart | |
119 | * $ sigrok-cli -i file.txt --show | |
120 | * $ sigrok-cli -i file.txt -O ascii:width=4000 | $PAGER | |
121 | * | |
122 | * $ echo "# -- sigrok protocol data values file --" > header.txt | |
123 | * $ echo "# -- sigrok protocol data header start --" >> header.txt | |
124 | * $ echo "protocol=uart" >> header.txt | |
125 | * $ echo "bitrate=100000" >> header.txt | |
126 | * $ echo "frameformat=8e2" >> header.txt | |
127 | * $ echo "textinput=yes" >> header.txt | |
128 | * $ echo "# -- sigrok protocol data header end --" >> header.txt | |
129 | * $ echo "# textinput: radix=16" > values.txt | |
130 | * $ echo "0f 40 a6 28 fa 78 05 19 ee c2 92 70 58 62 09 a9 f1 ca 44 90 d1 07 19 02 00" >> values.txt | |
131 | * $ head header.txt values.txt | |
132 | * $ cat values.txt | cat header.txt - | \ | |
133 | * sigrok-cli -i - -P uart:baudrate=100000:parity=even,sbus_futaba -A sbus_futaba | |
134 | * | |
135 | * $ pulseview -i file-spi-text.txt & | |
136 | * | |
137 | * Known issues: | |
138 | * - Only few protocols are implemented so far. Existing handlers have | |
139 | * suggested which infrastructure is required for future extension. | |
140 | * But future handlers may reveal more omissions or assumptions that | |
141 | * need addressing. | |
142 | * - Terminology may be inconsistent, because this input module supports | |
143 | * several protocols which often differ in how they use terms. What is | |
144 | * available: | |
145 | * - The input module constructs waveforms that span multiple traces. | |
146 | * Resulting waveforms are said to have a samplerate. Data that is | |
147 | * kept in that waveform can have a bitrate. Which is essential for | |
148 | * asynchronous communication, but could be unimportant for clocked | |
149 | * protocols. Protocol handlers may adjust their output to enforce | |
150 | * a bitrate, but need not. The timing is an approximation anyway, | |
151 | * does not reflect pauses or jitter or turnarounds which real world | |
152 | * traffic would reveal. | |
153 | * - Protocol handlers can generate an arbitrary number of samples for | |
154 | * a protocol data value. A maximum number of samples per value is | |
155 | * assumed. Variable length samples sequences per data value or per | |
156 | * invocation is supported (and can be considered the typical case). | |
157 | * - Protocol handlers can configure differing widths for the samples | |
158 | * that they derived from input data. These quanta get configured | |
159 | * when the frame format gets interpreted, and are assumed to remain | |
160 | * as they are across data value processing. | |
161 | * - Data values can be considered "a frame" (as seen with UART). But | |
162 | * data values could also be "bytes" or "words" in a protocol, while | |
163 | * "frames" or "transfers" are implemented by different means (as | |
164 | * seen with SPI or I2C). The typical approach would be to control a | |
165 | * "select" signal by means of pseudo comments which are interleaved | |
166 | * with data values. | |
167 | * - Data values need not get forwarded to decoders. They might also | |
168 | * control the processing of the following data values as well as | |
169 | * the waveform construction. This is at the discretion of protocol | |
170 | * handlers, think of slave addresses, preceeding field or value | |
171 | * counts before their data values follow, etc. | |
172 | * - Users may need to specify more options than expected when the file | |
173 | * content is "incomplete". The sequence of scanning builtin defaults, | |
174 | * then file content provided specs, then user specified specs, is | |
175 | * yet to get done. Until then it helps being explicit and thorough. | |
176 | * | |
177 | * TODO (arbitrary order, could partially be outdated) | |
178 | * - Implement the most appropriate order of option scanning. Use | |
179 | * builtin defaults first, file content then, then user specified | |
180 | * options (when available). This shall be most robust and correct. | |
181 | * - Switch to "submit one sample" in feed queue API when available. | |
182 | * The current implementation of this input module uses ugly ifdefs | |
183 | * to adjust to either feed queue API approach. | |
184 | * - (obsoleted by the introduction of support for text format input?) | |
185 | * Introduce TLV support for the binary input format? u32be type, | |
186 | * u64be length, u8[] payload. The complexity of the implementation | |
187 | * in the input module, combined with the complexity of generating | |
188 | * the input stream which uses TLV sections, are currently considered | |
189 | * undesirable for this input module. Do we expect huge files where | |
190 | * the computational cost of text conversion causes pain? | |
191 | * - Extend the UART protocol handler. Implement separate RX and TX | |
192 | * traces. Support tx-only, rx-only, and tx-then-rx input orders. | |
193 | * - Add a 'parallel' protocol handler, which grabs a bit pattern and | |
194 | * derives the waveform in straight forward ways? This would be similar | |
195 | * to the raw binary input module, but the text format could improve | |
196 | * readability, and the input module could generate a clock signal | |
197 | * which isn't part of the input stream. That 'parallel' protocol | |
198 | * could be used as a vehicle to bitbang any other protocol that is | |
199 | * unknown to the input module. The approach is only limited by the | |
200 | * input stream generator's imagination. | |
201 | * - Add other protocol variants. The binary input format was very | |
202 | * limiting, the text format could cover a lot of more cases: | |
203 | * - CAN: Pseudo comments can communicate the frame's flags (and | |
204 | * address type etc). The first data value can be the address. The | |
205 | * second data value or a pseudo comment can hold the CAN frame's | |
206 | * data length (bytes count). Other data values are the 0..8 data | |
207 | * bytes. CAN-FD might be possible with minimal adjustment? | |
208 | * - W1: Pseudo comments can start a frame (initiate RESET). First | |
209 | * value can carry frame length. Data bytes follow. Scans can get | |
210 | * represented as raw bytes (bit count results in full 8bit size). | |
211 | * - Are more than 8 traces desirable? The initial implementation was | |
212 | * motivated by serial communication (UART). More channels were not | |
213 | * needed so far. Even QuadSPI and Hitachi displays fit onto 8 lines. | |
214 | * | |
215 | * See the sigrok.org file format wiki page for details about the syntax | |
216 | * that is supported by this input module. Or see the top of the source | |
217 | * file and its preprocessor symbols to quickly get an idea of known | |
218 | * keywords in input files. | |
219 | */ | |
220 | ||
221 | #include "config.h" | |
222 | ||
223 | #include <ctype.h> | |
224 | #include <libsigrok/libsigrok.h> | |
225 | #include <string.h> | |
226 | #include <strings.h> | |
227 | ||
228 | #include "libsigrok-internal.h" | |
229 | ||
230 | #define LOG_PREFIX "input/protocoldata" | |
231 | ||
232 | #define CHUNK_SIZE (4 * 1024 * 1024) | |
233 | ||
234 | /* | |
235 | * Support optional automatic file type detection. Support optionally | |
236 | * embedded options in a header section after the file detection magic | |
237 | * and before the payload data (bytes or text). | |
238 | */ | |
239 | #define MAGIC_FILE_TYPE "# -- sigrok protocol data values file --" | |
240 | #define TEXT_HEAD_START "# -- sigrok protocol data header start --" | |
241 | #define TEXT_HEAD_END "# -- sigrok protocol data header end --" | |
242 | #define TEXT_COMM_LEADER "#" | |
243 | ||
244 | #define LABEL_SAMPLERATE "samplerate=" | |
245 | #define LABEL_BITRATE "bitrate=" | |
246 | #define LABEL_PROTOCOL "protocol=" | |
247 | #define LABEL_FRAMEFORMAT "frameformat=" | |
248 | #define LABEL_TEXTINPUT "textinput=" | |
249 | ||
250 | /* | |
251 | * Options which are embedded in pseudo comments and are related to | |
252 | * how the input module reads the input text stream. Universally | |
253 | * applicable to all text inputs regardless of protocol choice. | |
254 | */ | |
255 | #define TEXT_INPUT_PREFIX "textinput:" | |
256 | #define TEXT_INPUT_RADIX "radix=" | |
257 | ||
258 | /* | |
259 | * Protocol dependent frame formats, the default and absolute limits. | |
260 | * Protocol dependent keywords in pseudo-comments. | |
261 | * | |
262 | * UART assumes 9x2 as the longest useful frameformat. Additional STOP | |
263 | * bits let users insert idle phases between frames, until more general | |
264 | * support for inter-frame gaps is in place. By default the protocol | |
265 | * handler generously adds a few more idle bit times after a UART frame. | |
266 | * | |
267 | * SPI assumes exactly 8 bits per "word". And leaves bit slots around | |
268 | * the byte transmission, to have space where CS asserts or releases. | |
269 | * Including time where SCK changes to its idle level. And requires two | |
270 | * samples per bit time (pos and neg clock phase). The "decoration" also | |
271 | * helps users' interactive exploration of generated waveforms. | |
272 | * | |
273 | * I2C generously assumes six quanta per bit slot, to gracefully allow | |
274 | * for reliable SCL and SDA transitions regardless of samples that result | |
275 | * from prior communication. The longest waveform is a byte (with eight | |
276 | * data bits and an ACK slot). Special symbols like START, and STOP will | |
277 | * fit into that memory while it is not used to communicate a byte. | |
278 | */ | |
279 | #define UART_HANDLER_NAME "uart" | |
280 | #define UART_DFLT_SAMPLERATE SR_MHZ(1) | |
281 | #define UART_DFLT_BITRATE 115200 | |
282 | #define UART_DFLT_FRAMEFMT "8n1" | |
283 | #define UART_MIN_DATABITS 5 | |
284 | #define UART_MAX_DATABITS 9 | |
285 | #define UART_MAX_STOPBITS 20 | |
286 | #define UART_ADD_IDLEBITS 2 | |
287 | #define UART_MAX_WAVELEN (1 + UART_MAX_DATABITS + 1 + UART_MAX_STOPBITS \ | |
288 | + UART_ADD_IDLEBITS) | |
289 | #define UART_FORMAT_INVERT "inverted" | |
290 | /* In addition the usual '8n1' et al are supported. */ | |
291 | #define UART_PSEUDO_BREAK "break" | |
292 | #define UART_PSEUDO_IDLE "idle" | |
293 | ||
294 | #define SPI_HANDLER_NAME "spi" | |
295 | #define SPI_DFLT_SAMPLERATE SR_MHZ(10) | |
296 | #define SPI_DFLT_BITRATE SR_MHZ(1) | |
297 | #define SPI_DFLT_FRAMEFMT "cs-low,bits=8,mode=0,msb-first" | |
298 | #define SPI_MIN_DATABITS 8 | |
299 | #define SPI_MAX_DATABITS 8 | |
300 | #define SPI_MAX_WAVELEN (2 + 2 * SPI_MAX_DATABITS + 3) | |
301 | #define SPI_FORMAT_CS_LOW "cs-low" | |
302 | #define SPI_FORMAT_CS_HIGH "cs-high" | |
303 | #define SPI_FORMAT_DATA_BITS "bits=" | |
304 | #define SPI_FORMAT_SPI_MODE "mode=" | |
305 | #define SPI_FORMAT_MODE_CPOL "cpol=" | |
306 | #define SPI_FORMAT_MODE_CPHA "cpha=" | |
307 | #define SPI_FORMAT_MSB_FIRST "msb-first" | |
308 | #define SPI_FORMAT_LSB_FIRST "lsb-first" | |
309 | #define SPI_PSEUDO_MOSI_ONLY "mosi-only" | |
310 | #define SPI_PSEUDO_MOSI_FIXED "mosi-fixed=" | |
311 | #define SPI_PSEUDO_MISO_ONLY "miso-only" | |
312 | #define SPI_PSEUDO_MISO_FIXED "miso-fixed=" | |
313 | #define SPI_PSEUDO_MOSI_MISO "mosi-then-miso" | |
314 | #define SPI_PSEUDO_MISO_MOSI "miso-then-mosi" | |
315 | #define SPI_PSEUDO_CS_ASSERT "cs-assert" | |
316 | #define SPI_PSEUDO_CS_RELEASE "cs-release" | |
317 | #define SPI_PSEUDO_CS_NEXT "cs-auto-next=" | |
318 | #define SPI_PSEUDO_IDLE "idle" | |
319 | ||
320 | #define I2C_HANDLER_NAME "i2c" | |
321 | #define I2C_DFLT_SAMPLERATE SR_MHZ(10) | |
322 | #define I2C_DFLT_BITRATE SR_KHZ(400) | |
323 | #define I2C_DFLT_FRAMEFMT "addr-7bit" | |
324 | #define I2C_BITTIME_SLOTS (1 + 8 + 1 + 1) | |
325 | #define I2C_BITTIME_QUANTA 6 | |
326 | #define I2C_ADD_IDLESLOTS 2 | |
327 | #define I2C_MAX_WAVELEN (I2C_BITTIME_QUANTA * I2C_BITTIME_SLOTS + I2C_ADD_IDLESLOTS) | |
328 | #define I2C_FORMAT_ADDR_7BIT "addr-7bit" | |
329 | #define I2C_FORMAT_ADDR_10BIT "addr-10bit" | |
330 | #define I2C_PSEUDO_START "start" | |
331 | #define I2C_PSEUDO_REP_START "repeat-start" | |
332 | #define I2C_PSEUDO_STOP "stop" | |
333 | #define I2C_PSEUDO_ADDR_WRITE "addr-write=" | |
334 | #define I2C_PSEUDO_ADDR_READ "addr-read=" | |
335 | #define I2C_PSEUDO_ACK_NEXT "ack-next=" | |
336 | #define I2C_PSEUDO_ACK_ONCE "ack-next" | |
337 | ||
338 | enum textinput_t { | |
339 | INPUT_UNSPEC, | |
340 | INPUT_BYTES, | |
341 | INPUT_TEXT, | |
342 | }; | |
343 | ||
344 | static const char *input_format_texts[] = { | |
345 | [INPUT_UNSPEC] = "from-file", | |
346 | [INPUT_BYTES] = "raw-bytes", | |
347 | [INPUT_TEXT] = "text-format", | |
348 | }; | |
349 | ||
350 | struct spi_proto_context_t { | |
351 | gboolean needs_mosi, has_mosi; | |
352 | gboolean needs_miso, has_miso; | |
353 | gboolean mosi_first; | |
354 | gboolean cs_active; | |
355 | size_t auto_cs_remain; | |
356 | uint8_t mosi_byte, miso_byte; | |
357 | uint8_t mosi_fixed_value; | |
358 | gboolean mosi_is_fixed; | |
359 | uint8_t miso_fixed_value; | |
360 | gboolean miso_is_fixed; | |
361 | }; | |
362 | ||
363 | struct i2c_proto_context_t { | |
364 | size_t ack_remain; | |
365 | }; | |
366 | ||
367 | struct context; | |
368 | ||
369 | struct proto_handler_t { | |
370 | const char *name; | |
371 | struct { | |
372 | uint64_t samplerate; | |
373 | uint64_t bitrate; | |
374 | const char *frame_format; | |
375 | enum textinput_t textinput; | |
376 | } dflt; | |
377 | struct { | |
378 | size_t count; | |
379 | const char **names; | |
380 | } chans; | |
381 | size_t priv_size; | |
382 | int (*check_opts)(struct context *inc); | |
383 | int (*config_frame)(struct context *inc); | |
384 | int (*proc_pseudo)(struct sr_input *in, char *text); | |
385 | int (*proc_value)(struct context *inc, uint32_t value); | |
386 | int (*get_idle_capture)(struct context *inc, | |
387 | size_t *bits, uint8_t *lvls); | |
388 | int (*get_idle_interframe)(struct context *inc, | |
389 | size_t *samples, uint8_t *lvls); | |
390 | }; | |
391 | ||
392 | struct context { | |
393 | /* User provided options. */ | |
394 | struct user_opts_t { | |
395 | uint64_t samplerate; | |
396 | uint64_t bitrate; | |
397 | const char *proto_name; | |
398 | const char *fmt_text; | |
399 | enum textinput_t textinput; | |
400 | } user_opts; | |
401 | /* Derived at runtime. */ | |
402 | struct { | |
403 | uint64_t samplerate; | |
404 | uint64_t bitrate; | |
405 | uint64_t samples_per_bit; | |
406 | char *proto_name; | |
407 | char *fmt_text; | |
408 | enum textinput_t textinput; | |
409 | enum proto_type_t { | |
410 | PROTO_TYPE_NONE, | |
411 | PROTO_TYPE_UART, | |
412 | PROTO_TYPE_SPI, | |
413 | PROTO_TYPE_I2C, | |
414 | PROTO_TYPE_COUNT, | |
415 | } protocol_type; | |
416 | const struct proto_handler_t *prot_hdl; | |
417 | void *prot_priv; | |
418 | union { | |
419 | struct uart_frame_fmt_opts { | |
420 | size_t databit_count; | |
421 | enum { | |
422 | UART_PARITY_NONE, | |
423 | UART_PARITY_ODD, | |
424 | UART_PARITY_EVEN, | |
425 | } parity_type; | |
426 | size_t stopbit_count; | |
427 | gboolean half_stopbit; | |
428 | gboolean inverted; | |
429 | } uart; | |
430 | struct spi_frame_fmt_opts { | |
431 | uint8_t cs_polarity; | |
432 | size_t databit_count; | |
433 | gboolean msb_first; | |
434 | gboolean spi_mode_cpol; | |
435 | gboolean spi_mode_cpha; | |
436 | } spi; | |
437 | struct i2c_frame_fmt_opts { | |
438 | gboolean addr_10bit; | |
439 | } i2c; | |
440 | } frame_format; | |
441 | } curr_opts; | |
442 | /* Module stage. Logic output channels. Session feed. */ | |
443 | gboolean scanned_magic; | |
444 | gboolean has_magic; | |
445 | gboolean has_header; | |
446 | gboolean got_header; | |
447 | gboolean started; | |
448 | gboolean meta_sent; | |
449 | size_t channel_count; | |
450 | const char **channel_names; | |
451 | struct feed_queue_logic *feed_logic; | |
452 | /* | |
453 | * Internal state: Allocated space for a theoretical maximum | |
454 | * bit count. Filled in bit pattern for the current data value. | |
455 | * (Stuffing can result in varying bit counts across frames.) | |
456 | * | |
457 | * Keep the bits' width in sample numbers, as well as the bits' | |
458 | * boundaries relative to the start of the protocol frame's | |
459 | * start. Support a number of logic bits per bit time. | |
460 | * | |
461 | * Implementor's note: Due to development history terminology | |
462 | * might slip here. Strictly speaking it's "waveform sections" | |
463 | * that hold samples for a given number of cycles. "A bit" in | |
464 | * the protocol can occupy multiple of these slots to e.g. have | |
465 | * a synchronous clock, or to present setup and hold phases, | |
466 | * etc. Sample data spans several logic signal traces. You get | |
467 | * the idea ... | |
468 | */ | |
469 | size_t max_frame_bits; /* Reserved. */ | |
470 | size_t top_frame_bits; /* Currently filled. */ | |
471 | struct { | |
472 | size_t mul; | |
473 | size_t div; | |
474 | } *bit_scale; /* Quanta scaling. */ | |
475 | size_t *sample_edges; | |
476 | size_t *sample_widths; | |
477 | uint8_t *sample_levels; /* Sample data, logic traces. */ | |
478 | /* Common support for samples updating by manipulation. */ | |
479 | struct { | |
480 | uint8_t idle_levels; | |
481 | uint8_t curr_levels; | |
482 | } samples; | |
483 | /* Internal state of the input text reader. */ | |
484 | struct { | |
485 | int base; | |
486 | } read_text; | |
487 | /* Manage state across .reset() calls. Robustness. */ | |
488 | struct proto_prev { | |
489 | GSList *sr_channels; | |
490 | GSList *sr_groups; | |
491 | } prev; | |
492 | }; | |
493 | ||
494 | /* {{{ frame bits manipulation, waveform construction */ | |
495 | ||
496 | /* | |
497 | * Primitives to construct waveforms for a protocol frame, by sequencing | |
498 | * samples after data values were seen in the input stream. Individual | |
499 | * protocol handlers will use these common routines. | |
500 | * | |
501 | * The general idea is: The protocol handler's options parser determines | |
502 | * the frame format, and derives the maximum number of time slots needed | |
503 | * to represent the waveform. Slots can scale differintly, proportions | |
504 | * get configured once during initialization. All remaining operation | |
505 | * receives arbitrarily interleaved data values and pseudo comments, uses | |
506 | * the pre-allocated and pre-scaled time slots to construct waveforms, | |
507 | * which then get sent to the session bus as if an acquisition device | |
508 | * had captured wire traffic. For clocked signals the "coarse" timing | |
509 | * should never be an issue. Protocol handlers are free to use as many | |
510 | * time slots per bit time as they please or feel necessary. | |
511 | */ | |
512 | ||
513 | static int alloc_frame_storage(struct context *inc) | |
514 | { | |
515 | size_t bits, alloc; | |
516 | ||
517 | if (!inc) | |
518 | return SR_ERR_ARG; | |
519 | ||
520 | if (!inc->max_frame_bits) | |
521 | return SR_ERR_DATA; | |
522 | ||
523 | inc->top_frame_bits = 0; | |
524 | bits = inc->max_frame_bits; | |
525 | ||
526 | alloc = bits * sizeof(inc->sample_edges[0]); | |
527 | inc->sample_edges = g_malloc0(alloc); | |
528 | alloc = bits * sizeof(inc->sample_widths[0]); | |
529 | inc->sample_widths = g_malloc0(alloc); | |
530 | alloc = bits * sizeof(inc->sample_levels[0]); | |
531 | inc->sample_levels = g_malloc0(alloc); | |
532 | if (!inc->sample_edges || !inc->sample_widths || !inc->sample_levels) | |
533 | return SR_ERR_MALLOC; | |
534 | ||
535 | alloc = bits * sizeof(inc->bit_scale[0]); | |
536 | inc->bit_scale = g_malloc0(alloc); | |
537 | if (!inc->bit_scale) | |
538 | return SR_ERR_MALLOC; | |
539 | ||
540 | return SR_OK; | |
541 | } | |
542 | ||
543 | /* | |
544 | * Assign an equal bit width to all bits in the frame. Derive the width | |
545 | * from the bitrate and the sampelrate. Protocol handlers optionally can | |
546 | * arrange for "odd bit widths" (either fractions, or multiples, or when | |
547 | * desired any rational at all). Think half-bits, or think quanta within | |
548 | * a bit time, depends on the protocol handler really. | |
549 | * | |
550 | * Implementation note: The input module assumes that the position of | |
551 | * odd length bits will never vary during frame construction. The total | |
552 | * length may vary, 'top' can be smaller than 'max' in every iteration. | |
553 | * It is assumed that frames with odd-length bits have constant layout, | |
554 | * and that stuffing protocols have same-width bits. Odd lengths also | |
555 | * can support bit time quanta, while it's assumed that these always use | |
556 | * the same layout for all generated frames. This constraint is kept in | |
557 | * the implementation, until one of the supported protocols genuinely | |
558 | * requires higher flexibility and the involved complexity and runtime | |
559 | * cost of per-samplepoint adjustment. | |
560 | */ | |
561 | static int assign_bit_widths(struct context *inc) | |
562 | { | |
563 | const struct proto_handler_t *handler; | |
564 | int ret; | |
565 | double bit_edge, bit_time, this_bit_time; | |
566 | uint64_t bit_time_int, bit_time_prev, bit_times_total; | |
567 | size_t idx; | |
568 | ||
569 | if (!inc) | |
570 | return SR_ERR_ARG; | |
571 | ||
572 | /* | |
573 | * Run the protocol handler's optional configure routine. | |
574 | * It derives the maximum number of "bit slots" that are needed | |
575 | * to represent a protocol frame's waveform. | |
576 | */ | |
577 | handler = inc->curr_opts.prot_hdl; | |
578 | if (handler && handler->config_frame) { | |
579 | ret = handler->config_frame(inc); | |
580 | if (ret != SR_OK) | |
581 | return ret; | |
582 | } | |
583 | ||
584 | /* Assign bit widths to the protocol frame's bit positions. */ | |
585 | bit_time = inc->curr_opts.samplerate; | |
586 | bit_time /= inc->curr_opts.bitrate; | |
587 | inc->curr_opts.samples_per_bit = bit_time + 0.5; | |
588 | sr_dbg("Samplerate %" PRIu64 ", bitrate %" PRIu64 ".", | |
589 | inc->curr_opts.samplerate, inc->curr_opts.bitrate); | |
590 | sr_dbg("Resulting bit width %.2f samples, int %" PRIu64 ".", | |
591 | bit_time, inc->curr_opts.samples_per_bit); | |
592 | bit_edge = 0.0; | |
593 | bit_time_prev = 0; | |
594 | bit_times_total = 0; | |
595 | for (idx = 0; idx < inc->max_frame_bits; idx++) { | |
596 | this_bit_time = bit_time; | |
597 | if (inc->bit_scale[idx].mul) | |
598 | this_bit_time *= inc->bit_scale[idx].mul; | |
599 | if (inc->bit_scale[idx].div) | |
600 | this_bit_time /= inc->bit_scale[idx].div; | |
601 | bit_edge += this_bit_time; | |
602 | bit_time_int = (uint64_t)(bit_edge + 0.5); | |
603 | inc->sample_edges[idx] = bit_time_int; | |
604 | bit_time_int -= bit_time_prev; | |
605 | inc->sample_widths[idx] = bit_time_int; | |
606 | bit_time_prev = inc->sample_edges[idx]; | |
607 | bit_times_total += bit_time_int; | |
608 | sr_spew("Bit %zu, width %" PRIu64 ".", idx, bit_time_int); | |
609 | } | |
610 | sr_dbg("Maximum waveform width: %zu slots, %.2f / %zu samples.", | |
611 | inc->max_frame_bits, bit_edge, bit_times_total); | |
612 | ||
613 | return SR_OK; | |
614 | } | |
615 | ||
616 | /* Start accumulating the samples for a new part of the waveform. */ | |
617 | static int wave_clear_sequence(struct context *inc) | |
618 | { | |
619 | ||
620 | if (!inc) | |
621 | return SR_ERR_ARG; | |
622 | ||
623 | inc->top_frame_bits = 0; | |
624 | ||
625 | return SR_OK; | |
626 | } | |
627 | ||
628 | /* Append channels' levels to the waveform for another period of samples. */ | |
629 | static int wave_append_pattern(struct context *inc, uint8_t sample) | |
630 | { | |
631 | ||
632 | if (!inc) | |
633 | return SR_ERR_ARG; | |
634 | ||
635 | if (inc->top_frame_bits >= inc->max_frame_bits) | |
636 | return SR_ERR_DATA; | |
637 | ||
638 | inc->sample_levels[inc->top_frame_bits++] = sample; | |
639 | ||
640 | return SR_OK; | |
641 | } | |
642 | ||
643 | /* Initially assign idle levels, start the buffer from idle state. */ | |
644 | static void sample_buffer_preset(struct context *inc, uint8_t idle_sample) | |
645 | { | |
646 | inc->samples.idle_levels = idle_sample; | |
647 | inc->samples.curr_levels = idle_sample; | |
648 | } | |
649 | ||
650 | /* Modify the samples buffer by assigning a given traces state. */ | |
651 | static void sample_buffer_assign(struct context *inc, uint8_t sample) | |
652 | { | |
653 | inc->samples.curr_levels = sample; | |
654 | } | |
655 | ||
656 | /* Modify the samples buffer by changing individual traces. */ | |
657 | static void sample_buffer_modify(struct context *inc, | |
658 | uint8_t set_mask, uint8_t clr_mask) | |
659 | { | |
660 | inc->samples.curr_levels |= set_mask; | |
661 | inc->samples.curr_levels &= ~clr_mask; | |
662 | } | |
663 | ||
664 | static void sample_buffer_raise(struct context *inc, uint8_t bits) | |
665 | { | |
666 | return sample_buffer_modify(inc, bits, 0); | |
667 | } | |
668 | ||
669 | static void sample_buffer_clear(struct context *inc, uint8_t bits) | |
670 | { | |
671 | return sample_buffer_modify(inc, 0, bits); | |
672 | } | |
673 | ||
674 | static void sample_buffer_setclr(struct context *inc, | |
675 | gboolean level, uint8_t mask) | |
676 | { | |
677 | if (level) | |
678 | sample_buffer_raise(inc, mask); | |
679 | else | |
680 | sample_buffer_clear(inc, mask); | |
681 | } | |
682 | ||
683 | static void sample_buffer_toggle(struct context *inc, uint8_t mask) | |
684 | { | |
685 | inc->samples.curr_levels ^= mask; | |
686 | } | |
687 | ||
688 | /* Reset current sample buffer to idle state. */ | |
689 | static void sample_buffer_toidle(struct context *inc) | |
690 | { | |
691 | inc->samples.curr_levels = inc->samples.idle_levels; | |
692 | } | |
693 | ||
694 | /* Append the buffered samples to the waveform memory. */ | |
695 | static int wave_append_buffer(struct context *inc) | |
696 | { | |
697 | return wave_append_pattern(inc, inc->samples.curr_levels); | |
698 | } | |
699 | ||
700 | /* Send idle level before the first generated frame and at end of capture. */ | |
701 | static int send_idle_capture(struct context *inc) | |
702 | { | |
703 | const struct proto_handler_t *handler; | |
704 | size_t count; | |
705 | uint8_t data; | |
706 | int ret; | |
707 | ||
708 | handler = inc->curr_opts.prot_hdl; | |
709 | if (!handler->get_idle_capture) | |
710 | return SR_OK; | |
711 | ||
712 | ret = handler->get_idle_capture(inc, &count, &data); | |
713 | if (ret != SR_OK) | |
714 | return ret; | |
715 | count *= inc->curr_opts.samples_per_bit; | |
29bd62ff GS |
716 | ret = feed_queue_logic_submit_one(inc->feed_logic, &data, count); |
717 | if (ret != SR_OK) | |
718 | return ret; | |
ff7f7f73 GS |
719 | |
720 | return SR_OK; | |
721 | } | |
722 | ||
723 | /* Optionally send idle level between protocol frames. */ | |
724 | static int send_idle_interframe(struct context *inc) | |
725 | { | |
726 | const struct proto_handler_t *handler; | |
727 | size_t count; | |
728 | uint8_t data; | |
729 | int ret; | |
730 | ||
731 | handler = inc->curr_opts.prot_hdl; | |
732 | if (!handler->get_idle_interframe) | |
733 | return SR_OK; | |
734 | ||
735 | ret = handler->get_idle_interframe(inc, &count, &data); | |
736 | if (ret != SR_OK) | |
737 | return ret; | |
29bd62ff GS |
738 | ret = feed_queue_logic_submit_one(inc->feed_logic, &data, count); |
739 | if (ret != SR_OK) | |
740 | return ret; | |
ff7f7f73 GS |
741 | |
742 | return SR_OK; | |
743 | } | |
744 | ||
745 | /* Forward the previously accumulated samples of the waveform. */ | |
746 | static int send_frame(struct sr_input *in) | |
747 | { | |
748 | struct context *inc; | |
749 | size_t count, index; | |
750 | uint8_t data; | |
29bd62ff | 751 | int ret; |
ff7f7f73 GS |
752 | |
753 | inc = in->priv; | |
754 | ||
755 | for (index = 0; index < inc->top_frame_bits; index++) { | |
756 | data = inc->sample_levels[index]; | |
757 | count = inc->sample_widths[index]; | |
29bd62ff GS |
758 | ret = feed_queue_logic_submit_one(inc->feed_logic, |
759 | &data, count); | |
760 | if (ret != SR_OK) | |
761 | return ret; | |
ff7f7f73 GS |
762 | } |
763 | ||
764 | return SR_OK; | |
765 | } | |
766 | ||
767 | /* }}} frame bits manipulation */ | |
768 | /* {{{ UART protocol handler */ | |
769 | ||
770 | enum uart_pin_t { | |
771 | UART_PIN_RXTX, | |
772 | }; | |
773 | ||
774 | #define UART_PINMASK_RXTX (1UL << UART_PIN_RXTX) | |
775 | ||
776 | /* UART specific options and frame format check. */ | |
777 | static int uart_check_opts(struct context *inc) | |
778 | { | |
779 | struct uart_frame_fmt_opts *fmt_opts; | |
780 | const char *fmt_text; | |
781 | char **opts, *opt; | |
782 | size_t opt_count, opt_idx; | |
783 | int ret; | |
784 | unsigned long v; | |
785 | char par_text; | |
786 | char *endp; | |
787 | size_t total_bits; | |
788 | ||
789 | if (!inc) | |
790 | return SR_ERR_ARG; | |
791 | fmt_opts = &inc->curr_opts.frame_format.uart; | |
792 | ||
793 | /* Apply defaults before reading external spec. */ | |
794 | memset(fmt_opts, 0, sizeof(*fmt_opts)); | |
795 | fmt_opts->databit_count = 8; | |
796 | fmt_opts->parity_type = UART_PARITY_NONE; | |
797 | fmt_opts->stopbit_count = 1; | |
798 | fmt_opts->half_stopbit = FALSE; | |
799 | fmt_opts->inverted = FALSE; | |
800 | ||
801 | /* Provide a default UART frame format. */ | |
802 | fmt_text = inc->curr_opts.fmt_text; | |
803 | if (!fmt_text || !*fmt_text) | |
804 | fmt_text = UART_DFLT_FRAMEFMT; | |
805 | sr_dbg("UART frame format: %s.", fmt_text); | |
806 | ||
807 | /* Parse the comma separated list of user provided options. */ | |
808 | opts = g_strsplit_set(fmt_text, ", ", 0); | |
809 | opt_count = g_strv_length(opts); | |
810 | for (opt_idx = 0; opt_idx < opt_count; opt_idx++) { | |
811 | opt = opts[opt_idx]; | |
812 | if (!opt || !*opt) | |
813 | continue; | |
814 | sr_spew("UART format option: %s", opt); | |
815 | /* | |
816 | * Check for specific keywords. Before falling back to | |
817 | * attempting the "8n1" et al interpretation. | |
818 | */ | |
819 | if (strcmp(opt, UART_FORMAT_INVERT) == 0) { | |
820 | fmt_opts->inverted = TRUE; | |
821 | continue; | |
822 | } | |
823 | /* Parse an "8n1", "8e2", "7o1", or similar input spec. */ | |
824 | /* Get the data bits count. */ | |
825 | endp = NULL; | |
826 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
827 | if (ret != SR_OK || !endp) | |
828 | return SR_ERR_DATA; | |
829 | opt = endp; | |
830 | if (v < UART_MIN_DATABITS || v > UART_MAX_DATABITS) | |
831 | return SR_ERR_DATA; | |
832 | fmt_opts->databit_count = v; | |
833 | /* Get the parity type. */ | |
834 | par_text = tolower((int)*opt++); | |
835 | switch (par_text) { | |
836 | case 'n': | |
837 | fmt_opts->parity_type = UART_PARITY_NONE; | |
838 | break; | |
839 | case 'o': | |
840 | fmt_opts->parity_type = UART_PARITY_ODD; | |
841 | break; | |
842 | case 'e': | |
843 | fmt_opts->parity_type = UART_PARITY_EVEN; | |
844 | break; | |
845 | default: | |
846 | return SR_ERR_DATA; | |
847 | } | |
848 | /* Get the stop bits count. Supports half bits too. */ | |
849 | endp = NULL; | |
850 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
851 | if (ret != SR_OK || !endp) | |
852 | return SR_ERR_DATA; | |
853 | opt = endp; | |
854 | if (v > UART_MAX_STOPBITS) | |
855 | return SR_ERR_DATA; | |
856 | fmt_opts->stopbit_count = v; | |
857 | if (g_ascii_strcasecmp(opt, ".5") == 0) { | |
858 | opt += strlen(".5"); | |
859 | fmt_opts->half_stopbit = TRUE; | |
860 | } | |
861 | /* Incomplete consumption of input text is fatal. */ | |
862 | if (*opt) { | |
863 | sr_err("Unprocessed frame format remainder: %s.", opt); | |
864 | return SR_ERR_DATA; | |
865 | } | |
866 | continue; | |
867 | } | |
868 | g_strfreev(opts); | |
869 | ||
870 | /* | |
871 | * Calculate the total number of bit times in the UART frame. | |
872 | * Add a few more bit times to the reserved space. They usually | |
873 | * are not occupied during data transmission, but are useful to | |
874 | * have for special symbols (BREAK, IDLE). | |
875 | */ | |
876 | total_bits = 1; /* START bit, unconditional. */ | |
877 | total_bits += fmt_opts->databit_count; | |
878 | total_bits += (fmt_opts->parity_type != UART_PARITY_NONE) ? 1 : 0; | |
879 | total_bits += fmt_opts->stopbit_count; | |
880 | total_bits += fmt_opts->half_stopbit ? 1 : 0; | |
881 | total_bits += UART_ADD_IDLEBITS; | |
882 | sr_dbg("UART frame: total bits %lu.", total_bits); | |
883 | if (total_bits > UART_MAX_WAVELEN) | |
884 | return SR_ERR_DATA; | |
885 | inc->max_frame_bits = total_bits; | |
886 | ||
887 | return SR_OK; | |
888 | } | |
889 | ||
890 | /* | |
891 | * Configure the frame's bit widths when not identical across the | |
892 | * complete frame. Think half STOP bits. | |
893 | * Preset the sample data for an idle bus. | |
894 | */ | |
895 | static int uart_config_frame(struct context *inc) | |
896 | { | |
897 | struct uart_frame_fmt_opts *fmt_opts; | |
898 | size_t bit_idx; | |
899 | uint8_t sample; | |
900 | ||
901 | if (!inc) | |
902 | return SR_ERR_ARG; | |
903 | fmt_opts = &inc->curr_opts.frame_format.uart; | |
904 | ||
905 | /* | |
906 | * Position after the START bit. Advance over DATA, PARITY and | |
907 | * (full) STOP bits. Then set the trailing STOP bit to half if | |
908 | * needed. Make the trailing IDLE period after a UART frame | |
909 | * wider than regular bit times. Add an even wider IDLE period | |
910 | * which is used for special symbols. | |
911 | */ | |
912 | bit_idx = 1; | |
913 | bit_idx += fmt_opts->databit_count; | |
914 | bit_idx += (fmt_opts->parity_type == UART_PARITY_NONE) ? 0 : 1; | |
915 | bit_idx += fmt_opts->stopbit_count; | |
916 | if (fmt_opts->half_stopbit) { | |
917 | sr_dbg("Setting bit index %zu to half width.", bit_idx); | |
918 | inc->bit_scale[bit_idx].div = 2; | |
919 | bit_idx++; | |
920 | } | |
921 | inc->bit_scale[bit_idx++].mul = 2; | |
922 | inc->bit_scale[bit_idx++].mul = 4; | |
923 | ||
924 | /* Start from idle signal levels (high when not inverted). */ | |
925 | sample = 0; | |
926 | if (!fmt_opts->inverted) | |
927 | sample |= UART_PINMASK_RXTX; | |
928 | sample_buffer_preset(inc, sample); | |
929 | ||
930 | return SR_OK; | |
931 | } | |
932 | ||
933 | /* Create samples for a special UART frame (IDLE, BREAK). */ | |
934 | static int uart_write_special(struct context *inc, uint8_t level) | |
935 | { | |
936 | struct uart_frame_fmt_opts *fmt_opts; | |
937 | int ret; | |
938 | size_t bits; | |
939 | ||
940 | if (!inc) | |
941 | return SR_ERR_ARG; | |
942 | fmt_opts = &inc->curr_opts.frame_format.uart; | |
943 | ||
944 | ret = wave_clear_sequence(inc); | |
945 | if (ret != SR_OK) | |
946 | return ret; | |
947 | ||
948 | /* | |
949 | * Set the same level for all bit slots, covering all of | |
950 | * START and DATA (and PARITY) and STOP. This allows the | |
951 | * simulation of BREAK and IDLE phases. | |
952 | */ | |
953 | if (fmt_opts->inverted) | |
954 | level = !level; | |
955 | sample_buffer_setclr(inc, level, UART_PINMASK_RXTX); | |
956 | bits = 1; /* START */ | |
957 | bits += fmt_opts->databit_count; | |
958 | bits += (fmt_opts->parity_type != UART_PARITY_NONE) ? 1 : 0; | |
959 | bits += fmt_opts->stopbit_count; | |
960 | bits += fmt_opts->half_stopbit ? 1 : 0; | |
961 | while (bits--) { | |
962 | ret = wave_append_buffer(inc); | |
963 | if (ret != SR_OK) | |
964 | return ret; | |
965 | } | |
966 | ||
967 | /* | |
968 | * Force a few more idle bit times. This does not affect a | |
969 | * caller requested IDLE symbol. But helps separate (i.e. | |
970 | * robustly detect) several caller requested BREAK symbols. | |
971 | * Also separates those specials from subsequent data bytes. | |
972 | */ | |
973 | sample_buffer_toidle(inc); | |
974 | bits = UART_ADD_IDLEBITS; | |
975 | while (bits--) { | |
976 | ret = wave_append_buffer(inc); | |
977 | if (ret != SR_OK) | |
978 | return ret; | |
979 | } | |
980 | ||
981 | return SR_OK; | |
982 | } | |
983 | ||
984 | /* Process UART protocol specific pseudo comments. */ | |
985 | static int uart_proc_pseudo(struct sr_input *in, char *line) | |
986 | { | |
987 | struct context *inc; | |
988 | char *word; | |
989 | int ret; | |
990 | ||
991 | inc = in->priv; | |
992 | ||
993 | while (line) { | |
994 | word = sr_text_next_word(line, &line); | |
995 | if (!word) | |
996 | break; | |
997 | if (!*word) | |
998 | continue; | |
999 | if (strcmp(word, UART_PSEUDO_BREAK) == 0) { | |
1000 | ret = uart_write_special(inc, 0); | |
1001 | if (ret != SR_OK) | |
1002 | return ret; | |
1003 | ret = send_frame(in); | |
1004 | if (ret != SR_OK) | |
1005 | return ret; | |
1006 | continue; | |
1007 | } | |
1008 | if (strcmp(word, UART_PSEUDO_IDLE) == 0) { | |
1009 | ret = uart_write_special(inc, 1); | |
1010 | if (ret != SR_OK) | |
1011 | return ret; | |
1012 | ret = send_frame(in); | |
1013 | if (ret != SR_OK) | |
1014 | return ret; | |
1015 | continue; | |
1016 | } | |
1017 | return SR_ERR_DATA; | |
1018 | } | |
1019 | ||
1020 | return SR_OK; | |
1021 | } | |
1022 | ||
1023 | /* | |
1024 | * Create the UART frame's waveform for the given data value. | |
1025 | * | |
1026 | * In theory the protocol handler could setup START and STOP once during | |
1027 | * initialization. But the overhead compares to DATA and PARITY is small. | |
1028 | * And unconditional START/STOP would break the creation of BREAK and | |
1029 | * IDLE frames, or complicate their construction and recovery afterwards. | |
1030 | * A future implementation might as well support UART traffic on multiple | |
1031 | * traces, including interleaved bidirectional communication. So let's | |
1032 | * keep the implementation simple. Execution time is not a priority. | |
1033 | */ | |
1034 | static int uart_proc_value(struct context *inc, uint32_t value) | |
1035 | { | |
1036 | struct uart_frame_fmt_opts *fmt_opts; | |
1037 | int ret; | |
1038 | size_t bits; | |
1039 | int par_bit, data_bit; | |
1040 | ||
1041 | if (!inc) | |
1042 | return SR_ERR_ARG; | |
1043 | fmt_opts = &inc->curr_opts.frame_format.uart; | |
1044 | ||
1045 | ret = wave_clear_sequence(inc); | |
1046 | if (ret != SR_OK) | |
1047 | return ret; | |
1048 | ||
1049 | /* START bit, unconditional, always 0. */ | |
1050 | sample_buffer_clear(inc, UART_PINMASK_RXTX); | |
1051 | if (fmt_opts->inverted) | |
1052 | sample_buffer_toggle(inc, UART_PINMASK_RXTX); | |
1053 | ret = wave_append_buffer(inc); | |
1054 | ||
1055 | /* DATA bits. Track parity here (unconditionally). */ | |
1056 | par_bit = 0; | |
1057 | bits = fmt_opts->databit_count; | |
1058 | while (bits--) { | |
1059 | data_bit = value & 0x01; | |
1060 | value >>= 1; | |
1061 | par_bit ^= data_bit; | |
1062 | if (fmt_opts->inverted) | |
1063 | data_bit = !data_bit; | |
1064 | sample_buffer_setclr(inc, data_bit, UART_PINMASK_RXTX); | |
1065 | ret = wave_append_buffer(inc); | |
1066 | if (ret != SR_OK) | |
1067 | return ret; | |
1068 | } | |
1069 | ||
1070 | /* PARITY bit. Emission is optional. */ | |
1071 | switch (fmt_opts->parity_type) { | |
1072 | case UART_PARITY_ODD: | |
1073 | data_bit = par_bit ? 0 : 1; | |
1074 | bits = 1; | |
1075 | break; | |
1076 | case UART_PARITY_EVEN: | |
1077 | data_bit = par_bit ? 1 : 0; | |
1078 | bits = 1; | |
1079 | break; | |
1080 | default: | |
1081 | data_bit = 0; | |
1082 | bits = 0; | |
1083 | break; | |
1084 | } | |
1085 | if (bits) { | |
1086 | if (fmt_opts->inverted) | |
1087 | data_bit = !data_bit; | |
1088 | sample_buffer_setclr(inc, data_bit, UART_PINMASK_RXTX); | |
1089 | ret = wave_append_buffer(inc); | |
1090 | if (ret != SR_OK) | |
1091 | return ret; | |
1092 | } | |
1093 | ||
1094 | /* STOP bits. Optional. */ | |
1095 | sample_buffer_raise(inc, UART_PINMASK_RXTX); | |
1096 | if (fmt_opts->inverted) | |
1097 | sample_buffer_toggle(inc, UART_PINMASK_RXTX); | |
1098 | bits = fmt_opts->stopbit_count; | |
1099 | bits += fmt_opts->half_stopbit ? 1 : 0; | |
1100 | while (bits--) { | |
1101 | ret = wave_append_buffer(inc); | |
1102 | if (ret != SR_OK) | |
1103 | return ret; | |
1104 | } | |
1105 | ||
1106 | /* | |
1107 | * Force some idle time after the UART frame. | |
1108 | * A little shorter than for special symbols. | |
1109 | */ | |
1110 | sample_buffer_toidle(inc); | |
1111 | bits = UART_ADD_IDLEBITS - 1; | |
1112 | while (bits--) { | |
1113 | ret = wave_append_buffer(inc); | |
1114 | if (ret != SR_OK) | |
1115 | return ret; | |
1116 | } | |
1117 | ||
1118 | return SR_OK; | |
1119 | } | |
1120 | ||
1121 | /* Start/end the logic trace with a few bit times of idle level. */ | |
1122 | static int uart_get_idle_capture(struct context *inc, | |
1123 | size_t *bitcount, uint8_t *sample) | |
1124 | { | |
1125 | ||
1126 | /* Describe a UART frame's length of idle level. */ | |
1127 | if (bitcount) | |
1128 | *bitcount = inc->max_frame_bits; | |
1129 | if (sample) | |
1130 | *sample = inc->samples.idle_levels; | |
1131 | return SR_OK; | |
1132 | } | |
1133 | ||
1134 | /* Arrange for a few samples of idle level between UART frames. */ | |
1135 | static int uart_get_idle_interframe(struct context *inc, | |
1136 | size_t *samplecount, uint8_t *sample) | |
1137 | { | |
1138 | ||
1139 | (void)inc; | |
1140 | ||
1141 | /* | |
1142 | * Regular waveform creation for UART frames already includes | |
1143 | * padding between UART frames. That is why we don't need to | |
1144 | * add extra inter-frame samples. Yet prepare the implementation | |
1145 | * for when we need or want to add a few more idle samples. | |
1146 | */ | |
1147 | if (samplecount) { | |
1148 | *samplecount = inc->curr_opts.samples_per_bit; | |
1149 | *samplecount *= 0; | |
1150 | } | |
1151 | if (sample) | |
1152 | *sample = inc->samples.idle_levels; | |
1153 | return SR_OK; | |
1154 | } | |
1155 | ||
1156 | /* }}} UART protocol handler */ | |
1157 | /* {{{ SPI protocol handler */ | |
1158 | ||
1159 | enum spi_pin_t { | |
1160 | SPI_PIN_SCK, | |
1161 | SPI_PIN_MISO, | |
1162 | SPI_PIN_MOSI, | |
1163 | SPI_PIN_CS, | |
1164 | SPI_PIN_COUNT, | |
1165 | }; | |
1166 | ||
1167 | #define SPI_PINMASK_SCK (1UL << SPI_PIN_SCK) | |
1168 | #define SPI_PINMASK_MISO (1UL << SPI_PIN_MISO) | |
1169 | #define SPI_PINMASK_MOSI (1UL << SPI_PIN_MOSI) | |
1170 | #define SPI_PINMASK_CS (1UL << SPI_PIN_CS) | |
1171 | ||
1172 | /* "Forget" data which was seen before. */ | |
1173 | static void spi_value_discard_prev_data(struct context *inc) | |
1174 | { | |
1175 | struct spi_proto_context_t *incs; | |
1176 | ||
1177 | incs = inc->curr_opts.prot_priv; | |
1178 | incs->has_mosi = !incs->needs_mosi; | |
1179 | incs->has_miso = !incs->needs_miso; | |
1180 | incs->mosi_byte = 0; | |
1181 | incs->miso_byte = 0; | |
1182 | } | |
1183 | ||
1184 | /* Check whether all required values for the byte time were seen. */ | |
1185 | static gboolean spi_value_is_bytes_complete(struct context *inc) | |
1186 | { | |
1187 | struct spi_proto_context_t *incs; | |
1188 | ||
1189 | incs = inc->curr_opts.prot_priv; | |
1190 | ||
1191 | return incs->has_mosi && incs->has_miso; | |
1192 | } | |
1193 | ||
1194 | /* Arrange for data reception before waveform emission. */ | |
1195 | static void spi_pseudo_data_order(struct context *inc, | |
1196 | gboolean needs_mosi, gboolean needs_miso, gboolean mosi_first) | |
1197 | { | |
1198 | struct spi_proto_context_t *incs; | |
1199 | ||
1200 | incs = inc->curr_opts.prot_priv; | |
1201 | ||
1202 | incs->needs_mosi = needs_mosi; | |
1203 | incs->needs_miso = needs_miso; | |
1204 | incs->mosi_first = mosi_first; | |
1205 | if (needs_mosi) | |
1206 | incs->mosi_is_fixed = FALSE; | |
1207 | if (needs_miso) | |
1208 | incs->miso_is_fixed = FALSE; | |
1209 | spi_value_discard_prev_data(inc); | |
1210 | } | |
1211 | ||
1212 | static void spi_pseudo_mosi_fixed(struct context *inc, uint8_t v) | |
1213 | { | |
1214 | struct spi_proto_context_t *incs; | |
1215 | ||
1216 | incs = inc->curr_opts.prot_priv; | |
1217 | ||
1218 | incs->mosi_fixed_value = v; | |
1219 | incs->mosi_is_fixed = TRUE; | |
1220 | } | |
1221 | ||
1222 | static void spi_pseudo_miso_fixed(struct context *inc, uint8_t v) | |
1223 | { | |
1224 | struct spi_proto_context_t *incs; | |
1225 | ||
1226 | incs = inc->curr_opts.prot_priv; | |
1227 | ||
1228 | incs->miso_fixed_value = v; | |
1229 | incs->miso_is_fixed = TRUE; | |
1230 | } | |
1231 | ||
1232 | /* Explicit CS control. Arrange for next CS level, track state to keep it. */ | |
1233 | static void spi_pseudo_select_control(struct context *inc, gboolean cs_active) | |
1234 | { | |
1235 | struct spi_frame_fmt_opts *fmt_opts; | |
1236 | struct spi_proto_context_t *incs; | |
1237 | uint8_t cs_level, sck_level; | |
1238 | ||
1239 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1240 | incs = inc->curr_opts.prot_priv; | |
1241 | ||
1242 | /* Track current "CS active" state. */ | |
1243 | incs->cs_active = cs_active; | |
1244 | incs->auto_cs_remain = 0; | |
1245 | ||
1246 | /* Derive current "CS pin level". Update sample data buffer. */ | |
1247 | cs_level = 1 - fmt_opts->cs_polarity; | |
1248 | if (incs->cs_active) | |
1249 | cs_level = fmt_opts->cs_polarity; | |
1250 | sample_buffer_setclr(inc, cs_level, SPI_PINMASK_CS); | |
1251 | ||
1252 | /* Derive the idle "SCK level" from the SPI mode's CPOL. */ | |
1253 | sck_level = fmt_opts->spi_mode_cpol ? 1 : 0; | |
1254 | sample_buffer_setclr(inc, sck_level, SPI_PINMASK_SCK); | |
1255 | } | |
1256 | ||
1257 | /* Arrange for automatic CS release after transfer length. Starts the phase. */ | |
1258 | static void spi_pseudo_auto_select(struct context *inc, size_t length) | |
1259 | { | |
1260 | struct spi_frame_fmt_opts *fmt_opts; | |
1261 | struct spi_proto_context_t *incs; | |
1262 | uint8_t cs_level; | |
1263 | ||
1264 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1265 | incs = inc->curr_opts.prot_priv; | |
1266 | ||
1267 | /* Track current "CS active" state. */ | |
1268 | incs->cs_active = TRUE; | |
1269 | incs->auto_cs_remain = length; | |
1270 | ||
1271 | /* Derive current "CS pin level". Update sample data buffer. */ | |
1272 | cs_level = 1 - fmt_opts->cs_polarity; | |
1273 | if (incs->cs_active) | |
1274 | cs_level = fmt_opts->cs_polarity; | |
1275 | sample_buffer_setclr(inc, cs_level, SPI_PINMASK_CS); | |
1276 | } | |
1277 | ||
1278 | /* Check for automatic CS release. Decrements, yields result. No action here. */ | |
1279 | static gboolean spi_auto_select_ends(struct context *inc) | |
1280 | { | |
1281 | struct spi_proto_context_t *incs; | |
1282 | ||
1283 | incs = inc->curr_opts.prot_priv; | |
1284 | if (!incs->auto_cs_remain) | |
1285 | return FALSE; | |
1286 | ||
1287 | incs->auto_cs_remain--; | |
1288 | if (incs->auto_cs_remain) | |
1289 | return FALSE; | |
1290 | ||
1291 | /* | |
1292 | * DON'T release CS yet. The last data is yet to get sent. | |
1293 | * Keep the current "CS pin level", but tell the caller that | |
1294 | * CS will be released after transmission of that last data. | |
1295 | */ | |
1296 | return TRUE; | |
1297 | } | |
1298 | ||
1299 | /* Update for automatic CS release after last data was sent. */ | |
1300 | static void spi_auto_select_update(struct context *inc) | |
1301 | { | |
1302 | struct spi_frame_fmt_opts *fmt_opts; | |
1303 | struct spi_proto_context_t *incs; | |
1304 | uint8_t cs_level; | |
1305 | ||
1306 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1307 | incs = inc->curr_opts.prot_priv; | |
1308 | ||
1309 | /* Track current "CS active" state. */ | |
1310 | incs->cs_active = FALSE; | |
1311 | incs->auto_cs_remain = 0; | |
1312 | ||
1313 | /* Derive current "CS pin level". Map to bits pattern. */ | |
1314 | cs_level = 1 - fmt_opts->cs_polarity; | |
1315 | sample_buffer_setclr(inc, cs_level, SPI_PINMASK_CS); | |
1316 | } | |
1317 | ||
1318 | /* | |
1319 | * Create the waveforms for one SPI byte. Also cover idle periods: | |
1320 | * Dummy/padding bytes within a frame with clock. Idle lines outside | |
1321 | * of frames without clock edges. Optional automatic CS release with | |
1322 | * resulting inter-frame gap. | |
1323 | */ | |
1324 | static int spi_write_frame_patterns(struct context *inc, | |
1325 | gboolean idle, gboolean cs_release) | |
1326 | { | |
1327 | struct spi_proto_context_t *incs; | |
1328 | struct spi_frame_fmt_opts *fmt_opts; | |
1329 | int ret; | |
1330 | uint8_t mosi_bit, miso_bit; | |
1331 | size_t bits; | |
1332 | ||
1333 | if (!inc) | |
1334 | return SR_ERR_ARG; | |
1335 | incs = inc->curr_opts.prot_priv; | |
1336 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1337 | ||
1338 | /* Apply fixed values before drawing the waveform. */ | |
1339 | if (incs->mosi_is_fixed) | |
1340 | incs->mosi_byte = incs->mosi_fixed_value; | |
1341 | if (incs->miso_is_fixed) | |
1342 | incs->miso_byte = incs->miso_fixed_value; | |
1343 | ||
1344 | ret = wave_clear_sequence(inc); | |
1345 | if (ret != SR_OK) | |
1346 | return ret; | |
1347 | ||
1348 | /* Provide two samples with idle SCK and current CS. */ | |
1349 | ret = wave_append_buffer(inc); | |
1350 | if (ret != SR_OK) | |
1351 | return ret; | |
1352 | ret = wave_append_buffer(inc); | |
1353 | if (ret != SR_OK) | |
1354 | return ret; | |
1355 | ||
1356 | /* | |
1357 | * Provide two samples per DATABIT time slot. Keep CS as is. | |
1358 | * Toggle SCK according to CPHA specs. Shift out MOSI and MISO | |
1359 | * in the configured order. | |
1360 | * | |
1361 | * Force dummy MOSI/MISO bits for idle bytes within a frame. | |
1362 | * Skip SCK toggling for idle "frames" outside of active CS. | |
1363 | */ | |
1364 | bits = fmt_opts->databit_count; | |
1365 | while (bits--) { | |
1366 | /* | |
1367 | * First half-period. Provide next DATABIT values. | |
1368 | * Toggle SCK here when CPHA is set. | |
1369 | */ | |
1370 | if (fmt_opts->msb_first) { | |
1371 | mosi_bit = incs->mosi_byte & 0x80; | |
1372 | miso_bit = incs->miso_byte & 0x80; | |
1373 | incs->mosi_byte <<= 1; | |
1374 | incs->miso_byte <<= 1; | |
1375 | } else { | |
1376 | mosi_bit = incs->mosi_byte & 0x01; | |
1377 | miso_bit = incs->miso_byte & 0x01; | |
1378 | incs->mosi_byte >>= 1; | |
1379 | incs->miso_byte >>= 1; | |
1380 | } | |
1381 | if (incs->cs_active && !idle) { | |
1382 | sample_buffer_setclr(inc, mosi_bit, SPI_PINMASK_MOSI); | |
1383 | sample_buffer_setclr(inc, miso_bit, SPI_PINMASK_MISO); | |
1384 | } | |
1385 | if (fmt_opts->spi_mode_cpha && incs->cs_active) | |
1386 | sample_buffer_toggle(inc, SPI_PINMASK_SCK); | |
1387 | ret = wave_append_buffer(inc); | |
1388 | if (ret != SR_OK) | |
1389 | return ret; | |
1390 | /* Second half-period. Keep DATABIT, toggle SCK. */ | |
1391 | if (incs->cs_active) | |
1392 | sample_buffer_toggle(inc, SPI_PINMASK_SCK); | |
1393 | ret = wave_append_buffer(inc); | |
1394 | if (ret != SR_OK) | |
1395 | return ret; | |
1396 | /* Toggle SCK again unless done above due to CPHA. */ | |
1397 | if (!fmt_opts->spi_mode_cpha && incs->cs_active) | |
1398 | sample_buffer_toggle(inc, SPI_PINMASK_SCK); | |
1399 | } | |
1400 | ||
1401 | /* | |
1402 | * Hold the waveform for another sample period. Happens to | |
1403 | * also communicate the most recent SCK pin level. | |
1404 | * | |
1405 | * Optionally auto-release the CS signal after sending the | |
1406 | * last data byte. Update the CS trace's level. Add another | |
1407 | * (long) bit slot to present an inter-frame gap. | |
1408 | */ | |
1409 | ret = wave_append_buffer(inc); | |
1410 | if (ret != SR_OK) | |
1411 | return ret; | |
1412 | if (cs_release) | |
1413 | spi_auto_select_update(inc); | |
1414 | ret = wave_append_buffer(inc); | |
1415 | if (ret != SR_OK) | |
1416 | return ret; | |
1417 | if (cs_release) { | |
1418 | ret = wave_append_buffer(inc); | |
1419 | if (ret != SR_OK) | |
1420 | return ret; | |
1421 | } | |
1422 | ||
1423 | return SR_OK; | |
1424 | } | |
1425 | ||
1426 | /* SPI specific options and frame format check. */ | |
1427 | static int spi_check_opts(struct context *inc) | |
1428 | { | |
1429 | struct spi_frame_fmt_opts *fmt_opts; | |
1430 | const char *fmt_text; | |
1431 | char **opts, *opt; | |
1432 | size_t opt_count, opt_idx; | |
1433 | int ret; | |
1434 | unsigned long v; | |
1435 | char *endp; | |
1436 | size_t total_bits; | |
1437 | ||
1438 | if (!inc) | |
1439 | return SR_ERR_ARG; | |
1440 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1441 | ||
1442 | /* Setup defaults before reading external specs. */ | |
1443 | fmt_opts->cs_polarity = 0; | |
1444 | fmt_opts->databit_count = SPI_MIN_DATABITS; | |
1445 | fmt_opts->msb_first = TRUE; | |
1446 | fmt_opts->spi_mode_cpol = FALSE; | |
1447 | fmt_opts->spi_mode_cpha = FALSE; | |
1448 | ||
1449 | /* Provide a default SPI frame format. */ | |
1450 | fmt_text = inc->curr_opts.fmt_text; | |
1451 | if (!fmt_text || !*fmt_text) | |
1452 | fmt_text = SPI_DFLT_FRAMEFMT; | |
1453 | sr_dbg("SPI frame format: %s.", fmt_text); | |
1454 | ||
1455 | /* Accept comma separated key=value pairs of specs. */ | |
1456 | opts = g_strsplit_set(fmt_text, ", ", 0); | |
1457 | opt_count = g_strv_length(opts); | |
1458 | for (opt_idx = 0; opt_idx < opt_count; opt_idx++) { | |
1459 | opt = opts[opt_idx]; | |
1460 | if (!opt || !*opt) | |
1461 | continue; | |
1462 | sr_spew("SPI format option: %s.", opt); | |
1463 | if (strcmp(opt, SPI_FORMAT_CS_LOW) == 0) { | |
1464 | sr_spew("SPI chip select: low."); | |
1465 | fmt_opts->cs_polarity = 0; | |
1466 | continue; | |
1467 | } | |
1468 | if (strcmp(opt, SPI_FORMAT_CS_HIGH) == 0) { | |
1469 | sr_spew("SPI chip select: high."); | |
1470 | fmt_opts->cs_polarity = 1; | |
1471 | continue; | |
1472 | } | |
1473 | if (g_str_has_prefix(opt, SPI_FORMAT_DATA_BITS)) { | |
1474 | opt += strlen(SPI_FORMAT_DATA_BITS); | |
1475 | endp = NULL; | |
1476 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
1477 | if (ret != SR_OK) | |
1478 | return ret; | |
1479 | if (!endp || *endp) | |
1480 | return SR_ERR_ARG; | |
1481 | sr_spew("SPI word size: %lu.", v); | |
1482 | if (v < SPI_MIN_DATABITS || v > SPI_MAX_DATABITS) | |
1483 | return SR_ERR_ARG; | |
1484 | fmt_opts->databit_count = v; | |
1485 | continue; | |
1486 | } | |
1487 | if (g_str_has_prefix(opt, SPI_FORMAT_SPI_MODE)) { | |
1488 | opt += strlen(SPI_FORMAT_SPI_MODE); | |
1489 | endp = NULL; | |
1490 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
1491 | if (ret != SR_OK) | |
1492 | return ret; | |
1493 | if (!endp || *endp) | |
1494 | return SR_ERR_ARG; | |
1495 | sr_spew("SPI mode: %lu.", v); | |
1496 | if (v > 3) | |
1497 | return SR_ERR_ARG; | |
1498 | fmt_opts->spi_mode_cpol = v & (1UL << 1); | |
1499 | fmt_opts->spi_mode_cpha = v & (1UL << 0); | |
1500 | continue; | |
1501 | } | |
1502 | if (g_str_has_prefix(opt, SPI_FORMAT_MODE_CPOL)) { | |
1503 | opt += strlen(SPI_FORMAT_MODE_CPOL); | |
1504 | endp = NULL; | |
1505 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
1506 | if (ret != SR_OK) | |
1507 | return ret; | |
1508 | if (!endp || *endp) | |
1509 | return SR_ERR_ARG; | |
1510 | sr_spew("SPI cpol: %lu.", v); | |
1511 | if (v > 1) | |
1512 | return SR_ERR_ARG; | |
1513 | fmt_opts->spi_mode_cpol = !!v; | |
1514 | continue; | |
1515 | } | |
1516 | if (g_str_has_prefix(opt, SPI_FORMAT_MODE_CPHA)) { | |
1517 | opt += strlen(SPI_FORMAT_MODE_CPHA); | |
1518 | endp = NULL; | |
1519 | ret = sr_atoul_base(opt, &v, &endp, 10); | |
1520 | if (ret != SR_OK) | |
1521 | return ret; | |
1522 | if (!endp || *endp) | |
1523 | return SR_ERR_ARG; | |
1524 | sr_spew("SPI cpha: %lu.", v); | |
1525 | if (v > 1) | |
1526 | return SR_ERR_ARG; | |
1527 | fmt_opts->spi_mode_cpha = !!v; | |
1528 | continue; | |
1529 | } | |
1530 | if (strcmp(opt, SPI_FORMAT_MSB_FIRST) == 0) { | |
1531 | sr_spew("SPI endianess: MSB first."); | |
1532 | fmt_opts->msb_first = 1; | |
1533 | continue; | |
1534 | } | |
1535 | if (strcmp(opt, SPI_FORMAT_LSB_FIRST) == 0) { | |
1536 | sr_spew("SPI endianess: LSB first."); | |
1537 | fmt_opts->msb_first = 0; | |
1538 | continue; | |
1539 | } | |
1540 | return SR_ERR_ARG; | |
1541 | } | |
1542 | g_strfreev(opts); | |
1543 | ||
1544 | /* | |
1545 | * Get the total bit count. Add slack for CS control, and to | |
1546 | * visually separate bytes in frames. Multiply data bit count | |
1547 | * for the creation of two clock half-periods. | |
1548 | */ | |
1549 | total_bits = 2; | |
1550 | total_bits += 2 * fmt_opts->databit_count; | |
1551 | total_bits += 3; | |
1552 | ||
1553 | sr_dbg("SPI frame: total bits %lu.", total_bits); | |
1554 | if (total_bits > SPI_MAX_WAVELEN) | |
1555 | return SR_ERR_DATA; | |
1556 | inc->max_frame_bits = total_bits; | |
1557 | ||
1558 | return SR_OK; | |
1559 | } | |
1560 | ||
1561 | /* | |
1562 | * Setup half-width slots for the two halves of a DATABIT time. Keep | |
1563 | * the "decoration" (CS control) at full width. Setup a rather long | |
1564 | * last slot for potential inter-frame gaps. | |
1565 | * | |
1566 | * Preset CS and SCK from their idle levels according to the frame format | |
1567 | * configuration. So that idle times outside of SPI transfers are covered | |
1568 | * with simple logic despite the protocol's flexibility. | |
1569 | */ | |
1570 | static int spi_config_frame(struct context *inc) | |
1571 | { | |
1572 | struct spi_frame_fmt_opts *fmt_opts; | |
1573 | size_t bit_idx, bit_count; | |
1574 | ||
1575 | if (!inc) | |
1576 | return SR_ERR_ARG; | |
1577 | fmt_opts = &inc->curr_opts.frame_format.spi; | |
1578 | ||
1579 | /* Configure DATABIT positions for half width (for clock period). */ | |
1580 | bit_idx = 2; | |
1581 | bit_count = fmt_opts->databit_count; | |
1582 | while (bit_count--) { | |
1583 | inc->bit_scale[bit_idx + 0].div = 2; | |
1584 | inc->bit_scale[bit_idx + 1].div = 2; | |
1585 | bit_idx += 2; | |
1586 | } | |
1587 | bit_idx += 2; | |
1588 | inc->bit_scale[bit_idx].mul = fmt_opts->databit_count; | |
1589 | ||
1590 | /* | |
1591 | * Seed the protocol handler's internal state before seeing | |
1592 | * first data values. To properly cover idle periods, and to | |
1593 | * operate correctly in the absence of pseudo comments. | |
1594 | * | |
1595 | * Use internal helpers for sample data initialization. Then | |
1596 | * grab the resulting pin levels as the idle state. | |
1597 | */ | |
1598 | spi_value_discard_prev_data(inc); | |
1599 | spi_pseudo_data_order(inc, TRUE, TRUE, TRUE); | |
1600 | spi_pseudo_select_control(inc, FALSE); | |
1601 | sample_buffer_preset(inc, inc->samples.curr_levels); | |
1602 | ||
1603 | return SR_OK; | |
1604 | } | |
1605 | ||
1606 | /* | |
1607 | * Process protocol dependent pseudo comments. Can affect future frame | |
1608 | * construction and submission, or can immediately emit "inter frame" | |
1609 | * bit patterns like chip select control. | |
1610 | */ | |
1611 | static int spi_proc_pseudo(struct sr_input *in, char *line) | |
1612 | { | |
1613 | struct context *inc; | |
1614 | char *word, *endp; | |
1615 | int ret; | |
1616 | unsigned long v; | |
1617 | ||
1618 | inc = in->priv; | |
1619 | ||
1620 | while (line) { | |
1621 | word = sr_text_next_word(line, &line); | |
1622 | if (!word) | |
1623 | break; | |
1624 | if (!*word) | |
1625 | continue; | |
1626 | if (strcmp(word, SPI_PSEUDO_MOSI_ONLY) == 0) { | |
1627 | sr_spew("SPI pseudo: MOSI only"); | |
1628 | spi_pseudo_data_order(inc, TRUE, FALSE, TRUE); | |
1629 | continue; | |
1630 | } | |
1631 | if (g_str_has_prefix(word, SPI_PSEUDO_MOSI_FIXED)) { | |
1632 | word += strlen(SPI_PSEUDO_MOSI_FIXED); | |
1633 | endp = NULL; | |
1634 | ret = sr_atoul_base(word, &v, &endp, inc->read_text.base); | |
1635 | if (ret != SR_OK) | |
1636 | return ret; | |
1637 | if (!endp || *endp) | |
1638 | return SR_ERR_ARG; | |
1639 | sr_spew("SPI pseudo: MOSI fixed %lu", v); | |
1640 | spi_pseudo_mosi_fixed(inc, v); | |
1641 | continue; | |
1642 | } | |
1643 | if (strcmp(word, SPI_PSEUDO_MISO_ONLY) == 0) { | |
1644 | sr_spew("SPI pseudo: MISO only"); | |
1645 | spi_pseudo_data_order(inc, FALSE, TRUE, FALSE); | |
1646 | continue; | |
1647 | } | |
1648 | if (g_str_has_prefix(word, SPI_PSEUDO_MISO_FIXED)) { | |
1649 | word += strlen(SPI_PSEUDO_MISO_FIXED); | |
1650 | endp = NULL; | |
1651 | ret = sr_atoul_base(word, &v, &endp, inc->read_text.base); | |
1652 | if (ret != SR_OK) | |
1653 | return ret; | |
1654 | if (!endp || *endp) | |
1655 | return SR_ERR_ARG; | |
1656 | sr_spew("SPI pseudo: MISO fixed %lu", v); | |
1657 | spi_pseudo_miso_fixed(inc, v); | |
1658 | continue; | |
1659 | } | |
1660 | if (strcmp(word, SPI_PSEUDO_MOSI_MISO) == 0) { | |
1661 | sr_spew("SPI pseudo: MOSI then MISO"); | |
1662 | spi_pseudo_data_order(inc, TRUE, TRUE, TRUE); | |
1663 | continue; | |
1664 | } | |
1665 | if (strcmp(word, SPI_PSEUDO_MISO_MOSI) == 0) { | |
1666 | sr_spew("SPI pseudo: MISO then MOSI"); | |
1667 | spi_pseudo_data_order(inc, TRUE, TRUE, FALSE); | |
1668 | continue; | |
1669 | } | |
1670 | if (strcmp(word, SPI_PSEUDO_CS_ASSERT) == 0) { | |
1671 | sr_spew("SPI pseudo: CS assert"); | |
1672 | spi_pseudo_select_control(inc, TRUE); | |
1673 | continue; | |
1674 | } | |
1675 | if (strcmp(word, SPI_PSEUDO_CS_RELEASE) == 0) { | |
1676 | sr_spew("SPI pseudo: CS release"); | |
1677 | /* Release CS. Force IDLE to display the pin change. */ | |
1678 | spi_pseudo_select_control(inc, FALSE); | |
1679 | ret = spi_write_frame_patterns(inc, TRUE, FALSE); | |
1680 | if (ret != SR_OK) | |
1681 | return ret; | |
1682 | ret = send_frame(in); | |
1683 | if (ret != SR_OK) | |
1684 | return ret; | |
1685 | continue; | |
1686 | } | |
1687 | if (g_str_has_prefix(word, SPI_PSEUDO_CS_NEXT)) { | |
1688 | word += strlen(SPI_PSEUDO_CS_NEXT); | |
1689 | endp = NULL; | |
1690 | ret = sr_atoul_base(word, &v, &endp, 0); | |
1691 | if (ret != SR_OK) | |
1692 | return ret; | |
1693 | if (!endp || *endp) | |
1694 | return SR_ERR_ARG; | |
1695 | sr_spew("SPI pseudo: CS auto next %lu", v); | |
1696 | spi_pseudo_auto_select(inc, v); | |
1697 | continue; | |
1698 | } | |
1699 | if (strcmp(word, SPI_PSEUDO_IDLE) == 0) { | |
1700 | sr_spew("SPI pseudo: idle"); | |
1701 | ret = spi_write_frame_patterns(inc, TRUE, FALSE); | |
1702 | if (ret != SR_OK) | |
1703 | return ret; | |
1704 | ret = send_frame(in); | |
1705 | if (ret != SR_OK) | |
1706 | return ret; | |
1707 | continue; | |
1708 | } | |
1709 | return SR_ERR_DATA; | |
1710 | } | |
1711 | ||
1712 | return SR_OK; | |
1713 | } | |
1714 | ||
1715 | /* | |
1716 | * Create the frame's waveform for the given data value. For bidirectional | |
1717 | * communication multiple routine invocations accumulate data bits, while | |
1718 | * the last invocation completes the frame preparation. | |
1719 | */ | |
1720 | static int spi_proc_value(struct context *inc, uint32_t value) | |
1721 | { | |
1722 | struct spi_proto_context_t *incs; | |
1723 | gboolean taken; | |
1724 | int ret; | |
1725 | gboolean auto_cs_end; | |
1726 | ||
1727 | if (!inc) | |
1728 | return SR_ERR_ARG; | |
1729 | incs = inc->curr_opts.prot_priv; | |
1730 | ||
1731 | /* | |
1732 | * Discard previous data when we get here after having completed | |
1733 | * a previous frame. This roundtrip from filling in to clearing | |
1734 | * is required to have the caller emit the waveform that we have | |
1735 | * constructed after receiving data values. | |
1736 | */ | |
1737 | if (spi_value_is_bytes_complete(inc)) { | |
1738 | sr_spew("SPI value: discarding previous data"); | |
1739 | spi_value_discard_prev_data(inc); | |
1740 | } | |
1741 | ||
1742 | /* | |
1743 | * Consume the caller provided value. Apply data in the order | |
1744 | * that was configured before. | |
1745 | */ | |
1746 | taken = FALSE; | |
1747 | if (!taken && incs->mosi_first && !incs->has_mosi) { | |
1748 | sr_spew("SPI value: grabbing MOSI value"); | |
1749 | incs->mosi_byte = value & 0xff; | |
1750 | incs->has_mosi = TRUE; | |
1751 | taken = TRUE; | |
1752 | } | |
1753 | if (!taken && !incs->has_miso) { | |
1754 | sr_spew("SPI value: grabbing MISO value"); | |
1755 | incs->miso_byte = value & 0xff; | |
1756 | incs->has_miso = TRUE; | |
1757 | } | |
1758 | if (!taken && !incs->mosi_first && !incs->has_mosi) { | |
1759 | sr_spew("SPI value: grabbing MOSI value"); | |
1760 | incs->mosi_byte = value & 0xff; | |
1761 | incs->has_mosi = TRUE; | |
1762 | taken = TRUE; | |
1763 | } | |
1764 | ||
1765 | /* | |
1766 | * Generate the waveform when all data values in a byte time | |
1767 | * were seen (all MOSI and MISO including their being optional | |
1768 | * or fixed values). | |
1769 | * | |
1770 | * Optionally automatically release CS after a given number of | |
1771 | * data bytes, when requested by the input stream. | |
1772 | */ | |
1773 | if (!spi_value_is_bytes_complete(inc)) { | |
1774 | sr_spew("SPI value: need more values"); | |
1775 | return +1; | |
1776 | } | |
1777 | auto_cs_end = spi_auto_select_ends(inc); | |
1778 | sr_spew("SPI value: frame complete, drawing, auto CS %d", auto_cs_end); | |
1779 | ret = spi_write_frame_patterns(inc, FALSE, auto_cs_end); | |
1780 | if (ret != SR_OK) | |
1781 | return ret; | |
1782 | return 0; | |
1783 | } | |
1784 | ||
1785 | /* Start/end the logic trace with a few bit times of idle level. */ | |
1786 | static int spi_get_idle_capture(struct context *inc, | |
1787 | size_t *bitcount, uint8_t *sample) | |
1788 | { | |
1789 | ||
1790 | /* Describe one byte time of idle level. */ | |
1791 | if (bitcount) | |
1792 | *bitcount = inc->max_frame_bits; | |
1793 | if (sample) | |
1794 | *sample = inc->samples.idle_levels; | |
1795 | return SR_OK; | |
1796 | } | |
1797 | ||
1798 | /* Arrange for a few samples of idle level between UART frames. */ | |
1799 | static int spi_get_idle_interframe(struct context *inc, | |
1800 | size_t *samplecount, uint8_t *sample) | |
1801 | { | |
1802 | ||
1803 | /* Describe four bit times, re-use most recent pin levels. */ | |
1804 | if (samplecount) { | |
1805 | *samplecount = inc->curr_opts.samples_per_bit; | |
1806 | *samplecount *= 4; | |
1807 | } | |
1808 | if (sample) | |
1809 | *sample = inc->samples.curr_levels; | |
1810 | return SR_OK; | |
1811 | } | |
1812 | ||
1813 | /* }}} SPI protocol handler */ | |
1814 | /* {{{ I2C protocol handler */ | |
1815 | ||
1816 | enum i2c_pin_t { | |
1817 | I2C_PIN_SCL, | |
1818 | I2C_PIN_SDA, | |
1819 | I2C_PIN_COUNT, | |
1820 | }; | |
1821 | ||
1822 | #define I2C_PINMASK_SCL (1UL << I2C_PIN_SCL) | |
1823 | #define I2C_PINMASK_SDA (1UL << I2C_PIN_SDA) | |
1824 | ||
1825 | /* Arrange for automatic ACK for a given number of data bytes. */ | |
1826 | static void i2c_auto_ack_start(struct context *inc, size_t count) | |
1827 | { | |
1828 | struct i2c_proto_context_t *incs; | |
1829 | ||
1830 | incs = inc->curr_opts.prot_priv; | |
1831 | incs->ack_remain = count; | |
1832 | } | |
1833 | ||
1834 | /* Check whether automatic ACK is still applicable. Decrements. */ | |
1835 | static gboolean i2c_auto_ack_avail(struct context *inc) | |
1836 | { | |
1837 | struct i2c_proto_context_t *incs; | |
1838 | ||
1839 | incs = inc->curr_opts.prot_priv; | |
1840 | if (!incs->ack_remain) | |
1841 | return FALSE; | |
1842 | ||
1843 | if (incs->ack_remain--) | |
1844 | return TRUE; | |
1845 | return FALSE; | |
1846 | } | |
1847 | ||
1848 | /* Occupy the slots where START/STOP would be. Keep current levels. */ | |
1849 | static int i2c_write_nothing(struct context *inc) | |
1850 | { | |
1851 | size_t reps; | |
1852 | int ret; | |
1853 | ||
1854 | reps = I2C_BITTIME_QUANTA; | |
1855 | while (reps--) { | |
1856 | ret = wave_append_buffer(inc); | |
1857 | if (ret != SR_OK) | |
1858 | return ret; | |
1859 | } | |
1860 | ||
1861 | return SR_OK; | |
1862 | } | |
1863 | ||
1864 | /* | |
1865 | * Construct a START symbol. Occupy a full bit time in the waveform. | |
1866 | * Can also be used as REPEAT START due to its conservative signalling. | |
1867 | * | |
1868 | * Definition of START: Falling SDA while SCL is high. | |
1869 | * Repeated START: A START without a preceeding STOP. | |
1870 | */ | |
1871 | static int i2c_write_start(struct context *inc) | |
1872 | { | |
1873 | int ret; | |
1874 | ||
1875 | /* | |
1876 | * Important! Assumes that either SDA and SCL already are | |
1877 | * high (true when we come here from an idle bus). Or that | |
1878 | * SCL already is low before SDA potentially changes (this | |
1879 | * is true for preceeding START or REPEAT START or DATA BIT | |
1880 | * symbols). | |
1881 | * | |
1882 | * Implementation detail: This START implementation can be | |
1883 | * used for REPEAT START as well. The signalling sequence is | |
1884 | * conservatively done. | |
1885 | */ | |
1886 | ||
1887 | /* Enforce SDA high. */ | |
1888 | sample_buffer_raise(inc, I2C_PINMASK_SDA); | |
1889 | ret = wave_append_buffer(inc); | |
1890 | if (ret != SR_OK) | |
1891 | return ret; | |
1892 | ||
1893 | /* Enforce SCL high. */ | |
1894 | sample_buffer_raise(inc, I2C_PINMASK_SCL); | |
1895 | ret = wave_append_buffer(inc); | |
1896 | if (ret != SR_OK) | |
1897 | return ret; | |
1898 | ||
1899 | /* Keep high SCL and high SDA for another period. */ | |
1900 | ret = wave_append_buffer(inc); | |
1901 | if (ret != SR_OK) | |
1902 | return ret; | |
1903 | ||
1904 | /* Falling SDA while SCL is high. */ | |
1905 | sample_buffer_clear(inc, I2C_PINMASK_SDA); | |
1906 | ret = wave_append_buffer(inc); | |
1907 | if (ret != SR_OK) | |
1908 | return ret; | |
1909 | ||
1910 | /* Keep high SCL and low SDA for one more period. */ | |
1911 | ret = wave_append_buffer(inc); | |
1912 | if (ret != SR_OK) | |
1913 | return ret; | |
1914 | ||
1915 | /* | |
1916 | * Lower SCL here already. Which kind of prepares DATA BIT | |
1917 | * times (fits a data bit's start condition, does not harm). | |
1918 | * Improves back to back START and (repeated) START as well | |
1919 | * as STOP without preceeding DATA BIT. | |
1920 | */ | |
1921 | sample_buffer_clear(inc, I2C_PINMASK_SCL); | |
1922 | ret = wave_append_buffer(inc); | |
1923 | if (ret != SR_OK) | |
1924 | return ret; | |
1925 | ||
1926 | return SR_OK; | |
1927 | } | |
1928 | ||
1929 | /* | |
1930 | * Construct a STOP symbol. Occupy a full bit time in the waveform. | |
1931 | * | |
1932 | * Definition of STOP: Rising SDA while SCL is high. | |
1933 | */ | |
1934 | static int i2c_write_stop(struct context *inc) | |
1935 | { | |
1936 | int ret; | |
1937 | ||
1938 | /* Enforce SCL low before SDA changes. */ | |
1939 | sample_buffer_clear(inc, I2C_PINMASK_SCL); | |
1940 | ret = wave_append_buffer(inc); | |
1941 | if (ret != SR_OK) | |
1942 | return ret; | |
1943 | ||
1944 | /* Enforce SDA low (can change while SCL is low). */ | |
1945 | sample_buffer_clear(inc, I2C_PINMASK_SDA); | |
1946 | ret = wave_append_buffer(inc); | |
1947 | if (ret != SR_OK) | |
1948 | return ret; | |
1949 | ||
1950 | /* Rise SCL high while SDA is low. */ | |
1951 | sample_buffer_raise(inc, I2C_PINMASK_SCL); | |
1952 | ret = wave_append_buffer(inc); | |
1953 | if (ret != SR_OK) | |
1954 | return ret; | |
1955 | ||
1956 | /* Keep high SCL and low SDA for another period. */ | |
1957 | ret = wave_append_buffer(inc); | |
1958 | if (ret != SR_OK) | |
1959 | return ret; | |
1960 | ||
1961 | /* Rising SDA. */ | |
1962 | sample_buffer_raise(inc, I2C_PINMASK_SDA); | |
1963 | ret = wave_append_buffer(inc); | |
1964 | if (ret != SR_OK) | |
1965 | return ret; | |
1966 | ||
1967 | /* Keep high SCL and high SDA for one more periods. */ | |
1968 | ret = wave_append_buffer(inc); | |
1969 | if (ret != SR_OK) | |
1970 | return ret; | |
1971 | ||
1972 | return SR_OK; | |
1973 | } | |
1974 | ||
1975 | /* | |
1976 | * Construct a DATA BIT symbol. Occupy a full bit time in the waveform. | |
1977 | * | |
1978 | * SDA can change while SCL is low. SDA must be kept while SCL is high. | |
1979 | */ | |
1980 | static int i2c_write_bit(struct context *inc, uint8_t value) | |
1981 | { | |
1982 | int ret; | |
1983 | ||
1984 | /* Enforce SCL low before SDA changes. */ | |
1985 | sample_buffer_clear(inc, I2C_PINMASK_SCL); | |
1986 | ret = wave_append_buffer(inc); | |
1987 | if (ret != SR_OK) | |
1988 | return ret; | |
1989 | ||
1990 | /* Setup SDA pin level while SCL is low. */ | |
1991 | sample_buffer_setclr(inc, value, I2C_PINMASK_SDA); | |
1992 | ret = wave_append_buffer(inc); | |
1993 | if (ret != SR_OK) | |
1994 | return ret; | |
1995 | ||
1996 | /* Rising SCL, starting SDA validity. */ | |
1997 | sample_buffer_raise(inc, I2C_PINMASK_SCL); | |
1998 | ret = wave_append_buffer(inc); | |
1999 | if (ret != SR_OK) | |
2000 | return ret; | |
2001 | ||
2002 | /* Keep SDA level with high SCL for two more periods. */ | |
2003 | ret = wave_append_buffer(inc); | |
2004 | if (ret != SR_OK) | |
2005 | return ret; | |
2006 | ret = wave_append_buffer(inc); | |
2007 | if (ret != SR_OK) | |
2008 | return ret; | |
2009 | ||
2010 | /* Falling SCL, terminates SDA validity. */ | |
2011 | sample_buffer_clear(inc, I2C_PINMASK_SCL); | |
2012 | ret = wave_append_buffer(inc); | |
2013 | if (ret != SR_OK) | |
2014 | return ret; | |
2015 | ||
2016 | return SR_OK; | |
2017 | } | |
2018 | ||
2019 | /* Create a waveform for the eight data bits and the ACK/NAK slot. */ | |
2020 | static int i2c_write_byte(struct context *inc, uint8_t value, uint8_t ack) | |
2021 | { | |
2022 | size_t bit_mask, bit_value; | |
2023 | int ret; | |
2024 | ||
2025 | /* Keep an empty bit time before the data byte. */ | |
2026 | ret = i2c_write_nothing(inc); | |
2027 | if (ret != SR_OK) | |
2028 | return ret; | |
2029 | ||
2030 | /* Send 8 data bits, MSB first. */ | |
2031 | bit_mask = 0x80; | |
2032 | while (bit_mask) { | |
2033 | bit_value = value & bit_mask; | |
2034 | bit_mask >>= 1; | |
2035 | ret = i2c_write_bit(inc, bit_value); | |
2036 | if (ret != SR_OK) | |
2037 | return ret; | |
2038 | } | |
2039 | ||
2040 | /* Send ACK, which is low active. NAK is recessive, high. */ | |
2041 | bit_value = !ack; | |
2042 | ret = i2c_write_bit(inc, bit_value); | |
2043 | if (ret != SR_OK) | |
2044 | return ret; | |
2045 | ||
2046 | /* Keep an empty bit time after the data byte. */ | |
2047 | ret = i2c_write_nothing(inc); | |
2048 | if (ret != SR_OK) | |
2049 | return ret; | |
2050 | ||
2051 | return SR_OK; | |
2052 | } | |
2053 | ||
2054 | /* Send slave address (7bit or 10bit, 1 or 2 bytes). Consumes one ACK. */ | |
2055 | static int i2c_send_address(struct sr_input *in, uint16_t addr, gboolean read) | |
2056 | { | |
2057 | struct context *inc; | |
2058 | struct i2c_frame_fmt_opts *fmt_opts; | |
2059 | gboolean with_ack; | |
2060 | uint8_t addr_byte, rw_bit; | |
2061 | int ret; | |
2062 | ||
2063 | inc = in->priv; | |
2064 | fmt_opts = &inc->curr_opts.frame_format.i2c; | |
2065 | ||
2066 | addr &= 0x3ff; | |
2067 | rw_bit = read ? 1 : 0; | |
2068 | with_ack = i2c_auto_ack_avail(inc); | |
2069 | ||
2070 | if (!fmt_opts->addr_10bit) { | |
2071 | /* 7 bit address, the simple case. */ | |
2072 | addr_byte = addr & 0x7f; | |
2073 | addr_byte <<= 1; | |
2074 | addr_byte |= rw_bit; | |
2075 | sr_spew("I2C 7bit address, byte 0x%" PRIx8, addr_byte); | |
2076 | ret = wave_clear_sequence(inc); | |
2077 | if (ret != SR_OK) | |
2078 | return ret; | |
2079 | ret = i2c_write_byte(inc, addr_byte, with_ack); | |
2080 | if (ret != SR_OK) | |
2081 | return ret; | |
2082 | ret = send_frame(in); | |
2083 | if (ret != SR_OK) | |
2084 | return ret; | |
2085 | } else { | |
2086 | /* | |
2087 | * 10 bit address, need to write two bytes: First byte | |
2088 | * with prefix 0xf0, upper most 2 address bits, and R/W. | |
2089 | * Second byte with lower 8 address bits. | |
2090 | */ | |
2091 | addr_byte = addr >> 8; | |
2092 | addr_byte <<= 1; | |
2093 | addr_byte |= 0xf0; | |
2094 | addr_byte |= rw_bit; | |
2095 | sr_spew("I2C 10bit address, byte 0x%" PRIx8, addr_byte); | |
2096 | ret = wave_clear_sequence(inc); | |
2097 | if (ret != SR_OK) | |
2098 | return ret; | |
2099 | ret = i2c_write_byte(inc, addr_byte, with_ack); | |
2100 | if (ret != SR_OK) | |
2101 | return ret; | |
2102 | ret = send_frame(in); | |
2103 | if (ret != SR_OK) | |
2104 | return ret; | |
2105 | ||
2106 | addr_byte = addr & 0xff; | |
2107 | sr_spew("I2C 10bit address, byte 0x%" PRIx8, addr_byte); | |
2108 | ret = wave_clear_sequence(inc); | |
2109 | if (ret != SR_OK) | |
2110 | return ret; | |
2111 | ret = i2c_write_byte(inc, addr_byte, with_ack); | |
2112 | if (ret != SR_OK) | |
2113 | return ret; | |
2114 | ret = send_frame(in); | |
2115 | if (ret != SR_OK) | |
2116 | return ret; | |
2117 | } | |
2118 | ||
2119 | return SR_OK; | |
2120 | } | |
2121 | ||
2122 | /* I2C specific options and frame format check. */ | |
2123 | static int i2c_check_opts(struct context *inc) | |
2124 | { | |
2125 | struct i2c_frame_fmt_opts *fmt_opts; | |
2126 | const char *fmt_text; | |
2127 | char **opts, *opt; | |
2128 | size_t opt_count, opt_idx; | |
2129 | size_t total_bits; | |
2130 | ||
2131 | if (!inc) | |
2132 | return SR_ERR_ARG; | |
2133 | fmt_opts = &inc->curr_opts.frame_format.i2c; | |
2134 | ||
2135 | /* Apply defaults before reading external specs. */ | |
2136 | memset(fmt_opts, 0, sizeof(*fmt_opts)); | |
2137 | fmt_opts->addr_10bit = FALSE; | |
2138 | ||
2139 | /* Provide a default I2C frame format. */ | |
2140 | fmt_text = inc->curr_opts.fmt_text; | |
2141 | if (!fmt_text || !*fmt_text) | |
2142 | fmt_text = I2C_DFLT_FRAMEFMT; | |
2143 | sr_dbg("I2C frame format: %s.", fmt_text); | |
2144 | ||
2145 | /* Accept comma separated key=value pairs of specs. */ | |
2146 | opts = g_strsplit_set(fmt_text, ", ", 0); | |
2147 | opt_count = g_strv_length(opts); | |
2148 | for (opt_idx = 0; opt_idx < opt_count; opt_idx++) { | |
2149 | opt = opts[opt_idx]; | |
2150 | if (!opt || !*opt) | |
2151 | continue; | |
2152 | sr_spew("I2C format option: %s.", opt); | |
2153 | if (strcmp(opt, I2C_FORMAT_ADDR_7BIT) == 0) { | |
2154 | sr_spew("I2C address: 7 bit"); | |
2155 | fmt_opts->addr_10bit = FALSE; | |
2156 | continue; | |
2157 | } | |
2158 | if (strcmp(opt, I2C_FORMAT_ADDR_10BIT) == 0) { | |
2159 | sr_spew("I2C address: 10 bit"); | |
2160 | fmt_opts->addr_10bit = TRUE; | |
2161 | continue; | |
2162 | } | |
2163 | return SR_ERR_ARG; | |
2164 | } | |
2165 | g_strfreev(opts); | |
2166 | ||
2167 | /* Get the total slot count. Leave plenty room for convenience. */ | |
2168 | total_bits = 0; | |
2169 | total_bits += I2C_BITTIME_SLOTS; | |
2170 | total_bits *= I2C_BITTIME_QUANTA; | |
2171 | total_bits += I2C_ADD_IDLESLOTS; | |
2172 | ||
2173 | sr_dbg("I2C frame: total bits %lu.", total_bits); | |
2174 | if (total_bits > I2C_MAX_WAVELEN) | |
2175 | return SR_ERR_DATA; | |
2176 | inc->max_frame_bits = total_bits; | |
2177 | ||
2178 | return SR_OK; | |
2179 | } | |
2180 | ||
2181 | /* | |
2182 | * Don't bother with wide and narrow slots, just assume equal size for | |
2183 | * them all. Edges will occupy exactly one sample, then levels are kept. | |
2184 | * This protocol handler's oversampling should be sufficient for decoders | |
2185 | * to extract the content from generated waveforms. | |
2186 | * | |
2187 | * Start with high levels on SCL and SDA for an idle bus condition. | |
2188 | */ | |
2189 | static int i2c_config_frame(struct context *inc) | |
2190 | { | |
2191 | struct i2c_proto_context_t *incs; | |
2192 | size_t bit_idx; | |
2193 | uint8_t sample; | |
2194 | ||
2195 | if (!inc) | |
2196 | return SR_ERR_ARG; | |
2197 | incs = inc->curr_opts.prot_priv; | |
2198 | ||
2199 | memset(incs, 0, sizeof(*incs)); | |
2200 | incs->ack_remain = 0; | |
2201 | ||
2202 | /* | |
2203 | * Adjust all time slots since they represent a smaller quanta | |
2204 | * of an I2C bit time. | |
2205 | */ | |
2206 | for (bit_idx = 0; bit_idx < inc->max_frame_bits; bit_idx++) { | |
2207 | inc->bit_scale[bit_idx].div = I2C_BITTIME_QUANTA; | |
2208 | } | |
2209 | ||
2210 | sample = 0; | |
2211 | sample |= I2C_PINMASK_SCL; | |
2212 | sample |= I2C_PINMASK_SDA; | |
2213 | sample_buffer_preset(inc, sample); | |
2214 | ||
2215 | return SR_OK; | |
2216 | } | |
2217 | ||
2218 | /* | |
2219 | * Process protocol dependent pseudo comments. Can affect future frame | |
2220 | * construction and submission, or can immediately emit "inter frame" | |
2221 | * bit patterns like START/STOP control. Use wide waveforms for these | |
2222 | * transfer controls, put the special symbol nicely centered. Supports | |
2223 | * users during interactive exploration of generated waveforms. | |
2224 | */ | |
2225 | static int i2c_proc_pseudo(struct sr_input *in, char *line) | |
2226 | { | |
2227 | struct context *inc; | |
2228 | char *word, *endp; | |
2229 | int ret; | |
2230 | unsigned long v; | |
2231 | size_t bits; | |
2232 | ||
2233 | inc = in->priv; | |
2234 | ||
2235 | while (line) { | |
2236 | word = sr_text_next_word(line, &line); | |
2237 | if (!word) | |
2238 | break; | |
2239 | if (!*word) | |
2240 | continue; | |
2241 | sr_spew("I2C pseudo: word %s", word); | |
2242 | if (strcmp(word, I2C_PSEUDO_START) == 0) { | |
2243 | sr_spew("I2C pseudo: send START"); | |
2244 | ret = wave_clear_sequence(inc); | |
2245 | if (ret != SR_OK) | |
2246 | return ret; | |
2247 | bits = I2C_BITTIME_SLOTS / 2; | |
2248 | while (bits--) { | |
2249 | ret = i2c_write_nothing(inc); | |
2250 | if (ret != SR_OK) | |
2251 | return ret; | |
2252 | } | |
2253 | ret = i2c_write_start(inc); | |
2254 | if (ret != SR_OK) | |
2255 | return ret; | |
2256 | bits = I2C_BITTIME_SLOTS / 2; | |
2257 | while (bits--) { | |
2258 | ret = i2c_write_nothing(inc); | |
2259 | if (ret != SR_OK) | |
2260 | return ret; | |
2261 | } | |
2262 | ret = send_frame(in); | |
2263 | if (ret != SR_OK) | |
2264 | return ret; | |
2265 | continue; | |
2266 | } | |
2267 | if (strcmp(word, I2C_PSEUDO_REP_START) == 0) { | |
2268 | sr_spew("I2C pseudo: send REPEAT START"); | |
2269 | ret = wave_clear_sequence(inc); | |
2270 | if (ret != SR_OK) | |
2271 | return ret; | |
2272 | bits = I2C_BITTIME_SLOTS / 2; | |
2273 | while (bits--) { | |
2274 | ret = i2c_write_nothing(inc); | |
2275 | if (ret != SR_OK) | |
2276 | return ret; | |
2277 | } | |
2278 | ret = i2c_write_start(inc); | |
2279 | if (ret != SR_OK) | |
2280 | return ret; | |
2281 | bits = I2C_BITTIME_SLOTS / 2; | |
2282 | while (bits--) { | |
2283 | ret = i2c_write_nothing(inc); | |
2284 | if (ret != SR_OK) | |
2285 | return ret; | |
2286 | } | |
2287 | ret = send_frame(in); | |
2288 | if (ret != SR_OK) | |
2289 | return ret; | |
2290 | continue; | |
2291 | } | |
2292 | if (strcmp(word, I2C_PSEUDO_STOP) == 0) { | |
2293 | sr_spew("I2C pseudo: send STOP"); | |
2294 | ret = wave_clear_sequence(inc); | |
2295 | if (ret != SR_OK) | |
2296 | return ret; | |
2297 | bits = I2C_BITTIME_SLOTS / 2; | |
2298 | while (bits--) { | |
2299 | ret = i2c_write_nothing(inc); | |
2300 | if (ret != SR_OK) | |
2301 | return ret; | |
2302 | } | |
2303 | ret = i2c_write_stop(inc); | |
2304 | if (ret != SR_OK) | |
2305 | return ret; | |
2306 | bits = I2C_BITTIME_SLOTS / 2; | |
2307 | while (bits--) { | |
2308 | ret = i2c_write_nothing(inc); | |
2309 | if (ret != SR_OK) | |
2310 | return ret; | |
2311 | } | |
2312 | ret = send_frame(in); | |
2313 | if (ret != SR_OK) | |
2314 | return ret; | |
2315 | continue; | |
2316 | } | |
2317 | if (g_str_has_prefix(word, I2C_PSEUDO_ADDR_WRITE)) { | |
2318 | word += strlen(I2C_PSEUDO_ADDR_WRITE); | |
2319 | endp = NULL; | |
2320 | ret = sr_atoul_base(word, &v, &endp, 0); | |
2321 | if (ret != SR_OK) | |
2322 | return ret; | |
2323 | if (!endp || *endp) | |
2324 | return SR_ERR_ARG; | |
2325 | sr_spew("I2C pseudo: addr write %lu", v); | |
2326 | ret = i2c_send_address(in, v, FALSE); | |
2327 | if (ret != SR_OK) | |
2328 | return ret; | |
2329 | continue; | |
2330 | } | |
2331 | if (g_str_has_prefix(word, I2C_PSEUDO_ADDR_READ)) { | |
2332 | word += strlen(I2C_PSEUDO_ADDR_READ); | |
2333 | endp = NULL; | |
2334 | ret = sr_atoul_base(word, &v, &endp, 0); | |
2335 | if (ret != SR_OK) | |
2336 | return ret; | |
2337 | if (!endp || *endp) | |
2338 | return SR_ERR_ARG; | |
2339 | sr_spew("I2C pseudo: addr read %lu", v); | |
2340 | ret = i2c_send_address(in, v, TRUE); | |
2341 | if (ret != SR_OK) | |
2342 | return ret; | |
2343 | continue; | |
2344 | } | |
2345 | if (g_str_has_prefix(word, I2C_PSEUDO_ACK_NEXT)) { | |
2346 | word += strlen(I2C_PSEUDO_ACK_NEXT); | |
2347 | endp = NULL; | |
2348 | ret = sr_atoul_base(word, &v, &endp, 0); | |
2349 | if (ret != SR_OK) | |
2350 | return ret; | |
2351 | if (!endp || *endp) | |
2352 | return SR_ERR_ARG; | |
2353 | sr_spew("i2c pseudo: ack next %lu", v); | |
2354 | i2c_auto_ack_start(inc, v); | |
2355 | continue; | |
2356 | } | |
2357 | if (strcmp(word, I2C_PSEUDO_ACK_ONCE) == 0) { | |
2358 | sr_spew("i2c pseudo: ack once"); | |
2359 | i2c_auto_ack_start(inc, 1); | |
2360 | continue; | |
2361 | } | |
2362 | return SR_ERR_DATA; | |
2363 | } | |
2364 | ||
2365 | return SR_OK; | |
2366 | } | |
2367 | ||
2368 | /* | |
2369 | * Create the frame's waveform for the given data value. Automatically | |
2370 | * track ACK bits, Fallback to NAK when externally specified ACK counts | |
2371 | * have expired. The caller sends the waveform that we created. | |
2372 | */ | |
2373 | static int i2c_proc_value(struct context *inc, uint32_t value) | |
2374 | { | |
2375 | gboolean with_ack; | |
2376 | int ret; | |
2377 | ||
2378 | if (!inc) | |
2379 | return SR_ERR_ARG; | |
2380 | ||
2381 | with_ack = i2c_auto_ack_avail(inc); | |
2382 | ||
2383 | ret = wave_clear_sequence(inc); | |
2384 | if (ret != SR_OK) | |
2385 | return ret; | |
2386 | ret = i2c_write_byte(inc, value, with_ack); | |
2387 | if (ret != SR_OK) | |
2388 | return ret; | |
2389 | ||
2390 | return 0; | |
2391 | } | |
2392 | ||
2393 | /* Start/end the logic trace with a few bit times of idle level. */ | |
2394 | static int i2c_get_idle_capture(struct context *inc, | |
2395 | size_t *bitcount, uint8_t *sample) | |
2396 | { | |
2397 | ||
2398 | /* Describe a byte's time of idle level. */ | |
2399 | if (bitcount) | |
2400 | *bitcount = I2C_BITTIME_SLOTS; | |
2401 | if (sample) | |
2402 | *sample = inc->samples.idle_levels; | |
2403 | return SR_OK; | |
2404 | } | |
2405 | ||
2406 | /* Arrange for a few samples of idle level between UART frames. */ | |
2407 | static int i2c_get_idle_interframe(struct context *inc, | |
2408 | size_t *samplecount, uint8_t *sample) | |
2409 | { | |
2410 | ||
f6d0f7a8 GS |
2411 | /* |
2412 | * The space around regular bytes already is sufficient. We | |
2413 | * don't need to generate an inter-frame gap, but the code is | |
2414 | * prepared to in case we want to in the future. | |
2415 | */ | |
ff7f7f73 GS |
2416 | if (samplecount) { |
2417 | *samplecount = inc->curr_opts.samples_per_bit; | |
f6d0f7a8 | 2418 | *samplecount *= 0; |
ff7f7f73 GS |
2419 | } |
2420 | if (sample) | |
2421 | *sample = inc->samples.curr_levels; | |
2422 | return SR_OK; | |
2423 | } | |
2424 | ||
2425 | /* }}} I2C protocol handler */ | |
2426 | /* {{{ protocol dispatching */ | |
2427 | ||
2428 | /* | |
2429 | * The list of supported protocols and their handlers, including | |
2430 | * protocol specific defaults. The first item after the NONE slot | |
2431 | * is the default protocol, and takes effect in the absence of any | |
2432 | * user provided or file content provided spec. | |
2433 | */ | |
2434 | static const struct proto_handler_t protocols[PROTO_TYPE_COUNT] = { | |
2435 | [PROTO_TYPE_UART] = { | |
2436 | UART_HANDLER_NAME, | |
2437 | { | |
2438 | UART_DFLT_SAMPLERATE, | |
2439 | UART_DFLT_BITRATE, UART_DFLT_FRAMEFMT, | |
2440 | INPUT_BYTES, | |
2441 | }, | |
2442 | { | |
2443 | 1, (const char *[]){ | |
2444 | [UART_PIN_RXTX] = "rxtx", | |
2445 | }, | |
2446 | }, | |
2447 | 0, | |
2448 | uart_check_opts, | |
2449 | uart_config_frame, | |
2450 | uart_proc_pseudo, | |
2451 | uart_proc_value, | |
2452 | uart_get_idle_capture, | |
2453 | uart_get_idle_interframe, | |
2454 | }, | |
2455 | [PROTO_TYPE_SPI] = { | |
2456 | SPI_HANDLER_NAME, | |
2457 | { | |
2458 | SPI_DFLT_SAMPLERATE, | |
2459 | SPI_DFLT_BITRATE, SPI_DFLT_FRAMEFMT, | |
2460 | INPUT_TEXT, | |
2461 | }, | |
2462 | { | |
2463 | 4, (const char *[]){ | |
2464 | [SPI_PIN_SCK] = "sck", | |
2465 | [SPI_PIN_MISO] = "miso", | |
2466 | [SPI_PIN_MOSI] = "mosi", | |
2467 | [SPI_PIN_CS] = "cs", | |
2468 | }, | |
2469 | }, | |
2470 | sizeof(struct spi_proto_context_t), | |
2471 | spi_check_opts, | |
2472 | spi_config_frame, | |
2473 | spi_proc_pseudo, | |
2474 | spi_proc_value, | |
2475 | spi_get_idle_capture, | |
2476 | spi_get_idle_interframe, | |
2477 | }, | |
2478 | [PROTO_TYPE_I2C] = { | |
2479 | I2C_HANDLER_NAME, | |
2480 | { | |
2481 | I2C_DFLT_SAMPLERATE, | |
2482 | I2C_DFLT_BITRATE, I2C_DFLT_FRAMEFMT, | |
2483 | INPUT_TEXT, | |
2484 | }, | |
2485 | { | |
2486 | 2, (const char *[]){ | |
2487 | [I2C_PIN_SCL] = "scl", | |
2488 | [I2C_PIN_SDA] = "sda", | |
2489 | }, | |
2490 | }, | |
2491 | sizeof(struct i2c_proto_context_t), | |
2492 | i2c_check_opts, | |
2493 | i2c_config_frame, | |
2494 | i2c_proc_pseudo, | |
2495 | i2c_proc_value, | |
2496 | i2c_get_idle_capture, | |
2497 | i2c_get_idle_interframe, | |
2498 | }, | |
2499 | }; | |
2500 | ||
2501 | static int lookup_protocol_name(struct context *inc) | |
2502 | { | |
2503 | const char *name; | |
2504 | const struct proto_handler_t *handler; | |
2505 | size_t idx; | |
2506 | void *priv; | |
2507 | ||
2508 | /* | |
2509 | * Silence compiler warnings. Protocol handlers are free to use | |
2510 | * several alternative sets of primitives for their operation. | |
2511 | * Not using part of the API is nothing worth warning about. | |
2512 | */ | |
2513 | (void)sample_buffer_assign; | |
2514 | ||
2515 | if (!inc) | |
2516 | return SR_ERR_ARG; | |
2517 | inc->curr_opts.protocol_type = PROTO_TYPE_NONE; | |
2518 | inc->curr_opts.prot_hdl = NULL; | |
2519 | ||
2520 | name = inc->curr_opts.proto_name; | |
2521 | if (!name || !*name) { | |
2522 | /* Fallback to first item after NONE slot. */ | |
2523 | handler = &protocols[PROTO_TYPE_NONE + 1]; | |
2524 | name = handler->name; | |
2525 | } | |
2526 | ||
2527 | for (idx = 0; idx < ARRAY_SIZE(protocols); idx++) { | |
2528 | if (idx == PROTO_TYPE_NONE) | |
2529 | continue; | |
2530 | handler = &protocols[idx]; | |
2531 | if (!handler->name || !*handler->name) | |
2532 | continue; | |
2533 | if (strcmp(name, handler->name) != 0) | |
2534 | continue; | |
2535 | inc->curr_opts.protocol_type = idx; | |
2536 | inc->curr_opts.prot_hdl = handler; | |
2537 | if (handler->priv_size) { | |
2538 | priv = g_malloc0(handler->priv_size); | |
2539 | if (!priv) | |
2540 | return SR_ERR_MALLOC; | |
2541 | inc->curr_opts.prot_priv = priv; | |
2542 | } | |
2543 | return SR_OK; | |
2544 | } | |
2545 | ||
2546 | return SR_ERR_DATA; | |
2547 | } | |
2548 | ||
2549 | /* }}} protocol dispatching */ | |
2550 | /* {{{ text/binary input file reader */ | |
2551 | ||
2552 | /** | |
2553 | * Checks for UTF BOM, removes it when found at the start of the buffer. | |
2554 | * | |
2555 | * @param[in] buf The accumulated input buffer. | |
2556 | */ | |
2557 | static void check_remove_bom(GString *buf) | |
2558 | { | |
2559 | static const char *bom_text = "\xef\xbb\xbf"; | |
2560 | ||
2561 | if (buf->len < strlen(bom_text)) | |
2562 | return; | |
2563 | if (strncmp(buf->str, bom_text, strlen(bom_text)) != 0) | |
2564 | return; | |
2565 | g_string_erase(buf, 0, strlen(bom_text)); | |
2566 | } | |
2567 | ||
2568 | /** | |
2569 | * Checks for presence of a caption, yields the position after its text line. | |
2570 | * | |
2571 | * @param[in] buf The accumulated input buffer. | |
2572 | * @param[in] caption The text to search for (NUL terminated ASCII literal). | |
2573 | * @param[in] max_pos The maximum length to search for. | |
2574 | * | |
2575 | * @returns The position after the text line which contains the caption. | |
2576 | * Or #NULL when either the caption or the end-of-line was not found. | |
2577 | */ | |
2578 | static char *have_text_line(GString *buf, const char *caption, size_t max_pos) | |
2579 | { | |
2580 | size_t cap_len, rem_len; | |
2581 | char *p_read, *p_found; | |
2582 | ||
2583 | cap_len = strlen(caption); | |
2584 | rem_len = buf->len; | |
2585 | p_read = buf->str; | |
2586 | ||
2587 | /* Search for the occurance of the caption itself. */ | |
2588 | if (!max_pos) { | |
2589 | /* Caption must be at the start of the buffer. */ | |
2590 | if (rem_len < cap_len) | |
2591 | return NULL; | |
2592 | if (strncmp(p_read, caption, cap_len) != 0) | |
2593 | return NULL; | |
2594 | } else { | |
2595 | /* Caption can be anywhere up to a max position. */ | |
2596 | p_found = g_strstr_len(p_read, rem_len, caption); | |
2597 | if (!p_found) | |
2598 | return NULL; | |
2599 | /* Pretend that caption had been rather long. */ | |
2600 | cap_len += p_found - p_read; | |
2601 | } | |
2602 | ||
2603 | /* | |
2604 | * Advance over the caption. Advance over end-of-line. Supports | |
2605 | * several end-of-line conditions, but rejects unexpected trailer | |
2606 | * after the caption and before the end-of-line. Always wants LF. | |
2607 | */ | |
2608 | p_read += cap_len; | |
2609 | rem_len -= cap_len; | |
2610 | while (rem_len && *p_read != '\n' && g_ascii_isspace(*p_read)) { | |
2611 | p_read++; | |
2612 | rem_len--; | |
2613 | } | |
2614 | if (rem_len && *p_read != '\n' && *p_read == '\r') { | |
2615 | p_read++; | |
2616 | rem_len--; | |
2617 | } | |
2618 | if (rem_len && *p_read == '\n') { | |
2619 | p_read++; | |
2620 | rem_len--; | |
2621 | return p_read; | |
2622 | } | |
2623 | ||
2624 | return NULL; | |
2625 | } | |
2626 | ||
2627 | /** | |
2628 | * Checks for the presence of the magic string at the start of the file. | |
2629 | * | |
2630 | * @param[in] buf The accumulated input buffer. | |
2631 | * @param[out] next_pos The text after the magic text line. | |
2632 | * | |
2633 | * @returns Boolean whether the magic was found. | |
2634 | * | |
2635 | * This implementation assumes that the magic file type marker never gets | |
2636 | * split across receive chunks. | |
2637 | */ | |
2638 | static gboolean have_magic(GString *buf, char **next_pos) | |
2639 | { | |
2640 | char *next_line; | |
2641 | ||
2642 | if (next_pos) | |
2643 | *next_pos = NULL; | |
2644 | ||
2645 | next_line = have_text_line(buf, MAGIC_FILE_TYPE, 0); | |
2646 | if (!next_line) | |
2647 | return FALSE; | |
2648 | ||
2649 | if (next_pos) | |
2650 | *next_pos = next_line; | |
2651 | ||
2652 | return TRUE; | |
2653 | } | |
2654 | ||
2655 | /** | |
2656 | * Checks for the presence of the header section at the start of the file. | |
2657 | * | |
2658 | * @param[in] buf The accumulated input buffer. | |
2659 | * @param[out] next_pos The text after the header section. | |
2660 | * | |
2661 | * @returns A negative value when the answer is yet unknown (insufficient | |
2662 | * input data). Or boolean 0/1 when the header was found absent/present. | |
2663 | * | |
2664 | * The caller is supposed to have checked for and removed the magic text | |
2665 | * for the file type. This routine expects to find the header section | |
2666 | * boundaries right at the start of the input buffer. | |
2667 | * | |
2668 | * This implementation assumes that the header start marker never gets | |
2669 | * split across receive chunks. | |
2670 | */ | |
2671 | static int have_header(GString *buf, char **next_pos) | |
2672 | { | |
2673 | char *after_start, *after_end; | |
2674 | ||
2675 | if (next_pos) | |
2676 | *next_pos = NULL; | |
2677 | ||
2678 | after_start = have_text_line(buf, TEXT_HEAD_START, 0); | |
2679 | if (!after_start) | |
2680 | return 0; | |
2681 | ||
2682 | after_end = have_text_line(buf, TEXT_HEAD_END, buf->len); | |
2683 | if (!after_end) | |
2684 | return -1; | |
2685 | ||
2686 | if (next_pos) | |
2687 | *next_pos = after_end; | |
2688 | return 1; | |
2689 | } | |
2690 | ||
2691 | /* | |
2692 | * Implementation detail: Most parse routines merely accept an input | |
2693 | * string or at most convert text to numbers. Actual processing of the | |
2694 | * values or constraints checks are done later when the header section | |
2695 | * ended and all data was seen, regardless of order of appearance. | |
2696 | */ | |
2697 | ||
2698 | static int parse_samplerate(struct context *inc, const char *text) | |
2699 | { | |
2700 | uint64_t rate; | |
2701 | int ret; | |
2702 | ||
2703 | ret = sr_parse_sizestring(text, &rate); | |
2704 | if (ret != SR_OK) | |
2705 | return SR_ERR_DATA; | |
2706 | ||
2707 | inc->curr_opts.samplerate = rate; | |
2708 | ||
2709 | return SR_OK; | |
2710 | } | |
2711 | ||
2712 | static int parse_bitrate(struct context *inc, const char *text) | |
2713 | { | |
2714 | uint64_t rate; | |
2715 | int ret; | |
2716 | ||
2717 | ret = sr_parse_sizestring(text, &rate); | |
2718 | if (ret != SR_OK) | |
2719 | return SR_ERR_DATA; | |
2720 | ||
2721 | inc->curr_opts.bitrate = rate; | |
2722 | ||
2723 | return SR_OK; | |
2724 | } | |
2725 | ||
2726 | static int parse_protocol(struct context *inc, const char *line) | |
2727 | { | |
2728 | ||
2729 | if (!line || !*line) | |
2730 | return SR_ERR_DATA; | |
2731 | ||
2732 | if (inc->curr_opts.proto_name) { | |
2733 | free(inc->curr_opts.proto_name); | |
2734 | inc->curr_opts.proto_name = NULL; | |
2735 | } | |
2736 | inc->curr_opts.proto_name = g_strdup(line); | |
2737 | if (!inc->curr_opts.proto_name) | |
2738 | return SR_ERR_MALLOC; | |
2739 | line = inc->curr_opts.proto_name; | |
2740 | ||
2741 | return SR_OK; | |
2742 | } | |
2743 | ||
2744 | static int parse_frameformat(struct context *inc, const char *line) | |
2745 | { | |
2746 | ||
2747 | if (!line || !*line) | |
2748 | return SR_ERR_DATA; | |
2749 | ||
2750 | if (inc->curr_opts.fmt_text) { | |
2751 | free(inc->curr_opts.fmt_text); | |
2752 | inc->curr_opts.fmt_text = NULL; | |
2753 | } | |
2754 | inc->curr_opts.fmt_text = g_strdup(line); | |
2755 | if (!inc->curr_opts.fmt_text) | |
2756 | return SR_ERR_MALLOC; | |
2757 | line = inc->curr_opts.fmt_text; | |
2758 | ||
2759 | return SR_OK; | |
2760 | } | |
2761 | ||
2762 | static int parse_textinput(struct context *inc, const char *text) | |
2763 | { | |
2764 | gboolean is_text; | |
2765 | ||
2766 | if (!text || !*text) | |
2767 | return SR_ERR_ARG; | |
2768 | ||
2769 | is_text = sr_parse_boolstring(text); | |
2770 | inc->curr_opts.textinput = is_text ? INPUT_TEXT : INPUT_BYTES; | |
2771 | return SR_OK; | |
2772 | } | |
2773 | ||
2774 | static int parse_header_line(struct context *inc, const char *line) | |
2775 | { | |
2776 | ||
2777 | /* Silently ignore comment lines. Also covers start/end markers. */ | |
2778 | if (strncmp(line, TEXT_COMM_LEADER, strlen(TEXT_COMM_LEADER)) == 0) | |
2779 | return SR_OK; | |
2780 | ||
2781 | if (strncmp(line, LABEL_SAMPLERATE, strlen(LABEL_SAMPLERATE)) == 0) { | |
2782 | line += strlen(LABEL_SAMPLERATE); | |
2783 | return parse_samplerate(inc, line); | |
2784 | } | |
2785 | if (strncmp(line, LABEL_BITRATE, strlen(LABEL_BITRATE)) == 0) { | |
2786 | line += strlen(LABEL_BITRATE); | |
2787 | return parse_bitrate(inc, line); | |
2788 | } | |
2789 | if (strncmp(line, LABEL_PROTOCOL, strlen(LABEL_PROTOCOL)) == 0) { | |
2790 | line += strlen(LABEL_PROTOCOL); | |
2791 | return parse_protocol(inc, line); | |
2792 | } | |
2793 | if (strncmp(line, LABEL_FRAMEFORMAT, strlen(LABEL_FRAMEFORMAT)) == 0) { | |
2794 | line += strlen(LABEL_FRAMEFORMAT); | |
2795 | return parse_frameformat(inc, line); | |
2796 | } | |
2797 | if (strncmp(line, LABEL_TEXTINPUT, strlen(LABEL_TEXTINPUT)) == 0) { | |
2798 | line += strlen(LABEL_TEXTINPUT); | |
2799 | return parse_textinput(inc, line); | |
2800 | } | |
2801 | ||
2802 | /* Unsupported directive. */ | |
2803 | sr_err("Unsupported header directive: %s.", line); | |
2804 | ||
2805 | return SR_ERR_DATA; | |
2806 | } | |
2807 | ||
2808 | static int parse_header(struct context *inc, GString *buf, size_t hdr_len) | |
2809 | { | |
2810 | size_t remain; | |
2811 | char *curr, *next, *line; | |
2812 | int ret; | |
2813 | ||
2814 | ret = SR_OK; | |
2815 | ||
2816 | /* The caller determined where the header ends. Read up to there. */ | |
2817 | remain = hdr_len; | |
2818 | curr = buf->str; | |
2819 | while (curr && remain) { | |
2820 | /* Get another text line. Skip empty lines. */ | |
2821 | line = sr_text_next_line(curr, remain, &next, NULL); | |
2822 | if (!line) | |
2823 | break; | |
2824 | if (next) | |
2825 | remain -= next - curr; | |
2826 | else | |
2827 | remain = 0; | |
2828 | curr = next; | |
2829 | if (!*line) | |
2830 | continue; | |
2831 | /* Process the non-empty file header text line. */ | |
2832 | sr_dbg("Header line: %s", line); | |
2833 | ret = parse_header_line(inc, line); | |
2834 | if (ret != SR_OK) | |
2835 | break; | |
2836 | } | |
2837 | ||
2838 | return ret; | |
2839 | } | |
2840 | ||
2841 | /* Process input text reader specific pseudo comment. */ | |
2842 | static int process_pseudo_textinput(struct sr_input *in, char *line) | |
2843 | { | |
2844 | struct context *inc; | |
2845 | char *word; | |
2846 | unsigned long v; | |
2847 | char *endp; | |
2848 | int ret; | |
2849 | ||
2850 | inc = in->priv; | |
2851 | while (line) { | |
2852 | word = sr_text_next_word(line, &line); | |
2853 | if (!word) | |
2854 | break; | |
2855 | if (!*word) | |
2856 | continue; | |
2857 | if (g_str_has_prefix(word, TEXT_INPUT_RADIX)) { | |
2858 | word += strlen(TEXT_INPUT_RADIX); | |
2859 | endp = NULL; | |
2860 | ret = sr_atoul_base(word, &v, &endp, 10); | |
2861 | if (ret != SR_OK) | |
2862 | return ret; | |
2863 | inc->read_text.base = v; | |
2864 | continue; | |
2865 | } | |
2866 | return SR_ERR_DATA; | |
2867 | } | |
2868 | ||
2869 | return SR_OK; | |
2870 | } | |
2871 | ||
2872 | /* Process a line of input text. */ | |
2873 | static int process_textline(struct sr_input *in, char *line) | |
2874 | { | |
2875 | struct context *inc; | |
2876 | const struct proto_handler_t *handler; | |
2877 | gboolean is_comm, is_pseudo; | |
395ac73e | 2878 | char *p, *word, *endp; |
ff7f7f73 GS |
2879 | unsigned long value; |
2880 | int ret; | |
2881 | ||
2882 | inc = in->priv; | |
2883 | handler = inc->curr_opts.prot_hdl; | |
2884 | ||
2885 | /* | |
2886 | * Check for comments, including pseudo-comments with protocol | |
2887 | * specific or text reader specific instructions. It's essential | |
2888 | * to check for "# ${PROTO}:" last, because the implementation | |
2889 | * of the check advances the read position, cannot rewind when | |
2890 | * detection fails. But we know that it is a comment and was not | |
2891 | * a pseudo-comment. So any non-matching data just gets discarded. | |
2892 | * Matching data gets processed (when handlers exist). | |
2893 | */ | |
2894 | is_comm = g_str_has_prefix(line, TEXT_COMM_LEADER); | |
2895 | if (is_comm) { | |
2896 | line += strlen(TEXT_COMM_LEADER); | |
2897 | while (isspace(*line)) | |
2898 | line++; | |
2899 | is_pseudo = g_str_has_prefix(line, TEXT_INPUT_PREFIX); | |
2900 | if (is_pseudo) { | |
2901 | line += strlen(TEXT_INPUT_PREFIX); | |
2902 | while (isspace(*line)) | |
2903 | line++; | |
2904 | sr_dbg("pseudo comment, textinput: %s", line); | |
2905 | line = sr_text_trim_spaces(line); | |
2906 | return process_pseudo_textinput(in, line); | |
2907 | } | |
2908 | is_pseudo = g_str_has_prefix(line, handler->name); | |
2909 | if (is_pseudo) { | |
2910 | line += strlen(handler->name); | |
2911 | is_pseudo = *line == ':'; | |
2912 | if (is_pseudo) | |
2913 | line++; | |
2914 | } | |
2915 | if (is_pseudo) { | |
2916 | while (isspace(*line)) | |
2917 | line++; | |
2918 | sr_dbg("pseudo comment, protocol: %s", line); | |
2919 | if (!handler->proc_pseudo) | |
2920 | return SR_OK; | |
2921 | return handler->proc_pseudo(in, line); | |
2922 | } | |
2923 | sr_spew("comment, skipping: %s", line); | |
2924 | return SR_OK; | |
2925 | } | |
2926 | ||
2927 | /* | |
2928 | * Non-empty non-comment lines carry protocol values. | |
2929 | * (Empty lines are handled transparently when they get here.) | |
395ac73e | 2930 | * Accept comma and semicolon separators for user convenience. |
ff7f7f73 GS |
2931 | * Convert text according to previously received instructions. |
2932 | * Pass the values to the protocol handler. Flush waveforms | |
2933 | * when handlers state that their construction has completed. | |
2934 | */ | |
2935 | sr_spew("got values line: %s", line); | |
395ac73e GS |
2936 | for (p = line; *p; p++) { |
2937 | if (*p == ',' || *p == ';') | |
2938 | *p = ' '; | |
2939 | } | |
ff7f7f73 GS |
2940 | while (line) { |
2941 | word = sr_text_next_word(line, &line); | |
2942 | if (!word) | |
2943 | break; | |
2944 | if (!*word) | |
2945 | continue; | |
2946 | /* Get another numeric value. */ | |
2947 | endp = NULL; | |
2948 | ret = sr_atoul_base(word, &value, &endp, inc->read_text.base); | |
2949 | if (ret != SR_OK) | |
2950 | return ret; | |
2951 | if (!endp || *endp) | |
2952 | return SR_ERR_DATA; | |
2953 | sr_spew("got a value, text [%s] -> number [%lu]", word, value); | |
2954 | /* Forward the value to the protocol handler. */ | |
2955 | ret = 0; | |
2956 | if (handler->proc_value) | |
2957 | ret = handler->proc_value(inc, value); | |
2958 | if (ret < 0) | |
2959 | return ret; | |
2960 | /* Flush the waveform when handler signals completion. */ | |
2961 | if (ret > 0) | |
2962 | continue; | |
2963 | ret = send_frame(in); | |
2964 | if (ret != SR_OK) | |
2965 | return ret; | |
2966 | ret = send_idle_interframe(inc); | |
2967 | if (ret != SR_OK) | |
2968 | return ret; | |
2969 | } | |
2970 | ||
2971 | return SR_OK; | |
2972 | } | |
2973 | ||
2974 | /* }}} text/binary input file reader */ | |
2975 | ||
2976 | /* | |
2977 | * Consistency check of all previously received information. Combines | |
2978 | * the data file's optional header section, as well as user provided | |
2979 | * options that were specified during input module creation. User specs | |
2980 | * take precedence over file content. | |
2981 | */ | |
2982 | static int check_header_user_options(struct context *inc) | |
2983 | { | |
2984 | int ret; | |
2985 | const struct proto_handler_t *handler; | |
2986 | uint64_t rate; | |
2987 | const char *text; | |
2988 | enum textinput_t is_text; | |
2989 | ||
2990 | if (!inc) | |
2991 | return SR_ERR_ARG; | |
2992 | ||
2993 | /* Prefer user specs over file content. */ | |
2994 | rate = inc->user_opts.samplerate; | |
2995 | if (rate) { | |
2996 | sr_dbg("Using user samplerate %" PRIu64 ".", rate); | |
2997 | inc->curr_opts.samplerate = rate; | |
2998 | } | |
2999 | rate = inc->user_opts.bitrate; | |
3000 | if (rate) { | |
3001 | sr_dbg("Using user bitrate %" PRIu64 ".", rate); | |
3002 | inc->curr_opts.bitrate = rate; | |
3003 | } | |
3004 | text = inc->user_opts.proto_name; | |
3005 | if (text && *text) { | |
3006 | sr_dbg("Using user protocol %s.", text); | |
3007 | ret = parse_protocol(inc, text); | |
3008 | if (ret != SR_OK) | |
3009 | return SR_ERR_DATA; | |
3010 | } | |
3011 | text = inc->user_opts.fmt_text; | |
3012 | if (text && *text) { | |
3013 | sr_dbg("Using user frame format %s.", text); | |
3014 | ret = parse_frameformat(inc, text); | |
3015 | if (ret != SR_OK) | |
3016 | return SR_ERR_DATA; | |
3017 | } | |
3018 | is_text = inc->user_opts.textinput; | |
3019 | if (is_text) { | |
3020 | sr_dbg("Using user textinput %d.", is_text); | |
3021 | inc->curr_opts.textinput = is_text; | |
3022 | } | |
3023 | ||
3024 | /* Lookup the protocol (with fallback). Use protocol's defaults. */ | |
3025 | text = inc->curr_opts.proto_name; | |
3026 | ret = lookup_protocol_name(inc); | |
3027 | handler = inc->curr_opts.prot_hdl; | |
3028 | if (ret != SR_OK || !handler) { | |
3029 | sr_err("Unsupported protocol: %s.", text); | |
3030 | return SR_ERR_DATA; | |
3031 | } | |
3032 | text = handler->name; | |
3033 | if (!inc->curr_opts.proto_name && text) { | |
3034 | sr_dbg("Using protocol handler name %s.", text); | |
3035 | ret = parse_protocol(inc, text); | |
3036 | if (ret != SR_OK) | |
3037 | return SR_ERR_DATA; | |
3038 | } | |
3039 | rate = handler->dflt.samplerate; | |
3040 | if (!inc->curr_opts.samplerate && rate) { | |
3041 | sr_dbg("Using protocol handler samplerate %" PRIu64 ".", rate); | |
3042 | inc->curr_opts.samplerate = rate; | |
3043 | } | |
3044 | rate = handler->dflt.bitrate; | |
3045 | if (!inc->curr_opts.bitrate && rate) { | |
3046 | sr_dbg("Using protocol handler bitrate %" PRIu64 ".", rate); | |
3047 | inc->curr_opts.bitrate = rate; | |
3048 | } | |
3049 | text = handler->dflt.frame_format; | |
3050 | if (!inc->curr_opts.fmt_text && text && *text) { | |
3051 | sr_dbg("Using protocol handler frame format %s.", text); | |
3052 | ret = parse_frameformat(inc, text); | |
3053 | if (ret != SR_OK) | |
3054 | return SR_ERR_DATA; | |
3055 | } | |
3056 | is_text = handler->dflt.textinput; | |
3057 | if (!inc->curr_opts.textinput && is_text) { | |
3058 | sr_dbg("Using protocol handler text format %d.", is_text); | |
3059 | inc->curr_opts.textinput = is_text; | |
3060 | } | |
3061 | ||
3062 | if (!inc->curr_opts.samplerate) { | |
3063 | sr_err("Need a samplerate."); | |
3064 | return SR_ERR_DATA; | |
3065 | } | |
3066 | if (!inc->curr_opts.bitrate) { | |
3067 | sr_err("Need a protocol bitrate."); | |
3068 | return SR_ERR_DATA; | |
3069 | } | |
3070 | ||
3071 | if (inc->curr_opts.samplerate < inc->curr_opts.bitrate) { | |
3072 | sr_err("Bitrate cannot exceed samplerate."); | |
3073 | return SR_ERR_DATA; | |
3074 | } | |
3075 | if (inc->curr_opts.samplerate / inc->curr_opts.bitrate < 3) | |
3076 | sr_warn("Low oversampling, consider higher samplerate."); | |
3077 | if (inc->curr_opts.prot_hdl->check_opts) { | |
3078 | ret = inc->curr_opts.prot_hdl->check_opts(inc); | |
3079 | if (ret != SR_OK) { | |
3080 | sr_err("Options failed the protocol's check."); | |
3081 | return SR_ERR_DATA; | |
3082 | } | |
3083 | } | |
3084 | ||
3085 | return SR_OK; | |
3086 | } | |
3087 | ||
3088 | static int create_channels(struct sr_input *in) | |
3089 | { | |
3090 | struct context *inc; | |
3091 | struct sr_dev_inst *sdi; | |
3092 | const struct proto_handler_t *handler; | |
3093 | size_t index; | |
3094 | const char *name; | |
3095 | ||
3096 | if (!in) | |
3097 | return SR_ERR_ARG; | |
3098 | inc = in->priv; | |
3099 | if (!inc) | |
3100 | return SR_ERR_ARG; | |
3101 | sdi = in->sdi; | |
3102 | handler = inc->curr_opts.prot_hdl; | |
3103 | ||
3104 | for (index = 0; index < handler->chans.count; index++) { | |
3105 | name = handler->chans.names[index]; | |
3106 | sr_dbg("Channel %zu name %s.", index, name); | |
3107 | sr_channel_new(sdi, index, SR_CHANNEL_LOGIC, TRUE, name); | |
3108 | } | |
3109 | ||
3110 | inc->feed_logic = feed_queue_logic_alloc(in->sdi, | |
3111 | CHUNK_SIZE, sizeof(uint8_t)); | |
3112 | if (!inc->feed_logic) { | |
3113 | sr_err("Cannot create session feed."); | |
3114 | return SR_ERR_MALLOC; | |
3115 | } | |
3116 | ||
3117 | return SR_OK; | |
3118 | } | |
3119 | ||
3120 | /* | |
3121 | * Keep track of a previously created channel list, in preparation of | |
3122 | * re-reading the input file. Gets called from reset()/cleanup() paths. | |
3123 | */ | |
3124 | static void keep_header_for_reread(const struct sr_input *in) | |
3125 | { | |
3126 | struct context *inc; | |
3127 | ||
3128 | inc = in->priv; | |
3129 | ||
3130 | g_slist_free_full(inc->prev.sr_groups, sr_channel_group_free_cb); | |
3131 | inc->prev.sr_groups = in->sdi->channel_groups; | |
3132 | in->sdi->channel_groups = NULL; | |
3133 | ||
3134 | g_slist_free_full(inc->prev.sr_channels, sr_channel_free_cb); | |
3135 | inc->prev.sr_channels = in->sdi->channels; | |
3136 | in->sdi->channels = NULL; | |
3137 | } | |
3138 | ||
3139 | /* | |
3140 | * Check whether the input file is being re-read, and refuse operation | |
3141 | * when essential parameters of the acquisition have changed in ways | |
3142 | * that are unexpected to calling applications. Gets called after the | |
3143 | * file header got parsed (again). | |
3144 | * | |
3145 | * Changing the channel list across re-imports of the same file is not | |
3146 | * supported, by design and for valid reasons, see bug #1215 for details. | |
3147 | * Users are expected to start new sessions when they change these | |
3148 | * essential parameters in the acquisition's setup. When we accept the | |
3149 | * re-read file, then make sure to keep using the previous channel list, | |
3150 | * applications may still reference them. | |
3151 | */ | |
3152 | static gboolean check_header_in_reread(const struct sr_input *in) | |
3153 | { | |
3154 | struct context *inc; | |
3155 | ||
3156 | if (!in) | |
3157 | return FALSE; | |
3158 | inc = in->priv; | |
3159 | if (!inc) | |
3160 | return FALSE; | |
3161 | if (!inc->prev.sr_channels) | |
3162 | return TRUE; | |
3163 | ||
3164 | if (sr_channel_lists_differ(inc->prev.sr_channels, in->sdi->channels)) { | |
3165 | sr_err("Channel list change not supported for file re-read."); | |
3166 | return FALSE; | |
3167 | } | |
3168 | ||
3169 | g_slist_free_full(in->sdi->channel_groups, sr_channel_group_free_cb); | |
3170 | in->sdi->channel_groups = inc->prev.sr_groups; | |
3171 | inc->prev.sr_groups = NULL; | |
3172 | ||
3173 | g_slist_free_full(in->sdi->channels, sr_channel_free_cb); | |
3174 | in->sdi->channels = inc->prev.sr_channels; | |
3175 | inc->prev.sr_channels = NULL; | |
3176 | ||
3177 | return TRUE; | |
3178 | } | |
3179 | ||
3180 | /* Process another chunk of accumulated input data. */ | |
3181 | static int process_buffer(struct sr_input *in, gboolean is_eof) | |
3182 | { | |
3183 | struct context *inc; | |
3184 | GVariant *gvar; | |
3185 | int ret; | |
3186 | GString *buf; | |
3187 | const struct proto_handler_t *handler; | |
3188 | size_t seen; | |
3189 | char *line, *next; | |
3190 | uint8_t sample; | |
3191 | ||
3192 | inc = in->priv; | |
3193 | buf = in->buf; | |
3194 | handler = inc->curr_opts.prot_hdl; | |
3195 | ||
3196 | /* | |
3197 | * Send feed header and samplerate once before any sample data. | |
3198 | * Communicate an idle period before the first generated frame. | |
3199 | */ | |
3200 | if (!inc->started) { | |
3201 | std_session_send_df_header(in->sdi); | |
3202 | gvar = g_variant_new_uint64(inc->curr_opts.samplerate); | |
3203 | ret = sr_session_send_meta(in->sdi, SR_CONF_SAMPLERATE, gvar); | |
3204 | inc->started = TRUE; | |
3205 | if (ret != SR_OK) | |
3206 | return ret; | |
3207 | ||
3208 | ret = send_idle_capture(inc); | |
3209 | if (ret != SR_OK) | |
3210 | return ret; | |
3211 | } | |
3212 | ||
3213 | /* | |
3214 | * Force proper line termination when EOF is seen and the data | |
3215 | * is in text format. This does not affect binary input, while | |
3216 | * properly terminated text input does not suffer from another | |
3217 | * line feed, because empty lines are considered acceptable. | |
3218 | * Increases robustness for text input from broken generators | |
3219 | * (popular editors which don't terminate the last line). | |
3220 | */ | |
3221 | if (inc->curr_opts.textinput == INPUT_TEXT && is_eof) { | |
3222 | g_string_append_c(buf, '\n'); | |
3223 | } | |
3224 | ||
3225 | /* | |
3226 | * For text input: Scan for the completion of another text line. | |
3227 | * Process its values (or pseudo comments). Skip comment lines. | |
3228 | */ | |
3229 | if (inc->curr_opts.textinput == INPUT_TEXT) do { | |
3230 | /* Get another line of text. */ | |
3231 | seen = 0; | |
3232 | line = sr_text_next_line(buf->str, buf->len, &next, &seen); | |
3233 | if (!line) | |
3234 | break; | |
3235 | /* Process non-empty input lines. */ | |
3236 | ret = *line ? process_textline(in, line) : 0; | |
3237 | if (ret < 0) | |
3238 | return ret; | |
3239 | /* Discard processed input text. */ | |
3240 | g_string_erase(buf, 0, seen); | |
3241 | } while (buf->len); | |
3242 | ||
3243 | /* | |
3244 | * For binary input: Pass data values (individual bytes) to the | |
3245 | * creation of protocol frames. Send the frame's waveform to | |
3246 | * logic channels in the session feed when the protocol handler | |
3247 | * signals the completion of another waveform (zero return value). | |
3248 | * Non-zero positive values translate to "need more input data". | |
3249 | * Negative values signal fatal errors. Remove processed input | |
3250 | * data from the receive buffer. | |
3251 | */ | |
3252 | if (inc->curr_opts.textinput == INPUT_BYTES) { | |
3253 | seen = 0; | |
3254 | while (seen < buf->len) { | |
3255 | sample = buf->str[seen++]; | |
3256 | ret = 0; | |
3257 | if (handler->proc_value) | |
3258 | ret = handler->proc_value(inc, sample); | |
3259 | if (ret < 0) | |
3260 | return ret; | |
3261 | if (ret > 0) | |
3262 | continue; | |
3263 | ret = send_frame(in); | |
3264 | if (ret != SR_OK) | |
3265 | return ret; | |
3266 | ret = send_idle_interframe(inc); | |
3267 | if (ret != SR_OK) | |
3268 | return ret; | |
3269 | } | |
3270 | g_string_erase(buf, 0, seen); | |
3271 | } | |
3272 | ||
3273 | /* Send idle level, and flush when end of input data is seen. */ | |
3274 | if (is_eof) { | |
3275 | if (buf->len) | |
3276 | sr_warn("Unprocessed input data remains."); | |
3277 | ||
3278 | ret = send_idle_capture(inc); | |
3279 | if (ret != SR_OK) | |
3280 | return ret; | |
3281 | ||
3282 | ret = feed_queue_logic_flush(inc->feed_logic); | |
3283 | if (ret != SR_OK) | |
3284 | return ret; | |
3285 | } | |
3286 | ||
3287 | return SR_OK; | |
3288 | } | |
3289 | ||
3290 | static int format_match(GHashTable *metadata, unsigned int *confidence) | |
3291 | { | |
3292 | GString *buf, *tmpbuf; | |
3293 | gboolean has_magic; | |
3294 | ||
3295 | buf = g_hash_table_lookup(metadata, | |
3296 | GINT_TO_POINTER(SR_INPUT_META_HEADER)); | |
3297 | tmpbuf = g_string_new_len(buf->str, buf->len); | |
3298 | ||
3299 | check_remove_bom(tmpbuf); | |
3300 | has_magic = have_magic(tmpbuf, NULL); | |
3301 | g_string_free(tmpbuf, TRUE); | |
3302 | ||
3303 | if (!has_magic) | |
3304 | return SR_ERR; | |
3305 | ||
3306 | *confidence = 1; | |
3307 | return SR_OK; | |
3308 | } | |
3309 | ||
3310 | static int init(struct sr_input *in, GHashTable *options) | |
3311 | { | |
3312 | struct context *inc; | |
3313 | GVariant *gvar; | |
3314 | uint64_t rate; | |
3315 | char *copy; | |
3316 | const char *text; | |
3317 | ||
3318 | in->sdi = g_malloc0(sizeof(*in->sdi)); | |
3319 | inc = g_malloc0(sizeof(*inc)); | |
3320 | in->priv = inc; | |
3321 | ||
3322 | /* | |
3323 | * Store user specified options for later reference. | |
3324 | * | |
3325 | * TODO How to most appropriately hook up size strings with the | |
3326 | * input module's defaults, and applications and their input | |
3327 | * dialogs? | |
3328 | */ | |
3329 | gvar = g_hash_table_lookup(options, "samplerate"); | |
3330 | if (gvar) { | |
3331 | rate = g_variant_get_uint64(gvar); | |
3332 | if (rate) | |
3333 | sr_dbg("User samplerate %" PRIu64 ".", rate); | |
3334 | inc->user_opts.samplerate = rate; | |
3335 | } | |
3336 | ||
3337 | gvar = g_hash_table_lookup(options, "bitrate"); | |
3338 | if (gvar) { | |
3339 | rate = g_variant_get_uint64(gvar); | |
3340 | if (rate) | |
3341 | sr_dbg("User bitrate %" PRIu64 ".", rate); | |
3342 | inc->user_opts.bitrate = rate; | |
3343 | } | |
3344 | ||
3345 | gvar = g_hash_table_lookup(options, "protocol"); | |
3346 | if (gvar) { | |
3347 | copy = g_strdup(g_variant_get_string(gvar, NULL)); | |
3348 | if (!copy) | |
3349 | return SR_ERR_MALLOC; | |
3350 | if (*copy) | |
3351 | sr_dbg("User protocol %s.", copy); | |
3352 | inc->user_opts.proto_name = copy; | |
3353 | } | |
3354 | ||
3355 | gvar = g_hash_table_lookup(options, "frameformat"); | |
3356 | if (gvar) { | |
3357 | copy = g_strdup(g_variant_get_string(gvar, NULL)); | |
3358 | if (!copy) | |
3359 | return SR_ERR_MALLOC; | |
3360 | if (*copy) | |
3361 | sr_dbg("User frame format %s.", copy); | |
3362 | inc->user_opts.fmt_text = copy; | |
3363 | } | |
3364 | ||
3365 | inc->user_opts.textinput = INPUT_UNSPEC; | |
3366 | gvar = g_hash_table_lookup(options, "textinput"); | |
3367 | if (gvar) { | |
3368 | text = g_variant_get_string(gvar, NULL); | |
3369 | if (!text) | |
3370 | return SR_ERR_DATA; | |
3371 | if (!*text) | |
3372 | return SR_ERR_DATA; | |
3373 | sr_dbg("User text input %s.", text); | |
3374 | if (strcmp(text, input_format_texts[INPUT_UNSPEC]) == 0) { | |
3375 | inc->user_opts.textinput = INPUT_UNSPEC; | |
3376 | } else if (strcmp(text, input_format_texts[INPUT_BYTES]) == 0) { | |
3377 | inc->user_opts.textinput = INPUT_BYTES; | |
3378 | } else if (strcmp(text, input_format_texts[INPUT_TEXT]) == 0) { | |
3379 | inc->user_opts.textinput = INPUT_TEXT; | |
3380 | } else { | |
3381 | return SR_ERR_DATA; | |
3382 | } | |
3383 | } | |
3384 | ||
3385 | return SR_OK; | |
3386 | } | |
3387 | ||
3388 | static int receive(struct sr_input *in, GString *buf) | |
3389 | { | |
3390 | struct context *inc; | |
3391 | char *after_magic, *after_header; | |
3392 | size_t consumed; | |
3393 | int ret; | |
3394 | ||
3395 | inc = in->priv; | |
3396 | ||
3397 | /* | |
3398 | * Accumulate all input chunks, potential deferred processing. | |
3399 | * | |
3400 | * Remove an optional BOM at the very start of the input stream. | |
3401 | * BEWARE! This may affect binary input, and we cannot tell if | |
3402 | * the input is text or binary at this stage. Though probability | |
3403 | * for this issue is rather low. Workarounds are available (put | |
3404 | * another values before the first data which happens to match | |
3405 | * the BOM pattern, provide text input instead). | |
3406 | */ | |
3407 | g_string_append_len(in->buf, buf->str, buf->len); | |
3408 | if (!inc->scanned_magic) | |
3409 | check_remove_bom(in->buf); | |
3410 | ||
3411 | /* | |
3412 | * Must complete reception of the (optional) header first. Both | |
3413 | * end of header and absence of header will: Check options that | |
3414 | * were seen so far, then start processing the data part. | |
3415 | */ | |
3416 | if (!inc->got_header) { | |
3417 | /* Check for magic file type marker. */ | |
3418 | if (!inc->scanned_magic) { | |
3419 | inc->has_magic = have_magic(in->buf, &after_magic); | |
3420 | inc->scanned_magic = TRUE; | |
3421 | if (inc->has_magic) { | |
3422 | consumed = after_magic - in->buf->str; | |
3423 | sr_dbg("File format magic found (%zu).", consumed); | |
3424 | g_string_erase(in->buf, 0, consumed); | |
3425 | } | |
3426 | } | |
3427 | ||
3428 | /* Complete header reception and processing. */ | |
3429 | if (inc->has_magic) { | |
3430 | ret = have_header(in->buf, &after_header); | |
3431 | if (ret < 0) | |
3432 | return SR_OK; | |
3433 | inc->has_header = ret; | |
3434 | if (inc->has_header) { | |
3435 | consumed = after_header - in->buf->str; | |
3436 | sr_dbg("File header found (%zu), processing.", consumed); | |
3437 | ret = parse_header(inc, in->buf, consumed); | |
3438 | if (ret != SR_OK) | |
3439 | return ret; | |
3440 | g_string_erase(in->buf, 0, consumed); | |
3441 | } | |
3442 | } | |
3443 | inc->got_header = TRUE; | |
3444 | ||
3445 | /* | |
3446 | * Postprocess the combination of all options. Create | |
3447 | * logic channels, prepare resources for data processing. | |
3448 | */ | |
3449 | ret = check_header_user_options(inc); | |
3450 | if (ret != SR_OK) | |
3451 | return ret; | |
3452 | ret = create_channels(in); | |
3453 | if (ret != SR_OK) | |
3454 | return ret; | |
3455 | if (!check_header_in_reread(in)) | |
3456 | return SR_ERR_DATA; | |
3457 | ret = alloc_frame_storage(inc); | |
3458 | if (ret != SR_OK) | |
3459 | return ret; | |
3460 | ret = assign_bit_widths(inc); | |
3461 | if (ret != SR_OK) | |
3462 | return ret; | |
3463 | ||
3464 | /* Notify the frontend that sdi is ready. */ | |
3465 | in->sdi_ready = TRUE; | |
3466 | return SR_OK; | |
3467 | } | |
3468 | ||
3469 | /* | |
3470 | * Process the input file's data section after the header section | |
3471 | * was received and processed. | |
3472 | */ | |
3473 | ret = process_buffer(in, FALSE); | |
3474 | ||
3475 | return ret; | |
3476 | } | |
3477 | ||
3478 | static int end(struct sr_input *in) | |
3479 | { | |
3480 | struct context *inc; | |
3481 | int ret; | |
3482 | ||
3483 | inc = in->priv; | |
3484 | ||
3485 | /* Must complete processing of previously received chunks. */ | |
3486 | if (in->sdi_ready) { | |
3487 | ret = process_buffer(in, TRUE); | |
3488 | if (ret != SR_OK) | |
3489 | return ret; | |
3490 | } | |
3491 | ||
3492 | /* Must send DF_END when DF_HEADER was sent before. */ | |
3493 | if (inc->started) { | |
3494 | ret = std_session_send_df_end(in->sdi); | |
3495 | if (ret != SR_OK) | |
3496 | return ret; | |
3497 | } | |
3498 | ||
3499 | return SR_OK; | |
3500 | } | |
3501 | ||
3502 | static void cleanup(struct sr_input *in) | |
3503 | { | |
3504 | struct context *inc; | |
3505 | ||
3506 | inc = in->priv; | |
3507 | ||
3508 | keep_header_for_reread(in); | |
3509 | ||
3510 | g_free(inc->curr_opts.proto_name); | |
3511 | inc->curr_opts.proto_name = NULL; | |
3512 | g_free(inc->curr_opts.fmt_text); | |
3513 | inc->curr_opts.fmt_text = NULL; | |
3514 | g_free(inc->curr_opts.prot_priv); | |
3515 | inc->curr_opts.prot_priv = NULL; | |
3516 | feed_queue_logic_free(inc->feed_logic); | |
3517 | inc->feed_logic = NULL; | |
3518 | g_free(inc->sample_edges); | |
3519 | inc->sample_edges = NULL; | |
3520 | g_free(inc->sample_widths); | |
3521 | inc->sample_widths = NULL; | |
3522 | g_free(inc->sample_levels); | |
3523 | inc->sample_levels = NULL; | |
3524 | g_free(inc->bit_scale); | |
3525 | inc->bit_scale = NULL; | |
3526 | } | |
3527 | ||
3528 | static int reset(struct sr_input *in) | |
3529 | { | |
3530 | struct context *inc; | |
3531 | struct user_opts_t save_user_opts; | |
3532 | struct proto_prev save_chans; | |
3533 | ||
3534 | inc = in->priv; | |
3535 | ||
3536 | /* Release previously allocated resources. */ | |
3537 | cleanup(in); | |
3538 | g_string_truncate(in->buf, 0); | |
3539 | ||
3540 | /* Restore part of the context, init() won't run again. */ | |
3541 | save_user_opts = inc->user_opts; | |
3542 | save_chans = inc->prev; | |
3543 | memset(inc, 0, sizeof(*inc)); | |
3544 | inc->user_opts = save_user_opts; | |
3545 | inc->prev = save_chans; | |
3546 | ||
3547 | return SR_OK; | |
3548 | } | |
3549 | ||
3550 | enum proto_option_t { | |
3551 | OPT_SAMPLERATE, | |
3552 | OPT_BITRATE, | |
3553 | OPT_PROTOCOL, | |
3554 | OPT_FRAME_FORMAT, | |
3555 | OPT_TEXTINPUT, | |
3556 | OPT_MAX, | |
3557 | }; | |
3558 | ||
3559 | static struct sr_option options[] = { | |
3560 | [OPT_SAMPLERATE] = { | |
3561 | "samplerate", "Logic data samplerate", | |
3562 | "Samplerate of generated logic traces", | |
3563 | NULL, NULL, | |
3564 | }, | |
3565 | [OPT_BITRATE] = { | |
3566 | "bitrate", "Protocol bitrate", | |
3567 | "Bitrate used in protocol's communication", | |
3568 | NULL, NULL, | |
3569 | }, | |
3570 | [OPT_PROTOCOL] = { | |
3571 | "protocol", "Protocol type", | |
3572 | "The type of protocol to generate waveforms for", | |
3573 | NULL, NULL, | |
3574 | }, | |
3575 | [OPT_FRAME_FORMAT] = { | |
3576 | "frameformat", "Protocol frame format", | |
3577 | "Textual description of the protocol's frame format", | |
3578 | NULL, NULL, | |
3579 | }, | |
3580 | [OPT_TEXTINPUT] = { | |
3581 | "textinput", "Input data is in text format", | |
3582 | "Input is not data bytes, but text formatted values", | |
3583 | NULL, NULL, | |
3584 | }, | |
3585 | [OPT_MAX] = ALL_ZERO, | |
3586 | }; | |
3587 | ||
3588 | static const struct sr_option *get_options(void) | |
3589 | { | |
3590 | GSList *l; | |
3591 | enum proto_type_t p_idx; | |
3592 | enum textinput_t t_idx; | |
3593 | const char *s; | |
3594 | ||
3595 | if (options[0].def) | |
3596 | return options; | |
3597 | ||
3598 | options[OPT_SAMPLERATE].def = g_variant_ref_sink(g_variant_new_uint64(0)); | |
3599 | options[OPT_BITRATE].def = g_variant_ref_sink(g_variant_new_uint64(0)); | |
3600 | options[OPT_PROTOCOL].def = g_variant_ref_sink(g_variant_new_string("")); | |
3601 | l = NULL; | |
3602 | for (p_idx = 0; p_idx < ARRAY_SIZE(protocols); p_idx++) { | |
3603 | s = protocols[p_idx].name; | |
3604 | if (!s || !*s) | |
3605 | continue; | |
3606 | l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string(s))); | |
3607 | } | |
3608 | options[OPT_PROTOCOL].values = l; | |
3609 | options[OPT_FRAME_FORMAT].def = g_variant_ref_sink(g_variant_new_string("")); | |
3610 | l = NULL; | |
3611 | for (t_idx = INPUT_UNSPEC; t_idx <= INPUT_TEXT; t_idx++) { | |
3612 | s = input_format_texts[t_idx]; | |
3613 | l = g_slist_append(l, g_variant_ref_sink(g_variant_new_string(s))); | |
3614 | } | |
3615 | options[OPT_TEXTINPUT].values = l; | |
3616 | options[OPT_TEXTINPUT].def = g_variant_ref_sink(g_variant_new_string( | |
3617 | input_format_texts[INPUT_UNSPEC])); | |
3618 | return options; | |
3619 | } | |
3620 | ||
3621 | SR_PRIV struct sr_input_module input_protocoldata = { | |
3622 | .id = "protocoldata", | |
3623 | .name = "Protocol data", | |
3624 | .desc = "Generate logic traces from protocol's data values", | |
3625 | .exts = (const char *[]){ "sr-protocol", "protocol", "bin", NULL, }, | |
3626 | .metadata = { SR_INPUT_META_HEADER | SR_INPUT_META_REQUIRED }, | |
3627 | .options = get_options, | |
3628 | .format_match = format_match, | |
3629 | .init = init, | |
3630 | .receive = receive, | |
3631 | .end = end, | |
3632 | .reset = reset, | |
3633 | }; |