Skip to content

Instantly share code, notes, and snippets.

@Gadgetoid
Last active February 20, 2023 09:35
Show Gist options
  • Save Gadgetoid/c52ee2e04f1cd1c0854c3e77360011e2 to your computer and use it in GitHub Desktop.
Save Gadgetoid/c52ee2e04f1cd1c0854c3e77360011e2 to your computer and use it in GitHub Desktop.
Raspberry Pi Zero / Windows 10 automatic RNDIS driver install for composite gadgets

Preface

I owe my very rapid learning journey in the world of ConfigFs to several key sources which aren't necessarily relevant to this result, but I feel deserve a mention anyway.

The Result

One of the biggest and most repeated issues with the Pi Zero and OTG USB is that a composite gadget including RNDIS Ethernet for Ethernet-over-USB support in Windows will not automatically install drivers and, furthermore, is a heinous pain to install drivers for. My original idea was to develop and sign drivers to solve this problem- I still plan to do that, because the solution presented here is a hack - but it turned out signing inf files is really waaay more complex than it has any right to be.

So, using the resources above, plus some others (probably) which I've forgotten, and lots, and lots and lots of trial and error I finally accidentally hit upon a method to trick Windows 10 - repeatably I believe - into installing RNDIS drivers for a composite gadget.

The Technique

The technique is ridiculously simple;

  • Set up an RNDIS gadget using a VID/PID of a known good device that's compatible with composite RNDIS
  • Set bDeviceClass and bDeviceSubClass to 0x02 for a valid gadget
  • Set up the "os_desc" node with Windows magic (I don't think this is 100% necessary, but voodoo is voodoo!
  • Link only the RNDIS function to the config
  • Attach the USB gaget to the device
  • Wait some time for Windows to detect/install drivers- 5sec seems plenty as it happens, some experimentation required here
  • Detach the USB gadget
  • Link the rest of your functions- Mass Storage, Serial ACM, etc ( So far only tested with these )
  • Set bDeviceClass to 0x00
  • Re-attach the USB gadget
  • Now it should show up - in Windows 10 at least - as a composite gadget with functional RNDIS, Serial and Mass Storage. Yay!

Changelog

2017-11-05 - 00:26 - Tweaked to better support OSX. Still no RNDIS funcionality in 10.12, but Mass Storage and Serial seem to work

#!/bin/bash
# TODO: Figure out how to get ECM to work here
# without breaking Windows support
# Currently OSX supports Mass Storage + Serial but *not* RNDIS (at least not 10.12 anyway)
# Windows 10 and Linux seem to support everything
# Windows 8, 7 and below are untested
if [ ! -d /sys/kernel/config/usb_gadget ]; then
modprobe libcomposite
fi
if [ -d /sys/kernel/config/usb_gadget/g1 ]; then
exit 0
fi
ID_VENDOR="0x1d6b"
ID_PRODUCT="0x0104"
SERIAL="$(grep Serial /proc/cpuinfo | sed 's/Serial\s*: 0000\(\w*\)/\1/')"
MAC="$(echo ${SERIAL} | sed 's/\(\w\w\)/:\1/g' | cut -b 2-)"
MAC_HOST="12$(echo ${MAC} | cut -b 3-)"
MAC_DEV="02$(echo ${MAC} | cut -b 3-)"
cd /sys/kernel/config/usb_gadget/
mkdir g1
cd g1
echo "0x0200" > bcdUSB
echo "0x02" > bDeviceClass
echo "0x00" > bDeviceSubClass
echo "0x3066" > bcdDevice
echo $ID_VENDOR > idVendor
echo $ID_PRODUCT > idProduct
# Windows extensions to force config
echo "1" > os_desc/use
echo "0xcd" > os_desc/b_vendor_code
echo "MSFT100" > os_desc/qw_sign
mkdir strings/0x409
echo "9112473" > strings/0x409/serialnumber
echo "Pimoroni Ltd." > strings/0x409/manufacturer
echo "PiratePython" > strings/0x409/product
# Config #1 for OSX / Linux
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "CDC 2xACM+Mass Storage+RNDIS" > configs/c.1/strings/0x409/configuration
mkdir functions/acm.GS0
mkdir functions/acm.GS1
#mkdir functions/ecm.usb0 # OSX/Linux
mkdir functions/rndis.usb0 # Flippin' Windows
mkdir functions/mass_storage.piratepython
echo "/dev/mmcblk0p1" > functions/mass_storage.piratepython/lun.0/file
echo 0 > functions/mass_storage.piratepython/stall
echo 0 > functions/mass_storage.piratepython/lun.0/cdrom
echo 0 > functions/mass_storage.piratepython/lun.0/nofua
echo 1 > functions/mass_storage.piratepython/lun.0/removable
echo "PiratePython" > functions/mass_storage.piratepython/lun.0/inquiry_string
echo "RNDIS" > functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo "5162001" > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id
echo $MAC_HOST > functions/rndis.usb0/host_addr
echo $MAC_DEV > functions/rndis.usb0/dev_addr
# Set up the rndis device only first
ln -s functions/rndis.usb0 configs/c.1
# Tell Windows to use config #2
ln -s configs/c.1 os_desc
# Show Windows the RNDIS device with
# bDeviceClass 0x02
# bDeviceSubClass 0x02
echo "20980000.usb" > UDC
# Give it time to install
sleep 5
# Yank it back
echo "" > UDC
# Sneak in all the extra goodies
ln -s functions/acm.GS0 configs/c.1
ln -s functions/acm.GS1 configs/c.1
ln -s functions/mass_storage.piratepython configs/c.1
# Reset bDeviceClass to 0x00
# This is essential to make it work in Windows 10
# Basically forces it to use device information
# in the descriptors versus assuming a particular class.
echo "0x00" > bDeviceClass
# Re-attach the gadget
echo "20980000.usb" > UDC
# BOOM!
ifconfig usb0 up 10.0.99.1
@x821938
Copy link

x821938 commented Apr 25, 2018

Nice job! It works like a charm on the Raspberry Pi Zero :)

GavidDarkGlider: I currently have HID,RNDIS,Serial ACM, ECM Networking, and Mass Storage all working properly in multiple composite arangements, with no problems in windows 7

I am figthing to get RNDIS and HID working at the same time. Do you have an idea how to get that working?

@mame82
Copy link

mame82 commented Apr 28, 2018

Hi,

I'm running the P4wnP1 project and solved this issue over a year ago.

I'm using a composite device with RNDIS and additional gadget funtions (could be enabled optional).

The keys for proper PnP RNDIS on Win 10:

  • use inly ONE configuration
  • add Microsoft OS descriptors
  • in case of multilple compisite functions, RNDIS has to be the first one
  • if the VID+PID have been in use with misding or wrong IS descriptors, they're never enumerated again by Windows (cached in registry hive). So these reg keys have to be removed or the PID or VID have to be changed

Working code:
https://github.com/mame82/P4wnP1/blob/master/boot/init_usb.sh

Details on the registry caching of OS descriptors in this line:
https://github.com/mame82/P4wnP1/blob/master/boot/init_usb.sh#L150

Cheers

@nunojpg
Copy link

nunojpg commented Oct 22, 2018

Hi @mame82, I've tried without success your concept. Can you confirm if specific VID/PID are required or if any .INF installation is required at Windows 10? Thanks!

@aurelihein
Copy link

Since I see that you have modified your script 12 days ago, you should try this one : https://gist.github.com/geekman/5bdb5abdc9ec6ac91d5646de0c0c60c4 which for me is working under Windows 10

@jdevelop
Copy link

I tried this script and the one posted by @mame82 / @aurelihein - on Windows 10 the device appears under "Other devices" as RNDIS, but Windows can't find driver for it.

I wonder if anyone else faces this issue?

@Roy996
Copy link

Roy996 commented Oct 27, 2021

I tried this script and the one posted by @mame82 / @aurelihein - on Windows 10 the device appears under "Other devices" as RNDIS, but Windows can't find driver for it.

I wonder if anyone else faces this issue?

Did you solve it? I got the same problem now.

@AddaxSoft
Copy link

for people who dont want to bother you can get the driver from here: https://modclouddownloadprod.blob.core.windows.net/shared/mod-rndis-driver-windows.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment