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

📄 diag_l2.c

📁 Freediag contains various drivers (ISO9141, ISO14230, SAEJ1850-VPW, SAEJ1850-PWM) for different adap
💻 C
📖 第 1 页 / 共 2 页
字号:
 * We need to tell L1 what protocol we are going to use, because some L1
 * interfaces are smart and can support multiple protocols, also L2 needs
 * to know later (and asks L1)
 */
int
diag_l2_open(char *dev_name, int id, int L1protocol)
{
	int rv;
	diag_l2_link_t *d_l2_link;

	if (diag_l2_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr,"%s: diag_l2_open %s subid %d L1proto %d called\n",
			DIAG_MODULE, dev_name, id, L1protocol);

	d_l2_link = diag_l2_findlink(dev_name);

	if (d_l2_link)
	{
		/* device open */
		if (d_l2_link->diag_l2_l1protocol != L1protocol)
		{
			/* Wrong L1 protocol, close link */
			diag_l2_closelink(d_l2_link->diag_l2_fd);
			d_l2_link = NULL;
		}
	}

	if (d_l2_link)
	{
		/* Device was already open, with correct protocol  */
		return(d_l2_link->diag_l2_fd);
	}

	/* Else, create the link */
	d_l2_link = calloc(1, sizeof(diag_l2_link_t));
	if (d_l2_link == NULL)
	{
		/* Calloc failed */
		return(DIAG_ERR_NOMEM);
	}
	rv = diag_l1_open(dev_name, id, L1protocol);
	if (rv < 0)
	{
		free(d_l2_link);
		return(rv);
	}
	d_l2_link->diag_l2_fd = rv;
	d_l2_link->diag_l2_l1flags = diag_l1_getflags(rv);
	d_l2_link->diag_l2_l1type = diag_l1_gettype(rv);
	d_l2_link->diag_l2_l1protocol = L1protocol;

	strcpy(d_l2_link->diag_l2_name, dev_name);
	d_l2_link->diag_l2_id = id;

	d_l2_link->next = diag_l2_links;
	diag_l2_links = d_l2_link;
		
	return(d_l2_link->diag_l2_fd);
}

/*
 * Close a L2 interface, the caller
 * must have closed all the connections relating to this or they will
 * just get left hanging using resources. We dont kill the L1, it may
 * be useful later
 *
 * XXX, this needs some consideration, one fd can be used for more than
 * one L2, so closing by fd isnt appropriate, and so this routine does
 * nothing. However, all we have is the FD unless a StartCommunications()
 * has been done
 */
diag_l2_close(int fd)
{
	diag_l2_link_t *d_l2_link;

	if (diag_l2_debug & DIAG_DEBUG_CLOSE)
		fprintf(stderr,"%s: diag_l2_close %d called\n",
			DIAG_MODULE, fd);

	/* XXX */

	return(0);
}

/*
 * Close/kill a L1link
 */
diag_l2_closelink(int fd)
{
	diag_l2_link_t *d_l2_link;

	if (diag_l2_debug & DIAG_DEBUG_CLOSE)
		fprintf(stderr,"%s: diag_l2_closelink %d called\n",
			DIAG_MODULE, fd);

	d_l2_link = diag_l2_findlink_byfd(fd);

	if (d_l2_link)
	{
		/* Clear out this link */
		diag_l2_rmlink(d_l2_link);
		diag_l1_close(fd);
		free(d_l2_link);
	}


	return(0);
}

/*
 * startCommunication routine, establishes a connection to
 * an ECU by sending fast/slow start (or whatever the protocol is),
 * and sets all the timer parameters etc etc
 */
diag_l2_conn_t *
diag_l2_StartCommunications(int fd, int L2protocol, u_int32_t type,
	int bitrate, u_int8_t target, u_int8_t source)
{
	diag_l2_conn_t	*d_l2_conn;
	diag_l2_link_t *d_l2_link;
	int rv;
	int reusing = 0;
	u_int16_t flags;

	if (diag_l2_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr,
			"%s: diag_l2_startCommunications fd %d L2proto %d type %x baud %d target 0x%x src 0x%x called\n",
			DIAG_MODULE, fd, L2protocol, type ,
			bitrate, target&0xff, source&0xff);

	/*
	 * Check connection doesn't exist already, if it does, then use it
	 * but reinitialise ECU - when checking connection, we look at the
	 * target and the fd 
	 */
	d_l2_conn = diag_l2_conbyid[target];
	while (d_l2_conn)
	{
		/*
		 * Find if there's an entry for this FD (or may be talking
		 * to ECU with this ID on another channel !!
		 */
		if (d_l2_conn->diag_link->diag_l2_fd == fd)
		{
			reusing = 1;
			break;
		}
		d_l2_conn = d_l2_conn -> diag_l2_next ;
	}
	
	if (d_l2_conn == NULL)
	{
		/* New connection */
		d_l2_conn = calloc(1, sizeof(diag_l2_conn_t));
		if (d_l2_conn == NULL)
		{
			/* Calloc failed */
			return(NULL);
		}
		reusing = 0;
	}

	d_l2_link = diag_l2_findlink_byfd(fd);
	if (d_l2_link == NULL)
		return(NULL);

	d_l2_conn = calloc(1, sizeof(diag_l2_conn_t));
	if (d_l2_conn == NULL)
	{
		/* Calloc failed */
		return(NULL);
	}

	/* Link to the L1 device info that we keep (name, type, flags, fd) */
	d_l2_conn->diag_link = d_l2_link;

	/* Note the protocol we want to use */
	d_l2_conn->diag_l2_protocol = L2protocol ;
	d_l2_conn->diag_l2_type = type ;
	d_l2_conn->diag_l2_srcaddr = source ;
	d_l2_conn->diag_l2_destaddr = target ;

	/*
	 * We are going to assume that the ISO default timing values
	 * are general suitable defaults
	 */
	d_l2_conn->diag_l2_p1min = ISO_14230_TIM_MIN_P1;
	d_l2_conn->diag_l2_p1max = ISO_14230_TIM_MAX_P1;
	d_l2_conn->diag_l2_p2min = ISO_14230_TIM_MIN_P2;
	d_l2_conn->diag_l2_p2max = ISO_14230_TIM_MAX_P2;
	d_l2_conn->diag_l2_p2emin = ISO_14230_TIM_MIN_P2E;
	d_l2_conn->diag_l2_p2emax = ISO_14230_TIM_MAX_P2E;
	d_l2_conn->diag_l2_p3min = ISO_14230_TIM_MIN_P3;
	d_l2_conn->diag_l2_p3max = ISO_14230_TIM_MAX_P3;
	d_l2_conn->diag_l2_p4min = ISO_14230_TIM_MIN_P4;
	d_l2_conn->diag_l2_p4max = ISO_14230_TIM_MAX_P4;

	d_l2_conn -> diag_l2_state = DIAG_L2_STATE_CLOSED;

	/* Now do protocol version of StartCommunications */

	flags = type&0xffff;

	rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_startcomms(d_l2_conn, flags, bitrate, target, source);

	if (rv < 0)
	{
		/* Something went wrong */
		if (diag_l2_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr,"%s: protocol startcomms returned %d\n", DIAG_MODULE, rv);

		if (reusing == 0)
			free(d_l2_conn);
/* XXX tidy structures */

		d_l2_conn = NULL;
	}

	/*
	 * note target for quick lookup of connection for received messages
	 * - unless were re-using a established connection, then no need
	 * to re-note.
	 */
	if ( (reusing == 0) && d_l2_conn )
	{
		/* And attach connection info to our main list */
		d_l2_conn->next = diag_l2_connections ;
		diag_l2_connections = d_l2_conn ;

/* XXX insert in second linked list */

		diag_l2_conbyid[target] = d_l2_conn;

	}
	if (d_l2_conn)
		d_l2_conn -> diag_l2_state = DIAG_L2_STATE_OPEN;

	if (diag_l2_debug & DIAG_DEBUG_OPEN)
		fprintf(stderr,
			"%s: diag_l2_StartComms returns 0x%x\n",
				DIAG_MODULE, d_l2_conn);

	return (d_l2_conn);
}

/*
 * Stop communications - stop talking to an ECU
 * - some L2 protocols have an ordered mechanism to do this, others are
 * just timeout based (i.e don't send anything for 5 seconds)
 */
int
diag_l2_StopCommunications(diag_l2_conn_t *d_l2_conn)
{
	d_l2_conn->diag_l2_state = DIAG_L2_STATE_CLOSING;

	/*
	 * Call protocol close routine, if it exists
	 */
	if (diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_stopcomms)
		(void)diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_stopcomms(d_l2_conn);

	d_l2_conn->diag_l2_state = DIAG_L2_STATE_CLOSED;
	return(0);
}


/*
 * This is really only an ISO14230 protocol function, but the same function
 * is used to purely set the timer values on older protocols that don't
 * negotiate timer parameters with the ECU thus allowing L3 protocols to
 * control inter-byte delays, idle timeouts etc
 */
int
diag_l2_AccessTimingParameters(diag_l2_conn_t *d_l2_conn,
			int p2min, int p2max, int p3min, int p3max, int p4min)
{
	int rv = 0;
	if (diag_l2_debug & DIAG_DEBUG_PROTO)
		fprintf(stderr,
			"%s: diag_l2_AccessTimingParameters 0x%x called\n",
				DIAG_MODULE,d_l2_conn);

	if ( diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_atp)
	{
		rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_atp(
			d_l2_conn, p2min, p2max, p3min, p3max, p4min);
	}
	else
	{
		/* No protocol specific routine, just set the parameters */
		d_l2_conn->diag_l2_p2min = p2min;
		d_l2_conn->diag_l2_p2max = p2max;
		d_l2_conn->diag_l2_p3min = p3min;
		d_l2_conn->diag_l2_p3max = p3max;
		d_l2_conn->diag_l2_p4min = p4min;

	}
	return (rv);
}

/*
 * Send a message. This is synchronous.
 */
int
diag_l2_send(diag_l2_conn_t *d_l2_conn, diag_msg_t *msg)
{
	int rv;

	if (diag_l2_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr,
			"%s: diag_l2_send 0x%x msg 0x%x msglen %d called\n",
				DIAG_MODULE, d_l2_conn, msg, msg->len);

	/* Note the time, for calculation of "wakeup" message timeouts */
	(void) gettimeofday(&d_l2_conn->diag_l2_lastsend, NULL);

	/* Call protocol specific send routine */
	rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_send(d_l2_conn, msg);

	if (diag_l2_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr, "%s: diag_l2_send returns %d\n",
				DIAG_MODULE, rv);

	return(rv);
}

/*
 * Send a message, and wait the appropriate time for a response and return
 * that message or an error indicator
 * This is synchronous and sleeps and is meant too.
 */
diag_msg_t *
diag_l2_request(diag_l2_conn_t *d_l2_conn, diag_msg_t *msg, int *errval)
{
	diag_msg_t *rv;

	if (diag_l2_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr,
			"%s: diag_l2_msg 0x%x 0x%x called\n",
				DIAG_MODULE, d_l2_conn, msg);

	/* Call protocol specific send routine */
	rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_request(d_l2_conn, msg, errval);

	if (diag_l2_debug & DIAG_DEBUG_WRITE)
		fprintf(stderr, "%s: diag_l2_request returns 0x%x, err %d\n",
				DIAG_MODULE, rv, *errval);

	return(rv);
}


/*
 * Recv a message - will end up calling the callback routine with a message
 * or an error if an error has occurred
 *
 * At the moment this sleeps and the callback will happen before the recv()
 * returns - this is not the intention
 *
 * Timeout is in ms
 */
int
diag_l2_recv(diag_l2_conn_t *d_l2_conn, int timeout, 
	void (*callback)(void *handle, diag_msg_t *msg), void *handle)
{
	int rv;

	if (diag_l2_debug & DIAG_DEBUG_READ)
		fprintf(stderr,
			"%s: diag_l2_recv 0x%x timeout %d called\n",
				DIAG_MODULE, d_l2_conn, timeout);

	/* Call protocol specific recv routine */
	rv = diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_proto_recv(d_l2_conn, timeout, callback, handle);

	if (diag_l2_debug & DIAG_DEBUG_READ)
		fprintf(stderr, "%s: diag_l2_recv returns %d\n",
				DIAG_MODULE, rv);
	return(rv);
}

/*
 * IOCTL, for setting/asking how various layers are working - similar to
 * Unix ioctl()
 */
int diag_l2_ioctl(diag_l2_conn_t *d_l2_conn, int cmd, void *data)
{
	struct diag_l2_ic *ic;
	int rv = 0;
	int fd;
	struct diag_l2_data *d;

	if (diag_l2_debug & DIAG_DEBUG_IOCTL)
		fprintf(stderr,
			"%s: diag_l2_ioctl 0x%x cmd %d\n",
				DIAG_MODULE, d_l2_conn, cmd);


	fd = d_l2_conn->diag_link->diag_l2_fd ;

	switch (cmd)
	{
	case DIAG_IOCTL_GET_L1_TYPE:
		*(int *)data = diag_l1_gettype(fd);
		break;
	case DIAG_IOCTL_GET_L1_FLAGS:
		*(int *)data = diag_l1_getflags(fd);
		break;
	case DIAG_IOCTL_GET_L2_FLAGS:
		*(int *)data =
	 	   diag_protocols[d_l2_conn->diag_l2_protocol].diag_l2_flags;
		break;
	case DIAG_IOCTL_GET_L2_DATA:
		d = (struct diag_l2_data *)data;
		d->physaddr = d_l2_conn->diag_l2_physaddr;
		d->kb1 = d_l2_conn->diag_l2_kb1;
		d->kb2 = d_l2_conn->diag_l2_kb2;
		break;
	case DIAG_IOCTL_SETSPEED:
		ic = (struct diag_l2_ic *)data;
		rv = diag_l1_setspeed(fd, 
			ic->speed, ic->databits, ic->stopbits, ic->parityflag);
		break;
	case DIAG_IOCTL_INITBUS:
		rv = diag_l1_initbus(fd, data);
		break;
	default:
		rv = 0;	/* Do nothing, quietly */
		break;
	}

	return(rv);
}

⌨️ 快捷键说明

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