2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial enumerator driver
4 * FILE: drivers/bus/serenum/detect.c
5 * PURPOSE: Detection of serial devices
7 * PROGRAMMERS: Jason Filby (jasonfilby@yahoo.com)
8 * Filip Navara (xnavara@volny.cz)
9 * Hervé Poussineau (hpoussin@reactos.org)
18 IN PDEVICE_OBJECT DeviceObject
,
20 IN PVOID InputBuffer OPTIONAL
,
21 IN ULONG_PTR InputBufferSize
,
22 IN OUT PVOID OutputBuffer OPTIONAL
,
23 IN OUT PULONG_PTR OutputBufferSize
)
27 IO_STATUS_BLOCK IoStatus
;
30 KeInitializeEvent (&Event
, NotificationEvent
, FALSE
);
32 Irp
= IoBuildDeviceIoControlRequest(CtlCode
,
37 (OutputBufferSize
) ? *OutputBufferSize
: 0,
43 WARN_(SERENUM
, "IoBuildDeviceIoControlRequest() failed\n");
44 return STATUS_INSUFFICIENT_RESOURCES
;
47 Status
= IoCallDriver(DeviceObject
, Irp
);
49 if (Status
== STATUS_PENDING
)
51 INFO_(SERENUM
, "Operation pending\n");
52 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
53 Status
= IoStatus
.Status
;
58 *OutputBufferSize
= IoStatus
.Information
;
66 IN PDEVICE_OBJECT LowerDevice
,
69 OUT PULONG_PTR FilledBytes
)
72 IO_STATUS_BLOCK ioStatus
;
77 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
79 Irp
= IoBuildSynchronousFsdRequest(
89 Status
= IoCallDriver(LowerDevice
, Irp
);
90 if (Status
== STATUS_PENDING
)
92 KeWaitForSingleObject(&event
, Suspended
, KernelMode
, FALSE
, NULL
);
93 Status
= ioStatus
.Status
;
95 INFO_(SERENUM
, "Bytes received: %lu/%lu\n",
96 ioStatus
.Information
, BufferSize
);
97 *FilledBytes
= ioStatus
.Information
;
102 ReportDetectedDevice(
103 IN PDEVICE_OBJECT DeviceObject
,
104 IN PUNICODE_STRING DeviceDescription
,
105 IN PUNICODE_STRING DeviceId
,
106 IN PUNICODE_STRING InstanceId
,
107 IN PUNICODE_STRING HardwareIds
,
108 IN PUNICODE_STRING CompatibleIds
)
110 PDEVICE_OBJECT Pdo
= NULL
;
111 PPDO_DEVICE_EXTENSION PdoDeviceExtension
= NULL
;
112 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
115 TRACE_(SERENUM
, "ReportDetectedDevice() called with %wZ (%wZ) detected\n", DeviceId
, DeviceDescription
);
117 Status
= IoCreateDevice(
118 DeviceObject
->DriverObject
,
119 sizeof(PDO_DEVICE_EXTENSION
),
121 FILE_DEVICE_CONTROLLER
,
122 FILE_AUTOGENERATED_DEVICE_NAME
,
125 if (!NT_SUCCESS(Status
)) goto ByeBye
;
127 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
128 Pdo
->Flags
|= DO_POWER_PAGABLE
;
129 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Pdo
->DeviceExtension
;
130 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
131 RtlZeroMemory(PdoDeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
132 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
133 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, DeviceDescription
, &PdoDeviceExtension
->DeviceDescription
);
134 if (!NT_SUCCESS(Status
)) goto ByeBye
;
135 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, DeviceId
, &PdoDeviceExtension
->DeviceId
);
136 if (!NT_SUCCESS(Status
)) goto ByeBye
;
137 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, InstanceId
, &PdoDeviceExtension
->InstanceId
);
138 if (!NT_SUCCESS(Status
)) goto ByeBye
;
139 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, HardwareIds
, &PdoDeviceExtension
->HardwareIds
);
140 if (!NT_SUCCESS(Status
)) goto ByeBye
;
141 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, CompatibleIds
, &PdoDeviceExtension
->CompatibleIds
);
142 if (!NT_SUCCESS(Status
)) goto ByeBye
;
144 /* Device attached to serial port (Pdo) may delegate work to
145 * serial port stack (Fdo = DeviceObject variable) */
146 Pdo
->StackSize
= DeviceObject
->StackSize
+ 1;
148 FdoDeviceExtension
->AttachedPdo
= Pdo
;
149 PdoDeviceExtension
->AttachedFdo
= DeviceObject
;
151 Pdo
->Flags
|= DO_BUFFERED_IO
;
152 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
154 return STATUS_SUCCESS
;
159 ASSERT(PdoDeviceExtension
);
160 if (PdoDeviceExtension
->DeviceDescription
.Buffer
)
161 RtlFreeUnicodeString(&PdoDeviceExtension
->DeviceDescription
);
162 if (PdoDeviceExtension
->DeviceId
.Buffer
)
163 RtlFreeUnicodeString(&PdoDeviceExtension
->DeviceId
);
164 if (PdoDeviceExtension
->InstanceId
.Buffer
)
165 RtlFreeUnicodeString(&PdoDeviceExtension
->InstanceId
);
166 if (PdoDeviceExtension
->HardwareIds
.Buffer
)
167 RtlFreeUnicodeString(&PdoDeviceExtension
->HardwareIds
);
168 if (PdoDeviceExtension
->CompatibleIds
.Buffer
)
169 RtlFreeUnicodeString(&PdoDeviceExtension
->CompatibleIds
);
178 IN ULONG BufferLength
)
182 /* FIXME: IsValidPnpIdString not implemented */
184 String
.Length
= String
.MaximumLength
= BufferLength
;
185 String
.Buffer
= (PCHAR
)Buffer
;
186 ERR_(SERENUM
, "Buffer %Z\n", &String
);
191 ReportDetectedPnpDevice(
193 IN ULONG BufferLength
)
197 /* FIXME: ReportDetectedPnpDevice not implemented */
199 String
.Length
= String
.MaximumLength
= BufferLength
;
200 String
.Buffer
= (PCHAR
)Buffer
;
201 ERR_(SERENUM
, "Buffer %Z\n", &String
);
202 /* Call ReportDetectedDevice */
203 return STATUS_SUCCESS
;
211 IN ULONG milliseconds
)
214 LARGE_INTEGER DueTime
;
216 DueTime
.QuadPart
= milliseconds
* -10;
217 KeInitializeTimer(&Timer
);
218 KeSetTimer(&Timer
, DueTime
, NULL
);
219 return KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, NULL
);
223 SerenumDetectPnpDevice(
224 IN PDEVICE_OBJECT DeviceObject
,
225 IN PDEVICE_OBJECT LowerDevice
)
227 HANDLE Handle
= NULL
;
230 ULONG_PTR TotalBytesReceived
= 0;
234 BOOLEAN BufferContainsBeginId
= FALSE
;
235 BOOLEAN BufferContainsEndId
= FALSE
;
236 SERIAL_LINE_CONTROL Lcr
;
237 SERIAL_TIMEOUTS Timeouts
;
238 SERIALPERF_STATS PerfStats
;
242 Status
= ObOpenObjectByPointer(
250 if (!NT_SUCCESS(Status
)) goto ByeBye
;
252 /* 1. COM port initialization, check for device enumerate */
253 TRACE_(SERENUM
, "COM port initialization, check for device enumerate\n");
254 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
255 NULL
, 0, NULL
, NULL
);
256 if (!NT_SUCCESS(Status
)) goto ByeBye
;
257 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
258 NULL
, 0, NULL
, NULL
);
259 if (!NT_SUCCESS(Status
)) goto ByeBye
;
262 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
263 NULL
, 0, &Msr
, &Size
);
264 if (!NT_SUCCESS(Status
)) goto ByeBye
;
265 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto DisconnectIdle
;
267 /* 2. COM port setup, 1st phase */
268 TRACE_(SERENUM
, "COM port setup, 1st phase\n");
270 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
271 &BaudRate
, sizeof(BaudRate
), NULL
, 0);
272 if (!NT_SUCCESS(Status
)) goto ByeBye
;
274 Lcr
.Parity
= NO_PARITY
;
275 Lcr
.StopBits
= STOP_BIT_1
;
276 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
277 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
278 if (!NT_SUCCESS(Status
)) goto ByeBye
;
279 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
280 NULL
, 0, NULL
, NULL
);
281 if (!NT_SUCCESS(Status
)) goto ByeBye
;
282 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
283 NULL
, 0, NULL
, NULL
);
284 if (!NT_SUCCESS(Status
)) goto ByeBye
;
286 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
287 NULL
, 0, NULL
, NULL
);
288 if (!NT_SUCCESS(Status
)) goto ByeBye
;
291 /* 3. Wait for response, 1st phase */
292 TRACE_(SERENUM
, "Wait for response, 1st phase\n");
293 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
294 NULL
, 0, NULL
, NULL
);
295 if (!NT_SUCCESS(Status
)) goto ByeBye
;
296 Timeouts
.ReadIntervalTimeout
= 0;
297 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
298 Timeouts
.ReadTotalTimeoutConstant
= 200;
299 Timeouts
.WriteTotalTimeoutMultiplier
= Timeouts
.WriteTotalTimeoutConstant
= 0;
300 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
301 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
302 if (!NT_SUCCESS(Status
)) goto ByeBye
;
303 Status
= ReadBytes(LowerDevice
, Buffer
, sizeof(Buffer
), &Size
);
304 if (!NT_SUCCESS(Status
)) goto ByeBye
;
305 if (Size
!= 0) goto CollectPnpComDeviceId
;
307 /* 4. COM port setup, 2nd phase */
308 TRACE_(SERENUM
, "COM port setup, 2nd phase\n");
309 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
310 NULL
, 0, NULL
, NULL
);
311 if (!NT_SUCCESS(Status
)) goto ByeBye
;
312 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
313 NULL
, 0, NULL
, NULL
);
314 if (!NT_SUCCESS(Status
)) goto ByeBye
;
315 Purge
= SERIAL_PURGE_RXABORT
| SERIAL_PURGE_RXCLEAR
;
316 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_PURGE
,
317 &Purge
, sizeof(ULONG
), NULL
, NULL
);
318 if (!NT_SUCCESS(Status
)) goto ByeBye
;
321 /* 5. Wait for response, 2nd phase */
322 TRACE_(SERENUM
, "Wait for response, 2nd phase\n");
323 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
324 NULL
, 0, NULL
, NULL
);
325 if (!NT_SUCCESS(Status
)) goto ByeBye
;
326 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
327 NULL
, 0, NULL
, NULL
);
328 if (!NT_SUCCESS(Status
)) goto ByeBye
;
329 Status
= ReadBytes(LowerDevice
, Buffer
, 1, &TotalBytesReceived
);
330 if (!NT_SUCCESS(Status
)) goto ByeBye
;
331 if (TotalBytesReceived
!= 0) goto CollectPnpComDeviceId
;
333 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
334 NULL
, 0, &Msr
, &Size
);
335 if (!NT_SUCCESS(Status
)) goto ByeBye
;
336 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto VerifyDisconnect
; else goto ConnectIdle
;
338 /* 6. Collect PnP COM device ID */
339 CollectPnpComDeviceId
:
340 TRACE_(SERENUM
, "Collect PnP COM device ID\n");
341 Timeouts
.ReadIntervalTimeout
= 200;
342 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
343 Timeouts
.ReadTotalTimeoutConstant
= 2200;
344 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
345 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
346 if (!NT_SUCCESS(Status
)) goto ByeBye
;
347 Status
= ReadBytes(LowerDevice
, &Buffer
[TotalBytesReceived
], sizeof(Buffer
) - TotalBytesReceived
, &Size
);
348 if (!NT_SUCCESS(Status
)) goto ByeBye
;
349 TotalBytesReceived
+= Size
;
350 Size
= sizeof(PerfStats
);
351 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_STATS
,
352 NULL
, 0, &PerfStats
, &Size
);
353 if (!NT_SUCCESS(Status
)) goto ByeBye
;
354 if (PerfStats
.FrameErrorCount
+ PerfStats
.ParityErrorCount
!= 0) goto ConnectIdle
;
355 for (i
= 0; i
< TotalBytesReceived
; i
++)
357 if (Buffer
[i
] == BEGIN_ID
) BufferContainsBeginId
= TRUE
;
358 if (Buffer
[i
] == END_ID
) BufferContainsEndId
= TRUE
;
360 if (TotalBytesReceived
== 1 || BufferContainsEndId
)
362 if (IsValidPnpIdString(Buffer
, TotalBytesReceived
))
364 Status
= ReportDetectedPnpDevice(Buffer
, TotalBytesReceived
);
369 if (!BufferContainsBeginId
) goto ConnectIdle
;
370 if (!BufferContainsEndId
) goto ConnectIdle
;
372 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
373 NULL
, 0, &Msr
, &Size
);
374 if (!NT_SUCCESS(Status
)) goto ByeBye
;
375 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto VerifyDisconnect
;
377 /* 7. Verify disconnect */
379 TRACE_(SERENUM
, "Verify disconnect\n");
380 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
381 NULL
, 0, NULL
, NULL
);
382 if (!NT_SUCCESS(Status
)) goto ByeBye
;
383 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
384 NULL
, 0, NULL
, NULL
);
385 if (!NT_SUCCESS(Status
)) goto ByeBye
;
389 /* 8. Connect idle */
391 TRACE_(SERENUM
, "Connect idle\n");
392 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
393 NULL
, 0, NULL
, NULL
);
394 if (!NT_SUCCESS(Status
)) goto ByeBye
;
395 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
396 NULL
, 0, NULL
, NULL
);
397 if (!NT_SUCCESS(Status
)) goto ByeBye
;
399 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
400 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
401 if (!NT_SUCCESS(Status
)) goto ByeBye
;
403 Lcr
.Parity
= NO_PARITY
;
404 Lcr
.StopBits
= STOP_BIT_1
;
405 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
406 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
407 if (!NT_SUCCESS(Status
)) goto ByeBye
;
408 if (TotalBytesReceived
== 0)
409 Status
= STATUS_DEVICE_NOT_CONNECTED
;
411 Status
= STATUS_SUCCESS
;
414 /* 9. Disconnect idle */
416 TRACE_(SERENUM
, "Disconnect idle\n");
417 /* FIXME: report to OS device removal, if it was present */
418 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
419 NULL
, 0, NULL
, NULL
);
420 if (!NT_SUCCESS(Status
)) goto ByeBye
;
421 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
422 NULL
, 0, NULL
, NULL
);
423 if (!NT_SUCCESS(Status
)) goto ByeBye
;
425 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
426 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
427 if (!NT_SUCCESS(Status
)) goto ByeBye
;
429 Lcr
.Parity
= NO_PARITY
;
430 Lcr
.StopBits
= STOP_BIT_1
;
431 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
432 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
433 if (!NT_SUCCESS(Status
)) goto ByeBye
;
434 Status
= STATUS_DEVICE_NOT_CONNECTED
;
444 SerenumDetectLegacyDevice(
445 IN PDEVICE_OBJECT DeviceObject
,
446 IN PDEVICE_OBJECT LowerDevice
)
448 HANDLE Handle
= NULL
;
452 SERIAL_TIMEOUTS Timeouts
;
453 SERIAL_LINE_CONTROL LCR
;
456 UNICODE_STRING DeviceDescription
;
457 UNICODE_STRING DeviceId
;
458 UNICODE_STRING InstanceId
;
459 UNICODE_STRING HardwareIds
;
460 UNICODE_STRING CompatibleIds
;
463 TRACE_(SERENUM
, "SerenumDetectLegacyDevice(DeviceObject %p, LowerDevice %p)\n",
467 RtlZeroMemory(Buffer
, sizeof(Buffer
));
470 Status
= ObOpenObjectByPointer(
478 if (!NT_SUCCESS(Status
)) return Status
;
481 TRACE_(SERENUM
, "Reset UART\n");
482 Mcr
= 0; /* MCR: DTR/RTS/OUT2 off */
483 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_MODEM_CONTROL
,
484 &Mcr
, sizeof(Mcr
), NULL
, NULL
);
485 if (!NT_SUCCESS(Status
)) goto ByeBye
;
487 /* Set communications parameters */
488 TRACE_(SERENUM
, "Set communications parameters\n");
491 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_FIFO_CONTROL
,
492 &Fcr
, sizeof(Fcr
), NULL
, NULL
);
493 if (!NT_SUCCESS(Status
)) goto ByeBye
;
494 /* Set serial port speed */
496 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
497 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
498 if (!NT_SUCCESS(Status
)) goto ByeBye
;
501 LCR
.Parity
= NO_PARITY
;
502 LCR
.StopBits
= STOP_BITS_2
;
503 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
504 &LCR
, sizeof(LCR
), NULL
, NULL
);
505 if (!NT_SUCCESS(Status
)) goto ByeBye
;
507 /* Flush receive buffer */
508 TRACE_(SERENUM
, "Flush receive buffer\n");
509 Command
= SERIAL_PURGE_RXCLEAR
;
510 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_MODEM_CONTROL
,
511 &Command
, sizeof(Command
), NULL
, NULL
);
512 if (!NT_SUCCESS(Status
)) goto ByeBye
;
517 TRACE_(SERENUM
, "Enable DTR/RTS\n");
518 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
519 NULL
, 0, NULL
, NULL
);
520 if (!NT_SUCCESS(Status
)) goto ByeBye
;
521 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
522 NULL
, 0, NULL
, NULL
);
523 if (!NT_SUCCESS(Status
)) goto ByeBye
;
525 /* Set timeout to 500 microseconds */
526 TRACE_(SERENUM
, "Set timeout to 500 microseconds\n");
527 Timeouts
.ReadIntervalTimeout
= 100;
528 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
529 Timeouts
.ReadTotalTimeoutConstant
= 500;
530 Timeouts
.WriteTotalTimeoutMultiplier
= Timeouts
.WriteTotalTimeoutConstant
= 0;
531 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
532 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
533 if (!NT_SUCCESS(Status
)) goto ByeBye
;
535 /* Fill the read buffer */
536 TRACE_(SERENUM
, "Fill the read buffer\n");
537 Status
= ReadBytes(LowerDevice
, Buffer
, sizeof(Buffer
)/sizeof(Buffer
[0]), (PVOID
)&Count
);
538 if (!NT_SUCCESS(Status
)) goto ByeBye
;
540 RtlInitUnicodeString(&DeviceId
, L
"Serenum\\Mouse");
541 RtlInitUnicodeString(&InstanceId
, L
"0000"); /* FIXME */
542 for (i
= 0; i
< Count
; i
++)
544 if (Buffer
[i
] == 'B')
546 /* Sign for Microsoft Ballpoint */
547 /* Hardware id: *PNP0F09
548 * Compatible id: *PNP0F0F, SERIAL_MOUSE
550 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Ballpoint device");
551 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F09", NULL
);
552 SerenumInitMultiSzString(&CompatibleIds
, "*PNP0F0F", "SERIAL_MOUSE", NULL
);
553 Status
= ReportDetectedDevice(DeviceObject
,
554 &DeviceDescription
, &DeviceId
, &InstanceId
, &HardwareIds
, &CompatibleIds
);
555 RtlFreeUnicodeString(&HardwareIds
);
556 RtlFreeUnicodeString(&CompatibleIds
);
559 else if (Buffer
[i
] == 'M')
561 /* Sign for Microsoft Mouse protocol followed by button specifier */
562 if (i
== sizeof(Buffer
) - 1)
565 Status
= STATUS_DEVICE_NOT_CONNECTED
;
568 switch (Buffer
[i
+ 1])
571 /* Hardware id: *PNP0F08
572 * Compatible id: SERIAL_MOUSE
574 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Mouse with 3-buttons");
575 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F08", NULL
);
576 SerenumInitMultiSzString(&CompatibleIds
, "SERIAL_MOUSE", NULL
);
579 /* Hardware id: *PNP0F01
580 * Compatible id: SERIAL_MOUSE
582 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Mouse with 2-buttons or Microsoft Wheel Mouse");
583 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F01", NULL
);
584 SerenumInitMultiSzString(&CompatibleIds
, "SERIAL_MOUSE", NULL
);
587 Status
= ReportDetectedDevice(DeviceObject
,
588 &DeviceDescription
, &DeviceId
, &InstanceId
, &HardwareIds
, &CompatibleIds
);
589 RtlFreeUnicodeString(&HardwareIds
);
590 RtlFreeUnicodeString(&CompatibleIds
);
595 Status
= STATUS_DEVICE_NOT_CONNECTED
;