15113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright/*
25113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * Copyright (C) 2015 The Android Open Source Project
35113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright *
45113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * Licensed under the Apache License, Version 2.0 (the "License");
55113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * you may not use this file except in compliance with the License.
65113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * You may obtain a copy of the License at
75113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright *
85113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright *      http://www.apache.org/licenses/LICENSE-2.0
95113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright *
105113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * Unless required by applicable law or agreed to in writing, software
115113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * distributed under the License is distributed on an "AS IS" BASIS,
125113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * See the License for the specific language governing permissions and
145113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright * limitations under the License.
155113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright */
165113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
175113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright#define LOG_TAG "EvdevModule"
18fdd4d81ca191ae6096e94be1bf98975d17766b1aMichael Wright//#define LOG_NDEBUG 0
195113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
2073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include <memory>
2173475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include <string>
2273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include <thread>
2373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
245113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright#include <assert.h>
255113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright#include <hardware/hardware.h>
265113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright#include <hardware/input.h>
275113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
2873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include <utils/Log.h>
2973475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
3073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include "InputHub.h"
3173475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include "InputDeviceManager.h"
3273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn#include "InputHost.h"
3373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
3473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournnamespace android {
3573475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
3673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournstatic const char kDevInput[] = "/dev/input";
3773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
3873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournclass EvdevModule {
3973475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournpublic:
404f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    // Takes ownership of the InputHostInterface
414f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    explicit EvdevModule(InputHostInterface* inputHost);
4273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
4373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    void init();
4473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    void notifyReport(input_report_t* r);
4573475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
4673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournprivate:
4773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    void loop();
4873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
494f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    std::unique_ptr<InputHostInterface> mInputHost;
5073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    std::shared_ptr<InputDeviceManager> mDeviceManager;
51c929d2509530b0262681c8e6619609f44bfceea4Tim Kilbourn    std::unique_ptr<InputHub> mInputHub;
5273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    std::thread mPollThread;
5373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn};
5473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
55c929d2509530b0262681c8e6619609f44bfceea4Tim Kilbournstatic std::unique_ptr<EvdevModule> gEvdevModule;
5673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
574f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim KilbournEvdevModule::EvdevModule(InputHostInterface* inputHost) :
5873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    mInputHost(inputHost),
594f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    mDeviceManager(std::make_shared<InputDeviceManager>(mInputHost.get())),
60c929d2509530b0262681c8e6619609f44bfceea4Tim Kilbourn    mInputHub(std::make_unique<InputHub>(mDeviceManager)) {}
6173475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
6273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournvoid EvdevModule::init() {
6373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    ALOGV("%s", __func__);
6473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
6573475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    mInputHub->registerDevicePath(kDevInput);
6673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    mPollThread = std::thread(&EvdevModule::loop, this);
6773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn}
6873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
6973475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournvoid EvdevModule::notifyReport(input_report_t* r) {
7073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    ALOGV("%s", __func__);
7173475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
7273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    // notifyReport() will be called from an arbitrary thread within the input
7373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    // host. Since InputHub is not threadsafe, this is how I expect this to
7473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    // work:
7573475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    //   * notifyReport() will queue up the output report in the EvdevModule and
7673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    //     call wake() on the InputHub.
7773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    //   * In the main loop thread, after returning from poll(), the queue will
7873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    //     be processed with any pending work.
7973475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn}
8073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
8173475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournvoid EvdevModule::loop() {
8273475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    ALOGV("%s", __func__);
8373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    for (;;) {
8473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn        mInputHub->poll();
8573475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn
8673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn        // TODO: process any pending work, like notify reports
8773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    }
8873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn}
895113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
905113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wrightextern "C" {
915113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
925113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wrightstatic int dummy_open(const hw_module_t __unused *module, const char __unused *id,
9373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn        hw_device_t __unused **device) {
9473475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    ALOGW("open not implemented in the input HAL!");
955113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    return 0;
965113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright}
975113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
985113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wrightstatic void input_init(const input_module_t* module,
995113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        input_host_t* host, input_host_callbacks_t cb) {
10073475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    LOG_ALWAYS_FATAL_IF(strcmp(module->common.id, INPUT_HARDWARE_MODULE_ID) != 0);
1014f3145d75f5dfc87f07f8ddf6143ba77966f35e4Tim Kilbourn    auto inputHost = new InputHost(host, cb);
102c929d2509530b0262681c8e6619609f44bfceea4Tim Kilbourn    gEvdevModule = std::make_unique<EvdevModule>(inputHost);
10373475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    gEvdevModule->init();
1045113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright}
1055113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
10673475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbournstatic void input_notify_report(const input_module_t* module, input_report_t* r) {
10773475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    LOG_ALWAYS_FATAL_IF(strcmp(module->common.id, INPUT_HARDWARE_MODULE_ID) != 0);
10873475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    LOG_ALWAYS_FATAL_IF(gEvdevModule == nullptr);
10973475a4eb2cebf06f965c58e015d06c333e71e61Tim Kilbourn    gEvdevModule->notifyReport(r);
1105113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright}
1115113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
1125113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wrightstatic struct hw_module_methods_t input_module_methods = {
1135113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    .open = dummy_open,
1145113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright};
1155113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
1165113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wrightinput_module_t HAL_MODULE_INFO_SYM = {
1175113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    .common = {
1185113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .tag                = HARDWARE_MODULE_TAG,
1195113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .module_api_version = INPUT_MODULE_API_VERSION_1_0,
1205113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .hal_api_version    = HARDWARE_HAL_API_VERSION,
1215113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .id                 = INPUT_HARDWARE_MODULE_ID,
1225113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .name               = "Input evdev HAL",
1235113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .author             = "The Android Open Source Project",
1245113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .methods            = &input_module_methods,
1255113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .dso                = NULL,
1265113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright        .reserved           = {0},
1275113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    },
1285113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
1295113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    .init = input_init,
1305113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright    .notify_report = input_notify_report,
1315113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright};
1325113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
1335113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright}  // extern "C"
1345113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright
1355113aff7e2a8540cc3f6364b8c730f853784e2ffMichael Wright}  // namespace input
136