Skip to content

Instantly share code, notes, and snippets.

@jdoubleu
Last active January 25, 2024 21:44
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jdoubleu/048bd96971164ada3737e0964bb810f3 to your computer and use it in GitHub Desktop.
Save jdoubleu/048bd96971164ada3737e0964bb810f3 to your computer and use it in GitHub Desktop.
Windows RNDIS driver for Linux/RaspberryPi

Fix USB connection from Raspberry Pi on Windows

Following this tutorial https://gist.github.com/gbaman/975e2db164b3ca2b51ae11e45e8fd40a, many had problems connecting their Raspberry Pi's via OTG on Windows. Unfortunately, most of the linked drivers aren't available anymore.

Why doesn't it work out of the box?

As far as I understood, Windows only accepts signed drivers. It works with drivers from e.g. Acer though, because they provide signed drivers. The below tutorial shows how you can create/sign your own driver.

Create your own driver

  1. Create your own driver
  2. Download the driver .inf file from: https://github.com/torvalds/linux/blob/master/Documentation/usb/linux.inf
  3. Add a new entry CatalogFile inside [Version] section, pointing to a .cat file with the same name.
  4. Run PowerShell as Administrator
  5. Type .\DriverHelper.ps1 -Mode Sign -InfFile .\linux.inf
  6. Install the driver
  7. Open the device manager and locate the Raspberry Pi (usually under "Ports (COM &LPT)").
  8. Right click that device and select "Update driver"
  9. Choose "Browse my computer for driver software" and locate the directory of the .inf file.

ATTENTION: This will create a self-signed certificate and store it in your trusted root certificates store. You can remove it by running .\DriverHelper.ps1 -Mode UntrustCertificates -InfFile .\linux.inf.

Manage certificates

  1. Either open PowerShell or the "Run Command" Windows app
  2. Run mmc.exe
  3. Navigate to File > Add or Remove Snap-ins
  4. Select "Certificates" on the left and click "Add".
  5. Now select "Computer Account", press "Next" and then "Finish"
  6. Click "Ok".

The previously created certificate has been add to the following stores:

  • Personal
  • Trusted Root Certificate Authorities
  • Trusted Publishers

By default, the common name linux.local was used. You can change that by providing -CommonName "example.local" to the script.

# script parameters
param(
[ValidateSet("Sign", "UntrustCertificates")]
[string] $Mode = "Sign",
[string] $InfFile,
[string] $CommonName = "linux.local",
[switch] $Force
)
$ErrorActionPreference = "Stop"
# check if this script is run as administrator
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
Write-Error "You are not an Administrator. This script needs to be run by an Adminsitrator!"
}
# check if InfFile exists
if(-NOT (Test-Path -Path $InfFile))
{
Write-Error "$InfFile not found!"
}
# utility functions
function Step
{
param([string] $Desc, [System.Management.Automation.ScriptBlock] $Code)
Write-Output "[*] $Desc";
Invoke-Command -ScriptBlock $Code
}
function Get-CertificateThumbprint
{
param([string] $FilePath)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($(Resolve-Path $FilePath))
return $cert.Thumbprint
}
# Get Kits root
try {
$InstalledRoots = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
$WinKits = $InstalledRoots.KitsRoot10
$ToolsPrefix = "$($WinKits)\bin\10.0.18362.0\x64"
} catch {
Write-Error "Could not locate the Windows Driver Kit. Head to https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk and download the WDK"
}
function RunKit
{
param([Parameter(Mandatory=$true)][string] $ToolName, [string[]] $Arguments)
Write-Output "Running $($ToolsPrefix)\$($ToolName)"
$Proc = Start-Process -FilePath "$($ToolsPrefix)\$($ToolName)" -ArgumentList $Arguments -NoNewWindow -PassThru -Wait
if ($Proc.ExitCode -NE 0)
{
Write-Error "Process failed with exit code: $($Proc.ExitCode)"
}
}
# Script vars
$CatFile = [io.path]::GetFileNameWithoutExtension($InfFile) + ".cat"
$CertFile = [io.path]::GetFileNameWithoutExtension($InfFile) + ".cer"
# Scripts
function DoSign
{
# verify that the Inf file contains a "Catalog" entry
if (-NOT (Select-String -Path $InfFile -Pattern "CatalogFile" -CaseSensitive -SimpleMatch -Quiet))
{
Write-Error "Could not find the 'CatalogFile' entry inside the INF file! Make sure it points to a certificate with the same Name."
}
Step -Desc "Create Catalog file" -Code {
New-FileCatalog -Path $InfFile -CatalogFilePath $CatFile -CatalogVersion 2.0
}
if (-NOT (Test-Path -Path $CertFile) -OR $Force)
{
Step -Desc "Create a Test Certificate" -Code {
# see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/creating-test-certificates
# This will create a self-signed certificate and store it in the Personal certificate stora on the local machine.
RunKit -ToolName "makecert.exe" -Arguments "-r -sr LocalMachine -ss My -pe -n CN=$($CommonName) -eku 1.3.6.1.5.5.7.3.3 $CertFile"
}
Step -Desc "Import the Test Certificate into the Local Computer Trusted Root CAs and Trusted Publishers stores" -Code {
Import-Certificate -FilePath $CertFile -CertStoreLocation Cert:\LocalMachine\Root
Import-Certificate -FilePath $CertFile -CertStoreLocation Cert:\LocalMachine\TrustedPublisher
}
}
else
{
Write-Output "Certificate already exists. Using $CertFile. If you still want to create a new one, use the -Force option"
}
Step -Desc "Sign the Catalog with the Test Certificate" -Code {
# see https://docs.microsoft.com/en-us/windows-hardware/drivers/install/test-signing-a-catalog-file
RunKit -ToolName "signtool.exe" -Arguments "sign /v /sm /s My /n $($CommonName) /t http://timestamp.digicert.com $($CatFile)"
}
Write-Output "Successfully singed the driver and added the certificate to the trusted store."
}
function DoUntrustCertificates
{
Step -Desc "Remove the Test Certificate from the Local Computer Trusted Root CAs and Trusted Publishers stores" -Code {
$thumbprint = Get-CertificateThumbprint -FilePath $CertFile
Remove-Item -Path ("Cert:\LocalMachine\My\$($thumbprint)")
Remove-Item -Path ("Cert:\LocalMachine\Root\$($thumbprint)")
Remove-Item -Path ("Cert:\LocalMachine\TrustedPublisher\$($thumbprint)")
}
Write-Output "Sucessfully removed all certificates from the trusted certificate stores."
}
# entry
Write-Output "Selected Mode: $Mode"
Switch($Mode)
{
"Sign" { DoSign }
"UntrustCertificates" { DoUntrustCertificates }
}
; Taken from and modified:
; <https://github.com/torvalds/linux/blob/master/Documentation/usb/linux.inf>
; Based on template INF file found at
; <https://msdn.microsoft.com/en-us/library/ff570620.aspx>
; which was:
; Copyright (c) Microsoft Corporation
; and released under the MLPL as found at:
; <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.
; For use only on Windows operating systems.
[Version]
Signature = "$Windows NT$"
Class = Net
ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}
Provider = %Linux%
DriverVer = 10/10/2020,6.1.6000.16384
CatalogFile = linux.cat
[Manufacturer]
%Linux% = LinuxDevices,NTx86,NTamd64,NTia64
; Decoration for x86 architecture
[LinuxDevices.NTx86]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
; Decoration for x64 architecture
[LinuxDevices.NTamd64]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
; Decoration for ia64 architecture
[LinuxDevices.NTia64]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
;@@@ This is the common setting for setup
[ControlFlags]
ExcludeFromSelect=*
; DDInstall section
; References the in-build Netrndis.inf
[RNDIS.NT.5.1]
Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI
BusType = 15
; NEVER REMOVE THE FOLLOWING REFERENCE FOR NETRNDIS.INF
include = netrndis.inf
needs = Usb_Rndis.ndi
AddReg = Rndis_AddReg_Vista
; DDInstal.Services section
[RNDIS.NT.5.1.Services]
include = netrndis.inf
needs = Usb_Rndis.ndi.Services
; Optional registry settings. You can modify as needed.
[RNDIS_AddReg_Vista]
HKR, NDI\params\VistaProperty, ParamDesc, 0, %Vista_Property%
HKR, NDI\params\VistaProperty, type, 0, "edit"
HKR, NDI\params\VistaProperty, LimitText, 0, "12"
HKR, NDI\params\VistaProperty, UpperCase, 0, "1"
HKR, NDI\params\VistaProperty, default, 0, " "
HKR, NDI\params\VistaProperty, optional, 0, "1"
; No sys copyfiles - the sys files are already in-build
; (part of the operating system).
; We do not support XP SP1-, 2003 SP1-, ME, 9x.
[Strings]
Linux = "Linux Developer Community"
LinuxDevice = "Linux USB Ethernet/RNDIS Gadget"
Vista_Property = "Optional Vista Property"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment