mirror of
https://github.com/mii443/rust-openvr.git
synced 2025-08-27 02:29:42 +00:00
added linux makefile
This commit is contained in:
819
modules/oculus_sdk_linux/LibOVR/Src/OVR_Linux_HIDDevice.cpp
Normal file
819
modules/oculus_sdk_linux/LibOVR/Src/OVR_Linux_HIDDevice.cpp
Normal file
@ -0,0 +1,819 @@
|
||||
/************************************************************************************
|
||||
Filename : OVR_Linux_HIDDevice.cpp
|
||||
Content : Linux HID device implementation.
|
||||
Created : February 26, 2013
|
||||
Authors : Lee Cooper
|
||||
|
||||
Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
|
||||
|
||||
Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
|
||||
you may not use the Oculus VR Rift SDK except in compliance with the License,
|
||||
which is provided at the time of installation or download, or which
|
||||
otherwise accompanies this software in either electronic or hard copy form.
|
||||
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.oculusvr.com/licenses/LICENSE-3.1
|
||||
|
||||
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
#include "OVR_Linux_HIDDevice.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/hidraw.h>
|
||||
#include "OVR_HIDDeviceImpl.h"
|
||||
|
||||
namespace OVR { namespace Linux {
|
||||
|
||||
static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// **** Linux::DeviceManager
|
||||
//-----------------------------------------------------------------------------
|
||||
HIDDeviceManager::HIDDeviceManager(DeviceManager* manager) : DevManager(manager)
|
||||
{
|
||||
UdevInstance = NULL;
|
||||
HIDMonitor = NULL;
|
||||
HIDMonHandle = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HIDDeviceManager::~HIDDeviceManager()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::initializeManager()
|
||||
{
|
||||
if (HIDMonitor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a udev_monitor handle to watch for device changes (hot-plug detection)
|
||||
HIDMonitor = udev_monitor_new_from_netlink(UdevInstance, "udev");
|
||||
if (HIDMonitor == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL); // filter for hidraw only
|
||||
|
||||
int err = udev_monitor_enable_receiving(HIDMonitor);
|
||||
if (err)
|
||||
{
|
||||
udev_monitor_unref(HIDMonitor);
|
||||
HIDMonitor = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the file descriptor (fd) for the monitor.
|
||||
HIDMonHandle = udev_monitor_get_fd(HIDMonitor);
|
||||
if (HIDMonHandle < 0)
|
||||
{
|
||||
udev_monitor_unref(HIDMonitor);
|
||||
HIDMonitor = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This file handle will be polled along-side with the device hid handles for changes
|
||||
// Add the handle to the polling list
|
||||
if (!DevManager->pThread->AddSelectFd(this, HIDMonHandle))
|
||||
{
|
||||
close(HIDMonHandle);
|
||||
HIDMonHandle = -1;
|
||||
|
||||
udev_monitor_unref(HIDMonitor);
|
||||
HIDMonitor = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::Initialize()
|
||||
{
|
||||
// Get a udev library handle. This handle must stay active during the
|
||||
// duration the lifetime of device monitoring handles
|
||||
UdevInstance = udev_new();
|
||||
if (!UdevInstance)
|
||||
return false;
|
||||
|
||||
return initializeManager();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDeviceManager::Shutdown()
|
||||
{
|
||||
OVR_ASSERT_LOG((UdevInstance), ("Should have called 'Initialize' before 'Shutdown'."));
|
||||
|
||||
if (HIDMonitor)
|
||||
{
|
||||
DevManager->pThread->RemoveSelectFd(this, HIDMonHandle);
|
||||
close(HIDMonHandle);
|
||||
HIDMonHandle = -1;
|
||||
|
||||
udev_monitor_unref(HIDMonitor);
|
||||
HIDMonitor = NULL;
|
||||
}
|
||||
|
||||
udev_unref(UdevInstance); // release the library
|
||||
|
||||
LogText("OVR::Linux::HIDDeviceManager - shutting down.\n");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::AddNotificationDevice(HIDDevice* device)
|
||||
{
|
||||
NotificationDevices.PushBack(device);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::RemoveNotificationDevice(HIDDevice* device)
|
||||
{
|
||||
for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
|
||||
{
|
||||
if (NotificationDevices[i] == device)
|
||||
{
|
||||
NotificationDevices.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::getIntProperty(udev_device* device,
|
||||
const char* propertyName,
|
||||
SInt32* pResult)
|
||||
{
|
||||
const char* str = udev_device_get_sysattr_value(device, propertyName);
|
||||
if (str)
|
||||
{
|
||||
*pResult = strtol(str, NULL, 16);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pResult = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc)
|
||||
{
|
||||
SInt32 result;
|
||||
if (getIntProperty(device, "idVendor", &result))
|
||||
pDevDesc->VendorId = result;
|
||||
else
|
||||
return false;
|
||||
|
||||
if (getIntProperty(device, "idProduct", &result))
|
||||
pDevDesc->ProductId = result;
|
||||
else
|
||||
return false;
|
||||
|
||||
if (getIntProperty(device, "bcdDevice", &result))
|
||||
pDevDesc->VersionNumber = result;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::getStringProperty(udev_device* device,
|
||||
const char* propertyName,
|
||||
OVR::String* pResult)
|
||||
{
|
||||
// Get the attribute in UTF8
|
||||
const char* str = udev_device_get_sysattr_value(device, propertyName);
|
||||
if (str)
|
||||
{ // Copy the string into the return value
|
||||
*pResult = String(str);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
|
||||
{
|
||||
|
||||
if (!initializeManager())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a list of hid devices
|
||||
udev_enumerate* devices = udev_enumerate_new(UdevInstance);
|
||||
udev_enumerate_add_match_subsystem(devices, "hidraw");
|
||||
udev_enumerate_scan_devices(devices);
|
||||
|
||||
udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
|
||||
|
||||
// Search each device for the matching vid/pid
|
||||
while (entry != NULL)
|
||||
{
|
||||
// Get the device file name
|
||||
const char* sysfs_path = udev_list_entry_get_name(entry);
|
||||
udev_device* hid; // The device's HID udev node.
|
||||
hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
|
||||
const char* dev_path = udev_device_get_devnode(hid);
|
||||
|
||||
// Get the USB device
|
||||
hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
|
||||
if (hid)
|
||||
{
|
||||
HIDDeviceDesc devDesc;
|
||||
|
||||
// Check the VID/PID for a match
|
||||
if (dev_path &&
|
||||
initVendorProductVersion(hid, &devDesc) &&
|
||||
enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId))
|
||||
{
|
||||
devDesc.Path = dev_path;
|
||||
getFullDesc(hid, &devDesc);
|
||||
|
||||
// Look for the device to check if it is already opened.
|
||||
Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc, true);
|
||||
// if device exists and it is opened then most likely the device open()
|
||||
// will fail; therefore, we just set Enumerated to 'true' and continue.
|
||||
if (existingDevice && existingDevice->pDevice)
|
||||
{
|
||||
existingDevice->Enumerated = true;
|
||||
}
|
||||
else
|
||||
{ // open the device temporarily for startup communication
|
||||
int device_handle = open(dev_path, O_RDWR);
|
||||
if (device_handle >= 0)
|
||||
{
|
||||
// Construct minimal device that the visitor callback can get feature reports from
|
||||
Linux::HIDDevice device(this, device_handle);
|
||||
enumVisitor->Visit(device, devDesc);
|
||||
|
||||
close(device_handle); // close the file handle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
udev_device_unref(hid);
|
||||
entry = udev_list_entry_get_next(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the enumerator and udev objects
|
||||
udev_enumerate_unref(devices);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
|
||||
{
|
||||
Ptr<Linux::HIDDevice> device = *new Linux::HIDDevice(this);
|
||||
|
||||
if (device->HIDInitialize(path))
|
||||
{
|
||||
device->AddRef();
|
||||
return device;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::getFullDesc(udev_device* device, HIDDeviceDesc* desc)
|
||||
{
|
||||
|
||||
if (!initVendorProductVersion(device, desc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!getStringProperty(device, "serial", &(desc->SerialNumber)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
getStringProperty(device, "manufacturer", &(desc->Manufacturer));
|
||||
getStringProperty(device, "product", &(desc->Product));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDeviceManager::GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc)
|
||||
{
|
||||
if (!initializeManager())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Search for the udev device from the given pathname so we can
|
||||
// have a handle to query device properties
|
||||
|
||||
udev_enumerate* devices = udev_enumerate_new(UdevInstance);
|
||||
udev_enumerate_add_match_subsystem(devices, "hidraw");
|
||||
udev_enumerate_scan_devices(devices);
|
||||
|
||||
udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
|
||||
|
||||
bool success = false;
|
||||
// Search for the device with the matching path
|
||||
while (entry != NULL)
|
||||
{
|
||||
// Get the device file name
|
||||
const char* sysfs_path = udev_list_entry_get_name(entry);
|
||||
udev_device* hid; // The device's HID udev node.
|
||||
hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
|
||||
const char* path = udev_device_get_devnode(hid);
|
||||
|
||||
if (OVR_strcmp(dev_path, path) == 0)
|
||||
{ // Found the device so lets collect the device descriptor
|
||||
|
||||
// Get the USB device
|
||||
hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
|
||||
if (hid)
|
||||
{
|
||||
desc->Path = dev_path;
|
||||
success = getFullDesc(hid, desc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
udev_device_unref(hid);
|
||||
entry = udev_list_entry_get_next(entry);
|
||||
}
|
||||
|
||||
// Free the enumerator
|
||||
udev_enumerate_unref(devices);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDeviceManager::OnEvent(int i, int fd)
|
||||
{
|
||||
OVR_UNUSED(i);
|
||||
OVR_UNUSED(fd);
|
||||
|
||||
// There is a device status change
|
||||
udev_device* hid = udev_monitor_receive_device(HIDMonitor);
|
||||
if (hid)
|
||||
{
|
||||
const char* dev_path = udev_device_get_devnode(hid);
|
||||
const char* action = udev_device_get_action(hid);
|
||||
|
||||
HIDDeviceDesc device_info;
|
||||
device_info.Path = dev_path;
|
||||
|
||||
MessageType notify_type;
|
||||
if (OVR_strcmp(action, "add") == 0)
|
||||
{
|
||||
notify_type = Message_DeviceAdded;
|
||||
|
||||
// Retrieve the device info. This can only be done on a connected
|
||||
// device and is invalid for a disconnected device
|
||||
|
||||
// Get the USB device
|
||||
hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
|
||||
if (!hid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
getFullDesc(hid, &device_info);
|
||||
}
|
||||
else if (OVR_strcmp(action, "remove") == 0)
|
||||
{
|
||||
notify_type = Message_DeviceRemoved;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
bool deviceFound = false;
|
||||
for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
|
||||
{
|
||||
if (NotificationDevices[i] &&
|
||||
NotificationDevices[i]->OnDeviceNotification(notify_type, &device_info, &error))
|
||||
{
|
||||
// The notification was for an existing device
|
||||
deviceFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify_type == Message_DeviceAdded && !deviceFound)
|
||||
{
|
||||
DevManager->DetectHIDDevice(device_info);
|
||||
}
|
||||
|
||||
udev_device_unref(hid);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Linux::HIDDevice
|
||||
//=============================================================================
|
||||
HIDDevice::HIDDevice(HIDDeviceManager* manager)
|
||||
: InMinimalMode(false), HIDManager(manager)
|
||||
{
|
||||
DeviceHandle = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This is a minimal constructor used during enumeration for us to pass
|
||||
// a HIDDevice to the visit function (so that it can query feature reports).
|
||||
HIDDevice::HIDDevice(HIDDeviceManager* manager, int device_handle)
|
||||
: InMinimalMode(true), HIDManager(manager), DeviceHandle(device_handle)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HIDDevice::~HIDDevice()
|
||||
{
|
||||
if (!InMinimalMode)
|
||||
{
|
||||
HIDShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::HIDInitialize(const String& path)
|
||||
{
|
||||
const char* hid_path = path.ToCStr();
|
||||
if (!openDevice(hid_path))
|
||||
{
|
||||
LogText("OVR::Linux::HIDDevice - Failed to open HIDDevice: %s", hid_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
HIDManager->DevManager->pThread->AddTicksNotifier(this);
|
||||
HIDManager->AddNotificationDevice(this);
|
||||
|
||||
LogText("OVR::Linux::HIDDevice - Opened '%s'\n"
|
||||
" Manufacturer:'%s' Product:'%s' Serial#:'%s'\n",
|
||||
DevDesc.Path.ToCStr(),
|
||||
DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
|
||||
DevDesc.SerialNumber.ToCStr());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::initInfo()
|
||||
{
|
||||
// Device must have been successfully opened.
|
||||
OVR_ASSERT(DeviceHandle >= 0);
|
||||
|
||||
int desc_size = 0;
|
||||
hidraw_report_descriptor rpt_desc;
|
||||
memset(&rpt_desc, 0, sizeof(rpt_desc));
|
||||
|
||||
// get report descriptor size
|
||||
int r = ioctl(DeviceHandle, HIDIOCGRDESCSIZE, &desc_size);
|
||||
if (r < 0)
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Failed to get report descriptor size."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the report descriptor
|
||||
rpt_desc.size = desc_size;
|
||||
r = ioctl(DeviceHandle, HIDIOCGRDESC, &rpt_desc);
|
||||
if (r < 0)
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Failed to get report descriptor."));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
// Get report lengths.
|
||||
SInt32 bufferLength;
|
||||
bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
|
||||
OVR_ASSERT(getResult);
|
||||
InputReportBufferLength = (UInt16) bufferLength;
|
||||
|
||||
getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
|
||||
OVR_ASSERT(getResult);
|
||||
OutputReportBufferLength = (UInt16) bufferLength;
|
||||
|
||||
getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
|
||||
OVR_ASSERT(getResult);
|
||||
FeatureReportBufferLength = (UInt16) bufferLength;
|
||||
|
||||
|
||||
if (ReadBufferSize < InputReportBufferLength)
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get device desc.
|
||||
if (!HIDManager->getFullDesc(Device, &DevDesc))
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
*/
|
||||
|
||||
// Get report lengths.
|
||||
// TODO: hard-coded for now. Need to interpret these values from the report descriptor
|
||||
InputReportBufferLength = 62;
|
||||
OutputReportBufferLength = 0;
|
||||
FeatureReportBufferLength = 69;
|
||||
|
||||
if (ReadBufferSize < InputReportBufferLength)
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::openDevice(const char* device_path)
|
||||
{
|
||||
// First fill out the device descriptor
|
||||
if (!HIDManager->GetDescriptorFromPath(device_path, &DevDesc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now open the device
|
||||
DeviceHandle = open(device_path, O_RDWR);
|
||||
if (DeviceHandle < 0)
|
||||
{
|
||||
OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", errno));
|
||||
DeviceHandle = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// fill out some values from the feature report descriptor
|
||||
if (!initInfo())
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
|
||||
|
||||
close(DeviceHandle);
|
||||
DeviceHandle = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the device to the polling list
|
||||
if (!HIDManager->DevManager->pThread->AddSelectFd(this, DeviceHandle))
|
||||
{
|
||||
OVR_ASSERT_LOG(false, ("Failed to initialize polling for HIDDevice."));
|
||||
|
||||
close(DeviceHandle);
|
||||
DeviceHandle = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDevice::HIDShutdown()
|
||||
{
|
||||
|
||||
HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
|
||||
HIDManager->RemoveNotificationDevice(this);
|
||||
|
||||
if (DeviceHandle >= 0) // Device may already have been closed if unplugged.
|
||||
{
|
||||
closeDevice(false);
|
||||
}
|
||||
|
||||
LogText("OVR::Linux::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDevice::closeDevice(bool wasUnplugged)
|
||||
{
|
||||
OVR_UNUSED(wasUnplugged);
|
||||
OVR_ASSERT(DeviceHandle >= 0);
|
||||
|
||||
|
||||
HIDManager->DevManager->pThread->RemoveSelectFd(this, DeviceHandle);
|
||||
|
||||
close(DeviceHandle); // close the file handle
|
||||
DeviceHandle = -1;
|
||||
|
||||
LogText("OVR::Linux::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDevice::closeDeviceOnIOError()
|
||||
{
|
||||
LogText("OVR::Linux::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
|
||||
closeDevice(false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
|
||||
{
|
||||
|
||||
if (DeviceHandle < 0)
|
||||
return false;
|
||||
|
||||
UByte reportID = data[0];
|
||||
|
||||
if (reportID == 0)
|
||||
{
|
||||
// Not using reports so remove from data packet.
|
||||
data++;
|
||||
length--;
|
||||
}
|
||||
|
||||
int r = ioctl(DeviceHandle, HIDIOCSFEATURE(length), data);
|
||||
return (r >= 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
|
||||
{
|
||||
if (DeviceHandle < 0)
|
||||
return false;
|
||||
|
||||
int r = ioctl(DeviceHandle, HIDIOCGFEATURE(length), data);
|
||||
return (r >= 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
double HIDDevice::OnTicks(double tickSeconds)
|
||||
{
|
||||
if (Handler)
|
||||
{
|
||||
return Handler->OnTicks(tickSeconds);
|
||||
}
|
||||
|
||||
return DeviceManagerThread::Notifier::OnTicks(tickSeconds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void HIDDevice::OnEvent(int i, int fd)
|
||||
{
|
||||
OVR_UNUSED(i);
|
||||
// We have data to read from the device
|
||||
int bytes = read(fd, ReadBuffer, ReadBufferSize);
|
||||
if (bytes >= 0)
|
||||
{
|
||||
// TODO: I need to handle partial messages and package reconstruction
|
||||
if (Handler)
|
||||
{
|
||||
Handler->OnInputReport(ReadBuffer, bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Close the device on read error.
|
||||
closeDeviceOnIOError();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool HIDDevice::OnDeviceNotification(MessageType messageType,
|
||||
HIDDeviceDesc* device_info,
|
||||
bool* error)
|
||||
{
|
||||
const char* device_path = device_info->Path.ToCStr();
|
||||
|
||||
if (messageType == Message_DeviceAdded && DeviceHandle < 0)
|
||||
{
|
||||
// Is this the correct device?
|
||||
if (!(device_info->VendorId == DevDesc.VendorId
|
||||
&& device_info->ProductId == DevDesc.ProductId
|
||||
&& device_info->SerialNumber == DevDesc.SerialNumber))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// A closed device has been re-added. Try to reopen.
|
||||
if (!openDevice(device_path))
|
||||
{
|
||||
LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n",
|
||||
device_path);
|
||||
*error = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
LogText("OVR::Linux::HIDDevice - Reopened device '%s'\n", device_path);
|
||||
|
||||
if (Handler)
|
||||
{
|
||||
Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceAdded);
|
||||
}
|
||||
}
|
||||
else if (messageType == Message_DeviceRemoved)
|
||||
{
|
||||
// Is this the correct device?
|
||||
// For disconnected device, the device description will be invalid so
|
||||
// checking the path is the only way to match them
|
||||
if (DevDesc.Path.CompareNoCase(device_path) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DeviceHandle >= 0)
|
||||
{
|
||||
closeDevice(true);
|
||||
}
|
||||
|
||||
if (Handler)
|
||||
{
|
||||
Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceRemoved);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OVR_ASSERT(0);
|
||||
}
|
||||
|
||||
*error = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devManager)
|
||||
{
|
||||
|
||||
if (!System::IsInitialized())
|
||||
{
|
||||
// Use custom message, since Log is not yet installed.
|
||||
OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
|
||||
LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(devManager);
|
||||
|
||||
if (manager)
|
||||
{
|
||||
if (manager->Initialize())
|
||||
{
|
||||
manager->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
manager.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
return manager.GetPtr();
|
||||
}
|
||||
|
||||
} // namespace Linux
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// ***** Creation
|
||||
|
||||
// Creates a new HIDDeviceManager and initializes OVR.
|
||||
HIDDeviceManager* HIDDeviceManager::Create(Ptr<OVR::DeviceManager>& deviceManager)
|
||||
{
|
||||
|
||||
if (!System::IsInitialized())
|
||||
{
|
||||
// Use custom message, since Log is not yet installed.
|
||||
OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
|
||||
LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<Linux::DeviceManager> deviceManagerLinux = *new Linux::DeviceManager;
|
||||
|
||||
if (!deviceManagerLinux)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!deviceManagerLinux->Initialize(NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
deviceManager = deviceManagerLinux;
|
||||
|
||||
return deviceManagerLinux->GetHIDDeviceManager();
|
||||
}
|
||||
|
||||
} // namespace OVR
|
Reference in New Issue
Block a user