I know this isn't the preferred solution but the way I solved this was with an 8 byte code patch, and yes I know this is old, but hey we ARE in the Reverse Engineering section
Lets look at what's actually contained in the 'evsup1' byte;
Bit 0 : Catalyst monitoring 0xFE 1111 1110 0000 0001 1 0x01
Bit 1 : Heated catalyst monitoring 0xFD 1111 1101 0000 0010 2 0x02
Bit 2 : Evaporative system monitoring 0xFB 1111 1011 0000 0100 4 0x04
Bit 3 : Secondary air system monitoring 0xF7 1111 0111 0000 1000 8 0x08
Bit 4 : A/C system refrigerant monitoring 0xEF 1110 1111 0001 0000 16 0x10
Bit 5 : Oxygen sensor monitoring 0xDF 1101 1111 0010 0000 32 0x20
Bit 6 : Oxygen sensor heater monitoring 0xBF 1011 1111 0100 0000 64 0x40
Bit 7 : EGR system monitoring 0x7F 0111 1111 1000 0000 128 0x80
For example on this car I was looking at.
EVSUP1: 0x6D 0 1 1 0 1 1 0 1
7 6 5 4 3 2 1 0 bits
---------------
EVSUP1: 0x6D 0 1 1 0 1 1 0 1
| | | | | | | |
| | | | | | | +--- b_katfz Bit 0 : Condition bit for Catalyst monitoring Support
| | | | | | +----- b_kath Bit 1 : Condition bit for Heated catalyst monitoring Support
| | | | | +------- b_cdtes Bit 2 : Condition bit for Evaporative system monitoring Support
| | | | +--------- b_cdsls Bit 3 : Condition bit for Secondary air system monitoring Support
| | | +----------- b_??? Bit 4 : Condition bit for A/C system refrigerant monitoring Support
| | +------------- b_cdlsv Bit 5 : Condition bit for Oxygen sensor monitoring Support
| +--------------- b_cdhsv Bit 6 : Condition bit for Oxygen sensor heater monitoring Support
+----------------- b_cdagr Bit 7 : Condition bit for EGR system monitoring Support
In my case it looks like this... Obviously depends on the version of ME7.x your looking at.
Easy way to find it is look up the correct function from the function table. Search for the KWP2000_Setup_ini() function where it sets the services_table_OTHER.
e.g.
Init_KWP2000_Setup_ini:
mov r4, #kwp2000_checksumCalc_func
mov r5, #0
mov asc0_KWP2000_ChecksumCalculate_Function, r4
mov asc0_KWP2000_ChecksumCalculate_Function_segment, r5
mov r4, #kwp_timings_table0
mov r5, #0
mov kwp2000_Timings, r4
mov kwp2000_Timings_segment, r5
mov r4, #kwp_timings_table4
mov r5, #206h
mov kwp2000_Timings_Limit, r4
mov kwp2000_Timings_Limit_segment, r5
mov r4, #services_table_OTHER ; <--------------- ******** this one
mov r5, #206h
mov kwp2000_Services, r4
mov kwp2000_Services_segment, r5
mov r4, #serviceIndex_table1
mov r5, #206h
mov kwp2000_ServicesIndex, r4
mov kwp2000_ServicesIndex_segment, r5
mov r4, #KWPDIAG_Strings
mov r5, #206h
mov kwp2000_ECUD_datas, r4
mov kwp2000_ECUID_Table_segment, r5
...
e.g. In my firmware...
services_table_OTHER:
dw kwp2000_service_notSupported
dw 0
dw kwp2000_srv_startCommunication_81h
dw 82h
dw kwp2000_service_stopCommunication_82h
dw 0
dw kwp2000_service_accessTimingParameter_83h
dw 0
dw kwp2000_service_startDiagnosticSession_10h_VER_2
dw 82h
dw kwp2000_service_stopDiagnosticSession_20h
dw 0
dw kwp2000_service_startCommunicationMcMess_A0h
dw 82h
dw kwp2000_service_readEcuIdentification_1Ah
dw 82h
dw kwp2000_service_securityAccess_27h
dw 0
dw kwp2000_service_testerPresent_3Eh
dw 0
dw kwp2000_service_startRoutinebyLocalIdentifier_31h
dw 0
dw kwp2000_service_stopRoutineByLocalIdentifier_32h
dw 0
dw kwp2000_service_requestRoutineResultsByLocalIdentifier_33h
dw 82h
dw kwp2000_service_requestDownload_34h
dw 0
dw kwp2000_service_transferData_36h
dw 0
dw kwp2000_service_requestTransferExit_37h
dw 0
dw kwp2000_srv_ECUReset_suspected_11h_ret51h
dw 82h
dw kwp2000_srv_readDataByLocalIdentifier_21h
dw 83h
dw kwp2000_srv_readDataByCommonIdentifier_22h
dw 83h
dw kwp2000_srv_dynamicallyDefineLocalIdentifier_2Ch
dw 83h
dw kwp2000_srv_writeDataByLocalIdentifier_3Bh
dw 83h
dw kwp2000_srv_readMemoryByAddress_23h
dw 83h
dw kwp2000_srv_writeMemoryByAddress_3Dh
dw 83h
dw kwp2000_srv_readFreezeFrameData_func1_12h
dw 83h
dw kwp2000_srv_clearDiagnosticsInformation_14h
dw 83h
dw kwp2000_srv_readStatusOfDiagnosticTroubleCodes_17h
dw 83h
dw kwp2000_srv_readDiagnosticTroubleCodesByStatus_18h
dw 83h
dw kwp2000_srv_cmd_Negative_Response_7Fh
dw 83h
**** dw J1939_TC2MOD_DTCs_A_Pending_41h_CARB_Mode_1 <------------------- ****
dw 83h
dw J1939_TC8MOD_DTCs_A_ConfirmedActive_cmd_42h
dw 83h
dw J1939_TC8MOD_DTCs_A_PreviouslyActive_cmd_43h
dw 83h
dw J1939_TC8MOD_DTCs_B1_Pending_cmd_44h
dw 83h
dw J1939_TC8MOD_DTCs_B1_ConfirmedActive_cmd_45h
dw 83h
dw J1939_TC8MOD_DTCs_B1_PreviouslyActive_cmd_46h
dw 83h
dw J1939_TC8MOD_DTCs_B2_Pending_cmd_47h
dw 83h
dw J1939_TC8MOD_DTCs_B2_PreviouslyActive_cmd_48h
dw 83h
dw kwp2000_srv_inputOutputControlByLocalIdentifier_30h
dw 82h
So inside of J1939_TC2MOD_DTCs_A_Pending_41h_CARB_Mode_1(), that function makes a call to DIMC_J1939_TC1MOD_CARB_Mode_1().
That function uses a jump table to choose the appropriate PID call to use. Find PID 0x01 and you are there.
e.g.
DIMC_CARB_StatusInformationIncReadiness_PID_01h:
mov r12, #1
calls 83h, GetDTCPidsNumOf
movb [r6], rl4
movbz r4, milstat ; milstat : [DMIL CAN]
and r4, #40h
jmpr cc_Z, _skip_milstat_set
movb rl4, [r6]
addb rl4, #80h ; 'Ç' ; milstat set
movb [r6], rl4
_skip_milstat_set:
movb rl4, #4
movb [r7], rl4
mov r4, cd_bits1_w ; cd_bits1_w
and r4, #cdbits1w_0_CDMD
jmpr cc_Z, _not_CDMD_set
movb rl4, [r7]
orb rl4, #1 ; CDMD set
movb [r7], rl4
_not_CDMD_set:
mov r4, cd_bits1_w ; cd_bits1_w
and r4, #cdbits1w_11_CDKVS
jmpr cc_Z, _not_CDKVS_set
movb rl4, [r7]
orb rl4, #2 ; CDKVS set
movb [r7], rl4
_not_CDKVS_set:
;---------------------------------------------------------------------------------
movb [r8], evsup1 ; gets evsup1
movb rl4, ready ; gets readiness byte
movb [r9+5], rl4 ; returns in the payload of the protocol
;---------------------------------------------------------------------------------
movb rl4, #6
jmpa cc_UC, _exit_func
In my case it was trivial to force it with a few bytes patch...
** BEFORE **
0x00038D24:seg083: (+0 ) A4 08 B1 8A movb [r8], evsup1
0x00038D28:seg083: (+4 ) F3 F8 0F B3 movb r14, ready
0x00038D2C:seg083: (+8 ) E4 89 05 00 movb [r9+5], r14
***
** AFTER ** : Applied Forced Readiness and evsup1
0x00038D24:seg083: (+0 ) E7 F8 6D 00 movb r14, #006Dh ; <---- force use of any evsup1 value you want
0x00038D28:seg083: (+4 ) B9 88 movb [r8], r14
0x00038D2A:seg083: (+6 ) E1 08 movb r14, #0
0x00038D2C:seg083: (+8 ) E4 89 05 00 movb [r9+5], r14
***
Just change the value, in this case the 6D to whatever bitmask of supported features you want and your done. No waiting for drive cycles or other such stuff.