⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scantool.c

📁 Freediag contains various drivers (ISO9141, ISO14230, SAEJ1850-VPW, SAEJ1850-PWM) for different adap
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *	freediag - Vehicle Diagnostic Utility * * * Copyright (C) 2001 Richard Almeida & Ibex Ltd (rpa@ibex.co.uk) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ************************************************************************* * * * Mostly ODBII Compliant Scanner Program (SAE J1978) * * ODBII Scanners are defined in SAE J1978. References in this document * are to SAE J1978 Revised Feb1998. This document is available from * www.sae.org * * From Section 5. Required functions & support - the following are the basic * functions that the scan tool is required to support or provide * * a. Automatic hands-off determination of the communication interface user * b. Obtaining and displaying the status and results of vehicle on-board *	diagnostic evaluations * c. Obtaining & Displaying ODB II emissions related DTCs * d. Obtaining & Displaying ODB II emissions related current data * e. Obtaining & Displaying ODB II emissions related freeze frame data * f. Clearing the storage of (c) to (e) * g. Obtaining and displaying ODB II emissions related test params and *	results as described in SAE J1979 * h. Provide a user manual and/or help facility * * Section 6 - Vehicle interface *	Communication Data Link and Physical Layers *		SAE J1850 interface *		ISO 9141-2 interface *		ISO 14230-4 * * Section 7.3 - the scan tool must be capable of interfacing with a *	vehicle in which multiple modules may be used to support ODBII *	requirements *	The ODBII Scan tool must alert the user when multiple modules *	respond to the same request *	Ditto if different values *	The tool must provide the user with the ability to select for *	display as separate display items the responses received from *	multiple modules for the same data item * * * THIS DOESN'T SUPPORT Section 6 as we only have one interface * - It "copes" with 7.3 but doesn't tell user or allow user to select * which module to see responses from * * ************************************************************************* * * This file contains the workhorse routines, ie all that execute the * J1979 (ODBII) protocol */#include "diag_os.h" /* operating specific includes */#include "scantool.h"#include "scantool_cli.h"static char *cvsid = "$Id: scantool.c,v 1.15 2002/09/11 19:59:02 rpalmeida Exp $";/* * This is used to store the 1st message of a received set of messages * It's only 24 bytes long as this is plenty to store a J1979 message */#if notdefu_int8_t global_data[1024];int global_datalen;#endifdiag_l2_conn_t  *global_l2_conn;diag_l3_conn_t  *global_l3_conn;/* * Data received from each ecu */ecu_data_t	ecu_info[MAX_ECU];int ecu_count;		/* How many ecus are active *//* Merge of all the suported mode1 pids by all the ECUs */u_int8_t	merged_mode1_info[0x100];u_int8_t	merged_mode5_info[0x100];u_int8_t	global_O2_sensors;	/* O2 sensors bit mask */int		global_conmode;int		global_protocol;int		global_state;		/* See STATE_ definitions in .h file */int		global_l2_fd;		/* L2 Fd *//* Prototypes */int print_single_dtc(u_int8_t d0, u_int8_t d1) ;void do_j1979_getmodeinfo(int mode, int response_offset) ;diag_l2_conn_t *do_common_start(int L1protocol, int L2protocol,	u_int32_t type, int bitrate, u_int8_t target, u_int8_t source );int do_l3_md1pid0_rqst( diag_l2_conn_t *d_conn ) ;void initialse_ecu_data();diag_msg_t *find_ecu_msg(int byte, u_int8_t val){	ecu_data_t *ep;	diag_msg_t *rv = NULL;	int i;	for (i=0, ep=ecu_info; i<ecu_count; i++, ep++)	{		if (ep->rxmsg)		{			/* Some data arrived from this ecu */			if (ep->rxmsg->data[byte] == val)			{				rv = ep->rxmsg;				break;			}		}	}	return(rv);}/* * Message print out / debug routines */static voidprint_msg_header(FILE *fp, diag_msg_t *msg, int timestamp, int i){	if (timestamp)		fprintf(fp, "%d.%04d: ",			msg->rxtime.tv_sec, msg->rxtime.tv_usec/100);	fprintf(fp, "msg %02d src 0x%x dest 0x%x ", i, msg->src, msg->dest);	fprintf(fp, "msg %02d: ", i);}static voidprint_msg(FILE *fp, diag_msg_t *msg, int timestamp){    	diag_msg_t *tmsg;	int i, j;	for (tmsg = msg, i = 0; tmsg; tmsg = tmsg->next, i++)	{	    	print_msg_header(fp, tmsg, timestamp, i);		for (j = 0; j < tmsg->len; j++)		    	fprintf(fp, "0x%02x ", tmsg->data[j]);		fprintf(fp, "\n");	}}/* * ************ * Basic routines to connect/interrogate an ECU * ************ *//* * Receive callback routines. If handle is 1 then we're in "watch" * mode (set by caller to recv()), else in normal data mode * * We get called by L3/L2 with all the messages received within the * window, i.e we can get responses from many ECUs that all relate to  * a single request [ISO9141/14230 uses timing windows to decide when * no more responses will arrive] * * We can [and do] get more than one ecu responding with different bits * of data on certain vehicles */voidj1979_data_rcv(void *handle, diag_msg_t *msg){	int len = msg->len;	u_int8_t *data = msg->data;	diag_msg_t *tmsg;	int i;	struct timeval tv;	ecu_data_t	*ep;	char *O2_strings[] = {		"Test 0", 		"Rich to lean sensor threshold voltage",		"Lean to rich sensor threshold voltage",		"Low sensor voltage for switch time calc.",		"High sensor voltage for switch time calc.",		"Rich to lean sensor switch time",		"Lean to rich sensor switch time",		"Minimum sensor voltage for test cycle",		"Maximum sensor voltage for test cycle",		"Time between sensor transitions"		};	if (diag_cmd_debug > 0x80)	{		printf("scantool: Got handle %x %d bytes of data, src %x, dest %x msgcnt %d\n",			handle, len, msg->src, msg->dest, msg->mcnt);	}	/* Debug level for showing received data */	if (diag_cmd_debug & 0x80)	{	    	print_msg(stdout, msg, 0);		data = msg->data;	}	/* Deal with the diag type responses (send/recv/watch) */	switch ((u_int32_t)handle)	{	/* There is no difference between watch and decode ... */	case RQST_HANDLE_WATCH:	case RQST_HANDLE_DECODE:		if ((diag_cmd_debug & 0x80) == 0)		{			/* Print data (unless done already) */	    		print_msg(stdout, msg, 0);		}		return;	}	/* All other responses are J1979 response messages */	/* Clear out old messages */	for (i=0, ep=ecu_info; i<ecu_count; i++, ep++)	{		if (ep->rxmsg)		{			/* Old msg. release it */			diag_freemsg(ep->rxmsg);			ep->rxmsg = NULL;		}	}	/*	 * We may get more than one msg here, as more than one	 * ECU may respond.	 */	for (tmsg = msg; tmsg; tmsg=tmsg->next)	{		u_int8_t src = tmsg->src;		diag_msg_t *rmsg;		int found;			for (i=0, ep=ecu_info, found=0; i<MAX_ECU;i++, ep++)		{			if (ep->valid)			{				if (ep->ecu_addr == src)				{					found = 1;					break;				}			}			else			{				ecu_count++;				ep->valid = 1;				ep->ecu_addr = src;				found = 1;				break;			}		}		if (found == 0)		{			printf("ERROR: Too many ECUs responded\n");			printf("ERROR: Info from ECU addr 0x%x ignored\n", src);			return;		}		/* Ok, we now have the ecu_info for this message fragment */		/* Attach the fragment to the ecu_info */		rmsg = diag_dupsinglemsg(tmsg);			if (ep->rxmsg)		{			diag_msg_t *xmsg = ep->rxmsg;			while (xmsg)			{				if (xmsg->next == NULL)				{					xmsg->next = rmsg;					break;				}				xmsg = xmsg->next;			}		}		else		{			ep->rxmsg = rmsg;		}		/*		 * Deal with readiness tests, ncms and O2 sensor tests		 * Note that ecu_count gets to the correct value from		 * the first response from the ECU which is the mode1pid0		 * response		 */		data = msg->data;		switch ((u_int32_t)handle)		{		case RQST_HANDLE_READINESS:			/* Handled in cmd_test_readiness() */			break;		case RQST_HANDLE_NCMS:		case RQST_HANDLE_NCMS2:			/*			 * Non Continuously Monitored System result			 * NCMS2 prints everything, NCMS prints just failed			 * tests			 */			if (data[0] != 0x46)			{				printf("Test 0x%02x failed %d\n",					data[1], data[2]);				return;			}			if ((data[1] & 0x1f) == 0)			{				/* no Test support */				return;			}			for (tmsg = msg , i = 0; tmsg; tmsg=tmsg->next, i++)			{				int val, lim;				data = tmsg->data;				len = tmsg->len;				val = (data[3]*255) + data[4];				lim = (data[5]*255) + data[6];				if ((data[2] & 0x80) == 0)				{					if ((u_int32_t)handle						== RQST_HANDLE_NCMS2)					{						/* Only print fails */						if (val > lim)						{							printf("Test 0x%x Component 0x%x FAILED ",							data[1], data[2] & 0x7f);							printf("Max val %d Current Val %d\n",								lim, val);						}					}					else					{						/* Max value test */						printf("Test 0x%x Component 0x%x ",							data[1], data[2] & 0x7f);									if (val > lim)							printf("FAILED ");						else							printf("Passed ");						printf("Max val %d Current Val %d\n",							lim, val);					}				}				else				{					if ((u_int32_t)handle ==						RQST_HANDLE_NCMS2)					{						if (val < lim)						{							printf("Test 0x%x Component 0x%x FAILED ",								data[1], data[2] & 0x7f);							printf("Min val %d Current Val %d\n",								lim, val);						}					}					else					{						/* Min value test */						printf("Test 0x%x Component 0x%x ",							data[1], data[2] & 0x7f);						if (val < lim)							printf("FAILED ");						else							printf("Passed ");						printf("Min val %d Current Val %d\n",							lim, val);					}				}			}			return;		case RQST_HANDLE_O2S:			if (ecu_count>1)				printf("ECU %d ", i);			/* O2 Sensor test results */			if (msg->data[0] != 0x45)			{				printf("Test 0x%02x failed %d\n",					msg->data[1], msg->data[2]);				return;			}			if ((data[1] & 0x1f) == 0)			{				/* No Test support */			}			else			{				int val = data[4];				int min = data[5];				int max = data[6];				int failed ;				if ((val < min) || (val > max))					failed = 1;				else					failed = 0;				switch (data[1])				{				case 1:	/* Constant values voltages */				case 2:				case 3:				case 4:					printf("%s: %f\n", O2_strings[data[1]],							data[4]/200);					break;				case 5:				case 6:				case 9:					printf("%s: actual %2.2f min %2.2f max %2.2f %s\n",						O2_strings[data[1]], data[4]/250,						data[5]/250, data[6]/250,						failed?"FAILED":"Passed" );					break;				case 7:				case 8:					printf("%s: %f\n", O2_strings[data[1]],						data[4]/200,						data[5]/200,						data[6]/200,						failed?"FAILED":"Passed" );					break;				default:					printf("Test %d: actual 0x%x min 0x%x max 0x%x\n",						data[1], data[4],						data[5], data[6],						failed?"FAILED":"Passed" );					break;				}			}			return;		}	}	return;}/* * Receive callback routines, for watching mode, call * L3 (in this case SAE J1979) decode routine, if handle is NULL * just print the data */voidj1979_watch_rcv(void *handle, diag_msg_t *msg){	int len = msg->len;	u_int8_t *data = msg->data;	diag_msg_t *tmsg;	int i, j;	for ( tmsg = msg , i = 0; tmsg; tmsg=tmsg->next, i++ )	{		printf("%d.%04d: ", tmsg->rxtime.tv_sec, tmsg->rxtime.tv_usec/100);		printf("msg %02d src 0x%x dest 0x%x ", i, msg->src, msg->dest);		printf("msg %02d: ", i);		if (handle != NULL)			printf("%s\n",				diag_l3_decode((diag_l3_conn_t *)handle, tmsg));		else		{			for (j=0; j<tmsg->len; j++)				printf("0x%02x ", tmsg->data[j]);			printf("\n");		}	}}voidl2raw_data_rcv(void *handle, diag_msg_t *msg){	/*	 * Layer 2 call back, just print the data, this is used if we	 * do a "read" and we haven't yet added a L3 protocol	 */	diag_msg_t *tmsg;	int i;	int len;	u_int8_t *data;	for ( tmsg = msg , i = 0; tmsg; tmsg=tmsg->next, i++ )	{		printf("msg %02d src 0x%x dest 0x%x ", i, tmsg->src, tmsg->dest);		printf("msg %02d: ", i);		len = tmsg->len;		data = tmsg->data;		while (len)		{			printf("0x%02x ", *data);			len--; data++;		}		printf("\n");	}}/* * Routine to check the bitmasks of PIDS received in response * to a mode 1 PID 0/0x20/0x40 request */intl2_check_pid_bits(u_int8_t *data, int pid){	int offset;	int bit;	pid--;		/* (bits start at 0, pids at 1) */	/*	 * Bits 1-8 are in byte 1, 9-16 in byte 2 etc	 * Same code is for PID requests for 0x40 and 0x60	 */	while (pid > 0x20)		pid -= 0x20;	offset = pid/8;	bit = pid - (offset * 8);	bit = 7 - bit;	if (data[offset] & (1<<bit))		return(1);	return(0);}/* * Send a SAE J1979 request, and get a response, and part process it */l3_do_j1979_rqst(diag_l3_conn_t *d_conn, int mode, int p1, int p2,	int p3, int p4, int p5, int p6, int p7, void *handle){	diag_msg_t	msg;	u_int8_t data[256];	int rv;	ecu_data_t *ep;	int i;	u_int8_t *rxdata;	diag_msg_t *rxmsg;	/* Lengths of msg for each mode, 0 = this routine doesn't support */	char mode_lengths[] = { 0, 2, 3, 1, 1, 3, 2, 1, 7, 2 };#define J1979_MODE_MAX 9	if (diag_cmd_debug > 0x80)	{		printf("j1979_rqst: handle %x conn %x mode %x\n",			handle, d_conn, mode);	}	/* Put in src/dest etc, L3 or L2 may override/ignore them */	msg.src = set_testerid;	msg.dest = set_destaddr;	/* Current set destination */	/* XXX add funcmode flags */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -