├── README.md ├── LumiaUSBCKm ├── Public.h ├── Driver.h ├── ReadMe.txt ├── LumiaUSBCKm.vcxproj.filters ├── Device.h ├── Trace.h ├── LumiaUSBCKm.inf ├── Driver.c ├── LumiaUSBCKm.vcxproj └── Device.c ├── .gitattributes ├── LumiaUSBCKm.sln └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # LumiaUSBC 2 | USB-C controller driver for the Nokia Lumia 950 and 950XL 3 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Public.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | public.h 6 | 7 | Abstract: 8 | 9 | This module contains the common declarations shared by driver 10 | and user applications. 11 | 12 | Environment: 13 | 14 | user and kernel 15 | 16 | --*/ 17 | 18 | // 19 | // Define an Interface Guid so that apps can find the device and talk to it. 20 | // 21 | 22 | DEFINE_GUID(GUID_DEVINTERFACE_LumiaUSBCKm, 23 | 0xeca28b08, 0x54d9, 0x4c81, 0x95, 0xbd, 0xe5, 0x5c, 0xf9, 0xc6, 0xf3, 0xfd); 24 | // {eca28b08-54d9-4c81-95bd-e55cf9c6f3fd} 25 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Driver.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | driver.h 6 | 7 | Abstract: 8 | 9 | This file contains the driver definitions. 10 | 11 | Environment: 12 | 13 | Kernel-mode Driver Framework 14 | 15 | --*/ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "device.h" 22 | #include "trace.h" 23 | 24 | EXTERN_C_START 25 | 26 | // 27 | // WDFDRIVER Events 28 | // 29 | 30 | DRIVER_INITIALIZE DriverEntry; 31 | EVT_WDF_DRIVER_DEVICE_ADD LumiaUSBCKmEvtDeviceAdd; 32 | EVT_WDF_OBJECT_CONTEXT_CLEANUP LumiaUSBCKmEvtDriverContextCleanup; 33 | 34 | EXTERN_C_END 35 | -------------------------------------------------------------------------------- /LumiaUSBCKm/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | LumiaUSBCKm Project Overview 3 | ======================================================================== 4 | 5 | This file contains a summary of what you will find in each of the files that make up your project. 6 | 7 | LumiaUSBCKm.vcxproj 8 | This is the main project file for projects generated using an Application Wizard. 9 | It contains information about the version of the product that generated the file, and 10 | information about the platforms, configurations, and project features selected with the 11 | Application Wizard. 12 | 13 | LumiaUSBCKm.vcxproj.filters 14 | This is the filters file for VC++ projects generated using an Application Wizard. 15 | It contains information about the association between the files in your project 16 | and the filters. This association is used in the IDE to show grouping of files with 17 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 18 | "Source Files" filter). 19 | 20 | Public.h 21 | Header file to be shared with applications. 22 | 23 | Driver.c & Driver.h 24 | DriverEntry and WDFDRIVER related functionality and callbacks. 25 | 26 | Device.c & Device.h 27 | WDFDEVICE related functionality and callbacks. 28 | 29 | Trace.h 30 | Definitions for WPP tracing. 31 | 32 | ///////////////////////////////////////////////////////////////////////////// 33 | 34 | Learn more about Kernel Mode Driver Framework here: 35 | 36 | http://msdn.microsoft.com/en-us/library/ff544296(v=VS.85).aspx 37 | 38 | ///////////////////////////////////////////////////////////////////////////// 39 | -------------------------------------------------------------------------------- /LumiaUSBCKm/LumiaUSBCKm.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Driver Files 27 | 28 | 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Device.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | device.h 6 | 7 | Abstract: 8 | 9 | This file contains the device definitions. 10 | 11 | Environment: 12 | 13 | Kernel-mode Driver Framework 14 | 15 | --*/ 16 | 17 | #include "public.h" 18 | #include 19 | 20 | EXTERN_C_START 21 | 22 | DEFINE_GUID(PowerControlGuid, 0x9942B45EL, 0x2C94, 0x41F3, 0xA1, 0x5C, 0xC1, 0xA5, 0x91, 0xC7, 4, 0x69); 23 | 24 | // 25 | // The device context performs the same job as 26 | // a WDM device extension in the driver frameworks 27 | // 28 | typedef struct _DEVICE_CONTEXT 29 | { 30 | WDFDEVICE Device; 31 | UCMCONNECTOR Connector; 32 | POHANDLE PoHandle; 33 | LARGE_INTEGER SpiId; 34 | WDFIOTARGET Spi; 35 | BOOLEAN UseFakeSpi; 36 | LARGE_INTEGER FakeSpiMosiId; 37 | WDFIOTARGET FakeSpiMosi; 38 | LARGE_INTEGER FakeSpiMisoId; 39 | WDFIOTARGET FakeSpiMiso; 40 | LARGE_INTEGER FakeSpiCsId; 41 | WDFIOTARGET FakeSpiCs; 42 | LARGE_INTEGER FakeSpiClkId; 43 | WDFIOTARGET FakeSpiClk; 44 | LARGE_INTEGER VbusGpioId; 45 | WDFIOTARGET VbusGpio; 46 | LARGE_INTEGER PolGpioId; 47 | WDFIOTARGET PolGpio; 48 | LARGE_INTEGER AmselGpioId; 49 | WDFIOTARGET AmselGpio; 50 | LARGE_INTEGER EnGpioId; 51 | WDFIOTARGET EnGpio; 52 | LARGE_INTEGER ResetGpioId; 53 | WDFIOTARGET ResetGpio; 54 | BOOLEAN HaveResetGpio; 55 | WDFINTERRUPT PlugDetectInterrupt; 56 | WDFINTERRUPT Uc120Interrupt; 57 | WDFINTERRUPT MysteryInterrupt1; 58 | WDFINTERRUPT MysteryInterrupt2; 59 | } DEVICE_CONTEXT, *PDEVICE_CONTEXT; 60 | 61 | typedef struct _CONNECTOR_CONTEXT 62 | { 63 | int dummy; 64 | 65 | } CONNECTOR_CONTEXT, *PCONNECTOR_CONTEXT; 66 | 67 | // 68 | // This macro will generate an inline function called DeviceGetContext 69 | // which will be used to get a pointer to the device context memory 70 | // in a type safe manner. 71 | // 72 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext) 73 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CONNECTOR_CONTEXT, ConnectorGetContext) 74 | 75 | // 76 | // Function to initialize the device and its callbacks 77 | // 78 | NTSTATUS 79 | LumiaUSBCKmCreateDevice( 80 | _Inout_ PWDFDEVICE_INIT DeviceInit 81 | ); 82 | 83 | EXTERN_C_END 84 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Trace.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | Trace.h 6 | 7 | Abstract: 8 | 9 | Header file for the debug tracing related function defintions and macros. 10 | 11 | Environment: 12 | 13 | Kernel mode 14 | 15 | --*/ 16 | 17 | // 18 | // Define the tracing flags. 19 | // 20 | // Tracing GUID - b65b50d8-84e9-4190-84af-5e1aff83f253 21 | // 22 | 23 | #define WPP_CONTROL_GUIDS \ 24 | WPP_DEFINE_CONTROL_GUID( \ 25 | LumiaUSBCKmTraceGuid, (b65b50d8,84e9,4190,84af,5e1aff83f253), \ 26 | \ 27 | WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ 28 | WPP_DEFINE_BIT(TRACE_DRIVER) \ 29 | WPP_DEFINE_BIT(TRACE_DEVICE) \ 30 | WPP_DEFINE_BIT(TRACE_QUEUE) \ 31 | ) 32 | 33 | #define WPP_FLAG_LEVEL_LOGGER(flag, level) \ 34 | WPP_LEVEL_LOGGER(flag) 35 | 36 | #define WPP_FLAG_LEVEL_ENABLED(flag, level) \ 37 | (WPP_LEVEL_ENABLED(flag) && \ 38 | WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) 39 | 40 | #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ 41 | WPP_LEVEL_LOGGER(flags) 42 | 43 | #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ 44 | (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) 45 | 46 | // 47 | // WPP orders static parameters before dynamic parameters. To support the Trace function 48 | // defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to 49 | // reorder the arguments to what the .tpl configuration file expects. 50 | // 51 | #define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags) 52 | #define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags) 53 | 54 | // 55 | // This comment block is scanned by the trace preprocessor to define our 56 | // Trace function. 57 | // 58 | // begin_wpp config 59 | // FUNC Trace{FLAGS=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); 60 | // FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); 61 | // end_wpp 62 | // 63 | -------------------------------------------------------------------------------- /LumiaUSBCKm/LumiaUSBCKm.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; LumiaUSBCKm.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=USB 8 | ClassGuid={36FC9E60-C465-11CF-8056-444553540000} 9 | Provider=%ManufacturerName% 10 | CatalogFile=LumiaUSBCKm.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | LumiaUSBCKm_Device_CoInstaller_CopyFiles = 11 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | LumiaUSBCKm.sys = 1,, 22 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames 23 | 24 | ;***************************************** 25 | ; Install Section 26 | ;***************************************** 27 | 28 | [Manufacturer] 29 | %ManufacturerName%=Standard,NT$ARCH$ 30 | 31 | [Standard.NT$ARCH$] 32 | %LumiaUSBCKm.DeviceDesc%=LumiaUSBCKm_Device, ACPI\LUMI0001 33 | 34 | [LumiaUSBCKm_Device.NT] 35 | CopyFiles=Drivers_Dir 36 | 37 | [Drivers_Dir] 38 | LumiaUSBCKm.sys 39 | 40 | ;-------------- Service installation 41 | [LumiaUSBCKm_Device.NT.Services] 42 | AddService = LumiaUSBCKm,%SPSVCINST_ASSOCSERVICE%, LumiaUSBCKm_Service_Inst 43 | 44 | ; -------------- LumiaUSBCKm driver install sections 45 | [LumiaUSBCKm_Service_Inst] 46 | DisplayName = %LumiaUSBCKm.SVCDESC% 47 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 48 | StartType = 3 ; SERVICE_DEMAND_START 49 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 50 | ServiceBinary = %12%\LumiaUSBCKm.sys 51 | 52 | ; 53 | ;--- LumiaUSBCKm_Device Coinstaller installation ------ 54 | ; 55 | 56 | [LumiaUSBCKm_Device.NT.CoInstallers] 57 | AddReg=LumiaUSBCKm_Device_CoInstaller_AddReg 58 | CopyFiles=LumiaUSBCKm_Device_CoInstaller_CopyFiles 59 | 60 | [LumiaUSBCKm_Device_CoInstaller_AddReg] 61 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 62 | 63 | [LumiaUSBCKm_Device_CoInstaller_CopyFiles] 64 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 65 | 66 | [LumiaUSBCKm_Device.NT.Wdf] 67 | KmdfService = LumiaUSBCKm, LumiaUSBCKm_wdfsect 68 | [LumiaUSBCKm_wdfsect] 69 | KmdfLibraryVersion = $KMDFVERSION$ 70 | 71 | [Strings] 72 | SPSVCINST_ASSOCSERVICE= 0x00000002 73 | ManufacturerName="LumiaWOA Project" 74 | DiskName = "LumiaUSBCKm Installation Disk" 75 | LumiaUSBCKm.DeviceDesc = "LumiaUSBCKm Device (Pol=1, iteration=30)" 76 | LumiaUSBCKm.SVCDESC = "LumiaUSBCKm Service" 77 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /LumiaUSBCKm.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LumiaUSBCKm", "LumiaUSBCKm\LumiaUSBCKm.vcxproj", "{B20988AB-AFD4-4533-9F10-11E759EAE4C8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM.Build.0 = Debug|ARM 22 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x64.ActiveCfg = Debug|x64 27 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x64.Build.0 = Debug|x64 28 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x64.Deploy.0 = Debug|x64 29 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x86.ActiveCfg = Debug|Win32 30 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x86.Build.0 = Debug|Win32 31 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Debug|x86.Deploy.0 = Debug|Win32 32 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM.ActiveCfg = Release|ARM 33 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM.Build.0 = Release|ARM 34 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM.Deploy.0 = Release|ARM 35 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM64.Build.0 = Release|ARM64 37 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x64.ActiveCfg = Release|x64 39 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x64.Build.0 = Release|x64 40 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x64.Deploy.0 = Release|x64 41 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x86.ActiveCfg = Release|Win32 42 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x86.Build.0 = Release|Win32 43 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {86C242AB-F031-4972-885B-0F1011CFBECB} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Driver.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | driver.c 6 | 7 | Abstract: 8 | 9 | This file contains the driver entry points and callbacks. 10 | 11 | Environment: 12 | 13 | Kernel-mode Driver Framework 14 | 15 | --*/ 16 | 17 | #include "driver.h" 18 | #include "driver.tmh" 19 | 20 | #ifdef ALLOC_PRAGMA 21 | #pragma alloc_text (INIT, DriverEntry) 22 | #pragma alloc_text (PAGE, LumiaUSBCKmEvtDeviceAdd) 23 | #pragma alloc_text (PAGE, LumiaUSBCKmEvtDriverContextCleanup) 24 | #endif 25 | 26 | NTSTATUS 27 | DriverEntry( 28 | _In_ PDRIVER_OBJECT DriverObject, 29 | _In_ PUNICODE_STRING RegistryPath 30 | ) 31 | /*++ 32 | 33 | Routine Description: 34 | DriverEntry initializes the driver and is the first routine called by the 35 | system after the driver is loaded. DriverEntry specifies the other entry 36 | points in the function driver, such as EvtDevice and DriverUnload. 37 | 38 | Parameters Description: 39 | 40 | DriverObject - represents the instance of the function driver that is loaded 41 | into memory. DriverEntry must initialize members of DriverObject before it 42 | returns to the caller. DriverObject is allocated by the system before the 43 | driver is loaded, and it is released by the system after the system unloads 44 | the function driver from memory. 45 | 46 | RegistryPath - represents the driver specific path in the Registry. 47 | The function driver can use the path to store driver related data between 48 | reboots. The path does not store hardware instance specific data. 49 | 50 | Return Value: 51 | 52 | STATUS_SUCCESS if successful, 53 | STATUS_UNSUCCESSFUL otherwise. 54 | 55 | --*/ 56 | { 57 | WDF_DRIVER_CONFIG config; 58 | NTSTATUS status; 59 | WDF_OBJECT_ATTRIBUTES attributes; 60 | 61 | // 62 | // Initialize WPP Tracing 63 | // 64 | WPP_INIT_TRACING(DriverObject, RegistryPath); 65 | 66 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); 67 | 68 | // 69 | // Register a cleanup callback so that we can call WPP_CLEANUP when 70 | // the framework driver object is deleted during driver unload. 71 | // 72 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 73 | attributes.EvtCleanupCallback = LumiaUSBCKmEvtDriverContextCleanup; 74 | 75 | WDF_DRIVER_CONFIG_INIT(&config, 76 | LumiaUSBCKmEvtDeviceAdd 77 | ); 78 | 79 | status = WdfDriverCreate(DriverObject, 80 | RegistryPath, 81 | &attributes, 82 | &config, 83 | WDF_NO_HANDLE 84 | ); 85 | 86 | if (!NT_SUCCESS(status)) { 87 | TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status); 88 | WPP_CLEANUP(DriverObject); 89 | return status; 90 | } 91 | 92 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); 93 | 94 | return status; 95 | } 96 | 97 | NTSTATUS 98 | LumiaUSBCKmEvtDeviceAdd( 99 | _In_ WDFDRIVER Driver, 100 | _Inout_ PWDFDEVICE_INIT DeviceInit 101 | ) 102 | /*++ 103 | Routine Description: 104 | 105 | EvtDeviceAdd is called by the framework in response to AddDevice 106 | call from the PnP manager. We create and initialize a device object to 107 | represent a new instance of the device. 108 | 109 | Arguments: 110 | 111 | Driver - Handle to a framework driver object created in DriverEntry 112 | 113 | DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. 114 | 115 | Return Value: 116 | 117 | NTSTATUS 118 | 119 | --*/ 120 | { 121 | NTSTATUS status; 122 | 123 | UNREFERENCED_PARAMETER(Driver); 124 | 125 | PAGED_CODE(); 126 | 127 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); 128 | 129 | status = LumiaUSBCKmCreateDevice(DeviceInit); 130 | 131 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); 132 | 133 | return status; 134 | } 135 | 136 | VOID 137 | LumiaUSBCKmEvtDriverContextCleanup( 138 | _In_ WDFOBJECT DriverObject 139 | ) 140 | /*++ 141 | Routine Description: 142 | 143 | Free all the resources allocated in DriverEntry. 144 | 145 | Arguments: 146 | 147 | DriverObject - handle to a WDF Driver object. 148 | 149 | Return Value: 150 | 151 | VOID. 152 | 153 | --*/ 154 | { 155 | UNREFERENCED_PARAMETER(DriverObject); 156 | 157 | PAGED_CODE(); 158 | 159 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); 160 | 161 | // 162 | // Stop WPP Tracing 163 | // 164 | WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); 165 | } 166 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /LumiaUSBCKm/LumiaUSBCKm.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {B20988AB-AFD4-4533-9F10-11E759EAE4C8} 55 | {497e31cb-056b-4f31-abb8-447fd55ee5a5} 56 | v4.5 57 | 12.0 58 | Debug 59 | Win32 60 | LumiaUSBCKm 61 | 62 | 63 | 64 | Windows10 65 | true 66 | WindowsKernelModeDriver10.0 67 | Driver 68 | KMDF 69 | Universal 70 | true 71 | 72 | 73 | Windows10 74 | false 75 | WindowsKernelModeDriver10.0 76 | Driver 77 | KMDF 78 | Universal 79 | 80 | 81 | Windows10 82 | true 83 | WindowsKernelModeDriver10.0 84 | Driver 85 | KMDF 86 | Universal 87 | 88 | 89 | Windows10 90 | false 91 | WindowsKernelModeDriver10.0 92 | Driver 93 | KMDF 94 | Universal 95 | 96 | 97 | Windows10 98 | true 99 | WindowsKernelModeDriver10.0 100 | Driver 101 | KMDF 102 | Universal 103 | 104 | 105 | Windows10 106 | false 107 | WindowsKernelModeDriver10.0 108 | Driver 109 | KMDF 110 | Universal 111 | 112 | 113 | Windows10 114 | true 115 | WindowsKernelModeDriver10.0 116 | Driver 117 | KMDF 118 | Universal 119 | true 120 | 121 | 122 | Windows10 123 | false 124 | WindowsKernelModeDriver10.0 125 | Driver 126 | KMDF 127 | Universal 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | DbgengKernelDebugger 139 | true 140 | 141 | 142 | DbgengKernelDebugger 143 | 144 | 145 | DbgengKernelDebugger 146 | 147 | 148 | DbgengKernelDebugger 149 | 150 | 151 | DbgengKernelDebugger 152 | 153 | 154 | DbgengKernelDebugger 155 | 156 | 157 | DbgengKernelDebugger 158 | true 159 | 160 | 161 | DbgengKernelDebugger 162 | 163 | 164 | 165 | true 166 | true 167 | trace.h 168 | true 169 | 170 | 171 | 172 | 173 | true 174 | true 175 | trace.h 176 | true 177 | 178 | 179 | 180 | 181 | true 182 | true 183 | trace.h 184 | true 185 | 186 | 187 | 188 | 189 | true 190 | true 191 | trace.h 192 | true 193 | 194 | 195 | 196 | 197 | true 198 | true 199 | trace.h 200 | true 201 | 202 | 203 | 204 | 205 | true 206 | true 207 | trace.h 208 | true 209 | 210 | 211 | 212 | 213 | true 214 | true 215 | trace.h 216 | true 217 | 218 | 219 | 220 | 221 | true 222 | true 223 | trace.h 224 | true 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /LumiaUSBCKm/Device.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Module Name: 4 | 5 | device.c - Device handling events for example driver. 6 | 7 | Abstract: 8 | 9 | This file contains the device entry points and callbacks. 10 | 11 | Environment: 12 | 13 | Kernel-mode Driver Framework 14 | 15 | --*/ 16 | 17 | #include "driver.h" 18 | #include "device.tmh" 19 | #define RESHUB_USE_HELPER_ROUTINES 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | EVT_WDF_DEVICE_PREPARE_HARDWARE LumiaUSBCDevicePrepareHardware; 26 | EVT_UCM_CONNECTOR_SET_DATA_ROLE LumiaUSBCSetDataRole; 27 | //EVT_WDF_DEVICE_D0_ENTRY LumiaUSBCDeviceD0Entry; 28 | 29 | NTSTATUS ReadRegister(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length); 30 | NTSTATUS WriteRegister(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length); 31 | NTSTATUS GetGPIO(PDEVICE_CONTEXT ctx, WDFIOTARGET gpio, unsigned char *value); 32 | NTSTATUS SetGPIO(PDEVICE_CONTEXT ctx, WDFIOTARGET gpio, unsigned char *value); 33 | 34 | #ifdef ALLOC_PRAGMA 35 | #pragma alloc_text (PAGE, LumiaUSBCKmCreateDevice) 36 | #pragma alloc_text (PAGE, LumiaUSBCDevicePrepareHardware) 37 | #pragma alloc_text (PAGE, LumiaUSBCSetDataRole) 38 | #endif 39 | 40 | NTSTATUS 41 | LumiaUSBCSetDataRole( 42 | UCMCONNECTOR Connector, 43 | UCM_DATA_ROLE DataRole 44 | ) 45 | { 46 | PCONNECTOR_CONTEXT connCtx; 47 | 48 | UNREFERENCED_PARAMETER(DataRole); 49 | 50 | connCtx = ConnectorGetContext(Connector); 51 | 52 | return STATUS_SUCCESS; 53 | } 54 | 55 | BOOLEAN EvtInterruptIsr( 56 | WDFINTERRUPT Interrupt, 57 | ULONG MessageID 58 | ) 59 | { 60 | UNREFERENCED_PARAMETER((Interrupt, MessageID)); 61 | 62 | WdfInterruptQueueWorkItemForIsr(Interrupt); 63 | 64 | return TRUE; 65 | } 66 | 67 | void Uc120InterruptWorkItem( 68 | WDFINTERRUPT Interrupt, 69 | WDFOBJECT AssociatedObject 70 | ) 71 | { 72 | UNREFERENCED_PARAMETER(Interrupt); 73 | PDEVICE_CONTEXT ctx = DeviceGetContext(AssociatedObject); 74 | unsigned char registers[8]; 75 | NTSTATUS statuses[8]; 76 | unsigned char dismiss = 0xFF; 77 | wchar_t buf[260]; 78 | //ULONG data = 0; 79 | 80 | DbgPrint("Got an interrupt from the UC120!\n"); 81 | 82 | memset(registers, 0, sizeof(registers)); 83 | memset(statuses, 0, sizeof(statuses)); 84 | 85 | statuses[0] = ReadRegister(ctx, 0, registers + 0, 1); 86 | statuses[1] = ReadRegister(ctx, 1, registers + 1, 1); 87 | statuses[2] = ReadRegister(ctx, 2, registers + 2, 1); 88 | statuses[3] = ReadRegister(ctx, 5, registers + 3, 1); 89 | statuses[4] = ReadRegister(ctx, 7, registers + 4, 1); 90 | statuses[5] = ReadRegister(ctx, 9, registers + 5, 1); 91 | statuses[6] = ReadRegister(ctx, 10, registers + 6, 1); 92 | statuses[7] = ReadRegister(ctx, 11, registers + 7, 1); 93 | 94 | WriteRegister(ctx, 2, &dismiss, 1); 95 | 96 | swprintf(buf, L"UC120_%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", registers[0], registers[1], registers[2], registers[3], registers[4], registers[5], registers[6], registers[7]); 97 | 98 | DbgPrint("%ls\n", buf); 99 | 100 | /*RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 101 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 102 | (PCWSTR)buf, 103 | REG_DWORD, 104 | &data, 105 | sizeof(ULONG));*/ 106 | 107 | swprintf(buf, L"S_UC120_%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x", statuses[0], statuses[1], statuses[2], statuses[3], statuses[4], statuses[5], statuses[6], statuses[7]); 108 | 109 | DbgPrint("%ls\n", buf); 110 | 111 | /*RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 112 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 113 | (PCWSTR)buf, 114 | REG_DWORD, 115 | &data, 116 | sizeof(ULONG));*/ 117 | } 118 | 119 | void PlugDetInterruptWorkItem( 120 | WDFINTERRUPT Interrupt, 121 | WDFOBJECT AssociatedObject 122 | ) 123 | { 124 | UNREFERENCED_PARAMETER(Interrupt); 125 | PDEVICE_CONTEXT ctx = DeviceGetContext(AssociatedObject); 126 | unsigned char registers[8]; 127 | NTSTATUS statuses[8]; 128 | // unsigned char dismiss = 0x1; 129 | wchar_t buf[260]; 130 | ULONG data = 0; 131 | 132 | memset(registers, 0, sizeof(registers)); 133 | memset(statuses, 0, sizeof(statuses)); 134 | 135 | statuses[0] = ReadRegister(ctx, 0, registers + 0, 1); 136 | statuses[1] = ReadRegister(ctx, 1, registers + 1, 1); 137 | statuses[2] = ReadRegister(ctx, 2, registers + 2, 1); 138 | statuses[3] = ReadRegister(ctx, 5, registers + 3, 1); 139 | statuses[4] = ReadRegister(ctx, 7, registers + 4, 1); 140 | statuses[5] = ReadRegister(ctx, 9, registers + 5, 1); 141 | statuses[6] = ReadRegister(ctx, 10, registers + 6, 1); 142 | statuses[7] = ReadRegister(ctx, 11, registers + 7, 1); 143 | 144 | //WriteRegister(ctx, 2, &dismiss, 1); 145 | 146 | swprintf(buf, L"PLUGDET_%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", registers[0], registers[1], registers[2], registers[3], registers[4], registers[5], registers[6], registers[7]); 147 | 148 | RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 149 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 150 | (PCWSTR)buf, 151 | REG_DWORD, 152 | &data, 153 | sizeof(ULONG)); 154 | 155 | swprintf(buf, L"S_PLUGDET_%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x", statuses[0], statuses[1], statuses[2], statuses[3], statuses[4], statuses[5], statuses[6], statuses[7]); 156 | 157 | RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 158 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 159 | (PCWSTR)buf, 160 | REG_DWORD, 161 | &data, 162 | sizeof(ULONG)); 163 | } 164 | 165 | NTSTATUS Uc120InterruptEnable( 166 | WDFINTERRUPT Interrupt, 167 | WDFDEVICE AssociatedDevice 168 | ) 169 | { 170 | NTSTATUS status = STATUS_SUCCESS; 171 | PDEVICE_CONTEXT ctx = DeviceGetContext(AssociatedDevice); 172 | unsigned char value; 173 | UNREFERENCED_PARAMETER(Interrupt); 174 | 175 | value = 0xFF; 176 | WriteRegister(ctx, 2, &value, 1); 177 | WriteRegister(ctx, 3, &value, 1); 178 | 179 | ReadRegister(ctx, 4, &value, 1); 180 | value |= 1; 181 | WriteRegister(ctx, 4, &value, 1); 182 | 183 | ReadRegister(ctx, 5, &value, 1); 184 | value &= ~0x80; 185 | WriteRegister(ctx, 5, &value, 1); 186 | 187 | return status; 188 | } 189 | 190 | NTSTATUS Uc120InterruptDisable( 191 | WDFINTERRUPT Interrupt, 192 | WDFDEVICE AssociatedDevice 193 | ) 194 | { 195 | NTSTATUS status = STATUS_SUCCESS; 196 | PDEVICE_CONTEXT ctx = DeviceGetContext(AssociatedDevice); 197 | unsigned char value; 198 | UNREFERENCED_PARAMETER(Interrupt); 199 | 200 | ReadRegister(ctx, 4, &value, 1); 201 | value &= ~1; 202 | WriteRegister(ctx, 4, &value, 1); 203 | 204 | return status; 205 | } 206 | 207 | NTSTATUS OpenIOTarget(PDEVICE_CONTEXT ctx, LARGE_INTEGER res, ACCESS_MASK use, WDFIOTARGET *target) 208 | { 209 | NTSTATUS status = STATUS_SUCCESS; 210 | WDF_OBJECT_ATTRIBUTES ObjectAttributes; 211 | WDF_IO_TARGET_OPEN_PARAMS OpenParams; 212 | UNICODE_STRING ReadString; 213 | WCHAR ReadStringBuffer[260]; 214 | 215 | DbgPrint("%!FUNC! Entry"); 216 | 217 | RtlInitEmptyUnicodeString(&ReadString, 218 | ReadStringBuffer, 219 | sizeof(ReadStringBuffer)); 220 | 221 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID(&ReadString, 222 | res.LowPart, 223 | res.HighPart); 224 | if (!NT_SUCCESS(status)) { 225 | DbgPrint("RESOURCE_HUB_CREATE_PATH_FROM_ID failed %!STATUS!\n", status); 226 | return status; 227 | } 228 | 229 | WDF_OBJECT_ATTRIBUTES_INIT(&ObjectAttributes); 230 | ObjectAttributes.ParentObject = ctx->Device; 231 | 232 | status = WdfIoTargetCreate(ctx->Device, &ObjectAttributes, target); 233 | if (!NT_SUCCESS(status)) { 234 | DbgPrint("WdfIoTargetCreate failed %!STATUS!\n", status); 235 | return status; 236 | } 237 | 238 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&OpenParams, &ReadString, use); 239 | status = WdfIoTargetOpen(*target, &OpenParams); 240 | if (!NT_SUCCESS(status)) { 241 | DbgPrint("WdfIoTargetOpen failed %!STATUS!\n", status); 242 | } 243 | 244 | DbgPrint("%!FUNC! Exit\n"); 245 | return status; 246 | } 247 | 248 | NTSTATUS 249 | LumiaUSBCProbeResources( 250 | PDEVICE_CONTEXT ctx, 251 | WDFCMRESLIST res, 252 | WDFCMRESLIST rawres 253 | ) 254 | { 255 | NTSTATUS status = STATUS_SUCCESS; 256 | PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; 257 | WDF_INTERRUPT_CONFIG Config; 258 | int k = 0, l = 0; 259 | int spi_found = 0; 260 | ctx->HaveResetGpio = FALSE; 261 | ctx->UseFakeSpi = FALSE; 262 | DbgPrint("%!FUNC! Entry\n"); 263 | 264 | for (unsigned int i = 0; i < WdfCmResourceListGetCount(res); i++) { 265 | desc = WdfCmResourceListGetDescriptor(res, i); 266 | switch (desc->Type) { 267 | 268 | case CmResourceTypeConnection: 269 | // 270 | // Handle memory resources here. 271 | // 272 | if (desc->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_GPIO && desc->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_GPIO_IO) { 273 | switch (k) { 274 | case 0: 275 | ctx->VbusGpioId.LowPart = desc->u.Connection.IdLowPart; 276 | ctx->VbusGpioId.HighPart = desc->u.Connection.IdHighPart; 277 | break; 278 | case 1: 279 | ctx->PolGpioId.LowPart = desc->u.Connection.IdLowPart; 280 | ctx->PolGpioId.HighPart = desc->u.Connection.IdHighPart; 281 | break; 282 | case 2: 283 | ctx->AmselGpioId.LowPart = desc->u.Connection.IdLowPart; 284 | ctx->AmselGpioId.HighPart = desc->u.Connection.IdHighPart; 285 | break; 286 | case 3: 287 | ctx->EnGpioId.LowPart = desc->u.Connection.IdLowPart; 288 | ctx->EnGpioId.HighPart = desc->u.Connection.IdHighPart; 289 | break; 290 | case 4: 291 | ctx->ResetGpioId.LowPart = desc->u.Connection.IdLowPart; 292 | ctx->ResetGpioId.HighPart = desc->u.Connection.IdHighPart; 293 | ctx->HaveResetGpio = TRUE; 294 | break; 295 | case 5: 296 | ctx->FakeSpiMosiId.LowPart = desc->u.Connection.IdLowPart; 297 | ctx->FakeSpiMosiId.HighPart = desc->u.Connection.IdHighPart; 298 | break; 299 | case 6: 300 | ctx->FakeSpiMisoId.LowPart = desc->u.Connection.IdLowPart; 301 | ctx->FakeSpiMisoId.HighPart = desc->u.Connection.IdHighPart; 302 | break; 303 | case 7: 304 | ctx->FakeSpiCsId.LowPart = desc->u.Connection.IdLowPart; 305 | ctx->FakeSpiCsId.HighPart = desc->u.Connection.IdHighPart; 306 | break; 307 | case 8: 308 | ctx->FakeSpiClkId.LowPart = desc->u.Connection.IdLowPart; 309 | ctx->FakeSpiClkId.HighPart = desc->u.Connection.IdHighPart; 310 | break; 311 | default: 312 | break; 313 | } 314 | 315 | k++; 316 | } 317 | 318 | if (desc->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && desc->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_SPI) { 319 | ctx->SpiId.LowPart = desc->u.Connection.IdLowPart; 320 | ctx->SpiId.HighPart = desc->u.Connection.IdHighPart; 321 | spi_found = 1; 322 | } 323 | break; 324 | 325 | case CmResourceTypeInterrupt: 326 | switch (l) 327 | { 328 | case 0: 329 | WDF_INTERRUPT_CONFIG_INIT(&Config, EvtInterruptIsr, NULL); 330 | //Config.PassiveHandling = TRUE; 331 | Config.EvtInterruptWorkItem = PlugDetInterruptWorkItem; 332 | Config.InterruptRaw = WdfCmResourceListGetDescriptor(rawres, i); 333 | Config.InterruptTranslated = desc; 334 | //status = WdfInterruptCreate(ctx->Device, &Config, WDF_NO_OBJECT_ATTRIBUTES, &ctx->PlugDetectInterrupt); 335 | if (!NT_SUCCESS(status)) { 336 | DbgPrint("WdfInterruptCreate failed for plug detection %!STATUS!\n", status); 337 | return status; 338 | } 339 | break; 340 | case 1: 341 | WDF_INTERRUPT_CONFIG_INIT(&Config, EvtInterruptIsr, NULL); 342 | Config.PassiveHandling = TRUE; 343 | Config.EvtInterruptWorkItem = Uc120InterruptWorkItem; 344 | Config.InterruptRaw = WdfCmResourceListGetDescriptor(rawres, i); 345 | Config.InterruptTranslated = desc; 346 | Config.EvtInterruptEnable = Uc120InterruptEnable; 347 | Config.EvtInterruptDisable = Uc120InterruptDisable; 348 | status = WdfInterruptCreate(ctx->Device, &Config, WDF_NO_OBJECT_ATTRIBUTES, &ctx->Uc120Interrupt); 349 | if (!NT_SUCCESS(status)) { 350 | DbgPrint("WdfInterruptCreate failed for UC120 interrupt %!STATUS!\n", status); 351 | return status; 352 | } 353 | break; 354 | default: 355 | break; 356 | } 357 | l++; 358 | break; 359 | default: 360 | // 361 | // Ignore all other descriptors. 362 | // 363 | break; 364 | } 365 | } 366 | 367 | if (!spi_found && k >= 8) { 368 | spi_found = 1; 369 | ctx->UseFakeSpi = TRUE; 370 | } 371 | 372 | if (!spi_found || k < 4) { 373 | DbgPrint("Not all resources were found, SPI = %d, GPIO = %d\n", spi_found, k); 374 | status = 0xC0000000 + 8 * spi_found + k; 375 | } 376 | 377 | DbgPrint("%!FUNC! Exit\n"); 378 | return status; 379 | } 380 | 381 | NTSTATUS 382 | LumiaUSBCOpenResources( 383 | PDEVICE_CONTEXT ctx 384 | ) 385 | { 386 | NTSTATUS status = STATUS_SUCCESS; 387 | DbgPrint("%!FUNC! Entry\n"); 388 | 389 | if (!(ctx->UseFakeSpi)) { 390 | status = OpenIOTarget(ctx, ctx->SpiId, GENERIC_READ | GENERIC_WRITE, &ctx->Spi); 391 | if (!NT_SUCCESS(status)) { 392 | DbgPrint("OpenIOTarget failed for SPI %!STATUS! Falling back to fake SPI.\n", status); 393 | ctx->UseFakeSpi = TRUE; 394 | status = STATUS_SUCCESS; // return status; 395 | } 396 | } 397 | 398 | status = OpenIOTarget(ctx, ctx->VbusGpioId, GENERIC_READ | GENERIC_WRITE, &ctx->VbusGpio); 399 | if (!NT_SUCCESS(status)) { 400 | DbgPrint("OpenIOTarget failed for VBUS GPIO %!STATUS!\n", status); 401 | return status; 402 | } 403 | 404 | status = OpenIOTarget(ctx, ctx->PolGpioId, GENERIC_READ | GENERIC_WRITE, &ctx->PolGpio); 405 | if (!NT_SUCCESS(status)) { 406 | DbgPrint("OpenIOTarget failed for polarity GPIO %!STATUS!\n", status); 407 | return status; 408 | } 409 | 410 | status = OpenIOTarget(ctx, ctx->AmselGpioId, GENERIC_READ | GENERIC_WRITE, &ctx->AmselGpio); 411 | if (!NT_SUCCESS(status)) { 412 | DbgPrint("OpenIOTarget failed for alternate mode selection GPIO %!STATUS!\n", status); 413 | return status; 414 | } 415 | 416 | status = OpenIOTarget(ctx, ctx->EnGpioId, GENERIC_READ | GENERIC_WRITE, &ctx->EnGpio); 417 | if (!NT_SUCCESS(status)) { 418 | DbgPrint("OpenIOTarget failed for mux enable GPIO %!STATUS!\n", status); 419 | return status; 420 | } 421 | 422 | if (ctx->HaveResetGpio) { 423 | status = OpenIOTarget(ctx, ctx->ResetGpioId, GENERIC_READ | GENERIC_WRITE, &ctx->ResetGpio); 424 | if (!(NT_SUCCESS(status))) { 425 | DbgPrint("OpenIOTarget failed for chip reset GPIO %!STATUS!\n", status); 426 | ctx->HaveResetGpio = FALSE; 427 | } 428 | status = STATUS_SUCCESS; // this GPIO is optional - make sure we never fail on it missing 429 | } 430 | 431 | if (ctx->UseFakeSpi) { 432 | status = OpenIOTarget(ctx, ctx->FakeSpiMosiId, GENERIC_READ | GENERIC_WRITE, &ctx->FakeSpiMosi); 433 | if (!NT_SUCCESS(status)) { 434 | DbgPrint("OpenIOTarget failed for fake SPI MOSI line %!STATUS!\n", status); 435 | return status; 436 | } 437 | status = OpenIOTarget(ctx, ctx->FakeSpiMisoId, GENERIC_READ | GENERIC_WRITE, &ctx->FakeSpiMiso); 438 | if (!NT_SUCCESS(status)) { 439 | DbgPrint("OpenIOTarget failed for fake SPI MISO line %!STATUS!\n", status); 440 | return status; 441 | } 442 | status = OpenIOTarget(ctx, ctx->FakeSpiCsId, GENERIC_READ | GENERIC_WRITE, &ctx->FakeSpiCs); 443 | if (!NT_SUCCESS(status)) { 444 | DbgPrint("OpenIOTarget failed for fake SPI CS# line %!STATUS!\n", status); 445 | return status; 446 | } 447 | status = OpenIOTarget(ctx, ctx->FakeSpiClkId, GENERIC_READ | GENERIC_WRITE, &ctx->FakeSpiClk); 448 | if (!NT_SUCCESS(status)) { 449 | DbgPrint("OpenIOTarget failed for fake SPI clock line %!STATUS!\n", status); 450 | return status; 451 | } 452 | } 453 | 454 | DbgPrint("%!FUNC! Exit\n"); 455 | return status; 456 | } 457 | 458 | void 459 | LumiaUSBCCloseResources( 460 | PDEVICE_CONTEXT ctx 461 | ) 462 | { 463 | DbgPrint("%!FUNC! Entry\n"); 464 | 465 | if (ctx->Spi) { 466 | WdfIoTargetClose(ctx->Spi); 467 | } 468 | 469 | if (ctx->VbusGpio) { 470 | WdfIoTargetClose(ctx->VbusGpio); 471 | } 472 | 473 | if (ctx->PolGpio) { 474 | WdfIoTargetClose(ctx->PolGpio); 475 | } 476 | 477 | if (ctx->AmselGpio) { 478 | WdfIoTargetClose(ctx->AmselGpio); 479 | } 480 | 481 | if (ctx->EnGpio) { 482 | WdfIoTargetClose(ctx->EnGpio); 483 | } 484 | 485 | if (ctx->ResetGpio) { 486 | WdfIoTargetClose(ctx->ResetGpio); 487 | } 488 | 489 | if (ctx->FakeSpiClk) { 490 | WdfIoTargetClose(ctx->FakeSpiClk); 491 | } 492 | 493 | if (ctx->FakeSpiCs) { 494 | WdfIoTargetClose(ctx->FakeSpiCs); 495 | } 496 | 497 | if (ctx->FakeSpiMiso) { 498 | WdfIoTargetClose(ctx->FakeSpiMiso); 499 | } 500 | 501 | if (ctx->FakeSpiMosi) { 502 | WdfIoTargetClose(ctx->FakeSpiMosi); 503 | } 504 | 505 | DbgPrint("%!FUNC! Exit\n"); 506 | } 507 | 508 | NTSTATUS LumiaUSBCDeviceD0Exit( 509 | WDFDEVICE Device, 510 | WDF_POWER_DEVICE_STATE TargetState 511 | ) 512 | { 513 | PDEVICE_CONTEXT devCtx = DeviceGetContext(Device); 514 | UNREFERENCED_PARAMETER(TargetState); 515 | 516 | LumiaUSBCCloseResources(devCtx); 517 | 518 | return STATUS_SUCCESS; 519 | } 520 | 521 | NTSTATUS LumiaUSBCDeviceReleaseHardware( 522 | WDFDEVICE Device, 523 | WDFCMRESLIST ResourcesTranslated 524 | ) 525 | { 526 | UNREFERENCED_PARAMETER((Device, ResourcesTranslated)); 527 | 528 | return STATUS_SUCCESS; 529 | } 530 | 531 | #define IOCTL_QUP_SPI_CS_MANIPULATION 0x610 532 | 533 | #define IOCTL_QUP_SPI_AUTO_CS CTL_CODE(FILE_DEVICE_CONTROLLER, IOCTL_QUP_SPI_CS_MANIPULATION | 0x2, METHOD_BUFFERED, FILE_ANY_ACCESS) 534 | #define IOCTL_QUP_SPI_ASSERT_CS CTL_CODE(FILE_DEVICE_CONTROLLER, IOCTL_QUP_SPI_CS_MANIPULATION | 0x1, METHOD_BUFFERED, FILE_ANY_ACCESS) 535 | #define IOCTL_QUP_SPI_DEASSERT_CS CTL_CODE(FILE_DEVICE_CONTROLLER, IOCTL_QUP_SPI_CS_MANIPULATION | 0x0, METHOD_BUFFERED, FILE_ANY_ACCESS) 536 | 537 | NTSTATUS ReadRegisterReal(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 538 | { 539 | NTSTATUS status = STATUS_SUCCESS; 540 | WDF_MEMORY_DESCRIPTOR regDescriptor, outputDescriptor; 541 | unsigned char command = (unsigned char)(reg << 3); 542 | 543 | WdfObjectAcquireLock(ctx->Device); 544 | 545 | status = WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_ASSERT_CS, NULL, NULL, NULL, NULL); 546 | if (!NT_SUCCESS(status)) 547 | { 548 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 549 | WdfObjectReleaseLock(ctx->Device); 550 | return status; 551 | } 552 | 553 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(®Descriptor, &command, 1); 554 | status = WdfIoTargetSendWriteSynchronously(ctx->Spi, NULL, ®Descriptor, NULL, NULL, NULL); 555 | if (!NT_SUCCESS(status)) 556 | { 557 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 558 | WdfObjectReleaseLock(ctx->Device); 559 | return status; 560 | } 561 | 562 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, value, length); 563 | 564 | // need to read 3 times to get the correct value, for some reason 565 | // NOTE: original driver does a full-duplex transfer here, where the 1st byte starts reading *before* 566 | // the register ID is written, so possibly we will need 2 here instead! 567 | for (int i = 0; i < 3; i++) { 568 | status = WdfIoTargetSendReadSynchronously(ctx->Spi, NULL, &outputDescriptor, NULL, NULL, NULL); 569 | 570 | if (!NT_SUCCESS(status)) 571 | { 572 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 573 | WdfObjectReleaseLock(ctx->Device); 574 | return status; 575 | } 576 | } 577 | 578 | status = WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 579 | 580 | WdfObjectReleaseLock(ctx->Device); 581 | 582 | return status; 583 | } 584 | 585 | NTSTATUS WriteRegisterReal(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 586 | { 587 | NTSTATUS status = STATUS_SUCCESS; 588 | WDF_MEMORY_DESCRIPTOR regDescriptor, inputDescriptor; 589 | unsigned char command = (unsigned char)((reg << 3) | 1); 590 | 591 | WdfObjectAcquireLock(ctx->Device); 592 | 593 | status = WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_ASSERT_CS, NULL, NULL, NULL, NULL); 594 | if (!NT_SUCCESS(status)) 595 | { 596 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 597 | WdfObjectReleaseLock(ctx->Device); 598 | return status; 599 | } 600 | 601 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(®Descriptor, &command, 1); 602 | status = WdfIoTargetSendWriteSynchronously(ctx->Spi, NULL, ®Descriptor, NULL, NULL, NULL); 603 | if (!NT_SUCCESS(status)) 604 | { 605 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 606 | WdfObjectReleaseLock(ctx->Device); 607 | return status; 608 | } 609 | 610 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDescriptor, value, length); 611 | status = WdfIoTargetSendWriteSynchronously(ctx->Spi, NULL, &inputDescriptor, NULL, NULL, NULL); 612 | if (!NT_SUCCESS(status)) 613 | { 614 | WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 615 | WdfObjectReleaseLock(ctx->Device); 616 | return status; 617 | } 618 | 619 | status = WdfIoTargetSendIoctlSynchronously(ctx->Spi, NULL, IOCTL_QUP_SPI_AUTO_CS, NULL, NULL, NULL, NULL); 620 | 621 | WdfObjectReleaseLock(ctx->Device); 622 | 623 | return status; 624 | } 625 | 626 | 627 | NTSTATUS GetGPIO(PDEVICE_CONTEXT ctx, WDFIOTARGET gpio, unsigned char *value) 628 | { 629 | NTSTATUS status = STATUS_SUCCESS; 630 | WDF_MEMORY_DESCRIPTOR outputDescriptor; 631 | 632 | UNREFERENCED_PARAMETER(ctx); 633 | 634 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, value, 1); 635 | 636 | status = WdfIoTargetSendIoctlSynchronously(gpio, NULL, IOCTL_GPIO_READ_PINS, NULL, &outputDescriptor, NULL, NULL); 637 | 638 | return status; 639 | } 640 | 641 | NTSTATUS SetGPIO(PDEVICE_CONTEXT ctx, WDFIOTARGET gpio, unsigned char *value) 642 | { 643 | NTSTATUS status = STATUS_SUCCESS; 644 | WDF_MEMORY_DESCRIPTOR inputDescriptor, outputDescriptor; 645 | 646 | UNREFERENCED_PARAMETER(ctx); 647 | 648 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDescriptor, value, 1); 649 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, value, 1); 650 | 651 | status = WdfIoTargetSendIoctlSynchronously(gpio, NULL, IOCTL_GPIO_WRITE_PINS, &inputDescriptor, &outputDescriptor, NULL, NULL); 652 | 653 | return status; 654 | } 655 | 656 | NTSTATUS ReadRegisterFake(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 657 | { 658 | NTSTATUS status; 659 | unsigned char data; 660 | unsigned char command = (unsigned char)(reg << 3); 661 | LARGE_INTEGER delay; 662 | int i; 663 | unsigned int j; 664 | 665 | delay.QuadPart = -10; // 1ms 666 | 667 | // Select the chip 668 | data = 0; 669 | status = SetGPIO(ctx, ctx->FakeSpiCs, &data); 670 | if (!NT_SUCCESS(status)) 671 | return status; 672 | 673 | // Send the read command bit by bit, MSB first 674 | for (i = 7; i >= 0; i--) { 675 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 676 | 677 | data = (command >> i) & 1; 678 | status = SetGPIO(ctx, ctx->FakeSpiMosi, &data); 679 | if (!NT_SUCCESS(status)) 680 | return status; 681 | 682 | data = 0; 683 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 684 | if (!NT_SUCCESS(status)) 685 | return status; 686 | 687 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 688 | 689 | data = 1; 690 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 691 | if (!NT_SUCCESS(status)) 692 | return status; 693 | } 694 | 695 | // Receive the result, MSB first 696 | for (j = 0; j < length; j++) { 697 | value[j] = 0; 698 | for (i = 7; i >= 0; i--) { 699 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 700 | 701 | data = 0; 702 | status = GetGPIO(ctx, ctx->FakeSpiMiso, &data); 703 | if (!NT_SUCCESS(status)) 704 | return status; 705 | 706 | value[j] |= (data & 1) << i; 707 | 708 | data = 0; 709 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 710 | if (!NT_SUCCESS(status)) 711 | return status; 712 | 713 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 714 | 715 | data = 1; 716 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 717 | if (!NT_SUCCESS(status)) 718 | return status; 719 | } 720 | } 721 | 722 | // Deselect the chip 723 | data = 1; 724 | status = SetGPIO(ctx, ctx->FakeSpiCs, &data); 725 | if (!NT_SUCCESS(status)) 726 | return status; 727 | 728 | return status; 729 | } 730 | 731 | NTSTATUS WriteRegisterFake(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 732 | { 733 | NTSTATUS status; 734 | unsigned char data; 735 | unsigned char command = (unsigned char)((reg << 3) | 1); 736 | LARGE_INTEGER delay; 737 | int i; 738 | unsigned int j; 739 | 740 | delay.QuadPart = -10; // 1ms 741 | 742 | // Select the chip 743 | data = 0; 744 | status = SetGPIO(ctx, ctx->FakeSpiCs, &data); 745 | if (!NT_SUCCESS(status)) 746 | return status; 747 | 748 | // Send the write command bit by bit, MSB first 749 | for (i = 7; i >= 0; i--) { 750 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 751 | 752 | data = (command >> i) & 1; 753 | status = SetGPIO(ctx, ctx->FakeSpiMosi, &data); 754 | if (!NT_SUCCESS(status)) 755 | return status; 756 | 757 | data = 0; 758 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 759 | if (!NT_SUCCESS(status)) 760 | return status; 761 | 762 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 763 | 764 | data = 1; 765 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 766 | if (!NT_SUCCESS(status)) 767 | return status; 768 | } 769 | 770 | // Send the data, MSB 771 | for (j = 0; j < length; j++) { 772 | for (i = 7; i >= 0; i--) { 773 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 774 | 775 | data = (value[j] >> i) & 1; 776 | status = SetGPIO(ctx, ctx->FakeSpiMosi, &data); 777 | if (!NT_SUCCESS(status)) 778 | return status; 779 | 780 | data = 0; 781 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 782 | if (!NT_SUCCESS(status)) 783 | return status; 784 | 785 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 786 | 787 | data = 1; 788 | status = SetGPIO(ctx, ctx->FakeSpiClk, &data); 789 | if (!NT_SUCCESS(status)) 790 | return status; 791 | } 792 | } 793 | 794 | // Deselect the chip 795 | data = 1; 796 | status = SetGPIO(ctx, ctx->FakeSpiCs, &data); 797 | if (!NT_SUCCESS(status)) 798 | return status; 799 | 800 | return status; 801 | } 802 | 803 | NTSTATUS ReadRegister(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 804 | { 805 | if (ctx->UseFakeSpi) 806 | return ReadRegisterFake(ctx, reg, value, length); 807 | else 808 | return ReadRegisterReal(ctx, reg, value, length); 809 | } 810 | 811 | NTSTATUS WriteRegister(PDEVICE_CONTEXT ctx, int reg, unsigned char *value, ULONG length) 812 | { 813 | if (ctx->UseFakeSpi) 814 | return WriteRegisterFake(ctx, reg, value, length); 815 | else 816 | return WriteRegisterReal(ctx, reg, value, length); 817 | } 818 | 819 | NTSTATUS 820 | LumiaUSBCDevicePrepareHardware( 821 | WDFDEVICE Device, 822 | WDFCMRESLIST ResourcesRaw, 823 | WDFCMRESLIST ResourcesTranslated 824 | ) 825 | { 826 | NTSTATUS status = STATUS_SUCCESS; 827 | PDEVICE_CONTEXT devCtx; 828 | UCM_MANAGER_CONFIG ucmCfg; 829 | UCM_CONNECTOR_CONFIG connCfg; 830 | UCM_CONNECTOR_TYPEC_CONFIG typeCConfig; 831 | UCM_CONNECTOR_PD_CONFIG pdConfig; 832 | WDF_OBJECT_ATTRIBUTES attr; 833 | 834 | DbgPrint("%!FUNC! Entry\n"); 835 | 836 | devCtx = DeviceGetContext(Device); 837 | 838 | status = LumiaUSBCProbeResources(devCtx, ResourcesTranslated, ResourcesRaw); 839 | if (!NT_SUCCESS(status)) { 840 | DbgPrint("LumiaUSBCProbeResources failed %!STATUS!\n", status); 841 | return status; 842 | } 843 | 844 | if (devCtx->Connector) 845 | { 846 | goto Exit; 847 | } 848 | 849 | // 850 | // Initialize UCM Manager 851 | // 852 | UCM_MANAGER_CONFIG_INIT(&ucmCfg); 853 | 854 | status = UcmInitializeDevice(Device, &ucmCfg); 855 | if (!NT_SUCCESS(status)) 856 | { 857 | DbgPrint("UcmInitializeDevice failed %!STATUS!\n", status); 858 | goto Exit; 859 | } 860 | 861 | // 862 | // Create a USB Type-C connector #0 with PD 863 | // 864 | UCM_CONNECTOR_CONFIG_INIT(&connCfg, 0); 865 | 866 | UCM_CONNECTOR_TYPEC_CONFIG_INIT( 867 | &typeCConfig, 868 | UcmTypeCOperatingModeDrp, 869 | UcmTypeCCurrentDefaultUsb); 870 | 871 | typeCConfig.EvtSetDataRole = LumiaUSBCSetDataRole; 872 | 873 | UCM_CONNECTOR_PD_CONFIG_INIT(&pdConfig, UcmPowerRoleSink | UcmPowerRoleSource); 874 | 875 | connCfg.TypeCConfig = &typeCConfig; 876 | connCfg.PdConfig = &pdConfig; 877 | 878 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CONNECTOR_CONTEXT); 879 | 880 | status = UcmConnectorCreate(Device, &connCfg, &attr, &devCtx->Connector); 881 | if (!NT_SUCCESS(status)) 882 | { 883 | DbgPrint("UcmConnectorCreate failed %!STATUS!\n", status); 884 | goto Exit; 885 | } 886 | 887 | //UcmEventInitialize(&connCtx->EventSetDataRole); 888 | Exit: 889 | DbgPrint("%!FUNC! Exit\n"); 890 | return status; 891 | } 892 | 893 | // I can't believe RtlWriteRegistryValue exists, but not RtlReadRegistryValue... 894 | NTSTATUS MyReadRegistryValue(PCWSTR registry_path, PCWSTR value_name, ULONG type, 895 | PVOID data, ULONG length) 896 | { 897 | UNICODE_STRING valname; 898 | UNICODE_STRING keyname; 899 | OBJECT_ATTRIBUTES attribs; 900 | PKEY_VALUE_PARTIAL_INFORMATION pinfo; 901 | HANDLE handle; 902 | NTSTATUS rc; 903 | ULONG len, reslen; 904 | 905 | RtlInitUnicodeString(&keyname, registry_path); 906 | RtlInitUnicodeString(&valname, value_name); 907 | 908 | InitializeObjectAttributes(&attribs, &keyname, OBJ_CASE_INSENSITIVE, 909 | NULL, NULL); 910 | rc = ZwOpenKey(&handle, KEY_QUERY_VALUE, &attribs); 911 | if (!NT_SUCCESS(rc)) 912 | return 0; 913 | 914 | len = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + length; 915 | pinfo = ExAllocatePool(NonPagedPool, len); 916 | rc = ZwQueryValueKey(handle, &valname, KeyValuePartialInformation, 917 | pinfo, len, &reslen); 918 | if ((NT_SUCCESS(rc) || rc == STATUS_BUFFER_OVERFLOW) && 919 | reslen >= (sizeof(KEY_VALUE_PARTIAL_INFORMATION) - 1) && 920 | (!type || pinfo->Type == type)) 921 | { 922 | reslen = pinfo->DataLength; 923 | memcpy(data, pinfo->Data, min(length, reslen)); 924 | } 925 | else 926 | reslen = 0; 927 | ExFreePool(pinfo); 928 | 929 | ZwClose(handle); 930 | return rc; 931 | } 932 | 933 | NTSTATUS LumiaUSBCDeviceD0Entry( 934 | WDFDEVICE Device, 935 | WDF_POWER_DEVICE_STATE PreviousState 936 | ) 937 | { 938 | NTSTATUS status = STATUS_SUCCESS; 939 | PDEVICE_CONTEXT devCtx = DeviceGetContext(Device); 940 | //PCONNECTOR_CONTEXT connCtx = ConnectorGetContext(devCtx->Connector); 941 | ULONG data = 0; 942 | UNREFERENCED_PARAMETER(PreviousState); 943 | 944 | DbgPrint("%!FUNC! Entry\n"); 945 | 946 | status = LumiaUSBCOpenResources(devCtx); 947 | if (!NT_SUCCESS(status)) { 948 | DbgPrint("LumiaUSBCOpenResources failed %!STATUS!\n", status); 949 | return status; 950 | } 951 | 952 | UCM_CONNECTOR_TYPEC_ATTACH_PARAMS Params; 953 | UCM_CONNECTOR_TYPEC_ATTACH_PARAMS_INIT(&Params, UcmTypeCPartnerUfp); 954 | Params.CurrentAdvertisement = UcmTypeCCurrentDefaultUsb; 955 | UcmConnectorTypeCAttach(devCtx->Connector, &Params); 956 | 957 | unsigned char value = (unsigned char)0; 958 | 959 | SetGPIO(devCtx, devCtx->PolGpio, &value); 960 | SetGPIO(devCtx, devCtx->AmselGpio, &value); // high = HDMI only, medium (unsupported) = USB only, low = both 961 | value = (unsigned char)1; 962 | SetGPIO(devCtx, devCtx->EnGpio, &value); 963 | /* 964 | SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 965 | if (devCtx->HaveResetGpio) { 966 | delay.QuadPart = -2000; // 200us 967 | value = (unsigned char)0; 968 | SetGPIO(devCtx, devCtx->ResetGpio, &value); 969 | SetGPIO(devCtx, devCtx->FakeSpiCs, &value); 970 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 971 | value = (unsigned char)1; 972 | SetGPIO(devCtx, devCtx->ResetGpio, &value); 973 | 974 | delay.QuadPart = -12000; // 1200us 975 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 976 | 977 | delay.QuadPart = -10; // 1us 978 | value = (unsigned char)1; 979 | SetGPIO(devCtx, devCtx->FakeSpiCs, &value); 980 | 981 | for (i = 0; i < 8; i++) { 982 | value = (unsigned char)0; 983 | SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 984 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 985 | value = (unsigned char)1; 986 | SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 987 | KeDelayExecutionThread(KernelMode, TRUE, &delay); 988 | } 989 | 990 | value = (unsigned char)0; 991 | SetGPIO(devCtx, devCtx->FakeSpiCs, &value); 992 | 993 | for (i = 0; i < 71339; i++) { 994 | for (j = 7; j >= 0; j--) { 995 | //KeDelayExecutionThread(KernelMode, TRUE, &delay); 996 | 997 | value = (unsigned char)((bitstream[i] >> j) & 1); 998 | status = SetGPIO(devCtx, devCtx->FakeSpiMosi, &value); 999 | if (!NT_SUCCESS(status)) 1000 | return status; 1001 | 1002 | value = (unsigned char)0; 1003 | status = SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 1004 | if (!NT_SUCCESS(status)) 1005 | return status; 1006 | 1007 | //KeDelayExecutionThread(KernelMode, TRUE, &delay); 1008 | 1009 | value = (unsigned char)1; 1010 | status = SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 1011 | if (!NT_SUCCESS(status)) 1012 | return status; 1013 | } 1014 | } 1015 | 1016 | for (i = 0; i < 150; i++) { 1017 | value = (unsigned char)0; 1018 | SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 1019 | //KeDelayExecutionThread(KernelMode, TRUE, &delay); 1020 | value = (unsigned char)1; 1021 | SetGPIO(devCtx, devCtx->FakeSpiClk, &value); 1022 | //KeDelayExecutionThread(KernelMode, TRUE, &delay); 1023 | } 1024 | } 1025 | */ 1026 | if (!NT_SUCCESS(MyReadRegistryValue( 1027 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 1028 | (PCWSTR)L"VbusEnable", 1029 | REG_DWORD, 1030 | &data, 1031 | sizeof(ULONG)))) 1032 | { 1033 | data = 0; 1034 | } 1035 | value = !!data; 1036 | SetGPIO(devCtx, devCtx->VbusGpio, &value); 1037 | if (data) { 1038 | UCM_PD_POWER_DATA_OBJECT Pdos[1]; 1039 | UCM_PD_POWER_DATA_OBJECT_INIT_FIXED(&Pdos[0]); 1040 | 1041 | Pdos[0].FixedSupplyPdo.VoltageIn50mV = 100; // 5V 1042 | Pdos[0].FixedSupplyPdo.MaximumCurrentIn10mA = 50; // 500 mA 1043 | UcmConnectorPdSourceCaps(devCtx->Connector, Pdos, 1); 1044 | UCM_CONNECTOR_PD_CONN_STATE_CHANGED_PARAMS PdParams; 1045 | UCM_CONNECTOR_PD_CONN_STATE_CHANGED_PARAMS_INIT(&PdParams, UcmPdConnStateNotSupported); 1046 | PdParams.ChargingState = UcmChargingStateNotCharging; 1047 | UcmConnectorPdConnectionStateChanged(devCtx->Connector, &PdParams); 1048 | UcmConnectorPowerDirectionChanged(devCtx->Connector, TRUE, UcmPowerRoleSource); 1049 | UcmConnectorChargingStateChanged(devCtx->Connector, PdParams.ChargingState); 1050 | } 1051 | else 1052 | { 1053 | UCM_PD_POWER_DATA_OBJECT Pdos[1]; 1054 | UCM_PD_POWER_DATA_OBJECT_INIT_FIXED(&Pdos[0]); 1055 | 1056 | Pdos[0].FixedSupplyPdo.VoltageIn50mV = 100; // 5V 1057 | Pdos[0].FixedSupplyPdo.MaximumCurrentIn10mA = 50; // 500 mA - can be overridden in Registry 1058 | if (NT_SUCCESS(MyReadRegistryValue( 1059 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 1060 | (PCWSTR)L"ChargeCurrent", 1061 | REG_DWORD, 1062 | &data, 1063 | sizeof(ULONG)))) 1064 | { 1065 | Pdos[0].FixedSupplyPdo.MaximumCurrentIn10mA = data / 10; 1066 | } 1067 | UcmConnectorPdPartnerSourceCaps(devCtx->Connector, Pdos, 1); 1068 | UCM_CONNECTOR_PD_CONN_STATE_CHANGED_PARAMS PdParams; 1069 | UCM_CONNECTOR_PD_CONN_STATE_CHANGED_PARAMS_INIT(&PdParams, UcmPdConnStateNotSupported); 1070 | PdParams.ChargingState = UcmChargingStateNominalCharging; 1071 | UcmConnectorPdConnectionStateChanged(devCtx->Connector, &PdParams); 1072 | UcmConnectorPowerDirectionChanged(devCtx->Connector, TRUE, UcmPowerRoleSink); 1073 | UcmConnectorTypeCCurrentAdChanged(devCtx->Connector, UcmTypeCCurrent3000mA); 1074 | UcmConnectorChargingStateChanged(devCtx->Connector, PdParams.ChargingState); 1075 | } 1076 | 1077 | return status; 1078 | } 1079 | 1080 | NTSTATUS LumiaUSBCSelfManagedIoInit( 1081 | WDFDEVICE Device 1082 | ) 1083 | { 1084 | NTSTATUS status = STATUS_SUCCESS; 1085 | PDEVICE_CONTEXT devCtx = DeviceGetContext(Device); 1086 | wchar_t buf[260]; 1087 | unsigned char value = (unsigned char)0; 1088 | ULONG input[8], output[6]; 1089 | LARGE_INTEGER delay; 1090 | LONG i = 0;// , j = 0; 1091 | PO_FX_DEVICE poFxDevice; 1092 | PO_FX_COMPONENT_IDLE_STATE idleState; 1093 | 1094 | memset(&poFxDevice, 0, sizeof(poFxDevice)); 1095 | memset(&idleState, 0, sizeof(idleState)); 1096 | poFxDevice.Version = PO_FX_VERSION_V1; 1097 | poFxDevice.ComponentCount = 1; 1098 | poFxDevice.Components[0].IdleStateCount = 1; 1099 | poFxDevice.Components[0].IdleStates = &idleState; 1100 | poFxDevice.DeviceContext = devCtx; 1101 | idleState.NominalPower = PO_FX_UNKNOWN_POWER; 1102 | 1103 | status = PoFxRegisterDevice(WdfDeviceWdmGetPhysicalDevice(Device), &poFxDevice, &devCtx->PoHandle); 1104 | if (!NT_SUCCESS(status)) { 1105 | DbgPrint("PoFxRegisterDevice failed %!STATUS!\n", status); 1106 | return status; 1107 | } 1108 | 1109 | PoFxActivateComponent(devCtx->PoHandle, 0, PO_FX_FLAG_BLOCKING); 1110 | 1111 | PoFxStartDevicePowerManagement(devCtx->PoHandle); 1112 | 1113 | // Tell PEP to turn on the clock 1114 | memset(input, 0, sizeof(input)); 1115 | input[0] = 2; 1116 | input[7] = 2; 1117 | status = PoFxPowerControl(devCtx->PoHandle, &PowerControlGuid, &input, sizeof(input), &output, sizeof(output), NULL); 1118 | if (!NT_SUCCESS(status)) { 1119 | DbgPrint("PoFxPowerControl failed %!STATUS!\n", status); 1120 | return status; 1121 | } 1122 | 1123 | // Initialize the UC120 1124 | unsigned char initvals[] = { 0x0C, 0x7C, 0x31, 0x5E, 0x9D, 0x0A, 0x7A, 0x2F, 0x5C, 0x9B }; 1125 | 1126 | //ReadRegister(devCtx, 4, &value, 1); 1127 | value = 6; 1128 | WriteRegister(devCtx, 4, &value, 1); 1129 | 1130 | //ReadRegister(devCtx, 5, &value, 1); 1131 | value = 0x88; 1132 | WriteRegister(devCtx, 5, &value, 1); 1133 | 1134 | //ReadRegister(devCtx, 13, &value, 1); 1135 | value = 2; 1136 | WriteRegister(devCtx, 13, &value, 1); 1137 | 1138 | WriteRegister(devCtx, 18, initvals + 0, 1); 1139 | WriteRegister(devCtx, 19, initvals + 1, 1); 1140 | WriteRegister(devCtx, 20, initvals + 2, 1); 1141 | WriteRegister(devCtx, 21, initvals + 3, 1); 1142 | WriteRegister(devCtx, 26, initvals + 4, 1); 1143 | WriteRegister(devCtx, 22, initvals + 5, 1); 1144 | WriteRegister(devCtx, 23, initvals + 6, 1); 1145 | WriteRegister(devCtx, 24, initvals + 7, 1); 1146 | WriteRegister(devCtx, 25, initvals + 8, 1); 1147 | WriteRegister(devCtx, 27, initvals + 9, 1); 1148 | 1149 | value = 0; 1150 | 1151 | delay.QuadPart = -1000000; 1152 | KeDelayExecutionThread(UserMode, TRUE, &delay); 1153 | delay.QuadPart = -100000; 1154 | do { 1155 | if (!NT_SUCCESS(ReadRegister(devCtx, 5, &value, 1))) 1156 | DbgPrint("Failed to read register #5 in the init waiting loop!\n"); 1157 | KeDelayExecutionThread(UserMode, TRUE, &delay); 1158 | i++; 1159 | if (i > 500) { 1160 | break; 1161 | } 1162 | } while (value == 0); 1163 | 1164 | DbgPrint("UC120 initialized after %d iterations with value of %x\n", i, value); 1165 | 1166 | /*i |= value << 16; 1167 | 1168 | RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 1169 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 1170 | (PCWSTR)L"startdelay", 1171 | REG_DWORD, 1172 | &i, 1173 | sizeof(ULONG));*/ 1174 | 1175 | unsigned char registers[8]; 1176 | NTSTATUS statuses[8]; 1177 | 1178 | memset(registers, 0, sizeof(registers)); 1179 | memset(statuses, 0, sizeof(statuses)); 1180 | 1181 | statuses[0] = ReadRegister(devCtx, 0, registers + 0, 1); 1182 | statuses[1] = ReadRegister(devCtx, 1, registers + 1, 1); 1183 | statuses[2] = ReadRegister(devCtx, 2, registers + 2, 1); 1184 | statuses[3] = ReadRegister(devCtx, 5, registers + 3, 1); 1185 | statuses[4] = ReadRegister(devCtx, 7, registers + 4, 1); 1186 | statuses[5] = ReadRegister(devCtx, 9, registers + 5, 1); 1187 | statuses[6] = ReadRegister(devCtx, 10, registers + 6, 1); 1188 | statuses[7] = ReadRegister(devCtx, 11, registers + 7, 1); 1189 | swprintf(buf, L"INIT_%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", registers[0], registers[1], registers[2], registers[3], registers[4], registers[5], registers[6], registers[7]); 1190 | DbgPrint("%ls\n", buf); 1191 | 1192 | /*RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 1193 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 1194 | (PCWSTR)buf, 1195 | REG_DWORD, 1196 | &data, 1197 | sizeof(ULONG));*/ 1198 | 1199 | swprintf(buf, L"S_INIT_%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x", statuses[0], statuses[1], statuses[2], statuses[3], statuses[4], statuses[5], statuses[6], statuses[7]); 1200 | DbgPrint("%ls\n", buf); 1201 | 1202 | /*RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, 1203 | (PCWSTR)L"\\Registry\\Machine\\System\\usbc", 1204 | (PCWSTR)buf, 1205 | REG_DWORD, 1206 | &data, 1207 | sizeof(ULONG));*/ 1208 | 1209 | DbgPrint("%!FUNC! Exit\n"); 1210 | return status; 1211 | } 1212 | 1213 | NTSTATUS 1214 | LumiaUSBCKmCreateDevice( 1215 | _Inout_ PWDFDEVICE_INIT DeviceInit 1216 | ) 1217 | /*++ 1218 | 1219 | Routine Description: 1220 | 1221 | Worker routine called to create a device and its software resources. 1222 | 1223 | Arguments: 1224 | 1225 | DeviceInit - Pointer to an opaque init structure. Memory for this 1226 | structure will be freed by the framework when the WdfDeviceCreate 1227 | succeeds. So don't access the structure after that point. 1228 | 1229 | Return Value: 1230 | 1231 | NTSTATUS 1232 | 1233 | --*/ 1234 | { 1235 | WDF_OBJECT_ATTRIBUTES deviceAttributes; 1236 | WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; 1237 | PDEVICE_CONTEXT deviceContext; 1238 | WDFDEVICE device; 1239 | UCM_MANAGER_CONFIG ucmConfig; 1240 | NTSTATUS status; 1241 | 1242 | PAGED_CODE(); 1243 | 1244 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); 1245 | pnpPowerCallbacks.EvtDevicePrepareHardware = LumiaUSBCDevicePrepareHardware; 1246 | pnpPowerCallbacks.EvtDeviceReleaseHardware = LumiaUSBCDeviceReleaseHardware; 1247 | pnpPowerCallbacks.EvtDeviceD0Entry = LumiaUSBCDeviceD0Entry; 1248 | pnpPowerCallbacks.EvtDeviceD0Exit = LumiaUSBCDeviceD0Exit; 1249 | pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = LumiaUSBCSelfManagedIoInit; 1250 | //pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = Fdo_EvtDeviceSelfManagedIoRestart; 1251 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); 1252 | 1253 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); 1254 | 1255 | status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); 1256 | 1257 | if (NT_SUCCESS(status)) { 1258 | // 1259 | // Get a pointer to the device context structure that we just associated 1260 | // with the device object. We define this structure in the device.h 1261 | // header file. DeviceGetContext is an inline function generated by 1262 | // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h. 1263 | // This function will do the type checking and return the device context. 1264 | // If you pass a wrong object handle it will return NULL and assert if 1265 | // run under framework verifier mode. 1266 | // 1267 | deviceContext = DeviceGetContext(device); 1268 | 1269 | // 1270 | // Initialize the context. 1271 | // 1272 | deviceContext->Device = device; 1273 | deviceContext->Connector = NULL; 1274 | 1275 | UCM_MANAGER_CONFIG_INIT(&ucmConfig); 1276 | status = UcmInitializeDevice(device, &ucmConfig); 1277 | if (!NT_SUCCESS(status)) 1278 | return status; 1279 | 1280 | /*WDF_POWER_FRAMEWORK_SETTINGS poFxSettings; 1281 | 1282 | WDF_POWER_FRAMEWORK_SETTINGS_INIT(&poFxSettings); 1283 | 1284 | poFxSettings.EvtDeviceWdmPostPoFxRegisterDevice = LumiaUSBCPostPoFxRegisterDevice; 1285 | poFxSettings.ComponentActiveConditionCallback = LumiaUSBCActiveConditionCallback; 1286 | 1287 | poFxSettings.Component = NULL;// &component; 1288 | poFxSettings.PoFxDeviceContext = (PVOID)device; 1289 | 1290 | status = WdfDeviceWdmAssignPowerFrameworkSettings(device, &poFxSettings); 1291 | if (!NT_SUCCESS(status)) { 1292 | return status; 1293 | }*/ 1294 | 1295 | WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; 1296 | 1297 | WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT( 1298 | &idleSettings, 1299 | IdleCannotWakeFromS0 1300 | ); 1301 | idleSettings.IdleTimeoutType = DriverManagedIdleTimeout; 1302 | 1303 | status = WdfDeviceAssignS0IdleSettings( 1304 | device, 1305 | &idleSettings 1306 | ); 1307 | if (!NT_SUCCESS(status)) { 1308 | return status; 1309 | } 1310 | 1311 | // 1312 | // Create a device interface so that applications can find and talk 1313 | // to us. 1314 | // 1315 | /*status = WdfDeviceCreateDeviceInterface( 1316 | device, 1317 | &GUID_DEVINTERFACE_LumiaUSBCKm, 1318 | NULL // ReferenceString 1319 | ); 1320 | 1321 | if (NT_SUCCESS(status)) { 1322 | // 1323 | // Initialize the I/O Package and any Queues 1324 | // 1325 | status = LumiaUSBCKmQueueInitialize(device); 1326 | }*/ 1327 | } 1328 | 1329 | return status; 1330 | } 1331 | --------------------------------------------------------------------------------