📄 scantool.c
字号:
if (mode > J1979_MODE_MAX) return(-1); else msg.len = mode_lengths[mode]; msg.data = data; data[0] = mode; data[1] = p1; data[2] = p2; data[3] = p3; data[4] = p4; data[5] = p5; data[6] = p6; data[7] = p7; diag_l3_send(d_conn, &msg); /* And get response(s) within a short while */ rv = diag_l3_recv(d_conn, 300, j1979_data_rcv, handle); if (rv < 0) { /* Try again */ if (diag_cmd_debug > 0xF8) { printf("retry\n"); } diag_l3_send(d_conn, &msg); rv = diag_l3_recv(d_conn, 300, j1979_data_rcv, handle); if (rv < 0) { rv = do_l3_md1pid0_rqst(global_l2_conn); if (rv < 0) printf("resync failed, connection to ECU may be lost"); return(rv); } } switch ((u_int32_t)handle) { /* We dont process the info in watch/decode mode */ case RQST_HANDLE_WATCH: case RQST_HANDLE_DECODE: return(rv); } /* * Go thru the ecu_data and see what was received. */ for (i=0, ep=ecu_info; i<ecu_count; i++, ep++) { if (ep->rxmsg) { /* Some data arrived from this ecu */ rxmsg = ep->rxmsg; rxdata = ep->rxmsg->data; switch (mode) { case 1: if (rxdata[0] != 0x41) { ep->mode1_data[p1].type = TYPE_FAILED; break; } memcpy(ep->mode1_data[p1].data, rxdata, rxmsg->len); ep->mode1_data[p1].len = rxmsg->len; ep->mode1_data[p1].type = TYPE_GOOD; break; case 2: if (rxdata[0] != 0x42) { ep->mode2_data[p1].type = TYPE_FAILED; break; } memcpy(ep->mode2_data[p1].data, rxdata, rxmsg->len); ep->mode2_data[p1].len = rxmsg->len; ep->mode2_data[p1].type = TYPE_GOOD; break; } } } return(0);}/* * Send some data to the ECU (L3) */intl3_do_send(diag_l3_conn_t *d_conn, char *data, int len, void *handle){ diag_msg_t msg; int rv; /* Put in src/dest etc, L3 or L2 may override/ignore them */ msg.src = set_testerid; msg.dest = set_destaddr; msg.len = len; msg.data = data; diag_l3_send(d_conn, &msg); /* And get response(s) */ rv = diag_l3_recv(d_conn, 300, j1979_data_rcv, handle); return (rv);}/* * Same but L2 type */intl2_do_send(diag_l2_conn_t *d_conn, char *data, int len, void *handle){ diag_msg_t msg; int rv; /* Put in src/dest etc, L2 may override/ignore them */ msg.src = set_testerid; msg.dest = set_destaddr; msg.len = len; msg.data = data; diag_l2_send(d_conn, &msg); /* And get response(s) */ rv = diag_l2_recv(d_conn, 300, l2raw_data_rcv, handle); return (rv);}/* * Common start routine used by all protocols * - initialises the diagnostic layer * - opens a Layer 2 device for the specified Layer 1 protocol * If necessary tries to poll the ECU * returns L2 file descriptor */diag_l2_conn_t * do_l2_common_start(int L1protocol, int L2protocol, u_int32_t type, int bitrate, u_int8_t target, u_int8_t source ){ int rv, fd; diag_l2_conn_t *d_conn = NULL; int l2flags; /* Clear out all ECU data as we're starting again */ clear_data(); rv = diag_init(); if (rv != 0) { fprintf(stderr, "diag_init failed\n"); return(NULL); } rv = diag_l2_open(set_interface, set_subinterface, L1protocol); if (rv < 0) { if ((rv != DIAG_ERR_BADIFADAPTER) && (rv != DIAG_ERR_PROTO_NOTSUPP)) printf("Failed to open hardware interface\n"); return(NULL); } fd = rv; /* Now do the Layer 2 startcommunications */ d_conn = diag_l2_StartCommunications(fd, L2protocol, type, bitrate, target, source); if (d_conn == NULL) { diag_l2_close(fd); return(NULL); } /* * Now Get the L2 flags, and if this is a network type where * startcommunications always works, we have to try and see if * the ECU is there * * Some interface types will always return success from StartComms() * but you only know if the ECU is on the network if you then can * send/receive data to it in the appropriate format. * For those type of interfaces we send a J1979 mode1 pid1 request * (since we are a scantool, thats the correct thing to send) */ if (diag_l2_ioctl(d_conn, DIAG_IOCTL_GET_L2_FLAGS, &l2flags) != 0) { printf("Failed to get Layer 2 flags\n"); diag_l2_close(fd); return(NULL); } if (l2flags & DIAG_L2_FLAG_CONNECTS_ALWAYS) { rv = do_l3_md1pid0_rqst(d_conn); if (rv < 0) { /* Not actually there, close L2 and go */ diag_l2_close(fd); return(NULL); } } return(d_conn);}/* * Send a mode1 pid1 request and wait for a response. This is used to * (a) See if there is an ECU there * (b) Error recovery if we get multiple timeouts on an ECU * * It cant use the normal request routine, since that calls this * * * XXX This is wrong and needs to talk to L3 not L2, so this breaks * on ISO9141 type interfaces */int do_l3_md1pid0_rqst( diag_l2_conn_t *d_conn ){ diag_msg_t msg; diag_msg_t *rmsg; u_int8_t data[256]; int rv; int errval = DIAG_ERR_GENERAL; /* Create mode 1 pid 0 message */ msg.src = set_testerid; msg.dest = set_destaddr; msg.len = 2; msg.data = data; data[0] = 1; data[1] = 0; // Do a L2 request ... rmsg = diag_l2_request(d_conn, &msg, &errval); if (rmsg != NULL) { /* Check its a Mode1 Pid0 response */ if (rmsg->len < 1) { return(DIAG_ERR_BADDATA); } if (rmsg->data[0] != 0x41) { return(DIAG_ERR_BADDATA); } return(0); } return(errval);}/* * 9141 init */int do_l2_9141_start(int destaddr){ diag_l2_conn_t *d_conn; d_conn = do_l2_common_start(DIAG_L1_ISO9141, DIAG_L2_PROT_ISO9141_2, DIAG_L2_TYPE_SLOWINIT, set_speed, (u_int8_t)destaddr, set_testerid); if (d_conn == NULL) return(-1); /* Connected ! */ global_l2_conn = d_conn; return(0);}/* * 14120 init */intdo_l2_14230_start(int init_type){ diag_l2_conn_t *d_conn; int flags = 0; if (set_addrtype == 1) flags = DIAG_L2_TYPE_FUNCADDR; else flags = 0; flags |= DIAG_L2_IDLE_J1978; /* Use J1978 idle msgs */ flags |= (init_type & DIAG_L2_TYPE_INITMASK) ; d_conn = do_l2_common_start(DIAG_L1_ISO14230, DIAG_L2_PROT_ISO14230, flags, set_speed, 0x33, set_testerid); if (d_conn == NULL) return(-1); /* Connected ! */ global_l2_conn = d_conn; return(0);}/* * J1850 init, J1850 interface type passed as l1_type */intdo_l2_j1850_start(int l1_type){ int fd, rv; int flags = 0; diag_l2_conn_t *d_conn; d_conn = do_l2_common_start(l1_type, DIAG_L2_PROT_SAEJ1850, flags, set_speed, 0x6a, set_testerid); if (d_conn == NULL) return(-1); /* Connected ! */ global_l2_conn = d_conn; return(0);}/* * Generic init, using parameters set by user */do_l2_generic_start(void){ diag_l2_conn_t *d_conn; int fd, rv; int flags = 0; rv = diag_init(); if (rv != 0) { fprintf(stderr, "diag_init failed\n"); return(-1); } /* Open interface using hardware type ISO14230 */ fd = diag_l2_open(set_interface, set_subinterface, set_L1protocol); if (fd < 0) { if ((fd != DIAG_ERR_BADIFADAPTER) && (fd != DIAG_ERR_PROTO_NOTSUPP)) printf("Failed to open hardware interface protocol %d\n", set_L1protocol); return(-1); } if (set_addrtype == 1) flags = DIAG_L2_TYPE_FUNCADDR; else flags = 0; flags |= (set_initmode & DIAG_L2_TYPE_INITMASK) ; d_conn = diag_l2_StartCommunications(fd, set_L2protocol, flags, set_speed, set_destaddr, set_testerid); if (d_conn == NULL) { diag_l2_close(fd); return(-1); } /* Connected ! */ global_l2_conn = d_conn; global_l2_fd = fd; /* Saved for close */ return(0);}/* * Gets the data for every supported test * * Returns <0 on failure, 0 on good and 1 on interrupted * * If Interruptible is 1, then this is interruptible by the stdin * becoming ready for read (using diag_os_read() with a timeout of 0) * * It is used in "Interuptible" mode when doing "monitor" command */intdo_j1979_getdata(int interruptible){ int i,j, rv; diag_l3_conn_t *d_conn; ecu_data_t *ep; diag_msg_t *msg; d_conn = global_l3_conn; /* * Now get all the data supported */ for (i=3; i<0x100; i++) { if (merged_mode1_info[i]) { rv = l3_do_j1979_rqst(d_conn, 0x1, i, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (void *)0); if (rv < 0) { printf("Mode 1 Pid 0x%x request failed %d\n", i, rv); } else { msg = find_ecu_msg(0, 0x41); if (msg == NULL) printf("Mode 1 Pid 0x%x request no-data %d\n", i, rv); } if (interruptible) { rv = diag_os_read(fileno(stdin), NULL, 0, 0); if (rv == 0) return(1); } } } /* Get mode2/pid2 (DTC that caused freezeframe) */ rv = l3_do_j1979_rqst(d_conn, 0x2, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (void *)0); if (rv < 0) { printf("Mode 2 Pid 2 request failed %d\n", rv); return(0); } msg = find_ecu_msg(0, 0x42); if (msg == NULL) { printf("Mode 2 Pid 2 request no-data %d\n", rv); return(0); } /* Now go thru the ECUs that have responded with mode2 info */ for (j=0, ep=ecu_info; j<ecu_count; j++, ep++) { if ( (ep->mode1_data[2].type == TYPE_GOOD) && (ep->mode1_data[2].data[2] | ep->mode1_data[2].data[3]) ) { for (i=3; i<=0x100; i++) { if (ep->mode2_info[i]) { rv = l3_do_j1979_rqst(d_conn, 0x2, i, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (void *)0); if (rv < 0) { printf("Mode 2 Pid 0x%x request failed %d\n", i, rv); } msg = find_ecu_msg(0, 0x42); if (msg == NULL) { printf("Mode 2 Pid 2 request no-data %d\n", rv); return(0); } } if (interruptible) { rv = diag_os_read(fileno(stdin), NULL, 0, 0); if (rv == 0) { return(1); } } } } } return(0);}/* * Find out basic info from the ECU (what it supports, DTCs etc) * * This is the basic work horse routine */voiddo_j1979_basics(){ diag_l3_conn_t *d_conn; ecu_data_t *ep; int i; int o2monitoring = 0; d_conn = global_l3_conn; /* * Get supported PIDs and Tests etc */ do_j1979_getpids(); global_state = STATE_SCANDONE ; /* * Get current DTCs/MIL lamp status/Tests supported for this ECU * and test, and wait for those tests to complete */ do_j1979_getdtcs(); /* * Get data supported by ECU, non-interruptibly */ do_j1979_getdata(0); /* * And now do stuff with that data */ for (i=0, ep=ecu_info; i<ecu_count; i++, ep++) { if ( (ep->mode1_data[2].type == TYPE_GOOD) && (ep->mode1_data[2].data[2] | ep->mode1_data[2].data[3]) ) { printf("ECU %d Freezeframe data exists, caused by DTC ", i); print_single_dtc(ep->mode1_data[2].data[2] , ep->mode1_data[2].data[3]); printf("\n"); } if (ep->mode1_data[0x1c].type == TYPE_GOOD) { printf("ECU %d is ", i); switch(ep->mode1_data[0x1c].data[2]) { case 1: printf("OBD II (California ARB)"); break; case 2: printf("OBD (Federal EPA)"); break; case 3: printf("OBD and OBD II"); break; case 4: printf("OBD I"); break; case 5: printf("not OBD"); break; case 6: printf("EOBD (Europe)"); break; default: printf("unknown (%d)", ep->mode1_data[0x1c].data[2]); break; } printf(" compliant\n"); } /* * If ECU supports Oxygen sensor monitoring, then do O2 sensor * stuff */ if ( (ep->mode1_data[1].type == TYPE_GOOD) && (ep->mode1_data[1].data[4] & 0x20) ) { o2monitoring = 1; } } do_j1979_getO2sensors(); if (o2monitoring > 0) { do_j1979_O2tests(); } else { printf("Oxygen (O2) sensor monitoring not supported\n"); }}print_single_dtc(u_int8_t d0, u_int8_t d1){ char db[2]; db[0] = d0; db[1] = d1; printf("%s", diag_dtc_decode(db, 2, set_vehicle, set_ecu, DIAG_DTC_PROTOCOL_J2012) ); return (0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -