From patchwork Thu Jun 11 17:16:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 4030 Return-Path: Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 51BAC61167 for ; Thu, 11 Jun 2020 19:16:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="MLvjpl9k"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=BemP8mCiSuDiWTKrP7yL6afMkUnpjFUGlYIFEVEdddU=; b=MLvjpl9kjlza2Iy4nM/mQQ483uKT6+qClWBfu+oVNc50PH3WB9zKTVTnAucw5Xr9NBDL D6tqouVnW5bQATFqowVniHR6nCEytdnX3lmj79v/px3JVVBmpMma9efJr6i3YN8rVA5thl Zqb3tLiVTmUgVcSuuoZconf7Wkw8YVWwk= Received: by filterdrecv-p3iad2-784dbb6bd8-hcng7 with SMTP id filterdrecv-p3iad2-784dbb6bd8-hcng7-18-5EE266D7-DD 2020-06-11 17:16:08.22047431 +0000 UTC m=+680961.308968930 Received: from mail.uajain.com (unknown) by ismtpd0008p1maa1.sendgrid.net (SG) with ESMTP id Pfb7fKVHRxi6I5sRD3YkMQ Thu, 11 Jun 2020 17:16:07.475 +0000 (UTC) From: Umang Jain Date: Thu, 11 Jun 2020 17:16:08 +0000 (UTC) Message-Id: <20200611171528.9381-7-email@uajain.com> In-Reply-To: <20200611171528.9381-1-email@uajain.com> References: <20200611171528.9381-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcYDswUgqLHty1lirORaEntR95UyLLITGvBSHaUC4UjCvx2dCMfy3hTqgrHZ5ipiSUrCjpIrCCy7Qh//02WzlWEIfZvUgptFn09BhgLNaxQw8M8wHM6Zp0mHT8kaWM5v4ceJLBZ4db5ezZkpdmTwO67bGgf7EsIAJ9theFlLxjT8ZwRScRPCXYC2IVBPZPL4CF0yO7OkTG0mj+2f+XG5on3A== To: laurent.pinchart@ideasonboard.com, libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v4 6/6] tests: Introduce hotplug hot-unplug unit test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jun 2020 17:16:09 -0000 This test checks the code-paths for camera's hotplugged and unplugged support. It is based on bind/unbind of a UVC device from sysfs. Hence, this test requires root permissions to run and should have at least one already bound UVC device present in the system. Signed-off-by: Umang Jain Reviewed-by: Laurent Pinchart --- test/hotplug-cameras.cpp | 124 +++++++++++++++++++++++++++++++++++++++ test/meson.build | 1 + 2 files changed, 125 insertions(+) create mode 100644 test/hotplug-cameras.cpp diff --git a/test/hotplug-cameras.cpp b/test/hotplug-cameras.cpp new file mode 100644 index 0000000..07500fc --- /dev/null +++ b/test/hotplug-cameras.cpp @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Umang Jain + * + * hotplug-cameras.cpp - Test cameraAdded/cameraRemoved signals in CameraManager + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "libcamera/internal/file.h" +#include "libcamera/internal/thread.h" + +#include "test.h" + +using namespace libcamera; + +class HotplugTest : public Test +{ +protected: + void cameraAddedHandler(std::shared_ptr cam) + { + cameraAdded_ = true; + } + + void cameraRemovedHandler(std::shared_ptr cam) + { + cameraRemoved_ = true; + } + + int init() + { + if (!File::exists("/sys/module/uvcvideo")) { + std::cout << "uvcvideo driver is not loaded, skipping" << std::endl; + return TestSkip; + } + + if (geteuid() != 0) { + std::cout << "This test requires root permissions, skipping" << std::endl; + return TestSkip; + } + + cm_ = new CameraManager(); + if (cm_->start()) { + std::cout << "Failed to start camera manager" << std::endl; + return TestFail; + } + + cameraAdded_ = false; + cameraRemoved_ = false; + + cm_->cameraAdded.connect(this, &HotplugTest::cameraAddedHandler); + cm_->cameraRemoved.connect(this, &HotplugTest::cameraRemovedHandler); + + return 0; + } + + int run() + { + DIR *dir; + struct dirent *dirent; + std::string uvcDeviceDir; + + dir = opendir(uvcDriverDir_.c_str()); + /* Find a UVC device directory, which we can bind/unbind. */ + while ((dirent = readdir(dir)) != nullptr) { + if (!File::exists(uvcDriverDir_ + dirent->d_name + "/video4linux")) + continue; + + uvcDeviceDir = dirent->d_name; + break; + } + closedir(dir); + + /* If no UVC device found, skip the test. */ + if (uvcDeviceDir.empty()) + return TestSkip; + + /* Unbind a camera and process events. */ + std::ofstream(uvcDriverDir_ + "unbind", std::ios::binary) + << uvcDeviceDir; + Timer timer; + timer.start(1000); + while (timer.isRunning() && !cameraRemoved_) + Thread::current()->eventDispatcher()->processEvents(); + if (!cameraRemoved_) + return TestFail; + + /* Bind the camera again and process events. */ + std::ofstream(uvcDriverDir_ + "bind", std::ios::binary) + << uvcDeviceDir; + timer.start(1000); + while (timer.isRunning() && !cameraAdded_) + Thread::current()->eventDispatcher()->processEvents(); + if (!cameraAdded_) + return TestFail; + + return TestPass; + } + + void cleanup() + { + cm_->stop(); + delete cm_; + } + +private: + CameraManager *cm_; + static const std::string uvcDriverDir_; + bool cameraRemoved_; + bool cameraAdded_; +}; + +const std::string HotplugTest::uvcDriverDir_ = "/sys/bus/usb/drivers/uvcvideo/"; + +TEST_REGISTER(HotplugTest) diff --git a/test/meson.build b/test/meson.build index bd7da14..a868813 100644 --- a/test/meson.build +++ b/test/meson.build @@ -30,6 +30,7 @@ internal_tests = [ ['event-thread', 'event-thread.cpp'], ['file', 'file.cpp'], ['file-descriptor', 'file-descriptor.cpp'], + ['hotplug-cameras', 'hotplug-cameras.cpp'], ['message', 'message.cpp'], ['object', 'object.cpp'], ['object-invoke', 'object-invoke.cpp'],