├── .github └── workflows │ └── .dev.workflow.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── Flags.cmake ├── Hunter │ └── config.cmake ├── HunterGate.cmake ├── XLink.cmake ├── XLinkConfig.cmake.in └── XLinkDependencies.cmake ├── examples ├── CMakeLists.txt ├── boot_bootloader.cpp ├── boot_firmware.cpp ├── device_connect_reset.cpp ├── list_devices.cpp └── search_devices.cpp ├── include └── XLink │ ├── XLink.h │ ├── XLinkDispatcher.h │ ├── XLinkDispatcherImpl.h │ ├── XLinkErrorUtils.h │ ├── XLinkLog.h │ ├── XLinkMacros.h │ ├── XLinkPlatform.h │ ├── XLinkPlatformErrorUtils.h │ ├── XLinkPrivateDefines.h │ ├── XLinkPrivateFields.h │ ├── XLinkPublicDefines.h │ ├── XLinkSemaphore.h │ ├── XLinkStream.h │ ├── XLinkStringUtils.h │ ├── XLinkTime.h │ └── XLinkVersion.h ├── src ├── pc │ ├── Android │ │ ├── ifaddrs.c │ │ └── ifaddrs.h │ ├── MacOS │ │ ├── pthread_semaphore.c │ │ └── pthread_semaphore.h │ ├── PlatformData.c │ ├── PlatformDeviceControl.c │ ├── PlatformDeviceFd.cpp │ ├── PlatformDeviceFd.h │ ├── PlatformDeviceSearch.c │ ├── PlatformDeviceSearchDynamic.cpp │ ├── ProtocolManager.cpp │ ├── Win │ │ ├── include │ │ │ ├── win_pthread.h │ │ │ ├── win_semaphore.h │ │ │ ├── win_synchapi.h │ │ │ └── win_time.h │ │ └── src │ │ │ ├── win_pthread.c │ │ │ ├── win_semaphore.c │ │ │ ├── win_synchapi.c │ │ │ ├── win_time.c │ │ │ └── win_usb_host.cpp │ └── protocols │ │ ├── pcie_host.c │ │ ├── pcie_host.h │ │ ├── tcpip_host.cpp │ │ ├── tcpip_host.h │ │ ├── usb_host.cpp │ │ ├── usb_host.h │ │ ├── usb_mx_id.cpp │ │ └── usb_mx_id.h └── shared │ ├── XLinkAssertions.cpp │ ├── XLinkData.c │ ├── XLinkDevice.c │ ├── XLinkDispatcher.c │ ├── XLinkDispatcherImpl.c │ ├── XLinkLog.c │ ├── XLinkPrivateDefines.c │ ├── XLinkPrivateFields.c │ ├── XLinkSemaphore.c │ ├── XLinkStream.c │ ├── XLinkStringUtils.c │ └── XLinkTime.cpp └── tests ├── CMakeLists.txt ├── multiple_open_stream.cpp └── multithreading_search_test.cpp /.github/workflows/.dev.workflow.yml: -------------------------------------------------------------------------------- 1 | name: Dev Workflow 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - xlink_upstream 7 | pull_request: 8 | branches-ignore: 9 | - xlink_upstream 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [macos-latest, windows-latest, ubuntu-latest] 17 | compiler: [default, clang] 18 | libusb: [ON, OFF] 19 | include: 20 | - os: windows-latest 21 | compiler: mingw 22 | libusb: ON 23 | - os: windows-latest 24 | compiler: mingw 25 | libusb: OFF 26 | 27 | steps: 28 | - uses: actions/checkout@v2 29 | with: 30 | submodules: 'recursive' 31 | 32 | - name: Install libusb 33 | if: matrix.os == 'macos-latest' && matrix.libusb == 'ON' 34 | run: | 35 | brew install libusb 36 | 37 | - name: Install libusb 38 | if: matrix.os == 'ubuntu-latest' && matrix.libusb == 'ON' 39 | run: | 40 | sudo apt-get install libusb-1.0-0-dev libusb-1.0-0 41 | 42 | - name: Setup MinGW compiler 43 | if: matrix.compiler == 'mingw' 44 | run: | 45 | choco install mingw 46 | choco upgrade mingw 47 | 48 | - name: Install Clang on macOS 49 | if: matrix.os == 'macos-latest' && matrix.compiler == 'clang' 50 | run: | 51 | brew install llvm 52 | echo "/usr/local/opt/llvm/bin" >> $GITHUB_PATH 53 | 54 | - name: Install Clang on Ubuntu 55 | if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang' 56 | run: | 57 | sudo apt-get install clang 58 | 59 | - name: Install Clang on Windows 60 | if: matrix.os == 'windows-latest' && matrix.compiler == 'clang' 61 | run: | 62 | choco install llvm 63 | echo "C:\Program Files\LLVM\bin" >> $env:GITHUB_PATH 64 | 65 | - name: Install Ninja on macOS 66 | if: matrix.os == 'macos-latest' 67 | run: | 68 | brew install ninja 69 | 70 | - name: Install Ninja on Ubuntu 71 | if: matrix.os == 'ubuntu-latest' 72 | run: | 73 | sudo apt-get install ninja-build 74 | 75 | - name: Install Ninja on Windows 76 | if: matrix.os == 'windows-latest' 77 | run: | 78 | choco install ninja 79 | 80 | - name: configure 81 | if: matrix.compiler == 'default' 82 | run: cmake . -Bbuild -DXLINK_BUILD_EXAMPLES=ON -DXLINK_BUILD_TESTS=ON -DXLINK_ENABLE_LIBUSB=${{ matrix.libusb }} 83 | 84 | - name: configure 85 | if: matrix.compiler == 'mingw' 86 | run: cmake . -Bbuild -DXLINK_BUILD_EXAMPLES=ON -DXLINK_BUILD_TESTS=ON -DXLINK_ENABLE_LIBUSB=${{ matrix.libusb }} -G"MinGW Makefiles" 87 | 88 | - name: configure 89 | if: matrix.compiler == 'clang' 90 | run: cmake . -Bbuild -DXLINK_BUILD_EXAMPLES=ON -DXLINK_BUILD_TESTS=ON -DXLINK_ENABLE_LIBUSB=${{ matrix.libusb }} -G"Ninja" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ 91 | 92 | - name: build 93 | run: cmake --build build --parallel -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | build*/ 4 | .cache* 5 | 6 | #git 7 | *.orig 8 | *_REMOTE_* 9 | *_LOCAL_* 10 | *_BACKUP_* 11 | *_BASE_* 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2018-2021 Intel Corporation 2 | # SPDX-License-Identifier: Apache-2.0 3 | # With additions of Luxonis 4 | 5 | cmake_minimum_required(VERSION 3.10) 6 | 7 | include("cmake/HunterGate.cmake") 8 | HunterGate( 9 | URL "https://github.com/cpp-pm/hunter/archive/9d9242b60d5236269f894efd3ddd60a9ca83dd7f.tar.gz" 10 | SHA1 "16cc954aa723bccd16ea45fc91a858d0c5246376" 11 | LOCAL # Local config for dependencies 12 | ) 13 | 14 | ### Constants 15 | set(TARGET_NAME "XLink") 16 | set(TARGET_PUBLIC_NAME "XLinkPublic") 17 | 18 | # Create project 19 | project(${TARGET_NAME} LANGUAGES C CXX) 20 | 21 | set(PROJECT_EXPORT_GROUP "${PROJECT_NAME}Targets") 22 | 23 | # Set default installation directory 24 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 25 | set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Installation Directory" FORCE) 26 | endif() 27 | 28 | # Compile with USB protocol capabilities 29 | option(XLINK_ENABLE_LIBUSB "Enable USB protocol which requires libusb library" ON) 30 | # Build examples 31 | option(XLINK_BUILD_EXAMPLES "Build XLink examples" OFF) 32 | # Build tests 33 | option(XLINK_BUILD_TESTS "Build XLink tests" OFF) 34 | # Debug option 35 | set(XLINK_LIBUSB_LOCAL "" CACHE STRING "Path to local libub source to use instead of Hunter") 36 | # Debug option 37 | option(XLINK_LIBUSB_SYSTEM "Use system libusb library instead of Hunter" OFF) 38 | 39 | # Specify exporting all symbols on Windows 40 | if(WIN32 AND BUILD_SHARED_LIBS) 41 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON CACHE BOOL "") 42 | endif() 43 | 44 | if(XLINK_LIBUSB_LOCAL AND XLINK_LIBUSB_SYSTEM) 45 | message(FATAL_ERROR "XLINK_LIBUSB_LOCAL and XLINK_LIBUSB_SYSTEM options are mutually exclusive!") 46 | endif() 47 | 48 | message(STATUS "Configuring XLink with the following options:") 49 | message(STATUS " XLINK_BUILD_EXAMPLES: ${XLINK_BUILD_EXAMPLES}") 50 | message(STATUS " XLINK_BUILD_TESTS: ${XLINK_BUILD_TESTS}") 51 | message(STATUS " XLINK_ENABLE_LIBUSB: ${XLINK_ENABLE_LIBUSB}") 52 | if(XLINK_ENABLE_LIBUSB) 53 | message(STATUS " XLINK_LIBUSB_LOCAL: ${XLINK_LIBUSB_LOCAL}") 54 | message(STATUS " XLINK_LIBUSB_SYSTEM: ${XLINK_LIBUSB_SYSTEM}") 55 | endif() 56 | 57 | # Include XLink sources & flags helpers 58 | include(cmake/XLink.cmake) 59 | include(cmake/Flags.cmake) 60 | 61 | # Create library target 62 | add_library(${TARGET_NAME} ${XLINK_SOURCES}) 63 | add_flag_source(src/shared/XLinkDevice.c "-Werror=switch-enum") 64 | get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) 65 | if(is_multi_config) 66 | set_target_properties(${TARGET_NAME} PROPERTIES DEBUG_POSTFIX "d") 67 | endif() 68 | # Define export header to support shared library on Windows 69 | include(GenerateExportHeader) 70 | generate_export_header(${TARGET_NAME} 71 | EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}Export.h) 72 | # Add dependencies 73 | include(cmake/XLinkDependencies.cmake) 74 | 75 | if(XLINK_ENABLE_LIBUSB) 76 | if(XLINK_LIBUSB_SYSTEM) 77 | # Find system libusb 78 | find_path(LIBUSB_INCLUDE_DIR NAMES "libusb-1.0/libusb.h") 79 | find_library(LIBUSB_LIBRARY NAMES usb-1.0 PATH_SUFFIXES "lib") 80 | if(NOT LIBUSB_INCLUDE_DIR OR NOT LIBUSB_LIBRARY) 81 | message(FATAL_ERROR "libusb is required") 82 | endif() 83 | target_include_directories(${TARGET_NAME} 84 | PRIVATE "${LIBUSB_INCLUDE_DIR}" 85 | ) 86 | target_link_libraries(${TARGET_NAME} 87 | PUBLIC ${LIBUSB_LIBRARY} 88 | ) 89 | else() 90 | # Link to CMake libusb 91 | target_link_libraries(${TARGET_NAME} PRIVATE usb-1.0) 92 | if(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 93 | target_link_libraries(${TARGET_NAME} PRIVATE delayimp.lib) 94 | # workaround https://gitlab.kitware.com/cmake/cmake/-/issues/20022 95 | target_link_options(${TARGET_NAME} PUBLIC "$:d>.dll>") 96 | endif() 97 | endif() 98 | 99 | if(WIN32 AND NOT MINGW) 100 | target_link_libraries(${TARGET_NAME} PRIVATE Pathcch.lib) 101 | endif() 102 | 103 | # Add compile define stating a local libusb usage 104 | if(XLINK_LIBUSB_LOCAL) 105 | target_compile_definitions(${TARGET_NAME} PRIVATE XLINK_LIBUSB_LOCAL) 106 | endif() 107 | 108 | # Add compile define stating libusb is enabled 109 | target_compile_definitions(${TARGET_NAME} PRIVATE XLINK_ENABLE_LIBUSB) 110 | endif() 111 | 112 | if(WIN32) 113 | target_compile_definitions(${TARGET_NAME} PRIVATE WIN32_LEAN_AND_MEAN) 114 | else() 115 | find_package(Threads REQUIRED) 116 | target_link_libraries(${TARGET_NAME} PRIVATE Threads::Threads) 117 | endif() 118 | 119 | if(MINGW) 120 | target_link_libraries(${TARGET_NAME} 121 | PUBLIC 122 | libwinusb.a 123 | libsetupapi.a 124 | ws2_32 125 | Iphlpapi.lib 126 | ) 127 | endif() 128 | 129 | if(ANDROID) 130 | find_library(log-lib log) 131 | target_link_libraries(${TARGET_NAME} PRIVATE ${log-lib}) 132 | endif() 133 | 134 | # Create public "interface" library (no linking) 135 | add_library(${TARGET_PUBLIC_NAME} INTERFACE) 136 | target_include_directories(${TARGET_PUBLIC_NAME} INTERFACE 137 | "$" 138 | "$" 139 | "$" 140 | ) 141 | 142 | # Link to headers (public, as itself also needs the headers) 143 | target_link_libraries(${TARGET_NAME} PUBLIC ${TARGET_PUBLIC_NAME}) 144 | 145 | target_include_directories(${TARGET_NAME} 146 | PRIVATE 147 | ${XLINK_PLATFORM_INCLUDE} 148 | ${XLINK_PRIVATE_INCLUDE} 149 | ${XLINK_INCLUDE}/XLink 150 | ) 151 | 152 | target_compile_definitions(${TARGET_NAME} 153 | PRIVATE 154 | HAVE_STRUCT_TIMESPEC 155 | _CRT_SECURE_NO_WARNINGS 156 | USE_USB_VSC 157 | USE_TCP_IP 158 | ) 159 | 160 | if (ENABLE_MYRIAD_NO_BOOT) 161 | target_compile_definitions(${TARGET_NAME} 162 | PRIVATE 163 | NO_BOOT) 164 | endif() 165 | 166 | # Set C99 standard 167 | set_property(TARGET ${TARGET_NAME} PROPERTY C_STANDARD 99) 168 | # Set compiler features (c++11), and disables extensions (g++11) 169 | set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD 11) 170 | set_property(TARGET ${TARGET_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) 171 | set_property(TARGET ${TARGET_NAME} PROPERTY CXX_EXTENSIONS OFF) 172 | # Add interface transitive property (C++11) to public library 173 | if(${CMAKE_VERSION} VERSION_LESS "3.8.0") 174 | target_compile_features(${TARGET_PUBLIC_NAME} INTERFACE cxx_range_for) 175 | else() 176 | target_compile_features(${TARGET_PUBLIC_NAME} INTERFACE cxx_std_11) 177 | endif() 178 | 179 | # Add flags 180 | add_default_flags(${TARGET_NAME}) 181 | 182 | # Check if pthread_getname_np exists 183 | if(NOT WIN32) 184 | include(CheckSymbolExists) 185 | set(_TMP_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") 186 | set(_TMP_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") 187 | set(_TMP_CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 188 | list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) 189 | list(APPEND CMAKE_REQUIRED_LIBRARIES "-lpthread") 190 | # This flag breaks check_symbol_exists() 191 | string(REPLACE " -Werror " " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 192 | 193 | # perfom check for pthread_getname_np symbol 194 | check_symbol_exists(pthread_getname_np pthread.h HAVE_PTHREAD_GETNAME_NP) 195 | 196 | set(CMAKE_REQUIRED_DEFINITIONS "${_TMP_CMAKE_REQUIRED_DEFINITIONS}") 197 | set(CMAKE_REQUIRED_LIBRARIES "${_TMP_CMAKE_REQUIRED_LIBRARIES}") 198 | set(CMAKE_C_FLAGS "${_TMP_CMAKE_C_FLAGS}") 199 | unset(_TMP_CMAKE_REQUIRED_DEFINITIONS) 200 | unset(_TMP_CMAKE_REQUIRED_LIBRARIES) 201 | unset(_TMP_CMAKE_C_FLAGS) 202 | 203 | # Set the define 204 | if(HAVE_PTHREAD_GETNAME_NP) 205 | target_compile_definitions(${TARGET_NAME} PRIVATE HAVE_PTHREAD_GETNAME_NP) 206 | endif() 207 | endif() 208 | 209 | # Examples 210 | if(XLINK_BUILD_EXAMPLES) 211 | add_subdirectory(examples) 212 | endif() 213 | 214 | # Tests 215 | if(XLINK_BUILD_TESTS) 216 | add_subdirectory(tests) 217 | endif() 218 | 219 | # Installation 220 | 221 | include(GNUInstallDirs) 222 | 223 | # Export targets (capability to import current build directory) 224 | export(TARGETS ${TARGET_NAME} ${TARGET_PUBLIC_NAME} FILE "${PROJECT_NAME}Targets.cmake") 225 | 226 | # Dependencies file 227 | configure_file("cmake/${PROJECT_NAME}Dependencies.cmake" ${PROJECT_NAME}Dependencies.cmake COPYONLY) 228 | 229 | # Configure config file (one for exporting build directory, one for installation) 230 | if(${HUNTER_INSTALL_PREFIX}) 231 | file(RELATIVE_PATH XLINK_DEPENDENCIES_INSTALLATION_PATH_REL "${CMAKE_CURRENT_BINARY_DIR}" "${HUNTER_INSTALL_PREFIX}") 232 | endif() 233 | 234 | configure_file(cmake/${PROJECT_NAME}Config.cmake.in ${PROJECT_NAME}Config.cmake @ONLY) 235 | 236 | # Config for installation 237 | set(XLINK_DEPENDENCIES_INSTALLATION_PATH_REL "./dependencies") 238 | configure_file(cmake/${PROJECT_NAME}Config.cmake.in _install/${PROJECT_NAME}Config.cmake @ONLY) 239 | 240 | # Install targets 241 | install( 242 | TARGETS ${TARGET_NAME} ${TARGET_PUBLIC_NAME} 243 | EXPORT ${PROJECT_EXPORT_GROUP} 244 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 245 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" 246 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" 247 | ) 248 | #Install include folder 249 | install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 250 | # Install generated export header 251 | install( 252 | FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}Export.h 253 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/XLink 254 | ) 255 | 256 | # Install Hunter dependencies 257 | if(XLINK_ENABLE_LIBUSB) 258 | if(NOT XLINK_LIBUSB_LOCAL AND NOT XLINK_LIBUSB_SYSTEM) 259 | install(DIRECTORY "${HUNTER_INSTALL_PREFIX}/" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/dependencies") 260 | endif() 261 | endif() 262 | # Install export group (information about targets) 263 | install(EXPORT ${PROJECT_EXPORT_GROUP} 264 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 265 | ) 266 | # Install CMake specific files 267 | install(FILES 268 | "${CMAKE_CURRENT_BINARY_DIR}/_install/${PROJECT_NAME}Config.cmake" 269 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Dependencies.cmake" 270 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" 271 | ) 272 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XLink 2 | 3 | This is a "fork" of a library that used to be openvino repositories third party dependency - XLink. The original library was removed from openvino repositories in https://github.com/openvinotoolkit/openvino/pull/15131 . 4 | 5 | # Changes 6 | Some tweaks to CMake files to enable installation of this target and being able to be used with Hunter package manager 7 | -------------------------------------------------------------------------------- /cmake/Flags.cmake: -------------------------------------------------------------------------------- 1 | ## setup compilation flags 2 | # conditionally applies flag. If flag is supported by current compiler, it will be added to compile options. 3 | include(CheckCCompilerFlag) 4 | function(add_flag target flag) 5 | check_c_compiler_flag(${flag} FLAG_${flag}) 6 | if (FLAG_${flag} EQUAL 1) 7 | target_compile_options(${target} PRIVATE $<$:${flag}>) 8 | endif () 9 | endfunction() 10 | 11 | function(add_flag_source source flag) 12 | check_c_compiler_flag(${flag} FLAG_${flag}) 13 | if (FLAG_${flag} EQUAL 1) 14 | set_source_files_properties(${source} PROPERTIES COMPILE_FLAGS "-Werror=switch-enum") 15 | endif () 16 | endfunction() 17 | 18 | function(add_default_flags target) 19 | if ("${CMAKE_C_COMPILER_ID}" MATCHES "^(AppleClang|Clang|GNU)$") 20 | # enable those flags 21 | # add_flag(${target} -Woverloaded-virtual) # warn if you overload (not override) a virtual function 22 | add_flag(${target} -Wformat=2) # warn on security issues around functions that format output (ie printf) 23 | add_flag(${target} -Wmisleading-indentation) # (only in GCC >= 6.0) warn if indentation implies blocks where blocks do not exist 24 | add_flag(${target} -Wduplicated-cond) # (only in GCC >= 6.0) warn if if / else chain has duplicated conditions 25 | add_flag(${target} -Wduplicated-branches) # (only in GCC >= 7.0) warn if if / else branches have duplicated code 26 | add_flag(${target} -Wnull-dereference) # (only in GCC >= 6.0) warn if a null dereference is detected 27 | add_flag(${target} -Wsign-compare) 28 | add_flag(${target} -Wtype-limits) # size_t - size_t >= 0 -> always true 29 | 30 | # disable those flags 31 | add_flag(${target} -Wno-unused-command-line-argument) # clang: warning: argument unused during compilation: '--coverage' [-Wunused-command-line-argument] 32 | add_flag(${target} -Wno-unused-parameter) # prints too many useless warnings 33 | add_flag(${target} -Wno-format-nonliteral) # prints way too many warnings from spdlog 34 | add_flag(${target} -Wno-gnu-zero-variadic-macro-arguments) # https://stackoverflow.com/questions/21266380/is-the-gnu-zero-variadic-macro-arguments-safe-to-ignore 35 | 36 | # promote to errors 37 | add_flag(${target} -Werror=self-assign-field) # error if self assign - bugprone 38 | add_flag(${target} -Werror=unused-lambda-capture) # error if lambda capture is unused 39 | add_flag(${target} -Werror=return-type) # warning: control reaches end of non-void function [-Wreturn-type] 40 | # add_flag(${target} -Werror=non-virtual-dtor) # warn the user if a class with virtual functions has a non-virtual destructor. This helps catch hard to track down memory errors 41 | add_flag(${target} -Werror=sign-compare) # warn the user if they compare a signed and unsigned numbers 42 | # add_flag(${target} -Werror=reorder) # field '$1' will be initialized after field '$2' 43 | 44 | elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") 45 | # using Visual Studio C++ 46 | # TODO(warchant): add flags https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md#msvc 47 | endif() 48 | 49 | endfunction() -------------------------------------------------------------------------------- /cmake/Hunter/config.cmake: -------------------------------------------------------------------------------- 1 | # libusb without udev 2 | hunter_config( 3 | libusb-luxonis 4 | VERSION "1.0.24-cmake" 5 | URL "https://github.com/luxonis/libusb/archive/b7e4548958325b18feb73977163ad44398099534.tar.gz" 6 | SHA1 "2d79573d57628fe56d2868d2f6ce756d40906cf4" 7 | CMAKE_ARGS 8 | WITH_UDEV=OFF 9 | # Build shared libs by default to not cause licensing issues 10 | BUILD_SHARED_LIBS=ON 11 | ) 12 | -------------------------------------------------------------------------------- /cmake/XLink.cmake: -------------------------------------------------------------------------------- 1 | set(XLINK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../) 2 | 3 | set(XLINK_INCLUDE ${XLINK_ROOT_DIR}/include) 4 | 5 | set(XLINK_PRIVATE_INCLUDE ${XLINK_ROOT_DIR}/src/pc/protocols) 6 | 7 | file(GLOB PC_SRC "${XLINK_ROOT_DIR}/src/pc/*.c") 8 | file(GLOB PC_SRC_CPP "${XLINK_ROOT_DIR}/src/pc/*.cpp") 9 | file(GLOB PC_PROTO_SRC "${XLINK_ROOT_DIR}/src/pc/protocols/*.c") 10 | file(GLOB PC_PROTO_SRC_CPP "${XLINK_ROOT_DIR}/src/pc/protocols/*.cpp") 11 | file(GLOB_RECURSE SHARED_SRC "${XLINK_ROOT_DIR}/src/shared/*.c") 12 | file(GLOB_RECURSE SHARED_SRC_CPP "${XLINK_ROOT_DIR}/src/shared/*.cpp") 13 | 14 | list(APPEND XLINK_SOURCES ${PC_SRC} ${PC_SRC_CPP} ${PC_PROTO_SRC} ${PC_PROTO_SRC_CPP} ${SHARED_SRC} ${SHARED_SRC_CPP}) 15 | 16 | if(WIN32) 17 | set(XLINK_PLATFORM_INCLUDE ${XLINK_ROOT_DIR}/src/pc/Win/include) 18 | 19 | file(GLOB XLINK_PLATFORM_SRC "${XLINK_ROOT_DIR}/src/pc/Win/src/*.c") 20 | file(GLOB XLINK_PLATFORM_SRC_CPP "${XLINK_ROOT_DIR}/src/pc/Win/src/*.cpp") 21 | list(APPEND XLINK_SOURCES ${XLINK_PLATFORM_SRC} ${XLINK_PLATFORM_SRC_CPP}) 22 | endif() 23 | 24 | if(APPLE) 25 | set(XLINK_PLATFORM_INCLUDE "${XLINK_ROOT_DIR}/src/pc/MacOS" ) 26 | list(APPEND XLINK_SOURCES "${XLINK_ROOT_DIR}/src/pc/MacOS/pthread_semaphore.c") 27 | endif() 28 | 29 | # Provides custom getifaddrs if platform is less than 24 30 | if(ANDROID AND ANDROID_PLATFORM LESS 24) 31 | set(XLINK_PLATFORM_INCLUDE "${XLINK_ROOT_DIR}/src/pc/Android") 32 | list(APPEND XLINK_SOURCES "${XLINK_ROOT_DIR}/src/pc/Android/ifaddrs.c") 33 | endif() 34 | 35 | # Remove USB protocol if specified 36 | if(NOT XLINK_ENABLE_LIBUSB) 37 | list(REMOVE_ITEM XLINK_SOURCES 38 | "${XLINK_ROOT_DIR}/src/pc/protocols/usb_host.cpp" 39 | "${XLINK_ROOT_DIR}/src/pc/Win/src/win_usb_host.cpp" 40 | ) 41 | # message(FATAL_ERROR "Sources: ${XLINK_SOURCES}") 42 | endif() 43 | 44 | -------------------------------------------------------------------------------- /cmake/XLinkConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Get whether library was build as shared or not 2 | set(XLINK_SHARED_LIBS @BUILD_SHARED_LIBS@) 3 | 4 | # Get library options 5 | set(XLINK_ENABLE_LIBUSB @XLINK_ENABLE_LIBUSB@) 6 | set(XLINK_LIBUSB_LOCAL @XLINK_LIBUSB_LOCAL@) 7 | set(XLINK_LIBUSB_SYSTEM @XLINK_LIBUSB_SYSTEM@) 8 | 9 | # Specify that this is config mode (Called by find_package) 10 | set(CONFIG_MODE TRUE) 11 | 12 | # Compute the installation prefix relative to this file. 13 | set(_IMPORT_PREFIX "@XLINK_DEPENDENCIES_INSTALLATION_PATH_REL@") 14 | 15 | # Add dependencies file 16 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Dependencies.cmake") 17 | 18 | # Add the targets file 19 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_EXPORT_GROUP@.cmake") 20 | 21 | # Cleanup 22 | set(_IMPORT_PREFIX) 23 | -------------------------------------------------------------------------------- /cmake/XLinkDependencies.cmake: -------------------------------------------------------------------------------- 1 | if(CONFIG_MODE) 2 | set(_CMAKE_PREFIX_PATH_ORIGINAL ${CMAKE_PREFIX_PATH}) 3 | set(_CMAKE_FIND_ROOT_PATH_MODE_PACKAGE_ORIGINAL ${CMAKE_FIND_ROOT_PATH_MODE_PACKAGE}) 4 | # Fixes Android NDK build, where prefix path is ignored as its not inside sysroot 5 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE "BOTH") 6 | set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_LIST_DIR}/${_IMPORT_PREFIX}" ${CMAKE_PREFIX_PATH}) 7 | set(_QUIET "QUIET") 8 | else() 9 | # set(XLINK_SHARED_LIBS ${BUILD_SHARED_LIBS}) 10 | if(XLINK_ENABLE_LIBUSB) 11 | if(NOT XLINK_LIBUSB_LOCAL AND NOT XLINK_LIBUSB_SYSTEM) 12 | hunter_add_package(libusb-luxonis) 13 | endif() 14 | endif() 15 | endif() 16 | 17 | # libusb 18 | if(XLINK_ENABLE_LIBUSB) 19 | if(XLINK_LIBUSB_LOCAL) 20 | add_subdirectory("${XLINK_LIBUSB_LOCAL}" "${CMAKE_CURRENT_BINARY_DIR}/libusb" EXCLUDE_FROM_ALL) 21 | elseif(NOT XLINK_LIBUSB_SYSTEM) 22 | find_package(usb-1.0 ${_QUIET} CONFIG REQUIRED HINTS "${CMAKE_CURRENT_LIST_DIR}/libusb") 23 | endif() 24 | endif() 25 | 26 | # Add threads (c++) 27 | find_package(Threads ${_QUIET} REQUIRED) 28 | 29 | # include optional dependency cmake 30 | if(XLINK_DEPENDENCY_INCLUDE) 31 | include(${XLINK_DEPENDENCY_INCLUDE} OPTIONAL) 32 | endif() 33 | 34 | # Cleanup 35 | if(CONFIG_MODE) 36 | set(CMAKE_PREFIX_PATH ${_CMAKE_PREFIX_PATH_ORIGINAL}) 37 | set(_CMAKE_PREFIX_PATH_ORIGINAL) 38 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ${_CMAKE_FIND_ROOT_PATH_MODE_PACKAGE_ORIGINAL}) 39 | set(_CMAKE_FIND_ROOT_PATH_MODE_PACKAGE_ORIGINAL) 40 | set(_QUIET) 41 | else() 42 | set(XLINK_SHARED_LIBS) 43 | endif() 44 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Helper 'add_example' 2 | macro(add_example example_name example_src) 3 | add_executable(${example_name} ${example_src}) 4 | target_link_libraries(${example_name} ${TARGET_NAME}) 5 | set_property(TARGET ${example_name} PROPERTY CXX_STANDARD 11) 6 | set_property(TARGET ${example_name} PROPERTY CXX_STANDARD_REQUIRED ON) 7 | set_property(TARGET ${example_name} PROPERTY CXX_EXTENSIONS OFF) 8 | 9 | # Copy over required DLLs (Windows) 10 | if(WIN32) 11 | # Copy dlls to target directory - Windows only 12 | # TARGET_RUNTIME_DLLS generator expression available since CMake 3.21 13 | if(CMAKE_VERSION VERSION_LESS "3.21") 14 | message(WARNING "Automatic DLL copying not available") 15 | else() 16 | set(depthai_dll_libraries "$") 17 | add_custom_command(TARGET ${example_name} POST_BUILD COMMAND 18 | "$<$:${CMAKE_COMMAND};-E;copy_if_different;${depthai_dll_libraries};$>" 19 | COMMAND_EXPAND_LISTS 20 | VERBATIM 21 | ) 22 | endif() 23 | endif() 24 | endmacro() 25 | 26 | # Examples 27 | 28 | # List devices 29 | add_example(list_devices list_devices.cpp) 30 | 31 | # Search devices 32 | add_example(search_devices search_devices.cpp) 33 | 34 | # Boot bootloader 35 | add_example(boot_bootloader boot_bootloader.cpp) 36 | 37 | # Boot firmware 38 | add_example(boot_firmware boot_firmware.cpp) 39 | 40 | # Boot firmware 41 | add_example(device_connect_reset device_connect_reset.cpp) 42 | -------------------------------------------------------------------------------- /examples/boot_bootloader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "XLink/XLink.h" 8 | #include "XLink/XLinkPublicDefines.h" 9 | #include "XLink/XLinkLog.h" 10 | 11 | XLinkGlobalHandler_t xlinkGlobalHandler = {}; 12 | 13 | int main(){ 14 | 15 | // Initialize and suppress XLink logs 16 | mvLogDefaultLevelSet(MVLOG_LAST); 17 | auto status = XLinkInitialize(&xlinkGlobalHandler); 18 | if(X_LINK_SUCCESS != status) { 19 | throw std::runtime_error("Couldn't initialize XLink"); 20 | } 21 | 22 | // Get all flash booted devices 23 | unsigned int numdev = 0; 24 | std::array deviceDescAll = {}; 25 | deviceDesc_t suitableDevice = {}; 26 | suitableDevice.protocol = X_LINK_ANY_PROTOCOL; 27 | suitableDevice.platform = X_LINK_ANY_PLATFORM; 28 | suitableDevice.state = X_LINK_FLASH_BOOTED; 29 | 30 | status = XLinkFindAllSuitableDevices(suitableDevice, deviceDescAll.data(), deviceDescAll.size(), &numdev); 31 | if(status != X_LINK_SUCCESS) throw std::runtime_error("Couldn't retrieve all connected devices"); 32 | 33 | if(numdev == 0){ 34 | std::cout << "No " << XLinkDeviceStateToStr(X_LINK_FLASH_BOOTED) << " devices found to reset" << std::endl; 35 | return 0; 36 | } 37 | 38 | for(unsigned i = 0; i < numdev; i++) { 39 | std::cout << "Resetting " << deviceDescAll.at(i).name << " ..." << std::endl; 40 | XLinkBootBootloader(&deviceDescAll.at(i)); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /examples/boot_firmware.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "XLink/XLink.h" 8 | #include "XLink/XLinkPublicDefines.h" 9 | #include "XLink/XLinkLog.h" 10 | 11 | XLinkGlobalHandler_t xlinkGlobalHandler = {}; 12 | 13 | int main(int argc, const char** argv){ 14 | 15 | if(argc < 2) { 16 | std::cout << "Usage: " << argv[0] << " path/to/cmd\n"; 17 | return 0; 18 | } 19 | 20 | // Initialize and suppress XLink logs 21 | mvLogDefaultLevelSet(MVLOG_LAST); 22 | auto status = XLinkInitialize(&xlinkGlobalHandler); 23 | if(X_LINK_SUCCESS != status) { 24 | throw std::runtime_error("Couldn't initialize XLink"); 25 | } 26 | 27 | // Get all flash booted devices 28 | unsigned int numdev = 0; 29 | std::array deviceDescAll = {}; 30 | deviceDesc_t suitableDevice = {}; 31 | suitableDevice.protocol = X_LINK_ANY_PROTOCOL; 32 | suitableDevice.platform = X_LINK_ANY_PLATFORM; 33 | suitableDevice.state = X_LINK_UNBOOTED; 34 | 35 | status = XLinkFindAllSuitableDevices(suitableDevice, deviceDescAll.data(), deviceDescAll.size(), &numdev); 36 | if(status != X_LINK_SUCCESS) throw std::runtime_error("Couldn't retrieve all connected devices"); 37 | 38 | if(numdev == 0){ 39 | std::cout << "No " << XLinkDeviceStateToStr(X_LINK_UNBOOTED) << " devices found to boot" << std::endl; 40 | return 0; 41 | } 42 | 43 | for(unsigned i = 0; i < numdev; i++) { 44 | std::cout << "Booting: " << deviceDescAll.at(i).name << " with: " << argv[1] << std::endl; 45 | XLinkBoot(&deviceDescAll.at(i), argv[1]); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /examples/device_connect_reset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char** argv) { 13 | 14 | XLinkGlobalHandler_t gHandler; 15 | XLinkInitialize(&gHandler); 16 | 17 | if(argc <= 1) { 18 | printf("Usage: %s [usb/ip]\n", argv[0]); 19 | return 1; 20 | } 21 | 22 | // Search for booted device 23 | deviceDesc_t deviceDesc; 24 | strncpy(deviceDesc.name, argv[1], sizeof(deviceDesc.name)); 25 | deviceDesc.nameHintOnly = false; 26 | 27 | std::string name(argv[1]); 28 | XLinkProtocol_t protocol = X_LINK_USB_VSC; 29 | for(const char& c : name) { 30 | if(c == '.') { 31 | protocol = X_LINK_TCP_IP; 32 | } 33 | } 34 | 35 | printf("Connecting to device name: %s, protocol: %s\n", deviceDesc.name, XLinkProtocolToStr(protocol)); 36 | 37 | XLinkHandler_t handler; 38 | handler.devicePath = deviceDesc.name; 39 | handler.protocol = protocol; 40 | if(XLinkConnect(&handler) != X_LINK_SUCCESS) { 41 | printf("Couldn't connect to the device\n"); 42 | return -1; 43 | } 44 | 45 | // Wait 1s 46 | std::this_thread::sleep_for(std::chrono::seconds(1)); 47 | 48 | // Reset the device 49 | XLinkResetRemote(handler.linkId); 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /examples/list_devices.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "XLink/XLink.h" 8 | #include "XLink/XLinkPublicDefines.h" 9 | #include "XLink/XLinkLog.h" 10 | 11 | XLinkGlobalHandler_t xlinkGlobalHandler = {}; 12 | 13 | int main(){ 14 | 15 | mvLogDefaultLevelSet(MVLOG_WARN); 16 | auto status = XLinkInitialize(&xlinkGlobalHandler); 17 | if(X_LINK_SUCCESS != status) { 18 | throw std::runtime_error("Couldn't initialize XLink"); 19 | } 20 | 21 | XLinkDeviceState_t state = X_LINK_ANY_STATE; 22 | 23 | // Get all available devices 24 | unsigned int numdev = 0; 25 | std::array deviceDescAll = {}; 26 | deviceDesc_t suitableDevice = {}; 27 | suitableDevice.protocol = X_LINK_ANY_PROTOCOL; 28 | suitableDevice.platform = X_LINK_ANY_PLATFORM; 29 | 30 | status = XLinkFindAllSuitableDevices(suitableDevice, deviceDescAll.data(), deviceDescAll.size(), &numdev); 31 | if(status != X_LINK_SUCCESS) throw std::runtime_error("Couldn't retrieve all connected devices"); 32 | 33 | // Print device details 34 | for(int i = 0; i < numdev; i++){ 35 | const auto& dev = deviceDescAll[i]; 36 | std::cout << "status: " << XLinkErrorToStr(dev.status); 37 | std::cout << ", name: " << dev.name; 38 | std::cout << ", mxid: " << dev.mxid; 39 | std::cout << ", state: " << XLinkDeviceStateToStr(dev.state); 40 | std::cout << ", protocol: " << XLinkProtocolToStr(dev.protocol); 41 | std::cout << ", platform: " << XLinkPlatformToStr(dev.platform); 42 | std::cout << std::endl; 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /examples/search_devices.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "XLink/XLink.h" 8 | #include "XLink/XLinkPublicDefines.h" 9 | #include "XLink/XLinkLog.h" 10 | 11 | XLinkGlobalHandler_t xlinkGlobalHandler = {}; 12 | 13 | int main(){ 14 | 15 | mvLogDefaultLevelSet(MVLOG_WARN); 16 | auto status = XLinkInitialize(&xlinkGlobalHandler); 17 | if(X_LINK_SUCCESS != status) { 18 | throw std::runtime_error("Couldn't initialize XLink"); 19 | } 20 | 21 | XLinkDeviceState_t state = X_LINK_ANY_STATE; 22 | 23 | // Get all available devices 24 | unsigned int numdev = 0; 25 | std::array deviceDescAll = {}; 26 | deviceDesc_t suitableDevice = {}; 27 | suitableDevice.protocol = X_LINK_ANY_PROTOCOL; 28 | suitableDevice.platform = X_LINK_ANY_PLATFORM; 29 | 30 | status = XLinkSearchForDevices(suitableDevice, deviceDescAll.data(), deviceDescAll.size(), &numdev, 1000, [](deviceDesc_t* devs, unsigned numdev){ 31 | // Print device details 32 | for(int i = 0; i < numdev; i++){ 33 | const auto& dev = devs[i]; 34 | std::cout << "status: " << XLinkErrorToStr(dev.status); 35 | std::cout << ", name: " << dev.name; 36 | std::cout << ", mxid: " << dev.mxid; 37 | std::cout << ", state: " << XLinkDeviceStateToStr(dev.state); 38 | std::cout << ", protocol: " << XLinkProtocolToStr(dev.protocol); 39 | std::cout << ", platform: " << XLinkPlatformToStr(dev.platform); 40 | std::cout << std::endl; 41 | } 42 | std::cout << std::endl; 43 | 44 | // keep searching till timeout 45 | return false; 46 | }); 47 | if(status != X_LINK_SUCCESS && status != X_LINK_TIMEOUT) throw std::runtime_error("Couldn't retrieve all connected devices"); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /include/XLink/XLinkDispatcher.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @file 7 | /// 8 | /// @brief Application configuration Leon header 9 | /// 10 | #ifndef _XLINKDISPATCHER_H 11 | #define _XLINKDISPATCHER_H 12 | 13 | #include "XLinkPrivateDefines.h" 14 | #include "time.h" 15 | 16 | #ifdef __cplusplus 17 | extern "C" 18 | { 19 | #endif 20 | typedef int (*getRespFunction) (xLinkEvent_t*, 21 | xLinkEvent_t*); 22 | typedef struct { 23 | int (*eventSend) (xLinkEvent_t*); 24 | int (*eventReceive) (xLinkEvent_t*); 25 | getRespFunction localGetResponse; 26 | getRespFunction remoteGetResponse; 27 | void (*closeLink) (void* fd, int fullClose); 28 | void (*closeDeviceFd) (xLinkDeviceHandle_t* deviceHandle); 29 | } DispatcherControlFunctions; 30 | 31 | XLinkError_t DispatcherInitialize(DispatcherControlFunctions *controlFunc); 32 | XLinkError_t DispatcherStart(xLinkDeviceHandle_t *deviceHandle); 33 | int DispatcherClean(xLinkDeviceHandle_t *deviceHandle); 34 | int DispatcherDeviceFdDown(xLinkDeviceHandle_t *deviceHandle); 35 | 36 | xLinkEvent_t* DispatcherAddEvent(xLinkEventOrigin_t origin, xLinkEvent_t *event); 37 | int DispatcherWaitEventComplete(xLinkDeviceHandle_t *deviceHandle, unsigned int timeoutMs); 38 | int DispatcherWaitEventCompleteTimeout(xLinkDeviceHandle_t *deviceHandle, struct timespec abstime); 39 | 40 | char* TypeToStr(int type); 41 | int DispatcherUnblockEvent(eventId_t id, 42 | xLinkEventType_t type, 43 | streamId_t stream, 44 | void *xlinkFD); 45 | int DispatcherServeEvent(eventId_t id, 46 | xLinkEventType_t type, 47 | streamId_t stream, 48 | void *xlinkFD); 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif -------------------------------------------------------------------------------- /include/XLink/XLinkDispatcherImpl.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef _XLINKDISPATCHERIMPL_H 6 | #define _XLINKDISPATCHERIMPL_H 7 | 8 | #include "XLinkPrivateDefines.h" 9 | 10 | int dispatcherEventSend (xLinkEvent_t*); 11 | int dispatcherEventReceive (xLinkEvent_t*); 12 | int dispatcherLocalEventGetResponse (xLinkEvent_t*, 13 | xLinkEvent_t*); 14 | int dispatcherRemoteEventGetResponse (xLinkEvent_t*, 15 | xLinkEvent_t*); 16 | void dispatcherCloseLink (void* fd, int fullClose); 17 | void dispatcherCloseDeviceFd (xLinkDeviceHandle_t* deviceHandle); 18 | 19 | #endif //_XLINKDISPATCHERIMPL_H 20 | -------------------------------------------------------------------------------- /include/XLink/XLinkErrorUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef _XLINK_TOOL_H 6 | #define _XLINK_TOOL_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | #if 1 // Release configuration 14 | 15 | #ifndef ASSERT_XLINK 16 | #define ASSERT_XLINK(condition) do { \ 17 | if(!(condition)) { \ 18 | mvLog(MVLOG_ERROR, "Assertion Failed: %s \n", #condition); \ 19 | return X_LINK_ERROR; \ 20 | } \ 21 | } while(0) 22 | #endif // ASSERT_XLINK 23 | 24 | #else // Debug configuration 25 | 26 | #ifndef ASSERT_XLINK 27 | #define ASSERT_XLINK(condition) do { \ 28 | if(!(condition)) { \ 29 | mvLog(MVLOG_ERROR, "Assertion Failed: %s \n", #condition); \ 30 | exit(EXIT_FAILURE); \ 31 | } \ 32 | } while(0) 33 | #endif // ASSERT_XLINK 34 | 35 | #endif // NDEBUG 36 | 37 | 38 | //-------------------------------------------------------------------- 39 | //----- Check an expression and return error if needed. Begin. ------- 40 | //-------------------------------------------------------------------- 41 | 42 | //----------------- Check any condition. --------------------- 43 | 44 | #ifndef XLINK_RET_ERR_IF 45 | #define XLINK_RET_ERR_IF(condition, err) do { \ 46 | if ((condition)) { \ 47 | mvLog(MVLOG_ERROR, "Condition failed: %s", #condition);\ 48 | return (err); \ 49 | } \ 50 | } while(0) 51 | #endif // XLINK_RET_ERR_IF 52 | 53 | #ifndef XLINK_RET_IF 54 | #define XLINK_RET_IF(condition) do { \ 55 | \ 56 | XLINK_RET_ERR_IF((condition), X_LINK_ERROR);\ 57 | \ 58 | } while(0) 59 | #endif // XLINK_RET_IF 60 | 61 | //------------ Check method's return value. ------------------ 62 | 63 | #ifndef XLINK_RET_IF_FAIL 64 | #define XLINK_RET_IF_FAIL(call) do { \ 65 | int rc; \ 66 | if ((rc = (call))) { \ 67 | mvLog(MVLOG_ERROR, " %s method call failed with an error: %d", #call, rc); \ 68 | return rc; \ 69 | } \ 70 | } while(0) 71 | #endif // XLINK_RET_IF_FAIL 72 | 73 | 74 | //------------------------------------------------------------- 75 | //------- Check an expression and goto out if needed. --------- 76 | //------------------------------------------------------------- 77 | 78 | #ifndef XLINK_OUT_WITH_LOG_IF 79 | #define XLINK_OUT_WITH_LOG_IF(condition, log) do { \ 80 | if ((condition)) { \ 81 | (log); \ 82 | goto XLINK_OUT; \ 83 | } \ 84 | } while(0) 85 | #endif // XLINK_OUT_WITH_LOG_IF 86 | 87 | #ifndef XLINK_OUT_IF 88 | #define XLINK_OUT_IF(condition) do { \ 89 | \ 90 | XLINK_OUT_WITH_LOG_IF((condition), \ 91 | mvLog(MVLOG_ERROR, "Condition failed: %s \n", #condition));\ 92 | \ 93 | } while(0) 94 | #endif // XLINK_OUT_IF 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif //_XLINK_TOOL_H 101 | -------------------------------------------------------------------------------- /include/XLink/XLinkLog.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2020 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /* 6 | * Add logging capabilities over simple printf. 7 | * Allows 5 different logging levels: 8 | * 9 | * MVLOG_DEBUG = 0 10 | * MVLOG_INFO = 1 11 | * MVLOG_WARN = 2 12 | * MVLOG_ERROR = 3 13 | * MVLOG_FATAL = 4 14 | * Before including header, a unit name can be set, otherwise defaults to global. eg: 15 | * 16 | * #define MVLOG_UNIT_NAME unitname 17 | * #include 18 | * Setting log level through debugger can be done in the following way: 19 | * mset mvLogLevel_unitname 2 20 | * Will set log level to warnings and above 21 | */ 22 | #ifndef MVLOG_H__ 23 | #define MVLOG_H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "XLinkExport.h" 34 | 35 | #ifndef _GNU_SOURCE 36 | #define _GNU_SOURCE 37 | #endif 38 | 39 | 40 | typedef enum mvLog_t{ 41 | MVLOG_DEBUG = 0, 42 | MVLOG_INFO, 43 | MVLOG_WARN, 44 | MVLOG_ERROR, 45 | MVLOG_FATAL, 46 | MVLOG_LAST, 47 | } mvLog_t; 48 | 49 | // Windows-only 50 | #if (defined (WINNT) || defined(_WIN32) || defined(_WIN64) ) 51 | #define __attribute__(x) 52 | #define FUNCATTR_WEAK static 53 | #else 54 | #define FUNCATTR_WEAK 55 | #endif 56 | 57 | #define _MVLOGLEVEL(UNIT_NAME) mvLogLevel_ ## UNIT_NAME 58 | #define MVLOGLEVEL(UNIT_NAME) _MVLOGLEVEL(UNIT_NAME) 59 | 60 | #define MVLOG_STR(x) _MVLOG_STR(x) 61 | #define _MVLOG_STR(x) #x 62 | 63 | #ifndef MVLOG_UNIT_NAME 64 | #define MVLOG_UNIT_NAME global 65 | #else 66 | FUNCATTR_WEAK mvLog_t __attribute__ ((weak)) MVLOGLEVEL(MVLOG_UNIT_NAME) = MVLOG_LAST; 67 | #endif 68 | 69 | 70 | #ifndef MVLOG_MAXIMUM_THREAD_NAME_SIZE 71 | #define MVLOG_MAXIMUM_THREAD_NAME_SIZE 16 72 | #endif 73 | 74 | #define UNIT_NAME_STR MVLOG_STR(MVLOG_UNIT_NAME) 75 | 76 | 77 | extern XLINK_EXPORT mvLog_t MVLOGLEVEL(global); 78 | extern XLINK_EXPORT mvLog_t MVLOGLEVEL(default); 79 | 80 | int __attribute__ ((unused)) logprintf(mvLog_t curLogLvl, mvLog_t lvl, const char * func, const int line, const char * format, ...); 81 | 82 | #define mvLog(lvl, format, ...) \ 83 | logprintf(MVLOGLEVEL(MVLOG_UNIT_NAME), lvl, __func__, __LINE__, format, ##__VA_ARGS__) 84 | 85 | // Set log level for the current unit. Note that the level must be smaller than the global default 86 | static inline void mvLogLevelSet(mvLog_t lvl){ 87 | if(lvl < MVLOG_LAST){ 88 | MVLOGLEVEL(MVLOG_UNIT_NAME) = lvl; 89 | } 90 | } 91 | 92 | // Set the global log level. Can be used to prevent modules from hiding messages (enable all of them with a single change) 93 | // This should be an application setting, not a per module one 94 | inline void mvLogDefaultLevelSet(mvLog_t lvl){ 95 | if(lvl <= MVLOG_LAST){ 96 | MVLOGLEVEL(default) = lvl; 97 | } 98 | } 99 | 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif 106 | 107 | 108 | -------------------------------------------------------------------------------- /include/XLink/XLinkMacros.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef MVMACROS_H__ 6 | #define MVMACROS_H__ 7 | 8 | #define CIRCULAR_INCREMENT(x, maxVal) \ 9 | { \ 10 | x = (x + 1) % maxVal; \ 11 | } 12 | 13 | #define CIRCULAR_INCREMENT_BASE(x, maxVal, base) \ 14 | { \ 15 | if (++x == maxVal) \ 16 | x = base; \ 17 | } 18 | 19 | // Avoid problems with unsigned, first compare and then give the new value 20 | #define CIRCULAR_DECREMENT(x, maxVal) \ 21 | do { \ 22 | if ((x) == 0) \ 23 | (x) = (maxVal); \ 24 | else \ 25 | (x)--; \ 26 | } while(0) 27 | 28 | #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((!(sizeof(x) % sizeof(0[x]))))) 29 | #ifndef MIN 30 | #define MIN(a,b) \ 31 | ({ __typeof__ (a) _a = (a); \ 32 | __typeof__ (b) _b = (b); \ 33 | _a < _b ? _a : _b; }) 34 | #endif 35 | #ifndef MAX 36 | #define MAX(a,b) \ 37 | ({ __typeof__ (a) _a = (a); \ 38 | __typeof__ (b) _b = (b); \ 39 | _a > _b ? _a : _b; }) 40 | #endif 41 | /// @brief Aligns a pointer or number to a power of 2 value given 42 | /// @param[in] x number or pointer to be aligned 43 | /// @param[in] a value to align to (must be power of 2) 44 | /// @returns the aligned value 45 | #if (defined(_WIN32) || defined(_WIN64) ) 46 | #define ALIGN_UP_UINT32(x, a) ((uint32_t)(((uint32_t)(x) + a - 1) & (~(a-1)))) 47 | #define ALIGN_UP_INT32(x, a) ((int32_t)(((uint32_t)(x) + a - 1) & (~(a-1)))) 48 | #define ALIGN_UP(x, a) ALIGN_UP_UINT32(x,a) 49 | #else 50 | #define ALIGN_UP(x, a) ((typeof(x))(((uint32_t)(x) + a - 1) & (~(a-1)))) 51 | #define ALIGN_DOWN(x, a) ((typeof(x))(((uint32_t)(x)) & (~(a-1))) ) 52 | #define ALIGN_UP_UINT32(_x, _a) ALIGN_UP(_x, _a) 53 | #define ALIGN_UP_INT32(_x, _a) ALIGN_UP(_x, _a) 54 | #endif 55 | /// @brief Aligns a integernumber to any value given 56 | /// @param[in] x integer number to be aligned 57 | /// @param[in] a value to align to 58 | /// @returns the aligned value 59 | #ifndef ROUND_UP 60 | #define ROUND_UP(x, a) ((__typeof__(x))((((uint32_t)(x) + a - 1) / a) * a)) 61 | #endif 62 | #define ROUND_DOWN(x, a) ((__typeof__(x))(((uint32_t)(x) / a + 0) * a)) 63 | 64 | #if defined(__GNUC__) || defined(__sparc_v8__) 65 | #define ATTR_UNUSED __attribute__((unused)) 66 | #else 67 | #define ATTR_UNUSED 68 | #endif 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/XLink/XLinkPlatform.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @brief Application configuration Leon header 7 | /// 8 | 9 | #ifndef _XLINK_LINKPLATFORM_H 10 | #define _XLINK_LINKPLATFORM_H 11 | 12 | #include "XLinkPrivateDefines.h" 13 | #include 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | #ifdef XLINK_MAX_STREAM_RES 20 | #define MAX_POOLS_ALLOC XLINK_MAX_STREAM_RES 21 | #else 22 | #define MAX_POOLS_ALLOC 32 23 | #endif 24 | #define PACKET_LENGTH (64*1024) 25 | 26 | typedef enum { 27 | X_LINK_PLATFORM_SUCCESS = 0, 28 | X_LINK_PLATFORM_DEVICE_NOT_FOUND = -1, 29 | X_LINK_PLATFORM_ERROR = -2, 30 | X_LINK_PLATFORM_TIMEOUT = -3, 31 | X_LINK_PLATFORM_INVALID_PARAMETERS = -4, 32 | X_LINK_PLATFORM_INSUFFICIENT_PERMISSIONS = -5, 33 | X_LINK_PLATFORM_DEVICE_BUSY = -6, 34 | X_LINK_PLATFORM_DRIVER_NOT_LOADED = -128, 35 | X_LINK_PLATFORM_USB_DRIVER_NOT_LOADED = X_LINK_PLATFORM_DRIVER_NOT_LOADED+X_LINK_USB_VSC, 36 | X_LINK_PLATFORM_TCP_IP_DRIVER_NOT_LOADED = X_LINK_PLATFORM_DRIVER_NOT_LOADED+X_LINK_TCP_IP, 37 | X_LINK_PLATFORM_PCIE_DRIVER_NOT_LOADED = X_LINK_PLATFORM_DRIVER_NOT_LOADED+X_LINK_PCIE, 38 | } xLinkPlatformErrorCode_t; 39 | 40 | // ------------------------------------ 41 | // Device management. Begin. 42 | // ------------------------------------ 43 | 44 | xLinkPlatformErrorCode_t XLinkPlatformInit(void* options); 45 | 46 | #ifndef __DEVICE__ 47 | /** 48 | * @brief Return Myriad device description which meets the requirements 49 | */ 50 | xLinkPlatformErrorCode_t XLinkPlatformFindDevices(const deviceDesc_t in_deviceRequirements, 51 | deviceDesc_t* out_foundDevices, unsigned sizeFoundDevices, 52 | unsigned *out_amountOfFoundDevices); 53 | xLinkPlatformErrorCode_t XLinkPlatformFindDevicesDynamic(const deviceDesc_t in_deviceRequirements, 54 | deviceDesc_t* out_foundDevices, unsigned sizeFoundDevices, 55 | unsigned *out_amountOfFoundDevices, int timeoutMs, bool (*cb)(deviceDesc_t*, unsigned int)); 56 | 57 | xLinkPlatformErrorCode_t XLinkPlatformFindArrayOfDevicesNames( 58 | XLinkDeviceState_t state, 59 | const deviceDesc_t in_deviceRequirements, 60 | deviceDesc_t* out_foundDevicePtr, 61 | const unsigned int devicesArraySize, 62 | unsigned int *out_amountOfFoundDevices); 63 | 64 | xLinkPlatformErrorCode_t XLinkPlatformBootRemote(const deviceDesc_t* deviceDesc, const char* binaryPath); 65 | xLinkPlatformErrorCode_t XLinkPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length); 66 | xLinkPlatformErrorCode_t XLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, 67 | XLinkProtocol_t protocol, void** fd); 68 | xLinkPlatformErrorCode_t XLinkPlatformBootBootloader(const char* name, XLinkProtocol_t protocol); 69 | 70 | UsbSpeed_t get_usb_speed(); 71 | const char* get_mx_serial(); 72 | #endif // __DEVICE__ 73 | 74 | xLinkPlatformErrorCode_t XLinkPlatformCloseRemote(xLinkDeviceHandle_t* deviceHandle); 75 | 76 | // ------------------------------------ 77 | // Device management. End. 78 | // ------------------------------------ 79 | 80 | 81 | 82 | // ------------------------------------ 83 | // Data management. Begin. 84 | // ------------------------------------ 85 | 86 | int XLinkPlatformWrite(xLinkDeviceHandle_t *deviceHandle, void *data, int size); 87 | int XLinkPlatformRead(xLinkDeviceHandle_t *deviceHandle, void *data, int size); 88 | 89 | void* XLinkPlatformAllocateData(uint32_t size, uint32_t alignment); 90 | void XLinkPlatformDeallocateData(void *ptr, uint32_t size, uint32_t alignment); 91 | 92 | // ------------------------------------ 93 | // Data management. End. 94 | // ------------------------------------ 95 | 96 | 97 | 98 | // ------------------------------------ 99 | // Helpers. Begin. 100 | // ------------------------------------ 101 | 102 | #ifndef __DEVICE__ 103 | 104 | int XLinkPlatformIsDescriptionValid(const deviceDesc_t *in_deviceDesc, const XLinkDeviceState_t state); 105 | char* XLinkPlatformErrorToStr(const xLinkPlatformErrorCode_t errorCode); 106 | 107 | // for deprecated API 108 | XLinkPlatform_t XLinkPlatformPidToPlatform(const int pid); 109 | XLinkDeviceState_t XLinkPlatformPidToState(const int pid); 110 | // for deprecated API 111 | 112 | #endif // __DEVICE__ 113 | 114 | // ------------------------------------ 115 | // Helpers. End. 116 | // ------------------------------------ 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | 122 | #endif 123 | 124 | /* end of include file */ 125 | -------------------------------------------------------------------------------- /include/XLink/XLinkPlatformErrorUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef _XLINKPLATFORM_TOOL_H 6 | #define _XLINKPLATFORM_TOOL_H 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | #if 1 // Release configuration 14 | 15 | #ifndef ASSERT_XLINK_PLATFORM_R 16 | #define ASSERT_XLINK_PLATFORM_R(condition, err) do { \ 17 | if(!(condition)) { \ 18 | mvLog(MVLOG_ERROR, "Assertion Failed: %s \n", #condition); \ 19 | return (err); \ 20 | } \ 21 | } while(0) 22 | #endif // ASSERT_XLINK_PLATFORM_R 23 | 24 | #ifndef ASSERT_XLINK_PLATFORM 25 | #define ASSERT_XLINK_PLATFORM(condition) do { \ 26 | \ 27 | ASSERT_XLINK_PLATFORM_R((condition), X_LINK_PLATFORM_ERROR);\ 28 | \ 29 | } while(0) 30 | #endif // ASSERT_XLINK_PLATFORM 31 | 32 | #else // Debug configuration 33 | 34 | #ifndef ASSERT_XLINK_PLATFORM_R 35 | #define ASSERT_XLINK_PLATFORM_R(condition, err) do { \ 36 | if(!(condition)) { \ 37 | mvLog(MVLOG_ERROR, "Assertion Failed: %s \n", #condition); \ 38 | exit(EXIT_FAILURE); \ 39 | } \ 40 | } while(0) 41 | #endif // ASSERT_XLINK_PLATFORM_R 42 | 43 | #ifndef ASSERT_XLINK_PLATFORM 44 | #define ASSERT_XLINK_PLATFORM(condition) do { \ 45 | \ 46 | ASSERT_XLINK_PLATFORM_R((condition), X_LINK_PLATFORM_ERROR);\ 47 | \ 48 | } while(0) 49 | #endif // ASSERT_XLINK_PLATFORM 50 | 51 | #endif // NDEBUG 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif //_XLINKPLATFORM_TOOL_H 58 | -------------------------------------------------------------------------------- /include/XLink/XLinkPrivateDefines.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @file 7 | /// 8 | /// @brief Application configuration Leon header 9 | /// 10 | #ifndef _XLINKPRIVATEDEFINES_H 11 | #define _XLINKPRIVATEDEFINES_H 12 | 13 | #include "XLinkStream.h" 14 | #include "XLinkPublicDefines.h" 15 | 16 | #if !defined(XLINK_ALIGN_TO_BOUNDARY) 17 | # if defined(_WIN32) && !defined(__GNUC__) 18 | # define XLINK_ALIGN_TO_BOUNDARY(_n) __declspec(align(_n)) 19 | # else 20 | # define XLINK_ALIGN_TO_BOUNDARY(_n) __attribute__((aligned(_n))) 21 | # endif 22 | #endif // XLINK_ALIGN_TO_BOUNDARY 23 | 24 | #ifdef __cplusplus 25 | extern "C" 26 | { 27 | #endif 28 | 29 | #ifdef XLINK_MAX_STREAM_RES 30 | #define MAXIMUM_SEMAPHORES XLINK_MAX_STREAM_RES 31 | #else 32 | #define MAXIMUM_SEMAPHORES 32 33 | #endif 34 | #define __CACHE_LINE_SIZE 64 35 | 36 | typedef int32_t eventId_t; 37 | 38 | /** 39 | * @brief State for xLinkDesc_t 40 | */ 41 | typedef enum { 42 | XLINK_NOT_INIT, 43 | XLINK_UP, 44 | XLINK_DOWN, 45 | }xLinkState_t; 46 | 47 | /** 48 | * @brief Device description 49 | */ 50 | typedef struct xLinkDeviceHandle_t { 51 | XLinkProtocol_t protocol; 52 | void* xLinkFD; 53 | } xLinkDeviceHandle_t; 54 | 55 | /** 56 | * @brief XLink primitive for each device 57 | */ 58 | typedef struct xLinkDesc_t { 59 | // Incremental number, doesn't get decremented. 60 | uint32_t nextUniqueStreamId; 61 | streamDesc_t availableStreams[XLINK_MAX_STREAMS]; 62 | xLinkState_t peerState; 63 | xLinkDeviceHandle_t deviceHandle; 64 | linkId_t id; 65 | XLink_sem_t dispatcherClosedSem; 66 | UsbSpeed_t usbConnSpeed; 67 | char mxSerialId[XLINK_MAX_MX_ID_SIZE]; 68 | 69 | //Deprecated fields. Begin. 70 | int hostClosedFD; 71 | //Deprecated fields. End. 72 | 73 | // profiling 74 | XLinkProf_t profilingData; 75 | 76 | } xLinkDesc_t; 77 | 78 | streamId_t XLinkAddOrUpdateStream(void *fd, const char *name, 79 | uint32_t writeSize, uint32_t readSize, streamId_t forcedId); 80 | 81 | //events which are coming from remote 82 | typedef enum 83 | { 84 | /*USB-X_LINK_PCIE related events*/ 85 | XLINK_WRITE_REQ, 86 | XLINK_READ_REQ, 87 | XLINK_READ_REL_REQ, 88 | XLINK_CREATE_STREAM_REQ, 89 | XLINK_CLOSE_STREAM_REQ, 90 | XLINK_PING_REQ, 91 | XLINK_RESET_REQ, 92 | XLINK_REQUEST_LAST, 93 | //note that is important to separate request and response 94 | XLINK_WRITE_RESP, 95 | XLINK_READ_RESP, 96 | XLINK_READ_REL_RESP, 97 | XLINK_CREATE_STREAM_RESP, 98 | XLINK_CLOSE_STREAM_RESP, 99 | XLINK_PING_RESP, 100 | XLINK_RESET_RESP, 101 | XLINK_RESP_LAST, 102 | 103 | /*X_LINK_IPC related events*/ 104 | IPC_WRITE_REQ, 105 | IPC_READ_REQ, 106 | IPC_CREATE_STREAM_REQ, 107 | IPC_CLOSE_STREAM_REQ, 108 | // 109 | IPC_WRITE_RESP, 110 | IPC_READ_RESP, 111 | IPC_CREATE_STREAM_RESP, 112 | IPC_CLOSE_STREAM_RESP, 113 | XLINK_READ_REL_SPEC_REQ, 114 | XLINK_READ_REL_SPEC_RESP, 115 | } xLinkEventType_t; 116 | 117 | typedef enum 118 | { 119 | EVENT_LOCAL, 120 | EVENT_REMOTE, 121 | } xLinkEventOrigin_t; 122 | 123 | #ifndef __DEVICE__ 124 | #define MAX_LINKS 64 125 | #else 126 | #define MAX_LINKS 1 127 | #endif 128 | 129 | #define MAX_EVENTS 64 130 | #define MAX_SCHEDULERS MAX_LINKS 131 | #define XLINK_MAX_DEVICES MAX_LINKS 132 | 133 | typedef struct xLinkEventHeader_t{ 134 | eventId_t id; 135 | xLinkEventType_t type; 136 | char streamName[MAX_STREAM_NAME_LENGTH]; 137 | uint32_t tnsec; 138 | uint32_t tsecLsb; 139 | uint32_t tsecMsb; 140 | streamId_t streamId; 141 | uint32_t size; 142 | union{ 143 | uint32_t raw; 144 | struct{ 145 | uint32_t ack : 1; 146 | uint32_t nack : 1; 147 | uint32_t block : 1; 148 | uint32_t localServe : 1; 149 | uint32_t terminate : 1; 150 | uint32_t bufferFull : 1; 151 | uint32_t sizeTooBig : 1; 152 | uint32_t noSuchStream : 1; 153 | uint32_t moveSemantic : 1; 154 | }bitField; 155 | }flags; 156 | }xLinkEventHeader_t; 157 | 158 | typedef struct xLinkEvent_t { 159 | XLINK_ALIGN_TO_BOUNDARY(64) xLinkEventHeader_t header; 160 | xLinkDeviceHandle_t deviceHandle; 161 | void* data; 162 | }xLinkEvent_t; 163 | 164 | #define XLINK_INIT_EVENT(event, in_streamId, in_type, in_size, in_data, in_deviceHandle) do { \ 165 | (event).header.streamId = (in_streamId); \ 166 | (event).header.type = (in_type); \ 167 | (event).header.size = (in_size); \ 168 | (event).data = (in_data); \ 169 | (event).deviceHandle = (in_deviceHandle); \ 170 | } while(0) 171 | 172 | #define XLINK_EVENT_ACKNOWLEDGE(event) do { \ 173 | (event)->header.flags.bitField.ack = 1; \ 174 | (event)->header.flags.bitField.nack = 0; \ 175 | } while(0) 176 | 177 | #define XLINK_EVENT_NOT_ACKNOWLEDGE(event) do { \ 178 | (event)->header.flags.bitField.ack = 0; \ 179 | (event)->header.flags.bitField.nack = 1; \ 180 | } while(0) 181 | 182 | #define XLINK_SET_EVENT_FAILED_AND_SERVE(event) do { \ 183 | XLINK_EVENT_NOT_ACKNOWLEDGE(event); \ 184 | (event)->header.flags.bitField.localServe = 1; \ 185 | } while(0) 186 | 187 | #ifdef __cplusplus 188 | } 189 | #endif 190 | 191 | #endif 192 | 193 | /* end of include file */ 194 | -------------------------------------------------------------------------------- /include/XLink/XLinkPrivateFields.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef _XLINKPRIVATEFIELDS_H 6 | #define _XLINKPRIVATEFIELDS_H 7 | 8 | #include "XLinkDispatcher.h" 9 | 10 | #define LINK_ID_MASK 0xFF 11 | #define LINK_ID_SHIFT ((sizeof(uint32_t) - sizeof(uint8_t)) * 8) 12 | #define STREAM_ID_MASK 0xFFFFFF 13 | 14 | #define EXTRACT_LINK_ID(streamId) (((streamId) >> LINK_ID_SHIFT) & LINK_ID_MASK) 15 | #define EXTRACT_STREAM_ID(streamId) ((streamId) & STREAM_ID_MASK) 16 | 17 | #define COMBINE_IDS(streamId, linkid) \ 18 | streamId = streamId | ((linkid & LINK_ID_MASK) << LINK_ID_SHIFT); 19 | 20 | // ------------------------------------ 21 | // Global fields declaration. Begin. 22 | // ------------------------------------ 23 | 24 | extern XLinkGlobalHandler_t* glHandler; //TODO need to either protect this with semaphor 25 | //or make profiling data per device 26 | 27 | extern xLinkDesc_t availableXLinks[MAX_LINKS]; 28 | extern pthread_mutex_t availableXLinksMutex; 29 | extern DispatcherControlFunctions controlFunctionTbl; 30 | extern sem_t pingSem; //to b used by myriad 31 | 32 | // ------------------------------------ 33 | // Global fields declaration. End. 34 | // ------------------------------------ 35 | 36 | 37 | // ------------------------------------ 38 | // Helpers declaration. Begin. 39 | // ------------------------------------ 40 | 41 | xLinkDesc_t* getLinkById(linkId_t id); 42 | xLinkDesc_t* getLink(void* fd); 43 | xLinkState_t getXLinkState(xLinkDesc_t* link); 44 | 45 | 46 | streamId_t getStreamIdByName(xLinkDesc_t* link, const char* name); 47 | 48 | streamDesc_t* getStreamById(void* fd, streamId_t id); 49 | streamDesc_t* getStreamByName(xLinkDesc_t* link, const char* name); 50 | 51 | void releaseStream(streamDesc_t* stream); 52 | 53 | // ------------------------------------ 54 | // Helpers declaration. End. 55 | // ------------------------------------ 56 | 57 | #endif //PROJECT_XLINKPRIVATEFIELDS_H 58 | -------------------------------------------------------------------------------- /include/XLink/XLinkPublicDefines.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @file 7 | /// 8 | /// @brief Application configuration Leon header 9 | /// 10 | #ifndef _XLINKPUBLICDEFINES_H 11 | #define _XLINKPUBLICDEFINES_H 12 | #include 13 | #include 14 | #include "XLinkTime.h" 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #define XLINK_MAX_MX_ID_SIZE 32 21 | #define XLINK_MAX_NAME_SIZE 64 22 | 23 | #ifdef XLINK_MAX_STREAM_RES 24 | #define XLINK_MAX_STREAMS XLINK_MAX_STREAM_RES 25 | #else 26 | #define XLINK_MAX_STREAMS 32 27 | #endif 28 | #define XLINK_MAX_PACKETS_PER_STREAM 64 29 | #define XLINK_NO_RW_TIMEOUT 0xFFFFFFFF 30 | 31 | 32 | typedef enum { 33 | X_LINK_USB_SPEED_UNKNOWN = 0, 34 | X_LINK_USB_SPEED_LOW, 35 | X_LINK_USB_SPEED_FULL, 36 | X_LINK_USB_SPEED_HIGH, 37 | X_LINK_USB_SPEED_SUPER, 38 | X_LINK_USB_SPEED_SUPER_PLUS 39 | } UsbSpeed_t; 40 | 41 | typedef enum{ 42 | X_LINK_SUCCESS = 0, 43 | X_LINK_ALREADY_OPEN, 44 | X_LINK_COMMUNICATION_NOT_OPEN, 45 | X_LINK_COMMUNICATION_FAIL, 46 | X_LINK_COMMUNICATION_UNKNOWN_ERROR, 47 | X_LINK_DEVICE_NOT_FOUND, 48 | X_LINK_TIMEOUT, 49 | X_LINK_ERROR, 50 | X_LINK_OUT_OF_MEMORY, 51 | X_LINK_INSUFFICIENT_PERMISSIONS, 52 | X_LINK_DEVICE_ALREADY_IN_USE, 53 | X_LINK_NOT_IMPLEMENTED, 54 | X_LINK_INIT_USB_ERROR, 55 | X_LINK_INIT_TCP_IP_ERROR, 56 | X_LINK_INIT_PCIE_ERROR, 57 | } XLinkError_t; 58 | 59 | typedef enum{ 60 | X_LINK_USB_VSC = 0, 61 | X_LINK_USB_CDC, 62 | X_LINK_PCIE, 63 | X_LINK_IPC, 64 | X_LINK_TCP_IP, 65 | X_LINK_NMB_OF_PROTOCOLS, 66 | X_LINK_ANY_PROTOCOL 67 | } XLinkProtocol_t; 68 | 69 | typedef enum{ 70 | X_LINK_ANY_PLATFORM = 0, 71 | X_LINK_MYRIAD_2 = 2450, 72 | X_LINK_MYRIAD_X = 2480, 73 | } XLinkPlatform_t; 74 | 75 | typedef enum{ 76 | /** 77 | * Used only for searching devices. It means that the device state is not important. 78 | */ 79 | X_LINK_ANY_STATE = 0, 80 | /** 81 | * The device is booted (firmware is loaded) and the pipeline is running. 82 | */ 83 | X_LINK_BOOTED, 84 | /** 85 | * Device isn't booted, e.g. for USB devices with no bootloader flashed. In such case it's waiting for the USB boot. 86 | */ 87 | X_LINK_UNBOOTED, 88 | /** 89 | * The device is in bootloader and waiting for a connection. After the connection the state will change to BOOTED. 90 | */ 91 | X_LINK_BOOTLOADER, 92 | /** 93 | * The device has booted the flashed firmware/pipeline (e.g. in case of OAK POE devices in standalone mode). 94 | */ 95 | X_LINK_FLASH_BOOTED, 96 | /** 97 | * The device has booted the flashed firmware/pipeline (e.g. in case of OAK POE devices in standalone mode). 98 | */ 99 | X_LINK_BOOTED_NON_EXCLUSIVE = X_LINK_FLASH_BOOTED, 100 | } XLinkDeviceState_t; 101 | 102 | typedef enum{ 103 | X_LINK_PCIE_UNKNOWN_BOOTLOADER = 0, 104 | X_LINK_PCIE_SIMPLIFIED_BOOTLOADER = 1, 105 | X_LINK_PCIE_UNIFIED_BOOTLOADER = 2 106 | } XLinkPCIEBootloader; 107 | 108 | #define INVALID_STREAM_ID 0xDEADDEAD 109 | #define INVALID_STREAM_ID_OUT_OF_MEMORY 0xDEADFFFF 110 | #define INVALID_LINK_ID 0xFF 111 | #define MAX_STREAM_NAME_LENGTH 52 112 | 113 | typedef uint32_t streamId_t; 114 | typedef uint8_t linkId_t; 115 | 116 | typedef struct { 117 | XLinkProtocol_t protocol; 118 | XLinkPlatform_t platform; 119 | char name[XLINK_MAX_NAME_SIZE]; 120 | XLinkDeviceState_t state; 121 | char mxid[XLINK_MAX_MX_ID_SIZE]; 122 | XLinkError_t status; 123 | bool nameHintOnly; 124 | } deviceDesc_t; 125 | 126 | typedef struct streamPacketDesc_t 127 | { 128 | uint8_t* data; 129 | uint32_t length; 130 | XLinkTimespec tRemoteSent; /// remote timestamp of when the packet was sent. Related to remote clock. Note: not directly related to local clock 131 | XLinkTimespec tReceived; /// local timestamp of when the packet was received. Related to local monotonic clock 132 | } streamPacketDesc_t; 133 | 134 | typedef struct XLinkProf_t 135 | { 136 | float totalReadTime; 137 | float totalWriteTime; 138 | uint64_t totalReadBytes; 139 | uint64_t totalWriteBytes; 140 | unsigned long totalBootCount; 141 | float totalBootTime; 142 | } XLinkProf_t; 143 | 144 | typedef struct XLinkGlobalHandler_t 145 | { 146 | int profEnable; 147 | XLinkProf_t profilingData; 148 | void* options; 149 | 150 | //Deprecated fields. Begin. 151 | int loglevel; 152 | int protocol; 153 | //Deprecated fields. End. 154 | } XLinkGlobalHandler_t; 155 | 156 | typedef struct 157 | { 158 | char* devicePath; 159 | char* devicePath2; 160 | int linkId; 161 | XLinkProtocol_t protocol; 162 | } XLinkHandler_t; 163 | 164 | //Deprecated defines. Begin. 165 | 166 | typedef enum{ 167 | USB_VSC = 0, 168 | USB_CDC, 169 | PCIE, 170 | IPC, 171 | NMB_OF_PROTOCOLS 172 | } XLinkProtocol_deprecated_t; 173 | 174 | //Deprecated defines. End. 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif 179 | 180 | #endif 181 | 182 | /* end of include file */ 183 | -------------------------------------------------------------------------------- /include/XLink/XLinkSemaphore.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @file 7 | /// 8 | /// @brief Application configuration Leon header 9 | /// 10 | 11 | #ifndef _XLINKSEMAPHORE_H 12 | #define _XLINKSEMAPHORE_H 13 | 14 | # if (defined(_WIN32) || defined(_WIN64)) 15 | # include "win_pthread.h" 16 | # include "win_semaphore.h" 17 | # include "win_synchapi.h" 18 | # else 19 | # include 20 | # include 21 | # ifdef __APPLE__ 22 | # include "pthread_semaphore.h" 23 | # else 24 | # include 25 | # endif 26 | # endif 27 | 28 | #ifdef __cplusplus 29 | extern "C" 30 | { 31 | #endif 32 | 33 | // 34 | // This structure describes the semaphore used in XLink and 35 | // extends the standard semaphore with a reference count. 36 | // The counter is thread-safe and changes only in cases if 37 | // all tools of thread synchronization are really unlocked. 38 | // refs == -1 in case if semaphore was destroyed; 39 | // refs == 0 in case if semaphore was initialized but has no waiters; 40 | // refs == N in case if there are N waiters which called sem_wait(). 41 | // 42 | 43 | typedef struct { 44 | sem_t psem; 45 | int refs; 46 | } XLink_sem_t; 47 | 48 | // 49 | // XLink wrappers for POSIX semaphore functions (refer sem_overview for details) 50 | // In description of standard sem_destroy the following can be noted: 51 | // "Destroying a semaphore that other processes or threads are currently 52 | // blocked on (in sem_wait(3)) produces undefined behavior." 53 | // XLink wrappers use thread-safe reference count and destroy the semaphore only in case 54 | // if there are no waiters 55 | // 56 | 57 | int XLink_sem_init(XLink_sem_t* sem, int pshared, unsigned int value); 58 | int XLink_sem_destroy(XLink_sem_t* sem); 59 | int XLink_sem_post(XLink_sem_t* sem); 60 | int XLink_sem_wait(XLink_sem_t* sem); 61 | int XLink_sem_timedwait(XLink_sem_t* sem, const struct timespec* abstime); 62 | int XLink_sem_trywait(XLink_sem_t* sem); 63 | 64 | // 65 | // Helper functions for XLink semaphore wrappers. 66 | // Use them only in case if you know what you are doing. 67 | // 68 | 69 | int XLink_sem_set_refs(XLink_sem_t* sem, int refs); 70 | int XLink_sem_get_refs(XLink_sem_t* sem, int *sval); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif // _XLINKSEMAPHORE_H 77 | -------------------------------------------------------------------------------- /include/XLink/XLinkStream.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef _XLINKSTREAM_H 6 | #define _XLINKSTREAM_H 7 | 8 | #include "XLinkPublicDefines.h" 9 | #include "XLinkSemaphore.h" 10 | 11 | /** 12 | * @brief Streams opened to device 13 | */ 14 | typedef struct{ 15 | char name[MAX_STREAM_NAME_LENGTH]; 16 | streamId_t id; 17 | uint32_t writeSize; 18 | uint32_t readSize; /*No need of read buffer. It's on remote, 19 | will read it directly to the requested buffer*/ 20 | streamPacketDesc_t packets[XLINK_MAX_PACKETS_PER_STREAM]; 21 | uint32_t availablePackets; 22 | uint32_t blockedPackets; 23 | 24 | uint32_t firstPacket; 25 | uint32_t firstPacketUnused; 26 | uint32_t firstPacketFree; 27 | 28 | uint32_t remoteFillLevel; 29 | uint32_t localFillLevel; 30 | uint32_t remoteFillPacketLevel; 31 | 32 | uint32_t closeStreamInitiated; 33 | 34 | XLink_sem_t sem; 35 | }streamDesc_t; 36 | 37 | XLinkError_t XLinkStreamInitialize( 38 | streamDesc_t* stream, streamId_t id, const char* name); 39 | 40 | void XLinkStreamReset(streamDesc_t* stream); 41 | 42 | #endif //_XLINKSTREAM_H 43 | -------------------------------------------------------------------------------- /include/XLink/XLinkStringUtils.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef MVSTRINGUTILS_H__ 6 | #define MVSTRINGUTILS_H__ 7 | 8 | #include 9 | 10 | /* 11 | * Maximum sring length, 4KB. 12 | */ 13 | #define RSIZE_MAX_STR ( 4UL << 10 ) 14 | 15 | /** 16 | * @brief If the string utils functions have worked without errors, EOK will be 17 | * returned. On error, one of error codes, which is not equal to zero, will 18 | * be returned. 19 | */ 20 | typedef enum { 21 | EOK = 0, // Successful operation. 22 | ESNULLP = 1, // NULL pointer. 23 | ESZEROL = 2, // Zero length. 24 | ESLEMAX = 3, // Length exceeds max limit. 25 | ESOVRLP = 4, // Strings overlap. 26 | ESNOSPC = 5 // Not enough space to copy src 27 | } mvStringUtilsError; 28 | 29 | /** 30 | * @brief The mv_strcpy function copies the string pointed to by src 31 | * (including the terminating null character) into the array 32 | * pointed to by dest. 33 | * @param dest 34 | * pointer to string that will be replaced by src. 35 | * @param destsz 36 | * restricted maximum length of dest. 37 | * @param src 38 | * pointer to the string that will be copied to dest 39 | * @return zero on success and non-zero value on error. 40 | */ 41 | int mv_strcpy(char *dest, size_t destsz, const char *src); 42 | 43 | /** 44 | * @brief The mv_strncpy function copies at most count characters from the 45 | * string pointed to by src, including the terminating null byte ('\0'), to 46 | * the array pointed to by dest. Exactly count characters are written at 47 | * dest. If the length strlen_s(src) is greater than or equal to count, the 48 | * string pointed to by dest will contain count characters from src plus a 49 | * null characters (dest will be null-terminated). Therefore, destsz must 50 | * be at least count+1 in order to contain the terminator. 51 | * @param dest 52 | * pointer to string that will be replaced by src. 53 | * @param destsz 54 | * restricted maximum length of dest (must be at least count+1). 55 | * @param src 56 | * pointer to the string that will be copied to dest. 57 | * @param count 58 | * the maximum number of characters from src to copy into dest. 59 | * @return zero on success and non-zero value on error. 60 | */ 61 | int mv_strncpy(char *dest, size_t destsz, const char *src, size_t count); 62 | 63 | #endif // MVSTRINGUTILS_H__ 64 | -------------------------------------------------------------------------------- /include/XLink/XLinkTime.h: -------------------------------------------------------------------------------- 1 | #ifndef _XLINK_TIME_H 2 | #define _XLINK_TIME_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | typedef struct XLinkTimespec { 10 | uint64_t tv_sec; 11 | uint64_t tv_nsec; 12 | } XLinkTimespec; 13 | 14 | void getMonotonicTimestamp(XLinkTimespec* ts); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | #endif -------------------------------------------------------------------------------- /include/XLink/XLinkVersion.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /// 6 | /// @file 7 | /// @brief Application configuration Leon header 8 | /// 9 | 10 | #define X_LINK_VERSION_MAJOR 1 11 | #define X_LINK_VERSION_MINOR 0 12 | #define X_LINK_VERSION_PATCH 0 13 | -------------------------------------------------------------------------------- /src/pc/Android/ifaddrs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995, 1999 3 | * Berkeley Software Design, Inc. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND 12 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 13 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 14 | * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE 15 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 16 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 17 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 18 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 19 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 20 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 21 | * SUCH DAMAGE. 22 | * 23 | * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp 24 | */ 25 | 26 | #ifndef _IFADDRS_H_ 27 | #define _IFADDRS_H_ 28 | 29 | struct ifaddrs { 30 | struct ifaddrs *ifa_next; 31 | char *ifa_name; 32 | unsigned int ifa_flags; 33 | struct sockaddr *ifa_addr; 34 | struct sockaddr *ifa_netmask; 35 | struct sockaddr *ifa_dstaddr; 36 | void *ifa_data; 37 | }; 38 | 39 | /* 40 | * This may have been defined in . Note that if is 41 | * to be included it must be included before this header file. 42 | */ 43 | #ifndef ifa_broadaddr 44 | #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ 45 | #endif 46 | 47 | #include 48 | 49 | __BEGIN_DECLS 50 | extern int getifaddrs(struct ifaddrs **ifap); 51 | extern void freeifaddrs(struct ifaddrs *ifa); 52 | __END_DECLS 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/pc/MacOS/pthread_semaphore.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include "pthread_semaphore.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef SEM_VALUE_MAX 13 | # define SEM_VALUE_MAX INT_MAX 14 | #endif 15 | 16 | struct pthread_sem_private_t { 17 | pthread_mutex_t access; 18 | pthread_cond_t conditional; 19 | volatile int counter; // >= 0 no waiters, == -1 some waiters 20 | }; 21 | 22 | int pthread_sem_init(pthread_sem_t *psem, int pshared, unsigned int value) { 23 | int result = 0; 24 | if (NULL == psem) { 25 | errno = EINVAL; 26 | return -1; 27 | } 28 | if (value > SEM_VALUE_MAX){ 29 | errno = EINVAL; 30 | return -1; 31 | } 32 | if (pshared != 0) { 33 | errno = ENOSYS; 34 | return -1; 35 | } 36 | struct pthread_sem_private_t *psem_private = malloc(sizeof(struct pthread_sem_private_t)); 37 | if (NULL == psem_private) { 38 | return -1; 39 | } 40 | 41 | result = pthread_mutex_init(&psem_private->access, NULL); 42 | if (result) { 43 | free(psem_private); 44 | errno = result; 45 | return -1; 46 | } 47 | 48 | result = pthread_cond_init(&psem_private->conditional, NULL); 49 | if (result) { 50 | pthread_mutex_destroy(&psem_private->access); 51 | free(psem_private); 52 | errno = result; 53 | return -1; 54 | } 55 | 56 | psem_private->counter = value; 57 | 58 | *psem = (pthread_sem_t)psem_private; 59 | errno = 0; 60 | return 0; 61 | } 62 | 63 | int pthread_sem_destroy(pthread_sem_t *psem) { 64 | int result = 0; 65 | 66 | if (NULL == psem) { 67 | errno = EINVAL; 68 | return -1; 69 | } 70 | if (0 == *psem) { 71 | errno = EINVAL; 72 | return -1; 73 | } 74 | 75 | struct pthread_sem_private_t *psem_private = (struct pthread_sem_private_t *)*psem; 76 | 77 | result = pthread_mutex_lock(&psem_private->access); 78 | if (result) { 79 | errno = result; 80 | return -1; 81 | } 82 | 83 | if (psem_private->counter == -1) { 84 | pthread_mutex_unlock(&psem_private->access); 85 | errno = EBUSY; 86 | return -1; 87 | } 88 | 89 | // conditional variable might not be deleted due to wait queue - lets notify users 90 | result = pthread_cond_destroy(&psem_private->conditional); 91 | if (result) { 92 | pthread_mutex_unlock(&psem_private->access); 93 | errno = result; 94 | return -1; 95 | } 96 | 97 | result = pthread_mutex_unlock(&psem_private->access); 98 | if (result) { 99 | errno = result; 100 | return -1; 101 | } 102 | 103 | // UB - untested if mutex object corrupted 104 | result = pthread_mutex_destroy(&psem_private->access); 105 | if (result) { 106 | errno = result; 107 | return -1; 108 | } 109 | 110 | free(psem_private); 111 | *psem = 0; 112 | 113 | errno = 0; 114 | return 0; 115 | } 116 | static int pthread_sem_post_signal_or_broadcast(pthread_sem_t *psem, int broadcast) { 117 | int result; 118 | if (NULL == psem) { 119 | errno = EINVAL; 120 | return -1; 121 | } 122 | if (0 == *psem) { 123 | errno = EINVAL; 124 | return -1; 125 | } 126 | 127 | struct pthread_sem_private_t *psem_private = (struct pthread_sem_private_t *)*psem; 128 | result = pthread_mutex_lock(&psem_private->access); 129 | if (result) { 130 | errno = result; 131 | return -1; 132 | } 133 | 134 | // right now value == 0 not usually means that there is a waiter queue 135 | if (broadcast) { 136 | result = pthread_cond_broadcast(&psem_private->conditional); 137 | } else { 138 | result = pthread_cond_signal(&psem_private->conditional); 139 | } 140 | if (result) { 141 | pthread_mutex_unlock(&psem_private->access); 142 | errno = result; 143 | return -1; 144 | } 145 | 146 | // up counter 147 | if (psem_private->counter == SEM_VALUE_MAX) { 148 | pthread_mutex_unlock(&psem_private->access); 149 | errno = EOVERFLOW; 150 | return -1; 151 | } 152 | if (psem_private->counter == -1) { 153 | psem_private->counter = 1; 154 | } else { 155 | psem_private->counter ++; 156 | } 157 | 158 | result = pthread_mutex_unlock(&psem_private->access); 159 | if (result) { 160 | errno = result; 161 | return -1; 162 | } 163 | 164 | errno = 0; 165 | return 0; 166 | } 167 | 168 | int pthread_sem_post_broadcast(pthread_sem_t *psem) { 169 | return pthread_sem_post_signal_or_broadcast(psem, 1); 170 | } 171 | 172 | int pthread_sem_post(pthread_sem_t *psem) { 173 | return pthread_sem_post_signal_or_broadcast(psem, 0); 174 | } 175 | 176 | static int pthread_sem_timed_or_blocked_wait(pthread_sem_t *psem, const struct timespec *abstime) { 177 | int result = 0; 178 | if (NULL == psem) { 179 | errno = EINVAL; 180 | return -1; 181 | } 182 | if (0 == *psem) { 183 | errno = EINVAL; 184 | return -1; 185 | } 186 | struct pthread_sem_private_t *psem_private = (struct pthread_sem_private_t *)*psem; 187 | result = pthread_mutex_lock(&psem_private->access); 188 | if (result) { 189 | errno = result; 190 | return -1; 191 | } 192 | 193 | for (;psem_private->counter < 1;) { 194 | // indicate that we will be waiting this counter 195 | psem_private->counter = -1; 196 | if (abstime == NULL) { 197 | result = pthread_cond_wait(&psem_private->conditional, &psem_private->access); 198 | } else { 199 | result = pthread_cond_timedwait(&psem_private->conditional, &psem_private->access, abstime); 200 | } 201 | if (result != 0) { 202 | break; 203 | } 204 | } 205 | 206 | // printf("cond_wait=%d\n", result); 207 | if (result) { 208 | // sema not obtained - resetting counter back 209 | if (psem_private->counter == -1) { 210 | psem_private->counter = 0; 211 | } 212 | pthread_mutex_unlock(&psem_private->access); 213 | errno = result; 214 | return -1; 215 | } 216 | 217 | // acquire semaphore 218 | psem_private->counter --; 219 | 220 | result = pthread_mutex_unlock(&psem_private->access); 221 | if (result) { 222 | errno = result; 223 | return -1; 224 | } 225 | 226 | errno = 0; 227 | return 0; 228 | } 229 | 230 | int pthread_sem_wait(pthread_sem_t *psem) { 231 | return pthread_sem_timed_or_blocked_wait(psem, NULL); 232 | } 233 | 234 | int pthread_sem_timedwait(pthread_sem_t *psem, const struct timespec *abstime) { 235 | if (NULL == abstime) { 236 | errno = EINVAL; 237 | return -1; 238 | } 239 | if (abstime->tv_sec < 0 || abstime->tv_nsec < 0) { 240 | errno = EINVAL; 241 | return -1; 242 | } 243 | return pthread_sem_timed_or_blocked_wait(psem, abstime); 244 | } 245 | 246 | int pthread_sem_trywait(pthread_sem_t *psem) { 247 | return pthread_sem_timed_or_blocked_wait(psem, NULL); 248 | } 249 | 250 | # ifdef __APPLE__ 251 | 252 | int sem_init(sem_t *psem, int pshared, unsigned int value) { 253 | return pthread_sem_init(psem, pshared, value); 254 | } 255 | int sem_destroy(sem_t *psem) { 256 | return pthread_sem_destroy(psem); 257 | } 258 | int sem_post(sem_t *psem) { 259 | return pthread_sem_post(psem); 260 | } 261 | int sem_wait(sem_t *psem) { 262 | return pthread_sem_wait(psem); 263 | } 264 | int sem_trywait(sem_t *psem) { 265 | return pthread_sem_trywait(psem); 266 | } 267 | int sem_timedwait(sem_t *psem, const struct timespec *abstime) { 268 | return pthread_sem_timedwait(psem, abstime); 269 | } 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /src/pc/MacOS/pthread_semaphore.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef PTHREAD_SEMAPHORE_H 6 | #define PTHREAD_SEMAPHORE_H 7 | 8 | # include 9 | # include 10 | typedef intptr_t pthread_sem_t; 11 | 12 | # ifdef __cplusplus 13 | extern "C" { 14 | # endif 15 | int pthread_sem_init(pthread_sem_t *psem, int pshared, unsigned int value); 16 | int pthread_sem_destroy(pthread_sem_t *psem); 17 | int pthread_sem_post(pthread_sem_t *psem); 18 | int pthread_sem_post_broadcast(pthread_sem_t *psem); 19 | int pthread_sem_wait(pthread_sem_t *psem); 20 | int pthread_sem_trywait(pthread_sem_t *psem); 21 | int pthread_sem_timedwait(pthread_sem_t *psem, const struct timespec *abstime); 22 | # ifdef __cplusplus 23 | } 24 | # endif 25 | 26 | # ifdef __APPLE__ 27 | 28 | typedef pthread_sem_t sem_t; 29 | 30 | #define SEM_VALUE_MAX 32767 31 | 32 | # ifdef __cplusplus 33 | extern "C" { 34 | # endif 35 | 36 | int sem_init(sem_t *psem, int pshared, unsigned int value); 37 | int sem_destroy(sem_t *psem); 38 | int sem_post(sem_t *psem); 39 | int sem_wait(sem_t *psem); 40 | int sem_trywait(sem_t *psem); 41 | int sem_timedwait(sem_t *psem, const struct timespec *abstime); 42 | 43 | # ifdef __cplusplus 44 | } 45 | # endif 46 | 47 | # elif defined(_WIN32) 48 | # error "pthread based semaphores not implemented for WIN32" 49 | # else 50 | # include 51 | # endif // linux case 52 | #endif // PTHREAD_SEMAPHORE_H 53 | -------------------------------------------------------------------------------- /src/pc/PlatformData.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "XLinkPlatform.h" 12 | #include "XLinkPlatformErrorUtils.h" 13 | #include "XLinkStringUtils.h" 14 | #include "usb_host.h" 15 | #include "pcie_host.h" 16 | #include "tcpip_host.h" 17 | #include "PlatformDeviceFd.h" 18 | #include "inttypes.h" 19 | 20 | #define MVLOG_UNIT_NAME PlatformData 21 | #include "XLinkLog.h" 22 | 23 | #if (defined(_WIN32) || defined(_WIN64)) 24 | #ifndef _WIN32_WINNT 25 | #define _WIN32_WINNT 0x0601 /* Windows 7. */ 26 | #endif 27 | #include "win_time.h" 28 | #include "win_pthread.h" 29 | #include 30 | #include 31 | #pragma comment(lib, "Ws2_32.lib") 32 | #else 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #ifdef USE_LINK_JTAG 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #endif /*USE_LINK_JTAG*/ 47 | 48 | #ifndef USE_USB_VSC 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #include "usb_host.h" 55 | 56 | extern int usbFdWrite; 57 | extern int usbFdRead; 58 | #endif /*USE_USB_VSC*/ 59 | 60 | // ------------------------------------ 61 | // Wrappers declaration. Begin. 62 | // ------------------------------------ 63 | 64 | static int pciePlatformRead(void *f, void *data, int size); 65 | static int tcpipPlatformRead(void *fd, void *data, int size); 66 | 67 | static int pciePlatformWrite(void *f, void *data, int size); 68 | static int tcpipPlatformWrite(void *fd, void *data, int size); 69 | 70 | // ------------------------------------ 71 | // Wrappers declaration. End. 72 | // ------------------------------------ 73 | 74 | 75 | 76 | // ------------------------------------ 77 | // XLinkPlatform API implementation. Begin. 78 | // ------------------------------------ 79 | 80 | int XLinkPlatformWrite(xLinkDeviceHandle_t *deviceHandle, void *data, int size) 81 | { 82 | if(!XLinkIsProtocolInitialized(deviceHandle->protocol)) { 83 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+deviceHandle->protocol; 84 | } 85 | 86 | switch (deviceHandle->protocol) { 87 | case X_LINK_USB_VSC: 88 | case X_LINK_USB_CDC: 89 | return usbPlatformWrite(deviceHandle->xLinkFD, data, size); 90 | 91 | case X_LINK_PCIE: 92 | return pciePlatformWrite(deviceHandle->xLinkFD, data, size); 93 | 94 | case X_LINK_TCP_IP: 95 | return tcpipPlatformWrite(deviceHandle->xLinkFD, data, size); 96 | 97 | default: 98 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 99 | } 100 | } 101 | 102 | int XLinkPlatformRead(xLinkDeviceHandle_t *deviceHandle, void *data, int size) 103 | { 104 | if(!XLinkIsProtocolInitialized(deviceHandle->protocol)) { 105 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+deviceHandle->protocol; 106 | } 107 | 108 | switch (deviceHandle->protocol) { 109 | case X_LINK_USB_VSC: 110 | case X_LINK_USB_CDC: 111 | return usbPlatformRead(deviceHandle->xLinkFD, data, size); 112 | 113 | case X_LINK_PCIE: 114 | return pciePlatformRead(deviceHandle->xLinkFD, data, size); 115 | 116 | case X_LINK_TCP_IP: 117 | return tcpipPlatformRead(deviceHandle->xLinkFD, data, size); 118 | 119 | default: 120 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 121 | } 122 | } 123 | 124 | void* XLinkPlatformAllocateData(uint32_t size, uint32_t alignment) 125 | { 126 | void* ret = NULL; 127 | #if (defined(_WIN32) || defined(_WIN64) ) 128 | ret = _aligned_malloc(size, alignment); 129 | #else 130 | if (posix_memalign(&ret, alignment, size) != 0) { 131 | perror("memalign failed"); 132 | } 133 | #endif 134 | return ret; 135 | } 136 | 137 | void XLinkPlatformDeallocateData(void *ptr, uint32_t size, uint32_t alignment) 138 | { 139 | if (!ptr) 140 | return; 141 | #if (defined(_WIN32) || defined(_WIN64) ) 142 | _aligned_free(ptr); 143 | #else 144 | free(ptr); 145 | #endif 146 | } 147 | 148 | // ------------------------------------ 149 | // XLinkPlatform API implementation. End. 150 | // ------------------------------------ 151 | 152 | 153 | 154 | // ------------------------------------ 155 | // Wrappers implementation. Begin. 156 | // ------------------------------------ 157 | 158 | 159 | 160 | #if (defined(_WIN32) || defined(_WIN64)) 161 | static int write_pending = 0; 162 | static int read_pending = 0; 163 | #endif 164 | 165 | int pciePlatformWrite(void *f, void *data, int size) 166 | { 167 | #if (defined(_WIN32) || defined(_WIN64)) 168 | #define CHUNK_SIZE_BYTES (5ULL * 1024ULL * 1024ULL) 169 | 170 | while (size) 171 | { 172 | write_pending = 1; 173 | 174 | size_t chunk = (size_t)size < CHUNK_SIZE_BYTES ? (size_t)size : CHUNK_SIZE_BYTES; 175 | int num_written = pcie_write(f, data, chunk); 176 | 177 | write_pending = 0; 178 | 179 | if (num_written == -EAGAIN) { 180 | // Let read commands be submitted 181 | if (read_pending > 0) { 182 | usleep(1000); 183 | } 184 | continue; 185 | } 186 | 187 | if (num_written < 0) { 188 | return num_written; 189 | } 190 | 191 | data = ((char*) data) + num_written; 192 | /** 193 | * num_written is always not greater than size 194 | */ 195 | size -= num_written; 196 | } 197 | 198 | return 0; 199 | #undef CHUNK_SIZE_BYTES 200 | #else // Linux case 201 | int left = size; 202 | 203 | while (left > 0) 204 | { 205 | int bt = pcie_write(f, data, left); 206 | if (bt < 0) 207 | return bt; 208 | 209 | data = ((char *)data) + bt; 210 | left -= bt; 211 | } 212 | 213 | return 0; 214 | #endif 215 | } 216 | 217 | int pciePlatformRead(void *f, void *data, int size) 218 | { 219 | #if (defined(_WIN32) || defined(_WIN64)) 220 | while (size) 221 | { 222 | read_pending = 1; 223 | 224 | int num_read = pcie_read(f, data, size); 225 | 226 | read_pending = 0; 227 | 228 | if (num_read == -EAGAIN) { 229 | // Let write commands be submitted 230 | if (write_pending > 0) { 231 | usleep(1000); 232 | } 233 | continue; 234 | } 235 | 236 | if(num_read < 0) { 237 | return num_read; 238 | } 239 | 240 | data = ((char *)data) + num_read; 241 | /** 242 | * num_read is always not greater than size 243 | */ 244 | size -= num_read; 245 | } 246 | 247 | return 0; 248 | #else // Linux 249 | int left = size; 250 | 251 | while (left > 0) 252 | { 253 | int bt = pcie_read(f, data, left); 254 | if (bt < 0) 255 | return bt; 256 | 257 | data = ((char *)data) + bt; 258 | left -= bt; 259 | } 260 | 261 | return 0; 262 | #endif 263 | } 264 | 265 | static int tcpipPlatformRead(void *fdKey, void *data, int size) 266 | { 267 | #if defined(USE_TCP_IP) 268 | int nread = 0; 269 | 270 | void* tmpsockfd = NULL; 271 | if(getPlatformDeviceFdFromKey(fdKey, &tmpsockfd)){ 272 | mvLog(MVLOG_FATAL, "Cannot find file descriptor by key: %" PRIxPTR, (uintptr_t) fdKey); 273 | return -1; 274 | } 275 | TCPIP_SOCKET sock = (TCPIP_SOCKET) (uintptr_t) tmpsockfd; 276 | 277 | while(nread < size) 278 | { 279 | int rc = recv(sock, &((char*)data)[nread], size - nread, 0); 280 | if(rc <= 0) 281 | { 282 | return -1; 283 | } 284 | else 285 | { 286 | nread += rc; 287 | } 288 | } 289 | #endif 290 | return 0; 291 | } 292 | 293 | static int tcpipPlatformWrite(void *fdKey, void *data, int size) 294 | { 295 | #if defined(USE_TCP_IP) 296 | int byteCount = 0; 297 | 298 | void* tmpsockfd = NULL; 299 | if(getPlatformDeviceFdFromKey(fdKey, &tmpsockfd)){ 300 | mvLog(MVLOG_FATAL, "Cannot find file descriptor by key: %" PRIxPTR, (uintptr_t) fdKey); 301 | return -1; 302 | } 303 | TCPIP_SOCKET sock = (TCPIP_SOCKET) (uintptr_t) tmpsockfd; 304 | 305 | while(byteCount < size) 306 | { 307 | // Use send instead of write and ignore SIGPIPE 308 | //rc = write((intptr_t)fd, &((char*)data)[byteCount], size - byteCount); 309 | 310 | int flags = 0; 311 | #if defined(MSG_NOSIGNAL) 312 | // Use flag NOSIGNAL on send call 313 | flags = MSG_NOSIGNAL; 314 | #endif 315 | 316 | int rc = send(sock, &((char*)data)[byteCount], size - byteCount, flags); 317 | if(rc <= 0) 318 | { 319 | return -1; 320 | } 321 | else 322 | { 323 | byteCount += rc; 324 | } 325 | } 326 | #endif 327 | return 0; 328 | } 329 | 330 | // ------------------------------------ 331 | // Wrappers implementation. End. 332 | // ------------------------------------ 333 | -------------------------------------------------------------------------------- /src/pc/PlatformDeviceControl.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #include "XLinkPlatform.h" 9 | #include "XLinkPlatformErrorUtils.h" 10 | #include "usb_host.h" 11 | #include "pcie_host.h" 12 | #include "tcpip_host.h" 13 | #include "XLinkStringUtils.h" 14 | #include "PlatformDeviceFd.h" 15 | 16 | #define MVLOG_UNIT_NAME PlatformDeviceControl 17 | #include "XLinkLog.h" 18 | 19 | #ifndef USE_USB_VSC 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | int usbFdWrite = -1; 27 | int usbFdRead = -1; 28 | #endif /*USE_USB_VSC*/ 29 | 30 | #include "XLinkPublicDefines.h" 31 | 32 | #define USB_LINK_SOCKET_PORT 5678 33 | #define UNUSED __attribute__((unused)) 34 | 35 | 36 | static UsbSpeed_t usb_speed_enum = X_LINK_USB_SPEED_UNKNOWN; 37 | static char mx_serial[XLINK_MAX_MX_ID_SIZE] = { 0 }; 38 | #ifdef USE_USB_VSC 39 | static const int statuswaittimeout = 5; 40 | #endif 41 | 42 | #ifdef USE_TCP_IP 43 | 44 | #if (defined(_WIN32) || defined(_WIN64)) 45 | #ifndef _WIN32_WINNT 46 | #define _WIN32_WINNT 0x0601 /* Windows 7. */ 47 | #endif 48 | #include 49 | #include 50 | #pragma comment(lib, "Ws2_32.lib") 51 | #else 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #endif 58 | 59 | #endif /* USE_TCP_IP */ 60 | 61 | // ------------------------------------ 62 | // Wrappers declaration. Begin. 63 | // ------------------------------------ 64 | 65 | static int pciePlatformConnect(UNUSED const char *devPathRead, const char *devPathWrite, void **fd); 66 | static int tcpipPlatformConnect(const char *devPathRead, const char *devPathWrite, void **fd); 67 | 68 | static xLinkPlatformErrorCode_t usbPlatformBootBootloader(const char *name); 69 | static int pciePlatformBootBootloader(const char *name); 70 | static xLinkPlatformErrorCode_t tcpipPlatformBootBootloader(const char *name); 71 | 72 | static int pciePlatformClose(void *f); 73 | static int tcpipPlatformClose(void *fd); 74 | 75 | static int pciePlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length); 76 | static int tcpipPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length); 77 | 78 | // ------------------------------------ 79 | // Wrappers declaration. End. 80 | // ------------------------------------ 81 | 82 | 83 | void xlinkSetProtocolInitialized(const XLinkProtocol_t protocol, int initialized); 84 | 85 | // ------------------------------------ 86 | // XLinkPlatform API implementation. Begin. 87 | // ------------------------------------ 88 | 89 | xLinkPlatformErrorCode_t XLinkPlatformInit(void* options) 90 | { 91 | // Set that all protocols are initialized at first 92 | for(int i = 0; i < X_LINK_NMB_OF_PROTOCOLS; i++) { 93 | xlinkSetProtocolInitialized(i, 1); 94 | } 95 | 96 | // check for failed initialization; LIBUSB_SUCCESS = 0 97 | if (usbInitialize(options) != 0) { 98 | xlinkSetProtocolInitialized(X_LINK_USB_VSC, 0); 99 | } 100 | 101 | // TODO(themarpe) - move to tcpip_host 102 | //tcpipInitialize(); 103 | #if (defined(_WIN32) || defined(_WIN64)) && defined(USE_TCP_IP) 104 | WSADATA wsa_data; 105 | WSAStartup(MAKEWORD(2,2), &wsa_data); 106 | #endif 107 | return X_LINK_PLATFORM_SUCCESS; 108 | } 109 | 110 | 111 | xLinkPlatformErrorCode_t XLinkPlatformBootRemote(const deviceDesc_t* deviceDesc, const char* binaryPath) 112 | { 113 | FILE *file; 114 | long file_size; 115 | 116 | char *image_buffer; 117 | 118 | /* Open the mvcmd file */ 119 | file = fopen(binaryPath, "rb"); 120 | 121 | if(file == NULL) { 122 | mvLog(MVLOG_ERROR, "Cannot open file by path: %s", binaryPath); 123 | return -7; 124 | } 125 | 126 | fseek(file, 0, SEEK_END); 127 | file_size = ftell(file); 128 | rewind(file); 129 | if(file_size <= 0 || !(image_buffer = (char*)malloc(file_size))) 130 | { 131 | mvLog(MVLOG_ERROR, "cannot allocate image_buffer. file_size = %ld", file_size); 132 | fclose(file); 133 | return -3; 134 | } 135 | if((long) fread(image_buffer, 1, file_size, file) != file_size) 136 | { 137 | mvLog(MVLOG_ERROR, "cannot read file to image_buffer"); 138 | fclose(file); 139 | free(image_buffer); 140 | return -7; 141 | } 142 | fclose(file); 143 | 144 | if(XLinkPlatformBootFirmware(deviceDesc, image_buffer, file_size)) { 145 | free(image_buffer); 146 | return -1; 147 | } 148 | 149 | free(image_buffer); 150 | return 0; 151 | } 152 | 153 | xLinkPlatformErrorCode_t XLinkPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length) { 154 | 155 | if(!XLinkIsProtocolInitialized(deviceDesc->protocol)) { 156 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+deviceDesc->protocol; 157 | } 158 | 159 | switch (deviceDesc->protocol) { 160 | case X_LINK_USB_VSC: 161 | case X_LINK_USB_CDC: 162 | return usbPlatformBootFirmware(deviceDesc, firmware, length); 163 | 164 | case X_LINK_PCIE: 165 | return pciePlatformBootFirmware(deviceDesc, firmware, length); 166 | 167 | case X_LINK_TCP_IP: 168 | return tcpipPlatformBootFirmware(deviceDesc, firmware, length); 169 | 170 | default: 171 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 172 | } 173 | 174 | } 175 | 176 | 177 | xLinkPlatformErrorCode_t XLinkPlatformConnect(const char* devPathRead, const char* devPathWrite, XLinkProtocol_t protocol, void** fd) 178 | { 179 | if(!XLinkIsProtocolInitialized(protocol)) { 180 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+protocol; 181 | } 182 | switch (protocol) { 183 | case X_LINK_USB_VSC: 184 | case X_LINK_USB_CDC: 185 | return usbPlatformConnect(devPathRead, devPathWrite, fd); 186 | 187 | case X_LINK_PCIE: 188 | return pciePlatformConnect(devPathRead, devPathWrite, fd); 189 | 190 | case X_LINK_TCP_IP: 191 | return tcpipPlatformConnect(devPathRead, devPathWrite, fd); 192 | 193 | default: 194 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 195 | } 196 | } 197 | 198 | xLinkPlatformErrorCode_t XLinkPlatformBootBootloader(const char* name, XLinkProtocol_t protocol) 199 | { 200 | if(!XLinkIsProtocolInitialized(protocol)) { 201 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+protocol; 202 | } 203 | switch (protocol) { 204 | case X_LINK_USB_VSC: 205 | case X_LINK_USB_CDC: 206 | return usbPlatformBootBootloader(name); 207 | 208 | case X_LINK_PCIE: 209 | return pciePlatformBootBootloader(name); 210 | 211 | case X_LINK_TCP_IP: 212 | return tcpipPlatformBootBootloader(name); 213 | 214 | default: 215 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 216 | } 217 | } 218 | 219 | xLinkPlatformErrorCode_t XLinkPlatformCloseRemote(xLinkDeviceHandle_t* deviceHandle) 220 | { 221 | if(deviceHandle->protocol == X_LINK_ANY_PROTOCOL || 222 | deviceHandle->protocol == X_LINK_NMB_OF_PROTOCOLS) { 223 | return X_LINK_PLATFORM_ERROR; 224 | } 225 | 226 | if(!XLinkIsProtocolInitialized(deviceHandle->protocol)) { 227 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+deviceHandle->protocol; 228 | } 229 | 230 | switch (deviceHandle->protocol) { 231 | case X_LINK_USB_VSC: 232 | case X_LINK_USB_CDC: 233 | return usbPlatformClose(deviceHandle->xLinkFD); 234 | 235 | case X_LINK_PCIE: 236 | return pciePlatformClose(deviceHandle->xLinkFD); 237 | 238 | case X_LINK_TCP_IP: 239 | return tcpipPlatformClose(deviceHandle->xLinkFD); 240 | 241 | default: 242 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 243 | } 244 | 245 | } 246 | 247 | // ------------------------------------ 248 | // XLinkPlatform API implementation. End. 249 | // ------------------------------------ 250 | 251 | /** 252 | * getter to obtain the connected usb speed which was stored by 253 | * usb_find_device_with_bcd() during XLinkconnect(). 254 | * @note: 255 | * getter will return empty or different value 256 | * if called before XLinkConnect. 257 | */ 258 | UsbSpeed_t get_usb_speed(){ 259 | return usb_speed_enum; 260 | } 261 | 262 | /** 263 | * getter to obtain the Mx serial id which was received by 264 | * usb_find_device_with_bcd() during XLinkconnect(). 265 | * @note: 266 | * getter will return empty or different value 267 | * if called before XLinkConnect. 268 | */ 269 | const char* get_mx_serial(){ 270 | #ifdef USE_USB_VSC 271 | return mx_serial; 272 | #else 273 | return "UNKNOWN"; 274 | #endif 275 | } 276 | 277 | // ------------------------------------ 278 | // Helpers implementation. End. 279 | // ------------------------------------ 280 | 281 | 282 | 283 | // ------------------------------------ 284 | // Wrappers implementation. Begin. 285 | // ------------------------------------ 286 | 287 | 288 | int pciePlatformConnect(UNUSED const char *devPathRead, 289 | const char *devPathWrite, 290 | void **fd) 291 | { 292 | return pcie_init(devPathWrite, fd); 293 | } 294 | 295 | // TODO add IPv6 to tcpipPlatformConnect() 296 | int tcpipPlatformConnect(const char *devPathRead, const char *devPathWrite, void **fd) 297 | { 298 | #if defined(USE_TCP_IP) 299 | if (!devPathWrite || !fd) { 300 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 301 | } 302 | 303 | TCPIP_SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); 304 | 305 | #if (defined(_WIN32) || defined(_WIN64) ) 306 | if(sock == INVALID_SOCKET) 307 | { 308 | return TCPIP_HOST_ERROR; 309 | } 310 | #else 311 | if(sock < 0) 312 | { 313 | return TCPIP_HOST_ERROR; 314 | } 315 | #endif 316 | 317 | // Disable sigpipe reception on send 318 | #if defined(SO_NOSIGPIPE) 319 | const int set = 1; 320 | setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set)); 321 | #endif 322 | 323 | struct sockaddr_in serv_addr = { 0 }; 324 | 325 | const size_t maxlen = 255; 326 | size_t len = strnlen(devPathWrite, maxlen + 1); 327 | if (len == 0 || len >= maxlen + 1) 328 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 329 | char *const serv_ip = (char *)malloc(len + 1); 330 | if (!serv_ip) 331 | return X_LINK_PLATFORM_ERROR; 332 | serv_ip[0] = 0; 333 | // Parse port if specified, or use default 334 | int port = TCPIP_LINK_SOCKET_PORT; 335 | sscanf(devPathWrite, "%[^:]:%d", serv_ip, &port); 336 | 337 | serv_addr.sin_family = AF_INET; 338 | serv_addr.sin_port = htons(port); 339 | 340 | int ret = inet_pton(AF_INET, serv_ip, &serv_addr.sin_addr); 341 | free(serv_ip); 342 | 343 | if(ret <= 0) 344 | { 345 | tcpip_close_socket(sock); 346 | return -1; 347 | } 348 | 349 | int on = 1; 350 | if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 351 | { 352 | perror("setsockopt TCP_NODELAY"); 353 | tcpip_close_socket(sock); 354 | return -1; 355 | } 356 | 357 | if(connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 358 | { 359 | tcpip_close_socket(sock); 360 | return -1; 361 | } 362 | 363 | // Store the socket and create a "unique" key instead 364 | // (as file descriptors are reused and can cause a clash with lookups between scheduler and link) 365 | *fd = createPlatformDeviceFdKey((void*) (uintptr_t) sock); 366 | 367 | #endif 368 | return 0; 369 | } 370 | 371 | 372 | xLinkPlatformErrorCode_t usbPlatformBootBootloader(const char *name) 373 | { 374 | return usbLinkBootBootloader(name); 375 | } 376 | 377 | int pciePlatformBootBootloader(const char *name) 378 | { 379 | // TODO(themarpe) 380 | return -1; 381 | } 382 | 383 | xLinkPlatformErrorCode_t tcpipPlatformBootBootloader(const char *name) 384 | { 385 | return tcpip_boot_bootloader(name); 386 | } 387 | 388 | 389 | static char* pciePlatformStateToStr(const pciePlatformState_t platformState) { 390 | switch (platformState) { 391 | case PCIE_PLATFORM_ANY_STATE: return "PCIE_PLATFORM_ANY_STATE"; 392 | case PCIE_PLATFORM_BOOTED: return "PCIE_PLATFORM_BOOTED"; 393 | case PCIE_PLATFORM_UNBOOTED: return "PCIE_PLATFORM_UNBOOTED"; 394 | default: return ""; 395 | } 396 | } 397 | int pciePlatformClose(void *f) 398 | { 399 | int rc; 400 | 401 | /** For PCIe device reset is called on host side */ 402 | #if (defined(_WIN32) || defined(_WIN64)) 403 | rc = pcie_reset_device((HANDLE)f); 404 | #else 405 | rc = pcie_reset_device(*(int*)f); 406 | #endif 407 | if (rc) { 408 | mvLog(MVLOG_ERROR, "Device resetting failed with error %d", rc); 409 | pciePlatformState_t state = PCIE_PLATFORM_ANY_STATE; 410 | pcie_get_device_state(f, &state); 411 | mvLog(MVLOG_INFO, "Device state is %s", pciePlatformStateToStr(state)); 412 | } 413 | rc = pcie_close(f); 414 | if (rc) { 415 | mvLog(MVLOG_ERROR, "Device closing failed with error %d", rc); 416 | } 417 | return rc; 418 | } 419 | 420 | int tcpipPlatformClose(void *fdKey) 421 | { 422 | #if defined(USE_TCP_IP) 423 | 424 | int status = 0; 425 | 426 | void* tmpsockfd = NULL; 427 | if(getPlatformDeviceFdFromKey(fdKey, &tmpsockfd)){ 428 | mvLog(MVLOG_FATAL, "Cannot find file descriptor by key"); 429 | return -1; 430 | } 431 | TCPIP_SOCKET sock = (TCPIP_SOCKET) (uintptr_t) tmpsockfd; 432 | 433 | #ifdef _WIN32 434 | status = shutdown(sock, SD_BOTH); 435 | if (status == 0) { status = closesocket(sock); } 436 | #else 437 | if(sock != -1) 438 | { 439 | status = shutdown(sock, SHUT_RDWR); 440 | if (status == 0) { status = close(sock); } 441 | } 442 | #endif 443 | 444 | if(destroyPlatformDeviceFdKey(fdKey)){ 445 | mvLog(MVLOG_FATAL, "Cannot destroy file descriptor key"); 446 | return -1; 447 | } 448 | 449 | return status; 450 | 451 | #endif 452 | return -1; 453 | } 454 | 455 | 456 | 457 | int pciePlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length){ 458 | // Temporary open fd to boot device and then close it 459 | int* pcieFd = NULL; 460 | int rc = pcie_init(deviceDesc->name, (void**)&pcieFd); 461 | if (rc) { 462 | return rc; 463 | } 464 | #if (!defined(_WIN32) && !defined(_WIN64)) 465 | rc = pcie_boot_device(*(int*)pcieFd, firmware, length); 466 | #else 467 | rc = pcie_boot_device(pcieFd, firmware, length); 468 | #endif 469 | pcie_close(pcieFd); // Will not check result for now 470 | return rc; 471 | } 472 | 473 | int tcpipPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length){ 474 | // TCPIP doesn't support a boot mechanism 475 | return -1; 476 | } 477 | 478 | // ------------------------------------ 479 | // Wrappers implementation. End. 480 | // ------------------------------------ 481 | -------------------------------------------------------------------------------- /src/pc/PlatformDeviceFd.cpp: -------------------------------------------------------------------------------- 1 | #include "PlatformDeviceFd.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static std::mutex mutex; 9 | static std::unordered_map map; 10 | static std::uintptr_t uniqueFdKey{0x55}; 11 | 12 | int getPlatformDeviceFdFromKey(void* fdKeyRaw, void** fd){ 13 | if(fd == nullptr) return -1; 14 | std::unique_lock lock(mutex); 15 | 16 | std::uintptr_t fdKey = reinterpret_cast(fdKeyRaw); 17 | if(map.count(fdKey) > 0){ 18 | *fd = map.at(fdKey); 19 | return 0; 20 | } else { 21 | return 1; 22 | } 23 | } 24 | 25 | void* createPlatformDeviceFdKey(void* fd){ 26 | std::unique_lock lock(mutex); 27 | 28 | // Get uniqueFdKey 29 | std::uintptr_t fdKey = uniqueFdKey++; 30 | map[fdKey] = fd; 31 | return reinterpret_cast(fdKey); 32 | } 33 | 34 | int destroyPlatformDeviceFdKey(void* fdKeyRaw){ 35 | std::unique_lock lock(mutex); 36 | 37 | std::uintptr_t fdKey = reinterpret_cast(fdKeyRaw); 38 | if(map.count(fdKey) > 0){ 39 | map.erase(fdKey); 40 | return 0; 41 | } else { 42 | return -1; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/pc/PlatformDeviceFd.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_DEVICE_FD_H_ 2 | #define _PLATFORM_DEVICE_FD_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | int getPlatformDeviceFdFromKey(void* fdKeyRaw, void** fd); 10 | void* createPlatformDeviceFdKey(void* fd); 11 | int destroyPlatformDeviceFdKey(void* fdKeyRaw); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif -------------------------------------------------------------------------------- /src/pc/PlatformDeviceSearch.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | 7 | #include "XLinkPlatform.h" 8 | #include "XLinkPlatformErrorUtils.h" 9 | #include "usb_host.h" 10 | #include "pcie_host.h" 11 | #include "tcpip_host.h" 12 | #include "XLinkStringUtils.h" 13 | 14 | 15 | #define MVLOG_UNIT_NAME PlatformDeviceSearch 16 | #include "XLinkLog.h" 17 | 18 | // ------------------------------------ 19 | // Helpers declaration. Begin. 20 | // ------------------------------------ 21 | 22 | static int platformToPid(const XLinkPlatform_t platform, const XLinkDeviceState_t state); 23 | static pciePlatformState_t xlinkDeviceStateToPciePlatformState(const XLinkDeviceState_t state); 24 | 25 | static xLinkPlatformErrorCode_t parseUsbBootError(usbBootError_t rc); 26 | static xLinkPlatformErrorCode_t parsePCIeHostError(pcieHostError_t rc); 27 | 28 | static xLinkPlatformErrorCode_t getPCIeDeviceName(int index, 29 | XLinkDeviceState_t state, 30 | const deviceDesc_t in_deviceRequirements, 31 | deviceDesc_t* out_foundDevice); 32 | static xLinkPlatformErrorCode_t getTcpIpDevices(const deviceDesc_t in_deviceRequirements, 33 | deviceDesc_t* out_foundDevices, int sizeFoundDevices, 34 | unsigned int *out_amountOfFoundDevices); 35 | 36 | 37 | // ------------------------------------ 38 | // Helpers declaration. End. 39 | // ------------------------------------ 40 | 41 | 42 | // ------------------------------------ 43 | // XLinkPlatform API implementation. Begin. 44 | // ------------------------------------ 45 | 46 | xLinkPlatformErrorCode_t XLinkPlatformFindDevices(const deviceDesc_t in_deviceRequirements, 47 | deviceDesc_t* out_foundDevices, unsigned sizeFoundDevices, 48 | unsigned int *out_amountOfFoundDevices) { 49 | memset(out_foundDevices, 0, sizeFoundDevices * sizeof(deviceDesc_t)); 50 | xLinkPlatformErrorCode_t USB_rc; 51 | xLinkPlatformErrorCode_t PCIe_rc; 52 | xLinkPlatformErrorCode_t TCPIP_rc; 53 | unsigned numFoundDevices = 0; 54 | *out_amountOfFoundDevices = 0; 55 | 56 | switch (in_deviceRequirements.protocol){ 57 | case X_LINK_USB_CDC: 58 | case X_LINK_USB_VSC: 59 | if(!XLinkIsProtocolInitialized(in_deviceRequirements.protocol)) { 60 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+in_deviceRequirements.protocol; 61 | } 62 | // Check if protocol is initialized 63 | return getUSBDevices(in_deviceRequirements, out_foundDevices, sizeFoundDevices, out_amountOfFoundDevices); 64 | 65 | /* TODO(themarpe) - reenable PCIe 66 | case X_LINK_PCIE: 67 | return getPCIeDeviceName(0, state, in_deviceRequirements, out_foundDevice); 68 | */ 69 | 70 | case X_LINK_TCP_IP: 71 | if(!XLinkIsProtocolInitialized(in_deviceRequirements.protocol)) { 72 | return X_LINK_PLATFORM_DRIVER_NOT_LOADED+in_deviceRequirements.protocol; 73 | } 74 | return getTcpIpDevices(in_deviceRequirements, out_foundDevices, sizeFoundDevices, out_amountOfFoundDevices); 75 | 76 | case X_LINK_ANY_PROTOCOL: 77 | 78 | // If USB protocol is initialized 79 | if(XLinkIsProtocolInitialized(X_LINK_USB_VSC)) { 80 | // Find first correct USB Device 81 | numFoundDevices = 0; 82 | USB_rc = getUSBDevices(in_deviceRequirements, out_foundDevices, sizeFoundDevices, &numFoundDevices); 83 | *out_amountOfFoundDevices += numFoundDevices; 84 | out_foundDevices += numFoundDevices; 85 | // Found enough devices, return 86 | if (numFoundDevices >= sizeFoundDevices) { 87 | return X_LINK_PLATFORM_SUCCESS; 88 | } else { 89 | sizeFoundDevices -= numFoundDevices; 90 | } 91 | } 92 | 93 | 94 | /* TODO(themarpe) - reenable PCIe 95 | if(XLinkIsProtocolInitialized(X_LINK_PCIE)) { 96 | numFoundDevices = 0; 97 | PCIe_rc = getPCIeDeviceName(0, state, in_deviceRequirements, out_foundDevice); 98 | // Found enough devices, return 99 | out_foundDevices += numFoundDevices; 100 | if (numFoundDevices >= sizeFoundDevices) { 101 | return X_LINK_PLATFORM_SUCCESS; 102 | } else { 103 | sizeFoundDevices -= numFoundDevices; 104 | } 105 | *out_amountOfFoundDevices += numFoundDevices; 106 | } 107 | */ 108 | 109 | // Try find TCPIP device 110 | if(XLinkIsProtocolInitialized(X_LINK_TCP_IP)) { 111 | numFoundDevices = 0; 112 | TCPIP_rc = getTcpIpDevices(in_deviceRequirements, out_foundDevices, sizeFoundDevices, &numFoundDevices); 113 | *out_amountOfFoundDevices += numFoundDevices; 114 | out_foundDevices += numFoundDevices; 115 | // Found enough devices, return 116 | if (numFoundDevices >= sizeFoundDevices) { 117 | return X_LINK_PLATFORM_SUCCESS; 118 | } else { 119 | sizeFoundDevices -= numFoundDevices; 120 | } 121 | } 122 | 123 | return X_LINK_PLATFORM_SUCCESS; 124 | 125 | default: 126 | mvLog(MVLOG_WARN, "Unknown protocol"); 127 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 128 | } 129 | 130 | return X_LINK_PLATFORM_SUCCESS; 131 | } 132 | 133 | 134 | int XLinkPlatformIsDescriptionValid(const deviceDesc_t *in_deviceDesc, const XLinkDeviceState_t state) { 135 | if(!in_deviceDesc){ 136 | return 0; 137 | } 138 | 139 | return 1; 140 | } 141 | 142 | char* XLinkPlatformErrorToStr(const xLinkPlatformErrorCode_t errorCode) { 143 | switch (errorCode) { 144 | case X_LINK_PLATFORM_SUCCESS: return "X_LINK_PLATFORM_SUCCESS"; 145 | case X_LINK_PLATFORM_DEVICE_NOT_FOUND: return "X_LINK_PLATFORM_DEVICE_NOT_FOUND"; 146 | case X_LINK_PLATFORM_ERROR: return "X_LINK_PLATFORM_ERROR"; 147 | case X_LINK_PLATFORM_TIMEOUT: return "X_LINK_PLATFORM_TIMEOUT"; 148 | case X_LINK_PLATFORM_USB_DRIVER_NOT_LOADED: return "X_LINK_PLATFORM_USB_DRIVER_NOT_LOADED"; 149 | case X_LINK_PLATFORM_TCP_IP_DRIVER_NOT_LOADED: return "X_LINK_PLATFORM_TCP_IP_DRIVER_NOT_LOADED"; 150 | case X_LINK_PLATFORM_PCIE_DRIVER_NOT_LOADED: return "X_LINK_PLATFORM_PCIE_DRIVER_NOT_LOADED"; 151 | case X_LINK_PLATFORM_INVALID_PARAMETERS: return "X_LINK_PLATFORM_INVALID_PARAMETERS"; 152 | default: return ""; 153 | } 154 | } 155 | 156 | XLinkPlatform_t XLinkPlatformPidToPlatform(const int pid) { 157 | switch (pid) { 158 | case DEFAULT_UNBOOTPID_2150: return X_LINK_MYRIAD_2; 159 | case DEFAULT_UNBOOTPID_2485: return X_LINK_MYRIAD_X; 160 | default: return X_LINK_ANY_PLATFORM; 161 | } 162 | } 163 | 164 | XLinkDeviceState_t XLinkPlatformPidToState(const int pid) { 165 | switch (pid) { 166 | case DEFAULT_OPENPID: return X_LINK_BOOTED; 167 | case DEFAULT_BOOTLOADER_PID: return X_LINK_BOOTLOADER; 168 | case DEFAULT_FLASH_BOOTED_PID: return X_LINK_FLASH_BOOTED; 169 | case AUTO_PID: return X_LINK_ANY_STATE; 170 | default: return X_LINK_UNBOOTED; 171 | } 172 | } 173 | 174 | // ------------------------------------ 175 | // XLinkPlatform API implementation. End. 176 | // ------------------------------------ 177 | 178 | 179 | 180 | // ------------------------------------ 181 | // Helpers implementation. Begin. 182 | // ------------------------------------ 183 | 184 | int platformToPid(const XLinkPlatform_t platform, const XLinkDeviceState_t state) { 185 | if (state == X_LINK_UNBOOTED) { 186 | switch (platform) { 187 | case X_LINK_MYRIAD_2: return DEFAULT_UNBOOTPID_2150; 188 | case X_LINK_MYRIAD_X: return DEFAULT_UNBOOTPID_2485; 189 | default: return AUTO_UNBOOTED_PID; 190 | } 191 | } else if (state == X_LINK_BOOTED) { 192 | return DEFAULT_OPENPID; 193 | } else if(state == X_LINK_BOOTLOADER){ 194 | return DEFAULT_BOOTLOADER_PID; 195 | } else if(state == X_LINK_FLASH_BOOTED){ 196 | return DEFAULT_FLASH_BOOTED_PID; 197 | } else if (state == X_LINK_ANY_STATE) { 198 | switch (platform) { 199 | case X_LINK_MYRIAD_2: return DEFAULT_UNBOOTPID_2150; 200 | case X_LINK_MYRIAD_X: return DEFAULT_UNBOOTPID_2485; 201 | default: return AUTO_PID; 202 | } 203 | } 204 | 205 | return AUTO_PID; 206 | } 207 | 208 | pciePlatformState_t xlinkDeviceStateToPciePlatformState(const XLinkDeviceState_t state) { 209 | switch (state) { 210 | case X_LINK_ANY_STATE: return PCIE_PLATFORM_ANY_STATE; 211 | case X_LINK_BOOTED: return PCIE_PLATFORM_BOOTED; 212 | case X_LINK_UNBOOTED: return PCIE_PLATFORM_UNBOOTED; 213 | default: 214 | return PCIE_PLATFORM_ANY_STATE; 215 | } 216 | } 217 | 218 | xLinkPlatformErrorCode_t parseUsbBootError(usbBootError_t rc) { 219 | switch (rc) { 220 | case USB_BOOT_SUCCESS: 221 | return X_LINK_PLATFORM_SUCCESS; 222 | case USB_BOOT_DEVICE_NOT_FOUND: 223 | return X_LINK_PLATFORM_DEVICE_NOT_FOUND; 224 | case USB_BOOT_TIMEOUT: 225 | return X_LINK_PLATFORM_TIMEOUT; 226 | case USB_BOOT_ERROR: 227 | default: 228 | return X_LINK_PLATFORM_ERROR; 229 | } 230 | } 231 | 232 | xLinkPlatformErrorCode_t parsePCIeHostError(pcieHostError_t rc) { 233 | switch (rc) { 234 | case PCIE_HOST_SUCCESS: 235 | return X_LINK_PLATFORM_SUCCESS; 236 | case PCIE_HOST_DEVICE_NOT_FOUND: 237 | return X_LINK_PLATFORM_DEVICE_NOT_FOUND; 238 | case PCIE_HOST_ERROR: 239 | return X_LINK_PLATFORM_ERROR; 240 | case PCIE_HOST_TIMEOUT: 241 | return X_LINK_PLATFORM_TIMEOUT; 242 | case PCIE_HOST_DRIVER_NOT_LOADED: 243 | return X_LINK_PLATFORM_PCIE_DRIVER_NOT_LOADED; 244 | case PCIE_INVALID_PARAMETERS: 245 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 246 | default: 247 | return X_LINK_PLATFORM_ERROR; 248 | } 249 | } 250 | 251 | xLinkPlatformErrorCode_t getPCIeDeviceName(int index, 252 | XLinkDeviceState_t state, 253 | const deviceDesc_t in_deviceRequirements, 254 | deviceDesc_t* out_foundDevice) { 255 | ASSERT_XLINK_PLATFORM(index >= 0); 256 | ASSERT_XLINK_PLATFORM(out_foundDevice); 257 | if (in_deviceRequirements.platform == X_LINK_MYRIAD_2) { 258 | /** 259 | * There is no PCIe on Myriad 2. Asserting that check 260 | * produces enormous amount of logs in tests. 261 | */ 262 | return X_LINK_PLATFORM_ERROR; 263 | } 264 | 265 | char name[XLINK_MAX_NAME_SIZE] = { 0 }; 266 | 267 | if (strlen(in_deviceRequirements.name) > 0) { 268 | mv_strcpy(name, XLINK_MAX_NAME_SIZE, in_deviceRequirements.name); 269 | } 270 | 271 | pcieHostError_t pcieHostRc = pcie_find_device_port( 272 | index, name, XLINK_MAX_NAME_SIZE, xlinkDeviceStateToPciePlatformState(state)); 273 | 274 | xLinkPlatformErrorCode_t xLinkRc = parsePCIeHostError(pcieHostRc); 275 | 276 | if(xLinkRc == X_LINK_PLATFORM_SUCCESS) 277 | { 278 | if (xLinkRc == X_LINK_PLATFORM_SUCCESS) { 279 | mv_strcpy(out_foundDevice->name, XLINK_MAX_NAME_SIZE, name); 280 | out_foundDevice->protocol = X_LINK_PCIE; 281 | out_foundDevice->platform = X_LINK_MYRIAD_X; 282 | } 283 | 284 | } 285 | return xLinkRc; 286 | } 287 | 288 | xLinkPlatformErrorCode_t getTcpIpDevices(const deviceDesc_t in_deviceRequirements, 289 | deviceDesc_t* out_foundDevices, int sizeFoundDevices, 290 | unsigned int *out_amountOfFoundDevices) 291 | { 292 | ASSERT_XLINK_PLATFORM(out_foundDevices); 293 | ASSERT_XLINK_PLATFORM(out_amountOfFoundDevices); 294 | if (in_deviceRequirements.platform == X_LINK_MYRIAD_2) { 295 | /** 296 | * No case with TCP IP devices on TCP_IP protocol 297 | */ 298 | return X_LINK_PLATFORM_ERROR; 299 | } 300 | 301 | if(in_deviceRequirements.state == X_LINK_UNBOOTED) { 302 | /** 303 | * There is no condition where unbooted 304 | * state device to be found using tcp/ip. 305 | */ 306 | return X_LINK_PLATFORM_DEVICE_NOT_FOUND; 307 | } 308 | 309 | return tcpip_get_devices(in_deviceRequirements, out_foundDevices, sizeFoundDevices, out_amountOfFoundDevices); 310 | } 311 | 312 | // ------------------------------------ 313 | // Helpers implementation. End. 314 | // ------------------------------------ 315 | -------------------------------------------------------------------------------- /src/pc/PlatformDeviceSearchDynamic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | 7 | #include "XLinkPlatform.h" 8 | #include "XLinkPlatformErrorUtils.h" 9 | #include "usb_host.h" 10 | #include "pcie_host.h" 11 | #include "tcpip_host.h" 12 | #include "XLinkStringUtils.h" 13 | #include 14 | #include 15 | 16 | #define MVLOG_UNIT_NAME PlatformDeviceSearchDynamic 17 | #include "XLinkLog.h" 18 | 19 | xLinkPlatformErrorCode_t XLinkPlatformFindDevicesDynamic(const deviceDesc_t in_deviceRequirements, 20 | deviceDesc_t* out_foundDevices, unsigned sizeFoundDevices, 21 | unsigned int *out_amountOfFoundDevices, int timeoutMs, bool (*cb)(deviceDesc_t*, unsigned int)) { 22 | memset(out_foundDevices, sizeFoundDevices, sizeof(deviceDesc_t)); 23 | unsigned numFoundDevices = 0; 24 | *out_amountOfFoundDevices = 0; 25 | 26 | deviceDesc_t* pFoundDevices = out_foundDevices; 27 | 28 | using namespace std::chrono; 29 | auto tstart = steady_clock::now(); 30 | auto timeout = milliseconds(timeoutMs); 31 | bool unlimited = false; 32 | if(timeoutMs == -1) { 33 | unlimited = true; 34 | } 35 | const auto POOL_TIME = milliseconds(330); 36 | 37 | // Create TCP search context upfront 38 | 39 | void* tcpip_ctx; 40 | bool usb_vsc_available = false; 41 | bool tcpip_available = false; 42 | 43 | if(XLinkIsProtocolInitialized(X_LINK_USB_VSC)) { 44 | usb_vsc_available = true; 45 | } 46 | if(XLinkIsProtocolInitialized(X_LINK_TCP_IP) && tcpip_create_search_context(&tcpip_ctx, in_deviceRequirements) == X_LINK_PLATFORM_SUCCESS) { 47 | tcpip_available = true; 48 | } 49 | 50 | xLinkPlatformErrorCode_t status = X_LINK_PLATFORM_TIMEOUT; 51 | do { 52 | 53 | auto titeration = steady_clock::now(); 54 | 55 | switch (in_deviceRequirements.protocol){ 56 | case X_LINK_USB_CDC: 57 | case X_LINK_USB_VSC: 58 | if(!usb_vsc_available) { 59 | return static_cast((int) X_LINK_PLATFORM_DRIVER_NOT_LOADED+in_deviceRequirements.protocol); 60 | } 61 | // Check if protocol is initialized 62 | getUSBDevices(in_deviceRequirements, pFoundDevices, sizeFoundDevices, out_amountOfFoundDevices); 63 | 64 | /* TODO(themarpe) - reenable PCIe 65 | case X_LINK_PCIE: 66 | return getPCIeDeviceName(0, state, in_deviceRequirements, out_foundDevice); 67 | */ 68 | 69 | case X_LINK_TCP_IP: 70 | if(!tcpip_available) { 71 | return static_cast((int) X_LINK_PLATFORM_DRIVER_NOT_LOADED+in_deviceRequirements.protocol); 72 | } 73 | return tcpip_perform_search(tcpip_ctx, pFoundDevices, sizeFoundDevices, out_amountOfFoundDevices); 74 | 75 | case X_LINK_ANY_PROTOCOL: 76 | 77 | // If USB protocol is initialized 78 | if(usb_vsc_available) { 79 | // Find first correct USB Device 80 | numFoundDevices = 0; 81 | getUSBDevices(in_deviceRequirements, pFoundDevices, sizeFoundDevices, &numFoundDevices); 82 | *out_amountOfFoundDevices += numFoundDevices; 83 | pFoundDevices += numFoundDevices; 84 | // Found enough devices, return 85 | if (numFoundDevices >= sizeFoundDevices) { 86 | break; 87 | } else { 88 | sizeFoundDevices -= numFoundDevices; 89 | } 90 | } 91 | 92 | 93 | 94 | /* TODO(themarpe) - reenable PCIe 95 | if(XLinkIsProtocolInitialized(X_LINK_PCIE)) { 96 | numFoundDevices = 0; 97 | PCIe_rc = getPCIeDeviceName(0, state, in_deviceRequirements, out_foundDevice); 98 | // Found enough devices, return 99 | pFoundDevices += numFoundDevices; 100 | if (numFoundDevices >= sizeFoundDevices) { 101 | return X_LINK_PLATFORM_SUCCESS; 102 | } else { 103 | sizeFoundDevices -= numFoundDevices; 104 | } 105 | *out_amountOfFoundDevices += numFoundDevices; 106 | } 107 | */ 108 | 109 | // Try find TCPIP device 110 | if(tcpip_available) { 111 | numFoundDevices = 0; 112 | tcpip_perform_search(tcpip_ctx, pFoundDevices, sizeFoundDevices, &numFoundDevices); 113 | *out_amountOfFoundDevices += numFoundDevices; 114 | pFoundDevices += numFoundDevices; 115 | sizeFoundDevices -= numFoundDevices; 116 | // Found enough devices, return 117 | if (numFoundDevices >= sizeFoundDevices) { 118 | break; 119 | } else { 120 | sizeFoundDevices -= numFoundDevices; 121 | } 122 | } 123 | 124 | break; 125 | default: 126 | mvLog(MVLOG_WARN, "Unknown protocol"); 127 | return X_LINK_PLATFORM_INVALID_PARAMETERS; 128 | } 129 | 130 | // Filter out duplicates - routing table will decide through which interface the packets will traverse 131 | // TODO(themarpe) - properly separate interfaces. 132 | // Either bind to interface addr, or SO_BINDTODEVICE Linux, IP_BOUND_IF macOS, and prefix interface name 133 | { 134 | deviceDesc_t* devices = out_foundDevices; 135 | int write_index = 0; 136 | for(int i = 0; i < *out_amountOfFoundDevices; i++){ 137 | bool duplicate = false; 138 | for(int j = i - 1; j >= 0; j--){ 139 | // Check if duplicate 140 | if(devices[i].protocol == devices[j].protocol && strcmp(devices[i].name, devices[j].name) == 0 && strcmp(devices[i].mxid, devices[j].mxid) == 0){ 141 | duplicate = true; 142 | break; 143 | } 144 | } 145 | if(!duplicate){ 146 | devices[write_index] = devices[i]; 147 | write_index++; 148 | } 149 | } 150 | *out_amountOfFoundDevices = write_index; 151 | } 152 | 153 | // do cb 154 | if(cb) { 155 | if(cb(out_foundDevices, *out_amountOfFoundDevices)) { 156 | // found, exit up ahead 157 | status = X_LINK_PLATFORM_SUCCESS; 158 | break; 159 | } 160 | } 161 | 162 | if(status == X_LINK_PLATFORM_SUCCESS) { 163 | break; 164 | } 165 | 166 | auto tsleep = POOL_TIME - (steady_clock::now() - titeration); 167 | 168 | if(tsleep >= milliseconds(1)) { 169 | std::this_thread::sleep_for(tsleep); 170 | } 171 | 172 | } while(steady_clock::now() - tstart < timeout || unlimited); 173 | 174 | // close TCP_IP search context 175 | if(tcpip_available) { 176 | tcpip_close_search_context(tcpip_ctx); 177 | } 178 | 179 | return status; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /src/pc/ProtocolManager.cpp: -------------------------------------------------------------------------------- 1 | #include "XLink/XLink.h" 2 | #include 3 | 4 | static std::atomic protocolInitialized[X_LINK_NMB_OF_PROTOCOLS]; 5 | 6 | extern "C" void xlinkSetProtocolInitialized(const XLinkProtocol_t protocol, int initialized) { 7 | if(protocol >= 0 && protocol < X_LINK_NMB_OF_PROTOCOLS) { 8 | protocolInitialized[protocol] = initialized; 9 | } 10 | } 11 | 12 | int XLinkIsProtocolInitialized(const XLinkProtocol_t protocol) { 13 | if(protocol >= 0 && protocol < X_LINK_NMB_OF_PROTOCOLS) { 14 | return protocolInitialized[protocol]; 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/pc/Win/include/win_pthread.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #else 8 | #ifndef WIN_PTHREADS 9 | #define WIN_PTHREADS 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #ifndef ETIMEDOUT 22 | #define ETIMEDOUT 110 23 | #define ENOTSUP 134 24 | #endif 25 | 26 | //State related definition 27 | #define PTHREAD_CANCEL_DISABLE 0 28 | #define PTHREAD_CANCEL_ENABLE 0x01 29 | #define PTHREAD_CREATE_DETACHED 0x04 30 | #define PTHREAD_INHERIT_SCHED 0x08 31 | 32 | 33 | //Mutex related definition 34 | 35 | #define PTHREAD_MUTEX_INITIALIZER {(RTL_CRITICAL_SECTION_DEBUG*)-1,-1,0,0,0,0} 36 | 37 | 38 | #if (_MSC_VER == 1800) 39 | struct timespec 40 | { 41 | /* long long in windows is the same as long in unix for 64bit */ 42 | long long tv_sec; 43 | long long tv_nsec; 44 | }; 45 | #elif (_MSC_VER >= 1800) 46 | #include "time.h" 47 | #endif 48 | 49 | typedef struct 50 | { 51 | HANDLE handle; 52 | void *arg; 53 | void *(*start_routine)(void *); 54 | DWORD tid; 55 | unsigned pthread_state; 56 | }pthread_t; 57 | 58 | typedef struct 59 | { 60 | unsigned pthread_state; 61 | void *stack; 62 | size_t stack_size; 63 | }pthread_attr_t; 64 | 65 | 66 | typedef unsigned pthread_mutexattr_t; 67 | typedef CRITICAL_SECTION pthread_mutex_t; 68 | 69 | int pthread_mutex_lock(pthread_mutex_t *mutexm); 70 | int pthread_mutex_unlock(pthread_mutex_t *mutex); 71 | int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); 72 | int pthread_mutex_destroy(pthread_mutex_t *mutex); 73 | 74 | 75 | unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag); 76 | int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val); 77 | 78 | int pthread_attr_init(pthread_attr_t *attr); 79 | int pthread_attr_setinheritsched(pthread_attr_t *attr, int flag); 80 | int pthread_attr_getinheritsched(pthread_attr_t *attr, int *flag); 81 | int pthread_attr_destroy(pthread_attr_t *attr); 82 | 83 | #define pthread_equal(t1, t2) ((t1).tid == (t2).tid) 84 | unsigned int __stdcall _pthread_start_routine(void *args); 85 | int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*func)(void *), void *arg); 86 | #define pthread_join(a, b) _pthread_join(&(a), (b)) 87 | int _pthread_join(pthread_t *thread, void **res); 88 | pthread_t pthread_self(void); 89 | void pthread_exit(void *res); 90 | int pthread_setname_np(pthread_t target_thread, const char * name); 91 | int pthread_getname_np (pthread_t target_thread, char *__buf, size_t len); 92 | 93 | int pthread_detach(pthread_t thread); 94 | 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif /* WIN_PTHREADS */ 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /src/pc/Win/include/win_semaphore.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #else 8 | #ifndef _SEMAPHORE_H_ 9 | #define _SEMAPHORE_H_ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if __STDC_VERSION__ >= 199901L 18 | #define _XOPEN_SOURCE 600 19 | #else 20 | #define _XOPEN_SOURCE 500 21 | #endif /* __STDC_VERSION__ */ 22 | #include "time.h" 23 | 24 | 25 | #if !defined(malloc) 26 | #include 27 | #endif 28 | #if !defined(INT_MAX) 29 | #include 30 | #endif 31 | 32 | 33 | #ifndef SEM_VALUE_MAX 34 | #define SEM_VALUE_MAX INT_MAX 35 | #endif 36 | 37 | 38 | #if (_MSC_VER == 1800) 39 | struct timespec 40 | { 41 | /* long long in windows is the same as long in unix for 64bit */ 42 | long long tv_sec; 43 | long long tv_nsec; 44 | }; 45 | #elif (_MSC_VER >= 1800) 46 | #include "time.h" 47 | #endif 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | struct sem_t_ 54 | { 55 | HANDLE handle; 56 | }; 57 | typedef struct sem_t_ * sem_t; 58 | 59 | 60 | int sem_init(sem_t *sem, int pshared, unsigned int value); 61 | int sem_wait(sem_t *sem); 62 | int sem_timedwait(sem_t *sem, const struct timespec *ts); 63 | int sem_trywait(sem_t *sem); 64 | int sem_post(sem_t *sem); 65 | int sem_destroy(sem_t *sem); 66 | 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | 73 | #endif /* _SEMAPHORE_H_ */ 74 | #endif 75 | 76 | -------------------------------------------------------------------------------- /src/pc/Win/include/win_synchapi.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #else 8 | #ifndef WIN_SYNCHAPI 9 | #define WIN_SYNCHAPI 10 | 11 | #include "win_pthread.h" 12 | #include "synchapi.h" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #define PTHREAD_COND_INITIALIZER {0} 19 | 20 | typedef struct _pthread_condattr_t pthread_condattr_t; 21 | 22 | typedef struct 23 | { 24 | CONDITION_VARIABLE _cv; 25 | } 26 | pthread_cond_t; 27 | 28 | int pthread_cond_init(pthread_cond_t* __cond, const pthread_condattr_t* __cond_attr); 29 | int pthread_cond_destroy(pthread_cond_t* __cond); 30 | 31 | int pthread_cond_wait(pthread_cond_t *__cond, 32 | pthread_mutex_t *__mutex); 33 | int pthread_cond_timedwait(pthread_cond_t* __cond, 34 | pthread_mutex_t* __mutex, 35 | const struct timespec* __abstime); 36 | 37 | int pthread_cond_signal(pthread_cond_t* __cond); 38 | int pthread_cond_broadcast(pthread_cond_t* __cond); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* WIN_MUTEX */ 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /src/pc/Win/include/win_time.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #include 8 | #else 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #ifndef _WIN_TIME_H 14 | #define _WIN_TIME_H 15 | 16 | #if __STDC_VERSION__ >= 199901L 17 | #define _XOPEN_SOURCE 600 18 | #else 19 | #define _XOPEN_SOURCE 500 20 | #endif /* __STDC_VERSION__ */ 21 | 22 | #include "time.h" 23 | #include "windows.h" 24 | #ifndef CLOCK_REALTIME 25 | #define CLOCK_REALTIME 0 26 | #endif 27 | 28 | #ifndef CLOCK_MONOTONIC 29 | #define CLOCK_MONOTONIC 0 30 | #endif 31 | 32 | #define sleep(x) Sleep((DWORD)x) 33 | #define usleep(x) Sleep((DWORD)(x/1000)) 34 | 35 | 36 | int clock_gettime(int, struct timespec *); 37 | 38 | #endif // _WIN_TIME_H 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif // __GNUC__ 45 | 46 | -------------------------------------------------------------------------------- /src/pc/Win/src/win_pthread.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #else 8 | #include "win_pthread.h" 9 | #include 10 | #include 11 | 12 | #include "XLinkStringUtils.h" 13 | 14 | typedef HRESULT(WINAPI* SetThreadDescriptionDecl)(HANDLE hThread, 15 | PCWSTR lpThreadDescription); 16 | typedef HRESULT(WINAPI* GetThreadDescriptionDecl)(HANDLE hThread, 17 | PWSTR* ppszThreadDescription); 18 | 19 | //Mutex implementation 20 | int pthread_mutex_lock(pthread_mutex_t *mutex) 21 | { 22 | EnterCriticalSection(mutex); 23 | return 0; 24 | } 25 | 26 | int pthread_mutex_unlock(pthread_mutex_t *mutex) 27 | { 28 | LeaveCriticalSection(mutex); 29 | return 0; 30 | } 31 | 32 | int pthread_mutex_init(pthread_mutex_t *mutex, 33 | pthread_mutexattr_t *attr) 34 | { 35 | (void)attr; 36 | InitializeCriticalSection(mutex); 37 | 38 | return 0; 39 | } 40 | 41 | int pthread_mutex_destroy(pthread_mutex_t *mutex) 42 | { 43 | DeleteCriticalSection(mutex); 44 | return 0; 45 | } 46 | 47 | //State implementation 48 | unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag) 49 | { 50 | return attr->pthread_state & flag; 51 | } 52 | 53 | int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val) 54 | { 55 | if (~flag & val) return EINVAL; 56 | attr->pthread_state &= ~flag; 57 | attr->pthread_state |= val; 58 | 59 | return 0; 60 | } 61 | 62 | //Attribute implementation 63 | int pthread_attr_init(pthread_attr_t *attr) 64 | { 65 | attr->pthread_state = PTHREAD_CANCEL_ENABLE; 66 | attr->stack = NULL; 67 | attr->stack_size = 0; 68 | return 0; 69 | } 70 | 71 | int pthread_attr_destroy(pthread_attr_t *attr) 72 | { 73 | (void)attr; 74 | return 0; 75 | } 76 | 77 | int pthread_attr_setinheritsched(pthread_attr_t *attr, int flag) 78 | { 79 | return _pthread_set_state(attr, PTHREAD_INHERIT_SCHED, flag); 80 | } 81 | 82 | int pthread_attr_getinheritsched(pthread_attr_t *attr, int *flag) 83 | { 84 | *flag = _pthread_get_state(attr, PTHREAD_INHERIT_SCHED); 85 | return 0; 86 | } 87 | 88 | #define pthread_attr_getschedpolicy(ATTR, POLICY) ENOTSUP 89 | #define pthread_attr_setschedpolicy(ATTR, POLICY) ENOTSUP 90 | 91 | 92 | //Pthread creation 93 | unsigned int __stdcall _pthread_start_routine(void *args) 94 | { 95 | pthread_t *thread = args; 96 | thread->tid = GetCurrentThreadId(); 97 | thread->arg = thread->start_routine(thread->arg); 98 | return 0; 99 | } 100 | 101 | int pthread_create(pthread_t *thread, pthread_attr_t *attr, 102 | void *(*start_routine)(void *), void *arg) 103 | { 104 | unsigned stack_size = 0; 105 | 106 | /* Save data in pthread_t */ 107 | thread->arg = arg; 108 | thread->start_routine = start_routine; 109 | thread->pthread_state = PTHREAD_CANCEL_ENABLE; 110 | thread->handle = (HANDLE)-1; 111 | _ReadWriteBarrier(); 112 | 113 | if (attr) 114 | { 115 | thread->pthread_state = attr->pthread_state; 116 | stack_size = (unsigned)attr->stack_size; 117 | } 118 | 119 | thread->handle = (HANDLE)_beginthreadex((void *)NULL, stack_size, _pthread_start_routine, thread, 0, NULL); 120 | 121 | /* Failed */ 122 | if (!thread->handle) 123 | return 1; 124 | 125 | return 0; 126 | } 127 | 128 | int pthread_detach(pthread_t thread) 129 | { 130 | CloseHandle(thread.handle); 131 | _ReadWriteBarrier(); 132 | thread.handle = 0; 133 | 134 | return 0; 135 | } 136 | 137 | int _pthread_join(pthread_t *thread, void **res) 138 | { 139 | 140 | DWORD result = WaitForSingleObject(thread->handle, INFINITE); 141 | 142 | switch (result) { 143 | case WAIT_OBJECT_0: 144 | if (res) 145 | *res = thread->arg; 146 | return 0; 147 | case WAIT_ABANDONED: 148 | return EINVAL; 149 | default: 150 | return 1; 151 | } 152 | } 153 | 154 | pthread_t pthread_self(void) 155 | { 156 | pthread_t t = { 0 }; 157 | 158 | t.tid = GetCurrentThreadId(); 159 | t.arg = NULL; 160 | t.start_routine = NULL; 161 | t.pthread_state = PTHREAD_CANCEL_ENABLE; 162 | t.handle = GetCurrentThread(); 163 | 164 | return t; 165 | } 166 | 167 | void pthread_exit(void *res) 168 | { 169 | if(res) 170 | { 171 | _endthreadex(*(int *)res); 172 | } 173 | else 174 | _endthreadex(0); 175 | } 176 | 177 | #define MAX_THREAD_NAME_LENGHT 256 178 | 179 | int pthread_setname_np(pthread_t target_thread, const char * name) 180 | { 181 | wchar_t wstr[MAX_THREAD_NAME_LENGHT]; 182 | mbstowcs(wstr, name, MAX_THREAD_NAME_LENGHT); 183 | 184 | SetThreadDescriptionDecl set_thread_description_func = 185 | (SetThreadDescriptionDecl)(GetProcAddress( 186 | GetModuleHandle("Kernel32.dll"), "SetThreadDescription")); 187 | 188 | if (!set_thread_description_func) { 189 | return 0; 190 | } 191 | 192 | HRESULT hr = set_thread_description_func(target_thread.handle, wstr); 193 | 194 | if (FAILED(hr)) 195 | { 196 | return 1; 197 | } 198 | return 0; 199 | } 200 | 201 | int pthread_getname_np(pthread_t target_thread, char *buf, size_t len) 202 | { 203 | wchar_t* wstr; 204 | 205 | GetThreadDescriptionDecl get_thread_description_func = 206 | (GetThreadDescriptionDecl)(GetProcAddress( 207 | GetModuleHandle("Kernel32.dll"), "GetThreadDescription")); 208 | 209 | if (!get_thread_description_func) { 210 | return 0; 211 | } 212 | 213 | HRESULT hr = get_thread_description_func(target_thread.handle, &wstr); 214 | if (FAILED(hr)) 215 | { 216 | return 1; 217 | } 218 | 219 | char data[MAX_THREAD_NAME_LENGHT]; 220 | wcstombs(data, wstr, MAX_THREAD_NAME_LENGHT); 221 | LocalFree(wstr); 222 | 223 | mv_strncpy(buf, len, data, len - 1); 224 | return 0; 225 | } 226 | 227 | #endif 228 | 229 | -------------------------------------------------------------------------------- /src/pc/Win/src/win_semaphore.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | //lightweight semaphone wrapper 6 | 7 | #ifdef __GNUC__ 8 | #include 9 | #else 10 | #include "win_semaphore.h" 11 | #include "win_time.h" 12 | 13 | 14 | static int ls_set_errno(int result){ 15 | if (result != 0) { 16 | errno = result; 17 | return -1; 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | 24 | //Create an semaphore. 25 | int sem_init(sem_t *sem, int pshared, unsigned int value){ 26 | sem_t s = NULL; 27 | 28 | if (sem == NULL || value > (unsigned int) SEM_VALUE_MAX){ 29 | return ls_set_errno(EINVAL); 30 | } 31 | 32 | if (NULL == (s = (sem_t)calloc(1, sizeof(*s)))){ 33 | return ls_set_errno(ENOMEM); 34 | } 35 | 36 | if (pshared != 0){ 37 | free(s); 38 | //share between processes 39 | return ls_set_errno(EPERM); 40 | } 41 | 42 | if ((s->handle = CreateSemaphoreA(NULL, value, SEM_VALUE_MAX, NULL)) == NULL){ 43 | free(s); 44 | return ls_set_errno(ENOSPC); 45 | } 46 | 47 | *sem = s; 48 | return 0; 49 | } 50 | 51 | 52 | //Wait for a semaphore 53 | int sem_wait(sem_t *sem){ 54 | if (sem == NULL || *sem == NULL) { 55 | return ls_set_errno(EINVAL); 56 | } 57 | sem_t s = *sem; 58 | 59 | if (WaitForSingleObject(s->handle, INFINITE) != WAIT_OBJECT_0){ 60 | return ls_set_errno(EINVAL); 61 | } 62 | 63 | return 0; 64 | } 65 | 66 | 67 | //Wait for a semaphore 68 | int sem_timedwait(sem_t *sem, const struct timespec *ts) { 69 | if (sem == NULL || *sem == NULL) { 70 | return ls_set_errno(EINVAL); 71 | } 72 | 73 | sem_t s = *sem; 74 | 75 | struct timespec cts; 76 | if (clock_gettime(CLOCK_REALTIME, &cts) == -1) { 77 | return ls_set_errno(EINVAL); 78 | } 79 | 80 | unsigned long long t = (ts->tv_sec - cts.tv_sec) * 1000; 81 | t += (ts->tv_nsec - cts.tv_nsec) / 1000000; 82 | 83 | if (WaitForSingleObject(s->handle, (DWORD)t) != WAIT_OBJECT_0) { 84 | return ls_set_errno(EINVAL); 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | 91 | //Wait for a semaphore 92 | int sem_trywait(sem_t *sem){ 93 | if (sem == NULL || *sem == NULL) { 94 | return ls_set_errno(EINVAL); 95 | } 96 | sem_t s = *sem; 97 | if (WaitForSingleObject(s->handle, 0) != WAIT_OBJECT_0) { 98 | return ls_set_errno(EINVAL); 99 | } 100 | return 0; 101 | } 102 | 103 | 104 | //Release a semaphone 105 | int sem_post(sem_t *sem){ 106 | if (sem == NULL || *sem == NULL){ 107 | return ls_set_errno(EINVAL); 108 | } 109 | 110 | sem_t s = *sem; 111 | if (ReleaseSemaphore(s->handle, 1, NULL) == 0){ 112 | return ls_set_errno(EINVAL); 113 | } 114 | 115 | return 0; 116 | } 117 | 118 | 119 | 120 | //Destroy a semaphore 121 | int sem_destroy(sem_t *sem){ 122 | if (sem == NULL || *sem == NULL){ 123 | return ls_set_errno(EINVAL); 124 | } 125 | 126 | sem_t s = *sem; 127 | if (CloseHandle(s->handle) == 0){ 128 | return ls_set_errno(EINVAL); 129 | } 130 | 131 | free(s); 132 | *sem = NULL; 133 | return 0; 134 | } 135 | 136 | #endif 137 | 138 | -------------------------------------------------------------------------------- /src/pc/Win/src/win_synchapi.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #else 8 | #include "win_synchapi.h" 9 | 10 | int pthread_cond_init(pthread_cond_t* __cond, const pthread_condattr_t* __cond_attr) 11 | { 12 | if (__cond == NULL) { 13 | return ERROR_INVALID_HANDLE; 14 | } 15 | 16 | (void)__cond_attr; 17 | InitializeConditionVariable(&__cond->_cv); 18 | return 0; 19 | } 20 | 21 | int pthread_cond_destroy(pthread_cond_t* __cond) 22 | { 23 | (void)__cond; 24 | return 0; 25 | } 26 | 27 | int pthread_cond_wait(pthread_cond_t *__cond, 28 | pthread_mutex_t *__mutex) 29 | { 30 | if (__cond == NULL || __mutex == NULL) 31 | return ERROR_INVALID_HANDLE; 32 | return pthread_cond_timedwait(__cond, __mutex, NULL); 33 | } 34 | 35 | int pthread_cond_timedwait(pthread_cond_t* __cond, 36 | pthread_mutex_t* __mutex, 37 | const struct timespec* __abstime) 38 | { 39 | if (__cond == NULL) { 40 | return ERROR_INVALID_HANDLE; 41 | } 42 | 43 | long long msec = INFINITE; 44 | if (__abstime != NULL) { 45 | msec = __abstime->tv_sec * 1000 + __abstime->tv_nsec / 1000000; 46 | } 47 | 48 | // SleepConditionVariableCS returns bool=true on success. 49 | if (SleepConditionVariableCS(&__cond->_cv, __mutex, (DWORD)msec)) 50 | return 0; 51 | 52 | const int rc = (int)GetLastError(); 53 | return rc == ERROR_TIMEOUT ? ETIMEDOUT : rc; 54 | } 55 | 56 | int pthread_cond_signal(pthread_cond_t *__cond) 57 | { 58 | if (__cond == NULL) { 59 | return ERROR_INVALID_HANDLE; 60 | } 61 | 62 | WakeConditionVariable(&__cond->_cv); 63 | return 0; 64 | } 65 | 66 | int pthread_cond_broadcast(pthread_cond_t *__cond) 67 | { 68 | if (__cond == NULL) { 69 | return ERROR_INVALID_HANDLE; 70 | } 71 | 72 | WakeAllConditionVariable(&__cond->_cv); 73 | return 0; 74 | } 75 | 76 | #endif 77 | 78 | -------------------------------------------------------------------------------- /src/pc/Win/src/win_time.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __GNUC__ 6 | #include 7 | #include 8 | #else 9 | #include "win_time.h" 10 | 11 | int clock_gettime(int dummy, struct timespec *spec) 12 | { 13 | dummy; // for unreferenced formal parameter warning 14 | __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); 15 | wintime -= 116444736000000000LL; //1jan1601 to 1jan1970 16 | spec->tv_sec = wintime / 10000000LL; //seconds 17 | spec->tv_nsec = wintime % 10000000LL * 100; //nano-seconds 18 | return 0; 19 | } 20 | 21 | #endif // __GNUC__ 22 | 23 | -------------------------------------------------------------------------------- /src/pc/Win/src/win_usb_host.cpp: -------------------------------------------------------------------------------- 1 | // Win32 api and MSVC only; not mingw, *nix, etc. 2 | #if defined(_WIN32) && defined(_MSC_VER) 3 | 4 | // project 5 | #define MVLOG_UNIT_NAME xLinkUsb 6 | 7 | // libraries 8 | #ifdef XLINK_LIBUSB_LOCAL 9 | #include 10 | #else 11 | #include 12 | #endif 13 | 14 | #include "XLink/XLinkLog.h" 15 | #include "usb_host.h" 16 | 17 | // std 18 | #include 19 | #include 20 | 21 | int usbInitialize_customdir(void** hContext) { 22 | // get handle to the module containing a XLink static function/var 23 | // can not use GetModuleFileNameW(nullptr) because when the main depthai app is a DLL (e.g. plugin), 24 | // then it returns the main EXE which is usually wrong 25 | HMODULE hXLink = nullptr; 26 | if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)&MVLOGLEVEL(global), &hXLink) == 0) { 27 | return LIBUSB_ERROR_OVERFLOW; 28 | } 29 | 30 | // get path to that module 31 | std::array rawPath = {}; 32 | const auto len = GetModuleFileNameW(hXLink, rawPath.data(), static_cast(rawPath.size())); 33 | if ((len == 0) || (len == rawPath.size())) { 34 | return LIBUSB_ERROR_OVERFLOW; 35 | } 36 | 37 | // remove filename with string::find_last_of(), _wsplitpath_s(), PathCchRemoveFileSpec() 38 | // using PathCchRemoveFileSpec() as it handles special cases 39 | if (PathCchRemoveFileSpec(rawPath.data(), rawPath.size()) != S_OK) { 40 | return LIBUSB_ERROR_OVERFLOW; 41 | } 42 | 43 | // persist existing custom DLL load path 44 | bool oldGetError = false; 45 | std::array oldDllDir = {}; 46 | if (GetDllDirectoryW(static_cast(oldDllDir.size()), oldDllDir.data())) { 47 | // nothing 48 | } 49 | else { 50 | // SetDllDirectoryW() previously unused, or an error 51 | oldGetError = true; 52 | } 53 | 54 | // set custom dll load directory 55 | if (SetDllDirectoryW(rawPath.data()) == 0) { 56 | return LIBUSB_ERROR_OVERFLOW; 57 | } 58 | 59 | // initialize libusb 60 | int initResult = LIBUSB_SUCCESS; 61 | __try { 62 | initResult = libusb_init((libusb_context**)hContext); 63 | } 64 | __except (EXCEPTION_EXECUTE_HANDLER) { 65 | initResult = LIBUSB_ERROR_OVERFLOW; 66 | } 67 | 68 | // restore custom dll load directory 69 | SetDllDirectoryW(oldGetError ? nullptr : oldDllDir.data()); 70 | 71 | return initResult; 72 | } 73 | 74 | #endif // defined(_WIN32) && defined(_MSC_VER) 75 | -------------------------------------------------------------------------------- /src/pc/protocols/pcie_host.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifndef PCIE_HOST_H 6 | #define PCIE_HOST_H 7 | 8 | #include "XLinkPlatform.h" 9 | 10 | // ------------------------------------ 11 | // PCIe Enums 12 | // ------------------------------------ 13 | typedef enum { 14 | /* PCIE_PLATFORM_ANY_STATE intended for use in the device requirement, 15 | / but also means an unknown state if we cannot get the device status */ 16 | PCIE_PLATFORM_ANY_STATE = 0, 17 | PCIE_PLATFORM_BOOTED = 1, 18 | PCIE_PLATFORM_UNBOOTED = 2, 19 | } pciePlatformState_t; 20 | 21 | typedef enum { 22 | PCIE_HOST_SUCCESS = 0, 23 | PCIE_HOST_DEVICE_NOT_FOUND = -1, 24 | PCIE_HOST_ERROR = -2, 25 | PCIE_HOST_TIMEOUT = -3, 26 | PCIE_HOST_DRIVER_NOT_LOADED = -4, 27 | PCIE_INVALID_PARAMETERS = -5 28 | } pcieHostError_t; 29 | 30 | // ------------------------------------ 31 | // PCIe functions 32 | // ------------------------------------ 33 | 34 | /** 35 | * @brief Open device on specified slot 36 | * @param[in] slot - device address 37 | * @param[out] fd - Opened filedescriptor 38 | */ 39 | pcieHostError_t pcie_init(const char *slot, void **fd); 40 | 41 | pcieHostError_t pcie_close(void *fd); 42 | 43 | #if (!defined(_WIN32)) 44 | pcieHostError_t pcie_boot_device(int fd, const char *buffer, size_t length); 45 | pcieHostError_t pcie_reset_device(int fd); 46 | 47 | #else // Windows 48 | pcieHostError_t pcie_boot_device(HANDLE fd, const char *buffer, size_t length); 49 | pcieHostError_t pcie_reset_device(HANDLE fd); 50 | #endif 51 | 52 | int pcie_write(void *fd, void * buf, size_t bufSize); 53 | 54 | int pcie_read(void *fd, void *buf, size_t bufSize); 55 | 56 | 57 | /** 58 | * @brief Get device name on index 59 | * @param port_name Port on which device is located. 60 | * If not empty, function will search for device with this name 61 | */ 62 | pcieHostError_t pcie_find_device_port( 63 | int index, char* port_name, int name_length, pciePlatformState_t requiredState); 64 | 65 | // ------------------------------------ 66 | // PCIE Driver specific calls 67 | // ------------------------------------ 68 | /** 69 | * @brief Get state for PCIe device on specified port 70 | */ 71 | pcieHostError_t pcie_get_device_state( 72 | const char *port_name, pciePlatformState_t *platformState); 73 | 74 | #endif // PCIE_HOST_H 75 | -------------------------------------------------------------------------------- /src/pc/protocols/tcpip_host.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tcpip_host.h 3 | * @brief TCP/IP helper public header 4 | */ 5 | 6 | #ifndef TCPIP_HOST_H 7 | #define TCPIP_HOST_H 8 | 9 | /* **************************************************************************/ 10 | /* Include Files */ 11 | /* **************************************************************************/ 12 | #include "XLinkPlatform.h" 13 | #include "XLinkPublicDefines.h" 14 | 15 | 16 | #if (defined(_WIN32) || defined(_WIN64)) 17 | #include 18 | #include 19 | typedef SOCKET TCPIP_SOCKET; 20 | #else 21 | #include 22 | #include 23 | #include 24 | #include 25 | typedef int TCPIP_SOCKET; 26 | #endif 27 | 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* **************************************************************************/ 34 | /* Public Macro Definitions */ 35 | /* **************************************************************************/ 36 | #define TCPIP_LINK_SOCKET_PORT 11490 37 | 38 | 39 | /* **************************************************************************/ 40 | /* Public Type Definitions */ 41 | /* **************************************************************************/ 42 | /* TCP/IP error list */ 43 | typedef enum 44 | { 45 | TCPIP_HOST_DEVICE_FOUND = 1, 46 | TCPIP_HOST_SUCCESS = 0, 47 | TCPIP_HOST_DEVICE_NOT_FOUND = -1, 48 | TCPIP_HOST_ERROR = -2, 49 | TCPIP_HOST_TIMEOUT = -3, 50 | TCPIP_HOST_DRIVER_NOT_LOADED = -4, 51 | TCPIP_INVALID_PARAMETERS = -5 52 | } tcpipHostError_t; 53 | 54 | /* Host-to-device command list */ 55 | typedef enum 56 | { 57 | TCPIP_HOST_CMD_NO_COMMAND = 0, 58 | TCPIP_HOST_CMD_DEVICE_DISCOVER = 1, 59 | TCPIP_HOST_CMD_DEVICE_INFO = 2, 60 | TCPIP_HOST_CMD_RESET = 3, 61 | TCPIP_HOST_CMD_DEVICE_DISCOVERY_EX = 4, 62 | } tcpipHostCommand_t; 63 | 64 | /* Device state */ 65 | typedef enum 66 | { 67 | TCPIP_HOST_STATE_BOOTED = 1, 68 | TCPIP_HOST_STATE_BOOTLOADER = 3, 69 | TCPIP_HOST_STATE_FLASH_BOOTED = 4, 70 | } tcpipHostDeviceState_t; 71 | 72 | /* Device response payload */ 73 | typedef struct 74 | { 75 | tcpipHostCommand_t command; 76 | char mxid[32]; 77 | uint32_t state; 78 | } tcpipHostDeviceDiscoveryResp_t; 79 | 80 | /* Device response payload extended*/ 81 | typedef struct 82 | { 83 | tcpipHostCommand_t command; 84 | char id[32]; 85 | uint32_t state; 86 | uint32_t protocol; 87 | uint32_t platform; 88 | uint16_t portHttp; 89 | uint16_t portHttps; 90 | } tcpipHostDeviceDiscoveryExResp_t; 91 | 92 | /* **************************************************************************/ 93 | /* Public Function Declarations */ 94 | /* **************************************************************************/ 95 | 96 | /** 97 | * @brief Close socket 98 | * 99 | * @param[in] socket Socket 100 | * @retval TCPIP_HOST_ERROR Failed to close socket 101 | * @retval TCPIP_HOST_SUCCESS Success to close socket 102 | */ 103 | tcpipHostError_t tcpip_close_socket(TCPIP_SOCKET socket); 104 | 105 | /** 106 | * @brief Broadcast message and get all devices responses with their IPs 107 | * 108 | * @param[in] state Device state which to search for 109 | * @param[out] devices Pointer to store device information 110 | * @param[in] devices_size Size of devices array 111 | * @param[out] device_count Total device IP address obtained 112 | * @param[in] target_ip Target IP address to be checked 113 | * @retval TCPIP_HOST_ERROR Failed to get network interface informations 114 | * @retval TCPIP_HOST_SUCCESS Received all device IP address available 115 | */ 116 | xLinkPlatformErrorCode_t tcpip_get_devices(const deviceDesc_t in_deviceRequirements, deviceDesc_t* devices, size_t devices_size, unsigned int* device_count); 117 | 118 | xLinkPlatformErrorCode_t tcpip_create_search_context(void** pctx, const deviceDesc_t in_deviceRequirements); 119 | xLinkPlatformErrorCode_t tcpip_perform_search(void* ctx, deviceDesc_t* devices, size_t devices_size, unsigned int* device_count); 120 | xLinkPlatformErrorCode_t tcpip_close_search_context(void* ctx); 121 | 122 | /** 123 | * Send a boot to bootloader message to device with address 'name' 124 | * @param name device 125 | * @returns X_LINK_PLATFORM_SUCCESS If successfully sent boot to bootloader request or X_LINK_PLATFORM_ERROR couldn't send boot to bootloader request 126 | */ 127 | xLinkPlatformErrorCode_t tcpip_boot_bootloader(const char* name); 128 | 129 | 130 | #ifdef __cplusplus 131 | } 132 | #endif 133 | 134 | #endif /* TCPIP_HOST_H */ -------------------------------------------------------------------------------- /src/pc/protocols/usb_host.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #include 10 | #include "XLink/XLink.h" 11 | #include "XLink/XLinkPlatform.h" 12 | 13 | #define AUTO_VID 0 14 | #define AUTO_PID 0 15 | #define AUTO_UNBOOTED_PID -1 16 | 17 | #define DEFAULT_OPENVID 0x03E7 18 | #ifdef ALTERNATE_PID 19 | #define DEFAULT_OPENPID 0xf63c // Once opened in VSC mode, VID/PID change 20 | #else 21 | #define DEFAULT_OPENPID 0xf63b // Once opened in VSC mode, VID/PID change 22 | #endif 23 | #define DEFAULT_UNBOOTVID 0x03E7 24 | #define DEFAULT_UNBOOTPID_2485 0x2485 25 | #define DEFAULT_UNBOOTPID_2150 0x2150 26 | #define DEFAULT_BOOTLOADER_PID 0xf63c 27 | #define DEFAULT_FLASH_BOOTED_PID 0xf63d 28 | #define DEFAULT_CHUNKSZ 1024*1024 29 | 30 | 31 | typedef enum usbBootError { 32 | USB_BOOT_SUCCESS = 0, 33 | USB_BOOT_ERROR, 34 | USB_BOOT_DEVICE_NOT_FOUND, 35 | USB_BOOT_TIMEOUT 36 | } usbBootError_t; 37 | 38 | #ifdef XLINK_ENABLE_LIBUSB 39 | 40 | xLinkPlatformErrorCode_t getUSBDevices(const deviceDesc_t in_deviceRequirements, 41 | deviceDesc_t* out_foundDevices, int sizeFoundDevices, 42 | unsigned int *out_amountOfFoundDevices); 43 | int usbInitialize(void* options); 44 | int usbInitialize_customdir(void** hContext); 45 | 46 | int usb_boot(const char *addr, const void *mvcmd, unsigned size); 47 | int get_pid_by_name(const char* name); 48 | 49 | xLinkPlatformErrorCode_t usbLinkBootBootloader(const char* path); 50 | int usbPlatformConnect(const char *devPathRead, const char *devPathWrite, void **fd); 51 | int usbPlatformClose(void *fd); 52 | int usbPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length); 53 | 54 | int usbPlatformRead(void *fd, void *data, int size); 55 | int usbPlatformWrite(void *fd, void *data, int size); 56 | 57 | #else 58 | 59 | // Error out on these function calls 60 | static inline int usbInitialize(void* options) { return -1; } 61 | static inline xLinkPlatformErrorCode_t usbLinkBootBootloader(const char* path) { return X_LINK_PLATFORM_USB_DRIVER_NOT_LOADED; } 62 | 63 | static inline int usbPlatformConnect(const char *devPathRead, const char *devPathWrite, void **fd) { return -1; } 64 | static inline int usbPlatformClose(void *fd) { return -1; } 65 | static inline int usbPlatformBootFirmware(const deviceDesc_t* deviceDesc, const char* firmware, size_t length) { return -1; } 66 | 67 | static inline int usbPlatformRead(void *fd, void *data, int size) { return -1; } 68 | static inline int usbPlatformWrite(void *fd, void *data, int size) { return -1; } 69 | 70 | static inline xLinkPlatformErrorCode_t getUSBDevices(const deviceDesc_t in_deviceRequirements, 71 | deviceDesc_t* out_foundDevices, int sizeFoundDevices, 72 | unsigned int *out_amountOfFoundDevices) { 73 | return X_LINK_PLATFORM_USB_DRIVER_NOT_LOADED; 74 | } 75 | 76 | #endif 77 | 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | -------------------------------------------------------------------------------- /src/pc/protocols/usb_mx_id.cpp: -------------------------------------------------------------------------------- 1 | #include "usb_mx_id.h" 2 | 3 | #include "XLinkPublicDefines.h" 4 | 5 | #if (defined(_WIN32) || defined(_WIN64) ) 6 | #include "win_time.h" 7 | #else 8 | #include "time.h" 9 | #endif 10 | 11 | #include "string.h" 12 | #include 13 | #include 14 | 15 | static double steady_seconds() 16 | { 17 | struct timespec ts; 18 | clock_gettime(CLOCK_MONOTONIC, &ts); 19 | return ts.tv_sec + ts.tv_nsec * 1e-9; 20 | } 21 | 22 | #define ADDRESS_BUFF_SIZE 35 23 | 24 | // Commands and executable to read serial number from unbooted MX device 25 | static const uint8_t mxid_read_cmd[] = { 26 | // Header 27 | 0x4d, 0x41, 0x32, 0x78, 28 | // WD Protection - start 29 | 0x9A, 0xA8, 0x00, 0x32, 0x20, 0xAD, 0xDE, 0xD0, 0xF1, 30 | 0x9A, 0x9C, 0x00, 0x32, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 31 | 0x9A, 0xA8, 0x00, 0x32, 0x20, 0xAD, 0xDE, 0xD0, 0xF1, 32 | 0x9A, 0xA4, 0x00, 0x32, 0x20, 0x01, 0x00, 0x00, 0x00, 33 | // Payload 34 | 0x8a, 0x00, 0x00, 0x20, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x08, 0x03, 0x64, 35 | 0x61, 0x10, 0x84, 0x6c, 0x61, 0x10, 0x82, 0x00, 0x80, 0x00, 0xc4, 0x00, 0x40, 0x00, 0xc6, 0x03, 36 | 0xa0, 0x08, 0x84, 0x00, 0x40, 0x00, 0xc6, 0x03, 0x80, 0x88, 0x80, 0xfe, 0xff, 0xbf, 0x12, 0x00, 37 | 0x00, 0x00, 0x01, 0x08, 0xe0, 0xc3, 0x81, 0x00, 0x00, 0x00, 0x01, 0xa0, 0xbf, 0xe3, 0x9d, 0x00, 38 | 0x0c, 0x08, 0x3b, 0x68, 0x61, 0x17, 0xb8, 0x00, 0x00, 0x27, 0xc0, 0xf0, 0xff, 0xff, 0x7f, 0x00, 39 | 0x00, 0x00, 0x01, 0x70, 0x61, 0x17, 0x82, 0x64, 0x61, 0x17, 0xba, 0x00, 0x40, 0x00, 0xc2, 0x28, 40 | 0x00, 0x00, 0x03, 0x00, 0x00, 0x27, 0xc2, 0xe9, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 41 | 0x40, 0x27, 0xc0, 0x08, 0xe0, 0xc7, 0x81, 0x00, 0x00, 0xe8, 0x81, 0xa0, 0xbf, 0xe3, 0x9d, 0x00, 42 | 0x0c, 0x08, 0x3b, 0x64, 0x61, 0x17, 0x82, 0x68, 0x61, 0x17, 0xb8, 0x03, 0x20, 0x10, 0x84, 0x04, 43 | 0x00, 0x00, 0x37, 0x00, 0x40, 0x20, 0xc4, 0xdd, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 44 | 0x00, 0x27, 0xf6, 0xda, 0xff, 0xff, 0x7f, 0x10, 0xe0, 0x16, 0xb6, 0x00, 0x00, 0x27, 0xf6, 0xd7, 45 | 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x08, 0x20, 0x10, 0x82, 0x00, 0x00, 0x27, 0xc2, 0xd3, 46 | 0xff, 0xff, 0x7f, 0x70, 0x61, 0x17, 0xba, 0x00, 0x40, 0x07, 0xc2, 0x00, 0x00, 0x26, 0xc2, 0x09, 47 | 0x20, 0x10, 0x82, 0x00, 0x00, 0x27, 0xc2, 0xcd, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 48 | 0x40, 0x07, 0xc2, 0x04, 0x20, 0x26, 0xc2, 0x0a, 0x20, 0x10, 0x82, 0x00, 0x00, 0x27, 0xc2, 0xc7, 49 | 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x07, 0xc2, 0x08, 0x20, 0x26, 0xc2, 0xcf, 50 | 0xff, 0xff, 0x7f, 0x00, 0x00, 0xe8, 0x81, 0xa0, 0xbf, 0xe3, 0x9d, 0x00, 0x00, 0x1c, 0x11, 0xdb, 51 | 0xff, 0xff, 0x7f, 0x00, 0x20, 0x10, 0xb0, 0x08, 0xe0, 0xc7, 0x81, 0x00, 0x00, 0xe8, 0x81, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xfc, 0x00, 0x20, 0x70, 53 | 0x84, 0x00, 0x00, 0x00, 0x70, 0x09, 0x00, 54 | }; 55 | 56 | // WD Protection - end 57 | static const uint8_t mxid_read_end_cmd[] = { 58 | 0x9A, 0xA8, 0x00, 0x32, 0x20, 0xAD, 0xDE, 0xD0, 0xF1, 59 | 0x9A, 0xA4, 0x00, 0x32, 0x20, 0x00, 0x00, 0x00, 0x00, 60 | 0x9A, 0xA8, 0x00, 0x32, 0x20, 0xAD, 0xDE, 0xD0, 0xF1, 61 | 0x9A, 0x9C, 0x00, 0x32, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 62 | }; 63 | 64 | const uint8_t* usb_mx_id_get_payload() { 65 | return mxid_read_cmd; 66 | } 67 | 68 | int usb_mx_id_get_payload_size() { 69 | return sizeof(mxid_read_cmd); 70 | } 71 | 72 | const uint8_t* usb_mx_id_get_payload_end() { 73 | return mxid_read_end_cmd; 74 | } 75 | 76 | int usb_mx_id_get_payload_end_size() { 77 | return sizeof(mxid_read_end_cmd); 78 | } 79 | 80 | // list of devices for which the mx_id was already resolved (with small timeout) 81 | // Some consts 82 | #define MX_ID_LIST_SIZE 16 83 | const double LIST_ENTRY_TIMEOUT_SEC = 0.5; 84 | typedef struct { 85 | char mx_id[XLINK_MAX_MX_ID_SIZE]; 86 | char compat_name[ADDRESS_BUFF_SIZE]; 87 | double timestamp; 88 | } MxIdListEntry; 89 | static MxIdListEntry list_mx_id[MX_ID_LIST_SIZE] = { 0 }; 90 | static bool list_initialized = false; 91 | static std::mutex list_mutex; 92 | 93 | static bool list_mx_id_is_entry_valid(MxIdListEntry* entry) { 94 | if (entry == NULL) return false; 95 | if (entry->compat_name[0] == 0 || steady_seconds() - entry->timestamp >= LIST_ENTRY_TIMEOUT_SEC) return false; 96 | 97 | // otherwise entry ok 98 | return true; 99 | } 100 | 101 | void usb_mx_id_cache_init() { 102 | // initialize list 103 | if (!list_initialized) { 104 | for (int i = 0; i < MX_ID_LIST_SIZE; i++) { 105 | list_mx_id[i].timestamp = 0; 106 | list_mx_id[i].mx_id[0] = 0; 107 | list_mx_id[i].compat_name[0] = 0; 108 | } 109 | list_initialized = true; 110 | } 111 | } 112 | 113 | int usb_mx_id_cache_store_entry(const char* mx_id, const char* compat_addr) { 114 | for (int i = 0; i < MX_ID_LIST_SIZE; i++) { 115 | // If entry an invalid (timedout - default) 116 | if (!list_mx_id_is_entry_valid(&list_mx_id[i])) { 117 | strncpy(list_mx_id[i].mx_id, mx_id, sizeof(list_mx_id[i].mx_id)); 118 | strncpy(list_mx_id[i].compat_name, compat_addr, ADDRESS_BUFF_SIZE); 119 | list_mx_id[i].timestamp = steady_seconds(); 120 | return i; 121 | } 122 | } 123 | return -1; 124 | } 125 | 126 | bool usb_mx_id_cache_get_entry(const char* compat_addr, char* mx_id) { 127 | for (int i = 0; i < MX_ID_LIST_SIZE; i++) { 128 | // If entry still valid 129 | if (list_mx_id_is_entry_valid(&list_mx_id[i])) { 130 | // if entry compat name matches 131 | if (strncmp(compat_addr, list_mx_id[i].compat_name, ADDRESS_BUFF_SIZE) == 0) { 132 | // copy stored mx_id 133 | strncpy(mx_id, list_mx_id[i].mx_id, sizeof(list_mx_id[i].mx_id)); 134 | return true; 135 | } 136 | } 137 | } 138 | return false; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /src/pc/protocols/usb_mx_id.h: -------------------------------------------------------------------------------- 1 | #ifndef _USB_MX_ID_H_ 2 | #define _USB_MX_ID_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | const uint8_t* usb_mx_id_get_payload(); 12 | int usb_mx_id_get_payload_size(); 13 | const uint8_t* usb_mx_id_get_payload_end(); 14 | int usb_mx_id_get_payload_end_size(); 15 | 16 | int usb_mx_id_cache_store_entry(const char* mx_id, const char* compat_addr); 17 | bool usb_mx_id_cache_get_entry(const char* compat_addr, char* mx_id); 18 | void usb_mx_id_cache_init(); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif -------------------------------------------------------------------------------- /src/shared/XLinkAssertions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "XLinkPrivateDefines.h" 3 | 4 | static_assert(offsetof(xLinkEventHeader_t, id) == 0, "Offset to id is not 0"); 5 | static_assert(offsetof(xLinkEventHeader_t, type) == 4, "Offset to type is not 4"); 6 | static_assert(offsetof(xLinkEventHeader_t, streamName) == 8, "Offset to streamName is not 8"); 7 | static_assert(offsetof(xLinkEventHeader_t, tnsec) == 60, "Offset to tnsec is not 60"); 8 | static_assert(offsetof(xLinkEventHeader_t, tsecLsb) == 64, "Offset to tsecLsb is not 64"); 9 | static_assert(offsetof(xLinkEventHeader_t, tsecMsb) == 68, "Offset to tsecMsb is not 68"); 10 | -------------------------------------------------------------------------------- /src/shared/XLinkLog.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | /* 6 | * Add logging capabilities over simple printf. 7 | * Allows 5 different logging levels: 8 | * 9 | * MVLOG_DEBUG = 0 10 | * MVLOG_INFO = 1 11 | * MVLOG_WARN = 2 12 | * MVLOG_ERROR = 3 13 | * MVLOG_FATAL = 4 14 | * Before including header, a unit name can be set, otherwise defaults to global. eg: 15 | * 16 | * #define MVLOG_UNIT_NAME unitname 17 | * #include 18 | * Setting log level through debugger can be done in the following way: 19 | * mset mvLogLevel_unitname 2 20 | * Will set log level to warnings and above 21 | */ 22 | 23 | #include "XLinkLog.h" 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifndef _GNU_SOURCE 31 | #define _GNU_SOURCE 32 | #endif 33 | 34 | #if (defined (WINNT) || defined(_WIN32) || defined(_WIN64) ) 35 | #include "win_pthread.h" 36 | #else 37 | #ifndef __shave__ // SHAVE does not support threads 38 | #include 39 | #endif 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | #ifndef __shave__ // SHAVE does not support threads 46 | extern int pthread_getname_np (pthread_t , char *, size_t); 47 | #endif 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #ifdef __RTEMS__ 53 | #include 54 | #include 55 | #endif 56 | 57 | #ifdef __ANDROID__ 58 | #include 59 | #endif 60 | 61 | 62 | #define MVLOG_STR(x) _MVLOG_STR(x) 63 | #define _MVLOG_STR(x) #x 64 | 65 | #define UNIT_NAME_STR MVLOG_STR(MVLOG_UNIT_NAME) 66 | 67 | #define ANSI_COLOR_RED "\x1b[31m" 68 | #define ANSI_COLOR_GREEN "\x1b[32m" 69 | #define ANSI_COLOR_YELLOW "\x1b[33m" 70 | #define ANSI_COLOR_BLUE "\x1b[34m" 71 | #define ANSI_COLOR_MAGENTA "\x1b[35m" 72 | #define ANSI_COLOR_CYAN "\x1b[36m" 73 | #define ANSI_COLOR_WHITE "\x1b[37m" 74 | #define ANSI_COLOR_RESET "\x1b[0m" 75 | 76 | #ifndef MVLOG_DEBUG_COLOR 77 | #define MVLOG_DEBUG_COLOR ANSI_COLOR_WHITE 78 | #endif 79 | 80 | #ifndef MVLOG_INFO_COLOR 81 | #define MVLOG_INFO_COLOR ANSI_COLOR_CYAN 82 | #endif 83 | 84 | #ifndef MVLOG_WARN_COLOR 85 | #define MVLOG_WARN_COLOR ANSI_COLOR_YELLOW 86 | #endif 87 | 88 | #ifndef MVLOG_ERROR_COLOR 89 | #define MVLOG_ERROR_COLOR ANSI_COLOR_MAGENTA 90 | #endif 91 | 92 | #ifndef MVLOG_FATAL_COLOR 93 | #define MVLOG_FATAL_COLOR ANSI_COLOR_RED 94 | #endif 95 | 96 | 97 | #ifdef __shave__ 98 | __attribute__((section(".laststage"))) 99 | #endif 100 | static const char mvLogHeader[MVLOG_LAST][30] = 101 | { 102 | MVLOG_DEBUG_COLOR "D:", 103 | MVLOG_INFO_COLOR "I:", 104 | MVLOG_WARN_COLOR "W:", 105 | MVLOG_ERROR_COLOR "E:", 106 | MVLOG_FATAL_COLOR "F:" 107 | }; 108 | 109 | 110 | // Define global and default 111 | mvLog_t MVLOGLEVEL(global) = MVLOG_LAST; 112 | mvLog_t MVLOGLEVEL(default) = MVLOG_ERROR; 113 | 114 | void XLinkLogGetThreadName(char *buf, size_t len); 115 | 116 | void XLinkLogGetThreadName(char *buf, size_t len){ 117 | #ifdef HAVE_PTHREAD_GETNAME_NP 118 | pthread_getname_np(pthread_self(), buf, len); 119 | #else 120 | snprintf(buf, sizeof(len), "ThreadName_N/A"); 121 | #endif 122 | } 123 | 124 | #ifdef __shave__ 125 | __attribute__((section(".laststage"))) 126 | #endif 127 | int __attribute__ ((unused)) 128 | logprintf(mvLog_t curLogLvl, mvLog_t lvl, const char * func, const int line, 129 | const char * format, ...) 130 | { 131 | if((curLogLvl == MVLOG_LAST && lvl < MVLOGLEVEL(default))) 132 | return 0; 133 | 134 | if((curLogLvl < MVLOG_LAST && lvl < curLogLvl)) 135 | return 0; 136 | 137 | const char headerFormat[] = "%s [%s] [%10" PRId64 "] [%s] %s:%d\t"; 138 | #ifdef __RTEMS__ 139 | uint64_t timestamp = rtems_clock_get_uptime_nanoseconds() / 1000; 140 | #elif !defined(_WIN32) && !(defined MA2450 || defined __shave__) 141 | struct timespec spec; 142 | clock_gettime(CLOCK_REALTIME, &spec); 143 | uint64_t timestamp = (spec.tv_sec % 1000) * 1000 + spec.tv_nsec / 1e6; 144 | #else 145 | uint64_t timestamp = 0; 146 | #endif 147 | va_list args; 148 | va_start (args, format); 149 | 150 | char threadName[MVLOG_MAXIMUM_THREAD_NAME_SIZE] = {0}; 151 | #if defined MA2450 || defined __shave__ 152 | snprintf(threadName, sizeof(threadName), "ThreadName_N/A"); 153 | #elif !defined(ANDROID) 154 | XLinkLogGetThreadName(threadName, sizeof(threadName)); 155 | #endif 156 | 157 | #ifdef __RTEMS__ 158 | if(!rtems_interrupt_is_in_progress()) 159 | { 160 | #endif 161 | #if defined __sparc__ || !defined __DEVICE__ 162 | #ifdef __ANDROID__ 163 | // Convert to Android logging enumeration 164 | enum android_LogPriority logPrio = ANDROID_LOG_DEBUG + (lvl - MVLOG_DEBUG); 165 | //__android_log_print(logPrio, UNIT_NAME_STR, headerFormat, mvLogHeader[lvl], UNIT_NAME_STR, timestamp, threadName, func, line); 166 | __android_log_vprint(logPrio, UNIT_NAME_STR, format, args); 167 | // __android_log_print(logPrio, UNIT_NAME_STR, "%s", ANSI_COLOR_RESET); 168 | #else 169 | fprintf(stdout, headerFormat, mvLogHeader[lvl], UNIT_NAME_STR, timestamp, threadName, func, line); 170 | vfprintf(stdout, format, args); 171 | fprintf(stdout, "%s\n", ANSI_COLOR_RESET); 172 | #endif 173 | 174 | #elif defined __shave__ 175 | printf(headerFormat, mvLogHeader[lvl], UNIT_NAME_STR, timestamp, threadName, func, line); 176 | printf(format, args); 177 | printf("%s\n", ANSI_COLOR_RESET); 178 | 179 | #endif 180 | #ifdef __RTEMS__ 181 | } 182 | else 183 | { 184 | printk(headerFormat, mvLogHeader[lvl], UNIT_NAME_STR, timestamp, threadName, func, line); 185 | vprintk(format, args); 186 | printk("%s\n", ANSI_COLOR_RESET); 187 | } 188 | #endif 189 | va_end (args); 190 | return 0; 191 | } 192 | -------------------------------------------------------------------------------- /src/shared/XLinkPrivateDefines.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | 7 | #include "XLinkErrorUtils.h" 8 | #include "XLinkPrivateFields.h" 9 | #include "XLinkPrivateDefines.h" 10 | #include "XLinkPlatform.h" 11 | #include "XLinkMacros.h" 12 | 13 | #ifdef MVLOG_UNIT_NAME 14 | #undef MVLOG_UNIT_NAME 15 | #define MVLOG_UNIT_NAME xLink 16 | #endif 17 | 18 | #include "XLinkLog.h" 19 | 20 | // ------------------------------------ 21 | // Helpers declaration. Begin. 22 | // ------------------------------------ 23 | 24 | XLinkError_t getNextAvailableStreamIndex(xLinkDesc_t* link, int* out_id); 25 | static streamId_t getNextStreamUniqueId(xLinkDesc_t *link); 26 | 27 | // ------------------------------------ 28 | // Helpers declaration. End. 29 | // ------------------------------------ 30 | 31 | 32 | 33 | // ------------------------------------ 34 | // XLinkPrivateDefines API implementation. Begin. 35 | // ------------------------------------ 36 | 37 | streamId_t XLinkAddOrUpdateStream(void *fd, const char *name, 38 | uint32_t writeSize, uint32_t readSize, streamId_t forcedId) 39 | { 40 | mvLog(MVLOG_DEBUG, "name: %s, writeSize: %ld, readSize: %ld, forcedId: %ld\n", 41 | name, writeSize, readSize, forcedId); 42 | 43 | streamId_t retStreamId = INVALID_STREAM_ID; 44 | streamDesc_t* stream = NULL; 45 | xLinkDesc_t* link = getLink(fd); 46 | XLINK_OUT_IF(link == NULL); 47 | 48 | stream = getStreamByName(link, name); 49 | if (stream != NULL) { 50 | 51 | int streamAlreadyExists = (writeSize > stream->writeSize && stream->writeSize != 0) 52 | || (readSize > stream->readSize && stream->readSize != 0); 53 | 54 | // Don't error out 55 | // TODO(themarpe) - check if actually doesn't have any consequences 56 | if(streamAlreadyExists){ 57 | if (writeSize) { 58 | stream->writeSize = writeSize; 59 | } 60 | if (readSize) { 61 | stream->readSize = readSize; 62 | } 63 | } 64 | 65 | // XLINK_OUT_WITH_LOG_IF(streamAlreadyExists, 66 | // mvLog(MVLOG_ERROR, "Stream with name:%s already exists: id=%ld\n", name, stream->id)); 67 | 68 | // if(streamAlreadyExists){ 69 | // //stream->writeSize = writeSize; 70 | // stream->readSize = readSize; 71 | // printf("write size was: %d and set read size to: %d\n", stream->writeSize, readSize); 72 | // mvLogDefaultLevelSet(MVLOG_DEBUG); 73 | // 74 | // } 75 | 76 | 77 | } else { 78 | streamId_t nextStreamId = forcedId == INVALID_STREAM_ID ? 79 | getNextStreamUniqueId(link) : forcedId; 80 | int idx = 0; 81 | XLINK_OUT_IF(getNextAvailableStreamIndex(link, &idx)); 82 | stream = &link->availableStreams[idx]; 83 | 84 | XLINK_OUT_IF(XLinkStreamInitialize(stream, nextStreamId, name)); 85 | } 86 | 87 | if (readSize && !stream->readSize) { 88 | stream->readSize = readSize; 89 | 90 | #ifdef __DEVICE__ 91 | // FIXME: not the best solution but the simplest for now: 92 | // it is just for a check; real allocation will be done during receiving an usb package 93 | void *buffer = XLinkPlatformAllocateData(ALIGN_UP(readSize, __CACHE_LINE_SIZE), __CACHE_LINE_SIZE); 94 | if (buffer == NULL) { 95 | mvLog(MVLOG_ERROR,"Cannot create stream. Requested memory = %u", stream->readSize); 96 | return INVALID_STREAM_ID; 97 | } else { 98 | XLinkPlatformDeallocateData(buffer, ALIGN_UP(readSize, __CACHE_LINE_SIZE), __CACHE_LINE_SIZE); 99 | } 100 | #endif 101 | } 102 | if (writeSize && !stream->writeSize) { 103 | stream->writeSize = writeSize; 104 | } 105 | 106 | retStreamId = stream->id; 107 | mvLog(MVLOG_DEBUG, "The stream \"%s\" created, id = %u, writeSize = %d, readSize = %d\n", 108 | stream->name, stream->id, stream->writeSize, stream->readSize); 109 | 110 | XLINK_OUT: 111 | if(stream != NULL) { 112 | releaseStream(stream); 113 | } 114 | return retStreamId; 115 | } 116 | 117 | // ------------------------------------ 118 | // XLinkPrivateDefines API implementation. End. 119 | // ------------------------------------ 120 | 121 | 122 | 123 | // ------------------------------------ 124 | // Helpers implementation. Begin. 125 | // ------------------------------------ 126 | 127 | XLinkError_t getNextAvailableStreamIndex(xLinkDesc_t* link, int* out_id) 128 | { 129 | ASSERT_XLINK(link); 130 | 131 | *out_id = XLINK_MAX_STREAMS; 132 | for (int idx = 0; idx < XLINK_MAX_STREAMS; idx++) { 133 | if (link->availableStreams[idx].id == INVALID_STREAM_ID) { 134 | *out_id = idx; 135 | return X_LINK_SUCCESS; 136 | } 137 | } 138 | 139 | mvLog(MVLOG_DEBUG,"No next available stream!\n"); 140 | return X_LINK_ERROR; 141 | } 142 | 143 | streamId_t getNextStreamUniqueId(xLinkDesc_t *link) 144 | { 145 | XLINK_RET_ERR_IF(link == NULL, INVALID_STREAM_ID); 146 | uint32_t start = link->nextUniqueStreamId; 147 | uint32_t curr = link->nextUniqueStreamId; 148 | do 149 | { 150 | int i; 151 | for (i = 0; i < XLINK_MAX_STREAMS; i++) 152 | { 153 | if (link->availableStreams[i].id != INVALID_STREAM_ID && 154 | link->availableStreams[i].id == curr) 155 | break; 156 | } 157 | if (i >= XLINK_MAX_STREAMS) 158 | { 159 | link->nextUniqueStreamId = curr; 160 | return curr; 161 | } 162 | curr++; 163 | 164 | if (curr == INVALID_STREAM_ID) 165 | { 166 | curr = 0; 167 | } 168 | } while (start != curr); 169 | mvLog(MVLOG_ERROR, "%s():- no next available stream unique id!\n", __func__); 170 | return INVALID_STREAM_ID; 171 | } 172 | 173 | // ------------------------------------ 174 | // Helpers implementation. End. 175 | // ------------------------------------ 176 | -------------------------------------------------------------------------------- /src/shared/XLinkPrivateFields.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include "stdlib.h" 9 | 10 | #include "XLinkPrivateFields.h" 11 | #include "XLinkPrivateDefines.h" 12 | #include "XLinkErrorUtils.h" 13 | 14 | #ifdef MVLOG_UNIT_NAME 15 | #undef MVLOG_UNIT_NAME 16 | #define MVLOG_UNIT_NAME xLink 17 | #endif 18 | 19 | #include "XLinkLog.h" 20 | 21 | xLinkDesc_t* getLinkById(linkId_t id) 22 | { 23 | XLINK_RET_ERR_IF(pthread_mutex_lock(&availableXLinksMutex) != 0, NULL); 24 | 25 | int i; 26 | for (i = 0; i < MAX_LINKS; i++) { 27 | if (availableXLinks[i].id == id) { 28 | XLINK_RET_ERR_IF(pthread_mutex_unlock(&availableXLinksMutex) != 0, NULL); 29 | return &availableXLinks[i]; 30 | } 31 | } 32 | 33 | XLINK_RET_ERR_IF(pthread_mutex_unlock(&availableXLinksMutex) != 0, NULL); 34 | return NULL; 35 | } 36 | 37 | xLinkDesc_t* getLink(void* fd) 38 | { 39 | 40 | XLINK_RET_ERR_IF(pthread_mutex_lock(&availableXLinksMutex) != 0, NULL); 41 | 42 | int i; 43 | for (i = 0; i < MAX_LINKS; i++) { 44 | if (availableXLinks[i].deviceHandle.xLinkFD == fd) { 45 | XLINK_RET_ERR_IF(pthread_mutex_unlock(&availableXLinksMutex) != 0, NULL); 46 | return &availableXLinks[i]; 47 | } 48 | } 49 | 50 | XLINK_RET_ERR_IF(pthread_mutex_unlock(&availableXLinksMutex) != 0, NULL); 51 | return NULL; 52 | } 53 | 54 | streamId_t getStreamIdByName(xLinkDesc_t* link, const char* name) 55 | { 56 | streamDesc_t* stream = getStreamByName(link, name); 57 | 58 | if (stream) { 59 | streamId_t id = stream->id; 60 | releaseStream(stream); 61 | return id; 62 | } 63 | 64 | return INVALID_STREAM_ID; 65 | } 66 | 67 | streamDesc_t* getStreamById(void* fd, streamId_t id) 68 | { 69 | XLINK_RET_ERR_IF(id == INVALID_STREAM_ID, NULL); 70 | xLinkDesc_t* link = getLink(fd); 71 | XLINK_RET_ERR_IF(link == NULL, NULL); 72 | int stream; 73 | for (stream = 0; stream < XLINK_MAX_STREAMS; stream++) { 74 | if (link->availableStreams[stream].id == id) { 75 | int rc = 0; 76 | while(((rc = XLink_sem_wait(&link->availableStreams[stream].sem)) == -1) && errno == EINTR) 77 | continue; 78 | if (rc) { 79 | mvLog(MVLOG_ERROR,"can't wait semaphore\n"); 80 | return NULL; 81 | } 82 | return &link->availableStreams[stream]; 83 | } 84 | } 85 | return NULL; 86 | } 87 | 88 | streamDesc_t* getStreamByName(xLinkDesc_t* link, const char* name) 89 | { 90 | XLINK_RET_ERR_IF(link == NULL, NULL); 91 | int stream; 92 | for (stream = 0; stream < XLINK_MAX_STREAMS; stream++) { 93 | if (link->availableStreams[stream].id != INVALID_STREAM_ID && 94 | strcmp(link->availableStreams[stream].name, name) == 0) { 95 | int rc = 0; 96 | while(((rc = XLink_sem_wait(&link->availableStreams[stream].sem)) == -1) && errno == EINTR) 97 | continue; 98 | if (rc) { 99 | mvLog(MVLOG_ERROR,"can't wait semaphore\n"); 100 | return NULL; 101 | } 102 | return &link->availableStreams[stream]; 103 | } 104 | } 105 | return NULL; 106 | } 107 | 108 | void releaseStream(streamDesc_t* stream) 109 | { 110 | if (stream && stream->id != INVALID_STREAM_ID) { 111 | XLink_sem_post(&stream->sem); 112 | } 113 | else { 114 | mvLog(MVLOG_DEBUG,"trying to release a semaphore for a released stream\n"); 115 | } 116 | } 117 | 118 | xLinkState_t getXLinkState(xLinkDesc_t* link) 119 | { 120 | XLINK_RET_ERR_IF(link == NULL, XLINK_NOT_INIT); 121 | mvLog(MVLOG_DEBUG,"%s() link %p link->peerState %d\n", __func__,link, link->peerState); 122 | return link->peerState; 123 | } 124 | -------------------------------------------------------------------------------- /src/shared/XLinkSemaphore.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | #include "XLinkSemaphore.h" 7 | #include "XLinkErrorUtils.h" 8 | #include "XLinkLog.h" 9 | 10 | static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER; 11 | static pthread_cond_t ref_cond = PTHREAD_COND_INITIALIZER; 12 | 13 | int XLink_sem_inc(XLink_sem_t* sem) 14 | { 15 | XLINK_RET_IF_FAIL(pthread_mutex_lock(&ref_mutex)); 16 | if (sem->refs < 0) { 17 | // Semaphore has been already destroyed 18 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 19 | return -1; 20 | } 21 | 22 | sem->refs++; 23 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 24 | 25 | return 0; 26 | } 27 | 28 | int XLink_sem_dec(XLink_sem_t* sem) 29 | { 30 | XLINK_RET_IF_FAIL(pthread_mutex_lock(&ref_mutex)); 31 | if (sem->refs < 1) { 32 | // Can't decrement reference count if there are no waiters 33 | // or semaphore has been already destroyed 34 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 35 | return -1; 36 | } 37 | 38 | sem->refs--; 39 | int ret = pthread_cond_broadcast(&ref_cond); 40 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 41 | 42 | return ret; 43 | } 44 | 45 | 46 | int XLink_sem_init(XLink_sem_t* sem, int pshared, unsigned int value) 47 | { 48 | XLINK_RET_ERR_IF(sem == NULL, -1); 49 | 50 | XLINK_RET_IF_FAIL(sem_init(&sem->psem, pshared, value)); 51 | XLINK_RET_IF_FAIL(pthread_mutex_lock(&ref_mutex)); 52 | sem->refs = 0; 53 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 54 | 55 | return 0; 56 | } 57 | 58 | int XLink_sem_destroy(XLink_sem_t* sem) 59 | { 60 | XLINK_RET_ERR_IF(sem == NULL, -1); 61 | 62 | XLINK_RET_IF_FAIL(pthread_mutex_lock(&ref_mutex)); 63 | if (sem->refs < 0) { 64 | // Semaphore has been already destroyed 65 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 66 | return -1; 67 | } 68 | 69 | while(sem->refs > 0) { 70 | if (pthread_cond_wait(&ref_cond, &ref_mutex)) { 71 | break; 72 | }; 73 | } 74 | sem->refs = -1; 75 | int ret = sem_destroy(&sem->psem); 76 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 77 | 78 | return ret; 79 | } 80 | 81 | int XLink_sem_post(XLink_sem_t* sem) 82 | { 83 | XLINK_RET_ERR_IF(sem == NULL, -1); 84 | if (sem->refs < 0) { 85 | return -1; 86 | } 87 | 88 | return sem_post(&sem->psem); 89 | } 90 | 91 | int XLink_sem_wait(XLink_sem_t* sem) 92 | { 93 | XLINK_RET_ERR_IF(sem == NULL, -1); 94 | 95 | XLINK_RET_IF_FAIL(XLink_sem_inc(sem)); 96 | int ret; 97 | while(((ret = sem_wait(&sem->psem) == -1) && errno == EINTR)) 98 | continue; 99 | XLINK_RET_IF_FAIL(XLink_sem_dec(sem)); 100 | 101 | return ret; 102 | } 103 | 104 | int XLink_sem_timedwait(XLink_sem_t* sem, const struct timespec* abstime) 105 | { 106 | XLINK_RET_ERR_IF(sem == NULL, -1); 107 | XLINK_RET_ERR_IF(abstime == NULL, -1); 108 | 109 | XLINK_RET_IF_FAIL(XLink_sem_inc(sem)); 110 | int ret; 111 | while(((ret = sem_timedwait(&sem->psem, abstime)) == -1) && errno == EINTR) 112 | continue; 113 | XLINK_RET_IF_FAIL(XLink_sem_dec(sem)); 114 | 115 | return ret; 116 | } 117 | 118 | int XLink_sem_trywait(XLink_sem_t* sem) 119 | { 120 | XLINK_RET_ERR_IF(sem == NULL, -1); 121 | 122 | XLINK_RET_IF_FAIL(XLink_sem_inc(sem)); 123 | int ret = sem_trywait(&sem->psem); 124 | XLINK_RET_IF_FAIL(XLink_sem_dec(sem)); 125 | 126 | return ret; 127 | } 128 | 129 | int XLink_sem_set_refs(XLink_sem_t* sem, int refs) 130 | { 131 | XLINK_RET_ERR_IF(sem == NULL, -1); 132 | XLINK_RET_ERR_IF(refs < -1, -1); 133 | 134 | XLINK_RET_IF_FAIL(pthread_mutex_lock(&ref_mutex)); 135 | sem->refs = refs; 136 | int ret = pthread_cond_broadcast(&ref_cond); 137 | XLINK_RET_IF_FAIL(pthread_mutex_unlock(&ref_mutex)); 138 | 139 | return ret; 140 | } 141 | 142 | int XLink_sem_get_refs(XLink_sem_t* sem, int *sval) 143 | { 144 | XLINK_RET_ERR_IF(sem == NULL, -1); 145 | 146 | *sval = sem->refs; 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /src/shared/XLinkStream.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include 6 | 7 | #include "XLinkStream.h" 8 | #include "XLinkErrorUtils.h" 9 | 10 | #ifdef MVLOG_UNIT_NAME 11 | #undef MVLOG_UNIT_NAME 12 | #define MVLOG_UNIT_NAME xLink 13 | #endif 14 | 15 | #include "XLinkLog.h" 16 | #include "XLinkStringUtils.h" 17 | 18 | XLinkError_t XLinkStreamInitialize( 19 | streamDesc_t* stream, streamId_t id, const char* name) { 20 | mvLog(MVLOG_DEBUG, "name: %s, id: %ld\n", name, id); 21 | ASSERT_XLINK(stream); 22 | 23 | memset(stream, 0, sizeof(*stream)); 24 | 25 | if (XLink_sem_init(&stream->sem, 0, 0)) { 26 | mvLog(MVLOG_ERROR, "Cannot initialize semaphore\n"); 27 | return X_LINK_ERROR; 28 | } 29 | 30 | stream->id = id; 31 | mv_strncpy(stream->name, MAX_STREAM_NAME_LENGTH, 32 | name, MAX_STREAM_NAME_LENGTH - 1); 33 | 34 | return X_LINK_SUCCESS; 35 | } 36 | 37 | void XLinkStreamReset(streamDesc_t* stream) { 38 | if(stream == NULL) { 39 | return; 40 | } 41 | 42 | if(XLink_sem_destroy(&stream->sem)) { 43 | mvLog(MVLOG_DEBUG, "Cannot destroy semaphore\n"); 44 | } 45 | 46 | // sets all stream fields, including the packets circular buffer to NULL 47 | // with no check to see if something is open, packet is "blocked", etc. 48 | memset(stream, 0, sizeof(*stream)); 49 | stream->id = INVALID_STREAM_ID; 50 | } 51 | -------------------------------------------------------------------------------- /src/shared/XLinkStringUtils.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018-2021 Intel Corporation 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #include "XLinkStringUtils.h" 6 | 7 | int mv_strcpy(char *dest, size_t destsz, const char *src) { 8 | const char *overlap_bumper; 9 | 10 | if (dest == NULL) { 11 | return ESNULLP; 12 | } 13 | if (destsz == 0) { 14 | return ESZEROL; 15 | } 16 | if (destsz > RSIZE_MAX_STR) { 17 | return ESLEMAX; 18 | } 19 | if (src == NULL) { 20 | while (destsz) { 21 | *dest = '\0'; 22 | destsz--; 23 | dest++; 24 | } 25 | return ESNULLP; 26 | } 27 | // It's ok if src and dest are in the same place. No action is needed. 28 | if (dest == src) { 29 | return EOK; 30 | } 31 | 32 | if (dest < src) { 33 | overlap_bumper = src; 34 | 35 | while (destsz > 0) { 36 | if (dest == overlap_bumper) { 37 | return ESOVRLP; 38 | } 39 | 40 | *dest = *src; 41 | if (*dest == '\0') { 42 | while (destsz) { 43 | *dest = '\0'; 44 | destsz--; 45 | dest++; 46 | } 47 | return EOK; 48 | } 49 | destsz--; 50 | dest++; 51 | src++; 52 | } 53 | } else { 54 | overlap_bumper = dest; 55 | 56 | while (destsz > 0) { 57 | if (src == overlap_bumper) { 58 | return ESOVRLP; 59 | } 60 | 61 | *dest = *src; 62 | if (*dest == '\0') { 63 | while (destsz) { 64 | *dest = '\0'; 65 | destsz--; 66 | dest++; 67 | } 68 | return EOK; 69 | } 70 | destsz--; 71 | dest++; 72 | src++; 73 | } 74 | } 75 | 76 | // Ran out of space in dest, and did not find the null terminator in src. 77 | return ESNOSPC; 78 | } 79 | 80 | int mv_strncpy(char *dest, size_t destsz, const char *src, size_t count) { 81 | if (dest == NULL) { 82 | return ESNULLP; 83 | } 84 | if (src == NULL) { 85 | while (destsz) { 86 | *dest = '\0'; 87 | destsz--; 88 | dest++; 89 | } 90 | return ESNULLP; 91 | } 92 | if (destsz == 0) { 93 | return ESZEROL; 94 | } 95 | if (destsz > RSIZE_MAX_STR || count > RSIZE_MAX_STR) { 96 | return ESLEMAX; 97 | } 98 | if (destsz < (count + 1)) { 99 | dest[0] = '\0'; 100 | return ESNOSPC; 101 | } 102 | if (((src < dest) && ((src + destsz) >= dest)) || 103 | ((dest < src) && ((dest + destsz) >= src))) { 104 | dest[0] = '\0'; 105 | return ESOVRLP; 106 | } 107 | 108 | if (dest == src) { 109 | while (destsz > 0) { 110 | if (*dest == '\0') { 111 | // Add nulls to complete dest. 112 | while (destsz) { 113 | *dest = '\0'; 114 | destsz--; 115 | dest++; 116 | } 117 | return EOK; 118 | } 119 | destsz--; 120 | dest++; 121 | count--; 122 | if (count == 0) { 123 | // We have copied count characters, add null terminator. 124 | *dest = '\0'; 125 | } 126 | } 127 | return ESNOSPC; 128 | } 129 | 130 | // Normal copying. 131 | while (destsz > 0) { 132 | // Copy data from src to dest. 133 | *dest = *src; 134 | 135 | if (count == 0) { 136 | // We have copied count characters, add null terminator. 137 | *dest = '\0'; 138 | } 139 | 140 | // Check for end of copying. 141 | if (*dest == '\0') { 142 | // Add nulls to complete dest. 143 | while (destsz) { 144 | *dest = '\0'; 145 | destsz--; 146 | dest++; 147 | } 148 | return EOK; 149 | } 150 | destsz--; 151 | count--; 152 | dest++; 153 | src++; 154 | } 155 | 156 | // Ran out of space in dest, and did not find the null terminator in src. 157 | return ESNOSPC; 158 | } 159 | -------------------------------------------------------------------------------- /src/shared/XLinkTime.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "XLinkTime.h" 4 | 5 | void getMonotonicTimestamp(XLinkTimespec* ts) { 6 | auto now = std::chrono::steady_clock::now(); 7 | auto epoch = now.time_since_epoch(); 8 | ts->tv_sec = std::chrono::duration_cast(epoch).count(); 9 | ts->tv_nsec = std::chrono::duration_cast(epoch).count() % 1000000000; 10 | } -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Helper 'add_test' 2 | macro(add_test test_name test_src) 3 | add_executable(${test_name} ${test_src}) 4 | target_link_libraries(${test_name} ${TARGET_NAME}) 5 | set_property(TARGET ${test_name} PROPERTY CXX_STANDARD 11) 6 | set_property(TARGET ${test_name} PROPERTY CXX_STANDARD_REQUIRED ON) 7 | set_property(TARGET ${test_name} PROPERTY CXX_EXTENSIONS OFF) 8 | 9 | # Copy over required DLLs (Windows) 10 | if(WIN32) 11 | # Copy dlls to target directory - Windows only 12 | # TARGET_RUNTIME_DLLS generator expression available since CMake 3.21 13 | if(CMAKE_VERSION VERSION_LESS "3.21") 14 | message(WARNING "Automatic DLL copying not available") 15 | else() 16 | set(depthai_dll_libraries "$") 17 | add_custom_command(TARGET ${test_name} POST_BUILD COMMAND 18 | "$<$:${CMAKE_COMMAND};-E;copy_if_different;${depthai_dll_libraries};$>" 19 | COMMAND_EXPAND_LISTS 20 | VERBATIM 21 | ) 22 | endif() 23 | endif() 24 | endmacro() 25 | 26 | # Tests 27 | 28 | # Multiple stream open 29 | add_test(multiple_open_stream multiple_open_stream.cpp) 30 | 31 | # Multithreading search 32 | add_test(multithreading_search_test multithreading_search_test.cpp) -------------------------------------------------------------------------------- /tests/multiple_open_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | // The following is an Server side (host) test that opens many streams in random order. 13 | // Mainly used to test stream desync issue. 14 | 15 | // Use the following code on Client side (device) to test 16 | // ... 17 | // // loop through streams 18 | // constexpr static auto NUM_STREAMS = 16; 19 | // std::array threads; 20 | // for(int i = 0; i < NUM_STREAMS; i++){ 21 | // threads[i] = std::thread([i](){ 22 | // std::string name = "test_"; 23 | // auto s = XLinkOpenStream(0, (name + std::to_string(i)).c_str(), 1024); 24 | // assert(s != INVALID_STREAM_ID); 25 | // auto w = XLinkWriteData(s, (uint8_t*) &s, sizeof(s)); 26 | // assert(w == X_LINK_SUCCESS); 27 | // }); 28 | // } 29 | // for(auto& thread : threads){ 30 | // thread.join(); 31 | // } 32 | // ... 33 | 34 | int main() { 35 | 36 | XLinkGlobalHandler_t gHandler; 37 | XLinkInitialize(&gHandler); 38 | 39 | // Search for booted device 40 | deviceDesc_t deviceDesc, inDeviceDesc; 41 | inDeviceDesc.protocol = X_LINK_ANY_PROTOCOL; 42 | inDeviceDesc.state = X_LINK_BOOTED; 43 | if(X_LINK_SUCCESS != XLinkFindFirstSuitableDevice(inDeviceDesc, &deviceDesc)){ 44 | printf("Didn't find a device\n"); 45 | return -1; 46 | } 47 | 48 | printf("Device name: %s\n", deviceDesc.name); 49 | 50 | XLinkHandler_t handler; 51 | handler.devicePath = deviceDesc.name; 52 | handler.protocol = deviceDesc.protocol; 53 | XLinkConnect(&handler); 54 | 55 | // loop randomly over streams 56 | constexpr static auto NUM_STREAMS = 16; 57 | std::vector randomized; 58 | for(int i = 0; i < NUM_STREAMS; i++){ 59 | randomized.push_back(i); 60 | } 61 | std::random_shuffle(std::begin(randomized), std::end(randomized)); 62 | 63 | std::thread threads[NUM_STREAMS]; 64 | streamId_t streams[NUM_STREAMS]; 65 | for(auto i : randomized){ 66 | threads[i] = std::thread([&, i](){ 67 | std::string name = "test_" + std::to_string(i); 68 | auto s = XLinkOpenStream(handler.linkId, name.c_str(), 1024); 69 | if(s == INVALID_STREAM_ID){ 70 | printf("Open stream failed...\n"); 71 | } else { 72 | printf("Open stream OK - name %s, id: 0x%08X\n", name.c_str(), s); 73 | } 74 | streams[i] = s; 75 | }); 76 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 77 | } 78 | for(auto i : randomized){ 79 | threads[i].join(); 80 | } 81 | 82 | // Optionally, print stream names and ids here 83 | std::atomic success{true}; 84 | for(auto i : randomized){ 85 | threads[i] = std::thread([i, &streams, &success](){ 86 | std::string name = "test_" + std::to_string(i); 87 | auto s = streams[i]; 88 | 89 | streamPacketDesc_t* p; 90 | XLinkError_t err = XLinkReadData(s, &p); 91 | 92 | if(err == X_LINK_SUCCESS && p && p->data && s == *((streamId_t*) p->data)) { 93 | // OK 94 | } else { 95 | streamId_t id; 96 | memcpy(&id, p->data, sizeof(id)); 97 | printf("DESYNC error - name %s, id: 0x%08X, response id: 0x%08X\n", name.c_str(), s, id); 98 | success = false; 99 | } 100 | 101 | }); 102 | } 103 | for(auto i : randomized){ 104 | threads[i].join(); 105 | } 106 | 107 | XLinkResetRemote(handler.linkId); 108 | 109 | if(success){ 110 | printf("Success!\n"); 111 | return 0; 112 | } else { 113 | printf("Error!\n"); 114 | return -1; 115 | } 116 | } -------------------------------------------------------------------------------- /tests/multithreading_search_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() { 15 | 16 | XLinkGlobalHandler_t gHandler; 17 | XLinkInitialize(&gHandler); 18 | 19 | // Search for booted device 20 | deviceDesc_t deviceDesc, inDeviceDesc; 21 | inDeviceDesc.protocol = X_LINK_ANY_PROTOCOL; 22 | 23 | // loop randomly over streams 24 | constexpr static auto NUM_STREAMS = 128; 25 | std::vector randomized; 26 | std::vector results; 27 | results.resize(NUM_STREAMS); 28 | for(int i = 0; i < NUM_STREAMS; i++){ 29 | randomized.push_back(i); 30 | } 31 | std::random_shuffle(std::begin(randomized), std::end(randomized)); 32 | 33 | std::thread threads[NUM_STREAMS]; 34 | streamId_t streams[NUM_STREAMS]; 35 | for(auto i : randomized){ 36 | threads[i] = std::thread([&, i](){ 37 | // Get all available devices 38 | unsigned int numdev = 0; 39 | std::array deviceDescAll = {}; 40 | deviceDesc_t suitableDevice = {}; 41 | suitableDevice.protocol = X_LINK_ANY_PROTOCOL; 42 | suitableDevice.platform = X_LINK_ANY_PLATFORM; 43 | 44 | auto status = XLinkFindAllSuitableDevices(suitableDevice, deviceDescAll.data(), deviceDescAll.size(), &numdev); 45 | if(status != X_LINK_SUCCESS) throw std::runtime_error("Couldn't retrieve all connected devices"); 46 | 47 | // Print device details 48 | std::cout << "numdev: " + std::to_string(numdev) + "\n"; 49 | results[i] = numdev; 50 | }); 51 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); 52 | } 53 | for(auto i : randomized){ 54 | threads[i].join(); 55 | } 56 | 57 | int numdev = -1; 58 | for(auto num : results) { 59 | if(numdev == -1) numdev = num; 60 | // make sure all threads found the same number of devices 61 | if(num != numdev) { 62 | std::cout << "Failed, not all threads found same number of devices\n"; 63 | return -1; 64 | } 65 | } 66 | 67 | } --------------------------------------------------------------------------------