PageRenderTime 57ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/src/plugins/libreems/interrogate.c

https://gitlab.com/libreems-suite/megatunix
C | 1437 lines | 1145 code | 100 blank | 192 comment | 128 complexity | d9df269198970fa2cc207b491b2689f6 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (C) 2002-2012 by Dave J. Andruczyk <djandruczyk at yahoo dot com>
  3. *
  4. * Linux Megasquirt tuning software
  5. *
  6. * Most of this file contributed by Perry Harrington
  7. * slight changes applied (naming, addition ofbspot 1-3 vars)
  8. *
  9. * This software comes under the GPL (GNU Public License)
  10. * You may freely copy,distribute etc. this as long as the source code
  11. * is made available for FREE.
  12. *
  13. * No warranty is made or implied. You use this program at your own risk.
  14. */
  15. /*!
  16. \file src/plugins/libreems/interrogate.c
  17. \ingroup LibreEMSPlugin,Plugins
  18. \brief LibreEMS specific interrogation routine (INCOMPLETE/IN FLUX)
  19. \author David Andruczyk
  20. */
  21. #include <api-versions.h>
  22. #include <datamgmt.h>
  23. #include <getfiles.h>
  24. #include <interrogate.h>
  25. #include <libreems_plugin.h>
  26. #include <libreems_helpers.h>
  27. #include <libgen.h>
  28. #include <serialio.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. extern gconstpointer *global_data;
  32. /*!
  33. \brief interrogate_ecu() interrogates the target ECU to determine what
  34. firmware it is running. It does this by reading a list of tests, sending
  35. those tests in turn, reading the responses and them comparing the group of
  36. responses against a list of interrogation profiles until it finds a match.
  37. NOTE: This function is NOT yet complete for LibreEMS
  38. */
  39. G_MODULE_EXPORT gboolean interrogate_ecu(void)
  40. {
  41. GAsyncQueue *queue = NULL;
  42. GHashTable *tests_hash = NULL;
  43. GArray *tests = NULL;
  44. Detection_Test *test = NULL;
  45. guint i = 0;
  46. gboolean interrogated = FALSE;
  47. GList *locations = NULL;
  48. static GMutex mutex;
  49. ENTER();
  50. /* prevent multiple runs of interrogator simultaneously */
  51. g_mutex_lock(&mutex);
  52. MTXDBG(INTERROGATOR,_("ENTERED\n\n"));
  53. /* ECU has already been detected via comms test
  54. Now we need to figure out its variant and adapt to it
  55. */
  56. /* Send stream disable command */
  57. /*stop_streaming(); */
  58. /* Load tests from tests.cfg file */
  59. if (!validate_and_load_tests(&tests,&tests_hash))
  60. {
  61. MTXDBG(INTERROGATOR|CRITICAL,_("Didn't return a valid list of commands\n\t MegaTunix was NOT installed correctly, Aborting Interrogation\n"));
  62. update_logbar_f("interr_view",NULL,g_strdup(__FILE__": interrogate_ecu()\n\t validate_and_load_tests() didn't return a valid list of commands\n\t MegaTunix was NOT installed correctly, Aborting Interrogation\n"),FALSE,FALSE,TRUE);
  63. g_mutex_unlock(&mutex);
  64. EXIT();
  65. return FALSE;
  66. }
  67. thread_widget_set_sensitive_f("offline_button",FALSE);
  68. thread_widget_set_sensitive_f("interrogate_button",FALSE);
  69. /* how many tests.... */
  70. for (i=0;i<tests->len;i++)
  71. {
  72. /* Get the test */
  73. test = g_array_index(tests,Detection_Test *, i);
  74. /* Check func existance and run it */
  75. if (test->function)
  76. {
  77. test->result = test->function(&test->num_bytes);
  78. if (test->result_type == RESULT_TEXT)
  79. test->result_str = g_strndup((const gchar *)(test->result),test->num_bytes);
  80. }
  81. else
  82. test->result = NULL;
  83. }
  84. interrogated = determine_ecu(tests,tests_hash);
  85. DATA_SET(global_data,"interrogated",GINT_TO_POINTER(interrogated));
  86. if (interrogated)
  87. {
  88. thread_widget_set_sensitive_f("interrogate_button",FALSE);
  89. thread_widget_set_sensitive_f("offline_button",FALSE);
  90. }
  91. g_array_free(tests,TRUE);
  92. g_hash_table_destroy(tests_hash);
  93. g_mutex_unlock(&mutex);
  94. EXIT();
  95. return interrogated;
  96. }
  97. /*!
  98. \brief Issues a packet to the ECU to get its revision information.
  99. \param length is a pointer to a location to store the length of the data
  100. received, or NULL
  101. \returns the Firmware version as a text string
  102. */
  103. G_MODULE_EXPORT gchar *raw_request_firmware_version(gint *length)
  104. {
  105. OutputData *output = NULL;
  106. GAsyncQueue *queue = NULL;
  107. LibreEMS_Packet *packet = NULL;
  108. gchar *version = NULL;
  109. Serial_Params *serial_params = NULL;
  110. /* Raw packet */
  111. guint8 *buf = NULL;
  112. gint len = FIRMWARE_VERSION_REQ_PKT_LEN;
  113. guint8 pkt[FIRMWARE_VERSION_REQ_PKT_LEN];
  114. gint req = REQUEST_FIRMWARE_VERSION;
  115. gint resp = RESPONSE_FIRMWARE_VERSION;
  116. gint res = 0;
  117. gint i = 0;
  118. guint8 sum = 0;
  119. gint tmit_len = 0;
  120. ENTER();
  121. serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
  122. g_return_val_if_fail(serial_params,NULL);
  123. if (DATA_GET(global_data,"offline"))
  124. {
  125. EXIT();
  126. return g_strdup("Offline");
  127. }
  128. pkt[HEADER_IDX] = 0;
  129. pkt[H_PAYLOAD_IDX] = (req & 0xff00 ) >> 8;
  130. pkt[L_PAYLOAD_IDX] = (req & 0x00ff );
  131. for (i=0;i<len-1;i++)
  132. sum += pkt[i];
  133. pkt[len-1] = sum;
  134. buf = finalize_packet((guint8 *)&pkt,len,&tmit_len);
  135. queue = g_async_queue_new();
  136. register_packet_queue(PAYLOAD_ID,queue,resp);
  137. if (!write_wrapper_f(serial_params->fd,buf, tmit_len, NULL))
  138. {
  139. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  140. g_free(buf);
  141. g_async_queue_unref(queue);
  142. EXIT();
  143. return NULL;
  144. }
  145. g_free(buf);
  146. packet = (LibreEMS_Packet *)g_async_queue_timeout_pop(queue,500000);
  147. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  148. g_async_queue_unref(queue);
  149. if (packet)
  150. {
  151. version = g_strndup((const gchar *)(packet->data+packet->payload_base_offset),packet->payload_length);
  152. if (length)
  153. *length = packet->payload_length;
  154. libreems_packet_cleanup(packet);
  155. }
  156. EXIT();
  157. return version;
  158. }
  159. /*!
  160. \brief Issues a packet to the ECU to get its interface version.
  161. \param length is a pointer to a location to store the length of the data
  162. received, or NULL
  163. \returns the Firmware interface version as a text string
  164. */
  165. G_MODULE_EXPORT gchar * raw_request_interface_version(gint *length)
  166. {
  167. OutputData *output = NULL;
  168. GAsyncQueue *queue = NULL;
  169. LibreEMS_Packet *packet = NULL;
  170. gchar *version = NULL;
  171. Serial_Params *serial_params = NULL;
  172. guint8 *buf = NULL;
  173. /* Raw packet */
  174. gint len = INTERFACE_VERSION_REQ_PKT_LEN;
  175. guint8 pkt[INTERFACE_VERSION_REQ_PKT_LEN];
  176. gint req = REQUEST_INTERFACE_VERSION;
  177. gint resp = RESPONSE_INTERFACE_VERSION;
  178. gint res = 0;
  179. gint i = 0;
  180. guint8 sum = 0;
  181. gint tmit_len = 0;
  182. ENTER();
  183. serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
  184. g_return_val_if_fail(serial_params,NULL);
  185. if (DATA_GET(global_data,"offline"))
  186. {
  187. EXIT();
  188. return g_strdup("Offline");
  189. }
  190. pkt[HEADER_IDX] = 0;
  191. pkt[H_PAYLOAD_IDX] = (req & 0xff00 ) >> 8;
  192. pkt[L_PAYLOAD_IDX] = (req & 0x00ff );
  193. for (i=0;i<len-1;i++)
  194. sum += pkt[i];
  195. pkt[len-1] = sum;
  196. buf = finalize_packet((guint8 *)&pkt,len,&tmit_len);
  197. queue = g_async_queue_new();
  198. register_packet_queue(PAYLOAD_ID,queue,resp);
  199. if (!write_wrapper_f(serial_params->fd,buf, tmit_len, NULL))
  200. {
  201. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  202. g_free(buf);
  203. g_async_queue_unref(queue);
  204. EXIT();
  205. return NULL;
  206. }
  207. g_free(buf);
  208. packet = (LibreEMS_Packet *)g_async_queue_timeout_pop(queue,500000);
  209. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  210. g_async_queue_unref(queue);
  211. /*
  212. if (packet)
  213. printf("Firmware version PACKET ARRIVED!\n");
  214. else
  215. printf("TIMEOUT\n");
  216. */
  217. if (packet)
  218. {
  219. version = g_strndup((const gchar *)(packet->data+packet->payload_base_offset),packet->payload_length);
  220. if (length)
  221. *length = packet->payload_length;
  222. libreems_packet_cleanup(packet);
  223. }
  224. EXIT();
  225. return version;
  226. }
  227. /*!
  228. \brief Issues a packet to the ECU to get its revision information.
  229. received, or NULL
  230. */
  231. G_MODULE_EXPORT void request_firmware_version()
  232. {
  233. OutputData *output = NULL;
  234. GAsyncQueue *queue = NULL;
  235. gint seq = atomic_sequence();
  236. ENTER();
  237. output = initialize_outputdata_f();
  238. queue = g_async_queue_new();
  239. // register_packet_queue(PAYLOAD_ID,queue,RESPONSE_FIRMWARE_VERSION);
  240. register_packet_queue(SEQUENCE_NUM,queue,seq);
  241. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  242. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_FIRMWARE_VERSION));
  243. DATA_SET(output->data,"queue",queue);
  244. io_cmd_f("empty_payload_pkt",output);
  245. EXIT();
  246. return;
  247. }
  248. /*!
  249. \brief Issues a packet to the ECU to get its build date
  250. */
  251. G_MODULE_EXPORT void request_firmware_build_date()
  252. {
  253. OutputData *output = NULL;
  254. GAsyncQueue *queue = NULL;
  255. gint seq = atomic_sequence();
  256. ENTER();
  257. output = initialize_outputdata_f();
  258. queue = g_async_queue_new();
  259. //register_packet_queue(PAYLOAD_ID,queue,RESPONSE_FIRMWARE_BUILD_DATE);
  260. register_packet_queue(SEQUENCE_NUM,queue,seq);
  261. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  262. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_FIRMWARE_BUILD_DATE));
  263. DATA_SET(output->data,"queue",queue);
  264. io_cmd_f("empty_payload_pkt",output);
  265. EXIT();
  266. return;
  267. }
  268. /*!
  269. \brief Issues a packet to the ECU to get its build date
  270. */
  271. G_MODULE_EXPORT void request_firmware_decoder_name()
  272. {
  273. OutputData *output = NULL;
  274. GAsyncQueue *queue = NULL;
  275. gint seq = atomic_sequence();
  276. ENTER();
  277. output = initialize_outputdata_f();
  278. queue = g_async_queue_new();
  279. register_packet_queue(SEQUENCE_NUM,queue,seq);
  280. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  281. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_DECODER_NAME));
  282. DATA_SET(output->data,"queue",queue);
  283. io_cmd_f("empty_payload_pkt",output);
  284. EXIT();
  285. return;
  286. }
  287. /*!
  288. \brief Issues a packet to the ECU to get its build compiler
  289. \param length is a pointer to a location to store the length of the data
  290. received, or NULL
  291. \returns the Firmware version as a text string
  292. */
  293. G_MODULE_EXPORT void request_firmware_compiler()
  294. {
  295. OutputData *output = NULL;
  296. GAsyncQueue *queue = NULL;
  297. gint seq = atomic_sequence();
  298. ENTER();
  299. output = initialize_outputdata_f();
  300. queue = g_async_queue_new();
  301. register_packet_queue(SEQUENCE_NUM,queue,seq);
  302. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  303. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_FIRMWARE_COMPILER_VERSION));
  304. DATA_SET(output->data,"queue",queue);
  305. io_cmd_f("empty_payload_pkt",output);
  306. EXIT();
  307. return;
  308. }
  309. /*!
  310. \brief Issues a packet to the ECU to get its build os
  311. \param length is a pointer to a location to store the length of the data
  312. received, or NULL
  313. \returns the Firmware version as a text string
  314. */
  315. G_MODULE_EXPORT void request_firmware_build_os()
  316. {
  317. OutputData *output = NULL;
  318. GAsyncQueue *queue = NULL;
  319. gint seq = atomic_sequence();
  320. ENTER();
  321. output = initialize_outputdata_f();
  322. queue = g_async_queue_new();
  323. register_packet_queue(SEQUENCE_NUM,queue,seq);
  324. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  325. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_FIRMWARE_COMPILER_OS));
  326. DATA_SET(output->data,"queue",queue);
  327. io_cmd_f("empty_payload_pkt",output);
  328. EXIT();
  329. return;
  330. }
  331. /*!
  332. \brief Issues a packet to the ECU to get its interface version.
  333. \param length is a pointer to a location to store the length of the data
  334. received, or NULL
  335. \returns the Firmware interface version as a text string
  336. */
  337. G_MODULE_EXPORT void request_interface_version()
  338. {
  339. OutputData *output = NULL;
  340. GAsyncQueue *queue = NULL;
  341. gint seq = atomic_sequence();
  342. ENTER();
  343. output = initialize_outputdata_f();
  344. queue = g_async_queue_new();
  345. register_packet_queue(SEQUENCE_NUM,queue,seq);
  346. DATA_SET(output->data,"sequence_num",GINT_TO_POINTER(seq));
  347. DATA_SET(output->data,"payload_id",GINT_TO_POINTER(REQUEST_INTERFACE_VERSION));
  348. DATA_SET(output->data,"queue",queue);
  349. io_cmd_f("empty_payload_pkt",output);
  350. EXIT();
  351. return;
  352. }
  353. /*
  354. \brief Queries the ECU for a location ID list
  355. \paranm length is a pointer to a location where this function can store the
  356. length of data received, or NULL
  357. \returns a pointer to a Link list (GList) of location ID's
  358. */
  359. G_MODULE_EXPORT GList *raw_request_location_ids(gint * length)
  360. {
  361. OutputData *output = NULL;
  362. GAsyncQueue *queue = NULL;
  363. LibreEMS_Packet *packet = NULL;
  364. GList *list = NULL;
  365. Serial_Params *serial_params = NULL;
  366. guint8 *buf = NULL;
  367. /* Raw packet */
  368. gint len = LOCATION_ID_LIST_REQ_PKT_LEN;
  369. guint8 pkt[LOCATION_ID_LIST_REQ_PKT_LEN];
  370. gint req = REQUEST_LIST_OF_LOCATION_IDS;
  371. gint resp = RESPONSE_LIST_OF_LOCATION_IDS;
  372. gint res = 0;
  373. gint i = 0;
  374. guint8 sum = 0;
  375. gint tmit_len = 0;
  376. guint8 flag = BLOCK_BITS_AND;
  377. guint16 bits = 0;
  378. ENTER();
  379. serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
  380. g_return_val_if_fail(serial_params,NULL);
  381. pkt[HEADER_IDX] = 0;
  382. pkt[H_PAYLOAD_IDX] = (req & 0xff00 ) >> 8;
  383. pkt[L_PAYLOAD_IDX] = (req & 0x00ff );
  384. pkt[L_PAYLOAD_IDX+1] = flag; /* AND/OR */
  385. bits |= BLOCK_IS_INDEXABLE | BLOCK_IN_RAM;
  386. pkt[L_PAYLOAD_IDX+2] = (bits & 0xff00) >> 8; /* H bits */
  387. pkt[L_PAYLOAD_IDX+3] = (bits & 0x00ff); /* L bits */
  388. for (i=0;i<len-1;i++)
  389. sum += pkt[i];
  390. pkt[len-1] = sum;
  391. buf = finalize_packet((guint8 *)&pkt,len,&tmit_len);
  392. queue = g_async_queue_new();
  393. register_packet_queue(PAYLOAD_ID,queue,resp);
  394. if (!write_wrapper_f(serial_params->fd,buf, tmit_len, NULL))
  395. {
  396. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  397. g_free(buf);
  398. g_async_queue_unref(queue);
  399. EXIT();
  400. return NULL;
  401. }
  402. g_free(buf);
  403. packet = (LibreEMS_Packet *)g_async_queue_timeout_pop(queue,500000);
  404. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  405. g_async_queue_unref(queue);
  406. if (packet)
  407. {
  408. gint h = 0;
  409. gint l = 0;
  410. gint tmpi = 0;
  411. for (i=0;i<packet->payload_length;i++)
  412. {
  413. tmpi = 0;
  414. h = packet->data[packet->payload_base_offset+i];
  415. i++;
  416. l = packet->data[packet->payload_base_offset+i];
  417. tmpi = (h << 8) + l;
  418. list = g_list_append(list,GINT_TO_POINTER(tmpi));
  419. }
  420. if (length)
  421. *length = packet->payload_length;
  422. libreems_packet_cleanup(packet);
  423. }
  424. EXIT();
  425. return list;
  426. }
  427. /*
  428. \brief Queries the ECU for the details of a specific location ID
  429. \param loc_id, the location ID to get more information about
  430. \returns a pointer to a Location_Details structure
  431. \see Location_Details
  432. */
  433. G_MODULE_EXPORT Location_Details *request_location_id_details(guint16 loc_id)
  434. {
  435. OutputData *output = NULL;
  436. GAsyncQueue *queue = NULL;
  437. LibreEMS_Packet *packet = NULL;
  438. GList *list = NULL;
  439. Serial_Params *serial_params = NULL;
  440. guint8 *buf = NULL;
  441. Location_Details *details = NULL;
  442. /* Raw packet */
  443. guint8 pkt[LOCATION_ID_DETAILS_REQ_PKT_LEN];
  444. gint res = 0;
  445. gint i = 0;
  446. guint8 sum = 0;
  447. gint tmit_len = 0;
  448. ENTER();
  449. serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
  450. g_return_val_if_fail(serial_params,NULL);
  451. pkt[HEADER_IDX] = 0;
  452. pkt[H_PAYLOAD_IDX] = (REQUEST_LOCATION_ID_DETAILS & 0xff00 ) >> 8;
  453. pkt[L_PAYLOAD_IDX] = (REQUEST_LOCATION_ID_DETAILS & 0x00ff );
  454. pkt[L_PAYLOAD_IDX+1] = (loc_id & 0xff00) >> 8; /* H location bits */
  455. pkt[L_PAYLOAD_IDX+2] = (loc_id & 0x00ff); /* L location bits */
  456. for (i=0;i<LOCATION_ID_DETAILS_REQ_PKT_LEN-1;i++)
  457. sum += pkt[i];
  458. pkt[LOCATION_ID_DETAILS_REQ_PKT_LEN-1] = sum;
  459. buf = finalize_packet((guint8 *)&pkt,LOCATION_ID_DETAILS_REQ_PKT_LEN,&tmit_len);
  460. queue = g_async_queue_new();
  461. register_packet_queue(PAYLOAD_ID,queue,RESPONSE_LOCATION_ID_DETAILS);
  462. if (!write_wrapper_f(serial_params->fd,buf, tmit_len, NULL))
  463. {
  464. deregister_packet_queue(PAYLOAD_ID,queue,RESPONSE_LOCATION_ID_DETAILS);
  465. g_free(buf);
  466. g_async_queue_unref(queue);
  467. EXIT();
  468. return NULL;
  469. }
  470. g_free(buf);
  471. packet = (LibreEMS_Packet *)g_async_queue_timeout_pop(queue,500000);
  472. deregister_packet_queue(PAYLOAD_ID,queue,RESPONSE_LOCATION_ID_DETAILS);
  473. g_async_queue_unref(queue);
  474. if (packet)
  475. {
  476. gint tmpi = 0;
  477. gint h = 0;
  478. gint l = 0;
  479. /*printf("packet payload length %i\n",packet->payload_length);*/
  480. if (packet->payload_length != 12)
  481. printf("ERROR in locationID details response!\n");
  482. details = g_new0(Location_Details, 1);
  483. h = packet->data[packet->payload_base_offset];
  484. l = packet->data[packet->payload_base_offset+1];
  485. details->flags = (h << 8) + l;
  486. /*printf("loc id details flags %i\n",details->flags);*/
  487. h = packet->data[packet->payload_base_offset+2];
  488. l = packet->data[packet->payload_base_offset+3];
  489. details->parent = (h << 8) + l;
  490. /*printf("loc id details parent %i\n",details->parent);*/
  491. details->ram_page = packet->data[packet->payload_base_offset+4];
  492. details->flash_page = packet->data[packet->payload_base_offset+5];
  493. /*printf("loc id details ram_page %i\n",details->ram_page);*/
  494. /*printf("loc id details flash_page %i\n",details->flash_page);*/
  495. h = packet->data[packet->payload_base_offset+6];
  496. l = packet->data[packet->payload_base_offset+7];
  497. details->ram_address = (h << 8) + l;
  498. /*printf("loc id details ram_address %0x\n",details->ram_address);*/
  499. h = packet->data[packet->payload_base_offset+8];
  500. l = packet->data[packet->payload_base_offset+9];
  501. details->flash_address = (h << 8) + l;
  502. /*printf("loc id details flash_address %0x\n",details->flash_address);*/
  503. h = packet->data[packet->payload_base_offset+10];
  504. l = packet->data[packet->payload_base_offset+11];
  505. details->length = (h << 8) + l;
  506. /*printf("loc id details length %i\n",details->length);*/
  507. libreems_packet_cleanup(packet);
  508. }
  509. EXIT();
  510. return details;
  511. }
  512. /*!
  513. \brief validate_and_load_tests() loads the list of tests from the system
  514. checks them for validity, and populates the passed array and hashtables
  515. with them
  516. \param tests is a pointer to a pointer of a GArray structure of the tests
  517. \param tests_hash is a pointer to a pointer of a hashtable of the Tests
  518. \returns TRUE on success, FALSE otherwise
  519. */
  520. G_MODULE_EXPORT gboolean validate_and_load_tests(GArray **tests, GHashTable **tests_hash)
  521. {
  522. ConfigFile *cfgfile;
  523. Detection_Test *test = NULL;
  524. gchar * filename = NULL;
  525. gchar *section = NULL;
  526. gchar * tmpbuf = NULL;
  527. gchar ** vector = NULL;
  528. gint total_tests = 0;
  529. gint result = 0;
  530. gint major = 0;
  531. gint minor = 0;
  532. gint i = 0;
  533. gint j = 0;
  534. gchar *pathstub = NULL;
  535. ENTER();
  536. pathstub = g_build_filename(INTERROGATOR_DATA_DIR,"Profiles",DATA_GET(global_data,"ecu_family"),"tests.cfg",NULL);
  537. filename = get_file((const gchar *)DATA_GET(global_data,"project_name"),pathstub,NULL);
  538. g_free(pathstub);
  539. if (!filename)
  540. {
  541. update_logbar_f("interr_view","warning",g_strdup_printf(_("Interrogation profile tests file %s not found!\n"),filename),FALSE,FALSE,TRUE);
  542. EXIT();
  543. return FALSE;
  544. }
  545. cfgfile = cfg_open_file(filename);
  546. if (!cfgfile)
  547. {
  548. EXIT();
  549. return FALSE;
  550. }
  551. get_file_api_f(cfgfile,&major,&minor);
  552. if ((major != INTERROGATE_MAJOR_API) || (minor != INTERROGATE_MINOR_API))
  553. {
  554. update_logbar_f("interr_view","warning",g_strdup_printf(_("Interrogation profile tests API mismatch (%i.%i != %i.%i):\n\tFile %s.\n"),major,minor,INTERROGATE_MAJOR_API,INTERROGATE_MINOR_API,filename),FALSE,FALSE,TRUE);
  555. g_free(filename);
  556. cfg_free(cfgfile);
  557. EXIT();
  558. return FALSE;
  559. }
  560. *tests_hash = g_hash_table_new_full(g_str_hash,g_str_equal,NULL,test_cleanup);
  561. MTXDBG(INTERROGATOR,_("File %s, opened successfully\n"),filename);
  562. *tests = g_array_new(FALSE,TRUE,sizeof(Detection_Test *));
  563. cfg_read_int(cfgfile,"interrogation_tests","total_tests",&total_tests);
  564. for (i=0;i<total_tests;i++)
  565. {
  566. test = g_new0(Detection_Test, 1);
  567. section = g_strdup_printf("test_%.2i",i);
  568. if (!cfg_read_string(cfgfile,section,"test_name",&test->test_name))
  569. {
  570. MTXDBG(INTERROGATOR,_("test_name for %s is NULL\n"),section);
  571. g_free(section);
  572. break;
  573. }
  574. if (!cfg_read_string(cfgfile,section,"test_result_type",&tmpbuf))
  575. {
  576. MTXDBG(INTERROGATOR,_("test_result_type for %s is NULL\n"),section);
  577. g_free(section);
  578. break;
  579. }
  580. else
  581. {
  582. test->result_type = translate_string_f(tmpbuf);
  583. g_free(tmpbuf);
  584. }
  585. if (!cfg_read_string(cfgfile,section,"test_func",&test->test_func))
  586. {
  587. MTXDBG(INTERROGATOR,_("test_function for %s is NULL\n"),section);
  588. g_free(section);
  589. break;
  590. }
  591. get_symbol_f(test->test_func,(void **)&test->function);
  592. cfg_read_string(cfgfile,section,"test_desc",
  593. &test->test_desc);
  594. g_free(section);
  595. g_array_append_val(*tests,test);
  596. g_hash_table_insert(*tests_hash,test->test_name,test);
  597. }
  598. cfg_free(cfgfile);
  599. g_free(filename);
  600. EXIT();
  601. return TRUE;
  602. }
  603. /*!
  604. \brief Frees all the resources of a Detection_Test structure
  605. \param data is a pointer to a Detection_Test structure
  606. \see Detection_Test
  607. */
  608. G_MODULE_EXPORT void test_cleanup(gpointer data)
  609. {
  610. Detection_Test *test = (Detection_Test *)data;
  611. ENTER();
  612. cleanup_f(test->test_func);
  613. cleanup_f(test->test_name);
  614. cleanup_f(test->test_desc);
  615. cleanup_f(test->result_str);
  616. if (test->result_type == RESULT_LIST)
  617. g_list_free((GList *)test->result);
  618. else
  619. if (test->result)
  620. cleanup_f(test->result);
  621. cleanup_f(test);
  622. EXIT();
  623. return;
  624. }
  625. /*!
  626. \brief Compares the results of the test runs with the available
  627. interrogation profiles, favoring USER profiles over system ones.
  628. If we have a match, allocated resources for a Firmware structure, and load
  629. the firmware details.
  630. \param tests is a pointer to a GArray of tests
  631. \param tests_hash is a pointer to the hashtable of tests
  632. \returns TRUE on if we hit a match, FALSE otherwise
  633. */
  634. G_MODULE_EXPORT gboolean determine_ecu(GArray *tests, GHashTable *tests_hash)
  635. {
  636. extern gconstpointer *global_data;
  637. gboolean retval = TRUE;
  638. gint i = 0;
  639. Detection_Test *test = NULL;
  640. gint num_tests = tests->len;
  641. gboolean match = FALSE;
  642. gchar * filename = NULL;
  643. gchar ** filenames = NULL;
  644. GArray *classes = NULL;
  645. Firmware_Details *firmware = NULL;
  646. gchar *pathstub = NULL;
  647. ENTER();
  648. pathstub = g_build_filename(INTERROGATOR_DATA_DIR,"Profiles",DATA_GET(global_data,"ecu_family"),NULL);
  649. filenames = get_files((const gchar *)DATA_GET(global_data,"project_name"),pathstub,"prof",&classes);
  650. g_free(pathstub);
  651. if (!filenames)
  652. {
  653. MTXDBG(INTERROGATOR|CRITICAL,_("NO Interrogation profiles found, was MegaTunix installed properly?\n\n"));
  654. EXIT();
  655. return FALSE;
  656. }
  657. i = 0;
  658. while (filenames[i])
  659. {
  660. if (check_for_match(tests_hash,filenames[i]))
  661. {
  662. match = TRUE;
  663. filename = g_strdup(filenames[i]);
  664. break;
  665. }
  666. i++;
  667. }
  668. g_strfreev(filenames);
  669. g_array_free(classes,TRUE);
  670. /* Update the screen with the data... */
  671. for (i=0;i<num_tests;i++)
  672. {
  673. test = g_array_index(tests,Detection_Test *,i);
  674. if (test->result_type == RESULT_DATA)
  675. {
  676. MTXDBG(INTERROGATOR,_("Command (%s): returned %i byts\n"),test->test_desc,test->num_bytes);
  677. thread_update_logbar_f("interr_view","info",g_strdup_printf("Command (%s): returned %i bytes)\n",test->test_desc,test->num_bytes),FALSE,FALSE);
  678. }
  679. if (test->result_type == RESULT_TEXT)
  680. {
  681. MTXDBG(INTERROGATOR,_("Command (%s): returned (%s)\n"),test->test_desc,test->result_str);
  682. thread_update_logbar_f("interr_view","info",g_strdup_printf("Command (%s): returned (%s)\n",test->test_desc,test->result_str),FALSE,FALSE);
  683. }
  684. else if (test->result_type == RESULT_LIST)
  685. {
  686. MTXDBG(INTERROGATOR,_("Command (%s): returned %i elements\n"),test->test_desc,g_list_length((GList *)test->result));
  687. thread_update_logbar_f("interr_view","info",g_strdup_printf("Command (%s): returned %i elements\n",test->test_desc,g_list_length((GList *)test->result)),FALSE,FALSE);
  688. }
  689. }
  690. if (match == FALSE) /* (we DID NOT find one) */
  691. {
  692. MTXDBG(INTERROGATOR,_("Firmware NOT DETECTED, Enable Interrogation deb ugging, retry interrogation,\nclose megatunix, and send ~/mtx/%s/debug.log to the author for analysis with a note\ndescribing which firmware you are attempt ing to talk to.\n"),(gchar *)DATA_GET(global_data,"project_name"));
  693. update_logbar_f("interr_view","warning",g_strdup_printf("Firmware NOT DETECTED, Enable Interrogation debugging, retry interrogation,\nclose megatuni x, and send ~/mtx/%s/debug.log to the author for analysis with a note\ndescrib ing which firmware you are attempting to talk to.\n",(gchar *)DATA_GET(global_data,"project_name")),FALSE,FALSE,TRUE);
  694. retval = FALSE;
  695. }
  696. else
  697. {
  698. if (!firmware)
  699. {
  700. firmware = g_new0(Firmware_Details,1);
  701. DATA_SET(global_data,"firmware",firmware);
  702. }
  703. if (!load_firmware_details(firmware,filename))
  704. retval = FALSE;
  705. }
  706. g_free(filename);
  707. EXIT();
  708. return(retval);
  709. }
  710. /*!
  711. \brief check_for_match() compares the results of the interrogation with the
  712. ECU to the canidates in turn. When a match occurs TRUE is returned
  713. otherwise it returns FALSE
  714. \param tests_hash is a pointer to an hashtable of tests
  715. \param filename is a pointer to an interrogation profile file to check against
  716. \returns TRUE on match, FALSE on failure
  717. */
  718. G_MODULE_EXPORT gboolean check_for_match(GHashTable *tests_hash, gchar *filename)
  719. {
  720. ConfigFile *cfgfile = NULL;
  721. Detection_Test *test = NULL;
  722. guint i = 0;
  723. gint len = 0;
  724. gboolean pass = FALSE;
  725. gchar * tmpbuf = NULL;
  726. gchar ** vector = NULL;
  727. gchar ** match_on = NULL;
  728. gint major = 0;
  729. gint minor = 0;
  730. MatchClass match_class;
  731. ENTER();
  732. cfgfile = cfg_open_file(filename);
  733. if (!cfgfile)
  734. {
  735. EXIT();
  736. return FALSE;
  737. }
  738. get_file_api_f(cfgfile,&major,&minor);
  739. if ((major != INTERROGATE_MAJOR_API) || (minor != INTERROGATE_MINOR_API))
  740. {
  741. update_logbar_f("interr_view","warning",g_strdup_printf(_("Interrogation profile API mismatch (%i.%i != %i.%i):\n\tFile %s will be skipped\n"),major,minor,INTERROGATE_MAJOR_API,INTERROGATE_MINOR_API,filename),FALSE,FALSE,TRUE);
  742. cfg_free(cfgfile);
  743. EXIT();
  744. return FALSE;
  745. }
  746. if (cfg_read_string(cfgfile,"interrogation","match_on",&tmpbuf) == FALSE)
  747. printf(_("ERROR:!! \"match_on\" key missing from interrogation profile [interrogation] section\n"));
  748. match_on = g_strsplit(tmpbuf,",",-1);
  749. g_free(tmpbuf);
  750. for (i=0;i<g_strv_length(match_on);i++)
  751. {
  752. pass = FALSE;
  753. /*printf("checking for match on %s\n",match_on[i]);*/
  754. test = (Detection_Test *)g_hash_table_lookup(tests_hash,match_on[i]);
  755. if (!test)
  756. {
  757. printf(_("ERROR test data not found for test \"%s\"\n"),match_on[i]);
  758. continue;
  759. }
  760. /* If the test_name is NOT IN the interrogation profile, we
  761. * abort as it's NOT match
  762. */
  763. if (!cfg_read_string(cfgfile,"interrogation",test->test_name,&tmpbuf))
  764. {
  765. MTXDBG(INTERROGATOR,_("MISMATCH,\"%s\" is NOT a match...\n\n"),filename);
  766. cfg_free(cfgfile);
  767. g_strfreev(match_on);
  768. EXIT();
  769. return FALSE;
  770. }
  771. vector = g_strsplit(tmpbuf,",",-1);
  772. g_free(tmpbuf);
  773. /* Possible choices are "Count", "submatch" and "fullmatch", so
  774. * stringparse to get them into a consistent form
  775. */
  776. if (g_strv_length(vector) != 2)
  777. printf(_("ERROR interrogation check_for match vector does NOT have two args it has %i\n"),g_strv_length(vector));
  778. match_class = (MatchClass)translate_string_f(vector[0]);
  779. /*printf("potential data is %s\n",vector[1]);*/
  780. switch (match_class)
  781. {
  782. case COUNT:
  783. if (test->num_bytes == atoi(vector[1]))
  784. pass = TRUE;
  785. break;
  786. case NUMMATCH:
  787. if (test->result_str)
  788. {
  789. if ((GINT)(test->result_str[0]) == atoi(vector[1]))
  790. pass = TRUE;
  791. }
  792. else
  793. pass = FALSE;
  794. break;
  795. case SUBMATCH:
  796. if (test->result_str)
  797. {
  798. if (strstr(test->result_str,vector[1]) != NULL)
  799. pass = TRUE;
  800. }
  801. else
  802. pass = FALSE;
  803. break;
  804. case FULLMATCH:
  805. if (test->result_str)
  806. {
  807. if (g_ascii_strcasecmp(test->result_str,vector[1]) == 0)
  808. pass = TRUE;
  809. }
  810. else
  811. pass = FALSE;
  812. break;
  813. case REGEX:
  814. if (test->result_str)
  815. {
  816. if (g_regex_match_simple(vector[1],test->result_str,
  817. (GRegexCompileFlags)0,
  818. (GRegexMatchFlags)0))
  819. pass = TRUE;
  820. }
  821. else
  822. pass = FALSE;
  823. break;
  824. default:
  825. pass = FALSE;
  826. }
  827. g_strfreev(vector);
  828. if (pass == TRUE)
  829. continue;
  830. else
  831. {
  832. MTXDBG(INTERROGATOR,_("MISMATCH,\"%s\" is NOT a match...\n\n"),filename);
  833. g_strfreev(match_on);
  834. cfg_free(cfgfile);
  835. EXIT();
  836. return FALSE;
  837. }
  838. }
  839. g_strfreev(match_on);
  840. MTXDBG(INTERROGATOR,_("\"%s\" is a match for all conditions ...\n\n"),filename);
  841. cfg_free(cfgfile);
  842. EXIT();
  843. return TRUE;
  844. }
  845. /*!
  846. \brief updates the interrogation Gui (General Tab) with the Firmware and
  847. Interface Versions
  848. */
  849. G_MODULE_EXPORT void update_ecu_info(void)
  850. {
  851. gchar *int_version = NULL;
  852. gchar *fw_version = NULL;
  853. gchar *build_date = NULL;
  854. gchar *build_os = NULL;
  855. gchar *compiler = NULL;
  856. gchar *decoder = NULL;
  857. gchar *info = NULL;
  858. ENTER();
  859. fw_version = (gchar *)DATA_GET(global_data,"fw_version");
  860. int_version = (gchar *)DATA_GET(global_data,"int_version");
  861. build_date = (gchar *)DATA_GET(global_data,"build_date");
  862. build_os = (gchar *)DATA_GET(global_data,"build_os");
  863. compiler = (gchar *)DATA_GET(global_data,"compiler");
  864. decoder = (gchar *)DATA_GET(global_data,"decoder_name");
  865. if ((fw_version) && (int_version) && (build_date) && (build_os) && (compiler) && (decoder))
  866. {
  867. info = g_strdup_printf("<b>Firmware Version:</b> %s\n<b>Interface version:</b> %s\n<b>Decoder Name:</b>%s\nThis firmware was built on %s using the %s compiler on %s",fw_version,int_version,decoder,build_date,compiler,build_os);
  868. thread_update_widget_f("ecu_info_label",MTX_LABEL,g_strdup(info));
  869. g_free(info);
  870. }
  871. EXIT();
  872. return;
  873. }
  874. /*!
  875. \brief Initiates the calls to get the info to update the tab with the
  876. interrogated ECU infomation
  877. */
  878. G_MODULE_EXPORT void update_interrogation_gui_pf(void)
  879. {
  880. ENTER();
  881. if (!DATA_GET(global_data,"interrogated"))
  882. {
  883. EXIT();
  884. return;
  885. }
  886. /* Request firmware version */
  887. request_firmware_version();
  888. request_interface_version();
  889. request_firmware_build_date();
  890. request_firmware_build_os();
  891. request_firmware_compiler();
  892. EXIT();
  893. return;
  894. }
  895. /*!
  896. \brief Loads the remaining parts of the Interrogation profile and populates
  897. the firmware structure allocation resources as needed based on the contents
  898. of the profile
  899. \param firmware is a pointer to an allocated Firmware_Details structure
  900. \param filename is a pointer to the matched interrogation profile
  901. \returns TRUE on success, FALSE otherwise
  902. */
  903. G_MODULE_EXPORT gboolean load_firmware_details(Firmware_Details *firmware, gchar * filename)
  904. {
  905. ConfigFile *cfgfile;
  906. Location_Details *details = NULL;
  907. GList *locations = NULL;
  908. gchar *tmpbuf = NULL;
  909. gchar *section = NULL;
  910. gchar ** list = NULL;
  911. gint tmpi = 0;
  912. gint major = 0;
  913. gint minor = 0;
  914. gint size = 0;
  915. guint8 *packet = NULL;
  916. gboolean res = FALSE;
  917. gint x_bins = 0;
  918. gint y_bins = 0;
  919. ENTER();
  920. cfgfile = cfg_open_file((gchar *)filename);
  921. if (!cfgfile)
  922. MTXDBG(INTERROGATOR|CRITICAL,_("File \"%s\" NOT OPENED successfully\n"),filename);
  923. get_file_api_f(cfgfile,&major,&minor);
  924. if ((major != INTERROGATE_MAJOR_API) || (minor != INTERROGATE_MINOR_API))
  925. {
  926. thread_update_logbar_f("interr_view","warning",g_strdup_printf(_("Interrogation profile API mismatch (%i.%i != %i.%i):\n\tFile %s will be skipped\n"),major,minor,INTERROGATE_MAJOR_API,INTERROGATE_MINOR_API,filename),FALSE,FALSE);
  927. cfg_free(cfgfile);
  928. EXIT();
  929. return FALSE;
  930. }
  931. MTXDBG(INTERROGATOR,_("File:%s opened successfully\n"),filename);
  932. firmware->profile_filename = g_strdup(filename);
  933. cfg_read_string(cfgfile,"interrogation_profile","name",&firmware->name);
  934. if(cfg_read_string(cfgfile,"parameters","EcuTempUnits",&tmpbuf))
  935. {
  936. firmware->ecu_temp_units = (TempUnits)translate_string_f(tmpbuf);
  937. g_free(tmpbuf);
  938. }
  939. else
  940. MTXDBG(INTERROGATOR,_("Failed to find EcuTempUnits key in interrogation profile\n"));
  941. if(!cfg_read_boolean(cfgfile,"parameters","BigEndian",&firmware->bigendian))
  942. {
  943. MTXDBG(INTERROGATOR|CRITICAL,_("\"BigEndian\" key not found in interrogation profile, assuming ECU firmware byte order is big endian, ERROR in interrogation profile\n"));
  944. firmware->bigendian = TRUE;
  945. }
  946. if(!cfg_read_string(cfgfile,"parameters","Capabilities",
  947. &tmpbuf))
  948. MTXDBG(INTERROGATOR|CRITICAL,_("\"Capabilities\" enumeration list not found in interrogation profile, ERROR\n"));
  949. else
  950. {
  951. firmware->capabilities = translate_capabilities(tmpbuf);
  952. g_free(tmpbuf);
  953. }
  954. /* Commands to map against the comm.xml */
  955. if(!cfg_read_string(cfgfile,"parameters","RT_Command",&firmware->rt_command))
  956. MTXDBG(INTERROGATOR|CRITICAL,_("\"RT_Command\" variable not found in interrogation profile, ERROR\n"));
  957. if(!cfg_read_int(cfgfile,"parameters","RT_total_bytes",
  958. &firmware->rtvars_size))
  959. MTXDBG(INTERROGATOR|CRITICAL,_("\"RT_total_bytes\" variable not found in interrogation profile, ERROR\n"));
  960. if(!cfg_read_string(cfgfile,"parameters","Get_All_Command",
  961. &firmware->get_all_command))
  962. MTXDBG(INTERROGATOR|CRITICAL,_("\"Get_All_Command\" variable not found in interrogation profile, ERROR\n"));
  963. if(!cfg_read_string(cfgfile,"parameters","Read_Command",
  964. &firmware->read_command))
  965. MTXDBG(INTERROGATOR|CRITICAL,_("\"Read_Command\" variable not found in interrogation profile, ERROR\n"));
  966. if(!cfg_read_string(cfgfile,"parameters","Write_Command",
  967. &firmware->write_command))
  968. MTXDBG(INTERROGATOR|CRITICAL,_("\"Write_Command\" variable not found in interrogation profile, ERROR\n"));
  969. if(!cfg_read_string(cfgfile,"parameters","Burn_Command",
  970. &firmware->burn_command))
  971. MTXDBG(INTERROGATOR|CRITICAL,_("\"Burn_Command\" variable not found in interrogation profile, ERROR\n"));
  972. if(!cfg_read_string(cfgfile,"parameters","Burn_All_Command",
  973. &firmware->burn_all_command))
  974. MTXDBG(INTERROGATOR|CRITICAL,_("\"Burn_All_Command\" variable not found in interrogation profile, ERROR\n"));
  975. if(!cfg_read_boolean(cfgfile,"parameters","ChunkWriteSupport",
  976. &firmware->chunk_support))
  977. MTXDBG(INTERROGATOR|CRITICAL,_("\"ChunkWriteSupport\" flag not found in parameters section in interrogation profile, ERROR\n"));
  978. if (firmware->chunk_support)
  979. {
  980. if(!cfg_read_string(cfgfile,"parameters","Chunk_Write_Command",
  981. &firmware->chunk_write_command))
  982. MTXDBG(INTERROGATOR|CRITICAL,_("\"Chunk_Write_Command\" flag not found in parameters section in interrogation profile, ERROR\n"));
  983. }
  984. /* Gui Section */
  985. if(!cfg_read_string(cfgfile,"gui","LoadTabs",&tmpbuf))
  986. MTXDBG(INTERROGATOR|CRITICAL,_("\"LoadTabs\" list not found in interrogation profile, ERROR\n"));
  987. else
  988. {
  989. firmware->tab_list = g_strsplit(tmpbuf,",",0);
  990. g_free(tmpbuf);
  991. }
  992. if(!cfg_read_string(cfgfile,"gui","TabConfs",
  993. &tmpbuf))
  994. MTXDBG(INTERROGATOR|CRITICAL,_("\"TabConfs\" list not found in interrogation profile, ERROR\n"));
  995. else
  996. {
  997. firmware->tab_confs = g_strsplit(tmpbuf,",",0);
  998. g_free(tmpbuf);
  999. }
  1000. if(!cfg_read_string(cfgfile,"gui","RealtimeMapFile",
  1001. &firmware->rtv_map_file))
  1002. MTXDBG(INTERROGATOR|CRITICAL,_("\"RealtimeMapFile\" variable not found in interrogation profile, ERROR\n"));
  1003. if(!cfg_read_string(cfgfile,"gui","SliderMapFile",
  1004. &firmware->sliders_map_file))
  1005. MTXDBG(INTERROGATOR|CRITICAL,_("\"SliderMapFile\" variable not found in interrogation profile, ERROR\n"));
  1006. if(!cfg_read_string(cfgfile,"gui","RuntimeTextMapFile",
  1007. &firmware->rtt_map_file))
  1008. MTXDBG(INTERROGATOR|CRITICAL,_("\"RuntimeTextMapFile\" variable not found in interrogation profile, ERROR\n"));
  1009. if(!cfg_read_string(cfgfile,"gui","StatusMapFile",
  1010. &firmware->status_map_file))
  1011. MTXDBG(INTERROGATOR|CRITICAL,_("\"StatusMapFile\" variable not found in interrogation profile, ERROR\n"));
  1012. /* Mtx maps location id's as pseudo "pages" */
  1013. locations = raw_request_location_ids(NULL);
  1014. if (locations)
  1015. {
  1016. firmware->total_pages = g_list_length(locations);
  1017. firmware->page_params = g_new0(Page_Params *, firmware->total_pages);
  1018. for (gint i=0;i<firmware->total_pages;i++)
  1019. {
  1020. firmware->page_params[i] = initialize_page_params();
  1021. firmware->page_params[i]->phys_ecu_page = (GINT)g_list_nth_data(locations,i);
  1022. /*printf("mtx page %i corresponds to ecu physicaly location id %i\n",i,firmware->page_params[i]->phys_ecu_page);*/
  1023. details = request_location_id_details((GINT)g_list_nth_data(locations,i));
  1024. if (details)
  1025. {
  1026. firmware->page_params[i]->length = details->length;
  1027. firmware->page_params[i]->dl_by_default = (details->flags & BLOCK_IS_INDEXABLE);
  1028. firmware->page_params[i]->read_only = (details->flags & BLOCK_IS_READONLY);
  1029. g_free(details);
  1030. }
  1031. }
  1032. g_list_free(locations);
  1033. }
  1034. /* MAJOR HACK ALERT, hardcoded for fred! */
  1035. firmware->total_tables = 3;
  1036. firmware->table_params = g_new0(Table_Params *,firmware->total_tables);
  1037. /* Fuel Table */
  1038. firmware->table_params[0] = initialize_table_params();
  1039. res = libreems_find_mtx_page(0,&tmpi);
  1040. if (res)
  1041. {
  1042. firmware->table_params[0]->x_page = tmpi;
  1043. firmware->table_params[0]->y_page = tmpi;
  1044. firmware->table_params[0]->z_page = tmpi;
  1045. }
  1046. else
  1047. {
  1048. MTXDBG(INTERROGATOR|CRITICAL,_("CRITICAL FAULT, unable to determine mtx page for location ID %i\n"),0);
  1049. exit(-1);
  1050. }
  1051. /* Hard coding this is bad, but since Fred Doesn't provide any way to
  1052. * get metadata from the ECU, there is no real clean way!
  1053. * */
  1054. res = get_dimensions(0,0,4, &x_bins,&y_bins);
  1055. if (!res)
  1056. printf("unable to get table dimensions for location ID 0\n");
  1057. firmware->table_params[0]->x_bincount = x_bins;
  1058. firmware->table_params[0]->y_bincount = y_bins;
  1059. firmware->table_params[0]->x_base = 4;
  1060. firmware->table_params[0]->y_base = 58;
  1061. firmware->table_params[0]->z_base = 100;
  1062. firmware->table_params[0]->x_size = MTX_U16;
  1063. firmware->table_params[0]->y_size = MTX_U16;
  1064. firmware->table_params[0]->z_size = MTX_U16;
  1065. firmware->table_params[0]->x_fromecu_mult = g_new0(gfloat, 1);
  1066. firmware->table_params[0]->y_fromecu_mult = g_new0(gfloat, 1);
  1067. firmware->table_params[0]->z_fromecu_mult = g_new0(gfloat, 1);
  1068. firmware->table_params[0]->z_raw_lower = 0;
  1069. firmware->table_params[0]->z_raw_upper = 65535;
  1070. *(firmware->table_params[0]->x_fromecu_mult) = 0.5;
  1071. *(firmware->table_params[0]->y_fromecu_mult) = 0.01;
  1072. *(firmware->table_params[0]->z_fromecu_mult) = 1.0/512;
  1073. firmware->table_params[0]->x_source = g_strdup("RPM");
  1074. firmware->table_params[0]->y_source = g_strdup("LoadMain");
  1075. firmware->table_params[0]->z_source = g_strdup("VEMain");
  1076. firmware->table_params[0]->x_suffix = g_strdup("RPM");
  1077. firmware->table_params[0]->y_suffix = g_strdup("kPa");
  1078. firmware->table_params[0]->z_suffix = g_strdup("%");
  1079. firmware->table_params[0]->x_precision = 0;
  1080. firmware->table_params[0]->y_precision = 1;
  1081. firmware->table_params[0]->z_precision = 1;
  1082. firmware->table_params[0]->x_use_color = FALSE;
  1083. firmware->table_params[0]->y_use_color = FALSE;
  1084. firmware->table_params[0]->z_use_color = TRUE;
  1085. firmware->table_params[0]->table_name = g_strdup("LibreEMS very alpha fuel table");;
  1086. /* Lambda Table */
  1087. firmware->table_params[1] = initialize_table_params();
  1088. res = libreems_find_mtx_page(6,&tmpi);
  1089. if (res)
  1090. {
  1091. firmware->table_params[1]->x_page = tmpi;
  1092. firmware->table_params[1]->y_page = tmpi;
  1093. firmware->table_params[1]->z_page = tmpi;
  1094. }
  1095. else
  1096. {
  1097. MTXDBG(INTERROGATOR|CRITICAL,_("CRITICAL FAULT, unable to determine mtx page for location ID %i\n"),0);
  1098. exit(-1);
  1099. }
  1100. res = get_dimensions(6,0,4, &x_bins,&y_bins);
  1101. if (!res)
  1102. printf("unable to get table dimensions for location ID 1\n");
  1103. firmware->table_params[1]->x_bincount = x_bins;
  1104. firmware->table_params[1]->y_bincount = y_bins;
  1105. firmware->table_params[1]->x_base = 4;
  1106. firmware->table_params[1]->y_base = 58;
  1107. firmware->table_params[1]->z_base = 100;
  1108. firmware->table_params[1]->x_size = MTX_U16;
  1109. firmware->table_params[1]->y_size = MTX_U16;
  1110. firmware->table_params[1]->z_size = MTX_U16;
  1111. firmware->table_params[1]->x_fromecu_mult = g_new0(gfloat, 1);
  1112. firmware->table_params[1]->y_fromecu_mult = g_new0(gfloat, 1);
  1113. firmware->table_params[1]->z_fromecu_mult = g_new0(gfloat, 1);
  1114. firmware->table_params[1]->z_raw_lower = 22282;
  1115. firmware->table_params[1]->z_raw_upper = 44565;
  1116. *(firmware->table_params[1]->x_fromecu_mult) = 0.5;
  1117. *(firmware->table_params[1]->y_fromecu_mult) = 0.01;
  1118. *(firmware->table_params[1]->z_fromecu_mult) = 1.0/32768;
  1119. firmware->table_params[1]->x_source = g_strdup("RPM");
  1120. firmware->table_params[1]->y_source = g_strdup("LoadMain");
  1121. firmware->table_params[1]->z_source = g_strdup("Lambda");
  1122. firmware->table_params[1]->x_suffix = g_strdup("RPM");
  1123. firmware->table_params[1]->y_suffix = g_strdup("kPa");
  1124. firmware->table_params[1]->z_suffix = g_strdup("Lambda");
  1125. firmware->table_params[1]->x_precision = 0;
  1126. firmware->table_params[1]->y_precision = 1;
  1127. firmware->table_params[1]->z_precision = 2;
  1128. firmware->table_params[1]->x_use_color = FALSE;
  1129. firmware->table_params[1]->y_use_color = FALSE;
  1130. firmware->table_params[1]->z_use_color = TRUE;
  1131. firmware->table_params[1]->table_name = g_strdup("LibreEMS very alpha lambda table");;
  1132. firmware->table_params[2] = initialize_table_params();
  1133. res = libreems_find_mtx_page(8,&tmpi);
  1134. if (res)
  1135. {
  1136. firmware->table_params[2]->x_page = tmpi;
  1137. firmware->table_params[2]->y_page = tmpi;
  1138. firmware->table_params[2]->z_page = tmpi;
  1139. }
  1140. else
  1141. {
  1142. MTXDBG(INTERROGATOR|CRITICAL,_("CRITICAL FAULT, unable to determine mtx page for location ID %i\n"),0);
  1143. exit(-1);
  1144. }
  1145. res = get_dimensions(8,0,4, &x_bins,&y_bins);
  1146. if (!res)
  1147. printf("unable to get table dimensions for location ID 0\n");
  1148. firmware->table_params[2]->x_bincount = x_bins;
  1149. firmware->table_params[2]->y_bincount = y_bins;
  1150. firmware->table_params[2]->x_base = 4;
  1151. firmware->table_params[2]->y_base = 58;
  1152. firmware->table_params[2]->z_base = 100;
  1153. firmware->table_params[2]->x_size = MTX_U16;
  1154. firmware->table_params[2]->y_size = MTX_U16;
  1155. firmware->table_params[2]->z_size = MTX_U16;
  1156. firmware->table_params[2]->x_fromecu_mult = g_new0(gfloat, 1);
  1157. firmware->table_params[2]->y_fromecu_mult = g_new0(gfloat, 1);
  1158. firmware->table_params[2]->z_fromecu_mult = g_new0(gfloat, 1);
  1159. firmware->table_params[2]->z_raw_lower = 0;
  1160. firmware->table_params[2]->z_raw_upper = 65535;
  1161. *(firmware->table_params[2]->x_fromecu_mult) = 0.5;
  1162. *(firmware->table_params[2]->y_fromecu_mult) = 0.01;
  1163. *(firmware->table_params[2]->z_fromecu_mult) = 1.0/1024;
  1164. firmware->table_params[2]->x_source = g_strdup("RPM");
  1165. firmware->table_params[2]->y_source = g_strdup("LoadMain");
  1166. firmware->table_params[2]->z_source = g_strdup("Degrees");
  1167. firmware->table_params[2]->x_suffix = g_strdup("RPM");
  1168. firmware->table_params[2]->y_suffix = g_strdup("kPa");
  1169. firmware->table_params[2]->z_suffix = g_strdup("\302\260BTDC");
  1170. firmware->table_params[2]->x_precision = 0;
  1171. firmware->table_params[2]->y_precision = 1;
  1172. firmware->table_params[2]->z_precision = 1;
  1173. firmware->table_params[2]->x_use_color = FALSE;
  1174. firmware->table_params[2]->y_use_color = FALSE;
  1175. firmware->table_params[2]->z_use_color = TRUE;
  1176. firmware->table_params[2]->table_name = g_strdup("LibreEMS very alpha spark table");;
  1177. if (mem_alloc_f)
  1178. mem_alloc_f();
  1179. else
  1180. MTXDBG(INTERROGATOR|CRITICAL,_("FAILED TO LOCATE \"mem_alloc\" function within core/plugins\n"));
  1181. /* Display firmware version in the window... */
  1182. MTXDBG(INTERROGATOR|CRITICAL,_("Detected Firmware: %s\n"),firmware->name);
  1183. thread_update_logbar_f("interr_view","warning",g_strdup_printf(_("Detected Firmware: %s\n"),firmware->name),FALSE,FALSE);
  1184. thread_update_logbar_f("interr_view","info",g_strdup_printf(_("Loading Settings from: \"%s\"\n"),firmware->profile_filename),FALSE,FALSE);
  1185. cfg_free(cfgfile);
  1186. EXIT();
  1187. return TRUE;
  1188. }
  1189. /*!
  1190. \brief translate_capabilities() converts a stringlist into a mask of
  1191. enumerations and returns it
  1192. \param string is a listing of capabilities in textual format
  1193. \returns an integer mask of the capabilites
  1194. */
  1195. G_MODULE_EXPORT gint translate_capabilities(const gchar *string)
  1196. {
  1197. gchar **vector = NULL;
  1198. gint i = 0;
  1199. gint value = 0;
  1200. gint tmpi = 0;
  1201. ENTER();
  1202. if (!string)
  1203. {
  1204. MTXDBG(INTERROGATOR|CRITICAL,_("String fed is NULL!\n"));
  1205. EXIT();
  1206. return -1;
  1207. }
  1208. vector = g_strsplit(string,",",0);
  1209. MTXDBG(INTERROGATOR,_("String fed is %s\n"),string);
  1210. while (vector[i] != NULL)
  1211. {
  1212. MTXDBG(INTERROGATOR,_("Trying to translate %s\n"),vector[i]);
  1213. tmpi = translate_string_f(vector[i]);
  1214. MTXDBG(INTERROGATOR,_("Translated value of %s is %i\n"),vector[i],value);
  1215. value += tmpi;
  1216. i++;
  1217. }
  1218. g_strfreev(vector);
  1219. EXIT();
  1220. return value;
  1221. }
  1222. /*!
  1223. \brief Initializes a Page_Params datastructure and returns a pointer to it
  1224. */
  1225. G_MODULE_EXPORT Page_Params * initialize_page_params(void)
  1226. {
  1227. Page_Params *page_params = NULL;
  1228. ENTER();
  1229. page_params = (Page_Params *)g_malloc0(sizeof(Page_Params));
  1230. page_params->length = 0;
  1231. page_params->spconfig_offset = -1;
  1232. page_params->needs_burn = FALSE;
  1233. EXIT();
  1234. return page_params;
  1235. }
  1236. /*!
  1237. \brief Initializes a Table_Params datastructure and returns a pointer to it
  1238. */
  1239. G_MODULE_EXPORT Table_Params * initialize_table_params(void)
  1240. {
  1241. Table_Params *table_params = NULL;
  1242. ENTER();
  1243. table_params = (Table_Params *)g_malloc0(sizeof(Table_Params));
  1244. table_params->is_fuel = FALSE;
  1245. table_params->alternate_offset = -1;
  1246. table_params->divider_offset = -1;
  1247. table_params->rpmk_offset = -1;
  1248. table_params->reqfuel_offset = -1;
  1249. table_params->x_page = -1;
  1250. table_params->y_page = -1;
  1251. table_params->z_page = -1;
  1252. table_params->x_base = -1;
  1253. table_params->y_base = -1;
  1254. table_params->z_base = -1;
  1255. table_params->x_bincount = -1;
  1256. table_params->y_bincount = -1;
  1257. table_params->x_precision = 0;
  1258. table_params->y_precision = 0;
  1259. table_params->z_precision = 0;
  1260. table_params->bind_to_list = NULL;
  1261. table_params->x_suffix = NULL;
  1262. table_params->y_suffix = NULL;
  1263. table_params->z_suffix = NULL;
  1264. table_params->x_fromecu_mult = NULL;
  1265. table_params->x_fromecu_add = NULL;
  1266. table_params->y_fromecu_mult = NULL;
  1267. table_params->y_fromecu_add = NULL;
  1268. table_params->z_fromecu_mult = NULL;
  1269. table_params->z_fromecu_add = NULL;
  1270. table_params->x_fromecu_mults = NULL;
  1271. table_params->x_fromecu_adds = NULL;
  1272. table_params->y_fromecu_mults = NULL;
  1273. table_params->y_fromecu_adds = NULL;
  1274. table_params->z_fromecu_mults = NULL;
  1275. table_params->z_fromecu_adds = NULL;
  1276. table_params->x_source_key = NULL;
  1277. table_params->y_source_key = NULL;
  1278. table_params->z_source_key = NULL;
  1279. table_params->table_name = NULL;
  1280. table_params->x_ul_eval = NULL;
  1281. table_params->y_ul_eval = NULL;
  1282. table_params->z_ul_eval = NULL;
  1283. table_params->x_dl_eval = NULL;
  1284. table_params->y_dl_eval = NULL;
  1285. table_params->z_dl_eval = NULL;
  1286. EXIT();
  1287. return table_params;
  1288. }
  1289. /*!
  1290. \brief Gets the X/Y sizes for the table requested at the specified location ID/offset and length, typically offset and length are 0 and 4 respectively (reads the first 4 bytes of the table)
  1291. \returns TRU on success, false otherwise
  1292. */
  1293. gboolean get_dimensions(gint location_id,gint offset,gint length,gint *x_bins, gint *y_bins)
  1294. {
  1295. guint8 *buf = NULL;
  1296. LibreEMS_Packet *packet = NULL;
  1297. gint size = 0;
  1298. GAsyncQueue *queue = NULL;
  1299. guint16 *ptr = NULL;
  1300. gint resp = RESPONSE_RETRIEVE_BLOCK_FROM_RAM;
  1301. Serial_Params *serial_params = NULL;
  1302. ENTER();
  1303. serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");
  1304. g_return_val_if_fail(serial_params,FALSE);
  1305. g_return_val_if_fail(x_bins,FALSE);
  1306. g_return_val_if_fail(y_bins,FALSE);
  1307. g_return_val_if_fail(length > 0,FALSE);
  1308. buf = make_me_a_packet(&size,PAYLOAD_ID,REQUEST_RETRIEVE_BLOCK_FROM_RAM,\
  1309. LOCATION_ID,location_id,\
  1310. OFFSET,offset,\
  1311. LENGTH,length,\
  1312. -1);
  1313. queue = g_async_queue_new();
  1314. register_packet_queue(PAYLOAD_ID,queue,resp);
  1315. if (!write_wrapper_f(serial_params->fd,buf, size, NULL))
  1316. {
  1317. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  1318. g_free(buf);
  1319. g_async_queue_unref(queue);
  1320. EXIT();
  1321. return FALSE;
  1322. }
  1323. g_free(buf);
  1324. packet = (LibreEMS_Packet *)g_async_queue_timeout_pop(queue,500000);
  1325. deregister_packet_queue(PAYLOAD_ID,queue,resp);
  1326. g_async_queue_unref(queue);
  1327. if (packet)
  1328. {
  1329. *x_bins = (packet->data[packet->payload_base_offset] << 8 ) + packet->data[packet->payload_base_offset +1];
  1330. *y_bins = (packet->data[packet->payload_base_offset+2] << 8 ) + packet->data[packet->payload_base_offset +3];
  1331. libreems_packet_cleanup(packet);
  1332. EXIT();
  1333. return TRUE;
  1334. }
  1335. EXIT();
  1336. return FALSE;
  1337. }