set most of trunk svn property eol-style:native
[reactos.git] / reactos / drivers / usb / nt4compat / usbdriver / mouse.c
1 /*
2 * PROJECT: ReactOS USB Drivers
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: mouse.c
5 * PURPOSE: Generic USB mouse driver
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 #include "usbdriver.h"
10 #include "ntddmou.h"
11 #include "kbdmou.h"
12
13 //FIXME: is it needed at all?
14 typedef struct _USBMP_DEVICE_EXTENSION
15 {
16 BOOLEAN IsFDO;
17 } USBMP_DEVICE_EXTENSION, *PUSBMP_DEVICE_EXTENSION;
18
19 /* Data for embedded drivers */
20 //CONNECT_DATA KbdClassInformation;
21 CONNECT_DATA MouseClassInformation;
22
23 PDEVICE_OBJECT MouseFdo = NULL;
24
25
26 BOOLEAN mouse_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
27 BOOLEAN mouse_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
28 BOOLEAN mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
29 VOID mouse_irq(PURB purb, PVOID pcontext);
30 static NTSTATUS
31 MouseCreateDevice(IN PDRIVER_OBJECT DriverObject);
32
33
34 BOOLEAN
35 mouse_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
36 {
37 PMOUSE_DRVR_EXTENSION pdrvr_ext;
38
39 if (dev_mgr == NULL || pdriver == NULL)
40 return FALSE;
41
42 //init driver structure, no PNP table functions
43 pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
44 pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID
45 pdriver->driver_desc.product_id = 0xffff; // USB Product ID.
46 pdriver->driver_desc.release_num = 0x100; // Release Number of Device
47
48 pdriver->driver_desc.config_val = 1; // Configuration Value
49 pdriver->driver_desc.if_num = 1; // Interface Number
50 pdriver->driver_desc.if_class = USB_CLASS_HID; // Interface Class
51 pdriver->driver_desc.if_sub_class = 1; // Interface SubClass
52 pdriver->driver_desc.if_protocol = 2; // Interface Protocol
53
54 pdriver->driver_desc.driver_name = "USB Mouse driver"; // Driver name for Name Registry
55 pdriver->driver_desc.dev_class = USB_CLASS_HID;
56 pdriver->driver_desc.dev_sub_class = 1; // Device Subclass
57 pdriver->driver_desc.dev_protocol = 2; // Protocol Info.
58
59 pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(MOUSE_DRVR_EXTENSION));
60 pdriver->driver_ext_size = sizeof(MOUSE_DRVR_EXTENSION);
61
62 RtlZeroMemory(pdriver->driver_ext, sizeof(MOUSE_DRVR_EXTENSION));
63 pdrvr_ext = (PMOUSE_DRVR_EXTENSION) pdriver->driver_ext;
64 pdrvr_ext->dev_mgr = dev_mgr;
65
66 pdriver->disp_tbl.version = 1;
67 pdriver->disp_tbl.dev_connect = mouse_connect;
68 pdriver->disp_tbl.dev_disconnect = mouse_disconnect;
69 pdriver->disp_tbl.dev_stop = mouse_stop;
70 pdriver->disp_tbl.dev_reserved = NULL;
71
72 // Zero out the class information structure
73 RtlZeroMemory(&MouseClassInformation, sizeof(CONNECT_DATA));
74
75 // Create the device
76 MouseCreateDevice(dev_mgr->usb_driver_obj);
77
78 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_driver_init(): mouse driver is initialized\n"));
79 return TRUE;
80 }
81
82 BOOLEAN
83 mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
84 {
85 //PMOUSE_DRVR_EXTENSION pdrvr_ext;
86 if (dev_mgr == NULL || pdriver == NULL)
87 return FALSE;
88
89 //pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
90 //umss_delete_port_device(pdrvr_ext->port_dev_obj);
91 //pdrvr_ext->port_dev_obj = NULL;
92
93 //ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE);
94 usb_free_mem(pdriver->driver_ext);
95 pdriver->driver_ext = NULL;
96 pdriver->driver_ext_size = 0;
97 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_driver_destroy(): mouse driver is destroyed\n"));
98 return TRUE;
99 }
100
101 BOOLEAN
102 mouse_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
103 {
104 PURB purb;
105 NTSTATUS status;
106 PUSB_DEV_MANAGER dev_mgr;
107 PUSB_DRIVER pdrvr;
108 PUSB_DEV pdev;
109 PMOUSE_DRVR_EXTENSION pdev_ext;
110 // LONG i;
111 PUSB_ENDPOINT_DESC pendp_desc = NULL;
112 ULONG MaxPacketSize;
113
114 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_connect(): entering...\n"));
115
116 dev_mgr = param->dev_mgr;
117 pdrvr = param->pdriver;
118 pdev_ext = (PMOUSE_DRVR_EXTENSION)pdrvr->driver_ext;
119
120 // Lock USB Device
121 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
122 if (status != STATUS_SUCCESS)
123 {
124 //usb_free_mem(desc_buf);
125 usb_dbg_print(DBGLVL_MEDIUM, ("mouse_connect(): unable to query&lock device, status=0x%x\n", status));
126 return FALSE;
127 }
128
129 // Endpoint-finding code
130 if (param->if_desc)
131 {
132 // Get a pointer to the config packet from compdev
133 PUCHAR Buffer = (PUCHAR)param->if_desc;
134 ULONG Offset = 0;
135 BOOLEAN FoundEndpoint = FALSE;
136
137 // Find our the only needed endpoint descriptor
138 while (Offset < 512)
139 {
140 pendp_desc = (PUSB_ENDPOINT_DESC)&Buffer[Offset];
141 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_connect(): DescType=0x%x, Attrs=0x%x, Len=%d\n",
142 pendp_desc->bDescriptorType, pendp_desc->bmAttributes, pendp_desc->bLength));
143
144 if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT &&
145 pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
146 {
147 // Found it
148 FoundEndpoint = TRUE;
149 break;
150 }
151
152 Offset += pendp_desc->bLength;
153 }
154
155 if (!FoundEndpoint)
156 return FALSE;
157
158 // FIXME: Check if it's INT endpoint
159 // (pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
160
161 // endpoint must be IN
162 if ((pendp_desc->bEndpointAddress & USB_DIR_IN) == 0)
163 return FALSE;
164 }
165
166
167 // Endpoint descriptor substitution code
168 {
169 ULONG if_idx, endp_idx;
170 PUSB_ENDPOINT pendp;
171
172 //FoundEndpoint = FALSE;
173 for(if_idx = 0; if_idx < MAX_INTERFACES_PER_CONFIG /*pdev->usb_config->if_count*/; if_idx++)
174 {
175 for(endp_idx = 0; endp_idx < MAX_ENDPS_PER_IF /*pdev->usb_config->interf[if_idx].endp_count*/; endp_idx++)
176 {
177 pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx];
178
179 if (pendp->pusb_endp_desc != NULL)
180 {
181 //HACKHACK: for some reason this usb driver chooses different and completely wrong
182 // endpoint. Since I don't have time to research this, I just find the
183 // endpoint descriptor myself and copy it
184 memcpy(pendp->pusb_endp_desc, pendp_desc, pendp_desc->bLength);
185
186 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_connect(): [%i][%i] DescType=0x%x, Attrs=0x%x, Len=%d\n",if_idx, endp_idx,
187 pendp->pusb_endp_desc->bDescriptorType, pendp->pusb_endp_desc->bmAttributes, pendp->pusb_endp_desc->bLength));
188 }
189 }
190 }
191 }
192
193 // Unlock USB Device
194 usb_unlock_dev(pdev);
195
196 // Send URB
197 purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
198 if (purb == NULL)
199 return FALSE;
200 RtlZeroMemory(purb, sizeof(URB));
201
202 MaxPacketSize = pendp_desc->wMaxPacketSize;
203 if (MaxPacketSize > 8)
204 MaxPacketSize = 8;
205
206 // Build a URB for our interrupt transfer
207 UsbBuildInterruptOrBulkTransferRequest(purb,
208 usb_make_handle((dev_handle >> 16), 0, 0),
209 (PUCHAR)&pdev_ext->mouse_data,
210 MaxPacketSize, //use max packet size
211 mouse_irq,
212 pdev_ext,
213 0);
214
215 // Call USB driver stack
216 status = usb_submit_urb(pdev_ext->dev_mgr, purb);
217 if (status != STATUS_PENDING)
218 {
219 usb_free_mem(purb);
220 purb = NULL;
221 }
222
223 return TRUE;
224 }
225
226 VOID
227 mouse_irq(PURB purb, PVOID pcontext)
228 {
229 MOUSE_INPUT_DATA MouseInputData;
230 ULONG InputDataConsumed;
231 NTSTATUS status;
232 PMOUSE_DRVR_EXTENSION pdev_ext = (PMOUSE_DRVR_EXTENSION)pcontext;
233 signed char *data = pdev_ext->mouse_data;
234 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): called\n"));
235
236 ASSERT(purb);
237
238 if (purb->status != STATUS_SUCCESS)
239 {
240 usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): purb->status 0x%08X\n", purb->status));
241 //return;
242 }
243
244 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]));
245
246 // Fill mouse input data structure
247 MouseInputData.Flags = MOUSE_MOVE_RELATIVE;
248 MouseInputData.LastX = data[1];
249 MouseInputData.LastY = data[2];
250
251 MouseInputData.ButtonFlags = 0;
252 MouseInputData.ButtonData = 0;
253
254 if ((data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01)))
255 MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
256 else if (!(data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01)))
257 MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
258
259 if ((data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02)))
260 MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
261 else if (!(data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02)))
262 MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
263
264 if ((data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04)))
265 MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
266 else if (!(data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04)))
267 MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
268
269 if ((data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08)))
270 MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN;
271 else if (!(data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08)))
272 MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP;
273
274 if ((data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10)))
275 MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN;
276 else if (!(data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10)))
277 MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP;
278
279 if (data[3])
280 {
281 MouseInputData.ButtonFlags |= MOUSE_WHEEL;
282 MouseInputData.ButtonData = data[3];
283 }
284
285 // Commit the input data somewhere...
286 if (MouseClassInformation.ClassService)
287 {
288 KIRQL OldIrql;
289
290 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
291 (*(PSERVICE_CALLBACK_ROUTINE)MouseClassInformation.ClassService)(
292 MouseClassInformation.ClassDeviceObject,
293 &MouseInputData,
294 (&MouseInputData)+1,
295 &InputDataConsumed);
296 KeLowerIrql(OldIrql);
297 }
298
299 // Save old button data
300 pdev_ext->btn_old = data[0];
301
302 // resubmit the urb
303 status = usb_submit_urb(pdev_ext->dev_mgr, purb);
304 }
305
306 BOOLEAN
307 mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
308 {
309 UNREFERENCED_PARAMETER(dev_handle);
310 UNREFERENCED_PARAMETER(dev_mgr);
311 return TRUE;
312 }
313
314 BOOLEAN
315 mouse_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
316 {
317 PDEVICE_OBJECT dev_obj;
318 NTSTATUS status;
319 PUSB_DEV pdev;
320 PUSB_DRIVER pdrvr;
321
322 if (dev_mgr == NULL || dev_handle == 0)
323 return FALSE;
324
325 pdev = NULL;
326 //special use of the lock dev, simply use this routine to get the dev
327 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
328 if (pdev == NULL)
329 {
330 return FALSE;
331 }
332 if (status == STATUS_SUCCESS)
333 {
334 // must be a bug
335 TRAP();
336 usb_unlock_dev(pdev);
337 }
338 pdrvr = pdev->dev_driver;
339 dev_obj = pdev->dev_obj;
340 pdev = NULL;
341
342 return TRUE;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
343 }
344
345 // Dispatch routine for our IRPs
346 NTSTATUS
347 MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
348 {
349 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
350
351 usb_dbg_print(DBGLVL_MAXIMUM, ("MouseDispatch(DO %p, code 0x%lx) called\n",
352 DeviceObject,
353 IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode));
354 #if 0
355 if (DeviceObject == KeyboardFdo)
356 {
357 // it's keyboard's IOCTL
358 PIO_STACK_LOCATION Stk;
359
360 Irp->IoStatus.Information = 0;
361 Stk = IoGetCurrentIrpStackLocation(Irp);
362
363 switch (Stk->Parameters.DeviceIoControl.IoControlCode)
364 {
365 case IOCTL_INTERNAL_KEYBOARD_CONNECT:
366 DPRINT("IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
367 if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(DEV_CONNECT_DATA)) {
368 DPRINT1("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT "
369 "invalid buffer size\n");
370 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
371 goto intcontfailure;
372 }
373
374 RtlCopyMemory(&KbdClassInformation,
375 Stk->Parameters.DeviceIoControl.Type3InputBuffer,
376 sizeof(DEV_CONNECT_DATA));
377
378 Irp->IoStatus.Status = STATUS_SUCCESS;
379 break;
380
381 case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER:
382 DPRINT("IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER\n");
383 if (Stk->Parameters.DeviceIoControl.InputBufferLength < 1) {
384 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
385 goto intcontfailure;
386 }
387 /* if (!DevExt->KeyboardInterruptObject) {
388 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
389 goto intcontfailure;
390 }*/
391
392 Irp->IoStatus.Status = STATUS_SUCCESS;
393 break;
394 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
395 DPRINT("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n");
396 if (Stk->Parameters.DeviceIoControl.OutputBufferLength <
397 sizeof(KEYBOARD_ATTRIBUTES)) {
398 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES: "
399 "invalid buffer size\n");
400 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
401 goto intcontfailure;
402 }
403 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
404 &DevExt->KeyboardAttributes,
405 sizeof(KEYBOARD_ATTRIBUTES));*/
406
407 Irp->IoStatus.Status = STATUS_SUCCESS;
408 break;
409 case IOCTL_KEYBOARD_QUERY_INDICATORS:
410 DPRINT("IOCTL_KEYBOARD_QUERY_INDICATORS\n");
411 if (Stk->Parameters.DeviceIoControl.OutputBufferLength <
412 sizeof(KEYBOARD_INDICATOR_PARAMETERS)) {
413 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_INDICATORS: "
414 "invalid buffer size\n");
415 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
416 goto intcontfailure;
417 }
418 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
419 &DevExt->KeyboardIndicators,
420 sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/
421
422 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
423 break;
424 case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
425 DPRINT("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n");
426 if (Stk->Parameters.DeviceIoControl.OutputBufferLength <
427 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
428 DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC: "
429 "invalid buffer size\n");
430 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
431 goto intcontfailure;
432 }
433 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
434 &DevExt->KeyboardTypematic,
435 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
436
437 Irp->IoStatus.Status = STATUS_SUCCESS;
438 break;
439 case IOCTL_KEYBOARD_SET_INDICATORS:
440 DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n");
441 if (Stk->Parameters.DeviceIoControl.InputBufferLength <
442 sizeof(KEYBOARD_INDICATOR_PARAMETERS)) {
443 DPRINT("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS: "
444 "invalid buffer size\n");
445 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
446 goto intcontfailure;
447 }
448
449 /*RtlCopyMemory(&DevExt->KeyboardIndicators,
450 Irp->AssociatedIrp.SystemBuffer,
451 sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/
452
453 //DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags);
454
455 Irp->IoStatus.Status = STATUS_SUCCESS;
456 break;
457 case IOCTL_KEYBOARD_SET_TYPEMATIC:
458 DPRINT("IOCTL_KEYBOARD_SET_TYPEMATIC\n");
459 if (Stk->Parameters.DeviceIoControl.InputBufferLength <
460 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
461 DPRINT("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC "
462 "invalid buffer size\n");
463 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
464 goto intcontfailure;
465 }
466
467 /*RtlCopyMemory(&DevExt->KeyboardTypematic,
468 Irp->AssociatedIrp.SystemBuffer,
469 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/
470
471 Irp->IoStatus.Status = STATUS_SUCCESS;
472 break;
473 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
474 /* We should check the UnitID, but it's kind of pointless as
475 * all keyboards are supposed to have the same one
476 */
477 /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
478 &IndicatorTranslation,
479 sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION));*/
480
481 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
482 break;
483 case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
484 /* Nothing to do here */
485 Irp->IoStatus.Status = STATUS_SUCCESS;
486 break;
487 default:
488 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
489 break;
490 }
491
492 intcontfailure:
493 Status = Irp->IoStatus.Status;
494 }
495 else
496 #endif
497 if (DeviceObject == MouseFdo)
498 {
499 // it's mouse's IOCTL
500 PIO_STACK_LOCATION Stk;
501
502 Irp->IoStatus.Information = 0;
503 Stk = IoGetCurrentIrpStackLocation(Irp);
504
505 switch (Stk->Parameters.DeviceIoControl.IoControlCode)
506 {
507 case IOCTL_INTERNAL_MOUSE_CONNECT:
508 usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT\n"));
509 if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) {
510 usb_dbg_print(DBGLVL_MINIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT: "
511 "invalid buffer size\n"));
512 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
513 goto intcontfailure2;
514 }
515
516 RtlCopyMemory(&MouseClassInformation,
517 Stk->Parameters.DeviceIoControl.Type3InputBuffer,
518 sizeof(CONNECT_DATA));
519
520 Irp->IoStatus.Status = STATUS_SUCCESS;
521 break;
522
523 default:
524 Irp->IoStatus.Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST;
525 break;
526 }
527 intcontfailure2:
528 Status = Irp->IoStatus.Status;
529 }
530
531 if (Status == STATUS_INVALID_DEVICE_REQUEST)
532 {
533 usb_dbg_print(DBGLVL_MINIMUM, ("Invalid internal device request!\n"));
534 }
535
536 if (Status != STATUS_PENDING)
537 IoCompleteRequest(Irp, IO_NO_INCREMENT);
538
539 return Status;
540 }
541
542 NTSTATUS
543 AddRegistryEntry(
544 IN PCWSTR PortTypeName,
545 IN PUNICODE_STRING DeviceName,
546 IN PCWSTR RegistryPath)
547 {
548 UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
549 OBJECT_ATTRIBUTES ObjectAttributes;
550 HANDLE hDeviceMapKey = (HANDLE)-1;
551 HANDLE hPortKey = (HANDLE)-1;
552 UNICODE_STRING PortTypeNameU;
553 NTSTATUS Status;
554
555 InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
556 Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
557 if (!NT_SUCCESS(Status))
558 {
559 usb_dbg_print(DBGLVL_MINIMUM, ("ZwOpenKey() failed with status 0x%08lx\n", Status));
560 goto cleanup;
561 }
562
563 RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
564 InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
565 Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
566 if (!NT_SUCCESS(Status))
567 {
568 usb_dbg_print(DBGLVL_MINIMUM, ("ZwCreateKey() failed with status 0x%08lx\n", Status));
569 goto cleanup;
570 }
571
572 Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, (ULONG)(wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL)));
573 if (!NT_SUCCESS(Status))
574 {
575 usb_dbg_print(DBGLVL_MINIMUM, ("ZwSetValueKey() failed with status 0x%08lx\n", Status));
576 goto cleanup;
577 }
578
579 Status = STATUS_SUCCESS;
580
581 cleanup:
582 if (hDeviceMapKey != (HANDLE)-1)
583 ZwClose(hDeviceMapKey);
584 if (hPortKey != (HANDLE)-1)
585 ZwClose(hPortKey);
586 return Status;
587 }
588
589 static NTSTATUS
590 MouseCreateDevice(IN PDRIVER_OBJECT DriverObject)
591 {
592 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerPortUSB");
593 PDEVEXT_HEADER DeviceExtension;
594 PDEVICE_OBJECT Fdo;
595 NTSTATUS Status;
596
597 Status = AddRegistryEntry(L"PointerPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver");
598 if (!NT_SUCCESS(Status))
599 {
600 usb_dbg_print(DBGLVL_MINIMUM, ("AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status));
601 return Status;
602 }
603
604 Status = IoCreateDevice(DriverObject,
605 sizeof(DEVEXT_HEADER),
606 &DeviceName,
607 FILE_DEVICE_MOUSE,
608 FILE_DEVICE_SECURE_OPEN,
609 TRUE,
610 &Fdo);
611
612 if (!NT_SUCCESS(Status))
613 {
614 usb_dbg_print(DBGLVL_MINIMUM, ("IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status));
615 return Status;
616 }
617 DeviceExtension = (PDEVEXT_HEADER)Fdo->DeviceExtension;
618 RtlZeroMemory(DeviceExtension, sizeof(DEVEXT_HEADER));
619
620 DeviceExtension->dispatch = MouseDispatch;
621
622 MouseFdo = Fdo;
623 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
624 usb_dbg_print(DBGLVL_MEDIUM, ("Created mouse Fdo: %p\n", Fdo));
625
626 return STATUS_SUCCESS;
627 }
628