From: Aric Stewart Subject: [3/12]hidclass.sys: Implement a report ring buffer Message-Id: <55A4FEB2.1030308@codeweavers.com> Date: Tue, 14 Jul 2015 07:21:06 -0500 --- dlls/hidclass.sys/Makefile.in | 1 + dlls/hidclass.sys/buffer.c | 81 +++++++++++++++++++++++++++++++++++++++++++ dlls/hidclass.sys/device.c | 2 ++ dlls/hidclass.sys/hid.h | 7 ++++ dlls/hidclass.sys/pnp.c | 2 ++ 5 files changed, 93 insertions(+) create mode 100644 dlls/hidclass.sys/buffer.c diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index c5c9eb7..8ed51e6 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -4,6 +4,7 @@ IMPORTS = ntoskrnl.exe DELAYIMPORTS = setupapi hid C_SRCS = \ + buffer.c \ device.c \ main.c \ pnp.c diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c new file mode 100644 index 0000000..8c9a775 --- /dev/null +++ b/dlls/hidclass.sys/buffer.c @@ -0,0 +1,81 @@ +/* Implementation of a ring buffer for reports + * + * Copyright 2015 CodeWeavers, Aric Stewart + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include +#define NONAMELESSUNION +#include "hid.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(hid); + +#define BASE_BUFFER_SIZE 32 + +typedef struct ReportRingBuffer +{ + UINT start, end, size; + + int *pointers; + UINT pointer_alloc; + UINT buffer_size; + + CRITICAL_SECTION lock; + + BYTE *buffer; +} ReportRingBuffer; + +struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) +{ + ReportRingBuffer *ring; + TRACE("Create Ring Buffer with buffer size %i\n",buffer_size); + ring = HeapAlloc(GetProcessHeap(), 0, sizeof(*ring)); + if (!ring) + return NULL; + ring->start = ring->end = 0; + ring->size = BASE_BUFFER_SIZE; + ring->buffer_size = buffer_size; + ring->pointer_alloc = 2; + ring->pointers = HeapAlloc(GetProcessHeap(), 0, sizeof(int) * ring->pointer_alloc); + if (!ring->pointers) + { + HeapFree(GetProcessHeap(), 0, ring); + return NULL; + } + memset(ring->pointers, 0xff, sizeof(int) * 5); + ring->buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size * ring->size); + if (!ring->buffer) + { + HeapFree(GetProcessHeap(), 0, ring->pointers); + HeapFree(GetProcessHeap(), 0, ring); + return NULL; + } + InitializeCriticalSection(&ring->lock); + ring->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RingBuffer.lock"); + return ring; +} + +void RingBuffer_Destroy(struct ReportRingBuffer *ring) +{ + HeapFree(GetProcessHeap(), 0, ring->buffer); + HeapFree(GetProcessHeap(), 0, ring->pointers); + ring->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&ring->lock); + HeapFree(GetProcessHeap(), 0, ring); +} diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 5068716..708fa04 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -178,6 +178,8 @@ void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device CloseHandle(ext->halt_event); HeapFree(GetProcessHeap(), 0, ext->preparseData); + if (ext->ring_buffer) + RingBuffer_Destroy(ext->ring_buffer); entry = RemoveHeadList(&ext->irp_queue); while(entry != &ext->irp_queue) diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 9b700c3..b14cb94 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -33,6 +33,9 @@ #define DEFAULT_POLL_INTERVAL 200 #define MAX_POLL_INTERVAL_MSEC 10000 +/* Ring buffer functions */ +struct ReportRingBuffer; + typedef struct _BASE_DEVICE_EXTENSTION { HID_DEVICE_EXTENSION deviceExtension; @@ -42,6 +45,7 @@ typedef struct _BASE_DEVICE_EXTENSTION { ULONG poll_interval; WCHAR *device_name; WCHAR *link_name; + struct ReportRingBuffer *ring_buffer; HANDLE halt_event; HANDLE thread; @@ -50,6 +54,9 @@ typedef struct _BASE_DEVICE_EXTENSTION { /* Minidriver Specific stuff will end up here */ } BASE_DEVICE_EXTENSION; +void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; +struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN; + typedef struct _minidriver { struct list entry; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index e1e5962..00c177e 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -144,6 +144,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, void *native) ext->poll_interval = DEFAULT_POLL_INTERVAL; InitializeListHead(&ext->irp_queue); + ext->ring_buffer = RingBuffer_Create(sizeof(HID_XFER_PACKET) + ext->preparseData->caps.InputReportByteLength); + return STATUS_SUCCESS; }