-
Notifications
You must be signed in to change notification settings - Fork 1
/
comms
executable file
·746 lines (614 loc) · 49 KB
/
comms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
#!/usr/bin/env python3
import os
import sys
from itertools import islice
import logging
import serial
import click
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger(__name__)
# --- Captured message samples ---
# reset the remote analyzer
CMD_RSRE = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x52\x53\x52\x45\x1c\x3a'
# pad pad pad pad len fin crc crc crc crc
# response to reset is "accepted"
CMD_RSRE_R1ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5\xff'
# pad pad pad pad len fin crc crc A C C crc crc spare
# Identify the remote (IDRE)
CMD_IDRE = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x49\x44\x52\x45\xaa\xda'
# pad pad pad pad len fin crc crc I D R E crc crc
# ACC response from IDRE. But no id yet
CMD_IDRE_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
# pad pad pad pad len and crc crc A C C crc crc
# So controller sends 'ok, more please...'
CMD_IDRE_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
# pad pad pad pad -----ok and crc crc
# Response follows... the ID itself
CMD_IDRE_RESP2 = b'\x96\x96\x96\x96\x81\x07\xc0\x01\x00\x00\xc6\x11\x48\x50\x34\x39\x35\x32\x00\x7c\x62'
# pad pad pad pad len fin seq crc crc H P 4 9 5 2 nul crc crc
# another IDRE (same)
CM2_IDRE = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x49\x44\x52\x45\xaa\xda'
CM2_IDRE_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CM2_IDRE_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CM2_IDRE_RESP2 = b'\x96\x96\x96\x96\x81\x07\xc0\x01\x00\x00\xc6\x11\x48\x50\x34\x39\x35\x32\x00\x7c\x62\xff'
# select app 0
CMD_SEAP = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x53\x45\x41\x50\x30\xfd'
# name the app
# 'do go on...' response from SEAP0
CO_SEAP0 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\xff'
# tell it the VT100
CMD_SEAP_PART2 = b'\x96\x96\x96\x96\x81\x12\xc0\x01\x00\x00\xcb\xd2\x20\x20\x20\x20\x20\x20\x20\x20\x56\x54\x31\x30\x30\x20\x20\x20\x20\x20\x16\x5c'
# sp sp sp sp sp sp sp sp V T 1 0 0 sp sp sp sp sp
# ACC response from SEAP0 VT100
RSP__ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# execute app
CMD_EXAP = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x45\x58\x41\x50\xa4\xb3'
# response is just "ACC"
CMD_EXAP_R1ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# lock keyboard
CMD_LOKB = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x4c\x4f\x4b\x42\x91\x86'
# ACC response from LOKB
RSP_ACC4 = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# unlock keyboard
CMD_ENKB = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x45\x4e\x4b\x42\xc3\xda'
# ACC response from ENKB
RSP_ACC2 = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# ACC response from RSRE
RSP_ACC0 = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# REJ response (after RCAH)
RSP_REJ0 = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x52\x45\x4a\x12\xb6'
# *** *** *** R E J
# Error message after load fail (data length 0x21=33)
RSP_MSGF=b'\x96\x96\x96\x96\x81\x21\xc0\x01\x00\x00\xcf\xd6\x00\x00\x00\x00\x41\x6e\x20\x41\x70\x70\x6c\x69\x63\x20\x69\x73\x20\x41\x6c\x72\x65\x61\x64\x79\x20\x4c\x6f\x61\x64\x65\x64\x20\x00\x15\xc1'
# ....preamble.... A n A p p l i c
# Downloading an app to the analyzer
# send RCAH (Download Application Header)
CMD_RCAH = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x52\x43\x41\x48\xd1\x0a'
# response is "ok, what else"
CMD_RCAH_RESP1 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
# with the app description (first x80 bytes)
CMD_RCAH_PART2 = b'\x96\x96\x96\x96\x81\x80\xc0\x01\x00\x00\x72\x0f\x00\x00\x58\x00\x20\x20\x20\x20\x20\x20\x20\x20\x54\x45\x52\x4d\x49\x4e\x41\x4c\x20\x20\x34\x39\x35\x32\x20\x20\x00\x08\x00\x01\x41\x73\x79\x6e\x63\x20\x54\x65\x72\x6d\x69\x6e\x61\x6c\x20\x45\x6d\x75\x6c\x61\x74\x6f\x72\x20\x2d\x20\x44\x55\x4d\x42\x20\x20\x00\x00\x00\x00\x00\x00\x00\xc3\x97\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xba\xf7\x4b\x56'
# ^ T E R N I N A L
CMD_RCAH_R2ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# then a SEBL (Set Application Header)
CMD_SEBL = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x53\x45\x42\x4c\x31\xc4'
CMD_SEBL_RESP1 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
CMD_SEBL_PART2 = b'\x96\x96\x96\x96\x81\x06\xc0\x01\x00\x00\xfb\xd1\x00\x00\x08\x00\x00\x00\x02\x60'
CMD_SEBL_R2ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# then a RCAP (Download Application Module)
CMD_RCAP = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x52\x43\x41\x50\xd1\x00'
CMD_RCAP_RESP1 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
# this looks like the app start, all over (same data as CMD_RCAH_PART2, then more)
# note the \x41 means something like "this is partial data" with a seqno
CMD_RCAP_PART2 = b'\x96\x96\x96\x96\x81\x00\x41\x01\x00\x00\x5b\xed\x00\x00\x58\x00\x20\x20\x20\x20\x20\x20\x20\x20\x54\x45\x52\x4d\x49\x4e\x41\x4c\x20\x20\x34\x39\x35\x32\x20\x20\x00\x08\x00\x01\x41\x73\x79\x6e\x63\x20\x54\x65\x72\x6d\x69\x6e\x61\x6c\x20\x45\x6d\x75\x6c\x61\x74\x6f\x72\x20\x2d\x20\x44\x55\x4d\x42\x20\x20\x00\x00\x00\x00\x00\x00\x00\xc3\x97\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xba\xf7\x61\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x2d\x00\x00\x36\xc1\x02\x2d\x00\x00\x70\xc1\x02\x2d\x00\x00\x96\xc1\x50\x2d\x00\x00\x9d\xc1\x02\x2d\x00\x00\x07\xc3\x02\x2d\x00\x00\x0d\xc3\x54\x2e\x00\x00\x14\xc3\x02\x2d\x00\x00\x1a\xc3\x02\x2d\x00\x00\x39\xc3\x02\x2d\x00\x00\x47\xc3\x02\x2d\x00\x00\x50\xc3\x02\x2d\x00\x00\x5e\xc3\x3c\x2e\x00\x00\x1b\xc4\x3c\x2e\x00\x00\x1d\xc4\x3c\x2e\x00\x00\x1f\xc4\x3c\x2e\x00\x00\x21\xc4\x3c\x2e\x00\x00\x23\xc4\x3c\x2e\x00\x00\x25\xc4\x3c\x2e\x00\x00\xda\x84'
# this appears in VT100.APP at offset 0x0120 ^ onward (not sure why it starts at that offset)
CMD_RCAP_RESP2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
CMD_RCAP_PART3 = b'\x96\x96\x96\x96\x81\x00\x41\x02\x00\x00\xab\xed\x27\xc4\x3c\x2e\x00\x00\x29\xc4\x3c\x2e\x00\x00\x2b\xc4\x42\x2e\x00\x00\x2d\xc4\x42\x2e\x00\x00\x2f\xc4\x42\x2e\x00\x00\x31\xc4\x42\x2e\x00\x00\x33\xc4\x42\x2e\x00\x00\x35\xc4\x42\x2e\x00\x00\x37\xc4\x42\x2e\x00\x00\x39\xc4\x42\x2e\x00\x00\x3b\xc4\x42\x2e\x00\x00\x3d\xc4\x02\x2d\x00\x00\xd7\xc8\x3a\x2e\x00\x00\xf4\xc8\x02\x2d\x00\x00\x32\xc9\x02\x2d\x00\x00\x3b\xc9\x38\x2d\x00\x00\x3e\xc9\x02\x2d\x00\x00\x48\xc9\x50\x2d\x00\x00\x54\xc9\x60\x2e\x00\x00\xfd\xc9\x60\x2e\x00\x00\x09\xca\x60\x2e\x00\x00\x15\xca\x60\x2e\x00\x00\x21\xca\x60\x2e\x00\x00\x2d\xca\x60\x2e\x00\x00\x39\xca\x60\x2e\x00\x00\x45\xca\x60\x2e\x00\x00\x51\xca\x60\x2e\x00\x00\x5d\xca\xf8\x2d\x00\x00\xf7\xca\xea\x2d\x00\x00\xfa\xca\x02\x2e\x00\x00\x1d\xcb\xd0\x2d\x00\x00\x20\xcb\x32\x2d\x00\x00\x9c\xa4\x6e\x2e\x00\x00\x9f\xa4\x66\x2e\x03\x00\xa2\xa4\x66\x2e\x03\x00\xac\xa4\x66\x2e\x04\x00\xb2\xa4\x32\x2e\x00\x00\xc9\xa4\xb2\x2e\x00\x00\xd9\xa4\xda\x2e\x00\x00\xdc\xa4\x98\x2e\x00\x00\xdf\xa4\xdc\x2e\x00\x00\xe2\xa4\x6c\x2d\x00\x00\x06\xa5\xce\x2e\xd0\x0c'
# this appears in VT100.APP at offset 0x0220 ^ onward (we're sending 256 bytes per packet)
# (and so on - skip several packets)
# note the \xc1 means something like "and this is the final data" with a seqno
CMD_RCAP_PARTN = b'\x96\x96\x96\x96\x81\x00\xc1\x08\x00\x00\xa2\x2f\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\x20\x83\xf8\x31'
# this appears in VT100.APP at offset 0x4820 ^ which is coming up to the end
# and we get ACC at the end
CMD_RCAP_RNACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# TRBR accepted (Display Memory Usage)
CMD_TRBR = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x42\x52\x00\xbc'
CMD_TRBR_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CMD_TRBR_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRBR_RESP2 = b'\x96\x96\x96\x96\x81\x0e\xc0\x01\x00\x00\x1a\x10\x00\x00\x00\x20\x00\x18\x00\x18\x00\x20\x00\x01\x00\x01\x88\x06\xff'
# Another TRBR for comparison
CM2_TRBR = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x42\x52\x00\xbc'
CM2_TRBR_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CM2_TRBR_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CM2_TRBR_RESP2 = b'\x96\x96\x96\x96\x81\x0e\xc0\x01\x00\x00\x1a\x10\x00\x00\x00\x20\x00\x18\x00\x18\x00\x20\x00\x01\x00\x01\x88\x06\xff'
# SEBS (Set Buffer Size) rejected with 'operation not supported'
CMD_SEBS = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x53\x45\x42\x53\x70\x0c'
CMD_SEBS_R1REJ = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x52\x45\x4a\x12\xb6'
# oh do tell me why
CMD_SEBS_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_SEBS_RESP2 = b'\x96\x96\x96\x96\x81\x21\xc0\x01\x00\x00\xcf\xd6\x00\x00\x00\x00\x20\x20\x20\x4f\x70\x65\x72\x61\x74\x69\x6f\x6e\x20\x6e\x6f\x74\x20\x73\x75\x70\x70\x6f\x72\x74\x65\x64\x20\x20\x00\x33\x91'
# TRTC (Display Timers and Counters) accepted, produces a very large response
CMD_TRTC = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x54\x43\xce\xd0'
RSP_TRTC_ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CMD_TRTC_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
RSP_TRTC_PART2 = b'\x96\x96\x96\x96\x81\xf0\xc0\x01\x00\x00\x33\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x56\xdb\xff'
# TRRS (?) accepted
CMD_TRRS = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x52\x53\xcc\xbc'
CMD_TRRS_ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CMD_TRRS_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRRS_RESP2 = b'\x96\x96\x96\x96\x81\x06\xc0\x01\x00\x00\xfb\xd1\x00\x00\x00\x00\x00\x32\x81\xd5\xff'
# CKDR (?) accepted
CMD_CKDR = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x43\x4b\x44\x52\xd7\x6f'
CMD_CKDR_RESP1 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
CMD_CKDR_PART2 = b'\x96\x96\x96\x96\x81\x06\xc0\x01\x00\x00\xfb\xd1\x00\x00\x00\x01\x00\x01\x90\x00\xff\xff\xff'
CMD_CKDR_R2ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# SEBL
CMD_SEBL = b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x53\x45\x42\x4c\x31\xc4'
CMD_SEBL_RESP1 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55'
CMD_SEBL_PART2 = b'\x96\x96\x96\x96\x81\x02\xc0\x01\x00\x00\x0a\x11\x00\x01\xc1\xc0'
CMD_SEBL_R2ACC = b'\x96\x96\x96\x96\x81\x03\xc0\x00\x00\x00\x66\x11\x41\x43\x43\x20\xd5'
# TRCD (Upload Captured Data), long responses (0xc1 in the final)
CMD_TRCD = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x43\x44\x80\xe2\xff'
CMD_TRCD_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CMD_TRCD_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP2 = b'\x96\x96\x96\x96\x81\x00\x41\x01\x00\x00\x5b\xed\x00\x00\x7f\x00\x00\x02\x7f\x00\x00\x04\x7f\x00\x00\x06\x7f\x00\x00\x08\x7f\x00\x00\x0a\x7f\x00\x00\x0c\x7f\x00\x00\x0e\x7f\x00\x00\x10\x7f\x00\x00\x12\x7f\x00\x00\x14\x7f\x00\x00\x16\x7f\x00\x00\x18\x7f\x00\x00\x1a\x7f\x00\x00\x1c\x7f\x00\x00\x1e\x7f\x00\x00\x20\x7f\x00\x00\x22\x7f\x00\x00\x24\x7f\x00\x00\x26\x7f\x00\x00\x28\x7f\x00\x00\x2a\x7f\x00\x00\x2c\x7f\x00\x00\x2e\x7f\x00\x00\x30\x7f\x00\x00\x32\x7f\x00\x00\x34\x7f\x00\x00\x36\x7f\x00\x00\x38\x7f\x00\x00\x3a\x7f\x00\x00\x3c\x7f\x00\x00\x3e\x7f\x00\x00\x40\x7f\x00\x00\x42\x7f\x00\x00\x44\x7f\x00\x00\x46\x7f\x00\x00\x48\x7f\x00\x00\x4a\x7f\x00\x00\x4c\x7f\x00\x00\x4e\x7f\x00\x00\x50\x7f\x00\x00\x52\x7f\x00\x00\x54\x7f\x00\x00\x56\x7f\x00\x00\x58\x7f\x00\x00\x5a\x7f\x00\x00\x5c\x7f\x00\x00\x5e\x7f\x00\x00\x60\x7f\x00\x00\x62\x7f\x00\x00\x64\x7f\x00\x00\x66\x7f\x00\x00\x68\x7f\x00\x00\x6a\x7f\x00\x00\x6c\x7f\x00\x00\x6e\x7f\x00\x00\x70\x7f\x00\x00\x72\x7f\x00\x00\x74\x7f\x00\x00\x76\x7f\x00\x00\x78\x7f\x00\x00\x7a\x7f\x00\x00\x7c\x7f\x00\x00\x7e\x7f\x00\xad\x5b'
CMD_TRCD_PART3 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP3 = b'\x96\x96\x96\x96\x81\x00\x41\x02\x00\x00\xab\xed\x00\x80\x7f\x00\x00\x82\x7f\x00\x00\x84\x7f\x00\x00\x86\x7f\x00\x00\x88\x7f\x00\x00\x8a\x7f\x00\x00\x8c\x7f\x00\x00\x8e\x7f\x00\x00\x90\x7f\x00\x00\x92\x7f\x00\x00\x94\x7f\x00\x00\x96\x7f\x00\x00\x98\x7f\x00\x00\x9a\x7f\x00\x00\x9c\x7f\x00\x00\x9e\x7f\x00\x00\xa0\x7f\x00\x00\xa2\x7f\x00\x00\xa4\x7f\x00\x00\xa6\x7f\x00\x00\xa8\x7f\x00\x00\xaa\x7f\x00\x00\xac\x7f\x00\x00\xae\x7f\x00\x00\xb0\x7f\x00\x00\xb2\x7f\x00\x00\xb4\x7f\x00\x00\xb6\x7f\x00\x00\xb8\x7f\x00\x00\xba\x7f\x00\x00\xbc\x7f\x00\x00\xbe\x7f\x00\x00\xc0\x7f\x00\x00\xc2\x7f\x00\x00\xc4\x7f\x00\x00\xc6\x7f\x00\x00\xc8\x7f\x00\x00\xca\x7f\x00\x00\xcc\x7f\x00\x00\xce\x7f\x00\x00\xd0\x7f\x00\x00\xd2\x7f\x00\x00\xd4\x7f\x00\x00\xd6\x7f\x00\x00\xd8\x7f\x00\x00\xda\x7f\x00\x00\xdc\x7f\x00\x00\xde\x7f\x00\x00\xe0\x7f\x00\x00\xe2\x7f\x00\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\xfa\x86'
CMD_TRCD_PART4 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP4 = b'\x96\x96\x96\x96\x81\x00\x41\x03\x00\x00\xfa\x2d\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
CMD_TRCD_PART5 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP5 = b'\x96\x96\x96\x96\x81\x00\x41\x04\x00\x00\x4b\xec\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
CMD_TRCD_PART6 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP6 = b'\x96\x96\x96\x96\x81\x00\x41\x05\x00\x00\x1a\x2c\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
CMD_TRCD_PART7 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP7 = b'\x96\x96\x96\x96\x81\x00\x41\x06\x00\x00\xea\x2c\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
CMD_TRCD_PART8 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP8 = b'\x96\x96\x96\x96\x81\x00\x41\x07\x00\x00\xbb\xec\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
CMD_TRCD_PART9 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRCD_RESP9 = b'\x96\x96\x96\x96\x81\x00\xc1\x08\x00\x00\xa2\x2f\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x00\xdf\x0b\x62'
# TRAL (Upload Setup, Monitor, Simulate, Run and Display Menus) (with some repeated packets, same seqno)
CMD_TRAL = b'\x96\x96\x96\x96\x81\x04\xc0\x00\x00\x00\xd3\xd1\x54\x52\x41\x4c\x80\x44'
CMD_TRAL_R1ACC = b'\x96\x96\x96\x96\x81\x03\x40\x00\x00\x00\x4f\xd1\x41\x43\x43\x20\xd5'
CMD_TRAL_PART2 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP2 = b'\x96\x96\x96\x96\x81\x00\x41\x01\x00\x00\x5b\xed\x00\x07\x00\x02\x00\x04\x00\x01\x00\x01\x00\x02\x00\x01\x00\x01\x00\x01\x00\x01\x00\x02\x00\x03\x00\xc0\x00\x03\x00\x03\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x26\x00\x00\x00\x03\x00\x32\x00\x32\x00\x2d\x00\x2d\x00\x37\x00\x3d\x00\x70\x00\x7f\x00\xff\x00\x0a\x00\x08\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x09\x55\x73\x65\x72\x20\x64\x65\x66\x20\x20\x00\x80\x00\x80\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xe0'
CMD_TRAL_PART3 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP3 = b'\x96\x96\x96\x96\x81\x00\x41\x02\x00\x00\xab\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x05\x00\x00\x00\x17\x00\x00\x00\x1f\xde\x45\xde\x4c\x00\x00\x00\x00\xde\x68\xd3\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x2a'
CMD_TRAL_PART4 = b'\x96\x96\x96\x96\x05\x02\x40\x00\x00\x00\x6c\x55\x00\x00' # \x05\x02 = nope
CMD_TRAL_RESP4 = b'\x96\x96\x96\x96\x81\x00\x41\x02\x00\x00\xab\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x05\x00\x00\x00\x17\x00\x00\x00\x1f\xde\x45\xde\x4c\x00\x00\x00\x00\xde\x68\xd3\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x2a'
CMD_TRAL_PART5 = b'\x96\x96\x96\x96\x05\x02\x40\x00\x00\x00\x6c\x55\x00\x00' # \x05\x02 = nope
CMD_TRAL_RESP5 = b'\x96\x96\x96\x96\x81\x00\x41\x02\x00\x00\xab\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x05\x00\x00\x00\x17\x00\x00\x00\x1f\xde\x45\xde\x4c\x00\x00\x00\x00\xde\x68\xd3\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x2a'
CMD_TRAL_PART6 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP6 = b'\x96\x96\x96\x96\x81\x00\x41\x03\x00\x00\xfa\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
CMD_TRAL_PART7 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP7 = b'\x96\x96\x96\x96\x81\x00\x41\x04\x00\x00\x4b\xec\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
CMD_TRAL_PART8 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP8 = b'\x96\x96\x96\x96\x81\x00\x41\x05\x00\x00\x1a\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
CMD_TRAL_PART9 = b'\x96\x96\x96\x96\x05\x01\x40\x00\x00\x00\x28\x55\x00\x00'
CMD_TRAL_RESP9 = b'\x96\x96\x96\x96\x81\x00\x41\x06\x00\x00\xea\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# this continues... next part starts at line 6610
# all finally ends at 15332
# --- sources ---
class BytesIter:
"""
iterator for bytes
>>> list(BytesIter(b'def'))
[100, 101, 102]
>>> bytes([b for b in BytesIter(b'abc')])
b'abc'
"""
def __init__(self, data: bytes):
# serial should be open already, this won't open or close it
self.data = data
self.i = 0
def __iter__(self):
return self
def __next__(self):
try:
b = self.data[self.i]
self.i = self.i + 1
except IndexError:
raise StopIteration
return b
class SerialIter:
"""
iterator for serial
"""
def __init__(self, ser: serial):
# serial should be open already, this won't open or close it
self.ser = ser
def __iter__(self):
return self
def __next__(self):
b = self.ser.read(1)
if b == b'':
raise StopIteration
return ord(b)
def _read(itr, count: int):
"""
get (up to) count bytes from the source
>>> _read(BytesIter(b'abcdefghijklmn'), 5)
b'abcde'
"""
buff = bytes(islice(itr, count))
logger.debug(buff)
if len(buff) < count:
raise MessageFormatException("Missing data: expected {0} bytes, got {1}".format(
count, len(buff)))
return buff
def _read_from(itr, value: int, count: int):
"""
starting when we see 'value', read 'count' bytes
>>> _read_from(BytesIter(b'abcdefghijklmn'), ord('d'), 5)
b'defgh'
"""
skip = 0
while 1:
b = list(islice(itr, 1))
logger.debug(bytes(b))
if b == []:
raise MessageFormatException(f"No x{value:02x} after {skip} bytes")
if b[0] == value:
break
skip = skip + 1
return bytes(b) + _read(itr, count-1)
# --- Message class, to parse and create messages ---
class MessageFormatException(Exception):
pass
class HpMessage():
PREAMBLE = b'\x96\x96\x96\x96'
# Continuation flag:
CONT_FIN = 0xc0 # complete in itself
CONT_AND = 0x40 # expect another?
CONT_PARTIAL_DATA = 0x41 # partial packet
CONT_FINAL_DATA = 0xc1 # final packet
def __init__(self):
self.status: bool = False
self.cont: int = self.CONT_FIN
self.seqno: int = 0
self.data: bytes = None
self.rest = None
def __str__(self):
if self.data is None:
d = "no"
else:
d = len(self.data)
return "{0} bytes, {1:02x} {2:02x}, cont={3:02x}, seq={4:02x}".format(
d,
self._intro1(),
self._intro2(),
self.cont,
self.seqno
)
@property
def text(self):
# may raise if binary payload... only convert data to text when asked for it
return self.data.decode("ASCII")
def packet(self):
# (re)construct the whole packet
intro = bytes([self._intro1(), self._intro2(), self.cont, self.seqno, 0, 0])
if self.data is None:
pack = self.PREAMBLE + intro + crc_16(intro) + b'\x00\x00'
else:
pack = self.PREAMBLE + intro + crc_16(intro) + self.data + crc_16(self.data)
logger.debug(pack)
return pack
def _intro1(self):
if self.data is None:
return 0x05
else:
return 0x81
def _intro2(self):
if self.data is None:
if self.status:
return 0x01
else:
return 0x02
else:
qty = len(self.data)
if qty == 256:
return 0
else:
return qty
@staticmethod
def create(status:bool=True, data:bytes=None, more:bytes=None, seqno:int=0):
"""
Create a new message.
>>> HpMessage.create().data
>>> HpMessage.create(data=b"IDRE").text
'IDRE'
>>> HpMessage.create(data=b"IDRE").packet() == CMD_IDRE
True
>>> HpMessage.create(data=b"SEAP", more=b"VT100").next().text
'VT100'
# message with its continuation (we can send .next after receiving ACC) - see CMD_SEAP_PART2
>>> m = HpMessage.create(data=b"SEAP", more=b" VT100 ")
>>> m.next().packet().hex()
'969696968112c0010000cbd2202020202020202056543130302020202020165c'
# create a 'ok, and tell me more...' message (compare CMD_IDRE_PART2)
>>> HpMessage.create().packet().hex()
'9696969605014000000028550000'
# Create a message with a large random payload
>>> import secrets
>>> m = HpMessage.create(data=b'TEST', more=secrets.token_bytes(600))
>>> m = m.next()
>>> m.cont == HpMessage.CONT_PARTIAL_DATA
True
>>> m = m.next()
>>> m.cont == HpMessage.CONT_PARTIAL_DATA
True
>>> m = m.next()
>>> m.cont == HpMessage.CONT_FINAL_DATA
True
"""
it = HpMessage()
it.status = status
it.seqno = seqno
if isinstance(data, str):
data = data.encode("ASCII")
if isinstance(more, str):
more = more.encode("ASCII")
if data is None:
if more is None:
# we just want to send a "ok, and...?" message
it.cont = HpMessage.CONT_AND
else:
# this is continuation data from something before
if len(more) <= 256:
it.data = more
it.rest = None
it.cont = HpMessage.CONT_FINAL_DATA
else:
it.data = more[:256]
it.rest = BytesIter(more[256:])
it.cont = HpMessage.CONT_PARTIAL_DATA
else:
if len(data) <= 256:
it.data = data
if more is None:
it.cont = HpMessage.CONT_FIN
it.rest = None
else:
# needs a continuation message
it.cont = HpMessage.CONT_AND
it.rest = BytesIter(more)
else:
it.data = data[:256]
it.rest = BytesIter(data[256:])
it.cont = HpMessage.CONT_PARTIAL_DATA
if more is not None:
raise MessageFormatException("dunno, don't send MORE with long DATA")
return it
@staticmethod
def from_bytes(data: bytes):
r"""
Load and parse a message from a byte array.
The message should be complete, but can be padded at start and end.
>>> HpMessage.from_bytes(b'\x96\x96\x96\x96\x81\x04\x40\x00\x00\x00\xfa\x11\x53\x45\x41\x50\x30\xfd').text
'SEAP'
>>> HpMessage.from_bytes(b'\x00\xff\x00' + RSP_MSGF + b'\xff\x00').text
'\x00\x00\x00\x00An Applic is Already Loaded \x00'
>>> HpMessage.from_bytes(b'\xff\xff\xff\xff\xff' + RSP_ACC2 + b'\xff\xff\xff').text
'ACC'
>>> HpMessage.from_bytes(CMD_RSRE_R1ACC).status
True
>>> HpMessage.from_bytes(RSP_REJ0).status
False
>>> bytes(list(HpMessage.from_bytes(b'\x00\xff\x00' + RSP_MSGF + b'\xff\x01\x02').rest))
b'\xff\x01\x02'
# Just check we can parse these...
>>> len(HpMessage.from_bytes(RSP_REJ0).data)
3
>>> HpMessage.from_bytes(CMD_RCAH_RESP1).data is None
True
>>> HpMessage.from_bytes(CMD_CKDR_RESP1).data is None
True
>>> len(HpMessage.from_bytes(CMD_RCAH_PART2).data)
128
>>> len(HpMessage.from_bytes(CMD_TRAL_RESP2).data)
256
"""
return HpMessage.from_iterator(BytesIter(data))
@staticmethod
def from_iterator(data):
it = HpMessage()
it._parse_iter(data)
return it
def _parse_iter(self, itr):
pre = _read_from(itr, 0x96, 4)
if pre != self.PREAMBLE:
raise MessageFormatException("Bad preamble: 'x{0}'".format(bytes(pre).hex()))
intro = _read(itr, 6)
introcrc = _read(itr, 2)
if crc_16(intro) != introcrc:
raise MessageFormatException("Bad intro CRC: '{0}', expected '{1}'".format(
bytes(introcrc).hex(), crc_16(intro).hex()))
datacode = intro[0] # 0x81 or 0x05
datalen = intro[1] # length for 0x81, or status for 0x05
self.cont = intro[2] # 0xc0 (fin) or 0x40 (more) or 0x41 (partial-data) or 0xc1 (final-data)
self.seqno = intro[3] # sequence numbering for 0x41 and 0xc1
self.status = (self.cont == 0xc0 or self.cont == 0xc1)
if datacode == 5:
# 0x0501 is success with no data
# 0x0502 is failure with no data (ask for re-send)
databuff = None
datalen = 0
else:
if datalen == 0:
# Zero means 256 bytes of data
datalen = 256
databuff = _read(itr, datalen)
if len(databuff) < datalen:
raise MessageFormatException("Missing data: expected {0} bytes, got {1}".format(
datalen, len(databuff)))
datacrc = _read(itr, 2)
if crc_16(databuff) != datacrc:
raise MessageFormatException("Bad text CRC of {0} data bytes: '{1}', expected '{2}'".format(
datalen, bytes(datacrc).hex(), crc_16(databuff).hex()))
self.data = databuff
self.rest = itr
def next(self):
"""
Produce the next message
"""
if self.rest:
rest = bytes(list(self.rest))
if self.cont == HpMessage.CONT_PARTIAL_DATA:
return HpMessage.create(more=rest, seqno=self.seqno+1)
if len(rest) > 256:
return HpMessage.create(more=rest, seqno=self.seqno+1)
else:
return HpMessage.create(data=rest, seqno=self.seqno+1)
return None
def crc_16(in_data: bytes):
r"""
CRC-16 (laboriously extracted from https://github.com/tpircher/pycrc)
>>> crc_16(b'\x81\x04\xc0\x00\x00\x00')
b'\xd3\xd1'
>>> crc_16(b'\x52\x53\x52\x45') == b'\x1c\x3a'
True
>>> crc_16(b'\x49\x44\x52\x45')
b'\xaa\xda'
>>> crc_16(b'\x41\x43\x43') == b'\x20\xd5'
True
>>> crc_16(b'\x48\x50\x34\x39\x35\x32\x00') == b'\x7c\x62'
True
"""
def reflect(data, width):
"""
reflect a data word, i.e. reverts the bit order.
"""
res = data & 0x01
for _ in range(width - 1):
data >>= 1
res = (res << 1) | (data & 0x01)
return res
in_data = bytearray(in_data)
width = 16
poly = 0x8005
reflect_in = True
xor_in = 0x0
reflect_out = True
xor_out = 0x0
#check = 0xbb3d
msb_mask = 0x1 << (width - 1)
mask = ((msb_mask - 1) << 1) | 1
crc = xor_in
for _ in range(width):
bit = crc & 0x01
if bit:
crc ^= poly
crc >>= 1
if bit:
crc |= msb_mask
reg = crc & mask
for octet in in_data:
if reflect_in:
octet = reflect(octet, 8)
for i in range(8):
topbit = reg & msb_mask
reg = ((reg << 1) & mask) | ((octet >> (7 - i)) & 0x01)
if topbit:
reg ^= poly
for i in range(width):
topbit = reg & msb_mask
reg = ((reg << 1) & mask)
if topbit:
reg ^= poly
if reflect_out:
reg = reflect(reg, width)
crc = (reg ^ xor_out) & mask
return int(crc).to_bytes(2, byteorder='little')
@click.command()
@click.option("--reset", is_flag=True)
@click.option("--ident", is_flag=True)
@click.argument("port")
@click.argument("speed", default=9600)
@click.argument("filename", default=os.path.join(os.path.dirname(__file__), "../disks/04952-16009_utility_051690/VT100.APP"))
@click.argument("offset", default=0x100)
def main(reset, ident, port, speed, filename, offset):
# Read the app we want to send
# App file header begins with:
# 00000000 34 39 35 32 20 50 72 6f 74 6f 63 6f 6c 20 41 6e |4952 Protocol An|
# 00000010 61 6c 79 7a 65 72 c4 03 00 08 56 54 31 30 30 20 |alyzer....LONGER|
# 00000020 41 53 59 4e 43 20 54 45 52 4d 49 4e 41 4c 20 45 |APP DESCRIPTION |
# 00000030 4d 55 4c 41 20 4f 52 20 20 20 00 00 00 00 00 00 |GOES HERE ......|
# which is just a "local app name" and isn't sent across the wire.
#
# Then the actual app header begins at 0x100, e.g.
# 00000100 00 00 58 00 20 20 20 20 20 20 20 20 54 45 52 4d |..X. TERM|
# 00000110 49 4e 41 4c 20 20 34 39 35 32 20 20 00 08 00 01 |INAL 4952 ....|
# 00000120 41 73 79 6e 63 20 54 65 72 6d 69 6e 61 6c 20 45 |Async Terminal E|
# 00000130 6d 75 6c 61 74 6f 72 20 2d 20 44 55 4d 42 20 20 |mulator - DUMB |
# From David Kuder's 4952oss, the third byte (0x58) is
# (the number of 256-byte blocks in the whole file) - 1, in this case
# file size between 22528 and 22784 bytes (vt100.app is 22784).
#
# But apps extracted with lifutils, *** without the "-r" option, ***
# include an extra 0x20 bytes (the directory entry) at their start, so you may need
# to specify offset 0x120 to download those to the analyzer.
start_offset = offset
app_path = filename
app = None
appdata = None
do_load = False
if not (reset or ident):
do_load = True
with open(app_path, "rb") as appfile:
app = bytearray(appfile.read())
# skip first 0x100 of the app binary
appdata = app[start_offset:]
def send_message(ser, msg):
"""
Send a message and read the response
"""
logger.debug(f"Sending '{msg.text}'")
response = None
while 1:
logger.debug(f"Sending '{msg}'")
ser.write(msg.packet())
ser.write(0xff)
# Read the response
response = HpMessage.from_iterator(SerialIter(ser))
# TODO (for getting long data from the analyzer):
#if response.cont == HpMessage.CONT_PARTIAL_DATA:
# keep going until we got the chain of data
# (TODO: have the chain present as a single big buffer)
# TODO request re-send if we see a bad crc, etc
if response.data:
logger.debug(f"Received '{response.text}'")
if response.cont in (HpMessage.CONT_FIN, HpMessage.CONT_FINAL_DATA):
# this is the last message in sequence; we're done
# (unless we had more to send!)
if msg.rest:
logger.debug("Uh oh, we didn't finish")
return response
if response.cont == HpMessage.CONT_AND:
msg = msg.next()
if msg is None:
msg = HpMessage.create()
return response
with serial.Serial(port, speed, timeout=5) as ser:
if reset:
# reset
cmd = HpMessage.create(data='RSRE')
rsp = send_message(ser, cmd)
if rsp.text != "ACC":
sys.exit("Failed!")
if ident or do_load:
cmd = HpMessage.create(data='IDRE')
rsp = send_message(ser, cmd)
logger.info(rsp.text)
if do_load:
# OK, now try something more ambitious:
# install the app
cmd = HpMessage.create(data="DEAP")
send_message(ser, cmd)
cmd = HpMessage.create(data="TRRS")
send_message(ser, cmd)
cmd = HpMessage.create(data="RCAH", more=appdata[:0x80])
rsp = send_message(ser, cmd)
if rsp.text != "ACC":
sys.exit("Failed!")
# Send the app in blocks of 2kb
blocknum = 0
while appdata:
logger.info(f"App Block {blocknum}")
blockdata = appdata[:2048]
appdata = appdata[2048:]
seblflag = 0 if blocknum == 0 else 1 if appdata else 2
sebldata = bytes([0, blocknum, 8, 0, 0, seblflag])
cmd = HpMessage.create(data="SEBL", more=sebldata)
send_message(ser, cmd)
cmd = HpMessage.create(data="RCAP", more=blockdata)
send_message(ser, cmd)
blocknum = blocknum + 1
# App name is not important for 4592a
# cmd4 = HpMessage.create(data="SEAP", more=b' VT100 ')
cmd = HpMessage.create(data="SEAP", more=b' ')
send_message(ser, cmd)
# Execute!
cmd = HpMessage.create(data="EXAP")
rsp = send_message(ser, cmd)
logger.info(rsp.text)
if __name__ == "__main__":
main()