| 1 | #ifndef _SCANTOOL_H_ |
| 2 | #define _SCANTOOL_H_ |
| 3 | /* |
| 4 | * freediag - Vehicle Diagnostic Utility |
| 5 | * |
| 6 | * |
| 7 | * Copyright (C) 2001 Richard Almeida & Ibex Ltd ([email protected]) |
| 8 | * |
| 9 | * This program is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation; either version 2 of the License, or |
| 12 | * (at your option) any later version. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | * GNU General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU General Public License |
| 20 | * along with this program; if not, write to the Free Software |
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 22 | * |
| 23 | ************************************************************************* |
| 24 | * |
| 25 | * |
| 26 | * J1978 Scan tool |
| 27 | */ |
| 28 | |
| 29 | #include <stdint.h> |
| 30 | #include <stddef.h> |
| 31 | |
| 32 | #include "diag.h" |
| 33 | |
| 34 | #if defined(__cplusplus) |
| 35 | extern "C" { |
| 36 | #endif |
| 37 | |
| 38 | |
| 39 | /* Structure to hold responses */ |
| 40 | typedef struct { |
| 41 | uint8_t type; |
| 42 | uint8_t len; |
| 43 | uint8_t data[7]; |
| 44 | |
| 45 | } response; |
| 46 | |
| 47 | #define TYPE_UNTESTED 0 /* unchecked, prob because ECU doesn't support */ |
| 48 | #define TYPE_FAILED 1 /* Got failure response */ |
| 49 | #define TYPE_GOOD 2 /* Valid info */ |
| 50 | |
| 51 | /* |
| 52 | * This structure holds all the data/config info for a given ecu |
| 53 | * - one request can result in more than one ECU responding, and so |
| 54 | * the data is stored in this |
| 55 | */ |
| 56 | typedef struct { |
| 57 | uint8_t valid; /* Valid flag */ |
| 58 | uint8_t ecu_addr; /* Address */ |
| 59 | |
| 60 | uint8_t supress; /* Supress output of data from ECU in monitor mode; not implemented*/ |
| 61 | |
| 62 | uint8_t mode1_info[0x100]; /* Pids supported by ECU */ |
| 63 | uint8_t mode2_info[0x100]; /* Freeze frame version */ |
| 64 | uint8_t mode5_info[0x100]; /* Mode 5 info */ |
| 65 | uint8_t mode6_info[0x100]; /* Mode 6 info */ |
| 66 | uint8_t mode8_info[0x100]; /* Mode 8 info */ |
| 67 | uint8_t mode9_info[0x100]; /* Mode 9 info */ |
| 68 | |
| 69 | uint8_t data_good; /* Flags for above data */ |
| 70 | |
| 71 | uint8_t O2_sensors; /* O2 sensors bit mask */ |
| 72 | |
| 73 | response mode1_data[256]; /* Response data for all responses */ |
| 74 | response mode2_data[256]; /* Same, but for freeze frame */ |
| 75 | |
| 76 | struct diag_msg *rxmsg; /* Received message */ |
| 77 | } ecu_data; |
| 78 | |
| 79 | #define ECU_DATA_PIDS 0x01 |
| 80 | #define ECU_DATA_MODE2 0x02 |
| 81 | #define ECU_DATA_MODE5 0x04 |
| 82 | #define ECU_DATA_MODE6 0x08 |
| 83 | #define ECU_DATA_MODE8 0x10 |
| 84 | #define ECU_DATA_MODE9 0x20 |
| 85 | |
| 86 | #define MAX_ECU 8 /* Max 8 Ecus responding */ |
| 87 | extern ecu_data ecu_info[MAX_ECU]; |
| 88 | extern unsigned int ecu_count; |
| 89 | |
| 90 | struct diag_l2_conn; |
| 91 | struct diag_l3_conn; |
| 92 | |
| 93 | /** Send a SAE J1979 request, get a response, and partially process it |
| 94 | * |
| 95 | * J1979 messages are 7 data bytes long: mode(SID) byte + max 6 extra bytes |
| 96 | * (J1979 5.3.2; table 8) |
| 97 | * @return 0 if ok |
| 98 | */ |
| 99 | int l3_do_j1979_rqst(struct diag_l3_conn *d_conn, uint8_t mode, uint8_t p1, uint8_t p2, |
| 100 | uint8_t p3, uint8_t p4, uint8_t p5, uint8_t p6, void *handle); |
| 101 | |
| 102 | /* |
| 103 | * Send some data on the connection |
| 104 | */ |
| 105 | int l3_do_send( struct diag_l3_conn *d_conn, void *data, size_t len, void *handle); |
| 106 | int l2_do_send( struct diag_l2_conn *d_conn, void *data, size_t len, void *handle); |
| 107 | int l2_check_pid_bits(uint8_t *data, int pid); |
| 108 | int do_l2_9141_start(int destaddr); // 9141 init |
| 109 | int do_l2_14230_start(int init_type); //14230 init |
| 110 | int do_j1979_getdtcs(void); |
| 111 | int do_j1979_getO2sensors(void); |
| 112 | int diag_cleardtc(void); |
| 113 | int ecu_connect(void); |
| 114 | |
| 115 | struct diag_msg *find_ecu_msg(int byte, databyte_type val); |
| 116 | |
| 117 | /* |
| 118 | * Handle values for above (l3_do_j1979_rqst, j1979_data_rcv, etc) |
| 119 | * XXX This was extremely irregular: they were passed as void pointers. |
| 120 | * Now they are rather declared as const ints so we can pass |
| 121 | * pointers to that instead of masquerading ints as void pointers. |
| 122 | */ |
| 123 | #define RQST_HANDLE_NORMAL 0 /* Normal mode */ |
| 124 | #define RQST_HANDLE_WATCH 1 /* Watching, add timestamp */ |
| 125 | #define RQST_HANDLE_DECODE 2 /* Just decode what arrived */ |
| 126 | #define RQST_HANDLE_NCMS 3 /* Non cont. mon. tests */ |
| 127 | #define RQST_HANDLE_NCMS2 4 /* Ditto, print fails only */ |
| 128 | #define RQST_HANDLE_O2S 5 /* O2 sensor tests */ |
| 129 | #define RQST_HANDLE_READINESS 6 /* Readiness Tests */ |
| 130 | extern const int _RQST_HANDLE_NORMAL; //Normal mode |
| 131 | extern const int _RQST_HANDLE_WATCH; //Watching; add timestamp |
| 132 | extern const int _RQST_HANDLE_DECODE; //Just decode what arrived |
| 133 | extern const int _RQST_HANDLE_NCMS; //Non cont. mon. tests |
| 134 | extern const int _RQST_HANDLE_NCMS2; //Ditto; print fails only |
| 135 | extern const int _RQST_HANDLE_O2S; //O2 sensor tests |
| 136 | extern const int _RQST_HANDLE_READINESS; //Readiness tests |
| 137 | |
| 138 | int do_j1979_getdata(int interruptible_flag); |
| 139 | void do_j1979_basics(void); |
| 140 | void do_j1979_cms(void); |
| 141 | void do_j1979_ncms(int); |
| 142 | void do_j1979_getpids(void); |
| 143 | void do_j1979_O2tests(void); |
| 144 | void do_j1979_getO2tests(int O2sensor); |
| 145 | |
| 146 | /* |
| 147 | * Receive callback routines for various L3/L2 types |
| 148 | */ |
| 149 | void j1979_data_rcv(void *handle, struct diag_msg *msg); |
| 150 | void j1979_watch_rcv(void *handle, struct diag_msg *msg); |
| 151 | void l2raw_data_rcv(void *handle, struct diag_msg *msg); |
| 152 | |
| 153 | |
| 154 | |
| 155 | /** J1979 PID structures + utils **/ |
| 156 | struct pid; |
| 157 | /* format <numbytes> bytes of data into buf, up to <maxlen> chars. */ |
| 158 | typedef void (formatter)(char *buf, int maxlen, int units, const struct pid *, response *, int numbytes); |
| 159 | |
| 160 | struct pid { |
| 161 | int pidID; |
| 162 | const char *desc; |
| 163 | formatter *cust_snprintf; |
| 164 | int bytes; |
| 165 | const char *fmt1; // SI |
| 166 | double scale1; |
| 167 | double offset1; |
| 168 | const char *fmt2; // English (typically) |
| 169 | double scale2; |
| 170 | double offset2; |
| 171 | }; |
| 172 | |
| 173 | #define DATA_VALID(p, d) (d[p->pidID].type == TYPE_GOOD) |
| 174 | #define DATA_1(p, n, d) (d[p->pidID].data[n]) /* extract 8bit value @offset n */ |
| 175 | #define DATA_2(p, n, d) (DATA_1(p, n, d) * 256 + DATA_1(p, n+1, d)) /* extract 16bit value @offset n */ |
| 176 | #define DATA_RAW(p, n, d) (p->bytes == 1 ? DATA_1(p, n, d) : DATA_2(p, n, d)) |
| 177 | |
| 178 | #define DATA_SCALED(p, v) (v * p->scale1 + p->offset1) |
| 179 | #define DATA_ENGLISH(p, v) (v * p->scale2 + p->offset2) |
| 180 | |
| 181 | |
| 182 | const struct pid *get_pid ( unsigned int i ); |
| 183 | |
| 184 | |
| 185 | #if defined(__cplusplus) |
| 186 | } |
| 187 | #endif |
| 188 | #endif /* _SCANTOOL_H_ */ |
| 189 | |