From patchwork Tue Jun 16 19:45:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 4070 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 BE0D761F24 for ; Tue, 16 Jun 2020 21:45:40 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="hmXbvOGd"; 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=lCwG2FumzuGu3eT7GFXMRl8Auk2TG9RkFgA5H2Mq8L0=; b=hmXbvOGdmLYr/ZnpJ6FRPkY6v/gvqJstUdkHzDZYGZRHB0s7e53Cbev035pzdwcb+14+ BUwY0rNsW8JA5/fYzTJXGKxx9ClqOJBs7U8dTSb2RMbxln4Ek27TG0yyIVAuB8e0uMSl4o 9OH7hLnSSfd4s/IVxWQzqopr0Fwv4Ij+M= Received: by filterdrecv-p3mdw1-6f5df8956d-w9s4g with SMTP id filterdrecv-p3mdw1-6f5df8956d-w9s4g-18-5EE92163-16 2020-06-16 19:45:39.386303073 +0000 UTC m=+1121510.399594273 Received: from mail.uajain.com (unknown) by ismtpd0005p1maa1.sendgrid.net (SG) with ESMTP id QyotJ4fZRr-pQjWE0Cl0yw Tue, 16 Jun 2020 19:45:39.001 +0000 (UTC) From: Umang Jain Date: Tue, 16 Jun 2020 19:45:39 +0000 (UTC) Message-Id: <20200616194523.23268-7-email@uajain.com> In-Reply-To: <20200616194523.23268-1-email@uajain.com> References: <20200616194523.23268-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcaThFi/Xwo9wPYVdHfbcDxgDhEYNc+7SkskSbO1EHFmIdV6ojG+6PuxutfExZlOvl4kTrL4qFnq5eCS54j8tF04jqQRrY1+pfmLUtMAin6uKCH0BMzEEoFSmw0kl7IbDAOUEh2K/XQijoa/iZfsBL26jtIY3Bc4dln3BQiUPM79vaP4fzoGgIC4PfS08NTVsaqjI+oyqQyWliBlsPBwR+hA== To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com, libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH v5 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: Tue, 16 Jun 2020 19:45:41 -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 | 128 +++++++++++++++++++++++++++++++++++++++ test/meson.build | 1 + 2 files changed, 129 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..6a94535 --- /dev/null +++ b/test/hotplug-cameras.cpp @@ -0,0 +1,128 @@ +/* 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_) { + std::cout << "Camera unplug not detected" << std::endl; + 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_) { + std::cout << "Camera plug not detected" << std::endl; + 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'],