[USB-BRINGUP-TRUNK]
[reactos.git] / drivers / input / i8042prt / setup.c
1 /*
2 * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/input/i8042prt/setup.c
5 * PURPOSE: Create a legacy PDO during ReactOS installation
6 * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 /* NOTE:
10 * All this file is a big hack and should be removed one day...
11 */
12
13 /* INCLUDES ******************************************************************/
14
15 #include "i8042prt.h"
16
17 /* GLOBALS *******************************************************************/
18
19 #define KEYBOARD_DATA_PORT 0x60
20 #define KEYBOARD_CONTROL_PORT 0x64
21 #define KEYBOARD_IRQ 1
22
23 /* FUNCTIONS *****************************************************************/
24
25 BOOLEAN
26 IsFirstStageSetup(
27 VOID)
28 {
29 UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\Setup");
30 OBJECT_ATTRIBUTES ObjectAttributes;
31 HANDLE hSetupKey = (HANDLE)NULL;
32 NTSTATUS Status;
33 BOOLEAN ret = TRUE;
34
35 InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
36 Status = ZwOpenKey(&hSetupKey, KEY_QUERY_VALUE, &ObjectAttributes);
37
38 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
39 ret = TRUE;
40 else
41 ret = FALSE;
42
43 if (hSetupKey != (HANDLE)NULL)
44 ZwClose(hSetupKey);
45 INFO_(I8042PRT, "IsFirstStageSetup() returns %s\n", ret ? "YES" : "NO");
46 return ret;
47 }
48
49 static NTSTATUS
50 AddRegistryEntry(
51 IN PCWSTR PortTypeName,
52 IN PUNICODE_STRING DeviceName,
53 IN PCWSTR RegistryPath)
54 {
55 UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
56 OBJECT_ATTRIBUTES ObjectAttributes;
57 HANDLE hDeviceMapKey = (HANDLE)-1;
58 HANDLE hPortKey = (HANDLE)-1;
59 UNICODE_STRING PortTypeNameU;
60 NTSTATUS Status;
61
62 InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
63 Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
64 if (!NT_SUCCESS(Status))
65 {
66 WARN_(I8042PRT, "ZwOpenKey() failed with status 0x%08lx\n", Status);
67 goto cleanup;
68 }
69
70 RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
71 InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
72 Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
73 if (!NT_SUCCESS(Status))
74 {
75 WARN_(I8042PRT, "ZwCreateKey() failed with status 0x%08lx\n", Status);
76 goto cleanup;
77 }
78
79 Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
80 if (!NT_SUCCESS(Status))
81 {
82 WARN_(I8042PRT, "ZwSetValueKey() failed with status 0x%08lx\n", Status);
83 goto cleanup;
84 }
85
86 Status = STATUS_SUCCESS;
87
88 cleanup:
89 if (hDeviceMapKey != (HANDLE)-1)
90 ZwClose(hDeviceMapKey);
91 if (hPortKey != (HANDLE)-1)
92 ZwClose(hPortKey);
93 return Status;
94 }
95
96 NTSTATUS
97 i8042AddLegacyKeyboard(
98 IN PDRIVER_OBJECT DriverObject,
99 IN PUNICODE_STRING RegistryPath)
100 {
101 UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPort8042");
102 PI8042_DEVICE_TYPE DeviceExtension = NULL;
103 PDEVICE_OBJECT Pdo = NULL;
104 NTSTATUS Status;
105
106 TRACE_(I8042PRT, "i8042AddLegacyKeyboard()\n");
107
108 /* Create a named PDO */
109 Status = IoCreateDevice(
110 DriverObject,
111 sizeof(I8042_DEVICE_TYPE),
112 &KeyboardName,
113 FILE_DEVICE_8042_PORT,
114 FILE_DEVICE_SECURE_OPEN,
115 TRUE,
116 &Pdo);
117 if (!NT_SUCCESS(Status))
118 {
119 WARN_(I8042PRT, "IoCreateDevice() failed with status 0x%08lx\n", Status);
120 goto cleanup;
121 }
122
123 /* Initialize device extension */
124 DeviceExtension = (PI8042_DEVICE_TYPE)Pdo->DeviceExtension;
125 RtlZeroMemory(DeviceExtension, sizeof(I8042_DEVICE_TYPE));
126 *DeviceExtension = PhysicalDeviceObject;
127 Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
128
129 /* Add FDO at the top of the PDO */
130 Status = i8042AddDevice(DriverObject, Pdo);
131 if (!NT_SUCCESS(Status))
132 {
133 WARN_(I8042PRT, "i8042AddDevice() failed with status 0x%08lx\n", Status);
134 goto cleanup;
135 }
136
137 /* We will send the IRP_MN_START_DEVICE later when kbdclass looks for legacy drivers */
138 AddRegistryEntry(L"KeyboardPort", &KeyboardName, RegistryPath->Buffer);
139
140 Status = STATUS_SUCCESS;
141 /* Yes, completly forget the Pdo pointer, as we will never
142 * have to unload this driver during first stage setup.
143 */
144
145 cleanup:
146 if (!NT_SUCCESS(Status))
147 {
148 if (Pdo)
149 IoDeleteDevice(Pdo);
150 }
151 return Status;
152 }