ReactOS 0.4.17-dev-1281-g065abb3
hubsup.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS USB Driver Library
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Hub number allocator and serial number device list for usbhub3
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#define _USBD_
9#include <ntddk.h>
10#include <usbdi.h>
11#include <usbioctl.h>
13
14#define USBD_POOL_TAG 'DBSU'
15
16/* POOL_TYPE value for no-execute nonpaged pool on NT 6.2 and later */
17#define USBD_NONPAGED_POOL_NX ((POOL_TYPE)0x200)
18
19/* One record per attached device that reported a serial number */
20typedef struct _USBD_SERIAL_RECORD
21{
33
35
38
39static RTL_STATIC_LIST_HEAD(UsbdSerialList);
41
46{
49 SIZE_T BitmapSize;
50
52
54 OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
56 {
57 if (OsVersion.dwMajorVersion > 6 ||
58 (OsVersion.dwMajorVersion == 6 && OsVersion.dwMinorVersion >= 2))
59 {
61 }
62 }
63
65 InitializeListHead(&UsbdSerialList);
67
68 /* Without the bitmap every hub simply gets number 0 */
69 BitmapSize = sizeof(*Bitmap) + USBD_HUB_NUMBER_COUNT / 8;
71 if (Bitmap)
72 {
76 }
77
78 return STATUS_SUCCESS;
79}
80
84{
86 {
89 }
90
91 return STATUS_SUCCESS;
92}
93
97{
99
100 PAGED_CODE();
101
102 if (!UsbdHubNumbers)
104
108
109 if (Number == MAXULONG)
111
112 return Number;
113}
114
115VOID
116NTAPI
118 _In_ ULONG HubNumber)
119{
120 PAGED_CODE();
121
122 /* 0 is reserved and anything past the map would land outside the buffer */
123 if (!UsbdHubNumbers ||
124 HubNumber == USBD_HUB_NUMBER_NONE ||
125 HubNumber >= USBD_HUB_NUMBER_COUNT)
126 {
127 return;
128 }
129
131 RtlClearBits(UsbdHubNumbers, HubNumber, 1);
133}
134
135static
141 _In_ PUSB_ID_STRING SerialNumber)
142{
143 if (Record->IdVendor != IdVendor || Record->IdProduct != IdProduct)
144 return FALSE;
145
146 if (Record->SerialLength != SerialNumber->LengthInBytes)
147 return FALSE;
148
149 if (Record->SerialLength == 0)
150 return TRUE;
151
152 return RtlEqualMemory(Record->Serial,
153 SerialNumber->Buffer,
154 Record->SerialLength);
155}
156
157/* Decides whether a device colliding with an existing record may still be added */
158static
159ULONG
161 _In_ PUSBD_SERIAL_RECORD Existing,
165{
166 BOOLEAN SameConnector;
167 BOOLEAN SamePort;
168
169 SameConnector = (ConnectorNode != NULL && Existing->ConnectorNode == ConnectorNode);
170 SamePort = (HubContext != NULL &&
171 Existing->HubContext == HubContext &&
172 Existing->PortNumber == PortNumber);
173
174 /* A connected record on the same connector is the other speed's copy that has not left yet */
175 if (!Existing->Disconnected)
177
178 if (SameConnector || SamePort)
180
182}
183
184static
188{
191
192 for (Entry = UsbdSerialList.Flink; Entry != &UsbdSerialList; Entry = Entry->Flink)
193 {
195 if (Record->DeviceContext == DeviceContext)
196 return Record;
197 }
198
199 return NULL;
200}
201
202ULONG
203NTAPI
211 _In_ PUSB_ID_STRING SerialNumber)
212{
215 PUSBD_SERIAL_RECORD NewRecord;
218
220
221 /* Only the first record with the same identity decides */
222 for (Entry = UsbdSerialList.Flink; Entry != &UsbdSerialList; Entry = Entry->Flink)
223 {
226 {
228 break;
229 }
230 }
231
233 goto Exit;
234
235 /* The serial is stored right after the record */
237 sizeof(*NewRecord) + SerialNumber->LengthInBytes,
239 if (!NewRecord)
240 {
242 goto Exit;
243 }
244
245 RtlZeroMemory(NewRecord, sizeof(*NewRecord));
246
247 if (SerialNumber->LengthInBytes != 0)
248 {
249 NewRecord->Serial = (PWCHAR)(NewRecord + 1);
250 RtlCopyMemory(NewRecord->Serial, SerialNumber->Buffer, SerialNumber->LengthInBytes);
251 }
252
253 NewRecord->SerialLength = SerialNumber->LengthInBytes;
254 NewRecord->DeviceContext = DeviceContext;
255 NewRecord->HubContext = HubContext;
256 NewRecord->PortNumber = PortNumber;
257 NewRecord->ConnectorNode = ConnectorNode;
258 NewRecord->IdVendor = IdVendor;
259 NewRecord->IdProduct = IdProduct;
260 InsertTailList(&UsbdSerialList, &NewRecord->Link);
261
262Exit:
264 return Result;
265}
266
267VOID
268NTAPI
271{
274
276
278 if (Record)
279 Record->Disconnected = TRUE;
280
282}
283
284VOID
285NTAPI
288{
291
293
295 if (Record)
296 RemoveEntryList(&Record->Link);
297
299
300 if (Record)
302}
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define RtlClearBits
Definition: dbgbitmap.h:331
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlFindClearBitsAndSet
Definition: dbgbitmap.h:333
#define RtlSetBits
Definition: dbgbitmap.h:345
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:182
ULONG NTAPI DllUnload()
Definition: dll.cpp:28
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
_In_ PCUNICODE_STRING _Out_ HubUxdSettings * Record
static PUSBD_SERIAL_RECORD UsbdFindSerialRecordByDevice(_In_ PVOID DeviceContext)
Definition: hubsup.c:186
#define USBD_NONPAGED_POOL_NX
Definition: hubsup.c:17
static KEVENT UsbdHubNumberLock
Definition: hubsup.c:37
NTSTATUS NTAPI DllInitialize(_In_ PUNICODE_STRING RegistryPath)
Definition: hubsup.c:44
static POOL_TYPE UsbdNonPagedPoolType
Definition: hubsup.c:34
VOID NTAPI USBD_ReleaseHubNumber(_In_ ULONG HubNumber)
Definition: hubsup.c:117
VOID NTAPI USBD_MarkDeviceAsDisconnected(_In_ PVOID DeviceContext)
Definition: hubsup.c:269
struct _USBD_SERIAL_RECORD * PUSBD_SERIAL_RECORD
static BOOLEAN UsbdSerialRecordMatches(_In_ PUSBD_SERIAL_RECORD Record, _In_ USHORT IdVendor, _In_ USHORT IdProduct, _In_ PUSB_ID_STRING SerialNumber)
Definition: hubsup.c:137
static KSPIN_LOCK UsbdSerialListLock
Definition: hubsup.c:40
ULONG NTAPI USBD_AddDeviceToGlobalList(_In_ PVOID DeviceContext, _In_opt_ PVOID HubContext, _In_ ULONG PortNumber, _In_opt_ PVOID ConnectorNode, _In_ USHORT IdVendor, _In_ USHORT IdProduct, _In_ PUSB_ID_STRING SerialNumber)
Definition: hubsup.c:204
static ULONG UsbdClassifySerialCollision(_In_ PUSBD_SERIAL_RECORD Existing, _In_opt_ PVOID HubContext, _In_ ULONG PortNumber, _In_opt_ PVOID ConnectorNode)
Definition: hubsup.c:160
struct _USBD_SERIAL_RECORD USBD_SERIAL_RECORD
#define USBD_POOL_TAG
Definition: hubsup.c:14
static PRTL_BITMAP UsbdHubNumbers
Definition: hubsup.c:36
ULONG NTAPI USBD_AllocateHubNumber(VOID)
Definition: hubsup.c:96
VOID NTAPI USBD_RemoveDeviceFromGlobalList(_In_ PVOID DeviceContext)
Definition: hubsup.c:286
_In_ UCXHUB_DEVICE_CONTEXT DeviceContext
Definition: hubucx.h:237
_In_ ULONG PortNumber
Definition: hubucx.h:272
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static ULONG OsVersion
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
_In_ ULONG Number
Definition: haltypes.h:1940
#define KernelMode
Definition: asm.h:38
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ SynchronizationEvent
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY Link
Definition: hubsup.c:22
PVOID DeviceContext
Definition: hubsup.c:23
BOOLEAN Disconnected
Definition: hubsup.c:29
USHORT IdProduct
Definition: hubsup.c:28
PVOID ConnectorNode
Definition: hubsup.c:26
ULONG PortNumber
Definition: hubsup.c:25
PVOID HubContext
Definition: hubsup.c:24
USHORT IdVendor
Definition: hubsup.c:27
ULONG SerialLength
Definition: hubsup.c:30
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_In_opt_ PVOID _In_ ULONG _In_opt_ PVOID ConnectorNode
Definition: usbdhub.h:43
#define USBD_HUB_NUMBER_NONE
Definition: usbdhub.h:15
#define USBD_GLOBAL_LIST_DUPLICATE_PENDING
Definition: usbdhub.h:20
#define USBD_GLOBAL_LIST_ADDED
Definition: usbdhub.h:19
_In_opt_ PVOID HubContext
Definition: usbdhub.h:41
_In_opt_ PVOID _In_ ULONG _In_opt_ PVOID _In_ USHORT IdVendor
Definition: usbdhub.h:44
#define USBD_GLOBAL_LIST_DUPLICATE
Definition: usbdhub.h:21
_In_opt_ PVOID _In_ ULONG _In_opt_ PVOID _In_ USHORT _In_ USHORT _In_ PUSB_ID_STRING SerialNumber
Definition: usbdhub.h:46
#define USBD_GLOBAL_LIST_NO_MEMORY
Definition: usbdhub.h:22
_In_opt_ PVOID _In_ ULONG _In_opt_ PVOID _In_ USHORT _In_ USHORT IdProduct
Definition: usbdhub.h:45
#define USBD_HUB_NUMBER_COUNT
Definition: usbdhub.h:16
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:467
#define RTL_STATIC_LIST_HEAD(x)
Definition: rtlfuncs.h:47