/** * @private */ void printDeviceUsageLine(OutputStream* outputStream, char header, Device* device, bool showOnlyProblem) { DeviceInterface* deviceInterface = device->deviceInterface; int argumentLength = deviceInterface->deviceGetInterface(header, DEVICE_MODE_INPUT, true); int resultLength = deviceInterface->deviceGetInterface(header, DEVICE_MODE_OUTPUT, true); if (showOnlyProblem) { OutputStream nullOutputStream; initNullOutputStream(&nullOutputStream); bool ok = printMethodOrNotificationMetaData(&nullOutputStream, deviceInterface, header, argumentLength, resultLength, false); // If there is a problem, we relaunch with a real outputStream if (!ok) { printMethodOrNotificationMetaData(outputStream, deviceInterface, header, argumentLength, resultLength, false); } } else{ printMethodOrNotificationMetaData(outputStream, deviceInterface, header, argumentLength, resultLength, false); } }
Image::Image (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImageCreateInfo& imageCreateInfo, const MemoryRequirement memoryRequirement) { m_image = createImage(vk, device, &imageCreateInfo); m_allocation = allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement); VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset())); }
Buffer::Buffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBufferCreateInfo& bufferCreateInfo, const MemoryRequirement memoryRequirement) { m_buffer = createBuffer(vk, device, &bufferCreateInfo); m_allocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement); VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset())); }
std::vector<VkImage> getSwapchainImages (const DeviceInterface& vkd, VkDevice device, VkSwapchainKHR swapchain) { deUint32 numImages = 0; VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL)); if (numImages > 0) { std::vector<VkImage> images (numImages); VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0])); return images; } else return std::vector<VkImage>(); }
void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) { const VkCommandBufferBeginInfo commandBufBeginParams = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkCommandBufferUsageFlags flags; (const VkCommandBufferInheritanceInfo*)DE_NULL, }; VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams)); }
void invalidateMappedMemoryRange (const DeviceInterface& vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size) { const VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, DE_NULL, memory, offset, size }; VK_CHECK(vkd.invalidateMappedMemoryRanges(device, 1u, &range)); }
QVariant deviceNameColumnData(const Device::Node& node, DeviceInterface& dev, int role) { static const QFont italicFont{[] () { QFont f; f.setItalic(true); return f; }()}; using namespace iscore; switch(role) { case Qt::DisplayRole: case Qt::EditRole: return node.get<DeviceSettings>().name; case Qt::FontRole: { if(!dev.connected()) return italicFont; } default: return {}; } }
void bindImagePlaneMemory (const DeviceInterface& vkd, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset, VkImageAspectFlagBits planeAspect) { const VkBindImagePlaneMemoryInfo planeInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR, DE_NULL, planeAspect }; const VkBindImageMemoryInfo coreInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR, &planeInfo, image, memory, memoryOffset, }; VK_CHECK(vkd.bindImageMemory2(device, 1u, &coreInfo)); }
void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) { VK_CHECK(vk.endCommandBuffer(commandBuffer)); }
cl_int MemObject::init() { // Get the device list of the context DeviceInterface **devices = 0; cl_int rs; rs = ((Context *)parent())->info(CL_CONTEXT_NUM_DEVICES, sizeof(unsigned int), &p_num_devices, 0); if (rs != CL_SUCCESS) return rs; p_devices_to_allocate = p_num_devices; devices = (DeviceInterface **)std::malloc(p_num_devices * sizeof(DeviceInterface *)); if (!devices) return CL_OUT_OF_HOST_MEMORY; rs = ((Context *)parent())->info(CL_CONTEXT_DEVICES, p_num_devices * sizeof(DeviceInterface *), devices, 0); if (rs != CL_SUCCESS) { std::free((void *)devices); return rs; } // Allocate a table of DeviceBuffers p_devicebuffers = (DeviceBuffer **)std::malloc(p_num_devices * sizeof(DeviceBuffer *)); if (!p_devicebuffers) { std::free((void *)devices); return CL_OUT_OF_HOST_MEMORY; } // If we have more than one device, the allocation on the devices is // defered to first use, so host_ptr can become invalid. So, copy it in // a RAM location and keep it. Also, set a flag telling CPU devices that // they don't need to reallocate and re-copy host_ptr if (p_num_devices > 1 && (p_flags & CL_MEM_COPY_HOST_PTR)) { void *tmp_hostptr = std::malloc(size()); if (!tmp_hostptr) { std::free((void *)devices); return CL_OUT_OF_HOST_MEMORY; } std::memcpy(tmp_hostptr, p_host_ptr, size()); p_host_ptr = tmp_hostptr; // Now, the client application can safely std::free() its host_ptr } // Create a DeviceBuffer for each device unsigned int failed_devices = 0; for (unsigned int i=0; i<p_num_devices; ++i) { DeviceInterface *device = devices[i]; rs = CL_SUCCESS; p_devicebuffers[i] = device->createDeviceBuffer(this, &rs); if (rs != CL_SUCCESS) { p_devicebuffers[i] = 0; failed_devices++; } } if (failed_devices == p_num_devices) { // Each device found a reason to reject the buffer, so it's invalid std::free((void *)devices); return rs; } std::free((void *)devices); devices = 0; // If we have only one device, already allocate the buffer if (p_num_devices == 1) { if (!p_devicebuffers[0]->allocate()) return CL_MEM_OBJECT_ALLOCATION_FAILURE; } return CL_SUCCESS; }
/** * @private */ void printDeviceNotificationLine(OutputStream* outputStream, unsigned char header, Device* device) { DeviceInterface* deviceInterface = device->deviceInterface; int argumentLength = deviceInterface->deviceGetInterface(header, DEVICE_MODE_NOTIFY, true); printMethodOrNotificationMetaData(outputStream, deviceInterface, header, argumentLength, 0, true); }
DeviceContext::DeviceContext(bool disableFateTime) { HINSTANCE drv; ctor_b_InitDeviceDriver InitDeviceDriverPtr; last_timestamp = 0.0; // read in the csv file and parse it, then load the standard device driver and initialize it // the csv file is called plugins.csv errorMessage = DEVICE_NO_ERROR; std::string line, all(""); std::string envPath; std::string plgsPath; ifstream plugins; // Before we get the path out of the registry, we try to get the current working directory char workingDir[_MAX_PATH]; getcwd(workingDir,_MAX_PATH); // try to open plugin.csv from the current working directory, if there is no such file fallback and use the path from the registry, which was set at the installation envPath = workingDir; for(unsigned int i=0;i<envPath.length();i++) { if (envPath[i] == '\\'){ envPath.insert(i,1,'\\'); i++; } } plgsPath = envPath; plgsPath.append("\\\\plugins.csv"); plugins.open(plgsPath.c_str(),ios::out |ios::binary); if(plugins.fail()) { // we fallback and try the registry entry // NOTE: the installer of the lib, or the developer has to SET THE environment variable AMBIENT to the path where the lib is // this is because the library can be used by a variety of programs and every program has it's own working directory char *en; size_t si; errno_t err = _dupenv_s(&en,&si,"AMBIENT"); if(err) return; // nothing loaded, no available registry path envPath = en; // convert to nt path for(unsigned int i=0;i<envPath.length();i++) { if (envPath[i] == '\\'){ envPath.insert(i,1,'\\'); i++; } } plgsPath = envPath; plgsPath.append("\\\\plugins.csv"); plugins.open(plgsPath.c_str(),ios::out | ios::binary); } if(plugins.fail()) { cout << "Error opening:"<< plgsPath << endl; MessageBox(NULL,plgsPath.c_str(),"Ambient Library - Error", MB_OK); errorMessage = DEVICE_ERROR_OPEN_DRIVER_LIST ; }else { while(plugins.good()){ getline(plugins,line); all.append(line); } } plugins.close(); // parse the file //MessageBox(NULL,all.c_str(), "MUH", MB_OK); std::vector<std::string> devs = Utils::StringSplit(all,";"); // now we know which drivers to load, because the number after every dll specifies which ones we are going to load // after loading the dll, query it and save which effects it can handle for(unsigned int i=0;i<devs.size();i+=2){ if(atoi(devs[i+1].c_str()) == LOAD_DRIVER) { wchar_t *libText; std::string pt = envPath; pt.append("\\\\plugins\\\\"); pt.append(devs[i].c_str()); libText = new wchar_t[strlen(pt.c_str())+1]; memset(libText,0,strlen(pt.c_str())+1); MultiByteToWideChar(CP_ACP,NULL,pt.c_str(),-1,libText,strlen(pt.c_str())+1); drv = LoadLibrary(pt.c_str()); delete []libText; if(drv != NULL){ // dll got loaded properly // get our entrypoint InitDeviceDriverPtr = (ctor_b_InitDeviceDriver) GetProcAddress(drv,"ctor_b_InitDeviceDriver"); if (NULL != InitDeviceDriverPtr) { // add the driver to our list DeviceInterface *devI = InitDeviceDriverPtr(disableFateTime); ptr<std::vector<int>> vec; // we are responsible for the vector ... vec = new std::vector<int>(); devI->getSupportedSensoryEffects(vec); devices.insert(pair<DeviceInterface *,ptr<std::vector<int>>>(devI,vec)); // now we have our driver loaded cout << "Loaded device driver successfuly!"<< endl; loadedPlugins.push_back(drv); }else{ std::string error_msg; error_msg.append("Error at loading driver: "); error_msg.append(devs[i].c_str()); MessageBox(NULL, error_msg.c_str(), "Ambient Library - Error", MB_OK); cout << "Error at loading driver: "<< devs[i].c_str() << endl; errorMessage = DEVICE_ERROR_LOADING_DRIVERS; FreeLibrary(drv); } }else{ cout << "No such device driver could be found: " << devs[i].c_str() << endl; } }else{ //MessageBox(NULL, devs[i].c_str(), "Not Loading..", MB_OK); } } }
MovePtr<Allocation> bindBufferDedicated (const InstanceInterface& vki, const DeviceInterface& vkd, const VkPhysicalDevice physDevice, const VkDevice device, const VkBuffer buffer, const MemoryRequirement requirement) { MovePtr<Allocation> alloc(allocateDedicated(vki, vkd, physDevice, device, buffer, requirement)); VK_CHECK(vkd.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset())); return alloc; }
MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement) { MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement)); VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset())); return alloc; }
MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement) { MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement); VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset())); return alloc; }
/* * Native kernel */ NativeKernelEvent::NativeKernelEvent(CommandQueue *parent, void (*user_func)(void *), void *args, size_t cb_args, cl_uint num_mem_objects, const MemObject **mem_list, const void **args_mem_loc, cl_uint num_events_in_wait_list, const Event **event_wait_list, cl_int *errcode_ret) : Event (parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret), p_user_func((void *)user_func), p_args(0) { if (*errcode_ret != CL_SUCCESS) return; // Parameters sanity if (!user_func) { *errcode_ret = CL_INVALID_VALUE; return; } if (!args && (cb_args || num_mem_objects)) { *errcode_ret = CL_INVALID_VALUE; return; } if (args && !cb_args) { *errcode_ret = CL_INVALID_VALUE; return; } if (num_mem_objects && (!mem_list || !args_mem_loc)) { *errcode_ret = CL_INVALID_VALUE; return; } if (!num_mem_objects && (mem_list || args_mem_loc)) { *errcode_ret = CL_INVALID_VALUE; return; } // Check that the device can execute a native kernel DeviceInterface *device; cl_device_exec_capabilities caps; *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *), &device, 0); if (*errcode_ret != CL_SUCCESS) return; *errcode_ret = device->info(CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(cl_device_exec_capabilities), &caps, 0); if (*errcode_ret != CL_SUCCESS) return; if ((caps & CL_EXEC_NATIVE_KERNEL) == 0) { *errcode_ret = CL_INVALID_OPERATION; return; } // Copy the arguments in a new list if (cb_args) { p_args = std::malloc(cb_args); if (!p_args) { *errcode_ret = CL_OUT_OF_HOST_MEMORY; return; } std::memcpy((void *)p_args, (void *)args, cb_args); // Replace memory objects with global pointers for (cl_uint i=0; i<num_mem_objects; ++i) { const MemObject *buffer = mem_list[i]; const char *loc = (const char *)args_mem_loc[i]; if (!buffer) { *errcode_ret = CL_INVALID_MEM_OBJECT; return; } // We need to do relocation : loc is in args, we need it in p_args size_t delta = (char *)p_args - (char *)args; loc += delta; *(void **)loc = buffer->deviceBuffer(device)->nativeGlobalPointer(); } } }
/* * Kernel event */ KernelEvent::KernelEvent(CommandQueue *parent, Kernel *kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size, cl_uint num_events_in_wait_list, const Event **event_wait_list, cl_int *errcode_ret) : Event(parent, Queued, num_events_in_wait_list, event_wait_list, errcode_ret), p_work_dim(work_dim), p_kernel(kernel) { // TODO This is where everything else needs to be handled. Need to try to use // device specific methods though. #ifdef DBG_EVENT std::cerr << "Entering KernelEvent::KernelEvent\n"; #endif if (*errcode_ret != CL_SUCCESS) return; *errcode_ret = CL_SUCCESS; // Sanity checks if (!kernel) { *errcode_ret = CL_INVALID_KERNEL; return; } // Check that the kernel was built for parent's device. DeviceInterface *device; Context *k_ctx, *q_ctx; size_t max_work_group_size; cl_uint max_dims = 0; *errcode_ret = parent->info(CL_QUEUE_DEVICE, sizeof(DeviceInterface *), &device, 0); if (*errcode_ret != CL_SUCCESS) return; *errcode_ret = parent->info(CL_QUEUE_CONTEXT, sizeof(Context *), &q_ctx, 0); *errcode_ret |= kernel->info(CL_KERNEL_CONTEXT, sizeof(Context *), &k_ctx, 0); *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &max_work_group_size, 0); *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(size_t), &max_dims, 0); *errcode_ret |= device->info(CL_DEVICE_MAX_WORK_ITEM_SIZES, max_dims * sizeof(size_t), p_max_work_item_sizes, 0); if (*errcode_ret != CL_SUCCESS) return; p_dev_kernel = kernel->deviceDependentKernel(device); #ifdef DBG_EVENT std::cerr << "got deviceDependentKernel\n"; #endif if (!p_dev_kernel) { *errcode_ret = CL_INVALID_PROGRAM_EXECUTABLE; #ifdef DBG_EVENT std::cerr << "ERROR: deviceDependentKernel failed\n"; #endif return; } // Check that contexts match if (k_ctx != q_ctx) { #ifdef DBG_EVENT std::cerr << "ERROR: contexts don't match!\n"; #endif *errcode_ret = CL_INVALID_CONTEXT; return; } // Check args if (!kernel->argsSpecified()) { #ifdef DBG_EVENT std::cerr << "ERROR: kernel args aren't specifed\n"; #endif *errcode_ret = CL_INVALID_KERNEL_ARGS; return; } // Check dimension if (work_dim == 0 || work_dim > max_dims) { #ifdef DBG_EVENT std::cerr << "ERROR: invalid work dimension\n"; #endif *errcode_ret = CL_INVALID_WORK_DIMENSION; return; } // Initialise kernel attributes for (unsigned i = 0; i < 3; ++i) { p_global_work_offset[i] = 0; p_global_work_size[i] = 0; p_local_work_size[i] = 0; } // Populate work_offset, work_size and local_work_size size_t work_group_size = 1; for (cl_uint i=0; i<work_dim; ++i) { if (global_work_offset) { p_global_work_offset[i] = global_work_offset[i]; } else { p_global_work_offset[i] = 0; } if (!global_work_size || !global_work_size[i]) { *errcode_ret = CL_INVALID_GLOBAL_WORK_SIZE; } p_global_work_size[i] = global_work_size[i]; if (!local_work_size) { // Guess the best value according to the device // TODO Use this call to calculate work item merges. // Also try to set the kernel function to be a tailcall(?) // so it doesn't have to save the regs p_local_work_size[i] = p_dev_kernel->guessWorkGroupSize(work_dim, i, global_work_size[i]); // TODO: CL_INVALID_WORK_GROUP_SIZE if // __attribute__((reqd_work_group_size(X, Y, Z))) is set } else { // Check divisibility if ((global_work_size[i] % local_work_size[i]) != 0) { *errcode_ret = CL_INVALID_WORK_GROUP_SIZE; return; } // Not too big ? if (local_work_size[i] > p_max_work_item_sizes[i]) { *errcode_ret = CL_INVALID_WORK_ITEM_SIZE; return; } // TODO: CL_INVALID_WORK_GROUP_SIZE if // __attribute__((reqd_work_group_size(X, Y, Z))) doesn't match p_local_work_size[i] = local_work_size[i]; work_group_size *= local_work_size[i]; } } // Check we don't ask too much to the device if (work_group_size > max_work_group_size) { *errcode_ret = CL_INVALID_WORK_GROUP_SIZE; return; } // Check arguments (buffer alignment, image size, ...) for (unsigned int i=0; i<kernel->numArgs(); ++i) { #ifdef DBG_EVENT std::cerr << "Checking argument " << i << std::endl; #endif const Kernel::Arg &a = kernel->arg(i); if (a.file() == Kernel::Arg::Local) continue; if (a.kind() == Kernel::Arg::Buffer) { #ifdef DBG_EVENT std::cerr << "Arg is a buffer\n"; #endif const MemObject *buffer = *(const MemObject **)(a.value(0)); if (!BufferEvent::isSubBufferAligned(buffer, device)) { *errcode_ret = CL_MISALIGNED_SUB_BUFFER_OFFSET; return; } } else if (a.kind() == Kernel::Arg::Image2D) { const Image2D *image = *(const Image2D **)(a.value(0)); size_t maxWidth, maxHeight; *errcode_ret = device->info(CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &maxWidth, 0); *errcode_ret |= device->info(CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &maxHeight, 0); if (*errcode_ret != CL_SUCCESS) return; if (image->width() > maxWidth || image->height() > maxHeight) { *errcode_ret = CL_INVALID_IMAGE_SIZE; return; } } else if (a.kind() == Kernel::Arg::Image3D) { const Image3D *image = *(const Image3D **)a.value(0); size_t maxWidth, maxHeight, maxDepth; *errcode_ret = device->info(CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &maxWidth, 0); *errcode_ret |= device->info(CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &maxHeight, 0); *errcode_ret |= device->info(CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &maxDepth, 0); if (*errcode_ret != CL_SUCCESS) return; if (image->width() > maxWidth || image->height() > maxHeight || image->depth() > maxDepth) { *errcode_ret = CL_INVALID_IMAGE_SIZE; return; } } } #ifdef DBG_EVENT std::cerr << "Leaving KernelEvent::KernelEvent\n"; #endif }
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; }