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)
16 IN PDEVICE_OBJECT DeviceObject
,
18 IN PVOID InputBuffer OPTIONAL
,
19 IN ULONG_PTR InputBufferSize
,
20 IN OUT PVOID OutputBuffer OPTIONAL
,
21 IN OUT PULONG_PTR OutputBufferSize
)
25 IO_STATUS_BLOCK IoStatus
;
28 KeInitializeEvent (&Event
, NotificationEvent
, FALSE
);
30 Irp
= IoBuildDeviceIoControlRequest(CtlCode
,
35 (OutputBufferSize
) ? *OutputBufferSize
: 0,
41 WARN_(SERENUM
, "IoBuildDeviceIoControlRequest() failed\n");
42 return STATUS_INSUFFICIENT_RESOURCES
;
45 Status
= IoCallDriver(DeviceObject
, Irp
);
47 if (Status
== STATUS_PENDING
)
49 INFO_(SERENUM
, "Operation pending\n");
50 KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
51 Status
= IoStatus
.Status
;
56 *OutputBufferSize
= IoStatus
.Information
;
64 IN PDEVICE_OBJECT LowerDevice
,
67 OUT PULONG_PTR FilledBytes
)
70 IO_STATUS_BLOCK ioStatus
;
75 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
77 Irp
= IoBuildSynchronousFsdRequest(
87 Status
= IoCallDriver(LowerDevice
, Irp
);
88 if (Status
== STATUS_PENDING
)
90 KeWaitForSingleObject(&event
, Suspended
, KernelMode
, FALSE
, NULL
);
91 Status
= ioStatus
.Status
;
93 INFO_(SERENUM
, "Bytes received: %lu/%lu\n",
94 ioStatus
.Information
, BufferSize
);
95 *FilledBytes
= ioStatus
.Information
;
100 ReportDetectedDevice(
101 IN PDEVICE_OBJECT DeviceObject
,
102 IN PUNICODE_STRING DeviceDescription
,
103 IN PUNICODE_STRING DeviceId
,
104 IN PUNICODE_STRING InstanceId
,
105 IN PUNICODE_STRING HardwareIds
,
106 IN PUNICODE_STRING CompatibleIds
)
108 PDEVICE_OBJECT Pdo
= NULL
;
109 PPDO_DEVICE_EXTENSION PdoDeviceExtension
= NULL
;
110 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
113 TRACE_(SERENUM
, "ReportDetectedDevice() called with %wZ (%wZ) detected\n", DeviceId
, DeviceDescription
);
115 Status
= IoCreateDevice(
116 DeviceObject
->DriverObject
,
117 sizeof(PDO_DEVICE_EXTENSION
),
119 FILE_DEVICE_CONTROLLER
,
120 FILE_AUTOGENERATED_DEVICE_NAME
,
123 if (!NT_SUCCESS(Status
)) goto ByeBye
;
125 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
126 Pdo
->Flags
|= DO_POWER_PAGABLE
;
127 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Pdo
->DeviceExtension
;
128 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
129 RtlZeroMemory(PdoDeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
130 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
131 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, DeviceDescription
, &PdoDeviceExtension
->DeviceDescription
);
132 if (!NT_SUCCESS(Status
)) goto ByeBye
;
133 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, DeviceId
, &PdoDeviceExtension
->DeviceId
);
134 if (!NT_SUCCESS(Status
)) goto ByeBye
;
135 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, InstanceId
, &PdoDeviceExtension
->InstanceId
);
136 if (!NT_SUCCESS(Status
)) goto ByeBye
;
137 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, HardwareIds
, &PdoDeviceExtension
->HardwareIds
);
138 if (!NT_SUCCESS(Status
)) goto ByeBye
;
139 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, CompatibleIds
, &PdoDeviceExtension
->CompatibleIds
);
140 if (!NT_SUCCESS(Status
)) goto ByeBye
;
142 /* Device attached to serial port (Pdo) may delegate work to
143 * serial port stack (Fdo = DeviceObject variable) */
144 Pdo
->StackSize
= DeviceObject
->StackSize
+ 1;
146 FdoDeviceExtension
->AttachedPdo
= Pdo
;
147 PdoDeviceExtension
->AttachedFdo
= DeviceObject
;
149 Pdo
->Flags
|= DO_BUFFERED_IO
;
150 Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
152 return STATUS_SUCCESS
;
157 ASSERT(PdoDeviceExtension
);
158 if (PdoDeviceExtension
->DeviceDescription
.Buffer
)
159 RtlFreeUnicodeString(&PdoDeviceExtension
->DeviceDescription
);
160 if (PdoDeviceExtension
->DeviceId
.Buffer
)
161 RtlFreeUnicodeString(&PdoDeviceExtension
->DeviceId
);
162 if (PdoDeviceExtension
->InstanceId
.Buffer
)
163 RtlFreeUnicodeString(&PdoDeviceExtension
->InstanceId
);
164 if (PdoDeviceExtension
->HardwareIds
.Buffer
)
165 RtlFreeUnicodeString(&PdoDeviceExtension
->HardwareIds
);
166 if (PdoDeviceExtension
->CompatibleIds
.Buffer
)
167 RtlFreeUnicodeString(&PdoDeviceExtension
->CompatibleIds
);
176 IN ULONG BufferLength
)
180 /* FIXME: IsValidPnpIdString not implemented */
182 String
.Length
= String
.MaximumLength
= BufferLength
;
183 String
.Buffer
= (PCHAR
)Buffer
;
184 ERR_(SERENUM
, "Buffer %Z\n", &String
);
189 ReportDetectedPnpDevice(
191 IN ULONG BufferLength
)
195 /* FIXME: ReportDetectedPnpDevice not implemented */
197 String
.Length
= String
.MaximumLength
= BufferLength
;
198 String
.Buffer
= (PCHAR
)Buffer
;
199 ERR_(SERENUM
, "Buffer %Z\n", &String
);
200 /* Call ReportDetectedDevice */
201 return STATUS_SUCCESS
;
209 IN ULONG milliseconds
)
212 LARGE_INTEGER DueTime
;
214 DueTime
.QuadPart
= milliseconds
* -10;
215 KeInitializeTimer(&Timer
);
216 KeSetTimer(&Timer
, DueTime
, NULL
);
217 return KeWaitForSingleObject(&Timer
, Executive
, KernelMode
, FALSE
, NULL
);
221 SerenumDetectPnpDevice(
222 IN PDEVICE_OBJECT DeviceObject
,
223 IN PDEVICE_OBJECT LowerDevice
)
225 HANDLE Handle
= NULL
;
228 ULONG_PTR TotalBytesReceived
= 0;
232 BOOLEAN BufferContainsBeginId
= FALSE
;
233 BOOLEAN BufferContainsEndId
= FALSE
;
234 SERIAL_LINE_CONTROL Lcr
;
235 SERIAL_TIMEOUTS Timeouts
;
236 SERIALPERF_STATS PerfStats
;
240 Status
= ObOpenObjectByPointer(
248 if (!NT_SUCCESS(Status
)) goto ByeBye
;
250 /* 1. COM port initialization, check for device enumerate */
251 TRACE_(SERENUM
, "COM port initialization, check for device enumerate\n");
252 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
253 NULL
, 0, NULL
, NULL
);
254 if (!NT_SUCCESS(Status
)) goto ByeBye
;
255 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
256 NULL
, 0, NULL
, NULL
);
257 if (!NT_SUCCESS(Status
)) goto ByeBye
;
260 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
261 NULL
, 0, &Msr
, &Size
);
262 if (!NT_SUCCESS(Status
)) goto ByeBye
;
263 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto DisconnectIdle
;
265 /* 2. COM port setup, 1st phase */
266 TRACE_(SERENUM
, "COM port setup, 1st phase\n");
268 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
269 &BaudRate
, sizeof(BaudRate
), NULL
, 0);
270 if (!NT_SUCCESS(Status
)) goto ByeBye
;
272 Lcr
.Parity
= NO_PARITY
;
273 Lcr
.StopBits
= STOP_BIT_1
;
274 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
275 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
276 if (!NT_SUCCESS(Status
)) goto ByeBye
;
277 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
278 NULL
, 0, NULL
, NULL
);
279 if (!NT_SUCCESS(Status
)) goto ByeBye
;
280 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
281 NULL
, 0, NULL
, NULL
);
282 if (!NT_SUCCESS(Status
)) goto ByeBye
;
284 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
285 NULL
, 0, NULL
, NULL
);
286 if (!NT_SUCCESS(Status
)) goto ByeBye
;
289 /* 3. Wait for response, 1st phase */
290 TRACE_(SERENUM
, "Wait for response, 1st phase\n");
291 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
292 NULL
, 0, NULL
, NULL
);
293 if (!NT_SUCCESS(Status
)) goto ByeBye
;
294 Timeouts
.ReadIntervalTimeout
= 0;
295 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
296 Timeouts
.ReadTotalTimeoutConstant
= 200;
297 Timeouts
.WriteTotalTimeoutMultiplier
= Timeouts
.WriteTotalTimeoutConstant
= 0;
298 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
299 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
300 if (!NT_SUCCESS(Status
)) goto ByeBye
;
301 Status
= ReadBytes(LowerDevice
, Buffer
, sizeof(Buffer
), &Size
);
302 if (!NT_SUCCESS(Status
)) goto ByeBye
;
303 if (Size
!= 0) goto CollectPnpComDeviceId
;
305 /* 4. COM port setup, 2nd phase */
306 TRACE_(SERENUM
, "COM port setup, 2nd phase\n");
307 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_DTR
,
308 NULL
, 0, NULL
, NULL
);
309 if (!NT_SUCCESS(Status
)) goto ByeBye
;
310 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
311 NULL
, 0, NULL
, NULL
);
312 if (!NT_SUCCESS(Status
)) goto ByeBye
;
313 Purge
= SERIAL_PURGE_RXABORT
| SERIAL_PURGE_RXCLEAR
;
314 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_PURGE
,
315 &Purge
, sizeof(ULONG
), NULL
, NULL
);
316 if (!NT_SUCCESS(Status
)) goto ByeBye
;
319 /* 5. Wait for response, 2nd phase */
320 TRACE_(SERENUM
, "Wait for response, 2nd phase\n");
321 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
322 NULL
, 0, NULL
, NULL
);
323 if (!NT_SUCCESS(Status
)) goto ByeBye
;
324 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
325 NULL
, 0, NULL
, NULL
);
326 if (!NT_SUCCESS(Status
)) goto ByeBye
;
327 Status
= ReadBytes(LowerDevice
, Buffer
, 1, &TotalBytesReceived
);
328 if (!NT_SUCCESS(Status
)) goto ByeBye
;
329 if (TotalBytesReceived
!= 0) goto CollectPnpComDeviceId
;
331 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
332 NULL
, 0, &Msr
, &Size
);
333 if (!NT_SUCCESS(Status
)) goto ByeBye
;
334 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto VerifyDisconnect
; else goto ConnectIdle
;
336 /* 6. Collect PnP COM device ID */
337 CollectPnpComDeviceId
:
338 TRACE_(SERENUM
, "Collect PnP COM device ID\n");
339 Timeouts
.ReadIntervalTimeout
= 200;
340 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
341 Timeouts
.ReadTotalTimeoutConstant
= 2200;
342 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
343 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
344 if (!NT_SUCCESS(Status
)) goto ByeBye
;
345 Status
= ReadBytes(LowerDevice
, &Buffer
[TotalBytesReceived
], sizeof(Buffer
) - TotalBytesReceived
, &Size
);
346 if (!NT_SUCCESS(Status
)) goto ByeBye
;
347 TotalBytesReceived
+= Size
;
348 Size
= sizeof(PerfStats
);
349 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_STATS
,
350 NULL
, 0, &PerfStats
, &Size
);
351 if (!NT_SUCCESS(Status
)) goto ByeBye
;
352 if (PerfStats
.FrameErrorCount
+ PerfStats
.ParityErrorCount
!= 0) goto ConnectIdle
;
353 for (i
= 0; i
< TotalBytesReceived
; i
++)
355 if (Buffer
[i
] == BEGIN_ID
) BufferContainsBeginId
= TRUE
;
356 if (Buffer
[i
] == END_ID
) BufferContainsEndId
= TRUE
;
358 if (TotalBytesReceived
== 1 || BufferContainsEndId
)
360 if (IsValidPnpIdString(Buffer
, TotalBytesReceived
))
362 Status
= ReportDetectedPnpDevice(Buffer
, TotalBytesReceived
);
367 if (!BufferContainsBeginId
) goto ConnectIdle
;
368 if (!BufferContainsEndId
) goto ConnectIdle
;
370 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_GET_MODEMSTATUS
,
371 NULL
, 0, &Msr
, &Size
);
372 if (!NT_SUCCESS(Status
)) goto ByeBye
;
373 if ((Msr
& SERIAL_DSR_STATE
) == 0) goto VerifyDisconnect
;
375 /* 7. Verify disconnect */
377 TRACE_(SERENUM
, "Verify disconnect\n");
378 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
379 NULL
, 0, NULL
, NULL
);
380 if (!NT_SUCCESS(Status
)) goto ByeBye
;
381 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
382 NULL
, 0, NULL
, NULL
);
383 if (!NT_SUCCESS(Status
)) goto ByeBye
;
387 /* 8. Connect idle */
389 TRACE_(SERENUM
, "Connect idle\n");
390 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
391 NULL
, 0, NULL
, NULL
);
392 if (!NT_SUCCESS(Status
)) goto ByeBye
;
393 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
394 NULL
, 0, NULL
, NULL
);
395 if (!NT_SUCCESS(Status
)) goto ByeBye
;
397 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
398 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
399 if (!NT_SUCCESS(Status
)) goto ByeBye
;
401 Lcr
.Parity
= NO_PARITY
;
402 Lcr
.StopBits
= STOP_BIT_1
;
403 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
404 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
405 if (!NT_SUCCESS(Status
)) goto ByeBye
;
406 if (TotalBytesReceived
== 0)
407 Status
= STATUS_DEVICE_NOT_CONNECTED
;
409 Status
= STATUS_SUCCESS
;
412 /* 9. Disconnect idle */
414 TRACE_(SERENUM
, "Disconnect idle\n");
415 /* FIXME: report to OS device removal, if it was present */
416 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
417 NULL
, 0, NULL
, NULL
);
418 if (!NT_SUCCESS(Status
)) goto ByeBye
;
419 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_CLR_RTS
,
420 NULL
, 0, NULL
, NULL
);
421 if (!NT_SUCCESS(Status
)) goto ByeBye
;
423 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
424 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
425 if (!NT_SUCCESS(Status
)) goto ByeBye
;
427 Lcr
.Parity
= NO_PARITY
;
428 Lcr
.StopBits
= STOP_BIT_1
;
429 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
430 &Lcr
, sizeof(Lcr
), NULL
, NULL
);
431 if (!NT_SUCCESS(Status
)) goto ByeBye
;
432 Status
= STATUS_DEVICE_NOT_CONNECTED
;
442 SerenumDetectLegacyDevice(
443 IN PDEVICE_OBJECT DeviceObject
,
444 IN PDEVICE_OBJECT LowerDevice
)
446 HANDLE Handle
= NULL
;
450 SERIAL_TIMEOUTS Timeouts
;
451 SERIAL_LINE_CONTROL LCR
;
454 UNICODE_STRING DeviceDescription
;
455 UNICODE_STRING DeviceId
;
456 UNICODE_STRING InstanceId
;
457 UNICODE_STRING HardwareIds
;
458 UNICODE_STRING CompatibleIds
;
461 TRACE_(SERENUM
, "SerenumDetectLegacyDevice(DeviceObject %p, LowerDevice %p)\n",
465 RtlZeroMemory(Buffer
, sizeof(Buffer
));
468 Status
= ObOpenObjectByPointer(
476 if (!NT_SUCCESS(Status
)) return Status
;
479 TRACE_(SERENUM
, "Reset UART\n");
480 Mcr
= 0; /* MCR: DTR/RTS/OUT2 off */
481 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_MODEM_CONTROL
,
482 &Mcr
, sizeof(Mcr
), NULL
, NULL
);
483 if (!NT_SUCCESS(Status
)) goto ByeBye
;
485 /* Set communications parameters */
486 TRACE_(SERENUM
, "Set communications parameters\n");
489 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_FIFO_CONTROL
,
490 &Fcr
, sizeof(Fcr
), NULL
, NULL
);
491 if (!NT_SUCCESS(Status
)) goto ByeBye
;
492 /* Set serial port speed */
494 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_BAUD_RATE
,
495 &BaudRate
, sizeof(BaudRate
), NULL
, NULL
);
496 if (!NT_SUCCESS(Status
)) goto ByeBye
;
499 LCR
.Parity
= NO_PARITY
;
500 LCR
.StopBits
= STOP_BITS_2
;
501 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_LINE_CONTROL
,
502 &LCR
, sizeof(LCR
), NULL
, NULL
);
503 if (!NT_SUCCESS(Status
)) goto ByeBye
;
505 /* Flush receive buffer */
506 TRACE_(SERENUM
, "Flush receive buffer\n");
507 Command
= SERIAL_PURGE_RXCLEAR
;
508 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_MODEM_CONTROL
,
509 &Command
, sizeof(Command
), NULL
, NULL
);
510 if (!NT_SUCCESS(Status
)) goto ByeBye
;
515 TRACE_(SERENUM
, "Enable DTR/RTS\n");
516 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_DTR
,
517 NULL
, 0, NULL
, NULL
);
518 if (!NT_SUCCESS(Status
)) goto ByeBye
;
519 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_RTS
,
520 NULL
, 0, NULL
, NULL
);
521 if (!NT_SUCCESS(Status
)) goto ByeBye
;
523 /* Set timeout to 500 microseconds */
524 TRACE_(SERENUM
, "Set timeout to 500 microseconds\n");
525 Timeouts
.ReadIntervalTimeout
= 100;
526 Timeouts
.ReadTotalTimeoutMultiplier
= 0;
527 Timeouts
.ReadTotalTimeoutConstant
= 500;
528 Timeouts
.WriteTotalTimeoutMultiplier
= Timeouts
.WriteTotalTimeoutConstant
= 0;
529 Status
= DeviceIoControl(LowerDevice
, IOCTL_SERIAL_SET_TIMEOUTS
,
530 &Timeouts
, sizeof(Timeouts
), NULL
, NULL
);
531 if (!NT_SUCCESS(Status
)) goto ByeBye
;
533 /* Fill the read buffer */
534 TRACE_(SERENUM
, "Fill the read buffer\n");
535 Status
= ReadBytes(LowerDevice
, Buffer
, sizeof(Buffer
)/sizeof(Buffer
[0]), &Count
);
536 if (!NT_SUCCESS(Status
)) goto ByeBye
;
538 RtlInitUnicodeString(&DeviceId
, L
"Serenum\\Mouse");
539 RtlInitUnicodeString(&InstanceId
, L
"0000"); /* FIXME */
540 for (i
= 0; i
< Count
; i
++)
542 if (Buffer
[i
] == 'B')
544 /* Sign for Microsoft Ballpoint */
545 /* Hardware id: *PNP0F09
546 * Compatible id: *PNP0F0F, SERIAL_MOUSE
548 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Ballpoint device");
549 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F09", NULL
);
550 SerenumInitMultiSzString(&CompatibleIds
, "*PNP0F0F", "SERIAL_MOUSE", NULL
);
551 Status
= ReportDetectedDevice(DeviceObject
,
552 &DeviceDescription
, &DeviceId
, &InstanceId
, &HardwareIds
, &CompatibleIds
);
553 RtlFreeUnicodeString(&HardwareIds
);
554 RtlFreeUnicodeString(&CompatibleIds
);
557 else if (Buffer
[i
] == 'M')
559 /* Sign for Microsoft Mouse protocol followed by button specifier */
560 if (i
== sizeof(Buffer
) - 1)
563 Status
= STATUS_DEVICE_NOT_CONNECTED
;
566 switch (Buffer
[i
+ 1])
569 /* Hardware id: *PNP0F08
570 * Compatible id: SERIAL_MOUSE
572 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Mouse with 3-buttons");
573 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F08", NULL
);
574 SerenumInitMultiSzString(&CompatibleIds
, "SERIAL_MOUSE", NULL
);
577 /* Hardware id: *PNP0F01
578 * Compatible id: SERIAL_MOUSE
580 RtlInitUnicodeString(&DeviceDescription
, L
"Microsoft Mouse with 2-buttons or Microsoft Wheel Mouse");
581 SerenumInitMultiSzString(&HardwareIds
, "*PNP0F01", NULL
);
582 SerenumInitMultiSzString(&CompatibleIds
, "SERIAL_MOUSE", NULL
);
585 Status
= ReportDetectedDevice(DeviceObject
,
586 &DeviceDescription
, &DeviceId
, &InstanceId
, &HardwareIds
, &CompatibleIds
);
587 RtlFreeUnicodeString(&HardwareIds
);
588 RtlFreeUnicodeString(&CompatibleIds
);
593 Status
= STATUS_DEVICE_NOT_CONNECTED
;