Preliminary support for Logitech FP8071

* Updated detection for differences in FP8071
This commit is contained in:
Chris M
2023-12-27 10:02:58 +11:00
parent 366adce39e
commit 7b454ce5f4
3 changed files with 180 additions and 12 deletions

View File

@@ -17,7 +17,14 @@ const char* logitech_led_locations[] =
"Primary",
"Logo",
"Left",
"Right"
"Right",
"Combined",
"Group One",
"Group Two",
"Group Three",
"Group Four",
"Group Five",
"Group Six"
};
const int NUM_LOGITECH_LED_LOCATIONS = sizeof(logitech_led_locations);
@@ -589,11 +596,11 @@ void logitech_device::getRGBconfig()
result = hid_write(dev_use2, get_count.buffer, get_count.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
LOG_DEBUG("[%s] FP8071 - LED Count - %02X : %02X %02X %04X %04X %04X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(),
response.data[2], response.data[0], response.data[1], (response.data[3] << 8 | response.data[4]), (response.data[5] << 8 | response.data[6]),
LOG_DEBUG("[%s] FP8071 - LED Count - %04X : %02X %04X %04X %04X %04X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(),
(response.data[1] << 8 | response.data[2]), response.data[0], (response.data[1] << 8 | response.data[2]), (response.data[3] << 8 | response.data[4]), (response.data[5] << 8 | response.data[6]),
(response.data[7] << 8 | response.data[8]), response.data[9], response.data[10], response.data[11], response.data[12], response.data[13], response.data[14], response.data[15]);
led_response = response.data[2];
led_response = (response.data[1] << 8 | response.data[2]);
for(size_t i = 0; i < led_response; i++)
{
get_count.data[0] = (uint8_t)i;
@@ -602,7 +609,7 @@ void logitech_device::getRGBconfig()
result = hid_write(dev_use2, get_count.buffer, get_count.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
LOG_DEBUG("[%s] FP8071 - LED %02i - %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), led_counter,
LOG_DEBUG("[%s] FP8071 - LED %02i - %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), i,
response.data[0], response.data[1], response.data[2], response.data[3], response.data[4], response.data[5], response.data[6], response.data[7],
response.data[8], response.data[9], response.data[10], response.data[11], response.data[12], response.data[13], response.data[14], response.data[15]);
@@ -617,7 +624,7 @@ void logitech_device::getRGBconfig()
fx_response.init();
longFAPrequest get_effect;
get_effect.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_GET_INFO);
get_effect.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_GET_COUNT);
get_effect.data[0] = get_count.data[0];
get_effect.data[1] = i;
@@ -638,6 +645,10 @@ void logitech_device::getRGBconfig()
leds.emplace(response.data[0], new_led);
}
/*-----------------------------------------------------------------*\
| Set the config to SW control mode |
\*-----------------------------------------------------------------*/
set8071Effects(5);
}
/*get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_STATE;
@@ -682,7 +693,7 @@ uint8_t logitech_device::setDirectMode(bool direct)
| Turn the direct mode on or off via the RGB_feature_index |
\*-----------------------------------------------------------------*/
longFAPrequest set_direct;
set_direct.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_UNKNOWN);
set_direct.init(device_index, RGB_feature_index, LOGITECH_FP8070_SET_SW_CTL);
set_direct.data[0] = (direct) ? 1 : 0;
set_direct.data[1] = set_direct.data[0];
@@ -733,7 +744,13 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin
| Set the mode via the RGB_feature_index |
\*-----------------------------------------------------------------*/
longFAPrequest set_mode;
set_mode.init(device_index, RGB_feature_index, ((feature_page == LOGITECH_HIDPP_PAGE_RGB_EFFECTS1) ? LOGITECH_CMD_RGB_EFFECTS_SET_CONTROL : LOGITECH_CMD_RGB_EFFECTS_GET_INFO));
bool fp8070 = (feature_page == LOGITECH_HIDPP_PAGE_RGB_EFFECTS1);
set_mode.init(
device_index,
RGB_feature_index,
(fp8070 ? LOGITECH_FP8070_SET_EFFECT : LOGITECH_FP8071_SET_LED_EFFECT)
);
set_mode.data[0] = zone;
set_mode.data[1] = mode;
@@ -741,12 +758,13 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin
set_mode.data[3] = green;
set_mode.data[4] = blue;
set_mode.data[12] = fp8070 ? 0x00 : 0x01; //Bit 2-3 Power Mode : Bit 1-0 Persistence
speed *= 100;
switch(fx)
{
case LOGITECH_DEVICE_LED_ON:
set_mode.data[5] = 0x02; //zone;
//set_mode.data[12] = 0x01; //Save to flash testing
//set_mode.data[5] = 0x02; //zone;
break;
case LOGITECH_DEVICE_LED_SPECTRUM:
@@ -795,5 +813,108 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin
}
}
return result;
}
uint8_t logitech_device::set8071Effects(uint8_t control)
{
int result = 0;
/*-----------------------------------------------------------------*\
| Check the usage map for usage2 (0x11 Long FAP Message) |
| then set the device into direct mode via register 0x80 |
\*-----------------------------------------------------------------*/
hid_device* dev_use2 = getDevice(2);
if(dev_use2)
{
/*-----------------------------------------------------------------*\
| Create a buffer for reads |
\*-----------------------------------------------------------------*/
blankFAPmessage response;
response.init();
/*-----------------------------------------------------------------*\
| Turn the direct mode on or off via the RGB_feature_index |
\*-----------------------------------------------------------------*/
shortFAPrequest set_effects;
set_effects.init(device_index, RGB_feature_index);
set_effects.feature_command = LOGITECH_FP8071_CONTROL;
set_effects.data[0] = 1;
set_effects.data[1] = 3; //Disables all FW control for PWR (0x02) and RGB (0x01)
set_effects.data[2] = control;
/*-----------------------------------------------------*\
| Send packet |
| This code has to be protected to avoid crashes when |
| this is called at the same time to change a powerplay |
| mat and its paired wireless mouse leds. It will |
| happen when using effects engines with high framerate |
\*-----------------------------------------------------*/
if(mutex)
{
std::lock_guard<std::mutex> guard(*mutex);
result = hid_write(dev_use2, set_effects.buffer, set_effects.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
}
else
{
result = hid_write(dev_use2, set_effects.buffer, set_effects.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
}
}
return result;
}
uint8_t logitech_device::set8071TimeoutControl(uint8_t control)
{
int result = 0;
/*-----------------------------------------------------------------*\
| Check the usage map for usage2 (0x11 Long FAP Message) |
| then set the device into direct mode via register 0x80 |
\*-----------------------------------------------------------------*/
hid_device* dev_use2 = getDevice(2);
if(dev_use2)
{
/*-----------------------------------------------------------------*\
| Create a buffer for reads |
\*-----------------------------------------------------------------*/
blankFAPmessage response;
response.init();
/*-----------------------------------------------------------------*\
| Turn the direct mode on or off via the RGB_feature_index |
\*-----------------------------------------------------------------*/
longFAPrequest set_control;
set_control.init(device_index, RGB_feature_index, LOGITECH_FP8071_PWR_CFG);
set_control.data[0] = 1; //1;
set_control.data[3] = 0; //0x3C; //Inactive Lighting timeout MSB
set_control.data[4] = 5; //0x3C; //Inactive Lighting timeout LSB
set_control.data[5] = 0; //1; //Lights off timeout MSB
set_control.data[6] = 20; //0x2C; //Lights off timeout LSB
/*-----------------------------------------------------*\
| Send packet |
| This code has to be protected to avoid crashes when |
| this is called at the same time to change a powerplay |
| mat and its paired wireless mouse leds. It will |
| happen when using effects engines with high framerate |
\*-----------------------------------------------------*/
if(mutex)
{
std::lock_guard<std::mutex> guard(*mutex);
result = hid_write(dev_use2, set_control.buffer, set_control.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
}
else
{
result = hid_write(dev_use2, set_control.buffer, set_control.size());
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
}
}
return(result);
}