diff options
| author | Dave Wilson <[email protected]> | 2015-04-29 09:48:49 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-04-29 10:47:29 -0700 |
| commit | d40232638faaab19de557e70a3ee938da7a35295 (patch) | |
| tree | 14e61c973745949af186b7940e3a53d25322f5de /network/radio | |
| parent | 02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff) | |
samples update for //build
Diffstat (limited to 'network/radio')
35 files changed, 6722 insertions, 0 deletions
diff --git a/network/radio/HidSwitchDriverSample/HidSwitchDriverSample.sln b/network/radio/HidSwitchDriverSample/HidSwitchDriverSample.sln new file mode 100644 index 00000000..63278f58 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/HidSwitchDriverSample.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RadioSwitchHidUsbFx2", "RadioSwitchHidUsbFx2.vcxproj", "{299CE7FF-033A-4968-906D-5B8D00C1FE0C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Debug|Win32.ActiveCfg = Debug|Win32 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Debug|Win32.Build.0 = Debug|Win32 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Release|Win32.ActiveCfg = Release|Win32 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Release|Win32.Build.0 = Release|Win32 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Debug|x64.ActiveCfg = Debug|x64 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Debug|x64.Build.0 = Debug|x64 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Release|x64.ActiveCfg = Release|x64 + {299CE7FF-033A-4968-906D-5B8D00C1FE0C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/network/radio/HidSwitchDriverSample/READFIRST_InstructionsForDevelopingHIDDriver.htm b/network/radio/HidSwitchDriverSample/READFIRST_InstructionsForDevelopingHIDDriver.htm new file mode 100644 index 00000000..77351c56 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/READFIRST_InstructionsForDevelopingHIDDriver.htm @@ -0,0 +1,944 @@ +<html xmlns:v="urn:schemas-microsoft-com:vml" +xmlns:o="urn:schemas-microsoft-com:office:office" +xmlns:w="urn:schemas-microsoft-com:office:word" +xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" +xmlns="http://www.w3.org/TR/REC-html40"> + +<head> +<meta http-equiv=Content-Type content="text/html; charset=windows-1252"> +<meta name=ProgId content=Word.Document> +<meta name=Generator content="Microsoft Word 14"> +<meta name=Originator content="Microsoft Word 14"> +<link rel=File-List +href="READFIRST_InstructionsForDevelopingHIDDriver_files/filelist.xml"> +<title>HID USB FX2 Sample</title> +<!--[if gte mso 9]><xml> + <o:DocumentProperties> + <o:Author>MJ Bustamante</o:Author> + <o:Template>Normal</o:Template> + <o:LastAuthor>MJ Bustamante</o:LastAuthor> + <o:Revision>3</o:Revision> + <o:TotalTime>1415</o:TotalTime> + <o:LastPrinted>2011-12-08T19:23:00Z</o:LastPrinted> + <o:Created>2011-12-08T21:59:00Z</o:Created> + <o:LastSaved>2011-12-08T22:02:00Z</o:LastSaved> + <o:Pages>1</o:Pages> + <o:Words>211</o:Words> + <o:Characters>1206</o:Characters> + <o:Company>Microsoft Corporation</o:Company> + <o:Lines>10</o:Lines> + <o:Paragraphs>2</o:Paragraphs> + <o:CharactersWithSpaces>1415</o:CharactersWithSpaces> + <o:Version>14.00</o:Version> + </o:DocumentProperties> +</xml><![endif]--> +<link rel=themeData +href="READFIRST_InstructionsForDevelopingHIDDriver_files/themedata.thmx"> +<link rel=colorSchemeMapping +href="READFIRST_InstructionsForDevelopingHIDDriver_files/colorschememapping.xml"> +<!--[if gte mso 9]><xml> + <w:WordDocument> + <w:View>Print</w:View> + <w:SpellingState>Clean</w:SpellingState> + <w:GrammarState>Clean</w:GrammarState> + <w:TrackMoves>false</w:TrackMoves> + <w:TrackFormatting/> + <w:ValidateAgainstSchemas/> + <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> + <w:IgnoreMixedContent>false</w:IgnoreMixedContent> + <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> + <w:DoNotPromoteQF/> + <w:LidThemeOther>EN-US</w:LidThemeOther> + <w:LidThemeAsian>X-NONE</w:LidThemeAsian> + <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> + <w:Compatibility> + <w:BreakWrappedTables/> + <w:SplitPgBreakAndParaMark/> + </w:Compatibility> + <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> + <m:mathPr> + <m:mathFont m:val="Cambria Math"/> + <m:brkBin m:val="before"/> + <m:brkBinSub m:val="--"/> + <m:smallFrac m:val="off"/> + <m:dispDef/> + <m:lMargin m:val="0"/> + <m:rMargin m:val="0"/> + <m:defJc m:val="centerGroup"/> + <m:wrapIndent m:val="1440"/> + <m:intLim m:val="subSup"/> + <m:naryLim m:val="undOvr"/> + </m:mathPr></w:WordDocument> +</xml><![endif]--><!--[if gte mso 9]><xml> + <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" + DefSemiHidden="true" DefQFormat="false" DefPriority="99" + LatentStyleCount="267"> + <w:LsdException Locked="false" Priority="0" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Normal"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 3"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 4"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 5"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> + <w:LsdException Locked="false" Priority="39" Name="toc 1"/> + <w:LsdException Locked="false" Priority="39" Name="toc 2"/> + <w:LsdException Locked="false" Priority="39" Name="toc 3"/> + <w:LsdException Locked="false" Priority="39" Name="toc 4"/> + <w:LsdException Locked="false" Priority="39" Name="toc 5"/> + <w:LsdException Locked="false" Priority="39" Name="toc 6"/> + <w:LsdException Locked="false" Priority="39" Name="toc 7"/> + <w:LsdException Locked="false" Priority="39" Name="toc 8"/> + <w:LsdException Locked="false" Priority="39" Name="toc 9"/> + <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> + <w:LsdException Locked="false" Priority="10" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Title"/> + <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> + <w:LsdException Locked="false" Priority="11" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> + <w:LsdException Locked="false" Priority="22" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Strong"/> + <w:LsdException Locked="false" Priority="20" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/> + <w:LsdException Locked="false" Priority="59" SemiHidden="false" + UnhideWhenUsed="false" Name="Table Grid"/> + <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/> + <w:LsdException Locked="false" Priority="1" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 1"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 1"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 1"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/> + <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/> + <w:LsdException Locked="false" Priority="34" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/> + <w:LsdException Locked="false" Priority="29" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Quote"/> + <w:LsdException Locked="false" Priority="30" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 1"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 1"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 2"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 2"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 2"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 2"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 2"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 3"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 3"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 3"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 3"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 3"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 4"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 4"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 4"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 4"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 4"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 5"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 5"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 5"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 5"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 5"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 6"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 6"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 6"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 6"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 6"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/> + <w:LsdException Locked="false" Priority="19" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/> + <w:LsdException Locked="false" Priority="21" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/> + <w:LsdException Locked="false" Priority="31" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/> + <w:LsdException Locked="false" Priority="32" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/> + <w:LsdException Locked="false" Priority="33" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Book Title"/> + <w:LsdException Locked="false" Priority="37" Name="Bibliography"/> + <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/> + </w:LatentStyles> +</xml><![endif]--> +<style> +<!-- + /* Font Definitions */ + @font-face + {font-family:"Cambria Math"; + panose-1:2 4 5 3 5 4 6 3 2 4; + mso-font-charset:1; + mso-generic-font-family:roman; + mso-font-format:other; + mso-font-pitch:variable; + mso-font-signature:0 0 0 0 0 0;} +@font-face + {font-family:Verdana; + panose-1:2 11 6 4 3 5 4 4 2 4; + mso-font-charset:0; + mso-generic-font-family:swiss; + mso-font-pitch:variable; + mso-font-signature:-1593833729 1073750107 16 0 415 0;} + /* Style Definitions */ + p.MsoNormal, li.MsoNormal, div.MsoNormal + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-parent:""; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +h3 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 3 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:3; + font-size:13.5pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h4 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 4 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:4; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h5 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 5 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:5; + font-size:10.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +a:link, span.MsoHyperlink + {mso-style-noshow:yes; + mso-style-priority:99; + color:blue; + text-decoration:underline; + text-underline:single;} +a:visited, span.MsoHyperlinkFollowed + {mso-style-noshow:yes; + mso-style-priority:99; + color:purple; + text-decoration:underline; + text-underline:single;} +p + {mso-style-noshow:yes; + mso-style-priority:99; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +pre + {mso-style-noshow:yes; + mso-style-priority:99; + mso-style-link:"HTML Preformatted Char"; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt; + font-size:10.0pt; + font-family:"Courier New"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black;} +p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +span.Heading3Char + {mso-style-name:"Heading 3 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 3"; + color:black; + font-weight:bold;} +span.Heading4Char + {mso-style-name:"Heading 4 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 4"; + color:black; + font-weight:bold;} +span.Heading5Char + {mso-style-name:"Heading 5 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 5"; + color:black; + font-weight:bold;} +span.HTMLPreformattedChar + {mso-style-name:"HTML Preformatted Char"; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"HTML Preformatted"; + font-family:"Courier New"; + mso-ascii-font-family:"Courier New"; + mso-hansi-font-family:"Courier New"; + mso-bidi-font-family:"Courier New"; + color:black;} +p.msochpdefault, li.msochpdefault, div.msochpdefault + {mso-style-name:msochpdefault; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-unhide:no; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +span.xdrichtextboxxdbehaviorghostedtextctrl59ms-xedit-plaintext + {mso-style-name:"xdrichtextbox xdbehavior_ghostedtext ctrl59 ms-xedit-plaintext"; + mso-style-unhide:no;} +.MsoChpDefault + {mso-style-type:export-only; + mso-default-props:yes; + font-size:10.0pt; + mso-ansi-font-size:10.0pt; + mso-bidi-font-size:10.0pt;} +@page WordSection1 + {size:8.5in 11.0in; + margin:1.0in 1.25in 1.0in 1.25in; + mso-header-margin:.5in; + mso-footer-margin:.5in; + mso-paper-source:0;} +div.WordSection1 + {page:WordSection1;} + /* List Definitions */ + @list l0 + {mso-list-id:562642700; + mso-list-type:hybrid; + mso-list-template-ids:-1055364604 67698705 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} +@list l0:level1 + {mso-level-text:"%1\)"; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level2 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level3 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l0:level4 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level5 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level6 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l0:level7 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level8 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level9 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l1 + {mso-list-id:814641137; + mso-list-template-ids:1708158208;} +@list l1:level1 + {mso-level-start-at:2; + mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l1:level3 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2 + {mso-list-id:1015693652; + mso-list-type:hybrid; + mso-list-template-ids:120745856 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} +@list l2:level1 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level2 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level3 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l2:level4 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level5 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level6 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l2:level7 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level8 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2:level9 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l3 + {mso-list-id:1019820257; + mso-list-type:hybrid; + mso-list-template-ids:2110404088 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} +@list l3:level1 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level2 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level3 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l3:level4 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level5 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level6 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l3:level7 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level8 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level9 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l4 + {mso-list-id:1081100945; + mso-list-template-ids:-915523298;} +@list l4:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l5 + {mso-list-id:1977905290; + mso-list-template-ids:1992603632;} +@list l5:level1 + {mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l5:level3 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l5:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +ol + {margin-bottom:0in;} +ul + {margin-bottom:0in;} +--> +</style> +<!--[if gte mso 10]> +<style> + /* Style Definitions */ + table.MsoNormalTable + {mso-style-name:"Table Normal"; + mso-tstyle-rowband-size:0; + mso-tstyle-colband-size:0; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-parent:""; + mso-padding-alt:0in 5.4pt 0in 5.4pt; + mso-para-margin:0in; + mso-para-margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman","serif";} +</style> +<![endif]--><!--[if gte mso 9]><xml> + <o:shapedefaults v:ext="edit" spidmax="1026"/> +</xml><![endif]--><!--[if gte mso 9]><xml> + <o:shapelayout v:ext="edit"> + <o:idmap v:ext="edit" data="1"/> + </o:shapelayout></xml><![endif]--> +</head> + +<body lang=EN-US link=blue vlink=purple style='tab-interval:.5in'> + +<div class=WordSection1> + +<p class=MsoNormal><b><span style='font-size:16.0pt;font-family:"Verdana","sans-serif"'>Radio +Switch Driver Development</span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'><o:p> </o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Sample +HID driver for Radio Management</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>There +are several steps that must be followed to create a HID driver for the hardware +wireless switch:<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoListParagraphCxSpFirst style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>1)<span +style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Update System BIOS<o:p></o:p></span></p> + +<p class=MsoListParagraphCxSpMiddle style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>2)<span +style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Develop HID driver<o:p></o:p></span></p> + +<p class=MsoListParagraphCxSpLast style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana'><span style='mso-list:Ignore'>3)<span +style='font:7.0pt "Times New Roman"'> </span></span></span><![endif]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Validate HID driver +functionality<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Update +System BIOS<o:p></o:p></span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>The system BIOS needs to be updated in order to +report the radio hardware button/switch to software � that is, the switch must +be exposed via ACPI.<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>BIOS must not control the radios directly, but must +rely on Windows 8 software to control the state of the radios via the HID +driver.<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'><o:p> </o:p></span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Develop +the HID driver for the hardware wireless switch<o:p></o:p></span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Use the HID driver sample to develop your +HID-compliant driver that communicates with your proprietary interface (embedded +controller) on the bottom edge and is wireless HID switch compliant on the +upper edge. <o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'><o:p> </o:p></span></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Important +note:</span></b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'> if you are developing a HID driver for an A-B +switch, your proprietary embedded controller must report the correct state of +the switch at all times by sending a HID message to the HID driver, including +every time the PC is turned on back on. Reporting the state of the A-B switch +when the computer is turned back on is especially important in the case that +the switch changed states while the PC was in states S3/S4/S5.<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Validate +HID driver functionality<o:p></o:p></span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Logo tests are available in the Windows Hardware +Certification Kit to validate the functionality of your HID driver.</span><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'><o:p> </o:p></span></p> + +</div> + +</body> + +</html> diff --git a/network/radio/HidSwitchDriverSample/README.htm b/network/radio/HidSwitchDriverSample/README.htm new file mode 100644 index 00000000..ef09a38e --- /dev/null +++ b/network/radio/HidSwitchDriverSample/README.htm @@ -0,0 +1,1437 @@ +<html xmlns:v="urn:schemas-microsoft-com:vml" +xmlns:o="urn:schemas-microsoft-com:office:office" +xmlns:w="urn:schemas-microsoft-com:office:word" +xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" +xmlns="http://www.w3.org/TR/REC-html40"> + +<head> +<meta http-equiv=Content-Type content="text/html; charset=windows-1252"> +<meta name=ProgId content=Word.Document> +<meta name=Generator content="Microsoft Word 14"> +<meta name=Originator content="Microsoft Word 14"> +<link rel=File-List href="README_files/filelist.xml"> +<title>HID USB FX2 Sample</title> +<link rel=themeData href="README_files/themedata.thmx"> +<link rel=colorSchemeMapping href="README_files/colorschememapping.xml"> +<!--[if gte mso 9]><xml> + <w:WordDocument> + <w:View>Print</w:View> + <w:SpellingState>Clean</w:SpellingState> + <w:GrammarState>Clean</w:GrammarState> + <w:TrackMoves>false</w:TrackMoves> + <w:TrackFormatting/> + <w:ValidateAgainstSchemas/> + <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> + <w:IgnoreMixedContent>false</w:IgnoreMixedContent> + <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> + <w:DoNotPromoteQF/> + <w:LidThemeOther>EN-US</w:LidThemeOther> + <w:LidThemeAsian>X-NONE</w:LidThemeAsian> + <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> + <w:Compatibility> + <w:BreakWrappedTables/> + <w:SplitPgBreakAndParaMark/> + </w:Compatibility> + <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> + <m:mathPr> + <m:mathFont m:val="Cambria Math"/> + <m:brkBin m:val="before"/> + <m:brkBinSub m:val="--"/> + <m:smallFrac m:val="off"/> + <m:dispDef/> + <m:lMargin m:val="0"/> + <m:rMargin m:val="0"/> + <m:defJc m:val="centerGroup"/> + <m:wrapIndent m:val="1440"/> + <m:intLim m:val="subSup"/> + <m:naryLim m:val="undOvr"/> + </m:mathPr></w:WordDocument> +</xml><![endif]--><!--[if gte mso 9]><xml> + <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" + DefSemiHidden="true" DefQFormat="false" DefPriority="99" + LatentStyleCount="267"> + <w:LsdException Locked="false" Priority="0" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Normal"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 3"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 4"/> + <w:LsdException Locked="false" Priority="9" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="heading 5"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/> + <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> + <w:LsdException Locked="false" Priority="39" Name="toc 1"/> + <w:LsdException Locked="false" Priority="39" Name="toc 2"/> + <w:LsdException Locked="false" Priority="39" Name="toc 3"/> + <w:LsdException Locked="false" Priority="39" Name="toc 4"/> + <w:LsdException Locked="false" Priority="39" Name="toc 5"/> + <w:LsdException Locked="false" Priority="39" Name="toc 6"/> + <w:LsdException Locked="false" Priority="39" Name="toc 7"/> + <w:LsdException Locked="false" Priority="39" Name="toc 8"/> + <w:LsdException Locked="false" Priority="39" Name="toc 9"/> + <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> + <w:LsdException Locked="false" Priority="10" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Title"/> + <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> + <w:LsdException Locked="false" Priority="11" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> + <w:LsdException Locked="false" Priority="22" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Strong"/> + <w:LsdException Locked="false" Priority="20" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/> + <w:LsdException Locked="false" Priority="59" SemiHidden="false" + UnhideWhenUsed="false" Name="Table Grid"/> + <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/> + <w:LsdException Locked="false" Priority="1" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 1"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 1"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 1"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/> + <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/> + <w:LsdException Locked="false" Priority="34" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/> + <w:LsdException Locked="false" Priority="29" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Quote"/> + <w:LsdException Locked="false" Priority="30" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 1"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 1"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 2"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 2"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 2"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 2"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 2"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 3"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 3"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 3"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 3"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 3"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 4"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 4"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 4"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 4"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 4"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 5"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 5"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 5"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 5"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 5"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/> + <w:LsdException Locked="false" Priority="60" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Shading Accent 6"/> + <w:LsdException Locked="false" Priority="61" SemiHidden="false" + UnhideWhenUsed="false" Name="Light List Accent 6"/> + <w:LsdException Locked="false" Priority="62" SemiHidden="false" + UnhideWhenUsed="false" Name="Light Grid Accent 6"/> + <w:LsdException Locked="false" Priority="63" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/> + <w:LsdException Locked="false" Priority="64" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/> + <w:LsdException Locked="false" Priority="65" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/> + <w:LsdException Locked="false" Priority="66" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/> + <w:LsdException Locked="false" Priority="67" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/> + <w:LsdException Locked="false" Priority="68" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/> + <w:LsdException Locked="false" Priority="69" SemiHidden="false" + UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/> + <w:LsdException Locked="false" Priority="70" SemiHidden="false" + UnhideWhenUsed="false" Name="Dark List Accent 6"/> + <w:LsdException Locked="false" Priority="71" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/> + <w:LsdException Locked="false" Priority="72" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful List Accent 6"/> + <w:LsdException Locked="false" Priority="73" SemiHidden="false" + UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/> + <w:LsdException Locked="false" Priority="19" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/> + <w:LsdException Locked="false" Priority="21" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/> + <w:LsdException Locked="false" Priority="31" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/> + <w:LsdException Locked="false" Priority="32" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/> + <w:LsdException Locked="false" Priority="33" SemiHidden="false" + UnhideWhenUsed="false" QFormat="true" Name="Book Title"/> + <w:LsdException Locked="false" Priority="37" Name="Bibliography"/> + <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/> + </w:LatentStyles> +</xml><![endif]--> +<style> +<!-- + /* Font Definitions */ + @font-face + {font-family:Calibri; + panose-1:2 15 5 2 2 2 4 3 2 4; + mso-font-charset:0; + mso-generic-font-family:swiss; + mso-font-pitch:variable; + mso-font-signature:-520092929 1073786111 9 0 415 0;} +@font-face + {font-family:Verdana; + panose-1:2 11 6 4 3 5 4 4 2 4; + mso-font-charset:0; + mso-generic-font-family:swiss; + mso-font-pitch:variable; + mso-font-signature:-1593833729 1073750107 16 0 415 0;} + /* Style Definitions */ + p.MsoNormal, li.MsoNormal, div.MsoNormal + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-parent:""; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +h3 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 3 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:3; + font-size:13.5pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h4 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 4 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:4; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h5 + {mso-style-priority:9; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 5 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:5; + font-size:10.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +a:link, span.MsoHyperlink + {mso-style-noshow:yes; + mso-style-priority:99; + color:blue; + text-decoration:underline; + text-underline:single;} +a:visited, span.MsoHyperlinkFollowed + {mso-style-noshow:yes; + mso-style-priority:99; + color:purple; + text-decoration:underline; + text-underline:single;} +p + {mso-style-noshow:yes; + mso-style-priority:99; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +pre + {mso-style-noshow:yes; + mso-style-priority:99; + mso-style-link:"HTML Preformatted Char"; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt; + font-size:10.0pt; + font-family:"Courier New"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black;} +p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast + {mso-style-noshow:yes; + mso-style-priority:34; + mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-type:export-only; + margin-top:0in; + margin-right:0in; + margin-bottom:0in; + margin-left:.5in; + margin-bottom:.0001pt; + mso-add-space:auto; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +span.Heading3Char + {mso-style-name:"Heading 3 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 3"; + color:black; + font-weight:bold;} +span.Heading4Char + {mso-style-name:"Heading 4 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 4"; + color:black; + font-weight:bold;} +span.Heading5Char + {mso-style-name:"Heading 5 Char"; + mso-style-noshow:yes; + mso-style-priority:9; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 5"; + color:black; + font-weight:bold;} +span.HTMLPreformattedChar + {mso-style-name:"HTML Preformatted Char"; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"HTML Preformatted"; + font-family:"Courier New"; + mso-ascii-font-family:"Courier New"; + mso-hansi-font-family:"Courier New"; + mso-bidi-font-family:"Courier New"; + color:black;} +p.msochpdefault, li.msochpdefault, div.msochpdefault + {mso-style-name:msochpdefault; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-unhide:no; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast;} +span.xdrichtextboxxdbehaviorghostedtextctrl59ms-xedit-plaintext + {mso-style-name:"xdrichtextbox xdbehavior_ghostedtext ctrl59 ms-xedit-plaintext"; + mso-style-unhide:no;} +span.SpellE + {mso-style-name:""; + mso-spl-e:yes;} +span.GramE + {mso-style-name:""; + mso-gram-e:yes;} +.MsoChpDefault + {mso-style-type:export-only; + mso-default-props:yes; + font-size:10.0pt; + mso-ansi-font-size:10.0pt; + mso-bidi-font-size:10.0pt;} +@page WordSection1 + {size:8.5in 11.0in; + margin:1.0in 1.25in 1.0in 1.25in; + mso-header-margin:.5in; + mso-footer-margin:.5in; + mso-paper-source:0;} +div.WordSection1 + {page:WordSection1;} + /* List Definitions */ + @list l0 + {mso-list-id:1015693652; + mso-list-type:hybrid; + mso-list-template-ids:120745856 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} +@list l0:level1 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level2 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level3 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l0:level4 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level5 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level6 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l0:level7 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level8 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level9 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l1 + {mso-list-id:1019820257; + mso-list-type:hybrid; + mso-list-template-ids:2110404088 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;} +@list l1:level1 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level2 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level3 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l1:level4 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level5 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level6 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l1:level7 + {mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level8 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:none; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level9 + {mso-level-number-format:roman-lower; + mso-level-tab-stop:none; + mso-level-number-position:right; + text-indent:-9.0pt;} +@list l2 + {mso-list-id:1133792005; + mso-list-template-ids:1839505460;} +@list l2:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l3 + {mso-list-id:1493252706; + mso-list-template-ids:10805292;} +@list l3:level1 + {mso-level-start-at:2; + mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l3:level3 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4 + {mso-list-id:1977905290; + mso-list-template-ids:1992603632;} +@list l4:level1 + {mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level2 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l4:level3 + {mso-level-number-format:alpha-lower; + mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l4:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +ol + {margin-bottom:0in;} +ul + {margin-bottom:0in;} +--> +</style> +<!--[if gte mso 10]> +<style> + /* Style Definitions */ + table.MsoNormalTable + {mso-style-name:"Table Normal"; + mso-tstyle-rowband-size:0; + mso-tstyle-colband-size:0; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-parent:""; + mso-padding-alt:0in 5.4pt 0in 5.4pt; + mso-para-margin:0in; + mso-para-margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman","serif";} +</style> +<![endif]--><!--[if gte mso 9]><xml> + <o:shapedefaults v:ext="edit" spidmax="1026"/> +</xml><![endif]--><!--[if gte mso 9]><xml> + <o:shapelayout v:ext="edit"> + <o:idmap v:ext="edit" data="1"/> + </o:shapelayout></xml><![endif]--> +</head> + +<body lang=EN-US link=blue vlink=purple style='tab-interval:.5in'> + +<div class=WordSection1> + +<p class=MsoNormal><b><span style='font-size:16.0pt;font-family:"Verdana","sans-serif"'>Radio +Switch Test Driver for OSR USB-FX2 Development Board</span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'><o:p> </o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-size:11.0pt;font-family:"Verdana","sans-serif"'>Before +developing the HID driver, please make sure you read the READFIRST document, +which indicates the steps that must be taken in order to correctly develop a +HID driver.<o:p></o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'><o:p> </o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Sample HID +driver for Radio Management</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>This +sample demonstrates how to structure a HID driver for radio switches for the +OSR USB-FX2 Development Board.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>On +Windows 8 and later, the hardware switch or button to control wireless +transmission and the global software switch (Airplane mode switch) in the Radio +Management User Interface must be synchronized. To ensure the hardware and +software switches that control radio transmission are synchronized, the +hardware switch or button must have a HID-compliant driver.</span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Switch +Pack Mapping</span></b></p> + +<p class=MsoNormal><span style='font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 + style='border-collapse:collapse;mso-yfti-tbllook:1184;mso-padding-alt:0in 0in 0in 0in'> + <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Switch</span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>2</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>3</span></p> + </td> + <td width=72 valign=top style='width:.75in;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>4</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>5</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>6</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>7</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>8</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:1;mso-yfti-lastrow:yes'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Mapping</span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Mode Select</span></p> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Bit 3</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Mode Select</span></p> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Bit 2</span></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Mode Select</span></p> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Bit 1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'>-</p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'>-</p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'>-</p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'>-</p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Radio Switch</span></p> + </td> + </tr> +</table> + +<p class=MsoNormal><b><span style='font-family:"Arial","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"; +mso-bidi-font-family:Arial'>Sample Language Implementation<o:p></o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"; +mso-bidi-font-family:Arial'><span style='mso-tab-count:1'>��������� </span></span></b><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-bidi-font-family: +Arial;mso-bidi-font-weight:bold'>C++</span><span style='font-size:10.0pt; +font-family:"Verdana","sans-serif"'><o:p></o:p></span></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Prerequisites +for Installation<o:p></o:p></span></b></p> + +<p class=MsoListParagraphCxSpFirst style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana;mso-bidi-font-weight:bold'><span +style='mso-list:Ignore'>1.<span style='font:7.0pt "Times New Roman"'> +</span></span></span><![endif]><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Windows 8 Developer Preview x86<o:p></o:p></span></p> + +<p class=MsoListParagraphCxSpMiddle style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana;mso-bidi-font-weight:bold'><span +style='mso-list:Ignore'>2.<span style='font:7.0pt "Times New Roman"'> +</span></span></span><![endif]><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Visual Studio 11 Developer Preview<o:p></o:p></span></p> + +<p class=MsoListParagraphCxSpLast style='text-indent:-.25in;mso-list:l0 level1 lfo2'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana;mso-bidi-font-weight:bold'><span +style='mso-list:Ignore'>3.<span style='font:7.0pt "Times New Roman"'> +</span></span></span><![endif]><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Windows 8 WDK<o:p></o:p></span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'><o:p> </o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Building +the Driver<o:p></o:p></span></b></p> + +<p class=MsoListParagraphCxSpFirst style='text-indent:-.25in;mso-list:l1 level1 lfo4'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana;mso-bidi-font-weight:bold'><span +style='mso-list:Ignore'>1.<span style='font:7.0pt "Times New Roman"'> +</span></span></span><![endif]><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Open the RadioSwitchHidUsbFx2.VcxProj<o:p></o:p></span></p> + +<p class=MsoListParagraphCxSpLast style='text-indent:-.25in;mso-list:l1 level1 lfo4'><![if !supportLists]><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +Verdana;mso-bidi-font-family:Verdana;mso-bidi-font-weight:bold'><span +style='mso-list:Ignore'>2.<span style='font:7.0pt "Times New Roman"'> +</span></span></span><![endif]><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +mso-bidi-font-weight:bold'>Use Visual Studio 11 to build the project<o:p></o:p></span></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'><o:p> </o:p></span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Installing +the Driver</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>To +install the driver, you must:</span><o:p></o:p></p> + +<ol style='margin-top:0in' start=1 type=1 xmlns="http://www.w3.org/1999/xhtml"> + <li class=MsoNormal style='mso-list:l4 level1 lfo7;tab-stops:list .5in'><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Build the driver using Visual Studio 11 Developer + Preview and copy the following installation files to a folder on your hard + drive: </span><span style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <ul style='margin-top:0in' type=disc> + <li class=MsoNormal style='mso-list:l4 level2 lfo7;tab-stops:list 1.0in'><em><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>RadioSwitchHidUsbFx2.inf </span></em><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <li class=MsoNormal style='mso-list:l4 level2 lfo7;tab-stops:list 1.0in'><em><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>RadioSwitchHidUsbFx2.sys </span></em><em><span + style='font-style:normal'><o:p></o:p></span></em></li> + </ul> +</ol> + +<p class=MsoNormal style='margin-left:1.0in'><o:p> </o:p></p> + +<ol style='margin-top:0in' start=2 type=1> + <li class=MsoNormal style='mso-list:l4 level1 lfo7;tab-stops:list .5in'><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Plug in the device and do the following, depending on + the operating system that you are using:</span><span style='mso-fareast-font-family: + "Times New Roman"'><o:p></o:p></span></li> + <ul style='margin-top:0in' type=disc> + <ol style='margin-top:0in' start=1 type=a> + <li class=MsoNormal style='mso-list:l4 level3 lfo7;tab-stops:list 1.5in'><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Launch <b>Device Manager</b> by executing command <span + class=SpellE>devmgmt.msc</span> in a command window, or from <strong><span + style='font-family:"Verdana","sans-serif"'>Hardware and Sound </span></strong><strong><span + style='font-family:"Verdana","sans-serif";font-weight:normal'>program</span></strong><strong><span + style='font-family:"Verdana","sans-serif"'> </span></strong><strong><span + style='font-family:"Verdana","sans-serif";font-weight:normal'>group</span></strong><strong><span + style='font-family:"Verdana","sans-serif"'> in Control Panel</span></strong>.</span><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <li class=MsoNormal style='mso-list:l4 level3 lfo7;tab-stops:list 1.5in'><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman";font-weight:normal'>Select </span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>OSR USB-FX2</span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman";font-weight:normal'> device from </span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Other Devices</span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman";font-weight:normal'> category and click </span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Update Driver Software�</span></strong><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman";font-weight:normal'> from right-click menu.</span></strong><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <li class=MsoNormal style='mso-list:l4 level3 lfo7;tab-stops:list 1.5in'><strong><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman";font-weight:normal'>Select Browse my computer for + software and provide the location of the driver files.</span></strong><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <li class=MsoNormal style='mso-list:l4 level3 lfo7;tab-stops:list 1.5in'><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>Select <span class=GramE><strong><span + style='font-family:"Verdana","sans-serif"'>Install</span></strong></span><strong><span + style='font-family:"Verdana","sans-serif"'> this driver software anyway </span></strong>when + the <strong><span style='font-family:"Verdana","sans-serif"'>Windows + Security </span></strong>dialog box appears.</span><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + <li class=MsoNormal style='mso-list:l4 level3 lfo7;tab-stops:list 1.5in'><span + style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: + "Times New Roman"'>After the driver is installed, you should see the + device in Device Manager under "Human Interface Devices". </span><span + style='mso-fareast-font-family:"Times New Roman"'><o:p></o:p></span></li> + </ol> + </ul> +</ol> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'>Testing</span></b></p> + +<p class=MsoNormal><b><span style='font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Testing +Modes</span></b></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The +driver supports five modes representing the valid combinations of HID +descriptors that we have defined for the USB forum.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Modes +are selected using switches 1, 2, and 3 on the switch pack.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 + style='border-collapse:collapse;mso-yfti-tbllook:1184;mso-padding-alt:0in 0in 0in 0in'> + <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Switch</span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>2</span></p> + </td> + <td width=72 valign=top style='width:.75in;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>3</span></p> + </td> + <td width=72 valign=top style='width:.75in;border:solid windowtext 2.25pt; + border-left:none;background:#A0A0A0;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Arial","sans-serif"'>Mode</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:1'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'>Mapping</span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><i><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 1</span></i></p> + </td> + </tr> + <tr style='mso-yfti-irow:2'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 1</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:3'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 2</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:4'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 3</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:5'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 4</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:6'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + background:#EAF1DD;padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 5</span></p> + </td> + </tr> + <tr style='mso-yfti-irow:7'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>0</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><i><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 1</span></i></p> + </td> + </tr> + <tr style='mso-yfti-irow:8;mso-yfti-lastrow:yes'> + <td width=67 valign=top style='width:.7in;border:none;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal><b><span style='font-size:9.0pt;font-family:"Arial","sans-serif"'> </span></b></p> + </td> + <td width=60 valign=top style='width:45.0pt;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 0in 0in 0in'> + <p class=MsoNormal align=center style='text-align:center'><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>1</span></p> + </td> + <td width=72 valign=top style='width:.75in;border-top:none;border-left:none; + border-bottom:solid windowtext 2.25pt;border-right:solid windowtext 2.25pt; + padding:0in 5.4pt 0in 5.4pt'> + <p class=MsoNormal align=center style='text-align:center'><i><span + style='font-size:10.0pt;font-family:"Calibri","sans-serif"'>Mode 1</span></i></p> + </td> + </tr> +</table> + +<p class=MsoNormal> </p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The +Mode in use is displayed on the boards seven segment display.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +is determined at startup, so to change mode the board must be unplugged & +then re-connected</span></p> + +<p class=MsoNormal> </p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +1 Radio Push Button </span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +this mode the radio switch (switch 8 on the switch pack) represents a momentary +push button.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>A +HID report is generated when the switch transitions to the <span class=GramE>On</span> +state (switch down).</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +2 Radio Push Button & LED</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +this mode the radio switch (switch 8 on the switch pack) represents a momentary +push button.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>A +HID report is generated when the switch transitions to the <span class=GramE>On</span> +state (switch down).</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +addition, the LED array will reflect the state of the Radio LED: either all on +or all off (note that the top 2 LEDs never illuminate as these are not wired +in).</span></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></b></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +3 Radio Slider Switch</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +this mode the radio switch (switch 8 on the switch pack) represents an A-B +slider switch.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>A +HID report is generated in both cases: when the switch transitions to the <span +class=GramE>On</span> state (switch down) and to the Off state (switch up).</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'> </span></p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +4 Radio Slider Switch & LED</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +this mode the radio switch (switch 8 on the switch pack) represents an A-B +slider switch.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>A +HID report is generated in both cases: when the switch transitions to the <span +class=GramE>On</span> state (switch down) and to the Off state (switch up).</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +addition the LED array will reflect the state of the Radio LED: either all on +or all off (note that the top 2 LEDs never illuminate as these are not wired +in).</span></p> + +<p class=MsoNormal> </p> + +<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Mode +5 LED only</span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>In +this mode the radio switch (switch 8 on the switch pack) is ignored.</span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>The +LED array will reflect the state of the Radio LED: either all on or all off +(note that the top 2 LEDs never illuminate as these are not wired in).</span></p> + +</div> + +</body> + +</html> diff --git a/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.h b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.h new file mode 100644 index 00000000..ce92cfff --- /dev/null +++ b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.h @@ -0,0 +1,156 @@ +#ifndef _RADIOSWITCHHIDUSBFX2_H_ +#define _RADIOSWITCHHIDUSBFX2_H_ + +#include <initguid.h> +#include <wdm.h> +#include "usbdi.h" +#include "usbdlib.h" +#include <wdf.h> +#include "wdfusb.h" +#include <hidport.h> +#define NTSTRSAFE_LIB +#include <ntstrsafe.h> +#include "trace.h" + + +#define HID_CLASS_SPEC_RELEASE_1_00 0x0100 // HID Class Specification release 1.00 +#define HID_COUNTRY_NON_LOCALIZED 0x00 // Hardware is not localized + +#define GENERIC_DESKTOP_REPORT_ID 0x01 + +#define GENERIC_DESKTOP_USAGE_PAGE 0x01 +#define WIRELESS_RADIO_CONTROLS_USAGE 0x0C +#define WIRELESS_RADIO_BUTTON_USAGE 0xC6 +#define WIRELESS_RADIO_LED_USAGE 0xC7 +#define WIRELESS_RADIO_SLIDER_USAGE 0xC8 + + +#define MODE_SELECTION_BUTTONS_BIT_MASK 0xE0 +#define RADIO_SWITCH_BUTTONS_BIT_MASK 0x01 +#define SWITCHPACK_SELECTION_FOR_MODE2 0x40 +#define SWITCHPACK_SELECTION_FOR_MODE3 0x60 +#define SWITCHPACK_SELECTION_FOR_MODE4 0x80 +#define SWITCHPACK_SELECTION_FOR_MODE5 0xA0 + +#define INTERRUPT_ENDPOINT_INDEX (0) + +#define SWITCHPACK_DEBOUNCE_TIME 10 // in millseconds + +// Define the vendor commands supported by device +#define HIDFX2_READ_SWITCH_STATE 0xD6 +#define HIDFX2_READ_7SEGMENT_DISPLAY 0xD4 +#define HIDFX2_READ_BARGRAPH_DISPLAY 0xD7 +#define HIDFX2_SET_BARGRAPH_DISPLAY 0xD8 +#define HIDFX2_IS_HIGH_SPEED 0xD9 +#define HIDFX2_REENUMERATE 0xDA +#define HIDFX2_SET_7SEGMENT_DISPLAY 0xDB + +// Bit masks for 7 segment display to be used with vendor command +#define SEG_TOP 0x1 +#define SEG_R_UPPER 0x2 +#define SEG_R_LOWER 0x4 +#define SEG_DOT 0x8 +#define SEG_L_LOWER 0x10 +#define SEG_MID 0x20 +#define SEG_L_UPPER 0x40 +#define SEG_BASE 0x80 + +#define SEGMENT_DISPLAY_1 SEG_R_UPPER | SEG_R_LOWER +#define SEGMENT_DISPLAY_2 SEG_TOP | SEG_R_UPPER | SEG_MID | SEG_L_LOWER | SEG_BASE +#define SEGMENT_DISPLAY_3 SEG_TOP | SEG_R_UPPER | SEG_MID | SEG_R_LOWER | SEG_BASE +#define SEGMENT_DISPLAY_4 SEG_R_UPPER | SEG_R_LOWER | SEG_MID | SEG_L_UPPER +#define SEGMENT_DISPLAY_5 SEG_TOP | SEG_R_LOWER | SEG_MID | SEG_L_UPPER | SEG_BASE +#define SEGMENT_DISPLAY_6 SEG_TOP | SEG_R_LOWER | SEG_L_LOWER | SEG_MID | SEG_L_UPPER | SEG_BASE +#define SEGMENT_DISPLAY_7 SEG_TOP | SEG_R_UPPER | SEG_R_LOWER +#define SEGMENT_DISPLAY_8 SEG_TOP | SEG_R_UPPER | SEG_R_LOWER | SEG_L_UPPER | SEG_L_LOWER | SEG_MID | SEG_BASE + +#define BARGRAPH_LED_ALL_ON 0xff +#define BARGRAPH_LED_ALL_OFF 0x00 + + +typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; + +#include <pshpack1.h> // make sure packing is handled correctly + +typedef struct _HIDFX2_IO_REPORT +{ + unsigned char bReportId; //Report ID for the collection + unsigned char bData; //one-byte data for switch/LED +}HIDFX2_IO_REPORT, *PHIDFX2_IO_REPORT; + + +typedef enum _DRIVER_MODE +{ + DM_BUTTON = 1, + DM_BUTTON_AND_LED, + DM_SLIDER_SWITCH, + DM_SLIDER_SWITCH_AND_LED, + DM_LED_ONLY +} DRIVER_MODE; + +#include <poppack.h> + +typedef struct _DEVICE_EXTENSION +{ + WDFUSBDEVICE hUsbDevice; //WDF handles for USB Target + WDFUSBINTERFACE hUsbInterface; + WDFUSBPIPE hInterruptPipe; + WDFMEMORY hDeviceDescriptor; // Device descriptor for the USB device + unsigned char bCurrentSwitchState; // Switch state. + unsigned char bLatestToggledSwitch; // State for the switch that got toggled most recently + BOOLEAN fIsPowerUpSwitchState; //Interrupt endpoints sends switch state when first started .we ignore this + WDFTIMER hDebounceTimer; // Handle debouncing of switchpack + WDFQUEUE hInterruptMsgQueue; // WDF Queue for read IOCTLs from hidclass that get satisfied from USB interrupt endpoint + DRIVER_MODE driverMode; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, GetDeviceContext) + + +// +// Driver routines +// +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD HidFx2EvtDeviceAdd; + +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL HidFx2EvtInternalDeviceControl; + +EVT_WDF_DEVICE_PREPARE_HARDWARE HidFx2EvtDevicePrepareHardware; + +EVT_WDF_DEVICE_D0_ENTRY HidFx2EvtDeviceD0Entry; + +EVT_WDF_DEVICE_D0_EXIT HidFx2EvtDeviceD0Exit; + +EVT_WDF_USB_READER_COMPLETION_ROUTINE HidFx2EvtUsbInterruptPipeReadComplete; + +EVT_WDF_TIMER HidFx2EvtTimerFunction; + +EVT_WDF_OBJECT_CONTEXT_CLEANUP HidFx2EvtDriverContextCleanup; + +EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE HidFx2EvtIoCanceledOnQueue; + + +NTSTATUS HidFx2GetHidDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2GetReportDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2GetDeviceAttributes(_In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2ConfigContReaderForInterruptEndPoint(PDEVICE_EXTENSION pDeviceContext); + +NTSTATUS HidFx2SendIdleNotification(_In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2SetOutput(_In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2GetInput(_In_ WDFREQUEST hRequest); + +NTSTATUS HidFx2GetSwitchState(_In_ WDFDEVICE hDevice, _Out_ unsigned char *pbSwitchState); + +NTSTATUS SendVendorCommand(_In_ WDFDEVICE hDevice, _In_ unsigned char bVendorCommand, _In_ unsigned char bCommandData); + +PCWSTR DbgDevicePowerString(_In_ WDF_POWER_DEVICE_STATE powerState); + +#endif //_RADIOSWITCHHIDUSBFX2_H_ + + diff --git a/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.inx b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.inx new file mode 100644 index 00000000..5089dfdd --- /dev/null +++ b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.inx @@ -0,0 +1,114 @@ +[Version] +Signature="$Windows NT$" +Class=HIDClass +ClassGuid={745a17a0-74d3-11d0-b6fe-00a0c90f57da} +Provider=%VENDOR% +DriverVer=5/3/2011,1.0.0.0 +CatalogFile=HidRadioSwitchDrv.cat + + +[SourceDisksFiles] +RadioSwitchHidUsbFx2.sys = 99 + +[SourceDisksNames] +99 = %DISK_NAME%,,,"" + +[DestinationDirs] +CopyFunctionDriver = 12 +CopyFilterDriver = 12 + +[Manufacturer] +%VENDOR%=Vendor, NT$ARCH$.6.1 + +; For Win7 and later so that we can use inbox HID-KMDF mapper +[Vendor.NT$ARCH$.6.1] +%RadioSwitchHidUsbFx2% = RadioSwitchHidUsbFx2.Inst.Win7, USB\VID_0547&PID_1002 +%customCollection% = customCollection.Inst, HID_DEVICE_UP:FF00_U:0001 + +;=============================================================== +; RadioSwitchHidUsbFx2 for Win7 +; Instead of using hidkmdf.sys as a filter, use the inbox +; mshidkmdf.sys as a mapper filter +;=============================================================== +[RadioSwitchHidUsbFx2.Inst.Win7.NT] +; Just copy the driver. No neeed to copy other system binaries. +CopyFiles = CopyFunctionDriver + +[RadioSwitchHidUsbFx2.Inst.Win7.NT.HW] +AddReg = RadioSwitchHidUsbFx2_Win7_Parameters.AddReg + +; +; hidkmdf is the function driver and RadioSwitchHidUsbFx2 is the lower filter +; +[RadioSwitchHidUsbFx2.Inst.Win7.NT.Services] +AddService = RadioSwitchHidUsbFx2,0x00000002, RadioSwitchHidUsbFx2_Service_Inst + +[RadioSwitchHidUsbFx2_Win7_Parameters.AddReg] +HKR,,"UpperFilters",0x00010000,"mshidkmdf" + +;=============================================================== +; Sections common to all OS versions +;=============================================================== + +[CopyFunctionDriver] +RadioSwitchHidUsbFx2.sys + +[RadioSwitchHidUsbFx2_Service_Inst] +DisplayName = %RadioSwitchHidUsbFx2% +ServiceType = %SERVICE_KERNEL_DRIVER% +StartType = %SERVICE_DEMAND_START% +ErrorControl = %SERVICE_ERROR_IGNORE% +ServiceBinary = %12%\RadioSwitchHidUsbFx2.sys + +;=============================================================== +; Custom Collection install section +; - Only a Null service is installed. +;=============================================================== +[customCollection.Inst.NT] +; NULL section + +[customCollection.Inst.NT.HW] +AddReg = customCollection.Inst.AddReg.NT.HW + +[customCollection.Inst.AddReg.NT.HW] +HKR,,"SelectiveSuspendEnabled",0x00000001,0x1 + +[customCollection.Inst.NT.Services] +AddService = ,0x00000002, ; NULL Service + +;================================================================ +;--- WDF Coinstaller installation ------ +; +[DestinationDirs] +RadioSwitchHidUsbFx2.Inst_CoInstaller_CopyFiles = 11 + +[SourceDisksFiles] +WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=99 ; make sure the number matches with SourceDisksNames + +[Strings] +; *******Localizable Strings******* +VENDOR = "Vendor Name" +RadioSwitchHidUsbFx2 = "Radio Switch HID Mini-driver for OSR USB-FX-2 Device" +customCollection = "Radio Switch Collection for OSR USB-FX-2" +DISK_NAME = "HID Radio Switch USB FX-2 Install Disk" + +; *******Non Localizable Strings******* + +SERVICE_BOOT_START = 0x0 +SERVICE_SYSTEM_START = 0x1 +SERVICE_AUTO_START = 0x2 +SERVICE_DEMAND_START = 0x3 +SERVICE_DISABLED = 0x4 + +SERVICE_KERNEL_DRIVER = 0x1 +SERVICE_ERROR_IGNORE = 0x0 +SERVICE_ERROR_NORMAL = 0x1 +SERVICE_ERROR_SEVERE = 0x2 +SERVICE_ERROR_CRITICAL = 0x3 + +REG_EXPAND_SZ = 0x00020000 +REG_DWORD = 0x00010001 +REG_MULTI_SZ = 0x00010000 +REG_BINARY = 0x00000001 +REG_SZ = 0x00000000 + diff --git a/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.rc b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.rc new file mode 100644 index 00000000..6737f603 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.rc @@ -0,0 +1,11 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "HID Radio Switch mini driver for USB Fx2 Device" +#define VER_INTERNALNAME_STR "RadioSwitchHidUsbFx2.sys" + +#include "common.ver" + diff --git a/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj new file mode 100644 index 00000000..690f4f3f --- /dev/null +++ b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" 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="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{299CE7FF-033A-4968-906D-5B8D00C1FE0C}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{060E6040-ACF0-4A53-A87E-2D541F54BDC3}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </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')" /> + </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')" /> + </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')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <ClCompile Include="driver.c; hid.c; usb.c"> + <WppEnabled>true</WppEnabled> + <WppKernelMode>true</WppKernelMode> + <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...);TraceErr{LEVEL=TRACE_LEVEL_ERROR}(FLAGS,MSG,...);TraceWarning{LEVEL=TRACE_LEVEL_WARNING}(FLAGS,MSG,...);TraceInfo{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS,MSG,...);TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS,MSG,...)</WppTraceFunction> + <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile> + </ClCompile> + <Inf Include=".\RadioSwitchHidUsbFx2.inx"> + <Architecture>$(InfArch)</Architecture> + <SpecifyArchitecture>true</SpecifyArchitecture> + <CopyOutput>.\$(IntDir)\RadioSwitchHidUsbFx2.inf</CopyOutput> + </Inf> + <OtherWpp Include="RadioSwitchHidUsbFx2.rc"> + <WppEnabled>true</WppEnabled> + <WppKernelMode>true</WppKernelMode> + <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...);TraceErr{LEVEL=TRACE_LEVEL_ERROR}(FLAGS,MSG,...);TraceWarning{LEVEL=TRACE_LEVEL_WARNING}(FLAGS,MSG,...);TraceInfo{LEVEL=TRACE_LEVEL_INFORMATION}(FLAGS,MSG,...);TraceVerbose{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS,MSG,...)</WppTraceFunction> + <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile> + </OtherWpp> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>RadioSwitchHidUsbFx2</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>RadioSwitchHidUsbFx2</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>RadioSwitchHidUsbFx2</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>RadioSwitchHidUsbFx2</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidclass.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidclass.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidclass.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\hidclass.lib;$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ResourceCompile Include="RadioSwitchHidUsbFx2.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj.Filters b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj.Filters new file mode 100644 index 00000000..b4198ba4 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/RadioSwitchHidUsbFx2.vcxproj.Filters @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{FDCC489B-556E-43F5-BD3B-71316D442DEA}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{18150D25-6522-47D8-9CB4-5108F5F98F28}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{A79E57E4-3B90-45E9-95EB-A0541E4A8DF4}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{0F70BE0E-ED35-4FD6-88BE-92687BE1BBB6}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="driver.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="hid.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="usb.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <FilesToPackage Include=".\Debug\\RadioSwitchHidUsbFx2.inf"> + <Filter>Driver Files</Filter> + </FilesToPackage> + <Inf Include=".\RadioSwitchHidUsbFx2.inx"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="RadioSwitchHidUsbFx2.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/radio/HidSwitchDriverSample/ReadMe.md b/network/radio/HidSwitchDriverSample/ReadMe.md new file mode 100644 index 00000000..5a94b523 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/ReadMe.md @@ -0,0 +1,74 @@ +Radio Switch Test Driver for OSR USB-FX2 Development Board +========================================================== + +This sample demonstrates how to structure a HID driver for radio switches for the OSR USB-FX2 Development Board. + +Starting with Windows 8.1, the hardware switch or button to control wireless transmission and the global software switch (Airplane mode switch) in the Radio Management User Interface must be synchronized. To ensure the hardware and software switches that control radio transmission are synchronized, the hardware switch or button must have a HID-compliant driver. + + +Testing +------- + +### Testing Modes + +The driver supports five modes representing the valid combinations of HID descriptors that we have defined for the USB forum. Modes are selected using switches 1, 2, and 3 on the switch pack. + +### Switch Mapping + +<table> +<colgroup> +<col width="25%" /> +<col width="25%" /> +<col width="25%" /> +<col width="25%" /> +</colgroup> +<thead> +<tr class="header"> +<th align="left">1 +2 +3 +Mode</th> +</tr> +</thead> +<tbody> +<tr class="odd"> +<td align="left">0 +0 +0 +Mode 1</td> +<td align="left">0 +0 +1 +Mode 1</td> +<td align="left">0 +1 +0 +Mode 2</td> +<td align="left">0 +1 +1 +Mode 3</td> +</tr> +</tbody> +</table> + +### Mode 1 Radio Push Button + +In this mode the radio switch (switch 8 on the switch pack) represents a momentary push button. A HID report is generated when the switch transitions to the On state (switch down). + +### Mode 2 Radio Push Button & LED + +In this mode the radio switch (switch 8 on the switch pack) represents a momentary push button. A HID report is generated when the switch transitions to the On state (switch down). In addition, the LED array will reflect the state of the Radio LED: either all on or all off (note that the top 2 LEDs never illuminate as these are not wired in). + +### Mode 3 Radio Slider Switch + +In this mode the radio switch (switch 8 on the switch pack) represents a momentary push button. A HID report is generated when the switch transitions to the On state (switch down). + +### Mode 4 Radio Slider Switch & LED + +In this mode the radio switch (switch 8 on the switch pack) represents an A-B slider switch. A HID report is generated in both cases: when the switch transitions to the On state (switch down) and to the Off state (switch up). In addition the LED array will reflect the state of the Radio LED: either all on or all off (note that the top 2 LEDs never illuminate as these are not wired in). + +### Mode 5 LED only + +In this mode the radio switch (switch 8 on the switch pack) is ignored. The LED array will reflect the state of the Radio LED: either all on or all off (note that the top 2 LEDs never illuminate as these are not wired in). + diff --git a/network/radio/HidSwitchDriverSample/driver.c b/network/radio/HidSwitchDriverSample/driver.c new file mode 100644 index 00000000..a14d4fc4 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/driver.c @@ -0,0 +1,156 @@ +#include <RadioSwitchHidUsbFx2.h> +#pragma warning(disable:28252) +#pragma warning(disable:28253) +#include "driver.tmh" + + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(INIT, DriverEntry) + #pragma alloc_text(PAGE, HidFx2EvtDriverContextCleanup) + #pragma alloc_text(PAGE, HidFx2EvtDeviceAdd) +#endif + + + +//Installable driver initialization entry point. This entry point is called directly by the I/O system. +// +NTSTATUS DriverEntry (_In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING pszRegistryPath) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_DRIVER_CONFIG config; + WDF_OBJECT_ATTRIBUTES attributes; + + + // Initialize WPP Tracing + WPP_INIT_TRACING(pDriverObject, pszRegistryPath); + + TraceInfo(DBG_INIT, "(%!FUNC!) Enter -Sample Built %s %s\n", __DATE__, __TIME__); + + WDF_DRIVER_CONFIG_INIT(&config, HidFx2EvtDeviceAdd); + + // Register a cleanup callback so that we can call WPP_CLEANUP when the framework driver object is deleted during driver unload. + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = HidFx2EvtDriverContextCleanup; + + // Create a framework driver object to represent our driver. + status = WdfDriverCreate(pDriverObject, + pszRegistryPath, + &attributes, // Driver Attributes + &config, // Driver Config Info + WDF_NO_HANDLE + ); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_INIT, "(%!FUNC!)WdfDriverCreate failed with status %!STATUS!\n", status); + WPP_CLEANUP(pDriverObject); + } + + TraceVerbose(DBG_INIT, "(%!FUNC!) Exit\n"); + return status; +} + + + +//Free resources allocated in DriverEntry that are not automatically cleaned up framework. +// +void HidFx2EvtDriverContextCleanup(_In_ WDFOBJECT hDriver) +{ + PAGED_CODE (); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Enter/Exit\n"); + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(hDriver)); +} + + + +//HidFx2EvtDeviceAdd is called by the framework in response to AddDevicecall from the PnP manager. +//We create and initialize a WDF device object to represent a new instance of device. +// +NTSTATUS HidFx2EvtDeviceAdd(_In_ WDFDRIVER hDriver, _Inout_ PWDFDEVICE_INIT pDeviceInit) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_IO_QUEUE_CONFIG queueConfig; + WDF_OBJECT_ATTRIBUTES attributes; + WDFDEVICE hDevice; + PDEVICE_EXTENSION pDevContext = NULL; + WDFQUEUE hQueue; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_TIMER_CONFIG timerConfig; + WDFTIMER hTimer; + + UNREFERENCED_PARAMETER(hDriver); + + PAGED_CODE(); + + TraceVerbose(DBG_PNP, "(%!FUNC!) Enter\n"); + + // Tell framework this is a filter driver. + WdfFdoInitSetFilter(pDeviceInit); + + // Initialize pnp-power callbacks, attributes and a context area for the device object. + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + + // For usb devices, PrepareHardware callback is the to place select the interface and configure the device. + pnpPowerCallbacks.EvtDevicePrepareHardware = HidFx2EvtDevicePrepareHardware; + + // These two callbacks start and stop the wdfusb pipe continuous reader as we go in and out of the D0-working state. + pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; + + WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &pnpPowerCallbacks); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); + + // Create a framework device object.This call will in turn create a WDM device object, attach to the lower stack. + status = WdfDeviceCreate(&pDeviceInit, &attributes, &hDevice); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfDeviceCreate failed with status code %!STATUS!\n", status); + return status; + } + + pDevContext = GetDeviceContext(hDevice); + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); + queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; + + status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue); + if (!NT_SUCCESS (status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed 0x%x\n", status); + return status; + } + + // Register a manual I/O queue for handling Interrupt Message Read Requests. + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); + + // This queue is used for requests that dont directly access the device. + // The requests in this queue are serviced only when the device is in a fully powered state and sends an interrupt. + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hInterruptMsgQueue); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed %!STATUS!\n", status); + return status; + } + + // Create a timer to handle debouncing of switchpack + WDF_TIMER_CONFIG_INIT(&timerConfig, HidFx2EvtTimerFunction); + timerConfig.AutomaticSerialization = FALSE; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = hDevice; + status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); + return status; + } + + pDevContext->hDebounceTimer = hTimer; + + TraceVerbose(DBG_PNP, "(%!FUNC!) Exit\n"); + return status; +} diff --git a/network/radio/HidSwitchDriverSample/hid.c b/network/radio/HidSwitchDriverSample/hid.c new file mode 100644 index 00000000..27fcefea --- /dev/null +++ b/network/radio/HidSwitchDriverSample/hid.c @@ -0,0 +1,659 @@ +#include <RadioSwitchHidUsbFx2.h> +#include "hid.tmh" + +// Radio Management Collection - Scenario 1 control collection (Button only) +// +const HID_REPORT_DESCRIPTOR c_ButtonDescriptor[] = { + 0x05, GENERIC_DESKTOP_USAGE_PAGE, // USAGE_PAGE (Generic Desktop) + 0x09, WIRELESS_RADIO_CONTROLS_USAGE,// USAGE (Wireless Radio Controls) + 0xA1, 0x01, // COLLECTION (Application) + 0x85, GENERIC_DESKTOP_REPORT_ID, // REPORT_ID + 0x15, 0x00, // LOGICAL_MINIMUM(0) + 0x25, 0x01, // LOGICAL_MAXIMUM(1) + // + 0x09, WIRELESS_RADIO_BUTTON_USAGE, // USAGE (Wireless Radio Button) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x06, // INPUT (Data, Variable, Rel) - button bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x81, 0x03, // INPUT (const, var, abs) -7 bits of padding + 0xC0 // END_COLLECTION +}; + + +// Radio Management Collection - Scenario 2 control collection (Button with LED) +// +const HID_REPORT_DESCRIPTOR c_ButtonWithLedDescriptor[] = { + 0x05, GENERIC_DESKTOP_USAGE_PAGE, // USAGE_PAGE (Generic Desktop) + 0x09, WIRELESS_RADIO_CONTROLS_USAGE,// USAGE (Wireless Radio Controls) + 0xA1, 0x01, // COLLECTION (Application) + 0x85, GENERIC_DESKTOP_REPORT_ID, // REPORT_ID + 0x15, 0x00, // LOGICAL_MINIMUM(0) + 0x25, 0x01, // LOGICAL_MAXIMUM(1) + // + 0x09, WIRELESS_RADIO_BUTTON_USAGE, // USAGE (Wireless Radio Button) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x06, // INPUT (Data, Variable, Rel) - button bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x81, 0x03, // INPUT (const, var, abs) -7 bits of padding + // + 0x09, WIRELESS_RADIO_LED_USAGE, // USAGE (Wireless Radio LED) + 0x75, 0x01, // REPORT_SIZE (1) + 0x91, 0x02, // OUTPUT (Data, Variable, Rel) -led bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x91, 0x03, // OUTPUT (const, var, abs) -7 bits of padding + 0xC0 // END_COLLECTION +}; + + +// Radio Management Collection - Scenario 3 control collection (Slider Switch) +// +const HID_REPORT_DESCRIPTOR c_SliderSwitchDescriptor[] = { + 0x05, GENERIC_DESKTOP_USAGE_PAGE, // USAGE_PAGE (Generic Desktop) + 0x09, WIRELESS_RADIO_CONTROLS_USAGE,// USAGE (Wireless Radio Controls) + 0xA1, 0x01, // COLLECTION (Application) + 0x85, GENERIC_DESKTOP_REPORT_ID, // REPORT_ID + 0x15, 0x00, // LOGICAL_MINIMUM(0) + 0x25, 0x01, // LOGICAL_MAXIMUM(1) + // + 0x09, WIRELESS_RADIO_SLIDER_USAGE, // USAGE (Wireless Radio Slider Switch) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data, Variable, Abs) -switch bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x81, 0x03, // INPUT (const, var, abs) -7 bits of padding + 0xC0 // END_COLLECTION +}; + + +// Radio Management Collection - Scenario 4 control collection (Slider Switch with LED) +// +const HID_REPORT_DESCRIPTOR c_SliderSwitchWithLedDescriptor[] = { + 0x05, GENERIC_DESKTOP_USAGE_PAGE, // USAGE_PAGE (Generic Desktop) + 0x09, WIRELESS_RADIO_CONTROLS_USAGE,// USAGE (Wireless Radio Controls) + 0xA1, 0x01, // COLLECTION (Application) + 0x85, GENERIC_DESKTOP_REPORT_ID, // REPORT_ID + 0x15, 0x00, // LOGICAL_MINIMUM(0) + 0x25, 0x01, // LOGICAL_MAXIMUM(1) + // + 0x09, WIRELESS_RADIO_SLIDER_USAGE, // USAGE (Wireless Radio Slider Switch) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data, Variable, Abs) -switch bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x81, 0x03, // INPUT (const, var, abs) -7 bits of padding + // + 0x09, WIRELESS_RADIO_LED_USAGE, // USAGE (Wireless Radio LED) + 0x75, 0x01, // REPORT_SIZE (1) + 0x91, 0x02, // OUTPUT (Data, Variable, Rel) -led bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x91, 0x03, // OUTPUT (const, var, abs) -7 bits of padding + 0xC0 // END_COLLECTION +}; + + +// Radio Management Collection - Scenario 5 control collection (LED only) +// +const HID_REPORT_DESCRIPTOR c_LedOnlyDescriptor[] = { + 0x05, GENERIC_DESKTOP_USAGE_PAGE, // USAGE_PAGE (Generic Desktop) + 0x09, WIRELESS_RADIO_CONTROLS_USAGE,// USAGE (Wireless Radio Controls) + 0xA1, 0x01, // COLLECTION (Application) + 0x85, GENERIC_DESKTOP_REPORT_ID, // REPORT_ID + 0x15, 0x00, // LOGICAL_MINIMUM(0) + 0x25, 0x01, // LOGICAL_MAXIMUM(1) + // + 0x09, WIRELESS_RADIO_LED_USAGE, // USAGE (Wireless Radio LED) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x91, 0x02, // OUTPUT (Data, Variable, Rel) -led bit + 0x75, 0x07, // REPORT_SIZE (7) + 0x91, 0x03, // OUTPUT (const, var, abs) -7 bits of padding + 0xC0 // END_COLLECTION +}; + + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, HidFx2SetOutput) + #pragma alloc_text(PAGE, HidFx2GetInput) + #pragma alloc_text(PAGE, SendVendorCommand) +#endif + + +// This event is called when the framework receives IRP_MJ_INTERNAL DEVICE_CONTROL requests from the system. +// +void HidFx2EvtInternalDeviceControl( + _In_ WDFQUEUE hQueue, + _In_ WDFREQUEST hRequest, + _In_ size_t cOutputBufferLength, + _In_ size_t cInputBufferLength, + _In_ ULONG ulIoControlCode + ) +{ + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE hDevice; + PDEVICE_EXTENSION pDevContext = NULL; + + UNREFERENCED_PARAMETER(cOutputBufferLength); + UNREFERENCED_PARAMETER(cInputBufferLength); + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); + + hDevice = WdfIoQueueGetDevice(hQueue); + pDevContext = GetDeviceContext(hDevice); + + TraceInfo(DBG_IOCTL, "(%!FUNC!) Queue:0x%p, Request:0x%p\n", hQueue, hRequest); + + switch (ulIoControlCode) + { + case IOCTL_HID_GET_DEVICE_DESCRIPTOR: + TraceInfo(DBG_IOCTL, "IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"); + status = HidFx2GetHidDescriptor(hDevice, hRequest); + WdfRequestComplete(hRequest, status); + break; + + case IOCTL_HID_GET_DEVICE_ATTRIBUTES: + TraceInfo(DBG_IOCTL, "IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"); + status = HidFx2GetDeviceAttributes(hRequest); + WdfRequestComplete(hRequest, status); + break; + + case IOCTL_HID_GET_REPORT_DESCRIPTOR: + TraceInfo(DBG_IOCTL, "IOCTL_HID_GET_REPORT_DESCRIPTOR\n"); + status = HidFx2GetReportDescriptor(hDevice, hRequest); + WdfRequestComplete(hRequest, status); + break; + + case IOCTL_HID_READ_REPORT: + TraceInfo(DBG_IOCTL, "IOCTL_HID_READ_REPORT\n"); + status = WdfRequestForwardToIoQueue(hRequest, pDevContext->hInterruptMsgQueue); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_IOCTL, "WdfRequestForwardToIoQueue failed with status: %!STATUS!\n", status); + WdfRequestComplete(hRequest, status); + } + break; + + case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: + TraceInfo(DBG_IOCTL, "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST\n"); + status = HidFx2SendIdleNotification(hRequest); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_IOCTL, "SendIdleNotification failed with status: %!STATUS!\n", status); + WdfRequestComplete(hRequest, status); + } + break; + + case IOCTL_HID_GET_INPUT_REPORT: + TraceInfo(DBG_IOCTL, "IOCTL_HID_GET_INPUT_REPORT\n"); + HidFx2GetInput(hRequest); + WdfRequestComplete(hRequest, status); + break; + + case IOCTL_HID_SET_OUTPUT_REPORT: + TraceInfo(DBG_IOCTL, "IOCTL_HID_SET_OUTPUT_REPORT\n"); + status = HidFx2SetOutput(hRequest); + WdfRequestComplete(hRequest, status); + break; + + default: + TraceInfo(DBG_IOCTL, "IOCTL Not Supported 0x%X\n", ulIoControlCode); + status = STATUS_NOT_SUPPORTED; + WdfRequestComplete(hRequest, status); + break; + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit\n"); + return; +} + + + +NTSTATUS HidFx2GetInput(_In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_REQUEST_PARAMETERS params; + WDFDEVICE hDevice; + PHID_XFER_PACKET pTransferPacket = NULL; + PHIDFX2_IO_REPORT pOutputReport = NULL; + unsigned char bSwitchState = 0; + + PAGED_CODE(); + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); + + hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + WdfRequestGetParameters(hRequest, ¶ms); + + + if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); + return status; + } + + pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; + if (pTransferPacket == NULL) + { + status = STATUS_INVALID_DEVICE_REQUEST; + TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportBufferLen == 0) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) + { + status = STATUS_INVALID_DEVICE_REQUEST; + TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); + return status; + } + + pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; + + // Get the switch state directly from the hardware + status = HidFx2GetSwitchState(hDevice, &bSwitchState); + TraceVerbose(DBG_IOCTL, "(%!FUNC!) switch state 0x%x\n", bSwitchState); + + //Mask off everything except the actual switch bit + bSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK; + TraceVerbose(DBG_IOCTL, "(%!FUNC!) maskedswitch state 0x%x\n", bSwitchState); + + pOutputReport->bReportId = GENERIC_DESKTOP_REPORT_ID; + pOutputReport->bData = bSwitchState; + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); + return status; +} + + + +NTSTATUS HidFx2SetOutput(_In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + PHID_XFER_PACKET pTransferPacket = NULL; + WDF_REQUEST_PARAMETERS params; + PHIDFX2_IO_REPORT pOutputReport = NULL; + WDFDEVICE hDevice; + + PAGED_CODE(); + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); + + hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + WdfRequestGetParameters(hRequest, ¶ms); + + if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); + return status; + } + + pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; + if (pTransferPacket == NULL) + { + status = STATUS_INVALID_DEVICE_REQUEST; + TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportBufferLen == 0) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); + return status; + } + + if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) + { + status = STATUS_INVALID_DEVICE_REQUEST; + TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); + return status; + } + + pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; + + if (pOutputReport->bData == 0) + { + status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF); + } + else + { + status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_ON); + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); + return status; +} + + + +//This routine sets the state of the Feature: in this case Segment Display on the USB FX2 board. +NTSTATUS SendVendorCommand(_In_ WDFDEVICE hDevice, _In_ unsigned char bVendorCommand, _In_ unsigned char bCommandData) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG cBytesTransferred = 0; + PDEVICE_EXTENSION pDevContext = NULL; + WDF_MEMORY_DESCRIPTOR memDesc; + WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; + WDF_REQUEST_SEND_OPTIONS sendOptions; + + PAGED_CODE(); + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); + + pDevContext = GetDeviceContext(hDevice); + + TraceInfo(DBG_IOCTL, "(%!FUNC!): Command:0x%x, data: 0x%x\n", bVendorCommand, bCommandData); + + // Send the I/O with a timeout. + // We do that because we send the I/O in the context of the user thread and if it gets stuck, it would prevent the user process from existing. + WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); + + WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_SEC(5)); + + WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, + BmRequestHostToDevice, + BmRequestToDevice, + bVendorCommand, // Request + 0, // Value + 0); // Index + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, &bCommandData, sizeof(bCommandData)); + + status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDevContext->hUsbDevice, + WDF_NO_HANDLE, // Optional WDFREQUEST + &sendOptions, // PWDF_REQUEST_SEND_OPTIONS + &controlSetupPacket, + &memDesc, + &cBytesTransferred); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_IOCTL, "(%!FUNC!): Failed to set Segment Display state - %!STATUS!\n", status); + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit\n"); + + return status; +} + + + +// Finds the HID descriptor and copies it into the buffer provided by the Request. +// +NTSTATUS HidFx2GetHidDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + size_t cBytesToCopy = 0; + WDFMEMORY memory; + PDEVICE_EXTENSION pDevContext = NULL; + HID_DESCRIPTOR hidDescriptor; + + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); + + status = WdfRequestRetrieveOutputMemory(hRequest, &memory); + if (NT_SUCCESS(status)) + { + hidDescriptor.bLength= sizeof(hidDescriptor); // length of HID descriptor + hidDescriptor.bDescriptorType= HID_HID_DESCRIPTOR_TYPE; // descriptor type == HID 0x21 + hidDescriptor.bcdHID= HID_CLASS_SPEC_RELEASE_1_00; // hid spec release + hidDescriptor.bCountry= HID_COUNTRY_NON_LOCALIZED; // country code + hidDescriptor.bNumDescriptors= 0x01; // number of HID class descriptors + hidDescriptor.DescriptorList[0].bReportType =HID_REPORT_DESCRIPTOR_TYPE; + hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_ButtonDescriptor); + + pDevContext = GetDeviceContext(hDevice); + if (pDevContext != NULL) + { + // Set length of non default report descriptor + switch (pDevContext->driverMode) + { + case DM_BUTTON_AND_LED: + hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_ButtonWithLedDescriptor); + break; + case DM_SLIDER_SWITCH: + hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_SliderSwitchDescriptor); + break; + case DM_SLIDER_SWITCH_AND_LED: + hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_SliderSwitchWithLedDescriptor); + break; + case DM_LED_ONLY: + hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_LedOnlyDescriptor); + break; + default: + break; + } + } + cBytesToCopy = hidDescriptor.bLength; + if (cBytesToCopy != 0) + { + status = WdfMemoryCopyFromBuffer(memory, 0, (PVOID)&hidDescriptor, cBytesToCopy); + if (NT_SUCCESS(status)) + { + // Report how many bytes were copied + WdfRequestSetInformation(hRequest, cBytesToCopy); + } + else // WdfMemoryCopyFromBuffer failed + { + TraceErr(DBG_IOCTL, "(%!FUNC!) WdfMemoryCopyFromBuffer failed %!STATUS!\n", status); + return status; + } + } + else // length is zero + { + status = STATUS_INVALID_DEVICE_STATE; + TraceErr(DBG_IOCTL, "(%!FUNC!) c_DefaultHidDescriptor is zero, %!STATUS!\n", status); + return status; + } + + } + else // WdfRequestRetrieveOutputMemory failed + { + TraceErr(DBG_IOCTL, " (%!FUNC!) WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); + return status; + } + + TraceVerbose(DBG_IOCTL, " (%!FUNC!) HidFx2GetHidDescriptor Exit = %!STATUS!\n", status); + return status; +} + + + +// Finds the Report descriptor and copies it into the buffer provided by the Request. +// +NTSTATUS HidFx2GetReportDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + WDFMEMORY memory; + PDEVICE_EXTENSION pDevContext = NULL; + PVOID pBuffer = (PVOID)c_ButtonDescriptor; + size_t cBytesToCopy = sizeof(c_ButtonDescriptor); + + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); + + status = WdfRequestRetrieveOutputMemory(hRequest, &memory); + if (NT_SUCCESS(status)) + { + pDevContext = GetDeviceContext(hDevice); + if (pDevContext != NULL) + { + // Select a non default report descriptor + switch (pDevContext->driverMode) + { + case DM_BUTTON_AND_LED: + pBuffer = (PVOID)c_ButtonWithLedDescriptor; + cBytesToCopy = sizeof(c_ButtonWithLedDescriptor); + break; + case DM_SLIDER_SWITCH: + pBuffer = (PVOID)c_SliderSwitchDescriptor; + cBytesToCopy = sizeof(c_SliderSwitchDescriptor); + break; + case DM_SLIDER_SWITCH_AND_LED: + pBuffer = (PVOID)c_SliderSwitchWithLedDescriptor; + cBytesToCopy = sizeof(c_SliderSwitchWithLedDescriptor); + break; + case DM_LED_ONLY: + pBuffer = (PVOID)c_LedOnlyDescriptor; + cBytesToCopy = sizeof(c_LedOnlyDescriptor); + break; + default: + break; + } + } + if (cBytesToCopy != 0) + { + status = WdfMemoryCopyFromBuffer(memory, 0, pBuffer, cBytesToCopy); + if (NT_SUCCESS(status)) + { + // Report how many bytes were copied + WdfRequestSetInformation(hRequest, cBytesToCopy); + } + else // WdfMemoryCopyFromBuffer failed + { + TraceErr(DBG_IOCTL, "(%!FUNC!) WdfMemoryCopyFromBuffer failed %!STATUS!\n", status); + } + } + else // report length is zero + { + status = STATUS_INVALID_DEVICE_STATE; + TraceErr(DBG_IOCTL, "(%!FUNC!) c_DefaultHidDescriptor's reportLength is zero, %!STATUS!\n", status); + } + } + else // WdfRequestRetrieveOutputMemory failed + { + TraceErr(DBG_IOCTL, "(%!FUNC!)WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); + + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); + return status; +} + + + +// Fill in the given struct _HID_DEVICE_ATTRIBUTES +// +NTSTATUS HidFx2GetDeviceAttributes(_In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + PHID_DEVICE_ATTRIBUTES pDeviceAttributes = NULL; + PUSB_DEVICE_DESCRIPTOR pUsbDeviceDescriptor = NULL; + PDEVICE_EXTENSION pDeviceInfo = NULL; + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); + + pDeviceInfo = GetDeviceContext(WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest))); + status = WdfRequestRetrieveOutputBuffer(hRequest, sizeof (HID_DEVICE_ATTRIBUTES), &pDeviceAttributes, NULL); + if (NT_SUCCESS(status)) + { + // Retrieve USB device descriptor saved in device context + pUsbDeviceDescriptor = WdfMemoryGetBuffer(pDeviceInfo->hDeviceDescriptor, NULL); + pDeviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES); + pDeviceAttributes->VendorID = pUsbDeviceDescriptor->idVendor; + pDeviceAttributes->ProductID = pUsbDeviceDescriptor->idProduct; + pDeviceAttributes->VersionNumber = pUsbDeviceDescriptor->bcdDevice; + // Report how many bytes were copied + WdfRequestSetInformation(hRequest, sizeof (HID_DEVICE_ATTRIBUTES)); + } + else // WdfRequestRetrieveOutputBuffer failed + { + TraceErr(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer failed %!STATUS!\n", status); + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); + return status; +} + + + +// Pass down Idle notification request to lower driver +// +NTSTATUS HidFx2SendIdleNotification(_In_ WDFREQUEST hRequest) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_REQUEST_SEND_OPTIONS options; + WDFIOTARGET hNextLowerDriver; + WDFDEVICE hDevice; + PIO_STACK_LOCATION pCurrentIrpStack = NULL; + IO_STACK_LOCATION nextIrpStack; + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); + + hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); + pCurrentIrpStack = IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(hRequest)); + + // Convert the request to corresponding USB Idle notification request + if (pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)) + { + ASSERT(sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)); + #pragma warning(suppress :4127) // conditional expression is constant warning + if (sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)) + { + // prepare next stack location + RtlZeroMemory(&nextIrpStack, sizeof(IO_STACK_LOCATION)); + nextIrpStack.MajorFunction = pCurrentIrpStack->MajorFunction; + nextIrpStack.Parameters.DeviceIoControl.InputBufferLength = pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength; + nextIrpStack.Parameters.DeviceIoControl.Type3InputBuffer = pCurrentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; + nextIrpStack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION; + nextIrpStack.DeviceObject = WdfIoTargetWdmGetTargetDeviceObject(WdfDeviceGetIoTarget(hDevice)); + + // Format the I/O request for the driver's local I/O target by using the contents of the specified WDM I/O stack location structure. + WdfRequestWdmFormatUsingStackLocation(hRequest, &nextIrpStack); + + // Send the request down using Fire and forget option. + WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); + hNextLowerDriver = WdfDeviceGetIoTarget(hDevice); + if (WdfRequestSend(hRequest, hNextLowerDriver, &options) == FALSE) + { + status = STATUS_UNSUCCESSFUL; + } + } + else // Incorrect DeviceIoControl.InputBufferLength + { + status = STATUS_INFO_LENGTH_MISMATCH; + TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect DeviceIoControl.InputBufferLength, %!STATUS!\n", status); + return status; + } + } + else // DeviceIoControl.InputBufferLength too small + { + status = STATUS_BUFFER_TOO_SMALL; + TraceErr(DBG_IOCTL, "(%!FUNC!) DeviceIoControl.InputBufferLength too small, %!STATUS!\n", status); + return status; + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); + return status; +} + + + + + diff --git a/network/radio/HidSwitchDriverSample/trace.h b/network/radio/HidSwitchDriverSample/trace.h new file mode 100644 index 00000000..0ec09b91 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/trace.h @@ -0,0 +1,13 @@ +#pragma once + +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID(HidUsbFx2TraceGuid, (091182d7, 5167, 4e77, aa80, ca6c1e6201e9), \ + WPP_DEFINE_BIT(DBG_INIT) \ + WPP_DEFINE_BIT(DBG_PNP) \ + WPP_DEFINE_BIT(DBG_IOCTL) \ + ) + +#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) diff --git a/network/radio/HidSwitchDriverSample/usb.c b/network/radio/HidSwitchDriverSample/usb.c new file mode 100644 index 00000000..e6ac2da7 --- /dev/null +++ b/network/radio/HidSwitchDriverSample/usb.c @@ -0,0 +1,466 @@ +#include <RadioSwitchHidUsbFx2.h> +#include "usb.tmh" + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, HidFx2EvtDevicePrepareHardware) +#pragma alloc_text(PAGE, HidFx2EvtDeviceD0Exit) +#pragma alloc_text(PAGE, HidFx2ConfigContReaderForInterruptEndPoint) +#endif + + +// In this callback, the driver does whatever is necessary to make the hardware ready to use. +// In the case of a USB device, this involves reading and selecting descriptors. +NTSTATUS +HidFx2EvtDevicePrepareHardware( + _In_ WDFDEVICE hDevice, + _In_ WDFCMRESLIST hResourceList, + _In_ WDFCMRESLIST hResourceListTranslated + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PDEVICE_EXTENSION pDevContext = NULL; + WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; + WDF_OBJECT_ATTRIBUTES attributes; + PUSB_DEVICE_DESCRIPTOR pUsbDeviceDescriptor = NULL; + + UNREFERENCED_PARAMETER(hResourceList); + UNREFERENCED_PARAMETER(hResourceListTranslated); + + PAGED_CODE (); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n"); + + pDevContext = GetDeviceContext(hDevice); + + // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the USB device descriptor and the first USB configuration + //descriptor from the device and stores them. It also creates a framework USB interface object for each interface in the device's first configuration. + // + // The parent of each USB device object is the driver's framework driver object. The driver cannot change this parent, and the ParentObject + // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL. + // + // We only create device the first time PrepareHardware is called. If the device is restarted by pnp manager for resource rebalance, we + // will use the same device handle but then select the interfaces again because the USB stack could reconfigure the device on restart. + if (pDevContext->hUsbDevice == NULL) + { + status = WdfUsbTargetDeviceCreate(hDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hUsbDevice); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceCreate failed %!STATUS!\n", status); + return status; + } + } + + // Select a device configuration by using a WDF_USB_DEVICE_SELECT_CONFIG_PARAMS + WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams); + status = WdfUsbTargetDeviceSelectConfig(pDevContext->hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status); + return status; + } + + pDevContext->hUsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; + + // Get the device descriptor and store it in device context + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = hDevice; + status = WdfMemoryCreate(&attributes, + NonPagedPool, + 0, + sizeof(USB_DEVICE_DESCRIPTOR), + &pDevContext->hDeviceDescriptor, + &pUsbDeviceDescriptor); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_PNP, "(%!FUNC!) WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status); + return status; + } + + WdfUsbTargetDeviceGetDeviceDescriptor(pDevContext->hUsbDevice, pUsbDeviceDescriptor); + + // Get the Interrupt pipe. There are other endpoints but we are only interested in interrupt endpoint since our HID data comes from this + pDevContext->hInterruptPipe = WdfUsbInterfaceGetConfiguredPipe(pDevContext->hUsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL); + if (NULL == pDevContext->hInterruptPipe) + { + TraceErr(DBG_PNP, "(%!FUNC!) Failed to get interrupt pipe info\n"); + status = STATUS_INVALID_DEVICE_STATE; + return status; + } + + // Tell the framework that it's okay to read less than MaximumPacketSize + WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDevContext->hInterruptPipe); + + //configure continuous reader + status = HidFx2ConfigContReaderForInterruptEndPoint(pDevContext); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, Status: %!STATUS!\n", status); + + return status; +} + + + +// This routine configures a continuous reader on the interrupt endpoint. It's called from the PrepareHarware event. +// +NTSTATUS HidFx2ConfigContReaderForInterruptEndPoint(PDEVICE_EXTENSION pDeviceContext) +{ + WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig; + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE (); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n"); + + WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig, + HidFx2EvtUsbInterruptPipeReadComplete, + pDeviceContext, // Context + sizeof(UCHAR)); // TransferLength + + status = WdfUsbTargetPipeConfigContinuousReader(pDeviceContext->hInterruptPipe, &contReaderConfig); + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_INIT, "(%!FUNC!) failed %!STATUS!\n", status); + } + + TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, status: %!STATUS!\n", status); + + return status; +} + + + +// This the completion routine of the continuous reader. This can called concurrently on multiprocessor system if there are +// more than one readers configured. So make sure to protect access to global resources. +// +void HidFx2EvtUsbInterruptPipeReadComplete( + WDFUSBPIPE hPipe, + WDFMEMORY hBuffer, + size_t cNumBytesTransferred, + WDFCONTEXT pContext + ) +{ + PDEVICE_EXTENSION pDevContext = pContext; + BOOLEAN fInTimerQueue; + unsigned char *pbSwitchState = NULL; + unsigned char bCurrentSwitchState = 0; + unsigned char bPrevSwitchState = 0; + unsigned char bToggledSwitch = 0; + + UNREFERENCED_PARAMETER(cNumBytesTransferred); + UNREFERENCED_PARAMETER(hPipe); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n"); + + // Interrupt endpoints sends switch state when first started or when resuming from suspend. + // We need to ignore that data since user did not change the switch state. + if (pDevContext->fIsPowerUpSwitchState) + { + pDevContext->fIsPowerUpSwitchState = FALSE; + TraceInfo(DBG_INIT, "(%!FUNC!) Dropping interrupt message since received during powerup/resume\n"); + return; + } + + + // Make sure that there is data in the read packet. + // Depending on the device specification, it is possible for it to return a 0 length read in certain conditions. + if (cNumBytesTransferred == 0) + { + TraceWarning(DBG_INIT, "(%!FUNC!) Zero length read occured on the Interrupt Pipe's Continuous Reader\n"); + return; + } + + pbSwitchState = WdfMemoryGetBuffer(hBuffer, NULL); + bCurrentSwitchState = ~(*pbSwitchState); // switchs are inverted on hardware boards + bCurrentSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK; //Mask off everything except the actual radio switch bit + bPrevSwitchState = pDevContext->bCurrentSwitchState; + + if (bPrevSwitchState ^ bCurrentSwitchState) // make sure we toggled the radio switch + { + switch(pDevContext->driverMode) + { + // If it's a slider switch we want 0->1 and 1->0 transitions. + case DM_SLIDER_SWITCH: + case DM_SLIDER_SWITCH_AND_LED: + bToggledSwitch = bCurrentSwitchState; + // A timer is started for 10 ms everytime there is a switch toggled + fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME)); + TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue); + break; + //If it's a button so we only report 0->1 transitions + case DM_BUTTON: + case DM_BUTTON_AND_LED: + bToggledSwitch = (bPrevSwitchState ^ bCurrentSwitchState) & bCurrentSwitchState; + if (bToggledSwitch != 0) + { + // A timer is started for 10 ms everytime there is a switch toggled on + fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME)); + TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue); + } + break; + // Ignore button presses if LED only + case DM_LED_ONLY: + default: + break; + } + + // Store switch state in device context + pDevContext->bCurrentSwitchState = bCurrentSwitchState; + pDevContext->bLatestToggledSwitch = bToggledSwitch; + } + else + { + TraceInfo(DBG_INIT, "(%!FUNC!) Not a radio switch toggle\n"); + } + TraceInfo(DBG_INIT, "(%!FUNC!) Switch 0x%x, prevSwitch:0x%x, X0R:0x%x\n", bCurrentSwitchState, bPrevSwitchState, bToggledSwitch); + + TraceVerbose(DBG_INIT, "(%!FUNC!) Exit\n"); +} + + + +// This function gets called when the timeout period of debounce timer elapses. +// It reports a switch change by completing a pending request +// +void HidFx2EvtTimerFunction(_In_ WDFTIMER hTimer) +{ + WDFDEVICE hDevice = NULL; + WDFREQUEST hRequest; + PDEVICE_EXTENSION pDevContext = NULL; + NTSTATUS status = STATUS_SUCCESS; + size_t cBytesReturned = 0; + unsigned char bToggledSwitch = 0; + ULONG cBytesToCopy = 0; + PHIDFX2_IO_REPORT pInputReport = NULL; + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); + + + hDevice = WdfTimerGetParentObject(hTimer); + pDevContext = GetDeviceContext(hDevice); + + bToggledSwitch = pDevContext->bLatestToggledSwitch; + TraceInfo(DBG_IOCTL, "(%!FUNC!) mode %d switch %d\n", pDevContext->driverMode, bToggledSwitch); + + if (!((pDevContext->driverMode == DM_BUTTON || pDevContext->driverMode == DM_BUTTON_AND_LED) && bToggledSwitch == 0)) + { + // Check if there are any pending requests in the Interrupt Message Queue. + // If a request is found then complete the pending request. + status = WdfIoQueueRetrieveNextRequest(pDevContext->hInterruptMsgQueue, &hRequest); + if (NT_SUCCESS(status)) + { + cBytesToCopy = sizeof(pInputReport[0]); + status = WdfRequestRetrieveOutputBuffer(hRequest, + cBytesToCopy, + &pInputReport, + &cBytesReturned); // BufferLength + if (NT_SUCCESS(status)) + { + TraceInfo(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer switch %d\n", bToggledSwitch); + + pInputReport->bReportId = GENERIC_DESKTOP_REPORT_ID; + pInputReport->bData = bToggledSwitch; + cBytesReturned = cBytesToCopy; + } + else // WdfRequestRetrieveOutputBuffer failed + { + TraceErr(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer failed with status: %!STATUS!\n", status); + } + + WdfRequestCompleteWithInformation(hRequest, status, cBytesReturned); + + } + else if (status != STATUS_NO_MORE_ENTRIES) + { + TraceErr(DBG_IOCTL, "(%!FUNC!) WdfIoQueueRetrieveNextRequest status %!STATUS!\n", status); + } + } + else + { + TraceInfo(DBG_IOCTL, "(%!FUNC!) ignore switch"); + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit\n"); +} + + + +// This function gets the switch state of the USB device directly from the hardware +// +NTSTATUS HidFx2GetSwitchState(_In_ WDFDEVICE hDevice, _Out_ unsigned char *pbSwitchState) +{ + PDEVICE_EXTENSION pDevContext = NULL; + NTSTATUS status = STATUS_SUCCESS; + WDF_MEMORY_DESCRIPTOR memDesc; + WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; + ULONG cBytesTransferred = 0; + + if(pbSwitchState != NULL) + { + *pbSwitchState = 0; + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); + + pDevContext = GetDeviceContext(hDevice); + + // set the segment state on the USB device + WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, + BmRequestDeviceToHost, + BmRequestToDevice, + HIDFX2_READ_SWITCH_STATE, // Request + 0, // Value + 0); // Index + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, pbSwitchState, sizeof(*pbSwitchState)); + + status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDevContext->hUsbDevice, + NULL, // Optional WDFREQUEST + NULL, // PWDF_REQUEST_SEND_OPTIONS + &controlSetupPacket, + &memDesc, + &cBytesTransferred); + + if (!NT_SUCCESS(status)) + { + TraceErr(DBG_IOCTL, "(%!FUNC!) Failed to read switch state - %!STATUS! \n", status); + } + else + { + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Switch state is 0x%x\n", *pbSwitchState); + *pbSwitchState = ~(*pbSwitchState); // switchs are inverted on hardware boards + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Switch state is 0x%x\n", *pbSwitchState); + } + + TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit, status: %!STATUS!\n", status); + return status; +} + + + +// EvtDeviceD0Entry event callback must perform any operations that are necessary before the specified device is used. +// Called every time the hardware needs to be initialized/reinitialized. +// This function is not marked pageable because this function is in the device power up path. +// This function runs at PASSIVE_LEVEL, even though it is not paged. +// +NTSTATUS HidFx2EvtDeviceD0Entry(_In_ WDFDEVICE hDevice, _In_ WDF_POWER_DEVICE_STATE previousState) +{ + PDEVICE_EXTENSION pDevContext = NULL; + NTSTATUS status = STATUS_SUCCESS; + unsigned char bSwitchState = 0; + unsigned char bMode = 0; + + pDevContext = GetDeviceContext(hDevice); + + TraceVerbose(DBG_PNP, "(%!FUNC!) Enter - coming from %S\n", DbgDevicePowerString(previousState)); + + SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF); + + // Retrieve the current switch state and store it in device context + status = HidFx2GetSwitchState(hDevice, &bSwitchState); + if (NT_SUCCESS(status)) + { + // Left most switches define Mode + bMode = bSwitchState & MODE_SELECTION_BUTTONS_BIT_MASK; + switch (bMode) + { + case SWITCHPACK_SELECTION_FOR_MODE2: + pDevContext->driverMode = DM_BUTTON_AND_LED; + SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_2); + break; + case SWITCHPACK_SELECTION_FOR_MODE3: + pDevContext->driverMode = DM_SLIDER_SWITCH; + SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_3); + break; + case SWITCHPACK_SELECTION_FOR_MODE4: + pDevContext->driverMode = DM_SLIDER_SWITCH_AND_LED; + SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_4); + break; + case SWITCHPACK_SELECTION_FOR_MODE5: + pDevContext->driverMode = DM_LED_ONLY; + SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_5); + break; + default: + pDevContext->driverMode = DM_BUTTON; + SendVendorCommand(hDevice, HIDFX2_SET_7SEGMENT_DISPLAY, SEGMENT_DISPLAY_1); + break; + } + + pDevContext->bCurrentSwitchState = bSwitchState; + + // Start the target. This will start the continuous reader + status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDevContext->hInterruptPipe)); + if (NT_SUCCESS(status)) + { + pDevContext->fIsPowerUpSwitchState = TRUE; + } + } + else + { + TraceErr(DBG_PNP, "(%!FUNC!) Failed to get current switch state, status: %!STATUS!\n", status); + } + + TraceVerbose(DBG_PNP, "(%!FUNC!) Exit, status: %!STATUS!\n", status); + return status; +} + + + +/* +This routine undoes anything done in EvtDeviceD0Entry. It is called whenever the device leaves the D0 state, which happens when the device is +stopped, when it is removed, and when it is powered off. + +The device is still in D0 when this callback is invoked, which means that the driver can still touch hardware in this routine. + +EvtDeviceD0Exit event callback must perform any operations that are necessary before the specified device is moved out of the D0 state. +If the driver needs to save hardware state before the device is powered down, then that should be done here. + +This function runs at PASSIVE_LEVEL, though it is generally not paged. A driver can optionally make this function pageable if DO_POWER_PAGABLE is set. + +Even if DO_POWER_PAGABLE isn't set, this function still runs at PASSIVE_LEVEL. +In this case, though, the function absolutely must not do anything that will cause a page fault. +*/ +NTSTATUS HidFx2EvtDeviceD0Exit(_In_ WDFDEVICE hDevice, _In_ WDF_POWER_DEVICE_STATE targetState) +{ + PDEVICE_EXTENSION pDevContext; + + PAGED_CODE(); + + TraceVerbose(DBG_PNP, "(%!FUNC!) Enter- moving to %S\n", DbgDevicePowerString(targetState)); + + pDevContext = GetDeviceContext(hDevice); + + WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pDevContext->hInterruptPipe), WdfIoTargetCancelSentIo); + + TraceVerbose(DBG_PNP, "(%!FUNC!) Exit\n"); + + return STATUS_SUCCESS; +} + + + +PCWSTR DbgDevicePowerString(_In_ WDF_POWER_DEVICE_STATE powerState) +{ + switch (powerState) + { + case WdfPowerDeviceInvalid: + return L"WdfPowerDeviceInvalid"; + case WdfPowerDeviceD0: + return L"WdfPowerDeviceD0"; + case PowerDeviceD1: + return L"WdfPowerDeviceD1"; + case WdfPowerDeviceD2: + return L"WdfPowerDeviceD2"; + case WdfPowerDeviceD3: + return L"WdfPowerDeviceD3"; + case WdfPowerDeviceD3Final: + return L"WdfPowerDeviceD3Final"; + case WdfPowerDevicePrepareForHibernation: + return L"WdfPowerDevicePrepareForHibernation"; + case WdfPowerDeviceMaximum: + return L"PowerDeviceMaximum"; + default: + return L"UnKnown Device Power State"; + } +} + diff --git a/network/radio/RadioManagerSample/RadioManagerSample.sln b/network/radio/RadioManagerSample/RadioManagerSample.sln new file mode 100644 index 00000000..d5d0a144 --- /dev/null +++ b/network/radio/RadioManagerSample/RadioManagerSample.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleRM", "cpp\SampleRM.vcxproj", "{165D39D6-68AC-4E1F-89ED-483E13E84F9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|Win32.ActiveCfg = Debug|Win32 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|Win32.Build.0 = Debug|Win32 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|Win32.ActiveCfg = Release|Win32 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|Win32.Build.0 = Release|Win32 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|x64.ActiveCfg = Debug|x64 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Debug|x64.Build.0 = Debug|x64 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|x64.ActiveCfg = Release|x64 + {165D39D6-68AC-4E1F-89ED-483E13E84F9B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/network/radio/RadioManagerSample/ReadMe.md b/network/radio/RadioManagerSample/ReadMe.md new file mode 100644 index 00000000..4c481bbd --- /dev/null +++ b/network/radio/RadioManagerSample/ReadMe.md @@ -0,0 +1,171 @@ +Windows Radio Management Sample +=============================== + +The Radio Manager sample demonstrates how to structure a Radio Manager for use with the Windows 8.1 Radio Management APIs. + +Starting with Windows 8.1, the operating system contains a set of APIs which are used as a software mechanism to control the various radios found on the machine. The APIs work by communicating with a Radio Manager, which is a COM object that relays commands from the APIs to turn the radio on or off, and reports back radio information to the APIs. This feature is designed in such a way that a separate Radio Manager is required for each radio media type. For example, a WLAN radio will be controlled by a different Radio Manager than a GPS radio. If there are 2 WLAN radios and a GPS radio, the 2 WLAN radios will be controlled by one Radio Manager, and the GPS radio will be controlled by a different Radio Manager. The Radio Manager must be able to run correctly within Local Service Account context. Under this context, the Radio Manager will have the minimum privilege on the local computer. + +When the user turns the radio off (either by using the specific radio software switch or the airplane mode switch), radio transmission must be turned off. The device can be powered off as long as the radio switch does not disappear from the UI. It is very important that the radio manager developer ensures that when the device is powered off, the radio switch does not disappear from the UI. If the radio switch disappears from the UI when the radio is turned off by the user, then user has no way to turn the radio back on! If it is desired to conserve power by cutting power to the device when the radio is turned off, but the device cannot be completely powered off because it disappears from the UI, then the solution would be to put the device in a low power state (e.g. D3). + +**Important** The radio manager MUST be given a name. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port"). + + +Installation +------------ + +The sample contains a script, *install.cmd*, which copies the radio manager DLL to the system directory, registers as a COM component, and configures the registry. + +Copy the *install.cmd*, *SampleRM.reg* and *SampleRM.dll* files to a directory. Run *install.cmd*. + +Code Tour +--------- + +File + +Description + +install.cmd + +Installation script. Copies and registers the dll and executes SampleRM.reg. + +SampleRM.reg + +script to install the Sample Radio Manager into the registry, along with 2 radio instances. + +SampleRM.sln + +The Visual Studio solution file for building the Sample Radio Manager dll. + +sampleRM.idl + +The interface definition for the Sample Radio Manager. + +RadioMgr.idl + +The interface definition for a Windows Radio Manager. + +SampleRadioManager.h + +Header file for the functions required for a Radio Manager. + +SampleRadioInstance.h + +Header file for the functions required for a Radio Instance. + +SampleInstanceCollection.h + +Header file for the functions required for a Collection of Radio Instances. + +precomp.h + +Common header file. + +InternalInterfaces.h + +Header file for internal interface used for this sample. + +dllmain.cpp + +Standard dllmain. + +SampleRadioManager.cpp + +Implementation details for the Sample Radio Manager. Important concepts include: + +- Utilizing [IMediaRadioManagerNotifySink](http://msdn.microsoft.com/en-us/library/windows/hardware/hh406534) for radio instance events +- Adding/Removing radio instances +- Queuing and deploying worker jobs for system events + +SampleRadioInstance.cpp + +Implementation details for the Sample Radio Instance. Important concepts include: + +- Accessors & Modifiers for radio information +- Instance change functions + +SampleInstanceCollection.cpp + +Implementation details for the Sample Instance Collection. Important concepts include:l + +- Radio Instance discovery and retrieval + +RadioMgr\_interface.cpp + +Helper source file to include the MIDL-generated files. + +Run the sample +-------------- + +Operation +--------- + +This sample Radio Manager does not operate on an actual radio. Instead, it uses registry keys to act as virtual radios. + +Each "radio" instance can have the following values: + +Name + +RadioState + +PreviousRadioState + +IsMultiComm + +IsAssociatingDevice + +\*\*\* It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will fail to initialize. \*\*\* + +**Important** The radio manager must be given a name and the registry key must have, as a minimum, a Name value. Otherwise, the Sample Radio Manager will fail to initialize. This is the name of the radio switch that is displayed to the user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's name or some other word related to the functionality of the radio (e.g. "Location" OR "port"). + +When the Radio Manager is initialized, it uses these registry keys to retrieve the "radio" information. The radio state values can be any of the following enum values: + +<table> +<colgroup> +<col width="100%" /> +</colgroup> +<thead> +<tr class="header"> +<th align="left">C++</th> +</tr> +</thead> +<tbody> +<tr class="odd"> +<td align="left"><pre><code>typedef enum _DEVICE_RADIO_STATE +{ + DRS_RADIO_ON = 0, + DRS_SW_RADIO_OFF = 1, + DRS_HW_RADIO_OFF = 2, + DRS_SW_HW_RADIO_OFF = 3, + DRS_HW_RADIO_ON_UNCONTROLLABLE = 4, + DRS_RADIO_INVALID = 5, + DRS_HW_RADIO_OFF_UNCONTROLLABLE = 6, + DRS_RADIO_MAX = DRS_HW_RADIO_OFF_UNCONTROLLABLE +} DEVICE_RADIO_STATE;</code></pre></td> +</tr> +</tbody> +</table> + +For IsMultiComm and IsAssociatingDevice, a value of 0 means 'no' and 1 means 'yes'. + +Adding and Setting a Radio Instance +----------------------------------- + +To add a new radio instance, add a new instance key to the registry key like the following entry: + +``` {.syntax xml:space="preserve"} +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\RadioManagement\Misc\SampleRadioManager\SampleRadioX] +"RadioState"=dword:00000000 +"Name"="SampleRadioX" +"IsMultiComm"=dword:00000000 +``` + +Editing a Radio Instance +------------------------ + +Simply change the values in the registry. For example, change the radio state from DRS\_RADIO\_ON to DRS\_SW\_RADIO\_OFF by changing the 'RadioState' value from 0 to 1. + +Removing a Radio Instance +------------------------- + +Delete the corresponding registry key. + diff --git a/network/radio/RadioManagerSample/SampleRM.reg b/network/radio/RadioManagerSample/SampleRM.reg Binary files differnew file mode 100644 index 00000000..3ba004f1 --- /dev/null +++ b/network/radio/RadioManagerSample/SampleRM.reg diff --git a/network/radio/RadioManagerSample/cpp/InternalInterfaces.h b/network/radio/RadioManagerSample/cpp/InternalInterfaces.h new file mode 100644 index 00000000..6e7f7b02 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/InternalInterfaces.h @@ -0,0 +1,23 @@ +#pragma once + +interface __declspec(uuid("{931D7B9C-11FB-45B6-97DA-47894D597F39}")) ISampleRadioInstanceInternal : public IUnknown +{ + IFACEMETHOD(OnSysRadioChange)(_In_ SYSTEM_RADIO_STATE sysRadioState) = 0; +}; + +interface __declspec(uuid("{98595167-4F34-4247-A669-CA41ABBC479A}")) ISampleRadioManagerInternal : public IUnknown +{ + IFACEMETHOD(OnInstanceRadioChange)(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState) = 0; +}; + + +HRESULT CSampleRadioInstance_CreateInstance( + _In_ PCWSTR pszKeyName, + _In_ ISampleRadioManagerInternal *pParentManager, + _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance); + +HRESULT CRadioInstanceCollection_CreateInstance( + _In_ DWORD cInstances, + _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance, + _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection); + diff --git a/network/radio/RadioManagerSample/cpp/RadioMgr.idl b/network/radio/RadioManagerSample/cpp/RadioMgr.idl new file mode 100644 index 00000000..5c7b5866 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/RadioMgr.idl @@ -0,0 +1,155 @@ +// +// Microsoft Windows +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// File: RadioMgr.idl +// +//---------------------------------------------------------------------------- + + +cpp_quote("//+-------------------------------------------------------------------------") +cpp_quote("//") +cpp_quote("// Microsoft Windows") +cpp_quote("// Copyright (c) Microsoft Corporation. All rights reserved.") +cpp_quote("//") +cpp_quote("//--------------------------------------------------------------------------") + +cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN8)") + +import "oaidl.idl"; +import "wtypes.idl"; + + +interface IMediaRadioManager; +interface IRadioInstanceCollection; +interface IRadioInstance; +interface IMediaRadioManagerNotifySink; + +typedef enum _DEVICE_RADIO_STATE +{ + DRS_RADIO_ON = 0, + DRS_SW_RADIO_OFF = 1, + DRS_HW_RADIO_OFF = 2, + DRS_SW_HW_RADIO_OFF = 3, + DRS_HW_RADIO_ON_UNCONTROLLABLE = 4, + DRS_RADIO_INVALID = 5, + DRS_HW_RADIO_OFF_UNCONTROLLABLE = 6, + DRS_RADIO_MAX = DRS_HW_RADIO_OFF_UNCONTROLLABLE +} DEVICE_RADIO_STATE; + +typedef enum _SYSTEM_RADIO_STATE +{ + SRS_RADIO_ENABLED = 0, + SRS_RADIO_DISABLED = 1, +} SYSTEM_RADIO_STATE; + +//+-------------------------------------------------------------------------------- +// IMediaRadioManager -- Represents high level radio operations on each radio type. +// The object implementing this interface will implement a Connection point (IConnectionPoint) +// for IMediaRadioManagerNotifySink. +// Each IMediaRadioManager object controls several or no IRadioInstance objects. +[ + local, + object, + uuid(6CFDCAB5-FC47-42A5-9241-074B58830E73), + pointer_default(unique) +] +interface IMediaRadioManager : IUnknown +{ + HRESULT GetRadioInstances( + [out] IRadioInstanceCollection **ppCollection + ); + + HRESULT OnSystemRadioStateChange( + [in] SYSTEM_RADIO_STATE sysRadioState, + [in] UINT32 uTimeoutSec + ); + +}; + + +//+--------------------------------------------------------------------------- +// IRadioInstanceCollection -- a flat list of radio instances +// +[ + local, + object, + uuid(E5791FAE-5665-4E0C-95BE-5FDE31644185), + pointer_default(unique) +] +interface IRadioInstanceCollection : IUnknown +{ + HRESULT GetCount( + [out] UINT32 *pcInstance + ); + + HRESULT GetAt( + [in] UINT32 uIndex, + [out] IRadioInstance **ppRadioInstance + ); +}; + +//+--------------------------------------------------------------------------- +// IRadioInstance -- Interface to control specific radio instance +// +[ + local, + object, + uuid(70AA1C9E-F2B4-4C61-86D3-6B9FB75FD1A2), + pointer_default(unique) +] +interface IRadioInstance : IUnknown +{ + HRESULT GetRadioManagerSignature( + [out] GUID *pguidSignature + ); + + HRESULT GetInstanceSignature( + [out, string] BSTR *pbstrId + ); + + HRESULT GetFriendlyName( + [in] LCID lcid, + [out, string] BSTR *pbstrName + ); + + HRESULT GetRadioState( + [out] DEVICE_RADIO_STATE *pRadioState + ); + + HRESULT SetRadioState( + [in] DEVICE_RADIO_STATE radioState, + [in] UINT32 uTimeoutSec + ); + + BOOL IsMultiComm(); + + BOOL IsAssociatingDevice(); +} + +//+--------------------------------------------------------------------------- +// IMediaRadioManagerNotifySink -- notify instance add/remove and radio state change event +// +[ + local, + object, + uuid(89D81F5F-C147-49ED-A11C-77B20C31E7C9), + pointer_default(unique) +] +interface IMediaRadioManagerNotifySink : IUnknown +{ + HRESULT OnInstanceAdd( + [in] IRadioInstance *pRadioInstance + ); + + HRESULT OnInstanceRemove( + [in, string] BSTR bstrRadioInstanceId + ); + + HRESULT OnInstanceRadioChange( + [in, string] BSTR bstrRadioInstanceId, + [in] DEVICE_RADIO_STATE radioState + ); +}; + +cpp_quote("#endif // (NTDDI >= NTDDI_WIN8)") diff --git a/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp b/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp new file mode 100644 index 00000000..427e27fe --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/RadioMgr_interface.cpp @@ -0,0 +1,3 @@ +#include "precomp.h" +#pragma hdrstop +#include "RadioMgr_i.c"
\ No newline at end of file diff --git a/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp new file mode 100644 index 00000000..5a4371de --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.cpp @@ -0,0 +1,102 @@ +#include "precomp.h" +#pragma hdrstop + +HRESULT CRadioInstanceCollection_CreateInstance( + _In_ DWORD cInstances, + _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance, + _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection) +{ + return CRadioInstanceCollection::CreateInstance(cInstances, rgpIRadioInstance, ppInstanceCollection); +} + +void CRadioInstanceCollection::FinalRelease() +{ + POSITION p; + while (nullptr != (p = _listRadioInstances.GetHeadPosition())) + { + IRadioInstance *pRadioInstance = _listRadioInstances.GetAt(p); + pRadioInstance->Release(); + _listRadioInstances.SetAt(p, nullptr); + _listRadioInstances.RemoveHeadNoReturn(); + } +} + +// static +HRESULT CRadioInstanceCollection::CreateInstance( + _In_ DWORD cInstances, + _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance, + _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection) +{ + HRESULT hr; + CComObject<CRadioInstanceCollection> *pInstanceCollection; + CComPtr<IRadioInstanceCollection> spInstanceCollection; + + *ppInstanceCollection = nullptr; + + hr = CComObject<CRadioInstanceCollection>::CreateInstance(&pInstanceCollection); + + if (SUCCEEDED(hr) && (pInstanceCollection != nullptr)) + { + hr = pInstanceCollection->QueryInterface(IID_PPV_ARGS(&spInstanceCollection)); + } + + if (SUCCEEDED(hr) && (pInstanceCollection != nullptr)) + { + for (DWORD dwIndex = 0; dwIndex < cInstances; dwIndex++) + { + _ATLTRY + { + pInstanceCollection->_listRadioInstances.AddTail(rgpIRadioInstance[dwIndex]); + rgpIRadioInstance[dwIndex]->AddRef(); + } + _ATLCATCH(e) + { + hr = e; + break; + } + } + } + + if (SUCCEEDED(hr)) + { + *ppInstanceCollection = spInstanceCollection.Detach(); + } + + return hr; +} + +IFACEMETHODIMP CRadioInstanceCollection::GetCount(_Out_ UINT32 *pcInstance) +{ + if (nullptr == pcInstance) + { + return E_INVALIDARG; + } + + *pcInstance = static_cast<UINT32>(_listRadioInstances.GetCount()); + return S_OK; +} + +IFACEMETHODIMP CRadioInstanceCollection::GetAt(_In_ UINT32 uIndex, _COM_Outptr_ IRadioInstance **ppRadioInstance) +{ + if (nullptr == ppRadioInstance) + { + return E_INVALIDARG; + } + + HRESULT hr; + *ppRadioInstance = nullptr; + + POSITION p = _listRadioInstances.FindIndex(uIndex); + *ppRadioInstance = _listRadioInstances.GetAt(p); + if (nullptr != *ppRadioInstance) + { + (*ppRadioInstance)->AddRef(); + hr = S_OK; + } + else + { + hr = E_FAIL; + } + + return hr; +} diff --git a/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h new file mode 100644 index 00000000..b210adcb --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleInstanceCollection.h @@ -0,0 +1,32 @@ +#pragma once + +class ATL_NO_VTABLE CRadioInstanceCollection : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CRadioInstanceCollection>, + public IRadioInstanceCollection +{ +public: + DECLARE_CLASSFACTORY() + DECLARE_NOT_AGGREGATABLE(CRadioInstanceCollection) + + DECLARE_NO_REGISTRY() + + BEGIN_COM_MAP(CRadioInstanceCollection) + COM_INTERFACE_ENTRY(IRadioInstanceCollection) + END_COM_MAP() + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + void FinalRelease(); + + static HRESULT CreateInstance( + _In_ DWORD cInstances, + _In_reads_(cInstances) IRadioInstance **rgpIRadioInstance, + _COM_Outptr_ IRadioInstanceCollection **ppInstanceCollection); + + IFACEMETHOD(GetCount)(_Out_ UINT32 *pcInstance); + IFACEMETHOD(GetAt)(_In_ UINT32 uIndex, _COM_Outptr_ IRadioInstance **ppRadioInstance); + +private: + CAtlList<IRadioInstance *> _listRadioInstances; +}; diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.def b/network/radio/RadioManagerSample/cpp/SampleRM.def new file mode 100644 index 00000000..535078cd --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRM.def @@ -0,0 +1,8 @@ +LIBRARY SampleRM + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.rc b/network/radio/RadioManagerSample/cpp/SampleRM.rc new file mode 100644 index 00000000..2f491770 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRM.rc @@ -0,0 +1,10 @@ +#include <ntverp.h> +#include <winver.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Sample Radio Manager" +#define VER_INTERNALNAME_STR "SampleRM.dll" + +#include <common.ver> + diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj new file mode 100644 index 00000000..f26b9385 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj @@ -0,0 +1,326 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" 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="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{165D39D6-68AC-4E1F-89ED-483E13E84F9B}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{6D846F43-0EBE-4FCD-90E5-915DE0BCBA42}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </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')" /> + </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')" /> + </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')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>SampleRM</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SampleRM</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SampleRM</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SampleRM</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ResourceCompile> + <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ResourceCompile> + <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ResourceCompile> + <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ResourceCompile> + <AdditionalOptions>%(AdditionalOptions) -N</AdditionalOptions> + </ResourceCompile> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <UseOfAtl>Dynamic</UseOfAtl> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;UNICODE;_UNICODE;_NTSDK=1;WPP_USE_NTDLL_FUNCTIONS</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies> + <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies> + <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies> + <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);ntdll.lib;Kernel32.lib;advapi32.lib;oleaut32.lib;ole32.lib;uuid.lib;User32.lib</AdditionalDependencies> + <ModuleDefinitionFile>SampleRM.def</ModuleDefinitionFile> + </Link> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="precompsrc.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Create</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="SampleInstanceCollection.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="SampleRadioInstance.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="SampleRadioManager.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\precomp.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <Midl Include="SampleRM.idl" /> + <ResourceCompile Include="SampleRM.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters new file mode 100644 index 00000000..837a0aab --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRM.vcxproj.Filters @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{6C044E6F-8320-46E5-9EBE-BDB0427DF29D}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{55F7F46D-B2E7-422F-8140-2F6D4D30D4FE}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{EB9B7D59-264D-421A-8077-FA89E50F57CF}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dllmain.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="precompsrc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SampleInstanceCollection.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SampleRadioInstance.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SampleRadioManager.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <Midl Include="SampleRM.idl"> + <Filter>Source Files</Filter> + </Midl> + <None Include="SampleRM.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="SampleRM.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp new file mode 100644 index 00000000..08f7e285 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.cpp @@ -0,0 +1,523 @@ +#include "precomp.h" +#pragma hdrstop + +HRESULT CSampleRadioInstance_CreateInstance( + _In_ PCWSTR pszKeyName, + _In_ ISampleRadioManagerInternal *pParentManager, + _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance) +{ + return CSampleRadioInstance::CreateInstance(pszKeyName, pParentManager, ppRadioInstance); +} + +PCWSTR CSampleRadioInstance::s_pszInstanceName = L"Name"; +PCWSTR CSampleRadioInstance::s_pszInstanceRadioState = L"RadioState"; +PCWSTR CSampleRadioInstance::s_pszPreviousRadioState = L"PreviousRadioState"; +PCWSTR CSampleRadioInstance::s_pszMultiComm = L"IsMultiComm"; +PCWSTR CSampleRadioInstance::s_pszAssocatingDevice = L"IsAssociatingDevice"; + +CSampleRadioInstance::CSampleRadioInstance() + : _pParentManager(nullptr), + _fClosing(false), + _fIsMultiCommDevice(false) +{ +} + +void CSampleRadioInstance::FinalRelease() +{ + if ((nullptr != _hRegChangeEvent) && (nullptr != _hEventThread)) + { + { + // Critical section scope. + CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection); + _fClosing = true; + SetEvent(_hRegChangeEvent); + } + WaitForSingleObject(_hEventThread, INFINITE); + } + + _Cleanup(); +} + +// static +HRESULT CSampleRadioInstance::CreateInstance( + _In_ PCWSTR pszKeyName, + _In_ ISampleRadioManagerInternal *pParentManager, + _COM_Outptr_ ISampleRadioInstanceInternal **ppRadioInstance) +{ + HRESULT hr; + CComObject<CSampleRadioInstance> *pRadioInstance; + CComPtr<ISampleRadioInstanceInternal> spRadioInstanceInternal; + + *ppRadioInstance = nullptr; + + hr = CComObject<CSampleRadioInstance>::CreateInstance(&pRadioInstance); + if (SUCCEEDED(hr) && (pRadioInstance != nullptr)) + { + hr = pRadioInstance->QueryInterface(IID_PPV_ARGS(&spRadioInstanceInternal)); + } + if (SUCCEEDED(hr) && (pRadioInstance != nullptr)) + { + hr = pRadioInstance->_Init(pszKeyName, pParentManager); + } + if (SUCCEEDED(hr)) + { + *ppRadioInstance = spRadioInstanceInternal.Detach(); + } + + return hr; +} + +HRESULT CSampleRadioInstance::_Init(_In_ PCWSTR pszKeyName, _In_ ISampleRadioManagerInternal *pParentManager) +{ + HRESULT hr; + DWORD dwError; + WCHAR szInstanceName[128] = {}; + DWORD cchInstanceName = ARRAYSIZE(szInstanceName); + + _ATLTRY + { + _strInstanceId = pszKeyName; + } + _ATLCATCH(e) + { + return e; + } + + _pParentManager = pParentManager; + + dwError = _hKeyRoot.Open(HKEY_LOCAL_MACHINE, _strInstanceId, KEY_ALL_ACCESS); + + + if (ERROR_SUCCESS == dwError) + { + dwError = _hKeyRoot.QueryStringValue(s_pszInstanceName, szInstanceName, &cchInstanceName); + + if (ERROR_SUCCESS == dwError) + { + _ATLTRY + { + _strInstanceName = szInstanceName; + } + _ATLCATCH(e) + { + UNREFERENCED_PARAMETER(e); + dwError = ERROR_OUTOFMEMORY; + } + + if (ERROR_SUCCESS == dwError) + { + DWORD dwTemp = 0; + dwError = _hKeyRoot.QueryDWORDValue(s_pszMultiComm, dwTemp); + // only when key read successfully with non zero value, we regard device as multicomm chip + if ((ERROR_SUCCESS == dwError) && (0 != dwTemp)) + { + _fIsMultiCommDevice = true; + } + + // ignore the case when there is no IsMultiComm value in the registry, set ERROR_SUCCESS to continue with _Init + dwError = ERROR_SUCCESS; + } + } + } + + // register the regkey value change event + if (ERROR_SUCCESS == dwError) + { + HANDLE hRegChangeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + if ((NULL == hRegChangeEvent) || (INVALID_HANDLE_VALUE == hRegChangeEvent)) + { + dwError = GetLastError(); + } + else + { + _hRegChangeEvent.Attach(hRegChangeEvent); + } + } + + if (ERROR_SUCCESS == dwError) + { + HANDLE hThread= ::CreateThread(nullptr, + 0, + CSampleRadioInstance::s_ThreadInstanceChange, + reinterpret_cast<PVOID>(this), + 0, + nullptr); + + if ((NULL == hThread) || (INVALID_HANDLE_VALUE == hThread)) + { + dwError = GetLastError(); + } + else + { + _hEventThread.Attach(hThread); + } + + } + + hr = HRESULT_FROM_WIN32(dwError); + + if (FAILED(hr)) + { + _Cleanup(); + } + + return hr; +} + +void CSampleRadioInstance::_Cleanup() +{ + if (nullptr != _pParentManager) + { + _pParentManager = nullptr; + } +} + +IFACEMETHODIMP CSampleRadioInstance::GetRadioManagerSignature(_Out_ GUID *pguidSignature) +{ + if (nullptr == pguidSignature) + { + return E_INVALIDARG; + } + + *pguidSignature = __uuidof(SampleRadioManager); + + return S_OK; +} + +IFACEMETHODIMP CSampleRadioInstance::GetInstanceSignature(_Out_ BSTR *pbstrID) +{ + if (nullptr == pbstrID) + { + return E_INVALIDARG; + } + + HRESULT hr = S_OK; + + *pbstrID = _strInstanceId.AllocSysString(); + if (nullptr == *pbstrID) + { + hr = E_OUTOFMEMORY; + } + + return hr; +} + +IFACEMETHODIMP CSampleRadioInstance::GetFriendlyName(_In_ LCID /* lcid*/, _Out_ BSTR *pbstrName) +{ + if (nullptr == pbstrName) + { + return E_INVALIDARG; + } + + HRESULT hr = S_OK; + + *pbstrName = _strInstanceName.AllocSysString(); + if (nullptr == *pbstrName) + { + hr = E_OUTOFMEMORY; + } + + return hr; +} + +IFACEMETHODIMP CSampleRadioInstance::GetRadioState(_Out_ DEVICE_RADIO_STATE *pRadioState) +{ + if (nullptr == pRadioState) + { + return E_INVALIDARG; + } + + DWORD dwRadioState; + DEVICE_RADIO_STATE radioState = DRS_RADIO_ON; + + *pRadioState = DRS_RADIO_ON; + + // Read radio state directly from device. we do not save radio state in our module to avoid out of sync + DWORD dwError = _hKeyRoot.QueryDWORDValue(s_pszInstanceRadioState, dwRadioState); + + if (ERROR_SUCCESS == dwError) + { + if ((dwRadioState > DRS_RADIO_MAX) || (dwRadioState == DRS_RADIO_INVALID)) + { + radioState = DRS_HW_RADIO_ON_UNCONTROLLABLE; + } + else + { + radioState = static_cast<DEVICE_RADIO_STATE>(dwRadioState); + } + + *pRadioState = radioState; + } + + return HRESULT_FROM_WIN32(dwError); +} + + +IFACEMETHODIMP CSampleRadioInstance::SetRadioState(_In_ DEVICE_RADIO_STATE radioState, _In_ UINT32 uTimeoutSec) +{ + if ((radioState != DRS_RADIO_ON) && (radioState != DRS_SW_RADIO_OFF)) + { + return E_INVALIDARG; // invalid input + } + + DEVICE_RADIO_STATE drsCurrent; + bool fRefAdded = false; + HRESULT hr = GetRadioState(&drsCurrent); + + // fail to get current radio state or current radio state is uncontrollable + if (FAILED(hr) || (drsCurrent & DRS_HW_RADIO_ON_UNCONTROLLABLE)) + { + return E_FAIL; + } + + if ((drsCurrent & DRS_SW_RADIO_OFF) == radioState) + { + return S_OK; // current software radio is same as target software radio + } + + // Keep all other bits same, only change the last bit of radio state to represent software radio change + DEVICE_RADIO_STATE drsState = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | radioState); + + CAutoPtr<SET_DEVICE_RADIO_JOB> spSetDeviceRadioJob; + + spSetDeviceRadioJob.Attach(new SET_DEVICE_RADIO_JOB); + if (nullptr == spSetDeviceRadioJob) + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + spSetDeviceRadioJob->hr = E_FAIL; + spSetDeviceRadioJob->drsTarget = drsState; + spSetDeviceRadioJob->pInstance = this; + + // Let working thread hold ref on object such that object won't be released before working thread return. + this->AddRef(); + fRefAdded = true; + + HANDLE hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (nullptr == hEvent) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + else + { + spSetDeviceRadioJob->hEvent.Attach(hEvent); + } + } + + if (SUCCEEDED(hr)) + { + if (!QueueUserWorkItem(CSampleRadioInstance::s_ThreadSetRadio, spSetDeviceRadioJob, WT_EXECUTEDEFAULT)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + DWORD dwIgnore; + hr = CoWaitForMultipleHandles(0, + uTimeoutSec * 1000, + 1, + reinterpret_cast<LPHANDLE>(&(spSetDeviceRadioJob->hEvent)), + &dwIgnore); + if (RPC_S_CALLPENDING == hr) + { + spSetDeviceRadioJob.Detach(); + } + else + { + hr = spSetDeviceRadioJob->hr; + } + } + + if (fRefAdded) + { + this->Release(); + } + return hr; +} + +IFACEMETHODIMP_(BOOL) CSampleRadioInstance::IsMultiComm() +{ + return _fIsMultiCommDevice ? TRUE : FALSE; +} + +IFACEMETHODIMP_(BOOL) CSampleRadioInstance::IsAssociatingDevice() +{ + BOOL fIsAssociatingDevice = FALSE; + DWORD dwAssociatingDevice = 0; + + DWORD dwError = _hKeyRoot.QueryDWORDValue(s_pszAssocatingDevice, dwAssociatingDevice); + + // When key read successfully with non zero value, we regard device associating now. + if ((ERROR_SUCCESS == dwError) && (0 != dwAssociatingDevice)) + { + fIsAssociatingDevice = TRUE; + } + + return fIsAssociatingDevice; +} + +IFACEMETHODIMP CSampleRadioInstance::OnSysRadioChange(_In_ SYSTEM_RADIO_STATE sysRadioState) +{ + if ((sysRadioState != SRS_RADIO_ENABLED) && (sysRadioState != SRS_RADIO_DISABLED)) + { + return E_INVALIDARG; + } + + DEVICE_RADIO_STATE drsCurrent; + DWORD dwError = ERROR_SUCCESS; + DEVICE_RADIO_STATE drsTarget = DRS_RADIO_ON; + DEVICE_RADIO_STATE drsPrevious = DRS_RADIO_ON; + DWORD dwPreviousState; + bool fSetRadioState = false; + + HRESULT hr = GetRadioState(&drsCurrent); + + // fail to get current radio state or current radio state is uncontrollable, ignore this call + if (FAILED(hr) || (drsCurrent & DRS_HW_RADIO_ON_UNCONTROLLABLE)) + { + return S_OK; + } + + if (SRS_RADIO_ENABLED == sysRadioState) + { + // If device current software radio is already on during system radio enabled, + // we ignore the saved previous radio state and do nothing. + // radio state will be updated only when current state is off during system radio enabling. + if (DRS_RADIO_ON != (drsCurrent & DRS_SW_RADIO_OFF)) + { + // System radio enable, need get previous radio state and set to previous radio state. + // If fail to get previous radio state, assume previous radio state is software radio on. + dwError = _hKeyRoot.QueryDWORDValue(s_pszPreviousRadioState, dwPreviousState); + + if (ERROR_SUCCESS == dwError) + { + if ((DRS_RADIO_ON == dwPreviousState) || (DRS_SW_RADIO_OFF == dwPreviousState)) + { + drsPrevious = static_cast<DEVICE_RADIO_STATE>(dwPreviousState); + } + } + + if ((drsCurrent & DRS_SW_RADIO_OFF) != drsPrevious) + { + drsTarget = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | drsPrevious); + fSetRadioState = true; + } + } + } + else + { // System radio disable, need record previous radio state. + _hKeyRoot.SetDWORDValue(s_pszPreviousRadioState, static_cast<DWORD>(drsCurrent)); + + if ((drsCurrent & DRS_SW_RADIO_OFF) != DRS_SW_RADIO_OFF) + { + drsTarget = static_cast<DEVICE_RADIO_STATE>((drsCurrent & DRS_HW_RADIO_OFF) | DRS_SW_RADIO_OFF); + fSetRadioState = true; + } + } + + if (fSetRadioState) + { + dwError = _hKeyRoot.SetDWORDValue(s_pszInstanceRadioState, static_cast<DWORD>(drsTarget)); + } + + return HRESULT_FROM_WIN32(dwError); +} + +HRESULT CSampleRadioInstance::_SetRadioState(_In_ DEVICE_RADIO_STATE radioState) +{ + DWORD dwError = _hKeyRoot.SetDWORDValue(s_pszInstanceRadioState, static_cast<DWORD>(radioState)); + + return HRESULT_FROM_WIN32(dwError); +} + +void CSampleRadioInstance::_OnInstanceUpdate() +{ + DWORD dwError; + DWORD dwRadioState = 0; + DEVICE_RADIO_STATE drsCurrent; + + dwError = _hKeyRoot.QueryDWORDValue(s_pszInstanceRadioState, dwRadioState); + + if (ERROR_SUCCESS == dwError) + { + if ((dwRadioState > DRS_RADIO_MAX) || (dwRadioState == DRS_RADIO_INVALID)) + { + drsCurrent = DRS_HW_RADIO_ON_UNCONTROLLABLE; + } + else + { + drsCurrent = static_cast<DEVICE_RADIO_STATE>(dwRadioState); + } + CComBSTR sbstrID = _strInstanceId.AllocSysString(); + + if (nullptr != sbstrID) + { + _pParentManager->OnInstanceRadioChange(sbstrID, drsCurrent); + } + } +} + +DWORD WINAPI CSampleRadioInstance::s_ThreadInstanceChange(LPVOID pThis) +{ + CSampleRadioInstance *pRadioInstance = reinterpret_cast<CSampleRadioInstance *>(pThis); + DWORD dwError = ERROR_SUCCESS; + + { + CComCritSecLock<CComAutoCriticalSection> lock(pRadioInstance->_criticalSection); + if (pRadioInstance->_fClosing) + { + dwError = ERROR_APP_INIT_FAILURE; + } + else + { + dwError = pRadioInstance->_hKeyRoot.NotifyChangeKeyValue(FALSE, + REG_NOTIFY_CHANGE_LAST_SET, + pRadioInstance->_hRegChangeEvent, + TRUE); + } + } + + if (ERROR_SUCCESS != dwError) + { + return dwError; + } + + + while (ERROR_SUCCESS == dwError) + { + WaitForSingleObject(pRadioInstance->_hRegChangeEvent, INFINITE); + + { + CComCritSecLock<CComAutoCriticalSection> lock(pRadioInstance->_criticalSection); + if (pRadioInstance->_fClosing) + { + break; + } + + ResetEvent(pRadioInstance->_hRegChangeEvent); + + dwError = pRadioInstance->_hKeyRoot.NotifyChangeKeyValue(FALSE, + REG_NOTIFY_CHANGE_LAST_SET, + pRadioInstance->_hRegChangeEvent, + TRUE); + } + pRadioInstance->_OnInstanceUpdate(); + } + + return dwError; +} + +DWORD WINAPI CSampleRadioInstance::s_ThreadSetRadio(LPVOID pThis) +{ + SET_DEVICE_RADIO_JOB *pJob = reinterpret_cast<SET_DEVICE_RADIO_JOB *>(pThis); + + pJob->hr = pJob->pInstance->_SetRadioState(pJob->drsTarget); + + SetEvent(pJob->hEvent); + return ERROR_SUCCESS; +} diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h new file mode 100644 index 00000000..176aca3c --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRadioInstance.h @@ -0,0 +1,71 @@ +#pragma once + +class ATL_NO_VTABLE CSampleRadioInstance : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CSampleRadioInstance>, + public IRadioInstance, + public ISampleRadioInstanceInternal +{ +public: + DECLARE_CLASSFACTORY() + DECLARE_NOT_AGGREGATABLE(CSampleRadioInstance) + DECLARE_NO_REGISTRY() + + BEGIN_COM_MAP(CSampleRadioInstance) + COM_INTERFACE_ENTRY(IRadioInstance) + COM_INTERFACE_ENTRY(ISampleRadioInstanceInternal) + END_COM_MAP() + + CSampleRadioInstance(); + + void FinalRelease(); + + static HRESULT CreateInstance( + _In_ PCWSTR pszKeyName, + _In_ ISampleRadioManagerInternal *pParentManager, + _COM_Outptr_ ISampleRadioInstanceInternal **pRadioInstance); + + // IRadioInstance + IFACEMETHOD(GetRadioManagerSignature)(_Out_ GUID *pguidSignature); + IFACEMETHOD(GetInstanceSignature)(_Out_ BSTR *pbstrID); + IFACEMETHOD(GetFriendlyName)(_In_ LCID lcid, _Out_ BSTR *pbstrName); + IFACEMETHOD(GetRadioState)(_Out_ DEVICE_RADIO_STATE *pRadioState); + IFACEMETHOD(SetRadioState)(_In_ DEVICE_RADIO_STATE radioState, _In_ UINT32 uTimeoutSec); + IFACEMETHOD_(BOOL, IsMultiComm)(); + IFACEMETHOD_(BOOL, IsAssociatingDevice)(); + + // ISampleRadioInstanceInternal + IFACEMETHOD(OnSysRadioChange)(_In_ SYSTEM_RADIO_STATE sysRadioSate); + +private: + HRESULT _Init(_In_ PCWSTR pszKeyName, _In_ ISampleRadioManagerInternal *pParentManager); + void _Cleanup(); + void _OnInstanceUpdate(); + HRESULT _SetRadioState(_In_ DEVICE_RADIO_STATE radioState); + static DWORD WINAPI s_ThreadInstanceChange(LPVOID pThis); + static DWORD WINAPI s_ThreadSetRadio(LPVOID pThis); + + ISampleRadioManagerInternal *_pParentManager; + CComAutoCriticalSection _criticalSection; + CString _strInstanceId; + CString _strInstanceName; + bool _fIsMultiCommDevice; + + CHandle _hEventThread; + bool _fClosing; // object is closing + CHandle _hRegChangeEvent; + CRegKey _hKeyRoot; + static PCWSTR s_pszInstanceName; + static PCWSTR s_pszInstanceRadioState; + static PCWSTR s_pszPreviousRadioState; + static PCWSTR s_pszMultiComm; + static PCWSTR s_pszAssocatingDevice; +}; + +typedef struct _SET_DEVICE_RADIO_JOB{ + HRESULT hr; + CHandle hEvent; + CSampleRadioInstance *pInstance; + DEVICE_RADIO_STATE drsTarget; +} SET_DEVICE_RADIO_JOB; + diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp b/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp new file mode 100644 index 00000000..53bc4757 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRadioManager.cpp @@ -0,0 +1,570 @@ +#include "precomp.h" +#pragma hdrstop + +PCWSTR CSampleRadioManager::s_pszRootKey = L"SYSTEM\\CurrentControlSet\\Control\\RadioManagement\\Misc\\SampleRadioManager"; + +CSampleRadioManager::CSampleRadioManager() + : _fClosing(false) +{ +} + +HRESULT CSampleRadioManager::FinalConstruct() +{ + DWORD dwError; + HRESULT hr = S_OK; + WCHAR szSubKeyName[128]; + DWORD cchSubKeyName; + + dwError = _hKeyRoot.Open(HKEY_LOCAL_MACHINE, s_pszRootKey, KEY_ALL_ACCESS); + + + if (ERROR_SUCCESS == dwError) + { + + // Enumerate all instances + DWORD dwCount = 0; + while (true) + { + cchSubKeyName = ARRAYSIZE(szSubKeyName); + dwError = _hKeyRoot.EnumKey(dwCount, szSubKeyName, &cchSubKeyName, NULL); + + if (ERROR_SUCCESS == dwError) + { + CString strSubKeyName; + _ATLTRY + { + strSubKeyName.Format(L"%s\\%s", s_pszRootKey, szSubKeyName); + } + _ATLCATCH(e) + { + hr = e; + } + if (SUCCEEDED(hr)) + { + hr = _AddInstance(strSubKeyName, nullptr); + } + + dwCount++; + } + else + { + dwError = ERROR_SUCCESS; + break; + } + } + + } + + // register the regkey subkey add/remove event + if (ERROR_SUCCESS == dwError) + { + HANDLE hRegChangeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (nullptr == hRegChangeEvent) + { + dwError = GetLastError(); + } + else + { + _hRegChangeEvent.Attach(hRegChangeEvent); + } + } + + if (ERROR_SUCCESS == dwError) + { + HANDLE hThread = ::CreateThread(nullptr, + 0, + CSampleRadioManager::s_ThreadRegChange, + reinterpret_cast<PVOID>(this), + 0, + nullptr); + + if (nullptr == hThread) + { + dwError = GetLastError(); + } + else + { + _hEventThread.Attach(hThread); + } + } + + hr = HRESULT_FROM_WIN32(dwError); + + if (FAILED(hr)) + { + _Cleanup(); + } + + return hr; +} + +void CSampleRadioManager::FinalRelease() +{ + if ((nullptr != _hRegChangeEvent) && (nullptr != _hEventThread)) + { + { + CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection); + + _fClosing = true; + SetEvent(_hRegChangeEvent); // inform reg listening thread obj is leaving + } + + WaitForSingleObject(_hEventThread, INFINITE); // wait reg listening thread finish + } + + _Cleanup(); +} + +void CSampleRadioManager::_Cleanup() +{ + POSITION p; + while (nullptr != (p = _listRadioInstances.GetHeadPosition())) + { + INSTANCE_LIST_OBJ *pListObj = _listRadioInstances.GetAt(p); + if (nullptr != pListObj) + { + _listRadioInstances.SetAt(p, nullptr); + _listRadioInstances.RemoveHeadNoReturn(); + delete pListObj; + } + } +} + +IFACEMETHODIMP CSampleRadioManager::GetRadioInstances(_Out_ IRadioInstanceCollection **ppCollection) +{ + CAutoVectorPtr<IRadioInstance *> rgpIRadioInstance; + HRESULT hr = S_OK; + DWORD cInstance; + + if (nullptr == ppCollection) + { + return E_INVALIDARG; + } + + *ppCollection = nullptr; + + CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection); + cInstance = static_cast<DWORD>(_listRadioInstances.GetCount()); + if (cInstance > 0) + { + if (!rgpIRadioInstance.Allocate(cInstance)) + { + hr = E_OUTOFMEMORY; + } + if (SUCCEEDED(hr)) + { + ZeroMemory(rgpIRadioInstance, sizeof(rgpIRadioInstance[0]) * cInstance); + DWORD dwIndex = 0; + + for (POSITION p = _listRadioInstances.GetHeadPosition(); nullptr != p; _listRadioInstances.GetNext(p)) + { + hr = (_listRadioInstances.GetAt(p))->spRadioInstance.QueryInterface(&(rgpIRadioInstance[dwIndex])); + if (FAILED(hr)) + { + break; + } + else + { + dwIndex++; + } + } + } + } + + if (SUCCEEDED(hr)) + { + hr = CRadioInstanceCollection_CreateInstance(cInstance, rgpIRadioInstance, ppCollection); + } + + for (DWORD dwIndex = 0; dwIndex < cInstance; dwIndex++) + { + if (nullptr != rgpIRadioInstance[dwIndex]) + { + rgpIRadioInstance[dwIndex]->Release(); + } + } + + return hr; +} + +IFACEMETHODIMP CSampleRadioManager::OnSystemRadioStateChange( + _In_ SYSTEM_RADIO_STATE sysRadioState, + _In_ UINT32 uTimeoutSec) +{ + HRESULT hr = S_OK; + CAutoPtr<SET_SYS_RADIO_JOB> spSetSysRadioJob; + bool fRefAdded = false; + + spSetSysRadioJob.Attach(new SET_SYS_RADIO_JOB); + if (nullptr == spSetSysRadioJob) + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + spSetSysRadioJob->hr = E_FAIL; + spSetSysRadioJob->srsTarget = sysRadioState; + spSetSysRadioJob->pSampleRM = this; + + // Add ref to object to avoid object release before working thread return + this->AddRef(); + fRefAdded = true; + + HANDLE hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (nullptr == hEvent) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + else + { + spSetSysRadioJob->hEvent.Attach(hEvent); + } + } + + if (SUCCEEDED(hr)) + { + if (!QueueUserWorkItem(CSampleRadioManager::s_ThreadSetSysRadio, spSetSysRadioJob, WT_EXECUTEDEFAULT)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (SUCCEEDED(hr)) + { + DWORD dwIgnore; + hr = CoWaitForMultipleHandles(0, + uTimeoutSec * 1000, + 1, + reinterpret_cast<LPHANDLE>(&(spSetSysRadioJob->hEvent)), + &dwIgnore); + if (RPC_S_CALLPENDING == hr) + { + spSetSysRadioJob.Detach(); + } + else + { + hr = spSetSysRadioJob->hr; + } + } + + if (fRefAdded) + { + this->Release(); + } + + return hr; +} + +IFACEMETHODIMP CSampleRadioManager::OnInstanceRadioChange( + _In_ BSTR bstrRadioInstanceID, + _In_ DEVICE_RADIO_STATE radioState) +{ + return _FireEventOnInstanceRadioChange(bstrRadioInstanceID, radioState); +} + +HRESULT CSampleRadioManager::_FireEventOnInstanceAdd(_In_ IRadioInstance *pRadioInstance) +{ + HRESULT hr; + + Lock(); + for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++) + { + if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc)) + { + CComPtr<IMediaRadioManagerNotifySink> spSink; + + hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink)); + if (SUCCEEDED(hr)) + { + spSink->OnInstanceAdd(pRadioInstance); + } + } + } + Unlock(); + + return S_OK; +} + +HRESULT CSampleRadioManager::_FireEventOnInstanceRemove(_In_ BSTR bstrRadioInstanceID) +{ + HRESULT hr; + + Lock(); + for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++) + { + if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc)) + { + CComPtr<IMediaRadioManagerNotifySink> spSink; + + hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink)); + if (SUCCEEDED(hr)) + { + spSink->OnInstanceRemove(bstrRadioInstanceID); + } + } + } + Unlock(); + + return S_OK; +} + +HRESULT CSampleRadioManager::_FireEventOnInstanceRadioChange( + _In_ BSTR bstrRadioInstanceID, + _In_ DEVICE_RADIO_STATE radioState + ) +{ + HRESULT hr; + + Lock(); + for (IUnknown** ppUnkSrc = m_vec.begin(); ppUnkSrc < m_vec.end(); ppUnkSrc++) + { + if ((nullptr != ppUnkSrc) && (nullptr != *ppUnkSrc)) + { + CComPtr<IMediaRadioManagerNotifySink> spSink; + + hr = (*ppUnkSrc)->QueryInterface(IID_PPV_ARGS(&spSink)); + if (SUCCEEDED(hr)) + { + spSink->OnInstanceRadioChange(bstrRadioInstanceID, radioState); + } + } + } + Unlock(); + + return S_OK; +} + + +HRESULT CSampleRadioManager::_AddInstance(_In_ PCWSTR pszKeyName, _Out_opt_ IRadioInstance **ppRadioInstance) +{ + HRESULT hr = S_OK; + CComPtr<ISampleRadioInstanceInternal> spRadioInstance; + CAutoPtr<INSTANCE_LIST_OBJ> spInstanceObj; + + CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection); + + spInstanceObj.Attach(new INSTANCE_LIST_OBJ); + if (nullptr == spInstanceObj) + { + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + CComPtr<ISampleRadioManagerInternal> spRMInternal = this; + hr = CSampleRadioInstance_CreateInstance(pszKeyName, spRMInternal, &spRadioInstance); + } + + if (SUCCEEDED(hr)) + { + spInstanceObj->fExisting = true; + spInstanceObj->spRadioInstance = spRadioInstance; + + _ATLTRY + { + spInstanceObj->strRadioInstanceID = pszKeyName; + _listRadioInstances.AddTail(spInstanceObj); + spInstanceObj.Detach(); + } + _ATLCATCH(e) + { + hr = e; + } + + if (SUCCEEDED(hr)) + { + if (ppRadioInstance != nullptr) + { + hr = spRadioInstance->QueryInterface(IID_PPV_ARGS(ppRadioInstance)); + } + } + } + + return hr; +} + +void CSampleRadioManager::_OnInstanceAddRemove() +{ + DWORD dwError; + HRESULT hr= S_OK; + WCHAR szSubKeyName[128]; + DWORD cchSubKeyName; + POSITION p; + + // Set all instances as invalid + for (p = _listRadioInstances.GetHeadPosition(); p != nullptr; _listRadioInstances.GetNext(p)) + { + INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p); + pRadioInstanceObj->fExisting = false; + } + + DWORD dwCount = 0; + while (true) + { + cchSubKeyName = ARRAYSIZE(szSubKeyName); + dwError = _hKeyRoot.EnumKey(dwCount, szSubKeyName, &cchSubKeyName, NULL); + + if (ERROR_SUCCESS == dwError) + { + CString strKeyName; + _ATLTRY + { + strKeyName.Format(L"%s\\%s",s_pszRootKey,szSubKeyName); + } + _ATLCATCH(e) + { + hr = e; + } + + if (SUCCEEDED(hr)) + { + for (p = _listRadioInstances.GetHeadPosition(); p != nullptr; _listRadioInstances.GetNext(p)) + { + INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p); + if (pRadioInstanceObj->strRadioInstanceID == strKeyName) + { + break; + } + } + + // find new instance + if (nullptr == p) + { + CComPtr<IRadioInstance> spRadioInstance; + hr = _AddInstance(strKeyName, &spRadioInstance); + if(SUCCEEDED(hr)) + { + _FireEventOnInstanceAdd(spRadioInstance); + } + } + else + { + // The instance still valid. + INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p); + pRadioInstanceObj->fExisting = true; + } + } + + dwCount++; + } + else + { + dwError = ERROR_SUCCESS; + break; + } + } + + // Remove deleted instance from list + p = _listRadioInstances.GetHeadPosition(); + while (nullptr != p) + { + INSTANCE_LIST_OBJ *pRadioInstanceObj = _listRadioInstances.GetAt(p); + if ((pRadioInstanceObj != nullptr) && !pRadioInstanceObj->fExisting) + { + POSITION pTmp = p; + _listRadioInstances.GetPrev(pTmp); + + _listRadioInstances.RemoveAt(p); + CComBSTR bstrTmp = pRadioInstanceObj->strRadioInstanceID.AllocSysString(); + if (nullptr != bstrTmp) + { + _FireEventOnInstanceRemove(bstrTmp); + } + delete pRadioInstanceObj; + p = pTmp; + } + + if (nullptr != p) + { + _listRadioInstances.GetNext(p); + } + else + { + p = _listRadioInstances.GetHeadPosition(); + } + } +} + +HRESULT CSampleRadioManager::_SetSysRadioState(_In_ SYSTEM_RADIO_STATE sysRadioState) +{ + // Since set regkey is fast enough, this implemtation is to set instance radio sequentially. + // If set instance radio takes long time and there are multiple instance within one RM, + // it is better to do it parallelly. + HRESULT hr = S_OK; + CComCritSecLock<CComAutoCriticalSection> lock(_criticalSection); + for (POSITION p = _listRadioInstances.GetHeadPosition(); nullptr != p; _listRadioInstances.GetNext(p)) + { + INSTANCE_LIST_OBJ *pInstanceObj = _listRadioInstances.GetAt(p); + hr = pInstanceObj->spRadioInstance->OnSysRadioChange(sysRadioState); + if (FAILED(hr)) + { + break; + } + } + return hr; +} + +DWORD WINAPI CSampleRadioManager::s_ThreadRegChange(LPVOID pThis) +{ + CSampleRadioManager *pRadioMgr = reinterpret_cast<CSampleRadioManager *>(pThis); + DWORD dwError = ERROR_SUCCESS; + + { + CComCritSecLock<CComAutoCriticalSection> lock(pRadioMgr->_criticalSection); + if (pRadioMgr->_fClosing) + { + dwError = ERROR_APP_INIT_FAILURE; + } + else + { + dwError = pRadioMgr->_hKeyRoot.NotifyChangeKeyValue(FALSE, + REG_NOTIFY_CHANGE_NAME, + pRadioMgr->_hRegChangeEvent, + TRUE); + } + } + + if (ERROR_SUCCESS != dwError) + { + return dwError; + } + + while (ERROR_SUCCESS == dwError) + { + if (WaitForSingleObject(pRadioMgr->_hRegChangeEvent, INFINITE) == WAIT_FAILED) + { + break; + } + + { + CComCritSecLock<CComAutoCriticalSection> lock(pRadioMgr->_criticalSection); + if (pRadioMgr->_fClosing) // main thread is leaving + { + break; + } + + ResetEvent(pRadioMgr->_hRegChangeEvent); + + dwError = pRadioMgr->_hKeyRoot.NotifyChangeKeyValue(FALSE, + REG_NOTIFY_CHANGE_NAME, + pRadioMgr->_hRegChangeEvent, + TRUE); + } + // Receive reg subkey add/remove event. update list + pRadioMgr->_OnInstanceAddRemove(); + } + + return dwError; +} + +DWORD WINAPI CSampleRadioManager::s_ThreadSetSysRadio(LPVOID pThis) +{ + SET_SYS_RADIO_JOB *pJob = reinterpret_cast<SET_SYS_RADIO_JOB *>(pThis); + + pJob->hr = pJob->pSampleRM->_SetSysRadioState(pJob->srsTarget); + + SetEvent(pJob->hEvent); + return ERROR_SUCCESS; +} + diff --git a/network/radio/RadioManagerSample/cpp/SampleRadioManager.h b/network/radio/RadioManagerSample/cpp/SampleRadioManager.h new file mode 100644 index 00000000..a39673ed --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/SampleRadioManager.h @@ -0,0 +1,79 @@ +#pragma once + +typedef struct { + CString strRadioInstanceID; + bool fExisting; + CComPtr<ISampleRadioInstanceInternal> spRadioInstance; +} INSTANCE_LIST_OBJ; + +EXTERN_C const IID IID_IMediaRadioManagerNotifySink; + +class ATL_NO_VTABLE CSampleRadioManager : + public CComObjectRootEx<CComMultiThreadModel>, + public CComCoClass<CSampleRadioManager, &CLSID_SampleRadioManager>, + public IConnectionPointContainerImpl<CSampleRadioManager>, + public IConnectionPointImpl<CSampleRadioManager, &IID_IMediaRadioManagerNotifySink>, + public IMediaRadioManager, + public ISampleRadioManagerInternal +{ +public: + + DECLARE_CLASSFACTORY() + DECLARE_NOT_AGGREGATABLE(CSampleRadioManager) + + DECLARE_NO_REGISTRY() + + BEGIN_COM_MAP(CSampleRadioManager) + COM_INTERFACE_ENTRY(IMediaRadioManager) + COM_INTERFACE_ENTRY(ISampleRadioManagerInternal) + COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) + END_COM_MAP() + + BEGIN_CONNECTION_POINT_MAP(CSampleRadioManager) + CONNECTION_POINT_ENTRY(IID_IMediaRadioManagerNotifySink) + END_CONNECTION_POINT_MAP() + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + CSampleRadioManager(); + + HRESULT FinalConstruct(); + void FinalRelease(); + + // IMediaRadioManager interface + IFACEMETHOD(GetRadioInstances)(_Out_ IRadioInstanceCollection **ppCollection); + IFACEMETHOD(OnSystemRadioStateChange)(_In_ SYSTEM_RADIO_STATE sysRadioState, _In_ UINT32 uTimeoutSec); + + // ISampleRadioManagerInternal interface + IFACEMETHOD(OnInstanceRadioChange)(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState); + +private: + HRESULT _FireEventOnInstanceAdd(_In_ IRadioInstance *pRadioInstance); + HRESULT _FireEventOnInstanceRemove(_In_ BSTR bstrRadioInstanceID); + HRESULT _FireEventOnInstanceRadioChange(_In_ BSTR bstrRadioInstanceID, _In_ DEVICE_RADIO_STATE radioState); + + void _Cleanup(); + HRESULT _AddInstance(_In_ PCWSTR pszKeyName, _Out_opt_ IRadioInstance **ppRadioInstance); + void _OnInstanceAddRemove(); + HRESULT _SetSysRadioState(_In_ SYSTEM_RADIO_STATE sysRadioState); + static DWORD WINAPI s_ThreadRegChange(LPVOID pThis); + static DWORD WINAPI s_ThreadSetSysRadio(LPVOID pThis); + + CComAutoCriticalSection _criticalSection; + CAtlList<INSTANCE_LIST_OBJ *> _listRadioInstances; + + CRegKey _hKeyRoot; + CHandle _hRegChangeEvent; + CHandle _hEventThread; + bool _fClosing; // object is closing + + static PCWSTR s_pszRootKey; +}; + +typedef struct _SET_SYS_RADIO_JOB{ + HRESULT hr; + CHandle hEvent; + CSampleRadioManager *pSampleRM; + SYSTEM_RADIO_STATE srsTarget; +} SET_SYS_RADIO_JOB; + diff --git a/network/radio/RadioManagerSample/cpp/dllmain.cpp b/network/radio/RadioManagerSample/cpp/dllmain.cpp new file mode 100644 index 00000000..61d6898b --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/dllmain.cpp @@ -0,0 +1,57 @@ +#include "precomp.h" +#pragma hdrstop + +OBJECT_ENTRY_AUTO(__uuidof(SampleRadioManager), CSampleRadioManager); + +class CSampleRadioModule : public CAtlDllModuleT<CSampleRadioModule> +{ +public: +}; + +static CSampleRadioModule s_AtlModule; + +//+--------------------------------------------------------------------------- +// DLL Entry Point +// + +EXTERN_C BOOL WINAPI DllMain +( + HINSTANCE /*hInstance*/, + DWORD dwReason, + LPVOID pvReserved +) +{ + return s_AtlModule.DllMain(dwReason, pvReserved); +} + +STDAPI DllCanUnloadNow(void) +{ + return s_AtlModule.DllCanUnloadNow(); +} + +STDAPI DllGetClassObject( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Outptr_ LPVOID* ppv + ) +{ + return s_AtlModule.DllGetClassObject(rclsid, riid, ppv); +} + + +//+--------------------------------------------------------------------------- +// Adds entries to the system registry. Needed because the binary need copy to test machine. +// If binary is deployed by manifest, these functions are not needed. +STDAPI +DllRegisterServer () +{ + s_AtlModule.DllRegisterServer(FALSE); + return S_OK; +} + +STDAPI +DllUnregisterServer () +{ + HRESULT hr = s_AtlModule.DllUnregisterServer(); + return hr; +} diff --git a/network/radio/RadioManagerSample/cpp/precomp.h b/network/radio/RadioManagerSample/cpp/precomp.h new file mode 100644 index 00000000..346a3fe6 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/precomp.h @@ -0,0 +1,17 @@ +#include <windows.h> +#include <Winreg.h> + +// ATL includes +#include <ATLBase.h> +#include <ATLCom.h> +#include <ATLColl.h> +#include <ATLStr.h> + + +// radio mamanager includes +#include "RadioMgr.h" +#include "SampleRM.h" +#include "internalInterfaces.h" +#include "SampleRadioInstance.h" +#include "SampleInstanceCollection.h" +#include "SampleRadioManager.h" diff --git a/network/radio/RadioManagerSample/cpp/precompsrc.cpp b/network/radio/RadioManagerSample/cpp/precompsrc.cpp new file mode 100644 index 00000000..5944cf51 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/precompsrc.cpp @@ -0,0 +1 @@ +#include "precomp.h"
\ No newline at end of file diff --git a/network/radio/RadioManagerSample/cpp/sampleRM.idl b/network/radio/RadioManagerSample/cpp/sampleRM.idl new file mode 100644 index 00000000..64ec3fc5 --- /dev/null +++ b/network/radio/RadioManagerSample/cpp/sampleRM.idl @@ -0,0 +1,21 @@ +import "oaidl.idl"; +import "RadioMgr.idl"; + +[ + uuid(4BE52AA0-EF10-420F-9341-681FBCCD772C), + version(1.0), + helpstring("Sample Radio Manager library") +] +library SampleRadioManagerLib +{ + importlib("stdole2.tlb"); + + [ + uuid(41DC5063-AFAF-47DF-86B3-4B2ED82A82CF), + helpstring("Sample Media Radio Manager") + ] + coclass SampleRadioManager + { + [default] interface IMediaRadioManager; + } +} diff --git a/network/radio/RadioManagerSample/install.cmd b/network/radio/RadioManagerSample/install.cmd new file mode 100644 index 00000000..59b84572 --- /dev/null +++ b/network/radio/RadioManagerSample/install.cmd @@ -0,0 +1,3 @@ +copy SampleRM.dll %windir%\system32\ +regsvr32 SampleRM.dll +SampleRM.reg diff --git a/network/radio/RadioManagerSample/readme.txt b/network/radio/RadioManagerSample/readme.txt new file mode 100644 index 00000000..2bdd69bd --- /dev/null +++ b/network/radio/RadioManagerSample/readme.txt @@ -0,0 +1,192 @@ +Sample Radio Manager +==================== +Demonstrates how to structure a Radio Manager for use with the Windows 8 Radio Management APIs. + +On Windows 8 and later, the operating system contains a set of APIs which are used as a software mechanism +to control the various radios found on the machine. The APIs work by communicating with a Radio Manager, +which is a COM object that relays commands from the APIs to turn the radio on or off, and reports back +radio information to the APIs. This feature is designed in such a way that a separate Radio Manager is +required for each radio media type. For example, a WLAN radio will be controlled by a different Radio +Manager than a GPS radio. If there are 2 WLAN radios and a GPS radio, the 2 WLAN radios will be controlled +by one Radio Manager, and the GPS radio will be controlled by a different Radio Manager. The Radio Manager +must be able to run correctly within Local Service Account context. Under this context, the Radio Manager +will have the minimum privilege on the local computer. + +When the user turns the radio off (either by using the specific radio software switch or the airplane mode switch), +radio transmission must be turned off. The device can be powered off as long as the radio switch does not disappear +from the UI. It is very important that the radio manager developer ensures that when the device is powered off, the +radio switch does not disappear from the UI. If the radio switch disappears from the UI when the radio is turned off +by the user, then user has no way to turn the radio back on! If it is desired to conserve power by cutting power to +the device when the radio is turned off, but the device cannot be completely powered off because it disappears from +the UI, then the solution would be to put the device in a low power state (e.g. D3). + +IMPORTANT! The radio manager must be given a name � this is the name of the radio switch that is displayed to the +user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, +for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should +be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's +name or some other word related to the functionality of the radio (e.g. "Location" OR "port"). + + + +Sample Language Implementations +=============================== +This sample is available in the following language implementations: + C++ + + +Installation Files +================== +install.cmd +- Installation script. Copies and registers the dll and executes SampleRM.reg + +SampleRM.reg +- script to install the Sample Radio Manager into the registry, along with 2 radio instances + + +Source Files +============ +SampleRM.sln +- The Visual Studio 2010 solution file for building the Sample Radio Manager dll + +sampleRM.idl +- The interface definition for the Sample Radio Manager + +RadioMgr.idl +- The interface definition for a Windows Radio Manager + +SampleRadioManager.h +- Header file for the functions required for a Radio Manager + +SampleRadioInstance.h +- Header file for the functions required for a Radio Instance + +SampleInstanceCollection.h +- Header file for the functions required for a Collection of Radio Instances + +precomp.h +- Common header file + +InternalInterfaces.h +- Header file for internal interface used for this sample + +dllmain.cpp +- Standard dllmain + +SampleRadioManager.cpp +- Implementation details for the Sample Radio Manager. Important concepts include: + - Utilizing IMediaRadioManagerNotifySink for radio instance events + - Adding/Removing radio instances + - Queuing and deploying worker jobs for system events + +SampleRadioInstance.cpp +- Implementation details for the Sample Radio Instance. Important concepts include: + - Accessors & Modifiers for radio information + - Instance change functions + +SampleInstanceCollection.cpp +- Implementation details for the Sample Instance Collection. Important concepts include: + - Radio Instance discovery and retrieval + +RadioMgr_interface.cpp +- Helper source file to include the MIDL-generated files. + + +How the sample works +==================== +This sample Radio Manager does not operate on an actual radio. Instead, it uses registry keys to act as +virtual radios. Each "radio" instance can have the following values: + -Name + -RadioState + -PreviousRadioState + -IsMultiComm + -IsAssociatingDevice + +***It is required that the registry key has AT LEAST a Name value, otherwise the Sample Radio Manager will +fail to initialize*** + +IMPORTANT! The radio manager must be given a name � this is the name of the radio switch that is displayed to the +user in the Wireless page of PC Settings. The name must be simple, yet descriptive of what the radio is. For example, +for NFC radios, the value of the name field should be "NFC", and for GPS radios, the value of the name field should +be "GPS" or "GNSS", whichever is more appropriate. The name must not include the word "radio" or the manufacturer's +name or some other word related to the functionality of the radio (e.g. "Location" OR "port"). + + +When the Radio Manager is initialized, it uses these registry keys to retrieve the "radio" information. +The radio state values can be any of the following enum values: + + typedef enum _DEVICE_RADIO_STATE + { + DRS_RADIO_ON = 0, + DRS_SW_RADIO_OFF = 1, + DRS_HW_RADIO_OFF = 2, + DRS_SW_HW_RADIO_OFF = 3, + DRS_HW_RADIO_ON_UNCONTROLLABLE = 4, + DRS_RADIO_INVALID = 5, + DRS_HW_RADIO_OFF_UNCONTROLLABLE = 6, + DRS_RADIO_MAX = DRS_HW_RADIO_OFF_UNCONTROLLABLE + } DEVICE_RADIO_STATE; + +For IsMultiComm and IsAssociatingDevice, a value of 0 means 'no' and 1 means 'yes. + + +To Add a Radio Instance +======================= +Add a new item to the registry: +[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\RadioManagement\Misc\SampleRadioManager\SampleRadioX] +"RadioState"=dword:00000000 +"Name"="SampleRadioX" +"IsMultiComm"=dword:00000000 + +To Edit a Radio Instance +======================== +Simply change the values in the registry. For example, change the radio state from DRS_RADIO_ON to DRS_SW_RADIO_OFF +by changing the 'RadioState' value from 0 to 1. + + +To Remove a Radio Instance +========================== +Delete the corresponding registry key. + + +Prerequisites for viewing and building solution +=============================================== +1. Windows 7 +2. Visual Studio 2010 + + +To build the sample using Visual Studio 2010 (preferred method): +=============================================================== +1. Open File Explorer and navigate to the directory. +2. Double-click the icon for the SampleRM.sln (solution) file to open the file in Visual Studio. +3. In the Build menu, select Build Solution. The dll will be built in the default \Debug or \Release directory + + +Prerequisites for installing Radio Manager +========================================== +1. Windows 8 +2. The VC++ 2010 Redistributable package must be installed for this dll to load. + + +Installing Radio Manager +======================== +1. Copy the install.cmd, SampleRM.reg and SampleRM.dll files to a directory +2. Run install.cmd + + + + + + + + + + + + + + + + + + + |
