• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SPDX-License-Identifier: GPL-2.0-only
2# This file is part of Scapy
3# See https://scapy.net/ for more information
4# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>
5# Copyright (C) Nils Weiss <nils@we155.de>
6
7# scapy.contrib.status = skip
8
9from scapy.fields import ByteField, XByteField, BitEnumField, \
10    PacketListField, XBitField, XByteEnumField, FieldListField, FieldLenField
11from scapy.packet import Packet
12from scapy.contrib.automotive.obd.packet import OBD_Packet
13from scapy.config import conf
14
15
16class OBD_DTC(OBD_Packet):
17    name = "DiagnosticTroubleCode"
18
19    locations = {
20        0b00: 'Powertrain',
21        0b01: 'Chassis',
22        0b10: 'Body',
23        0b11: 'Network',
24    }
25
26    fields_desc = [
27        BitEnumField('location', 0, 2, locations),
28        XBitField('code1', 0, 2),
29        XBitField('code2', 0, 4),
30        XBitField('code3', 0, 4),
31        XBitField('code4', 0, 4),
32    ]
33
34
35class OBD_NR(Packet):
36    name = "NegativeResponse"
37
38    responses = {
39        0x10: 'generalReject',
40        0x11: 'serviceNotSupported',
41        0x12: 'subFunctionNotSupported-InvalidFormat',
42        0x21: 'busy-RepeatRequest',
43        0x22: 'conditionsNotCorrectOrRequestSequenceError',
44        0x78: 'requestCorrectlyReceived-ResponsePending'
45    }
46
47    fields_desc = [
48        XByteField('request_service_id', 0),
49        XByteEnumField('response_code', 0, responses)
50    ]
51
52    def answers(self, other):
53        return self.request_service_id == other.service and \
54            (self.response_code != 0x78 or
55             conf.contribs['OBD']['treat-response-pending-as-answer'])
56
57
58class OBD_S01(Packet):
59    name = "S1_CurrentData"
60    fields_desc = [
61        FieldListField("pid", [], XByteField('', 0))
62    ]
63
64
65class OBD_S02_Record(OBD_Packet):
66    fields_desc = [
67        XByteField('pid', 0),
68        ByteField('frame_no', 0)
69    ]
70
71
72class OBD_S02(Packet):
73    name = "S2_FreezeFrameData"
74    fields_desc = [
75        PacketListField("requests", [], OBD_S02_Record)
76    ]
77
78
79class OBD_S03(Packet):
80    name = "S3_RequestDTCs"
81
82
83class OBD_S03_PR(Packet):
84    name = "S3_ResponseDTCs"
85    fields_desc = [
86        FieldLenField('count', None, count_of='dtcs', fmt='B'),
87        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)
88    ]
89
90    def answers(self, other):
91        return isinstance(other, OBD_S03)
92
93
94class OBD_S04(Packet):
95    name = "S4_ClearDTCs"
96
97
98class OBD_S04_PR(Packet):
99    name = "S4_ClearDTCsPositiveResponse"
100
101    def answers(self, other):
102        return isinstance(other, OBD_S04)
103
104
105class OBD_S06(Packet):
106    name = "S6_OnBoardDiagnosticMonitoring"
107    fields_desc = [
108        FieldListField("mid", [], XByteField('', 0))
109    ]
110
111
112class OBD_S07(Packet):
113    name = "S7_RequestPendingDTCs"
114
115
116class OBD_S07_PR(Packet):
117    name = "S7_ResponsePendingDTCs"
118    fields_desc = [
119        FieldLenField('count', None, count_of='dtcs', fmt='B'),
120        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)
121    ]
122
123    def answers(self, other):
124        return isinstance(other, OBD_S07)
125
126
127class OBD_S08(Packet):
128    name = "S8_RequestControlOfSystem"
129    fields_desc = [
130        FieldListField("tid", [], XByteField('', 0))
131    ]
132
133
134class OBD_S09(Packet):
135    name = "S9_VehicleInformation"
136    fields_desc = [
137        FieldListField("iid", [], XByteField('', 0))
138    ]
139
140
141class OBD_S0A(Packet):
142    name = "S0A_RequestPermanentDTCs"
143
144
145class OBD_S0A_PR(Packet):
146    name = "S0A_ResponsePermanentDTCs"
147    fields_desc = [
148        FieldLenField('count', None, count_of='dtcs', fmt='B'),
149        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)
150    ]
151
152    def answers(self, other):
153        return isinstance(other, OBD_S0A)
154