Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit 6284152

Browse files
committed
Added HID Device
1 parent 2125e18 commit 6284152

File tree

2 files changed

+218
-0
lines changed

2 files changed

+218
-0
lines changed

libsrc/leddevice/LedHIDDevice.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
2+
// STL includes
3+
#include <cstring>
4+
#include <iostream>
5+
6+
// Qt includes
7+
#include <QTimer>
8+
9+
// Local Hyperion includes
10+
#include "LedHIDDevice.h"
11+
12+
LedHIDDevice::LedHIDDevice(const unsigned short VendorId, const unsigned short ProductId, int delayAfterConnect_ms, const bool useFeature) :
13+
_VendorId(VendorId),
14+
_ProductId(ProductId),
15+
_useFeature(useFeature),
16+
_deviceHandle(nullptr),
17+
_delayAfterConnect_ms(delayAfterConnect_ms),
18+
_blockedForDelay(false)
19+
{
20+
// empty
21+
}
22+
23+
LedHIDDevice::~LedHIDDevice()
24+
{
25+
if (_deviceHandle != nullptr)
26+
{
27+
hid_close(_deviceHandle);
28+
_deviceHandle = nullptr;
29+
}
30+
31+
hid_exit();
32+
}
33+
34+
int LedHIDDevice::open()
35+
{
36+
// Initialize the usb context
37+
int error = hid_init();
38+
if (error != 0)
39+
{
40+
std::cerr << "Error while initializing the hidapi context" << std::endl;
41+
return -1;
42+
}
43+
std::cout << "Hidapi initialized" << std::endl;
44+
45+
// Open the device
46+
printf("Opening device: VID %04hx PID %04hx\n", _VendorId, _ProductId);
47+
_deviceHandle = hid_open(_VendorId, _ProductId, nullptr);
48+
49+
if (_deviceHandle == nullptr)
50+
{
51+
// Failed to open the device
52+
std::cerr << "Failed to open HID device. Maybe your PID/VID setting is wrong?" << std::endl;
53+
54+
// http://www.signal11.us/oss/hidapi/
55+
/*
56+
std::cout << "Showing a list of all available HID devices:" << std::endl;
57+
auto devs = hid_enumerate(0x00, 0x00);
58+
auto cur_dev = devs;
59+
while (cur_dev) {
60+
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls",
61+
cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
62+
printf("\n");
63+
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
64+
printf(" Product: %ls\n", cur_dev->product_string);
65+
printf("\n");
66+
cur_dev = cur_dev->next;
67+
}
68+
hid_free_enumeration(devs);
69+
*/
70+
71+
return -1;
72+
}
73+
else{
74+
std::cout << "Opened HID device successful" << std::endl;
75+
}
76+
77+
// Wait after device got opened if enabled
78+
if (_delayAfterConnect_ms > 0)
79+
{
80+
_blockedForDelay = true;
81+
QTimer::singleShot(_delayAfterConnect_ms, this, SLOT(unblockAfterDelay()));
82+
std::cout << "Device blocked for " << _delayAfterConnect_ms << " ms" << std::endl;
83+
}
84+
85+
return 0;
86+
}
87+
88+
89+
int LedHIDDevice::writeBytes(const unsigned size, const uint8_t * data)
90+
{
91+
if (_blockedForDelay) {
92+
return 0;
93+
}
94+
95+
if (_deviceHandle == nullptr)
96+
{
97+
// try to reopen
98+
auto status = open();
99+
if(status < 0){
100+
// Try again in 3 seconds
101+
int seconds = 3000;
102+
_blockedForDelay = true;
103+
QTimer::singleShot(seconds, this, SLOT(unblockAfterDelay()));
104+
std::cout << "Device blocked for " << seconds << " ms" << std::endl;
105+
}
106+
// Return here, to not write led data if the device should be blocked after connect
107+
return status;
108+
}
109+
110+
// Prepend report ID to the buffer
111+
uint8_t ledData[size + 1];
112+
ledData[0] = 0; // Report ID
113+
memcpy(ledData + 1, data, size_t(size));
114+
115+
// Send data via feature or out report
116+
int ret;
117+
if(_useFeature){
118+
ret = hid_send_feature_report(_deviceHandle, ledData, size + 1);
119+
}
120+
else{
121+
ret = hid_write(_deviceHandle, ledData, size + 1);
122+
}
123+
124+
// Handle first error
125+
if(ret < 0){
126+
std::cerr << "Failed to write to HID device." << std::endl;
127+
128+
// Try again
129+
if(_useFeature){
130+
ret = hid_send_feature_report(_deviceHandle, ledData, size + 1);
131+
}
132+
else{
133+
ret = hid_write(_deviceHandle, ledData, size + 1);
134+
}
135+
136+
// Writing failed again, device might have disconnected
137+
if(ret < 0){
138+
std::cerr << "Failed to write to HID device." << std::endl;
139+
140+
hid_close(_deviceHandle);
141+
_deviceHandle = nullptr;
142+
}
143+
}
144+
145+
return ret;
146+
}
147+
148+
void LedHIDDevice::unblockAfterDelay()
149+
{
150+
std::cout << "Device unblocked" << std::endl;
151+
_blockedForDelay = false;
152+
}

libsrc/leddevice/LedHIDDevice.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#pragma once
2+
3+
#include <QObject>
4+
5+
// libusb include
6+
#include <hidapi/hidapi.h>
7+
8+
// Leddevice includes
9+
#include <leddevice/LedDevice.h>
10+
11+
///
12+
/// The LedHIDDevice implements an abstract base-class for LedDevices using an HID-device.
13+
///
14+
class LedHIDDevice : public QObject, public LedDevice
15+
{
16+
Q_OBJECT
17+
18+
public:
19+
///
20+
/// Constructs the LedDevice attached to an HID-device
21+
///
22+
/// @param[in] VendorId The USB VID of the output device
23+
/// @param[in] ProductId The USB PID of the output device
24+
///
25+
LedHIDDevice(const unsigned short VendorId, const unsigned short ProductId, int delayAfterConnect_ms = 0, const bool useFeature = false);
26+
27+
///
28+
/// Destructor of the LedDevice; closes the output device if it is open
29+
///
30+
virtual ~LedHIDDevice();
31+
32+
///
33+
/// Opens and configures the output device
34+
///
35+
/// @return Zero on succes else negative
36+
///
37+
int open();
38+
protected:
39+
/**
40+
* Writes the given bytes to the HID-device and
41+
*
42+
* @param[in[ size The length of the data
43+
* @param[in] data The data
44+
*
45+
* @return Zero on succes else negative
46+
*/
47+
int writeBytes(const unsigned size, const uint8_t *data);
48+
49+
private slots:
50+
/// Unblock the device after a connection delay
51+
void unblockAfterDelay();
52+
53+
private:
54+
// HID VID and PID
55+
const unsigned short _VendorId;
56+
const unsigned short _ProductId;
57+
const bool _useFeature;
58+
59+
/// libusb device handle
60+
hid_device * _deviceHandle;
61+
62+
/// Sleep after the connect before continuing
63+
const int _delayAfterConnect_ms;
64+
65+
bool _blockedForDelay;
66+
};

0 commit comments

Comments
 (0)