/** * @private * Try to verify if the char is a filtered char or not * @return true if it was filtered (=> buffer first char will be removed), false else */ bool filterFirstNextChar(Buffer* inputBuffer, filterCharFunction* inputFilterChar) { // read the first char (but do not pop from the FIFO) char deviceHeader = bufferGetCharAtIndex(inputBuffer, DEVICE_HEADER_INDEX); if (inputFilterChar != NULL) { if (!inputFilterChar(deviceHeader, &deviceHeader)) { // remove the char from the buffer bufferReadChar(inputBuffer); return true; } } return false; }
/** * @private * Try to clear the buffer if it contains some 'z' char. Very usefull when we have made a mistake taping an instruction. * @return true if it was cleared (=> buffer will be cleared), false else */ bool clearBufferIfNeeded(Buffer* inputBuffer) { int i; int inputBufferCount = getBufferElementsCount(inputBuffer); for (i = 0; i < inputBufferCount; i++) { char bufferElement = bufferGetCharAtIndex(inputBuffer, i); if (bufferElement == HEADER_CLEAR_INPUT_STREAM) { deepClearBuffer(inputBuffer); return true; } // remove all informations to the latest char if (bufferElement == HEADER_WRITE_CONTENT_AND_DEEP_CLEAR_BUFFER) { printDebugBuffer(getAlwaysOutputStreamLogger(), inputBuffer); deepClearBuffer(inputBuffer); return true; } } return false; }
bool transmitFromDriverRequestBuffer() { // Handle redirection if (redirectFunction != NULL) { bool result = redirectFunction(); return result; } // We do exactly as if the data was written by a end-user // requestBuffer must be filled before calling this method Buffer* requestBuffer = getDriverRequestBuffer(); Buffer* responseBuffer = getDriverResponseBuffer(); InputStream* inputStream = getDriverResponseInputStream(); if (inputStream == NULL) { writeError(DRIVER_INPUT_STREAM_NULL); return false; } // The first char is the device header unsigned dataDispacherLength = 0; unsigned char deviceHeader = bufferGetCharAtIndex(requestBuffer, DEVICE_HEADER_INDEX); if (deviceHeader == DISPATCHER_COMMAND_HEADER) { dataDispacherLength = DISPATCHER_COMMAND_AND_INDEX_HEADER_LENGTH; // Reload the real Device Header deviceHeader = bufferGetCharAtIndex(requestBuffer, dataDispacherLength + DEVICE_HEADER_INDEX); } // The second char is the command header unsigned char commandHeader = bufferGetCharAtIndex(requestBuffer, dataDispacherLength + COMMAND_HEADER_INDEX); bool result = handleStreamInstruction( requestBuffer, responseBuffer, // Don't copy to an outputStream, because, we // want to read the content of responseBuffer NULL, // TODO : Check why we don't provide any NotificationOutputStream NULL, // No Input Filter NULL, // No Output Filter NULL); // We need ack result = checkIsAck(inputStream); if (!result) { // The buffer is corrupted, but we would like to avoid further problem clearInputStream(inputStream); return false; } // Device header answer with the same header as the request checkIsChar(inputStream, deviceHeader); if (!result) { // The buffer is corrupted, but we would like to avoid further problem clearInputStream(inputStream); return false; } // Command header answer with the same header as the request checkIsChar(inputStream, commandHeader); if (!result) { // The buffer is corrupted, but we would like to avoid further problem clearInputStream(inputStream); return false; } return result; }
bool handleStreamInstruction(Buffer* inputBuffer, Buffer* outputBuffer, OutputStream* outputStream, filterCharFunction* inputFilterChar, filterCharFunction* outputFilterChar) { if (inputBuffer == NULL) { writeError(DRIVER_STREAM_LISTENER_INPUT_BUFFER_NULL); return false; } if (outputBuffer == NULL) { writeError(DRIVER_STREAM_LISTENER_OUTPUT_BUFFER_NULL); return false; } // Try to clear the buffer if needed ('z' char) if (clearBufferIfNeeded(inputBuffer)) { return false; } // We received data int inputBufferCount = getBufferElementsCount(inputBuffer); if (inputBufferCount > 0) { if (filterFirstNextChar(inputBuffer, inputFilterChar)) { return false; } // As there is clear of char filtering, we must reload the size of the buffer int bufferSize = getBufferElementsCount(inputBuffer); if (bufferSize < DEVICE_HEADER_LENGTH) { return false; } // Get the header unsigned char deviceHeader = bufferGetCharAtIndex(inputBuffer, DEVICE_HEADER_INDEX); // Manage the dispatcher specifier (3 chars : Ex j01 before real command ...) unsigned char specifyDispatcherLength = 0; if (deviceHeader == DATA_DISPATCHER_DEVICE_HEADER) { specifyDispatcherLength += DISPATCHER_COMMAND_AND_INDEX_HEADER_LENGTH; } // Check if enough data if (bufferSize < specifyDispatcherLength + DEVICE_AND_COMMAND_HEADER_LENGTH) { return false; } // Reload the deviceHeader to take the dispatcher specifier if any deviceHeader = bufferGetCharAtIndex(inputBuffer, specifyDispatcherLength + DEVICE_HEADER_INDEX); unsigned char commandHeader = bufferGetCharAtIndex(inputBuffer, specifyDispatcherLength + COMMAND_HEADER_INDEX); // find the device corresponding to this header. It must at least be declared in local or in remote ! unsigned char dataSize = bufferSize - specifyDispatcherLength; const Device* device = deviceDataDispatcherFindDevice(deviceHeader, commandHeader, dataSize, DEVICE_MODE_INPUT); // if the device was not found if (device == NULL) { return false; } // At this moment, device Interface is found DeviceInterface* deviceInterface = device->deviceInterface; // We must send device specifyDispatcherLength + Header + commandHeader + data => + 2 int dataToTransferCount = deviceInterface->deviceGetInterface(commandHeader, DEVICE_MODE_INPUT, false) + specifyDispatcherLength + DEVICE_AND_COMMAND_HEADER_LENGTH; if (bufferSize < dataToTransferCount) { return false; } // We must receive ack + device header + command header + data => + 3 int dataToReceiveCount = deviceInterface->deviceGetInterface(commandHeader, DEVICE_MODE_OUTPUT, false) + ACK_LENGTH + DEVICE_AND_COMMAND_HEADER_LENGTH; InputStream* bufferedInputStream = getInputStream(inputBuffer); OutputStream* bufferedOutputStream = getOutputStream(outputBuffer); TransmitMode transmitMode = device->transmitMode; // we handle locally the request if (specifyDispatcherLength == 0 && transmitMode == TRANSMIT_LOCAL) { // We need the implementation for local mode DeviceDescriptor* deviceDescriptor = device->descriptor; if (deviceDescriptor == NULL) { writeError(NO_DEVICE_DESC_FOUND_FOR); append(getErrorOutputStreamLogger(), deviceHeader); append(getErrorOutputStreamLogger(), commandHeader); return false; } // remove the first chars corresponding to the device header and command Header bufferClearLastChars(inputBuffer, DEVICE_AND_COMMAND_HEADER_LENGTH); // Call to the device deviceDescriptor->deviceHandleRawData(commandHeader, bufferedInputStream, bufferedOutputStream); } // we forward the request through Remote Operation with Dispatcher else if (specifyDispatcherLength > 0 || transmitMode == TRANSMIT_I2C || transmitMode == TRANSMIT_UART || transmitMode == TRANSMIT_ZIGBEE) { // Find dispatcher DriverDataDispatcher* dispatcher = NULL; if (specifyDispatcherLength > 0) { bufferClearLastChars(inputBuffer, DEVICE_HEADER_LENGTH); unsigned char dispatcherIndex = readHex2(bufferedInputStream); dispatcher = getDriverDataDispatcherByIndex(dispatcherIndex); if (dispatcher == NULL) { writeError(NO_DISPATCHER_FOUND); OutputStream* errorOutputStream = getErrorOutputStreamLogger(); appendStringAndDec(errorOutputStream, ", dispatcherIndex=", dispatcherIndex); return false; } } else { TransmitMode transmitMode = device->transmitMode; int address = device->address; dispatcher = getDriverDataDispatcherByTransmitMode(transmitMode, address); if (dispatcher == NULL) { writeError(NO_DISPATCHER_FOUND); OutputStream* errorOutputStream = getErrorOutputStreamLogger(); appendStringAndDec(errorOutputStream, ", transmitMode=", transmitMode); append(errorOutputStream, '('); appendString(errorOutputStream, getTransmitModeAsString(transmitMode)); append(errorOutputStream, ')'); appendStringAndDec(errorOutputStream, ", addr=", address); return false; } } // copy Driver buffer with remote Call dispatcher->driverDataDispatcherTransmitData(dispatcher, inputBuffer, outputBuffer, dataToTransferCount, dataToReceiveCount ); } // In All Cases (Local / I2C / UART / Zigbee ...) // Copy the data from bufferOutputStream to the outputStream if (outputStream != NULL) { copyInputToOutputStream(&(outputBuffer->inputStream), outputStream, outputFilterChar, dataToReceiveCount); } return true; } return false; }