示例#1
0
文件: lib.c 项目: wanghao-xznu/vte
int hexstring2candata(char *arg, struct can_frame *cf) {

	int len = strlen(arg);
	int i;
	unsigned char tmp;

	if (!len || len%2 || len > 16)
		return 1;

	for (i=0; i < len/2; i++) {

		tmp = asc2nibble(*(arg+(2*i)));
		if (tmp > 0x0F)
			return 1;

		cf->data[i] = (tmp << 4);

		tmp = asc2nibble(*(arg+(2*i)+1));
		if (tmp > 0x0F)
			return 1;

		cf->data[i] |= tmp;
	}

	return 0;
}
示例#2
0
/* Send one completely decapsulated can_frame to the network layer */
static void slc_bump(struct slcan *sl)
{
	struct net_device_stats *stats = sl->dev->get_stats(sl->dev);
	struct sk_buff *skb;
	struct can_frame cf;
	int i, dlc_pos, tmp;
	char cmd = sl->rbuff[0];

	if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
		return;

	if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
		dlc_pos = 4; /* dlc position tiiid */
	else
		dlc_pos = 9; /* dlc position Tiiiiiiiid */

	if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
		return;

	cf.can_dlc = sl->rbuff[dlc_pos] & 0x0F; /* get can_dlc */

	sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
	cf.can_id = simple_strtoul(sl->rbuff+1, NULL, 16);
	
	if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
		cf.can_id |= CAN_EFF_FLAG;

	if ((cmd | 0x20) == 'r') /* RTR frame */
		cf.can_id |= CAN_RTR_FLAG;

	*(u64 *) (&cf.data) = 0; /* clear payload */

	for (i = 0, dlc_pos++; i < cf.can_dlc; i++){
		
		if ((tmp = asc2nibble(sl->rbuff[dlc_pos++])) > 0x0F)
			return;
		cf.data[i] = (tmp << 4);
		if ((tmp = asc2nibble(sl->rbuff[dlc_pos++])) > 0x0F)
			return;
		cf.data[i] |= tmp;
	}


	skb = dev_alloc_skb(sizeof(struct can_frame));
	if (!skb)
		return;

	skb->dev = sl->dev;
	skb->protocol = htons(ETH_P_CAN);
	skb->pkt_type = PACKET_BROADCAST;
	skb->ip_summed = CHECKSUM_UNNECESSARY;
	memcpy(skb_put(skb, sizeof(struct can_frame)),
	       &cf, sizeof(struct can_frame));
	netif_rx(skb);

	sl->dev->last_rx = jiffies;
	stats->rx_packets++;
	stats->rx_bytes += cf.can_dlc;
}
示例#3
0
文件: slcanpty.c 项目: Webo/can-utils
/* read data from pty, send CAN frames to CAN socket and answer commands */
int pty2can(int pty, int socket, struct can_filter *fi,
	       int *is_open, int *tstamp)
{
	int nbytes;
	char cmd;
	char buf[200];
	char replybuf[10]; /* for answers to received commands */
	int ptr;
	struct can_frame frame;
	int tmp, i;

	nbytes = read(pty, &buf, sizeof(buf)-1);
	if (nbytes < 0) {
		perror("read pty");
		return 1;
	}

rx_restart:
	/* remove trailing '\r' characters to be robust against some apps */
	while (buf[0] == '\r' && nbytes > 0) {
		for (tmp = 0; tmp < nbytes; tmp++)
			buf[tmp] = buf[tmp+1];
		nbytes--;
	}

	if (!nbytes)
		return 0;

	cmd = buf[0];
	buf[nbytes] = 0;

#ifdef DEBUG
	for (tmp = 0; tmp < nbytes; tmp++)
		if (buf[tmp] == '\r')
			putchar('@');
		else
			putchar(buf[tmp]);
	printf("\n");
#endif

	/* check for filter configuration commands */
	if (cmd == 'm' || cmd == 'M') {
		buf[9] = 0; /* terminate filter string */
		ptr = 9;
#if 0
		/* the filter is no SocketCAN filter :-( */

		/* TODO: behave like a SJA1000 controller specific filter */

		if (cmd == 'm') {
			fi->can_id = strtoul(buf+1,NULL,16);
			fi->can_id &= CAN_EFF_MASK;
		} else {
			fi->can_mask = strtoul(buf+1,NULL,16);
			fi->can_mask &= CAN_EFF_MASK;
		}

		if (*is_open)
			setsockopt(socket, SOL_CAN_RAW,
				   CAN_RAW_FILTER, fi,
				   sizeof(struct can_filter));
#endif
		goto rx_out_ack;
	}


	/* check for timestamp on/off command */
	if (cmd == 'Z') {
		*tstamp = buf[1] & 0x01;
		ptr = 2;
		goto rx_out_ack;
	}

	/* check for 'O'pen command */
	if (cmd == 'O') {
		setsockopt(socket, SOL_CAN_RAW,
			   CAN_RAW_FILTER, fi,
			   sizeof(struct can_filter));
		ptr = 1;
		*is_open = 1;
		goto rx_out_ack;
	}

	/* check for 'C'lose command */
	if (cmd == 'C') {
		setsockopt(socket, SOL_CAN_RAW, CAN_RAW_FILTER,
			   NULL, 0);
		ptr = 1;
		*is_open = 0;
		goto rx_out_ack;
	}

	/* check for 'V'ersion command */
	if (cmd == 'V') {
		sprintf(replybuf, "V1013\r");
		tmp = strlen(replybuf);
		ptr = 1;
		goto rx_out;
	}

	/* check for serial 'N'umber command */
	if (cmd == 'N') {
		sprintf(replybuf, "N4242\r");
		tmp = strlen(replybuf);
		ptr = 1;
		goto rx_out;
	}

	/* check for read status 'F'lags */
	if (cmd == 'F') {
		sprintf(replybuf, "F00\r");
		tmp = strlen(replybuf);
		ptr = 1;
		goto rx_out;
	}

	/* correctly answer unsupported commands */
	if (cmd == 'U') {
		ptr = 2;
		goto rx_out_ack;
	}
	if (cmd == 'S') {
		ptr = 2;
		goto rx_out_ack;
	}
	if (cmd == 's') {
		ptr = 5;
		goto rx_out_ack;
	}
	if (cmd == 'P' || cmd == 'A') {
		ptr = 1;
		goto rx_out_nack;
	}
	if (cmd == 'X') {
		ptr = 2;
		if (buf[1] & 0x01)
			goto rx_out_ack;
		else
			goto rx_out_nack;
	}

	/* catch unknown commands */
	if ((cmd != 't') && (cmd != 'T') &&
	    (cmd != 'r') && (cmd != 'R')) {
		ptr = nbytes-1;
		goto rx_out_nack;
	}

	if (cmd & 0x20) /* tiny chars 'r' 't' => SFF */
		ptr = 4; /* dlc position tiiid */
	else
		ptr = 9; /* dlc position Tiiiiiiiid */

	*(unsigned long long *) (&frame.data) = 0ULL; /* clear data[] */

	if ((cmd | 0x20) == 'r' && buf[ptr] != '0') {

		/* 
		 * RTR frame without dlc information!
		 * This is against the SLCAN spec but sent
		 * by a commercial CAN tool ... so we are
		 * robust against this protocol violation.
		 */

		frame.can_dlc = buf[ptr]; /* save following byte */

		buf[ptr] = 0; /* terminate can_id string */

		frame.can_id = strtoul(buf+1, NULL, 16);
		frame.can_id |= CAN_RTR_FLAG;

		if (!(cmd & 0x20)) /* NO tiny chars => EFF */
			frame.can_id |= CAN_EFF_FLAG;

		buf[ptr]  = frame.can_dlc; /* restore following byte */
		frame.can_dlc = 0;
		ptr--; /* we have no dlc component in the violation case */

	} else {

		if (!(buf[ptr] >= '0' && buf[ptr] < '9'))
			goto rx_out_nack;

		frame.can_dlc = buf[ptr] - '0'; /* get dlc from ASCII val */

		buf[ptr] = 0; /* terminate can_id string */

		frame.can_id = strtoul(buf+1, NULL, 16);

		if (!(cmd & 0x20)) /* NO tiny chars => EFF */
			frame.can_id |= CAN_EFF_FLAG;

		if ((cmd | 0x20) == 'r') /* RTR frame */
			frame.can_id |= CAN_RTR_FLAG;

		for (i = 0, ptr++; i < frame.can_dlc; i++) {

			tmp = asc2nibble(buf[ptr++]);
			if (tmp > 0x0F)
				goto rx_out_nack;
			frame.data[i] = (tmp << 4);
			tmp = asc2nibble(buf[ptr++]);
			if (tmp > 0x0F)
				goto rx_out_nack;
			frame.data[i] |= tmp;
		}
		/* point to last real data */
		if (frame.can_dlc)
			ptr--;
	}

	tmp = write(socket, &frame, sizeof(frame));
	if (tmp != sizeof(frame)) {
		perror("write socket");
		return 1;
	}

rx_out_ack:
	replybuf[0] = '\r';
	tmp = 1;
	goto rx_out;
rx_out_nack:
	replybuf[0] = '\a';
	tmp = 1;
rx_out:
	tmp = write(pty, replybuf, tmp);
	if (tmp < 0) {
		perror("write pty replybuf");
		return 1;
	}

	/* check if there is another command in this buffer */
	if (nbytes > ptr+1) {
		for (tmp = 0, ptr++; ptr+tmp < nbytes; tmp++)
			buf[tmp] = buf[ptr+tmp];
		nbytes = tmp;
		goto rx_restart;
	}

	return 0;
}
示例#4
0
文件: lib.c 项目: wanghao-xznu/vte
int parse_canframe(char *cs, struct can_frame *cf) {
	/* documentation see lib.h */

	int i, idx, dlc, len;
	unsigned char tmp;

	len = strlen(cs);
	//printf("'%s' len %d\n", cs, len);

	memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */

	if (len < 4)
		return 1;

	if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
		return 1;

	if (cs[8] == CANID_DELIM) { /* 8 digits */

		idx = 9;
		for (i=0; i<8; i++){
			if ((tmp = asc2nibble(cs[i])) > 0x0F)
				return 1;
			cf->can_id |= (tmp << (7-i)*4);
		}
		if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe?  */
			cf->can_id |= CAN_EFF_FLAG;   /* then it is an extended frame */

	} else { /* 3 digits */

		idx = 4;
		for (i=0; i<3; i++){
			if ((tmp = asc2nibble(cs[i])) > 0x0F)
				return 1;
			cf->can_id |= (tmp << (2-i)*4);
		}
	}

	if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
		cf->can_id |= CAN_RTR_FLAG;
		return 0;
	}

	for (i=0, dlc=0; i<8; i++){

		if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
			idx++;

		if(idx >= len) /* end of string => end of data */
			break;

		if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
			return 1;
		cf->data[i] = (tmp << 4);
		if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
			return 1;
		cf->data[i] |= tmp;
		dlc++;
	}

	cf->can_dlc = dlc;

	return 0;
}
示例#5
0
void state_isotp() {
	int i, items, ret;

	char rxmsg[MAXLEN]; /* can to inet */
	char buf[MAXLEN]; /* inet commands to can */
	unsigned char isobuf[ISOTPLEN+1]; /* binary buffer for isotp socket */
	unsigned char tmp;
	
	if(previous_state == STATE_ISOTP) {
		state_isotp_init();
		previous_state = STATE_ISOTP;
	}

	FD_ZERO(&readfds);
	FD_SET(si, &readfds);
	FD_SET(client_socket, &readfds);

	/*
	 * Check if there are more elements in the element buffer before calling select() and
	 * blocking for new packets.
	 */
	if(more_elements) {
		FD_CLR(si, &readfds);
	} else {
		ret = select((si > client_socket)?si+1:client_socket+1, &readfds, NULL, NULL, NULL);
		if(ret < 0) {
			PRINT_ERROR("Error in select()\n")
			change_state(STATE_SHUTDOWN);
			return;
		}
	}

	if (FD_ISSET(si, &readfds)) {

		struct timeval tv = {0};

		items = read(si, isobuf, ISOTPLEN);

		/* read timestamp data */
		if(ioctl(si, SIOCGSTAMP, &tv) < 0) {
			PRINT_ERROR("Could not receive timestamp\n");
		}

		if (items > 0 && items <= ISOTPLEN) {

			int startlen;

			sprintf(rxmsg, "< pdu %ld.%06ld ", tv.tv_sec, tv.tv_usec);
			startlen = strlen(rxmsg);

			for (i=0; i < items; i++)
				sprintf(rxmsg + startlen + 2*i, "%02X", isobuf[i]);

			sprintf(rxmsg + strlen(rxmsg), " >");
			send(client_socket, rxmsg, strlen(rxmsg), 0);
		}
	}

	if (FD_ISSET(client_socket, &readfds)) {

		ret = receive_command(client_socket, buf);
		if(ret != 0) {
			change_state(STATE_SHUTDOWN);
			return;
		}

		if ( (ret = state_changed(buf, state)) ) {
			if(ret == CONTROL_SWITCH_STATE) state_isotp_deinit();
			strcpy(buf, "< ok >");
			send(client_socket, buf, strlen(buf), 0);
			return;
		}

#if 0
		if(!strcmp("< echo >", buf)) {
			send(client_socket, buf, strlen(buf), 0);
			return;
		}

		if(!strncmp("< sendpdu ", buf, 10)) {
			items = element_length(buf, 2);
			if (items & 1) {
				PRINT_ERROR("odd number of ASCII Hex values\n");
				return;
			}

			items /= 2;
			if (items > ISOTPLEN) {
				PRINT_ERROR("PDU too long\n");
				return;
			}

			for (i = 0; i < items; i++) {

				tmp = asc2nibble(buf[(2*i) + 10]);
				if (tmp > 0x0F)
					return;
				isobuf[i] = (tmp << 4);
				tmp = asc2nibble(buf[(2*i) + 11]);
				if (tmp > 0x0F)
					return;
				isobuf[i] |= tmp;
			}

			ret = write(si, isobuf, items);
			if(ret != items) {
				PRINT_ERROR("Error in write()\n")
				change_state(STATE_SHUTDOWN);
				return;
			}
		} else {
			PRINT_ERROR("unknown command '%s'.\n", buf)
				strcpy(buf, "< error unknown command >");
			send(client_socket, buf, strlen(buf), 0);
		}
#else
		ret = decode_command(buf);
		switch(ret) {

		case COMMAND_ECHO:
			send(client_socket, buf, strlen(buf), 0);
			break;

		case COMMAND_SENDPDU:
			items = element_length(buf, 2);
			if (items & 1) {
				PRINT_ERROR("odd number of ASCII Hex values\n");
				return;
			}

			items /= 2;
			if (items > ISOTPLEN) {
				PRINT_ERROR("PDU too long\n");
				return;
			}

			for (i = 0; i < items; i++) {

				tmp = asc2nibble(buf[(2*i) + 10]);
				if (tmp > 0x0F)
					return;
				isobuf[i] = (tmp << 4);
				tmp = asc2nibble(buf[(2*i) + 11]);
				if (tmp > 0x0F)
					return;
				isobuf[i] |= tmp;
			}

			ret = write(si, isobuf, items);
			if(ret != items) {
				PRINT_ERROR("Error in write()\n")
				change_state(STATE_SHUTDOWN);
				return;
			}
			break; /* COMMAND_SENDPDU */

		case COMMAND_UNKNOWN:
		default:
			PRINT_ERROR("unknown command '%s'.\n", buf)
			strcpy(buf, "< error unknown command >");
			send(client_socket, buf, strlen(buf), 0);
			break;	/* COMMAND_UNKNOWN */
		}


#endif
	}
}
示例#6
0
int ihex_parse(char input[], ihex_record_t *record) {
	//given a NULL-TERMINATED input string (use gets()) in I16HEX format, write the binary record in record. return 0 on success.

	uint8_t inputlen;
	uint8_t t, i, checksum_calc=0, checksum_read;

	//first check for ":" leading character
	if(input[0] != ':') return -1;

	//then check the string for only valid ASCII ['0'-'F']
	inputlen=1;
	while(input[inputlen]) {
		if( !isxdigit(input[inputlen++]) ) return -2;
	}

	//then read the length.
	record->length = (asc2nibble(input[1]) << 4) + asc2nibble(input[2]);
	if(input[(record->length<<1) + 11] != 0) return -3; //if we're missing a null terminator in the right place

	//then read the address.
	record->addr = (asc2nibble(input[3]) << 12) + (asc2nibble(input[4]) << 8) + (asc2nibble(input[5]) << 4) + asc2nibble(input[6]);

	//then read the record type.
	record->type = (asc2nibble(input[7]) << 4) + asc2nibble(input[8]);
//	if(record->type > 4) return -4;

	//then read the data, which goes from input[9] to input[9+length*2].
	for(i=0; i < record->length; i++) {
		t = 9 + (i<<1);
		record->data[i] = (asc2nibble(input[t]) << 4) + (asc2nibble(input[t + 1]));
		checksum_calc += record->data[i]; //might as well keep a running checksum as we read
	}
	checksum_calc += record->length + record->type + (record->addr >> 8) + (record->addr & 0xFF); //get the rest of the data into that checksum
	checksum_calc = ~checksum_calc + 1;	//checksum is 2's complement

	//now read the checksum of the record
	checksum_read = (asc2nibble(input[9 + (record->length<<1)]) << 4) + asc2nibble(input[10 + (record->length<<1)]);
	if(checksum_calc != checksum_read) return -5; //compare 'em

	return 0;
}