Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendetect.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Serial enumerator driver 00004 * FILE: drivers/bus/serenum/detect.c 00005 * PURPOSE: Detection of serial devices 00006 * 00007 * PROGRAMMERS: Jason Filby (jasonfilby@yahoo.com) 00008 * Filip Navara (xnavara@volny.cz) 00009 * Hervé Poussineau (hpoussin@reactos.org) 00010 */ 00011 00012 #include "serenum.h" 00013 00014 static NTSTATUS 00015 DeviceIoControl( 00016 IN PDEVICE_OBJECT DeviceObject, 00017 IN ULONG CtlCode, 00018 IN PVOID InputBuffer OPTIONAL, 00019 IN ULONG_PTR InputBufferSize, 00020 IN OUT PVOID OutputBuffer OPTIONAL, 00021 IN OUT PULONG_PTR OutputBufferSize) 00022 { 00023 KEVENT Event; 00024 PIRP Irp; 00025 IO_STATUS_BLOCK IoStatus; 00026 NTSTATUS Status; 00027 00028 KeInitializeEvent (&Event, NotificationEvent, FALSE); 00029 00030 Irp = IoBuildDeviceIoControlRequest(CtlCode, 00031 DeviceObject, 00032 InputBuffer, 00033 InputBufferSize, 00034 OutputBuffer, 00035 (OutputBufferSize) ? *OutputBufferSize : 0, 00036 FALSE, 00037 &Event, 00038 &IoStatus); 00039 if (Irp == NULL) 00040 { 00041 WARN_(SERENUM, "IoBuildDeviceIoControlRequest() failed\n"); 00042 return STATUS_INSUFFICIENT_RESOURCES; 00043 } 00044 00045 Status = IoCallDriver(DeviceObject, Irp); 00046 00047 if (Status == STATUS_PENDING) 00048 { 00049 INFO_(SERENUM, "Operation pending\n"); 00050 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 00051 Status = IoStatus.Status; 00052 } 00053 00054 if (OutputBufferSize) 00055 { 00056 *OutputBufferSize = IoStatus.Information; 00057 } 00058 00059 return Status; 00060 } 00061 00062 static NTSTATUS 00063 ReadBytes( 00064 IN PDEVICE_OBJECT LowerDevice, 00065 OUT PUCHAR Buffer, 00066 IN ULONG BufferSize, 00067 OUT PULONG_PTR FilledBytes) 00068 { 00069 PIRP Irp; 00070 IO_STATUS_BLOCK ioStatus; 00071 KEVENT event; 00072 LARGE_INTEGER zero; 00073 NTSTATUS Status; 00074 00075 KeInitializeEvent(&event, NotificationEvent, FALSE); 00076 zero.QuadPart = 0; 00077 Irp = IoBuildSynchronousFsdRequest( 00078 IRP_MJ_READ, 00079 LowerDevice, 00080 Buffer, BufferSize, 00081 &zero, 00082 &event, 00083 &ioStatus); 00084 if (!Irp) 00085 return FALSE; 00086 00087 Status = IoCallDriver(LowerDevice, Irp); 00088 if (Status == STATUS_PENDING) 00089 { 00090 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); 00091 Status = ioStatus.Status; 00092 } 00093 INFO_(SERENUM, "Bytes received: %lu/%lu\n", 00094 ioStatus.Information, BufferSize); 00095 *FilledBytes = ioStatus.Information; 00096 return Status; 00097 } 00098 00099 static NTSTATUS 00100 ReportDetectedDevice( 00101 IN PDEVICE_OBJECT DeviceObject, 00102 IN PUNICODE_STRING DeviceDescription, 00103 IN PUNICODE_STRING DeviceId, 00104 IN PUNICODE_STRING InstanceId, 00105 IN PUNICODE_STRING HardwareIds, 00106 IN PUNICODE_STRING CompatibleIds) 00107 { 00108 PDEVICE_OBJECT Pdo = NULL; 00109 PPDO_DEVICE_EXTENSION PdoDeviceExtension = NULL; 00110 PFDO_DEVICE_EXTENSION FdoDeviceExtension; 00111 NTSTATUS Status; 00112 00113 TRACE_(SERENUM, "ReportDetectedDevice() called with %wZ (%wZ) detected\n", DeviceId, DeviceDescription); 00114 00115 Status = IoCreateDevice( 00116 DeviceObject->DriverObject, 00117 sizeof(PDO_DEVICE_EXTENSION), 00118 NULL, 00119 FILE_DEVICE_CONTROLLER, 00120 FILE_AUTOGENERATED_DEVICE_NAME, 00121 FALSE, 00122 &Pdo); 00123 if (!NT_SUCCESS(Status)) goto ByeBye; 00124 00125 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 00126 Pdo->Flags |= DO_POWER_PAGABLE; 00127 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension; 00128 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00129 RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); 00130 PdoDeviceExtension->Common.IsFDO = FALSE; 00131 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, DeviceDescription, &PdoDeviceExtension->DeviceDescription); 00132 if (!NT_SUCCESS(Status)) goto ByeBye; 00133 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, DeviceId, &PdoDeviceExtension->DeviceId); 00134 if (!NT_SUCCESS(Status)) goto ByeBye; 00135 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, InstanceId, &PdoDeviceExtension->InstanceId); 00136 if (!NT_SUCCESS(Status)) goto ByeBye; 00137 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, HardwareIds, &PdoDeviceExtension->HardwareIds); 00138 if (!NT_SUCCESS(Status)) goto ByeBye; 00139 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, CompatibleIds, &PdoDeviceExtension->CompatibleIds); 00140 if (!NT_SUCCESS(Status)) goto ByeBye; 00141 00142 /* Device attached to serial port (Pdo) may delegate work to 00143 * serial port stack (Fdo = DeviceObject variable) */ 00144 Pdo->StackSize = DeviceObject->StackSize + 1; 00145 00146 FdoDeviceExtension->AttachedPdo = Pdo; 00147 PdoDeviceExtension->AttachedFdo = DeviceObject; 00148 00149 Pdo->Flags |= DO_BUFFERED_IO; 00150 Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00151 00152 return STATUS_SUCCESS; 00153 00154 ByeBye: 00155 if (Pdo) 00156 { 00157 ASSERT(PdoDeviceExtension); 00158 if (PdoDeviceExtension->DeviceDescription.Buffer) 00159 RtlFreeUnicodeString(&PdoDeviceExtension->DeviceDescription); 00160 if (PdoDeviceExtension->DeviceId.Buffer) 00161 RtlFreeUnicodeString(&PdoDeviceExtension->DeviceId); 00162 if (PdoDeviceExtension->InstanceId.Buffer) 00163 RtlFreeUnicodeString(&PdoDeviceExtension->InstanceId); 00164 if (PdoDeviceExtension->HardwareIds.Buffer) 00165 RtlFreeUnicodeString(&PdoDeviceExtension->HardwareIds); 00166 if (PdoDeviceExtension->CompatibleIds.Buffer) 00167 RtlFreeUnicodeString(&PdoDeviceExtension->CompatibleIds); 00168 IoDeleteDevice(Pdo); 00169 } 00170 return Status; 00171 } 00172 00173 static BOOLEAN 00174 IsValidPnpIdString( 00175 IN PUCHAR Buffer, 00176 IN ULONG BufferLength) 00177 { 00178 ANSI_STRING String; 00179 00180 /* FIXME: IsValidPnpIdString not implemented */ 00181 UNIMPLEMENTED; 00182 String.Length = String.MaximumLength = BufferLength; 00183 String.Buffer = (PCHAR)Buffer; 00184 ERR_(SERENUM, "Buffer %Z\n", &String); 00185 return TRUE; 00186 } 00187 00188 static NTSTATUS 00189 ReportDetectedPnpDevice( 00190 IN PUCHAR Buffer, 00191 IN ULONG BufferLength) 00192 { 00193 ANSI_STRING String; 00194 00195 /* FIXME: ReportDetectedPnpDevice not implemented */ 00196 UNIMPLEMENTED; 00197 String.Length = String.MaximumLength = BufferLength; 00198 String.Buffer = (PCHAR)Buffer; 00199 ERR_(SERENUM, "Buffer %Z\n", &String); 00200 /* Call ReportDetectedDevice */ 00201 return STATUS_SUCCESS; 00202 } 00203 00204 #define BEGIN_ID '(' 00205 #define END_ID ')' 00206 00207 static NTSTATUS 00208 Wait( 00209 IN ULONG milliseconds) 00210 { 00211 KTIMER Timer; 00212 LARGE_INTEGER DueTime; 00213 00214 DueTime.QuadPart = milliseconds * -10; 00215 KeInitializeTimer(&Timer); 00216 KeSetTimer(&Timer, DueTime, NULL); 00217 return KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL); 00218 } 00219 00220 NTSTATUS 00221 SerenumDetectPnpDevice( 00222 IN PDEVICE_OBJECT DeviceObject, 00223 IN PDEVICE_OBJECT LowerDevice) 00224 { 00225 HANDLE Handle = NULL; 00226 UCHAR Buffer[256]; 00227 ULONG BaudRate; 00228 ULONG_PTR TotalBytesReceived = 0; 00229 ULONG_PTR Size; 00230 ULONG Msr, Purge; 00231 ULONG i; 00232 BOOLEAN BufferContainsBeginId = FALSE; 00233 BOOLEAN BufferContainsEndId = FALSE; 00234 SERIAL_LINE_CONTROL Lcr; 00235 SERIAL_TIMEOUTS Timeouts; 00236 SERIALPERF_STATS PerfStats; 00237 NTSTATUS Status; 00238 00239 /* Open port */ 00240 Status = ObOpenObjectByPointer( 00241 LowerDevice, 00242 OBJ_KERNEL_HANDLE, 00243 NULL, 00244 0, 00245 NULL, 00246 KernelMode, 00247 &Handle); 00248 if (!NT_SUCCESS(Status)) goto ByeBye; 00249 00250 /* 1. COM port initialization, check for device enumerate */ 00251 TRACE_(SERENUM, "COM port initialization, check for device enumerate\n"); 00252 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR, 00253 NULL, 0, NULL, NULL); 00254 if (!NT_SUCCESS(Status)) goto ByeBye; 00255 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00256 NULL, 0, NULL, NULL); 00257 if (!NT_SUCCESS(Status)) goto ByeBye; 00258 Wait(200); 00259 Size = sizeof(Msr); 00260 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS, 00261 NULL, 0, &Msr, &Size); 00262 if (!NT_SUCCESS(Status)) goto ByeBye; 00263 if ((Msr & SERIAL_DSR_STATE) == 0) goto DisconnectIdle; 00264 00265 /* 2. COM port setup, 1st phase */ 00266 TRACE_(SERENUM, "COM port setup, 1st phase\n"); 00267 BaudRate = 1200; 00268 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, 00269 &BaudRate, sizeof(BaudRate), NULL, 0); 00270 if (!NT_SUCCESS(Status)) goto ByeBye; 00271 Lcr.WordLength = 7; 00272 Lcr.Parity = NO_PARITY; 00273 Lcr.StopBits = STOP_BIT_1; 00274 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, 00275 &Lcr, sizeof(Lcr), NULL, NULL); 00276 if (!NT_SUCCESS(Status)) goto ByeBye; 00277 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR, 00278 NULL, 0, NULL, NULL); 00279 if (!NT_SUCCESS(Status)) goto ByeBye; 00280 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00281 NULL, 0, NULL, NULL); 00282 if (!NT_SUCCESS(Status)) goto ByeBye; 00283 Wait(200); 00284 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00285 NULL, 0, NULL, NULL); 00286 if (!NT_SUCCESS(Status)) goto ByeBye; 00287 Wait(200); 00288 00289 /* 3. Wait for response, 1st phase */ 00290 TRACE_(SERENUM, "Wait for response, 1st phase\n"); 00291 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS, 00292 NULL, 0, NULL, NULL); 00293 if (!NT_SUCCESS(Status)) goto ByeBye; 00294 Timeouts.ReadIntervalTimeout = 0; 00295 Timeouts.ReadTotalTimeoutMultiplier = 0; 00296 Timeouts.ReadTotalTimeoutConstant = 200; 00297 Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0; 00298 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, 00299 &Timeouts, sizeof(Timeouts), NULL, NULL); 00300 if (!NT_SUCCESS(Status)) goto ByeBye; 00301 Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer), &Size); 00302 if (!NT_SUCCESS(Status)) goto ByeBye; 00303 if (Size != 0) goto CollectPnpComDeviceId; 00304 00305 /* 4. COM port setup, 2nd phase */ 00306 TRACE_(SERENUM, "COM port setup, 2nd phase\n"); 00307 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR, 00308 NULL, 0, NULL, NULL); 00309 if (!NT_SUCCESS(Status)) goto ByeBye; 00310 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00311 NULL, 0, NULL, NULL); 00312 if (!NT_SUCCESS(Status)) goto ByeBye; 00313 Purge = SERIAL_PURGE_RXABORT | SERIAL_PURGE_RXCLEAR; 00314 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_PURGE, 00315 &Purge, sizeof(ULONG), NULL, NULL); 00316 if (!NT_SUCCESS(Status)) goto ByeBye; 00317 Wait(200); 00318 00319 /* 5. Wait for response, 2nd phase */ 00320 TRACE_(SERENUM, "Wait for response, 2nd phase\n"); 00321 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00322 NULL, 0, NULL, NULL); 00323 if (!NT_SUCCESS(Status)) goto ByeBye; 00324 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS, 00325 NULL, 0, NULL, NULL); 00326 if (!NT_SUCCESS(Status)) goto ByeBye; 00327 Status = ReadBytes(LowerDevice, Buffer, 1, &TotalBytesReceived); 00328 if (!NT_SUCCESS(Status)) goto ByeBye; 00329 if (TotalBytesReceived != 0) goto CollectPnpComDeviceId; 00330 Size = sizeof(Msr); 00331 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS, 00332 NULL, 0, &Msr, &Size); 00333 if (!NT_SUCCESS(Status)) goto ByeBye; 00334 if ((Msr & SERIAL_DSR_STATE) == 0) goto VerifyDisconnect; else goto ConnectIdle; 00335 00336 /* 6. Collect PnP COM device ID */ 00337 CollectPnpComDeviceId: 00338 TRACE_(SERENUM, "Collect PnP COM device ID\n"); 00339 Timeouts.ReadIntervalTimeout = 200; 00340 Timeouts.ReadTotalTimeoutMultiplier = 0; 00341 Timeouts.ReadTotalTimeoutConstant = 2200; 00342 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, 00343 &Timeouts, sizeof(Timeouts), NULL, NULL); 00344 if (!NT_SUCCESS(Status)) goto ByeBye; 00345 Status = ReadBytes(LowerDevice, &Buffer[TotalBytesReceived], sizeof(Buffer) - TotalBytesReceived, &Size); 00346 if (!NT_SUCCESS(Status)) goto ByeBye; 00347 TotalBytesReceived += Size; 00348 Size = sizeof(PerfStats); 00349 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_STATS, 00350 NULL, 0, &PerfStats, &Size); 00351 if (!NT_SUCCESS(Status)) goto ByeBye; 00352 if (PerfStats.FrameErrorCount + PerfStats.ParityErrorCount != 0) goto ConnectIdle; 00353 for (i = 0; i < TotalBytesReceived; i++) 00354 { 00355 if (Buffer[i] == BEGIN_ID) BufferContainsBeginId = TRUE; 00356 if (Buffer[i] == END_ID) BufferContainsEndId = TRUE; 00357 } 00358 if (TotalBytesReceived == 1 || BufferContainsEndId) 00359 { 00360 if (IsValidPnpIdString(Buffer, TotalBytesReceived)) 00361 { 00362 Status = ReportDetectedPnpDevice(Buffer, TotalBytesReceived); 00363 goto ByeBye; 00364 } 00365 goto ConnectIdle; 00366 } 00367 if (!BufferContainsBeginId) goto ConnectIdle; 00368 if (!BufferContainsEndId) goto ConnectIdle; 00369 Size = sizeof(Msr); 00370 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS, 00371 NULL, 0, &Msr, &Size); 00372 if (!NT_SUCCESS(Status)) goto ByeBye; 00373 if ((Msr & SERIAL_DSR_STATE) == 0) goto VerifyDisconnect; 00374 00375 /* 7. Verify disconnect */ 00376 VerifyDisconnect: 00377 TRACE_(SERENUM, "Verify disconnect\n"); 00378 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00379 NULL, 0, NULL, NULL); 00380 if (!NT_SUCCESS(Status)) goto ByeBye; 00381 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00382 NULL, 0, NULL, NULL); 00383 if (!NT_SUCCESS(Status)) goto ByeBye; 00384 Wait(5000); 00385 goto DisconnectIdle; 00386 00387 /* 8. Connect idle */ 00388 ConnectIdle: 00389 TRACE_(SERENUM, "Connect idle\n"); 00390 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00391 NULL, 0, NULL, NULL); 00392 if (!NT_SUCCESS(Status)) goto ByeBye; 00393 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00394 NULL, 0, NULL, NULL); 00395 if (!NT_SUCCESS(Status)) goto ByeBye; 00396 BaudRate = 300; 00397 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, 00398 &BaudRate, sizeof(BaudRate), NULL, NULL); 00399 if (!NT_SUCCESS(Status)) goto ByeBye; 00400 Lcr.WordLength = 7; 00401 Lcr.Parity = NO_PARITY; 00402 Lcr.StopBits = STOP_BIT_1; 00403 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, 00404 &Lcr, sizeof(Lcr), NULL, NULL); 00405 if (!NT_SUCCESS(Status)) goto ByeBye; 00406 if (TotalBytesReceived == 0) 00407 Status = STATUS_DEVICE_NOT_CONNECTED; 00408 else 00409 Status = STATUS_SUCCESS; 00410 goto ByeBye; 00411 00412 /* 9. Disconnect idle */ 00413 DisconnectIdle: 00414 TRACE_(SERENUM, "Disconnect idle\n"); 00415 /* FIXME: report to OS device removal, if it was present */ 00416 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00417 NULL, 0, NULL, NULL); 00418 if (!NT_SUCCESS(Status)) goto ByeBye; 00419 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS, 00420 NULL, 0, NULL, NULL); 00421 if (!NT_SUCCESS(Status)) goto ByeBye; 00422 BaudRate = 300; 00423 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, 00424 &BaudRate, sizeof(BaudRate), NULL, NULL); 00425 if (!NT_SUCCESS(Status)) goto ByeBye; 00426 Lcr.WordLength = 7; 00427 Lcr.Parity = NO_PARITY; 00428 Lcr.StopBits = STOP_BIT_1; 00429 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, 00430 &Lcr, sizeof(Lcr), NULL, NULL); 00431 if (!NT_SUCCESS(Status)) goto ByeBye; 00432 Status = STATUS_DEVICE_NOT_CONNECTED; 00433 00434 ByeBye: 00435 /* Close port */ 00436 if (Handle) 00437 ZwClose(Handle); 00438 return Status; 00439 } 00440 00441 NTSTATUS 00442 SerenumDetectLegacyDevice( 00443 IN PDEVICE_OBJECT DeviceObject, 00444 IN PDEVICE_OBJECT LowerDevice) 00445 { 00446 HANDLE Handle = NULL; 00447 ULONG Fcr, Mcr; 00448 ULONG BaudRate; 00449 ULONG Command; 00450 SERIAL_TIMEOUTS Timeouts; 00451 SERIAL_LINE_CONTROL LCR; 00452 ULONG i, Count = 0; 00453 UCHAR Buffer[16]; 00454 UNICODE_STRING DeviceDescription; 00455 UNICODE_STRING DeviceId; 00456 UNICODE_STRING InstanceId; 00457 UNICODE_STRING HardwareIds; 00458 UNICODE_STRING CompatibleIds; 00459 NTSTATUS Status; 00460 00461 TRACE_(SERENUM, "SerenumDetectLegacyDevice(DeviceObject %p, LowerDevice %p)\n", 00462 DeviceObject, 00463 LowerDevice); 00464 00465 RtlZeroMemory(Buffer, sizeof(Buffer)); 00466 00467 /* Open port */ 00468 Status = ObOpenObjectByPointer( 00469 LowerDevice, 00470 OBJ_KERNEL_HANDLE, 00471 NULL, 00472 0, 00473 NULL, 00474 KernelMode, 00475 &Handle); 00476 if (!NT_SUCCESS(Status)) return Status; 00477 00478 /* Reset UART */ 00479 TRACE_(SERENUM, "Reset UART\n"); 00480 Mcr = 0; /* MCR: DTR/RTS/OUT2 off */ 00481 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL, 00482 &Mcr, sizeof(Mcr), NULL, NULL); 00483 if (!NT_SUCCESS(Status)) goto ByeBye; 00484 00485 /* Set communications parameters */ 00486 TRACE_(SERENUM, "Set communications parameters\n"); 00487 /* DLAB off */ 00488 Fcr = 0; 00489 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL, 00490 &Fcr, sizeof(Fcr), NULL, NULL); 00491 if (!NT_SUCCESS(Status)) goto ByeBye; 00492 /* Set serial port speed */ 00493 BaudRate = 1200; 00494 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE, 00495 &BaudRate, sizeof(BaudRate), NULL, NULL); 00496 if (!NT_SUCCESS(Status)) goto ByeBye; 00497 /* Set LCR */ 00498 LCR.WordLength = 7; 00499 LCR.Parity = NO_PARITY; 00500 LCR.StopBits = STOP_BITS_2; 00501 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL, 00502 &LCR, sizeof(LCR), NULL, NULL); 00503 if (!NT_SUCCESS(Status)) goto ByeBye; 00504 00505 /* Flush receive buffer */ 00506 TRACE_(SERENUM, "Flush receive buffer\n"); 00507 Command = SERIAL_PURGE_RXCLEAR; 00508 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL, 00509 &Command, sizeof(Command), NULL, NULL); 00510 if (!NT_SUCCESS(Status)) goto ByeBye; 00511 /* Wait 100 ms */ 00512 Wait(100); 00513 00514 /* Enable DTR/RTS */ 00515 TRACE_(SERENUM, "Enable DTR/RTS\n"); 00516 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR, 00517 NULL, 0, NULL, NULL); 00518 if (!NT_SUCCESS(Status)) goto ByeBye; 00519 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS, 00520 NULL, 0, NULL, NULL); 00521 if (!NT_SUCCESS(Status)) goto ByeBye; 00522 00523 /* Set timeout to 500 microseconds */ 00524 TRACE_(SERENUM, "Set timeout to 500 microseconds\n"); 00525 Timeouts.ReadIntervalTimeout = 100; 00526 Timeouts.ReadTotalTimeoutMultiplier = 0; 00527 Timeouts.ReadTotalTimeoutConstant = 500; 00528 Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0; 00529 Status = DeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS, 00530 &Timeouts, sizeof(Timeouts), NULL, NULL); 00531 if (!NT_SUCCESS(Status)) goto ByeBye; 00532 00533 /* Fill the read buffer */ 00534 TRACE_(SERENUM, "Fill the read buffer\n"); 00535 Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), (PVOID)&Count); 00536 if (!NT_SUCCESS(Status)) goto ByeBye; 00537 00538 RtlInitUnicodeString(&DeviceId, L"Serenum\\Mouse"); 00539 RtlInitUnicodeString(&InstanceId, L"0000"); /* FIXME */ 00540 for (i = 0; i < Count; i++) 00541 { 00542 if (Buffer[i] == 'B') 00543 { 00544 /* Sign for Microsoft Ballpoint */ 00545 /* Hardware id: *PNP0F09 00546 * Compatible id: *PNP0F0F, SERIAL_MOUSE 00547 */ 00548 RtlInitUnicodeString(&DeviceDescription, L"Microsoft Ballpoint device"); 00549 SerenumInitMultiSzString(&HardwareIds, "*PNP0F09", NULL); 00550 SerenumInitMultiSzString(&CompatibleIds, "*PNP0F0F", "SERIAL_MOUSE", NULL); 00551 Status = ReportDetectedDevice(DeviceObject, 00552 &DeviceDescription, &DeviceId, &InstanceId, &HardwareIds, &CompatibleIds); 00553 RtlFreeUnicodeString(&HardwareIds); 00554 RtlFreeUnicodeString(&CompatibleIds); 00555 goto ByeBye; 00556 } 00557 else if (Buffer[i] == 'M') 00558 { 00559 /* Sign for Microsoft Mouse protocol followed by button specifier */ 00560 if (i == sizeof(Buffer) - 1) 00561 { 00562 /* Overflow Error */ 00563 Status = STATUS_DEVICE_NOT_CONNECTED; 00564 goto ByeBye; 00565 } 00566 switch (Buffer[i + 1]) 00567 { 00568 case '3': 00569 /* Hardware id: *PNP0F08 00570 * Compatible id: SERIAL_MOUSE 00571 */ 00572 RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with 3-buttons"); 00573 SerenumInitMultiSzString(&HardwareIds, "*PNP0F08", NULL); 00574 SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL); 00575 break; 00576 default: 00577 /* Hardware id: *PNP0F01 00578 * Compatible id: SERIAL_MOUSE 00579 */ 00580 RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with 2-buttons or Microsoft Wheel Mouse"); 00581 SerenumInitMultiSzString(&HardwareIds, "*PNP0F01", NULL); 00582 SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL); 00583 break; 00584 } 00585 Status = ReportDetectedDevice(DeviceObject, 00586 &DeviceDescription, &DeviceId, &InstanceId, &HardwareIds, &CompatibleIds); 00587 RtlFreeUnicodeString(&HardwareIds); 00588 RtlFreeUnicodeString(&CompatibleIds); 00589 goto ByeBye; 00590 } 00591 } 00592 00593 Status = STATUS_DEVICE_NOT_CONNECTED; 00594 00595 ByeBye: 00596 /* Close port */ 00597 if (Handle) 00598 ZwClose(Handle); 00599 return Status; 00600 } Generated on Sun May 27 2012 04:27:50 for ReactOS by
1.7.6.1
|