Hi there, I've a Logitech K750 wireless and solar keyboard, and want to retrieve the battery level and the light meter information. So far I've reverse-engineered the missing pieces with success, and write a small userland utility which works and allows me to retrieve this information. I'm attaching the code here.
/* Written by Julien Danjou <julien@xxxxxxxxxxx> in 2012 */ #include <libusb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { libusb_context *ctx; libusb_init(&ctx); libusb_set_debug(ctx, 3); libusb_device_handle *device_handle = libusb_open_device_with_vid_pid(ctx, 0x046d, 0xc52b); fprintf(stderr, "Found keyboard 0x%p\n", device_handle); libusb_device *device = libusb_get_device(device_handle); struct libusb_device_descriptor desc; /* XXX check return code */ libusb_get_device_descriptor(device, &desc); for(uint8_t config_index = 0; config_index < desc.bNumConfigurations; config_index++) { struct libusb_config_descriptor *config; /* XXX check return code */ libusb_get_config_descriptor(device, config_index, &config); /* We know we want interface 2 */ int iface_index = 2; const struct libusb_interface *iface = &config->interface[iface_index]; for (int altsetting_index = 0; altsetting_index < iface->num_altsetting; altsetting_index++) { const struct libusb_interface_descriptor *iface_desc = &iface->altsetting[altsetting_index]; if (iface_desc->bInterfaceClass == LIBUSB_CLASS_HID) { libusb_detach_kernel_driver(device_handle, iface_index); libusb_claim_interface(device_handle, iface_index); unsigned char ret[65535]; unsigned char payload[] = "\x10\x02\x09\x03\x78\x01\x00"; if(libusb_control_transfer(device_handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_SET_CONFIGURATION, 0x0210, 2, payload, sizeof(payload) - 1, 10000)) { int actual_length = 0; while(actual_length != 20 || strncmp((const char *) &ret[9], "GOOD", 4)) libusb_interrupt_transfer(device_handle, iface_desc->endpoint[0].bEndpointAddress, ret, sizeof(ret), &actual_length, 100000); uint16_t lux = ret[5] << 8 | ret[6]; fprintf(stderr, "Charge: %d %%\nLight: %d lux\n", ret[4], lux); } libusb_release_interface(device_handle, iface_index); libusb_attach_kernel_driver(device_handle, iface_index); } } } libusb_close(device_handle); libusb_exit(ctx); }
The problem with this approach, is that I've to detach the driver, making some input events lost. Therefore I'd like to add native support for this "device" in the kernel. It's officialy supported by "hid-logitech-dj" because it's hidden behind a Logitech Unifying receiver. I've poked into the hid subsystem and dj-logitech a bit, but I can't really find how to do things correctly. As you can see, I need to send some control transfer directly over USB, and I am not sure the HID driver is the good place to do that. I also though about going rogue and write an USB driver, bypassing hid, but since the Logitech Unifying Receiver is handled by hid-logitech-dj, I'm not authorized to have another driver doing that. Then, for now, I'm stuck because I'm not sure where to put my code. I'm not even sure on how to export the retrieved values. Cc'ing Nestor in case he have any idea about this. Thanks in advance, Cheers, -- Julien
Attachment:
pgpItwuRaWPwY.pgp
Description: PGP signature