winusb: 本体を追加

This commit is contained in:
nns779
2021-06-27 21:56:41 +09:00
parent 242772cb02
commit a2213e9426
72 changed files with 10221 additions and 0 deletions

5
winusb/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.vs/
build/
*.aps
*.user

View File

@@ -0,0 +1,39 @@
// IBonDriver.h: IBonDriver <20>N<EFBFBD><4E><EFBFBD>X<EFBFBD>̃C<CC83><43><EFBFBD>^<5E>[<5B>t<EFBFBD>F<EFBFBD>C<EFBFBD>X
//
//////////////////////////////////////////////////////////////////////
#if !defined(_IBONDRIVER_H_)
#define _IBONDRIVER_H_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// <20>}<7D>h<EFBFBD><68><EFBFBD>C<EFBFBD>o<EFBFBD>C<EFBFBD><43><EFBFBD>^<5E>t<EFBFBD>F<EFBFBD>[<5B>X
class IBonDriver
{
public:
virtual const BOOL OpenTuner(void) = 0;
virtual void CloseTuner(void) = 0;
virtual const BOOL SetChannel(const BYTE bCh) = 0;
virtual const float GetSignalLevel(void) = 0;
virtual const DWORD WaitTsStream(const DWORD dwTimeOut = 0) = 0;
virtual const DWORD GetReadyCount(void) = 0;
virtual const BOOL GetTsStream(BYTE *pDst, DWORD *pdwSize, DWORD *pdwRemain) = 0;
virtual const BOOL GetTsStream(BYTE **ppDst, DWORD *pdwSize, DWORD *pdwRemain) = 0;
virtual void PurgeTsStream(void) = 0;
virtual void Release(void) = 0;
};
// <20>C<EFBFBD><43><EFBFBD>X<EFBFBD>^<5E><><EFBFBD>X<EFBFBD><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\<5C>b<EFBFBD>h
extern "C" __declspec(dllimport) IBonDriver * CreateBonDriver();
#endif // !defined(_IBONDRIVER_H_)

View File

@@ -0,0 +1,36 @@
// IBonDriver2.h: IBonDriver2 <20>N<EFBFBD><4E><EFBFBD>X<EFBFBD>̃C<CC83><43><EFBFBD>^<5E>[<5B>t<EFBFBD>F<EFBFBD>C<EFBFBD>X
//
//////////////////////////////////////////////////////////////////////
#if !defined(_IBONDRIVER2_H_)
#define _IBONDRIVER2_H_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "IBonDriver.h"
// <20>}<7D>h<EFBFBD><68><EFBFBD>C<EFBFBD>o<EFBFBD>C<EFBFBD><43><EFBFBD>^<5E>t<EFBFBD>F<EFBFBD>[<5B>X2
class IBonDriver2 : public IBonDriver
{
public:
virtual LPCTSTR GetTunerName(void) = 0;
virtual const BOOL IsTunerOpening(void) = 0;
virtual LPCTSTR EnumTuningSpace(const DWORD dwSpace) = 0;
virtual LPCTSTR EnumChannelName(const DWORD dwSpace, const DWORD dwChannel) = 0;
virtual const BOOL SetChannel(const DWORD dwSpace, const DWORD dwChannel) = 0;
virtual const DWORD GetCurSpace(void) = 0;
virtual const DWORD GetCurChannel(void) = 0;
// IBonDriver
virtual void Release(void) = 0;
};
#endif // !defined(_IBONDRIVER2_H_)

65
winusb/px4_winusb.sln Normal file
View File

@@ -0,0 +1,65 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29613.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BonDriver_PX4", "src\BonDriver_PX4\BonDriver_PX4.vcxproj", "{E57919FC-F7EA-4551-B021-A1ACD2E324B1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DriverHost_PX4", "src\DriverHost_PX4\DriverHost_PX4.vcxproj", "{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fwtool", "src\fwtool\fwtool.vcxproj", "{BDBD265F-5914-426F-89F7-16478BE1AFCC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
Release-static|x64 = Release-static|x64
Release-static|x86 = Release-static|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Debug|x64.ActiveCfg = Debug|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Debug|x64.Build.0 = Debug|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Debug|x86.ActiveCfg = Debug|Win32
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Debug|x86.Build.0 = Debug|Win32
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release|x64.ActiveCfg = Release|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release|x64.Build.0 = Release|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release|x86.ActiveCfg = Release|Win32
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release|x86.Build.0 = Release|Win32
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release-static|x64.ActiveCfg = Release-static|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release-static|x64.Build.0 = Release-static|x64
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release-static|x86.ActiveCfg = Release-static|Win32
{E57919FC-F7EA-4551-B021-A1ACD2E324B1}.Release-static|x86.Build.0 = Release-static|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Debug|x64.ActiveCfg = Debug|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Debug|x64.Build.0 = Debug|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Debug|x86.ActiveCfg = Debug|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Debug|x86.Build.0 = Debug|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release|x64.ActiveCfg = Release|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release|x64.Build.0 = Release|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release|x86.ActiveCfg = Release|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release|x86.Build.0 = Release|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release-static|x64.ActiveCfg = Release-static|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release-static|x64.Build.0 = Release-static|x64
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release-static|x86.ActiveCfg = Release-static|Win32
{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}.Release-static|x86.Build.0 = Release-static|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Debug|x64.ActiveCfg = Debug|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Debug|x64.Build.0 = Debug|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Debug|x86.ActiveCfg = Debug|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Debug|x86.Build.0 = Debug|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release|x64.ActiveCfg = Release|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release|x64.Build.0 = Release|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release|x86.ActiveCfg = Release|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release|x86.Build.0 = Release|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release-static|x64.ActiveCfg = Release-static|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release-static|x64.Build.0 = Release-static|x64
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release-static|x86.ActiveCfg = Release-static|Win32
{BDBD265F-5914-426F-89F7-16478BE1AFCC}.Release-static|x86.Build.0 = Release-static|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {91D321FC-F13A-44DF-88BB-2B76CDE50DE2}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,296 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|Win32">
<Configuration>Release-static</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|x64">
<Configuration>Release-static</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{E57919FC-F7EA-4551-B021-A1ACD2E324B1}</ProjectGuid>
<RootNamespace>BonDriverPX4</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)include;$(SolutionDir)src\common;$(ProjectDir);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\common\config.cpp" />
<ClCompile Include="..\common\msg.c" />
<ClCompile Include="..\common\pipe.cpp" />
<ClCompile Include="..\common\util.cpp" />
<ClCompile Include="bon_driver.cpp" />
<ClCompile Include="chset.cpp" />
<ClCompile Include="cmd_client.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="io_queue.cpp" />
<ClCompile Include="pipe_client.cpp" />
<ClCompile Include="receiver_info_set.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\IBonDriver.h" />
<ClInclude Include="..\..\include\IBonDriver2.h" />
<ClInclude Include="..\common\command.hpp" />
<ClInclude Include="..\common\config.hpp" />
<ClInclude Include="..\common\msg.h" />
<ClInclude Include="..\common\pipe.hpp" />
<ClInclude Include="..\common\type.hpp" />
<ClInclude Include="..\common\util.hpp" />
<ClInclude Include="bon_driver.hpp" />
<ClInclude Include="chset.hpp" />
<ClInclude Include="cmd_client.hpp" />
<ClInclude Include="io_queue.hpp" />
<ClInclude Include="pipe_client.hpp" />
<ClInclude Include="receiver_info_set.hpp" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX-MLT.ini" />
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-S.ini" />
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-T.ini" />
<None Include="dll.def" />
</ItemGroup>
<ItemGroup>
<Text Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-S.ChSet.txt" />
<Text Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-T.ChSet.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="BonDriver_PX4.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="ソース ファイル">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="ヘッダー ファイル">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="リソース ファイル">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="パッケージ">
<UniqueIdentifier>{0d60a9d3-c999-47a3-a4fd-27e57fc16b6a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common\config.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\msg.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\pipe.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\util.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="bon_driver.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="chset.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="cmd_client.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="io_queue.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="pipe_client.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="receiver_info_set.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\IBonDriver.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\include\IBonDriver2.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\command.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\config.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\msg.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\pipe.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\type.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\util.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="bon_driver.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="chset.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="cmd_client.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="io_queue.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="pipe_client.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="receiver_info_set.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX-MLT.ini">
<Filter>パッケージ</Filter>
</None>
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-S.ini">
<Filter>パッケージ</Filter>
</None>
<None Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-T.ini">
<Filter>パッケージ</Filter>
</None>
<None Include="dll.def">
<Filter>ソース ファイル</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-S.ChSet.txt">
<Filter>パッケージ</Filter>
</Text>
<Text Include="..\..\pkg\BonDriver_PX4\BonDriver_PX4-T.ChSet.txt">
<Filter>パッケージ</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="BonDriver_PX4.rc">
<Filter>リソース ファイル</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,556 @@
// bon_driver.cpp
#include <string>
#include <map>
#include <stdexcept>
#include <windows.h>
#include <aclapi.h>
#include <shlwapi.h>
#include "bon_driver.hpp"
#include "config.hpp"
#include "chset.hpp"
#include "pipe_client.hpp"
#include "command.hpp"
#include "util.hpp"
namespace px4 {
BonDriver::BonDriver() noexcept
: mtx_(),
driver_host_path_(),
configs_(),
name_(),
systems_(px4::SystemType::UNSPECIFIED),
chset_(),
receivers_(),
ctrl_client_(nullptr),
data_pipe_(nullptr),
open_(FALSE),
space_(0),
ch_(0),
stream_mtx_(),
ioq_(nullptr),
iorp_(*this),
current_ofs_(0),
quit_event_(nullptr)
{
}
BonDriver::~BonDriver()
{
CloseTuner();
Term();
}
bool BonDriver::Init()
{
try {
const std::wstring &dir_path = px4::util::path::GetDir();
if (!configs_.Load(px4::util::path::GetFileBase() + L".ini"))
return false;
if (configs_.Exists(L"BonDriver")) {
const px4::Config &bon_config = configs_.Get(L"BonDriver");
const std::wstring &mode = bon_config.Get(L"System", L"ISDB-T");
WCHAR path[MAX_PATH];
if (!px4::util::ParseSystemStr(mode, systems_))
return false;
driver_host_path_ = bon_config.Get(L"DriverHostPath", dir_path + L"DriverHost_PX4.exe");
if (PathIsRelativeW(driver_host_path_.c_str()) && PathCanonicalizeW(path, (dir_path + driver_host_path_).c_str()))
driver_host_path_ = path;
name_ = bon_config.Get(L"Name", L"PX4");
} else {
systems_ = px4::SystemType::ISDB_T;
driver_host_path_ = dir_path + L"DriverHost_PX4.exe";
name_ = L"PX4";
}
if ((systems_ & px4::SystemType::ISDB_T) == px4::SystemType::ISDB_T) {
px4::ChannelSet chset_t;
bool result;
try {
result = chset_t.Load(configs_.Get(L"BonDriver.ISDB-T").Get(L"ChSetPath"), px4::SystemType::ISDB_T);
} catch (const std::out_of_range&) {
result = false;
}
if (!result) {
chset_t.Clear();
result = chset_t.Load(L".\\BonDriver_PX4-T.ChSet.txt", px4::SystemType::ISDB_T);
}
if (result)
chset_.Merge(chset_t);
}
if ((systems_ & px4::SystemType::ISDB_S) == px4::SystemType::ISDB_S) {
px4::ChannelSet chset_s;
bool result;
try {
result = chset_s.Load(configs_.Get(L"BonDriver.ISDB-S").Get(L"ChSetPath"), px4::SystemType::ISDB_S);
} catch (const std::out_of_range&) {
result = false;
}
if (!result) {
chset_s.Clear();
result = chset_s.Load(L".\\BonDriver_PX4-S.ChSet.txt", px4::SystemType::ISDB_S);
}
if (result)
chset_.Merge(chset_s);
}
receivers_.Load(configs_);
quit_event_ = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!quit_event_)
return false;
ioq_.reset(new px4::IoQueue(px4::IoQueue::IoOperation::READ, iorp_, 188 * 2048, 32, 2));
} catch (const std::runtime_error &e) {
MessageBoxA(nullptr, e.what(), "BonDriver_PX4 (BonDriver::Init)", MB_OK);
return false;
} catch (...) {
MessageBoxA(nullptr, "Fatal error!", "BonDriver_PX4 (BonDriver::Init)", MB_OK);
return false;
}
return true;
}
void BonDriver::Term() noexcept
{
ioq_.reset();
if (quit_event_)
CloseHandle(quit_event_);
}
const BOOL BonDriver::OpenTuner()
{
BOOL ret = TRUE;
std::lock_guard<std::mutex> lock(mtx_);
if (open_)
return TRUE;
try {
SID_IDENTIFIER_AUTHORITY sia;
PSID sid = nullptr;
EXPLICIT_ACCESSW ea;
PACL acl = nullptr;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
HANDLE startup_event;
DWORD st;
sia = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sid))
throw BonDriverError("BonDriver::OpenTuner: AllocateAndInitializeSid() failed.");
memset(&ea, 0, sizeof(ea));
ea.grfAccessPermissions = EVENT_ALL_ACCESS;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPWSTR)sid;
if (SetEntriesInAclW(1, &ea, nullptr, &acl) != ERROR_SUCCESS) {
LocalFree(sid);
throw BonDriverError("BonDriver::OpenTuner: SetEntriesInAclW() failed.");
}
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
startup_event = CreateEventW(&sa, TRUE, FALSE, L"DriverHost_PX4_StartupEvent");
LocalFree(acl);
LocalFree(sid);
if (!startup_event) {
throw BonDriverError("BonDriver::OpenTuner: CreateEventW(\"DriverHost_PX4_StartupEvent\") failed.");
} else if (GetLastError() != ERROR_ALREADY_EXISTS) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
if (!CreateProcessW(driver_host_path_.c_str(), nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
CloseHandle(startup_event);
throw BonDriverError("BonDriver::OpenTuner: CreateProcessW() failed.");
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
st = WaitForSingleObject(startup_event, 10000);
CloseHandle(startup_event);
if (st != WAIT_OBJECT_0)
throw BonDriverError("BonDriver::OpenTuner: WaitForSingleObject() failed.");
std::unique_ptr<px4::PipeClient> ctrl_pipe(new px4::PipeClient());
px4::PipeClient::PipeClientConfig ctrl_pipe_config;
px4::command::ReceiverInfo ri_res;
ctrl_pipe_config.stream_read = false;
ctrl_pipe_config.timeout = 2000;
if (!ctrl_pipe->Connect(L"px4_ctrl_pipe", ctrl_pipe_config, nullptr)) {
throw BonDriverError("BonDriver::OpenTuner: control pipe: cannot connect.");
}
ctrl_client_.SetPipe(ctrl_pipe);
for (std::size_t i = 0; ; i++) {
const px4::command::ReceiverInfo &ri = receivers_.Get(i);
if (ctrl_client_.Open(ri, systems_, &ri_res))
break;
}
px4::PipeClient::PipeClientConfig data_pipe_config;
data_pipe_config.stream_read = true;
data_pipe_config.timeout = 2000;
data_pipe_.reset(new px4::PipeClient());
if (!data_pipe_->Connect(L"px4_data_pipe", data_pipe_config, nullptr)) {
throw BonDriverError("BonDriver::OpenTuner: data pipe: cannot connect.");
}
px4::command::DataCmd data_cmd;
std::size_t ret_size;
data_cmd.cmd = px4::command::DataCmdCode::SET_DATA_ID;
data_cmd.data_id = ri_res.data_id;
if (!data_pipe_->Write(&data_cmd, sizeof(data_cmd), ret_size)) {
data_pipe_.reset();
ctrl_client_.Close();
ctrl_client_.ClearPipe();
throw BonDriverError("BonDriver::OpenTuner: command failed.");
}
if (!ctrl_client_.SetCapture(true)) {
data_pipe_.reset();
ctrl_client_.Close();
ctrl_client_.ClearPipe();
throw BonDriverError("BonDriver::OpenTuner: command failed.");
}
ioq_->Start();
open_ = TRUE;
} catch (const std::out_of_range &) {
ret = FALSE;
MessageBoxA(nullptr, "BonDriver::OpenTuner: cannot open.", "BonDriver_PX4 (BonDriver::OpenTuner)", MB_OK | MB_ICONERROR);
} catch (const std::exception &e) {
ret = FALSE;
MessageBoxA(nullptr, e.what(), "BonDriver_PX4 (BonDriver::OpenTuner)", MB_OK | MB_ICONERROR);
} catch (...) {
ret = FALSE;
MessageBoxA(nullptr, "Fatal error!", "BonDriver_PX4 (BonDriver::OpenTuner)", MB_OK | MB_ICONERROR);
}
if (!open_) {
if (data_pipe_) {
SetEvent(quit_event_);
ioq_->Stop();
data_pipe_.reset();
}
ctrl_client_.ClearPipe();
}
return ret;
}
void BonDriver::CloseTuner()
{
std::lock_guard<std::mutex> lock(mtx_);
if (!open_)
return;
if (data_pipe_) {
SetEvent(quit_event_);
ioq_->Stop();
data_pipe_.reset();
}
ctrl_client_.ClearPipe();
space_ = 0;
ch_ = 0;
open_ = FALSE;
return;
}
const BOOL BonDriver::SetChannel(const BYTE bCh)
{
return SetChannel(0, bCh);
}
const float BonDriver::GetSignalLevel(void)
{
std::lock_guard<std::mutex> lock(mtx_);
if (!open_)
return 0.0f;
px4::command::StatSet stat_set;
stat_set.num = 1;
stat_set.data[0].type = px4::command::StatType::CNR;
stat_set.data[0].value = 0;
if (!ctrl_client_.ReadStats(stat_set))
return 0.0f;
return static_cast<float>(stat_set.data[0].value) / 1000.0f;
}
const DWORD BonDriver::WaitTsStream(const DWORD dwTimeOut)
{
return (ioq_->WaitDataBuffer(std::chrono::milliseconds((dwTimeOut == INFINITE) ? 5000 : dwTimeOut))) ? WAIT_OBJECT_0 : WAIT_TIMEOUT;
}
const DWORD BonDriver::GetReadyCount(void)
{
return static_cast<::DWORD>(ioq_->GetDataBufferCount() + (ioq_->HaveReadingBuffer() ? 1 : 0));
}
const BOOL BonDriver::GetTsStream(BYTE *pDst, DWORD *pdwSize, DWORD *pdwRemain)
{
if (!pDst || !pdwSize)
return FALSE;
std::size_t size, remain;
if (!ioq_->Read(pDst, size, remain, false))
return FALSE;
*pdwSize = static_cast<::DWORD>(size);
if (pdwRemain)
*pdwRemain = static_cast<::DWORD>(remain);
return TRUE;
}
const BOOL BonDriver::GetTsStream(BYTE **ppDst, DWORD *pdwSize, DWORD *pdwRemain)
{
if (!ppDst || !pdwSize)
return FALSE;
std::size_t size, remain;
if (!ioq_->ReadBuffer(reinterpret_cast<void **>(ppDst), size, remain, false))
return FALSE;
*pdwSize = static_cast<::DWORD>(size);
if (pdwRemain)
*pdwRemain = static_cast<::DWORD>(remain);
return TRUE;
}
void BonDriver::PurgeTsStream(void)
{
ioq_->PurgeDataBuffer();
return;
}
void BonDriver::Release(void)
{
delete this;
}
LPCTSTR BonDriver::GetTunerName(void)
{
return name_.c_str();
}
const BOOL BonDriver::IsTunerOpening(void)
{
return open_;
}
LPCTSTR BonDriver::EnumTuningSpace(const DWORD dwSpace)
{
try {
return chset_.GetSpaceName(dwSpace).c_str();
} catch (const std::out_of_range&) {
return nullptr;
}
}
LPCTSTR BonDriver::EnumChannelName(const DWORD dwSpace, const DWORD dwChannel)
{
try {
return chset_.GetChannel(dwSpace, dwChannel).name.c_str();
} catch (const std::out_of_range&) {
return nullptr;
}
}
const BOOL BonDriver::SetChannel(const DWORD dwSpace, const DWORD dwChannel)
{
if (!open_)
return FALSE;
if (!chset_.ExistsChannel(dwSpace, dwChannel))
return FALSE;
const px4::ChannelSet::ChannelInfo &channel = chset_.GetChannel(dwSpace, dwChannel);
px4::SystemType system = chset_.GetSpaceSystem(dwSpace);
std::uint32_t real_freq, num_param = 0;
switch (system) {
case px4::SystemType::ISDB_T:
if ((channel.ptx_ch >= 3 && channel.ptx_ch <= 12) || (channel.ptx_ch >= 22 && channel.ptx_ch <= 62)) {
// CATV C13-22ch, C23-63ch
real_freq = 93143 + (channel.ptx_ch * 6000);
if (channel.ptx_ch == 12)
real_freq += 2000;
} else if (channel.ptx_ch >= 63 && channel.ptx_ch <= 112) {
// UHF 13-62ch
real_freq = 95143 + (channel.ptx_ch * 6000);
} else {
// unknown channel
return FALSE;
}
break;
case px4::SystemType::ISDB_S:
if (channel.ptx_ch <= 11) {
// BS
real_freq = 1049480 + (channel.ptx_ch * 38360);
} else if (channel.ptx_ch <= 23) {
// CS 110
real_freq = 1613000 + ((channel.ptx_ch - 12) * 40000);
} else {
// unknown channel
return FALSE;
}
num_param = 1;
break;
default:
// unknown system
return FALSE;
}
px4::command::ParameterSet *param_set = reinterpret_cast<px4::command::ParameterSet*>(new std::uint8_t[sizeof(*param_set) - sizeof(param_set->params) + (sizeof(param_set->params[0]) * num_param)]);
param_set->system = system;
param_set->freq = real_freq;
param_set->num = num_param;
if (system == px4::SystemType::ISDB_S && num_param) {
param_set->params[0].type = px4::command::ParameterType::STREAM_ID;
param_set->params[0].value = channel.tsid;
}
bool ret = false;
try {
ret = ctrl_client_.SetParams(*param_set);
if (ret)
ret = ctrl_client_.Tune();
} catch (const std::exception &e) {
MessageBoxA(nullptr, e.what(), "BonDriver_PX4 (BonDriver::SetChannel)", MB_OK | MB_ICONERROR);
} catch (...) {
MessageBoxA(nullptr, "Fatal error!", "BonDriver_PX4 (BonDriver::SetChannel)", MB_OK | MB_ICONERROR);
}
delete[] reinterpret_cast<std::uint8_t*>(param_set);
if (ret) {
// succeeded
space_ = dwSpace;
ch_ = dwChannel;
}
return !!ret;
}
const DWORD BonDriver::GetCurSpace(void)
{
return space_;
}
const DWORD BonDriver::GetCurChannel(void)
{
return ch_;
}
bool BonDriver::ReadProvider::Start()
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
return true;
}
void BonDriver::ReadProvider::Stop()
{
return;
}
bool BonDriver::ReadProvider::Do(void *buf, std::size_t &size)
{
return parent_.data_pipe_->Read(buf, size, size, parent_.quit_event_);
}
} // namespace px4
#pragma warning(disable: 4273)
extern "C" IBonDriver* CreateBonDriver()
{
try {
auto bon = new px4::BonDriver();
if (!bon)
return nullptr;
if (!bon->Init()) {
delete bon;
return nullptr;
}
return bon;
} catch (const std::exception &e) {
MessageBoxA(nullptr, e.what(), "BonDriver_PX4 (CreateBonDriver)", MB_ICONERROR | MB_OK);
return nullptr;
} catch (...) {
MessageBoxA(nullptr, "Fatal error!", "BonDriver_PX4 (CreateBonDriver)", MB_ICONERROR | MB_OK);
return nullptr;
}
}
#pragma warning(default: 4273)

View File

@@ -0,0 +1,101 @@
// bon_driver.hpp
#pragma once
#include <memory>
#include <string>
#include <mutex>
#include <map>
#include <queue>
#include <stdexcept>
#include <windows.h>
#include "IBonDriver2.h"
#include "config.hpp"
#include "chset.hpp"
#include "receiver_info_set.hpp"
#include "pipe_client.hpp"
#include "command.hpp"
#include "cmd_client.hpp"
#include "io_queue.hpp"
namespace px4 {
class BonDriver final : public IBonDriver2 {
public:
BonDriver() noexcept;
~BonDriver();
bool Init();
void Term() noexcept;
// IBonDriver
const BOOL OpenTuner(void) override;
void CloseTuner(void) override;
const BOOL SetChannel(const BYTE bCh) override;
const float GetSignalLevel(void) override;
const DWORD WaitTsStream(const DWORD dwTimeOut = 0) override;
const DWORD GetReadyCount(void) override;
const BOOL GetTsStream(BYTE *pDst, DWORD *pdwSize, DWORD *pdwRemain) override;
const BOOL GetTsStream(BYTE **ppDst, DWORD *pdwSize, DWORD *pdwRemain) override;
void PurgeTsStream(void) override;
void Release(void) override;
// IBonDriver2
LPCTSTR GetTunerName(void) override;
const BOOL IsTunerOpening(void) override;
LPCTSTR EnumTuningSpace(const DWORD dwSpace) override;
LPCTSTR EnumChannelName(const DWORD dwSpace, const DWORD dwChannel) override;
const BOOL SetChannel(const DWORD dwSpace, const DWORD dwChannel) override;
const DWORD GetCurSpace(void) override;
const DWORD GetCurChannel(void) override;
private:
class ReadProvider final : public IoQueue::IoProvider {
public:
explicit ReadProvider(BonDriver& parent) : parent_(parent) {}
~ReadProvider() {}
bool Start() override;
void Stop() override;
bool Do(void *buf, std::size_t &size) override;
private:
BonDriver &parent_;
};
std::mutex mtx_;
std::wstring driver_host_path_;
px4::ConfigSet configs_;
std::wstring name_;
px4::SystemType systems_;
px4::ChannelSet chset_;
px4::ReceiverInfoSet receivers_;
px4::CtrlCmdClient ctrl_client_;
std::unique_ptr<px4::PipeClient> data_pipe_;
BOOL open_;
DWORD space_, ch_;
std::mutex stream_mtx_;
std::unique_ptr<px4::IoQueue> ioq_;
ReadProvider iorp_;
std::size_t current_ofs_;
HANDLE quit_event_;
};
class BonDriverError : public std::runtime_error {
public:
explicit BonDriverError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,213 @@
// chset.cpp
#include "chset.hpp"
#include <mutex>
#include <fstream>
#include "util.hpp"
namespace px4 {
bool ChannelSet::Load(const std::wstring &path, px4::SystemType system) noexcept
{
std::lock_guard<std::shared_mutex> lock(mtx_);
std::ifstream ifs(path);
if (!ifs.is_open())
return false;
std::unordered_map<std::uint32_t, std::uint32_t> space_id_table;
while (true) {
char line[256];
std::streamsize gcount;
char *tmp_head, *tmp_tail = nullptr;
if (!ifs.getline(line, 256))
break;
gcount = ifs.gcount();
if (!gcount)
continue;
if (line[gcount] == '\r') {
// CRLF
line[gcount] = '\0';
gcount--;
}
if (line[0] == ';') {
// comment
continue;
}
if (line[0] == '$') {
// tuning space
std::wstring name;
std::uint32_t space_id;
tmp_head = line + 1;
// name
Split(&tmp_head, &tmp_tail, '\t');
px4::util::ShiftJisToUtf16(tmp_head, name);
// space
Split(&tmp_head, &tmp_tail, '\t');
space_id = px4::util::atoui(tmp_head);
space_id_table.emplace(space_id, next_space_id_);
if (!AddSpace(next_space_id_++, &name, system))
return false;
} else {
// channel
std::uint32_t space_id, ch_id;
ChannelInfo ch;
tmp_head = line;
// name
Split(&tmp_head, &tmp_tail, '\t');
px4::util::ShiftJisToUtf16(tmp_head, ch.name);
// space
Split(&tmp_head, &tmp_tail, '\t');
space_id = px4::util::atoui(tmp_head);
try {
space_id = space_id_table.at(space_id);
} catch (const std::out_of_range&) {
if (strict_)
return false;
else
continue;
}
// ch
Split(&tmp_head, &tmp_tail, '\t');
ch_id = px4::util::atoui(tmp_head);
// ptx_ch
Split(&tmp_head, &tmp_tail, '\t');
ch.ptx_ch = px4::util::atoui(tmp_head);
// tsid
Split(&tmp_head, &tmp_tail, '\t');
ch.tsid = static_cast<std::uint16_t>(px4::util::atoui(tmp_head));
if (!AddChannel(space_id, ch_id, ch))
return false;
}
}
return true;
}
bool ChannelSet::Merge(ChannelSet &chset) noexcept
{
// TODO: Space ID<49><44><EFBFBD><EFBFBD><EFBFBD>
try {
for (auto it = chset.spaces_.cbegin(); it != chset.spaces_.cend(); ++it)
spaces_.emplace_back(*it);
return true;
} catch (...) {
return false;
}
}
bool ChannelSet::ExistsSpace(std::uint32_t space_id) const noexcept
{
std::shared_lock<std::shared_mutex> lock(mtx_);
return (spaces_.size() > space_id);
}
const std::wstring& ChannelSet::GetSpaceName(std::uint32_t space_id) const
{
std::shared_lock<std::shared_mutex> lock(mtx_);
return spaces_.at(space_id).name;
}
px4::SystemType ChannelSet::GetSpaceSystem(std::uint32_t space_id) const
{
std::shared_lock<std::shared_mutex> lock(mtx_);
return spaces_.at(space_id).system;
}
bool ChannelSet::ExistsChannel(std::uint32_t space_id, std::uint32_t ch_id) const noexcept
{
std::shared_lock<std::shared_mutex> lock(mtx_);
try {
return !!spaces_.at(space_id).channels.count(ch_id);
} catch (const std::out_of_range&) {
return false;
}
}
const px4::ChannelSet::ChannelInfo& ChannelSet::GetChannel(std::uint32_t space_id, std::uint32_t ch_id) const
{
std::shared_lock<std::shared_mutex> lock(mtx_);
return spaces_.at(space_id).channels.at(ch_id);
}
bool ChannelSet::AddSpace(std::uint32_t space_id, const std::wstring *name, px4::SystemType system) noexcept
{
if (spaces_.size() > space_id) {
auto& space = spaces_.at(space_id);
if (name && space.name.empty())
space.name = *name;
if (space.system == px4::SystemType::UNSPECIFIED)
space.system = system;
} else if (name) {
spaces_.emplace_back(SpaceInfo(*name, system));
} else if (!strict_) {
spaces_.emplace_back(SpaceInfo(system));
} else {
return false;
}
return true;
}
bool ChannelSet::AddChannel(std::uint32_t space_id, std::uint32_t ch_id, const ChannelInfo &ch) noexcept
{
if (!AddSpace(space_id, nullptr))
return false;
auto& space = spaces_.at(space_id);
if (space.channels.count(ch_id))
space.channels.at(ch_id) = ch;
else
space.channels.emplace(ch_id, ch);
return true;
}
void ChannelSet::Split(char **head, char **tail, char c) noexcept
{
char *h = *head, *t = *tail;
if (t)
h = t + 1;
t = std::strchr(h, c);
if (t)
*t = '\0';
*head = h;
*tail = t;
return;
}
} // namespace px4

View File

@@ -0,0 +1,59 @@
// chset.hpp
#pragma once
#include <string>
#include <shared_mutex>
#include <vector>
#include <unordered_map>
#include <stdexcept>
#include "type.hpp"
namespace px4 {
class ChannelSet final {
public:
struct ChannelInfo final {
ChannelInfo() noexcept : ptx_ch(0), tsid(0) {}
std::wstring name;
std::uint32_t ptx_ch;
std::uint16_t tsid;
};
struct SpaceInfo final {
explicit SpaceInfo(px4::SystemType system = px4::SystemType::UNSPECIFIED) noexcept : SpaceInfo(L"", system) {}
explicit SpaceInfo(const std::wstring &name, px4::SystemType system = px4::SystemType::UNSPECIFIED) noexcept
: name(name),
system(system)
{}
std::wstring name;
px4::SystemType system;
std::unordered_map<std::uint32_t, ChannelInfo> channels;
};
public:
explicit ChannelSet(bool strict = false) noexcept : next_space_id_(0) { SetStrict(strict); }
~ChannelSet() {}
void SetStrict(bool strict) noexcept { strict_ = strict; }
void Clear() noexcept { spaces_.clear(); next_space_id_ = 0; }
bool Load(const std::wstring &path, px4::SystemType system) noexcept;
bool Merge(ChannelSet &chset) noexcept;
bool ExistsSpace(std::uint32_t space_id) const noexcept;
const std::wstring& GetSpaceName(std::uint32_t space_id) const;
px4::SystemType GetSpaceSystem(std::uint32_t space_id) const;
bool ExistsChannel(std::uint32_t space_id, std::uint32_t ch_id) const noexcept;
const ChannelInfo& GetChannel(std::uint32_t space_id, std::uint32_t ch_id) const;
private:
bool AddSpace(uint32_t space_id, const std::wstring *name, px4::SystemType system = px4::SystemType::UNSPECIFIED) noexcept;
bool AddChannel(uint32_t space_id, uint32_t ch_id, const ChannelInfo& ch) noexcept;
static void Split(char **head, char **tail, char c) noexcept;
bool strict_;
mutable std::shared_mutex mtx_;
std::uint32_t next_space_id_;
std::vector<SpaceInfo> spaces_;
};
} // namespace px4

View File

@@ -0,0 +1,152 @@
// cmd_client.cpp
#include "cmd_client.hpp"
namespace px4 {
bool CtrlCmdClient::Open(const px4::command::ReceiverInfo &in, px4::SystemType systems, px4::command::ReceiverInfo *out) noexcept
{
px4::command::CtrlOpenCmd open_cmd;
if ((systems & in.systems) == px4::SystemType::UNSPECIFIED)
return false;
open_cmd.cmd = px4::command::CtrlCmdCode::OPEN;
open_cmd.status = px4::command::CtrlStatusCode::NONE;
wcscpy_s(open_cmd.receiver_info.device_name, in.device_name);
open_cmd.receiver_info.device_guid = in.device_guid;
wcscpy_s(open_cmd.receiver_info.receiver_name, in.receiver_name);
open_cmd.receiver_info.receiver_guid = in.receiver_guid;
open_cmd.receiver_info.systems = systems & in.systems;
open_cmd.receiver_info.index = in.index;
open_cmd.receiver_info.data_id = 0;
bool ret = Call(open_cmd);
if (out)
*out = open_cmd.receiver_info;
return ret;
}
bool CtrlCmdClient::Close() noexcept
{
px4::command::CtrlCloseCmd close_cmd;
close_cmd.cmd = px4::command::CtrlCmdCode::CLOSE;
close_cmd.status = px4::command::CtrlStatusCode::NONE;
return Call(close_cmd);
}
bool CtrlCmdClient::GetInfo(px4::command::ReceiverInfo &receiver_info) noexcept
{
px4::command::CtrlReceiverInfoCmd info_cmd;
info_cmd.cmd = px4::command::CtrlCmdCode::GET_INFO;
info_cmd.status = px4::command::CtrlStatusCode::NONE;
info_cmd.receiver_info = receiver_info;
bool ret = Call(info_cmd);
if (ret)
receiver_info = info_cmd.receiver_info;
return ret;
}
bool CtrlCmdClient::SetCapture(bool capture) noexcept
{
px4::command::CtrlCaptureCmd capture_cmd;
capture_cmd.cmd = px4::command::CtrlCmdCode::SET_CAPTURE;
capture_cmd.status = px4::command::CtrlStatusCode::NONE;
capture_cmd.capture = capture;
return Call(capture_cmd);
}
bool CtrlCmdClient::GetParams(px4::command::ParameterSet &param_set) noexcept
{
px4::command::CtrlParamsCmd params_cmd;
params_cmd.cmd = px4::command::CtrlCmdCode::GET_PARAMS;
params_cmd.status = px4::command::CtrlStatusCode::NONE;
params_cmd.param_set = param_set;
bool ret = Call(params_cmd);
if (ret)
param_set = params_cmd.param_set;
return ret;
}
bool CtrlCmdClient::SetParams(const px4::command::ParameterSet &param_set) noexcept
{
px4::command::CtrlParamsCmd params_cmd;
params_cmd.cmd = px4::command::CtrlCmdCode::SET_PARAMS;
params_cmd.status = px4::command::CtrlStatusCode::NONE;
params_cmd.param_set = param_set;
return Call(params_cmd);
}
bool CtrlCmdClient::ClearParams() noexcept
{
px4::command::CtrlClearParamsCmd clear_cmd;
clear_cmd.cmd = px4::command::CtrlCmdCode::CLEAR_PARAMS;
clear_cmd.status = px4::command::CtrlStatusCode::NONE;
return Call(clear_cmd);
}
bool CtrlCmdClient::Tune() noexcept
{
px4::command::CtrlTuneCmd tune_cmd;
tune_cmd.cmd = px4::command::CtrlCmdCode::TUNE;
tune_cmd.status = px4::command::CtrlStatusCode::NONE;
return Call(tune_cmd);
}
bool CtrlCmdClient::SetLnbVoltage(std::int32_t voltage) noexcept
{
px4::command::CtrlLnbVoltageCmd lnb_cmd;
lnb_cmd.cmd = px4::command::CtrlCmdCode::SET_LNB_VOLTAGE;
lnb_cmd.status = px4::command::CtrlStatusCode::NONE;
lnb_cmd.voltage = voltage;
return Call(lnb_cmd);
}
bool CtrlCmdClient::ReadStats(px4::command::StatSet &stat_set) noexcept
{
px4::command::CtrlStatsCmd stat_cmd;
stat_cmd.cmd = px4::command::CtrlCmdCode::READ_STATS;
stat_cmd.status = px4::command::CtrlStatusCode::NONE;
stat_cmd.stat_set = stat_set;
bool ret = Call(stat_cmd);
if (ret)
stat_set = stat_cmd.stat_set;
return ret;
}
template <typename T>
bool CtrlCmdClient::Call(T& cmd) noexcept
{
if (!pipe_)
return false;
return (pipe_->Call(&cmd, sizeof(cmd)) && cmd.status == px4::command::CtrlStatusCode::SUCCEEDED);
}
} // namespace px4

View File

@@ -0,0 +1,47 @@
// cmd_client.hpp
#pragma once
#include <memory>
#include "command.hpp"
#include "pipe.hpp"
#include "pipe_client.hpp"
namespace px4 {
class CtrlCmdClient final {
public:
explicit CtrlCmdClient(px4::PipeClient *pipe = nullptr) noexcept : pipe_(pipe) {}
~CtrlCmdClient() {}
// cannot copy
CtrlCmdClient(const CtrlCmdClient &) = delete;
CtrlCmdClient& operator=(const CtrlCmdClient &) = delete;
// cannot move
CtrlCmdClient(CtrlCmdClient &&) = delete;
CtrlCmdClient& operator=(CtrlCmdClient &&) = delete;
void SetPipe(px4::PipeClient *pipe) noexcept { pipe_.reset(pipe); }
void SetPipe(std::unique_ptr<px4::PipeClient> &pipe) noexcept { pipe_ = std::move(pipe); }
void ClearPipe() noexcept { pipe_.reset(); }
bool Open(const px4::command::ReceiverInfo &in, px4::SystemType systems, px4::command::ReceiverInfo *out) noexcept;
bool Close() noexcept;
bool GetInfo(px4::command::ReceiverInfo &receiver_info) noexcept;
bool SetCapture(bool capture) noexcept;
bool GetParams(px4::command::ParameterSet &param_set) noexcept;
bool SetParams(const px4::command::ParameterSet &param_set) noexcept;
bool ClearParams() noexcept;
bool Tune() noexcept;
bool SetLnbVoltage(std::int32_t voltage) noexcept;
bool ReadStats(px4::command::StatSet& stat_set) noexcept;
private:
template <typename T> bool Call(T &cmd) noexcept;
std::unique_ptr<px4::PipeClient> pipe_;
};
} // namespace px4

View File

@@ -0,0 +1,3 @@
LIBRARY BonDriver_PX4
EXPORTS
CreateBonDriver

View File

@@ -0,0 +1,22 @@
// dllmain.cpp
#include <windows.h>
#include "util.hpp"
BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
BOOL ret = TRUE;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
if (!px4::util::path::Init(hinstDLL))
ret = FALSE;
break;
default:
break;
}
return ret;
}

View File

@@ -0,0 +1,417 @@
// SPDX-License-Identifier: MIT
/*
* I/O queue operator (io_queue.cpp)
*
* Copyright (c) 2021 nns779
*/
#include "io_queue.hpp"
#include <cstring>
#include <utility>
namespace px4 {
IoQueue::IoQueue(IoOperation io_op, IoProvider &iop, std::size_t buf_size, std::uintptr_t max, std::uintptr_t min)
: io_op_(io_op),
iop_(iop),
buf_size_(buf_size),
max_(max),
min_(min),
total_buf_num_(0),
current_ofs_(0)
{
while (min--)
IncreaseFreeBuffer();
}
IoQueue::~IoQueue()
{
Stop();
data_buf_.clear();
free_buf_.clear();
}
bool IoQueue::Start()
{
std::lock_guard<std::mutex> lock(mtx_);
if (th_)
return true;
std::unique_lock<std::mutex> free_lock(free_mtx_);
std::unique_lock<std::mutex> data_lock(data_mtx_);
for (auto it = free_buf_.begin(); it != free_buf_.end();) {
if (!*it)
it = free_buf_.erase(it);
else
++it;
}
if (current_buf_) {
free_buf_.push_back(std::move(current_buf_));
current_ofs_ = 0;
}
while (!data_buf_.empty()) {
auto buf = std::move(data_buf_.front());
data_buf_.pop_front();
if (!buf)
continue;
free_buf_.push_back(std::move(buf));
}
free_lock.unlock();
free_cond_.notify_all();
data_lock.unlock();
th_.reset(new std::thread((io_op_ == IoOperation::READ) ? &px4::IoQueue::ReadWorker : &px4::IoQueue::WriteWorker, this));
return true;
}
bool IoQueue::Stop()
{
std::lock_guard<std::mutex> lock(mtx_);
if (!th_)
return true;
if (io_op_ == IoOperation::READ) {
// stop ReadWorker
PushBackFreeBuffer(nullptr);
} else {
if (current_buf_) {
// flush
PushBackDataBuffer(std::move(current_buf_));
current_ofs_ = 0;
}
// stop WriteWorker
PushBackDataBuffer(nullptr);
}
try {
th_->join();
} catch (...) {}
th_.reset();
return true;
}
std::size_t IoQueue::GetDataBufferCount() const
{
std::lock_guard<std::mutex> lock(data_mtx_);
return data_buf_.size();
}
std::size_t IoQueue::GetFreeBufferCount() const
{
std::lock_guard<std::mutex> lock(free_mtx_);
return free_buf_.size();
}
bool IoQueue::WaitDataBuffer(std::chrono::milliseconds ms)
{
std::lock_guard<std::mutex> lock(mtx_);
std::unique_lock<std::mutex> data_lock(data_mtx_);
if (data_buf_.size())
return true;
if (ms.count()) {
if (data_cond_.wait_for(data_lock, ms) == std::cv_status::timeout)
return false;
} else {
data_cond_.wait(data_lock);
}
return true;
}
void IoQueue::PurgeDataBuffer()
{
std::lock_guard<std::mutex> lock(mtx_);
std::unique_lock<std::mutex> free_lock(free_mtx_);
std::lock_guard<std::mutex> data_lock(data_mtx_);
if (current_buf_) {
free_buf_.push_back(std::move(current_buf_));
current_ofs_ = 0;
}
while (!data_buf_.empty()) {
auto buf = std::move(data_buf_.front());
data_buf_.pop_front();
free_buf_.push_back(std::move(buf));
}
free_lock.unlock();
free_cond_.notify_all();
return;
}
bool IoQueue::Read(void *buf, std::size_t &size, std::size_t &remain_count, bool blocking)
{
if (io_op_ != IoOperation::READ)
return false;
bool ret = false;
std::lock_guard<std::mutex> lock(mtx_);
std::uint8_t *p = static_cast<std::uint8_t*>(buf);
std::size_t remain = size;
while (remain) {
if (!current_buf_) {
current_buf_ = PopFrontDataBuffer(blocking);
if (!current_buf_)
break;
}
auto buf = current_buf_.get();
std::size_t rlen = ((buf->actual_length - current_ofs_) < remain) ? (buf->actual_length - current_ofs_) : remain;
std::memcpy(p, buf->buf.get() + current_ofs_, rlen);
current_ofs_ += rlen;
p += rlen;
remain -= rlen;
ret = true;
if (buf->actual_length == current_ofs_) {
PushBackFreeBuffer(std::move(current_buf_));
current_ofs_ = 0;
}
}
size -= remain;
remain_count = GetDataBufferCount() + ((current_buf_) ? 1 : 0);
return ret;
}
bool IoQueue::ReadBuffer(void **buf, std::size_t &size, std::size_t &remain_count, bool blocking)
{
if (io_op_ != IoOperation::READ)
return false;
remain_count = 0;
std::lock_guard<std::mutex> lock(mtx_);
if (current_buf_ && current_buf_->actual_length == current_ofs_) {
PushBackFreeBuffer(std::move(current_buf_));
current_ofs_ = 0;
}
if (!current_buf_) {
current_buf_ = PopFrontDataBuffer(blocking);
if (!current_buf_)
return false;
}
*buf = current_buf_->buf.get() + current_ofs_;
size = current_buf_->actual_length - current_ofs_;
current_ofs_ = current_buf_->actual_length;
remain_count = GetDataBufferCount();
return true;
}
bool IoQueue::HaveReadingBuffer()
{
return !!current_buf_;
}
bool IoQueue::Write(void *buf, std::size_t &size, bool blocking)
{
// not implemented
return false;
}
bool IoQueue::IncreaseFreeBuffer()
{
if (total_buf_num_ >= max_)
return false;
auto buf = new IoBuffer;
buf->buf.reset(new std::uint8_t[buf_size_]);
buf->actual_length = 0;
free_buf_.emplace_front(buf);
total_buf_num_++;
return true;
}
void IoQueue::DecreaseFreeBuffer()
{
if (free_buf_.empty() || !free_buf_.front())
return;
free_buf_.pop_front();
total_buf_num_--;
return;
}
bool IoQueue::PushBackDataBuffer(std::unique_ptr<IoBuffer> &&buf)
{
std::unique_lock<std::mutex> lock(data_mtx_);
data_buf_.push_back(std::move(buf));
lock.unlock();
data_cond_.notify_all();
return true;
}
bool IoQueue::PushBackFreeBuffer(std::unique_ptr<IoBuffer> &&buf)
{
std::unique_lock<std::mutex> lock(free_mtx_);
free_buf_.push_back(std::move(buf));
lock.unlock();
free_cond_.notify_all();
return true;
}
std::unique_ptr<IoQueue::IoBuffer> IoQueue::PopFrontDataBuffer(bool wait)
{
std::unique_lock<std::mutex> lock(data_mtx_);
if (data_buf_.empty()) {
if (wait) {
do {
data_cond_.wait(lock);
} while (data_buf_.empty());
} else {
return nullptr;
}
}
auto buf = std::move(data_buf_.front());
data_buf_.pop_front();
if (!buf)
data_buf_.push_front(nullptr);
return buf;
}
std::unique_ptr<IoQueue::IoBuffer> IoQueue::PopBackFreeBuffer(bool wait)
{
std::unique_lock<std::mutex> lock(free_mtx_);
auto size = free_buf_.size();
if (!size) {
if (!IncreaseFreeBuffer()) {
if (wait) {
do {
free_cond_.wait(lock);
} while (free_buf_.empty());
} else {
return nullptr;
}
}
} else if (size > min_) {
DecreaseFreeBuffer();
}
auto buf = std::move(free_buf_.back());
free_buf_.pop_back();
if (!buf)
free_buf_.push_back(nullptr);
return buf;
}
void IoQueue::ReadWorker()
{
if (!iop_.Start())
return;
while (true) {
auto buf = PopBackFreeBuffer(true);
if (!buf) {
PushBackDataBuffer(nullptr);
break;
}
std::size_t rofs = 0;
bool quit = false;
while (rofs < buf_size_) {
std::size_t rlen = buf_size_ - rofs;
if (!iop_.Do(buf->buf.get() + rofs, rlen)) {
quit = true;
break;
}
rofs += rlen;
}
buf->actual_length = rofs;
PushBackDataBuffer(std::move(buf));
if (quit) {
PushBackDataBuffer(nullptr);
break;
}
}
iop_.Stop();
}
void IoQueue::WriteWorker()
{
if (!iop_.Start())
return;
while (true) {
auto buf = PopFrontDataBuffer(true);
if (!buf) {
PushBackFreeBuffer(nullptr);
break;
}
std::size_t len = buf->actual_length, wofs = 0;
bool quit = false;
while (wofs < len) {
std::size_t wlen = len - wofs;
if (!iop_.Do(buf->buf.get() + wofs, wlen)) {
quit = true;
break;
}
wofs += wlen;
}
PushBackFreeBuffer(std::move(buf));
if (quit) {
PushBackFreeBuffer(nullptr);
break;
}
}
iop_.Stop();
}
} // namespace px4

View File

@@ -0,0 +1,87 @@
// io_queue.hpp
#pragma once
#include <cstddef>
#include <cstdint>
#include <memory>
#include <chrono>
#include <mutex>
#include <deque>
#include <condition_variable>
#include <thread>
namespace px4 {
class IoQueue final {
public:
enum class IoOperation : int {
READ = 0,
WRITE
};
struct IoBuffer final {
std::unique_ptr<std::uint8_t[]> buf;
std::size_t actual_length;
};
class IoProvider {
public:
IoProvider() noexcept {}
virtual ~IoProvider() {}
virtual bool Start() = 0;
virtual void Stop() = 0;
virtual bool Do(void *buf, std::size_t &size) = 0;
};
IoQueue(IoOperation io_op, IoProvider &iop, std::size_t buf_size, std::uintptr_t max = 32, std::uintptr_t min = 2);
~IoQueue();
// cannot copy
IoQueue(const IoQueue &) = delete;
IoQueue& operator=(const IoQueue &) = delete;
bool Start();
bool Stop();
std::size_t GetDataBufferCount() const;
std::size_t GetFreeBufferCount() const;
bool WaitDataBuffer(std::chrono::milliseconds ms);
void PurgeDataBuffer();
bool Read(void *buf, std::size_t &size, std::size_t &remain_count, bool blocking);
bool ReadBuffer(void **buf, std::size_t &size, std::size_t &remain_count, bool blocking);
bool HaveReadingBuffer();
bool Write(void *buf, std::size_t &size, bool blocking);
private:
bool IncreaseFreeBuffer();
void DecreaseFreeBuffer();
bool PushBackDataBuffer(std::unique_ptr<IoBuffer> &&buf);
bool PushBackFreeBuffer(std::unique_ptr<IoBuffer> &&buf);
std::unique_ptr<IoBuffer> PopFrontDataBuffer(bool wait);
std::unique_ptr<IoBuffer> PopBackFreeBuffer(bool wait);
void ReadWorker();
void WriteWorker();
IoOperation io_op_;
IoProvider &iop_;
std::size_t buf_size_;
std::uintptr_t max_;
std::uintptr_t min_;
std::mutex mtx_;
std::size_t total_buf_num_;
std::deque<std::unique_ptr<IoBuffer>> data_buf_;
mutable std::mutex data_mtx_;
std::deque<std::unique_ptr<IoBuffer>> free_buf_;
mutable std::mutex free_mtx_;
std::condition_variable data_cond_;
std::condition_variable free_cond_;
std::unique_ptr<IoBuffer> current_buf_;
std::size_t current_ofs_;
std::unique_ptr<std::thread> th_;
};
} // namespace px4

View File

@@ -0,0 +1,60 @@
// pipe_client.cpp
#include "pipe_client.hpp"
#include <system_error>
namespace px4 {
PipeClient::PipeClient() noexcept
: Pipe()
{
}
PipeClient::~PipeClient()
{
}
bool PipeClient::Connect(const std::wstring &name, const PipeClientConfig &config, HANDLE cancel_event) noexcept
{
std::wstring path = L"\\\\.\\pipe\\" + name;
HANDLE pipe_handle;
while (true) {
DWORD mode;
if (!WaitNamedPipeW(path.c_str(), config.timeout)) {
error_.assign(GetLastError(), std::system_category());
return false;
}
pipe_handle = CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
if (pipe_handle == INVALID_HANDLE_VALUE) {
DWORD ec = GetLastError();
if (ec == ERROR_PIPE_BUSY)
continue;
error_.assign(ec, std::system_category());
return false;
}
mode = ((config.stream_read) ? PIPE_READMODE_BYTE : PIPE_READMODE_MESSAGE) | PIPE_WAIT;
if (!SetNamedPipeHandleState(pipe_handle, &mode, nullptr, nullptr)) {
CloseHandle(pipe_handle);
error_.assign(GetLastError(), std::system_category());
return false;
}
SetHandle(pipe_handle);
break;
}
return true;
}
} // namespace px4

View File

@@ -0,0 +1,27 @@
// pipe_client.hpp
#pragma once
#include <cstdint>
#include <string>
#include <windows.h>
#include "pipe.hpp"
namespace px4 {
class PipeClient final : public px4::Pipe {
public:
struct PipeClientConfig {
bool stream_read;
std::uint32_t timeout;
};
PipeClient() noexcept;
~PipeClient();
bool Connect(const std::wstring &name, const PipeClientConfig &config, HANDLE cancel_event) noexcept;
};
} // namespace px4

View File

@@ -0,0 +1,46 @@
// receiver_info_set.cpp
#include "receiver_info_set.hpp"
#include "util.hpp"
namespace px4 {
void ReceiverInfoSet::Load(const px4::ConfigSet &configs) noexcept
{
for (int i = 0; i <= 512; i++) {
wchar_t sct[32];
swprintf_s(sct, L"ReceiverDefinition%d", i);
if (!configs.Exists(sct))
break;
const px4::Config &c = configs.Get(sct);
const std::wstring &device_name = c.Get(L"DeviceName", L"");
const std::wstring &device_guid_str = c.Get(L"DeviceGUID", L"");
const std::wstring &receiver_name = c.Get(L"ReceiverName", L"");
const std::wstring &receiver_guid_str = c.Get(L"ReceiverGUID", L"");
const std::wstring &system_str = c.Get(L"System", L"");
const std::wstring &index_str = c.Get(L"Index", L"-1");
px4::command::ReceiverInfo receiver_info = { 0 };
wcscpy_s(receiver_info.device_name, device_name.c_str());
px4::util::ParseGuidStr(device_guid_str, receiver_info.device_guid);
wcscpy_s(receiver_info.receiver_name, receiver_name.c_str());
px4::util::ParseGuidStr(receiver_guid_str, receiver_info.receiver_guid);
px4::util::ParseSystemStr(system_str, receiver_info.systems);
receiver_info.index = static_cast<std::int32_t>(std::stol(index_str));
receiver_info.data_id = 0;
receivers_.push_back(receiver_info);
}
}
const px4::command::ReceiverInfo& ReceiverInfoSet::Get(std::size_t i) const
{
return receivers_.at(i);
}
} // namespace px4

View File

@@ -0,0 +1,25 @@
// receiver_info_set.hpp
#pragma once
#include <string>
#include <vector>
#include "config.hpp"
#include "command.hpp"
namespace px4 {
class ReceiverInfoSet {
public:
ReceiverInfoSet() noexcept {}
~ReceiverInfoSet() {}
void Load(const px4::ConfigSet &configs) noexcept;
const px4::command::ReceiverInfo& Get(std::size_t i) const;
private:
std::vector<px4::command::ReceiverInfo> receivers_;
};
} // namespace px4

View File

@@ -0,0 +1,30 @@
// resource.h
#pragma once
#include <windows.h>
#define VER_FILE 0,4,0,0
#define VER_FILE_STR "0.4.0"
#define VER_PRODUCT 0,4,0,0
#define VER_PRODUCT_STR "0.4.0"
#define VER_COMMENTS_STR ""
#define VER_COMPANYNAME_STR "nns779"
#define VER_FILEDESCRIPTION_STR "BonDriver for PX4 Devices"
#define VER_INTERNALNAME_STR "BonDriver_PX4.dll"
#define VER_LEGALCOPYRIGHT_STR ""
#define VER_LEGALTRADEMARKS_STR ""
#define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR
#define VER_PRIVATEBUILD_STR ""
#define VER_PRODUCTNAME_STR "BonDriver_PX4"
#define VER_SPECIALBUILD_STR ""
#if defined(_DEBUG)
#define VER_FLAGS VS_FF_PRERELEASE | VS_FF_DEBUG
#elif defined(_DEBUG_MSG)
#define VER_FLAGS VS_FF_PRERELEASE
#else
#define VER_FLAGS 0
#endif

View File

@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|Win32">
<Configuration>Release-static</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|x64">
<Configuration>Release-static</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{4601F387-ACC7-445B-AD12-4D9C4B2EFB04}</ProjectGuid>
<RootNamespace>DriverHostPX4</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)src\common;$(ProjectDir);$(ProjectDir)..\..\..\driver;</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_DEBUG_MSG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_DEBUG_MSG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;winusb.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\driver\cxd2856er.c" />
<ClCompile Include="..\..\..\driver\cxd2858er.c" />
<ClCompile Include="..\..\..\driver\it930x.c" />
<ClCompile Include="..\..\..\driver\r850.c" />
<ClCompile Include="..\..\..\driver\rt710.c" />
<ClCompile Include="..\..\..\driver\tc90522.c" />
<ClCompile Include="..\common\config.cpp" />
<ClCompile Include="..\common\msg.c" />
<ClCompile Include="..\common\pipe.cpp" />
<ClCompile Include="..\common\util.cpp" />
<ClCompile Include="ctrl_server.cpp" />
<ClCompile Include="device_base.cpp" />
<ClCompile Include="device_definition_set.cpp" />
<ClCompile Include="device_manager.cpp" />
<ClCompile Include="device_notifier.cpp" />
<ClCompile Include="driver_host.cpp" />
<ClCompile Include="itedtv_bus_winusb.c" />
<ClCompile Include="main.cpp" />
<ClCompile Include="misc_win.c" />
<ClCompile Include="pipe_server.cpp" />
<ClCompile Include="px4_device.cpp" />
<ClCompile Include="pxmlt_device.cpp" />
<ClCompile Include="receiver_base.cpp" />
<ClCompile Include="receiver_manager.cpp" />
<ClCompile Include="ringbuffer.cpp" />
<ClCompile Include="server_base.cpp" />
<ClCompile Include="stream_server.cpp" />
<ClCompile Include="notify_icon.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\driver\cxd2856er.h" />
<ClInclude Include="..\..\..\driver\cxd2858er.h" />
<ClInclude Include="..\..\..\driver\i2c_comm.h" />
<ClInclude Include="..\..\..\driver\it930x.h" />
<ClInclude Include="..\..\..\driver\itedtv_bus.h" />
<ClInclude Include="..\..\..\driver\r850.h" />
<ClInclude Include="..\..\..\driver\rt710.h" />
<ClInclude Include="..\..\..\driver\tc90522.h" />
<ClInclude Include="..\common\command.hpp" />
<ClInclude Include="..\common\config.hpp" />
<ClInclude Include="..\common\msg.h" />
<ClInclude Include="..\common\pipe.hpp" />
<ClInclude Include="..\common\type.hpp" />
<ClInclude Include="..\common\util.hpp" />
<ClInclude Include="ctrl_server.hpp" />
<ClInclude Include="device_base.hpp" />
<ClInclude Include="device_definition_set.hpp" />
<ClInclude Include="device_manager.hpp" />
<ClInclude Include="device_notifier.hpp" />
<ClInclude Include="driver_host.hpp" />
<ClInclude Include="misc_win.h" />
<ClInclude Include="notify_icon.hpp" />
<ClInclude Include="pipe_server.hpp" />
<ClInclude Include="px4_device.hpp" />
<ClInclude Include="pxmlt_device.hpp" />
<ClInclude Include="receiver_base.hpp" />
<ClInclude Include="receiver_manager.hpp" />
<ClInclude Include="resource.h" />
<ClInclude Include="ringbuffer.hpp" />
<ClInclude Include="server_base.hpp" />
<ClInclude Include="stream_server.hpp" />
<ClInclude Include="winusb_compat.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\pkg\DriverHost_PX4\DriverHost_PX4.ini" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DriverHost_PX4.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="ソース ファイル">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="ヘッダー ファイル">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="リソース ファイル">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="パッケージ">
<UniqueIdentifier>{c7712df7-53c8-44b0-9b66-82d857601e6a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\driver\cxd2856er.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\driver\cxd2858er.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\driver\it930x.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\driver\r850.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\driver\rt710.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\driver\tc90522.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\config.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\msg.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\pipe.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\common\util.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="ctrl_server.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="device_base.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="device_definition_set.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="device_manager.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="device_notifier.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="driver_host.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="itedtv_bus_winusb.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="misc_win.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="pipe_server.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="px4_device.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="pxmlt_device.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="receiver_base.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="receiver_manager.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="ringbuffer.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="server_base.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="stream_server.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="notify_icon.cpp">
<Filter>ソース ファイル</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\driver\cxd2856er.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\cxd2858er.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\i2c_comm.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\it930x.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\itedtv_bus.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\r850.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\rt710.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\driver\tc90522.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\command.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\config.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\msg.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\pipe.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\type.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\common\util.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="ctrl_server.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="device_base.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="device_definition_set.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="device_manager.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="device_notifier.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="driver_host.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="misc_win.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="notify_icon.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="pipe_server.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="px4_device.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="pxmlt_device.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="receiver_base.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="receiver_manager.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="ringbuffer.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="server_base.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="stream_server.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="winusb_compat.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\pkg\DriverHost_PX4\DriverHost_PX4.ini">
<Filter>パッケージ</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DriverHost_PX4.rc">
<Filter>リソース ファイル</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,217 @@
// ctrl_server.cpp
#include "ctrl_server.hpp"
namespace px4 {
CtrlServer::CtrlServer(px4::ReceiverManager &receiver_manager)
: ServerBase(L"px4_ctrl_pipe", receiver_manager)
{
pipe_config_.in_buffer_size = 512;
pipe_config_.out_buffer_size = 512;
pipe_config_.stream_pipe = false;
pipe_config_.stream_read = false;
pipe_config_.default_timeout = 2000;
}
px4::ServerBase::Connection* CtrlServer::CreateConnection(std::unique_ptr<px4::PipeServer> &pipe)
{
return new CtrlConnection(*this, pipe);
}
CtrlServer::CtrlConnection::CtrlConnection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept
: Connection(parent, pipe)
{
}
void CtrlServer::CtrlConnection::Worker() noexcept
{
std::size_t size = config_.in_buffer_size;
std::unique_ptr<std::uint8_t[]> buf(new std::uint8_t[size]);
px4::command::ReceiverInfo info = { 0 };
px4::ReceiverBase *receiver = nullptr;
while (true) {
bool ret = true;
std::size_t read;
if (!conn_->Read(buf.get(), size, read, quit_event_))
break;
px4::command::CtrlCmdHeader *hdr = reinterpret_cast<px4::command::CtrlCmdHeader *>(buf.get());
switch (hdr->cmd) {
case px4::command::CtrlCmdCode::GET_VERSION:
{
px4::command::CtrlVersionCmd *version = reinterpret_cast<px4::command::CtrlVersionCmd *>(buf.get());
version->status = px4::command::CtrlStatusCode::SUCCEEDED;
version->driver_version = 0x00040000;
version->cmd_version = px4::command::VERSION;
break;
}
case px4::command::CtrlCmdCode::OPEN:
{
if (receiver) {
receiver->Close();
receiver_manager_.ClearDataId(receiver);
receiver = nullptr;
}
px4::command::CtrlOpenCmd *open = reinterpret_cast<px4::command::CtrlOpenCmd *>(buf.get());
receiver = receiver_manager_.Search(open->receiver_info, info);
if (receiver) {
int ret;
ret = receiver->Open();
if (!ret) {
std::uint32_t data_id;
if (receiver_manager_.GenerateDataId(receiver, data_id)) {
open->status = px4::command::CtrlStatusCode::SUCCEEDED;
open->receiver_info = info;
open->receiver_info.data_id = data_id;
break;
}
receiver->Close();
}
receiver = nullptr;
}
open->status = px4::command::CtrlStatusCode::FAILED;
break;
}
case px4::command::CtrlCmdCode::CLOSE:
if (receiver) {
receiver->Close();
receiver_manager_.ClearDataId(receiver);
receiver = nullptr;
info = { 0 };
hdr->status = px4::command::CtrlStatusCode::SUCCEEDED;
} else {
hdr->status = px4::command::CtrlStatusCode::FAILED;
}
break;
case px4::command::CtrlCmdCode::GET_INFO:
{
px4::command::CtrlReceiverInfoCmd *receiver_info = reinterpret_cast<px4::command::CtrlReceiverInfoCmd *>(buf.get());
if (receiver) {
receiver_info->receiver_info = info;
hdr->status = px4::command::CtrlStatusCode::SUCCEEDED;
} else {
hdr->status = px4::command::CtrlStatusCode::FAILED;
}
break;
}
case px4::command::CtrlCmdCode::SET_CAPTURE:
{
px4::command::CtrlCaptureCmd *capture = reinterpret_cast<px4::command::CtrlCaptureCmd *>(buf.get());
if (receiver && !receiver->SetCapture((capture->capture) ? true : false))
capture->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
capture->status = px4::command::CtrlStatusCode::FAILED;
break;
}
case px4::command::CtrlCmdCode::GET_PARAMS:
{
px4::command::CtrlParamsCmd *params = reinterpret_cast<px4::command::CtrlParamsCmd *>(buf.get());
if (receiver && receiver->GetParameters(params->param_set))
params->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
params->status = px4::command::CtrlStatusCode::FAILED;
break;
}
case px4::command::CtrlCmdCode::SET_PARAMS:
{
px4::command::CtrlParamsCmd *params = reinterpret_cast<px4::command::CtrlParamsCmd *>(buf.get());
if (receiver && receiver->SetParameters(params->param_set))
params->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
params->status = px4::command::CtrlStatusCode::FAILED;
break;
}
case px4::command::CtrlCmdCode::CLEAR_PARAMS:
if (receiver && (receiver->ClearParameters(), true))
hdr->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
hdr->status = px4::command::CtrlStatusCode::FAILED;
break;
case px4::command::CtrlCmdCode::TUNE:
if (receiver && !receiver->Tune())
hdr->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
hdr->status = px4::command::CtrlStatusCode::FAILED;
break;
case px4::command::CtrlCmdCode::SET_LNB_VOLTAGE:
{
px4::command::CtrlLnbVoltageCmd *lnb = reinterpret_cast<px4::command::CtrlLnbVoltageCmd *>(buf.get());
if (receiver && !receiver->SetLnbVoltage(lnb->voltage))
lnb->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
lnb->status = px4::command::CtrlStatusCode::FAILED;
break;
}
case px4::command::CtrlCmdCode::READ_STATS:
{
px4::command::CtrlStatsCmd *stats = reinterpret_cast<px4::command::CtrlStatsCmd *>(buf.get());
if (receiver && receiver->ReadStats(stats->stat_set))
stats->status = px4::command::CtrlStatusCode::SUCCEEDED;
else
stats->status = px4::command::CtrlStatusCode::FAILED;
break;
}
default:
hdr->status = px4::command::CtrlStatusCode::FAILED;
break;
}
if (!ret)
break;
std::size_t written;
if (!conn_->Write(buf.get(), read, written) || read != written)
break;
}
if (receiver) {
receiver->Close();
receiver_manager_.ClearDataId(receiver);
}
delete this;
}
} // namespace px4

View File

@@ -0,0 +1,49 @@
// ctrl_server.hpp
#pragma once
#include <cstdint>
#include <memory>
#include "server_base.hpp"
#include "pipe_server.hpp"
#include "receiver_base.hpp"
#include "receiver_manager.hpp"
namespace px4 {
class CtrlServer final : public px4::ServerBase {
public:
explicit CtrlServer(px4::ReceiverManager &receiver_manager);
~CtrlServer() {}
// cannot copy
CtrlServer(const CtrlServer &) = delete;
CtrlServer& operator=(const CtrlServer &) = delete;
// cannot move
CtrlServer(CtrlServer &&) = delete;
CtrlServer& operator=(CtrlServer &&) = delete;
private:
class CtrlConnection final : public px4::ServerBase::Connection {
public:
explicit CtrlConnection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept;
~CtrlConnection() {}
// cannot copy
CtrlConnection(const CtrlConnection &) = delete;
CtrlConnection& operator=(const CtrlConnection &) = delete;
// cannot move
CtrlConnection(CtrlConnection &&) = delete;
CtrlConnection& operator=(CtrlConnection &&) = delete;
private:
void Worker() noexcept override;
};
px4::ServerBase::Connection* CreateConnection(std::unique_ptr<px4::PipeServer> &pipe) override;
};
} // namespace px4

View File

@@ -0,0 +1,67 @@
// device_base.cpp
#include "device_base.hpp"
#include <cinttypes>
#include "msg.h"
#include "command.hpp"
namespace px4 {
DeviceBase::DeviceBase(const std::wstring &path, const px4::DeviceDefinition &device_def, std::uintptr_t index, px4::ReceiverManager &receiver_manager)
: device_def_(device_def),
receiver_manager_(receiver_manager)
{
strncpy_s(dev_.driver_name, "px4_winusb", sizeof("px4_winusb"));
sprintf_s(dev_.device_name, "%" PRIuPTR, index);
usb_dev_.winusb = nullptr;
usb_dev_.dev = CreateFileW(
path.c_str(),
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
nullptr);
if (usb_dev_.dev == INVALID_HANDLE_VALUE)
throw DeviceError("px4::DeviceBase::DeviceBase: CreateFileW() failed.");
if (!WinUsb_Initialize(usb_dev_.dev, &usb_dev_.winusb)) {
CloseHandle(usb_dev_.dev);
throw DeviceError("px4::DeviceBase::DeviceBase: WinUsb_Initialize() failed.");
}
ULONG size;
if (!WinUsb_GetDescriptor(
usb_dev_.winusb,
USB_DEVICE_DESCRIPTOR_TYPE,
0x00,
0x0000,
reinterpret_cast<PUCHAR>(&usb_dev_.descriptor),
sizeof(usb_dev_.descriptor),
&size)
) {
WinUsb_Free(usb_dev_.winusb);
CloseHandle(usb_dev_.dev);
throw DeviceError("px4::DeviceBase::DeviceBase: WinUsb_GetDescriptor(USB_DEVICE_DESCRIPTOR_TYPE) failed.");
}
}
DeviceBase::~DeviceBase()
{
if (usb_dev_.winusb) {
WinUsb_Free(usb_dev_.winusb);
usb_dev_.winusb = nullptr;
}
if (usb_dev_.dev != INVALID_HANDLE_VALUE) {
CloseHandle(usb_dev_.dev);
usb_dev_.dev = INVALID_HANDLE_VALUE;
}
}
} // namespace px4

View File

@@ -0,0 +1,56 @@
// device_base.hpp
#pragma once
#include <cstdint>
#include <string>
#include <stdexcept>
#include <windows.h>
#include <winusb.h>
#include "type.hpp"
#include "command.hpp"
#include "device_definition_set.hpp"
#include "receiver_base.hpp"
#include "receiver_manager.hpp"
#include "misc_win.h"
#include "winusb_compat.h"
namespace px4 {
class DeviceBase {
public:
explicit DeviceBase(const std::wstring &path, const px4::DeviceDefinition &device_def, std::uintptr_t index, px4::ReceiverManager &receiver_manager);
virtual ~DeviceBase();
// cannot copy
DeviceBase(const DeviceBase &) = delete;
DeviceBase& operator=(const DeviceBase &) = delete;
// cannot move
DeviceBase(DeviceBase &&) = delete;
DeviceBase& operator=(DeviceBase &&) = delete;
virtual int Init() = 0;
virtual void Term() = 0;
virtual void SetAvailability(bool available) = 0;
virtual px4::ReceiverBase* GetReceiver(int id) const = 0;
protected:
const device& GetDevice() const { return dev_; }
const px4::DeviceDefinition &device_def_;
px4::ReceiverManager &receiver_manager_;
device dev_;
usb_device usb_dev_;
};
class DeviceError : public std::runtime_error {
public:
explicit DeviceError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,72 @@
// device_definition_set.cpp
#include "device_definition_set.hpp"
namespace px4 {
void DeviceDefinitionSet::Load(const px4::ConfigSet &configs) noexcept
{
for (int i = 0; i < 512; i++) {
wchar_t dev_sct[32];
swprintf_s(dev_sct, L"DeviceDefinition%d", i);
if (!configs.Exists(dev_sct))
break;
const px4::Config &cd = configs.Get(dev_sct);
const std::wstring &dev_name = cd.Get(L"Name", L"");
const std::wstring &dev_guid_str = cd.Get(L"GUID", L"");
const std::wstring &dev_type = cd.Get(L"Type", L"PX4");
const std::wstring &dev_intf_guid_str = cd.Get(L"DeviceInterfaceGUID", L"");
DeviceDefinition dev_def = {};
dev_def.name = dev_name;
px4::util::ParseGuidStr(dev_guid_str, dev_def.guid);
px4::util::ParseGuidStr(dev_intf_guid_str, dev_def.device_interface_guid);
for (int j = 0; j < 64; j++) {
wchar_t rcvr_sct[64];
swprintf_s(rcvr_sct, L"DeviceDefinition%d.Receiver%d", i, j);
if (!configs.Exists(rcvr_sct))
break;
const px4::Config &cr = configs.Get(rcvr_sct);
const std::wstring &rcvr_name = cr.Get(L"Name", L"");
const std::wstring &rcvr_guid_str = cr.Get(L"GUID", L"");
const std::wstring &rcvr_system_str = cr.Get(L"System", L"");
const std::wstring &rcvr_index_str = cr.Get(L"Index", L"-1");
ReceiverDefinition rcvr_def = {};
rcvr_def.name = rcvr_name;
px4::util::ParseGuidStr(rcvr_guid_str, rcvr_def.guid);
px4::util::ParseSystemStr(rcvr_system_str, rcvr_def.systems);
rcvr_def.index = static_cast<std::int32_t>(std::stol(rcvr_index_str));
dev_def.receivers.emplace_back(rcvr_def);
}
if (!devices_.count(dev_type))
devices_.emplace(dev_type, std::vector<px4::DeviceDefinition>());
devices_.at(dev_type).emplace_back(dev_def);
}
}
const std::vector<DeviceDefinition>& DeviceDefinitionSet::Get(const std::wstring &type) const
{
return devices_.at(type);
}
const std::unordered_map<std::wstring, std::vector<DeviceDefinition>>& DeviceDefinitionSet::GetAll() const
{
return devices_;
}
} // namespace px4

View File

@@ -0,0 +1,47 @@
// device_definition_set.hpp
#pragma once
#include <cstdint>
#include <string>
#include <functional>
#include <vector>
#include <unordered_map>
#include <guiddef.h>
#include "type.hpp"
#include "util.hpp"
#include "config.hpp"
namespace px4 {
struct ReceiverDefinition final {
std::wstring name;
GUID guid;
px4::SystemType systems;
std::int32_t index;
};
struct DeviceDefinition final {
std::wstring name;
GUID guid;
GUID device_interface_guid;
std::vector<ReceiverDefinition> receivers;
};
class DeviceDefinitionSet final {
public:
DeviceDefinitionSet() noexcept {}
~DeviceDefinitionSet() {};
void Load(const px4::ConfigSet &configs) noexcept;
const std::vector<DeviceDefinition>& Get(const std::wstring &type) const;
const std::unordered_map<std::wstring, std::vector<DeviceDefinition>>& GetAll() const;
private:
std::unordered_map<std::wstring, std::vector<DeviceDefinition>> devices_;
};
} // namespace px4

View File

@@ -0,0 +1,162 @@
// device_manager.cpp
#include "device_manager.hpp"
#include <algorithm>
#include <windows.h>
#include <setupapi.h>
#include "px4_device.hpp"
#include "pxmlt_device.hpp"
namespace px4 {
void DeviceManager::NotifyHandler::Handle(px4::DeviceNotifyType type, const GUID &interface_guid, const wchar_t *path) noexcept
{
try {
std::wstring path_lower = path;
std::transform(path_lower.cbegin(), path_lower.cend(), path_lower.begin(), tolower);
switch (type) {
case px4::DeviceNotifyType::ARRIVAL:
parent_.Add(path_lower, parent_.device_map_.at(interface_guid));
break;
case px4::DeviceNotifyType::REMOVE:
parent_.Remove(path_lower);
break;
}
} catch (const std::out_of_range &) {}
}
DeviceManager::DeviceManager(const px4::DeviceDefinitionSet &device_defs, px4::ReceiverManager &receiver_manager)
: device_map_(),
receiver_manager_(receiver_manager),
mtx_(),
index_(0),
handler_(*this)
{
auto &all_devs = device_defs.GetAll();
for (auto it = all_devs.cbegin(); it != all_devs.cend(); ++it) {
DeviceType type = DeviceType::UNKNOWN;
if (it->first == L"PX4")
type = DeviceType::PX4;
else if (it->first == L"PXMLT")
type = DeviceType::PXMLT;
if (type == DeviceType::UNKNOWN)
continue;
auto &devs = it->second;
for (auto it2 = devs.begin(); it2 != devs.end(); ++it2)
device_map_.emplace(it2->device_interface_guid, std::move(std::pair<DeviceType, px4::DeviceDefinition>(type, *it2)));
}
notifier_.reset(new px4::DeviceNotifier(&handler_));
for (auto it = device_map_.cbegin(); it != device_map_.cend(); ++it)
Search(it->first, it->second);
}
DeviceManager::~DeviceManager()
{
notifier_.reset();
}
void DeviceManager::Search(const GUID &guid, const std::pair<DeviceType, px4::DeviceDefinition> &def)
{
HDEVINFO dev_info;
dev_info = SetupDiGetClassDevsW(&guid, nullptr, nullptr, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (dev_info == INVALID_HANDLE_VALUE)
throw DeviceManagerError("px4::DeviceManager::Search: SetupDiGetClassDevsW() failed.");
SP_DEVICE_INTERFACE_DATA intf_data;
DWORD i = 0;
intf_data.cbSize = sizeof(intf_data);
while (SetupDiEnumDeviceInterfaces(dev_info, nullptr, &guid, i, &intf_data)) {
DWORD detail_size;
SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail_data;
SetupDiGetDeviceInterfaceDetailW(dev_info, &intf_data, nullptr, 0, &detail_size, nullptr);
if (!detail_size)
continue;
detail_data = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_W *>(new std::uint8_t[detail_size]);
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
if (SetupDiGetDeviceInterfaceDetailW(dev_info, &intf_data, detail_data, detail_size, nullptr, nullptr)) {
std::wstring path_lower = detail_data->DevicePath;
std::transform(path_lower.cbegin(), path_lower.cend(), path_lower.begin(), tolower);
Add(path_lower, def);
}
delete[] reinterpret_cast<std::uint8_t *>(detail_data);
i++;
}
SetupDiDestroyDeviceInfoList(dev_info);
}
void DeviceManager::Add(const std::wstring &path, const std::pair<DeviceType, px4::DeviceDefinition> &def)
{
std::lock_guard<std::mutex> lock(mtx_);
if (Exists(path))
return;
switch (def.first) {
case px4::DeviceType::PX4:
{
auto dev = std::make_unique<Px4Device>(path, def.second, ++index_, receiver_manager_);
if (!dev->Init())
devices_.emplace(path, std::move(dev));
break;
}
case px4::DeviceType::PXMLT:
{
auto dev = std::make_unique<PxMltDevice>(path, def.second, ++index_, receiver_manager_);
if (!dev->Init())
devices_.emplace(path, std::move(dev));
break;
}
default:
break;
}
return;
}
void DeviceManager::Remove(const std::wstring &path)
{
std::lock_guard<std::mutex> lock(mtx_);
if (!Exists(path))
return;
devices_.at(path)->SetAvailability(false);
devices_.erase(path);
}
bool DeviceManager::Exists(const std::wstring &path) const
{
return !!devices_.count(path);
}
} // namespace px4

View File

@@ -0,0 +1,74 @@
// device_manager.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <mutex>
#include <vector>
#include <unordered_map>
#include <stdexcept>
#include <guiddef.h>
#include "device_notifier.hpp"
#include "device_definition_set.hpp"
#include "device_base.hpp"
#include "receiver_manager.hpp"
namespace px4 {
enum class DeviceType : std::uint32_t {
UNKNOWN = 0,
PX4,
PXMLT
};
class DeviceManager final {
private:
class NotifyHandler final : public px4::DeviceNotifyHandler {
public:
explicit NotifyHandler(DeviceManager &parent) : parent_(parent) {}
~NotifyHandler() {}
void Handle(px4::DeviceNotifyType type, const GUID &interface_guid, const wchar_t *path) noexcept;
private:
DeviceManager &parent_;
};
public:
explicit DeviceManager(const px4::DeviceDefinitionSet &device_defs, px4::ReceiverManager &receiver_manager);
~DeviceManager();
// cannot copy
DeviceManager(const DeviceManager &) = delete;
DeviceManager& operator=(const DeviceManager &) = delete;
// cannot move
DeviceManager(DeviceManager &&) = delete;
DeviceManager& operator=(DeviceManager &&) = delete;
private:
void Search(const GUID &guid, const std::pair<DeviceType, px4::DeviceDefinition> &def);
void Add(const std::wstring &path, const std::pair<DeviceType, px4::DeviceDefinition> &def);
void Remove(const std::wstring &path);
bool Exists(const std::wstring &path) const;
std::unordered_map<GUID, std::pair<DeviceType, px4::DeviceDefinition>> device_map_;
px4::ReceiverManager &receiver_manager_;
std::mutex mtx_;
std::unordered_map<std::wstring, std::unique_ptr<DeviceBase>> devices_;
std::uintptr_t index_;
NotifyHandler handler_;
std::unique_ptr<px4::DeviceNotifier> notifier_;
};
class DeviceManagerError : public std::runtime_error {
public:
explicit DeviceManagerError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,163 @@
// device_notifier.cpp
#include "device_notifier.hpp"
namespace px4 {
DeviceNotifier::DeviceNotifier(DeviceNotifyHandler *handler)
: handler_(handler),
hinst_(GetModuleHandleW(nullptr)),
hwnd_(nullptr),
notify_handle_(nullptr),
mtx_(),
cond_(),
ready_(false),
th_(&px4::DeviceNotifier::Worker, this)
{
std::unique_lock<std::mutex> lock(mtx_);
cond_.wait(lock);
if (!ready_.load()) {
lock.unlock();
throw DeviceNotifierError("px4::DeviceNotifier::DeviceNotifier: failed.");
}
}
DeviceNotifier::~DeviceNotifier()
{
SendMessageW(hwnd_, WM_CLOSE, 0, 0);
th_.join();
}
LRESULT CALLBACK DeviceNotifier::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
void *p;
DeviceNotifier *dn = nullptr;
p = reinterpret_cast<void *>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
if (p) {
dn = reinterpret_cast<DeviceNotifier *>(DecodePointer(p));
} else if (uMsg == WM_CREATE && lParam) {
dn = reinterpret_cast<DeviceNotifier *>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(EncodePointer(dn)));
}
if (!dn)
return -1;
std::unique_lock<std::mutex> lock(dn->mtx_, std::defer_lock);
switch (uMsg) {
case WM_CREATE:
{
DEV_BROADCAST_DEVICEINTERFACE_W dbdi;
HDEVNOTIFY notify_handle;
dbdi.dbcc_size = sizeof(dbdi);
dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notify_handle = RegisterDeviceNotificationW(hwnd, &dbdi, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
if (!notify_handle)
return -1;
dn->notify_handle_ = notify_handle;
return 0;
}
case WM_CLOSE:
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
lock.lock();
if (dn->notify_handle_) {
UnregisterDeviceNotification(dn->notify_handle_);
dn->notify_handle_ = nullptr;
}
lock.unlock();
PostQuitMessage(0);
return 0;
case WM_DEVICECHANGE:
{
DEV_BROADCAST_DEVICEINTERFACE_W *dbdi = reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE_W *>(lParam);
if (!dbdi || dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
return TRUE;
lock.lock();
switch (wParam) {
case DBT_DEVICEARRIVAL:
dn->handler_->Handle(DeviceNotifyType::ARRIVAL, dbdi->dbcc_classguid, dbdi->dbcc_name);
break;
case DBT_DEVICEREMOVECOMPLETE:
dn->handler_->Handle(DeviceNotifyType::REMOVE, dbdi->dbcc_classguid, dbdi->dbcc_name);
break;
default:
break;
}
lock.unlock();
return TRUE;
}
default:
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
void DeviceNotifier::Worker()
{
WCHAR class_name[] = TEXT("DeviceNotifier_MessageWindow");
WNDCLASSEXW wc;
MSG msg;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst_;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = class_name;
wc.hIconSm = nullptr;
if (!RegisterClassExW(&wc)) {
ready_.store(false);
cond_.notify_all();
return;
}
hwnd_ = CreateWindowExW(0, class_name, nullptr, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, nullptr, hinst_, this);
if (!hwnd_) {
ready_.store(false);
cond_.notify_all();
return;
}
ready_.store(true);
cond_.notify_all();
while (GetMessage(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return;
}
} // namespace px4

View File

@@ -0,0 +1,62 @@
// device_notifier.hpp
#pragma once
#include <string>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <thread>
#include <stdexcept>
#include <windows.h>
#include <dbt.h>
namespace px4 {
enum class DeviceNotifyType {
UNDEFINED = 0,
ARRIVAL,
REMOVE,
};
class DeviceNotifyHandler {
public:
virtual ~DeviceNotifyHandler() {}
virtual void Handle(DeviceNotifyType type, const GUID &interface_guid, const wchar_t *path) noexcept = 0;
};
class DeviceNotifier final {
public:
explicit DeviceNotifier(DeviceNotifyHandler *handler);
~DeviceNotifier();
// cannot copy
DeviceNotifier(const DeviceNotifier &) = delete;
DeviceNotifier& operator=(const DeviceNotifier &) = delete;
// cannot move
DeviceNotifier(DeviceNotifier &&) = delete;
DeviceNotifier& operator=(DeviceNotifier &&) = delete;
private:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void Worker();
DeviceNotifyHandler *handler_;
HINSTANCE hinst_;
HWND hwnd_;
HDEVNOTIFY notify_handle_;
std::mutex mtx_;
std::condition_variable cond_;
std::atomic_bool ready_;
std::thread th_;
};
class DeviceNotifierError : public std::runtime_error {
public:
explicit DeviceNotifierError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,99 @@
// driver_host.cpp
#include "driver_host.hpp"
#include <aclapi.h>
#include "notify_icon.hpp"
namespace px4 {
DriverHost::DriverHost()
: startup_event_(nullptr)
{
configs_.Load(px4::util::path::GetFileBase() + L".ini");
dev_defs_.Load(configs_);
}
DriverHost::~DriverHost()
{
ctrl_server_.reset();
device_manager_.reset();
if (startup_event_)
CloseHandle(startup_event_);
}
void DriverHost::Run()
{
SID_IDENTIFIER_AUTHORITY sia;
PSID sid = nullptr;
EXPLICIT_ACCESSW ea;
PACL acl = nullptr;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
sia = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&sia, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sid))
throw DriverHostError("px4::DriverHost::Run: AllocateAndInitializeSid() failed.");
memset(&ea, 0, sizeof(ea));
ea.grfAccessPermissions = EVENT_ALL_ACCESS;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPWSTR)sid;
if (SetEntriesInAclW(1, &ea, nullptr, &acl) != ERROR_SUCCESS) {
LocalFree(sid);
throw DriverHostError("px4::DriverHost::Run: SetEntriesInAclW() failed.");
}
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE);
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
startup_event_ = CreateEventW(&sa, TRUE, FALSE, L"DriverHost_PX4_StartupEvent");
if (!startup_event_)
throw DriverHostError("px4::DriverHost::Run: CreateEventW() failed.");
LocalFree(sid);
device_manager_.reset(new px4::DeviceManager(dev_defs_, receiver_manager_));
ctrl_server_.reset(new px4::CtrlServer(receiver_manager_));
stream_server_.reset(new px4::StreamServer(receiver_manager_));
ctrl_server_->Start();
stream_server_->Start();
SetEvent(startup_event_);
{
NotifyIcon ni(L"ICON1", L"PX4 Device Driver");
int n = 0;
while (n < 3) {
Sleep(5000);
if (!ctrl_server_->GetActiveConnectionCount() && !stream_server_->GetActiveConnectionCount())
n++;
else
n = 0;
}
}
stream_server_.reset();
ctrl_server_.reset();
device_manager_.reset();
CloseHandle(startup_event_);
startup_event_ = nullptr;
}
} // namespace px4

View File

@@ -0,0 +1,52 @@
// driver_host.hpp
#pragma once
#include <memory>
#include <string>
#include <stdexcept>
#include <windows.h>
#include "config.hpp"
#include "device_definition_set.hpp"
#include "device_manager.hpp"
#include "receiver_manager.hpp"
#include "ctrl_server.hpp"
#include "stream_server.hpp"
#include "util.hpp"
namespace px4 {
class DriverHost final {
public:
DriverHost();
~DriverHost();
// cannot copy
DriverHost(const DriverHost &) = delete;
DriverHost& operator=(const DriverHost &) = delete;
// cannot move
DriverHost(DriverHost &&) = delete;
DriverHost& operator=(DriverHost &&) = delete;
void Run();
private:
px4::ConfigSet configs_;
px4::DeviceDefinitionSet dev_defs_;
px4::ReceiverManager receiver_manager_;
HANDLE startup_event_;
std::unique_ptr<px4::DeviceManager> device_manager_;
std::unique_ptr<px4::CtrlServer> ctrl_server_;
std::unique_ptr<px4::StreamServer> stream_server_;
};
class DriverHostError : public std::runtime_error {
public:
explicit DriverHostError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View File

@@ -0,0 +1,592 @@
// itedev_bus_winusb.c
#if !defined(_WIN32) && !defined(_WIN64)
#error Unsupported platform.
#endif
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <process.h>
#include <windows.h>
#include "itedtv_bus.h"
struct itedtv_usb_context;
struct itedtv_usb_work {
struct itedtv_usb_context *ctx;
OVERLAPPED ol;
void *buffer;
size_t size;
bool can_submit;
};
struct itedtv_usb_context {
CRITICAL_SECTION lock;
HANDLE ctrl_event[2];
struct itedtv_bus *bus;
itedtv_bus_stream_handler_t stream_handler;
void *ctx;
uint32_t num_urb;
bool no_raw_io;
uint32_t num_works;
struct itedtv_usb_work *works;
LONG streaming;
HANDLE worker_thread;
};
static int winerr_to_errno(struct device *dev)
{
int ret = 0;
switch (GetLastError()) {
case ERROR_SUCCESS:
ret = 0;
break;
case ERROR_INVALID_HANDLE:
ret = EINVAL;
break;
case ERROR_IO_PENDING:
case ERROR_IO_INCOMPLETE:
ret = ETIMEDOUT;
break;
case ERROR_NOT_ENOUGH_MEMORY:
ret = ENOMEM;
break;
case ERROR_SEM_TIMEOUT:
ret = ETIMEDOUT;
break;
case ERROR_BAD_COMMAND:
ret = EIO;
break;
default:
dev_err(dev, "winusb unknown error: 0x%08x\n", GetLastError());
ret = EINVAL;
break;
}
return ret;
}
static int itedtv_usb_ctrl_tx(struct itedtv_bus *bus, void *buf, int len)
{
int ret = 0;
struct usb_device *dev = bus->usb.dev;
struct itedtv_usb_context *ctx = bus->usb.priv;
ULONG rlen = 0;
OVERLAPPED ol;
if (!buf || !len)
return -EINVAL;
ol.hEvent = ctx->ctrl_event[0];
ResetEvent(ol.hEvent);
/* Endpoint 0x02: Host->Device bulk endpoint for controlling the device */
if (!WinUsb_WritePipe(dev->winusb, 0x02, buf, len, &rlen, &ol)) {
if (GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ol.hEvent, bus->usb.ctrl_timeout);
else
ret = -winerr_to_errno(bus->dev);
} else {
dev_dbg(bus->dev, "itedtv_usb_ctrl_tx: WinUsb_WritePipe() TRUE\n");
}
if (!ret) {
if (!WinUsb_GetOverlappedResult(dev->winusb, &ol, &rlen, FALSE))
ret = -winerr_to_errno(bus->dev);
}
if (ret)
WinUsb_AbortPipe(dev->winusb, 0x02);
return ret;
}
static int itedtv_usb_ctrl_rx(struct itedtv_bus *bus, void *buf, int *len)
{
int ret = 0;
struct usb_device *dev = bus->usb.dev;
struct itedtv_usb_context *ctx = bus->usb.priv;
ULONG rlen = 0;
OVERLAPPED ol;
if (!buf || !len || !*len)
return -EINVAL;
ol.hEvent = ctx->ctrl_event[1];
ResetEvent(ol.hEvent);
/* Endpoint 0x81: Device->Host bulk endpoint for controlling the device */
if (!WinUsb_ReadPipe(dev->winusb, 0x81, buf, *len, &rlen, &ol)) {
if (GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ol.hEvent, bus->usb.ctrl_timeout);
else
ret = -winerr_to_errno(bus->dev);
} else {
dev_dbg(bus->dev, "itedtv_usb_ctrl_rx: WinUsb_ReadPipe() TRUE\n");
}
if (!ret) {
if (!WinUsb_GetOverlappedResult(dev->winusb, &ol, &rlen, FALSE))
ret = -winerr_to_errno(bus->dev);
}
if (ret)
WinUsb_AbortPipe(dev->winusb, 0x81);
*len = (rlen <= INT_MAX) ? rlen : -1;
return ret;
}
static int itedtv_usb_stream_rx(struct itedtv_bus *bus, void *buf, int *len, int timeout)
{
int ret = 0;
struct usb_device *dev = bus->usb.dev;
ULONG rlen = 0;
OVERLAPPED ol;
if (!buf | !len || !*len)
return -EINVAL;
ol.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!ol.hEvent) {
*len = 0;
return -winerr_to_errno(bus->dev);
}
/* Endpoint 0x84: Device->Host bulk endpoint for receiving TS from the device */
if (!WinUsb_ReadPipe(dev->winusb, 0x84, buf, *len, &rlen, &ol)) {
if (GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ol.hEvent, timeout);
else
ret = -winerr_to_errno(bus->dev);
} else {
dev_dbg(bus->dev, "itedtv_usb_stream_rx: WinUsb_ReadPipe() TRUE\n");
}
if (!ret) {
if (!WinUsb_GetOverlappedResult(dev->winusb, &ol, &rlen, FALSE))
ret = -winerr_to_errno(bus->dev);
}
if (ret)
WinUsb_AbortPipe(dev->winusb, 0x84);
*len = (rlen <= INT_MAX) ? rlen : -1;
CloseHandle(ol.hEvent);
return ret;
}
static int itedtv_usb_alloc_work_buffers(struct itedtv_usb_context *ctx, uint32_t buf_size)
{
uint32_t i;
struct itedtv_bus *bus = ctx->bus;
struct usb_device *dev = bus->usb.dev;
uint32_t num = ctx->num_works;
struct itedtv_usb_work *works = ctx->works;
if (!works)
return -EINVAL;
for (i = 0; i < num; i++) {
void *p;
works[i].ctx = ctx;
if (!works[i].ol.hEvent) {
works[i].ol.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!works[i].ol.hEvent) {
dev_err(bus->dev, "itedtv_usb_alloc_work_buffers: CreateEventW() failed. (i: %u)\n", i);
break;
}
}
if (works[i].buffer && works[i].size != buf_size) {
VirtualFree(works[i].buffer, 0, MEM_RELEASE);
works[i].buffer = NULL;
}
if (!works[i].buffer) {
p = VirtualAlloc(NULL, buf_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!p) {
dev_err(bus->dev, "itedtv_usb_alloc_work_buffers: VirtualAlloc() failed. (i: %u)\n", i);
CloseHandle(works[i].ol.hEvent);
works[i].ol.hEvent = NULL;
break;
}
dev_dbg(bus->dev, "itedtv_usb_alloc_work_buffers: p: %p, buf_size: %u\n", p, buf_size);
works[i].buffer = p;
works[i].size = buf_size;
}
works[i].can_submit = true;
}
ctx->num_urb = i;
if (!i)
return -ENOMEM;
return 0;
}
static void itedtv_usb_free_work_buffers(struct itedtv_usb_context *ctx)
{
uint32_t i;
struct usb_device *dev = ctx->bus->usb.dev;
uint32_t num = ctx->num_works;
struct itedtv_usb_work *works = ctx->works;
if (!works)
return;
for (i = 0; i < num; i++) {
if (works[i].ol.hEvent) {
CloseHandle(works[i].ol.hEvent);
works[i].ol.hEvent = NULL;
}
if (works[i].buffer) {
VirtualFree(works[i].buffer, 0, MEM_RELEASE);
works[i].buffer = NULL;
}
works[i].size = 0;
works[i].can_submit = false;
}
ctx->num_urb = 0;
return;
}
static void itedtv_usb_clean_context(struct itedtv_usb_context *ctx)
{
if (ctx->works) {
itedtv_usb_free_work_buffers(ctx);
free(ctx->works);
}
ctx->stream_handler = NULL;
ctx->ctx = NULL;
ctx->num_urb = 0;
ctx->num_works = 0;
ctx->works = NULL;
}
unsigned __stdcall itedtv_winusb_worker(void *arg)
{
struct itedtv_usb_context *ctx = arg;
struct itedtv_bus *bus = ctx->bus;
uint32_t i, num, next_idx = 0;
struct itedtv_usb_work *works;
WINUSB_INTERFACE_HANDLE winusb;
UCHAR raw_io;
dev_dbg(bus->dev, "itedtv_winusb_worker: start\n");
num = ctx->num_urb;
works = ctx->works;
winusb = bus->usb.dev->winusb;
raw_io = (ctx->no_raw_io) ? 0 : 1;
if (!WinUsb_SetPipePolicy(winusb, 0x84, RAW_IO, sizeof(raw_io), &raw_io)) {
dev_err(bus->dev, "itedtv_winusb_worker: WinUsb_SetPipePolicy(RAW_IO, %u) failed.\n", raw_io);
goto exit;
}
for (i = 0; i < num; i++) {
if (!works[i].can_submit)
continue;
works[i].can_submit = false;
ResetEvent(works[i].ol.hEvent);
if (WinUsb_ReadPipe(winusb, 0x84, works[i].buffer, (ULONG)works[i].size, NULL, &works[i].ol))
continue;
if (GetLastError() == ERROR_IO_PENDING)
continue;
dev_err(bus->dev, "itedtv_winusb_worker: WinUsb_ReadPipe() 1 failed. (%u, %u)\n", i, GetLastError());
works[i].can_submit = true;
num = i;
break;
}
dev_dbg(bus->dev, "itedtv_winusb_worker: num: %u\n", num);
while (ctx->streaming) {
uint32_t idx = next_idx;
DWORD ret, rlen = 0;
struct itedtv_usb_work *work = &works[idx];
if (work->can_submit) {
dev_dbg(bus->dev, "itedtv_winusb_worker: can_submit %u\n", idx);
for (i = (idx + 1) % num; i != idx; i = (i + 1) % num) {
if (!works[i].can_submit)
break;
}
if (i == idx)
break;
idx = i;
work = &works[idx];
}
ret = WaitForSingleObject(work->ol.hEvent, 500);
if (ret == WAIT_TIMEOUT) {
dev_dbg(bus->dev, "itedtv_winusb_worker: timeout %u\n", idx);
continue;
} else if (ret == WAIT_FAILED)
break;
if (WinUsb_GetOverlappedResult(winusb, &work->ol, &rlen, TRUE))
ctx->stream_handler(ctx->ctx, work->buffer, rlen);
next_idx = (idx + 1) % num;
ResetEvent(work->ol.hEvent);
if (WinUsb_ReadPipe(winusb, 0x84, work->buffer, (ULONG)work->size, NULL, &work->ol))
continue;
if (GetLastError() == ERROR_IO_PENDING)
continue;
dev_err(bus->dev, "itedtv_winusb_worker: WinUsb_ReadPipe() 2 failed. (%u, %u)\n", idx, GetLastError());
work->can_submit = true;
}
WinUsb_AbortPipe(winusb, 0x84);
if (raw_io) {
raw_io = 0;
WinUsb_SetPipePolicy(winusb, 0x84, RAW_IO, sizeof(raw_io), &raw_io);
}
exit:
dev_dbg(bus->dev, "itedtv_winusb_worker: exit\n");
return 0;
}
static int itedtv_usb_start_streaming(struct itedtv_bus *bus, itedtv_bus_stream_handler_t stream_handler, void *context)
{
int ret = 0;
u32 buf_size, num;
struct itedtv_usb_context *ctx = bus->usb.priv;
struct itedtv_usb_work *works;
if (!stream_handler)
return -EINVAL;
dev_dbg(bus->dev, "itedtv_usb_start_streaming\n");
EnterCriticalSection(&ctx->lock);
ctx->stream_handler = stream_handler;
ctx->ctx = context;
ctx->no_raw_io = bus->usb.streaming.no_raw_io;
buf_size = bus->usb.streaming.urb_buffer_size;
num = bus->usb.streaming.urb_num;
if (num > 64)
goto fail;
if (!ctx->no_raw_io && (buf_size % bus->usb.max_bulk_size))
buf_size += bus->usb.max_bulk_size - (buf_size % bus->usb.max_bulk_size);
if (ctx->works && num != ctx->num_works) {
itedtv_usb_free_work_buffers(ctx);
free(ctx->works);
ctx->works = NULL;
}
ctx->num_works = num;
if (!ctx->works) {
ctx->works = calloc(ctx->num_works, sizeof(*works));
if (!ctx->works) {
ret = -ENOMEM;
goto fail;
}
}
ret = itedtv_usb_alloc_work_buffers(ctx, buf_size);
if (ret)
goto fail;
WinUsb_ResetPipe(bus->usb.dev->winusb, 0x84);
InterlockedExchange(&ctx->streaming, 1);
ctx->worker_thread = (HANDLE)_beginthreadex(NULL, 0, itedtv_winusb_worker, ctx, 0, NULL);
if (!ctx->worker_thread) {
dev_err(bus->dev, "itedtv_usb_start_streaming: _beginthreadex() failed.");
goto fail;
}
if (!SetThreadPriority(ctx->worker_thread, THREAD_PRIORITY_TIME_CRITICAL))
dev_dbg(bus->dev, "itedtv_usb_start_streaming: SetThreadPriority(THREAD_PRIORITY_TIME_CRITICAL) failed.\n");
dev_dbg(bus->dev, "itedtv_usb_start_streaming: num: %u\n", num);
LeaveCriticalSection(&ctx->lock);
return ret;
fail:
InterlockedExchange(&ctx->streaming, 0);
if (ctx->worker_thread) {
WaitForSingleObject(ctx->worker_thread, INFINITE);
CloseHandle(ctx->worker_thread);
ctx->worker_thread = NULL;
}
itedtv_usb_clean_context(ctx);
LeaveCriticalSection(&ctx->lock);
return ret;
}
static int itedtv_usb_stop_streaming(struct itedtv_bus *bus)
{
struct itedtv_usb_context *ctx = bus->usb.priv;
dev_dbg(bus->dev, "itedtv_usb_stop_streaming\n");
EnterCriticalSection(&ctx->lock);
InterlockedExchange(&ctx->streaming, 0);
WaitForSingleObject(ctx->worker_thread, INFINITE);
CloseHandle(ctx->worker_thread);
ctx->worker_thread = NULL;
itedtv_usb_clean_context(ctx);
LeaveCriticalSection(&ctx->lock);
dev_dbg(bus->dev, "itedtv_usb_stop_streaming: exit\n");
return 0;
}
int itedtv_bus_init(struct itedtv_bus *bus)
{
int ret = 0;
if (!bus)
return -EINVAL;
switch (bus->type) {
case ITEDTV_BUS_USB:
{
UCHAR raw_io;
struct itedtv_usb_context *ctx;
if (!bus->usb.dev) {
ret = -EINVAL;
break;
}
if (bus->usb.dev->descriptor.bcdUSB < 0x0110) {
ret = -EIO;
break;
}
raw_io = 1;
if (!WinUsb_SetPipePolicy(bus->usb.dev->winusb, 0x84, RAW_IO, sizeof(raw_io), &raw_io)) {
ret = -winerr_to_errno(bus->dev);
break;
}
ctx = malloc(sizeof(*ctx));
if (!ctx) {
ret = -ENOMEM;
break;
}
InitializeCriticalSection(&ctx->lock);
for (int i = 0; i < 2; i++) {
ctx->ctrl_event[i] = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!ctx->ctrl_event[i]) {
ret = -winerr_to_errno(bus->dev);
break;
}
}
ctx->bus = bus;
ctx->stream_handler = NULL;
ctx->ctx = NULL;
ctx->num_urb = 0;
ctx->num_works = 0;
ctx->works = NULL;
ctx->streaming = 0;
ctx->worker_thread = NULL;
bus->usb.priv = ctx;
if (!bus->usb.max_bulk_size)
bus->usb.max_bulk_size = (bus->usb.dev->descriptor.bcdUSB == 0x0110) ? 64 : 512;
bus->ops.ctrl_tx = itedtv_usb_ctrl_tx;
bus->ops.ctrl_rx = itedtv_usb_ctrl_rx;
bus->ops.stream_rx = itedtv_usb_stream_rx;
bus->ops.start_streaming = itedtv_usb_start_streaming;
bus->ops.stop_streaming = itedtv_usb_stop_streaming;
break;
}
default:
ret = -EINVAL;
break;
}
return ret;
}
int itedtv_bus_term(struct itedtv_bus *bus)
{
if (!bus)
return -EINVAL;
switch (bus->type) {
case ITEDTV_BUS_USB:
{
struct itedtv_usb_context *ctx = bus->usb.priv;
if (ctx) {
itedtv_usb_stop_streaming(bus);
CloseHandle(ctx->ctrl_event[0]);
CloseHandle(ctx->ctrl_event[1]);
DeleteCriticalSection(&ctx->lock);
free(ctx);
}
break;
}
default:
break;
}
dev_dbg(bus->dev, "itedtv_bus_term: exit\n");
memset(bus, 0, sizeof(*bus));
return 0;
}

View File

@@ -0,0 +1,51 @@
// main.cpp
#define msg_prefix "DriverHost_PX4"
#include <string>
#include <iostream>
#include <stdexcept>
#include <windows.h>
#include "driver_host.hpp"
#include "util.hpp"
#include "msg.h"
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR pCmdLine, _In_ int nCmdShow)
{
#ifdef _DEBUG
FILE *fp;
AllocConsole();
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
msg_set_mode(MSG_MODE_CONSOLE);
#else
msg_set_mode(MSG_MODE_DEBUGGER);
#endif
msg_info("Start\n");
px4::util::path::Init(hInstance);
try {
px4::DriverHost host;
host.Run();
} catch (const std::runtime_error & e) {
msg_err("%s\n", e.what());
MessageBoxA(nullptr, e.what(), "DriverHost_PX4 (wWinMain)", MB_OK | MB_ICONERROR);
}
msg_info("Exiting...\n");
#ifdef _DEBUG
Sleep(2000);
FreeConsole();
#endif
return 0;
}

View File

@@ -0,0 +1,75 @@
// misc_win.c
#include "misc_win.h"
int request_firmware(const struct firmware **p, const char *name, struct device *dummy)
{
int ret = 0;
HANDLE file;
LARGE_INTEGER size;
DWORD remain;
struct firmware *fw;
uint8_t *buf = NULL, *data;
file = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE) {
ret = -ENOENT;
goto fail;
}
if (!GetFileSizeEx(file, &size)) {
ret = -EINVAL;
goto fail;
}
if (size.HighPart) {
ret = -EFBIG;
goto fail;
}
buf = malloc(sizeof(*fw) + size.LowPart);
if (!buf) {
ret = -ENOMEM;
goto fail;
}
fw = (struct firmware *)buf;
data = buf + sizeof(*fw);
remain = size.LowPart;
while (remain) {
DWORD read = 0;
if (!ReadFile(file, data + (size.LowPart - remain), remain, &read, NULL)) {
ret = -EIO;
goto fail;
}
remain -= read;
}
fw->size = size.LowPart;
fw->data = data;
*p = fw;
CloseHandle(file);
return 0;
fail:
if (buf)
free(buf);
if (file != INVALID_HANDLE_VALUE)
CloseHandle(file);
return ret;
}
void release_firmware(const struct firmware *fw)
{
free((void *)fw);
return;
}

View File

@@ -0,0 +1,112 @@
// misc_win.h
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <stdio.h>
#include <windows.h>
#include "msg.h"
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define msleep(ms) Sleep(ms)
#define mdelay(ms) /* do nothing*/
#define GFP_KERNEL 0
#define GFP_ATOMIC 0
#define kmalloc(size, gfp) malloc(size)
#define kcalloc(n, size, gfp) calloc(n, size)
#define kfree(p) free(p)
static inline void * kzalloc(size_t size, int dummy)
{
void *p;
p = malloc(size);
if (p)
memset(p, 0, size);
return p;
}
struct mutex {
CRITICAL_SECTION s;
};
static inline void mutex_init(struct mutex *lock)
{
InitializeCriticalSection(&lock->s);
}
static inline void mutex_destroy(struct mutex *lock)
{
DeleteCriticalSection(&lock->s);
}
static inline void mutex_lock(struct mutex *lock)
{
EnterCriticalSection(&lock->s);
}
static inline void mutex_unlock(struct mutex *lock)
{
LeaveCriticalSection(&lock->s);
}
struct device {
char driver_name[64];
char device_name[64];
};
#define printk(format, ...) msg_printf(format, ##__VA_ARGS__)
#define dev_print(level, dev, format, ...) msg_printf("[" level "] %s %s: " format, (dev)->driver_name, (dev)->device_name, ##__VA_ARGS__)
#define dev_err(dev, format, ...) dev_print("ERR", dev, format, ##__VA_ARGS__)
#define dev_warn(dev, format, ...) dev_print("WARN", dev, format, ##__VA_ARGS__)
#define dev_info(dev, format, ...) dev_print("INFO", dev, format, ##__VA_ARGS__)
#if defined(_DEBUG) || defined(_DEBUG_MSG)
#define dev_dbg(dev, format, ...) dev_print("DBG", dev, format, ##__VA_ARGS__)
#else
#define dev_dbg(dev, format, ...)
#endif
typedef int atomic_t;
static inline void atomic_set(atomic_t *p, int v)
{
_ReadWriteBarrier();
*p = v;
_ReadWriteBarrier();
}
static inline int atomic_read(const atomic_t *p)
{
int v;
_ReadWriteBarrier();
v = *p;
_ReadWriteBarrier();
return v;
}
struct firmware {
size_t size;
const u8 *data;
};
int request_firmware(const struct firmware **fw, const char *name, struct device *);
void release_firmware(const struct firmware *fw);

View File

@@ -0,0 +1,139 @@
// notify_icon.cpp
#include "notify_icon.hpp"
#include <tchar.h>
namespace px4 {
#define WM_NOTIFYICON (WM_USER + 0x100);
UINT NotifyIcon::next_id_ = 1;
NotifyIcon::NotifyIcon(LPCWSTR icon_name, std::wstring tip)
: hinst_(GetModuleHandleW(nullptr)),
hwnd_(nullptr),
param_(new CreateParam(icon_name, tip)),
mtx_(),
cond_(),
ready_(false),
th_(&px4::NotifyIcon::Worker, this)
{
std::unique_lock<std::mutex> lock(mtx_);
cond_.wait(lock);
param_.release();
if (!ready_.load()) {
lock.unlock();
throw NotifyIconError("px4::NotifyIcon::NotifyIcon: failed.");
}
}
NotifyIcon::~NotifyIcon()
{
SendMessageW(hwnd_, WM_CLOSE, 0, 0);
th_.join();
}
LRESULT CALLBACK NotifyIcon::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
void *p;
NotifyIcon *ni = nullptr;
static NOTIFYICONDATAW nid;
p = reinterpret_cast<void *>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
if (p) {
ni = reinterpret_cast<NotifyIcon *>(DecodePointer(p));
} else if (uMsg == WM_CREATE && lParam) {
ni = reinterpret_cast<NotifyIcon *>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(EncodePointer(ni)));
}
if (!ni)
return -1;
std::unique_lock<std::mutex> lock(ni->mtx_, std::defer_lock);
switch (uMsg) {
case WM_CREATE:
{
nid.cbSize = sizeof(NOTIFYICONDATAW);
nid.hWnd = hwnd;
nid.uID = next_id_++;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
nid.uCallbackMessage = WM_NOTIFYICON;
nid.hIcon = LoadIconW(ni->hinst_, ni->param_->icon_name);
wcscpy_s(nid.szTip, sizeof(nid.szTip) / sizeof(nid.szTip[0]), ni->param_->tip.c_str());
Shell_NotifyIconW(NIM_ADD, &nid);
return 0;
}
case WM_CLOSE:
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
lock.lock();
Shell_NotifyIcon(NIM_DELETE, &nid);
DestroyIcon(nid.hIcon);
lock.unlock();
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
void NotifyIcon::Worker()
{
WCHAR class_name[] = TEXT("NotifyIcon_MessageWindow");
WNDCLASSEXW wc;
MSG msg;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst_;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = class_name;
wc.hIconSm = nullptr;
if (!RegisterClassExW(&wc)) {
ready_.store(false);
cond_.notify_all();
return;
}
hwnd_ = CreateWindowExW(0, class_name, nullptr, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, nullptr, hinst_, this);
if (!hwnd_) {
ready_.store(false);
cond_.notify_all();
return;
}
ready_.store(true);
cond_.notify_all();
while (GetMessage(&msg, nullptr, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return;
}
} // namespace px4

View File

@@ -0,0 +1,58 @@
// notify_icon.hpp
#pragma once
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <memory>
#include <thread>
#include <stdexcept>
#include <windows.h>
namespace px4 {
class NotifyIcon final {
public:
NotifyIcon(LPCWSTR icon_name, std::wstring tip);
~NotifyIcon();
// cannot copy
NotifyIcon(const NotifyIcon &) = delete;
NotifyIcon& operator=(const NotifyIcon &) = delete;
// cannot move
NotifyIcon(NotifyIcon &&) = delete;
NotifyIcon& operator=(NotifyIcon &&) = delete;
private:
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void Worker();
struct CreateParam {
CreateParam(LPCWSTR icon_name, std::wstring &tip)
: icon_name(icon_name), tip(tip)
{
}
LPCWSTR icon_name;
std::wstring &tip;
};
static UINT next_id_;
HINSTANCE hinst_;
HWND hwnd_;
std::unique_ptr<CreateParam> param_;
std::mutex mtx_;
std::condition_variable cond_;
std::atomic_bool ready_;
std::thread th_;
};
class NotifyIconError : public std::runtime_error {
public:
explicit NotifyIconError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,98 @@
// pipe_server.cpp
#include "pipe_server.hpp"
#include <system_error>
namespace px4 {
PipeServer::PipeServer() noexcept
: Pipe()
{
}
PipeServer::~PipeServer()
{
if (!IsConnected())
return;
FlushFileBuffers(handle_);
DisconnectNamedPipe(handle_);
}
bool PipeServer::Accept(const std::wstring &name, const PipeServerConfig &config, HANDLE ready_event, HANDLE cancel_event, DWORD timeout) noexcept
{
if (IsConnected())
return false;
bool ret = false;
std::wstring path = L"\\\\.\\pipe\\" + name;
OVERLAPPED ol = { 0 };
DWORD mode = 0;
HANDLE pipe_handle = nullptr;
ol.hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!ol.hEvent) {
error_.assign(GetLastError(), std::system_category());
goto exit;
}
mode |= (config.stream_pipe) ? PIPE_TYPE_BYTE : PIPE_TYPE_MESSAGE;
mode |= (config.stream_read) ? PIPE_READMODE_BYTE : PIPE_READMODE_MESSAGE;
mode |= PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS;
pipe_handle = CreateNamedPipeW(
path.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
mode,
PIPE_UNLIMITED_INSTANCES,
static_cast<DWORD>(config.out_buffer_size),
static_cast<DWORD>(config.in_buffer_size),
config.default_timeout,
nullptr);
if (pipe_handle == INVALID_HANDLE_VALUE) {
error_.assign(GetLastError(), std::system_category());
goto exit;
}
if (ready_event)
SetEvent(ready_event);
if (ConnectNamedPipe(pipe_handle, &ol)) {
ret = true;
goto exit;
} else {
DWORD err = GetLastError();
if (err == ERROR_IO_PENDING || err == ERROR_PIPE_LISTENING) {
HANDLE handles[2] = { ol.hEvent, cancel_event };
DWORD res, t;
res = WaitForMultipleObjects((cancel_event) ? 2 : 1, handles, FALSE, INFINITE);
if (res == WAIT_OBJECT_0 && GetOverlappedResult(pipe_handle, &ol, &t, TRUE))
ret = true;
else
error_.assign(err, std::system_category());
} else if (err == ERROR_PIPE_CONNECTED) {
ret = true;
} else {
error_.assign(err, std::system_category());
}
}
exit:
if (ret) {
SetHandle(pipe_handle);
} else {
if (pipe_handle && pipe_handle != INVALID_HANDLE_VALUE)
CloseHandle(pipe_handle);
}
if (ol.hEvent)
CloseHandle(ol.hEvent);
return ret;
}
} // namespace px4

View File

@@ -0,0 +1,30 @@
// pipe_server.hpp
#pragma once
#include <cstdint>
#include <string>
#include <windows.h>
#include "pipe.hpp"
namespace px4 {
class PipeServer final : public px4::Pipe {
public:
struct PipeServerConfig {
bool stream_pipe;
bool stream_read;
std::size_t out_buffer_size;
std::size_t in_buffer_size;
std::uint32_t default_timeout;
};
PipeServer() noexcept;
~PipeServer();
bool Accept(const std::wstring &name, const PipeServerConfig &config, HANDLE ready_event, HANDLE cancel_event, DWORD timeout = INFINITE) noexcept;
};
} // namespace px4

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
// px4_device.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <atomic>
#include <string>
#include <mutex>
#include <condition_variable>
#include "device_definition_set.hpp"
#include "device_base.hpp"
#include "receiver_base.hpp"
#include "receiver_manager.hpp"
#include "ringbuffer.hpp"
#include "winusb_compat.h"
#include "i2c_comm.h"
#include "it930x.h"
#include "itedtv_bus.h"
#include "tc90522.h"
#include "r850.h"
#include "rt710.h"
namespace px4 {
#define PX4_DEVICE_TS_SYNC_COUNT 4U
#define PX4_DEVICE_TS_SYNC_SIZE (188U * PX4_DEVICE_TS_SYNC_COUNT)
struct Px4DeviceConfig final {
Px4DeviceConfig()
: usb{ 816, 816, 5, false },
device{ 2048, 2000, true }
{}
struct {
unsigned int xfer_packets;
unsigned int urb_max_packets;
unsigned int max_urbs;
bool no_raw_io;
} usb;
struct {
unsigned int receiver_max_packets;
int psb_purge_timeout;
bool discard_null_packets;
} device;
};
class Px4Device final : public px4::DeviceBase {
public:
Px4Device() = delete;
Px4Device(const std::wstring &path, const px4::DeviceDefinition &device_def, std::uintptr_t index, px4::ReceiverManager &receiver_manager);
~Px4Device();
// cannot copy
Px4Device(const Px4Device &) = delete;
Px4Device& operator=(const Px4Device &) = delete;
// cannot move
Px4Device(Px4Device &&) = delete;
Px4Device& operator=(Px4Device &&) = delete;
int Init() override;
void Term() override;
void SetAvailability(bool available) override;
px4::ReceiverBase * GetReceiver(int id) const override;
private:
struct SerialNumber final {
std::uint64_t serial_number;
std::uint8_t dev_id;
};
struct StreamContext final {
std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf[4];
std::uint8_t remain_buf[PX4_DEVICE_TS_SYNC_SIZE];
std::size_t remain_len;
};
class MultiDevice final {
public:
enum class Mode {
ALL = 0,
S_ONLY,
S0_ONLY,
S1_ONLY
};
~MultiDevice();
// cannot copy
MultiDevice(const MultiDevice &) = delete;
MultiDevice& operator=(const MultiDevice &) = delete;
// cannot move
MultiDevice(MultiDevice &&) = delete;
MultiDevice& operator=(MultiDevice &&) = delete;
static bool Search(std::uint64_t serial_number, std::shared_ptr<MultiDevice> &mldev);
static int Alloc(Px4Device &dev, Mode mode, std::shared_ptr<MultiDevice> &mldev);
int Add(Px4Device &dev);
int Remove(Px4Device &dev);
int SetPower(Px4Device &dev, std::uintptr_t index, bool state, bool *first);
private:
MultiDevice(Mode mode, std::uint64_t serial_number);
std::uint8_t GetDeviceCount() const noexcept;
bool GetReceiverStatus(std::uint8_t dev_id) const noexcept;
bool IsPowerIntelockingRequried(std::uint8_t dev_id) const noexcept;
static std::mutex mldev_list_lock_;
static std::unordered_map<std::uint64_t, std::shared_ptr<MultiDevice>> mldev_list_;
std::mutex lock_;
std::uint64_t serial_number_;
Mode mode_;
Px4Device *dev_[2];
bool power_state_[2];
bool receiver_state_[2][4];
};
class Px4Receiver final : public px4::ReceiverBase {
public:
Px4Receiver() = delete;
Px4Receiver(Px4Device &parent, std::uintptr_t index);
~Px4Receiver();
// cannot copy
Px4Receiver(const Px4Receiver &) = delete;
Px4Receiver& operator=(const Px4Receiver &) = delete;
// cannot move
Px4Receiver(Px4Receiver &&) = delete;
Px4Receiver& operator=(Px4Receiver &&) = delete;
int Init(bool sleep);
void Term();
int Open() override;
void Close() override;
int Tune() override;
int CheckLock(bool &locked) override;
int SetLnbVoltage(std::int32_t voltage) override;
int SetCapture(bool capture) override;
int ReadStat(px4::command::StatType type, std::int32_t &value) override;
int InitPrimary();
private:
static struct tc90522_regbuf tc_init_t0_[];
static struct tc90522_regbuf tc_init_s0_[];
static struct tc90522_regbuf tc_init_t_[];
static struct tc90522_regbuf tc_init_s_[];
Px4Device &parent_;
std::uintptr_t index_;
std::mutex lock_;
px4::SystemType system_;
std::atomic_bool init_;
std::atomic_bool open_;
std::condition_variable close_cond_;
bool lnb_power_;
tc90522_demod tc90522_;
union {
r850_tuner r850_;
rt710_tuner rt710_;
};
std::atomic_bool streaming_;
};
const i2c_comm_master& GetI2cMaster(int bus) const;
int SetBackendPower(bool state);
int SetLnbVoltage(std::int32_t voltage);
int PrepareCapture();
int StartCapture();
int StopCapture();
static void StreamProcess(std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf[], std::uint8_t **buf, std::size_t &len);
static int StreamHandler(void *context, void *buf, std::uint32_t len);
Px4DeviceConfig config_;
std::recursive_mutex lock_;
std::atomic_bool available_;
SerialNumber serial_;
std::shared_ptr<MultiDevice> mldev_;
std::atomic_bool init_;
unsigned int open_count_;
unsigned int lnb_power_count_;
unsigned int streaming_count_;
std::unique_ptr<Px4Receiver> receivers_[4];
it930x_bridge it930x_;
StreamContext stream_ctx_;
};
} // namespace px4

View File

@@ -0,0 +1,960 @@
// pxmlt_device.cpp
#include "pxmlt_device.hpp"
#include <cassert>
#include <cmath>
#include "type.hpp"
#include "command.hpp"
#include "misc_win.h"
namespace px4 {
const PxMltDevice::PxMltDeviceParam PxMltDevice::params_[][5] = {
/* PX-MLT5U */
{ { 0x65, 3, 4 }, { 0x6c, 1, 3 }, { 0x64, 1, 1 }, { 0x6c, 3, 2 }, { 0x64, 3, 0 } },
/* PX-MLT5PE */
{ { 0x65, 3, 0 }, { 0x6c, 1, 1 }, { 0x64, 1, 2 }, { 0x6c, 3, 3 }, { 0x64, 3, 4 } },
/* PX-MLT8PE3 */
{ { 0x65, 3, 0 }, { 0x6c, 3, 3 }, { 0x64, 3, 4 }, { 0x00, 0, 1 }, { 0x00, 0, 2 } },
/* PX-MLT8PE5 */
{ { 0x65, 1, 0 }, { 0x64, 1, 1 }, { 0x6c, 1, 2 }, { 0x6c, 3, 3 }, { 0x64, 3, 4 } },
/* ISDB6014 V2.0 (4TS) */
{ { 0x65, 3, 0 }, { 0x6c, 1, 1 }, { 0x64, 1, 2 }, { 0x64, 3, 4 }, { 0x00, 0, 3 } }
};
PxMltDevice::PxMltDevice(const std::wstring &path, const px4::DeviceDefinition &device_def, std::uintptr_t index, px4::ReceiverManager &receiver_manager)
: DeviceBase(path, device_def, index, receiver_manager),
config_(),
lock_(),
available_(false),
init_(false),
open_count_(0),
lnb_power_count_(0),
streaming_count_(0),
tuner_lock_{}
{
if (usb_dev_.descriptor.idVendor != 0x0511)
throw DeviceError("px4::PxMltDevice::PxMltDevice: unsupported device. (unknown vendor id)");
receiver_num_ = 5;
switch (usb_dev_.descriptor.idProduct) {
case 0x084e:
model_ = PxMltDeviceModel::PXMLT5U;
break;
case 0x24e:
model_ = PxMltDeviceModel::PXMLT5PE;
break;
case 0x0252:
model_ = PxMltDeviceModel::PXMLT8PE3;
receiver_num_ = 3;
break;
case 0x0253:
model_ = PxMltDeviceModel::PXMLT8PE5;
break;
case 0x0254:
model_ = PxMltDeviceModel::ISDB6014_4TS;
receiver_num_ = 4;
break;
default:
throw DeviceError("px4::PxMltDevice::PxMltDevice: unsupported device. (unknown product id)");
}
memset(&it930x_, 0, sizeof(it930x_));
memset(&stream_ctx_, 0, sizeof(stream_ctx_));
}
PxMltDevice::~PxMltDevice()
{
Term();
}
int PxMltDevice::Init()
{
dev_dbg(&dev_, "px4::PxMltDevice::Init: init_: %s\n", (init_) ? "true" : "false");
std::lock_guard<std::recursive_mutex> lock(lock_);
if (init_)
return -EALREADY;
int ret = 0;
itedtv_bus &bus = it930x_.bus;
bus.dev = &dev_;
bus.type = ITEDTV_BUS_USB;
bus.usb.dev = &usb_dev_;
bus.usb.ctrl_timeout = 3000;
it930x_.dev = &dev_;
it930x_.config.xfer_size = 188 * config_.usb.xfer_packets;
it930x_.config.i2c_speed = 0x07;
ret = itedtv_bus_init(&bus);
if (ret)
goto fail_bus;
ret = it930x_init(&it930x_);
if (ret)
goto fail_bridge;
for (int i = 0; i < receiver_num_; i++) {
it930x_stream_input &input = it930x_.config.input[i];
input.enable = true;
input.is_parallel = false;
input.port_number = params_[static_cast<int>(model_)][i].port_number;
input.slave_number = i;
input.i2c_bus = params_[static_cast<int>(model_)][i].i2c_bus;
input.i2c_addr = params_[static_cast<int>(model_)][i].i2c_addr;
input.packet_len = 188;
input.sync_byte = ((i + 1) << 4) | 0x07;
receivers_[i].reset(new PxMltReceiver(*this, i));
stream_ctx_.stream_buf[i] = receivers_[i]->GetStreamBuffer();
}
for (int i = receiver_num_; i < 5; i++) {
it930x_.config.input[i].enable = false;
it930x_.config.input[i].port_number = params_[static_cast<int>(model_)][i].port_number;
}
ret = it930x_load_firmware(&it930x_, "it930x-firmware.bin");
if (ret)
goto fail_device;
ret = it930x_init_warm(&it930x_);
if (ret)
goto fail_device;
/* GPIO */
ret = it930x_set_gpio_mode(&it930x_, 7, IT930X_GPIO_OUT, true);
if (ret)
goto fail_device;
ret = it930x_write_gpio(&it930x_, 7, true);
if (ret)
goto fail_device;
ret = it930x_set_gpio_mode(&it930x_, 2, IT930X_GPIO_OUT, true);
if (ret)
goto fail_device;
ret = it930x_write_gpio(&it930x_, 2, false);
if (ret)
goto fail_device;
ret = it930x_set_gpio_mode(&it930x_, 11, IT930X_GPIO_OUT, true);
if (ret)
goto fail_device;
/* LNB power supply: off */
ret = it930x_write_gpio(&it930x_, 11, false);
if (ret)
goto fail_device;
if (config_.device.discard_null_packets) {
it930x_pid_filter filter;
filter.block = true;
filter.num = 1;
filter.pid[0] = 0x1fff;
for (int i = 0; i < receiver_num_; i++) {
ret = it930x_set_pid_filter(&it930x_, i, &filter);
if (ret)
goto fail_device;
}
}
init_ = true;
for (auto it = device_def_.receivers.cbegin(); it != device_def_.receivers.cend(); ++it) {
px4::command::ReceiverInfo ri;
if (it->index < 0 || it->index > 4)
continue;
wcscpy_s(ri.device_name, device_def_.name.c_str());
ri.device_guid = device_def_.guid;
wcscpy_s(ri.receiver_name, it->name.c_str());
ri.receiver_guid = it->guid;
ri.systems = it->systems;
ri.index = it->index;
ri.data_id = 0;
receiver_manager_.Register(ri, receivers_[it->index].get());
}
return 0;
fail_device:
for (int i = 0; i < receiver_num_; i++) {
stream_ctx_.stream_buf[i] = nullptr;
receivers_[i].reset();
}
it930x_term(&it930x_);
fail_bridge:
itedtv_bus_term(&bus);
fail_bus:
return ret;
}
void PxMltDevice::Term()
{
dev_dbg(&dev_, "px4::PxMltDevice::Term: init_: %s\n", (init_) ? "true" : "false");
std::unique_lock<std::recursive_mutex> lock(lock_);
if (!init_)
return;
for (int i = 0; i < receiver_num_; i++)
receiver_manager_.Unregister(receivers_[i].get());
lock.unlock();
for (int i = 0; i < receiver_num_; i++) {
stream_ctx_.stream_buf[i] = nullptr;
receivers_[i].reset();
}
lock.lock();
it930x_term(&it930x_);
itedtv_bus_term(&it930x_.bus);
init_ = false;
return;
}
void PxMltDevice::SetAvailability(bool available)
{
available_ = available;
}
ReceiverBase* PxMltDevice::GetReceiver(int id) const
{
if (id < 0 || id >= receiver_num_)
throw std::out_of_range("receiver id out of range");
return receivers_[id].get();
}
const i2c_comm_master& PxMltDevice::GetI2cMaster(int bus) const
{
if (bus < 1 || bus > 3)
throw std::out_of_range("bus number out of range");
return it930x_.i2c_master[bus - 1];
}
int PxMltDevice::SetBackendPower(bool state)
{
dev_dbg(&dev_, "px4::PxMltDevice::SetBackendPower: state: %s\n", (state) ? "true" : "false");
int ret = 0;
std::lock_guard<std::recursive_mutex> lock(lock_);
if (!state && !available_)
return 0;
if (state) {
ret = it930x_write_gpio(&it930x_, 7, false);
if (ret)
return ret;
Sleep(80);
ret = it930x_write_gpio(&it930x_, 2, true);
if (ret)
return ret;
Sleep(20);
} else {
it930x_write_gpio(&it930x_, 2, false);
it930x_write_gpio(&it930x_, 7, true);
}
return 0;
}
int PxMltDevice::SetLnbVoltage(std::int32_t voltage)
{
dev_dbg(&dev_, "px4::PxMltDevice::SetLnbVoltage: voltage: %d\n", voltage);
int ret = 0;
std::lock_guard<std::recursive_mutex> lock(lock_);
assert((voltage && lnb_power_count_ >= 0) || (!voltage && lnb_power_count_ > 0));
if (!voltage) {
lnb_power_count_--;
if (!available_)
return 0;
}
if (!lnb_power_count_)
ret = it930x_write_gpio(&it930x_, 11, !!voltage);
if (voltage && !ret)
lnb_power_count_++;
return ret;
}
int PxMltDevice::StartCapture()
{
dev_dbg(&dev_, "px4::PxMltDevice::StartCapture\n");
int ret = 0;
std::lock_guard<std::recursive_mutex> lock(lock_);
if (!streaming_count_) {
ret = it930x_purge_psb(&it930x_, config_.device.psb_purge_timeout);
if (ret) {
dev_err(&dev_, "px4::PxMltDevice::StartCapture: it930x_purge_psb() failed. (ret: %d)\n", ret);
return ret;
}
it930x_.bus.usb.streaming.urb_buffer_size = 188 * config_.usb.urb_max_packets;
it930x_.bus.usb.streaming.urb_num = config_.usb.max_urbs;
it930x_.bus.usb.streaming.no_dma = true;
it930x_.bus.usb.streaming.no_raw_io = config_.usb.no_raw_io;
stream_ctx_.remain_len = 0;
ret = itedtv_bus_start_streaming(&it930x_.bus, StreamHandler, this);
if (ret) {
dev_err(&dev_, "px4::PxMltDevice::StartCapture: itedtv_bus_start_streaming() failed. (ret: %d)\n", ret);
return ret;
}
}
streaming_count_++;
dev_dbg(&dev_, "px4::PxMltDevice::StartCapture: streaming_count_: %u\n", streaming_count_);
return 0;
}
int PxMltDevice::StopCapture()
{
dev_dbg(&dev_, "px4::PxMltDevice::StopCapture\n");
std::lock_guard<std::recursive_mutex> lock(lock_);
assert(streaming_count_ > 0);
streaming_count_--;
if (!streaming_count_) {
dev_dbg(&dev_, "px4::PxMltDevice::StopCapture: stopping...\n");
itedtv_bus_stop_streaming(&it930x_.bus);
} else {
dev_dbg(&dev_, "px4::PxMltDevice::StopCapture: streaming_count_: %u\n", streaming_count_);
}
return 0;
}
void PxMltDevice::StreamProcess(std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf[], std::uint8_t **buf, std::size_t &len)
{
std::uint8_t *p = *buf;
std::size_t remain = len;
while (remain) {
std::size_t i;
bool sync_remain = false;
for (i = 0; i < PXMLT_DEVICE_TS_SYNC_COUNT; i++) {
if (((i + 1) * 188) <= remain) {
if ((p[i * 188] & 0x8f) != 0x07)
break;
} else {
sync_remain = true;
break;
}
}
if (sync_remain)
break;
if (i < PXMLT_DEVICE_TS_SYNC_COUNT) {
p++;
remain--;
continue;
}
while (remain >= 188 && ((p[0] & 0x8f) == 0x07)) {
u8 id = (p[0] & 0x70) >> 4;
if (id && id < 6) {
std::size_t pkt_len = 188;
p[0] = 0x47;
stream_buf[id - 1]->Write(p, pkt_len);
}
p += 188;
remain -= 188;
}
}
for (int i = 0; i < 5; i++)
stream_buf[i]->NotifyWrite();
*buf = p;
len = remain;
return;
}
int PxMltDevice::StreamHandler(void *context, void *buf, std::uint32_t len)
{
PxMltDevice &obj = *static_cast<PxMltDevice*>(context);
StreamContext &stream_ctx = obj.stream_ctx_;
std::uint8_t *p = static_cast<std::uint8_t*>(buf);
std::size_t remain = len;
if (stream_ctx.remain_len) {
if ((stream_ctx.remain_len + len) >= PXMLT_DEVICE_TS_SYNC_SIZE) {
std::uint8_t * remain_buf = stream_ctx.remain_buf;
std::size_t t = PXMLT_DEVICE_TS_SYNC_SIZE - stream_ctx.remain_len;
memcpy(remain_buf + stream_ctx.remain_len, p, t);
stream_ctx.remain_len = PXMLT_DEVICE_TS_SYNC_SIZE;
StreamProcess(stream_ctx.stream_buf, &remain_buf, stream_ctx.remain_len);
if (!stream_ctx.remain_len) {
p += t;
remain -= t;
}
stream_ctx.remain_len = 0;
} else {
memcpy(stream_ctx.remain_buf + stream_ctx.remain_len, p, len);
stream_ctx.remain_len += len;
return 0;
}
}
StreamProcess(stream_ctx.stream_buf, &p, remain);
if (remain) {
dev_dbg(&obj.dev_, "px4::PxMltDevice::StreamHandler: remain: %lu\n", remain);
memcpy(stream_ctx.remain_buf, p, remain);
stream_ctx.remain_len = remain;
}
return 0;
}
const PxMltDevice::PxMltReceiver::PxMltReceiverCnTableIsdbS PxMltDevice::PxMltReceiver::isdbs_cn_table_[] = {
{ 0x5af, 0 }, { 0x597, 100 }, { 0x57e, 200 }, { 0x567, 300 },
{ 0x550, 400 }, { 0x539, 500 }, { 0x522, 600 }, { 0x50c, 700 },
{ 0x4f6, 800 }, { 0x4e1, 900 }, { 0x4cc, 1000 }, { 0x4b6, 1100 },
{ 0x4a1, 1200 }, { 0x48c, 1300 }, { 0x477, 1400 }, { 0x463, 1500 },
{ 0x44f, 1600 }, { 0x43c, 1700 }, { 0x428, 1800 }, { 0x416, 1900 },
{ 0x403, 2000 }, { 0x3ef, 2100 }, { 0x3dc, 2200 }, { 0x3c9, 2300 },
{ 0x3b6, 2400 }, { 0x3a4, 2500 }, { 0x392, 2600 }, { 0x381, 2700 },
{ 0x36f, 2800 }, { 0x35f, 2900 }, { 0x34e, 3000 }, { 0x33d, 3100 },
{ 0x32d, 3200 }, { 0x31d, 3300 }, { 0x30d, 3400 }, { 0x2fd, 3500 },
{ 0x2ee, 3600 }, { 0x2df, 3700 }, { 0x2d0, 3800 }, { 0x2c2, 3900 },
{ 0x2b4, 4000 }, { 0x2a6, 4100 }, { 0x299, 4200 }, { 0x28c, 4300 },
{ 0x27f, 4400 }, { 0x272, 4500 }, { 0x265, 4600 }, { 0x259, 4700 },
{ 0x24d, 4800 }, { 0x241, 4900 }, { 0x236, 5000 }, { 0x22b, 5100 },
{ 0x220, 5200 }, { 0x215, 5300 }, { 0x20a, 5400 }, { 0x200, 5500 },
{ 0x1f6, 5600 }, { 0x1ec, 5700 }, { 0x1e2, 5800 }, { 0x1d8, 5900 },
{ 0x1cf, 6000 }, { 0x1c6, 6100 }, { 0x1bc, 6200 }, { 0x1b3, 6300 },
{ 0x1aa, 6400 }, { 0x1a2, 6500 }, { 0x199, 6600 }, { 0x191, 6700 },
{ 0x189, 6800 }, { 0x181, 6900 }, { 0x179, 7000 }, { 0x171, 7100 },
{ 0x169, 7200 }, { 0x161, 7300 }, { 0x15a, 7400 }, { 0x153, 7500 },
{ 0x14b, 7600 }, { 0x144, 7700 }, { 0x13d, 7800 }, { 0x137, 7900 },
{ 0x130, 8000 }, { 0x12a, 8100 }, { 0x124, 8200 }, { 0x11e, 8300 },
{ 0x118, 8400 }, { 0x112, 8500 }, { 0x10c, 8600 }, { 0x107, 8700 },
{ 0x101, 8800 }, { 0xfc, 8900 }, { 0xf7, 9000 }, { 0xf2, 9100 },
{ 0xec, 9200 }, { 0xe7, 9300 }, { 0xe2, 9400 }, { 0xdd, 9500 },
{ 0xd8, 9600 }, { 0xd4, 9700 }, { 0xcf, 9800 }, { 0xca, 9900 },
{ 0xc6, 10000 }, { 0xc2, 10100 }, { 0xbe, 10200 }, { 0xb9, 10300 },
{ 0xb5, 10400 }, { 0xb1, 10500 }, { 0xae, 10600 }, { 0xaa, 10700 },
{ 0xa6, 10800 }, { 0xa3, 10900 }, { 0x9f, 11000 }, { 0x9b, 11100 },
{ 0x98, 11200 }, { 0x95, 11300 }, { 0x91, 11400 }, { 0x8e, 11500 },
{ 0x8b, 11600 }, { 0x88, 11700 }, { 0x85, 11800 }, { 0x82, 11900 },
{ 0x7f, 12000 }, { 0x7c, 12100 }, { 0x7a, 12200 }, { 0x77, 12300 },
{ 0x74, 12400 }, { 0x72, 12500 }, { 0x6f, 12600 }, { 0x6d, 12700 },
{ 0x6b, 12800 }, { 0x68, 12900 }, { 0x66, 13000 }, { 0x64, 13100 },
{ 0x61, 13200 }, { 0x5f, 13300 }, { 0x5d, 13400 }, { 0x5b, 13500 },
{ 0x59, 13600 }, { 0x57, 13700 }, { 0x55, 13800 }, { 0x53, 13900 },
{ 0x51, 14000 }, { 0x4f, 14100 }, { 0x4e, 14200 }, { 0x4c, 14300 },
{ 0x4a, 14400 }, { 0x49, 14500 }, { 0x47, 14600 }, { 0x45, 14700 },
{ 0x44, 14800 }, { 0x42, 14900 }, { 0x41, 15000 }, { 0x3f, 15100 },
{ 0x3e, 15200 }, { 0x3c, 15300 }, { 0x3b, 15400 }, { 0x3a, 15500 },
{ 0x38, 15600 }, { 0x37, 15700 }, { 0x36, 15800 }, { 0x34, 15900 },
{ 0x33, 16000 }, { 0x32, 16100 }, { 0x31, 16200 }, { 0x30, 16300 },
{ 0x2f, 16400 }, { 0x2e, 16500 }, { 0x2d, 16600 }, { 0x2c, 16700 },
{ 0x2b, 16800 }, { 0x2a, 16900 }, { 0x29, 17000 }, { 0x28, 17100 },
{ 0x27, 17200 }, { 0x26, 17300 }, { 0x25, 17400 }, { 0x24, 17500 },
{ 0x23, 17600 }, { 0x22, 17800 }, { 0x21, 17900 }, { 0x20, 18000 },
{ 0x1f, 18200 }, { 0x1e, 18300 }, { 0x1d, 18500 }, { 0x1c, 18700 },
{ 0x1b, 18900 }, { 0x1a, 19000 }, { 0x19, 19200 }, { 0x18, 19300 },
{ 0x17, 19500 }, { 0x16, 19700 }, { 0x15, 19900 }, { 0x14, 20000 }
};
PxMltDevice::PxMltReceiver::PxMltReceiver(PxMltDevice &parent, std::uintptr_t index)
: parent_(parent),
index_(index),
lock_(),
open_(false),
close_cond_(),
lnb_power_(false),
current_system_(px4::SystemType::UNSPECIFIED),
streaming_(false)
{
auto i2c_addr = parent_.params_[static_cast<int>(parent_.model_)][index_].i2c_addr;
auto i2c_bus = parent_.params_[static_cast<int>(parent_.model_)][index_].i2c_bus;
tuner_lock_ = &parent_.tuner_lock_[(i2c_bus == 3) ? 0 : 1];
const device *dev = &parent_.GetDevice();
const i2c_comm_master *i2c = &parent_.GetI2cMaster(i2c_bus);
cxd2856er_.dev = dev;
cxd2856er_.i2c = i2c;
cxd2856er_.i2c_addr.slvx = i2c_addr + 2;
cxd2856er_.i2c_addr.slvt = i2c_addr;
cxd2856er_.config.xtal = 24000;
cxd2856er_.config.tuner_i2c = true;
cxd2858er_.dev = dev;
cxd2858er_.i2c = &cxd2856er_.i2c_master;
cxd2858er_.i2c_addr = 0x60;
cxd2858er_.config.xtal = 16000;
cxd2858er_.config.ter.lna = true;
cxd2858er_.config.sat.lna = true;
}
PxMltDevice::PxMltReceiver::~PxMltReceiver()
{
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::~PxMltReceiver(%u)\n", index_);
std::unique_lock<std::mutex> lock(lock_);
close_cond_.wait(lock, [this] { return !open_; });
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::~PxMltReceiver(%u): exit\n", index_);
}
int PxMltDevice::PxMltReceiver::Open()
{
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Open(%u): open_: %s\n", index_, (open_) ? "true" : "false");
int ret = 0;
std::lock_guard<std::mutex> lock(lock_);
std::lock_guard<std::recursive_mutex> dev_lock(parent_.lock_);
if (open_)
return -EALREADY;
if (!parent_.open_count_) {
ret = parent_.SetBackendPower(true);
if (ret) {
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Open(%u): SetBackendPower(true) failed. (ret: %d)\n", index_, ret);
goto fail_power;
}
}
ret = cxd2856er_init(&cxd2856er_);
if (ret) {
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Open(%u): cxd2856er_init() failed. (ret: %d)\n", index_, ret);
goto fail_demod_init;
}
{
std::lock_guard<std::mutex> tuner_lock(*tuner_lock_);
ret = cxd2858er_init(&cxd2858er_);
if (ret) {
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Open(%u): cxd2858er_init() failed. (ret: %d)\n", index_, ret);
goto fail_tuner_init;
}
}
ret = cxd2856er_write_slvt_reg(&cxd2856er_, 0x00, 0x00);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xc4, 0x80, 0x88);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xc5, 0x01, 0x01);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xc6, 0x03, 0x1f);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg(&cxd2856er_, 0x00, 0x60);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0x52, 0x03, 0x1f);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg(&cxd2856er_, 0x00, 0x00);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xc8, 0x03, 0x1f);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xc9, 0x03, 0x1f);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg(&cxd2856er_, 0x00, 0xa0);
if (ret)
goto fail_backend;
ret = cxd2856er_write_slvt_reg_mask(&cxd2856er_, 0xb9, 0x01, 0x01);
if (ret)
goto fail_backend;
current_system_ = px4::SystemType::UNSPECIFIED;
parent_.open_count_++;
open_ = true;
return 0;
fail_backend:
{
std::lock_guard<std::mutex> tuner_lock(*tuner_lock_);
cxd2858er_term(&cxd2858er_);
}
fail_tuner_init:
cxd2856er_term(&cxd2856er_);
fail_demod_init:
if (!parent_.open_count_)
parent_.SetBackendPower(true);
fail_power:
return ret;
}
void PxMltDevice::PxMltReceiver::Close()
{
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Close(%u): open_: %s\n", index_, (open_) ? "true" : "false");
if (!open_)
return;
SetCapture(false);
SetLnbVoltage(0);
std::unique_lock<std::mutex> lock(lock_);
std::lock_guard<std::recursive_mutex> dev_lock(parent_.lock_);
assert(parent_.open_count_ > 0);
{
std::lock_guard<std::mutex> tuner_lock(*tuner_lock_);
cxd2858er_term(&cxd2858er_);
}
cxd2856er_term(&cxd2856er_);
parent_.open_count_--;
if (!parent_.open_count_)
parent_.SetBackendPower(false);
open_ = false;
lock.unlock();
close_cond_.notify_all();
return;
}
int PxMltDevice::PxMltReceiver::Tune()
{
if (!open_)
return -EINVAL;
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): freq: %u\n", index_, params_.freq);
int ret = 0;
cxd2856er_system_params demod_params = { 0 };
std::unique_lock<std::mutex> lock(lock_);
current_system_ = px4::SystemType::UNSPECIFIED;
switch (params_.system) {
case px4::SystemType::ISDB_T:
demod_params.bandwidth = (params_.bandwidth) ? params_.bandwidth : 6;
ret = cxd2856er_wakeup(&cxd2856er_, CXD2856ER_ISDB_T_SYSTEM, &demod_params);
if (ret)
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2856er_wakeup(CXD2856ER_ISDB_T_SYSTEM) failed. (ret: %d)\n", index_, ret);
break;
case px4::SystemType::ISDB_S:
if (params_.stream_id < 12) {
ret = cxd2856er_set_slot_isdbs(&cxd2856er_, params_.stream_id);
if (ret) {
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2856er_set_slot_isdbs(%u) failed. (ret: %d)\n", index_, params_.stream_id, ret);
break;
}
} else {
ret = cxd2856er_set_tsid_isdbs(&cxd2856er_, params_.stream_id);
if (ret) {
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2856er_set_tsid_isdbs(%u) failed. (ret: %d)\n", index_, params_.stream_id, ret);
break;
}
}
ret = cxd2856er_wakeup(&cxd2856er_, CXD2856ER_ISDB_S_SYSTEM, &demod_params);
if (ret)
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2856er_wakeup(CXD2856ER_ISDB_S_SYSTEM) failed. (ret: %d)\n", index_, ret);
break;
default:
ret = -EINVAL;
break;
}
if (ret)
return ret;
{
std::lock_guard<std::mutex> tuner_lock(*tuner_lock_);
switch (params_.system) {
case px4::SystemType::ISDB_T:
ret = cxd2858er_set_params_t(&cxd2858er_, CXD2858ER_ISDB_T_SYSTEM, params_.freq, 6);
if (ret)
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2858er_set_params_t(%u, 6) failed. (ret: %d)\n");
break;
case px4::SystemType::ISDB_S:
ret = cxd2858er_set_params_s(&cxd2858er_, CXD2858ER_ISDB_S_SYSTEM, params_.freq, 28860);
if (ret)
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2858er_set_params_s(%u, 28860) failed. (ret: %d)\n");
break;
default:
break;
}
}
if (ret)
return ret;
ret = cxd2856er_post_tune(&cxd2856er_);
if (ret)
dev_err(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::Tune(%u): cxd2856er_post_tune() failed. (ret: %d)\n");
else
current_system_ = params_.system;
int i = 300;
while (i--) {
bool locked = false, unlocked = false;
switch (current_system_) {
case px4::SystemType::ISDB_T:
ret = cxd2856er_is_ts_locked_isdbt(&cxd2856er_, &locked, &unlocked);
if (!ret && unlocked)
ret = -ECANCELED;
break;
case px4::SystemType::ISDB_S:
ret = cxd2856er_is_ts_locked_isdbs(&cxd2856er_, &locked);
break;
default:
ret = -EINVAL;
break;
}
if (locked || ret)
break;
lock_.unlock();
msleep(10);
lock_.lock();
}
return ret;
}
int PxMltDevice::PxMltReceiver::CheckLock(bool &locked)
{
return -ENOSYS;
}
int PxMltDevice::PxMltReceiver::SetLnbVoltage(std::int32_t voltage)
{
if (!open_)
return -EINVAL;
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::SetLnbVoltage(%u): voltage: %d\n", index_, voltage);
if (voltage != 0 && voltage != 15)
return -EINVAL;
int ret = 0;
std::lock_guard<std::mutex> lock(lock_);
if (lnb_power_ == !!voltage)
return 0;
ret = parent_.SetLnbVoltage(voltage);
if (!ret || !voltage)
lnb_power_ = !!voltage;
return ret;
}
int PxMltDevice::PxMltReceiver::SetCapture(bool capture)
{
if (!open_)
return -EINVAL;
dev_dbg(&parent_.dev_, "px4::PxMltDevice::PxMltReceiver::SetCapture(%u): capture: %s\n", index_, (capture) ? "true" : "false");
int ret = 0;
std::lock_guard<std::mutex> lock(lock_);
if ((capture && streaming_) || (!capture && !streaming_))
return -EALREADY;
if (capture)
ret = parent_.StartCapture();
else
ret = parent_.StopCapture();
if (!ret) {
if (capture) {
std::size_t size = 188 * parent_.config_.device.receiver_max_packets;
stream_buf_->Alloc(size);
stream_buf_->SetThresholdSize(size / 10);
stream_buf_->Start();
} else {
stream_buf_->Stop();
}
streaming_ = capture;
}
return ret;
}
int PxMltDevice::PxMltReceiver::ReadStat(px4::command::StatType type, std::int32_t &value)
{
if (!open_)
return -EINVAL;
int ret = 0;
std::lock_guard<std::mutex> lock(lock_);
value = 0;
switch (type) {
case px4::command::StatType::SIGNAL_STRENGTH:
// not implemented
ret = -ENOSYS;
break;
case px4::command::StatType::CNR:
switch (current_system_) {
case px4::SystemType::ISDB_T:
{
std::uint16_t val;
ret = cxd2856er_read_cnr_raw_isdbt(&cxd2856er_, &val);
if (ret)
break;
value = static_cast<std::int32_t>((std::log10(val) * 10000) - 9031);
break;
}
case px4::SystemType::ISDB_S:
{
int i, i_min, i_max;
std::uint16_t val;
ret = cxd2856er_read_cnr_raw_isdbs(&cxd2856er_, &val);
if (ret)
break;
i_min = 0;
i_max = (sizeof(isdbs_cn_table_) / sizeof(isdbs_cn_table_[0])) - 1;
if (isdbs_cn_table_[i_min].val <= val) {
value = isdbs_cn_table_[i_min].cnr;
break;
}
if (isdbs_cn_table_[i_max].val >= val) {
value = isdbs_cn_table_[i_max].cnr;
break;
}
while (true) {
i = i_min + (i_max - i_min) / 2;
if (isdbs_cn_table_[i].val == val) {
value = isdbs_cn_table_[i].cnr;
break;
}
if (isdbs_cn_table_[i].val > val)
i_min = i + 1;
else
i_max = i - 1;
if (i_max < i_min) {
value = isdbs_cn_table_[i_max].cnr;
break;
}
}
break;
}
default:
ret = -EINVAL;
break;
}
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
} // namespace px4

View File

@@ -0,0 +1,157 @@
// pxmlt_device.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <atomic>
#include <string>
#include <mutex>
#include <condition_variable>
#include "device_definition_set.hpp"
#include "device_base.hpp"
#include "receiver_base.hpp"
#include "receiver_manager.hpp"
#include "ringbuffer.hpp"
#include "winusb_compat.h"
#include "i2c_comm.h"
#include "it930x.h"
#include "itedtv_bus.h"
#include "cxd2856er.h"
#include "cxd2858er.h"
namespace px4 {
#define PXMLT_DEVICE_TS_SYNC_COUNT 4
#define PXMLT_DEVICE_TS_SYNC_SIZE (188 * PXMLT_DEVICE_TS_SYNC_COUNT)
enum class PxMltDeviceModel {
PXMLT5U = 0,
PXMLT5PE,
PXMLT8PE3,
PXMLT8PE5,
ISDB6014_4TS
};
struct PxMltDeviceConfig final {
PxMltDeviceConfig()
: usb{ 816, 816, 5, false },
device{ 2048, 2000, true }
{}
struct {
unsigned int xfer_packets;
unsigned int urb_max_packets;
unsigned int max_urbs;
bool no_raw_io;
} usb;
struct {
unsigned int receiver_max_packets;
int psb_purge_timeout;
bool discard_null_packets;
} device;
};
class PxMltDevice final : public px4::DeviceBase {
public:
PxMltDevice() = delete;
PxMltDevice(const std::wstring &path, const px4::DeviceDefinition &device_def, std::uintptr_t index, px4::ReceiverManager &receiver_manager);
~PxMltDevice();
// cannot copy
PxMltDevice(const PxMltDevice &) = delete;
PxMltDevice& operator=(const PxMltDevice &) = delete;
// cannot move
PxMltDevice(PxMltDevice &&) = delete;
PxMltDevice& operator=(PxMltDevice &&) = delete;
int Init() override;
void Term() override;
void SetAvailability(bool available) override;
px4::ReceiverBase* GetReceiver(int id) const override;
private:
struct StreamContext final {
std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf[5];
std::uint8_t remain_buf[PXMLT_DEVICE_TS_SYNC_SIZE];
std::size_t remain_len;
};
class PxMltReceiver final : public px4::ReceiverBase {
public:
PxMltReceiver() = delete;
PxMltReceiver(PxMltDevice &parent, std::uintptr_t index);
~PxMltReceiver();
// cannot copy
PxMltReceiver(const PxMltReceiver &) = delete;
PxMltReceiver& operator=(const PxMltReceiver &) = delete;
// cannot move
PxMltReceiver(PxMltReceiver &&) = delete;
PxMltReceiver& operator=(PxMltReceiver &&) = delete;
int Open() override;
void Close() override;
int Tune() override;
int CheckLock(bool &locked) override;
int SetLnbVoltage(std::int32_t voltage) override;
int SetCapture(bool capture) override;
int ReadStat(px4::command::StatType type, std::int32_t &value) override;
private:
static const struct PxMltReceiverCnTableIsdbS final {
uint16_t val;
uint32_t cnr;
} isdbs_cn_table_[];
PxMltDevice &parent_;
std::uintptr_t index_;
std::mutex lock_;
std::atomic_bool open_;
std::condition_variable close_cond_;
bool lnb_power_;
std::mutex *tuner_lock_;
cxd2856er_demod cxd2856er_;
cxd2858er_tuner cxd2858er_;
px4::SystemType current_system_;
bool streaming_;
};
const i2c_comm_master& GetI2cMaster(int bus) const;
int SetBackendPower(bool state);
int SetLnbVoltage(std::int32_t voltage);
int StartCapture();
int StopCapture();
static void StreamProcess(std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf[], std::uint8_t **buf, std::size_t &len);
static int StreamHandler(void *context, void *buf, std::uint32_t len);
static const struct PxMltDeviceParam final {
std::uint8_t i2c_addr;
std::uint8_t i2c_bus;
std::uint8_t port_number;
} params_[][5];
PxMltDeviceModel model_;
PxMltDeviceConfig config_;
std::recursive_mutex lock_;
std::atomic_bool available_;
std::atomic_bool init_;
unsigned int open_count_;
unsigned int lnb_power_count_;
unsigned int streaming_count_;
std::mutex tuner_lock_[2];
int receiver_num_;
std::unique_ptr<PxMltReceiver> receivers_[5];
it930x_bridge it930x_;
StreamContext stream_ctx_;
};
} // namespace px4

View File

@@ -0,0 +1,182 @@
// receiver_base.cpp
#include "receiver_base.hpp"
namespace px4 {
ReceiverBase::ReceiverBase()
{
memset(&params_, 0, sizeof(params_));
stream_buf_.reset(new StreamBuffer());
}
ReceiverBase::~ReceiverBase()
{
}
bool ReceiverBase::GetParameters(px4::command::ParameterSet &param_set) noexcept
{
param_set.system = params_.system;
param_set.freq = params_.freq;
for (std::uint32_t i = 0; i < param_set.num; i++) {
switch (param_set.params[i].type) {
case px4::command::ParameterType::BANDWIDTH:
param_set.params[i].value = params_.bandwidth;
break;
case px4::command::ParameterType::STREAM_ID:
param_set.params[i].value = params_.stream_id;
break;
default:
// unknown parameter type
return false;
}
}
return true;
}
bool ReceiverBase::SetParameters(const px4::command::ParameterSet &param_set) noexcept
{
params_.system = param_set.system;
params_.freq = param_set.freq;
for (std::uint32_t i = 0; i < param_set.num; i++) {
switch (param_set.params[i].type) {
case px4::command::ParameterType::BANDWIDTH:
params_.bandwidth = param_set.params[i].value;
break;
case px4::command::ParameterType::STREAM_ID:
params_.stream_id = param_set.params[i].value;
break;
default:
// unknown parameter type
return false;
}
}
return true;
}
void ReceiverBase::ClearParameters() noexcept
{
memset(&params_, 0, sizeof(params_));
}
bool ReceiverBase::ReadStats(px4::command::StatSet &stat_set)
{
for (std::uint32_t i = 0; i < stat_set.num; i++) {
if (ReadStat(stat_set.data[i].type, stat_set.data[i].value))
return false;
}
return true;
}
ReceiverBase::StreamBuffer::StreamBuffer()
: write_size_(0),
threshold_size_(0)
{
}
ReceiverBase::StreamBuffer::~StreamBuffer()
{
}
void ReceiverBase::StreamBuffer::SetThresholdSize(std::size_t size) noexcept
{
threshold_size_ = size;
}
bool ReceiverBase::StreamBuffer::Alloc(std::size_t size)
{
return ringbuf_.Alloc(size);
}
void ReceiverBase::StreamBuffer::Start() noexcept
{
stop_ = false;
write_size_ = 0;
ringbuf_.Start();
return;
}
void ReceiverBase::StreamBuffer::Stop() noexcept
{
ringbuf_.Stop();
stop_ = true;
cond_.notify_all();
return;
}
void ReceiverBase::StreamBuffer::StopRequest() noexcept
{
stop_ = true;
cond_.notify_all();
return;
}
bool ReceiverBase::StreamBuffer::Write(const void *buf, std::size_t &size) noexcept
{
bool ret;
ret = ringbuf_.Write(buf, size);
write_size_ += size;
return ret;
}
void ReceiverBase::StreamBuffer::NotifyWrite() noexcept
{
if (write_size_ >= threshold_size_) {
cond_.notify_all();
write_size_ -= threshold_size_;
}
return;
}
void ReceiverBase::StreamBuffer::HandleRead(std::size_t buf_size, std::function<bool(const void *buf, std::size_t size)> handler)
{
stop_ = false;
std::unique_ptr<std::uint8_t[]> buf(new std::uint8_t[buf_size]);
std::uint8_t *p = buf.get();
std::unique_lock<std::mutex> lock(mtx_);
while (!ringbuf_.IsActive() && !stop_)
cond_.wait(lock);
while (true) {
while (!ringbuf_.GetReadableSize() && !stop_)
cond_.wait(lock);
if (stop_)
break;
std::size_t size = buf_size;
if (!ringbuf_.Read(p, size))
break;
if (!size)
continue;
if (!handler(p, size))
break;
}
return;
}
} // namespace px4

View File

@@ -0,0 +1,86 @@
// receiver_base.hpp
#pragma once
#include <cstdint>
#include <cstddef>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <stdexcept>
#include "type.hpp"
#include "command.hpp"
#include "ringbuffer.hpp"
namespace px4 {
class ReceiverBase {
public:
struct Parameters {
px4::SystemType system;
std::uint32_t freq;
std::uint32_t bandwidth;
std::uint32_t stream_id;
};
class StreamBuffer final {
public:
StreamBuffer();
~StreamBuffer();
void SetThresholdSize(std::size_t size) noexcept;
bool Alloc(std::size_t size);
void Start() noexcept;
void Stop() noexcept;
void StopRequest() noexcept;
bool Write(const void *buf, std::size_t &size) noexcept;
void NotifyWrite() noexcept;
void HandleRead(std::size_t buf_size, std::function<bool(const void *buf, std::size_t size)> handler);
private:
std::mutex mtx_;
px4::RingBuffer ringbuf_;
std::atomic_bool stop_;
std::condition_variable cond_;
std::size_t write_size_;
std::size_t threshold_size_;
};
ReceiverBase();
virtual ~ReceiverBase();
// cannot copy
ReceiverBase(const ReceiverBase &) = delete;
ReceiverBase& operator=(const ReceiverBase &) = delete;
// cannot move
ReceiverBase(ReceiverBase &&) = delete;
ReceiverBase& operator=(ReceiverBase &&) = delete;
bool GetParameters(px4::command::ParameterSet &param_set) noexcept;
bool SetParameters(const px4::command::ParameterSet &param_set) noexcept;
void ClearParameters() noexcept;
bool ReadStats(px4::command::StatSet &stat_set);
std::shared_ptr<StreamBuffer> GetStreamBuffer() noexcept { return stream_buf_; }
virtual int Open() = 0;
virtual void Close() = 0;
virtual int Tune() = 0;
virtual int CheckLock(bool &locked) = 0;
virtual int SetLnbVoltage(std::int32_t voltage) = 0;
virtual int SetCapture(bool capture) = 0;
virtual int ReadStat(px4::command::StatType type, std::int32_t &value) = 0;
protected:
Parameters params_;
std::shared_ptr<StreamBuffer> stream_buf_;
};
class ReceiverError : public std::runtime_error {
public:
explicit ReceiverError(const std::string &what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,133 @@
// receiver_manager.cpp
#include "receiver_manager.hpp"
#include <random>
namespace px4 {
bool ReceiverManager::Register(px4::command::ReceiverInfo &info, px4::ReceiverBase *receiver)
{
std::lock_guard<std::shared_mutex> lock(mtx_);
if (data_.count(receiver))
return false;
data_.emplace(receiver, ReceiverData{ info, false });
return true;
}
bool ReceiverManager::Unregister(px4::ReceiverBase *receiver)
{
std::lock_guard<std::shared_mutex> lock(mtx_);
if (!data_.count(receiver))
return false;
data_.erase(receiver);
return true;
}
static GUID empty_guid = { 0 };
px4::ReceiverBase* ReceiverManager::Search(px4::command::ReceiverInfo &key, px4::command::ReceiverInfo &info)
{
std::shared_lock<std::shared_mutex> lock(mtx_);
for (auto it = data_.cbegin(); it != data_.cend(); ++it) {
const px4::command::ReceiverInfo& k = it->second.info;
if (k.data_id)
continue;
if (key.device_name[0] && wcscmp(key.device_name, k.device_name))
continue;
if (memcmp(&key.device_guid, &empty_guid, sizeof(key.device_guid) && memcmp(&key.device_guid, &k.device_guid, sizeof(key.device_guid))))
continue;
if (key.receiver_name[0] && wcscmp(key.receiver_name, k.receiver_name))
continue;
if (memcmp(&key.receiver_guid, &empty_guid, sizeof(key.receiver_guid) && memcmp(&key.receiver_guid, &k.receiver_guid, sizeof(key.receiver_guid))))
continue;
if ((key.systems & k.systems) != key.systems)
continue;
if ((key.index >= 0) && (key.index != k.index))
continue;
info = k;
return it->first;
}
return nullptr;
}
px4::ReceiverBase* ReceiverManager::SearchByDataId(std::uint32_t data_id)
{
std::shared_lock<std::shared_mutex> lock(mtx_);
for (auto it = data_.begin(); it != data_.end(); ++it) {
if (it->second.info.data_id != data_id || !it->second.valid_data_id)
continue;
it->second.valid_data_id = false;
return it->first;
}
return nullptr;
}
bool ReceiverManager::GenerateDataId(px4::ReceiverBase *receiver, std::uint32_t &data_id)
{
std::lock_guard<std::shared_mutex> lock(mtx_);
if (!data_.count(receiver))
return false;
auto& v = data_.at(receiver);
if (v.info.data_id)
return false;
while (true) {
std::uint32_t tmp = std::random_device()();
if (!tmp)
continue;
auto it = data_.cbegin();
for (; it != data_.cend(); ++it) {
if (it->second.info.data_id == tmp)
break;
}
if (it == data_.cend()) {
v.info.data_id = data_id = tmp;
v.valid_data_id = true;
break;
}
}
return true;
}
void ReceiverManager::ClearDataId(px4::ReceiverBase *receiver)
{
std::lock_guard<std::shared_mutex> lock(mtx_);
if (!data_.count(receiver))
return;
auto& data = data_.at(receiver);
data.info.data_id = 0;
data.valid_data_id = false;
return;
}
} // namespace px4

View File

@@ -0,0 +1,43 @@
// receiver_manager.hpp
#pragma once
#include <shared_mutex>
#include <unordered_map>
#include "command.hpp"
#include "receiver_base.hpp"
namespace px4 {
class ReceiverManager final {
public:
ReceiverManager() {};
~ReceiverManager() {};
// cannot copy
ReceiverManager(const ReceiverManager &) = delete;
ReceiverManager& operator=(const ReceiverManager &) = delete;
// cannot move
ReceiverManager(ReceiverManager &&) = delete;
ReceiverManager& operator=(ReceiverManager &&) = delete;
bool Register(px4::command::ReceiverInfo &info, px4::ReceiverBase *receiver);
bool Unregister(px4::ReceiverBase *receiver);
px4::ReceiverBase* Search(px4::command::ReceiverInfo &key, px4::command::ReceiverInfo &info);
px4::ReceiverBase* SearchByDataId(std::uint32_t data_id);
bool GenerateDataId(px4::ReceiverBase *receiver, std::uint32_t &data_id);
void ClearDataId(px4::ReceiverBase *receiver);
private:
struct ReceiverData {
px4::command::ReceiverInfo info;
bool valid_data_id;
};
std::shared_mutex mtx_;
std::unordered_map<px4::ReceiverBase*, ReceiverData> data_;
};
} // namespace px4

View File

@@ -0,0 +1,30 @@
// resource.h
#pragma once
#include <windows.h>
#define VER_FILE 0,4,0,0
#define VER_FILE_STR "0.4.0"
#define VER_PRODUCT 0,4,0,0
#define VER_PRODUCT_STR "0.4.0"
#define VER_COMMENTS_STR ""
#define VER_COMPANYNAME_STR "nns779"
#define VER_FILEDESCRIPTION_STR "PX4 Device Driver (WinUSB)"
#define VER_INTERNALNAME_STR "DriverHost_PX4.exe"
#define VER_LEGALCOPYRIGHT_STR ""
#define VER_LEGALTRADEMARKS_STR ""
#define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR
#define VER_PRIVATEBUILD_STR ""
#define VER_PRODUCTNAME_STR "DriverHost_PX4"
#define VER_SPECIALBUILD_STR ""
#if defined(_DEBUG)
#define VER_FLAGS VS_FF_PRERELEASE | VS_FF_DEBUG
#elif defined(_DEBUG_MSG)
#define VER_FLAGS VS_FF_PRERELEASE
#else
#define VER_FLAGS 0
#endif

View File

@@ -0,0 +1,143 @@
// ringbuffer.cpp
#include "ringbuffer.hpp"
#include <cstring>
#include <windows.h>
namespace px4 {
RingBuffer::RingBuffer(std::size_t size)
: state_(0),
buf_(nullptr),
actual_size_(0),
head_(0),
tail_(0)
{
Alloc(size);
}
RingBuffer::~RingBuffer()
{
Stop();
if (buf_)
VirtualFree(buf_, 0, MEM_RELEASE);
}
bool RingBuffer::Alloc(std::size_t size)
{
if (state_)
return false;
if (buf_ && buf_size_ != size) {
VirtualFree(buf_, 0, MEM_RELEASE);
buf_ = nullptr;
buf_size_ = 0;
}
if (!buf_ && size) {
buf_ = reinterpret_cast<std::uint8_t*>(VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
if (!buf_)
return false;
buf_size_ = size;
}
Reset();
return true;
}
void RingBuffer::Reset() noexcept
{
actual_size_ = 0;
head_ = 0;
tail_ = 0;
}
void RingBuffer::Start() noexcept
{
int expected = 0;
state_.compare_exchange_strong(expected, 1);
}
void RingBuffer::Stop() noexcept
{
state_ = 0;
}
bool RingBuffer::Read(void *buf, std::size_t &size) noexcept
{
#if 0
int expected_state = 1;
state_.compare_exchange_strong(expected_state, 2);
#endif
std::size_t actual_size = actual_size_;
std::intptr_t head = head_;
std::size_t buf_size = buf_size_;
std::size_t read_size = (size <= actual_size) ? size : actual_size;
if (read_size) {
std::size_t tmp = (head + read_size <= buf_size) ? read_size : (buf_size - head);
memcpy(buf, buf_ + head, tmp);
if (tmp < read_size) {
memcpy(reinterpret_cast<std::uint8_t *>(buf) + tmp, buf_, read_size - tmp);
head = read_size - tmp;
} else {
head = (head + read_size == buf_size) ? 0 : (head + read_size);
}
head_ = head;
actual_size_ -= read_size;
}
size = read_size;
return true;
}
bool RingBuffer::Write(const void *buf, std::size_t &size) noexcept
{
#if 0
if (state_ != 2)
return false;
#else
if (!state_)
return false;
#endif
std::size_t actual_size = actual_size_;
std::intptr_t tail = tail_;
std::size_t buf_size = buf_size_;
std::size_t write_size = (actual_size + size <= buf_size) ? size : (buf_size - actual_size);
if (write_size) {
std::size_t tmp = (tail + write_size <= buf_size) ? write_size : (buf_size - tail);
std::memcpy(buf_ + tail, buf, tmp);
if (tmp < write_size) {
std::memcpy(buf_, reinterpret_cast<const std::uint8_t *>(buf) + tmp, write_size - tmp);
tail = write_size - tmp;
} else {
tail = (tail + write_size == buf_size) ? 0 : (tail + write_size);
}
tail_ = tail;
actual_size_ += write_size;
}
bool ret = (size == write_size);
size = write_size;
return ret;
}
} // namespace px4

View File

@@ -0,0 +1,36 @@
// ringbuffer.hpp
#pragma once
#include <cstdint>
#include <atomic>
#include <memory>
namespace px4 {
class RingBuffer final {
public:
explicit RingBuffer() : RingBuffer(0) {}
explicit RingBuffer(std::size_t size);
~RingBuffer();
bool Alloc(std::size_t size);
void Reset() noexcept;
void Start() noexcept;
void Stop() noexcept;
bool IsActive() noexcept { return (state_.load()); }
bool Read(void *buf, std::size_t &size) noexcept;
bool Write(const void *buf, std::size_t &size) noexcept;
std::size_t GetReadableSize() const noexcept { return actual_size_; }
std::size_t GetWritableSize() const noexcept { return buf_size_ - actual_size_; }
private:
std::atomic_int state_;
std::uint8_t *buf_;
std::size_t buf_size_;
std::atomic_size_t actual_size_;
std::atomic_intptr_t head_; // read
std::atomic_intptr_t tail_; // write
};
} // namespace px4

View File

@@ -0,0 +1,204 @@
// server_base.cpp
#include "server_base.hpp"
namespace px4 {
ServerBase::ServerBase(const std::wstring &pipe_name, px4::ReceiverManager &receiver_manager) noexcept
: pipe_name_(pipe_name),
receiver_manager_(receiver_manager),
mtx_(),
quit_event_(nullptr)
{
pipe_config_ = { 0 };
}
ServerBase::~ServerBase()
{
Stop();
}
bool ServerBase::Start() noexcept
{
if (th_) {
error_.assign(EINVAL, std::generic_category());
return false;
}
if (!quit_event_) {
quit_event_ = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!quit_event_) {
error_.assign(GetLastError(), std::system_category());
return false;
}
}
HANDLE ready_event;
ready_event = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!ready_event) {
CloseHandle(quit_event_);
quit_event_ = nullptr;
error_.assign(GetLastError(), std::system_category());
return false;
}
try {
th_.reset(new std::thread(&px4::ServerBase::Worker, this, ready_event));
} catch (const std::system_error &e) {
CloseHandle(ready_event);
CloseHandle(quit_event_);
quit_event_ = nullptr;
error_.assign(e.code().value(), e.code().category());
return false;
}
WaitForSingleObject(ready_event, INFINITE);
CloseHandle(ready_event);
return true;
}
bool ServerBase::Stop() noexcept
{
if (!th_) {
error_.assign(EINVAL, std::generic_category());
return false;
}
SetEvent(quit_event_);
try {
th_->join();
} catch (...) {}
th_.reset();
try {
std::unique_lock<std::mutex> lock(mtx_);
while (conns_.size())
cond_.wait(lock);
lock.unlock();
} catch (...) {}
CloseHandle(quit_event_);
quit_event_ = nullptr;
return true;
}
std::size_t ServerBase::GetActiveConnectionCount() const noexcept
{
std::lock_guard<std::mutex> lock(mtx_);
return conns_.size();
}
void ServerBase::RemoveConnection(Connection *conn, bool destruct) noexcept
{
bool empty = false;
try {
std::lock_guard<std::mutex> lock(mtx_);
for (auto it = conns_.begin(); it != conns_.end(); ++it) {
if (it->get() == conn) {
if (!destruct)
it->release();
conns_.erase(it);
break;
}
}
empty = !conns_.size();
} catch (...) {}
if (empty)
cond_.notify_all();
}
void ServerBase::Worker(HANDLE ready_event) noexcept
{
while (true) {
std::unique_ptr<px4::PipeServer> pipe(new px4::PipeServer());
if (!pipe->Accept(pipe_name_, pipe_config_, ready_event, quit_event_))
break;
ready_event = NULL;
try {
std::lock_guard<std::mutex> lock(mtx_);
auto &p = conns_.emplace_back(std::unique_ptr<Connection>());
p.reset(CreateConnection(pipe));
if (!p->Start())
break;
} catch (...) {
break;
}
}
return;
}
ServerBase::Connection::Connection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept
: parent_(parent),
conn_(std::move(pipe)),
config_(parent_.pipe_config_),
receiver_manager_(parent_.receiver_manager_),
quit_event_(parent.quit_event_),
th_()
{
}
ServerBase::Connection::~Connection()
{
Stop();
conn_.reset();
parent_.RemoveConnection(this, false);
}
bool ServerBase::Connection::Start() noexcept
{
if (th_) {
error_.assign(EINVAL, std::generic_category());
return false;
}
try {
th_.reset(new std::thread(&px4::ServerBase::Connection::Worker, this));
} catch (const std::system_error &e) {
error_.assign(static_cast<int>(e.code().value()), e.code().category());
return false;
}
return true;
}
bool ServerBase::Connection::Stop() noexcept
{
if (!th_) {
error_.assign(EINVAL, std::generic_category());
return false;
}
try {
if (std::this_thread::get_id() == th_->get_id())
th_->detach();
else
th_->join();
} catch (...) {}
th_.reset();
return true;
}
} // namespace px4

View File

@@ -0,0 +1,87 @@
// server_base.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <deque>
#include <mutex>
#include <thread>
#include <system_error>
#include <windows.h>
#include "pipe_server.hpp"
#include "receiver_manager.hpp"
namespace px4 {
class ServerBase {
public:
explicit ServerBase(const std::wstring &pipe_name, px4::ReceiverManager &receiver_manager) noexcept;
virtual ~ServerBase();
// cannot copy
ServerBase(const ServerBase &) = delete;
ServerBase& operator=(const ServerBase &) = delete;
// cannot move
ServerBase(ServerBase &&) = delete;
ServerBase& operator=(ServerBase &&) = delete;
bool Start() noexcept;
bool Stop() noexcept;
std::size_t GetActiveConnectionCount() const noexcept;
const std::error_condition& GetError() const noexcept { return error_; }
protected:
class Connection {
public:
explicit Connection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept;
virtual ~Connection();
// cannot copy
Connection(const Connection &) = delete;
Connection& operator=(const Connection &) = delete;
// cannot move
Connection(Connection &&) = delete;
Connection& operator=(Connection &&) = delete;
bool Start() noexcept;
bool Stop() noexcept;
const std::error_condition& GetError() const noexcept { return error_; }
protected:
virtual void Worker() noexcept {};
ServerBase &parent_;
std::unique_ptr<PipeServer> conn_;
px4::PipeServer::PipeServerConfig config_;
px4::ReceiverManager &receiver_manager_;
HANDLE quit_event_;
std::error_condition error_;
std::unique_ptr<std::thread> th_;
};
virtual Connection* CreateConnection(std::unique_ptr<px4::PipeServer> &pipe) = 0;
void RemoveConnection(Connection *conn, bool destruct) noexcept;
void Worker(HANDLE ready_event) noexcept;
const std::wstring pipe_name_;
px4::PipeServer::PipeServerConfig pipe_config_;
px4::ReceiverManager &receiver_manager_;
std::error_condition error_;
mutable std::mutex mtx_;
std::condition_variable cond_;
std::deque<std::unique_ptr<Connection>> conns_;
HANDLE quit_event_;
std::unique_ptr<std::thread> th_;
};
} // namespace px4

View File

@@ -0,0 +1,109 @@
// steram_server.cpp
#define msg_prefix "px4_winusb"
#include "stream_server.hpp"
#include <thread>
#include <windows.h>
#include "msg.h"
#include "command.hpp"
namespace px4 {
StreamServer::StreamServer(px4::ReceiverManager &receiver_manager) noexcept
: ServerBase(L"px4_data_pipe", receiver_manager)
{
pipe_config_.in_buffer_size = 512;
pipe_config_.out_buffer_size = 188 * 4096;
pipe_config_.stream_pipe = false;
pipe_config_.stream_read = false;
pipe_config_.default_timeout = 2000;
}
px4::ServerBase::Connection* StreamServer::CreateConnection(std::unique_ptr<px4::PipeServer> &pipe)
{
return new StreamConnection(*this, pipe);
}
StreamServer::StreamConnection::StreamConnection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept
: Connection(parent, pipe)
{
}
void StreamServer::StreamConnection::Worker() noexcept
{
std::size_t size = config_.in_buffer_size;
std::unique_ptr<std::uint8_t[]> buf(new std::uint8_t[size]);
px4::ReceiverBase *receiver = nullptr;
std::unique_ptr<std::thread> stream_th;
while (true) {
std::size_t read;
if (!conn_->Read(buf.get(), size, read, quit_event_))
break;
int ret = true;
px4::command::DataCmd *cmd = reinterpret_cast<px4::command::DataCmd *>(buf.get());
switch (cmd->cmd) {
case px4::command::DataCmdCode::SET_DATA_ID:
if (receiver)
break;
receiver = receiver_manager_.SearchByDataId(cmd->data_id);
if (!receiver) {
ret = false;
break;
}
try {
stream_th.reset(new std::thread(&px4::StreamServer::StreamConnection::StreamWorker, this, receiver->GetStreamBuffer()));
} catch (...) {
ret = false;
break;
}
break;
default:
ret = false;
break;
}
if (!ret)
break;
}
if (receiver && stream_th) {
receiver->GetStreamBuffer()->StopRequest();
stream_th->join();
stream_th.reset();
}
delete this;
}
void StreamServer::StreamConnection::StreamWorker(std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf) noexcept
{
msg_dbg("px4::StreamServer::StreamConnection::StreamWorker\n");
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
stream_buf->HandleRead(config_.out_buffer_size / 4,
[this](const void *buf, std::size_t size) {
return conn_->Write(buf, size, size, quit_event_);
}
);
msg_dbg("px4::StreamServer::StreamConnection::StreamWorker: exit\n");
return;
}
} // namespace px4

View File

@@ -0,0 +1,51 @@
// stream_server.hpp
#pragma once
#include <cstdint>
#include <memory>
#include <atomic>
#include "server_base.hpp"
#include "pipe_server.hpp"
#include "receiver_base.hpp"
#include "receiver_manager.hpp"
namespace px4 {
class StreamServer final : public px4::ServerBase {
public:
explicit StreamServer(px4::ReceiverManager &receiver_manager) noexcept;
~StreamServer() {}
// cannot copy
StreamServer(const StreamServer &) = delete;
StreamServer& operator=(const StreamServer &) = delete;
// cannot move
StreamServer(StreamServer &&) = delete;
StreamServer& operator=(StreamServer &&) = delete;
private:
class StreamConnection final : public px4::ServerBase::Connection {
public:
explicit StreamConnection(ServerBase &parent, std::unique_ptr<px4::PipeServer> &pipe) noexcept;
~StreamConnection() {}
// cannot copy
StreamConnection(const StreamConnection &) = delete;
StreamConnection& operator=(const StreamConnection &) = delete;
// cannot move
StreamConnection(StreamConnection &&) = delete;
StreamConnection& operator=(StreamConnection &&) = delete;
private:
void Worker() noexcept override;
void StreamWorker(std::shared_ptr<px4::ReceiverBase::StreamBuffer> stream_buf) noexcept;
};
px4::ServerBase::Connection* CreateConnection(std::unique_ptr<px4::PipeServer> &pipe) override;
};
} // namespace px4

View File

@@ -0,0 +1,12 @@
// winusb_compat.h
#pragma once
#include <windows.h>
#include <winusb.h>
struct usb_device {
HANDLE dev;
WINUSB_INTERFACE_HANDLE winusb;
USB_DEVICE_DESCRIPTOR descriptor;
};

View File

@@ -0,0 +1,146 @@
// command.hpp
#pragma once
#include <cstdint>
#include <cwchar>
#include <guiddef.h>
#include "type.hpp"
namespace px4 {
#pragma pack(push, 8)
namespace command {
static const std::uint32_t VERSION = 0x00040000U;
enum class CtrlCmdCode : std::uint32_t {
UNDEFINED = 0,
GET_VERSION = 1,
OPEN = 8,
CLOSE,
GET_INFO,
SET_CAPTURE,
GET_PARAMS = 16,
SET_PARAMS,
CLEAR_PARAMS,
TUNE,
SET_LNB_VOLTAGE = 24,
READ_STATS = 32,
};
enum class CtrlStatusCode : std::uint32_t {
NONE = 0, // request
SUCCEEDED, // response
FAILED, // response
};
struct CtrlCmdHeader {
CtrlCmdCode cmd;
CtrlStatusCode status;
};
struct CtrlVersionCmd : CtrlCmdHeader {
std::uint32_t driver_version;
std::uint32_t cmd_version;
};
struct ReceiverInfo {
wchar_t device_name[96];
GUID device_guid; // not 'DeviceInterfaceGUID'
wchar_t receiver_name[96];
GUID receiver_guid;
px4::SystemType systems;
std::int32_t index;
std::uint32_t data_id;
};
struct CtrlOpenCmd : CtrlCmdHeader {
ReceiverInfo receiver_info;
};
struct CtrlCloseCmd : CtrlCmdHeader {
// header only
};
struct CtrlReceiverInfoCmd : CtrlCmdHeader {
ReceiverInfo receiver_info;
};
struct CtrlCaptureCmd : CtrlCmdHeader {
bool capture;
};
enum class ParameterType : std::uint32_t {
UNDEFINED = 0,
BANDWIDTH = 1,
STREAM_ID = 16,
};
struct Parameter {
ParameterType type;
std::uint32_t value;
};
struct ParameterSet {
px4::SystemType system;
std::uint32_t freq;
std::uint32_t num;
Parameter params[1];
};
struct CtrlParamsCmd : CtrlCmdHeader {
ParameterSet param_set;
};
struct CtrlClearParamsCmd : CtrlCmdHeader {
// header only
};
struct CtrlTuneCmd : CtrlCmdHeader {
// header only
};
struct CtrlLnbVoltageCmd : CtrlCmdHeader {
std::int32_t voltage;
};
enum class StatType : std::uint32_t {
UNDEFINED = 0,
SIGNAL_STRENGTH,
CNR,
};
struct Stat {
StatType type;
std::int32_t value;
};
struct StatSet {
std::uint32_t num;
Stat data[1];
};
struct CtrlStatsCmd : CtrlCmdHeader {
StatSet stat_set;
};
enum class DataCmdCode : std::uint32_t {
UNDEFINED = 0,
SET_DATA_ID,
};
struct DataCmd {
DataCmdCode cmd;
union {
std::uint32_t data_id;
};
};
} // namespace command
#pragma pack(pop)
} // namespace px4

View File

@@ -0,0 +1,105 @@
// config.cpp
#include "config.hpp"
#include <memory>
#include <iostream>
#include <windows.h>
namespace px4 {
bool Config::Load(const std::wstring &path, const std::wstring &section) noexcept
{
std::unique_ptr<WCHAR[]> data(new WCHAR[16384]);
DWORD len;
values_.clear();
len = GetPrivateProfileSectionW(section.c_str(), data.get(), 16384, path.c_str());
if (!len)
return false;
WCHAR *p = data.get();
while (*p != L'\0') {
wchar_t *split, *key, *value;
std::size_t value_len;
split = std::wcschr(p, L'=');
if (split == nullptr)
continue;
*split = L'\0';
key = p;
value = split + 1;
value_len = std::wcslen(value);
if ((value[0] == L'\"' && value[value_len - 1] == L'\"') ||
(value[0] == L'\'' && value[value_len - 1] == L'\'')) {
value[value_len - 1] = L'\0';
value++;
value_len--;
}
values_.emplace(key, value);
p = value + value_len + 1;
}
return true;
}
bool Config::Exists(const std::wstring &key) const noexcept
{
return !!values_.count(key);
}
const std::wstring& Config::Get(const std::wstring &key) const
{
return values_.at(key);
}
const std::wstring Config::Get(const std::wstring &key, const std::wstring &default_value) const
{
try {
return Get(key);
} catch (const std::out_of_range&) {
return default_value;
}
}
bool ConfigSet::Load(const std::wstring &path) noexcept
{
std::unique_ptr<WCHAR[]> sct(new WCHAR[8192]);
DWORD len;
configs_.clear();
len = GetPrivateProfileSectionNamesW(sct.get(), 8192, path.c_str());
if (!len)
return false;
for (WCHAR *p = sct.get(); *p != L'\0'; p += std::wcslen(p) + 1) {
auto v = configs_.emplace(p, Config());
if (!v.first->second.Load(path, p)) {
configs_.clear();
return false;
}
}
return true;
}
bool ConfigSet::Exists(const std::wstring &sct) const noexcept
{
return !!configs_.count(sct);
}
const px4::Config& ConfigSet::Get(const std::wstring &sct) const
{
return configs_.at(sct);
}
} // namespace px4

View File

@@ -0,0 +1,38 @@
// config.hpp
#pragma once
#include <string>
#include <unordered_map>
#include <stdexcept>
namespace px4 {
class Config final {
public:
Config() noexcept {}
~Config() {}
bool Load(const std::wstring &path, const std::wstring &section) noexcept;
bool Exists(const std::wstring &key) const noexcept;
const std::wstring& Get(const std::wstring &key) const;
const std::wstring Get(const std::wstring &key, const std::wstring &default_value) const;
private:
std::unordered_map<std::wstring, std::wstring> values_;
};
class ConfigSet final {
public:
ConfigSet() noexcept {}
~ConfigSet() {}
bool Load(const std::wstring &path) noexcept;
bool Exists(const std::wstring &sct) const noexcept;
const px4::Config& Get(const std::wstring &sct) const;
private:
std::unordered_map<std::wstring, Config> configs_;
};
} // namespace px4

64
winusb/src/common/msg.c Normal file
View File

@@ -0,0 +1,64 @@
// msg.c
#include "msg.h"
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
static enum msg_mode mode = MSG_MODE_NONE;
static HANDLE file_handle = INVALID_HANDLE_VALUE;
void msg_set_mode(enum msg_mode new_mode)
{
mode = new_mode;
}
bool msg_open_file(const wchar_t *path)
{
if (file_handle != INVALID_HANDLE_VALUE)
CloseHandle(file_handle);
file_handle = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
return (file_handle != INVALID_HANDLE_VALUE) ? true : false;
}
void msg_close_file()
{
if (file_handle != INVALID_HANDLE_VALUE) {
CloseHandle(file_handle);
file_handle = INVALID_HANDLE_VALUE;
}
return;
}
int msg_printf(const char *format, ...)
{
va_list args;
char buf[1024];
int c;
if (mode == MSG_MODE_NONE)
return 0;
va_start(args, format);
c = vsprintf_s(buf, 1024, format, args);
va_end(args);
if (mode & MSG_MODE_CONSOLE)
printf("%s", buf);
if (mode & MSG_MODE_DEBUGGER)
OutputDebugStringA(buf);
if ((mode & MSG_MODE_LOG_FILE) && (file_handle != INVALID_HANDLE_VALUE)) {
DWORD wb;
WriteFile(file_handle, buf, c, &wb, NULL);
}
return c;
}

37
winusb/src/common/msg.h Normal file
View File

@@ -0,0 +1,37 @@
// msg.h
#pragma once
#include <stdbool.h>
#include <wctype.h>
enum msg_mode {
MSG_MODE_NONE = 0x0000,
MSG_MODE_CONSOLE = 0x0001,
MSG_MODE_DEBUGGER = 0x0002,
MSG_MODE_LOG_FILE = 0x0004
};
#ifdef __cplusplus
extern "C" {
#endif
void msg_set_mode(enum msg_mode new_mode);
bool msg_open_file(const wchar_t *path);
void msg_close_file();
int msg_printf(const char *format, ...);
#ifdef __cplusplus
}
#endif
#ifndef msg_prefix
#define msg_prefix ""
#endif
#define msg_err(format, ...) msg_printf("[ERR] " msg_prefix ": " format, ##__VA_ARGS__)
#define msg_warn(format, ...) msg_printf("[WARN] " msg_prefix ": " format, ##__VA_ARGS__)
#define msg_info(format, ...) msg_printf("[INFO] " msg_prefix ": " format, ##__VA_ARGS__)
#if defined(_DEBUG) || defined(_DEBUG_MSG)
#define msg_dbg(format, ...) msg_printf("[DBG] " msg_prefix ": " format, ##__VA_ARGS__)
#else
#define msg_dbg(format, ...)
#endif

160
winusb/src/common/pipe.cpp Normal file
View File

@@ -0,0 +1,160 @@
// pipe.cpp
#include "pipe.hpp"
namespace px4 {
Pipe::Pipe(HANDLE handle) noexcept
: handle_(handle),
ol_event_()
{
}
Pipe::~Pipe()
{
if (!IsConnected())
return;
CloseHandle(handle_);
handle_ = INVALID_HANDLE_VALUE;
for (int i = 0; i < 2; i++) {
if (ol_event_[i]) {
CloseHandle(ol_event_[i]);
ol_event_[i] = nullptr;
}
}
}
bool Pipe::Read(void *buf, std::size_t size, std::size_t &return_size) noexcept
{
return Read(buf, size, return_size, nullptr);
}
bool Pipe::Read(void *buf, std::size_t size, std::size_t &return_size, HANDLE cancel_event) noexcept
{
if (!ol_event_[0]) {
ol_event_[0] = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!ol_event_[0]) {
error_.assign(GetLastError(), std::system_category());
return false;
}
}
DWORD read = 0, err;
OVERLAPPED ol = { 0 };
ResetEvent(ol_event_[0]);
ol.hEvent = ol_event_[0];
if (ReadFile(handle_, buf, static_cast<DWORD>(size), &read, &ol)) {
return_size = read;
return true;
}
err = GetLastError();
if (err != ERROR_IO_PENDING) {
error_.assign(err, std::system_category());
return false;
}
HANDLE events[2] = { ol_event_[0], cancel_event };
DWORD res;
res = WaitForMultipleObjects((cancel_event) ? 2 : 1, events, FALSE, INFINITE);
if (res == WAIT_FAILED) {
error_.assign(GetLastError(), std::system_category());
return false;
}
if (res != WAIT_OBJECT_0) {
error_.assign(ECANCELED, std::generic_category());
return false;
}
if (!GetOverlappedResult(handle_, &ol, &read, TRUE)) {
error_.assign(GetLastError(), std::system_category());
return false;
}
return_size = read;
return true;
}
bool Pipe::Write(const void *buf, std::size_t size, std::size_t &return_size) noexcept
{
return Write(buf, size, return_size, nullptr);
}
bool Pipe::Write(const void *buf, std::size_t size, std::size_t &return_size, HANDLE cancel_event) noexcept
{
if (!ol_event_[1]) {
ol_event_[1] = CreateEventW(nullptr, TRUE, FALSE, nullptr);
if (!ol_event_[1]) {
error_.assign(GetLastError(), std::system_category());
return false;
}
}
DWORD written = 0, err;
OVERLAPPED ol = { 0 };
ResetEvent(ol_event_[1]);
ol.hEvent = ol_event_[1];
if (WriteFile(handle_, buf, static_cast<DWORD>(size), &written, &ol)) {
return_size = written;
return true;
}
err = GetLastError();
if (err != ERROR_IO_PENDING) {
error_.assign(err, std::system_category());
return false;
}
HANDLE events[2] = { ol_event_[1], cancel_event };
DWORD res;
res = WaitForMultipleObjects((cancel_event) ? 2 : 1, events, FALSE, INFINITE);
if (res == WAIT_FAILED) {
error_.assign(GetLastError(), std::system_category());
return false;
}
if (res != WAIT_OBJECT_0) {
error_.assign(ECANCELED, std::generic_category());
return false;
}
if (!GetOverlappedResult(handle_, &ol, &written, TRUE)) {
error_.assign(GetLastError(), std::system_category());
return false;
}
return_size = written;
return true;
}
bool Pipe::Call(void *buf, std::size_t size) noexcept
{
return Call(buf, size, buf, size);
}
bool Pipe::Call(const void *buf_in, std::size_t size_in, void *buf_out, std::size_t size_out) noexcept
{
std::size_t ret_size;
if (!Write(buf_in, size_in, ret_size) || ret_size != size_in)
return false;
if (!Read(buf_out, size_out, ret_size) || ret_size != size_out)
return false;
return true;
}
} // namespace px4

View File

@@ -0,0 +1,51 @@
// pipe.hpp
#pragma once
#include <string>
#include <stdexcept>
#include <system_error>
#include <windows.h>
namespace px4 {
class Pipe {
public:
explicit Pipe(HANDLE handle) noexcept; // for compatibility
virtual ~Pipe();
// cannot copy
Pipe(const Pipe &) = delete;
Pipe& operator=(const Pipe &) = delete;
// cannot move
Pipe(Pipe &&) = delete;
Pipe& operator=(Pipe &&) = delete;
bool Read(void *buf, std::size_t size, std::size_t &return_size) noexcept;
bool Read(void *buf, std::size_t size, std::size_t &return_size, HANDLE cancel_event) noexcept;
bool Write(const void *buf, std::size_t size, std::size_t &return_size) noexcept;
bool Write(const void *buf, std::size_t size, std::size_t &return_size, HANDLE cancel_event) noexcept;
bool Call(void *buf, std::size_t size) noexcept;
bool Call(const void *buf_in, std::size_t size_in, void *buf_out, std::size_t size_out) noexcept;
const std::error_condition& GetError() const noexcept { return error_; }
protected:
Pipe() noexcept : Pipe(nullptr) {}
bool IsConnected() const noexcept { return (handle_ && handle_ != INVALID_HANDLE_VALUE); }
void SetHandle(HANDLE handle) noexcept { handle_ = handle; }
std::error_condition error_;
HANDLE handle_;
HANDLE ol_event_[2]; // [0]: read, [1]: write
};
class PipeError : public std::runtime_error {
public:
explicit PipeError(const std::string& what_arg) : runtime_error(what_arg.c_str()) {};
};
} // namespace px4

View File

@@ -0,0 +1,63 @@
// type.hpp
#pragma once
#include <cstdint>
#include <functional>
#include <guiddef.h>
namespace px4 {
enum class SystemType : std::uint32_t {
UNSPECIFIED = 0x00,
ISDB_T = 0x10,
ISDB_S = 0x20,
};
constexpr SystemType operator&(SystemType left, SystemType right) noexcept
{
return static_cast<SystemType>(static_cast<std::uint32_t>(left) & static_cast<std::uint32_t>(right));
}
constexpr SystemType operator|(SystemType left, SystemType right) noexcept
{
return static_cast<SystemType>(static_cast<std::uint32_t>(left) | static_cast<std::uint32_t>(right));
}
constexpr SystemType& operator&=(SystemType& left, SystemType right) noexcept
{
left = static_cast<SystemType>(static_cast<std::uint32_t>(left) & static_cast<std::uint32_t>(right));
return left;
}
constexpr SystemType& operator|=(SystemType& left, SystemType right) noexcept
{
left = static_cast<SystemType>(static_cast<std::uint32_t>(left) | static_cast<std::uint32_t>(right));
return left;
}
} // namespace px4
static inline bool operator<(const GUID &left, const GUID &right) noexcept
{
return memcmp(&left, &right, sizeof(GUID)) < 0;
}
namespace std {
template<> struct hash<GUID> {
std::size_t operator()(const GUID &guid) const noexcept
{
std::hash<std::size_t> hash;
const std::size_t *p = reinterpret_cast<const std::size_t *>(&guid);
std::size_t val = 0;
for (int i = 0; i < (sizeof(guid) / sizeof(std::size_t)); i++)
val ^= hash(p[i]);
return val;
}
};
} // namespace std

182
winusb/src/common/util.cpp Normal file
View File

@@ -0,0 +1,182 @@
// util.cpp
#include "util.hpp"
#include <windows.h>
namespace px4 {
namespace util {
bool HexFromStr(const wchar_t c, std::uint8_t &v)
{
if (c >= L'0' && c <= L'9')
v = c - '0';
else if (c >= 'A' && c <= L'F')
v = c - 'A' + 0x0a;
else if (c >= 'a' && c <= L'f')
v = c - 'a' + 0x0a;
else
return false;
return true;
}
bool HexStrToUInt8(const wchar_t *str, std::uint8_t &v)
{
std::uint8_t t;
if (!HexFromStr(str[0], t))
return false;
v = t << 4;
if (!HexFromStr(str[1], t))
return false;
v |= t;
return true;
}
bool ShiftJisToUtf16(const char *sjis, std::wstring &utf16)
{
int required_size;
required_size = MultiByteToWideChar(932, MB_ERR_INVALID_CHARS, sjis, -1, nullptr, 0);
if (!required_size)
return false;
WCHAR *buf = new WCHAR[required_size];
if (!MultiByteToWideChar(932, MB_ERR_INVALID_CHARS, sjis, -1, buf, required_size))
return false;
utf16 = buf;
delete[] buf;
return true;
}
bool ParseGuidStr(const std::wstring &utf16, GUID &guid)
{
GUID tmp;
const wchar_t *str = utf16.c_str();
wchar_t *end;
if (std::wcslen(str) != 38 ||
str[0] != L'{' ||
str[9] != L'-' ||
str[14] != L'-' ||
str[19] != L'-' ||
str[24] != L'-' ||
str[37] != L'}')
return false;
tmp.Data1 = std::wcstoul(&str[1], &end, 16);
if (end != &str[9])
return false;
tmp.Data2 = static_cast<unsigned short>(std::wcstoul(&str[10], &end, 16));
if (end != &str[14])
return false;
tmp.Data3 = static_cast<unsigned short>(std::wcstoul(&str[15], &end, 16));
if (end != &str[19])
return false;
for (int i = 0, j = 0; i < 17; i += 2, j++) {
if (i == 4)
i++;
if (!HexStrToUInt8(&str[20 + i], tmp.Data4[j]))
return false;
}
guid = tmp;
return true;
}
bool ParseSystemStr(const std::wstring &str, px4::SystemType &systems)
{
const wchar_t *head, *tail, *p, *split;
systems = px4::SystemType::UNSPECIFIED;
head = p = str.c_str();
tail = head + std::wcslen(head);
while (p <= tail) {
p += std::wcsspn(p, L", \t");
split = p + std::wcscspn(p, L", \t");
if (split == p)
split = tail;
if (!std::wcsncmp(L"ISDB-T", p, 6))
systems |= px4::SystemType::ISDB_T;
else if (!std::wcsncmp(L"ISDB-S", p, 6))
systems |= px4::SystemType::ISDB_S;
else {
systems = px4::SystemType::UNSPECIFIED;
return false;
}
p = split + 1;
}
return true;
}
namespace path {
static std::wstring dir_path;
static std::wstring file_base;
bool Init(void *mod)
{
WCHAR path[MAX_PATH];
wchar_t *filename, *fileext;
if (!GetModuleFileNameW(static_cast<HMODULE>(mod), path, MAX_PATH - 4))
return false;
filename = std::wcsrchr(path, L'\\');
if (!filename)
filename = std::wcsrchr(path, L'/');
if (!filename)
filename = path;
else
filename++;
fileext = std::wcsrchr(filename, L'.');
if (fileext)
*fileext = L'\0';
else
fileext = filename + std::wcslen(filename);
file_base = std::wstring(path);
*filename = L'\0';
dir_path = std::wstring(path);
return true;
}
const std::wstring& GetDir() noexcept
{
return dir_path;
}
const std::wstring& GetFileBase() noexcept
{
return file_base;
}
} // namespace path
} // namespace util
} // namespace px4

View File

@@ -0,0 +1,46 @@
// util.hpp
#pragma once
#include <string>
#include <guiddef.h>
#include "type.hpp"
namespace px4 {
namespace util {
static std::uint32_t atoui(const char *str)
{
std::uint32_t value = 0;
for (; *str; str++) {
if (*str < '0' || *str > '9')
break;
value *= 10;
value += *str - '0';
}
return value;
}
bool HexFromStr(const wchar_t c, std::uint8_t &v);
bool HexStrToUInt8(const wchar_t *str, std::uint8_t &v);
bool ShiftJisToUtf16(const char *sjis, std::wstring &utf16);
bool ParseGuidStr(const std::wstring &utf16, GUID &guid);
bool ParseSystemStr(const std::wstring &str, px4::SystemType &systems);
namespace path {
bool Init(void *mod);
const std::wstring& GetDir() noexcept;
const std::wstring& GetFileBase() noexcept;
} // namespace path
} // namespace util
} // namespace px4

View File

@@ -0,0 +1,241 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|Win32">
<Configuration>Release-static</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release-static|x64">
<Configuration>Release-static</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{BDBD265F-5914-426F-89F7-16478BE1AFCC}</ProjectGuid>
<RootNamespace>fwtool</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(PlatformTarget)\$(Configuration)\</OutDir>
<IntDir>build\$(PlatformTarget)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-static|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\fwtool\crc32.c" />
<ClCompile Include="..\..\..\fwtool\fwtool.c" />
<ClCompile Include="..\..\..\fwtool\tsv.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\fwtool\crc32.h" />
<ClInclude Include="..\..\..\fwtool\tsv.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\fwtool\fwinfo.tsv" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="ソース ファイル">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="ヘッダー ファイル">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="リソース ファイル">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\fwtool\crc32.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\fwtool\fwtool.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
<ClCompile Include="..\..\..\fwtool\tsv.c">
<Filter>ソース ファイル</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\fwtool\crc32.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
<ClInclude Include="..\..\..\fwtool\tsv.h">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\fwtool\fwinfo.tsv" />
</ItemGroup>
</Project>