struct ratbag_device* ratbag_device_new(struct ratbag *ratbag, struct udev_device *udev_device, const char *name, const struct input_id *id) { struct ratbag_device *device = NULL; device = zalloc(sizeof(*device)); device->name = strdup_safe(name); device->ratbag = ratbag_ref(ratbag); device->refcount = 1; device->udev_device = udev_device_ref(udev_device); device->ids = *id; device->data = ratbag_device_data_new_for_id(ratbag, id); list_init(&device->profiles); list_insert(&ratbag->devices, &device->link); /* We assume that most devices have this capability, so let's set it * by default. The few devices that miss this capability should * unset it instead. */ ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_QUERY_CONFIGURATION); return device; }
static int hidpp20drv_init_feature(struct ratbag_device *device, uint16_t feature) { struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); struct ratbag *ratbag = device->ratbag; int rc; uint8_t feature_index, feature_type, feature_version; rc = hidpp_root_get_feature(drv_data->dev, feature, &feature_index, &feature_type, &feature_version); switch (feature) { case HIDPP_PAGE_ROOT: case HIDPP_PAGE_FEATURE_SET: /* these features are mandatory and already handled */ break; case HIDPP_PAGE_MOUSE_POINTER_BASIC: { drv_data->capabilities |= HIDPP_CAP_RESOLUTION_2200; break; } case HIDPP_PAGE_ADJUSTABLE_DPI: { log_debug(ratbag, "device has adjustable dpi\n"); /* we read the profile once to get the correct number of * supported resolutions. */ rc = hidpp20drv_read_resolution_dpi_2201(device); if (rc < 0) return 0; /* this is not a hard failure */ ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_SWITCHABLE_RESOLUTION); drv_data->capabilities |= HIDPP_CAP_SWITCHABLE_RESOLUTION_2201; break; } case HIDPP_PAGE_SPECIAL_KEYS_BUTTONS: { log_debug(ratbag, "device has programmable keys/buttons\n"); drv_data->capabilities |= HIDPP_CAP_BUTTON_KEY_1b04; ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_KEY); /* we read the profile once to get the correct number of * supported buttons. */ if (!hidpp20drv_read_special_key_mouse(device)) device->num_buttons = drv_data->num_controls; break; } case HIDPP_PAGE_BATTERY_LEVEL_STATUS: { uint16_t level, next_level; enum hidpp20_battery_status status; rc = hidpp20_batterylevel_get_battery_level(drv_data->dev, &level, &next_level); if (rc < 0) return rc; status = rc; log_debug(ratbag, "device battery level is %d%% (next %d%%), status %d \n", level, next_level, status); drv_data->capabilities |= HIDPP_CAP_BATTERY_LEVEL_1000; break; } case HIDPP_PAGE_KBD_REPROGRAMMABLE_KEYS: { log_debug(ratbag, "device has programmable keys/buttons\n"); drv_data->capabilities |= HIDPP_CAP_KBD_REPROGRAMMABLE_KEYS_1b00; /* we read the profile once to get the correct number of * supported buttons. */ if (!hidpp20drv_read_kbd_reprogrammable_key(device)) device->num_buttons = drv_data->num_controls; break; } case HIDPP_PAGE_ADJUSTABLE_REPORT_RATE: { log_debug(ratbag, "device has adjustable report rate\n"); break; } case HIDPP_PAGE_COLOR_LED_EFFECTS: { log_debug(ratbag, "device has color effects\n"); break; } case HIDPP_PAGE_ONBOARD_PROFILES: { log_debug(ratbag, "device has onboard profiles\n"); drv_data->capabilities |= HIDPP_CAP_ONBOARD_PROFILES_8100; rc = hidpp20_onboard_profiles_allocate(drv_data->dev, &drv_data->profiles); if (rc < 0) return rc; drv_data->num_profiles = drv_data->profiles->num_profiles; drv_data->num_resolutions = drv_data->profiles->num_modes; drv_data->num_buttons = drv_data->profiles->num_buttons; break; } case HIDPP_PAGE_MOUSE_BUTTON_SPY: { log_debug(ratbag, "device has configurable mouse button spy\n"); break; } default: log_raw(device->ratbag, "unknown feature 0x%04x\n", feature); } return 0; }