]> sigrok.org Git - libsigrokdecode.git/blob - decoders/modbus/pd.py
all decoders: introduce a reset() method
[libsigrokdecode.git] / decoders / modbus / pd.py
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2015 Bart de Waal <bart@waalamo.com>
5 ##
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 3 of the License, or
9 ## (at your option) any later version.
10 ##
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ## GNU General Public License for more details.
15 ##
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
18 ##
19
20 import sigrokdecode as srd
21 from math import ceil
22
23 RX = 0
24 TX = 1
25
26 class No_more_data(Exception):
27     '''This exception is a signal that we should stop parsing an ADU as there
28     is no more data to parse.'''
29     pass
30
31 class Data:
32     '''The Data class is used to hold the bytes from the serial decode.'''
33     def __init__(self, start, end, data):
34         self.start = start
35         self.end = end
36         self.data = data
37
38 class Modbus_ADU:
39     '''An Application Data Unit is what Modbus calls one message.
40     Protocol decoders are supposed to keep track of state and then provide
41     decoded data to the backend as it reads it. In Modbus' case, the state is
42     the ADU up to that point. This class represents the state and writes the
43     messages to the backend.
44     This class is for the common infrastructure between CS and SC. It should
45     not be used directly, only inhereted from.'''
46
47     def __init__(self, parent, start, write_channel, annotation_prefix):
48         self.data = [] # List of all the data received up to now
49         self.parent = parent # Reference to the decoder object
50         self.start = start
51         self.last_read = start # The last moment parsed by this ADU object
52         self.write_channel = write_channel
53         self.last_byte_put = -1
54         self.annotation_prefix = annotation_prefix
55         # Any Modbus message needs to be at least 4 bytes long. The Modbus
56         # function may make this longer.
57         self.minimum_length = 4
58
59         # This variable is used by an external function to determine when the
60         # next frame should be started.
61         self.startNewFrame = False
62
63         # If there is an error in a frame, we'd like to highlight it. Keep
64         # track of errors.
65         self.hasError = False
66
67     def add_data(self, start, end, data):
68         '''Let the frame handle another piece of data.
69         start: start of this data
70         end: end of this data
71         data: data as received from the UART decoder'''
72         ptype, rxtx, pdata = data
73         self.last_read = end
74         if ptype == 'DATA':
75             self.data.append(Data(start, end, pdata[0]))
76             self.parse() # parse() is defined in the specific type of ADU.
77
78     def puti(self, byte_to_put, annotation, message):
79         '''This class keeps track of how much of the data has already been
80         annotated. This function tells the parent class to write message, but
81         only if it hasn't written about this bit before.
82         byte_to_put: Only write if it hasn't yet written byte_to_put. It will
83                      write from the start of self.last_byte_put+1 to the end
84                      of byte_to_put.
85         annotation: Annotation to write to, without annotation_prefix.
86         message: Message to write.'''
87         if byte_to_put > len(self.data) - 1:
88             # If the byte_to_put hasn't been read yet.
89             raise No_more_data
90
91         if annotation == 'error':
92             self.hasError = True
93
94         if byte_to_put > self.last_byte_put:
95             self.parent.puta(
96                 self.data[self.last_byte_put + 1].start,
97                 self.data[byte_to_put].end,
98                 self.annotation_prefix + annotation,
99                 message)
100             self.last_byte_put = byte_to_put
101             raise No_more_data
102
103     def putl(self, annotation, message, maximum=None):
104         '''Puts the last byte on the stack with message. The contents of the
105         last byte will be applied to message using format.'''
106         last_byte_address = len(self.data) - 1
107         if maximum is not None and last_byte_address > maximum:
108             return
109         self.puti(last_byte_address, annotation,
110                   message.format(self.data[-1].data))
111
112     def close(self, message_overflow):
113         '''Function to be called when next message is started. As there is
114         always space between one message and the next, we can use that space
115         for errors at the end.'''
116         # TODO: Figure out how to make this happen for last message.
117         data = self.data
118         if len(data) < self.minimum_length:
119             if len(data) == 0:
120                 # Sometimes happens with noise, safe to ignore.
121                 return
122             self.parent.puta(
123                 data[self.last_byte_put].end, message_overflow,
124                 self.annotation_prefix + 'error',
125                 'Message too short or not finished')
126             self.hasError = True
127         if self.hasError and self.parent.options['channel'] == 'RX':
128             # If we are on RX mode (so client->server and server->client
129             # messages can be seperated) we like to mark blocks containing
130             # errors. We don't do this in TX mode, because then we interpret
131             # each frame as both a client->server and server->client frame, and
132             # one of those is bound to contain an error, making highlighting
133             # frames useless.
134             self.parent.puta(data[0].start, data[-1].end,
135                              'error-indication', 'Frame contains error')
136         if len(data) > 256:
137             try:
138                 self.puti(len(data) - 1, self.annotation_prefix + 'error',
139                     'Modbus data frames are limited to 256 bytes')
140             except No_more_data:
141                 pass
142
143     def check_crc(self, byte_to_put):
144         '''Check the CRC code, data[byte_to_put] is the 2nd byte of the CRC.'''
145         crc_byte1, crc_byte2 = self.calc_crc(byte_to_put)
146         data = self.data
147         if data[-2].data == crc_byte1 and data[-1].data == crc_byte2:
148             self.puti(byte_to_put, 'crc', 'CRC correct')
149         else:
150             self.puti(byte_to_put, 'error',
151                 'CRC should be {} {}'.format(crc_byte1, crc_byte2))
152
153     def half_word(self, start):
154         '''Return the half word (16 bit) value starting at start bytes in. If
155         it goes out of range it raises the usual errors.'''
156         if (start + 1) > (len(self.data) - 1):
157             # If there isn't enough length to access data[start + 1].
158             raise No_more_data
159         return self.data[start].data * 0x100 + self.data[start + 1].data
160
161     def calc_crc(self, last_byte):
162         '''Calculate the CRC, as described in the spec.
163         The last byte of the CRC should be data[last_byte].'''
164         if last_byte < 3:
165             # Every Modbus ADU should be as least 4 long, so we should never
166             # have to calculate a CRC on something shorter.
167             raise Exception('Could not calculate CRC: message too short')
168
169         result = 0xFFFF
170         magic_number = 0xA001 # As defined in the modbus specification.
171         for byte in self.data[:last_byte - 1]:
172             result = result ^ byte.data
173             for i in range(8):
174                 LSB = result & 1
175                 result = result >> 1
176                 if (LSB): # If the LSB is true.
177                     result = result ^ magic_number
178         byte1 = result & 0xFF
179         byte2 = (result & 0xFF00) >> 8
180         return (byte1, byte2)
181
182     def parse_write_single_coil(self):
183         '''Parse function 5, write single coil.'''
184         self.minimum_length = 8
185
186         self.puti(1, 'function', 'Function 5: Write Single Coil')
187
188         address = self.half_word(2)
189         self.puti(3, 'address',
190             'Address 0x{:X} / {:d}'.format(address, address + 10000))
191
192         raw_value = self.half_word(4)
193         value = 'Invalid Coil Value'
194         if raw_value == 0x0000:
195             value = 'Coil Value OFF'
196         elif raw_value == 0xFF00:
197             value = 'Coil Value ON'
198         self.puti(5, 'data', value)
199
200         self.check_crc(7)
201
202     def parse_write_single_register(self):
203         '''Parse function 6, write single register.'''
204         self.minimum_length = 8
205
206         self.puti(1, 'function', 'Function 6: Write Single Register')
207
208         address = self.half_word(2)
209         self.puti(3, 'address',
210             'Address 0x{:X} / {:d}'.format(address, address + 30000))
211
212         value = self.half_word(4)
213         value_formatted = 'Register Value 0x{0:X} / {0:d}'.format(value)
214         self.puti(5, 'data', value_formatted)
215
216         self.check_crc(7)
217
218     def parse_diagnostics(self):
219         '''Parse function 8, diagnostics. This function has many subfunctions,
220         but they are all more or less the same.'''
221         self.minimum_length = 8
222
223         self.puti(1, 'function', 'Function 8: Diagnostics')
224
225         diag_subfunction = {
226             0: 'Return Query data',
227             1: 'Restart Communications Option',
228             2: 'Return Diagnostics Register',
229             3: 'Change ASCII Input Delimiter',
230             4: 'Force Listen Only Mode',
231             10: 'Clear Counters and Diagnostic Register',
232             11: 'Return Bus Message Count',
233             12: 'Return Bus Communication Error Count',
234             13: 'Return Bus Exception Error Count',
235             14: 'Return Slave Message Count',
236             15: 'Return Slave No Response Count',
237             16: 'Return Slave NAK Count',
238             17: 'Return Slave Busy Count',
239             18: 'Return Bus Character Overrun Count',
240             20: 'Return Overrun Counter and Flag',
241         }
242         subfunction = self.half_word(2)
243         subfunction_name = diag_subfunction.get(subfunction,
244                                                 'Reserved subfunction')
245         self.puti(3, 'data',
246             'Subfunction {}: {}'.format(subfunction, subfunction_name))
247
248         diagnostic_data = self.half_word(4)
249         self.puti(5, 'data',
250             'Data Field: {0} / 0x{0:04X}'.format(diagnostic_data))
251
252         self.check_crc(7)
253
254     def parse_mask_write_register(self):
255         '''Parse function 22, Mask Write Register.'''
256         self.minimum_length = 10
257         data = self.data
258
259         self.puti(1, 'function', 'Function 22: Mask Write Register')
260
261         address = self.half_word(2)
262         self.puti(3, 'address',
263             'Address 0x{:X} / {:d}'.format(address, address + 30001))
264
265         self.half_word(4) # To make sure we don't oveflow data.
266         and_mask_1 = data[4].data
267         and_mask_2 = data[5].data
268         self.puti(5, 'data',
269             'AND mask: {:08b} {:08b}'.format(and_mask_1, and_mask_2))
270
271         self.half_word(6) # To make sure we don't oveflow data.
272         or_mask_1 = data[6].data
273         or_mask_2 = data[7].data
274         self.puti(7, 'data',
275             'OR mask: {:08b} {:08b}'.format(or_mask_1, or_mask_2))
276
277         self.check_crc(9)
278
279     def parse_not_implemented(self):
280         '''Explicitly mark certain functions as legal functions, but not
281         implemented in this parser. This is due to the author not being able to
282         find anything (hardware or software) that supports these functions.'''
283         # TODO: Implement these functions.
284
285         # Mentioning what function it is is no problem.
286         function = self.data[1].data
287         functionname = {
288             20: 'Read File Record',
289             21: 'Write File Record',
290             24: 'Read FIFO Queue',
291             43: 'Read Device Identification/Encapsulated Interface Transport',
292         }[function]
293         self.puti(1, 'function',
294             'Function {}: {} (not supported)'.format(function, functionname))
295
296         # From there on out we can keep marking it unsupported.
297         self.putl('data', 'This function is not currently supported')
298
299 class Modbus_ADU_SC(Modbus_ADU):
300     '''SC stands for Server -> Client.'''
301     def parse(self):
302         '''Select which specific Modbus function we should parse.'''
303         data = self.data
304
305         # This try-catch is being used as flow control.
306         try:
307             server_id = data[0].data
308             if 1 <= server_id <= 247:
309                 message = 'Slave ID: {}'.format(server_id)
310             else:
311                 message = 'Slave ID {} is invalid'
312             self.puti(0, 'server-id', message)
313
314             function = data[1].data
315             if function == 1 or function == 2:
316                 self.parse_read_bits()
317             elif function == 3 or function == 4 or function == 23:
318                 self.parse_read_registers()
319             elif function == 5:
320                 self.parse_write_single_coil()
321             elif function == 6:
322                 self.parse_write_single_register()
323             elif function == 7:
324                 self.parse_read_exception_status()
325             elif function == 8:
326                 self.parse_diagnostics()
327             elif function == 11:
328                 self.parse_get_comm_event_counter()
329             elif function == 12:
330                 self.parse_get_comm_event_log()
331             elif function == 15 or function == 16:
332                 self.parse_write_multiple()
333             elif function == 17:
334                 self.parse_report_server_id()
335             elif function == 22:
336                 self.parse_mask_write_register()
337             elif function in {21, 21, 24, 43}:
338                 self.parse_not_implemented()
339             elif function > 0x80:
340                 self.parse_error()
341             else:
342                 self.puti(1, 'error',
343                           'Unknown function: {}'.format(data[1].data))
344                 self.putl('error', 'Unknown function')
345
346             # If the message gets here without raising an exception, the
347             # message goes on longer than it should.
348             self.putl('error', 'Message too long')
349
350         except No_more_data:
351             # Just a message saying we don't need to parse anymore this round.
352             pass
353
354     def parse_read_bits(self):
355         self.mimumum_length = 5
356
357         data = self.data
358         function = data[1].data
359
360         if function == 1:
361             self.puti(1, 'function', 'Function 1: Read Coils')
362         else:
363             self.puti(1, 'function', 'Function 2: Read Discrete Inputs')
364
365         bytecount = self.data[2].data
366         self.minimum_length = 5 + bytecount # 3 before data, 2 CRC.
367         self.puti(2, 'length', 'Byte count: {}'.format(bytecount))
368
369         # From here on out, we expect registers on 3 and 4, 5 and 6 etc.
370         # So registers never start when the length is even.
371         self.putl('data', '{:08b}', bytecount + 2)
372         self.check_crc(bytecount + 4)
373
374     def parse_read_registers(self):
375         self.mimumum_length = 5
376
377         data = self.data
378
379         function = data[1].data
380         if function == 3:
381             self.puti(1, 'function', 'Function 3: Read Holding Registers')
382         elif function == 4:
383             self.puti(1, 'function', 'Function 4: Read Input Registers')
384         elif function == 23:
385             self.puti(1, 'function', 'Function 23: Read/Write Multiple Registers')
386
387         bytecount = self.data[2].data
388         self.minimum_length = 5 + bytecount # 3 before data, 2 CRC.
389         if bytecount % 2 == 0:
390             self.puti(2, 'length', 'Byte count: {}'.format(bytecount))
391         else:
392             self.puti(2, 'error',
393                 'Error: Odd byte count ({})'.format(bytecount))
394
395         # From here on out, we expect registers on 3 and 4, 5 and 6 etc.
396         # So registers never start when the length is even.
397         if len(data) % 2 == 1:
398             register_value = self.half_word(-2)
399             self.putl('data', '0x{0:04X} / {0}'.format(register_value),
400                       bytecount + 2)
401         else:
402             raise No_more_data
403
404         self.check_crc(bytecount + 4)
405
406     def parse_read_exception_status(self):
407         self.mimumum_length = 5
408
409         self.puti(1, 'function', 'Function 7: Read Exception Status')
410         exception_status = self.data[2].data
411         self.puti(2, 'data',
412                   'Exception status: {:08b}'.format(exception_status))
413         self.check_crc(4)
414
415     def parse_get_comm_event_counter(self):
416         self.mimumum_length = 8
417
418         self.puti(1, 'function', 'Function 11: Get Comm Event Counter')
419
420         status = self.half_word(2)
421         if status == 0x0000:
422             self.puti(3, 'data', 'Status: not busy')
423         elif status == 0xFFFF:
424             self.puti(3, 'data', 'Status: busy')
425         else:
426             self.puti(3, 'error', 'Bad status: 0x{:04X}'.format(status))
427
428         count = self.half_word(4)
429         self.puti(5, 'data', 'Event Count: {}'.format(count))
430         self.check_crc(7)
431
432     def parse_get_comm_event_log(self):
433         self.mimumum_length = 11
434         self.puti(1, 'function', 'Function 12: Get Comm Event Log')
435
436         data = self.data
437
438         bytecount = data[2].data
439         self.puti(2, 'length', 'Bytecount: {}'.format(bytecount))
440         # The bytecount is the length of everything except the slaveID,
441         # function code, bytecount and CRC.
442         self.mimumum_length = 5 + bytecount
443
444         status = self.half_word(3)
445         if status == 0x0000:
446             self.puti(4, 'data', 'Status: not busy')
447         elif status == 0xFFFF:
448             self.puti(4, 'data', 'Status: busy')
449         else:
450             self.puti(4, 'error', 'Bad status: 0x{:04X}'.format(status))
451
452         event_count = self.half_word(5)
453         self.puti(6, 'data', 'Event Count: {}'.format(event_count))
454
455         message_count = self.half_word(7)
456         self.puti(8, 'data', 'Message Count: {}'.format(message_count))
457
458         self.putl('data', 'Event: 0x{:02X}'.format(data[-1].data),
459                   bytecount + 2)
460
461         self.check_crc(bytecount + 4)
462
463     def parse_write_multiple(self):
464         '''Function 15 and 16 are almost the same, so we can parse them both
465         using one function.'''
466         self.mimumum_length = 8
467
468         function = self.data[1].data
469         if function == 15:
470             data_unit = 'Coils'
471             max_outputs = 0x07B0
472             long_address_offset = 10001
473         elif function == 16:
474             data_unit = 'Registers'
475             max_outputs = 0x007B
476             long_address_offset = 30001
477
478         self.puti(1, 'function',
479             'Function {}: Write Multiple {}'.format(function, data_unit))
480
481         starting_address = self.half_word(2)
482         # Some instruction manuals use a long form name for addresses, this is
483         # listed here for convienience.
484         address_name = long_address_offset + starting_address
485         self.puti(3, 'address',
486             'Start at address 0x{:X} / {:d}'.format(starting_address,
487                                                     address_name))
488
489         quantity_of_outputs = self.half_word(4)
490         if quantity_of_outputs <= max_outputs:
491             self.puti(5, 'data',
492                 'Write {} {}'.format(quantity_of_outputs, data_unit))
493         else:
494             self.puti(5, 'error',
495                 'Bad value: {} {}. Max is {}'.format(quantity_of_outputs,
496                                                      data_unit, max_outputs))
497
498         self.check_crc(7)
499
500     def parse_report_server_id(self):
501         # Buildup of this function:
502         # 1 byte serverID
503         # 1 byte function (17)
504         # 1 byte bytecount
505         # 1 byte serverID (counts for bytecount)
506         # 1 byte Run Indicator Status (counts for bytecount)
507         # bytecount - 2 bytes of device specific data (counts for bytecount)
508         # 2 bytes of CRC
509         self.mimumum_length = 7
510         data = self.data
511         self.puti(1, 'function', 'Function 17: Report Server ID')
512
513         bytecount = data[2].data
514         self.puti(2, 'length', 'Data is {} bytes long'.format(bytecount))
515
516         self.puti(3, 'data', 'serverID: {}'.format(data[3].data))
517
518         run_indicator_status = data[4].data
519         if run_indicator_status == 0x00:
520             self.puti(4, 'data', 'Run Indicator status: Off')
521         elif run_indicator_status == 0xFF:
522             self.puti(4, 'data', 'Run Indicator status: On')
523         else:
524             self.puti(4, 'error',
525                 'Bad Run Indicator status: 0x{:X}'.format(run_indicator_status))
526
527         self.putl('data', 'Device specific data: {}, "{}"'.format(data[-1].data,
528                   chr(data[-1].data)), 2 + bytecount)
529
530         self.check_crc(4 + bytecount)
531
532     def parse_error(self):
533         '''Parse a Modbus error message.'''
534         self.mimumum_length = 5
535         # The function code of an error is always 0x80 above the function call
536         # that caused it.
537         functioncode = self.data[1].data - 0x80
538
539         functions = {
540             1: 'Read Coils',
541             2: 'Read Discrete Inputs',
542             3: 'Read Holding Registers',
543             4: 'Read Input Registers',
544             5: 'Write Single Coil',
545             6: 'Write Single Register',
546             7: 'Read Exception Status',
547             8: 'Diagnostic',
548             11: 'Get Com Event Counter',
549             12: 'Get Com Event Log',
550             15: 'Write Multiple Coils',
551             16: 'Write Multiple Registers',
552             17: 'Report Slave ID',
553             20: 'Read File Record',
554             21: 'Write File Record',
555             22: 'Mask Write Register',
556             23: 'Read/Write Multiple Registers',
557             24: 'Read FIFO Queue',
558             43: 'Read Device Identification/Encapsulated Interface Transport',
559         }
560         functionname = '{}: {}'.format(functioncode,
561             functions.get(functioncode, 'Unknown function'))
562         self.puti(1, 'function',
563                   'Error for function {}'.format(functionname))
564
565         error = self.data[2].data
566         errorcodes = {
567             1: 'Illegal Function',
568             2: 'Illegal Data Address',
569             3: 'Illegal Data Value',
570             4: 'Slave Device Failure',
571             5: 'Acknowledge',
572             6: 'Slave Device Busy',
573             8: 'Memory Parity Error',
574             10: 'Gateway Path Unavailable',
575             11: 'Gateway Target Device failed to respond',
576         }
577         errorname = '{}: {}'.format(error, errorcodes.get(error, 'Unknown'))
578         self.puti(2, 'data', 'Error {}'.format(errorname))
579         self.check_crc(4)
580
581 class Modbus_ADU_CS(Modbus_ADU):
582     '''CS stands for Client -> Server.'''
583     def parse(self):
584         '''Select which specific Modbus function we should parse.'''
585         data = self.data
586
587         # This try-catch is being used as flow control.
588         try:
589             server_id = data[0].data
590             message = ''
591             if server_id == 0:
592                 message = 'Broadcast message'
593             elif 1 <= server_id <= 247:
594                 message = 'Slave ID: {}'.format(server_id)
595             elif 248 <= server_id <= 255:
596                 message = 'Slave ID: {} (reserved address)'.format(server_id)
597             self.puti(0, 'server-id', message)
598
599             function = data[1].data
600             if function >= 1 and function <= 4:
601                 self.parse_read_data_command()
602             if function == 5:
603                 self.parse_write_single_coil()
604             if function == 6:
605                 self.parse_write_single_register()
606             if function in {7, 11, 12, 17}:
607                 self.parse_single_byte_request()
608             elif function == 8:
609                 self.parse_diagnostics()
610             if function in {15, 16}:
611                 self.parse_write_multiple()
612             elif function == 22:
613                 self.parse_mask_write_register()
614             elif function == 23:
615                 self.parse_read_write_registers()
616             elif function in {21, 21, 24, 43}:
617                 self.parse_not_implemented()
618             else:
619                 self.puti(1, 'error',
620                           'Unknown function: {}'.format(data[1].data))
621                 self.putl('error', 'Unknown function')
622
623             # If the message gets here without raising an exception, the
624             # message goes on longer than it should.
625             self.putl('error', 'Message too long')
626
627         except No_more_data:
628             # Just a message saying we don't need to parse anymore this round.
629             pass
630
631     def parse_read_data_command(self):
632         '''Interpret a command to read x units of data starting at address, ie
633         functions 1, 2, 3 and 4, and write the result to the annotations.'''
634         data = self.data
635         self.minimum_length = 8
636
637         function = data[1].data
638         functionname = {1: 'Read Coils',
639                         2: 'Read Discrete Inputs',
640                         3: 'Read Holding Registers',
641                         4: 'Read Input Registers',
642                         }[function]
643
644         self.puti(1, 'function',
645                   'Function {}: {}'.format(function, functionname))
646
647         starting_address = self.half_word(2)
648         # Some instruction manuals use a long form name for addresses, this is
649         # listed here for convienience.
650         # Example: holding register 60 becomes 30061.
651         address_name = 10000 * function + 1 + starting_address
652         self.puti(3, 'address',
653             'Start at address 0x{:X} / {:d}'.format(starting_address,
654                                                     address_name))
655
656         self.puti(5, 'length',
657                   'Read {:d} units of data'.format(self.half_word(4)))
658         self.check_crc(7)
659
660     def parse_single_byte_request(self):
661         '''Some Modbus functions have no arguments, this parses those.'''
662         function = self.data[1].data
663         function_name = {7: 'Read Exception Status',
664                          11: 'Get Comm Event Counter',
665                          12: 'Get Comm Event Log',
666                          17: 'Report Slave ID',
667                          }[function]
668         self.puti(1, 'function',
669                   'Function {}: {}'.format(function, function_name))
670
671         self.check_crc(3)
672
673     def parse_write_multiple(self):
674         '''Function 15 and 16 are almost the same, so we can parse them both
675         using one function.'''
676         self.mimumum_length = 9
677
678         function = self.data[1].data
679         if function == 15:
680             data_unit = 'Coils'
681             max_outputs = 0x07B0
682             ratio_bytes_data = 1/8
683             long_address_offset = 10001
684         elif function == 16:
685             data_unit = 'Registers'
686             max_outputs = 0x007B
687             ratio_bytes_data = 2
688             long_address_offset = 30001
689
690         self.puti(1, 'function',
691             'Function {}: Write Multiple {}'.format(function, data_unit))
692
693         starting_address = self.half_word(2)
694         # Some instruction manuals use a long form name for addresses, this is
695         # listed here for convienience.
696         address_name = long_address_offset + starting_address
697         self.puti(3, 'address',
698             'Start at address 0x{:X} / {:d}'.format(starting_address,
699                                                     address_name))
700
701         quantity_of_outputs = self.half_word(4)
702         if quantity_of_outputs <= max_outputs:
703             self.puti(5, 'length',
704                 'Write {} {}'.format(quantity_of_outputs, data_unit))
705         else:
706             self.puti(5, 'error',
707                 'Bad value: {} {}. Max is {}'.format(quantity_of_outputs,
708                                                      data_unit, max_outputs))
709         proper_bytecount = ceil(quantity_of_outputs * ratio_bytes_data)
710
711         bytecount = self.data[6].data
712         if bytecount == proper_bytecount:
713             self.puti(6, 'length', 'Byte count: {}'.format(bytecount))
714         else:
715             self.puti(6, 'error',
716                 'Bad byte count, is {}, should be {}'.format(bytecount,
717                                                              proper_bytecount))
718         self.mimumum_length = bytecount + 9
719
720         self.putl('data', 'Value 0x{:X}', 6 + bytecount)
721
722         self.check_crc(bytecount + 8)
723
724     def parse_read_file_record(self):
725         self.puti(1, 'function', 'Function 20: Read file records')
726
727         data = self.data
728
729         bytecount = data[2].data
730
731         self.minimum_length = 5 + bytecount
732         # 1 for serverID, 1 for function, 1 for bytecount, 2 for CRC.
733
734         if 0x07 <= bytecount <= 0xF5:
735             self.puti(2, 'length', 'Request is {} bytes long'.format(bytecount))
736         else:
737             self.puti(2, 'error',
738                 'Request claims to be {} bytes long, legal values are between'
739                 ' 7 and 247'.format(bytecount))
740
741         current_byte = len(data) - 1
742         # Function 20 is a number of sub-requests, the first starting at 3,
743         # the total length of the sub-requests is bytecount.
744         if current_byte <= bytecount + 2:
745             step = (current_byte - 3) % 7
746             if step == 0:
747                 if data[current_byte].data == 6:
748                     self.puti(current_byte, 'data', 'Start sub-request')
749                 else:
750                     self.puti(current_byte, 'error',
751                         'First byte of subrequest should be 0x06')
752             elif step == 1:
753                 raise No_more_data
754             elif step == 2:
755                 file_number = self.half_word(current_byte - 1)
756                 self.puti(current_byte, 'data',
757                           'Read File number {}'.format(file_number))
758             elif step == 3:
759                 raise No_more_data
760             elif step == 4:
761                 record_number = self.half_word(current_byte - 1)
762                 self.puti(current_byte, 'address',
763                     'Read from record number {}'.format(record_number))
764                 # TODO: Check if within range.
765             elif step == 5:
766                 raise No_more_data
767             elif step == 6:
768                 records_to_read = self.half_word(current_byte - 1)
769                 self.puti(current_byte, 'length',
770                     'Read {} records'.format(records_to_read))
771         self.check_crc(4 + bytecount)
772
773     def parse_read_write_registers(self):
774         '''Parse function 23: Read/Write multiple registers.'''
775         self.minimum_length = 13
776
777         self.puti(1, 'function', 'Function 23: Read/Write Multiple Registers')
778
779         starting_address = self.half_word(2)
780         # Some instruction manuals use a long form name for addresses, this is
781         # listed here for convienience.
782         # Example: holding register 60 becomes 30061.
783         address_name = 30001 + starting_address
784         self.puti(3, 'address',
785             'Read starting at address 0x{:X} / {:d}'.format(starting_address,
786                                                             address_name))
787
788         self.puti(5, 'length', 'Read {:d} units of data'.format(self.half_word(4)))
789
790         starting_address = self.half_word(6)
791         self.puti(7, 'address',
792             'Write starting at address 0x{:X} / {:d}'.format(starting_address,
793                                                              address_name))
794
795         quantity_of_outputs = self.half_word(8)
796         self.puti(9, 'length',
797                            'Write {} registers'.format(quantity_of_outputs))
798         proper_bytecount = quantity_of_outputs * 2
799
800         bytecount = self.data[10].data
801         if bytecount == proper_bytecount:
802             self.puti(10, 'length', 'Byte count: {}'.format(bytecount))
803         else:
804             self.puti(10, 'error',
805                 'Bad byte count, is {}, should be {}'.format(bytecount,
806                                                              proper_bytecount))
807         self.mimumum_length = bytecount + 13
808
809         self.putl('data', 'Data, value 0x{:02X}', 10 + bytecount)
810
811         self.check_crc(bytecount + 12)
812
813 class Decoder(srd.Decoder):
814     api_version = 3
815     id = 'modbus'
816     name = 'Modbus'
817     longname = 'Modbus RTU over RS232/RS485'
818     desc = 'Modbus RTU protocol for industrial applications.'
819     license = 'gplv3+'
820     inputs = ['uart']
821     outputs = ['modbus']
822     annotations = (
823         ('sc-server-id', ''),
824         ('sc-function', ''),
825         ('sc-crc', ''),
826         ('sc-address', ''),
827         ('sc-data', ''),
828         ('sc-length', ''),
829         ('sc-error', ''),
830         ('cs-server-id', ''),
831         ('cs-function', ''),
832         ('cs-crc', ''),
833         ('cs-address', ''),
834         ('cs-data', ''),
835         ('cs-length', ''),
836         ('cs-error', ''),
837         ('error-indication', ''),
838     )
839     annotation_rows = (
840         ('sc', 'Server->client', (0, 1, 2, 3, 4, 5, 6)),
841         ('cs', 'Client->server', (7, 8, 9, 10, 11, 12, 13)),
842         ('error-indicator', 'Errors in frame', (14,)),
843     )
844     options = (
845         {'id': 'channel', 'desc': 'Server -> client channel', 'default': 'RX',
846             'values': ('RX', 'TX')},
847     )
848
849     def __init__(self):
850         self.reset()
851
852     def reset(self):
853         self.ADUSc = None # Start off with empty slave -> client ADU.
854         self.ADUCs = None # Start off with empty client -> slave ADU.
855
856         # The reason we have both (despite not supporting full duplex comms) is
857         # because we want to be able to decode the message as both client ->
858         # server and server -> client, and let the user see which of the two
859         # the ADU was.
860
861         self.bitlength = None # We will later test how long a bit is.
862
863     def start(self):
864         self.out_ann = self.register(srd.OUTPUT_ANN)
865
866     def puta(self, start, end, ann_str, message):
867         '''Put an annotation from start to end, with ann as a
868         string. This means you don't have to know the ann's
869         number to write annotations to it.'''
870         ann = [s[0] for s in self.annotations].index(ann_str)
871         self.put(start, end, self.out_ann, [ann, [message]])
872
873     def decode_adu(self, ss, es, data, direction):
874         '''Decode the next byte or bit (depending on type) in the ADU.
875         ss: Start time of the data
876         es: End time of the data
877         data: Data as passed from the UART decoder
878         direction: Is this data for the Cs (client -> server) or Sc (server ->
879                    client) being decoded right now?'''
880         ptype, rxtx, pdata = data
881
882         # We don't have a nice way to get the baud rate from UART, so we have
883         # to figure out how long a bit lasts. We do this by looking at the
884         # length of (probably) the startbit.
885         if self.bitlength is None:
886             if ptype == 'STARTBIT' or ptype == 'STOPBIT':
887                 self.bitlength = es - ss
888             else:
889                 # If we don't know the bitlength yet, we can't start decoding.
890                 return
891
892         # Select the ADU, create the ADU if needed.
893         # We set ADU.startNewFrame = True when we know the old one is over.
894         if direction == 'Sc':
895             if (self.ADUSc is None) or self.ADUSc.startNewFrame:
896                 self.ADUSc = Modbus_ADU_SC(self, ss, TX, 'sc-')
897             ADU = self.ADUSc
898         if direction == 'Cs':
899             if self.ADUCs is None or self.ADUCs.startNewFrame:
900                 self.ADUCs = Modbus_ADU_CS(self, ss, TX, 'cs-')
901             ADU = self.ADUCs
902
903         # We need to determine if the last ADU is over.
904         # According to the Modbus spec, there should be 3.5 characters worth of
905         # space between each message. But if within a message there is a length
906         # of more than 1.5 character, that's an error. For our purposes
907         # somewhere between seems fine.
908         # A character is 11 bits long, so (3.5 + 1.5)/2 * 11 ~= 28
909         # TODO: Display error for too short or too long.
910         if (ss - ADU.last_read) <= self.bitlength * 28:
911             ADU.add_data(ss, es, data)
912         else:
913             # It's been too long since the last part of the ADU!
914             # If there is any data in the ADU we need to show it to the user
915             if len(ADU.data) > 0:
916                 # Extend errors for 3 bits after last byte, we can guarantee
917                 # space.
918                 ADU.close(ADU.data[-1].end + self.bitlength * 3)
919
920             ADU.startNewFrame = True
921             # Restart this function, it will make a new ADU for us.
922             self.decode_adu(ss, es, data, direction)
923
924     def decode(self, ss, es, data):
925         ptype, rxtx, pdata = data
926
927         # Decide what ADU(s) we need this packet to go to.
928         # Note that it's possible to go to both ADUs.
929         if rxtx == TX:
930             self.decode_adu(ss, es, data, 'Cs')
931         if rxtx == TX and self.options['channel'] == 'TX':
932             self.decode_adu(ss, es, data, 'Sc')
933         if rxtx == RX and self.options['channel'] == 'RX':
934             self.decode_adu(ss, es, data, 'Sc')