/** * Responds to a signal requesting that the fuel pump be run. */ void CUXInterface::onFuelPumpRunRequest() { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { c14cux_runFuelPump(&m_cuxinfo); } }
/** * Calls readData() in a loop until commanded to disconnect and possibly * shut down the thread. */ void CUXInterface::runServiceLoop() { ReadResult res = ReadResult_NoStatement; bool connected = c14cux_isConnected(&m_cuxinfo); while (!m_stopPolling && !m_shutdownThread && connected) { res = readData(); if (res == ReadResult_Success) { emit readSuccess(); emit dataReady(); } else if (res == ReadResult_Failure) { emit readError(); } QCoreApplication::processEvents(); } if (connected) { c14cux_disconnect(&m_cuxinfo); } emit disconnected(); clearFlagsAndData(); if (m_shutdownThread) { QThread::currentThread()->quit(); } }
/** * Reads the entire 16KB ROM. */ void CUXInterface::onReadROMImageRequested() { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { if (m_romImage == 0) { m_romImage = new QByteArray(16384, 0x00); } if (c14cux_dumpROM(&m_cuxinfo, (uint8_t*)m_romImage->data())) { if (!m_readCanceled) { emit romImageReady(); } } else { if (!m_readCanceled) { emit romImageReadFailed(); } } m_readCanceled = false; } else { emit notConnected(); } }
/** * Reads bytes from the serial device using an OS-specific call. * @param buffer Buffer into which data should be read * @param quantity Number of bytes to read * @return Number of bytes read from the device, or -1 if no bytes could be read */ int16_t c14cux_readSerialBytes(c14cux_info* info, uint8_t* buffer, uint16_t quantity) { int16_t bytesRead = -1; if (c14cux_isConnected(info)) { #if defined(WIN32) DWORD w32BytesRead = 0; if ((ReadFile(info->sd, (UCHAR*) buffer, quantity, &w32BytesRead, NULL) == TRUE) && (w32BytesRead > 0)) { bytesRead = w32BytesRead; } #else bytesRead = read(info->sd, buffer, quantity); #endif } else { dprintf_warn("14CUX(warning): Not connected.\n"); } return bytesRead; }
/** * Responds to a signal requesting that the idle air control valve be moved. * @param direction Direction of travel for the idle air control valve; * 0 to open and 1 to close * @param steps Number of steps to move the valve in the specified direction */ void CUXInterface::onIdleAirControlMovementRequest(int direction, int steps) { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { c14cux_driveIdleAirControlMotor(&m_cuxinfo, (uint8_t)direction, (uint8_t)steps); } else { emit notConnected(); } }
/** * Cleans up and exits the worker thread. */ void CUXInterface::onShutdownThreadRequest() { // If we're currently connected, just set a flag to let the polling loop // shut the thread down. Otherwise, shut it down here. if (c14cux_isConnected(&m_cuxinfo)) { m_shutdownThread = true; } else { QThread::currentThread()->quit(); } }
/** * Clears the block of fault codes. */ void CUXInterface::onFaultCodesClearRequested() { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { if (c14cux_clearFaultCodes(&m_cuxinfo) && c14cux_getFaultCodes(&m_cuxinfo, &m_faultCodes)) { emit faultCodesClearSuccess(m_faultCodes); } else { emit faultCodesClearFailure(); } } else { emit notConnected(); } }
/** * Writes bytes to the serial device using an OS-specific call * @param buffer Buffer from which written data should be drawn * @param quantity Number of bytes to write * @return Number of bytes written to the device, or -1 if no bytes could be written */ int16_t c14cux_writeSerialBytes(c14cux_info* info, uint8_t* buffer, uint16_t quantity) { int16_t bytesWritten = -1; if (c14cux_isConnected(info)) { #if defined(WIN32) DWORD w32BytesWritten = 0; if ((WriteFile(info->sd, (UCHAR *) buffer, quantity, &w32BytesWritten, NULL) == TRUE) && (w32BytesWritten == quantity)) { bytesWritten = w32BytesWritten; } #else bytesWritten = write(info->sd, buffer, quantity); #endif } return bytesWritten; }
/** * Reads fault codes from the 14CUX and stores in a member structure. */ void CUXInterface::onFaultCodesRequested() { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { memset(&m_faultCodes, 0, sizeof(m_faultCodes)); if (c14cux_getFaultCodes(&m_cuxinfo, &m_faultCodes)) { emit faultCodesReady(); } else { emit faultCodesReadFailed(); } } else { emit notConnected(); } }
/** * Respond to a signal requesting fuel map data by reading the desired fuel * map from the ECU, and emitting a signal when done. * @param fuelMapId ID of the fuel map that should be retrieved (1 through 5) */ void CUXInterface::onFuelMapRequested(unsigned int fuelMapId) { if (m_initComplete && c14cux_isConnected(&m_cuxinfo)) { if (readFuelMap(fuelMapId)) { emit fuelMapReady(fuelMapId); } if (c14cux_getRPMLimit(&m_cuxinfo, &m_rpmLimit)) { emit rpmLimitReady(m_rpmLimit); } if (c14cux_getRpmTable(&m_cuxinfo, &m_rpmTable)) { emit rpmTableReady(); } } }
/** * Reads the specified number of bytes from memory at the specified address. * @param info State information for the active connection. * @param addr Address at which memory should be read. * @param len Number of bytes to read. * @param buffer Pointer to a buffer of at least len bytes * @return 1 when the operation was successful; 0 otherwise */ bool c14cux_readMem(c14cux_info* info, uint16_t addr, uint16_t len, uint8_t* buffer) { #if defined(WIN32) if (WaitForSingleObject(info->mutex, INFINITE) != WAIT_OBJECT_0) { return 0; } #else pthread_mutex_lock(&info->mutex); #endif uint16_t totalBytesRead = 0; uint16_t singleReqQuantity = 0; uint16_t singleReqBytesRead = 0; bool readSuccess = false; int16_t readCallBytesRead = 1; bool sendLastByteOnly = false; info->cancelRead = 0; if (c14cux_isConnected(info)) { // loop until we've read all the bytes, or we experienced a read error while ((totalBytesRead < len) && (readCallBytesRead > 0) && (info->cancelRead == 0)) { // read the maximum number of bytes as is reasonable singleReqQuantity = c14cux_getByteCountForNextRead(len, totalBytesRead); // if the next address to read is within the 64-byte window // created by the last coarse address that was set, then we // can just send the final byte of the read command sendLastByteOnly = ((singleReqQuantity == info->lastReadQuantity) && ((addr + totalBytesRead) < (info->lastReadCoarseAddress + 64)) && (info->lastReadCoarseAddress <= (addr + totalBytesRead))); dprintf_info("14CUX(info): Sending cmd to read %d bytes at 0x%04X...\n", singleReqQuantity, addr + totalBytesRead); // if sending the read command is successful... if (c14cux_sendReadCmd(info, addr + totalBytesRead, singleReqQuantity, sendLastByteOnly)) { dprintf_info("14CUX(info): Successfully sent read command.\n"); // reset the number of bytes read during this single read operation singleReqBytesRead = 0; // loop until we've read all the bytes for this single read operation, // or until we time out do { readCallBytesRead = c14cux_readSerialBytes(info, buffer + totalBytesRead + singleReqBytesRead, singleReqQuantity - singleReqBytesRead); singleReqBytesRead += readCallBytesRead; } while ((readCallBytesRead > 0) && (singleReqBytesRead < singleReqQuantity)); // if all the reads were successful, add the total bytes // read from this request to the overall total if (readCallBytesRead > 0) { dprintf_info("14CUX(info): Successfully read %d bytes.\n", singleReqBytesRead); totalBytesRead += singleReqBytesRead; // remember the number of bytes read on this pass, in case we // want to issue an abbreviated command next time (which will // send the same number of bytes) info->lastReadQuantity = singleReqQuantity; } } else { // if we were unable to even send the read command, // stop with failure dprintf_err("14CUX(error): Failed to send read command\n"); readCallBytesRead = -1; } } } // if we read as many bytes as were requested, indicate success if (totalBytesRead == len) { dprintf_info("14CUX(info): Successfully read all requested bytes.\n"); readSuccess = true; } else { info->lastReadCoarseAddress = 0; info->lastReadQuantity = 0; } #if defined(WIN32) ReleaseMutex(info->mutex); #else pthread_mutex_unlock(&info->mutex); #endif return readSuccess; }
/** * Indicates whether the serial device is currently open/connected. * @return True when the device is connected; false otherwise. */ bool CUXInterface::isConnected() { return (m_initComplete && c14cux_isConnected(&m_cuxinfo)); }