2 * PROJECT: ReactOS USB Drivers
3 * COPYRIGHT: GPL - See COPYING in the top level directory
5 * PURPOSE: Generic USB mouse driver
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
11 BOOLEAN
mouse_connect(PDEV_CONNECT_DATA dev_mgr
, DEV_HANDLE dev_handle
);
12 BOOLEAN
mouse_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
13 BOOLEAN
mouse_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
);
14 VOID
mouse_irq(PURB purb
, PVOID pcontext
);
15 static NTSTATUS
MouseCreateDevice(IN PDRIVER_OBJECT DriverObject
, IN PMOUSE_DRVR_EXTENSION DriverExtension
);
18 mouse_driver_init(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
20 PMOUSE_DRVR_EXTENSION pdrvr_ext
;
22 if (dev_mgr
== NULL
|| pdriver
== NULL
)
25 //init driver structure, no PNP table functions
26 pdriver
->driver_desc
.flags
= USB_DRIVER_FLAG_IF_CAPABLE
;
27 pdriver
->driver_desc
.vendor_id
= 0xffff; // USB Vendor ID
28 pdriver
->driver_desc
.product_id
= 0xffff; // USB Product ID.
29 pdriver
->driver_desc
.release_num
= 0x100; // Release Number of Device
31 pdriver
->driver_desc
.config_val
= 1; // Configuration Value
32 pdriver
->driver_desc
.if_num
= 1; // Interface Number
33 pdriver
->driver_desc
.if_class
= USB_CLASS_HID
; // Interface Class
34 pdriver
->driver_desc
.if_sub_class
= 1; // Interface SubClass
35 pdriver
->driver_desc
.if_protocol
= 2; // Interface Protocol
37 pdriver
->driver_desc
.driver_name
= "USB Mouse driver"; // Driver name for Name Registry
38 pdriver
->driver_desc
.dev_class
= USB_CLASS_HID
;
39 pdriver
->driver_desc
.dev_sub_class
= 1; // Device Subclass
40 pdriver
->driver_desc
.dev_protocol
= 2; // Protocol Info.
42 pdriver
->driver_ext
= usb_alloc_mem(NonPagedPool
, sizeof(MOUSE_DRVR_EXTENSION
));
43 if (!pdriver
->driver_ext
) return FALSE
;
45 pdriver
->driver_ext_size
= sizeof(MOUSE_DRVR_EXTENSION
);
47 RtlZeroMemory(pdriver
->driver_ext
, sizeof(MOUSE_DRVR_EXTENSION
));
48 pdrvr_ext
= (PMOUSE_DRVR_EXTENSION
) pdriver
->driver_ext
;
49 pdrvr_ext
->dev_mgr
= dev_mgr
;
51 pdriver
->disp_tbl
.version
= 1;
52 pdriver
->disp_tbl
.dev_connect
= mouse_connect
;
53 pdriver
->disp_tbl
.dev_disconnect
= mouse_disconnect
;
54 pdriver
->disp_tbl
.dev_stop
= mouse_stop
;
55 pdriver
->disp_tbl
.dev_reserved
= NULL
;
58 MouseCreateDevice(dev_mgr
->usb_driver_obj
, pdrvr_ext
);
60 usb_dbg_print(DBGLVL_MAXIMUM
, ("mouse_driver_init(): mouse driver is initialized\n"));
65 mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr
, PUSB_DRIVER pdriver
)
67 //PMOUSE_DRVR_EXTENSION pdrvr_ext;
68 if (dev_mgr
== NULL
|| pdriver
== NULL
)
71 //pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
72 //umss_delete_port_device(pdrvr_ext->port_dev_obj);
73 //pdrvr_ext->port_dev_obj = NULL;
75 //ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE);
76 usb_free_mem(pdriver
->driver_ext
);
77 pdriver
->driver_ext
= NULL
;
78 pdriver
->driver_ext_size
= 0;
79 usb_dbg_print(DBGLVL_MAXIMUM
, ("mouse_driver_destroy(): mouse driver is destroyed\n"));
84 mouse_connect(PDEV_CONNECT_DATA param
, DEV_HANDLE dev_handle
)
88 PUSB_DEV_MANAGER dev_mgr
;
91 PMOUSE_DRVR_EXTENSION pdev_ext
;
93 PUSB_ENDPOINT_DESC pendp_desc
= NULL
;
96 usb_dbg_print(DBGLVL_MAXIMUM
, ("mouse_connect(): entering...\n"));
98 dev_mgr
= param
->dev_mgr
;
99 pdrvr
= param
->pdriver
;
100 pdev_ext
= (PMOUSE_DRVR_EXTENSION
)pdrvr
->driver_ext
;
103 status
= usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
);
104 if (status
!= STATUS_SUCCESS
)
106 //usb_free_mem(desc_buf);
107 usb_dbg_print(DBGLVL_MEDIUM
, ("mouse_connect(): unable to query&lock device, status=0x%x\n", status
));
111 // Get pointer to the endpoint descriptor
112 pendp_desc
= pdev
->usb_config
->interf
[0].endp
[0].pusb_endp_desc
;
114 // Store max packet size
115 MaxPacketSize
= pendp_desc
->wMaxPacketSize
;
116 if (MaxPacketSize
> 8)
120 usb_unlock_dev(pdev
);
123 purb
= usb_alloc_mem(NonPagedPool
, sizeof(URB
));
126 RtlZeroMemory(purb
, sizeof(URB
));
128 // Build a URB for our interrupt transfer
129 UsbBuildInterruptOrBulkTransferRequest(purb
,
130 usb_make_handle((dev_handle
>> 16), 0, 0),
131 (PUCHAR
)&pdev_ext
->mouse_data
,
132 MaxPacketSize
, //use max packet size
134 pdev_ext
->device_ext
,
137 // Call USB driver stack
138 status
= usb_submit_urb(pdev_ext
->dev_mgr
, purb
);
139 if (status
!= STATUS_PENDING
)
149 mouse_irq(PURB purb
, PVOID pcontext
)
151 MOUSE_INPUT_DATA MouseInputData
;
152 ULONG InputDataConsumed
;
154 PMOUSE_DRVR_EXTENSION pdev_ext
;
155 PMOUSE_DEVICE_EXTENSION DeviceExtension
= (PMOUSE_DEVICE_EXTENSION
)pcontext
;
157 usb_dbg_print(DBGLVL_MAXIMUM
, ("mouse_irq(): called\n"));
161 if (purb
->status
!= STATUS_SUCCESS
)
163 usb_dbg_print(DBGLVL_MAXIMUM
, ("mouse_irq(): purb->status 0x%08X\n", purb
->status
));
167 pdev_ext
= DeviceExtension
->DriverExtension
;
168 data
= pdev_ext
->mouse_data
;
170 usb_dbg_print(DBGLVL_MAXIMUM
, ("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data
[1], data
[2], data
[3], data
[0]));
172 // Fill mouse input data structure
173 MouseInputData
.Flags
= MOUSE_MOVE_RELATIVE
;
174 MouseInputData
.LastX
= data
[1];
175 MouseInputData
.LastY
= data
[2];
177 MouseInputData
.ButtonFlags
= 0;
178 MouseInputData
.ButtonData
= 0;
180 if ((data
[0] & 0x01) && ((pdev_ext
->btn_old
& 0x01) != (data
[0] & 0x01)))
181 MouseInputData
.ButtonFlags
|= MOUSE_LEFT_BUTTON_DOWN
;
182 else if (!(data
[0] & 0x01) && ((pdev_ext
->btn_old
& 0x01) != (data
[0] & 0x01)))
183 MouseInputData
.ButtonFlags
|= MOUSE_LEFT_BUTTON_UP
;
185 if ((data
[0] & 0x02) && ((pdev_ext
->btn_old
& 0x02) != (data
[0] & 0x02)))
186 MouseInputData
.ButtonFlags
|= MOUSE_RIGHT_BUTTON_DOWN
;
187 else if (!(data
[0] & 0x02) && ((pdev_ext
->btn_old
& 0x02) != (data
[0] & 0x02)))
188 MouseInputData
.ButtonFlags
|= MOUSE_RIGHT_BUTTON_UP
;
190 if ((data
[0] & 0x04) && ((pdev_ext
->btn_old
& 0x04) != (data
[0] & 0x04)))
191 MouseInputData
.ButtonFlags
|= MOUSE_MIDDLE_BUTTON_DOWN
;
192 else if (!(data
[0] & 0x04) && ((pdev_ext
->btn_old
& 0x04) != (data
[0] & 0x04)))
193 MouseInputData
.ButtonFlags
|= MOUSE_MIDDLE_BUTTON_UP
;
195 if ((data
[0] & 0x08) && ((pdev_ext
->btn_old
& 0x08) != (data
[0] & 0x08)))
196 MouseInputData
.ButtonFlags
|= MOUSE_BUTTON_4_DOWN
;
197 else if (!(data
[0] & 0x08) && ((pdev_ext
->btn_old
& 0x08) != (data
[0] & 0x08)))
198 MouseInputData
.ButtonFlags
|= MOUSE_BUTTON_4_UP
;
200 if ((data
[0] & 0x10) && ((pdev_ext
->btn_old
& 0x10) != (data
[0] & 0x10)))
201 MouseInputData
.ButtonFlags
|= MOUSE_BUTTON_5_DOWN
;
202 else if (!(data
[0] & 0x10) && ((pdev_ext
->btn_old
& 0x10) != (data
[0] & 0x10)))
203 MouseInputData
.ButtonFlags
|= MOUSE_BUTTON_5_UP
;
207 MouseInputData
.ButtonFlags
|= MOUSE_WHEEL
;
208 MouseInputData
.ButtonData
= data
[3];
211 // Commit the input data somewhere...
212 if (DeviceExtension
->ConnectData
.ClassService
)
216 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
217 (*(PSERVICE_CALLBACK_ROUTINE
)DeviceExtension
->ConnectData
.ClassService
)(
218 DeviceExtension
->ConnectData
.ClassDeviceObject
,
222 KeLowerIrql(OldIrql
);
225 // Save old button data
226 pdev_ext
->btn_old
= data
[0];
229 status
= usb_submit_urb(pdev_ext
->dev_mgr
, purb
);
233 mouse_stop(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
235 UNREFERENCED_PARAMETER(dev_handle
);
236 UNREFERENCED_PARAMETER(dev_mgr
);
241 mouse_disconnect(PUSB_DEV_MANAGER dev_mgr
, DEV_HANDLE dev_handle
)
243 PDEVICE_OBJECT dev_obj
;
248 if (dev_mgr
== NULL
|| dev_handle
== 0)
252 //special use of the lock dev, simply use this routine to get the dev
253 status
= usb_query_and_lock_dev(dev_mgr
, dev_handle
, &pdev
);
258 if (status
== STATUS_SUCCESS
)
262 usb_unlock_dev(pdev
);
264 pdrvr
= pdev
->dev_driver
;
265 dev_obj
= pdev
->dev_obj
;
268 return TRUE
;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
271 // Dispatch routine for our IRPs
273 MouseDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
275 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
276 PMOUSE_DEVICE_EXTENSION DeviceExtension
;
278 DeviceExtension
= DeviceObject
->DeviceExtension
;
280 usb_dbg_print(DBGLVL_MAXIMUM
, ("MouseDispatch(DO %p, code 0x%lx) called\n",
282 IoGetCurrentIrpStackLocation(Irp
)->Parameters
.DeviceIoControl
.IoControlCode
));
284 if (DeviceObject
== DeviceExtension
->Fdo
)
286 // it's mouse's IOCTL
287 PIO_STACK_LOCATION Stk
;
289 Irp
->IoStatus
.Information
= 0;
290 Stk
= IoGetCurrentIrpStackLocation(Irp
);
292 switch (Stk
->Parameters
.DeviceIoControl
.IoControlCode
)
294 case IOCTL_INTERNAL_MOUSE_CONNECT
:
295 usb_dbg_print(DBGLVL_MAXIMUM
, ("IOCTL_INTERNAL_MOUSE_CONNECT\n"));
296 if (Stk
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(CONNECT_DATA
)) {
297 usb_dbg_print(DBGLVL_MINIMUM
, ("IOCTL_INTERNAL_MOUSE_CONNECT: "
298 "invalid buffer size\n"));
299 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
300 goto intcontfailure2
;
303 RtlCopyMemory(&DeviceExtension
->ConnectData
,
304 Stk
->Parameters
.DeviceIoControl
.Type3InputBuffer
,
305 sizeof(CONNECT_DATA
));
307 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
311 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;//STATUS_INVALID_DEVICE_REQUEST;
315 Status
= Irp
->IoStatus
.Status
;
318 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
320 usb_dbg_print(DBGLVL_MINIMUM
, ("Invalid internal device request!\n"));
323 if (Status
!= STATUS_PENDING
)
324 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
331 IN PCWSTR PortTypeName
,
332 IN PUNICODE_STRING DeviceName
,
333 IN PCWSTR RegistryPath
)
335 UNICODE_STRING PathU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
336 OBJECT_ATTRIBUTES ObjectAttributes
;
337 HANDLE hDeviceMapKey
= (HANDLE
)-1;
338 HANDLE hPortKey
= (HANDLE
)-1;
339 UNICODE_STRING PortTypeNameU
;
342 InitializeObjectAttributes(&ObjectAttributes
, &PathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
343 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
344 if (!NT_SUCCESS(Status
))
346 usb_dbg_print(DBGLVL_MINIMUM
, ("ZwOpenKey() failed with status 0x%08lx\n", Status
));
350 RtlInitUnicodeString(&PortTypeNameU
, PortTypeName
);
351 InitializeObjectAttributes(&ObjectAttributes
, &PortTypeNameU
, OBJ_KERNEL_HANDLE
, hDeviceMapKey
, NULL
);
352 Status
= ZwCreateKey(&hPortKey
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
353 if (!NT_SUCCESS(Status
))
355 usb_dbg_print(DBGLVL_MINIMUM
, ("ZwCreateKey() failed with status 0x%08lx\n", Status
));
359 Status
= ZwSetValueKey(hPortKey
, DeviceName
, 0, REG_SZ
, (PVOID
)RegistryPath
, (ULONG
)(wcslen(RegistryPath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
)));
360 if (!NT_SUCCESS(Status
))
362 usb_dbg_print(DBGLVL_MINIMUM
, ("ZwSetValueKey() failed with status 0x%08lx\n", Status
));
366 Status
= STATUS_SUCCESS
;
369 if (hDeviceMapKey
!= (HANDLE
)-1)
370 ZwClose(hDeviceMapKey
);
371 if (hPortKey
!= (HANDLE
)-1)
377 MouseCreateDevice(IN PDRIVER_OBJECT DriverObject
, IN PMOUSE_DRVR_EXTENSION DriverExtension
)
379 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\PointerPortUSB");
380 PMOUSE_DEVICE_EXTENSION DeviceExtension
;
384 Status
= AddRegistryEntry(L
"PointerPort", &DeviceName
, L
"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver");
385 if (!NT_SUCCESS(Status
))
387 usb_dbg_print(DBGLVL_MINIMUM
, ("AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status
));
391 Status
= IoCreateDevice(DriverObject
,
392 sizeof(MOUSE_DEVICE_EXTENSION
),
395 FILE_DEVICE_SECURE_OPEN
,
399 if (!NT_SUCCESS(Status
))
401 usb_dbg_print(DBGLVL_MINIMUM
, ("IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status
));
404 DeviceExtension
= (PMOUSE_DEVICE_EXTENSION
)Fdo
->DeviceExtension
;
405 RtlZeroMemory(DeviceExtension
, sizeof(MOUSE_DEVICE_EXTENSION
));
407 DeviceExtension
->hdr
.dispatch
= MouseDispatch
;
408 DeviceExtension
->DriverExtension
= DriverExtension
;
409 DriverExtension
->device_ext
= DeviceExtension
;
411 DeviceExtension
->Fdo
= Fdo
;
412 Fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
413 usb_dbg_print(DBGLVL_MEDIUM
, ("Created mouse Fdo: %p\n", Fdo
));
415 return STATUS_SUCCESS
;