diff --git a/daemon/device_information.h b/daemon/device_information.h new file mode 100644 index 0000000..c2b73c4 --- /dev/null +++ b/daemon/device_information.h @@ -0,0 +1,51 @@ +#pragma once +#include + +struct device_information { + char const* const device_name; + + bool screen_rotation_supported; + char const* const target_output; + char const* const target_motion_sensor; + enum wl_output_transform const sensor_to_output_rotation[4]; + + bool basestation_detection_supported; + uint16_t const basestation_vendor_id; + uint16_t const basestation_product_id; +}; + +static struct device_information DEVICE_INFORMATION_GENERIC = { + .device_name = "generic", + .screen_rotation_supported = true, + .target_output = "eDP-1", + .target_motion_sensor = "/sys/bus/iio/devices/iio:device0", + .sensor_to_output_rotation = + { + [ACCEL_ROTATION_0DEG] = WL_OUTPUT_TRANSFORM_NORMAL, + [ACCEL_ROTATION_90DEG] = WL_OUTPUT_TRANSFORM_90, + [ACCEL_ROTATION_180DEG] = WL_OUTPUT_TRANSFORM_180, + [ACCEL_ROTATION_270DEG] = WL_OUTPUT_TRANSFORM_270, + }, + .basestation_detection_supported = false, + .basestation_vendor_id = 0, + .basestation_product_id = 0, +}; + +static struct device_information DEVICE_INFOS[] = { + { + .device_name = "lenovo-miix-320-10icr", + .screen_rotation_supported = true, + .target_output = "DSI-1", + .target_motion_sensor = "/sys/bus/iio/devices/iio:device0", + .sensor_to_output_rotation = + { + [ACCEL_ROTATION_0DEG] = WL_OUTPUT_TRANSFORM_270, + [ACCEL_ROTATION_90DEG] = WL_OUTPUT_TRANSFORM_NORMAL, + [ACCEL_ROTATION_180DEG] = WL_OUTPUT_TRANSFORM_90, + [ACCEL_ROTATION_270DEG] = WL_OUTPUT_TRANSFORM_180, + }, + .basestation_detection_supported = true, + .basestation_vendor_id = 0x048d, + .basestation_product_id = 0x8911, + }, +}; diff --git a/daemon/main.c b/daemon/main.c index e92f7df..a50f273 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -11,27 +12,37 @@ #include "accel_monitor.h" #include "output_manager.h" #include "usb_device_detection.h" +#include "device_information.h" -static enum wl_output_transform const SENSOR_TO_OUTPUT_ROTATION[] = { - [ACCEL_ROTATION_0DEG] = WL_OUTPUT_TRANSFORM_270, - [ACCEL_ROTATION_90DEG] = WL_OUTPUT_TRANSFORM_NORMAL, - [ACCEL_ROTATION_180DEG] = WL_OUTPUT_TRANSFORM_90, - [ACCEL_ROTATION_270DEG] = WL_OUTPUT_TRANSFORM_180, -}; +static struct device_information get_device_info_for_name( + char const* const device_name) +{ + if (strcmp(device_name, "generic") == 0) { + fprintf( + stderr, + "WARNING: Using a 'generic' device. This may not work properly.\n"); + return DEVICE_INFORMATION_GENERIC; + } -static char const* const DEFAULT_OUTPUT = "DSI-1"; -static char const* const DEFAULT_MOTION_SENSOR = - "/sys/bus/iio/devices/iio:device0"; + static size_t const device_info_count = + sizeof(DEVICE_INFOS) / sizeof(*DEVICE_INFOS); + for (size_t i = 0; i < device_info_count; ++i) { + struct device_information current = DEVICE_INFOS[i]; + if (strcmp(current.device_name, device_name) == 0) return current; + } -static uint16_t const BASESTATION_VENDOR_ID = 0x048d; -static uint16_t const BASESTATION_PRODUCT_ID = 0x8911; + fprintf(stderr, "No matching configuration for '%s'.\n", device_name); + + return DEVICE_INFORMATION_GENERIC; +} static char* get_hook_path(char const* const hook_name) { char* path; char* xdg_config_dir = getenv("XDG_CONFIG_HOME"); if (xdg_config_dir) - asprintf(&path, "%s/convertablet/hooks/%s-hook", xdg_config_dir, hook_name); + asprintf( + &path, "%s/convertablet/hooks/%s-hook", xdg_config_dir, hook_name); else asprintf(&path, "%s/.config/convertablet/hooks/%s-hook", @@ -99,25 +110,65 @@ static void on_basestation_disconnected() static enum accel_rotation last_accel_rotation = ACCEL_ROTATION_NO_CHANGE; -int main(int, char**) +int main(int argc, char** argv) { - struct accel_monitor* monitor = accel_start_monitor(DEFAULT_MOTION_SENSOR); - - if (!monitor) { - fprintf(stderr, "Failed to start iio motion monitoring\n"); + if (argc < 2) { + fprintf(stderr, + "No device specified! Please specify your device's name or use " + "'generic' for sane defaults.\n"); + fprintf(stderr, "\tUsage: %s \n", argv[0]); + fprintf(stderr, "\t %s list-devices \n", argv[0]); return -1; } - struct usb_detector* base_station_detector = - create_detector(BASESTATION_VENDOR_ID, BASESTATION_PRODUCT_ID); + if (strcmp(argv[1], "list-devices") == 0) { + printf("Device names:\n"); + static size_t const device_info_count = + sizeof(DEVICE_INFOS) / sizeof(*DEVICE_INFOS); + for (size_t i = 0; i < device_info_count; ++i) + printf("\t- %s\n", DEVICE_INFOS[i].device_name); + return 0; + } - base_station_detector->on_connected = &on_basestation_connected; - base_station_detector->on_disconnected = &on_basestation_disconnected; - base_station_detector->has_hotplug_callbacks = true; + struct device_information device_info = get_device_info_for_name(argv[1]); - struct miix_wlr_state* state = miix_wlr_init(); + struct accel_monitor* monitor = 0; + struct miix_wlr_state* state = 0; + if (device_info.screen_rotation_supported) { + monitor = accel_start_monitor(device_info.target_motion_sensor); + if (!monitor) { + fprintf(stderr, "Failed to start iio motion monitoring\n"); + return -1; + } + + state = miix_wlr_init(); + if (!state) { + fprintf(stderr, "Failed to connect to wayland server.\n"); + return -1; + } + } else + fprintf(stderr, "Screen rotation not supported.\n"); + + struct usb_detector* base_station_detector = 0; + if (device_info.basestation_detection_supported) { + base_station_detector = + create_detector(device_info.basestation_vendor_id, + device_info.basestation_product_id); + if (!base_station_detector) { + fprintf(stderr, "Failed to create basestation detector.\n"); + return -1; + } + + base_station_detector->on_connected = &on_basestation_connected; + base_station_detector->on_disconnected = &on_basestation_disconnected; + base_station_detector->has_hotplug_callbacks = true; + } else + fprintf(stderr, "Base station detection not supported.\n"); + + for (;;) { // Main loop that handles the rotation detection. + // If screen rotation isn't supported, let's just do nothing. + if (!device_info.screen_rotation_supported) continue; - for (;;) { thrd_sleep(&(struct timespec){0, 10000000UL}, NULL); if (!monitor->data_is_ready) continue; @@ -125,8 +176,8 @@ int main(int, char**) if (last_accel_rotation != ACCEL_ROTATION_0DEG) { miix_wlr_head_set_transform( state, - DEFAULT_OUTPUT, - SENSOR_TO_OUTPUT_ROTATION[ACCEL_ROTATION_0DEG]); + device_info.target_output, + device_info.sensor_to_output_rotation[ACCEL_ROTATION_0DEG]); last_accel_rotation = ACCEL_ROTATION_0DEG; } continue; @@ -137,11 +188,17 @@ int main(int, char**) rotation == last_accel_rotation) continue; miix_wlr_head_set_transform( - state, DEFAULT_OUTPUT, SENSOR_TO_OUTPUT_ROTATION[rotation]); + state, + device_info.target_output, + device_info.sensor_to_output_rotation[rotation]); last_accel_rotation = rotation; } - accel_stop_monitor(monitor); - destroy_detector(base_station_detector); - miix_wlr_cleanup(state); + if (device_info.screen_rotation_supported) { + accel_stop_monitor(monitor); + miix_wlr_cleanup(state); + } + + if (device_info.basestation_detection_supported) + destroy_detector(base_station_detector); }