2 * WINE HID Pseudo-Plug and Play support
4 * Copyright 2015 Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSUNION
25 #include "ddk/hidtypes.h"
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
28 #include "wine/list.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
32 typedef struct _NATIVE_DEVICE
{
38 HID_MINIDRIVER_REGISTRATION
*minidriver
;
42 static struct list tracked_devices
= LIST_INIT(tracked_devices
);
44 NTSTATUS WINAPI
PNP_AddDevice(DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*PDO
)
46 DEVICE_OBJECT
*device
= NULL
;
48 minidriver
*minidriver
;
49 HID_DEVICE_ATTRIBUTES attr
;
50 BASE_DEVICE_EXTENSION
*ext
= NULL
;
53 DWORD index
= HID_STRING_ID_ISERIALNUMBER
;
54 NATIVE_DEVICE
*tracked_device
, *ptr
;
55 INT interface_index
= 1;
57 static const WCHAR ig_fmtW
[] = {'I','G','_','%','i',0};
58 static const WCHAR im_fmtW
[] = {'I','M','_','%','i',0};
61 TRACE("PDO add device(%p)\n", PDO
);
62 minidriver
= find_minidriver(driver
);
64 status
= HID_CreateDevice(PDO
, &minidriver
->minidriver
, &device
);
65 if (status
!= STATUS_SUCCESS
)
67 ERR("Failed to create HID object (%x)\n",status
);
71 TRACE("Created device %p\n",device
);
72 status
= minidriver
->AddDevice(minidriver
->minidriver
.DriverObject
, device
);
73 if (status
!= STATUS_SUCCESS
)
75 ERR("Minidriver AddDevice failed (%x)\n",status
);
76 HID_DeleteDevice(&minidriver
->minidriver
, device
);
80 status
= call_minidriver(IOCTL_HID_GET_DEVICE_ATTRIBUTES
, device
,
81 NULL
, 0, &attr
, sizeof(attr
));
83 if (status
!= STATUS_SUCCESS
)
85 ERR("Minidriver failed to get Attributes(%x)\n",status
);
86 HID_DeleteDevice(&minidriver
->minidriver
, device
);
90 ext
= device
->DeviceExtension
;
91 ext
->information
.VendorID
= attr
.VendorID
;
92 ext
->information
.ProductID
= attr
.ProductID
;
93 ext
->information
.VersionNumber
= attr
.VersionNumber
;
94 ext
->information
.Polled
= minidriver
->minidriver
.DevicesArePolled
;
96 tracked_device
= HeapAlloc(GetProcessHeap(), 0, sizeof(*tracked_device
));
97 tracked_device
->vidpid
= MAKELONG(attr
.VendorID
, attr
.ProductID
);
98 tracked_device
->PDO
= PDO
;
99 tracked_device
->FDO
= device
;
100 tracked_device
->minidriver
= &minidriver
->minidriver
;
102 LIST_FOR_EACH_ENTRY(ptr
, &tracked_devices
, NATIVE_DEVICE
, entry
)
103 if (ptr
->vidpid
== tracked_device
->vidpid
) interface_index
++;
105 list_add_tail(&tracked_devices
, &tracked_device
->entry
);
108 status
= call_minidriver(IOCTL_HID_GET_STRING
, device
,
109 &index
, sizeof(DWORD
), serial
, sizeof(serial
));
113 static const WCHAR wZeroSerial
[]= {'0','0','0','0',0};
114 lstrcpyW(serial
, wZeroSerial
);
117 if (ext
->preparseData
->caps
.UsagePage
== HID_USAGE_PAGE_GENERIC
&&
118 (ext
->preparseData
->caps
.Usage
== HID_USAGE_GENERIC_GAMEPAD
||
119 ext
->preparseData
->caps
.Usage
== HID_USAGE_GENERIC_JOYSTICK
))
120 sprintfW(interface
, ig_fmtW
, interface_index
);
122 sprintfW(interface
, im_fmtW
, interface_index
);
124 HID_LinkDevice(device
, serial
, interface
);
126 ext
->poll_interval
= DEFAULT_POLL_INTERVAL
;
127 InitializeListHead(&ext
->irp_queue
);
129 ext
->ring_buffer
= RingBuffer_Create(sizeof(HID_XFER_PACKET
) + ext
->preparseData
->caps
.InputReportByteLength
);
131 return STATUS_SUCCESS
;
134 void PNP_CleanupPNP(DRIVER_OBJECT
*driver
)
136 NATIVE_DEVICE
*tracked_device
, *ptr
;
138 LIST_FOR_EACH_ENTRY_SAFE(tracked_device
, ptr
, &tracked_devices
,
139 NATIVE_DEVICE
, entry
)
141 if (tracked_device
->minidriver
->DriverObject
== driver
)
143 list_remove(&tracked_device
->entry
);
144 HID_DeleteDevice(tracked_device
->minidriver
, tracked_device
->FDO
);
145 HeapFree(GetProcessHeap(), 0, tracked_device
);