- Attempt to avoid interaction with kernel debugging over serial port.
[reactos.git] / reactos / drivers / input / sermouse / sermouse.c
1 /*
2 * Serial Mouse driver 0.0.9
3 * Written by Jason Filby (jasonfilby@yahoo.com)
4 * And heavily rewritten by Filip Navara (xnavara@volny.cz)
5 * For ReactOS (www.reactos.com)
6 *
7 * Technical information about mouse protocols can be found
8 * in the file sermouse.txt.
9 */
10
11 #include <ddk/ntddk.h>
12 #include <ddk/ntddmou.h>
13
14 /*
15 * HAL:KdComPortInUse used to prevent detecting mouse on port
16 * that is occupied by kernel debugger.
17 */
18 ULONG DECLSPEC_IMPORT KdComPortInUse;
19
20 /*
21 * Compile time options
22 */
23
24 /* Support for the IOCTL_MOUSE_QUERY_ATTRIBUTES I/O control code */
25 #define SERMOUSE_QUERYATTRIBUTES_SUPPORT
26 /* Check for mouse on COM1? */
27 #define SERMOUSE_COM1_SUPPORT
28 /* Check for mouse on COM2? */
29 #define SERMOUSE_COM2_SUPPORT
30 /* Create \??\Mouse* symlink for device? */
31 #define SERMOUSE_MOUSESYMLINK_SUPPORT
32
33 /*
34 * Definitions
35 */
36
37 #define MOUSE_IRQ_COM1 4
38 #define MOUSE_IRQ_COM2 3
39 #define MOUSE_PORT_COM1 0x3f8
40 #define MOUSE_PORT_COM2 0x2f8
41
42 /* Maximum value plus one for \Device\PointerClass* device name */
43 #define POINTER_PORTS_MAXIMUM 8
44 /* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
45 #define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
46
47 /* No Mouse */
48 #define MOUSE_TYPE_NONE 0
49 /* Microsoft Mouse with 2 buttons */
50 #define MOUSE_TYPE_MICROSOFT 1
51 /* Logitech Mouse with 3 buttons */
52 #define MOUSE_TYPE_LOGITECH 2
53 /* Microsoft Wheel Mouse (aka Z Mouse) */
54 #define MOUSE_TYPE_WHEELZ 3
55 /* Mouse Systems Mouse */
56 #define MOUSE_TYPE_MOUSESYSTEMS 4
57
58 /* Size for packet buffer used in interrupt routine */
59 #define PACKET_BUFFER_SIZE 4
60
61 /* Hardware byte mask for left button */
62 #define LEFT_BUTTON_MASK 0x20
63 /* Hardware to Microsoft specific code byte shift for left button */
64 #define LEFT_BUTTON_SHIFT 5
65 /* Hardware byte mask for right button */
66 #define RIGHT_BUTTON_MASK 0x10
67 /* Hardware to Microsoft specific code byte shift for right button */
68 #define RIGHT_BUTTON_SHIFT 3
69 /* Hardware byte mask for middle button */
70 #define MIDDLE_BUTTON_MASK 0x20
71 /* Hardware to Microsoft specific code byte shift for middle button */
72 #define MIDDLE_BUTTON_SHIFT 3
73
74 /* Microsoft byte mask for left button */
75 #define MOUSE_BUTTON_LEFT 0x01
76 /* Microsoft byte mask for right button */
77 #define MOUSE_BUTTON_RIGHT 0x02
78 /* Microsoft byte mask for middle button */
79 #define MOUSE_BUTTON_MIDDLE 0x04
80
81 /*
82 * Structures
83 */
84
85 typedef struct _DEVICE_EXTENSION {
86 PDEVICE_OBJECT DeviceObject;
87 ULONG ActiveQueue;
88 ULONG InputDataCount[2];
89 MOUSE_INPUT_DATA MouseInputData[2][MOUSE_BUFFER_SIZE];
90 CLASS_INFORMATION ClassInformation;
91 PKINTERRUPT MouseInterrupt;
92 KDPC IsrDpc;
93 ULONG MousePort;
94 ULONG MouseType;
95 UCHAR PacketBuffer[PACKET_BUFFER_SIZE];
96 ULONG PacketBufferPosition;
97 ULONG PreviousButtons;
98 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
99 MOUSE_ATTRIBUTES AttributesInformation;
100 #endif
101 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
102
103 /*
104 * Functions
105 */
106
107 void ClearMouse(ULONG Port)
108 {
109 /* Waits until the mouse calms down but also quits out after a while
110 * in case some destructive user wants to keep moving the mouse
111 * before we're done */
112 unsigned int Restarts = 0, i;
113 for (i = 0; i < 60000; i++)
114 {
115 unsigned Temp = READ_PORT_UCHAR((PUCHAR)Port);
116 if (Temp != 0)
117 {
118 Restarts++;
119 if (Restarts < 300000)
120 i = 0;
121 else
122 i = 60000;
123 }
124 }
125 }
126
127 BOOLEAN STDCALL
128 SerialMouseInterruptService(IN PKINTERRUPT Interrupt, PVOID ServiceContext)
129 {
130 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
131 PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
132 UCHAR *PacketBuffer = DeviceExtension->PacketBuffer;
133 ULONG MousePort = DeviceExtension->MousePort;
134 UCHAR InterruptId = READ_PORT_UCHAR((PUCHAR)MousePort + 2);
135 UCHAR RecievedByte;
136 ULONG Queue;
137 PMOUSE_INPUT_DATA Input;
138 ULONG ButtonsDifference;
139
140 /* Is the interrupt for us? */
141 if ((InterruptId & 0x01) == 0x01)
142 {
143 return FALSE;
144 }
145
146 /* Not a Receive Data Available interrupt? */
147 if ((InterruptId & 0x04) == 0)
148 {
149 return TRUE;
150 }
151
152 /* Read all available data and process */
153 while ((READ_PORT_UCHAR((PUCHAR)MousePort + 5) & 0x01) != 0)
154 {
155 RecievedByte = READ_PORT_UCHAR((PUCHAR)MousePort);
156
157 /* Synchronize */
158 if ((RecievedByte & 0x40) == 0x40)
159 DeviceExtension->PacketBufferPosition = 0;
160
161 PacketBuffer[DeviceExtension->PacketBufferPosition] =
162 (RecievedByte & 0x7f);
163 ++DeviceExtension->PacketBufferPosition;
164
165 /* Process packet if complete */
166 if (DeviceExtension->PacketBufferPosition >= 3)
167 {
168 Queue = DeviceExtension->ActiveQueue % 2;
169
170 /* Prevent buffer overflow */
171 if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
172 continue;
173
174 Input = &DeviceExtension->MouseInputData[Queue][DeviceExtension->InputDataCount[Queue]];
175
176 if (DeviceExtension->PacketBufferPosition == 3)
177 {
178 /* Retrieve change in x and y from packet */
179 Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6));
180 Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4));
181
182 /* Determine the current state of the buttons */
183 Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) |
184 ((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) |
185 ((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT);
186 } else
187 if (DeviceExtension->PacketBufferPosition == 4)
188 {
189 DeviceExtension->PacketBufferPosition = 0;
190 /* If middle button state changed than report event */
191 if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^
192 (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE))
193 {
194 Input->RawButtons ^= MOUSE_BUTTON_MIDDLE;
195 Input->LastX = 0;
196 Input->LastY = 0;
197 }
198 else
199 {
200 continue;
201 }
202 }
203
204 /* Determine ButtonFlags */
205 Input->ButtonFlags = 0;
206 ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons;
207
208 if (ButtonsDifference != 0)
209 {
210 if (ButtonsDifference & MOUSE_BUTTON_LEFT)
211 {
212 if (Input->RawButtons & MOUSE_BUTTON_LEFT)
213 Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
214 else
215 Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
216 }
217 if (ButtonsDifference & MOUSE_BUTTON_RIGHT)
218 {
219 if (Input->RawButtons & MOUSE_BUTTON_RIGHT)
220 Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
221 else
222 Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
223 }
224 if (ButtonsDifference & MOUSE_BUTTON_MIDDLE)
225 {
226 if (Input->RawButtons & MOUSE_BUTTON_MIDDLE)
227 Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
228 else
229 Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
230 }
231 }
232
233 /* Send the Input data to the Mouse Class driver */
234 DeviceExtension->InputDataCount[Queue]++;
235 KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
236
237 /* Copy RawButtons to Previous Buttons for Input */
238 DeviceExtension->PreviousButtons = Input->RawButtons;
239 }
240 }
241
242 return TRUE;
243 }
244
245 VOID
246 SerialMouseInitializeDataQueue(PVOID Context)
247 {
248 }
249
250 BOOLEAN STDCALL
251 MouseSynchronizeRoutine(PVOID Context)
252 {
253 return TRUE;
254 }
255
256 VOID STDCALL
257 SerialMouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
258 {
259 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
260
261 if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
262 {
263 KIRQL oldIrql;
264 Irp->IoStatus.Status = STATUS_SUCCESS;
265 Irp->IoStatus.Information = 0;
266 IoCompleteRequest(Irp, IO_NO_INCREMENT);
267 oldIrql = KeGetCurrentIrql();
268 if (oldIrql < DISPATCH_LEVEL)
269 {
270 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
271 IoStartNextPacket(DeviceObject, FALSE);
272 KeLowerIrql(oldIrql);
273 }
274 else
275 {
276 IoStartNextPacket (DeviceObject, FALSE);
277 }
278 }
279 }
280
281 NTSTATUS STDCALL
282 SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
283 {
284 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
285 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
286 NTSTATUS Status;
287
288 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
289 {
290 case IOCTL_INTERNAL_MOUSE_CONNECT:
291 DeviceExtension->ClassInformation =
292 *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
293
294 /* Reinitialize the port input data queue synchronously */
295 KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
296 (PKSYNCHRONIZE_ROUTINE)SerialMouseInitializeDataQueue,
297 DeviceExtension);
298
299 Status = STATUS_SUCCESS;
300 break;
301
302 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
303 case IOCTL_MOUSE_QUERY_ATTRIBUTES:
304 if (Stack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(MOUSE_ATTRIBUTES))
305 {
306 *(PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer =
307 DeviceExtension->AttributesInformation;
308 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
309 Status = STATUS_SUCCESS;
310 } else {
311 Status = STATUS_BUFFER_TOO_SMALL;
312 }
313 break;
314 #endif
315
316 default:
317 Status = STATUS_INVALID_DEVICE_REQUEST;
318 break;
319 }
320
321 Irp->IoStatus.Status = Status;
322 if (Status == STATUS_PENDING)
323 {
324 IoMarkIrpPending(Irp);
325 IoStartPacket(DeviceObject, Irp, NULL, NULL);
326 }
327 else
328 {
329 IoCompleteRequest(Irp, IO_NO_INCREMENT);
330 }
331
332 return Status;
333 }
334
335 NTSTATUS STDCALL
336 SerialMouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
337 {
338 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
339 NTSTATUS Status;
340
341 switch (Stack->MajorFunction)
342 {
343 case IRP_MJ_CREATE:
344 case IRP_MJ_CLOSE:
345 Status = STATUS_SUCCESS;
346 break;
347
348 default:
349 DbgPrint("NOT IMPLEMENTED\n");
350 Status = STATUS_NOT_IMPLEMENTED;
351 break;
352 }
353
354 if (Status == STATUS_PENDING)
355 {
356 IoMarkIrpPending(Irp);
357 }
358 else
359 {
360 Irp->IoStatus.Status = Status;
361 Irp->IoStatus.Information = 0;
362 IoCompleteRequest(Irp, IO_NO_INCREMENT);
363 }
364
365 return Status;
366 }
367
368 VOID SerialMouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
369 {
370 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
371 ULONG Queue;
372
373 Queue = DeviceExtension->ActiveQueue % 2;
374 InterlockedIncrement(&DeviceExtension->ActiveQueue);
375 (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
376 DeviceExtension->ClassInformation.DeviceObject,
377 DeviceExtension->MouseInputData[Queue],
378 NULL,
379 &DeviceExtension->InputDataCount[Queue]);
380
381 DeviceExtension->InputDataCount[Queue] = 0;
382 }
383
384 void InitializeSerialPort(ULONG Port)
385 {
386 /* DLAB off */
387 WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0);
388 WRITE_PORT_UCHAR((PUCHAR)Port + 2, 0); /* FCR: disable FIFO */
389 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0); /* IER: disable ints */
390 /* Set DLAB on */
391 WRITE_PORT_UCHAR((PUCHAR)Port + 3, 0x80);
392 /* Set serial port speed */
393 WRITE_PORT_UCHAR((PUCHAR)Port, 0x60);
394 WRITE_PORT_UCHAR((PUCHAR)Port + 1, 0);
395 /* Set DLAB off and set LCR */
396 WRITE_PORT_UCHAR((PUCHAR)Port + 3, 2);
397 }
398
399 BOOL UARTReadChar(ULONG Port, CHAR *Value, ULONG Timeout)
400 {
401 ULONG i, j;
402
403 for (i = 0; i < Timeout; i++)
404 {
405 for (j = 0; j < 1000; j++)
406 {
407 /* Is there a character ready? */
408 if (READ_PORT_UCHAR((PUCHAR)Port + 5) & 0x01)
409 {
410 /* Yes, read it and return */
411 *Value = READ_PORT_UCHAR((PUCHAR)Port);
412 return TRUE;
413 }
414 else
415 {
416 /* No, wait */
417 KeStallExecutionProcessor(1);
418 }
419 }
420 }
421
422 return FALSE;
423 }
424
425 ULONG DetectMicrosoftMouse(ULONG Port)
426 {
427 CHAR Buffer[8];
428 ULONG Count, i;
429 UCHAR LCR, MCR;
430
431 /* Save original LCR/MCR */
432 LCR = READ_PORT_UCHAR((PUCHAR)Port + 3); /* LCR (line ctrl reg) */
433 MCR = READ_PORT_UCHAR((PUCHAR)Port + 4); /* MCR (modem ctrl reg) */
434
435 /* Reset UART */
436 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0); /* MCR: DTR/RTS/OUT2 off */
437
438 /* Set communications parameters */
439 InitializeSerialPort(Port);
440
441 /* Flush receive buffer */
442 (void) READ_PORT_UCHAR((PUCHAR)Port);
443 /* right? -> wait two ticks (approx 1/9 sec) */
444 KeStallExecutionProcessor(100000);
445
446 /* Enable DTR/RTS (OUT2 disabled) */
447 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 3);
448
449 if (UARTReadChar(Port, &Buffer[0], 500))
450 {
451 Count = 1;
452 while (Count < 8)
453 {
454 if (UARTReadChar(Port, &Buffer[Count], 100))
455 Count++;
456 else
457 break;
458 }
459 }
460 else
461 return MOUSE_TYPE_NONE;
462
463 /* Restore LCR/MCR */
464 WRITE_PORT_UCHAR((PUCHAR)Port + 3, LCR); /* LCR (line ctrl reg) */
465 WRITE_PORT_UCHAR((PUCHAR)Port + 4, MCR); /* MCR (modem ctrl reg) */
466
467 for (i = 0; i < Count; ++i)
468 {
469 /* Sign for Microsoft Ballpoint */
470 if (Buffer[i] == 'B')
471 {
472 DbgPrint("Microsoft Ballpoint device detected");
473 DbgPrint("THIS DEVICE IS NOT SUPPORTED, YET");
474 return MOUSE_TYPE_NONE;
475 } else
476 /* Sign for Microsoft Mouse protocol followed by button specifier */
477 if (Buffer[i] == 'M')
478 {
479 if (i == 3)
480 {
481 /* Overflow Error */
482 return MOUSE_TYPE_NONE;
483 }
484 switch (Buffer[i + 1])
485 {
486 case '3':
487 DbgPrint("Microsoft Mouse with 3-buttons detected\n");
488 return MOUSE_TYPE_LOGITECH;
489 case 'Z':
490 DbgPrint("Microsoft Wheel Mouse detected\n");
491 return MOUSE_TYPE_WHEELZ;
492 /* case '2': */
493 default:
494 DbgPrint("Microsoft Mouse with 2-buttons detected\n");
495 return MOUSE_TYPE_MICROSOFT;
496 }
497 }
498 }
499
500 return MOUSE_TYPE_NONE;
501 }
502
503 PDEVICE_OBJECT
504 AllocatePointerDevice(PDRIVER_OBJECT DriverObject)
505 {
506 PDEVICE_OBJECT DeviceObject;
507 UNICODE_STRING DeviceName;
508 UNICODE_STRING SuffixString;
509 UNICODE_STRING SymlinkName;
510 PDEVICE_EXTENSION DeviceExtension;
511 ULONG Suffix;
512 NTSTATUS Status;
513
514 /* Allocate buffer for full device name */
515 RtlInitUnicodeString(&DeviceName, NULL);
516 DeviceName.MaximumLength = sizeof(DD_MOUSE_DEVICE_NAME_U) + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
517 DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
518 RtlAppendUnicodeToString(&DeviceName, DD_MOUSE_DEVICE_NAME_U);
519
520 /* Allocate buffer for device name suffix */
521 RtlInitUnicodeString(&SuffixString, NULL);
522 SuffixString.MaximumLength = SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
523 SuffixString.Buffer = ExAllocatePool(PagedPool, SuffixString.MaximumLength);
524
525 /* Generate full qualified name with suffix */
526 for (Suffix = 0; Suffix < POINTER_PORTS_MAXIMUM; ++Suffix)
527 {
528 RtlIntegerToUnicodeString(Suffix, 10, &SuffixString);
529 RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
530 Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
531 &DeviceName, FILE_DEVICE_SERIAL_MOUSE_PORT, 0, TRUE, &DeviceObject);
532 /* Device successfully created, leave the cyclus */
533 if (NT_SUCCESS(Status))
534 break;
535 DeviceName.Length -= SuffixString.Length;
536 }
537
538 ExFreePool(DeviceName.Buffer);
539
540 /* Couldn't create device */
541 if (!NT_SUCCESS(Status))
542 {
543 ExFreePool(SuffixString.Buffer);
544 return NULL;
545 }
546
547 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
548
549 #ifdef SERMOUSE_MOUSESYMLINK_SUPPORT
550 /* Create symlink */
551 /* FIXME: Why? FiN 20/08/2003 */
552 RtlInitUnicodeString(&SymlinkName, NULL);
553 SymlinkName.MaximumLength = sizeof(L"\\??\\Mouse") + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
554 SymlinkName.Buffer = ExAllocatePool(PagedPool, SymlinkName.MaximumLength);
555 RtlAppendUnicodeToString(&SymlinkName, L"\\??\\Mouse");
556 RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
557 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
558 #endif
559 ExFreePool(SuffixString.Buffer);
560
561 DeviceExtension = DeviceObject->DeviceExtension;
562 KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
563
564 return DeviceObject;
565 }
566
567 BOOLEAN
568 InitializeMouse(ULONG Port, ULONG Irq, PDRIVER_OBJECT DriverObject)
569 {
570 PDEVICE_EXTENSION DeviceExtension;
571 PDEVICE_OBJECT DeviceObject;
572 ULONG MappedIrq;
573 KIRQL Dirql;
574 KAFFINITY Affinity;
575 ULONG MouseType;
576
577 /* Don't detect mouse on port that is occupied by kernel debugger */
578 if (KdComPortInUse == Port)
579 return FALSE;
580
581 /* Try to detect mouse on specified port */
582 MouseType = DetectMicrosoftMouse(Port);
583
584 /* No mouse, no need to continue */
585 if (MouseType == MOUSE_TYPE_NONE)
586 {
587 return FALSE;
588 }
589
590 /* Enable interrupts */
591 WRITE_PORT_UCHAR((PUCHAR)(Port) + 1, 1);
592
593 ClearMouse(Port);
594
595 /* Enable RTS, DTR and OUT2 */
596 WRITE_PORT_UCHAR((PUCHAR)Port + 4, 0x0b);
597
598 /* Allocate new device */
599 DeviceObject = AllocatePointerDevice(DriverObject);
600 if (!DeviceObject)
601 {
602 DbgPrint("Oops, couldn't creat device object.\n");
603 return FALSE;
604 }
605
606 DeviceExtension = DeviceObject->DeviceExtension;
607
608 /* Setup device extension structure */
609 DeviceExtension->ActiveQueue = 0;
610 DeviceExtension->MouseType = MouseType;
611 DeviceExtension->MousePort = Port;
612 DeviceExtension->PacketBufferPosition = 0;
613 DeviceExtension->PreviousButtons = 0;
614 #ifdef SERMOUSE_QUERYATTRIBUTES_SUPPORT
615 switch (MouseType)
616 {
617 case MOUSE_TYPE_MICROSOFT:
618 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
619 DeviceExtension->AttributesInformation.NumberOfButtons = 2;
620 break;
621 case MOUSE_TYPE_LOGITECH:
622 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
623 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
624 break;
625 case MOUSE_TYPE_WHEELZ:
626 DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE;
627 DeviceExtension->AttributesInformation.NumberOfButtons = 3;
628 break;
629 };
630 DeviceExtension->AttributesInformation.SampleRate = 40;
631 DeviceExtension->AttributesInformation.InputDataQueueLength = MOUSE_BUFFER_SIZE;
632 #endif
633
634 MappedIrq = HalGetInterruptVector(Internal, 0, 0, Irq, &Dirql, &Affinity);
635
636 IoConnectInterrupt(
637 &DeviceExtension->MouseInterrupt, SerialMouseInterruptService,
638 DeviceObject, NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
639 Affinity, FALSE);
640
641 return TRUE;
642 }
643
644 NTSTATUS STDCALL
645 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
646 {
647 BOOL MouseFound = FALSE;
648
649 DbgPrint("Serial Mouse Driver 0.0.9\n");
650 #ifdef SERMOUSE_COM1_SUPPORT
651 DbgPrint("Trying to find mouse on COM1\n");
652 MouseFound |= InitializeMouse(MOUSE_PORT_COM1, MOUSE_IRQ_COM1, DriverObject);
653 #endif
654 #ifdef SERMOUSE_COM2_SUPPORT
655 DbgPrint("Trying to find mouse on COM2\n");
656 MouseFound |= InitializeMouse(MOUSE_PORT_COM2, MOUSE_IRQ_COM2, DriverObject);
657 #endif
658
659 if (!MouseFound)
660 {
661 DbgPrint("No serial mouse found.\n");
662 return STATUS_UNSUCCESSFUL;
663 }
664
665 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)SerialMouseDispatch;
666 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)SerialMouseDispatch;
667 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)SerialMouseInternalDeviceControl;
668 DriverObject->DriverStartIo = SerialMouseStartIo;
669
670 return STATUS_SUCCESS;
671 }