From patchwork Fri Sep 18 07:59:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 28330 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6EA66C335F for ; Fri, 18 Sep 2026 08:08:10 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EEAAC6849B; Fri, 18 Sep 2026 10:08:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="pxWVWZFm"; dkim-atps=neutral Received: from mail-wr2-x10.google.com (mail-wr2-x10.google.com [IPv6:2a00:1450:4864:30::10]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7A10568712 for ; Fri, 18 Sep 2026 10:07:56 +0200 (CEST) Received: by mail-wr2-x10.google.com with SMTP id ffacd0b85a97d-484399babcaso57297f8f.0 for ; Fri, 18 Sep 2026 01:07:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1789718876; x=1790323676; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3a6X9cuXND1R7NoyBs8TDwFSx68X5NaB1JmGtl9PbSo=; b=pxWVWZFmqODXoUwh/qqcCFtobN3UWYcdll0+h9nNicSO849BZ87fOByHwRnN1g7gr9 G/GB4O7Uf9VWClHsE2F6h6ZqfphW40HZchz2goij9qPKMZ1DP1cEXYrO9xlJ1Efj9g5/ NxHGLUQl1OzRAMogmeI7ezkevhvfM6Rdj8QRdYF+8jc7E4RKHGcDMLQSLhoRhawAuucA y7AgZYN3vmGoh2Eu5k4RS2aHa0WUO5O9aw2seOCAVFjrCgm3lqB/lhs+Xlk5ylJzH9QZ Ncr96uVBRyYI7aOkYIO1ix6j5yelCnF7YhxBVtGQvQpPXfYNcgVstVJ++H92icsaW6IF srVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789718876; x=1790323676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=3a6X9cuXND1R7NoyBs8TDwFSx68X5NaB1JmGtl9PbSo=; b=VcmkZHBaWYVLi+yQdjO9r5NxO+vHPY23uFoiggXNj02VlY7ml+HOsJ1DzCP89ll72A awHh6kDyYOu8mWLNUicfk3KDL57PobLl0OdM0DhPnuXIUzTQUqv1SfhhaKgEDYDeskg2 4EqErcK9KOJ8R8nB+bZqCU5AM2sMuAU4ZMIowXn630qDw/Xej5uNXhzneqlq4O/HzW2s 1MdGuB0ts3/ByYNCwUU5OA2brO649wL8moyXBF9YVlqIZpuD36XPKaUkMMRzM7i5AFM0 kvgBFWjpjj5caXBqaoOqa04TmCgOqMY1/ZpwX6fvdZLDBcVbx05odC6r2qA0ytWVRn8r l4pw== X-Gm-Message-State: AFuF++nVK7T4YlIxE+fhvYnOProH6qk0n8FDVmwhV9pubw5J10Sfo77X wAolIdMbOc76cjHBWDSV9voyLfIW4Wo/UROahoOerQsTw8TjbPT1LpzqjPdOsmQL3MfVWmlYIBt yApVPjkk= X-Gm-Gg: AYBFou3c6w1mwGqBdYWX5a3FFJCiqfET1CT4ISEWjsDHJrGdJNLQ7L2L9KoLcL7OqH7 P8f0ii32Zi0AMMYX9QmB/ikOk5pj5yyYRUfLjFTKFvgobLqJ8oQfZ5BpaiHpxP9xKOx8TVlPJp3 G4Ii3lvpDAkzPv9fOdqNNe6Ijjy2FhW0Fd0w16rsop52RkmmhoLMeO86lS+F1Q95GRScQSYdllZ HlvcULBwjjOkPFp3tka98nTw9YbRK476dlJmkmA5fUIOgdq86uiN/7xXMGM1y1Efmw1RFpMqD9W JfKkMfTxnUo8YsicrR3zZuLFUjXh9sYJW7wbj+IeVfo+IclCcGLEfxEJyfZyqZyYueBJKmmsWXP AXoJer+lArG5tC/zQRaEttSEj8vhTMVymtvlTrwdsdTjYi9ggZX67j09sZAJrkm+x3pAku/OdA/ MspTis556a32Hz1z7IyW0RkUDISLlojH8OfN+7W1O1SZF4YSIAIm5+6WPE6DEfIE5x2BKozhcva peWGebHrYMyZYyizw51nQp4lyXLZ7i2oeSFSUhqGU1BghAZw4sXPF33F7EjnZoQBeY28GXFJNsC muglU9gfVNOZn0LqoIIEkAj+la8BTIMzdaRdAB4wySOJb9cc//D3cTVv3rOVjFVlwp6aSowdywc zWVfpfndAWS4NQnwnuCI4713Ad6sey8/ZFS3ojyuFLDp9pw== X-Received: by 2002:a05:6000:400e:b0:487:fa3:7630 with SMTP id ffacd0b85a97d-4871faae24cmr1315832f8f.6.1789718875913; Fri, 18 Sep 2026 01:07:55 -0700 (PDT) Received: from naush-dell.pitowers.org ([2a00:1098:3142:1f:45e3:df8b:2b18:6253]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-487203f077fsm1742230f8f.26.2026.09.18.01.07.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 01:07:55 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Cc: Naushir Patuck Subject: [RFC PATCH v1 18/20] pipeline: uvcvideo: Factor out camera ID generation Date: Fri, 18 Sep 2026 08:59:56 +0100 Message-ID: <20260918080734.1228227-19-naush@raspberrypi.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918080734.1228227-1-naush@raspberrypi.com> References: <20260918080734.1228227-1-naush@raspberrypi.com> MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extract the camera ID computation from UVCCameraData::generateId() into a helper taking the sysfs path of the device backing the video node. The path is available from the media entity device numbers without opening the video device, which will allow generating the same ID when surveying cameras at enumeration time. This will be used in a subsequent commit when adding the camera survey mechanism to the uvcvideo pipeline handler. Signed-off-by: Naushir Patuck --- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 127 ++++++++++--------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 4b09bd6e2f7c..5fa1bdb0ff0e 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -129,6 +129,72 @@ std::optional v4l2ToExposureMode(int32_t x) } } +/* + * Generate the camera ID from the sysfs path of the UVC device video node. The + * path is derived from the device numbers of the media entity, so the ID can be + * generated without opening the video device. + */ +std::string generateIdFromPath(const std::string &path) +{ + /* Create a controller ID from first device described in firmware. */ + std::string controllerId; + std::string searchPath = path; + while (true) { + std::string::size_type pos = searchPath.rfind('/'); + if (pos <= 1) { + LOG(UVC, Error) << "Can not find controller ID"; + return {}; + } + + searchPath = searchPath.substr(0, pos); + + controllerId = sysfs::firmwareNodePath(searchPath); + if (!controllerId.empty()) + break; + } + + /* + * Create a USB ID from the device path which has the known format: + * + * path = bus, "-", ports, ":", config, ".", interface ; + * bus = number ; + * ports = port, [ ".", ports ] ; + * port = number ; + * config = number ; + * interface = number ; + * + * Example: 3-2.4:1.0 + * + * The bus is not guaranteed to be stable and needs to be stripped from + * the USB ID. The final USB ID is built up of the ports, config and + * interface properties. + * + * Example 2.4:1.0. + */ + std::string usbId = utils::basename(path.c_str()); + usbId = usbId.substr(usbId.find('-') + 1); + + /* Creata a device ID from the USB devices vendor and product ID. */ + std::string deviceId; + for (const char *name : { "idVendor", "idProduct" }) { + std::ifstream file(path + "/../" + name); + + if (!file.is_open()) + return {}; + + std::string value; + std::getline(file, value); + file.close(); + + if (!deviceId.empty()) + deviceId += ":"; + + deviceId += value; + } + + return controllerId + "-" + usbId + "-" + deviceId; +} + } /* namespace */ UVCCameraConfiguration::UVCCameraConfiguration(UVCCameraData *data) @@ -628,66 +694,9 @@ int UVCCameraData::init(std::shared_ptr media) bool UVCCameraData::generateId() { - const std::string path = video_->devicePath(); + id_ = generateIdFromPath(video_->devicePath()); - /* Create a controller ID from first device described in firmware. */ - std::string controllerId; - std::string searchPath = path; - while (true) { - std::string::size_type pos = searchPath.rfind('/'); - if (pos <= 1) { - LOG(UVC, Error) << "Can not find controller ID"; - return false; - } - - searchPath = searchPath.substr(0, pos); - - controllerId = sysfs::firmwareNodePath(searchPath); - if (!controllerId.empty()) - break; - } - - /* - * Create a USB ID from the device path which has the known format: - * - * path = bus, "-", ports, ":", config, ".", interface ; - * bus = number ; - * ports = port, [ ".", ports ] ; - * port = number ; - * config = number ; - * interface = number ; - * - * Example: 3-2.4:1.0 - * - * The bus is not guaranteed to be stable and needs to be stripped from - * the USB ID. The final USB ID is built up of the ports, config and - * interface properties. - * - * Example 2.4:1.0. - */ - std::string usbId = utils::basename(path.c_str()); - usbId = usbId.substr(usbId.find('-') + 1); - - /* Creata a device ID from the USB devices vendor and product ID. */ - std::string deviceId; - for (const char *name : { "idVendor", "idProduct" }) { - std::ifstream file(path + "/../" + name); - - if (!file.is_open()) - return false; - - std::string value; - std::getline(file, value); - file.close(); - - if (!deviceId.empty()) - deviceId += ":"; - - deviceId += value; - } - - id_ = controllerId + "-" + usbId + "-" + deviceId; - return true; + return !id_.empty(); } void UVCCameraData::addControl(uint32_t cid, const ControlInfo &v4l2Info,