diff --git a/stmhal/Makefile b/stmhal/Makefile
index 97891899463511156cd42692e647009350ece647..f0d132520d8bdf916cf4f2b993bd73febaa1401a 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -210,6 +210,14 @@ PREFIX_FILE = boards/stm32f4xx-prefix.c
 GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
 GEN_PINS_HDR = $(BUILD)/pins.h
 
+INSERT_USB_IDS = ../tools/insert-usb-ids.py
+FILE2H = ../tools/file2h.py
+
+USB_IDS_FILE = usbd_desc_cdc_msc.c
+CDCINF_TEMPLATE = pybcdc.inf_template
+GEN_CDCINF_FILE = $(BUILD)/pybcdc.inf
+GEN_CDCINF_HEADER = $(BUILD)/pybcdc_inf.h
+
 # Making OBJ use an order-only depenedency on the generated pins.h file
 # has the side effect of making the pins.h file before we actually compile
 # any of the objects. The normal dependency generation will deal with the
@@ -217,6 +225,8 @@ GEN_PINS_HDR = $(BUILD)/pins.h
 # which source files might need it.
 $(OBJ): | $(BUILD)/pins.h
 
+$(BUILD)/main.o: $(GEN_CDCINF_HEADER)
+
 # Use a pattern rule here so that make will only call make-pins.py once to make
 # both pins_$(BOARD).c and pins.h
 $(BUILD)/%_$(BOARD).c $(BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE)
@@ -226,4 +236,12 @@ $(BUILD)/%_$(BOARD).c $(BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE
 $(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c
 	$(call compile_c)
 
+$(GEN_CDCINF_HEADER): $(GEN_CDCINF_FILE) $(FILE2H)
+	$(ECHO) "Create $@"
+	$(Q)$(PYTHON) $(FILE2H) $< > $@
+
+$(GEN_CDCINF_FILE): $(CDCINF_TEMPLATE) $(INSERT_USB_IDS) $(USB_IDS_FILE)
+	$(ECHO) "Create $@"
+	$(Q)$(PYTHON) $(INSERT_USB_IDS) $(USB_IDS_FILE) $< > $@
+
 include ../py/mkrules.mk
diff --git a/stmhal/main.c b/stmhal/main.c
index cc41a195a3e7342d9f0e77eae53850f8e5ee7483..c5633fb68ba16aa22638b7606f1acda5e042814c 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -134,7 +134,7 @@ static const char fresh_main_py[] =
 ;
 
 static const char fresh_pybcdc_inf[] =
-#include "pybcdc.h"
+#include "build/pybcdc_inf.h"
 ;
 
 static const char fresh_readme_txt[] =
diff --git a/stmhal/pybcdc.h b/stmhal/pybcdc.h
deleted file mode 100644
index 44685a05bab57624ce886d07db663674e0a5a110..0000000000000000000000000000000000000000
--- a/stmhal/pybcdc.h
+++ /dev/null
@@ -1,92 +0,0 @@
-"; Windows USB CDC ACM Setup File\r\n"
-"; Based on INF files which were:\r\n"
-";     Copyright (c) 2000 Microsoft Corporation\r\n"
-";     Copyright (C) 2007 Microchip Technology Inc.\r\n"
-"; Likely to be covered by the MLPL as found at:\r\n"
-";    <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.\r\n"
-"\r\n"
-"[Version]\r\n"
-"Signature=\"$Windows NT$\"\r\n"
-"Class=Ports\r\n"
-"ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}\r\n"
-"Provider=%MFGNAME%\r\n"
-"LayoutFile=layout.inf\r\n"
-"DriverVer=03/11/2010,5.1.2600.3\r\n"
-"\r\n"
-"[Manufacturer]\r\n"
-"%MFGNAME%=DeviceList, NTamd64\r\n"
-"\r\n"
-"[DestinationDirs]\r\n"
-"DefaultDestDir=12\r\n"
-"\r\n"
-";---------------------------------------------------------------------\r\n"
-"; Windows 2000/XP/Server2003/Vista/Server2008/7 - 32bit Sections\r\n"
-"\r\n"
-"[DriverInstall.nt]\r\n"
-"include=mdmcpq.inf\r\n"
-"CopyFiles=DriverCopyFiles.nt\r\n"
-"AddReg=DriverInstall.nt.AddReg\r\n"
-"\r\n"
-"[DriverCopyFiles.nt]\r\n"
-"usbser.sys,,,0x20\r\n"
-"\r\n"
-"[DriverInstall.nt.AddReg]\r\n"
-"HKR,,DevLoader,,*ntkern\r\n"
-"HKR,,NTMPDriver,,usbser.sys\r\n"
-"HKR,,EnumPropPages32,,\"MsPorts.dll,SerialPortPropPageProvider\"\r\n"
-"\r\n"
-"[DriverInstall.nt.Services]\r\n"
-"AddService=usbser, 0x00000002, DriverService.nt\r\n"
-"\r\n"
-"[DriverService.nt]\r\n"
-"DisplayName=%SERVICE%\r\n"
-"ServiceType=1\r\n"
-"StartType=3\r\n"
-"ErrorControl=1\r\n"
-"ServiceBinary=%12%\\usbser.sys\r\n"
-"\r\n"
-";---------------------------------------------------------------------\r\n"
-";  Windows XP/Server2003/Vista/Server2008/7 - 64bit Sections\r\n"
-"\r\n"
-"[DriverInstall.NTamd64]\r\n"
-"include=mdmcpq.inf\r\n"
-"CopyFiles=DriverCopyFiles.NTamd64\r\n"
-"AddReg=DriverInstall.NTamd64.AddReg\r\n"
-"\r\n"
-"[DriverCopyFiles.NTamd64]\r\n"
-"usbser.sys,,,0x20\r\n"
-"\r\n"
-"[DriverInstall.NTamd64.AddReg]\r\n"
-"HKR,,DevLoader,,*ntkern\r\n"
-"HKR,,NTMPDriver,,usbser.sys\r\n"
-"HKR,,EnumPropPages32,,\"MsPorts.dll,SerialPortPropPageProvider\"\r\n"
-"\r\n"
-"[DriverInstall.NTamd64.Services]\r\n"
-"AddService=usbser, 0x00000002, DriverService.NTamd64\r\n"
-"\r\n"
-"[DriverService.NTamd64]\r\n"
-"DisplayName=%SERVICE%\r\n"
-"ServiceType=1\r\n"
-"StartType=3\r\n"
-"ErrorControl=1\r\n"
-"ServiceBinary=%12%\\usbser.sys\r\n"
-"\r\n"
-";---------------------------------------------------------------------\r\n"
-";  Vendor and Product ID Definitions\r\n"
-"\r\n"
-"[SourceDisksFiles]\r\n"
-"[SourceDisksNames]\r\n"
-"[DeviceList]\r\n"
-"%DESCRIPTION%=DriverInstall, USB\\VID_0483&PID_5740&MI_00, USB\\VID_0483&PID_5740&MI_01\r\n"
-"\r\n"
-"[DeviceList.NTamd64]\r\n"
-"%DESCRIPTION%=DriverInstall, USB\\VID_0483&PID_5740&MI_00, USB\\VID_0483&PID_5740&MI_01\r\n"
-"\r\n"
-";---------------------------------------------------------------------\r\n"
-";  String Definitions\r\n"
-"\r\n"
-"[Strings]\r\n"
-"MFGFILENAME=\"pybcdc\"\r\n"
-"MFGNAME=\"Micro Python\"\r\n"
-"DESCRIPTION=\"Pyboard USB Comm Port\"\r\n"
-"SERVICE=\"USB Serial Driver\"\r\n"
diff --git a/stmhal/pybcdc.inf b/stmhal/pybcdc.inf_template
old mode 100755
new mode 100644
similarity index 87%
rename from stmhal/pybcdc.inf
rename to stmhal/pybcdc.inf_template
index eb04b65cee08aad2f3ef6fa82440d7c46c798202..87cd1467b23b82f6ecd81e2b0af4d3e36c7b1c8a
--- a/stmhal/pybcdc.inf
+++ b/stmhal/pybcdc.inf_template
@@ -77,10 +77,10 @@ ServiceBinary=%12%\usbser.sys
 [SourceDisksFiles]
 [SourceDisksNames]
 [DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0483&PID_5740&MI_00, USB\VID_0483&PID_5740&MI_01
+%DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID}&MI_01
 
 [DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0483&PID_5740&MI_00, USB\VID_0483&PID_5740&MI_01
+%DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID}&MI_01
 
 ;---------------------------------------------------------------------
 ;  String Definitions
diff --git a/tools/file2h.py b/tools/file2h.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb5bd1a4b9c5990f725c1e04e68becea729173db
--- /dev/null
+++ b/tools/file2h.py
@@ -0,0 +1,28 @@
+# Reads in a text file, and performs the necessary escapes so that it
+# can be #included as a static string like:
+#    static const char string_from_textfile[] =
+#    #include "build/textfile.h"
+#    ;
+# This script simply prints the escaped string straight to stdout
+
+from __future__ import print_function
+
+import sys
+
+# Can either be set explicitly, or left blank to auto-detect
+line_end = ''
+
+if __name__ == "__main__":
+    filename = sys.argv[1]
+    for line in open(filename, 'r').readlines():
+        if not line_end:
+            for ending in ('\r\n', '\r', '\n'):
+                if line.endswith(ending):
+                    line_end = ending.replace('\r', '\\r').replace('\n', '\\n')
+                    break
+            if not line_end:
+                raise Exception("Couldn't auto-detect line-ending of %s" % filename)
+        line = line.rstrip('\r\n')
+        line = line.replace('\\', '\\\\')
+        line = line.replace('"', '\\"')
+        print('"%s%s"' % (line, line_end))
diff --git a/tools/insert-usb-ids.py b/tools/insert-usb-ids.py
new file mode 100644
index 0000000000000000000000000000000000000000..af010dad954df27df60ff87a784b7dab761dbe9e
--- /dev/null
+++ b/tools/insert-usb-ids.py
@@ -0,0 +1,36 @@
+# Reads the USB VID and PID from the file specifed by sys.arg[1] and then
+# inserts those values into the template file specified by sys.argv[2],
+# printing the result to stdout
+
+from __future__ import print_function
+
+import sys
+import re
+import string
+
+def parse_usb_ids(filename):
+    rv = dict()
+    if filename == 'usbd_desc_cdc_msc.c':
+        for line in open(filename).readlines():
+            line = line.rstrip('\r\n')
+            match = re.match('^#define\s+(\w+)\s+0x(\d+)$', line)
+            if match:
+                if match.group(1) == 'USBD_VID':
+                    rv['USB_VID'] = match.group(2)
+                elif match.group(1) == 'USBD_PID':
+                    rv['USB_PID'] = match.group(2)
+                if 'USB_VID' in rv and 'USB_PID' in rv:
+                    break
+    else:
+        raise Exception("Don't (yet) know how to parse USB IDs from %s" % filename)
+    for k in ('USB_PID', 'USB_VID'):
+        if k not in rv:
+            raise Exception("Unable to parse %s from %s" % (k, filename))
+    return rv
+
+if __name__ == "__main__":
+    usb_ids_file = sys.argv[1]
+    template_file = sys.argv[2]
+    replacements = parse_usb_ids(usb_ids_file)
+    for line in open(template_file, 'r').readlines():
+        print(string.Template(line).safe_substitute(replacements), end='')