hidclass.sys: Implement a report ring buffer.

This commit is contained in:
Aric Stewart 2015-09-11 10:45:54 -05:00 committed by Alexandre Julliard
parent a833aaa5ce
commit 7e2ca70f79
5 changed files with 93 additions and 0 deletions

View File

@ -4,6 +4,7 @@ IMPORTS = ntoskrnl.exe
DELAYIMPORTS = setupapi hid
C_SRCS = \
buffer.c \
device.c \
main.c \
pnp.c

View File

@ -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 <stdarg.h>
#define NONAMELESSUNION
#include "hid.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(hid);
#define BASE_BUFFER_SIZE 32
struct ReportRingBuffer
{
UINT start, end, size;
int *pointers;
UINT pointer_alloc;
UINT buffer_size;
CRITICAL_SECTION lock;
BYTE *buffer;
};
struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size)
{
struct 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) * ring->pointer_alloc);
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);
}

View File

@ -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)

View File

@ -35,6 +35,9 @@
typedef NTSTATUS (WINAPI *pAddDevice)(DRIVER_OBJECT *DriverObject, DEVICE_OBJECT *PhysicalDeviceObject);
/* Ring buffer functions */
struct ReportRingBuffer;
typedef struct _BASE_DEVICE_EXTENSTION {
HID_DEVICE_EXTENSION deviceExtension;
@ -44,6 +47,7 @@ typedef struct _BASE_DEVICE_EXTENSTION {
ULONG poll_interval;
WCHAR *device_name;
WCHAR *link_name;
struct ReportRingBuffer *ring_buffer;
HANDLE halt_event;
HANDLE thread;
@ -52,6 +56,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;

View File

@ -126,6 +126,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
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;
}