Example #1
0
EXPORT void simple_read_pf(void * data, XmlCmdType type)
{
	Io_Message *message  = NULL;
	OutputData *output  = NULL;
	gint count = 0;
	gchar *tmpbuf = NULL;
	gint page = -1;
	gint canID = -1;
	guint16 curcount = 0;
	static guint16 lastcount = 0;
	extern Firmware_Details *firmware;
	extern gint ms_ve_goodread_count;
	extern gint ms_reset_count;
	extern gint ms_goodread_count;
	guint8 *ptr8 = NULL;
	guint16 *ptr16 = NULL;
	static gboolean just_starting = TRUE;
	extern gboolean forced_update;
	extern gboolean force_page_change;
	extern volatile gboolean offline;


	message = (Io_Message *)data;
	output = (OutputData *)message->payload;

	switch (type)
	{
		case WRITE_VERIFY:
			printf(_("MS2_WRITE_VERIFY not written yet\n"));
			break;
		case MISMATCH_COUNT:
			printf(_("MS2_MISMATCH_COUNT not written yet\n"));
			break;
		case MS1_CLOCK:
			printf(_("MS1_CLOCK not written yet\n"));
			break;
		case MS2_CLOCK:
			printf(_("MS2_CLOCK not written yet\n"));
			break;
		case NUM_REV:
			if (offline)
				break;
			count = read_data(-1,&message->recv_buf,FALSE);
			ptr8 = (guchar *)message->recv_buf;
			firmware->ecu_revision=(gint)ptr8[0];
			if (count > 0)
				thread_update_widget("ecu_revision_entry",MTX_ENTRY,g_strdup_printf("%.1f",((gint)ptr8[0]/10.0)));
			else
				thread_update_widget("ecu_revision_entry",MTX_ENTRY,g_strdup(""));
			break;
		case TEXT_REV:
			if (offline)
				break;
			count = read_data(-1,&message->recv_buf,FALSE);
			if (count > 0)
			{
				thread_update_widget("text_version_entry",MTX_ENTRY,g_strndup(message->recv_buf,count));
				 firmware->txt_rev_len = count;
				firmware->text_revision = g_strndup(message->recv_buf,count);
			}
			break;
		case SIGNATURE:
			if (offline)
				break;
			 count = read_data(-1,&message->recv_buf,FALSE);
                         if (count > 0)
			 {
				 thread_update_widget("ecu_signature_entry",MTX_ENTRY,g_strndup(message->recv_buf,count));
				 firmware->signature_len = count;
				 firmware->actual_signature = g_strndup(message->recv_buf,count);
			 }
			break;
		case MS1_VECONST:
		case MS2_VECONST:
			page = (GINT)OBJ_GET(output->object,"page");
			canID = (GINT)OBJ_GET(output->object,"canID");
			count = read_data(firmware->page_params[page]->length,&message->recv_buf,TRUE);
			if (count != firmware->page_params[page]->length)
				break;
			store_new_block(canID,page,0,
					message->recv_buf,
					firmware->page_params[page]->length);
			backup_current_data(canID,page);
			ms_ve_goodread_count++;
			break;
		case MS1_RT_VARS:
			count = read_data(firmware->rtvars_size,&message->recv_buf,TRUE);
			if (count != firmware->rtvars_size)
				break;
			ptr8 = (guchar *)message->recv_buf;
			/* Test for MS reset */
			if (just_starting)
			{
				lastcount = ptr8[0];
				just_starting = FALSE;
			}
			/* Check for clock jump from the MS, a 
			 * jump in time from the MS clock indicates 
			 * a reset due to power and/or noise.
			 */
			if ((lastcount - ptr8[0] > 1) && \
					(lastcount - ptr8[0] != 255))
			{
				ms_reset_count++;
				printf(_("MS1 Reset detected!, lastcount %i, current %i\n"),lastcount,ptr8[0]);
				gdk_threads_enter();
				gdk_beep();
				gdk_threads_leave();
			}
			else
				ms_goodread_count++;
			lastcount = ptr8[0];
			/* Feed raw buffer over to post_process()
			 * as a void * and pass it a pointer to the new
			 * area for the parsed data...
			 */
			process_rt_vars((void *)message->recv_buf);
			break;
		case MS2_RT_VARS:
			page = (GINT)OBJ_GET(output->object,"page");
			canID = (GINT)OBJ_GET(output->object,"canID");
			count = read_data(firmware->rtvars_size,&message->recv_buf,TRUE);
			if (count != firmware->rtvars_size)
				break;
			store_new_block(canID,page,0,
					message->recv_buf,
					firmware->page_params[page]->length);
			backup_current_data(canID,page);
			ptr16 = (guint16 *)message->recv_buf;
			/* Test for MS reset */
			if (just_starting)
			{
				lastcount = GUINT16_TO_BE(ptr16[0]);
				curcount = GUINT16_TO_BE(ptr16[0]);
				just_starting = FALSE;
			}
			else
				curcount = GUINT16_TO_BE(ptr16[0]);
			/* Check for clock jump from the MS, a 
			 * jump in time from the MS clock indicates 
			 * a reset due to power and/or noise.
			 */
			if ((lastcount - curcount > 1) && \
					(lastcount - curcount != 65535))
			{
				ms_reset_count++;
				printf(_("MS2 rtvars reset detected, lastcount is %i, current %i"),lastcount,curcount);
				gdk_threads_enter();
				gdk_beep();
				gdk_threads_leave();
			}
			else
				ms_goodread_count++;
			lastcount = curcount;
			/* Feed raw buffer over to post_process()
			 * as a void * and pass it a pointer to the new
			 * area for the parsed data...
			 */
			process_rt_vars((void *)message->recv_buf);
			break;
		case MS2_BOOTLOADER:
			printf(_("MS2_BOOTLOADER not written yet\n"));
			break;
		case MS1_GETERROR:
			forced_update = TRUE;
			force_page_change = TRUE;
			count = read_data(-1,&message->recv_buf,FALSE);
			if (count <= 10)
			{
				thread_update_logbar("error_status_view",NULL,g_strdup(_("No ECU Errors were reported....\n")),FALSE,FALSE);
				break;
			}
			if (g_utf8_validate(((gchar *)message->recv_buf)+1,count-1,NULL))
			{
				thread_update_logbar("error_status_view",NULL,g_strndup(((gchar *)message->recv_buf+7)+1,count-8),FALSE,FALSE);
				if (dbg_lvl & (IO_PROCESS|SERIAL_RD))
				{
					tmpbuf = g_strndup(((gchar *)message->recv_buf)+1,count-1);
					dbg_func(IO_PROCESS|SERIAL_RD,g_strdup_printf(__FILE__"\tECU  ERROR string: \"%s\"\n",tmpbuf));
					g_free(tmpbuf);
				}

			}
			else
				thread_update_logbar("error_status_view",NULL,g_strdup("The data came back as gibberish, please try again...\n"),FALSE,FALSE);
			break;
		default:
			break;
	}
}
Example #2
0
/*!
  \brief write_data() physically sends the data to the ECU.
  \param message is the pointer to an Io_Message structure
  */
G_MODULE_EXPORT gboolean write_data(Io_Message *message)
{
	static GMutex *serio_mutex = NULL;
	static Serial_Params *serial_params = NULL;
	static Firmware_Details *firmware = NULL;
	static gfloat *factor = NULL;
	OutputData *output = (OutputData *)message->payload;
	gint res = 0;
	gchar * err_text = NULL;
	guint i = 0;
	gint j = 0;
	gint len = 0;
	guint8 * buffer = NULL;
	gint burst_len = 0;
	gboolean notifies = FALSE;
	gint notif_divisor = 32;
	WriteMode mode = MTX_CMD_WRITE;
	gboolean retval = TRUE;
	DBlock *block = NULL;
	static GMutex mutex;
	static void (*store_new_block)(gpointer) = NULL;
	static void (*set_ecu_data)(gpointer,gint *) = NULL;

	ENTER();

	if (!firmware)
		firmware = (Firmware_Details *)DATA_GET(global_data,"firmware");
	if (!serial_params)
		serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
	if (!serio_mutex)
		serio_mutex = (GMutex *)DATA_GET(global_data,"serio_mutex");
	if (!factor)
		factor = (gfloat *)DATA_GET(global_data,"sleep_correction");
	if (!set_ecu_data)
		get_symbol("set_ecu_data",(void **)&set_ecu_data);
	if (!store_new_block)
		get_symbol("store_new_block",(void **)&store_new_block);

	g_return_val_if_fail(firmware,FALSE);
	g_return_val_if_fail(serial_params,FALSE);
	g_return_val_if_fail(serio_mutex,FALSE);
	g_return_val_if_fail(factor,FALSE);
	g_return_val_if_fail(set_ecu_data,FALSE);
	g_return_val_if_fail(store_new_block,FALSE);

	g_mutex_lock(&mutex);
	g_mutex_lock(serio_mutex);

	if (output)
		mode = (WriteMode)(GINT)DATA_GET(output->data,"mode");

	if (DATA_GET(global_data,"offline"))
	{
		switch (mode)
		{
			case MTX_SIMPLE_WRITE:
				set_ecu_data(output->data,NULL);
				break;
			case MTX_CHUNK_WRITE:
				store_new_block(output->data);
				break;
			case MTX_CMD_WRITE:
				break;
		}
		g_mutex_unlock(serio_mutex);
		g_mutex_unlock(&mutex);
		EXIT();
		return TRUE;		/* can't write anything if offline */
	}
	if (!DATA_GET(global_data,"connected"))
	{
		g_mutex_unlock(serio_mutex);
		g_mutex_unlock(&mutex);
		EXIT();
		return FALSE;		/* can't write anything if disconnected */
	}

	/* For MS3 1.1 which uses a CRC32 wrapped serial stream, we can't easily
	 * do the old way as it had a bunch of fugly worarounds for ECU editions 
	 * that couldn't handle bursts and needed to be artificially throttled.
	 */
	if(DATA_GET(message->data,"burst_write"))
	{
		buffer = (guint8 *)DATA_GET(message->data,"burst_buffer");
		if (!buffer)
		{
			MTXDBG(CRITICAL|SERIAL_WR,_("MS3 CRC32 burst blob is not stored in the OutputData->data structure, ABORTING\n"));
			EXIT();
			return FALSE;
		}
		burst_len = (GINT)DATA_GET(message->data,"burst_len");
		QUIET_MTXDBG(SERIAL_WR,_("Writing MS3 burst write %i bytes\n"),burst_len);
		res = write_wrapper(serial_params->fd,buffer,burst_len, &len);
		/* Send write command */
		if (!res)
		{
			MTXDBG((Dbg_Class)(SERIAL_WR|CRITICAL),_("Error writing MS3 burst block ERROR \"%s\"!!!\n"),err_text);
			retval = FALSE;
		}
	}

	else
	{
		g_return_val_if_fail(message,FALSE);
		g_return_val_if_fail(message->sequence,FALSE);
		g_return_val_if_fail(message->sequence->len > 0,FALSE);
		
		for (i=0;i<message->sequence->len;i++)
		{
			block = g_array_index(message->sequence,DBlock *,i);
			/*	printf("Block pulled\n");*/
			if (block->type == ACTION)
			{
				/*		printf("Block type of ACTION!\n");*/
				if (block->action == SLEEP)
				{
					/*			printf("Sleeping for %i usec\n", block->arg);*/
					MTXDBG(SERIAL_WR,_("Sleeping for %i microseconds \n"),block->arg);
					g_usleep((*factor)*block->arg);
				}
			}
			else if (block->type == DATA)
			{
				/*		printf("Block type of DATA!\n");*/
				if (block->len > 100)
					notifies = TRUE;
				/* ICK bad form man, writing one byte at a time,  due to ECU's that can't take full wire speed without
				   dropping chars due to uber tiny buffers */
				for (j=0;j<block->len;j++)
				{
					/*printf("comms.c data[%i] is %i, block len is %i\n",j,block->data[j],block->len);*/
					if ((notifies) && ((j % notif_divisor) == 0))
						thread_update_widget("info_label",MTX_LABEL,g_strdup_printf(_("<b>Sending %i of %i bytes</b>"),j,block->len));
					QUIET_MTXDBG(SERIAL_WR,_("Writing argument %i byte %i of %i, \"%.2X\"\n"),i,j+1,block->len,block->data[j]);
					res = write_wrapper(serial_params->fd,&(block->data[j]),1, &len);
					/* Send write command */
					if (!res)
					{
						MTXDBG((Dbg_Class)(SERIAL_WR|CRITICAL),_("Error writing block offset %i, value \"%.2X\" ERROR \"%s\"!!!\n"),j,block->data[j],err_text);
						retval = FALSE;
					}
					if (firmware->capabilities & MS2)
						g_usleep((*factor)*firmware->interchardelay*1000);
				}
			}
		}
	}
	if (notifies)
	{
		thread_update_widget("info_label",MTX_LABEL,g_strdup("<b>Transfer Completed</b>"));
		g_timeout_add(2000,(GSourceFunc)reset_infolabel_wrapper,NULL);
	}
	/* If sucessfull update ecu_data as well, this way, current 
	 * and pending match, in the case of a failed write, the 
	 * update_write_status() function will catch it and rollback as needed
	 */
	if ((output) && (retval))
	{
		if (mode == MTX_SIMPLE_WRITE)
			set_ecu_data(output->data,NULL);
		else if (mode == MTX_CHUNK_WRITE)
			store_new_block(output->data);
	}

	g_mutex_unlock(serio_mutex);
	g_mutex_unlock(&mutex);
	EXIT();
	return retval;
}