diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt new file mode 100644 index 00000000000..c79aa4b6baf --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CHANGELOG.txt @@ -0,0 +1,101 @@ +1.1.3: +- power management fixes for Vista +- user friendly default values +- mixer settings are restored after hibernation/sleep + +1.1.2: +- implementation for power management stuff (hibernation, standby etc) + +1.1.1: +- minor fix of the DataRangeIntersection() handler for Vista +- support for Phillips PSC60x cards + +1.1.0: +- uninstaller for the control panel applet / cmicontrol.exe +- some minor GUI improvements +- SPDIF-In recording mode now engagable only in the control panel applet + +1.0.9: +- command line options for cmicontrol.exe +- pause bug fixed (thanks, max) +- SPDIF-In recording fixed (bitperfect!) +- all settings are now saved when you press "Apply" in the window of the control panel applet + +1.0.8: +- resource allocation bug fixed (thanks, teemue) + +1.0.7: +- two major bugs fixed (thanks, Any2) +- new feature: format selection + +1.0.6: +- prevent WaveRT driver from loading (and crashing) on XP/2k +- another UART fix - driver will now load on systems on which the i/o ports 0x300-0x330 can't be assigned + +1.0.5: +- recording format validation fixed (thanks, Any2) +- UART miniport installation failure non-critical anymore (thanks, Tom) + +1.0.4: +- installer for XP x64 fixed +- MPU401 for 64 bit systems fixed + +1.0.3: +- 100% CPU usage bug fixed + +1.0.2: +- new feature: UART/MPU-401 +- even more inf bugfixes +- line-in mute control was mono - fixed (thanks, Egor) +- playback mute switch was toggled - fixed (thanks, DualIP) +- installer can delete cmedia 'Run' registry entries + +1.0.1: +- some installer fixes +- inf fix for 64bit WaveRT drivers (thanks, jeffrey) +- inf fix for Terratec Aureon and other cards (thanks, alex) +- some other minor inf fixes + +1.0.0: +- installer application +- minor issue with the control panel and Vista fixed +- small fix for control panel applet: subwoofer test signal was incorrectly sent to center (thanks, DualIP) +- KSPROPERTY_GENERAL_COMPONENTID handler fixed + +0.9.9: +- major inf bugfixes +- control panel (cmicontrol.exe, cpl) +- dummy master mute control (for support of legacy software) +- lots of other minor bugfixes +- KNOWN ISSUE: center/sub and BL/BR swapped in 5.1 mode - there isn't a trivial solution for this + +0.9.8: +- fixed some AC3 issues under XP +- fixed w2k compatibility (thanks, egor) + +0.9.7: +- fixed multi-channel stuff for 2k/XP (thanks, cmediafl) +- 96kHz spdif output support for Vista + +0.9.6: +- WaveRT implementation for Vista - very fast, low latency recording and playback possible +- APO ('Enhancements') support for Vista - I have no idea why this works only on the SPDIF interface. +If you know why this is happening or why the XP mixer tries to render the AC3 pin, please drop me a line. + +0.9.5: +- recording support for Windows Vista +- selection of spdif-in suppported +- recording mixer fix for XP + +0.9.4a: +- .inf fix for the 64bit version (thanks, martin) + +0.9.4: +- mixer settings and channel config saved and restored +- option for disabling the s/pdif output +- s/pdif and multi channel audio support for Windows Vista +- some small fixes + +0.9.3: +- bug fixes for multi channel audio +- several other minor fixes \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32-WaveRT.inf b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32-WaveRT.inf new file mode 100644 index 00000000000..b019fa661cc --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32-WaveRT.inf @@ -0,0 +1,287 @@ +[Version] +Signature="$CHICAGO$" +Class=MEDIA +ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} +provider=%CMMfgName% +LayoutFile=layout.inf, layout1.inf, layout2.inf +DriverVer=CMIReleaseDate,CMIVersion.1111 + +[SourceDisksNames] +200="C-Media 8738/8768 WDM Drivers","",0 + +[SourceDisksFiles] +cmipci.sys=200 +cmicpl.cpl=200 +CMICONTROL.exe=200 + +[Manufacturer] +%CMMfgName%=CMI + +[ControlFlags] +ExcludeFromSelect=* + +[CMI] +;generic +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011013F6 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6 +;Terratec +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_1144153B +;Auzentech +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_3731584D +;Diamond +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_87681092 +;TurtleBeach +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020110B0 +;Phillips +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_060417AB +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020210B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020410B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_009C145F +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_50701462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_52801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54511462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_56501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59001462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70411462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_71011462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_A016147A +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_30021919 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_0577A0A0 +%*WDM_CMMPU.DeviceDesc%=MPU401, MPU401, *PNPB006 + +[WDM_CMPCI] +Include=ks.inf,wdmaudio.inf +Needs=KS.Registration,WDMAUDIO.Registration,mssysfx.CopyFilesAndRegister +CopyFiles=CMPCI.CopyList,CPanel.CopyList +AddReg=WDM_CMPCI.AddReg,Mixer_CMPCI.AddReg + +[WDM_CMPCI.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_REALTIME%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[MPU401.Interface.UART] +AddReg=MPU401.Interface.UART.AddReg +[MPU401.Interface.UART.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.UART.szPname% + +[WDM_CMPCI.Interface.Wave] +AddReg=WDM_PCI.Interface.Wave.AddReg,WDM_CMPCI.SysFx.Render +[WDM_PCI.Interface.Wave.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Wave.szPname% + +[WDM_CMPCI.Interface.Topo] +AddReg=WDM_PCI.Interface.Topo.AddReg +[WDM_PCI.Interface.Topo.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Topo.szPname% + +[WDM_CMPCI.AddReg] +HKR,,AssociatedFilters,,"wdmaud,swmidi,redbook" +HKR,,Driver,,CMIPCI.SYS +HKR,,NTMPDriver,,"CMIPCI.sys,sbemul.sys" +HKR,Drivers,SubClasses,,"wave,midi,mixer,aux" +HKR,Drivers\wave\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\midi\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\aux\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\wave\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\midi\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\mixer\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\aux\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% + +; System Effects settings +[WDM_CMPCI.SysFx.Render] +HKR,"FX\\0",%PKEY_ItemNameDisplay%,,%FX_FriendlyName% +HKR,"FX\\0",%PKEY_FX_PreMixClsid%,,%FX_PREMIX_CLSID% +HKR,"FX\\0",%PKEY_FX_PostMixClsid%,,%FX_POSTMIX_CLSID% +HKR,"FX\\0",%PKEY_FX_UiClsid%,,%FX_UI_CLSID% +HKR,"FX\\0",%PKEY_FX_Association%,,%KSNODETYPE_ANY% +HKR,"FX\\1",%PKEY_ItemNameDisplay%,,%FX_FriendlyName% +HKR,"FX\\1",%PKEY_FX_PreMixClsid%,,%FX_PREMIX_CLSID% +HKR,"FX\\1",%PKEY_FX_PostMixClsid%,,%FX_POSTMIX_CLSID% +HKR,"FX\\1",%PKEY_FX_UiClsid%,,%FX_UI_CLSID% +HKR,"FX\\1",%PKEY_FX_Association%,,%KSNODETYPE_SPDIF_INTERFACE% + +[Mixer_CMPCI.AddReg] +HKLM,%MediaCategories%\%GUID.CMIPCI%,Name,,%*WDM_CMPCI.DeviceDesc% +HKLM,%MediaCategories%\%GUID.CMIPCI%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IEC5V%,Name,,%Name.IEC5V% +HKLM,%MediaCategories%\%GUID.IEC5V%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECOut%,Name,,%Name.IECOut% +HKLM,%MediaCategories%\%GUID.IECOut%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECMonitor%,Name,,%Name.IECMonitor% +HKLM,%MediaCategories%\%GUID.IECMonitor%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECInverse%,Name,,%Name.IECInverse% +HKLM,%MediaCategories%\%GUID.IECInverse%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.DAC%,Name,,%Name.DAC% +HKLM,%MediaCategories%\%GUID.DAC%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECSelect%,Name,,%Name.IECSelect% +HKLM,%MediaCategories%\%GUID.IECSelect%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.XCHGFB%,Name,,%Name.XCHGFB% +HKLM,%MediaCategories%\%GUID.XCHGFB%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.BassLine%,Name,,%Name.BassLine% +HKLM,%MediaCategories%\%GUID.BassLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterLine%,Name,,%Name.CenterLine% +HKLM,%MediaCategories%\%GUID.CenterLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECCopyright%,Name,,%Name.IECCopyright% +HKLM,%MediaCategories%\%GUID.IECCopyright%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECPolValid%,Name,,%Name.IECPolValid% +HKLM,%MediaCategories%\%GUID.IECPolValid%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECLoop%,Name,,%Name.IECLoop% +HKLM,%MediaCategories%\%GUID.IECLoop%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.RearLine%,Name,,%Name.RearLine% +HKLM,%MediaCategories%\%GUID.RearLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterMic%,Name,,%Name.CenterMic% +HKLM,%MediaCategories%\%GUID.CenterMic%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Manuf%,Name,,%Name.Manuf% +HKLM,%MediaCategories%\%GUID.Manuf%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Component%,Name,,%Name.Component% +HKLM,%MediaCategories%\%GUID.Component%,Display,1,00,00,00,00 + +[DestinationDirs] +CMPCI.CopyList = 10, system32\drivers ; %SystemRoot%\system32\drivers +CPanel.CopyList = 10, system32 ; %SystemRoot%\system32\drivers +DefaultDestDir = 11 + +[CMPCI.CopyList] +cmipci.sys + +[CPanel.CopyList] +cmicpl.cpl +CMICONTROL.exe + +;;**************** NT Install **************** + +[WDM_CMPCI.NTx86] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList, CPanel.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.NTx86.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_REALTIME%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[WDM_CMPCI.NTx86.Services] +AddService = cmipci, 0x00000002, cmipci_Service_Inst + +[cmipci_Service_Inst] +DisplayName = %CMIPCI.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\system32\drivers\cmipci.sys + +[MPU401.NTx86] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.NTx86.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.NTx86.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[Strings] +CMMfgName="Dogbert" +*WDM_CMPCI.DeviceDesc="CMI8738/8768 Audio Device" +*WDM_CMMPU.DeviceDesc="CMI8738/8768 MPU-401" +WDM_CMPCI.Wave.szPname="CMI8738/8768 Wave" +WDM_CMPCI.Topo.szPname="CMI8738/8768 Mixer" +WDM_CMPCI.UART.szPname="CMI8738/8768 MPU401" +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_REALTIME="{EB115FFC-10C8-4964-831D-6DCB02E6F23F}" +KSNAME_Wave="Wave" +KSNAME_Topology="Topology" +KSNAME_UART="UART" +FX_UI_CLSID="{5860E1C5-F95C-4a7a-8EC8-8AEF24F379A1}" +KSNODETYPE_ANY="{00000000-0000-0000-0000-000000000000}" +FX_PREMIX_CLSID="{62dc1a93-ae24-464c-a43e-452f824c4250}" +FX_POSTMIX_CLSID="{637c490d-eee3-4c0a-973f-371958802da2}" +FX_FriendlyName="Microsoft Audio Home Theater Effects" +PKEY_FX_Association="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},0" +PKEY_FX_PreMixClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},1" +PKEY_FX_PostMixClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},2" +PKEY_FX_UiClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},3" +PKEY_ItemNameDisplay="{B725F130-47EF-101A-A5F1-02608C9EEBAC},10" +KSNODETYPE_SPEAKER="{DFF21CE1-F70F-11D0-B917-00A0C9223196}" +KSNODETYPE_SPDIF_INTERFACE="{DFF21FE5-F70F-11D0-B917-00A0C9223196}" +CMIPCI.SvcDesc="CMI8738/8768 Audio Driver" +GUID.CMIPCI="{9DB14E9A-7BE7-480d-A2FA-32932489DE9C}" +GUID.IEC5V="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0}" +Name.IEC5V="S/PDIF-out 5V signal levels" +GUID.IECOut="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1}" +Name.IECOut="Enable S/PDIF-out" +GUID.IECInverse="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2}" +Name.IECInverse="Invert S/PDIF-in signal" +GUID.IECMonitor="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3}" +Name.IECMonitor="Enable PCM DAC" +GUID.DAC="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4}" +Name.DAC="DAC" +GUID.IECSelect="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5}" +Name.IECSelect="Select secondary S/PDIF-in" +GUID.XCHGFB="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6}" +Name.XCHGFB="Exchange Front/Rear Jacks" +GUID.BassLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7}" +Name.BassLine="Route Bass to Line-In Jack" +GUID.CenterLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8}" +Name.CenterLine="Route Center to Line-In Jack" +GUID.IECCopyright="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9}" +Name.IECCopyright="Enable copyright bit" +GUID.IECPolValid="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA}" +Name.IECPolValid="Invert validity flag" +GUID.IECLoop="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB}" +Name.IECLoop="Loop S/PDIF-in to S/PDIF-out" +GUID.RearLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC}" +Name.RearLine="Route Rear to Line-In Jack" +GUID.CenterMic="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD}" +Name.CenterMic="Route Center to Mic-In Jack" +GUID.Manuf="{9DB14E9A-7BE7-480d-A2FA-32932489DE9E}" +Name.Manuf="Dogbert" +GUID.Component="{9DB14E9A-7BE7-480d-A2FA-32932489DE9D}" +Name.Component="main" \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32.inf b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32.inf new file mode 100644 index 00000000000..4e747a15e4a --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x32.inf @@ -0,0 +1,257 @@ +[Version] +Signature="$CHICAGO$" +Class=MEDIA +ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} +provider=%CMMfgName% +LayoutFile=layout.inf, layout1.inf, layout2.inf +DriverVer=CMIReleaseDate,CMIVersion + +[SourceDisksNames] +200="C-Media 8738/8768 WDM Drivers","",0 + +[SourceDisksFiles] +cmipci.sys=200 +cmicpl.cpl=200 +CMICONTROL.exe=200 + +[Manufacturer] +%CMMfgName%=CMI + +[ControlFlags] +ExcludeFromSelect=* + +[CMI] +;generic +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011013F6 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6 +;Terratec +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_1144153B +;Auzentech +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_3731584D +;Diamond +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_87681092 +;TurtleBeach +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020110B0 +;Phillips +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_060417AB +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020210B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020410B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_009C145F +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_50701462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_52801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54511462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_56501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59001462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70411462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_71011462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_A016147A +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_30021919 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_0577A0A0 +%*WDM_CMMPU.DeviceDesc%=MPU401, MPU401, *PNPB006 + +[WDM_CMPCI] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[MPU401.Interface.UART] +AddReg=MPU401.Interface.UART.AddReg +[MPU401.Interface.UART.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.UART.szPname% + +[WDM_CMPCI.Interface.Wave] +AddReg=WDM_PCI.Interface.Wave.AddReg +[WDM_PCI.Interface.Wave.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Wave.szPname% + +[WDM_CMPCI.Interface.Topo] +AddReg=WDM_PCI.Interface.Topo.AddReg +[WDM_PCI.Interface.Topo.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Topo.szPname% + +[WDM_CMPCI.AddReg] +HKR,,AssociatedFilters,,"wdmaud,swmidi,redbook" +HKR,,Driver,,CMIPCI.SYS +HKR,,NTMPDriver,,"CMIPCI.sys,sbemul.sys" +HKR,Drivers,SubClasses,,"wave,midi,mixer" +HKR,Drivers\wave\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\midi\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\wave\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\midi\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\mixer\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% + +[Mixer_CMPCI.AddReg] +HKLM,%MediaCategories%\%GUID.CMIPCI%,Name,,%*WDM_CMPCI.DeviceDesc% +HKLM,%MediaCategories%\%GUID.CMIPCI%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IEC5V%,Name,,%Name.IEC5V% +HKLM,%MediaCategories%\%GUID.IEC5V%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECOut%,Name,,%Name.IECOut% +HKLM,%MediaCategories%\%GUID.IECOut%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECMonitor%,Name,,%Name.IECMonitor% +HKLM,%MediaCategories%\%GUID.IECMonitor%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECInverse%,Name,,%Name.IECInverse% +HKLM,%MediaCategories%\%GUID.IECInverse%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.DAC%,Name,,%Name.DAC% +HKLM,%MediaCategories%\%GUID.DAC%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECSelect%,Name,,%Name.IECSelect% +HKLM,%MediaCategories%\%GUID.IECSelect%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.XCHGFB%,Name,,%Name.XCHGFB% +HKLM,%MediaCategories%\%GUID.XCHGFB%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.BassLine%,Name,,%Name.BassLine% +HKLM,%MediaCategories%\%GUID.BassLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterLine%,Name,,%Name.CenterLine% +HKLM,%MediaCategories%\%GUID.CenterLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECCopyright%,Name,,%Name.IECCopyright% +HKLM,%MediaCategories%\%GUID.IECCopyright%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECPolValid%,Name,,%Name.IECPolValid% +HKLM,%MediaCategories%\%GUID.IECPolValid%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECLoop%,Name,,%Name.IECLoop% +HKLM,%MediaCategories%\%GUID.IECLoop%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.RearLine%,Name,,%Name.RearLine% +HKLM,%MediaCategories%\%GUID.RearLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterMic%,Name,,%Name.CenterMic% +HKLM,%MediaCategories%\%GUID.CenterMic%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Manuf%,Name,,%Name.Manuf% +HKLM,%MediaCategories%\%GUID.Manuf%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Component%,Name,,%Name.Component% +HKLM,%MediaCategories%\%GUID.Component%,Display,1,00,00,00,00 + +[DestinationDirs] +CMPCI.CopyList = 10, system32\drivers ; %SystemRoot%\system32\drivers +CPanel.CopyList = 10, system32 ; %SystemRoot%\system32\drivers +DefaultDestDir = 11 + +[CMPCI.CopyList] +cmipci.sys + +[CPanel.CopyList] +cmicpl.cpl +CMICONTROL.exe + +;;**************** NT Install **************** + +[WDM_CMPCI.NTx86] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList, CPanel.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.NTx86.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[WDM_CMPCI.NTx86.Services] +AddService = cmipci, 0x00000002, cmipci_Service_Inst + +[cmipci_Service_Inst] +DisplayName = %CMIPCI.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\system32\drivers\cmipci.sys + +[MPU401.NTx86] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.NTx86.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.NTx86.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[Strings] +CMMfgName="Dogbert" +*WDM_CMPCI.DeviceDesc="CMI8738/8768 Audio Device" +*WDM_CMMPU.DeviceDesc="CMI8738/8768 MPU-401" +WDM_CMPCI.Wave.szPname="CMI8738/8768 Wave" +WDM_CMPCI.Topo.szPname="CMI8738/8768 Mixer" +WDM_CMPCI.UART.szPname="CMI8738/8768 MPU-401" +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSNAME_Wave="Wave" +KSNAME_Topology="Topology" +KSNAME_UART="UART" +CMIPCI.SvcDesc = "CMI8738/8768 Audio Driver" +GUID.CMIPCI="{9DB14E9A-7BE7-480d-A2FA-32932489DE9C}" +GUID.IEC5V="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0}" +Name.IEC5V="S/PDIF-out 5V signal levels" +GUID.IECOut="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1}" +Name.IECOut="Enable S/PDIF-out" +GUID.IECInverse="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2}" +Name.IECInverse="Invert S/PDIF-in signal" +GUID.IECMonitor="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3}" +Name.IECMonitor="Enable PCM DAC" +GUID.DAC="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4}" +Name.DAC="DAC" +GUID.IECSelect="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5}" +Name.IECSelect="Select secondary S/PDIF-in" +GUID.XCHGFB="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6}" +Name.XCHGFB="Exchange Front/Rear Jacks" +GUID.BassLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7}" +Name.BassLine="Route Bass to Line-In Jack" +GUID.CenterLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8}" +Name.CenterLine="Route Center to Line-In Jack" +GUID.IECCopyright="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9}" +Name.IECCopyright="Enable copyright bit" +GUID.IECPolValid="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA}" +Name.IECPolValid="Invert validity flag" +GUID.IECLoop="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB}" +Name.IECLoop="Loop S/PDIF-in to S/PDIF-out" +GUID.RearLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC}" +Name.RearLine="Route Rear to Line-In Jack" +GUID.CenterMic="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD}" +Name.CenterMic="Route Center to Mic-In Jack" +GUID.Manuf="{9DB14E9A-7BE7-480d-A2FA-32932489DE9E}" +Name.Manuf="Dogbert" +GUID.Component="{9DB14E9A-7BE7-480d-A2FA-32932489DE9D}" +Name.Component="main" \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64-WaveRT.inf b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64-WaveRT.inf new file mode 100644 index 00000000000..e6ae26c3fe9 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64-WaveRT.inf @@ -0,0 +1,287 @@ +[Version] +Signature="$CHICAGO$" +Class=MEDIA +ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} +provider=%CMMfgName% +LayoutFile=layout.inf, layout1.inf, layout2.inf +DriverVer=CMIReleaseDate,CMIVersion.1111 + +[SourceDisksNames] +200="C-Media 8738/8768 WDM Drivers","",0 + +[SourceDisksFiles] +cmipci.sys=200 +cmicpl.cpl=200 +CMICONTROL.exe=200 + +[Manufacturer] +%CMMfgName%=CMI,NTamd64 + +[ControlFlags] +ExcludeFromSelect=* + +[CMI.NTamd64] +;generic +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011013F6 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6 +;Terratec +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_1144153B +;Auzentech +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_3731584D +;Diamond +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_87681092 +;TurtleBeach +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020110B0 +;Phillips +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_060417AB +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020210B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020410B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_009C145F +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_50701462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_52801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54511462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_56501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59001462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70411462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_71011462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_A016147A +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_30021919 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_0577A0A0 +%*WDM_CMMPU.DeviceDesc%=MPU401, MPU401, *PNPB006 + +[WDM_CMPCI] +Include=ks.inf,wdmaudio.inf +Needs=KS.Registration,WDMAUDIO.Registration,mssysfx.CopyFilesAndRegister +CopyFiles=CMPCI.CopyList,CPanel.CopyList +AddReg=WDM_CMPCI.AddReg,Mixer_CMPCI.AddReg + +[WDM_CMPCI.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_REALTIME%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[MPU401.Interface.UART] +AddReg=MPU401.Interface.UART.AddReg +[MPU401.Interface.UART.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.UART.szPname% + +[WDM_CMPCI.Interface.Wave] +AddReg=WDM_PCI.Interface.Wave.AddReg,WDM_CMPCI.SysFx.Render +[WDM_PCI.Interface.Wave.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Wave.szPname% + +[WDM_CMPCI.Interface.Topo] +AddReg=WDM_PCI.Interface.Topo.AddReg +[WDM_PCI.Interface.Topo.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Topo.szPname% + +[WDM_CMPCI.AddReg] +HKR,,AssociatedFilters,,"wdmaud,swmidi,redbook" +HKR,,Driver,,CMIPCI.SYS +HKR,,NTMPDriver,,"CMIPCI.sys,sbemul.sys" +HKR,Drivers,SubClasses,,"wave,midi,mixer,aux" +HKR,Drivers\wave\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\midi\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\aux\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\wave\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\midi\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\mixer\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\aux\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% + +; System Effects settings +[WDM_CMPCI.SysFx.Render] +HKR,"FX\\0",%PKEY_ItemNameDisplay%,,%FX_FriendlyName% +HKR,"FX\\0",%PKEY_FX_PreMixClsid%,,%FX_PREMIX_CLSID% +HKR,"FX\\0",%PKEY_FX_PostMixClsid%,,%FX_POSTMIX_CLSID% +HKR,"FX\\0",%PKEY_FX_UiClsid%,,%FX_UI_CLSID% +HKR,"FX\\0",%PKEY_FX_Association%,,%KSNODETYPE_ANY% +HKR,"FX\\1",%PKEY_ItemNameDisplay%,,%FX_FriendlyName% +HKR,"FX\\1",%PKEY_FX_PreMixClsid%,,%FX_PREMIX_CLSID% +HKR,"FX\\1",%PKEY_FX_PostMixClsid%,,%FX_POSTMIX_CLSID% +HKR,"FX\\1",%PKEY_FX_UiClsid%,,%FX_UI_CLSID% +HKR,"FX\\1",%PKEY_FX_Association%,,%KSNODETYPE_SPDIF_INTERFACE% + +[Mixer_CMPCI.AddReg] +HKLM,%MediaCategories%\%GUID.CMIPCI%,Name,,%*WDM_CMPCI.DeviceDesc% +HKLM,%MediaCategories%\%GUID.CMIPCI%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IEC5V%,Name,,%Name.IEC5V% +HKLM,%MediaCategories%\%GUID.IEC5V%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECOut%,Name,,%Name.IECOut% +HKLM,%MediaCategories%\%GUID.IECOut%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECMonitor%,Name,,%Name.IECMonitor% +HKLM,%MediaCategories%\%GUID.IECMonitor%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECInverse%,Name,,%Name.IECInverse% +HKLM,%MediaCategories%\%GUID.IECInverse%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.DAC%,Name,,%Name.DAC% +HKLM,%MediaCategories%\%GUID.DAC%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECSelect%,Name,,%Name.IECSelect% +HKLM,%MediaCategories%\%GUID.IECSelect%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.XCHGFB%,Name,,%Name.XCHGFB% +HKLM,%MediaCategories%\%GUID.XCHGFB%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.BassLine%,Name,,%Name.BassLine% +HKLM,%MediaCategories%\%GUID.BassLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterLine%,Name,,%Name.CenterLine% +HKLM,%MediaCategories%\%GUID.CenterLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECCopyright%,Name,,%Name.IECCopyright% +HKLM,%MediaCategories%\%GUID.IECCopyright%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECPolValid%,Name,,%Name.IECPolValid% +HKLM,%MediaCategories%\%GUID.IECPolValid%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECLoop%,Name,,%Name.IECLoop% +HKLM,%MediaCategories%\%GUID.IECLoop%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.RearLine%,Name,,%Name.RearLine% +HKLM,%MediaCategories%\%GUID.RearLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterMic%,Name,,%Name.CenterMic% +HKLM,%MediaCategories%\%GUID.CenterMic%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Manuf%,Name,,%Name.Manuf% +HKLM,%MediaCategories%\%GUID.Manuf%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Component%,Name,,%Name.Component% +HKLM,%MediaCategories%\%GUID.Component%,Display,1,00,00,00,00 + +[DestinationDirs] +CMPCI.CopyList = 10, system32\drivers ; %SystemRoot%\system32\drivers +CPanel.CopyList = 10, system32 ; %SystemRoot%\system32\drivers +DefaultDestDir = 11 + +[CMPCI.CopyList] +cmipci.sys + +[CPanel.CopyList] +cmicpl.cpl +CMICONTROL.exe + +;;**************** NT Install **************** + +[WDM_CMPCI.NTAMD64] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList, CPanel.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.NTAMD64.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_REALTIME%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[WDM_CMPCI.NTAMD64.Services] +AddService = cmipci, 0x00000002, cmipci_Service_Inst + +[cmipci_Service_Inst] +DisplayName = %CMIPCI.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\system32\drivers\cmipci.sys + +[MPU401.NTAMD64] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.NTAMD64.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.NTAMD64.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[Strings] +CMMfgName="Dogbert" +*WDM_CMPCI.DeviceDesc="CMI8738/8768 Audio Device" +*WDM_CMMPU.DeviceDesc="CMI8738/8768 MPU-401" +WDM_CMPCI.Wave.szPname="CMI8738/8768 Wave" +WDM_CMPCI.Topo.szPname="CMI8738/8768 Mixer" +WDM_CMPCI.UART.szPname="CMI8738/8768 MPU401" +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_REALTIME="{EB115FFC-10C8-4964-831D-6DCB02E6F23F}" +KSNAME_Wave="Wave" +KSNAME_Topology="Topology" +KSNAME_UART="UART" +FX_UI_CLSID="{5860E1C5-F95C-4a7a-8EC8-8AEF24F379A1}" +KSNODETYPE_ANY="{00000000-0000-0000-0000-000000000000}" +FX_PREMIX_CLSID="{62dc1a93-ae24-464c-a43e-452f824c4250}" +FX_POSTMIX_CLSID="{637c490d-eee3-4c0a-973f-371958802da2}" +FX_FriendlyName="Microsoft Audio Home Theater Effects" +PKEY_FX_Association="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},0" +PKEY_FX_PreMixClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},1" +PKEY_FX_PostMixClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},2" +PKEY_FX_UiClsid="{D04E05A6-594B-4fb6-A80D-01AF5EED7D1D},3" +PKEY_ItemNameDisplay="{B725F130-47EF-101A-A5F1-02608C9EEBAC},10" +KSNODETYPE_SPEAKER="{DFF21CE1-F70F-11D0-B917-00A0C9223196}" +KSNODETYPE_SPDIF_INTERFACE="{DFF21FE5-F70F-11D0-B917-00A0C9223196}" +CMIPCI.SvcDesc="CMI8738/8768 Audio Driver" +GUID.CMIPCI="{9DB14E9A-7BE7-480d-A2FA-32932489DE9C}" +GUID.IEC5V="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0}" +Name.IEC5V="S/PDIF-out 5V signal levels" +GUID.IECOut="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1}" +Name.IECOut="Enable S/PDIF-out" +GUID.IECInverse="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2}" +Name.IECInverse="Invert S/PDIF-in signal" +GUID.IECMonitor="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3}" +Name.IECMonitor="Enable PCM DAC" +GUID.DAC="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4}" +Name.DAC="DAC" +GUID.IECSelect="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5}" +Name.IECSelect="Select secondary S/PDIF-in" +GUID.XCHGFB="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6}" +Name.XCHGFB="Exchange Front/Rear Jacks" +GUID.BassLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7}" +Name.BassLine="Route Bass to Line-In Jack" +GUID.CenterLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8}" +Name.CenterLine="Route Center to Line-In Jack" +GUID.IECCopyright="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9}" +Name.IECCopyright="Enable copyright bit" +GUID.IECPolValid="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA}" +Name.IECPolValid="Invert validity flag" +GUID.IECLoop="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB}" +Name.IECLoop="Loop S/PDIF-in to S/PDIF-out" +GUID.RearLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC}" +Name.RearLine="Route Rear to Line-In Jack" +GUID.CenterMic="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD}" +Name.CenterMic="Route Center to Mic-In Jack" +GUID.Manuf="{9DB14E9A-7BE7-480d-A2FA-32932489DE9E}" +Name.Manuf="Dogbert" +GUID.Component="{9DB14E9A-7BE7-480d-A2FA-32932489DE9D}" +Name.Component="main" diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64.inf b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64.inf new file mode 100644 index 00000000000..82d3323f938 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/CM8738-x64.inf @@ -0,0 +1,257 @@ +[Version] +Signature="$CHICAGO$" +Class=MEDIA +ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} +provider=%CMMfgName% +LayoutFile=layout.inf, layout1.inf, layout2.inf +DriverVer=CMIReleaseDate,CMIVersion.64 + +[SourceDisksNames] +200="C-Media 8738/8768 WDM Drivers","",0 + +[SourceDisksFiles] +cmipci.sys=200 +cmicpl.cpl=200 +CMICONTROL.exe=200 + +[Manufacturer] +%CMMfgName%=CMI,NTamd64 + +[ControlFlags] +ExcludeFromSelect=* + +[CMI.NTamd64] +;generic +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011013F6 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6 +;Terratec +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_1144153B +;Auzentech +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_3731584D +;Diamond +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_87681092 +;TurtleBeach +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020110B0 +;Phillips +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_060417AB +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020210B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_020410B0 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_009C145F +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_39801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_50701462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_52801462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_53401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_54511462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_56501462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59001462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_59201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70201462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70401462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_70411462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_71011462 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_A016147A +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_30021919 +%*WDM_CMPCI.DeviceDesc%=WDM_CMPCI, PCI\VEN_13F6&DEV_0111&SUBSYS_0577A0A0 +%*WDM_CMMPU.DeviceDesc%=MPU401, MPU401, *PNPB006 + +[WDM_CMPCI] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList,CPanel.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[MPU401.Interface.UART] +AddReg=MPU401.Interface.UART.AddReg +[MPU401.Interface.UART.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.UART.szPname% + +[WDM_CMPCI.Interface.Wave] +AddReg=WDM_PCI.Interface.Wave.AddReg +[WDM_PCI.Interface.Wave.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Wave.szPname% + +[WDM_CMPCI.Interface.Topo] +AddReg=WDM_PCI.Interface.Topo.AddReg +[WDM_PCI.Interface.Topo.AddReg] +HKR,,CLSID,,%Proxy.CLSID% +HKR,,FriendlyName,,%WDM_CMPCI.Topo.szPname% + +[WDM_CMPCI.AddReg] +HKR,,AssociatedFilters,,"wdmaud,swmidi,redbook" +HKR,,Driver,,CMIPCI.SYS +HKR,,NTMPDriver,,"CMIPCI.sys,sbemul.sys" +HKR,Drivers,SubClasses,,"wave,midi,mixer" +HKR,Drivers\wave\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\midi\wdmaud.drv, Driver,,wdmaud.drv +HKR,Drivers\mixer\wdmaud.drv,Driver,,wdmaud.drv +HKR,Drivers\wave\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\midi\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% +HKR,Drivers\mixer\wdmaud.drv,Description,,%*WDM_CMPCI.DeviceDesc% + +[Mixer_CMPCI.AddReg] +HKLM,%MediaCategories%\%GUID.CMIPCI%,Name,,%*WDM_CMPCI.DeviceDesc% +HKLM,%MediaCategories%\%GUID.CMIPCI%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IEC5V%,Name,,%Name.IEC5V% +HKLM,%MediaCategories%\%GUID.IEC5V%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECOut%,Name,,%Name.IECOut% +HKLM,%MediaCategories%\%GUID.IECOut%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECMonitor%,Name,,%Name.IECMonitor% +HKLM,%MediaCategories%\%GUID.IECMonitor%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECInverse%,Name,,%Name.IECInverse% +HKLM,%MediaCategories%\%GUID.IECInverse%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.DAC%,Name,,%Name.DAC% +HKLM,%MediaCategories%\%GUID.DAC%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECSelect%,Name,,%Name.IECSelect% +HKLM,%MediaCategories%\%GUID.IECSelect%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.XCHGFB%,Name,,%Name.XCHGFB% +HKLM,%MediaCategories%\%GUID.XCHGFB%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.BassLine%,Name,,%Name.BassLine% +HKLM,%MediaCategories%\%GUID.BassLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterLine%,Name,,%Name.CenterLine% +HKLM,%MediaCategories%\%GUID.CenterLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECCopyright%,Name,,%Name.IECCopyright% +HKLM,%MediaCategories%\%GUID.IECCopyright%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECPolValid%,Name,,%Name.IECPolValid% +HKLM,%MediaCategories%\%GUID.IECPolValid%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.IECLoop%,Name,,%Name.IECLoop% +HKLM,%MediaCategories%\%GUID.IECLoop%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.RearLine%,Name,,%Name.RearLine% +HKLM,%MediaCategories%\%GUID.RearLine%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.CenterMic%,Name,,%Name.CenterMic% +HKLM,%MediaCategories%\%GUID.CenterMic%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Manuf%,Name,,%Name.Manuf% +HKLM,%MediaCategories%\%GUID.Manuf%,Display,1,00,00,00,00 +HKLM,%MediaCategories%\%GUID.Component%,Name,,%Name.Component% +HKLM,%MediaCategories%\%GUID.Component%,Display,1,00,00,00,00 + +[DestinationDirs] +CMPCI.CopyList = 10, system32\drivers ; %SystemRoot%\system32\drivers +CPanel.CopyList = 10, system32 ; %SystemRoot%\system32\drivers +DefaultDestDir = 11 + +[CMPCI.CopyList] +cmipci.sys + +[CPanel.CopyList] +cmicpl.cpl +CMICONTROL.exe + +;;**************** NT Install **************** + +[WDM_CMPCI.NTAMD64] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration +CopyFiles=CMPCI.CopyList, CPanel.CopyList +AddReg=WDM_CMPCI.AddReg, Mixer_CMPCI.AddReg + +[WDM_CMPCI.NTAMD64.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_Wave%,WDM_CMPCI.Interface.Wave +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_Topology%,WDM_CMPCI.Interface.Topo +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[WDM_CMPCI.NTAMD64.Services] +AddService = cmipci, 0x00000002, cmipci_Service_Inst + +[cmipci_Service_Inst] +DisplayName = %CMIPCI.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %10%\system32\drivers\cmipci.sys + +[MPU401.NTAMD64] +Include=ks.inf, wdmaudio.inf +Needs=KS.Registration, WDMAUDIO.Registration, WDMAUDIO.MPU401 +AlsoInstall=KS.Registration(ks.inf), WDMAUDIO.Registration(wdmaudio.inf), WDMAUDIO.MPU401(wdmaudio.inf) + +[MPU401.NTAMD64.Interfaces] +AddInterface=%KSCATEGORY_AUDIO%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_RENDER%,%KSNAME_UART%,MPU401.Interface.UART +AddInterface=%KSCATEGORY_CAPTURE%,%KSNAME_UART%,MPU401.Interface.UART + +[MPU401.NTAMD64.Services] +Needs=WDMAUDIO.MPU401.Services +AlsoInstall=WDMAUDIO.MPU401.Services(wdmaudio.inf) + +[Strings] +CMMfgName="Dogbert" +*WDM_CMPCI.DeviceDesc="CMI8738/8768 Audio Device" +*WDM_CMMPU.DeviceDesc="CMI8738/8768 MPU-401" +WDM_CMPCI.Wave.szPname="CMI8738/8768 Wave" +WDM_CMPCI.Topo.szPname="CMI8738/8768 Mixer" +WDM_CMPCI.UART.szPname="CMI8738/8768 MPU401" +MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories" +Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" +KSCATEGORY_AUDIO="{6994AD04-93EF-11D0-A3CC-00A0C9223196}" +KSCATEGORY_RENDER="{65E8773E-8F56-11D0-A3B9-00A0C9223196}" +KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}" +KSNAME_Wave="Wave" +KSNAME_Topology="Topology" +KSNAME_UART="UART" +CMIPCI.SvcDesc = "CMI8738/8768 Audio Driver" +GUID.CMIPCI="{9DB14E9A-7BE7-480d-A2FA-32932489DE9C}" +GUID.IEC5V="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0}" +Name.IEC5V="S/PDIF-out 5V signal levels" +GUID.IECOut="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1}" +Name.IECOut="Enable S/PDIF-out" +GUID.IECInverse="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2}" +Name.IECInverse="Invert S/PDIF-in signal" +GUID.IECMonitor="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3}" +Name.IECMonitor="Enable PCM DAC" +GUID.DAC="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4}" +Name.DAC="DAC" +GUID.IECSelect="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5}" +Name.IECSelect="Select secondary S/PDIF-in" +GUID.XCHGFB="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6}" +Name.XCHGFB="Exchange Front/Rear Jacks" +GUID.BassLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7}" +Name.BassLine="Route Bass to Line-In Jack" +GUID.CenterLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8}" +Name.CenterLine="Route Center to Line-In Jack" +GUID.IECCopyright="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9}" +Name.IECCopyright="Enable copyright bit" +GUID.IECPolValid="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA}" +Name.IECPolValid="Invert validity flag" +GUID.IECLoop="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB}" +Name.IECLoop="Loop S/PDIF-in to S/PDIF-out" +GUID.RearLine="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC}" +Name.RearLine="Route Rear to Line-In Jack" +GUID.CenterMic="{2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD}" +Name.CenterMic="Route Center to Mic-In Jack" +GUID.Manuf="{9DB14E9A-7BE7-480d-A2FA-32932489DE9E}" +Name.Manuf="Dogbert" +GUID.Component="{9DB14E9A-7BE7-480d-A2FA-32932489DE9D}" +Name.Component="main" \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/HowToBuild.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/HowToBuild.txt new file mode 100644 index 00000000000..254d0722fa8 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/HowToBuild.txt @@ -0,0 +1,22 @@ +For compiling and building the WDM driver, the following software is required: +- Microsoft Windows Driver Development Kit (http://www.microsoft.com/whdc/devtools/wdk/default.mspx) +- 7Zip (http://www.7-zip.org/) +- Sed (http://gnuwin32.sourceforge.net/packages/sed.htm) + +The directories which contain 7z.exe, sed.exe and devcon.exe need to be in your %PATH% environment variable. Replace the file 'dsound.lib' in the [WINDDK]\[xxxx]\lib\w2k\i386 folder with the version from [WINDDK]\[xxxx]\lib\wxp\i386. + +The source files should be unpacked to [WINDDK]\[xxxx]\src\[\wdm]\audio\cmedia + +envars.bat - contains some environment variables: you probably want to change them +make.bat - creates a debug build for x86 systems +update.bat - replaces the currently installed driver with the x86 debug build +build-release-x64.bat - creates a non-WaveRT deployment build for x64 systems +build-release-x64-WaveRT.bat - creates a WaveRT deployment build for x64 systems +build-release-x86.bat - creates a non-WaveRT deployment build for x86 systems +build-release-x86-WaveRT.bat - creates a WaveRT deployment build for x86 systems +distclean.bat - cleans up and packs the source +build-all.bat - builds all versions and packs the source + +For testing and debugging, DebugView (http://www.microsoft.com/technet/sysinternals/utilities/debugview.mspx) is very helpful. + +If you have questions, feel free to mail me: dogber1@gmail.com \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp new file mode 100644 index 00000000000..9a385742b95 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp @@ -0,0 +1,417 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define PUT_GUIDS_HERE + +#include "adapter.hpp" + +#pragma code_seg("PAGE") + + +NTSTATUS InstallSubdevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PWCHAR Name, REFGUID PortClassId, REFGUID MiniportClassId, PFNCREATEINSTANCE MiniportCreate, PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, REFGUID PortInterfaceId, PUNKNOWN* OutPortUnknown) +{ + PAGED_CODE(); + DBGPRINT(("InstallSubdevice()")); + + NTSTATUS ntStatus; + PPORT Port; + PMINIPORT MiniPort; + + ntStatus = PcNewPort(&Port, PortClassId); + if (NT_SUCCESS(ntStatus)) { + if (MiniportCreate) { + ntStatus = MiniportCreate((PUNKNOWN*)&MiniPort, MiniportClassId, NULL, NonPagedPool); + } else { + ntStatus = PcNewMiniport(&MiniPort, MiniportClassId); + } + } + + if (!NT_SUCCESS(ntStatus)) { + Port->Release(); + return ntStatus; + } + + ntStatus = Port->Init(DeviceObject, Irp, MiniPort, UnknownAdapter, ResourceList); + if (NT_SUCCESS(ntStatus)) { + ntStatus = PcRegisterSubdevice(DeviceObject, Name, Port); + + if (OutPortUnknown && NT_SUCCESS (ntStatus)) { + ntStatus = Port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown); + } + } + + if (MiniPort) { + MiniPort->Release(); + } + + if (Port) { + Port->Release(); + } + + return ntStatus; +} + + +NTSTATUS ProcessResources(PRESOURCELIST ResourceList, PRESOURCELIST* UartResourceList) +{ + PAGED_CODE(); + ASSERT(ResourceList); + ASSERT(UartResourceList); + DBGPRINT(("ProcessResources()")); + DBGPRINT(("NumberOfPorts: %d, NumberOfInterrupts: %d, NumberOfDmas: %d", ResourceList->NumberOfPorts(), ResourceList->NumberOfInterrupts(), ResourceList->NumberOfDmas())); + +#ifdef UART + (*UartResourceList) = NULL; +#endif + + NTSTATUS ntStatus; + if ((ResourceList->NumberOfPorts() == 0) || (ResourceList->NumberOfPorts() > 2) || (ResourceList->NumberOfInterrupts() != 1) || (ResourceList->NumberOfDmas() != 0)) { + DBGPRINT(("Unexpected configuration")); + return STATUS_DEVICE_CONFIGURATION_ERROR; + } + +#ifdef UART + ntStatus = PcNewResourceSublist(UartResourceList, NULL, PagedPool, ResourceList, 2); + if (NT_SUCCESS(ntStatus)) { + (*UartResourceList)->AddPortFromParent(ResourceList, 1); + (*UartResourceList)->AddInterruptFromParent(ResourceList, 0); + } +#endif + + return STATUS_SUCCESS; +} + + +NTSTATUS StartDevice(PDEVICE_OBJECT DeviceObject, PIRP Irp, PRESOURCELIST ResourceList) +{ + PAGED_CODE(); + ASSERT(DeviceObject); + ASSERT(Irp); + ASSERT(ResourceList); + DBGPRINT(("StartDevice()")); + + NTSTATUS ntStatus; + PPORT pPort = 0; + ULONG* MPUBase; + + ntStatus = PcNewPort(&pPort,CLSID_PortWaveCyclic); + if (NT_SUCCESS(ntStatus)) { + // not supported in the first edition of win98 + PPORTEVENTS pPortEvents = 0; + ntStatus = pPort->QueryInterface(IID_IPortEvents, (PVOID *)&pPortEvents); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("ERROR: This driver doesn't work under Win98!")); + ntStatus = STATUS_UNSUCCESSFUL; + } + else + { + pPortEvents->Release(); + } + pPort->Release (); + } else { + return ntStatus; + } + + // resource validation + PRESOURCELIST UartResourceList = NULL; + ntStatus = ProcessResources(ResourceList, &UartResourceList); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("ProcessResources() failed")); + return ntStatus; + } + + PCMIADAPTER pCMIAdapter = NULL; + PUNKNOWN pUnknownCommon = NULL; + + // create the CMIAdapter object + ntStatus = NewCMIAdapter(&pUnknownCommon, IID_ICMIAdapter, NULL, NonPagedPool); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("NewCMIAdapter() failed")); + return ntStatus; + } + + ntStatus = pUnknownCommon->QueryInterface(IID_ICMIAdapter, (PVOID *)&pCMIAdapter); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("QueryInterface() for ICMIAdapter failed")); + return ntStatus; + } + ntStatus = pCMIAdapter->init(ResourceList, DeviceObject); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("CMIAdapter->init() failed")); + return ntStatus; + } + + ntStatus = PcRegisterAdapterPowerManagement((PUNKNOWN)pCMIAdapter, DeviceObject); + + pUnknownCommon->Release(); + + PUNKNOWN unknownWave = NULL; + PUNKNOWN unknownTopology = NULL; + + // install the topology miniport. + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Topology", CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyCMI, pCMIAdapter, NULL, GUID_NULL, &unknownTopology); + if (!NT_SUCCESS (ntStatus)) { + DBGPRINT(("Topology miniport installation failed")); + return ntStatus; + } + +#ifdef UART + // install the UART miniport - execution order important + ntStatus = STATUS_UNSUCCESSFUL; + MPUBase = 0; + for (int i=0;iNumberOfPorts();i++) { + if (ResourceList->FindTranslatedPort(i)->u.Port.Length == 2) { + MPUBase = (UInt32*)ResourceList->FindTranslatedPort(i)->u.Port.Start.QuadPart; + } + } + if (MPUBase != 0) { + ntStatus = pCMIAdapter->activateMPU(MPUBase); + if (NT_SUCCESS(ntStatus)) { + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Uart", CLSID_PortDMus, CLSID_MiniportDriverDMusUART, NULL, pCMIAdapter->getInterruptSync(), UartResourceList, IID_IPortDMus, NULL); + } + } + if (!NT_SUCCESS(ntStatus)) { + MPUBase = 0; + pCMIAdapter->activateMPU(0); + DBGPRINT(("UART miniport installation failed")); + } + if (UartResourceList) { + UartResourceList->Release(); + } +#endif + + // install the wave miniport - the order matters here +#ifdef WAVERT + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveRT, CLSID_PortWaveRT, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveRT, &unknownWave); +#else + ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave", CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCMI, pCMIAdapter, ResourceList, IID_IPortWaveCyclic, &unknownWave); +#endif + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Wave miniport installation failed")); + return ntStatus; + } + + // connect wave and topology pins + ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownWave, PIN_WAVE_RENDER_SOURCE, unknownTopology, PIN_WAVEOUT_SOURCE); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Cannot connect topology and wave miniport (render)!")); + return ntStatus; + } + ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownTopology, PIN_WAVEIN_DEST, unknownWave, PIN_WAVE_CAPTURE_SOURCE); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Cannot connect topology and wave miniport (capture)!")); + return ntStatus; + } + if (!IoIsWdmVersionAvailable(6,0)) { + // this shit fixes the fucking XP mixer and breaks the vista mixer, so we have to check for vista here + ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownWave, PIN_WAVE_AC3_RENDER_SOURCE, unknownTopology, PIN_SPDIF_AC3_SOURCE); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Cannot connect topology and wave miniport (ac3)!")); + } + } + + // clean up + if (pCMIAdapter) { + pCMIAdapter->Release(); + } + if (unknownTopology) { + unknownTopology->Release(); + } + if (unknownWave) { + unknownWave->Release(); + } + + return ntStatus; +} + +extern "C" NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject) +{ + PAGED_CODE(); + DBGPRINT(("AddDevice()")); + + return PcAddAdapterDevice(DriverObject, PhysicalDeviceObject, (PCPFNSTARTDEVICE)StartDevice, MAX_MINIPORTS, 0); +} + +bool CopyResourceDescriptor(PIO_RESOURCE_DESCRIPTOR pInResDescriptor, PIO_RESOURCE_DESCRIPTOR pOutResDescriptor) +{ + PAGED_CODE(); + ASSERT(pInResDescriptor); + ASSERT(pOutResDescriptor); + DBGPRINT(("CopyResourceDescriptor()")); + +#if 0 + RtlCopyMemory(pOutResDescriptor, pInResDescriptor, sizeof(IO_RESOURCE_DESCRIPTOR)); +#else + pOutResDescriptor->Type = pInResDescriptor->Type; + pOutResDescriptor->ShareDisposition = pInResDescriptor->ShareDisposition; + pOutResDescriptor->Flags = pInResDescriptor->Flags; + pOutResDescriptor->Option = pInResDescriptor->Option; + + switch (pInResDescriptor->Type) { + case CmResourceTypePort: + case CmResourceTypePort | CmResourceTypeNonArbitrated: // huh? +/* // filter crap + if ((pInResDescriptor->u.Port.Length == 0) || + ( (pInResDescriptor->u.Port.MinimumAddress.HighPart == pInResDescriptor->u.Port.MaximumAddress.HighPart) && (pInResDescriptor->u.Port.MinimumAddress.LowPart == pInResDescriptor->u.Port.MaximumAddress.LowPart) ) ) { + return FALSE; + } +*/ pOutResDescriptor->u.Port.MinimumAddress = pInResDescriptor->u.Port.MinimumAddress; + pOutResDescriptor->u.Port.MaximumAddress = pInResDescriptor->u.Port.MaximumAddress; + pOutResDescriptor->u.Port.Length = pInResDescriptor->u.Port.Length; + pOutResDescriptor->u.Port.Alignment = pInResDescriptor->u.Port.Alignment; + DBGPRINT((" Port: min %08x.%08x max %08x.%08x, Length: %x, Option: %x", pOutResDescriptor->u.Port.MinimumAddress.HighPart, pOutResDescriptor->u.Port.MinimumAddress.LowPart, + pOutResDescriptor->u.Port.MaximumAddress.HighPart, pOutResDescriptor->u.Port.MaximumAddress.LowPart, + pOutResDescriptor->u.Port.Length, pOutResDescriptor->Option)); + break; + case CmResourceTypeInterrupt: + pOutResDescriptor->u.Interrupt.MinimumVector = pInResDescriptor->u.Interrupt.MinimumVector; + pOutResDescriptor->u.Interrupt.MaximumVector = pInResDescriptor->u.Interrupt.MaximumVector; + DBGPRINT((" IRQ: min %x max %x, Option: %d", pOutResDescriptor->u.Interrupt.MinimumVector, pOutResDescriptor->u.Interrupt.MaximumVector, pOutResDescriptor->Option)); + break; + default: + return FALSE; + } + return TRUE; +#endif +} + +extern "C" NTSTATUS AdapterDispatchPnp(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) +{ + PAGED_CODE(); + ASSERT(pDeviceObject); + ASSERT(pIrp); + DBGPRINT(("AdapterDispatchPnp()")); + + NTSTATUS ntStatus = STATUS_SUCCESS; + ULONG resourceListSize; + PIO_RESOURCE_REQUIREMENTS_LIST resourceList, list; + PIO_RESOURCE_DESCRIPTOR descriptor; + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + + if (pIrpStack->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS) { + DBGPRINT(("[AdapterDispatchPnp] - IRP_MN_FILTER_RESOURCE_REQUIREMENTS")); + + list = (PIO_RESOURCE_REQUIREMENTS_LIST)pIrp->IoStatus.Information; + + // IO_RESOURCE_REQUIREMENTS_LIST has 1 IO_RESOURCE_LIST, IO_RESOURCE_LIST has 1 IO_RESOURCE_DESCRIPTOR and we want 2 more + resourceListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR)*(list->List[0].Count+2) ; + resourceList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, resourceListSize, 'LRDV'); + + if (!resourceList) { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; + } + + + RtlZeroMemory(resourceList, resourceListSize); + + // initialize the list header + resourceList->AlternativeLists = 1; // number of IO_RESOURCE_LISTs + resourceList->ListSize = resourceListSize; + + resourceList->List[0].Version = 1; + resourceList->List[0].Revision = 1; + resourceList->List[0].Count = 0; + + // copy the resources which have already been assigned + for (int i=0;iList[0].Count;i++) { + if (CopyResourceDescriptor(&list->List[0].Descriptors[i], &resourceList->List[0].Descriptors[resourceList->List[0].Count])) { + resourceList->List[0].Count++; + } + } + ExFreePool(list); + + // an additional port for mpu401 + resourceList->List[0].Count++; + descriptor = &resourceList->List[0].Descriptors[resourceList->List[0].Count-1]; + descriptor->Option = IO_RESOURCE_PREFERRED; + descriptor->Type = CmResourceTypePort; + descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + descriptor->Flags = CM_RESOURCE_PORT_IO; + descriptor->u.Port.MinimumAddress.LowPart = 0x300; + descriptor->u.Port.MinimumAddress.HighPart = 0; + descriptor->u.Port.MaximumAddress.LowPart = 0x330; + descriptor->u.Port.MaximumAddress.HighPart = 0; + descriptor->u.Port.Length = 2; + descriptor->u.Port.Alignment = 0x10; + + // mpu401 port should be optional. yes, this is severely braindamaged. + resourceList->List[0].Count++; + descriptor = &resourceList->List[0].Descriptors[resourceList->List[0].Count-1]; + descriptor->Option = IO_RESOURCE_ALTERNATIVE; + descriptor->Type = CmResourceTypePort; + descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + descriptor->Flags = CM_RESOURCE_PORT_IO; + descriptor->u.Port.MinimumAddress.LowPart = 0x0; + descriptor->u.Port.MinimumAddress.HighPart = 0; + descriptor->u.Port.MaximumAddress.LowPart = 0xFFFF; + descriptor->u.Port.MaximumAddress.HighPart = 0; + descriptor->u.Port.Length = 1; + descriptor->u.Port.Alignment = 0x10; + + DBGPRINT(("number of resource list descriptors: %d", resourceList->List[0].Count)); + + pIrp->IoStatus.Information = (ULONG_PTR)resourceList; + + // set the return status + pIrp->IoStatus.Status = ntStatus; + } + + // Pass the IRPs on to PortCls + ntStatus = PcDispatchIrp(pDeviceObject, pIrp); + + return ntStatus; +} + +extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPathName) +{ + PAGED_CODE(); + DBGPRINT(("DriverEntry()")); + + NTSTATUS ntStatus; + + //bind the adapter driver to the portclass driver + ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName, AddDevice); +#ifdef UART + if(NT_SUCCESS(ntStatus)) { + DriverObject->MajorFunction[IRP_MJ_PNP] = AdapterDispatchPnp; + } +#endif +#ifdef WAVERT + if (!IoIsWdmVersionAvailable(6,0)) { + ntStatus = STATUS_UNSUCCESSFUL; + } +#endif + + return ntStatus; +} + +#pragma code_seg() +int __cdecl _purecall (void) +{ + return 0; +} diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp new file mode 100644 index 00000000000..c457dc79a14 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.hpp @@ -0,0 +1,72 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _ADAPTER_HPP_ +#define _ADAPTER_HPP_ + +#include "interfaces.hpp" +#include "debug.hpp" +#include "DMusicKS.h" + +#ifdef UART +const ULONG MAX_MINIPORTS = 3; +#else +const ULONG MAX_MINIPORTS = 2; +#endif + +extern NTSTATUS CreateMiniportWaveCMI +( + OUT PUNKNOWN * Unknown, + IN REFCLSID, + IN PUNKNOWN UnknownOuter OPTIONAL, + IN POOL_TYPE PoolType +); + +extern NTSTATUS CreateMiniportTopologyCMI +( + OUT PUNKNOWN * Unknown, + IN REFCLSID, + IN PUNKNOWN UnknownOuter OPTIONAL, + IN POOL_TYPE PoolType +); + +extern NTSTATUS NewCMIAdapter +( + OUT PUNKNOWN * Unknown, + IN REFCLSID, + IN PUNKNOWN UnknownOuter OPTIONAL, + IN POOL_TYPE PoolType +); + +extern "C" NTSTATUS AdapterDispatchPnp +( + IN PDEVICE_OBJECT pDeviceObject, + IN PIRP pIrp +); + +#endif //_ADAPTER_HPP_ + diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/build-all.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-all.bat new file mode 100644 index 00000000000..53e1b814e8a --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-all.bat @@ -0,0 +1,6 @@ +@echo off +start /wait cmd.exe /c distclean.bat +start /wait cmd.exe /c build-release-x64.bat +start /wait cmd.exe /c build-release-x64-WaveRT.bat +start /wait cmd.exe /c build-release-x86.bat +start /wait cmd.exe /c build-release-x86-WaveRT.bat \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64-WaveRT.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64-WaveRT.bat new file mode 100644 index 00000000000..1672e3be805 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64-WaveRT.bat @@ -0,0 +1,32 @@ +@echo off +call envars.bat +call %CMI_DDKDIR%\bin\setenv %CMI_DDKDIR% fre AMD64 +cd %CMI_BUILDDIR% +del CMIDriver-%CMI_VERSION%-bin-x64-WaveRT.zip +del installer\objfre_wlh_AMD64\AMD64\*.obj +del installer\objfre_wlh_AMD64\AMD64\*.exe +del cmicontrol\objfre_wlh_AMD64\AMD64\*.obj +del cmicontrol\objfre_wlh_AMD64\AMD64\*.exe +del cpl\objfre_wlh_AMD64\AMD64\*.obj +del cpl\objfre_wlh_AMD64\AMD64\*.exe +del objfre_wlh_AMD64\AMD64\*.obj +del objfre_wlh_AMD64\AMD64\*.sys +sed -i "s/CMIVERSION.*/CMIVERSION \"%CMI_VERSION%\"/" debug.hpp +sed -i "s/^\/\/#define WAVERT/#define WAVERT/" debug.hpp +nmake /x errors.err +mkdir release-x64-WaveRT +copy objfre_wlh_AMD64\AMD64\*.sys release-x64-WaveRT +sed -e "s/CMIVersion/%CMI_VERSION%/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x64-WaveRT.inf >release-x64-WaveRT\CM8738.inf +copy CHANGELOG.txt release-x64-WaveRT +cd cmicontrol +nmake /x errors.err +copy objfre_wlh_AMD64\AMD64\cmicontrol.exe ..\release-x64-WaveRT +cd ..\cpl +build -cZ +copy objfre_wlh_AMD64\AMD64\cmicpl.cpl ..\release-x64-WaveRT +cd ..\installer +build -cZ +copy objfre_wlh_AMD64\AMD64\setup.exe ..\release-x64-WaveRT +cd ..\release-x64-WaveRT +7z a -tzip ..\CMIDriver-%CMI_VERSION%-bin-x64-WaveRT.zip * +cd .. \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64.bat new file mode 100644 index 00000000000..a2843b008c4 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x64.bat @@ -0,0 +1,32 @@ +@echo off +call envars.bat +call %CMI_DDKDIR%\bin\setenv %CMI_DDKDIR% fre AMD64 +cd %CMI_BUILDDIR% +del CMIDriver-%CMI_VERSION%-bin-x64.zip +del installer\objfre_wlh_AMD64\AMD64\*.obj +del installer\objfre_wlh_AMD64\AMD64\*.exe +del cmicontrol\objfre_wlh_AMD64\AMD64\*.obj +del cmicontrol\objfre_wlh_AMD64\AMD64\*.exe +del cpl\objfre_wlh_AMD64\AMD64\*.obj +del cpl\objfre_wlh_AMD64\AMD64\*.exe +del objfre_wlh_AMD64\AMD64\*.obj +del objfre_wlh_AMD64\AMD64\*.sys +sed -i "s/CMIVERSION.*/CMIVERSION \"%CMI_VERSION%\"/" debug.hpp +sed -i "s/^#define WAVERT/\/\/#define WAVERT/" debug.hpp +nmake /x errors.err +mkdir release-x64 +copy objfre_wlh_AMD64\AMD64\*.sys release-x64 +sed -e "s/CMIVersion/%CMI_VERSION%/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x64.inf >release-x64\CM8738.inf +copy CHANGELOG.txt release-x64 +cd cmicontrol +nmake /x errors.err +copy objfre_wlh_AMD64\AMD64\cmicontrol.exe ..\release-x64 +cd ..\cpl +build -cZ +copy objfre_wlh_AMD64\AMD64\cmicpl.cpl ..\release-x64 +cd ..\installer +build -cZ +copy objfre_wlh_AMD64\AMD64\setup.exe ..\release-x64 +cd ..\release-x64 +7z a -tzip ..\CMIDriver-%CMI_VERSION%-bin-x64.zip * +cd .. \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86-WaveRT.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86-WaveRT.bat new file mode 100644 index 00000000000..02c6bbe6f09 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86-WaveRT.bat @@ -0,0 +1,32 @@ +@echo off +call envars.bat +call %CMI_DDKDIR%\bin\setenv %CMI_DDKDIR% fre x86 +cd %CMI_BUILDDIR% +del CMIDriver-%CMI_VERSION%-bin-x86-WaveRT.zip +del installer\objfre_wlh_x86\i386\*.obj +del installer\objfre_wlh_x86\i386\*.exe +del cmicontrol\objfre_wlh_x86\i386\*.obj +del cmicontrol\objfre_wlh_x86\i386\*.exe +del cpl\objfre_wlh_x86\i386\*.obj +del cpl\objfre_wlh_x86\i386\*.exe +del objfre_wlh_x86\i386\*.obj +del objfre_wlh_x86\i386\*.sys +sed -i "s/CMIVERSION.*/CMIVERSION \"%CMI_VERSION%\"/" debug.hpp +sed -i "s/^\/\/#define WAVERT/#define WAVERT/" debug.hpp +nmake /x errors.err +mkdir release-x86-WaveRT +copy objfre_wlh_x86\i386\*.sys release-x86-WaveRT +sed -e "s/CMIVersion/%CMI_VERSION%/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x32-WaveRT.inf >release-x86-WaveRT\CM8738.inf +copy CHANGELOG.txt release-x86-WaveRT +cd cmicontrol +nmake /x errors.err +copy objfre_wlh_x86\i386\cmicontrol.exe ..\release-x86-WaveRT +cd ..\cpl +build -cZ +copy objfre_wlh_x86\i386\cmicpl.cpl ..\release-x86-WaveRT +cd ..\installer +build -cZ +copy objfre_wlh_x86\i386\setup.exe ..\release-x86-WaveRT +cd ..\release-x86-WaveRT +7z a -tzip ..\CMIDriver-%CMI_VERSION%-bin-x86-WaveRT.zip * +cd .. \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86.bat new file mode 100644 index 00000000000..823d55a0049 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/build-release-x86.bat @@ -0,0 +1,32 @@ +@echo off +call envars.bat +call %CMI_DDKDIR%\bin\setenv %CMI_DDKDIR% fre x86 wxp +cd %CMI_BUILDDIR% +del CMIDriver-%CMI_VERSION%-bin-x86.zip +del installer\objfre_wxp_x86\i386\*.obj +del installer\objfre_wxp_x86\i386\*.exe +del cmicontrol\objfre_wxp_x86\i386\*.obj +del cmicontrol\objfre_wxp_x86\i386\*.exe +del cpl\objfre_wxp_x86\i386\*.obj +del cpl\objfre_wxp_x86\i386\*.exe +del objfre_wxp_x86\i386\*.obj +del objfre_wxp_x86\i386\*.sys +sed -i "s/CMIVERSION.*/CMIVERSION \"%CMI_VERSION%\"/" debug.hpp +sed -i "s/^#define WAVERT/\/\/#define WAVERT/" debug.hpp +nmake /x errors.err +mkdir release-x86 +copy objfre_wxp_x86\i386\*.sys release-x86 +sed -e "s/CMIVersion/%CMI_VERSION%/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x32.inf >release-x86\CM8738.inf +copy CHANGELOG.txt release-x86 +cd cmicontrol +nmake /x errors.err +copy objfre_wxp_x86\i386\cmicontrol.exe ..\release-x86 +cd ..\cpl +build -cZ +copy objfre_wxp_x86\i386\cmicpl.cpl ..\release-x86 +cd ..\installer +build -cZ +copy objfre_wxp_x86\i386\setup.exe ..\release-x86 +cd ..\release-x86 +7z a -tzip ..\CMIDriver-%CMI_VERSION%-bin-x86.zip * +cd .. \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp new file mode 100644 index 00000000000..5b715a8a5b2 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.cpp @@ -0,0 +1,970 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "main.h" + + +void PrintLastError(LPCSTR function) +{ + LPVOID lpMsgBuf; + DWORD errorid = GetLastError(); + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); + MessageBox(NULL, (LPCSTR)lpMsgBuf, function, MB_ICONEXCLAMATION | MB_OK); + LocalFree(lpMsgBuf); +} + +BOOL generateTestSignal(double amplitude, int Channels, int SamplesPerSec, SHORT** buffer) +{ + int i, o2, o3, o4, o5; + bool Left,Right,BackLeft,BackRight,Center,Sub, CenterLeft, CenterRight; + short value; + double x = SPEAKER_FREQUENCY*2*3.141592654/SamplesPerSec; + double y = BASS_FREQUENCY*2*3.141592654/SamplesPerSec; + + Left = (SendMessage(GetDlgItem(hWndChild[0], IDC_LEFT), BM_GETCHECK, 0, 0) == BST_CHECKED); + Right = (SendMessage(GetDlgItem(hWndChild[0], IDC_RIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED); + BackLeft = (SendMessage(GetDlgItem(hWndChild[0], IDC_BLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); + BackRight = (SendMessage(GetDlgItem(hWndChild[0], IDC_BRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); + Center = (SendMessage(GetDlgItem(hWndChild[0], IDC_CENTER), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); + Sub = (SendMessage(GetDlgItem(hWndChild[0], IDC_SUB), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); + CenterLeft = (SendMessage(GetDlgItem(hWndChild[0], IDC_CLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); + CenterRight = (SendMessage(GetDlgItem(hWndChild[0], IDC_CRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); + + if (!(Left || Right || BackLeft || BackRight || Center || Sub || CenterLeft || CenterRight)) { + return FALSE; + } + + if (currentChannelCount > 4) { + o2 = 4; o3 = 5; + o4 = 2; o5 = 3; + } else { + o2 = 2; o3 = 3; + o4 = 4; o5 = 5; + } + + (*buffer) = (SHORT*)LocalAlloc(LPTR, SamplesPerSec*sizeof(SHORT)*Channels); + ZeroMemory((*buffer), SamplesPerSec*sizeof(SHORT)*Channels); + + for (i=0;i> 3) * wfx.Format.nChannels; + wfx.Format.nAvgBytesPerSec = SAMPLE_RATE * (wfx.Format.wBitsPerSample >> 3) * wfx.Format.nChannels; + wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample ; + wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; +#else + WAVEFORMATEX wfx; + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.wBitsPerSample = 16; + wfx.nChannels = (WORD)currentChannelCount; + wfx.nSamplesPerSec = SAMPLE_RATE; + wfx.nAvgBytesPerSec = SAMPLE_RATE * (wfx.wBitsPerSample >> 3) * wfx.nChannels; + wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; + wfx.cbSize = 0; +#endif + + if (waveOutOpen(&hWave, findWaveDeviceID(), (WAVEFORMATEX*)&(wfx), 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) { + PrintLastError("waveOutOpen()"); + return FALSE; + } + + if (!generateTestSignal(SPEAKER_AMPLITUDE, currentChannelCount, SAMPLE_RATE, &buffer)) { + return FALSE; + } + + ZeroMemory(&pwh, sizeof(pwh)); + pwh.lpData = (LPSTR)buffer; + pwh.dwBufferLength = SAMPLE_RATE*sizeof(SHORT)*currentChannelCount; + pwh.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; + pwh.dwLoops = 0xFFFFFFFF; + if (waveOutPrepareHeader(hWave, &pwh, sizeof(pwh)) != MMSYSERR_NOERROR) { + LocalFree(buffer); + PrintLastError("waveOutPrepareHeader()"); + return FALSE; + } + + if (waveOutReset(hWave) != MMSYSERR_NOERROR) { + LocalFree(buffer); + PrintLastError("waveOutReset()"); + return FALSE; + } + if (waveOutWrite(hWave, &pwh, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) { + LocalFree(buffer); + PrintLastError("waveOutWrite()"); + return FALSE; + } + + return TRUE; +} + + +BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext) +{ + LPGUID* pGUID = (LPGUID*)lpContext; + + if (pGUID == NULL) { + return FALSE; + } + if ((*pGUID) != NULL) { + return TRUE; + } + + if (lpGUID != NULL) { + // XP, 2k + if ((CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, lpszDrvName, -1, TEXT("cmipci.sys"), -1) == CSTR_EQUAL) && + (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, lpszDesc, -1, TEXT("CMI8738/8768 Wave"), -1) == CSTR_EQUAL)) { + (*pGUID) = (LPGUID)LocalAlloc(LPTR, sizeof(GUID)); + memcpy((*pGUID), lpGUID, sizeof(GUID)); + return TRUE; + } + // Vista + if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, lpszDesc, -1, TEXT("Speakers (CMI8738/8768 Audio Device)"), -1) == CSTR_EQUAL) { + (*pGUID) = (LPGUID)LocalAlloc(LPTR, sizeof(GUID)); + memcpy((*pGUID), lpGUID, sizeof(GUID)); + return TRUE; + } + } + return TRUE; +} + +BOOL getCurrentChannelConfig() +{ + IDirectSound8* ds; + DWORD speakerConfig; + LPGUID guid = NULL; + + DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, (VOID*)&guid); + + if (DirectSoundCreate8(guid, &ds, NULL) != S_OK) { + PrintLastError("DirectSoundCreate8()"); + return FALSE; + } + + ds->Initialize(NULL); + + if (ds->GetSpeakerConfig(&speakerConfig) != S_OK) { + PrintLastError("GetSpeakerConfig()"); + return FALSE; + } + + if (ds) { + ds->Release(); + } + if (guid) { + LocalFree(guid); + } + + switch (DSSPEAKER_CONFIG(speakerConfig)) { + case DSSPEAKER_STEREO: currentChannelCount = 2; return TRUE; + case DSSPEAKER_QUAD: currentChannelCount = 4; return TRUE; + case DSSPEAKER_5POINT1: currentChannelCount = 6; return TRUE; + case DSSPEAKER_7POINT1: currentChannelCount = 8; return TRUE; + } + + return FALSE; +} + +BOOL setCurrentChannelConfig() +{ + IDirectSound8* ds; + DWORD speakerConfig; + LPGUID guid = NULL; + + DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, (VOID*)&guid); + + if (DirectSoundCreate8(guid, &ds, NULL) != S_OK) { + PrintLastError("DirectSoundCreate8()"); + return FALSE; + } + + + ds->Initialize(NULL); + + switch (currentChannelCount) { + case 2: speakerConfig = DSSPEAKER_STEREO; break; + case 4: speakerConfig = DSSPEAKER_QUAD; break; + case 6: speakerConfig = DSSPEAKER_5POINT1; break; + case 8: speakerConfig = DSSPEAKER_7POINT1; break; + } + + if (ds->SetSpeakerConfig(speakerConfig) != S_OK) { + PrintLastError("SetSpeakerConfig()"); + return FALSE; + } + + if (ds) { + ds->Release(); + } + if (guid) { + LocalFree(guid); + } + + + return FALSE; +} + +BOOL getDeviceInfo(const GUID* category, CMIDEV* pDev) +{ + TCHAR szServiceName[128]; + int nIndex = 0; + + pDev->Info = SetupDiGetClassDevs(category, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if (pDev->Info == INVALID_HANDLE_VALUE) { + PrintLastError("SetupDiGetClassDevs()"); + return FALSE; + } + + pDev->InfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + while (SetupDiEnumDeviceInfo(pDev->Info, nIndex, &(pDev->InfoData))) { + if (!SetupDiGetDeviceRegistryProperty(pDev->Info, &(pDev->InfoData), SPDRP_SERVICE, NULL, (PBYTE)szServiceName, sizeof(szServiceName), NULL)) { + PrintLastError("SetupDiGetDeviceRegistryProperty()"); + SetupDiDestroyDeviceInfoList(pDev->Info); + pDev->Info = NULL; + return FALSE; + } + + if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, szServiceName, -1, TEXT("cmipci"), -1) == CSTR_EQUAL) { + return TRUE; + } + nIndex++; + } + + SetupDiDestroyDeviceInfoList(pDev->Info); + pDev->Info = NULL; + return FALSE; +} + +BOOL getDeviceInterfaceDetail(const GUID* category, CMIDEV* pDev) +{ + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + DWORD dataSize = 0; + BOOL result; + PTSTR pnpStr = NULL; + HDEVINFO hDevInfoWithInterface; + SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; + ULONG ulDeviceInterfaceDetailDataSize = 0; + + // get the PnP string + SetupDiGetDeviceInstanceId(pDev->Info, &(pDev->InfoData), NULL, 0, &dataSize); + if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (!dataSize)) { + PrintLastError("SetupDiGetDeviceInstanceId()"); + return FALSE; + } + pnpStr = (PTSTR)LocalAlloc(LPTR, dataSize * sizeof(TCHAR)); + if (!pnpStr) { + PrintLastError("LocalAlloc()"); + return FALSE; + } + result = SetupDiGetDeviceInstanceId(pDev->Info, &(pDev->InfoData), pnpStr, dataSize, NULL); + if (!result) { + PrintLastError("SetupDiGetDeviceInstanceId()"); + LocalFree(pnpStr); + return FALSE; + } + hDevInfoWithInterface = SetupDiGetClassDevs(&KSCATEGORY_TOPOLOGY, pnpStr, NULL, DIGCF_DEVICEINTERFACE); + LocalFree(pnpStr); + if (hDevInfoWithInterface == INVALID_HANDLE_VALUE) { + PrintLastError("SetupDiGetClassDevs()"); + return FALSE; + } + + // get the device interface data + DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); + result = SetupDiEnumDeviceInterfaces(hDevInfoWithInterface, NULL, &KSCATEGORY_TOPOLOGY, 0, &DeviceInterfaceData); + if (!result) { + PrintLastError("SetupDiEnumDeviceInterfaces()"); + SetupDiDestroyDeviceInfoList(hDevInfoWithInterface); + return FALSE; + } + + // get the device interface detail data + dataSize = 0; + SetupDiGetDeviceInterfaceDetail(hDevInfoWithInterface, &DeviceInterfaceData, NULL, 0, &dataSize, NULL); + if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (!dataSize)) { + PrintLastError("SetupDiGetDeviceInterfaceDetail()"); + SetupDiDestroyDeviceInfoList(hDevInfoWithInterface); + return FALSE; + } + pDev->InterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, dataSize); + if (!pDev->InterfaceDetailData) { + PrintLastError("LocalAlloc()"); + SetupDiDestroyDeviceInfoList(hDevInfoWithInterface); + return FALSE; + } + pDev->InterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + result = SetupDiGetDeviceInterfaceDetail(hDevInfoWithInterface, &DeviceInterfaceData, pDev->InterfaceDetailData, dataSize, NULL, NULL); + SetupDiDestroyDeviceInfoList(hDevInfoWithInterface); + if (!result) { + PrintLastError("SetupDiGetDeviceInterfaceDetail()"); + LocalFree(pDev->InterfaceDetailData); + pDev->InterfaceDetailData = NULL; + return FALSE; + } + + return TRUE; + +} + +BOOL getDriverData(CMIDEV* pDev) +{ + BOOL result; + HANDLE hDevice; + KSPROPERTY KSProp; + DWORD dataSize; + + hDevice = CreateFile(pDev->InterfaceDetailData->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) { + PrintLastError("CreateFile()"); + return FALSE; + } + KSProp.Set = KSPROPSETID_CMI; + KSProp.Flags = KSPROPERTY_TYPE_GET; + KSProp.Id = KSPROPERTY_CMI_GET; + result = DeviceIoControl(hDevice, IOCTL_KS_PROPERTY, &KSProp, sizeof(KSProp), &cmiData, sizeof(cmiData), &dataSize, NULL); + CloseHandle(hDevice); + + if (!result) { + PrintLastError("DeviceIoControl()"); + return FALSE; + } + + return TRUE; +} + +BOOL setDriverData(CMIDEV* pDev) +{ + BOOL result; + HANDLE hDevice; + KSPROPERTY KSProp; + DWORD dataSize; + + hDevice = CreateFile(pDev->InterfaceDetailData->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) { + PrintLastError("CreateFile()"); + return FALSE; + } + KSProp.Set = KSPROPSETID_CMI; + KSProp.Flags = KSPROPERTY_TYPE_SET; + KSProp.Id = KSPROPERTY_CMI_SET; + result = DeviceIoControl(hDevice, IOCTL_KS_PROPERTY, &KSProp, sizeof(KSProp), &cmiData, sizeof(cmiData), &dataSize, NULL); + CloseHandle(hDevice); + + if (!result) { + PrintLastError("DeviceIoControl()"); + return FALSE; + } + + return TRUE; +} + +void cleanUp() +{ + stopTestTone(); + if (cmiTopologyDev.Info) { + SetupDiDestroyDeviceInfoList(cmiTopologyDev.Info); + cmiTopologyDev.Info = NULL; + } + if (cmiTopologyDev.InterfaceDetailData) { + LocalFree(cmiTopologyDev.InterfaceDetailData); + cmiTopologyDev.InterfaceDetailData = NULL; + } + if (hURLFont) { + DeleteObject(hURLFont); //hm? + hURLFont = NULL; + } +} + +BOOL openDevice() +{ + if (!getDeviceInfo(&KSCATEGORY_TOPOLOGY, &cmiTopologyDev)) { + PrintLastError("getDeviceInfo()"); + return FALSE; + } + + if (!getDeviceInterfaceDetail(&KSCATEGORY_TOPOLOGY, &cmiTopologyDev)) { + PrintLastError("getDeviceInterfaceDetail()"); + return FALSE; + } + + return TRUE; +} + +void updateChannelBoxes(HWND hWnd) +{ + switch (SendMessage(GetDlgItem(hWndChild[0], IDCB_CHANNELCONFIG), CB_GETCURSEL, 0, 0)) { + case 0: // stereo + ShowWindow(GetDlgItem(hWndChild[0], IDC_BLEFT), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_BRIGHT), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CENTER), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_SUB), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CLEFT), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CRIGHT), SW_HIDE); + SetDlgItemText(hWnd, IDT_SWAPJACKS, ""); + break; + case 1: // quad + ShowWindow(GetDlgItem(hWndChild[0], IDC_BLEFT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_BRIGHT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CENTER), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_SUB), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CLEFT), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CRIGHT), SW_HIDE); + SetDlgItemText(hWnd, IDT_SWAPJACKS, ""); + break; + case 2: // 5.1 + ShowWindow(GetDlgItem(hWndChild[0], IDC_BLEFT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_BRIGHT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CENTER), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_SUB), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CLEFT), SW_HIDE); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CRIGHT), SW_HIDE); + SetDlgItemText(hWnd, IDT_SWAPJACKS, "BL/BR and C/LFE jacks are swapped!"); + break; + case 3: // 7.1 + ShowWindow(GetDlgItem(hWndChild[0], IDC_BLEFT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_BRIGHT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CENTER), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_SUB), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CLEFT), SW_SHOW); + ShowWindow(GetDlgItem(hWndChild[0], IDC_CRIGHT), SW_SHOW); + SetDlgItemText(hWnd, IDT_SWAPJACKS, "BL/BR and C/LFE jacks are swapped!"); + break; + } +} + + +BOOL setDlgItems(HWND hWnd) +{ + HWND hWndItem; + char buffer[127]; + + if (!getDriverData(&cmiTopologyDev)) { + PrintLastError("getDriverData()"); + return FALSE; + } + + // 'About' tab + SetWindowText(GetDlgItem(hWndChild[NUM_TABS-1], IDC_VERSION), cmiData.driverVersion); + wsprintf(buffer, "%d", cmiData.hardwareRevision); + SetWindowText(GetDlgItem(hWndChild[NUM_TABS-1], IDC_HWREV), buffer); + wsprintf(buffer, "%d", cmiData.maxChannels); + SetWindowText(GetDlgItem(hWndChild[NUM_TABS-1], IDC_MAXCHAN), buffer); + wsprintf(buffer, "%04X", cmiData.IOBase); + SetWindowText(GetDlgItem(hWndChild[NUM_TABS-1], IDC_BASEADR), buffer); + wsprintf(buffer, "%04X", cmiData.MPUBase); + SetWindowText(GetDlgItem(hWndChild[NUM_TABS-1], IDC_MPUADR), buffer); + + // channel config combobox + hWndItem = GetDlgItem(hWndChild[0], IDCB_CHANNELCONFIG); + SendMessage(hWndItem, CB_RESETCONTENT, 0, 0); + if (cmiData.maxChannels >= 2) { + SendMessage(hWndItem, CB_ADDSTRING, 0, (LPARAM)"Stereo (2.0)"); + } + if (cmiData.maxChannels >= 4) { + SendMessage(hWndItem, CB_ADDSTRING, 0, (LPARAM)"Quadrophonic (4.0)"); + } + if (cmiData.maxChannels >= 6) { + SendMessage(hWndItem, CB_ADDSTRING, 0, (LPARAM)"5.1 Surround"); + } + if (cmiData.maxChannels >= 8) { + SendMessage(hWndItem, CB_ADDSTRING, 0, (LPARAM)"7.1 Surround"); + } + getCurrentChannelConfig(); + SendMessage(hWndItem, CB_SETCURSEL, (currentChannelCount/2)-1, 0); + updateChannelBoxes(hWnd); + + // checkboxes + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_PCMDAC), BM_SETCHECK, (cmiData.enablePCMDAC ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_EXCH_FB), BM_SETCHECK, (cmiData.exchangeFrontBack ? BST_CHECKED : BST_UNCHECKED), 0); + + SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO), BM_SETCHECK, (cmiData.enableSPDO ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO5V), BM_SETCHECK, (cmiData.enableSPDO5V ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDCOPYRHT), BM_SETCHECK, (cmiData.enableSPDOCopyright ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDI), BM_SETCHECK, (cmiData.enableSPDI ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_SEL_SPDIFI), BM_SETCHECK, (cmiData.select2ndSPDI ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_INV_SPDIFI), BM_SETCHECK, (cmiData.invertPhaseSPDI ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_POLVALID), BM_SETCHECK, (cmiData.invertValidBitSPDI ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[1], IDC_LOOP_SPDF), BM_SETCHECK, (cmiData.loopSPDI ? BST_CHECKED : BST_UNCHECKED), 0); + + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_PCM), BM_SETCHECK, ((cmiData.formatMask & FMT_441_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_PCM), BM_SETCHECK, ((cmiData.formatMask & FMT_480_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_PCM), BM_SETCHECK, ((cmiData.formatMask & FMT_882_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_PCM), BM_SETCHECK, ((cmiData.formatMask & FMT_960_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_MULTI_PCM),BM_SETCHECK, ((cmiData.formatMask & FMT_441_MULTI_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_MULTI_PCM),BM_SETCHECK, ((cmiData.formatMask & FMT_480_MULTI_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_MULTI_PCM),BM_SETCHECK, ((cmiData.formatMask & FMT_882_MULTI_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_MULTI_PCM),BM_SETCHECK, ((cmiData.formatMask & FMT_960_MULTI_PCM) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_DOLBY), BM_SETCHECK, ((cmiData.formatMask & FMT_441_DOLBY) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_DOLBY), BM_SETCHECK, ((cmiData.formatMask & FMT_480_DOLBY) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_DOLBY), BM_SETCHECK, ((cmiData.formatMask & FMT_882_DOLBY) ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_DOLBY), BM_SETCHECK, ((cmiData.formatMask & FMT_960_DOLBY) ? BST_CHECKED : BST_UNCHECKED), 0); + + // radioboxes + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_BASS2LINE), BM_SETCHECK, (cmiData.enableBass2Line ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2LINE), BM_SETCHECK, (cmiData.enableCenter2Line ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_REAR2LINE), BM_SETCHECK, (cmiData.enableRear2Line ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_NOROUTE_LINE), BM_SETCHECK, ((!cmiData.enableCenter2Line && !cmiData.enableBass2Line && !cmiData.enableRear2Line) ? BST_CHECKED : BST_UNCHECKED), 0); + + SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2MIC), BM_SETCHECK, (cmiData.enableCenter2Mic ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(GetDlgItem(hWndChild[0], IDC_NOROUTE_MIC), BM_SETCHECK, (!cmiData.enableCenter2Mic ? BST_CHECKED : BST_UNCHECKED), 0); + + + return TRUE; +} + +BOOL applySettings() +{ + cmiData.enablePCMDAC = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_PCMDAC), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.exchangeFrontBack = (SendMessage(GetDlgItem(hWndChild[0], IDC_EXCH_FB), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableBass2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_BASS2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableCenter2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableRear2Line = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_REAR2LINE), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableCenter2Mic = (SendMessage(GetDlgItem(hWndChild[0], IDC_EN_CENTER2MIC), BM_GETCHECK, 0, 0) == BST_CHECKED); + + cmiData.enableSPDO = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableSPDO5V = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDO5V), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableSPDOCopyright = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDCOPYRHT), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.enableSPDI = (SendMessage(GetDlgItem(hWndChild[1], IDC_EN_SPDI), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.select2ndSPDI = (SendMessage(GetDlgItem(hWndChild[1], IDC_SEL_SPDIFI), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.invertPhaseSPDI = (SendMessage(GetDlgItem(hWndChild[1], IDC_INV_SPDIFI), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.invertValidBitSPDI = (SendMessage(GetDlgItem(hWndChild[1], IDC_POLVALID), BM_GETCHECK, 0, 0) == BST_CHECKED); + cmiData.loopSPDI = (SendMessage(GetDlgItem(hWndChild[1], IDC_LOOP_SPDF), BM_GETCHECK, 0, 0) == BST_CHECKED); + + cmiData.formatMask = 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_441_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_480_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_882_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_960_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_MULTI_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_441_MULTI_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_MULTI_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_480_MULTI_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_MULTI_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_882_MULTI_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_MULTI_PCM), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_960_MULTI_PCM : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_441_DOLBY), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_441_DOLBY : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_480_DOLBY), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_480_DOLBY : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_882_DOLBY), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_882_DOLBY : 0; + cmiData.formatMask |= (SendMessage(GetDlgItem(hWndChild[2], IDC_FMT_960_DOLBY), BM_GETCHECK, 0, 0) == BST_CHECKED) ? FMT_960_DOLBY : 0; + + currentChannelCount = (int)(SendMessage(GetDlgItem(hWndChild[0], IDCB_CHANNELCONFIG), CB_GETCURSEL, 0, 0)+1)*2; + + return (setDriverData(&cmiTopologyDev) && setCurrentChannelConfig()); +} + +BOOL initDialog(HWND hWnd) +{ + HICON hIcon; + TC_ITEM tci; + int i; + + hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICON)); + SendMessage(hWnd, WM_SETICON, (LPARAM) ICON_BIG, (WPARAM) hIcon); + hURLFont = 0; + + hWndTab = GetDlgItem(hWnd,IDC_TAB); + + ZeroMemory(&tci, sizeof(TC_ITEM)); + tci.mask = TCIF_TEXT; + for (i=0;icode != TCN_SELCHANGE) { + return FALSE; + } + ShowWindow(hWndChild[currentTab], SW_HIDE); + currentTab = SendMessage(hWndTab, TCM_GETCURSEL, 0, 0); + ShowWindow(hWndChild[currentTab], SW_SHOWDEFAULT); + return TRUE; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + if (!initDialog(hWnd)) { + PostQuitMessage(0); + } + return TRUE; + case WM_CLOSE: + DestroyWindow(hWnd); + return TRUE; + case WM_NOTIFY: + return changeTab((LPNMHDR)lParam); + case WM_DESTROY: + cleanUp(); + PostQuitMessage(0); + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDB_CLOSE) { + PostQuitMessage(0); + return TRUE; + } + if (LOWORD(wParam) == IDB_APPLY) { + applySettings(); + setDlgItems(hWnd); + return TRUE; + } + break; + } + return 0; +} + +void openURL(int control) +{ + char buffer[127]; + GetWindowText(GetDlgItem(hWndChild[3], control), buffer, sizeof(buffer)); + ShellExecute(hWndMain, "open", buffer, NULL, NULL, SW_SHOWNORMAL); +} + +LRESULT CALLBACK TabDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDB_STARTSTOP: + if (stopTestTone()) { + SetDlgItemText(hWndChild[0], IDB_STARTSTOP, "&Start"); + return TRUE; + } + if (playTestTone()) { + SetDlgItemText(hWndChild[0], IDB_STARTSTOP, "&Stop"); + return TRUE; + } + break; + case IDC_URL1: + case IDC_URL2: + openURL(LOWORD(wParam)); + break; + } + case WM_CTLCOLORSTATIC: + if ( (GetDlgItem(hWndChild[3], IDC_URL1) == (HANDLE)lParam) || (GetDlgItem(hWndChild[3], IDC_URL2) == (HANDLE)lParam) ) { + SetTextColor((HDC)wParam, 0xFF0000); + SetBkMode((HDC)wParam, TRANSPARENT); + return (LRESULT)GetSysColorBrush(COLOR_BTNFACE); + } + } + + return 0; +} + +void printUsage() +{ + unsigned char usage[] = "/h - print this help message\r\n" \ + "/enable71Mode - change channel configuration to 7.1\r\n" \ + "/enable51Mode - change channel configuration to 5.1\r\n" \ + "/enable40Mode - change channel configuration to 4.0 (Quad)\r\n" \ + "/enable20Mode - change channel configuration to 2.0 (Stereo)\r\n" \ + "/enableSPDIFo - enable SPDIF-out\r\n" \ + "/disableSPDIFo - disable SPDIF-out\r\n"\ + "/enableSPDIFi - enable SPDIF-in recording\r\n" \ + "/disableSPDIFi - disable SPDIF-in recording\r\n"; + + MessageBox(NULL, (LPCSTR)usage, TEXT("Usage Help"), MB_ICONINFORMATION | MB_OK); + return; +} + +void deleteDriverFiles() { + TCHAR SysDir[MAX_PATH]; + unsigned int len; + if (GetSystemDirectory(SysDir, sizeof(SysDir))==0) { + PrintLastError("GetSystemDirectory()"); + return; + } + len = strlen(SysDir); + + strcat(SysDir, "\\cmicpl.cpl"); + if (!DeleteFile(SysDir)) { + MoveFileEx(SysDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); + } + SysDir[len] = 0; + + strcat(SysDir, "\\cmicontrol.exe"); + if (!DeleteFile(SysDir)) { + MoveFileEx(SysDir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); + } +} + + +void performUninstall() { + deleteDriverFiles(); + RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CMIDriver"); + MessageBox(NULL, "The CMI driver applications were successfully removed from your computer!", "CMIDriver", MB_ICONINFORMATION); + ExitProcess(0); +} + +bool checkToken(char* token) { + if ((strcmp(token, "?")==0) || (strcmp(token, "H")==0)) { + printUsage(); + return TRUE; + } else + if (strcmp(token, "ENABLE71MODE")==0) { + currentChannelCount = 8; + } else + if (strcmp(token, "ENABLE51MODE")==0) { + currentChannelCount = 6; + } else + if ((strcmp(token, "ENABLE40MODE")==0) || (strcmp(token, "ENABLEQUADMODE")==0) || (strcmp(token, "QUAD")==0) ) { + currentChannelCount = 4; + } else + if ((strcmp(token, "ENABLE20MODE")==0) || (strcmp(token, "ENABLESTEREOMODE")==0) || (strcmp(token, "STEREO")==0) ) { + currentChannelCount = 2; + } else + if (strcmp(token, "ENABLESPDIFO")==0) { + cmiData.enableSPDO = TRUE; + } else + if (strcmp(token, "DISABLESPDIFO")==0) { + cmiData.enableSPDO = FALSE; + } else + if (strcmp(token, "ENABLESPDIFI")==0) { + cmiData.enableSPDI = TRUE; + } else + if (strcmp(token, "DISABLESPDIFI")==0) { + cmiData.enableSPDI = FALSE; + } else + if (strcmp(token, "UNINSTALL")==0) { + performUninstall(); + } + return FALSE; +} + +int parseArguments(LPSTR szCmdLine) { + BOOL inToken = false; + int i = 0, j; + char token[MAX_TOKEN_SIZE]; + + if (!openDevice()) { + return FALSE; + } + + if (!getDriverData(&cmiTopologyDev)) { + PrintLastError("getDriverData()"); + return FALSE; + } + if (!getCurrentChannelConfig()) { + PrintLastError("getCurrentChannelConfig()"); + return FALSE; + } + + while (szCmdLine[i]) { + if (inToken) { + if (szCmdLine[i] == ' ') { + inToken = false; + token[j] = 0; + if (checkToken(token)) { + return TRUE; + } + } else { + token[j] = (char)toupper(szCmdLine[i]); + if (j < MAX_TOKEN_SIZE-1) { + j++; + } + } + } else { + if ((szCmdLine[i] == '-') || (szCmdLine[i] == '/')) { + j = 0; + inToken = true; + } + } + + i++; + } + token[j] = 0; + checkToken(token); + return (setDriverData(&cmiTopologyDev) && setCurrentChannelConfig()); +} + +void InitURLControl() +{ + WNDCLASSEX wce; + + ZeroMemory(&wce, sizeof(wce)); + wce.cbSize = sizeof(WNDCLASSEX); + if (GetClassInfoEx(hInst, "Static", &wce)==0) { + PrintLastError("GetClassInfoEx()"); + return; + } + + wce.hCursor = LoadCursor(NULL, IDC_HAND); + wce.hInstance = hInst; + wce.lpszClassName = "URLLink"; + if (RegisterClassEx(&wce) == 0) { + PrintLastError("RegisterClassEx()"); + } + +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) +{ + WNDCLASSEX wce; + MSG msg; + + ZeroMemory(&cmiData, sizeof(CMIDATA)); + ZeroMemory(&cmiTopologyDev, sizeof(CMIDEV)); + hWave = NULL; + + if (szCmdLine) { + if (strlen(szCmdLine) > 0) { + int result = parseArguments(szCmdLine); + cleanUp(); + return result; + } + } + + if (hWndMain = FindWindow("cmiControlPanel", NULL)) { + SetForegroundWindow(hWndMain); + return FALSE; + } + + hInst = hInstance; + InitCommonControls(); + CoInitialize(NULL); + + ZeroMemory(&wce, sizeof(WNDCLASSEX)); + wce.cbSize = sizeof(WNDCLASSEX); + wce.lpfnWndProc = DefDlgProc; + wce.style = 0; + wce.cbWndExtra = DLGWINDOWEXTRA; + wce.hInstance = hInstance; + wce.hCursor = LoadCursor(NULL, IDC_ARROW); + wce.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); + wce.lpszClassName = "cmiControlPanel"; + wce.lpszMenuName = NULL; + wce.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + wce.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + if(!RegisterClassEx(&wce)) { + PrintLastError("RegisterClassEx()"); + return -1; + } + InitURLControl(); + + hWndMain = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)WndProc, NULL); + if (!hWndMain) { + PrintLastError("CreateDialogParam()"); + return -1; + } + + while (GetMessage(&msg, (HWND) NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return 0; +} diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h new file mode 100644 index 00000000000..4230e55ad52 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/main.h @@ -0,0 +1,83 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define INITGUID +#define DIRECTSOUND_VERSION 0x800 +#include + +#include "resource.h" +#include "property.h" + +#define SAMPLE_RATE 44100 + +#define BASS_FREQUENCY 90 +#define BASS_AMPLITUDE 0.5 + +#define SPEAKER_FREQUENCY 440 +#define SPEAKER_AMPLITUDE 0.5 + +#define MAX_TOKEN_SIZE 128 + +typedef struct _CMIDEV { + HDEVINFO Info; + SP_DEVINFO_DATA InfoData; + PSP_DEVICE_INTERFACE_DETAIL_DATA InterfaceDetailData; + +} CMIDEV; + +static LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK TabDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +HINSTANCE hInst; +HWND hWndMain; +HWND hWndTab; +HWND hWndChild[NUM_TABS]; +LRESULT currentTab; +CMIDEV cmiTopologyDev; +CMIDATA cmiData; +HWAVEOUT hWave; +WAVEHDR pwh; +int currentChannelCount; +HFONT hURLFont; + +#endif //_MAIN_H_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile new file mode 100644 index 00000000000..5acbbd24c0e --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/makefile @@ -0,0 +1 @@ +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h new file mode 100644 index 00000000000..90aa21ea9fc --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/resource.h @@ -0,0 +1,96 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define IDC_STATIC -1 + +// icons +#define IDI_APP_ICON 150 + +// main dialog +#define IDD_MAIN 100 +#define IDB_CLOSE 101 +#define IDB_APPLY 102 +#define IDC_TAB 103 +#define IDT_SWAPJACKS 104 + +#define IDD_TAB1 200 +#define IDC_EN_PCMDAC 201 +#define IDC_EXCH_FB 202 +#define IDC_EN_REAR2LINE 203 +#define IDC_EN_BASS2LINE 204 +#define IDC_EN_CENTER2LINE 205 +#define IDC_NOROUTE_LINE 206 +#define IDC_EN_CENTER2MIC 207 +#define IDC_NOROUTE_MIC 208 +#define IDCB_CHANNELCONFIG 210 +#define IDC_LEFT 211 +#define IDC_CLEFT 212 +#define IDC_CENTER 213 +#define IDC_CRIGHT 214 +#define IDC_RIGHT 215 +#define IDC_BLEFT 216 +#define IDC_BRIGHT 217 +#define IDC_SUB 218 +#define IDB_STARTSTOP 219 + +#define IDD_TAB2 300 +#define IDC_EN_SPDO 301 +#define IDC_EN_SPDO5V 302 +#define IDC_EN_SPDCOPYRHT 303 +#define IDC_EN_DAC2SPDO 304 +#define IDC_SEL_SPDIFI 310 +#define IDC_INV_SPDIFI 311 +#define IDC_POLVALID 312 +#define IDC_LOOP_SPDF 313 +#define IDC_EN_SPDI 314 + +#define IDD_TAB3 400 +#define IDC_FMT_441_PCM 401 +#define IDC_FMT_480_PCM 402 +#define IDC_FMT_882_PCM 403 +#define IDC_FMT_960_PCM 404 +#define IDC_FMT_441_MULTI_PCM 405 +#define IDC_FMT_480_MULTI_PCM 406 +#define IDC_FMT_882_MULTI_PCM 407 +#define IDC_FMT_960_MULTI_PCM 408 +#define IDC_FMT_441_DOLBY 409 +#define IDC_FMT_480_DOLBY 410 +#define IDC_FMT_882_DOLBY 411 +#define IDC_FMT_960_DOLBY 412 + +#define IDD_TAB4 500 +#define IDC_VERSION 501 +#define IDC_HWREV 502 +#define IDC_MAXCHAN 503 +#define IDC_BASEADR 504 +#define IDC_MPUADR 505 +#define IDC_URL1 506 +#define IDC_URL2 507 + +char* tabsName[] = { "Analog", "Digital", "Formats", "About" }; +int tabsResource[] = { IDD_TAB1, IDD_TAB2, IDD_TAB3, IDD_TAB4 }; +#define NUM_TABS 4 diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources new file mode 100644 index 00000000000..3f1cf7a6dae --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/sources @@ -0,0 +1,31 @@ +TARGETNAME=CMICONTROL +TARGETTYPE=PROGRAM +TARGETPATH= + +USE_MSVCRT=1 + +INCLUDES=.. + +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib \ + $(SDK_LIB_PATH)\comctl32.lib \ + $(SDK_LIB_PATH)\shell32.lib \ + $(SDK_LIB_PATH)\setupapi.lib \ + $(SDK_LIB_PATH)\winmm.lib \ + $(SDK_LIB_PATH)\dsound.lib \ + $(SDK_LIB_PATH)\ole32.lib + +MSC_WARNING_LEVEL=/W3 /WX + +SOURCES= main.cpp \ + window.rc + +UMTYPE=windows +UMENTRY=winmain + +C_DEFINES=/DW32 /DWIN32 + +TARGET_DESTINATION=idw +_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WIN2K) + +MUI=0 \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.aps b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.aps new file mode 100644 index 00000000000..e596df04b52 Binary files /dev/null and b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.aps differ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico new file mode 100644 index 00000000000..71482b08a70 Binary files /dev/null and b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico differ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico-license.txt b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico-license.txt new file mode 100644 index 00000000000..4d8a3745090 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.ico-license.txt @@ -0,0 +1 @@ +This icon originates from Freedesktop Tango icon set (http://tango.freedesktop.org) and is licensed under the Creative Commons Attribution Share-Alike license (http://creativecommons.org/licenses/by-sa/2.5/). \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc new file mode 100644 index 00000000000..40bcb6a44ec --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmicontrol/window.rc @@ -0,0 +1,155 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "resource.h" + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Audio Control Panel (CMI 8738/8768)" +#define VER_INTERNALNAME_STR "cmicontrol.exe" +#define VER_ORIGINALFILENAME_STR "cmicontrol.exe" +#ifdef VER_COMPANYNAME_STR +#undef VER_COMPANYNAME_STR +#endif +#define VER_COMPANYNAME_STR "Dogbert" +#ifdef VER_PRODUCTNAME_STR +#undef VER_PRODUCTNAME_STR +#endif +#define VER_PRODUCTNAME_STR "" +#define VER_LEGALCOPYRIGHT_YEARS "" +#define VER_LEGALCOPYRIGHT_STR "BSD-style license" + +#include "common.ver" + +IDI_APP_ICON ICON DISCARDABLE "window.ico" + +IDD_MAIN DIALOG DISCARDABLE 0, 0, 310, 176 +STYLE DS_ABSALIGN | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Audio Control Panel (CMI 8738/8768)" +FONT 8, "MS Shell Dlg" +CLASS "cmiControlPanel" +BEGIN + PUSHBUTTON "&Close",IDB_CLOSE,250,158,50,14 + DEFPUSHBUTTON "&Apply",IDB_APPLY,190,158,50,14 + CONTROL "",IDC_TAB,"SysTabControl32",0x0,7,7,296,146 + LTEXT " ", IDT_SWAPJACKS, 10,162,180,8 +END + +IDD_TAB1 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + AUTOCHECKBOX "Enable PCM DAC", IDC_EN_PCMDAC, 4,4,104,10 + AUTOCHECKBOX "Exchange Front/Rear Jacks", IDC_EXCH_FB, 4,16,104,10 + GROUPBOX "Line-In Jack", IDC_STATIC, 4,30,110,54 + AUTORADIOBUTTON "Route Rear to Line-In", IDC_EN_REAR2LINE, 8,40,104,10,WS_GROUP + AUTORADIOBUTTON "Route Bass to Line-In", IDC_EN_BASS2LINE, 8,50,104,10 + AUTORADIOBUTTON "Route Center to Line-In", IDC_EN_CENTER2LINE,8,60,104,10 + AUTORADIOBUTTON "Don't route", IDC_NOROUTE_LINE, 8,70,104,10 + GROUPBOX "Mic-In Jack", IDC_STATIC, 4,86,110,34 + AUTORADIOBUTTON "Route Center to Mic-In", IDC_EN_CENTER2MIC, 8,96,104,10,WS_GROUP + AUTORADIOBUTTON "Don't route", IDC_NOROUTE_MIC, 8,106,104,10 + GROUPBOX "Channel Configuration", IDC_STATIC, 120,4,160,116 + COMBOBOX IDCB_CHANNELCONFIG,124,14,150,50, CBS_DROPDOWNLIST | WS_TABSTOP + AUTOCHECKBOX "L" IDC_LEFT, 130,30,20,20 + AUTOCHECKBOX "CL" IDC_CLEFT, 160,30,20,20 + AUTOCHECKBOX "C" IDC_CENTER, 190,30,20,20 + AUTOCHECKBOX "CR" IDC_CRIGHT, 220,30,20,20 + AUTOCHECKBOX "R" IDC_RIGHT, 250,30,20,20 + AUTOCHECKBOX "BL" IDC_BLEFT, 130,96,20,20 + AUTOCHECKBOX "BR" IDC_BRIGHT, 250,96,20,20 + AUTOCHECKBOX "Sub" IDC_SUB, 240,60,30,20 + DEFPUSHBUTTON "&Start" IDB_STARTSTOP, 175,98,50,14 +END + +IDD_TAB2 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "S/PDIF output" IDC_STATIC, 4,4,132,116 + AUTOCHECKBOX "Enable S/PDIF-out", IDC_EN_SPDO, 8,14,110,10 + AUTOCHECKBOX "Enable 5V signal levels", IDC_EN_SPDO5V, 8,28,110,10 + AUTOCHECKBOX "Enable copyright bit", IDC_EN_SPDCOPYRHT, 8,42,110,10 + GROUPBOX "S/PDIF input", IDC_STATIC, 146,4,134,116 + AUTOCHECKBOX "Enable S/PDIF-in recording", IDC_EN_SPDI, 150,14,110,10 + LTEXT "(and disable all analog inputs)", -1 , 162,26,110,10 + AUTOCHECKBOX "Select secondary S/PDIF-in", IDC_SEL_SPDIFI, 150,42,110,10 + AUTOCHECKBOX "Invert phase", IDC_INV_SPDIFI, 150,56,110,10 + AUTOCHECKBOX "Invert validity flag", IDC_POLVALID, 150,70,110,10 + AUTOCHECKBOX "Loop S/PDIF-in to S/PDIF-out",IDC_LOOP_SPDF, 150,84,110,10 +END + +IDD_TAB3 DIALOG DISCARDABLE 4, 15, 290, 122 +STYLE WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "44.1 kHz", IDC_STATIC, 74,8,40,8 + LTEXT "48 kHz", IDC_STATIC, 114,8,40,8 + LTEXT "88.2 kHz", IDC_STATIC, 154,8,40,8 + LTEXT "96 kHz", IDC_STATIC, 194,8,40,8 + LTEXT "PCM" , IDC_STATIC, 4,20,60,8 + LTEXT "Multi-Channel PCM", IDC_STATIC, 4,32,60,8 + LTEXT "Dolby (AC3)/DTS", IDC_STATIC, 4,44,60,8 + AUTOCHECKBOX "", IDC_FMT_441_PCM, 82,20,10,10 + AUTOCHECKBOX "", IDC_FMT_441_MULTI_PCM, 82,32,10,10 + AUTOCHECKBOX "", IDC_FMT_441_DOLBY, 82,44,10,10 + AUTOCHECKBOX "", IDC_FMT_480_PCM, 122,20,10,10 + AUTOCHECKBOX "", IDC_FMT_480_MULTI_PCM, 122,32,10,10 + AUTOCHECKBOX "", IDC_FMT_480_DOLBY, 122,44,10,10 + AUTOCHECKBOX "", IDC_FMT_882_PCM, 162,20,10,10 + AUTOCHECKBOX "", IDC_FMT_882_MULTI_PCM, 162,32,10,10 + AUTOCHECKBOX "", IDC_FMT_882_DOLBY, 162,44,10,10 + AUTOCHECKBOX "", IDC_FMT_960_PCM, 202,20,10,10 + AUTOCHECKBOX "", IDC_FMT_960_MULTI_PCM, 202,32,10,10 + AUTOCHECKBOX "", IDC_FMT_960_DOLBY, 202,44,10,10 +END + +IDD_TAB4 DIALOG DISCARDABLE 4, 15, 290, 124 +STYLE WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Driver Version:", IDC_STATIC, 4,5,100,10 + LTEXT "", IDC_VERSION,80,4,60,10, SS_SUNKEN + LTEXT "Hardware Revision:", IDC_STATIC, 4,21,100,8 + LTEXT "", IDC_HWREV, 80,20,60,10, SS_SUNKEN + LTEXT "Maximum Channels:", IDC_STATIC, 4,37,100,8 + LTEXT "", IDC_MAXCHAN,80,36,60,10, SS_SUNKEN + LTEXT "Base Address:", IDC_STATIC, 4,53,100,8 + LTEXT "", IDC_BASEADR,80,52,60,10, SS_SUNKEN + LTEXT "MPU401 Address:", IDC_STATIC, 4,69,100,8 + LTEXT "", IDC_MPUADR, 80,68,60,10, SS_SUNKEN + + LTEXT "Application Icon: Copyright (c) Tango Desktop Project,", IDC_STATIC,4,84,176,8 + CONTROL "http://tango.freedesktop.org/",IDC_URL1,"URLLink",SS_NOTIFY, 178,84,100,8 + + LTEXT "Copyright (c) 2006-2007 Dogbert ", IDC_STATIC,4,96,202,8 + CONTROL "http://cmediadrivers.googlepages.com/",IDC_URL2,"URLLink",SS_NOTIFY,54,110,182,22 +END diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc new file mode 100644 index 00000000000..f3f6d0be578 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmipci.rc @@ -0,0 +1,50 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include + +#ifdef VER_COMPANYNAME_STR +#undef VER_COMPANYNAME_STR +#endif + +#ifdef VER_PRODUCTNAME_STR +#undef VER_PRODUCTNAME_STR +#endif + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SOUND +#define VER_FILEDESCRIPTION_STR "Homebrew Audio Drivers for CMI8738/8768 based soundcards" +#define VER_INTERNALNAME_STR "cmipci.sys" +#define VER_ORIGINALFILENAME_STR "cmipci.sys" +#define VER_COMPANYNAME_STR "Dogbert" +#define VER_PRODUCTNAME_STR "" +#define VER_LEGALCOPYRIGHT_YEARS "" +#define VER_LEGALCOPYRIGHT_STR "BSD-style license" + +#include "common.ver" diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp new file mode 100644 index 00000000000..09c1e9e7fe3 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cmireg.hpp @@ -0,0 +1,173 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _CMIREG_HPP_ +#define _CMIREG_HPP_ + +// registers (from CMI8738_6ch_series_spec_v18f_registers.pdf) + +#define REG_FUNCTRL0 0x00 // Function Control Register 0 (32bit) +#define ADC_CH0 0x00000001 // enable ADC on channel 0 for recording +#define ADC_CH1 0x00000002 // enable ADC on channel 1 for recording +#define PAUSE_CH0 0x00000004 // pause channel 0 +#define PAUSE_CH1 0x00000008 // pause channel 1 +#define EN_CH0 0x00010000 // enable channel 0 +#define EN_CH1 0x00020000 // enable channel 1 +#define RST_CH0 0x00040000 // reset channel 0 +#define RST_CH1 0x00080000 // reset channel 1 + +#define REG_FUNCTRL1 0x04 // Function Control Register 1 (32bit) +#define EN_ZVPORT 0x00000001 // enable ZVPort +#define EN_GAMEPORT 0x00000002 // enable legacy gameport +#define EN_UART 0x00000004 // enable UART (MIDI interface) +#define BREQ 0x00000010 // enable bus master request +#define INTRM 0x00000020 // enable master control block interrupt +#define SPDO2DAC 0x00000040 // send S/PDIF out through DAC +#define LOOP_SPDF 0x00000080 // loop S/PDIF in to S/PDIF out +#define SPDF_0 0x00000100 // enable S/PDIF out at channel 0 +#define SPDF_1 0x00000200 // enable S/PDIF in/out at channel 1 +#define SFC_CH0_MASK 0x00001C00 // mask for the sample rate bits of channel 0 +#define SFC_44K_CH0 0x00000C00 // 44.1kHz channel 0 +#define SFC_48K_CH0 0x00001C00 // 48kHz channel 0 +#define SFC_CH1_MASK 0x0000E000 // mask for the sample rate bits of channel 1 +#define SFC_44K_CH1 0x00006000 // 44.1kHz channel 1 +#define SFC_48K_CH1 0x0000E000 // 48kHz channel 1 + +#define REG_CHFORMAT 0x08 // Channel Format Register (32bit) +#define FORMAT_CH0 0x00000003 // enable 16bit stereo format for channel 0 +#define FORMAT_CH1 0x0000000C // enable 16bit stereo format for channel 1 +#define SPDLOCKED 0x00000010 // +#define POLVALID 0x00000020 // invert S/PDIF in valid bit +#define DBLSPDS 0x00000040 // double S/PDIF sampling rate (44.1 => 88.2, 48 => 96) +#define INV_SPDIFI2 0x00000080 // invert S/PDIF in signal (whatever that means, version >37) +#define SPD88_CH0 0x00000100 // double sample rate from 44.1 to 88.2 kHz on channel 0 +#define SPD88_CH1 0x00000200 // double sample rate from 44.1 to 88.2 kHz on channel 1 +#define SPD96_CH0 0x00000400 // double sample rate from 48 to 96 kHz on channel 0 +#define SPD96_CH1 0x00000800 // double sample rate from 48 to 96 kHz on channel 1 +#define SEL_SPDIFI1 0x00080000 // select secondary S/PDIF in (only for versions <=37) +#define EN_SPDO_AC3_3 0x00020000 // undocumented: enable AC3 mode on S/PDIF out (requires hardware support) +#define EN_SPDO_AC3_1 0x00100000 // undocumented: enable AC3 mode on S/PDIF out +#define SPD24SEL 0x00200000 // enable 24bit S/PDIF out +#define VERSION_37 0x01000000 // undocumented: hardware revision 37 +#define EN_4CH_CH1 0x20000000 // enable 4 channel mode on channel 1 +#define EN_5CH_CH1 0x80000000 // enable 5 channel mode on channel 1 + +#define REG_INTHLDCLR 0x0C // Interrupt Hold/Clear Register (32bit) +#define VERSION_MASK 0xFF000000 // mask for the version number, bits [31:24], highest byte +#define VERSION_68 0x20000000 // undocumented: hardware revision 68 (8768) +#define VERSION_55 0x08000000 // undocumented: hardware revision 55 +#define VERSION_39 0x04000000 // undocumented: hardware revision 39 +#define VERSION_39_6 0x01000000 // undocumented: 6 channel version of revision 39 +#define INT_CLEAR 0x00000001 // clear interrupt +#define INT_HOLD 0x00000002 // hold interrupt +#define EN_CH0_INT 0x00010000 // enable interrupt on channel 0 +#define EN_CH1_INT 0x00020000 // enable interrupt on channel 1 + +#define REG_INT_STAT 0x10 // Interrupt Register (32bit) +#define INT_CH0 0x00000001 // interrupt on channel 0 +#define INT_CH1 0x00000002 // interrupt on channel 1 +#define BUSY_CH0 0x00000004 // channel 0 busy +#define BUSY_CH1 0x00000008 // channel 1 busy +#define INT_UART 0x00010000 // interrupt on UART interface +#define INT_PENDING 0x80000000 // interrupt pending + +#define REG_LEGACY 0x14 // Legacy Control Register (32bit) +#define CENTER2LINE 0x00002000 // route center channel to line-in jack +#define BASS2LINE 0x00004000 // route bass channel to line-in jack +#define EN_6CH_CH1 0x00008000 // enable 6 channel mode on channel 1 +#define DAC2SPDO 0x00200000 // enable PCM+FM to S/PDIF out +#define EN_SPDCOPYRHT 0x00400000 // enable S/PDIF out copyright bit +#define EN_SPDIF_OUT 0x00800000 // enable S/PDIF out +#define UART_330 0x00000000 // i/o addresses for UART +#define UART_320 0x20000000 +#define UART_310 0x40000000 +#define UART_300 0x60000000 +#define DWORD_MAPPING 0x80000000 // enable DWORD-based position in base register + +#define REG_MISCCTRL 0x18 // Miscellaneous Control Register (32bit) +#define EN_CENTER 0x00000080 // enable center channel +#define SEL_SPDIFI2 0x00000100 // select secondary S/PDIF in +#define EN_SPDIF_48_1 0x00008000 // enable 48kHz sampling rate on S/PDIF out +#define EN_SPDO_AC3_2 0x00040000 // enable AC3 mode on S/PDIF out +#define LOOP_SPDF_I 0x00100000 // loop internal S/PDIF out to internal S/PDIF in +#define SPD32SEL 0x00200000 // enable 32bit S/PDIF out +#define XCHG_DAC 0x00400000 // exchange DACs +#define EN_DBLDAC 0x00800000 // enable double DAC mode +#define EN_SPDIF_48_2 0x01000000 // enable 48kHz sampling rate on S/PDIF out +#define EN_SPDO5V 0x02000000 // enable 5V levels on S/PDIF out +#define RST_CHIP 0x40000000 // reset bus master / DSP engine +#define PWD_CHIP 0x80000000 // enable power down mode (standby mode etc.) +#define EN_SPDIF_48 (EN_SPDIF_48_1 | EN_SPDIF_48_2) + +#define REG_SBDATA 0x22 // SoundBlaster compatible mixer data register (8bit) +#define REG_SBINDEX 0x23 // SoundBlaster compatible mixer index register (8bit) + +#define REG_MIXER1 0x24 // Mixer Register 1 (8bit) +#define EN_SPDI2DAC 0x01 // enable S/PDIF in conversion +#define EN_3DSOUND 0x02 // enable 3D sound +#define EN_WAVEIN_L 0x04 // enable left wave in recording channel +#define EN_WAVEIN_R 0x08 // enable right wave in recording channel +#define REAR2FRONT 0x10 // exchange rear/front jacks +#define REAR2LINE 0x20 // enable rear out on line-in jack +#define MUTE_WAVE 0x40 // disable analog conversion of the wave stream +#define MUTE_FM 0x80 // mute FM + +#define REG_MIXER2 0x25 // Mixer Register 2 (8bit) +#define DIS_MICGAIN 0x01 // disable microphone gain +#define MUTE_AUX_L 0x10 // mute left aux playback channel +#define MUTE_AUX_R 0x20 // mute right aux playback channel +#define MUTE_RAUX_L 0x40 // mute left aux recording channel +#define MUTE_RAUX_R 0x80 // mute right aux recording channel + +#define REG_MIXER3 0x26 // Mixer Register 3 (8bit) + +#define REG_MIXER4 0x27 // Mixer Register 4 (8bit) +#define INV_SPDIFI1 0x04 // invert S/PDIF in signal (version <=37) +#define CENTER2MIC 0x04 // route center to mic-in jack (version >37) + +#define REG_CH0_FRAME1 0x80 // Channel 0 Frame Register 1 (32bit) +#define REG_CH0_FRAME2 0x84 // Channel 0 Frame Register 2 (32bit) +#define REG_CH1_FRAME1 0x88 // Channel 1 Frame Register 1 (32bit) +#define REG_CH1_FRAME2 0x8C // Channel 1 Frame Register 2 (32bit) + +#define REG_MISCCTRL2 0x92 // Miscellaneous Control Register 2 (16bit) +#define EN_8CH_CH1 0x0020 // enable 8 channel mode on channel 1 + +#define SBREG_OUTPUTCTRL 0x3C // Soundblaster register for output controls (8bit) +#define EN_MIC 0x01 // enable microphone output +#define EN_CD_L 0x02 // enable left channel of CD input +#define EN_CD_R 0x04 // enable right channel of CD input +#define EN_LINEIN_L 0x08 // enable left channel of line-in +#define EN_LINEIN_R 0x10 // enable right channel of line-in + +#define SBREG_IN_CTRL_L 0x3D // Soundblaster register for left channel recording controls (8bit) +#define SBREG_IN_CTRL_R 0x3E // Soundblaster register for right channel recording controls (8bit) + +#define SBREG_EXTENSION 0xF0 // Soundblaster Extension Register (8bit) +#define EN_MICBOOST 0x01 // enable microphone boost for recording + +#endif \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp new file mode 100644 index 00000000000..d31d39ff434 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.cpp @@ -0,0 +1,480 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "common.hpp" + +#pragma code_seg("PAGE") + +NTSTATUS NewCMIAdapter(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) +{ + PAGED_CODE(); + DBGPRINT(("NewCMIAdapter()")); + ASSERT (Unknown); + STD_CREATE_BODY_(CCMIAdapter, Unknown, UnknownOuter, PoolType, PCMIADAPTER); +} + + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::init(PRESOURCELIST ResourceList, PDEVICE_OBJECT aDeviceObject) +{ + PAGED_CODE(); + ASSERT(ResourceList); + ASSERT(aDeviceObject); + ASSERT(ResourceList->FindTranslatedPort(0)); + DBGPRINT(("CCMIAdapter[%p]::init()", this)); + + NTSTATUS ntStatus = STATUS_SUCCESS; + + RtlFillMemory(&mixerCache, 0xFF, 0xFF); + RtlFillMemory(&cm, sizeof(cm), 0x00); + + DeviceObject = aDeviceObject; + + cm.IOBase = 0; + for (int i=0;iNumberOfPorts();i++) { + if (ResourceList->FindTranslatedPort(i)->u.Port.Length == 0x100) { + cm.IOBase = (UInt32*)ResourceList->FindTranslatedPort(i)->u.Port.Start.QuadPart; + } + } + + if (cm.IOBase == 0) { + return STATUS_INSUFFICIENT_RESOURCES; + } + cm.MPUBase = 0; + +#ifdef WAVERT + INFOPRINT(("Driver Version: %s-WAVERT", CMIVERSION)); +#else + INFOPRINT(("Driver Version: %s", CMIVERSION)); +#endif + INFOPRINT(("Configuration:")); + INFOPRINT((" IO Base: 0x%X", cm.IOBase)); + INFOPRINT((" MPU Base: 0x%X", cm.MPUBase)); + + if (!queryChip()) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + INFOPRINT((" Chip Version: %d", cm.chipVersion)); + INFOPRINT((" Max Channels: %d", cm.maxChannels)); + INFOPRINT((" CanAC3HW: %d", cm.canAC3HW)); + + resetController(); + + ntStatus = PcNewInterruptSync(&(InterruptSync), NULL, ResourceList, 0, InterruptSyncModeNormal); + if (!NT_SUCCESS(ntStatus) || !(InterruptSync)) { + DBGPRINT(("Failed to create an interrupt sync!")); + return STATUS_INSUFFICIENT_RESOURCES; + } + ntStatus = InterruptSync->RegisterServiceRoutine(InterruptServiceRoutine, (PVOID)this, FALSE); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Failed to register ISR!")); + return ntStatus; + } + + ntStatus = InterruptSync->Connect(); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Failed to connect the ISR with InterruptSync!")); + return ntStatus; + } + + // Initialize the device state. + CurrentPowerState = PowerDeviceD0; + + return ntStatus; +} + + +CCMIAdapter::~CCMIAdapter() +{ + PAGED_CODE (); + DBGPRINT(("CCMIAdapter[%p]::~CCMIAdapter()", this)); + + if (InterruptSync) { + InterruptSync->Disconnect(); + InterruptSync->Release(); + InterruptSync = NULL; + } +} + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::NonDelegatingQueryInterface(REFIID Interface, PVOID* Object) +{ + PAGED_CODE(); + + DBGPRINT(("CCMIAdapter[%p]::NonDelegatingQueryInterface()", this)); + + ASSERT(Object); + + // Is it IID_IUnknown? + if (IsEqualGUIDAligned (Interface, IID_IUnknown)) { + *Object = (PVOID)(PUNKNOWN)(PCMIADAPTER)this; + } + else + // or IID_IAdapterCommon ... + if (IsEqualGUIDAligned (Interface, IID_ICMIAdapter)) { + *Object = (PVOID)(PCMIADAPTER)this; + } else + // or IID_IAdapterPowerManagement ... + if (IsEqualGUIDAligned (Interface, IID_IAdapterPowerManagement)) { + *Object = (PVOID)(PADAPTERPOWERMANAGEMENT)this; + } else { + // nothing found, must be an unknown interface. + *Object = NULL; + return STATUS_INVALID_PARAMETER; + } + + // + // We reference the interface for the caller. + // + ((PUNKNOWN)*Object)->AddRef(); + return STATUS_SUCCESS; +} + +bool CCMIAdapter::queryChip() +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::queryChip()", this)); + + UInt32 version = readUInt32(REG_INTHLDCLR) & VERSION_MASK; + if (version == 0xFFFFFFFF) { + return false; + } + if (version) { + if (version & VERSION_68) { + cm.chipVersion = 68; + cm.maxChannels = 8; + cm.canAC3HW = true; + cm.hasDualDAC = true; + cm.canMultiChannel = true; + return true; + } + if (version & VERSION_55) { + cm.chipVersion = 55; + cm.maxChannels = 6; + cm.canAC3HW = true; + cm.hasDualDAC = true; + cm.canMultiChannel = true; + return true; + } + if (version & VERSION_39) { + cm.chipVersion = 39; + if (version & VERSION_39_6) { + cm.maxChannels = 6; + } else { + cm.maxChannels = 4; + } + cm.canAC3HW = true; + cm.hasDualDAC = true; + cm.canMultiChannel = true; + return true; + } + } else { + version = readUInt32(REG_CHFORMAT) & VERSION_37; + if (!version) { + cm.chipVersion = 33; + cm.maxChannels = 2; + if (cm.doAC3SW) { + cm.canAC3SW = true; + } else { + cm.canAC3HW = true; + } + cm.hasDualDAC = true; + return true; + } else { + cm.chipVersion = 37; + cm.maxChannels = 2; + cm.canAC3HW = true; + cm.hasDualDAC = 1; + return true; + } + } + return false; +} + +void CCMIAdapter::resetMixer() +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::resetMixer()", this)); + + writeMixer(0, 0); + setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); +} + +void CCMIAdapter::resetController() +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::resetController()", this)); + + writeUInt32(REG_INTHLDCLR, 0); + +#if OUT_CHANNEL == 1 + writeUInt32(REG_FUNCTRL0, ADC_CH0 | (RST_CH0 | RST_CH1)); + writeUInt32(REG_FUNCTRL0, ADC_CH0 & ~(RST_CH0 | RST_CH1)); +#else + writeUInt32(REG_FUNCTRL0, ADC_CH1 | (RST_CH0 | RST_CH1)); + writeUInt32(REG_FUNCTRL0, ADC_CH1 & ~(RST_CH0 | RST_CH1)); +#endif + KeStallExecutionProcessor(100L); + + writeUInt32(REG_FUNCTRL0, 0); + writeUInt32(REG_FUNCTRL1, 0); + + writeUInt32(REG_CHFORMAT, 0); + writeUInt32(REG_MISCCTRL, EN_DBLDAC); +#if OUT_CHANNEL == 1 + setUInt32Bit(REG_MISCCTRL, XCHG_DAC); +#endif + + setUInt32Bit(REG_FUNCTRL1, BREQ); + + writeMixer(0, 0); + + return; +} + + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::activateMPU(ULONG* MPUBase) +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::activateMPU(%X)", this, MPUBase)); + + UInt32 LegacyCtrl; + + switch ((LONGLONG)MPUBase) { + case 0x300: LegacyCtrl = UART_300; break; + case 0x310: LegacyCtrl = UART_310; break; + case 0x320: LegacyCtrl = UART_320; break; + case 0x330: LegacyCtrl = UART_330; break; // UART_330 == 0 + default: LegacyCtrl = 0xFFFFFFFF; break; + } + if (LegacyCtrl < 0xFFFFFFFF) { + cm.MPUBase = MPUBase; + setUInt32Bit(REG_FUNCTRL1, EN_UART); + writeUInt32(REG_LEGACY, LegacyCtrl); + return STATUS_SUCCESS; + } + + return STATUS_UNSUCCESSFUL; +} + +// "The code for this method must reside in paged memory.", IID_IAdapterPowerManagement.PowerChangeState() docs +// XP's order of power states when going to hibernate: D3 -> D0, waking up: D0 -> D3. +STDMETHODIMP_(void) CCMIAdapter::PowerChangeState(POWER_STATE NewState) +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::PowerChangeState(%p)", this, NewState)); + + if (NewState.DeviceState == CurrentPowerState ) { + return; + } + + switch (NewState.DeviceState) { + case PowerDeviceD0: // powering up, hardware access allowed + clearUInt32Bit(REG_MISCCTRL, PWD_CHIP); + cm.WaveMiniport->powerUp(); + CurrentPowerState = NewState.DeviceState; + break; + + case PowerDeviceD1: // powering down, hardware access still allowed + setUInt32Bit(REG_MISCCTRL, PWD_CHIP); + CurrentPowerState = NewState.DeviceState; + break; + + case PowerDeviceD2: // sleep state - hardware access not allowed + case PowerDeviceD3: // hibernation state - hardware access not allowed + if (CurrentPowerState == PowerDeviceD0) { + cm.WaveMiniport->powerDown(); + setUInt32Bit(REG_MISCCTRL, PWD_CHIP); + } + CurrentPowerState = NewState.DeviceState; + break; + default: // unknown power state + break; + } +} + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryPowerChangeState(POWER_STATE NewStateQuery) +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::QueryPowerChangeState(%p)", this, NewStateQuery)); + return STATUS_SUCCESS; +} + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::QueryDeviceCapabilities(PDEVICE_CAPABILITIES PowerDeviceCaps) +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::QueryDeviceCapabilities(%p)", this, PowerDeviceCaps)); + return STATUS_SUCCESS; +} + +STDMETHODIMP_(NTSTATUS) CCMIAdapter::loadSBMixerFromMemory() +{ + PAGED_CODE(); + DBGPRINT(("CCMIAdapter[%p]::loadSBMixerFromMemory()", this)); + UInt8 sbIndex[] = { 0x04, 0x0A, 0x22, 0x28, 0x2E, 0x30, 0x31, 0x32, 0x33, 0x36, 0x37, 0x38, + 0x39, 0x3A, 0x3C, 0x3D, 0x3E, 0xF0 }; + + for (int i = 0; i<(sizeof(sbIndex)/sizeof(sbIndex[0]));i++) { + writeUInt8(REG_SBINDEX, sbIndex[i]); + writeUInt8(REG_SBDATA, mixerCache[i]); + } + + return STATUS_SUCCESS; +} + +/* +** non-paged code below +*/ +#pragma code_seg() + +STDMETHODIMP_(UInt8) CCMIAdapter::readUInt8(UInt8 reg) +{ + return READ_PORT_UCHAR((PUCHAR)(reinterpret_cast(cm.IOBase) + reg)); +} + +STDMETHODIMP_(void) CCMIAdapter::writeUInt8(UInt8 cmd, UInt8 value) +{ + WRITE_PORT_UCHAR((PUCHAR)(reinterpret_cast(cm.IOBase) + cmd), value); +} + +STDMETHODIMP_(void) CCMIAdapter::setUInt8Bit(UInt8 reg, UInt8 flag) +{ + writeUInt8(reg, readUInt8(reg) | flag); +} + +STDMETHODIMP_(void) CCMIAdapter::clearUInt8Bit(UInt8 reg, UInt8 flag) +{ + writeUInt8(reg, readUInt8(reg) & ~flag); +} + +STDMETHODIMP_(UInt16) CCMIAdapter::readUInt16(UInt8 reg) +{ + return READ_PORT_USHORT((PUSHORT)(reinterpret_cast(cm.IOBase) + reg)); +} + +STDMETHODIMP_(void) CCMIAdapter::writeUInt16(UInt8 cmd, UInt16 value) +{ + WRITE_PORT_USHORT((PUSHORT)(reinterpret_cast(cm.IOBase) + cmd), value); +} + + +STDMETHODIMP_(UInt32) CCMIAdapter::readUInt32(UInt8 reg) +{ + return READ_PORT_ULONG((PULONG)(reinterpret_cast(cm.IOBase) + reg)); +} + +STDMETHODIMP_(void) CCMIAdapter::writeUInt32(UInt8 cmd, UInt32 value) +{ + WRITE_PORT_ULONG((PULONG)(reinterpret_cast(cm.IOBase) + cmd), value); +} + +STDMETHODIMP_(void) CCMIAdapter::setUInt32Bit(UInt8 reg, UInt32 flag) +{ + writeUInt32(reg, readUInt32(reg) | flag); +} + +STDMETHODIMP_(void) CCMIAdapter::clearUInt32Bit(UInt8 reg, UInt32 flag) +{ + writeUInt32(reg, readUInt32(reg) & ~flag); +} + +STDMETHODIMP_(UInt8) CCMIAdapter::readMixer(UInt8 index) +{ + if (mixerCache[index] == 0xFF) { + writeUInt8(REG_SBINDEX, index); + mixerCache[index] = readUInt8(REG_SBDATA); + } + return mixerCache[index]; +} + +STDMETHODIMP_(void) CCMIAdapter::writeMixer(UInt8 index, UInt8 value) +{ + if (value != mixerCache[index]) { + mixerCache[index] = value; + writeUInt8(REG_SBINDEX, index); + writeUInt8(REG_SBDATA, value); + } +} + +STDMETHODIMP_(void) CCMIAdapter::setMixerBit(UInt8 index, UInt8 flag) +{ + writeMixer(index, readMixer(index) | flag); +} + +STDMETHODIMP_(void) CCMIAdapter::clearMixerBit(UInt8 index, UInt8 flag) +{ + writeMixer(index, readMixer(index) & ~flag); +} + +NTSTATUS CCMIAdapter::InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID DynamicContext) +{ + ASSERT(InterruptSync); + ASSERT(DynamicContext); + + UInt32 status, mask = 0; + + CCMIAdapter *CMIAdapter = (CCMIAdapter *)DynamicContext; + + if (!(CMIAdapter->cm.WaveMiniport)) { + return STATUS_UNSUCCESSFUL; + } + + status = CMIAdapter->readUInt32(REG_INT_STAT); + + if ((!(status & INT_PENDING)) || (status == 0xFFFFFFFF)) { + return STATUS_UNSUCCESSFUL; + } + + if (status & INT_CH0) { + mask |= EN_CH0_INT; +#if OUT_CHANNEL == 0 + CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_OUT_STREAM); +#endif +#if IN_CHANNEL == 0 + CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_IN_STREAM); +#endif + } + if (status & INT_CH1) { + mask |= EN_CH1_INT; +#if OUT_CHANNEL == 1 + CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_OUT_STREAM); +#endif +#if IN_CHANNEL == 1 + CMIAdapter->cm.WaveMiniport->ServiceWaveISR(PCM_IN_STREAM); +#endif + } +#ifdef UART + if (status & INT_UART) { + // the UART miniport should catch / have caught the interrupt + return STATUS_UNSUCCESSFUL; + } +#endif + + CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, mask); + CMIAdapter->setUInt32Bit(REG_INTHLDCLR, mask); + + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp new file mode 100644 index 00000000000..919cb9970c8 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/common.hpp @@ -0,0 +1,110 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _COMMON_HPP_ +#define _COMMON_HPP_ + +#include "stdunk.h" +#include "portcls.h" +#include "dmusicks.h" +#include "ksdebug.h" +#include "kcom.h" + +#include "interfaces.hpp" +#include "debug.hpp" +#include "cmireg.hpp" + +class CCMIAdapter : public ICMIAdapter, + public IAdapterPowerManagement, + public CUnknown +{ +private: + PDEVICE_OBJECT DeviceObject; + PINTERRUPTSYNC InterruptSync; + DEVICE_POWER_STATE CurrentPowerState; + UInt8 mixerCache[0xFF]; + + CMI8738Info cm; + + bool queryChip(); + void resetController(); + +public: + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CCMIAdapter); + ~CCMIAdapter(); + + IMP_IAdapterPowerManagement; + + STDMETHODIMP_(NTSTATUS) init(PRESOURCELIST ResourceList, PDEVICE_OBJECT aDeviceObject); + STDMETHODIMP_(NTSTATUS) activateMPU(ULONG* MPUBase); + STDMETHODIMP_(NTSTATUS) loadSBMixerFromMemory(); + + STDMETHODIMP_(UInt8) readUInt8(UInt8 reg); + STDMETHODIMP_(void) writeUInt8(UInt8 reg, UInt8 value); + + STDMETHODIMP_(void) setUInt8Bit(UInt8 reg, UInt8 flag); + STDMETHODIMP_(void) clearUInt8Bit(UInt8 reg, UInt8 flag); + + STDMETHODIMP_(UInt16) readUInt16(UInt8 reg); + STDMETHODIMP_(void) writeUInt16(UInt8 reg, UInt16 value); + + STDMETHODIMP_(UInt32) readUInt32(UInt8 reg); + STDMETHODIMP_(void) writeUInt32(UInt8 reg, UInt32 value); + + STDMETHODIMP_(void) setUInt32Bit(UInt8 reg, UInt32 flag); + STDMETHODIMP_(void) clearUInt32Bit(UInt8 reg, UInt32 flag); + + STDMETHODIMP_(UInt8) readMixer(UInt8 index); + STDMETHODIMP_(void) writeMixer(UInt8 index, UInt8 value); + STDMETHODIMP_(void) setMixerBit(UInt8 index, UInt8 flag); + STDMETHODIMP_(void) clearMixerBit(UInt8 index, UInt8 flag); + + STDMETHODIMP_(void) resetMixer(); + + static NTSTATUS InterruptServiceRoutine(PINTERRUPTSYNC InterruptSync, PVOID StaticContext); + + STDMETHODIMP_(PCMI8738Info) getCMI8738Info(void) + { + return &cm; + }; + + STDMETHODIMP_(PINTERRUPTSYNC) getInterruptSync(void) + { + return InterruptSync; + }; + STDMETHODIMP_(PDEVICE_OBJECT) getDeviceObject(void) + { + return DeviceObject; + }; + + friend NTSTATUS NewCCMIAdapter(PCMIADAPTER* OutCMIAdapter, PRESOURCELIST ResourceList); +}; + +NTSTATUS NewCMIAdapter(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType); + +#endif //_COMMON_HPP_ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp new file mode 100644 index 00000000000..8646d3e9b15 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.cpp @@ -0,0 +1,96 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include "resource.h" + +BOOL APIENTRY DllMain (HANDLE hModule, ULONG gna, LPVOID lpReserved) +{ + return TRUE; +} + +BOOL execControlPanel() +{ + TCHAR szSysDir[1024]; + if (!GetSystemDirectory(szSysDir, sizeof(szSysDir) / sizeof(TCHAR))) { + return FALSE; + } + _tcscat(szSysDir, _T("\\cmicontrol.exe")); //unsafe + ShellExecute(NULL, _T("open"), szSysDir, NULL, NULL, SW_SHOWNORMAL); + return TRUE; +} + +LONG APIENTRY CPlApplet (HWND hWnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2) +{ + switch (uMsg) + { + case CPL_INIT: + return TRUE; + + case CPL_GETCOUNT: + return 1; + + case CPL_INQUIRE: + { + LPCPLINFO pCplInfo = (LPCPLINFO)lParam2; + + if (!pCplInfo) { + return TRUE; + } + + if ((UINT)lParam1 == 0) { + pCplInfo->idIcon = IDI_CPLICON; + pCplInfo->idName = IDS_CPLNAME; + pCplInfo->idInfo = IDS_CPLINFO; + } + break; + } + + case CPL_NEWINQUIRE: + break; + + case CPL_DBLCLK: + case CPL_STARTWPARMS: + if ((UINT)lParam1 == 0) { + if (!execControlPanel()) { + return TRUE; + } + } + break; + case CPL_EXIT: + break; + + default: + break; + } + + return 0; +} + diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.def b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.def new file mode 100644 index 00000000000..a1fe6f819ba --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.def @@ -0,0 +1,4 @@ +LIBRARY "CMICPL" + +EXPORTS + CPlApplet diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc new file mode 100644 index 00000000000..7ebd49d4f22 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/cmicpl.rc @@ -0,0 +1,56 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "resource.h" + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Audio Control Panel (CMI 8738/8768)" +#define VER_INTERNALNAME_STR "cmicontrol.exe" +#define VER_ORIGINALFILENAME_STR "cmicontrol.exe" +#ifdef VER_COMPANYNAME_STR +#undef VER_COMPANYNAME_STR +#endif +#define VER_COMPANYNAME_STR "Dogbert" +#ifdef VER_PRODUCTNAME_STR +#undef VER_PRODUCTNAME_STR +#endif +#define VER_PRODUCTNAME_STR "" +#define VER_LEGALCOPYRIGHT_YEARS "" +#define VER_LEGALCOPYRIGHT_STR "BSD-style license" + +#include + +IDI_CPLICON ICON PRELOAD DISCARDABLE "..\cmicontrol\window.ico" + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CPLNAME "CMI8738/8768 Control Panel" + IDS_CPLINFO "Display and set features of your C-Media soundcard" +END diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile new file mode 100644 index 00000000000..5acbbd24c0e --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/makefile @@ -0,0 +1 @@ +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h new file mode 100644 index 00000000000..6a73cbc2550 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/resource.h @@ -0,0 +1,30 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define IDI_CPLICON 100 +#define IDS_CPLNAME 200 +#define IDS_CPLINFO 201 diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources new file mode 100644 index 00000000000..54d43b35b5c --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/cpl/sources @@ -0,0 +1,24 @@ +TARGETNAME = cmicpl +TARGETTYPE = DYNLINK +TARGETEXT = cpl +DLLENTRY = _DllMainCRTStartup + +TARGETLIBS = $(SDK_LIB_PATH)\setupapi.lib \ + $(SDK_LIB_PATH)\comctl32.lib \ + $(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib \ + $(SDK_LIB_PATH)\shell32.lib + +INCLUDES = .. + +USE_MSVCRT=1 + +MSC_WARNING_LEVEL = $(MSC_WARNING_LEVEL) /WX + +C_DEFINES = $(CFASTFLAGS) $(C_DEFINES) -DUNICODE -D_UNICODE -DUNDER_NT + +UMTYPE = windows + +SOURCES = cmicpl.rc \ + cmicpl.cpp + diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp new file mode 100644 index 00000000000..598cad7a5ae Binary files /dev/null and b/reactos/drivers/wdm/audio/drivers/CMIDriver/debug.hpp differ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/distclean.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/distclean.bat new file mode 100644 index 00000000000..e7d8b07ddba --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/distclean.bat @@ -0,0 +1,53 @@ +@echo off +call envars.bat + +rd /s /q cpl\objchk_wxp_x86 +rd /s /q cpl\objchk_wxp_amd64 +rd /s /q cpl\objfre_wxp_x86 +rd /s /q cpl\objfre_wxp_amd64 +rd /s /q cpl\objchk_wlh_x86 +rd /s /q cpl\objchk_wlh_amd64 +rd /s /q cpl\objfre_wlh_x86 +rd /s /q cpl\objfre_wlh_amd64 +del cpl\errors.err +del cpl\build*.* + +rd /s /q cmicontrol\objchk_wxp_x86 +rd /s /q cmicontrol\objchk_wxp_amd64 +rd /s /q cmicontrol\objfre_wxp_x86 +rd /s /q cmicontrol\objfre_wxp_amd64 +rd /s /q cmicontrol\objchk_wlh_x86 +rd /s /q cmicontrol\objchk_wlh_amd64 +rd /s /q cmicontrol\objfre_wlh_x86 +rd /s /q cmicontrol\objfre_wlh_amd64 +del cmicontrol\errors.err +del cmicontrol\build*.* + +rd /s /q installer\objchk_wxp_x86 +rd /s /q installer\objchk_wxp_amd64 +rd /s /q installer\objfre_wxp_x86 +rd /s /q installer\objfre_wxp_amd64 +rd /s /q installer\objchk_wlh_x86 +rd /s /q installer\objchk_wlh_amd64 +rd /s /q installer\objfre_wlh_x86 +rd /s /q installer\objfre_wlh_amd64 +del installer\errors.err +del installer\build*.* + +rd /s /q objchk_wxp_x86 +rd /s /q objchk_wxp_amd64 +rd /s /q objfre_wxp_x86 +rd /s /q objfre_wxp_amd64 +rd /s /q objchk_wlh_x86 +rd /s /q objchk_wlh_amd64 +rd /s /q objfre_wlh_x86 +rd /s /q objfre_wlh_amd64 +del errors.err + +rd /s /q release-x86 +rd /s /q release-x64 +rd /s /q release-x86-WaveRT +rd /s /q release-x64-WaveRT +rd /s /q debug-x86 +del *.zip +7z a -tzip CMIDriver-%CMI_VERSION%-src.zip * cmicontrol\* cpl\* installer\* \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/envars.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/envars.bat new file mode 100644 index 00000000000..9407422dfb3 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/envars.bat @@ -0,0 +1,14 @@ +@echo off +set CMI_DDKDIR=c:\WinDDK\6000 +set CMI_BUILDDIR=C:\WinDDK\6000\src\Audio\CMedia +set CMI_VERSION=1.1.3 +REM the slashes need to be escaped for sed.exe +set CMI_RELEASEDATE=06\/30\/2007 +REM wxp | wlh +set CMI_DEBUGOS=wlh +REM x86 | AMD64 +set CMI_DEBUGARCH=x86 +REM WaveRT | +set CMI_DEBUGVER= +REM find out with 'devcon dp_enum' +set CMI_OEMINF="oem1.inf" \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp new file mode 100644 index 00000000000..4f2dd8ab81f --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/main.cpp @@ -0,0 +1,204 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "main.h" + + +void PrintLastError(LPCSTR function) +{ + LPVOID lpMsgBuf; + DWORD errorid = GetLastError(); + + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); + MessageBox(NULL, (LPCSTR)lpMsgBuf, function, MB_ICONEXCLAMATION | MB_OK); + LocalFree(lpMsgBuf); +} + +BOOL deleteCMIKeys() +{ + HKEY key; + unsigned int i; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), NULL, KEY_SET_VALUE, &key) != ERROR_SUCCESS) { + PrintLastError("RegOpenKeyEx()"); + return FALSE; + } + for (i=0;i +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include +#include +#include +#include "resource.h" + +HINSTANCE hInst; + +const TCHAR* devIDs[] = {"PCI\\VEN_13F6&DEV_0111", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_011013F6", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_011113F6", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_1144153B", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_3731584D", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_87681092", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_020110B0", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_020210B0", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_020410B0", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_009C145F", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_39201462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_39801462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_50701462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_52801462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_53201462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_53401462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_54501462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_56501462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_59001462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_59201462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_70201462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_70401462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_70411462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_71011462", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_A016147A", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_30021919", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_0577A0A0", + "PCI\\VEN_13F6&DEV_0111&SUBSYS_060417AB", + }; + +const unsigned int devArraySize = sizeof(devIDs) / sizeof(devIDs[0]); + +const char* CMIKeys[] = { "Cmaudio", "CmPCIaudio", "C-Media Mixer" }; +const unsigned int NumberOfCMIKeys = sizeof(CMIKeys) / sizeof(CMIKeys[0]); + +//uninstaller stuff +const char DisplayName[] = _T("CMI 8738/8768 Audio Driver (remove only)"); +const char DisplayIcon[] = _T("\\cmicontrol.exe,0"); +const char Uninstaller[] = _T("\\cmicontrol.exe /uninstall"); +const char Publisher[] = _T("Dogbert "); +const char URLInfoAbout[] = _T("http://cmediadrivers.googlepages.com/"); + + +#endif //_MAIN_H_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile new file mode 100644 index 00000000000..5acbbd24c0e --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/makefile @@ -0,0 +1 @@ +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h new file mode 100644 index 00000000000..cfb787a5600 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/resource.h @@ -0,0 +1,36 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define IDC_STATIC -1 + +// icons +#define IDI_APP_ICON 150 + +// main dialog +#define IDD_MAIN 100 +#define IDB_CLOSE 101 +#define IDB_INSTALL 102 diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources new file mode 100644 index 00000000000..572cbd72ec7 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/sources @@ -0,0 +1,26 @@ +TARGETNAME=setup +TARGETTYPE=PROGRAM +TARGETPATH= + +USE_MSVCRT=1 + +INCLUDES=.. + +TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ + $(SDK_LIB_PATH)\user32.lib \ + $(SDK_LIB_PATH)\newdev.lib + +MSC_WARNING_LEVEL=/W3 /WX + +SOURCES= main.cpp \ + window.rc + +UMTYPE=windows +UMENTRY=winmain + +C_DEFINES=/DW32 /DWIN32 +_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WIN2K) + +TARGET_DESTINATION=idw + +MUI=0 \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc new file mode 100644 index 00000000000..ddf1cb58c26 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/installer/window.rc @@ -0,0 +1,62 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "resource.h" + +#include + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Driver Installer (CMI 8738/8768)" +#define VER_INTERNALNAME_STR "install.exe" +#define VER_ORIGINALFILENAME_STR "install.exe" +#ifdef VER_COMPANYNAME_STR +#undef VER_COMPANYNAME_STR +#endif +#define VER_COMPANYNAME_STR "Dogbert" +#ifdef VER_PRODUCTNAME_STR +#undef VER_PRODUCTNAME_STR +#endif +#define VER_PRODUCTNAME_STR "" +#define VER_LEGALCOPYRIGHT_YEARS "" +#define VER_LEGALCOPYRIGHT_STR "BSD-style license" + +#include "common.ver" + +IDI_APP_ICON ICON DISCARDABLE "..\cmicontrol\window.ico" + +IDD_MAIN DIALOG DISCARDABLE 0, 0, 120, 54 +STYLE DS_ABSALIGN | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Driver Installer" +FONT 8, "MS Shell Dlg" +CLASS "cmiDriverInstaller" +BEGIN + DEFPUSHBUTTON "&Install Driver",IDB_INSTALL,10,10,100,14 + PUSHBUTTON "&Close",IDB_CLOSE,10,30,100,14 +END diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp new file mode 100644 index 00000000000..80b9cd87974 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/interfaces.hpp @@ -0,0 +1,463 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _INTERFACES_HPP_ +#define _INTERFACES_HPP_ + +#include +#include + +#define MAXLEN_DMA_BUFFER 0x18000 +#define MAX_OUTPUT_STREAMS 1 +#define MAX_INPUT_STREAMS 1 +#define MAX_AC3_INPUT_STREAMS 1 + +// PCM Info +#define MIN_CHANNELS 2 +#define MAX_CHANNELS_PCM 8 +#define MIN_BITS_PER_SAMPLE_PCM 16 +#define MAX_BITS_PER_SAMPLE_PCM 32 +#define MIN_SAMPLE_RATE 44100 +#define MAX_SAMPLE_RATE 96000 +#define MAX_SAMPLE_RATE_MULTI 48000 + +// AC3 Info +#define MAX_CHANNELS_AC3 2 +#define MIN_BITS_PER_SAMPLE_AC3 16 +#define MAX_BITS_PER_SAMPLE_AC3 16 +#define MIN_SAMPLE_RATE_AC3 48000 +#define MAX_SAMPLE_RATE_AC3 48000 + + +#define PCM_OUT_STREAM 0 +#define PCM_IN_STREAM 1 +#define AC3_OUT_STREAM 2 + +#define CHAN_LEFT 0 +#define CHAN_RIGHT 1 +#define CHAN_MASTER (-1) + +#define IN_CHANNEL 0 +#define OUT_CHANNEL 1 + +#define UInt32 ULONG +#define UInt16 USHORT +#define UInt8 BYTE +#define Int32 LONG + +#define KSSTATE_STOP_AC3 (KSSTATE)5 +#define KSSTATE_RUN_AC3 (KSSTATE)6 + +// Interface ICMITopology +DECLARE_INTERFACE_(ICMITopology,IMiniportTopology) +{ + STDMETHOD_(NTSTATUS,GetDescription) + ( THIS_ + PPCFILTER_DESCRIPTOR* OutFilterDescriptor + ) PURE; + STDMETHOD_(NTSTATUS,DataRangeIntersection) + ( THIS_ + ULONG PinId, + PKSDATARANGE DataRange, + PKSDATARANGE MatchingDataRange, + ULONG OutputBufferLength, + PVOID ResultantFormat, + PULONG ResultantFormatLength + ) PURE; + STDMETHOD_(NTSTATUS,Init) + ( THIS_ + PUNKNOWN UnknownAdapter, + PRESOURCELIST ResourceList, + PPORTTOPOLOGY Port + ) PURE; + STDMETHOD_(NTSTATUS,loadMixerSettingsFromMemory) + ( THIS_ + void + ) PURE; + STDMETHOD_(NTSTATUS,storeMixerSettingsToMemory) + ( THIS_ + void + ) PURE; +}; +typedef ICMITopology *PCMITOPOLOGY; + +// Interface IMiniportWaveCMI +DECLARE_INTERFACE_(IMiniportWaveCMI,IUnknown) +{ + STDMETHOD_(void,ServiceWaveISR) + ( THIS_ + ULONG channel + ) PURE; + + STDMETHOD_(void,powerUp) + ( THIS_ + void + ) PURE; + STDMETHOD_(void,powerDown) + ( THIS_ + void + ) PURE; +}; +typedef IMiniportWaveCMI *PCMIWAVE; + +// structure to avoid the fucking COM crapola +typedef struct CMI8738Info { + int chipVersion; + int maxChannels; + bool canAC3HW, canAC3SW; + bool canMultiChannel; + bool doAC3SW; + bool hasDualDAC; + UInt32* IOBase; + UInt32* MPUBase; + PCMIWAVE WaveMiniport; + PCMITOPOLOGY TopoMiniport; + bool enableSPDIFOut; + bool enableSPDIFIn; + UInt32 formatMask; + UInt32 regFUNCTRL0; +} CMI8738Info; +typedef CMI8738Info* PCMI8738Info; + +typedef struct VolumeTable { + UInt32 node; + UInt8 reg; + UInt8 mask; + UInt8 shift; + Int32 max; + Int32 min; + Int32 step; + Int32 dbshift; +} VolumeTable; + +// Interface ICMIAdapter +DECLARE_INTERFACE_(ICMIAdapter,IUnknown) +{ + STDMETHOD_(NTSTATUS,init) + ( THIS_ + PRESOURCELIST ResourceList, + PDEVICE_OBJECT DeviceObject + ) PURE; + STDMETHOD_(PINTERRUPTSYNC,getInterruptSync) + ( THIS_ + void + ) PURE; + STDMETHOD_(PDEVICE_OBJECT,getDeviceObject) + ( THIS_ + void + ) PURE; + STDMETHOD_(PCMI8738Info,getCMI8738Info) + ( THIS_ + void + ) PURE; + STDMETHOD_(UInt8, readUInt8) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt8) + ( THIS_ + UInt8 reg, + UInt8 value + ) PURE; + STDMETHOD_(void, setUInt8Bit) + ( THIS_ + UInt8 reg, + UInt8 flag + ) PURE; + STDMETHOD_(void, clearUInt8Bit) + ( THIS_ + UInt8 reg, + UInt8 flag + ) PURE; + STDMETHOD_(UInt16, readUInt16) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt16) + ( THIS_ + UInt8 reg, + UInt16 value + ) PURE; + STDMETHOD_(UInt32, readUInt32) + ( THIS_ + UInt8 reg + ) PURE; + STDMETHOD_(void, writeUInt32) + ( THIS_ + UInt8 reg, + UInt32 value + ) PURE; + STDMETHOD_(void, setUInt32Bit) + ( THIS_ + UInt8 reg, + UInt32 flag + ) PURE; + STDMETHOD_(void, clearUInt32Bit) + ( THIS_ + UInt8 reg, + UInt32 flag + ) PURE; + STDMETHOD_(UInt8, readMixer) + ( THIS_ + UInt8 index + ) PURE; + STDMETHOD_(void, writeMixer) + ( THIS_ + UInt8 index, + UInt8 value + ) PURE; + STDMETHOD_(void, setMixerBit) + ( THIS_ + UInt8 index, + UInt8 flag + ) PURE; + STDMETHOD_(void, clearMixerBit) + ( THIS_ + UInt8 index, + UInt8 flag + ) PURE; + STDMETHOD_(void,resetMixer) + ( THIS_ + ) PURE; + STDMETHOD_(NTSTATUS,activateMPU) + ( THIS_ + ULONG* MPUBase + ) PURE; + STDMETHOD_(NTSTATUS,loadSBMixerFromMemory) + ( THIS_ + ) PURE; +}; +typedef ICMIAdapter *PCMIADAPTER; + +// GUIDs + +// {34B338A2-BB40-4ecd-B97A-AEB03F325825} +DEFINE_GUID(IID_ICMIAdapter, 0x34b338a2, 0xbb40, 0x4ecd, 0xb9, 0x7a, 0xae, 0xb0, 0x3f, 0x32, 0x58, 0x25); +// {60BB55CF-C960-4ddf-B7A4-243978B2FE7B} +DEFINE_GUID(IID_ICMITopolgy, 0x60bb55cf, 0xc960, 0x4ddf, 0xb7, 0xa4, 0x24, 0x39, 0x78, 0xb2, 0xfe, 0x7b); +// {E8698236-D854-4da7-BF31-8332C614CE91} +DEFINE_GUID(IID_IMiniportWaveCMI, 0xe8698236, 0xd854, 0x4da7, 0xbf, 0x31, 0x83, 0x32, 0xc6, 0x14, 0xce, 0x91); + + +// {9DB14E9A-7BE7-480d-A2FA-32932489DE9C} +#define STATIC_PRODUCT_CM8738 \ + 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9c +DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9C", PRODUCT_CM8738); +#define PRODUCT_CM8738 DEFINE_GUIDNAMED(PRODUCT_CM8738) + +// {9DB14E9A-7BE7-480d-A2FA-32932489DE9D} +#define STATIC_COMPONENT_CM8738 \ + 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9d +DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9D", COMPONENT_CM8738); +#define COMPONENT_CM8738 DEFINE_GUIDNAMED(COMPONENT_CM8738) + +// {9DB14E9A-7BE7-480d-A2FA-32932489DE9E} +#define STATIC_MANUFACTURER_CM8738 \ + 0x9db14e9a, 0x7be7, 0x480d, 0xa2, 0xfa, 0x32, 0x93, 0x24, 0x89, 0xde, 0x9e +DEFINE_GUIDSTRUCT("9DB14E9A-7BE7-480d-A2FA-32932489DE9E", MANUFACTURER_CM8738); +#define MANUFACTURER_CM8738 DEFINE_GUIDNAMED(MANUFACTURER_CM8738) + + +#define CMIPCI_VERSION 0x00 + +// topology node names (refer to .inf file) +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0} +#define STATIC_CMINAME_IEC_5V \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF0 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF0", _STATIC_CMINAME_IEC_5V); +#define CMINAME_IEC_5V DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_5V) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1} +#define STATIC_CMINAME_IEC_OUT \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF1 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF1", _STATIC_CMINAME_IEC_OUT); +#define CMINAME_IEC_OUT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_OUT) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2} +#define STATIC_CMINAME_IEC_INVERSE \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF2 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF2", _STATIC_CMINAME_IEC_INVERSE); +#define CMINAME_IEC_INVERSE DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_INVERSE) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3} +#define STATIC_CMINAME_IEC_MONITOR \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF3 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF3", _STATIC_CMINAME_IEC_MONITOR); +#define CMINAME_IEC_MONITOR DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_MONITOR) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4} +#define STATIC_CMINAME_DAC \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF4 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF4", _STATIC_CMINAME_DAC); +#define CMINAME_DAC DEFINE_GUIDNAMED(_STATIC_CMINAME_DAC) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5} +#define STATIC_CMINAME_IEC_SELECT \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF5 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF5", _STATIC_CMINAME_IEC_SELECT); +#define CMINAME_IEC_SELECT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_SELECT) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6} +#define STATIC_CMINAME_XCHG_FB \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF6 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF6", _STATIC_CMINAME_XCHG_FB); +#define CMINAME_XCHG_FB DEFINE_GUIDNAMED(_STATIC_CMINAME_XCHG_FB) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7} +#define STATIC_CMINAME_BASS2LINE \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF7 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF7", _STATIC_CMINAME_BASS2LINE); +#define CMINAME_BASS2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_BASS2LINE) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8} +#define STATIC_CMINAME_CENTER2LINE \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF8 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF8", _STATIC_CMINAME_CENTER2LINE); +#define CMINAME_CENTER2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_CENTER2LINE) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9} +#define STATIC_CMINAME_IEC_COPYRIGHT \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xF9 +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DF9", _STATIC_CMINAME_IEC_COPYRIGHT); +#define CMINAME_IEC_COPYRIGHT DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_COPYRIGHT) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA} +#define STATIC_CMINAME_IEC_POLVALID \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFA +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFA", _STATIC_CMINAME_IEC_POLVALID); +#define CMINAME_IEC_POLVALID DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_POLVALID) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB} +#define STATIC_CMINAME_IEC_LOOP \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFB +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFB", _STATIC_CMINAME_IEC_LOOP); +#define CMINAME_IEC_LOOP DEFINE_GUIDNAMED(_STATIC_CMINAME_IEC_LOOP) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC} +#define STATIC_CMINAME_REAR2LINE \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFC +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFC", _STATIC_CMINAME_REAR2LINE); +#define CMINAME_REAR2LINE DEFINE_GUIDNAMED(_STATIC_CMINAME_REAR2LINE) + +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD} +#define STATIC_CMINAME_CENTER2MIC \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFD +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFD", _STATIC_CMINAME_CENTER2MIC); +#define CMINAME_CENTER2MIC DEFINE_GUIDNAMED(_STATIC_CMINAME_CENTER2MIC) + +//topology pins +enum +{ + PIN_WAVEOUT_SOURCE = 0, + PIN_SPDIFIN_SOURCE, + PIN_MIC_SOURCE, + PIN_CD_SOURCE, + PIN_LINEIN_SOURCE, + PIN_AUX_SOURCE, + PIN_DAC_SOURCE, + PIN_LINEOUT_DEST, + PIN_WAVEIN_DEST, + PIN_SPDIF_AC3_SOURCE, + PIN_SPDIF_AC3_DEST, + + PIN_INVALID +}; + +//topology nodes +enum +{ + KSNODE_TOPO_WAVEOUT_VOLUME = 0, + KSNODE_TOPO_WAVEOUT_MUTE, + KSNODE_TOPO_MICOUT_VOLUME, + KSNODE_TOPO_LINEOUT_MIX, + KSNODE_TOPO_LINEOUT_VOLUME, + KSNODE_TOPO_WAVEIN_SUM, + KSNODE_TOPO_CD_VOLUME, + KSNODE_TOPO_LINEIN_VOLUME, + KSNODE_TOPO_AUX_VOLUME, + KSNODE_TOPO_MICIN_VOLUME, + KSNODE_TOPO_MICIN_LOUDNESS, + KSNODE_TOPO_MICOUT_LOUDNESS, + KSNODE_TOPO_CD_MUTE, + KSNODE_TOPO_LINEIN_MUTE, + KSNODE_TOPO_MICOUT_MUTE, + KSNODE_TOPO_AUX_MUTE, + KSNODE_TOPO_LINEIN_MUTE_IN, + KSNODE_TOPO_MIC_MUTE_IN, + KSNODE_TOPO_AUX_MUTE_IN, + KSNODE_TOPO_CD_MUTE_IN, + KSNODE_TOPO_WAVEOUT_MUTE_IN, + KSNODE_TOPO_IEC_5V, + KSNODE_TOPO_IEC_OUT, + KSNODE_TOPO_IEC_INVERSE, + KSNODE_TOPO_IEC_MONITOR, + KSNODE_TOPO_IEC_SELECT, + KSNODE_TOPO_SPDIF_AC3_MUTE, + KSNODE_TOPO_SPDIF_AC3_MUX, + KSNODE_TOPO_XCHG_FB, + KSNODE_TOPO_BASS2LINE, + KSNODE_TOPO_CENTER2LINE, + KSNODE_TOPO_IEC_COPYRIGHT, + KSNODE_TOPO_IEC_POLVALID, + KSNODE_TOPO_IEC_LOOP, + KSNODE_TOPO_REAR2LINE, + KSNODE_TOPO_CENTER2MIC, + KSNODE_TOPO_MASTER_MUTE_DUMMY, + + KSNODE_TOPO_INVALID +}; + +//wave miniport pins +enum +{ + PIN_WAVE_CAPTURE_SINK = 0, + PIN_WAVE_CAPTURE_SOURCE, + PIN_WAVE_RENDER_SINK, + PIN_WAVE_RENDER_SOURCE, + PIN_WAVE_AC3_RENDER_SINK, + PIN_WAVE_AC3_RENDER_SOURCE, + + PIN_WAVE_INVALID +}; + +//wave miniport nodes +enum +{ + KSNODE_WAVE_ADC = 0, + KSNODE_WAVE_VOLUME1, + KSNODE_WAVE_3D_EFFECTS, + KSNODE_WAVE_SUPERMIX, + KSNODE_WAVE_VOLUME2, + KSNODE_WAVE_SRC, + KSNODE_WAVE_SUM, + KSNODE_WAVE_DAC, + KSNODE_WAVE_SPDIF, + + KSNODE_WAVE_INVALID +}; + +#endif //_INTERFACES_HPP_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/make.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/make.bat new file mode 100644 index 00000000000..383b007c4d1 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/make.bat @@ -0,0 +1,40 @@ +@echo off +call envars.bat +if "%DDKBUILDENV%"=="chk" goto :AlreadyDefined +call %CMI_DDKDIR%\bin\setenv %CMI_DDKDIR% chk %CMI_DEBUGARCH% %CMI_DEBUGOS% +:AlreadyDefined +cd %CMI_BUILDDIR% + +if "%CMI_DEBUGARCH%"=="AMD64" goto :x64 +set CMI_DEBUGDIR=objchk_%CMI_DEBUGOS%_%CMI_DEBUGARCH%\i386 +mkdir %CMI_DEBUGDIR% +sed -e "s/CMIVersion/%CMI_VERSION%-dbg/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x32%WAVERTSTR%.INF >%CMI_DEBUGDIR%\CM8738.inf +goto start +:x64 +set CMI_DEBUGDIR=objchk_%CMI_DEBUGOS%_%CMI_DEBUGARCH%\AMD64 +mkdir %CMI_DEBUGDIR% +sed -e "s/CMIVersion/%CMI_VERSION%-dbg/" -e "s/CMIReleaseDate/%CMI_RELEASEDATE%/" CM8738-x64%WAVERTSTR%.inf >%CMI_DEBUGDIR%\CM8738.inf + +:start +del %CMI_DEBUGDIR%\*.obj + +sed -i "s/CMIVERSION.*/CMIVERSION \"%CMI_VERSION%-debug\"/" debug.hpp + +if "%CMI_DEBUGVER%"=="WaveRT" goto :WaveRT +sed -i "s/^#define WAVERT/\/\/#define WAVERT/" debug.hpp +goto next +:WaveRT +sed -i "s/^\/\/#define WAVERT/#define WAVERT/" debug.hpp +:next + +nmake /x errors.err + +if "%CMI_DEBUGVER%"=="WaveRT" goto :WaveRT2 +set WAVERTSTR="" +goto end +:WaveRT2 +set WAVERTSTR="-WAVERT" + +:end +sed -i "s/^cmicpl.*$//g" %CMI_DEBUGDIR%\CM8738.inf +sed -i "s/^CMICONTROL.*$//g" %CMI_DEBUGDIR%\CM8738.inf diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/makefile b/reactos/drivers/wdm/audio/drivers/CMIDriver/makefile new file mode 100644 index 00000000000..67a66452b9f --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/makefile @@ -0,0 +1,6 @@ +!if defined(DDK_TARGET_OS) && "$(DDK_TARGET_OS)"!="Win2K" +!INCLUDE $(NTMAKEENV)\makefile.def +!else +!message This project is for Windows XP (or later) only. +!endif + diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp new file mode 100644 index 00000000000..f42c9b2a461 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.cpp @@ -0,0 +1,1495 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "limits.h" +#include "mintopo.hpp" +#include "mintopotables.hpp" +#define NTSTRSAFE_LIB //for Windows 2000 compatibility +#include "NtStrsafe.h" + +#pragma code_seg("PAGE") + +NTSTATUS CreateMiniportTopologyCMI(PUNKNOWN* Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) +{ + PAGED_CODE(); + ASSERT(Unknown); + STD_CREATE_BODY_(CCMITopology,Unknown,UnknownOuter,PoolType,PMINIPORTTOPOLOGY); +} + +STDMETHODIMP CCMITopology::NonDelegatingQueryInterface(REFIID Interface, PVOID* Object) +{ + PAGED_CODE(); + ASSERT(Object); + DBGPRINT(("CCMITopology::NonDelegatingQueryInterface")); + + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { + *Object = PVOID(PUNKNOWN(PMINIPORTTOPOLOGY(this))); + } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) { + *Object = PVOID(PMINIPORT(this)); + } else if (IsEqualGUIDAligned(Interface,IID_IMiniportTopology)) { + *Object = PVOID(PMINIPORTTOPOLOGY(this)); + } else if (IsEqualGUIDAligned (Interface, IID_ICMITopolgy)) { + *Object = (PVOID)(PMINIPORTTOPOLOGY)this; + } else { + *Object = NULL; + } + + if (*Object) { + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +CCMITopology::~CCMITopology() +{ + PAGED_CODE(); + + DBGPRINT(("CCMITopology::~CCMITopology")); + + storeMixerSettingsToRegistry(); //or not. during system shutdown, this doesn't seem to work. + cm->TopoMiniport = NULL; + + if (CMIAdapter) { + CMIAdapter->Release(); + } +} + +STDMETHODIMP CCMITopology::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTTOPOLOGY Port) +{ + PAGED_CODE(); + ASSERT(UnknownAdapter); + ASSERT(Port); + DBGPRINT(("CCMITopology::Init")); + + NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *)&CMIAdapter); + + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("UnknownAdapter->QueryInterface() failed")); + return STATUS_INVALID_PARAMETER; + } + + CMIAdapter->resetMixer(); + auxVolumeRegister = CMIAdapter->readUInt8(REG_MIXER3); + micVolumeRegister = CMIAdapter->readUInt8(REG_MIXER2); + functrl1Register = 0; + chformatRegister = 0; + legacyRegister = 0; + miscctrlRegister = 0; + + cm = CMIAdapter->getCMI8738Info(); + cm->TopoMiniport = this; //this is not really nice + loadMixerSettingsFromRegistry(); + + return STATUS_SUCCESS; +} + +STDMETHODIMP CCMITopology::GetDescription(PPCFILTER_DESCRIPTOR* OutFilterDescriptor) +{ + PAGED_CODE(); + ASSERT(OutFilterDescriptor); + DBGPRINT(("CCMITopology::GetDescription")); + + *OutFilterDescriptor = &MiniportFilterDescriptor; + + return STATUS_SUCCESS; +} + +STDMETHODIMP CCMITopology::loadMixerSettingsFromRegistry() +{ + PAGED_CODE(); + DBGPRINT(("CCMITopology::loadMixerSettingsFromRegistry")); + + PREGISTRYKEY DriverKey; + PREGISTRYKEY SettingsKey; + UNICODE_STRING KeyName; + PCPROPERTY_REQUEST PropertyRequest; + PCPROPERTY_ITEM PropertyItem; + DWORD Channel; + PVOID KeyInfo; + ULONG ResultLength; + WCHAR buffer[128]; + + if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { + DBGPRINT(("CMIAdapter->getDeviceObject() failed")); + return STATUS_UNSUCCESSFUL; + } + + settingsLoaded = FALSE; + + NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); + + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("PcNewRegistryKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&KeyName, L"Settings"); + + ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("DriverKey->NewSubKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'dbrt'); + if(KeyInfo == NULL) { + DBGPRINT(("ExAllocatePoolWithTag() failed")); + return STATUS_UNSUCCESSFUL; + } + + PropertyRequest.MajorTarget = this; + PropertyRequest.Verb = KSPROPERTY_TYPE_SET; + PropertyRequest.Instance = &Channel; + PropertyRequest.InstanceSize = sizeof(DWORD); + PropertyRequest.Value = &(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->Data); + PropertyRequest.ValueSize = sizeof(DWORD); + PropertyRequest.PropertyItem = &PropertyItem; + + for (int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) { + PropertyRequest.Node = i; + + Channel = CHAN_LEFT; + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); + if (NT_SUCCESS(ntStatus)) { + if(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->DataLength == sizeof(DWORD)) { + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) { + PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + PropertyHandler_Level(&PropertyRequest); + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) { + PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; + PropertyHandler_OnOff(&PropertyRequest); + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + PropertyHandler_OnOff(&PropertyRequest); + } + } + } else { + // default values + if (i == KSNODE_TOPO_IEC_OUT) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + *(PBOOL(PropertyRequest.Value)) = true; + PropertyHandler_OnOff(&PropertyRequest); + } + if (i == KSNODE_TOPO_WAVEOUT_MUTE_IN) { + PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; + *(PBOOL(PropertyRequest.Value)) = true; + PropertyHandler_OnOff(&PropertyRequest); + } + if (i == KSNODE_TOPO_CENTER2MIC) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + *(PBOOL(PropertyRequest.Value)) = false; + PropertyHandler_OnOff(&PropertyRequest); + } + } + + Channel = CHAN_RIGHT; + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); + if (NT_SUCCESS(ntStatus)) { + if(PKEY_VALUE_PARTIAL_INFORMATION(KeyInfo)->DataLength == sizeof(DWORD)) { + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) { + PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + PropertyHandler_Level(&PropertyRequest); + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) { + PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; + PropertyHandler_OnOff(&PropertyRequest); + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + PropertyHandler_OnOff(&PropertyRequest); + } + } + } else { + if (i == KSNODE_TOPO_WAVEOUT_MUTE_IN) { + PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; + *(PBOOL(PropertyRequest.Value)) = true; + PropertyHandler_OnOff(&PropertyRequest); + } + } + + } + RtlInitUnicodeString(&KeyName, L"FormatMask"); + ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); + if (NT_SUCCESS (ntStatus)) { + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; + if (PartialInfo->DataLength == sizeof(DWORD)) { + cm->formatMask = (*(PLONG)PartialInfo->Data); + } + } else { + cm->formatMask = 0xFFFFFFFF; + } + + ExFreePoolWithTag (KeyInfo,'dbrt'); + + SettingsKey->Release(); + DriverKey->Release(); + + settingsLoaded = TRUE; + + return STATUS_SUCCESS; +} + +STDMETHODIMP CCMITopology::storeMixerSettingsToRegistry() +{ + PAGED_CODE(); + DBGPRINT(("CCMITopology::storeMixerSettingsToRegistry")); + + PREGISTRYKEY DriverKey; + PREGISTRYKEY SettingsKey; + UNICODE_STRING KeyName; + PCPROPERTY_REQUEST PropertyRequest; + PCPROPERTY_ITEM PropertyItem; + DWORD Value,Channel; + WCHAR buffer[128]; + + if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { + return STATUS_UNSUCCESSFUL; + } + + NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); + + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("PcNewRegistryKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&KeyName, L"Settings"); + + ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); + + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("DriverKey->NewSubKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + PropertyRequest.MajorTarget = this; + PropertyRequest.Verb = KSPROPERTY_TYPE_GET; + PropertyRequest.Instance = &Channel; + PropertyRequest.InstanceSize = sizeof(DWORD); + PropertyRequest.Value = &Value; + PropertyRequest.ValueSize = sizeof(DWORD); + PropertyRequest.PropertyItem = &PropertyItem; + + for (int i=0;i < SIZEOF_ARRAY(TopologyNodes); i++) { + PropertyRequest.Node = i; + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_VOLUME)) { + PropertyRequest.Node = i; + PropertyItem.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_LEFT; + ntStatus = PropertyHandler_Level(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_RIGHT; + ntStatus = PropertyHandler_Level(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_MUTE)) { + PropertyItem.Id = KSPROPERTY_AUDIO_MUTE; + PropertyHandler_OnOff(&PropertyRequest); + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_LEFT; + ntStatus = PropertyHandler_OnOff(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_RIGHT; + ntStatus = PropertyHandler_OnOff(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + } + if (IsEqualGUIDAligned(*(TopologyNodes[i].Type), KSNODETYPE_LOUDNESS)) { + PropertyItem.Id = KSPROPERTY_AUDIO_LOUDNESS; + PropertyHandler_OnOff(&PropertyRequest); + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dLeft", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_LEFT; + ntStatus = PropertyHandler_OnOff(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + + ntStatus = RtlStringCbPrintfW(buffer, sizeof(buffer), L"Node%dRight", i); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("RtlStringCbPrintfW() failed")); + } + RtlInitUnicodeString(&KeyName, buffer); + Channel = CHAN_RIGHT; + ntStatus = PropertyHandler_OnOff(&PropertyRequest); + if (NT_SUCCESS(ntStatus)) { + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + break; + } + } + } + } + Value = cm->formatMask; + RtlInitUnicodeString(&KeyName, L"FormatMask"); + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + } + + SettingsKey->Release(); + DriverKey->Release(); + + return STATUS_SUCCESS; +} + +STDMETHODIMP CCMITopology::loadMixerSettingsFromMemory() +{ + PAGED_CODE(); + DBGPRINT(("CCMITopology::loadMixerSettingsFromMemory")); + + CMIAdapter->resetMixer(); + CMIAdapter->loadSBMixerFromMemory(); + CMIAdapter->writeUInt8(REG_MIXER1, mixer1Register); + CMIAdapter->writeUInt8(REG_MIXER2, auxVolumeRegister); + CMIAdapter->writeUInt8(REG_MIXER3, micVolumeRegister); + CMIAdapter->writeUInt8(REG_MIXER4, mixer4Register); + + CMIAdapter->setUInt32Bit(REG_FUNCTRL1, functrl1Register); + CMIAdapter->setUInt32Bit(REG_CHFORMAT, chformatRegister); + CMIAdapter->setUInt32Bit(REG_LEGACY, legacyRegister); + CMIAdapter->setUInt32Bit(REG_MISCCTRL, miscctrlRegister); + + return STATUS_SUCCESS; +} + +STDMETHODIMP CCMITopology::storeMixerSettingsToMemory() +{ + PAGED_CODE(); + DBGPRINT(("CCMITopology::storeMixerSettingsToMemory")); + + mixer1Register = CMIAdapter->readUInt8(REG_MIXER1); + mixer4Register = CMIAdapter->readUInt8(REG_MIXER4); + functrl1Register = CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF ; + chformatRegister = CMIAdapter->readUInt32(REG_CHFORMAT) & (INV_SPDIFI1 | SEL_SPDIFI1 | POLVALID); + legacyRegister = CMIAdapter->readUInt32(REG_LEGACY) & (BASS2LINE | CENTER2LINE | EN_SPDCOPYRHT); + miscctrlRegister = CMIAdapter->readUInt32(REG_MISCCTRL) & (EN_SPDO5V | SEL_SPDIFI2); + + return STATUS_SUCCESS; +} + +static NTSTATUS PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_OnOff]")); + + CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); + + NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; + UInt8 data, mask, reg; + LONG channel; + + if (PropertyRequest->Node == ULONG(-1)) { + return ntStatus; + } + + if ( ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) || (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)) && (PropertyRequest->InstanceSize >= sizeof(LONG)) ) { + channel = *(PLONG(PropertyRequest->Instance)); + if (PropertyRequest->ValueSize >= sizeof(BOOL)) { + + if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MUTE) { + PBOOL Muted = PBOOL(PropertyRequest->Value); + switch (PropertyRequest->Node) { + + case KSNODE_TOPO_WAVEOUT_MUTE: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = (that->CMIAdapter->readUInt8(REG_MIXER1) & MUTE_WAVE); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, MUTE_WAVE); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, MUTE_WAVE); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_AUX_MUTE: + switch (channel) { + case CHAN_LEFT: mask = MUTE_AUX_L; break; + case CHAN_RIGHT: mask = MUTE_AUX_R; break; + default: return ntStatus; + } + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->micVolumeRegister & mask); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->micVolumeRegister &= ~mask; + } else { + that->micVolumeRegister |= mask; + } + that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister); + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_MICOUT_MUTE: + if (channel != CHAN_LEFT) { + return ntStatus; + } + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & EN_MIC); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, EN_MIC); + } else { + that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, EN_MIC); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_CD_MUTE: + switch (channel) { + case CHAN_LEFT: mask = EN_CD_L; break; + case CHAN_RIGHT: mask = EN_CD_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & mask); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, mask); + } else { + that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, mask); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_LINEIN_MUTE: + switch (channel) { + case CHAN_LEFT: mask = EN_LINEIN_L; break; + case CHAN_RIGHT: mask = EN_LINEIN_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(SBREG_OUTPUTCTRL) & mask); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(SBREG_OUTPUTCTRL, mask); + } else { + that->CMIAdapter->setMixerBit(SBREG_OUTPUTCTRL, mask); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_MIC_MUTE_IN: + if (channel != CHAN_LEFT) { + return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(SBREG_IN_CTRL_L) & EN_MIC); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(SBREG_IN_CTRL_L, EN_MIC); + that->CMIAdapter->clearMixerBit(SBREG_IN_CTRL_R, EN_MIC); + } else { + that->CMIAdapter->setMixerBit(SBREG_IN_CTRL_L, EN_MIC); + that->CMIAdapter->setMixerBit(SBREG_IN_CTRL_R, EN_MIC); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_CD_MUTE_IN: + switch (channel) { + case CHAN_LEFT: mask = EN_LINEIN_L; reg = EN_CD_L; break; + case CHAN_RIGHT: mask = EN_LINEIN_R; reg = EN_CD_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(reg) & mask); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(reg, mask); + } else { + that->CMIAdapter->setMixerBit(reg, mask); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_LINEIN_MUTE_IN: + switch (channel) { + case CHAN_LEFT: mask = EN_LINEIN_L; reg = SBREG_IN_CTRL_L; break; + case CHAN_RIGHT: mask = EN_LINEIN_R; reg = SBREG_IN_CTRL_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = !(that->CMIAdapter->readMixer(reg) & mask); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->CMIAdapter->clearMixerBit(reg, mask); + } else { + that->CMIAdapter->setMixerBit(reg, mask); + } + } + ntStatus = STATUS_SUCCESS; + break; + + + case KSNODE_TOPO_AUX_MUTE_IN: + switch (channel) { + case CHAN_LEFT: mask = MUTE_RAUX_L; break; + case CHAN_RIGHT: mask = MUTE_RAUX_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = (that->micVolumeRegister & mask) ; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->micVolumeRegister |= mask; + } else { + that->micVolumeRegister &= ~mask; + } + that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister); + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_WAVEOUT_MUTE_IN: + switch (channel) { + case CHAN_LEFT: mask = EN_WAVEIN_L; break; + case CHAN_RIGHT: mask = EN_WAVEIN_R; break; + default: return ntStatus; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { +// *Muted = !(that->CMIAdapter->readUInt8(REG_MIXER1) & mask); + *Muted = !(that->cm->enableSPDIFIn); + ntStatus = STATUS_SUCCESS; + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*Muted) { + that->cm->enableSPDIFIn = FALSE; + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, mask); + } else { + that->cm->enableSPDIFIn = TRUE; + that->CMIAdapter->setUInt8Bit(REG_MIXER1, mask); + } + ntStatus = STATUS_SUCCESS; + } + break; + + case KSNODE_TOPO_MASTER_MUTE_DUMMY: + channel = (1 << channel); + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Muted = that->masterMuteDummy & channel; + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Muted) { + that->masterMuteDummy |= channel; + } else { + that->masterMuteDummy &= ~channel; + } + } + ntStatus = STATUS_SUCCESS; + break; + } + } + + if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_LOUDNESS) { + PBOOL LoudnessOn = PBOOL(PropertyRequest->Value); + switch (PropertyRequest->Node) { + case KSNODE_TOPO_MICIN_LOUDNESS: + if (channel == CHAN_LEFT) { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { +// DBGPRINT(("setting mic boost: previous state %d, new state %d", (that->CMIAdapter->readMixer(SBREG_EXTENSION) & EN_MICBOOST), (*LoudnessOn))); + if (*LoudnessOn) { + that->CMIAdapter->setMixerBit(SBREG_EXTENSION, EN_MICBOOST); + } else { + that->CMIAdapter->clearMixerBit(SBREG_EXTENSION, EN_MICBOOST); + } + } + ntStatus = STATUS_SUCCESS; + } + break; + case KSNODE_TOPO_MICOUT_LOUDNESS: + if (channel == CHAN_LEFT) { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = !(that->CMIAdapter->readUInt8(REG_MIXER2) & DIS_MICGAIN); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*LoudnessOn) { + that->CMIAdapter->clearUInt8Bit(REG_MIXER2, DIS_MICGAIN); + } else { + that->CMIAdapter->setUInt8Bit(REG_MIXER2, DIS_MICGAIN); + } + } + ntStatus = STATUS_SUCCESS; + } + break; + case KSNODE_TOPO_IEC_5V: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & EN_SPDO5V); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO5V); + } else { + that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO5V); + } + } + ntStatus = STATUS_SUCCESS; + break; + case KSNODE_TOPO_IEC_OUT: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (that->cm) { + *LoudnessOn = that->cm->enableSPDIFOut; + } + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (that->cm) { + that->cm->enableSPDIFOut = (*LoudnessOn); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_INVERSE: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (that->cm->chipVersion <= 37) { + *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER4) & INV_SPDIFI1); + } else { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & INV_SPDIFI2); + } + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*LoudnessOn) { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->setUInt8Bit(REG_MIXER4, INV_SPDIFI1); + } else { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, INV_SPDIFI2); + } + } else { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->clearUInt8Bit(REG_MIXER4, INV_SPDIFI1); + } else { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, INV_SPDIFI2); + } + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_MONITOR: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC); + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_SELECT: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (that->cm->chipVersion <= 37) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & SEL_SPDIFI1); + } else { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & SEL_SPDIFI2); + } + } + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*LoudnessOn) { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1); + } else { + that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2); + } + } else { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1); + } else { + that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2); + } + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_XCHG_FB: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2FRONT); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2FRONT); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2FRONT); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_BASS2LINE: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & BASS2LINE); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, BASS2LINE); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, BASS2LINE); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_CENTER2LINE: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & CENTER2LINE); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, CENTER2LINE); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, CENTER2LINE); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_COPYRIGHT: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_LEGACY) & EN_SPDCOPYRHT); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_POLVALID: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & POLVALID); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, POLVALID); + } else { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, POLVALID); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_IEC_LOOP: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, LOOP_SPDF); + } else { + that->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, LOOP_SPDF); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_REAR2LINE: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2LINE); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2LINE); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2LINE); + } + } + ntStatus = STATUS_SUCCESS; + break; + + case KSNODE_TOPO_CENTER2MIC: + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *LoudnessOn = (that->CMIAdapter->readUInt8(REG_MIXER4) & CENTER2MIC) && (that->cm->chipVersion > 37); + } + if ((PropertyRequest->Verb & KSPROPERTY_TYPE_SET) && !(that->settingsLoaded) && (that->cm->chipVersion > 37)) { + if (*LoudnessOn) { + that->CMIAdapter->setUInt8Bit(REG_MIXER4, CENTER2MIC); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER4, CENTER2MIC); + } + } + ntStatus = STATUS_SUCCESS; + break; + } + } + + if ((NT_SUCCESS(ntStatus)) && (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)) { + PropertyRequest->ValueSize = sizeof(BOOL); + } + + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + bool supported = false; + if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_MUTE) { + switch (PropertyRequest->Node) { + case KSNODE_TOPO_CD_MUTE: + case KSNODE_TOPO_LINEIN_MUTE: + case KSNODE_TOPO_MICOUT_MUTE: + case KSNODE_TOPO_AUX_MUTE: + case KSNODE_TOPO_WAVEOUT_MUTE: + case KSNODE_TOPO_LINEIN_MUTE_IN: + case KSNODE_TOPO_MIC_MUTE_IN: + case KSNODE_TOPO_CD_MUTE_IN: + case KSNODE_TOPO_AUX_MUTE_IN: + case KSNODE_TOPO_WAVEOUT_MUTE_IN: + case KSNODE_TOPO_MASTER_MUTE_DUMMY: + supported = true; + } + } + + if (PropertyRequest->PropertyItem->Id == KSPROPERTY_AUDIO_LOUDNESS) { + switch (PropertyRequest->Node) { + case KSNODE_TOPO_MICIN_LOUDNESS: + case KSNODE_TOPO_MICOUT_LOUDNESS: + case KSNODE_TOPO_IEC_5V: + case KSNODE_TOPO_IEC_OUT: + case KSNODE_TOPO_IEC_INVERSE: + case KSNODE_TOPO_IEC_MONITOR: + case KSNODE_TOPO_IEC_SELECT: + case KSNODE_TOPO_XCHG_FB: + case KSNODE_TOPO_BASS2LINE: + case KSNODE_TOPO_CENTER2LINE: + case KSNODE_TOPO_IEC_COPYRIGHT: + case KSNODE_TOPO_IEC_POLVALID: + case KSNODE_TOPO_IEC_LOOP: + case KSNODE_TOPO_REAR2LINE: + supported = true; + } + if ((PropertyRequest->Node == KSNODE_TOPO_CENTER2MIC) && (that->cm->chipVersion > 37)) { + supported = true; + } + } + + if (supported) { + if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) { + PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + + PropDesc->AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT; + PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = VT_BOOL; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 0; + PropDesc->Reserved = 0; + + PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); + ntStatus = STATUS_SUCCESS; + } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + *AccessFlags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT; + + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } + } + } + + return ntStatus; +} + +static NTSTATUS BasicSupportHandler(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[BasicSupportHandler]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) { + PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + + PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET; + PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = VT_I4; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 1; + PropDesc->Reserved = 0; + + if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG))) { + PKSPROPERTY_MEMBERSHEADER Members = PKSPROPERTY_MEMBERSHEADER(PropDesc + 1); + + Members->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES; + Members->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG); + Members->MembersCount = 1; + Members->Flags = 0; + + PKSPROPERTY_STEPPING_LONG Range = PKSPROPERTY_STEPPING_LONG(Members + 1); + + for (int i=0;iNode) { + Range->Bounds.SignedMaximum = (VolTable[i].max << 16); + Range->Bounds.SignedMinimum = (VolTable[i].min << 16); + Range->SteppingDelta = (VolTable[i].step << 16); + ntStatus = STATUS_SUCCESS; + } + } + if (!NT_SUCCESS(ntStatus)) { + switch (PropertyRequest->Node) { + case KSNODE_TOPO_AUX_VOLUME: + Range->Bounds.SignedMaximum = 0; + Range->Bounds.SignedMinimum = (-60 << 16); + Range->SteppingDelta = (4 << 16); + ntStatus = STATUS_SUCCESS; + break; + case KSNODE_TOPO_MICIN_VOLUME: + Range->Bounds.SignedMaximum = 0; + Range->Bounds.SignedMinimum = (-56 << 16); + Range->SteppingDelta = (8 << 16); + ntStatus = STATUS_SUCCESS; + break; + } + } + Range->Reserved = 0; + + PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); + } else { + PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); + ntStatus = STATUS_SUCCESS; + } + } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET; + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } + + return ntStatus; +} + +static NTSTATUS PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_Level]")); + + CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); + NTSTATUS ntStatus = STATUS_INVALID_PARAMETER; + UInt32 channel; + UInt8 mixerValue; + + if ((PropertyRequest->Node == ULONG(-1)) || (PropertyRequest->Node >= KSNODE_TOPO_INVALID) || (PropertyRequest->PropertyItem->Id != KSPROPERTY_AUDIO_VOLUMELEVEL)) { + return ntStatus; + } + + if ( ((PropertyRequest->Verb & KSPROPERTY_TYPE_GET) || (PropertyRequest->Verb & KSPROPERTY_TYPE_SET)) && (PropertyRequest->InstanceSize >= sizeof(LONG)) ) { + + channel = *(PLONG(PropertyRequest->Instance)); + + if ((PropertyRequest->Node == KSNODE_TOPO_MICOUT_VOLUME) && (channel != CHAN_LEFT)) { + return STATUS_INVALID_PARAMETER; + } + + if ( ( (channel == CHAN_LEFT) || (channel == CHAN_RIGHT) ) && (PropertyRequest->ValueSize >= sizeof(LONG))) { + + PLONG Level = (PLONG)PropertyRequest->Value; + + for (int i=0;iNode) { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + + mixerValue = (that->CMIAdapter->readMixer(VolTable[i].reg+channel) >> VolTable[i].shift) & VolTable[i].mask; + *Level = that->NodeCache[(2*PropertyRequest->Node)+channel]; + + if (mixerValue != ((*Level >> (VolTable[i].dbshift+16))+VolTable[i].mask)) { + *Level = (mixerValue - VolTable[i].mask) << (16+VolTable[i].dbshift); + that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level; + } + } else + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Level <= (VolTable[i].min << 16)) { + mixerValue = 0; + that->NodeCache[(2*PropertyRequest->Node)+channel] = VolTable[i].min << 16; + } else + if (*Level >= (VolTable[i].max << 16)) { + mixerValue = VolTable[i].mask; + that->NodeCache[(2*PropertyRequest->Node)+channel] = VolTable[i].max << 16; + } else { + mixerValue = ((*Level >> (VolTable[i].dbshift+16)) + VolTable[i].mask) & VolTable[i].mask; + that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level; + } + that->CMIAdapter->writeMixer(VolTable[i].reg+channel, mixerValue << VolTable[i].shift); + } + ntStatus = STATUS_SUCCESS; + } + } + if (PropertyRequest->Node == KSNODE_TOPO_AUX_VOLUME) { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + mixerValue = that->auxVolumeRegister; + *Level = that->NodeCache[(2*PropertyRequest->Node)+channel]; + if (channel == CHAN_LEFT) { + mixerValue >>= 4; + } + mixerValue &= 0x0F; + if (mixerValue != ((*Level >> 18)+0x0F)) { + *Level = (mixerValue - 0x0F) << 18; + that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level; + } + } else + if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Level <= (-30 << 16)) { + mixerValue = 0; + that->NodeCache[(2*PropertyRequest->Node)+channel] = -30 << 16; + } else + if (*Level >= 0) { + mixerValue = 0x0F; + that->NodeCache[(2*PropertyRequest->Node)+channel] = 0; + } else { + mixerValue = ((*Level >> 18) + 0x0F) & 0x0F; + that->NodeCache[(2*PropertyRequest->Node)+channel] = *Level; + } + + if (channel == CHAN_RIGHT) { + that->auxVolumeRegister = (that->auxVolumeRegister & 0xF0) | mixerValue; + } else if (channel == CHAN_LEFT) { + that->auxVolumeRegister = (that->auxVolumeRegister & 0x0F) | (mixerValue << 4); + } + that->CMIAdapter->writeUInt8(REG_MIXER3, that->auxVolumeRegister); + } + ntStatus = STATUS_SUCCESS; + } + if ((PropertyRequest->Node == KSNODE_TOPO_MICIN_VOLUME) && (channel == CHAN_LEFT)) { + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *Level = that->NodeCache[(2*PropertyRequest->Node)]; + mixerValue = that->micVolumeRegister >> 1 & 0x7; + if (mixerValue != ((*Level >> 19)+0x07)) { + *Level = (mixerValue - 0x07) << 19; + that->NodeCache[(2*PropertyRequest->Node)] = *Level; + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*Level <= (-56 << 16)) { + mixerValue = 0; + that->NodeCache[(2*PropertyRequest->Node)] = -56 << 16; + } else if (*Level >= 0) { + mixerValue = 0x07; + that->NodeCache[(2*PropertyRequest->Node)] = 0; + } else { + mixerValue = ((*Level >> 19) + 0x07) & 0x07; + that->NodeCache[(2*PropertyRequest->Node)] = *Level; + } + that->micVolumeRegister &= ~(0x07 << 1); + that->micVolumeRegister |= mixerValue << 1; + that->CMIAdapter->writeUInt8(REG_MIXER2, that->micVolumeRegister); + } + ntStatus = STATUS_SUCCESS; + } + if ((NT_SUCCESS(ntStatus)) && (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)) { + PropertyRequest->ValueSize = sizeof(LONG); + } + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + switch(PropertyRequest->Node) { + case KSNODE_TOPO_LINEOUT_VOLUME: + case KSNODE_TOPO_WAVEOUT_VOLUME: + case KSNODE_TOPO_CD_VOLUME: + case KSNODE_TOPO_LINEIN_VOLUME: + case KSNODE_TOPO_MICOUT_VOLUME: + case KSNODE_TOPO_MICIN_VOLUME: + case KSNODE_TOPO_AUX_VOLUME: + ntStatus = BasicSupportHandler(PropertyRequest); + break; + } + } + + return ntStatus; +} + +static NTSTATUS PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_CpuResources]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + if (PropertyRequest->Node == (ULONG)-1) { + return ntStatus; + } + if (PropertyRequest->Node >= KSNODE_TOPO_INVALID) { + return ntStatus; + } + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (PropertyRequest->ValueSize >= sizeof(LONG)) { + *((PLONG)PropertyRequest->Value) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU; + + PropertyRequest->ValueSize = sizeof(LONG); + ntStatus = STATUS_SUCCESS; + } else { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + if (PropertyRequest->ValueSize >= (sizeof(KSPROPERTY_DESCRIPTION))) { + PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + + PropDesc->AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | + KSPROPERTY_TYPE_GET; + PropDesc->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = VT_I4; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 0; + PropDesc->Reserved = 0; + + PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); + ntStatus = STATUS_SUCCESS; + } else if (PropertyRequest->ValueSize >= sizeof(ULONG)) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } + } + + return ntStatus; +} + +NTSTATUS PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_ComponentId]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (PropertyRequest->ValueSize >= sizeof(KSCOMPONENTID)) { + PKSCOMPONENTID pComponentId = (PKSCOMPONENTID)PropertyRequest->Value; + + pComponentId->Manufacturer = MANUFACTURER_CM8738; + pComponentId->Product = PRODUCT_CM8738; + pComponentId->Component = COMPONENT_CM8738; + pComponentId->Name = GUID_NULL; + pComponentId->Version = CMIPCI_VERSION; + pComponentId->Revision = that->cm->chipVersion; + + PropertyRequest->ValueSize = sizeof(KSCOMPONENTID); + ntStatus = STATUS_SUCCESS; + } else if (PropertyRequest->ValueSize == 0) { + PropertyRequest->ValueSize = sizeof(KSCOMPONENTID); + ntStatus = STATUS_BUFFER_OVERFLOW; + } else { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + if (PropertyRequest->ValueSize >= sizeof(ULONG)) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET; + + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } else { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + } + + return ntStatus; +} + +NTSTATUS PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_Private]")); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + CCMITopology *that = (CCMITopology *) ((PMINIPORTTOPOLOGY) PropertyRequest->MajorTarget); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + if (PropertyRequest->PropertyItem->Id != KSPROPERTY_CMI_GET) { + return STATUS_INVALID_DEVICE_REQUEST; + } + + if (PropertyRequest->ValueSize == 0) { + PropertyRequest->ValueSize = sizeof(CMIDATA); + return STATUS_BUFFER_OVERFLOW; + } else if (PropertyRequest->ValueSize < sizeof (CMIDATA)) { + PropertyRequest->ValueSize = 0; + return STATUS_BUFFER_TOO_SMALL; + } + + CMIDATA* cmiData = (CMIDATA*)PropertyRequest->Value; +#ifdef WAVERT + RtlStringCbPrintfA(cmiData->driverVersion, sizeof(cmiData->driverVersion), CMIVERSION "-WaveRT"); +#else + RtlStringCbPrintfA(cmiData->driverVersion, sizeof(cmiData->driverVersion), CMIVERSION); +#endif + cmiData->hardwareRevision = that->cm->chipVersion; + cmiData->maxChannels = that->cm->maxChannels; + cmiData->IOBase = (USHORT)that->cm->IOBase; + cmiData->MPUBase = (USHORT)that->cm->MPUBase; + cmiData->enableSPDO = that->cm->enableSPDIFOut; + cmiData->enableSPDI = that->cm->enableSPDIFIn; + cmiData->formatMask = that->cm->formatMask; + cmiData->exchangeFrontBack = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2FRONT); + cmiData->enableSPDO5V = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & EN_SPDO5V); + cmiData->enablePCMDAC = (that->CMIAdapter->readUInt8(REG_MIXER1) & EN_SPDI2DAC); + cmiData->enableBass2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & BASS2LINE); + cmiData->enableCenter2Line = (that->CMIAdapter->readUInt32(REG_LEGACY) & CENTER2LINE); + cmiData->enableRear2Line = (that->CMIAdapter->readUInt8(REG_MIXER1) & REAR2LINE); + cmiData->enableCenter2Mic = (that->CMIAdapter->readUInt8(REG_MIXER4) & CENTER2MIC) && (that->cm->chipVersion > 37); + cmiData->enableSPDOCopyright = (that->CMIAdapter->readUInt32(REG_LEGACY) & EN_SPDCOPYRHT); + cmiData->invertValidBitSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & POLVALID); + cmiData->loopSPDI = (that->CMIAdapter->readUInt32(REG_FUNCTRL1) & LOOP_SPDF); + if (that->cm->chipVersion <= 37) { + cmiData->select2ndSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & SEL_SPDIFI1); + cmiData->invertPhaseSPDI = (that->CMIAdapter->readUInt8(REG_MIXER4) & INV_SPDIFI1); + } else { + cmiData->select2ndSPDI = (that->CMIAdapter->readUInt32(REG_MISCCTRL) & SEL_SPDIFI2); + cmiData->invertPhaseSPDI = (that->CMIAdapter->readUInt32(REG_CHFORMAT) & INV_SPDIFI2); + } + + PropertyRequest->ValueSize = sizeof(CMIDATA); + ntStatus = STATUS_SUCCESS; + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (PropertyRequest->PropertyItem->Id != KSPROPERTY_CMI_SET) { + return STATUS_INVALID_DEVICE_REQUEST; + } + + if (PropertyRequest->ValueSize == 0) { + PropertyRequest->ValueSize = sizeof(CMIDATA); + return STATUS_BUFFER_OVERFLOW; + } else if (PropertyRequest->ValueSize < sizeof (CMIDATA)) { + PropertyRequest->ValueSize = 0; + return STATUS_BUFFER_TOO_SMALL; + } + CMIDATA* cmiData = (CMIDATA*)PropertyRequest->Value; + that->cm->enableSPDIFIn = cmiData->enableSPDI; + that->cm->enableSPDIFOut = cmiData->enableSPDO; + that->cm->formatMask = cmiData->formatMask; + + if (cmiData->enableSPDI) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_WAVEIN_L | EN_WAVEIN_R); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_WAVEIN_L | EN_WAVEIN_R); + } + + if (cmiData->exchangeFrontBack) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2FRONT); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2FRONT); + } + if (cmiData->enableSPDO5V) { + that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO5V); + } else { + that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO5V); + } + if (cmiData->enablePCMDAC) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } + if (cmiData->enableBass2Line) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, BASS2LINE); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, BASS2LINE); + } + if (cmiData->enableCenter2Line) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, CENTER2LINE); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, CENTER2LINE); + } + if (cmiData->enableRear2Line) { + that->CMIAdapter->setUInt8Bit(REG_MIXER1, REAR2LINE); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER1, REAR2LINE); + } + if (that->cm->chipVersion > 37) { + if (cmiData->enableCenter2Mic) { + that->CMIAdapter->setUInt8Bit(REG_MIXER4, CENTER2MIC); + } else { + that->CMIAdapter->clearUInt8Bit(REG_MIXER4, CENTER2MIC); + } + } + if (cmiData->enableSPDOCopyright) { + that->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT); + } else { + that->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDCOPYRHT); + } + if (cmiData->invertValidBitSPDI) { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, POLVALID); + } else { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, POLVALID); + } + if (cmiData->loopSPDI) { + that->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, LOOP_SPDF); + } else { + that->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, LOOP_SPDF); + } + if (cmiData->select2ndSPDI) { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1); + } else { + that->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2); + } + } else { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SEL_SPDIFI1); + } else { + that->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SEL_SPDIFI2); + } + } + if (cmiData->invertPhaseSPDI) { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->setUInt8Bit(REG_MIXER4, INV_SPDIFI1); + } else { + that->CMIAdapter->setUInt32Bit(REG_CHFORMAT, INV_SPDIFI2); + } + } else { + if (that->cm->chipVersion <= 37) { + that->CMIAdapter->clearUInt8Bit(REG_MIXER4, INV_SPDIFI1); + } else { + that->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, INV_SPDIFI2); + } + } + + that->storeMixerSettingsToRegistry(); + + ntStatus = STATUS_SUCCESS; + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + if (PropertyRequest->ValueSize >= sizeof(ULONG)) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET; + + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } else { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + } + + return ntStatus; +} diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp new file mode 100644 index 00000000000..5bec34fcc5b --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopo.hpp @@ -0,0 +1,93 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MINTOPO_HPP_ +#define _MINTOPO_HPP_ + +#include "common.hpp" +#include "property.h" + +class CCMITopology : public ICMITopology, + public CUnknown +{ +private: + PCMIADAPTER CMIAdapter; // Adapter common object. + CMI8738Info *cm; + UInt8 auxVolumeRegister, micVolumeRegister, mixer1Register, mixer4Register; + UInt32 functrl1Register, chformatRegister, legacyRegister, miscctrlRegister; + UInt32 NodeCache[2*KSNODE_TOPO_INVALID]; + UInt32 masterMuteDummy; + BOOLEAN settingsLoaded; // workaround for the fucking XP mixer + + NTSTATUS ProcessResources(PRESOURCELIST ResourceList); +public: + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CCMITopology); + ~CCMITopology(); + STDMETHODIMP_(NTSTATUS) loadMixerSettingsFromRegistry(); + STDMETHODIMP_(NTSTATUS) storeMixerSettingsToRegistry(); + + STDMETHODIMP_(NTSTATUS) loadMixerSettingsFromMemory(); + STDMETHODIMP_(NTSTATUS) storeMixerSettingsToMemory(); + + STDMETHODIMP_(NTSTATUS) GetDescription + ( + OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor + ); + STDMETHODIMP_(NTSTATUS) DataRangeIntersection + ( + IN ULONG PinId, + IN PKSDATARANGE DataRange, + IN PKSDATARANGE MatchingDataRange, + IN ULONG OutputBufferLength, + OUT PVOID ResultantFormat OPTIONAL, + OUT PULONG ResultantFormatLength + ) + { + return STATUS_NOT_IMPLEMENTED; + } + + // public methods + STDMETHODIMP_(NTSTATUS) Init + ( + IN PUNKNOWN UnknownAdapter, + IN PRESOURCELIST ResourceList, + IN PPORTTOPOLOGY Port + ); + + //friends + friend NTSTATUS PropertyHandler_OnOff(PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_Level(PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_CpuResources(PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_ComponentId(PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_Private(PPCPROPERTY_REQUEST PropertyRequest); + friend NTSTATUS PropertyHandler_Mux(PPCPROPERTY_REQUEST PropertyRequest); + + static NTSTATUS EventHandler(PPCEVENT_REQUEST EventRequest); +}; + +#endif //_MINTOPO_HPP_ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp new file mode 100644 index 00000000000..c97bb1e6368 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/mintopotables.hpp @@ -0,0 +1,537 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _TABLES_HPP_ +#define _TABLES_HPP_ + +#include "mintopo.hpp" + +#ifndef STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF +#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\ + DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) +DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF); +#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) +#endif + + +static KSDATARANGE PinDataRangesBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static PKSDATARANGE PinDataRangePointersBridge[] = +{ + &PinDataRangesBridge[0] +}; + +static KSDATARANGE WavePinDataRangesAC3Bridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static PKSDATARANGE WavePinDataRangePointersAC3Bridge[] = +{ + &WavePinDataRangesAC3Bridge[0] +}; + +static PCPIN_DESCRIPTOR MiniportPins[] = +{ + // WAVEOUT_SOURCE - 0 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSCATEGORY_AUDIO, // Category + NULL, // Name + 0 // Reserved + } + }, + + // SPDIF_IN_SOURCE - 1 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_SPDIF_INTERFACE, // Category + NULL, // Name + 0 // Reserved + } + }, + + // MIC_SOURCE - 2 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_MICROPHONE, // Category + NULL, // Name + 0 // Reserved + } + }, + + // CD_SOURCE - 3 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_CD_PLAYER, // Category + NULL, // Name + 0 // Reserved + } + }, + + // LINEIN_SOURCE - 4 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_LINE_CONNECTOR, // Category + NULL, // Name + 0 // Reserved + } + }, + + // AUX_SOURCE - 5 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_ANALOG_CONNECTOR, // Category + NULL, // Name + 0 // Reserved + } + }, + + // DAC_SOURCE - 6 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_ANALOG_CONNECTOR, // Category + &CMINAME_DAC, // Name + 0 // Reserved + } + }, + + // LINEOUT_DEST - 7 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSNODETYPE_SPEAKER, // Category + NULL, // Name + 0 // Reserved + } + }, + + // WAVEIN_DEST - 8 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(PinDataRangePointersBridge), // DataRangesCount + PinDataRangePointersBridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSCATEGORY_AUDIO, // Category + NULL, // Name + 0 // Reserved + } + }, + + // SPDIF_AC3_SOURCE - 9 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(WavePinDataRangePointersAC3Bridge), // DataRangesCount + WavePinDataRangePointersAC3Bridge, // DataRanges + KSPIN_DATAFLOW_IN, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + &KSCATEGORY_AUDIO, // Category + NULL, // Name + 0 // Reserved + } + }, + + // SPDIF_AC3_DEST - 10 + { + 0,0,0, // InstanceCount + NULL, // AutomationTable + { // KsPinDescriptor + 0, // InterfacesCount + NULL, // Interfaces + 0, // MediumsCount + NULL, // Mediums + SIZEOF_ARRAY(WavePinDataRangePointersAC3Bridge), // DataRangesCount + WavePinDataRangePointersAC3Bridge, // DataRanges + KSPIN_DATAFLOW_OUT, // DataFlow + KSPIN_COMMUNICATION_NONE, // Communication + NULL, // Category + NULL, // Name + 0 // Reserved + } + } +}; + +static PCPROPERTY_ITEM PropertiesVolume[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_VOLUMELEVEL, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_Level + }, + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_CPU_RESOURCES, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_CpuResources + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationVolume,PropertiesVolume); + +static PCPROPERTY_ITEM PropertiesLoudness[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_LOUDNESS, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_OnOff + }, + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_CPU_RESOURCES, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_CpuResources + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationLoudness,PropertiesLoudness); + +static PCPROPERTY_ITEM PropertiesMute[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_MUTE, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_OnOff + }, + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_CPU_RESOURCES, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_CpuResources + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMute,PropertiesMute); + +static PCPROPERTY_ITEM PropertiesFilter[] = +{ + { + &KSPROPSETID_General, + KSPROPERTY_GENERAL_COMPONENTID, + KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, + PropertyHandler_ComponentId + }, + { + &KSPROPSETID_CMI, + KSPROPERTY_CMI_GET, + KSPROPERTY_TYPE_GET, + PropertyHandler_Private + }, + { + &KSPROPSETID_CMI, + KSPROPERTY_CMI_SET, + KSPROPERTY_TYPE_SET, + PropertyHandler_Private + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationFilter,PropertiesFilter); + + +const VolumeTable VolTable[] = +{// Node Reg Mask Shift max min step dbshift + { KSNODE_TOPO_LINEOUT_VOLUME, 0x30, 0x1F, 3, 0, -62, 2, 1 }, + { KSNODE_TOPO_WAVEOUT_VOLUME, 0x32, 0x1F, 3, 0, -62, 2, 1 }, + { KSNODE_TOPO_CD_VOLUME, 0x36, 0x1F, 3, 0, -62, 2, 1 }, + { KSNODE_TOPO_LINEIN_VOLUME, 0x38, 0x1F, 3, 0, -62, 2, 1 }, + { KSNODE_TOPO_MICOUT_VOLUME, 0x3a, 0x1F, 3, 0, -62, 2, 1 } +}; + +static PCNODE_DESCRIPTOR TopologyNodes[] = +{// Flags AutomationTable Type Name +// 0 - WAVEOUT_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_WAVE_VOLUME }, +// 1 - WAVEOUT_MUTE + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_WAVE_MUTE }, +// 2 - MICOUT_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_MIC_VOLUME }, +// 3 - LINEOUT_MIX + { 0, NULL, &KSNODETYPE_SUM, NULL }, +// 4 - LINEOUT_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_MASTER_VOLUME }, +// 5 - WAVEIN_SUM + { 0, &AutomationMute, &KSNODETYPE_SUM, &KSAUDFNAME_RECORDING_SOURCE }, +// 6 - CD_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_CD_VOLUME }, +// 7 - LINEIN_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_LINE_IN_VOLUME }, +// 8 - AUX_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_AUX_VOLUME }, +// 9 - MICIN_VOLUME + { 0, &AutomationVolume, &KSNODETYPE_VOLUME, &KSAUDFNAME_MIC_IN_VOLUME }, +// 10 - MICIN_LOUDNESS + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &KSAUDFNAME_MICROPHONE_BOOST }, +// 11 - MICOUT_LOUDNESS + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &KSAUDFNAME_MICROPHONE_BOOST }, +// 12 - CD_MUTE + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_CD_MUTE }, +// 13 - LINEIN_MUTE + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_LINE_MUTE }, +// 14 - MICOUT_MUTE + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_MIC_MUTE }, +// 15 - AUX_MUTE + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_AUX_MUTE }, +// 16 - LINEIN_MUTE_IN + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_LINE_MUTE }, +// 17 - MIC_MUTE_IN + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_MIC_MUTE }, +// 18 - AUX_MUTE_IN + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_CD_MUTE }, +// 19 - CD_MUTE_IN + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_AUX_MUTE }, +// 20 - WAVEOUT_MUTE_IN + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_WAVE_MUTE }, +// 21 - IEC_5V + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_5V }, +// 22 - IEC_OUT + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_OUT }, +// 23 - IEC_INVERSE + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_INVERSE }, +// 24 - IEC_MONITOR + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_MONITOR }, +// 25 - IEC_SELECT + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_SELECT }, +// 26 - SPDIF_AC3_MUTE - the WDM is truly braindamaged + { 0, NULL, &KSNODETYPE_MUTE, NULL }, +// 27 - SPDIF_AC3_MUX + { 0, NULL, &KSNODETYPE_MUX, NULL }, +// 28 - XCHG_FB + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_XCHG_FB }, +// 29 - BASS2LINE + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_BASS2LINE }, +// 30 - CENTER2LINE + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_CENTER2LINE }, +// 31 - IEC_COPYRIGHT + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_COPYRIGHT }, +// 32 - IEC_POLVALID + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_POLVALID }, +// 33 - IEC_LOOP + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_IEC_LOOP }, +// 34 - REAR2LINE + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_REAR2LINE }, +// 35 - CENTER2MIC + { 0, &AutomationLoudness, &KSNODETYPE_LOUDNESS, &CMINAME_CENTER2MIC }, +// 36 - MASTER_MUTE_DUMMY + { 0, &AutomationMute, &KSNODETYPE_MUTE, &KSAUDFNAME_MASTER_MUTE } +}; + +static PCCONNECTION_DESCRIPTOR MiniportConnections[] = +{// FromNode, FromPin, ToNode, ToPin + { PCFILTER_NODE, PIN_WAVEOUT_SOURCE, KSNODE_TOPO_WAVEOUT_VOLUME, 1 }, + { KSNODE_TOPO_WAVEOUT_VOLUME, 0, KSNODE_TOPO_WAVEOUT_MUTE, 1 }, + { KSNODE_TOPO_WAVEOUT_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 1 }, + + { PCFILTER_NODE, PIN_CD_SOURCE, KSNODE_TOPO_CD_VOLUME, 1 }, + { KSNODE_TOPO_CD_VOLUME, 0, KSNODE_TOPO_CD_MUTE, 1 }, + { KSNODE_TOPO_CD_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 2 }, + + { PCFILTER_NODE, PIN_LINEIN_SOURCE, KSNODE_TOPO_LINEIN_VOLUME, 1 }, + { KSNODE_TOPO_LINEIN_VOLUME, 0, KSNODE_TOPO_LINEIN_MUTE, 1 }, + { KSNODE_TOPO_LINEIN_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 3 }, + + { PCFILTER_NODE, PIN_AUX_SOURCE, KSNODE_TOPO_AUX_VOLUME, 1 }, + { KSNODE_TOPO_AUX_VOLUME, 0, KSNODE_TOPO_AUX_MUTE, 1 }, + { KSNODE_TOPO_AUX_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 3 }, + + { PCFILTER_NODE, PIN_MIC_SOURCE, KSNODE_TOPO_MICOUT_LOUDNESS, 1 }, + { KSNODE_TOPO_MICOUT_LOUDNESS, 0, KSNODE_TOPO_MICOUT_VOLUME, 1 }, + { KSNODE_TOPO_MICOUT_VOLUME, 0, KSNODE_TOPO_MICOUT_MUTE, 1 }, + { KSNODE_TOPO_MICOUT_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 4 }, + + { PCFILTER_NODE, PIN_DAC_SOURCE, KSNODE_TOPO_IEC_MONITOR, 1 }, + { KSNODE_TOPO_IEC_MONITOR, 0, KSNODE_TOPO_BASS2LINE, 1 }, + { KSNODE_TOPO_BASS2LINE, 0, KSNODE_TOPO_CENTER2LINE, 1 }, + { KSNODE_TOPO_CENTER2LINE, 0, KSNODE_TOPO_REAR2LINE, 1 }, + { KSNODE_TOPO_REAR2LINE, 0, KSNODE_TOPO_CENTER2MIC, 1 }, + { KSNODE_TOPO_CENTER2MIC, 0, KSNODE_TOPO_XCHG_FB, 1 }, + { KSNODE_TOPO_XCHG_FB, 0, KSNODE_TOPO_WAVEOUT_VOLUME, 1 }, + { KSNODE_TOPO_WAVEOUT_VOLUME, 0, KSNODE_TOPO_WAVEOUT_MUTE, 1 }, + { KSNODE_TOPO_WAVEOUT_MUTE, 0, KSNODE_TOPO_LINEOUT_MIX, 5 }, + + { KSNODE_TOPO_LINEOUT_MIX, 0, KSNODE_TOPO_IEC_OUT, 1 }, + { KSNODE_TOPO_IEC_OUT, 0, KSNODE_TOPO_IEC_5V, 1 }, + { KSNODE_TOPO_IEC_5V, 0, KSNODE_TOPO_MASTER_MUTE_DUMMY, 1 }, + { KSNODE_TOPO_MASTER_MUTE_DUMMY, 0, KSNODE_TOPO_LINEOUT_VOLUME, 1 }, + { KSNODE_TOPO_LINEOUT_VOLUME, 0, PCFILTER_NODE, PIN_LINEOUT_DEST }, + + { PCFILTER_NODE, PIN_MIC_SOURCE, KSNODE_TOPO_MICIN_LOUDNESS, 1 }, + { KSNODE_TOPO_MICIN_LOUDNESS, 0, KSNODE_TOPO_MICIN_VOLUME, 1 }, + { KSNODE_TOPO_MICIN_VOLUME, 0, KSNODE_TOPO_MIC_MUTE_IN, 1 }, + { KSNODE_TOPO_MIC_MUTE_IN, 0, KSNODE_TOPO_WAVEIN_SUM, 1 }, + + { KSNODE_TOPO_LINEIN_VOLUME, 0, KSNODE_TOPO_LINEIN_MUTE_IN, 1 }, + { KSNODE_TOPO_LINEIN_MUTE_IN, 0, KSNODE_TOPO_WAVEIN_SUM, 2 }, + + { KSNODE_TOPO_CD_VOLUME, 0, KSNODE_TOPO_CD_MUTE_IN, 1 }, + { KSNODE_TOPO_CD_MUTE_IN, 0, KSNODE_TOPO_WAVEIN_SUM, 3 }, + + { KSNODE_TOPO_AUX_VOLUME, 0, KSNODE_TOPO_AUX_MUTE_IN, 1 }, + { KSNODE_TOPO_AUX_MUTE_IN, 0, KSNODE_TOPO_WAVEIN_SUM, 4 }, + + { PCFILTER_NODE, PIN_SPDIFIN_SOURCE, KSNODE_TOPO_WAVEOUT_MUTE_IN, 1 }, + { KSNODE_TOPO_WAVEOUT_MUTE_IN, 0, KSNODE_TOPO_IEC_INVERSE, 1 }, + { KSNODE_TOPO_IEC_INVERSE, 0, KSNODE_TOPO_IEC_SELECT, 1 }, + { KSNODE_TOPO_IEC_SELECT, 0, KSNODE_TOPO_IEC_COPYRIGHT, 1 }, + { KSNODE_TOPO_IEC_COPYRIGHT, 0, KSNODE_TOPO_IEC_POLVALID, 1 }, + { KSNODE_TOPO_IEC_POLVALID, 0, KSNODE_TOPO_IEC_LOOP, 1 }, + { KSNODE_TOPO_IEC_LOOP, 0, KSNODE_TOPO_WAVEIN_SUM, 5 }, + + { KSNODE_TOPO_WAVEIN_SUM, 0, PCFILTER_NODE, PIN_WAVEIN_DEST }, + + { PCFILTER_NODE, PIN_SPDIF_AC3_SOURCE, KSNODE_TOPO_SPDIF_AC3_MUTE, 1 }, + { KSNODE_TOPO_SPDIF_AC3_MUTE, 0, KSNODE_TOPO_SPDIF_AC3_MUX, 1 }, + { KSNODE_TOPO_SPDIF_AC3_MUX, 0, PCFILTER_NODE, PIN_SPDIF_AC3_DEST }, +}; + + +static PCFILTER_DESCRIPTOR MiniportFilterDescriptor = +{ + 0, // Version + &AutomationFilter, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(MiniportPins), // PinCount + MiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(TopologyNodes), // NodeCount + TopologyNodes, // Nodes + SIZEOF_ARRAY(MiniportConnections), // ConnectionCount + MiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories: NULL->use default (audio, render, capture) +}; + + +#endif diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp new file mode 100644 index 00000000000..a2415b94101 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.cpp @@ -0,0 +1,1668 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "minwave.hpp" +#include "minwavetables.hpp" +#include "ntddk.h" + +#pragma code_seg("PAGE") + +NTSTATUS CreateMiniportWaveCMI(PUNKNOWN *Unknown, REFCLSID, PUNKNOWN UnknownOuter, POOL_TYPE PoolType) +{ + PAGED_CODE(); + ASSERT(Unknown); +#ifdef WAVERT + STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVERT); +#else + STD_CREATE_BODY_(CMiniportWaveCMI,Unknown,UnknownOuter,PoolType,PMINIPORTWAVECYCLIC); +#endif +} + +NTSTATUS CMiniportWaveCMI::processResources(PRESOURCELIST resourceList) +{ + PAGED_CODE(); + ASSERT (resourceList); + DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList)); + + if (resourceList->NumberOfInterrupts() < 1) { + DBGPRINT(("Unknown configuration for wave miniport")); + return STATUS_DEVICE_CONFIGURATION_ERROR; + } + return STATUS_SUCCESS; +} + +#ifndef WAVERT +NTSTATUS CMiniportWaveCMI::newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength) +{ + PAGED_CODE(); + ASSERT(dmaChannel); + DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel)); + + NTSTATUS ntStatus; + + ntStatus = Port->NewMasterDmaChannel(dmaChannel, NULL, NULL, bufferLength, TRUE, FALSE, (DMA_WIDTH)(-1), (DMA_SPEED)(-1)); + if (NT_SUCCESS(ntStatus)) { + ULONG lDMABufferLength = bufferLength; + do { + ntStatus = (*dmaChannel)->AllocateBuffer(lDMABufferLength,NULL); + lDMABufferLength >>= 1; + } while (!NT_SUCCESS(ntStatus) && (lDMABufferLength > (PAGE_SIZE / 2))); + } + return ntStatus; +} +#endif + +//generic crap +STDMETHODIMP CMiniportWaveCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object) +{ + PAGED_CODE(); + ASSERT(Object); + DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface")); + + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { +#ifdef WAVERT + *Object = PVOID(PUNKNOWN(PMINIPORTWAVERT(this))); +#else + *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this))); +#endif + } else if (IsEqualGUIDAligned(Interface,IID_IMiniport)) { + *Object = PVOID(PMINIPORT(this)); +#ifdef WAVERT + } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRT)) { + *Object = PVOID(PMINIPORTWAVERT(this)); +#else + } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclic)) { + *Object = PVOID(PMINIPORTWAVECYCLIC(this)); +#endif + } else { + *Object = NULL; + } + + if (*Object) { + // We reference the interface for the caller. + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +CMiniportWaveCMI::~CMiniportWaveCMI(void) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this)); + + storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work. + + if (CMIAdapter) { + CMIAdapter->Release(); + CMIAdapter = NULL; + } + + for (int i=0;i<3;i++) { +#ifndef WAVERT + if (DMAChannel[i]) { + DMAChannel[i]->Release(); + DMAChannel[i] = NULL; + } +#endif + if (isStreamRunning[i]) { + isStreamRunning[i] = false; + stream[i]->Release(); + stream[i] = NULL; + } + } + + if (Port) { + Port->Release(); + Port = NULL; + } +} + +#ifdef WAVERT +STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVERT Port_) +#else +STDMETHODIMP CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter, PRESOURCELIST ResourceList, PPORTWAVECYCLIC Port_) +#endif +{ + PAGED_CODE(); + + ASSERT(UnknownAdapter); + ASSERT(ResourceList); + ASSERT(Port_); + + DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter, ResourceList, Port_)); + + Port = Port_; + Port->AddRef(); + + NTSTATUS ntStatus = UnknownAdapter->QueryInterface(IID_ICMIAdapter, (PVOID *) &CMIAdapter); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("QueryInterface(CMIAdapter) failed")); + return ntStatus; + } + + //check for Vista, set the AC3 stuff accordingly + if (IoIsWdmVersionAvailable(0x06,0x00)) { + WavePinDataRangesAC3Stream[1].MinimumSampleFrequency = MIN_SAMPLE_RATE; + WavePinDataRangesAC3Stream[1].MaximumSampleFrequency = MAX_SAMPLE_RATE; + WavePinDataRangesAC3Stream[1].DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WavePinDataRangesAC3Stream[1].DataRange.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + } + + cm = CMIAdapter->getCMI8738Info(); + cm->regFUNCTRL0 = 0; + cm->WaveMiniport = this; + + loadChannelConfigFromRegistry(); + + for (int i=0;i<3;i++) + { + isStreamRunning[i] = false; + +#ifndef WAVERT + ntStatus = newDMAChannel(&DMAChannel[i], MAXLEN_DMA_BUFFER); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("NewDmaChannel() failed")); + return ntStatus; + } +#endif + } + + KeInitializeMutex(&mutex, 1); + + return processResources(ResourceList); +} + +#ifdef WAVERT +STDMETHODIMP_(NTSTATUS) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor) +{ + PAGED_CODE(); + ASSERT(OutDeviceDescriptor); + DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor)); + + RtlZeroMemory(OutDeviceDescriptor, sizeof(DEVICE_DESCRIPTION)); + OutDeviceDescriptor->ScatterGather = false; + OutDeviceDescriptor->Master = true; + OutDeviceDescriptor->Dma32BitAddresses = true; + OutDeviceDescriptor->InterfaceType = PCIBus; + OutDeviceDescriptor->MaximumLength = MAXLEN_DMA_BUFFER-2; + + return STATUS_SUCCESS; +} +#endif + +STDMETHODIMP CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR *OutFilterDescriptor) +{ + PAGED_CODE(); + ASSERT(OutFilterDescriptor); + DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor)); + + *OutFilterDescriptor = &WaveMiniportFilterDescriptor; + + return STATUS_SUCCESS; +} + +NTSTATUS CMiniportWaveCMI::loadChannelConfigFromRegistry() +{ + PAGED_CODE(); + PREGISTRYKEY DriverKey; + PREGISTRYKEY SettingsKey; + UNICODE_STRING KeyName; + DWORD Value, ResultLength; + PVOID KeyInfo; + + DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()")); + + if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { + return STATUS_UNSUCCESSFUL; + } + + NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); + + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("PcNewRegistryKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&KeyName, L"Settings"); + + ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("DriverKey->NewSubKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + KeyInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), 'gnaa'); + if (KeyInfo) { + RtlInitUnicodeString(&KeyName, L"ChannelCount"); + ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); + if (NT_SUCCESS (ntStatus)) { + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; + if (PartialInfo->DataLength == sizeof(DWORD)) { + requestedChannelCount = (*(PLONG)PartialInfo->Data); + } + } else { + requestedChannelCount = 2; + } + + RtlInitUnicodeString(&KeyName, L"ChannelMask"); + ntStatus = SettingsKey->QueryValueKey(&KeyName, KeyValuePartialInformation, KeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ResultLength); + if (NT_SUCCESS (ntStatus)) { + PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; + if (PartialInfo->DataLength == sizeof(DWORD)) { + requestedChannelMask = (*(PLONG)PartialInfo->Data); + } + } else { + requestedChannelMask = KSAUDIO_SPEAKER_STEREO; + } + } + ExFreePoolWithTag(KeyInfo,'gnaa'); + + SettingsKey->Release(); + DriverKey->Release(); + + return STATUS_SUCCESS; +} + +NTSTATUS CMiniportWaveCMI::storeChannelConfigToRegistry() +{ + PAGED_CODE(); + PREGISTRYKEY DriverKey; + PREGISTRYKEY SettingsKey; + UNICODE_STRING KeyName; + DWORD Value; + DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()")); + + if ((!CMIAdapter) || (!(CMIAdapter->getDeviceObject()))) { + return STATUS_UNSUCCESSFUL; + } + + NTSTATUS ntStatus = PcNewRegistryKey(&DriverKey, NULL, DriverRegistryKey, KEY_ALL_ACCESS, CMIAdapter->getDeviceObject(), NULL, NULL, 0, NULL); + + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("PcNewRegistryKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&KeyName, L"Settings"); + + ntStatus = DriverKey->NewSubKey(&SettingsKey, NULL, KEY_ALL_ACCESS, &KeyName, REG_OPTION_NON_VOLATILE, NULL); + if(!NT_SUCCESS(ntStatus)) { + DBGPRINT(("DriverKey->NewSubKey() failed")); + return STATUS_UNSUCCESSFUL; + } + + Value = requestedChannelCount; + RtlInitUnicodeString(&KeyName, L"ChannelCount"); + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + } + Value = requestedChannelMask; + RtlInitUnicodeString(&KeyName, L"ChannelMask"); + ntStatus = SettingsKey->SetValueKey(&KeyName, REG_DWORD, PVOID(&Value), sizeof(DWORD)); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetValueKey() failed")); + } + + SettingsKey->Release(); + DriverKey->Release(); + + return STATUS_SUCCESS; +} + + +STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this)); + KSSTATE oldState[3]; + + for (int i=0;i<3;i++) { + if (isStreamRunning[i]) { + oldState[i] = stream[i]->state; + stream[i]->SetState(KSSTATE_STOP); + } + } + + if (cm->TopoMiniport) { + cm->TopoMiniport->loadMixerSettingsFromMemory(); + } + + for (int i=0;i<3;i++) { + if (isStreamRunning[i]) { + stream[i]->prepareStream(); + stream[i]->SetState(KSSTATE_ACQUIRE); + stream[i]->SetState(oldState[i]); + } + } +} + +STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this)); + + if (cm->TopoMiniport) { + cm->TopoMiniport->storeMixerSettingsToMemory(); + } + +} + + +NTSTATUS CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3) +{ + PAGED_CODE(); + ASSERT(sampleRate); + DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate, multiChan, AC3)); + + if (multiChan) { + switch (sampleRate) { + case 44100: if (cm->formatMask & FMT_441_MULTI_PCM) return STATUS_SUCCESS; break; + case 48000: if (cm->formatMask & FMT_480_MULTI_PCM) return STATUS_SUCCESS; break; + case 88200: if (cm->formatMask & FMT_882_MULTI_PCM) return STATUS_SUCCESS; break; + case 96000: if (cm->formatMask & FMT_960_MULTI_PCM) return STATUS_SUCCESS; break; + } + return STATUS_INVALID_PARAMETER; + } + if (AC3) { + switch (sampleRate) { + case 44100: if (cm->formatMask & FMT_441_DOLBY) return STATUS_SUCCESS; break; + case 48000: if (cm->formatMask & FMT_480_DOLBY) return STATUS_SUCCESS; break; + case 88200: if (cm->formatMask & FMT_882_DOLBY) return STATUS_SUCCESS; break; + case 96000: if (cm->formatMask & FMT_960_DOLBY) return STATUS_SUCCESS; break; + } + return STATUS_INVALID_PARAMETER; + } + switch (sampleRate) { + case 44100: if (cm->formatMask & FMT_441_PCM) return STATUS_SUCCESS; break; + case 48000: if (cm->formatMask & FMT_480_PCM) return STATUS_SUCCESS; break; + case 88200: if (cm->formatMask & FMT_882_PCM) return STATUS_SUCCESS; break; + case 96000: if (cm->formatMask & FMT_960_PCM) return STATUS_SUCCESS; break; + } + return STATUS_INVALID_PARAMETER; +} + +NTSTATUS CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture) +{ + PAGED_CODE(); + ASSERT(format); + DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format, PinID, capture)); + + PWAVEFORMATEX waveFormat = PWAVEFORMATEX(format + 1); + DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat->nChannels, waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, PinID, cm->formatMask)); + +//WaveFormatEx + if ( ( format->FormatSize >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) + && IsEqualGUIDAligned(format->MajorFormat,KSDATAFORMAT_TYPE_AUDIO) + && IsEqualGUIDAligned(format->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ) { + switch (EXTRACT_WAVEFORMATEX_ID(&format->SubFormat)) { + case WAVE_FORMAT_PCM: + if ((PinID != PIN_WAVE_RENDER_SINK) && (PinID != PIN_WAVE_CAPTURE_SOURCE) && (PinID != -1)) { + if ((PinID == PIN_WAVE_AC3_RENDER_SINK) && !IoIsWdmVersionAvailable(6,0)) { + return STATUS_INVALID_PARAMETER; + } + } + + if ( ((waveFormat->wBitsPerSample == 16) || (waveFormat->wBitsPerSample == 24)) + && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000) || (waveFormat->nSamplesPerSec == 88200) || (waveFormat->nSamplesPerSec == 96000)) + && (waveFormat->nChannels == 2) ) { + if ((capture) && (waveFormat->nSamplesPerSec > 48000) ) { + return STATUS_INVALID_PARAMETER; + } + return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, FALSE); + } + if ( (waveFormat->wBitsPerSample == 16) + && ((waveFormat->nChannels >= 4) && (waveFormat->nChannels <= cm->maxChannels)) + && ((waveFormat->nSamplesPerSec == 44100) || (waveFormat->nSamplesPerSec == 48000)) ) { +#if OUT_CHANNEL == 1 + if ((PinID == PIN_WAVE_RENDER_SINK) || (PinID == -1)) { + return isFormatAllowed(waveFormat->nSamplesPerSec, TRUE, FALSE); + } +#else + return STATUS_INVALID_PARAMETER; +#endif + } + break; + case WAVE_FORMAT_DOLBY_AC3_SPDIF: + if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != -1)) { + return STATUS_INVALID_PARAMETER; + } + if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3)) + && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_AC3) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_AC3)) + && (waveFormat->nChannels == MAX_CHANNELS_AC3) ) { + return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE); + } + break; + } + } + + return STATUS_INVALID_PARAMETER; +} + +// Tests a data range intersection +STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength)); + + if (PinId == PIN_WAVE_AC3_RENDER_SINK) { + bool isAC3Pin = true; + // Under Windows 2000 and XP, the client's DataRange should be AC3 only. + // The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed. + + if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) + && !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { + return STATUS_NO_MATCH; + } + + + if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) + && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { + // check for Vista + isAC3Pin = false; + if (IoIsWdmVersionAvailable(0x06,0x00)) { + if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) + && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { + return STATUS_NO_MATCH; + } + } else { + return STATUS_NO_MATCH; + } + } + + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + || IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); + } else + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND); + } else { + return STATUS_NO_MATCH; + } + + // Validate return buffer size, if the request is only for the + // size of the resultant structure, return it now. + if (!OutputBufferLength) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); + return STATUS_BUFFER_OVERFLOW; + } else + if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) { + return STATUS_BUFFER_TOO_SMALL; + } + + PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat; + PWAVEFORMATEX pWaveFormatEx; + + // Return the best (only) available format. + resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength; + resultantFormatWFX->DataFormat.Flags = 0; + resultantFormatWFX->DataFormat.SampleSize = 4; // must match nBlockAlign + resultantFormatWFX->DataFormat.Reserved = 0; + + resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_DOLBY_AC3_SPDIF); + + // Extra space for the DSound specifier + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + + PKSDATAFORMAT_DSOUND resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat; + + resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND; + + // DSound format capabilities are not expressed + // this way in KS, so we express no capabilities. + resultantFormatDSound->BufferDesc.Flags = 0 ; + resultantFormatDSound->BufferDesc.Control = 0 ; + + pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx; + } else { + // WAVEFORMATEX or WILDCARD (WAVEFORMATEX) + resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + + pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1); + } + + pWaveFormatEx->nChannels = 2; + pWaveFormatEx->wBitsPerSample = 16; // SPDIF + pWaveFormatEx->cbSize = 0; + if (isAC3Pin) { + pWaveFormatEx->wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; + pWaveFormatEx->nSamplesPerSec = 48000; + } else { + pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM; + pWaveFormatEx->nSamplesPerSec = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE); + } + pWaveFormatEx->nBlockAlign = pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample / 8; + pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nSamplesPerSec * pWaveFormatEx->nBlockAlign; + + return STATUS_SUCCESS; + } + if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) { + + if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) && + !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) { + return STATUS_NO_MATCH; + } + + if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) && + !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) { + return STATUS_NO_MATCH; + } + + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) || + IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); + } else + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND); + } else { + return STATUS_NO_MATCH; + } + + + ULONG sampleRate = 0; + ULONG nMaxChannels = min(((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, requestedChannelCount); + + // check for Vista + if (IoIsWdmVersionAvailable(6,0) && (PinId == PIN_WAVE_RENDER_SINK)) { + nMaxChannels = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels; + } + if (nMaxChannels & 0x01) { + nMaxChannels--; + } + if (!nMaxChannels) { + return STATUS_NO_MATCH; + } + + if (isStreamRunning[PCM_OUT_STREAM]) { + sampleRate = stream[PCM_OUT_STREAM]->currentSampleRate; + } else + if (isStreamRunning[PCM_IN_STREAM]) { + sampleRate = stream[PCM_IN_STREAM]->currentSampleRate; + } + if (sampleRate == 0) { + if ((nMaxChannels > 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE_MULTI)) { + sampleRate = MAX_SAMPLE_RATE_MULTI; + } else + if ((nMaxChannels == 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE)) { + sampleRate = MAX_SAMPLE_RATE; + } else { + sampleRate = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency; + } + } + + if ((((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency < sampleRate) + || (((PKSDATARANGE_AUDIO)ClientDataRange)->MinimumSampleFrequency > sampleRate)) { + return STATUS_NO_MATCH; + } + + if (PinId == PIN_WAVE_RENDER_SINK) { + if (!OutputBufferLength) { + *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); + return STATUS_BUFFER_OVERFLOW; + } else + if (OutputBufferLength < sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)) { + return STATUS_BUFFER_TOO_SMALL; + } + + if (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels < 2) { + DBGPRINT(("[[DataRangeIntersection] mono format not supported")); + return STATUS_NO_MATCH; + } + + PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1); + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + return STATUS_NOT_SUPPORTED; + } + *(PKSDATAFORMAT)ResultantFormat = *MyDataRange; + ((PKSDATAFORMAT)ResultantFormat)->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); + + + WaveFormat->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + WaveFormat->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WaveFormat->Format.nChannels = (WORD)nMaxChannels; + WaveFormat->Format.wBitsPerSample = 16; + WaveFormat->Format.nBlockAlign = (WaveFormat->Format.wBitsPerSample >> 3) * WaveFormat->Format.nChannels; + WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign; + WaveFormat->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + WaveFormat->Format.nSamplesPerSec = sampleRate; + WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample; + switch (nMaxChannels) { + case 8: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break; + case 6: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break; + case 4: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD; break; + case 2: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO; break; + } + if (nMaxChannels == requestedChannelCount) { + WaveFormat->dwChannelMask = requestedChannelMask; + } + ((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign; + + *ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX); + DBGPRINT(("[DataRangeIntersection] MultiChannel Renderer: SampleRate: %d, ClientDataRange->MaxChans: %d, Channels: %d, BitPerSample: %d, BlockAlign: %d, AvgBytesPerSec: %d, ChannelMask: %08X", WaveFormat->Format.nSamplesPerSec, ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, WaveFormat->Format.nChannels, WaveFormat->Format.wBitsPerSample, WaveFormat->Format.nBlockAlign, WaveFormat->Format.nAvgBytesPerSec, WaveFormat->dwChannelMask)); + } else + if (PinId == PIN_WAVE_CAPTURE_SINK) { + PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX; + PWAVEFORMATEX pWaveFormatEx; + + if (!OutputBufferLength) { + *ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX); + return STATUS_BUFFER_OVERFLOW; + } else + if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) { + return STATUS_BUFFER_TOO_SMALL; + } + + if (nMaxChannels > 2) { + nMaxChannels = 2; + } + + resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat; + resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength; + resultantFormatWFX->DataFormat.Flags = 0; + resultantFormatWFX->DataFormat.SampleSize = 4; + resultantFormatWFX->DataFormat.Reserved = 0; + resultantFormatWFX->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM); + + if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) { + PKSDATAFORMAT_DSOUND resultantFormatDSound; + resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat; + resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND; + resultantFormatDSound->BufferDesc.Flags = 0 ; + resultantFormatDSound->BufferDesc.Control = 0 ; + pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx; + } else { + resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1); + } + pWaveFormatEx->wFormatTag = WAVE_FORMAT_PCM; + pWaveFormatEx->nChannels = nMaxChannels; + pWaveFormatEx->nSamplesPerSec = sampleRate; + pWaveFormatEx->wBitsPerSample = 16; + pWaveFormatEx->cbSize = 0; + pWaveFormatEx->nBlockAlign = 4; + pWaveFormatEx->nAvgBytesPerSec = 192000; + } + return STATUS_SUCCESS; + } + return STATUS_NO_MATCH; +} + +//from IMiniportWaveCyclic::NewStream() +#ifdef WAVERT +STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORTWAVERTSTREAM OuterUnknown, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat) +#else +STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup) +#endif +{ + PAGED_CODE(); + ASSERT(OutStream); + ASSERT(DataFormat); +#ifdef WAVERT + DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat)); +#else + ASSERT(OutDmaChannel); + ASSERT(OutServiceGroup); + DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup)); +#endif + + NTSTATUS ntStatus = STATUS_SUCCESS; + PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1); + UInt32 streamIndex = PCM_OUT_STREAM; + + ntStatus = validateFormat(DataFormat, PinID, Capture); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("invalid stream format")); + return STATUS_UNSUCCESSFUL; + } + + CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + + if (Capture) { + streamIndex = PCM_IN_STREAM; + } else if (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) { + streamIndex = AC3_OUT_STREAM; + } + + // make sure the hardware is not already in use + if (isStreamRunning[streamIndex]) { + DBGPRINT(("Stream %d running, exiting...", streamIndex)); + return STATUS_UNSUCCESSFUL; + } + if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { + stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3); + } + if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) { + return STATUS_UNSUCCESSFUL; + } + + DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex, + waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels, + (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)))); + + // the DAC and ADC can only run at the same sample rate simultaneously + if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) { + if (waveFormat->nSamplesPerSec != stream[PCM_OUT_STREAM]->currentSampleRate) { + return STATUS_UNSUCCESSFUL; + } + } + if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[PCM_IN_STREAM]) { + if (waveFormat->nSamplesPerSec != stream[PCM_IN_STREAM]->currentSampleRate) { + return STATUS_UNSUCCESSFUL; + } + } + + // instantiate a stream +#ifdef WAVERT + ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, NonPagedPool); +#else + ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, PoolType); +#endif + if (!NT_SUCCESS (ntStatus)) { + DBGPRINT(("Failed to create stream")); + return ntStatus; + } + + // initialize it +#ifdef WAVERT + ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, OuterUnknown); +#else + ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, DMAChannel[streamIndex], OutServiceGroup); +#endif + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("Failed to init stream")); + stream[streamIndex]->Release(); + stream[streamIndex] = NULL; + *OutStream = NULL; +#ifndef WAVERT + *OutServiceGroup = NULL; + *OutDmaChannel = NULL; +#endif + return ntStatus; + } + +#ifdef WAVERT +//this has been referenced in CreateMiniportWaveStreamCMI() already + *OutStream = (PMINIPORTWAVERTSTREAM)stream[streamIndex]; +#else + *OutDmaChannel = DMAChannel[streamIndex]; + DMAChannel[streamIndex]->AddRef(); + *OutStream = (PMINIPORTWAVECYCLICSTREAM)stream[streamIndex]; +#endif + + return ntStatus; +} + +static NTSTATUS PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest) +{ + PAGED_CODE(); + ASSERT(PropertyRequest); + DBGPRINT(("[PropertyHandler_ChannelConfig]")); + +#ifdef WAVERT + CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVERT)PropertyRequest->MajorTarget); +#else + CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVECYCLIC)PropertyRequest->MajorTarget); +#endif + + if (PropertyRequest->Node == KSNODE_WAVE_DAC) { + + if (PropertyRequest->ValueSize == 0) { + PropertyRequest->ValueSize = sizeof(LONG); + return STATUS_BUFFER_OVERFLOW; + } else if (PropertyRequest->ValueSize < sizeof (LONG)) { + PropertyRequest->ValueSize = 0; + return STATUS_BUFFER_TOO_SMALL; + } + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) { + *(PLONG)PropertyRequest->Value = that->requestedChannelMask; + PropertyRequest->ValueSize = sizeof(ULONG); + return STATUS_SUCCESS; + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) { + if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_7POINT1) { + that->requestedChannelMask = *(PLONG)PropertyRequest->Value; + that->requestedChannelCount = 8; + return STATUS_SUCCESS; + } + if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1) { + that->requestedChannelMask = *(PLONG)PropertyRequest->Value; + that->requestedChannelCount = 6; + return STATUS_SUCCESS; + } + if ((*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_QUAD) || (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_SURROUND)) { + that->requestedChannelMask = *(PLONG)PropertyRequest->Value; + that->requestedChannelCount = 4; + return STATUS_SUCCESS; + } + if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_STEREO) { + that->requestedChannelMask = *(PLONG)PropertyRequest->Value; + that->requestedChannelCount = 2; + return STATUS_SUCCESS; + } + } else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) { + PULONG AccessFlags = PULONG(PropertyRequest->Value); + *AccessFlags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET; + PropertyRequest->ValueSize = sizeof(ULONG); + return STATUS_SUCCESS; + } + } + return STATUS_INVALID_PARAMETER; +} + +/////////////////////////// + +NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType) +{ + PAGED_CODE(); + DBGPRINT(("CreateMiniportWaveStreamCMI")); + +#ifdef WAVERT + *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(NULL); +#else + *MiniportWaveStreamCMI = new (PoolType, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter); +#endif + if (*MiniportWaveStreamCMI) { + (*MiniportWaveStreamCMI)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INSUFFICIENT_RESOURCES; +} + +NTSTATUS CMiniportWaveStreamCMI::prepareStream() +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this)); + DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); + + NTSTATUS ntStatus; + UInt8 reg; + UInt32 val; + + if (state == KSSTATE_RUN) { + return STATUS_INVALID_DEVICE_REQUEST; + } + + if (!(Miniport->cm)) { + DBGPRINT(("Miniport not set")); + return STATUS_INVALID_DEVICE_REQUEST; + } + + enableSPDIF = ((currentSampleRate == 44100 || currentSampleRate == 48000 || currentSampleRate == 88200 || currentSampleRate == 96000) && + ((currentResolution == 16) || (currentResolution == 24)) && (currentChannelCount == 2)) && + (Miniport->cm->enableSPDIFOut); + + ntStatus = setupSPDIFPlayback(enableSPDIF); + if (!NT_SUCCESS(ntStatus)) { + return ntStatus; + } + + if (!isCaptureStream) { + ntStatus = setDACChannels(); + if (!NT_SUCCESS(ntStatus)) { + return ntStatus; + } + } + + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); + + val = channelNumber ? ADC_CH1 : ADC_CH0; + if (isCaptureStream) { + Miniport->cm->regFUNCTRL0 |= val; // 1->Recording + } else { + Miniport->cm->regFUNCTRL0 &= ~val; // 0->Playback + } + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); + + //set sampling frequency + val = Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1); + if ((currentSampleRate == 88200) || (currentSampleRate == 44100)) { + if (channelNumber) { + val &= ~SFC_CH1_MASK; + val |= SFC_44K_CH1; + } else { + val &= ~SFC_CH0_MASK; + val |= SFC_44K_CH0; + } + } else if ((currentSampleRate == 96000) || (currentSampleRate == 48000)) { + if (channelNumber) { + val &= ~SFC_CH1_MASK; + val |= SFC_48K_CH1; + } else { + val &= ~SFC_CH0_MASK; + val |= SFC_48K_CH0; + } + } else { + KeReleaseMutex(&Miniport->mutex, FALSE); + return STATUS_INVALID_DEVICE_REQUEST; + } + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL1, val); + + //set resolution + val = Miniport->CMIAdapter->readUInt32(REG_CHFORMAT); + if (channelNumber) { + val |= FORMAT_CH1; + } else { + val |= FORMAT_CH0; + } + Miniport->CMIAdapter->writeUInt32(REG_CHFORMAT, val); + + KeReleaseMutex(&Miniport->mutex, false); + + return STATUS_SUCCESS; +} + +NTSTATUS CMiniportWaveStreamCMI::setDACChannels() +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this)); + NTSTATUS ntStatus = STATUS_SUCCESS; + + if (currentChannelCount > 2) { + if (Miniport->cm->maxChannels < currentChannelCount) { + return STATUS_INVALID_DEVICE_REQUEST; + } + if ((currentResolution != 16) || (currentChannelCount < 2)) { + return STATUS_INVALID_DEVICE_REQUEST; + } +#if OUT_CHANNEL == 0 + return STATUS_INVALID_DEVICE_REQUEST; +#endif + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, DWORD_MAPPING); + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, XCHG_DAC); + + switch (currentChannelCount) { + case 4: + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); + Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1); + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER); + break; + case 6: + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER); + break; + case 8: + if (Miniport->cm->chipVersion == 68) { + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_4CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_5CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_6CH_CH1); + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_CENTER); + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1); + break; + } else { + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + default: + ntStatus = STATUS_INVALID_DEVICE_REQUEST; + } + KeReleaseMutex(&Miniport->mutex, FALSE); + } else { + if (Miniport->cm->canMultiChannel) { + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_5CH_CH1 | EN_4CH_CH1); + Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_6CH_CH1 | DWORD_MAPPING); + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_CENTER); + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, XCHG_DAC); + if (Miniport->cm->chipVersion == 68) { + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL2, EN_8CH_CH1); + } + KeReleaseMutex(&Miniport->mutex, FALSE); + } + } + return ntStatus; +} + +NTSTATUS CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF)); + + NTSTATUS ntStatus; + + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); + + if (enableSPDIF) { + Miniport->CMIAdapter->setUInt32Bit(REG_LEGACY, EN_SPDIF_OUT); + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDO2DAC); +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); +#else + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); +#endif + setupAC3Passthru(); + + if ( (currentSampleRate == 48000) || (currentSampleRate == 96000) ) { + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDIF_48); + } else { + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDIF_48); + } + + if (currentSampleRate == 96000) { +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0); +#else + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1); +#endif + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS); + } else if (currentSampleRate == 88200) { +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH0); +#else + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD88_CH1); +#endif + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, DBLSPDS); + } else { +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1); +#endif + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS); + } + + } else { + Miniport->CMIAdapter->clearUInt32Bit(REG_LEGACY, EN_SPDIF_OUT); + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDO2DAC); +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1); +#endif +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH0 | SPD96_CH0); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD88_CH1 | SPD96_CH1); +#endif + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, DBLSPDS); + setupAC3Passthru(); + } + + KeReleaseMutex(&Miniport->mutex, false); + return STATUS_SUCCESS; +} + +NTSTATUS CMiniportWaveStreamCMI::setupAC3Passthru() +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()")); + + if (enableAC3Passthru) { + Miniport->CMIAdapter->writeUInt8(REG_MIXER1, Miniport->CMIAdapter->readUInt8(REG_MIXER1) | MUTE_WAVE); + + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1); + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2); + + if (Miniport->cm->canAC3HW) { + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3); + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); + if (Miniport->cm->chipVersion >= 39) { + Miniport->CMIAdapter->clearUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + } + } else { + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL); + if (Miniport->cm->chipVersion == 33) { + if (currentSampleRate >= 48000) { +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH0); +#else + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD96_CH1); +#endif + } else { +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1); +#endif + } + } + } + } else { + Miniport->CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC); + + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_1); + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, EN_SPDO_AC3_2); + + if (Miniport->cm->canAC3HW) { + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, EN_SPDO_AC3_3); + if (currentResolution > 16) { + Miniport->CMIAdapter->setUInt32Bit(REG_MISCCTRL, SPD32SEL); + Miniport->CMIAdapter->setUInt32Bit(REG_CHFORMAT, SPD24SEL); + } else { + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD24SEL); + } + } else { + Miniport->CMIAdapter->clearUInt32Bit(REG_MISCCTRL, SPD32SEL); +#if OUT_CHANNEL == 0 + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH0); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_CHFORMAT, SPD96_CH1); +#endif + } + } + return STATUS_SUCCESS; +} + +CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void) +{ + PAGED_CODE(); + + DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this)); + +#ifdef WAVERT + if (Port) { + Port->Release(); + Port = NULL; + } +#else + if (DMAChannel) { + DMAChannel->Release(); + DMAChannel = NULL; + } + + if (ServiceGroup) { + ServiceGroup->Release(); + ServiceGroup = NULL; + } +#endif + + Miniport->isStreamRunning[streamIndex] = false; + + if ((streamIndex == AC3_OUT_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) { + KSSTATE temp = Miniport->stream[PCM_OUT_STREAM]->state; + Miniport->stream[PCM_OUT_STREAM]->state = KSSTATE_STOP; + Miniport->stream[PCM_OUT_STREAM]->prepareStream(); + Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_ACQUIRE); + Miniport->stream[PCM_OUT_STREAM]->state = temp; + Miniport->stream[PCM_OUT_STREAM]->SetState(KSSTATE_RUN_AC3); + } + + if (Miniport) { + Miniport->Release(); + Miniport = NULL; + } +} + +STDMETHODIMP CMiniportWaveStreamCMI::NonDelegatingQueryInterface(REFIID Interface, PVOID *Object) +{ + PAGED_CODE(); + ASSERT(Object); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface, Object)); + + if (IsEqualGUIDAligned(Interface,IID_IUnknown)) { + *Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this))); +#ifdef WAVERT + } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveRTStream)) { + *Object = PVOID(PMINIPORTWAVERTSTREAM(this)); +#else + } else if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream)) { + *Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this)); +#endif + } else if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream)) { + *Object = (PVOID)(PDRMAUDIOSTREAM(this)); + } else { + *Object = NULL; + } + + if (*Object) { + PUNKNOWN(*Object)->AddRef(); + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +#ifdef WAVERT +NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM Port_) +#else +NTSTATUS CMiniportWaveStreamCMI::Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup) +#endif +{ + PAGED_CODE(); + ASSERT(Miniport_); + ASSERT(DataFormat); + + NTSTATUS ntStatus; + +#ifdef WAVERT + ASSERT(Port_); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, Port_)); + Port = Port_; + Port->AddRef(); +#else + DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, DMAChannel_, OutServiceGroup)); + DMAChannel = DMAChannel_; + DMAChannel->AddRef(); +#endif + + Miniport = Miniport_; + Miniport->AddRef(); + + streamIndex = streamIndex_; + isCaptureStream = isCaptureStream_; + state = KSSTATE_STOP; + + if ( (streamIndex == PCM_OUT_STREAM) || (streamIndex == AC3_OUT_STREAM) ) { + channelNumber = OUT_CHANNEL; + } else { + channelNumber = IN_CHANNEL; + } + +#ifndef WAVERT + ntStatus = PcNewServiceGroup(&ServiceGroup,NULL); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed")); + return ntStatus; + } + *OutServiceGroup = ServiceGroup; + ServiceGroup->AddRef(); +#endif + + ntStatus = SetFormat(DataFormat); + if (!NT_SUCCESS(ntStatus)) { + DBGPRINT(("SetFormat() failed")); + return ntStatus; + } + + Miniport->isStreamRunning[streamIndex] = true; + + return ntStatus; +} + +NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format)); + PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1); + NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream); + if (!NT_SUCCESS(ntStatus)) { + return ntStatus; + } + // the DAC and ADC can only run at the same sample rate simultaneously + if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) { + if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_OUT_STREAM]->currentSampleRate) { + return STATUS_UNSUCCESSFUL; + } + } + if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { + if (waveFormat->nSamplesPerSec != Miniport->stream[AC3_OUT_STREAM]->currentSampleRate) { + return STATUS_UNSUCCESSFUL; + } + } + if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[PCM_IN_STREAM]) { + if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_IN_STREAM]->currentSampleRate) { + return STATUS_UNSUCCESSFUL; + } + } + if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { + return STATUS_UNSUCCESSFUL; + } + + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); + currentSampleRate = waveFormat->nSamplesPerSec; + currentChannelCount = waveFormat->nChannels; + currentResolution = waveFormat->wBitsPerSample; + enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat)); + KeReleaseMutex(&Miniport->mutex, false); + ntStatus = prepareStream(); + + return ntStatus; +} + +// DRM crap - we're supposed to disable every digital interface here +STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights)); + + return STATUS_SUCCESS; +} + +#ifdef WAVERT + +STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType) +{ + PAGED_CODE(); + + PHYSICAL_ADDRESS low; + PHYSICAL_ADDRESS high; + DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType)); + + if (size <= size % (currentChannelCount * 2)) { + return STATUS_UNSUCCESSFUL; + } + size -= size % (currentChannelCount * 2); + + if (size == 0) { + return STATUS_UNSUCCESSFUL; + } + + low.QuadPart = 0; + high.HighPart = 0, high.LowPart = MAXULONG; + + audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size); + + if (!audioBufferMDL) { + DBGPRINT(("AllocateContiguousPagesForMdl() failed")); + return STATUS_UNSUCCESSFUL; + } + + dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart; + dmaMemorySize = size; + + *userModeBuffer = audioBufferMDL; + *bufferSize = size; + *bufferOffset = 0; + *cacheType = MmCached; + + return STATUS_SUCCESS; +} + + +STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size)); + + Port->FreePagesFromMdl(Mdl); + audioBufferMDL = NULL; + dmaAddress = 0; + dmaMemorySize = 0; +} + +STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) { + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency)); + hwLatency->FifoSize = 32; + hwLatency->ChipsetDelay = 0; + hwLatency->CodecDelay = 4; +} + +STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister)); + + return STATUS_UNSUCCESSFUL; +} + +STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister) +{ + PAGED_CODE(); + DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister)); + + return STATUS_UNSUCCESSFUL; +} + +#endif // WAVERT + +/* +** non-paged code below +*/ +#pragma code_seg() + +STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState) +{ + DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState)); + + UInt32 inthld, chen, reset, pause; + UInt8 reg; + + inthld = EN_CH0_INT << channelNumber; + chen = EN_CH0 << channelNumber; + reset = RST_CH0 << channelNumber; + pause = PAUSE_CH0 << channelNumber; + + NTSTATUS ntStatus = STATUS_SUCCESS; + + if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) { + return STATUS_INVALID_PARAMETER; + } + + if (NewState == KSSTATE_RUN_AC3) { + NewState = state; + state = KSSTATE_STOP; + } + + // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP + if (state != NewState) { + switch (NewState) { + case KSSTATE_ACQUIRE: + DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state)); + if (state == KSSTATE_PAUSE) { + break; + } + +#ifdef WAVERT + if ((dmaMemorySize == 0) || (dmaAddress == 0)) { + return STATUS_UNSUCCESSFUL; + } + dmaSize = (dmaMemorySize / (2 * (currentResolution >> 3)) ); + periodSize = dmaSize; + DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize)); +#else + if (currentResolution == 24) { + dmaSize = (DMAChannel->BufferSize() / (2 * (24 >> 3)) ); + } else { + dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) ); + } +#endif + DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber)); + DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount)); + + if (periodSize > dmaSize) { + periodSize = dmaSize; + } + + // set address of the DMA buffer + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + reg = channelNumber ? REG_CH1_FRAME1 : REG_CH0_FRAME1; +#ifdef WAVERT + Miniport->CMIAdapter->writeUInt32(reg, dmaAddress); +#else + Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart); +#endif + // count of samples + reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2; + Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1); + Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1); + DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn)); + if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) { +#if OUT_CHANNEL==0 + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1); +#else + Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0); +#endif + } + KeReleaseMutex(&Miniport->mutex, false); + break; + + case KSSTATE_PAUSE: + DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state)); + if (state == KSSTATE_RUN) { + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); + Miniport->cm->regFUNCTRL0 |= pause; + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); + KeReleaseMutex(&Miniport->mutex, FALSE); + } + if (state == KSSTATE_STOP) { + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL); + Miniport->cm->regFUNCTRL0 &= ~pause; + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); + KeReleaseMutex(&Miniport->mutex, false); + } + break; + + case KSSTATE_RUN: + DBGPRINT(("---KSSTATE_RUN: previous state: %d", state)); + + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + // set interrupt + Miniport->CMIAdapter->setUInt32Bit(REG_INTHLDCLR, inthld); + Miniport->cm->regFUNCTRL0 &= ~pause; + Miniport->cm->regFUNCTRL0 |= chen; + // and enable the channel + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0); + + DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport->cm->regFUNCTRL0)); + DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1))); + DBGPRINT(("---CHFORMAT: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_CHFORMAT))); + DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_LEGACY))); + DBGPRINT(("---MISCCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_MISCCTRL))); + DBGPRINT(("---MIX1: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER1))); + DBGPRINT(("---MIX2: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER2))); + DBGPRINT(("---MIX3: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER3))); + + KeReleaseMutex(&Miniport->mutex, false); + break; + + case KSSTATE_STOP_AC3: + case KSSTATE_STOP: + DBGPRINT(("---KSSTATE_STOP: previous state: %d", state)); + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + // clear interrupt + Miniport->CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, inthld); + Miniport->cm->regFUNCTRL0 &= ~chen; + // reset + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 | reset); + Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 & ~reset); + if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) { +#if OUT_CHANNEL==0 + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1); +#else + Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0); +#endif + } + KeReleaseMutex(&Miniport->mutex, FALSE); + break; + } + if (NewState != KSSTATE_STOP_AC3) { + state = NewState; + } + } + return ntStatus; +} + +#ifdef WAVERT +STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position) +{ + ASSERT(Position); + + UInt32 reg; + + if ((state == KSSTATE_RUN) && (dmaAddress)) { + reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; + Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress; + Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8; + } else { + Position->PlayOffset = 0; + Position->WriteOffset = 0; + } + + return STATUS_SUCCESS; +} + +#else //WaveCyclic +STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position) +{ + ASSERT(Position); + + UInt32 reg; + + if ((DMAChannel) && (state == KSSTATE_RUN)) { +#if 0 +// this implementation messes with SPDIF-in recording + reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2; + *Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1); + *Position *= 2 * (currentResolution >> 3); +#else + reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1; + *Position = Miniport->CMIAdapter->readUInt32(reg); + if (*Position > DMAChannel->PhysicalAddress().u.LowPart) { + *Position -= DMAChannel->PhysicalAddress().u.LowPart; + } else { + *Position = 0; + } +#endif + } else { + *Position = 0; + } + + return STATUS_SUCCESS; +} + +STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, PULONG FramingSize) +{ + Miniport->notificationInterval = Interval; + + if (state == KSSTATE_RUN) { + return 0; + } + periodSize = Interval * currentSampleRate/1000; + *FramingSize = periodSize*currentChannelCount*(currentResolution >> 3); + + KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL); + Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1); + KeReleaseMutex(&Miniport->mutex, FALSE); + + DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize, *FramingSize)); + return Interval; +} + +STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition) +{ + *PhysicalPosition = (_100NS_UNITS_PER_SECOND / currentChannelCount * (currentResolution >> 3) * *PhysicalPosition) / currentSampleRate; + return STATUS_SUCCESS; +} + + +STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer, ULONG ByteCount) +{ + RtlFillMemory(Buffer, ByteCount, 0x00); +} + +#endif //WAVERT + +STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex) +{ +#ifndef WAVERT + if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) { + streamIndex = AC3_OUT_STREAM; + } + if (Port && stream[streamIndex]->ServiceGroup) { + Port->Notify(stream[streamIndex]->ServiceGroup); + } +#endif +} diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp new file mode 100644 index 00000000000..7dfeacf14a4 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwave.hpp @@ -0,0 +1,150 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MINWAVE_HPP_ +#define _MINWAVE_HPP_ + +#define PC_IMPLEMENTATION // for the implementation of IDMAChannel + +#include "common.hpp" +#include "property.h" + +class CMiniportWaveStreamCMI; + +class CMiniportWaveCMI: +#ifdef WAVERT + public IMiniportWaveRT, +#else + public IMiniportWaveCyclic, +#endif + public IMiniportWaveCMI, + public CUnknown +{ +private: + PCMIADAPTER CMIAdapter; // Adapter common object. +#ifdef WAVERT + PPORTWAVERT Port; +#else + PPORTWAVECYCLIC Port; + PDMACHANNEL DMAChannel[3]; + UInt32 notificationInterval; +#endif + CMI8738Info *cm; + UInt32 requestedChannelCount; + UInt32 requestedChannelMask; + + + CMiniportWaveStreamCMI *stream[3]; + bool isStreamRunning[3]; + KMUTEX mutex; + + NTSTATUS processResources(PRESOURCELIST resourceList); + + NTSTATUS isFormatAllowed(UInt32 sampleRate, BOOLEAN multiChan, BOOLEAN AC3); + NTSTATUS validateFormat(PKSDATAFORMAT format, ULONG PinID, BOOLEAN capture); +#ifndef WAVERT + NTSTATUS newDMAChannel(PDMACHANNEL *dmaChannel, UInt32 bufferLength); +#endif + NTSTATUS loadChannelConfigFromRegistry(); + NTSTATUS storeChannelConfigToRegistry(); +public: + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CMiniportWaveCMI); + ~CMiniportWaveCMI(); +#ifdef WAVERT + IMP_IMiniportWaveRT; +#else + IMP_IMiniportWaveCyclic; +#endif + + STDMETHODIMP_(void) ServiceWaveISR(UInt32 streamIndex); + STDMETHODIMP_(void) powerUp(); + STDMETHODIMP_(void) powerDown(); + + friend NTSTATUS PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest); + friend class CMiniportWaveStreamCMI; +}; + + +class CMiniportWaveStreamCMI: +#ifdef WAVERT + public IMiniportWaveRTStream, +#else + public IMiniportWaveCyclicStream, +#endif + public IDrmAudioStream, + public CUnknown +{ +private: + CMiniportWaveCMI *Miniport; +#ifdef WAVERT + PPORTWAVERTSTREAM Port; + PMDL audioBufferMDL; + UInt32 dmaAddress; + UInt32 dmaMemorySize; +#else + PDMACHANNEL DMAChannel; + PSERVICEGROUP ServiceGroup; // For notification. +#endif + + bool isCaptureStream;// Capture or render. + UInt32 streamIndex; + UInt32 channelNumber; // hardware channel number: 0/A or 1/B + KSSTATE state; // Stop, pause, run. + UInt32 periodSize; // process n frames until the interrupt is fired in frames, NOT in bytes + UInt32 dmaSize; // size of the DMA buffer in frames, NOT in bytes + UInt32 currentChannelCount, currentSampleRate, currentResolution; + bool enableAC3Passthru, enableSPDIF; + + NTSTATUS prepareStream(); + NTSTATUS setDACChannels(); + NTSTATUS setupSPDIFPlayback(bool enableSPDIF); + NTSTATUS setupAC3Passthru(); + +public: + DECLARE_STD_UNKNOWN(); + DEFINE_STD_CONSTRUCTOR(CMiniportWaveStreamCMI); + ~CMiniportWaveStreamCMI(); +#ifdef WAVERT + IMP_IMiniportWaveRTStream; +#else + IMP_IMiniportWaveCyclicStream; +#endif + + IMP_IDrmAudioStream; + +#ifdef WAVERT + NTSTATUS Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PPORTWAVERTSTREAM PortStream_); +#else + NTSTATUS Init(CMiniportWaveCMI* Miniport_, UInt32 streamIndex_, bool isCaptureStream_, PKSDATAFORMAT DataFormat, PDMACHANNEL DMAChannel_, PSERVICEGROUP* OutServiceGroup); +#endif + friend class CMiniportWaveCMI; +}; + +NTSTATUS CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI **MiniportWaveStreamCMI, PUNKNOWN pUnknownOuter, POOL_TYPE PoolType); + +#endif //_MINWAVE_HPP_ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp new file mode 100644 index 00000000000..f22312c3527 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/minwavetables.hpp @@ -0,0 +1,338 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _MINWAVETABLES_HPP_ +#define _MINWAVETABLES_HPP_ + +#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\ + DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) +DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF); +#define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) + +static KSDATARANGE_AUDIO WavePinDataRangesPCMStream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MAX_CHANNELS_PCM, + MIN_BITS_PER_SAMPLE_PCM, + MAX_BITS_PER_SAMPLE_PCM, + MIN_SAMPLE_RATE, + MAX_SAMPLE_RATE + } +}; + +static KSDATARANGE_AUDIO WavePinDataRangesAC3Stream[] = +{ + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) + }, + MAX_CHANNELS_AC3, + MIN_BITS_PER_SAMPLE_AC3, + MAX_BITS_PER_SAMPLE_AC3, + MIN_SAMPLE_RATE_AC3, + MAX_SAMPLE_RATE_AC3 + }, + { + { + sizeof(KSDATARANGE_AUDIO), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_DSOUND) + }, + MAX_CHANNELS_AC3, + MIN_BITS_PER_SAMPLE_AC3, + MAX_BITS_PER_SAMPLE_AC3, + MIN_SAMPLE_RATE_AC3, + MAX_SAMPLE_RATE_AC3 + } +}; + +static PKSDATARANGE WavePinDataRangePointersPCMStream[] = +{ + PKSDATARANGE(&WavePinDataRangesPCMStream[0]) +}; + +static PKSDATARANGE WavePinDataRangePointersAC3Stream[] = +{ + PKSDATARANGE(&WavePinDataRangesAC3Stream[0]), + PKSDATARANGE(&WavePinDataRangesAC3Stream[1]), +}; + + + +static KSDATARANGE WavePinDataRangesPCMBridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static KSDATARANGE WavePinDataRangesAC3Bridge[] = +{ + { + sizeof(KSDATARANGE), + 0, + 0, + 0, + STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SUBTYPE_AC3_AUDIO), + STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) + } +}; + +static PKSDATARANGE WavePinDataRangePointersPCMBridge[] = +{ + &WavePinDataRangesPCMBridge[0] +}; + +static PKSDATARANGE WavePinDataRangePointersAC3Bridge[] = +{ + &WavePinDataRangesAC3Bridge[0] +}; + +static PCPIN_DESCRIPTOR WaveMiniportPins[] = +{ + // PIN_WAVE_CAPTURE_SINK - 0 + { + MAX_OUTPUT_STREAMS, + MAX_OUTPUT_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersPCMStream), + WavePinDataRangePointersPCMStream, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + &KSAUDFNAME_RECORDING_CONTROL, + 0 + } + }, + + // PIN_WAVE_CAPTURE_SOURCE - 1 + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersPCMBridge), + WavePinDataRangePointersPCMBridge, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_NONE, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + + // PIN_WAVE_RENDER_SINK - 2 + { + MAX_INPUT_STREAMS, + MAX_INPUT_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersPCMStream), + WavePinDataRangePointersPCMStream, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + &KSAUDFNAME_VOLUME_CONTROL, + 0 + } + }, + + // PIN_WAVE_RENDER_SOURCE - 3 + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersPCMBridge), + WavePinDataRangePointersPCMBridge, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_NONE, + &KSNODETYPE_SPEAKER, + NULL, + 0 + } + }, + + // PIN_WAVE_AC3_RENDER_SINK - 4 + { + MAX_AC3_INPUT_STREAMS, + MAX_AC3_INPUT_STREAMS, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersAC3Stream), + WavePinDataRangePointersAC3Stream, + KSPIN_DATAFLOW_IN, + KSPIN_COMMUNICATION_SINK, + &KSCATEGORY_AUDIO, + NULL, + 0 + } + }, + + + // PIN_WAVE_AC3_RENDER_SOURCE - 5 + { + 0, + 0, + 0, + NULL, + { + 0, + NULL, + 0, + NULL, + SIZEOF_ARRAY(WavePinDataRangePointersAC3Bridge), + WavePinDataRangePointersAC3Bridge, + KSPIN_DATAFLOW_OUT, + KSPIN_COMMUNICATION_NONE, + &KSNODETYPE_SPDIF_INTERFACE, + NULL, + 0 + } + } +}; + +static PCPROPERTY_ITEM PropertiesChannels[] = +{ + { + &KSPROPSETID_Audio, + KSPROPERTY_AUDIO_CHANNEL_CONFIG, + KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET, + PropertyHandler_ChannelConfig + } +}; +DEFINE_PCAUTOMATION_TABLE_PROP(AutomationChans,PropertiesChannels); + +static PCNODE_DESCRIPTOR WaveMiniportNodes[] = +{// Flags AutomationTable Type Name +// 0 - KSNODE_WAVE_ADC + { 0, NULL, &KSNODETYPE_ADC, NULL }, +// 1 - KSNODE_WAVE_VOLUME1 + { 0, NULL, &KSNODETYPE_VOLUME, NULL }, +// 2 - KSNODE_WAVE_3D_EFFECTS + { 0, NULL, &KSNODETYPE_3D_EFFECTS, NULL }, +// 3 - KSNODE_WAVE_SUPERMIX + { 0, NULL, &KSNODETYPE_SUPERMIX, NULL }, +// 4 - KSNODE_WAVE_VOLUME2 + { 0, NULL, &KSNODETYPE_VOLUME, NULL }, +// 5 - KSNODE_WAVE_SRC + { 0, NULL, &KSNODETYPE_SRC, NULL }, +// 6 - KSNODE_WAVE_SUM + { 0, NULL, &KSNODETYPE_SUM, NULL }, +// 7 - KSNODE_WAVE_DAC + { 0, &AutomationChans, &KSNODETYPE_DAC, NULL }, +// 8 - KSNODE_WAVE_SPDIF (XP crashes if the pins are directly connected) + { 0, NULL, &KSNODETYPE_SPDIF_INTERFACE, NULL }, +}; + +static PCCONNECTION_DESCRIPTOR WaveMiniportConnections[] = +{// FromNode, FromPin, ToNode, ToPin + { PCFILTER_NODE, PIN_WAVE_CAPTURE_SOURCE, KSNODE_WAVE_ADC, 1 }, + { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, PIN_WAVE_CAPTURE_SINK }, + + { PCFILTER_NODE, PIN_WAVE_RENDER_SINK, KSNODE_WAVE_VOLUME1, 1 }, + { KSNODE_WAVE_VOLUME1, 0, KSNODE_WAVE_3D_EFFECTS, 1 }, + { KSNODE_WAVE_3D_EFFECTS, 0, KSNODE_WAVE_SUPERMIX, 1 }, + { KSNODE_WAVE_SUPERMIX, 0, KSNODE_WAVE_VOLUME2, 1 }, + { KSNODE_WAVE_VOLUME2, 0, KSNODE_WAVE_SRC, 1 }, + { KSNODE_WAVE_SRC, 0, KSNODE_WAVE_SUM, 1 }, + { KSNODE_WAVE_SUM, 0, KSNODE_WAVE_DAC, 1 }, + { KSNODE_WAVE_DAC, 0, PCFILTER_NODE, PIN_WAVE_RENDER_SOURCE }, + + { PCFILTER_NODE, PIN_WAVE_AC3_RENDER_SINK,KSNODE_WAVE_SPDIF, 1 }, + { KSNODE_WAVE_SPDIF, 0, PCFILTER_NODE, PIN_WAVE_AC3_RENDER_SOURCE }, +}; + +static PCFILTER_DESCRIPTOR WaveMiniportFilterDescriptor = +{ + 0, // Version + NULL, // AutomationTable + sizeof(PCPIN_DESCRIPTOR), // PinSize + SIZEOF_ARRAY(WaveMiniportPins), // PinCount + WaveMiniportPins, // Pins + sizeof(PCNODE_DESCRIPTOR), // NodeSize + SIZEOF_ARRAY(WaveMiniportNodes), // NodeCount + WaveMiniportNodes, // Nodes + SIZEOF_ARRAY(WaveMiniportConnections), // ConnectionCount + WaveMiniportConnections, // Connections + 0, // CategoryCount + NULL // Categories - use the default categories (audio, render, capture) +}; + +#endif //_MINWAVETABLES_HPP_ diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h b/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h new file mode 100644 index 00000000000..ffd841fe370 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/property.h @@ -0,0 +1,86 @@ +/* +Copyright (c) 2006-2007 dogbert +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _PROPERTY_H_ +#define _PROPERTY_H_ + +//GUID for the private property +// {2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFF} +#define STATIC_KSPROPSETID_CMI \ + 0x2B81CDBB, 0xEE6C, 0x4ECC, 0x8A, 0xA5, 0x9A, 0x18, 0x8B, 0x02, 0x3D, 0xFF +DEFINE_GUIDSTRUCT("2B81CDBB-EE6C-4ECC-8AA5-9A188B023DFF", _STATIC_KSPROPSETID_CMI); +#define KSPROPSETID_CMI DEFINE_GUIDNAMED(_STATIC_KSPROPSETID_CMI) + +//methods +#define KSPROPERTY_CMI_GET 1 +#define KSPROPERTY_CMI_SET 2 + +#define FMT_441_PCM 0x00000001 +#define FMT_480_PCM 0x00000002 +#define FMT_882_PCM 0x00000004 +#define FMT_960_PCM 0x00000008 +#define FMT_441_MULTI_PCM 0x00000010 +#define FMT_480_MULTI_PCM 0x00000020 +#define FMT_882_MULTI_PCM 0x00000040 +#define FMT_960_MULTI_PCM 0x00000080 +#define FMT_441_DOLBY 0x00000100 +#define FMT_480_DOLBY 0x00000200 +#define FMT_882_DOLBY 0x00000400 +#define FMT_960_DOLBY 0x00000800 + +#ifndef UInt32 +#define UInt32 ULONG +#define UInt16 USHORT +#define UInt8 BYTE +#define Int32 LONG +#endif + +typedef struct +{ + char driverVersion[32]; + int hardwareRevision; + UInt16 IOBase; + UInt16 MPUBase; + UInt32 maxChannels; + UInt32 enablePCMDAC; + UInt32 exchangeFrontBack; + UInt32 enableBass2Line; + UInt32 enableCenter2Line; + UInt32 enableRear2Line; + UInt32 enableCenter2Mic; + UInt32 enableSPDO; + UInt32 enableSPDO5V; + UInt32 enableSPDOCopyright; + UInt32 select2ndSPDI; + UInt32 invertPhaseSPDI; + UInt32 invertValidBitSPDI; + UInt32 loopSPDI; + UInt32 formatMask; + UInt32 enableSPDI; +} CMIDATA; + +#endif //_PROPERTY_H_ \ No newline at end of file diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/sources b/reactos/drivers/wdm/audio/drivers/CMIDriver/sources new file mode 100644 index 00000000000..8e91606c143 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/sources @@ -0,0 +1,20 @@ +TARGETNAME=cmipci +TARGETTYPE=DRIVER +TARGETPATH=obj + +TARGETLIBS= $(DDK_LIB_PATH)\portcls.lib \ + $(DDK_LIB_PATH)\stdunk.lib \ + $(SDK_LIB_PATH)\libcntpr.lib \ + $(DDK_LIB_PATH)\ntstrsafe.lib + +INCLUDES= + +MSC_WARNING_LEVEL=-WX + +C_DEFINES= $(C_DEFINES) -D_WIN32 -DUNICODE -D_UNICODE -DDEBUG_LEVEL=DEBUGLVL_TERSE + +SOURCES = adapter.cpp \ + common.cpp \ + mintopo.cpp \ + minwave.cpp \ + cmipci.rc diff --git a/reactos/drivers/wdm/audio/drivers/CMIDriver/update.bat b/reactos/drivers/wdm/audio/drivers/CMIDriver/update.bat new file mode 100644 index 00000000000..ba3f0002105 --- /dev/null +++ b/reactos/drivers/wdm/audio/drivers/CMIDriver/update.bat @@ -0,0 +1,12 @@ +@echo off +call envars.bat +if "%CMI_DEBUGARCH%"=="AMD64" goto :x64 +set CMI_DEBUGDIR=objchk_%CMI_DEBUGOS%_%CMI_DEBUGARCH%\i386 +goto start +:x64 +set CMI_DEBUGDIR=objchk_%CMI_DEBUGOS%_%CMI_DEBUGARCH%\AMD64 +:start +devcon remove "PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6&REV_10" +devcon dp_delete %CMI_OEMINF% +devcon rescan +devcon update %CMI_DEBUGDIR%\CM8738.INF "PCI\VEN_13F6&DEV_0111&SUBSYS_011113F6&REV_10"