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