winebus.sys: Create bus devices.
Signed-off-by: Aric Stewart <aric@codeweavers.com> Signed-off-by: Sebastian Lackner <sebastian@fds-team.de> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e316b40ca1
commit
159c2eb16e
|
@ -1,5 +1,5 @@
|
|||
MODULE = winebus.sys
|
||||
IMPORTS = ntoskrnl
|
||||
IMPORTS = ntoskrnl setupapi
|
||||
EXTRALIBS = $(UDEV_LIBS)
|
||||
EXTRAINCL = $(UDEV_CFLAGS)
|
||||
EXTRADLLFLAGS = -Wb,--subsystem,native
|
||||
|
|
|
@ -21,3 +21,6 @@ NTSTATUS WINAPI udev_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry
|
|||
|
||||
/* HID Plug and Play Bus */
|
||||
NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
|
||||
DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW, void *native, WORD vid,
|
||||
WORD pid, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
|
||||
const GUID *class) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -50,6 +50,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
|
|||
static struct udev *udev_context = NULL;
|
||||
static DRIVER_OBJECT *udev_driver_obj = NULL;
|
||||
|
||||
static const WCHAR hidraw_busidW[] = {'H','I','D','R','A','W',0};
|
||||
|
||||
#include "initguid.h"
|
||||
DEFINE_GUID(GUID_DEVCLASS_HIDRAW, 0x3def44ad,0x242e,0x46e5,0x82,0x6d,0x70,0x72,0x13,0xf3,0xaa,0x81);
|
||||
|
||||
static DWORD get_sysattr_dword(struct udev_device *dev, const char *sysattr, int base)
|
||||
{
|
||||
const char *attr = udev_device_get_sysattr_value(dev, sysattr);
|
||||
|
@ -81,6 +86,8 @@ static void try_add_device(struct udev_device *dev)
|
|||
{
|
||||
DWORD vid = 0, pid = 0, version = 0;
|
||||
struct udev_device *usbdev;
|
||||
DEVICE_OBJECT *device = NULL;
|
||||
const char *subsystem;
|
||||
const char *devnode;
|
||||
WCHAR *serial = NULL;
|
||||
int fd;
|
||||
|
@ -107,6 +114,18 @@ static void try_add_device(struct udev_device *dev)
|
|||
TRACE("Found udev device %s (vid %04x, pid %04x, version %u, serial %s)\n",
|
||||
debugstr_a(devnode), vid, pid, version, debugstr_w(serial));
|
||||
|
||||
subsystem = udev_device_get_subsystem(dev);
|
||||
if (strcmp(subsystem, "hidraw") == 0)
|
||||
{
|
||||
device = bus_create_hid_device(udev_driver_obj, hidraw_busidW, dev, vid, pid,
|
||||
version, 0, serial, FALSE, &GUID_DEVCLASS_HIDRAW);
|
||||
}
|
||||
|
||||
if (device)
|
||||
udev_device_ref(dev);
|
||||
else
|
||||
WARN("Ignoring device %s with subsystem %s\n", debugstr_a(devnode), subsystem);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, serial);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,14 +26,164 @@
|
|||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winternl.h"
|
||||
#include "winreg.h"
|
||||
#include "setupapi.h"
|
||||
#include "ddk/wdm.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
|
||||
|
||||
struct pnp_device
|
||||
{
|
||||
struct list entry;
|
||||
DEVICE_OBJECT *device;
|
||||
};
|
||||
|
||||
struct device_extension
|
||||
{
|
||||
void *native; /* Must be the first member of the structure */
|
||||
|
||||
WORD vid, pid;
|
||||
DWORD uid, version, index;
|
||||
BOOL is_gamepad;
|
||||
WCHAR *serial;
|
||||
const WCHAR *busid; /* Expected to be a static constant */
|
||||
};
|
||||
|
||||
static CRITICAL_SECTION device_list_cs;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
{
|
||||
0, 0, &device_list_cs,
|
||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": device_list_cs") }
|
||||
};
|
||||
static CRITICAL_SECTION device_list_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static struct list pnp_devset = LIST_INIT(pnp_devset);
|
||||
|
||||
static const WCHAR zero_serialW[]= {'0','0','0','0',0};
|
||||
static const WCHAR imW[] = {'I','M',0};
|
||||
static const WCHAR igW[] = {'I','G',0};
|
||||
|
||||
static inline WCHAR *strdupW(const WCHAR *src)
|
||||
{
|
||||
WCHAR *dst;
|
||||
if (!src) return NULL;
|
||||
dst = HeapAlloc(GetProcessHeap(), 0, (strlenW(src) + 1)*sizeof(WCHAR));
|
||||
if (dst) strcpyW(dst, src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static DWORD get_vidpid_index(WORD vid, WORD pid)
|
||||
{
|
||||
struct pnp_device *ptr;
|
||||
DWORD index = 1;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(ptr, &pnp_devset, struct pnp_device, entry)
|
||||
{
|
||||
struct device_extension *ext = (struct device_extension *)ptr->device->DeviceExtension;
|
||||
if (ext->vid == vid && ext->pid == pid)
|
||||
index = max(ext->index + 1, index);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static WCHAR *get_instance_id(DEVICE_OBJECT *device)
|
||||
{
|
||||
static const WCHAR formatW[] = {'%','s','\\','V','i','d','_','%','0','4','x','&', 'P','i','d','_','%','0','4','x','&',
|
||||
'%','s','_','%','i','\\','%','i','&','%','s','&','%','x',0};
|
||||
struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
|
||||
const WCHAR *serial = ext->serial ? ext->serial : zero_serialW;
|
||||
DWORD len = strlenW(ext->busid) + strlenW(serial) + 64;
|
||||
WCHAR *dst;
|
||||
|
||||
if ((dst = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
|
||||
sprintfW(dst, formatW, ext->busid, ext->vid, ext->pid, ext->is_gamepad ? igW : imW,
|
||||
ext->index, ext->version, serial, ext->uid);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
DEVICE_OBJECT *bus_create_hid_device(DRIVER_OBJECT *driver, const WCHAR *busidW, void *native, WORD vid,
|
||||
WORD pid, DWORD version, DWORD uid, const WCHAR *serialW, BOOL is_gamepad,
|
||||
const GUID *class)
|
||||
{
|
||||
static const WCHAR device_name_fmtW[] = {'\\','D','e','v','i','c','e','\\','%','s','#','%','p',0};
|
||||
struct device_extension *ext;
|
||||
struct pnp_device *pnp_dev;
|
||||
DEVICE_OBJECT *device;
|
||||
UNICODE_STRING nameW;
|
||||
WCHAR dev_name[256];
|
||||
HDEVINFO devinfo;
|
||||
NTSTATUS status;
|
||||
|
||||
TRACE("(%p, %s, %p, %04x, %04x, %u, %u, %s, %u, %s)\n", driver, debugstr_w(busidW), native,
|
||||
vid, pid, version, uid, debugstr_w(serialW), is_gamepad, debugstr_guid(class));
|
||||
|
||||
if (!(pnp_dev = HeapAlloc(GetProcessHeap(), 0, sizeof(*pnp_dev))))
|
||||
return NULL;
|
||||
|
||||
sprintfW(dev_name, device_name_fmtW, busidW, native);
|
||||
RtlInitUnicodeString(&nameW, dev_name);
|
||||
status = IoCreateDevice(driver, sizeof(*ext), &nameW, 0, 0, FALSE, &device);
|
||||
if (status)
|
||||
{
|
||||
FIXME("failed to create device error %x\n", status);
|
||||
HeapFree(GetProcessHeap(), 0, pnp_dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&device_list_cs);
|
||||
|
||||
/* fill out device_extension struct */
|
||||
ext = (struct device_extension *)device->DeviceExtension;
|
||||
ext->native = native;
|
||||
ext->vid = vid;
|
||||
ext->pid = pid;
|
||||
ext->uid = uid;
|
||||
ext->version = version;
|
||||
ext->index = get_vidpid_index(vid, pid);
|
||||
ext->is_gamepad = is_gamepad;
|
||||
ext->serial = strdupW(serialW);
|
||||
ext->busid = busidW;
|
||||
|
||||
/* add to list of pnp devices */
|
||||
pnp_dev->device = device;
|
||||
list_add_tail(&pnp_devset, &pnp_dev->entry);
|
||||
|
||||
LeaveCriticalSection(&device_list_cs);
|
||||
|
||||
devinfo = SetupDiGetClassDevsW(class, NULL, NULL, DIGCF_DEVICEINTERFACE);
|
||||
if (devinfo)
|
||||
{
|
||||
SP_DEVINFO_DATA data;
|
||||
WCHAR *instance;
|
||||
|
||||
data.cbSize = sizeof(data);
|
||||
if (!(instance = get_instance_id(device)))
|
||||
ERR("failed to generate instance id\n");
|
||||
else if (!SetupDiCreateDeviceInfoW(devinfo, instance, class, NULL, NULL, DICD_INHERIT_CLASSDRVS, &data))
|
||||
ERR("failed to create device info: %x\n", GetLastError());
|
||||
else if (!SetupDiRegisterDeviceInfo(devinfo, &data, 0, NULL, NULL, NULL))
|
||||
ERR("failed to register device info: %x\n", GetLastError());
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, instance);
|
||||
SetupDiDestroyDeviceInfoList(devinfo);
|
||||
}
|
||||
else
|
||||
ERR("failed to get ClassDevs: %x\n", GetLastError());
|
||||
|
||||
IoInvalidateDeviceRelations(device, BusRelations);
|
||||
return device;
|
||||
}
|
||||
|
||||
NTSTATUS WINAPI common_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||
{
|
||||
NTSTATUS status = irp->IoStatus.u.Status;
|
||||
|
|
Loading…
Reference in New Issue