#include #include "Report.h" #include "Receiver.h" #include "Error.h" using namespace logid::backend::dj; using namespace logid::backend; InvalidReceiver::InvalidReceiver(Reason reason) : _reason (reason) { } const char* InvalidReceiver::what() const noexcept { return "Invalid receiver"; } InvalidReceiver::Reason InvalidReceiver::code() const noexcept { return _reason; } Receiver::Receiver(std::string path) : raw_device (std::make_shared(path)), _hidpp10_device (raw_device, hidpp::DefaultDevice) { if(!supportsDjReports(raw_device->reportDescriptor())) throw InvalidReceiver(InvalidReceiver::NoDJReports); // Pass all HID++ events on DefaultDevice to handleHidppEvent RawEventHandler hidppRawEventHandler; hidppRawEventHandler.condition = [this](std::vector& report)->bool { return (report[hidpp::Offset::Type] == hidpp::Report::Type::Short || report[hidpp::Offset::Type] == hidpp::Report::Type::Long) && (report[hidpp::Offset::DeviceIndex] == hidpp::DefaultDevice); }; hidppRawEventHandler.callback = [this](std::vector& report)->void { hidpp::Report _report(report); this->handleHidppEvent(_report); }; // Pass all DJ events with device index to handleHidppEvent RawEventHandler djRawEventHandler; djRawEventHandler.condition = [this](std::vector& report)->bool { return (report[Offset::Type] == Report::Type::Short || report[Offset::Type] == Report::Type::Long); }; djRawEventHandler.callback = [this](std::vector& report)->void { Report _report(report); this->handleDjEvent(_report); }; raw_device->addEventHandler("RECV_HIDPP", hidppRawEventHandler); raw_device->addEventHandler("RECV_DJ", djRawEventHandler); } void Receiver::enumerate() { sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{}); } Receiver::notification_flags Receiver::getHidppNotifications() { auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {}); notification_flags flags{}; flags.device_battery_status = response[0] & (1 << 4); flags.receiver_wireless_notifications = response[1] & (1 << 0); flags.receiver_software_present = response[1] & (1 << 3); } void Receiver::enableHidppNotifications(notification_flags flags) { std::vector request(3); if(flags.device_battery_status) request[0] |= (1 << 4); if(flags.receiver_wireless_notifications) request[1] |= (1 << 0); if(flags.receiver_software_present) request[1] |= (1 << 3); _hidpp10_device.setRegister(EnableHidppNotifications, request); } ///TODO: Investigate usage uint8_t Receiver::getConnectionState(hidpp::DeviceIndex index) { auto response = _hidpp10_device.setRegister(ConnectionState, {index}); return response[0]; } void Receiver::startPairing(uint8_t timeout) { ///TODO: Device number == Device index? std::vector request(3); request[0] = 1; request[1] = hidpp::DefaultDevice; request[2] = timeout; _hidpp10_device.setRegister(DevicePairing, request); } void Receiver::stopPairing() { ///TODO: Device number == Device index? std::vector request(3); request[0] = 2; request[1] = hidpp::DefaultDevice; _hidpp10_device.setRegister(DevicePairing, request); } void Receiver::disconnect(hidpp::DeviceIndex index) { ///TODO: Device number == Device index? std::vector request(3); request[0] = 3; request[1] = index; _hidpp10_device.setRegister(DevicePairing, request); } std::map Receiver::getDeviceActivity() { auto response = _hidpp10_device.getRegister(DeviceActivity, {}); std::map device_activity; for(uint8_t i = hidpp::WirelessDevice1; i <= hidpp::WirelessDevice6; i++) device_activity[static_cast(i)] = response[i]; return device_activity; } Receiver::pairing_info Receiver::getPairingInfo(hidpp::DeviceIndex index) { std::vector request(1); request[0] = index; request[0] += 0x19; auto response = _hidpp10_device.getRegister(PairingInfo, request); pairing_info info{}; info.destination_id = response[0]; info.report_interval = response[1]; info.pid = response[2]; info.pid |= (response[3] << 8); info.device_type = response[6]; return info; } Receiver::extended_pairing_info Receiver::getExtendedPairingInfo(hidpp::DeviceIndex index) { std::vector request(1); request[0] = index; request[0] += 0x29; auto response = _hidpp10_device.getRegister(PairingInfo, request); extended_pairing_info info{}; info.serial_number = 0; for(uint8_t i = 0; i < 4; i++) info.serial_number |= (response[i] << 8*i); for(uint8_t i = 0; i < 4; i++) info.report_types[i] = response[i + 4]; info.power_switch_location = response[8] & 0xf; return info; } std::string Receiver::getDeviceName(hidpp::DeviceIndex index) { std::vector request(1); request[0] = index; request[0] += 0x39; auto response = _hidpp10_device.getRegister(PairingInfo, request); uint8_t size = response[0]; assert(size <= 14); std::string name(size, ' '); for(std::size_t i = 0; i < size; i++) name[i] = response[i + 1]; return name; } hidpp::DeviceIndex Receiver::deviceConnectionEvent(hidpp::Report &report) { assert(report.subId() == DeviceConnection); return report.deviceIndex(); } hidpp::DeviceIndex Receiver::deviceDisconnectionEvent(hidpp::Report& report) { assert(report.subId() == DeviceDisconnection); return report.deviceIndex(); } void Receiver::handleDjEvent(Report& report) { if(report.feature() == DeviceConnection || report.feature() == DeviceDisconnection || report.feature() == ConnectionStatus) { printf("%s DJ IN: ", raw_device->hidrawPath().c_str()); for(auto &i: report.rawData()) printf("%02x ", i); printf("\n"); } } void Receiver::handleHidppEvent(hidpp::Report &report) { printf("%s HID++ IN: ", raw_device->hidrawPath().c_str()); for(auto &i: report.rawReport()) printf("%02x ", i); printf("\n"); } void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function, const std::vector&& params) { assert(params.size() <= LongParamLength); Report::Type type = params.size() <= ShortParamLength ? ReportType::Short : ReportType::Long; Report request(type, index, function); std::copy(params.begin(), params.end(), request.paramBegin()); raw_device->sendReportNoResponse(request.rawData()); } void Receiver::listen() { std::thread{[=]() { raw_device->listen(); }}.detach(); }