ReactOS  0.4.14-dev-50-g13bb5e2
fbtusb.c
Go to the documentation of this file.
1 // Copyright (c) 2004, Antony C. Roberts
2 
3 // Use of this file is subject to the terms
4 // described in the LICENSE.TXT file that
5 // accompanies this file.
6 //
7 // Your use of this file indicates your
8 // acceptance of the terms described in
9 // LICENSE.TXT.
10 //
11 // http://www.freebt.net
12 
13 #include "stdio.h"
14 #include "fbtusb.h"
15 #include "fbtpnp.h"
16 #include "fbtpwr.h"
17 #include "fbtdev.h"
18 #include "fbtwmi.h"
19 #include "fbtrwr.h"
20 
21 #include "fbtusr.h"
22 
23 
24 // Globals
27 
28 // Forward declaration
32 
33 #ifdef PAGE_CODE
34 #ifdef ALLOC_PRAGMA
35 #pragma alloc_text(INIT, DriverEntry)
36 #pragma alloc_text(PAGE, FreeBT_DriverUnload)
37 #endif
38 #endif
39 
41 {
42  NTSTATUS ntStatus;
44 
46 
47  registryPath->MaximumLength = UniRegistryPath->Length + sizeof(UNICODE_NULL);
48  registryPath->Length = UniRegistryPath->Length;
49  registryPath->Buffer = (PWSTR) ExAllocatePool(PagedPool, registryPath->MaximumLength);
50 
51  if (!registryPath->Buffer)
52  {
53  FreeBT_DbgPrint(1, ("FBTUSB: Failed to allocate memory for registryPath\n"));
55  goto DriverEntry_Exit;
56 
57  }
58 
59 
60  RtlZeroMemory (registryPath->Buffer, registryPath->MaximumLength);
61  RtlMoveMemory (registryPath->Buffer, UniRegistryPath->Buffer, UniRegistryPath->Length);
62 
63  ntStatus = STATUS_SUCCESS;
64 
65  // Initialize the driver object with this driver's entry points.
74 #ifdef ENABLE_WMI
76 #endif
79 
80 DriverEntry_Exit:
81  return ntStatus;
82 
83 }
84 
86 {
88 
89  FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Entered\n"));
90 
92  if(registryPath->Buffer)
93  {
94  ExFreePool(registryPath->Buffer);
95  registryPath->Buffer = NULL;
96 
97  }
98 
99  FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DriverUnload: Leaving\n"));
100 
101  return;
102 
103 }
104 
105 // AddDevice, called when an instance of our supported hardware is found
106 // Returning anything other than NT_SUCCESS here causes the device to fail
107 // to initialise
109 {
110  NTSTATUS ntStatus;
111  PDEVICE_OBJECT deviceObject;
112  PDEVICE_EXTENSION deviceExtension;
114  //KIRQL oldIrql;
115  UNICODE_STRING uniDeviceName;
116  WCHAR wszDeviceName[255]={0};
117  UNICODE_STRING uniDosDeviceName;
118  LONG instanceNumber=0;
119 
120  FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Entered\n"));
121 
122  deviceObject = NULL;
123 
124  swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber);
125  RtlInitUnicodeString(&uniDeviceName, wszDeviceName);
127  while (instanceNumber<99 && !NT_SUCCESS(ntStatus))
128  {
129  swprintf(wszDeviceName, L"\\Device\\FbtUsb%02d", instanceNumber);
130  uniDeviceName.Length = wcslen(wszDeviceName) * sizeof(WCHAR);
131  FreeBT_DbgPrint(1, ("FBTUSB: Attempting to create device %ws\n", wszDeviceName));
132  ntStatus = IoCreateDevice(
133  DriverObject, // our driver object
134  sizeof(DEVICE_EXTENSION), // extension size for us
135  &uniDeviceName, // name for this device
137  0, // device characteristics
138  FALSE, // Not exclusive
139  &deviceObject); // Our device object
140 
141  if (!NT_SUCCESS(ntStatus))
142  instanceNumber++;
143 
144  }
145 
146  if (!NT_SUCCESS(ntStatus))
147  {
148  FreeBT_DbgPrint(1, ("FBTUSB: Failed to create device object\n"));
149  return ntStatus;
150 
151  }
152 
153  FreeBT_DbgPrint(1, ("FBTUSB: Created device %ws\n", wszDeviceName));
154 
155  deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
156  deviceExtension->FunctionalDeviceObject = deviceObject;
157  deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
158  deviceObject->Flags |= DO_DIRECT_IO;
159 
160  swprintf(deviceExtension->wszDosDeviceName, L"\\DosDevices\\FbtUsb%02d", instanceNumber);
161  RtlInitUnicodeString(&uniDosDeviceName, deviceExtension->wszDosDeviceName);
162  ntStatus=IoCreateSymbolicLink(&uniDosDeviceName, &uniDeviceName);
163  if (!NT_SUCCESS(ntStatus))
164  {
165  FreeBT_DbgPrint(1, ("FBTUSB: Failed to create symbolic link %ws to %ws, status=0x%08x\n", deviceExtension->wszDosDeviceName, wszDeviceName, ntStatus));
166  IoDeleteDevice(deviceObject);
167  return ntStatus;
168 
169  }
170 
171  FreeBT_DbgPrint(1, ("FBTUSB: Created symbolic link %ws\n", deviceExtension->wszDosDeviceName));
172 
173  KeInitializeSpinLock(&deviceExtension->DevStateLock);
174 
175  INITIALIZE_PNP_STATE(deviceExtension);
176 
177  deviceExtension->OpenHandleCount = 0;
178 
179  // Initialize the selective suspend variables
180  KeInitializeSpinLock(&deviceExtension->IdleReqStateLock);
181  deviceExtension->IdleReqPend = 0;
182  deviceExtension->PendingIdleIrp = NULL;
183 
184  // Hold requests until the device is started
185  deviceExtension->QueueState = HoldRequests;
186 
187  // Initialize the queue and the queue spin lock
188  InitializeListHead(&deviceExtension->NewRequestsQueue);
189  KeInitializeSpinLock(&deviceExtension->QueueLock);
190 
191  // Initialize the remove event to not-signaled.
192  KeInitializeEvent(&deviceExtension->RemoveEvent, SynchronizationEvent, FALSE);
193 
194  // Initialize the stop event to signaled.
195  // This event is signaled when the OutstandingIO becomes 1
196  KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, TRUE);
197 
198  // OutstandingIo count biased to 1.
199  // Transition to 0 during remove device means IO is finished.
200  // Transition to 1 means the device can be stopped
201  deviceExtension->OutStandingIO = 1;
202  KeInitializeSpinLock(&deviceExtension->IOCountLock);
203 
204 #ifdef ENABLE_WMI
205  // Delegating to WMILIB
206  ntStatus = FreeBT_WmiRegistration(deviceExtension);
207  if (!NT_SUCCESS(ntStatus))
208  {
209  FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WmiRegistration failed with %X\n", ntStatus));
210  IoDeleteDevice(deviceObject);
211  IoDeleteSymbolicLink(&uniDosDeviceName);
212  return ntStatus;
213 
214  }
215 #endif
216 
217  // Set the flags as underlying PDO
219  {
220  deviceObject->Flags |= DO_POWER_PAGABLE;
221 
222  }
223 
224  // Typically, the function driver for a device is its
225  // power policy owner, although for some devices another
226  // driver or system component may assume this role.
227  // Set the initial power state of the device, if known, by calling
228  // PoSetPowerState.
229  deviceExtension->DevPower = PowerDeviceD0;
230  deviceExtension->SysPower = PowerSystemWorking;
231 
232  state.DeviceState = PowerDeviceD0;
233  PoSetPowerState(deviceObject, DevicePowerState, state);
234 
235  // attach our driver to device stack
236  // The return value of IoAttachDeviceToDeviceStack is the top of the
237  // attachment chain. This is where all the IRPs should be routed.
238  deviceExtension->TopOfStackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
239  if (NULL == deviceExtension->TopOfStackDeviceObject)
240  {
241 #ifdef ENABLE_WMI
242  FreeBT_WmiDeRegistration(deviceExtension);
243 #endif
244  IoDeleteDevice(deviceObject);
245  IoDeleteSymbolicLink(&uniDosDeviceName);
246  return STATUS_NO_SUCH_DEVICE;
247 
248  }
249 
250  // Register device interfaces
251  ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject,
252  &GUID_CLASS_FREEBT_USB,
253  NULL,
254  &deviceExtension->InterfaceName);
255  if (!NT_SUCCESS(ntStatus))
256  {
257 #ifdef ENABLE_WMI
258  FreeBT_WmiDeRegistration(deviceExtension);
259 #endif
260  IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
261  IoDeleteDevice(deviceObject);
262  IoDeleteSymbolicLink(&uniDosDeviceName);
263  return ntStatus;
264 
265  }
266 
267  if (IoIsWdmVersionAvailable(1, 0x20))
268  {
269  deviceExtension->WdmVersion = WinXpOrBetter;
270 
271  }
272 
273  else if (IoIsWdmVersionAvailable(1, 0x10))
274  {
275  deviceExtension->WdmVersion = Win2kOrBetter;
276 
277  }
278 
279  else if (IoIsWdmVersionAvailable(1, 0x5))
280  {
281  deviceExtension->WdmVersion = WinMeOrBetter;
282 
283  }
284 
285  else if (IoIsWdmVersionAvailable(1, 0x0))
286  {
287  deviceExtension->WdmVersion = Win98OrBetter;
288 
289  }
290 
291  deviceExtension->SSRegistryEnable = 0;
292  deviceExtension->SSEnable = 0;
293 
294  // WinXP only: check the registry flag indicating whether
295  // the device should selectively suspend when idle
296  if (WinXpOrBetter == deviceExtension->WdmVersion)
297  {
299  L"BulkUsbEnable",
300  (PULONG)(&deviceExtension->SSRegistryEnable));
301  if (deviceExtension->SSRegistryEnable)
302  {
303  // initialize DPC
304  KeInitializeDpc(&deviceExtension->DeferredProcCall, DpcRoutine, deviceObject);
305 
306  // initialize the timer.
307  // the DPC and the timer in conjunction,
308  // monitor the state of the device to
309  // selectively suspend the device.
310  KeInitializeTimerEx(&deviceExtension->Timer, NotificationTimer);
311 
312  // Initialize the NoDpcWorkItemPendingEvent to signaled state.
313  // This event is cleared when a Dpc is fired and signaled
314  // on completion of the work-item.
315  KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent, NotificationEvent, TRUE);
316 
317  // Initialize the NoIdleReqPendEvent to ensure that the idle request
318  // is indeed complete before we unload the drivers.
319  KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent, NotificationEvent, TRUE);
320 
321  }
322 
323  }
324 
325  // Initialize the NoIdleReqPendEvent to ensure that the idle request
326  // is indeed complete before we unload the drivers.
327  KeInitializeEvent(&deviceExtension->DelayEvent, NotificationEvent, FALSE);
328 
329  // Clear the DO_DEVICE_INITIALIZING flag.
330  // Note: Do not clear this flag until the driver has set the
331  // device power state and the power DO flags.
332  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
333  InterlockedIncrement(&instanceNumber);
334 
335  FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AddDevice: Leaving\n"));
336 
337  return ntStatus;
338 
339 }
340 
341 
NTSTATUS NTAPI FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtpnp.c:1565
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
NTSTATUS NTAPI FreeBT_WmiRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
Definition: fbtwmi.c:37
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define DO_POWER_PAGABLE
VOID NTAPI DpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: fbtpnp.c:1298
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
GLint x0
Definition: linetemp.h:95
uint16_t * PWSTR
Definition: typedefs.h:54
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
LPCTSTR registryPath
Definition: butterflies.c:16
GLOBALS Globals
Definition: fbtusb.c:25
LONG NTSTATUS
Definition: precomp.h:26
UNICODE_STRING FreeBT_RegistryPath
Definition: fbtusb.h:61
#define FREEBT_REGISTRY_PARAMETERS_PATH
Definition: fbtusb.h:121
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
NTSTATUS NTAPI FreeBT_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtdev.c:412
NTSTATUS NTAPI FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtpwr.c:23
NTSTATUS NTAPI FreeBT_DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtdev.c:102
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1114
NTSTATUS NTAPI FreeBT_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value)
Definition: fbtpnp.c:1517
ULONG DebugLevel
Definition: fbtusb.c:26
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define UNICODE_NULL
long LONG
Definition: pedump.c:60
PDEVICE_OBJECT NTAPI IoAttachDeviceToDeviceStack(IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:966
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2174
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
PVOID DeviceExtension
Definition: env_spec_w32.h:418
NTSTATUS NTAPI FreeBT_DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtrwr.c:23
VOID NTAPI FreeBT_DriverUnload(IN PDRIVER_OBJECT DriverObject)
Definition: fbtusb.c:85
#define FreeBT_DbgPrint(level, _x_)
Definition: fbtusb.h:55
smooth NULL
Definition: ftsmooth.c:416
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
NTSTATUS NTAPI FreeBT_WmiDeRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
Definition: fbtwmi.c:59
NTSTATUS NTAPI FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtpnp.c:24
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define IRP_MJ_POWER
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
static const WCHAR L[]
Definition: oid.c:1250
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2180
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
static int state
Definition: maze.c:121
NTSTATUS NTAPI FreeBT_DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtrwr.c:253
#define IRP_MJ_SYSTEM_CONTROL
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PDRIVER_ADD_DEVICE AddDevice
Definition: iotypes.h:2112
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DRIVER_ADD_DEVICE * PDRIVER_ADD_DEVICE
Definition: iotypes.h:2108
unsigned int * PULONG
Definition: retypes.h:1
#define FILE_DEVICE_UNKNOWN
Definition: winioctl.h:139
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define INITIALIZE_PNP_STATE(_Data_)
Definition: fbtusb.h:107
NTSTATUS NTAPI FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtwmi.c:66
#define IRP_MJ_CLEANUP
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: iotypes.h:2181
NTSTATUS NTAPI FreeBT_AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: fbtusb.c:108
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
POWER_STATE NTAPI PoSetPowerState(IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE_TYPE Type, IN POWER_STATE State)
Definition: power.c:597
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
NTSTATUS NTAPI FreeBT_DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: fbtdev.c:23
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
return STATUS_SUCCESS
Definition: btrfs.c:2966
NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING UniRegistryPath)
Definition: fbtusb.c:40
struct _BEEP_DEVICE_EXTENSION * PDEVICE_EXTENSION
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
VOID NTAPI KeInitializeTimerEx(OUT PKTIMER Timer, IN TIMER_TYPE Type)
Definition: timerobj.c:244
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
BOOLEAN NTAPI IoIsWdmVersionAvailable(IN UCHAR MajorVersion, IN UCHAR MinorVersion)
Definition: util.c:126