wacom: SMAP Fixes and Refactoring
Utilize user_memcpy and IS_USER_ADDRESS when necessary to prevent SMAP violations.
Also add a "wacom_device_header" struct to more easily share data between the wacom
kernel driver and input_server addon.
Should fix #14589
Change-Id: I607a34c704b95eb80be38b6bd3ec3c915601a27c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3448
Reviewed-by: Alex von Gluck IV <kallisti5@unixzen.com>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
Diff
headers/private/input/wacom_driver.h | 19 +++++++++++++++++++
src/add-ons/input_server/devices/wacom/DeviceReader.cpp | 47 +++++++++++++++++++++++++++++++++--------------
src/add-ons/input_server/devices/wacom/DeviceReader.h | 2 +-
src/add-ons/kernel/drivers/input/wacom/Jamfile | 2 ++
src/add-ons/kernel/drivers/input/wacom/wacom.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
5 files changed, 89 insertions(+), 49 deletions(-)
@@ -1,0 +1,19 @@
/*
* Copyright 2020, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*/
#ifndef WACOM_DRIVER_H
#define WACOM_DRIVER_H
#include <SupportDefs.h>
typedef struct {
uint16 vendor_id;
uint16 product_id;
size_t max_packet_size;
} _PACKED wacom_device_header;
#endif
@@ -1,7 +1,10 @@
/*
* Copyright 2005-2008 Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT license.
* Copyright 2005-2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright 2020 Jacob Secunda <secundaja@gmail.com>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include "DeviceReader.h"
#include <malloc.h>
@@ -9,19 +12,21 @@
#include <File.h>
#include "MasterServerDevice.h"
#include <wacom_driver.h>
#include "MasterServerDevice.h"
static ssize_t kHeaderSize = 8;
static ssize_t kHeaderSize = sizeof(wacom_device_header);
DeviceReader::DeviceReader()
: fDevicePath(NULL),
fDeviceFile(NULL),
fVendorID(0),
fProductID(0),
fMaxPackedSize(0)
:
fDevicePath(NULL),
fDeviceFile(NULL),
fVendorID(0),
fProductID(0),
fMaxPacketSize(0)
{
}
@@ -36,23 +41,21 @@
DeviceReader::SetTo(const char* path)
{
status_t ret = B_BAD_VALUE;
if (path) {
if (path != NULL) {
_Unset();
fDevicePath = strdup(path);
fDeviceFile = new BFile(path, B_READ_ONLY);
ret = fDeviceFile->InitCheck();
if (ret >= B_OK) {
uint8 buffer[kHeaderSize];
ret = fDeviceFile->Read(buffer, kHeaderSize);
wacom_device_header device_header;
ret = fDeviceFile->Read(&device_header, kHeaderSize);
if (ret == kHeaderSize) {
ret = B_OK;
uint16* ids = (uint16*)buffer;
fVendorID = ids[0];
fProductID = ids[1];
uint32* ps = (uint32*)buffer;
fMaxPackedSize = ps[1];
fVendorID = device_header.vendor_id;
fProductID = device_header.product_id;
fMaxPacketSize = device_header.max_packet_size;
} else {
_Unset();
}
@@ -100,20 +103,20 @@
size_t
DeviceReader::MaxPacketSize() const
{
return fMaxPackedSize;
return fMaxPacketSize;
}
ssize_t
DeviceReader::ReadData(uint8* data, const size_t size) const
{
if (!fDeviceFile || fMaxPackedSize <= 0 || fMaxPackedSize > 128)
if (!fDeviceFile || fMaxPacketSize <= 0 || fMaxPacketSize > 128)
return B_NO_INIT;
status_t ret = fDeviceFile->InitCheck();
if (ret < B_OK)
return (ssize_t)ret;
ssize_t requested = fMaxPackedSize + kHeaderSize;
ssize_t requested = fMaxPacketSize + kHeaderSize;
uint8 buffer[requested];
ssize_t read = fDeviceFile->Read(buffer, requested);
if (read > kHeaderSize) {
@@ -153,5 +156,5 @@
fDeviceFile = NULL;
fVendorID = 0;
fProductID = 0;
fMaxPackedSize = 0;
fMaxPacketSize = 0;
}
@@ -58,6 +58,6 @@
uint16 fVendorID;
uint16 fProductID;
size_t fMaxPackedSize;
size_t fMaxPacketSize;
};
#endif
@@ -1,6 +1,8 @@
SubDir HAIKU_TOP src add-ons kernel drivers input wacom ;
SubDirSysHdrs $(HAIKU_TOP) headers os drivers ;
UsePrivateHeaders input ;
UsePrivateKernelHeaders ;
KernelAddon wacom :
wacom.c
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2005-2020, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -18,6 +18,9 @@
#include <OS.h>
#include <USB3.h>
#include <kernel.h>
#include <wacom_driver.h>
int32 api_version = B_CUR_DRIVER_API_VERSION;
#define DEBUG_DRIVER 0
@@ -430,7 +433,8 @@
release_sem(sDeviceListLock);
return ret;
@@ -502,15 +506,20 @@
}
static void
static status_t
read_header(const wacom_device* device, void* buffer)
{
uint16* ids = (uint16*)buffer;
uint32* size = (uint32*)buffer;
ids[0] = device->vendor;
ids[1] = device->product;
size[1] = device->max_packet_size;
wacom_device_header device_header;
device_header.vendor_id = device->vendor;
device_header.product_id = device->product;
device_header.max_packet_size = device->max_packet_size;
if (!IS_USER_ADDRESS(buffer)) {
memcpy(buffer, &device_header, sizeof(wacom_device_header));
return B_OK;
}
return user_memcpy(buffer, &device_header, sizeof(wacom_device_header));
}
@@ -532,11 +541,11 @@
if (ret >= B_OK) {
if (*count > 8) {
if (*count > sizeof(wacom_device_header)) {
ret = usb->queue_interrupt(device->pipe, device->data,
device->max_packet_size, device_interupt_callback, device);
@@ -557,9 +566,8 @@
DPRINTF_INFO((ID "device_read(%p) name = \"%s%d\" -> "
"B_TIMED_OUT\n", cookie, kBasePublishPath,
device->number));
*count = 8;
read_header(device, buffer);
ret = B_OK;
*count = sizeof(wacom_device_header);
ret = read_header(device, buffer);
} else {
*count = 0;
@@ -568,10 +576,19 @@
if (device->status == 0) {
DPRINTF_INFO((ID "interrupt transfer - success\n"));
dataLength = min_c(device->length, *count - 8);
*count = dataLength + 8;
read_header(device, buffer);
memcpy(buffer + 8, device->data, dataLength);
dataLength = min_c(device->length,
*count - sizeof(wacom_device_header));
*count = dataLength + sizeof(wacom_device_header);
ret = read_header(device, buffer);
if (ret == B_OK) {
if (IS_USER_ADDRESS(buffer))
ret = user_memcpy(
buffer + sizeof(wacom_device_header),
device->data, dataLength);
else
memcpy(buffer + sizeof(wacom_device_header),
device->data, dataLength);
}
} else {
*count = 0;
@@ -586,13 +603,12 @@
"interrupt: %" B_PRId32 "\n", cookie, kBasePublishPath,
device->number, ret);
}
} else if (*count == 8) {
read_header(device, buffer);
ret = B_OK;
} else if (*count == sizeof(wacom_device_header)) {
ret = read_header(device, buffer);
} else {
dprintf(ID "device_read(%p) name = \"%s%d\" -> buffer size must be "
"at least 8 bytes!\n", cookie, kBasePublishPath,
device->number);
"at least the size of the wacom_device_header struct!\n",
cookie, kBasePublishPath, device->number);
*count = 0;
ret = B_BAD_VALUE;
}