1 // Copyright (C) 2018-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
11 #include "XLinkErrorUtils.h"
13 #include "XLinkPlatform.h"
14 #include "XLinkPrivateFields.h"
15 #include "XLinkDispatcherImpl.h"
17 #ifdef MVLOG_UNIT_NAME
18 #undef MVLOG_UNIT_NAME
19 #define MVLOG_UNIT_NAME xLink
22 #include "XLinkStringUtils.h"
24 #define MAX_PATH_LENGTH (255)
26 // ------------------------------------
27 // Global fields. Begin.
28 // ------------------------------------
30 XLinkGlobalHandler_t* glHandler; //TODO need to either protect this with semaphor
31 //or make profiling data per device
33 xLinkDesc_t availableXLinks[MAX_LINKS];
34 sem_t pingSem; //to b used by myriad
35 DispatcherControlFunctions controlFunctionTbl;
36 linkId_t nextUniqueLinkId = 0; //incremental number, doesn't get decremented.
38 // ------------------------------------
39 // Global fields. End.
40 // ------------------------------------
44 // ------------------------------------
45 // Helpers declaration. Begin.
46 // ------------------------------------
48 static linkId_t getNextAvailableLinkUniqueId();
49 static xLinkDesc_t* getNextAvailableLink();
53 static XLinkError_t parsePlatformError(xLinkPlatformErrorCode_t rc);
57 // ------------------------------------
58 // Helpers declaration. End.
59 // ------------------------------------
63 // ------------------------------------
64 // API implementation. Begin.
65 // ------------------------------------
67 XLinkError_t XLinkInitialize(XLinkGlobalHandler_t* globalHandler)
70 mvLogLevelSet(MVLOG_FATAL);
71 mvLogDefaultLevelSet(MVLOG_FATAL);
74 XLINK_RET_IF(globalHandler == NULL);
75 ASSERT_XLINK(XLINK_MAX_STREAMS <= MAX_POOLS_ALLOC);
76 glHandler = globalHandler;
77 if (sem_init(&pingSem,0,0)) {
78 mvLog(MVLOG_ERROR, "Can't create semaphore\n");
84 //Using deprecated fields. Begin.
85 int loglevel = globalHandler->loglevel;
86 int protocol = globalHandler->protocol;
87 //Using deprecated fields. End.
89 memset((void*)globalHandler, 0, sizeof(XLinkGlobalHandler_t));
91 //Using deprecated fields. Begin.
92 globalHandler->loglevel = loglevel;
93 globalHandler->protocol = protocol;
94 //Using deprecated fields. End.
96 controlFunctionTbl.eventReceive = &dispatcherEventReceive;
97 controlFunctionTbl.eventSend = &dispatcherEventSend;
98 controlFunctionTbl.localGetResponse = &dispatcherLocalEventGetResponse;
99 controlFunctionTbl.remoteGetResponse = &dispatcherRemoteEventGetResponse;
100 controlFunctionTbl.closeLink = &dispatcherCloseLink;
101 controlFunctionTbl.closeDeviceFd = &dispatcherCloseDeviceFd;
103 XLINK_RET_IF(DispatcherInitialize(&controlFunctionTbl));
105 //initialize availableStreams
106 memset(availableXLinks, 0, sizeof(availableXLinks));
109 for (i = 0; i < MAX_LINKS; i++) {
110 link = &availableXLinks[i];
112 link->id = INVALID_LINK_ID;
113 link->deviceHandle.xLinkFD = NULL;
114 link->peerState = XLINK_NOT_INIT;
116 for (stream = 0; stream < XLINK_MAX_STREAMS; stream++)
117 link->availableStreams[stream].id = INVALID_STREAM_ID;
121 link = getNextAvailableLink();
123 return X_LINK_COMMUNICATION_NOT_OPEN;
125 link->id = getNextAvailableLinkUniqueId();
126 link->peerState = XLINK_UP;
127 link->deviceHandle.xLinkFD = NULL;
129 xLinkDeviceHandle_t temp = {0};
130 temp.protocol = X_LINK_ANY_PROTOCOL;
131 XLINK_RET_IF_FAIL(DispatcherStart(&temp)); //myriad has one
136 return X_LINK_SUCCESS;
141 int XLinkIsDescriptionValid(const deviceDesc_t *in_deviceDesc, const XLinkDeviceState_t state) {
142 return XLinkPlatformIsDescriptionValid(in_deviceDesc, state);
145 XLinkError_t XLinkFindFirstSuitableDevice(XLinkDeviceState_t state,
146 const deviceDesc_t in_deviceRequirements,
147 deviceDesc_t *out_foundDevice)
149 XLINK_RET_IF(out_foundDevice == NULL);
151 xLinkPlatformErrorCode_t rc;
152 rc = XLinkPlatformFindDeviceName(state, in_deviceRequirements, out_foundDevice);
153 return parsePlatformError(rc);
156 XLinkError_t XLinkFindAllSuitableDevices(XLinkDeviceState_t state,
157 const deviceDesc_t in_deviceRequirements,
158 deviceDesc_t *out_foundDevicesPtr,
159 const unsigned int devicesArraySize,
160 unsigned int* out_foundDevicesCount) {
161 XLINK_RET_IF(out_foundDevicesPtr == NULL);
162 XLINK_RET_IF(devicesArraySize <= 0);
163 XLINK_RET_IF(out_foundDevicesCount == NULL);
165 xLinkPlatformErrorCode_t rc;
166 rc = XLinkPlatformFindArrayOfDevicesNames(
167 state, in_deviceRequirements,
168 out_foundDevicesPtr, devicesArraySize, out_foundDevicesCount);
170 return parsePlatformError(rc);
173 //Called only from app - per device
174 XLinkError_t XLinkConnect(XLinkHandler_t* handler)
176 XLINK_RET_IF(handler == NULL);
177 if (strnlen(handler->devicePath, MAX_PATH_LENGTH) < 2) {
178 mvLog(MVLOG_ERROR, "Device path is incorrect");
182 xLinkDesc_t* link = getNextAvailableLink();
183 XLINK_RET_IF(link == NULL);
184 mvLog(MVLOG_DEBUG,"%s() device name %s glHandler %p protocol %d\n", __func__, handler->devicePath, glHandler, handler->protocol);
186 link->deviceHandle.protocol = handler->protocol;
187 int connectStatus = XLinkPlatformConnect(handler->devicePath2, handler->devicePath,
188 link->deviceHandle.protocol, &link->deviceHandle.xLinkFD);
190 if (connectStatus < 0) {
192 * Connection may be unsuccessful at some amount of first tries.
193 * In this case, asserting the status provides enormous amount of logs in tests.
195 return X_LINK_COMMUNICATION_NOT_OPEN;
199 DispatcherStart(&link->deviceHandle) != X_LINK_SUCCESS, X_LINK_TIMEOUT);
201 xLinkEvent_t event = {0};
203 event.header.type = XLINK_PING_REQ;
204 event.deviceHandle = link->deviceHandle;
205 DispatcherAddEvent(EVENT_LOCAL, &event);
207 if (DispatcherWaitEventComplete(&link->deviceHandle)) {
208 DispatcherClean(&link->deviceHandle);
209 return X_LINK_TIMEOUT;
212 link->id = getNextAvailableLinkUniqueId();
213 link->peerState = XLINK_UP;
214 link->hostClosedFD = 0;
215 handler->linkId = link->id;
216 return X_LINK_SUCCESS;
219 XLinkError_t XLinkBoot(deviceDesc_t* deviceDesc, const char* binaryPath)
221 if (XLinkPlatformBootRemote(deviceDesc, binaryPath) == 0) {
222 return X_LINK_SUCCESS;
225 return X_LINK_COMMUNICATION_FAIL;
228 XLinkError_t XLinkBootFirmware(deviceDesc_t* deviceDesc, const char* firmware, unsigned long length) {
229 if (!XLinkPlatformBootFirmware(deviceDesc, firmware, length)) {
230 return X_LINK_SUCCESS;
233 return X_LINK_COMMUNICATION_FAIL;
236 XLinkError_t XLinkResetRemote(linkId_t id)
238 xLinkDesc_t* link = getLinkById(id);
239 XLINK_RET_IF(link == NULL);
241 if (getXLinkState(link) != XLINK_UP) {
242 mvLog(MVLOG_WARN, "Link is down, close connection to device without reset");
243 XLinkPlatformCloseRemote(&link->deviceHandle);
244 return X_LINK_COMMUNICATION_NOT_OPEN;
247 // Add event to reset device. After sending it, dispatcher will close fd link
248 xLinkEvent_t event = {0};
249 event.header.type = XLINK_RESET_REQ;
250 event.deviceHandle = link->deviceHandle;
251 mvLog(MVLOG_DEBUG, "sending reset remote event\n");
252 DispatcherAddEvent(EVENT_LOCAL, &event);
253 XLINK_RET_ERR_IF(DispatcherWaitEventComplete(&link->deviceHandle),
256 if(XLink_sem_wait(&link->dispatcherClosedSem)) {
257 mvLog(MVLOG_ERROR,"can't wait dispatcherClosedSem\n");
261 return X_LINK_SUCCESS;
264 XLinkError_t XLinkResetAll()
267 mvLog(MVLOG_INFO, "Devices will not be restarted for this configuration (NO_BOOT)");
270 for (i = 0; i < MAX_LINKS; i++) {
271 if (availableXLinks[i].id != INVALID_LINK_ID) {
272 xLinkDesc_t* link = &availableXLinks[i];
274 for (stream = 0; stream < XLINK_MAX_STREAMS; stream++) {
275 if (link->availableStreams[stream].id != INVALID_STREAM_ID) {
276 streamId_t streamId = link->availableStreams[stream].id;
277 mvLog(MVLOG_DEBUG,"%s() Closing stream (stream = %d) %d on link %d\n",
278 __func__, stream, (int) streamId, (int) link->id);
279 COMBINE_IDS(streamId, link->id);
280 if (XLinkCloseStream(streamId) != X_LINK_SUCCESS) {
281 mvLog(MVLOG_WARN,"Failed to close stream");
285 if (XLinkResetRemote(link->id) != X_LINK_SUCCESS) {
286 mvLog(MVLOG_WARN,"Failed to reset");
291 return X_LINK_SUCCESS;
296 XLinkError_t XLinkProfStart()
298 glHandler->profEnable = 1;
299 glHandler->profilingData.totalReadBytes = 0;
300 glHandler->profilingData.totalWriteBytes = 0;
301 glHandler->profilingData.totalWriteTime = 0;
302 glHandler->profilingData.totalReadTime = 0;
303 glHandler->profilingData.totalBootCount = 0;
304 glHandler->profilingData.totalBootTime = 0;
306 return X_LINK_SUCCESS;
309 XLinkError_t XLinkProfStop()
311 glHandler->profEnable = 0;
312 return X_LINK_SUCCESS;
315 XLinkError_t XLinkProfPrint()
317 printf("XLink profiling results:\n");
318 if (glHandler->profilingData.totalWriteTime)
320 printf("Average write speed: %f MB/Sec\n",
321 glHandler->profilingData.totalWriteBytes /
322 glHandler->profilingData.totalWriteTime /
326 if (glHandler->profilingData.totalReadTime)
328 printf("Average read speed: %f MB/Sec\n",
329 glHandler->profilingData.totalReadBytes /
330 glHandler->profilingData.totalReadTime /
334 if (glHandler->profilingData.totalBootCount)
336 printf("Average boot speed: %f sec\n",
337 glHandler->profilingData.totalBootTime /
338 glHandler->profilingData.totalBootCount);
340 return X_LINK_SUCCESS;
343 // ------------------------------------
344 // API implementation. End.
345 // ------------------------------------
348 // ------------------------------------
349 // Helpers implementation. Begin.
350 // ------------------------------------
352 static linkId_t getNextAvailableLinkUniqueId()
354 linkId_t start = nextUniqueLinkId;
358 for (i = 0; i < MAX_LINKS; i++)
360 if (availableXLinks[i].id != INVALID_LINK_ID &&
361 availableXLinks[i].id == nextUniqueLinkId)
366 return nextUniqueLinkId;
369 if (nextUniqueLinkId == INVALID_LINK_ID)
371 nextUniqueLinkId = 0;
373 } while (start != nextUniqueLinkId);
374 mvLog(MVLOG_ERROR, "%s():- no next available unique link id!\n", __func__);
375 return INVALID_LINK_ID;
378 static xLinkDesc_t* getNextAvailableLink() {
380 for (i = 0; i < MAX_LINKS; i++) {
381 if (availableXLinks[i].id == INVALID_LINK_ID) {
387 mvLog(MVLOG_ERROR,"%s():- no next available link!\n", __func__);
391 xLinkDesc_t* link = &availableXLinks[i];
393 if (XLink_sem_init(&link->dispatcherClosedSem, 0 ,0)) {
394 mvLog(MVLOG_ERROR, "Cannot initialize semaphore\n");
403 static XLinkError_t parsePlatformError(xLinkPlatformErrorCode_t rc) {
405 case X_LINK_PLATFORM_SUCCESS:
406 return X_LINK_SUCCESS;
407 case X_LINK_PLATFORM_DEVICE_NOT_FOUND:
408 return X_LINK_DEVICE_NOT_FOUND;
409 case X_LINK_PLATFORM_TIMEOUT:
410 return X_LINK_TIMEOUT;
418 // ------------------------------------
419 // Helpers implementation. End.
420 // ------------------------------------