Exemplo n.º 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;
	}
}
Exemplo n.º 2
0
/*!
  \brief thread_dispatcher() runs continuously as a thread listening to the 
  io_data_queue and running handlers as messages come in. After they are done it
  passes the message back to the gui via the dispatch_queue for further
  gui handling (for things that can't run in a thread context)
  \param data is unused
  */
G_MODULE_EXPORT void *thread_dispatcher(gpointer data)
{
	GThread * repair_thread = NULL;
	Serial_Params *serial_params = NULL;
	Io_Message *message = NULL;	
	GAsyncQueue *io_data_queue = NULL;
	CmdLineArgs *args  = NULL;
	void *(*network_repair_thread)(gpointer data) = NULL;
	void *(*serial_repair_thread)(gpointer data) = NULL;
	/*	GTimer *clock;*/

	ENTER();
	io_data_queue = (GAsyncQueue *)DATA_GET(global_data,"io_data_queue");
	serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
	get_symbol("serial_repair_thread",(void **)&serial_repair_thread);
	args = (CmdLineArgs *)DATA_GET(global_data,"args");
	if (args->network_mode)
		get_symbol("network_repair_thread",(void **)&network_repair_thread);

	g_return_val_if_fail(args,NULL);
	g_return_val_if_fail(io_data_queue,NULL);
	g_return_val_if_fail(serial_params,NULL);
	g_async_queue_ref(io_data_queue);
	/*	clock = g_timer_new();*/
	/* Endless Loop, wait for message, processs and repeat... */
	while (TRUE)
	{
		if (DATA_GET(global_data,"thread_dispatcher_exit"))
		{
fast_exit:
			/* drain queue and exit thread */
			while ((message = (Io_Message *)g_async_queue_try_pop(io_data_queue)) != NULL)
				dealloc_io_message(message);
			g_async_queue_unref(io_data_queue);

			EXIT();
			g_thread_exit(0);
		}
		message = (Io_Message *)g_async_queue_timeout_pop(io_data_queue,1000000);
		if (!message) /* NULL message */
		{
			MTXDBG(THREADS|IO_MSG,_("No message received...\n"));
			continue;
		}
		else
			MTXDBG(THREADS|IO_MSG,_("MESSAGE ARRIVED on IO queue...\n"));

		if ((!DATA_GET(global_data,"offline")) && 
				(((!DATA_GET(global_data,"connected")) && 
				  (serial_params->open)) || 
				 (!(serial_params->open))))
		{
			/*printf("somehow somethign went wrong,  connected is %i, offline is %i, serial_params->open is %i\n",DATA_GET(global_data,"connected"),DATA_GET(global_data,"offline"),serial_params->open);*/
			if (args->network_mode)
			{
				MTXDBG(THREADS,_("LINK DOWN, Initiating NETWORK repair thread!\n"));
				repair_thread = g_thread_new("Network Repair thread",network_repair_thread,NULL);
			}
			else
			{
				MTXDBG(THREADS,_("LINK DOWN, Initiating serial repair thread!\n"));
				repair_thread = g_thread_new("Serial Repair thread",serial_repair_thread,NULL);
			}
			g_thread_join(repair_thread);
		}
		if ((!serial_params->open) && (!DATA_GET(global_data,"offline")))
		{
			MTXDBG(THREADS,_("LINK DOWN, Can't process requested command, aborting call\n"));
			thread_update_logbar("comm_view","warning",g_strdup("Disconnected Serial Link. Check Communications link/cable...\n"),FALSE,FALSE);
			thread_update_widget("titlebar",MTX_TITLE,g_strdup("Disconnected link, check Communications tab..."));
			message->status = FALSE;
			continue;
		}
		switch ((CmdType)message->command->type)
		{
			case FUNC_CALL:
				if (!message->command->function)
					MTXDBG(CRITICAL|THREADS,_("CRITICAL ERROR, function \"%s()\" is not found!!\n"),message->command->func_call_name);
				else
				{
					/*printf("Calling FUNC_CALL, function \"%s()\" \n",message->command->func_call_name);*/
					message->status = message->command->function(message->command,message->command->func_call_arg);
					/*
					   if (!result)
					   message->command->defer_post_functions=TRUE;
					   */
				}
				break;
			case WRITE_CMD:
				/*g_timer_start(clock);*/
				message->status = write_data(message);
				if (!message->status)
					DATA_SET(global_data,"connected",GINT_TO_POINTER(FALSE));

				/*printf("Write command elapsed time %f\n",g_timer_elapsed(clock,NULL));*/
				if (message)
				{
					if (message->command)
					{
						if (message->command->helper_function)
						{
							message->command->helper_function(message, message->command->helper_func_arg);
						}
					}
				}

				/*printf("Write command with post function time %f\n",g_timer_elapsed(clock,NULL));*/
				break;
			case NULL_CMD:
				/*printf("null_cmd, just passing thru\n");*/
				break;

			default:
				MTXDBG(THREADS|CRITICAL,_("Hit default case, this SHOULD NOT HAPPEN it's a bug, notify author! \n"));

				break;

		}
		/* If set to defer post functions, it means they were passed 
		   via a function fall, thus dealloc it here., Otherwise
		   push up the queue to the postfunction dispatcher
		   */
		if (message->command->defer_post_functions)
			dealloc_io_message(message);
		else
			g_idle_add(process_pf_message,message);
	}
	EXIT();
	return 0;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/*!
  \brief open_serial() called to open the serial port, updates textviews on the
  comms page on success/failure
  \param port_name is the name of the port to open
  \param nonblock is a flag if we should open hte port in nonblocking mode
  */
G_MODULE_EXPORT gboolean open_serial(gchar * port_name, gboolean nonblock)
{
	/* We are using DOS/Win32 style com port numbers instead of unix
	 * style as its easier to think of COM1 instead of /dev/ttyS0
	 * thus com1=/dev/ttyS0, com2=/dev/ttyS1 and so on 
	 */
	static GMutex *serio_mutex = NULL;
	gboolean port_open = FALSE;
	Serial_Params *serial_params = NULL;
	gint fd = -1;
	gchar * err_text = NULL;
	serial_params = DATA_GET(global_data,"serial_params");
	serio_mutex = DATA_GET(global_data,"serio_mutex");

	g_mutex_lock(serio_mutex);
	/*printf("Opening serial port %s\n",port_name);*/
	/* Open Read/Write and NOT as the controlling TTY */
	/* Blocking mode... */
	if (nonblock)
	{
#ifdef __WIN32__
		fd = open(port_name, O_RDWR | O_BINARY);
//		serial_params->comm_handle = CreateFile(port_name,
//				GENERIC_READ|GENERIC_WRITE, /* Access */
//				0, /* not shared */
//				0, /* No security */
//				OPEN_EXISTING, /* Don't create a file */
//				FILE_FLAG_OVERLAPPED, /* Overlapped IO */
//				0 /* No templates... */
//				);
//		fd = _open_osfhandle(serial_params->comm_handle, 0);
#else
		fd = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
#endif
		DATA_SET(global_data,"serial_nonblock",GINT_TO_POINTER(TRUE));
	}
	else
	{
#ifdef __WIN32__
		fd = open(port_name, O_RDWR | O_BINARY );
#else
		fd = open(port_name, O_RDWR | O_NOCTTY );
#endif
	}
	if (fd > 0)
	{
		/* SUCCESS */
		/* NO Errors occurred opening the port */
		serial_params->port_name = g_strdup(port_name); 
		serial_params->open = TRUE;
		port_open = TRUE;
		serial_params->fd = fd;
		MTXDBG(SERIAL_RD|SERIAL_WR,_("\"%s\" Opened Successfully\n"),port_name);
		thread_update_logbar("comms_view",NULL,g_strdup_printf(_("%s Opened Successfully\n"),port_name),FALSE,FALSE);

	}
	else
	{
		/* FAILURE */
		/* An Error occurred opening the port */
		port_open = FALSE;
		if (serial_params->port_name)
			g_free(serial_params->port_name);
		serial_params->port_name = NULL;
		serial_params->open = FALSE;
		serial_params->fd = -1;
		err_text = (gchar *)g_strerror(errno);
		MTXDBG(SERIAL_RD|SERIAL_WR|CRITICAL,_("Error Opening \"%s\", Error Code: \"%s\"\n"),port_name,err_text);
		thread_update_widget("titlebar",MTX_TITLE,g_strdup_printf(_("Error Opening \"%s\", Error Code: \"%s\""),port_name,err_text));

		thread_update_logbar("comms_view","warning",g_strdup_printf(_("Error Opening \"%s\", Error Code: %s \n"),port_name,err_text),FALSE,FALSE);
	}

	/*printf("open_serial returning\n");*/
	g_mutex_unlock(serio_mutex);
	return port_open;
}