]>
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 | { |
2ecc5d43 AG |
179 | /* |
180 | * Check for valid mode first, before calculating the checksum. | |
181 | * No point calculating the checksum, if we know we'll reject the packet | |
182 | * */ | |
183 | if (!(rs_packet->mode < MODE_INVALID)) | |
d375b3c3 AG |
184 | return FALSE; |
185 | ||
90473587 AG |
186 | if (!checksum_valid(rs_packet)) { |
187 | sr_spew("Packet with invalid checksum. Discarding."); | |
d375b3c3 | 188 | return FALSE; |
90473587 | 189 | } |
d375b3c3 | 190 | |
90473587 AG |
191 | if (!selection_good(rs_packet)) { |
192 | sr_spew("Packet with invalid selection bits. Discarding."); | |
d375b3c3 | 193 | return FALSE; |
90473587 | 194 | } |
ba6383f8 | 195 | |
d375b3c3 AG |
196 | return TRUE; |
197 | } | |
198 | ||
ba6383f8 | 199 | static uint8_t decode_digit(uint8_t raw_digit) |
d375b3c3 | 200 | { |
ba6383f8 | 201 | /* Take out the decimal point, so we can use a simple switch(). */ |
4e172b8f | 202 | raw_digit &= ~DP_MASK; |
ba6383f8 UH |
203 | |
204 | switch (raw_digit) { | |
d375b3c3 | 205 | case 0x00: |
4e172b8f | 206 | case LCD_0: |
d375b3c3 | 207 | return 0; |
4e172b8f | 208 | case LCD_1: |
d375b3c3 | 209 | return 1; |
4e172b8f | 210 | case LCD_2: |
d375b3c3 | 211 | return 2; |
4e172b8f | 212 | case LCD_3: |
d375b3c3 | 213 | return 3; |
4e172b8f | 214 | case LCD_4: |
d375b3c3 | 215 | return 4; |
4e172b8f | 216 | case LCD_5: |
d375b3c3 | 217 | return 5; |
4e172b8f | 218 | case LCD_6: |
d375b3c3 | 219 | return 6; |
4e172b8f | 220 | case LCD_7: |
d375b3c3 | 221 | return 7; |
4e172b8f | 222 | case LCD_8: |
d375b3c3 | 223 | return 8; |
4e172b8f | 224 | case LCD_9: |
d375b3c3 AG |
225 | return 9; |
226 | default: | |
ba6383f8 | 227 | sr_err("Invalid digit byte: 0x%02x.", raw_digit); |
d375b3c3 AG |
228 | return 0xff; |
229 | } | |
230 | } | |
231 | ||
4e172b8f | 232 | static double lcd_to_double(const struct rs_22_812_packet *rs_packet, int type) |
d375b3c3 | 233 | { |
ba6383f8 UH |
234 | double rawval, multiplier = 1; |
235 | uint8_t digit, raw_digit; | |
d375b3c3 AG |
236 | gboolean dp_reached = FALSE; |
237 | int i, end; | |
ba6383f8 UH |
238 | |
239 | /* end = 1: Don't parse last digit. end = 0: Parse all digits. */ | |
240 | end = (type == READ_TEMP) ? 1 : 0; | |
241 | ||
242 | /* We have 4 digits, and we start from the most significant. */ | |
243 | for (i = 3; i >= end; i--) { | |
244 | raw_digit = *(&(rs_packet->digit4) + i); | |
245 | digit = decode_digit(raw_digit); | |
246 | if (digit == 0xff) { | |
d375b3c3 AG |
247 | rawval = NAN; |
248 | break; | |
249 | } | |
ba6383f8 UH |
250 | /* |
251 | * Digit 1 does not have a decimal point. Instead, the decimal | |
252 | * point is used to indicate MAX, so we must avoid testing it. | |
253 | */ | |
4e172b8f | 254 | if ((i < 3) && (raw_digit & DP_MASK)) |
d375b3c3 | 255 | dp_reached = TRUE; |
ba6383f8 UH |
256 | if (dp_reached) |
257 | multiplier /= 10; | |
d375b3c3 AG |
258 | rawval = rawval * 10 + digit; |
259 | } | |
260 | rawval *= multiplier; | |
4e172b8f | 261 | if (rs_packet->info & INFO_NEG) |
d375b3c3 AG |
262 | rawval *= -1; |
263 | ||
ba6383f8 | 264 | /* See if we need to multiply our raw value by anything. */ |
4e172b8f | 265 | if (rs_packet->indicatrix1 & IND2_NANO) { |
d375b3c3 | 266 | rawval *= 1E-9; |
4e172b8f | 267 | } else if (rs_packet->indicatrix2 & IND2_MICRO) { |
d375b3c3 | 268 | rawval *= 1E-6; |
4e172b8f | 269 | } else if (rs_packet->indicatrix1 & IND1_MILI) { |
d375b3c3 | 270 | rawval *= 1E-3; |
4e172b8f | 271 | } else if (rs_packet->indicatrix1 & IND1_KILO) { |
d375b3c3 | 272 | rawval *= 1E3; |
4e172b8f | 273 | } else if (rs_packet->indicatrix1 & IND1_MEGA) { |
d375b3c3 AG |
274 | rawval *= 1E6; |
275 | } | |
276 | ||
277 | return rawval; | |
278 | } | |
279 | ||
ba6383f8 | 280 | static gboolean is_celsius(struct rs_22_812_packet *rs_packet) |
d375b3c3 | 281 | { |
4e172b8f | 282 | return ((rs_packet->digit4 & ~DP_MASK) == LCD_C); |
d375b3c3 AG |
283 | } |
284 | ||
ba6383f8 | 285 | static gboolean is_shortcirc(struct rs_22_812_packet *rs_packet) |
d375b3c3 | 286 | { |
4e172b8f | 287 | return ((rs_packet->digit2 & ~DP_MASK) == LCD_h); |
d375b3c3 AG |
288 | } |
289 | ||
ba6383f8 | 290 | static gboolean is_logic_high(struct rs_22_812_packet *rs_packet) |
7c41dc47 | 291 | { |
4e172b8f UH |
292 | sr_spew("Digit 2: 0x%02x.", rs_packet->digit2 & ~DP_MASK); |
293 | return ((rs_packet->digit2 & ~DP_MASK) == LCD_H); | |
7c41dc47 AG |
294 | } |
295 | ||
ba6383f8 UH |
296 | static void handle_packet(struct rs_22_812_packet *rs_packet, |
297 | struct dev_context *devc) | |
d375b3c3 | 298 | { |
ba6383f8 | 299 | double rawval; |
d375b3c3 AG |
300 | struct sr_datafeed_packet packet; |
301 | struct sr_datafeed_analog *analog; | |
302 | ||
4e172b8f | 303 | rawval = lcd_to_double(rs_packet, READ_ALL); |
ba6383f8 | 304 | |
886a52b6 | 305 | /* TODO: Check malloc return value. */ |
d375b3c3 AG |
306 | analog = g_try_malloc0(sizeof(struct sr_datafeed_analog)); |
307 | analog->num_samples = 1; | |
886a52b6 | 308 | /* TODO: Check malloc return value. */ |
d375b3c3 AG |
309 | analog->data = g_try_malloc(sizeof(float)); |
310 | *analog->data = (float)rawval; | |
311 | analog->mq = -1; | |
312 | ||
ba6383f8 | 313 | switch (rs_packet->mode) { |
4e172b8f | 314 | case MODE_DC_V: |
d375b3c3 AG |
315 | analog->mq = SR_MQ_VOLTAGE; |
316 | analog->unit = SR_UNIT_VOLT; | |
317 | analog->mqflags |= SR_MQFLAG_DC; | |
318 | break; | |
4e172b8f | 319 | case MODE_AC_V: |
d375b3c3 AG |
320 | analog->mq = SR_MQ_VOLTAGE; |
321 | analog->unit = SR_UNIT_VOLT; | |
322 | analog->mqflags |= SR_MQFLAG_AC; | |
323 | break; | |
4e172b8f UH |
324 | case MODE_DC_UA: |
325 | case MODE_DC_MA: | |
326 | case MODE_DC_A: | |
d375b3c3 AG |
327 | analog->mq = SR_MQ_CURRENT; |
328 | analog->unit = SR_UNIT_AMPERE; | |
329 | analog->mqflags |= SR_MQFLAG_DC; | |
330 | break; | |
4e172b8f UH |
331 | case MODE_AC_UA: |
332 | case MODE_AC_MA: | |
333 | case MODE_AC_A: | |
d375b3c3 AG |
334 | analog->mq = SR_MQ_CURRENT; |
335 | analog->unit = SR_UNIT_AMPERE; | |
336 | analog->mqflags |= SR_MQFLAG_AC; | |
337 | break; | |
4e172b8f | 338 | case MODE_OHM: |
d375b3c3 AG |
339 | analog->mq = SR_MQ_RESISTANCE; |
340 | analog->unit = SR_UNIT_OHM; | |
341 | break; | |
4e172b8f | 342 | case MODE_FARAD: |
d375b3c3 AG |
343 | analog->mq = SR_MQ_CAPACITANCE; |
344 | analog->unit = SR_UNIT_FARAD; | |
345 | break; | |
4e172b8f | 346 | case MODE_CONT: |
d375b3c3 AG |
347 | analog->mq = SR_MQ_CONTINUITY; |
348 | analog->unit = SR_UNIT_BOOLEAN; | |
ba6383f8 | 349 | *analog->data = is_shortcirc(rs_packet); |
d375b3c3 | 350 | break; |
4e172b8f | 351 | case MODE_DIODE: |
d375b3c3 AG |
352 | analog->mq = SR_MQ_VOLTAGE; |
353 | analog->unit = SR_UNIT_VOLT; | |
354 | analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; | |
355 | break; | |
4e172b8f UH |
356 | case MODE_HZ: |
357 | case MODE_VOLT_HZ: | |
358 | case MODE_AMP_HZ: | |
d375b3c3 AG |
359 | analog->mq = SR_MQ_FREQUENCY; |
360 | analog->unit = SR_UNIT_HERTZ; | |
361 | break; | |
4e172b8f | 362 | case MODE_LOGIC: |
ba6383f8 UH |
363 | /* |
364 | * No matter whether or not we have an actual voltage reading, | |
365 | * we are measuring voltage, so we set our MQ as VOLTAGE. | |
366 | */ | |
7c41dc47 | 367 | analog->mq = SR_MQ_VOLTAGE; |
ba6383f8 UH |
368 | if (!isnan(rawval)) { |
369 | /* We have an actual voltage. */ | |
7c41dc47 AG |
370 | analog->unit = SR_UNIT_VOLT; |
371 | } else { | |
ba6383f8 | 372 | /* We have either HI or LOW. */ |
7c41dc47 | 373 | analog->unit = SR_UNIT_BOOLEAN; |
ba6383f8 | 374 | *analog->data = is_logic_high(rs_packet); |
7c41dc47 | 375 | } |
d375b3c3 | 376 | break; |
4e172b8f | 377 | case MODE_HFE: |
d375b3c3 AG |
378 | analog->mq = SR_MQ_GAIN; |
379 | analog->unit = SR_UNIT_UNITLESS; | |
380 | break; | |
4e172b8f UH |
381 | case MODE_DUTY: |
382 | case MODE_VOLT_DUTY: | |
383 | case MODE_AMP_DUTY: | |
d375b3c3 AG |
384 | analog->mq = SR_MQ_DUTY_CYCLE; |
385 | analog->unit = SR_UNIT_PERCENTAGE; | |
386 | break; | |
4e172b8f UH |
387 | case MODE_WIDTH: |
388 | case MODE_VOLT_WIDTH: | |
389 | case MODE_AMP_WIDTH: | |
d375b3c3 AG |
390 | analog->mq = SR_MQ_PULSE_WIDTH; |
391 | analog->unit = SR_UNIT_SECOND; | |
4e172b8f | 392 | case MODE_TEMP: |
d375b3c3 | 393 | analog->mq = SR_MQ_TEMPERATURE; |
ba6383f8 | 394 | /* We need to reparse. */ |
4e172b8f | 395 | *analog->data = lcd_to_double(rs_packet, READ_TEMP); |
ba6383f8 UH |
396 | analog->unit = is_celsius(rs_packet) ? |
397 | SR_UNIT_CELSIUS : SR_UNIT_FAHRENHEIT; | |
d375b3c3 | 398 | break; |
4e172b8f | 399 | case MODE_DBM: |
d375b3c3 AG |
400 | analog->mq = SR_MQ_POWER; |
401 | analog->unit = SR_UNIT_DECIBEL_MW; | |
402 | analog->mqflags |= SR_MQFLAG_AC; | |
403 | break; | |
404 | default: | |
ba6383f8 | 405 | sr_err("Unknown mode: %d.", rs_packet->mode); |
d375b3c3 AG |
406 | break; |
407 | } | |
408 | ||
4e172b8f | 409 | if (rs_packet->info & INFO_HOLD) |
d375b3c3 | 410 | analog->mqflags |= SR_MQFLAG_HOLD; |
4e172b8f | 411 | if (rs_packet->digit4 & DIG4_MAX) |
d375b3c3 | 412 | analog->mqflags |= SR_MQFLAG_MAX; |
4e172b8f | 413 | if (rs_packet->indicatrix2 & IND2_MIN) |
d375b3c3 | 414 | analog->mqflags |= SR_MQFLAG_MIN; |
4e172b8f | 415 | if (rs_packet->info & INFO_AUTO) |
d375b3c3 | 416 | analog->mqflags |= SR_MQFLAG_AUTORANGE; |
d375b3c3 AG |
417 | |
418 | if (analog->mq != -1) { | |
419 | /* Got a measurement. */ | |
dccbd0ed | 420 | sr_spew("Value: %f.", rawval); |
d375b3c3 AG |
421 | packet.type = SR_DF_ANALOG; |
422 | packet.payload = analog; | |
423 | sr_session_send(devc->cb_data, &packet); | |
424 | devc->num_samples++; | |
425 | } | |
426 | g_free(analog->data); | |
427 | g_free(analog); | |
428 | } | |
429 | ||
401476da | 430 | static void handle_new_data(struct dev_context *devc) |
d375b3c3 AG |
431 | { |
432 | int len; | |
ba6383f8 UH |
433 | size_t i, offset = 0; |
434 | struct rs_22_812_packet *rs_packet; | |
435 | ||
436 | /* Try to get as much data as the buffer can hold. */ | |
d375b3c3 | 437 | len = RS_DMM_BUFSIZE - devc->buflen; |
401476da | 438 | len = serial_read(devc->serial, devc->buf + devc->buflen, len); |
d375b3c3 | 439 | if (len < 1) { |
ba6383f8 | 440 | sr_err("Serial port read error."); |
d375b3c3 AG |
441 | return; |
442 | } | |
443 | devc->buflen += len; | |
444 | ||
ba6383f8 UH |
445 | /* Now look for packets in that data. */ |
446 | while ((devc->buflen - offset) >= RS_22_812_PACKET_SIZE) { | |
447 | rs_packet = (void *)(devc->buf + offset); | |
448 | if (rs_22_812_packet_valid(rs_packet)) { | |
449 | handle_packet(rs_packet, devc); | |
d375b3c3 AG |
450 | offset += RS_22_812_PACKET_SIZE; |
451 | } else { | |
452 | offset++; | |
453 | } | |
454 | } | |
455 | ||
ba6383f8 UH |
456 | /* If we have any data left, move it to the beginning of our buffer. */ |
457 | for (i = 0; i < devc->buflen - offset; i++) | |
d375b3c3 AG |
458 | devc->buf[i] = devc->buf[offset + i]; |
459 | devc->buflen -= offset; | |
460 | } | |
461 | ||
ba6383f8 | 462 | SR_PRIV int radioshack_dmm_receive_data(int fd, int revents, void *cb_data) |
d375b3c3 | 463 | { |
642e9d62 | 464 | struct sr_dev_inst *sdi; |
d375b3c3 AG |
465 | struct dev_context *devc; |
466 | ||
401476da BV |
467 | (void)fd; |
468 | ||
d375b3c3 AG |
469 | if (!(sdi = cb_data)) |
470 | return TRUE; | |
471 | ||
472 | if (!(devc = sdi->priv)) | |
473 | return TRUE; | |
474 | ||
ba6383f8 | 475 | if (revents == G_IO_IN) { |
d375b3c3 | 476 | /* Serial data arrived. */ |
401476da | 477 | handle_new_data(devc); |
d375b3c3 AG |
478 | } |
479 | ||
480 | if (devc->num_samples >= devc->limit_samples) { | |
481 | sdi->driver->dev_acquisition_stop(sdi, cb_data); | |
482 | return TRUE; | |
483 | } | |
484 | ||
485 | return TRUE; | |
486 | } |