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; } }
/*! \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; }