]>
Commit | Line | Data |
---|---|---|
d375b3c3 AG |
1 | /* |
2 | * This file is part of the sigrok project. | |
3 | * | |
4 | * Copyright (C) 2012 Bert Vermeulen <bert@biot.com> | |
5 | * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com> | |
6 | * | |
7 | * This program is free software: you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation, either version 3 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
20 | ||
d375b3c3 AG |
21 | #include <stdlib.h> |
22 | #include <math.h> | |
23 | #include <string.h> | |
24 | #include <errno.h> | |
ba6383f8 UH |
25 | #include <glib.h> |
26 | #include "libsigrok.h" | |
27 | #include "libsigrok-internal.h" | |
936e27f1 | 28 | #include "protocol.h" |
ba6383f8 | 29 | |
4e172b8f UH |
30 | /* Byte 1 of the packet, and the modes it represents */ |
31 | #define IND1_HZ 0x80 | |
32 | #define IND1_OHM 0x40 | |
33 | #define IND1_KILO 0x20 | |
34 | #define IND1_MEGA 0x10 | |
35 | #define IND1_FARAD 0x08 | |
36 | #define IND1_AMP 0x04 | |
37 | #define IND1_VOLT 0x02 | |
38 | #define IND1_MILI 0x01 | |
39 | /* Byte 2 of the packet, and the modes it represents */ | |
40 | #define IND2_MICRO 0x80 | |
41 | #define IND2_NANO 0x40 | |
42 | #define IND2_DBM 0x20 | |
43 | #define IND2_SEC 0x10 | |
44 | #define IND2_DUTY 0x08 | |
45 | #define IND2_HFE 0x04 | |
46 | #define IND2_REL 0x02 | |
47 | #define IND2_MIN 0x01 | |
48 | /* Byte 7 of the packet, and the modes it represents */ | |
49 | #define INFO_BEEP 0x80 | |
50 | #define INFO_DIODE 0x30 | |
51 | #define INFO_BAT 0x20 | |
52 | #define INFO_HOLD 0x10 | |
53 | #define INFO_NEG 0x08 | |
54 | #define INFO_AC 0x04 | |
55 | #define INFO_RS232 0x02 | |
56 | #define INFO_AUTO 0x01 | |
57 | /* Instead of a decimal point, digit 4 carries the MAX flag */ | |
58 | #define DIG4_MAX 0x08 | |
59 | /* Mask to remove the decimal point from a digit */ | |
60 | #define DP_MASK 0x08 | |
61 | ||
62 | /* What the LCD values represent */ | |
63 | #define LCD_0 0xd7 | |
64 | #define LCD_1 0x50 | |
65 | #define LCD_2 0xb5 | |
66 | #define LCD_3 0xf1 | |
67 | #define LCD_4 0x72 | |
68 | #define LCD_5 0xe3 | |
69 | #define LCD_6 0xe7 | |
70 | #define LCD_7 0x51 | |
71 | #define LCD_8 0xf7 | |
72 | #define LCD_9 0xf3 | |
73 | ||
74 | #define LCD_C 0x87 | |
75 | #define LCD_E | |
76 | #define LCD_F | |
77 | #define LCD_h 0x66 | |
78 | #define LCD_H 0x76 | |
79 | #define LCD_I | |
80 | #define LCD_n | |
81 | #define LCD_P 0x37 | |
82 | #define LCD_r | |
83 | ||
84 | enum { | |
85 | MODE_DC_V = 0, | |
86 | MODE_AC_V = 1, | |
87 | MODE_DC_UA = 2, | |
88 | MODE_DC_MA = 3, | |
89 | MODE_DC_A = 4, | |
90 | MODE_AC_UA = 5, | |
91 | MODE_AC_MA = 6, | |
92 | MODE_AC_A = 7, | |
93 | MODE_OHM = 8, | |
94 | MODE_FARAD = 9, | |
95 | MODE_HZ = 10, | |
96 | MODE_VOLT_HZ = 11, | |
97 | MODE_AMP_HZ = 12, | |
98 | MODE_DUTY = 13, | |
99 | MODE_VOLT_DUTY = 14, | |
100 | MODE_AMP_DUTY = 15, | |
101 | MODE_WIDTH = 16, | |
102 | MODE_VOLT_WIDTH = 17, | |
103 | MODE_AMP_WIDTH = 18, | |
104 | MODE_DIODE = 19, | |
105 | MODE_CONT = 20, | |
106 | MODE_HFE = 21, | |
107 | MODE_LOGIC = 22, | |
108 | MODE_DBM = 23, | |
109 | // MODE_EF = 24, | |
110 | MODE_TEMP = 25, | |
111 | MODE_INVALID = 26, | |
112 | }; | |
113 | ||
ba6383f8 UH |
114 | enum { |
115 | READ_ALL, | |
116 | READ_TEMP, | |
117 | }; | |
d375b3c3 | 118 | |
ba6383f8 | 119 | static gboolean checksum_valid(const struct rs_22_812_packet *rs_packet) |
d375b3c3 | 120 | { |
ba6383f8 | 121 | uint8_t *raw; |
d375b3c3 | 122 | uint8_t sum = 0; |
ba6383f8 UH |
123 | int i; |
124 | ||
125 | raw = (void *)rs_packet; | |
126 | ||
127 | for (i = 0; i < RS_22_812_PACKET_SIZE - 1; i++) | |
d375b3c3 | 128 | sum += raw[i]; |
ba6383f8 UH |
129 | |
130 | /* This is just a funky constant added to the checksum. */ | |
d375b3c3 | 131 | sum += 57; |
ba6383f8 UH |
132 | sum -= rs_packet->checksum; |
133 | return (sum == 0); | |
d375b3c3 AG |
134 | } |
135 | ||
ba6383f8 | 136 | static gboolean selection_good(const struct rs_22_812_packet *rs_packet) |
d375b3c3 | 137 | { |
ba6383f8 | 138 | int count; |
d375b3c3 | 139 | |
d375b3c3 | 140 | /* Does the packet have more than one multiplier ? */ |
ba6383f8 | 141 | count = 0; |
4e172b8f UH |
142 | count += (rs_packet->indicatrix1 & IND1_KILO) ? 1 : 0; |
143 | count += (rs_packet->indicatrix1 & IND1_MEGA) ? 1 : 0; | |
144 | count += (rs_packet->indicatrix1 & IND1_MILI) ? 1 : 0; | |
145 | count += (rs_packet->indicatrix2 & IND2_MICRO) ? 1 : 0; | |
146 | count += (rs_packet->indicatrix2 & IND2_NANO) ? 1 : 0; | |
ba6383f8 UH |
147 | if (count > 1) { |
148 | sr_err("More than one multiplier detected in packet."); | |
d375b3c3 | 149 | return FALSE; |
ba6383f8 | 150 | } |
d375b3c3 | 151 | |
ba6383f8 UH |
152 | /* Does the packet "measure" more than one type of value? */ |
153 | count = 0; | |
4e172b8f UH |
154 | count += (rs_packet->indicatrix1 & IND1_HZ) ? 1 : 0; |
155 | count += (rs_packet->indicatrix1 & IND1_OHM) ? 1 : 0; | |
156 | count += (rs_packet->indicatrix1 & IND1_FARAD) ? 1 : 0; | |
157 | count += (rs_packet->indicatrix1 & IND1_AMP) ? 1 : 0; | |
158 | count += (rs_packet->indicatrix1 & IND1_VOLT) ? 1 : 0; | |
159 | count += (rs_packet->indicatrix2 & IND2_DBM) ? 1 : 0; | |
160 | count += (rs_packet->indicatrix2 & IND2_SEC) ? 1 : 0; | |
161 | count += (rs_packet->indicatrix2 & IND2_DUTY) ? 1 : 0; | |
162 | count += (rs_packet->indicatrix2 & IND2_HFE) ? 1 : 0; | |
ba6383f8 UH |
163 | if (count > 1) { |
164 | sr_err("More than one measurement type detected in packet."); | |
d375b3c3 | 165 | return FALSE; |
ba6383f8 | 166 | } |
d375b3c3 | 167 | |
d375b3c3 AG |
168 | return TRUE; |
169 | } | |
170 | ||
ba6383f8 UH |
171 | /* |
172 | * Since the 22-812 does not identify itself in any way, shape, or form, | |
d375b3c3 AG |
173 | * we really don't know for sure who is sending the data. We must use every |
174 | * possible check to filter out bad packets, especially since detection of the | |
ba6383f8 UH |
175 | * 22-812 depends on how well we can filter the packets. |
176 | */ | |
177 | SR_PRIV gboolean rs_22_812_packet_valid(const struct rs_22_812_packet *rs_packet) | |
d375b3c3 | 178 | { |
ba6383f8 | 179 | if (!checksum_valid(rs_packet)) |
d375b3c3 AG |
180 | return FALSE; |
181 | ||
4e172b8f | 182 | if (!(rs_packet->mode < MODE_INVALID)) |
d375b3c3 AG |
183 | return FALSE; |
184 | ||
ba6383f8 | 185 | if (!selection_good(rs_packet)) |
d375b3c3 | 186 | return FALSE; |
ba6383f8 | 187 | |
d375b3c3 AG |
188 | return TRUE; |
189 | } | |
190 | ||
ba6383f8 | 191 | static uint8_t decode_digit(uint8_t raw_digit) |
d375b3c3 | 192 | { |
ba6383f8 | 193 | /* Take out the decimal point, so we can use a simple switch(). */ |
4e172b8f | 194 | raw_digit &= ~DP_MASK; |
ba6383f8 UH |
195 | |
196 | switch (raw_digit) { | |
d375b3c3 | 197 | case 0x00: |
4e172b8f | 198 | case LCD_0: |
d375b3c3 | 199 | return 0; |
4e172b8f | 200 | case LCD_1: |
d375b3c3 | 201 | return 1; |
4e172b8f | 202 | case LCD_2: |
d375b3c3 | 203 | return 2; |
4e172b8f | 204 | case LCD_3: |
d375b3c3 | 205 | return 3; |
4e172b8f | 206 | case LCD_4: |
d375b3c3 | 207 | return 4; |
4e172b8f | 208 | case LCD_5: |
d375b3c3 | 209 | return 5; |
4e172b8f | 210 | case LCD_6: |
d375b3c3 | 211 | return 6; |
4e172b8f | 212 | case LCD_7: |
d375b3c3 | 213 | return 7; |
4e172b8f | 214 | case LCD_8: |
d375b3c3 | 215 | return 8; |
4e172b8f | 216 | case LCD_9: |
d375b3c3 AG |
217 | return 9; |
218 | default: | |
ba6383f8 | 219 | sr_err("Invalid digit byte: 0x%02x.", raw_digit); |
d375b3c3 AG |
220 | return 0xff; |
221 | } | |
222 | } | |
223 | ||
4e172b8f | 224 | static double lcd_to_double(const struct rs_22_812_packet *rs_packet, int type) |
d375b3c3 | 225 | { |
ba6383f8 UH |
226 | double rawval, multiplier = 1; |
227 | uint8_t digit, raw_digit; | |
d375b3c3 AG |
228 | gboolean dp_reached = FALSE; |
229 | int i, end; | |
ba6383f8 UH |
230 | |
231 | /* end = 1: Don't parse last digit. end = 0: Parse all digits. */ | |
232 | end = (type == READ_TEMP) ? 1 : 0; | |
233 | ||
234 | /* We have 4 digits, and we start from the most significant. */ | |
235 | for (i = 3; i >= end; i--) { | |
236 | raw_digit = *(&(rs_packet->digit4) + i); | |
237 | digit = decode_digit(raw_digit); | |
238 | if (digit == 0xff) { | |
d375b3c3 AG |
239 | rawval = NAN; |
240 | break; | |
241 | } | |
ba6383f8 UH |
242 | /* |
243 | * Digit 1 does not have a decimal point. Instead, the decimal | |
244 | * point is used to indicate MAX, so we must avoid testing it. | |
245 | */ | |
4e172b8f | 246 | if ((i < 3) && (raw_digit & DP_MASK)) |
d375b3c3 | 247 | dp_reached = TRUE; |
ba6383f8 UH |
248 | if (dp_reached) |
249 | multiplier /= 10; | |
d375b3c3 AG |
250 | rawval = rawval * 10 + digit; |
251 | } | |
252 | rawval *= multiplier; | |
4e172b8f | 253 | if (rs_packet->info & INFO_NEG) |
d375b3c3 AG |
254 | rawval *= -1; |
255 | ||
ba6383f8 | 256 | /* See if we need to multiply our raw value by anything. */ |
4e172b8f | 257 | if (rs_packet->indicatrix1 & IND2_NANO) { |
d375b3c3 | 258 | rawval *= 1E-9; |
4e172b8f | 259 | } else if (rs_packet->indicatrix2 & IND2_MICRO) { |
d375b3c3 | 260 | rawval *= 1E-6; |
4e172b8f | 261 | } else if (rs_packet->indicatrix1 & IND1_MILI) { |
d375b3c3 | 262 | rawval *= 1E-3; |
4e172b8f | 263 | } else if (rs_packet->indicatrix1 & IND1_KILO) { |
d375b3c3 | 264 | rawval *= 1E3; |
4e172b8f | 265 | } else if (rs_packet->indicatrix1 & IND1_MEGA) { |
d375b3c3 AG |
266 | rawval *= 1E6; |
267 | } | |
268 | ||
269 | return rawval; | |
270 | } | |
271 | ||
ba6383f8 | 272 | static gboolean is_celsius(struct rs_22_812_packet *rs_packet) |
d375b3c3 | 273 | { |
4e172b8f | 274 | return ((rs_packet->digit4 & ~DP_MASK) == LCD_C); |
d375b3c3 AG |
275 | } |
276 | ||
ba6383f8 | 277 | static gboolean is_shortcirc(struct rs_22_812_packet *rs_packet) |
d375b3c3 | 278 | { |
4e172b8f | 279 | return ((rs_packet->digit2 & ~DP_MASK) == LCD_h); |
d375b3c3 AG |
280 | } |
281 | ||
ba6383f8 | 282 | static gboolean is_logic_high(struct rs_22_812_packet *rs_packet) |
7c41dc47 | 283 | { |
4e172b8f UH |
284 | sr_spew("Digit 2: 0x%02x.", rs_packet->digit2 & ~DP_MASK); |
285 | return ((rs_packet->digit2 & ~DP_MASK) == LCD_H); | |
7c41dc47 AG |
286 | } |
287 | ||
ba6383f8 UH |
288 | static void handle_packet(struct rs_22_812_packet *rs_packet, |
289 | struct dev_context *devc) | |
d375b3c3 | 290 | { |
ba6383f8 | 291 | double rawval; |
d375b3c3 AG |
292 | struct sr_datafeed_packet packet; |
293 | struct sr_datafeed_analog *analog; | |
294 | ||
4e172b8f | 295 | rawval = lcd_to_double(rs_packet, READ_ALL); |
ba6383f8 | 296 | |
886a52b6 | 297 | /* TODO: Check malloc return value. */ |
d375b3c3 AG |
298 | analog = g_try_malloc0(sizeof(struct sr_datafeed_analog)); |
299 | analog->num_samples = 1; | |
886a52b6 | 300 | /* TODO: Check malloc return value. */ |
d375b3c3 AG |
301 | analog->data = g_try_malloc(sizeof(float)); |
302 | *analog->data = (float)rawval; | |
303 | analog->mq = -1; | |
304 | ||
ba6383f8 | 305 | switch (rs_packet->mode) { |
4e172b8f | 306 | case MODE_DC_V: |
d375b3c3 AG |
307 | analog->mq = SR_MQ_VOLTAGE; |
308 | analog->unit = SR_UNIT_VOLT; | |
309 | analog->mqflags |= SR_MQFLAG_DC; | |
310 | break; | |
4e172b8f | 311 | case MODE_AC_V: |
d375b3c3 AG |
312 | analog->mq = SR_MQ_VOLTAGE; |
313 | analog->unit = SR_UNIT_VOLT; | |
314 | analog->mqflags |= SR_MQFLAG_AC; | |
315 | break; | |
4e172b8f UH |
316 | case MODE_DC_UA: |
317 | case MODE_DC_MA: | |
318 | case MODE_DC_A: | |
d375b3c3 AG |
319 | analog->mq = SR_MQ_CURRENT; |
320 | analog->unit = SR_UNIT_AMPERE; | |
321 | analog->mqflags |= SR_MQFLAG_DC; | |
322 | break; | |
4e172b8f UH |
323 | case MODE_AC_UA: |
324 | case MODE_AC_MA: | |
325 | case MODE_AC_A: | |
d375b3c3 AG |
326 | analog->mq = SR_MQ_CURRENT; |
327 | analog->unit = SR_UNIT_AMPERE; | |
328 | analog->mqflags |= SR_MQFLAG_AC; | |
329 | break; | |
4e172b8f | 330 | case MODE_OHM: |
d375b3c3 AG |
331 | analog->mq = SR_MQ_RESISTANCE; |
332 | analog->unit = SR_UNIT_OHM; | |
333 | break; | |
4e172b8f | 334 | case MODE_FARAD: |
d375b3c3 AG |
335 | analog->mq = SR_MQ_CAPACITANCE; |
336 | analog->unit = SR_UNIT_FARAD; | |
337 | break; | |
4e172b8f | 338 | case MODE_CONT: |
d375b3c3 AG |
339 | analog->mq = SR_MQ_CONTINUITY; |
340 | analog->unit = SR_UNIT_BOOLEAN; | |
ba6383f8 | 341 | *analog->data = is_shortcirc(rs_packet); |
d375b3c3 | 342 | break; |
4e172b8f | 343 | case MODE_DIODE: |
d375b3c3 AG |
344 | analog->mq = SR_MQ_VOLTAGE; |
345 | analog->unit = SR_UNIT_VOLT; | |
346 | analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; | |
347 | break; | |
4e172b8f UH |
348 | case MODE_HZ: |
349 | case MODE_VOLT_HZ: | |
350 | case MODE_AMP_HZ: | |
d375b3c3 AG |
351 | analog->mq = SR_MQ_FREQUENCY; |
352 | analog->unit = SR_UNIT_HERTZ; | |
353 | break; | |
4e172b8f | 354 | case MODE_LOGIC: |
ba6383f8 UH |
355 | /* |
356 | * No matter whether or not we have an actual voltage reading, | |
357 | * we are measuring voltage, so we set our MQ as VOLTAGE. | |
358 | */ | |
7c41dc47 | 359 | analog->mq = SR_MQ_VOLTAGE; |
ba6383f8 UH |
360 | if (!isnan(rawval)) { |
361 | /* We have an actual voltage. */ | |
7c41dc47 AG |
362 | analog->unit = SR_UNIT_VOLT; |
363 | } else { | |
ba6383f8 | 364 | /* We have either HI or LOW. */ |
7c41dc47 | 365 | analog->unit = SR_UNIT_BOOLEAN; |
ba6383f8 | 366 | *analog->data = is_logic_high(rs_packet); |
7c41dc47 | 367 | } |
d375b3c3 | 368 | break; |
4e172b8f | 369 | case MODE_HFE: |
d375b3c3 AG |
370 | analog->mq = SR_MQ_GAIN; |
371 | analog->unit = SR_UNIT_UNITLESS; | |
372 | break; | |
4e172b8f UH |
373 | case MODE_DUTY: |
374 | case MODE_VOLT_DUTY: | |
375 | case MODE_AMP_DUTY: | |
d375b3c3 AG |
376 | analog->mq = SR_MQ_DUTY_CYCLE; |
377 | analog->unit = SR_UNIT_PERCENTAGE; | |
378 | break; | |
4e172b8f UH |
379 | case MODE_WIDTH: |
380 | case MODE_VOLT_WIDTH: | |
381 | case MODE_AMP_WIDTH: | |
d375b3c3 AG |
382 | analog->mq = SR_MQ_PULSE_WIDTH; |
383 | analog->unit = SR_UNIT_SECOND; | |
4e172b8f | 384 | case MODE_TEMP: |
d375b3c3 | 385 | analog->mq = SR_MQ_TEMPERATURE; |
ba6383f8 | 386 | /* We need to reparse. */ |
4e172b8f | 387 | *analog->data = lcd_to_double(rs_packet, READ_TEMP); |
ba6383f8 UH |
388 | analog->unit = is_celsius(rs_packet) ? |
389 | SR_UNIT_CELSIUS : SR_UNIT_FAHRENHEIT; | |
d375b3c3 | 390 | break; |
4e172b8f | 391 | case MODE_DBM: |
d375b3c3 AG |
392 | analog->mq = SR_MQ_POWER; |
393 | analog->unit = SR_UNIT_DECIBEL_MW; | |
394 | analog->mqflags |= SR_MQFLAG_AC; | |
395 | break; | |
396 | default: | |
ba6383f8 | 397 | sr_err("Unknown mode: %d.", rs_packet->mode); |
d375b3c3 AG |
398 | break; |
399 | } | |
400 | ||
4e172b8f | 401 | if (rs_packet->info & INFO_HOLD) |
d375b3c3 | 402 | analog->mqflags |= SR_MQFLAG_HOLD; |
4e172b8f | 403 | if (rs_packet->digit4 & DIG4_MAX) |
d375b3c3 | 404 | analog->mqflags |= SR_MQFLAG_MAX; |
4e172b8f | 405 | if (rs_packet->indicatrix2 & IND2_MIN) |
d375b3c3 | 406 | analog->mqflags |= SR_MQFLAG_MIN; |
4e172b8f | 407 | if (rs_packet->info & INFO_AUTO) |
d375b3c3 | 408 | analog->mqflags |= SR_MQFLAG_AUTORANGE; |
d375b3c3 AG |
409 | |
410 | if (analog->mq != -1) { | |
411 | /* Got a measurement. */ | |
dccbd0ed | 412 | sr_spew("Value: %f.", rawval); |
d375b3c3 AG |
413 | packet.type = SR_DF_ANALOG; |
414 | packet.payload = analog; | |
415 | sr_session_send(devc->cb_data, &packet); | |
416 | devc->num_samples++; | |
417 | } | |
418 | g_free(analog->data); | |
419 | g_free(analog); | |
420 | } | |
421 | ||
ba6383f8 | 422 | static void handle_new_data(struct dev_context *devc, int fd) |
d375b3c3 AG |
423 | { |
424 | int len; | |
ba6383f8 UH |
425 | size_t i, offset = 0; |
426 | struct rs_22_812_packet *rs_packet; | |
427 | ||
428 | /* Try to get as much data as the buffer can hold. */ | |
d375b3c3 AG |
429 | len = RS_DMM_BUFSIZE - devc->buflen; |
430 | len = serial_read(fd, devc->buf + devc->buflen, len); | |
431 | if (len < 1) { | |
ba6383f8 | 432 | sr_err("Serial port read error."); |
d375b3c3 AG |
433 | return; |
434 | } | |
435 | devc->buflen += len; | |
436 | ||
ba6383f8 UH |
437 | /* Now look for packets in that data. */ |
438 | while ((devc->buflen - offset) >= RS_22_812_PACKET_SIZE) { | |
439 | rs_packet = (void *)(devc->buf + offset); | |
440 | if (rs_22_812_packet_valid(rs_packet)) { | |
441 | handle_packet(rs_packet, devc); | |
d375b3c3 AG |
442 | offset += RS_22_812_PACKET_SIZE; |
443 | } else { | |
444 | offset++; | |
445 | } | |
446 | } | |
447 | ||
ba6383f8 UH |
448 | /* If we have any data left, move it to the beginning of our buffer. */ |
449 | for (i = 0; i < devc->buflen - offset; i++) | |
d375b3c3 AG |
450 | devc->buf[i] = devc->buf[offset + i]; |
451 | devc->buflen -= offset; | |
452 | } | |
453 | ||
ba6383f8 | 454 | SR_PRIV int radioshack_dmm_receive_data(int fd, int revents, void *cb_data) |
d375b3c3 | 455 | { |
642e9d62 | 456 | struct sr_dev_inst *sdi; |
d375b3c3 AG |
457 | struct dev_context *devc; |
458 | ||
459 | if (!(sdi = cb_data)) | |
460 | return TRUE; | |
461 | ||
462 | if (!(devc = sdi->priv)) | |
463 | return TRUE; | |
464 | ||
ba6383f8 | 465 | if (revents == G_IO_IN) { |
d375b3c3 AG |
466 | /* Serial data arrived. */ |
467 | handle_new_data(devc, fd); | |
468 | } | |
469 | ||
470 | if (devc->num_samples >= devc->limit_samples) { | |
471 | sdi->driver->dev_acquisition_stop(sdi, cb_data); | |
472 | return TRUE; | |
473 | } | |
474 | ||
475 | return TRUE; | |
476 | } |