Skip to content

Commit

Permalink
v4.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
EmixamPP committed Jul 4, 2022
1 parent 48d7c1a commit 0cea32a
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 144 deletions.
2 changes: 1 addition & 1 deletion AUR/git/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ provides=(linux-enable-ir-emitter)
conflicts=(linux-enable-ir-emitter chicony-ir-toggle)

makedepends=(git)
depends=(python opencv usbutils)
depends=(python opencv usbutils fmt)

install=linux-enable-ir-emitter.install

Expand Down
4 changes: 4 additions & 0 deletions AUR/git/linux-enable-ir-emitter.install
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
post_upgrade() {
post_intall
}

post_intall() {
# support update v3 to v4
if [ -f /etc/linux-enable-ir-emitter.yaml ]; then
Expand Down
4 changes: 2 additions & 2 deletions AUR/release/PKGBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Contributor: Antoine Bertin <[email protected]>

pkgname=linux-enable-ir-emitter
pkgver=4.0.0
pkgver=4.1.2
pkgrel=1
epoch=1
pkgdesc="Enables infrared cameras that are not directly enabled out-of-the box."
Expand All @@ -16,7 +16,7 @@ arch=('x86_64')
provides=(linux-enable-ir-emitter)
conflicts=(linux-enable-ir-emitter-git chicony-ir-toggle)

depends=(python opencv usbutils)
depends=(python opencv usbutils fmt)

install=linux-enable-ir-emitter.install

Expand Down
4 changes: 4 additions & 0 deletions AUR/release/linux-enable-ir-emitter.install
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
post_upgrade() {
post_intall
}

post_intall() {
# support update v3 to v4
if [ -f /etc/linux-enable-ir-emitter.yaml ]; then
Expand Down
8 changes: 6 additions & 2 deletions COPR/linux-enable-ir-emitter.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%global debug_package %{nil}

Name: linux-enable-ir-emitter
Version: 4.0.0
Version: 4.1.2
Release: 1%{?dist}
Summary: Enables infrared cameras that are not directly enabled out-of-the box
URL: https://github.com/EmixamPP/%{name}
Expand Down Expand Up @@ -71,7 +71,7 @@ fi
if [ "$1" -eq 0 ]; then
# remove SeLinux permission
which semanage &> /dev/null
if [ "$?" -eq 0 ] && [ "$1" -eq 0 ]; then
if [ "$?" -eq 0 ]; then
semanage fcontext -d %{_exec_prefix}/lib/%{name}/driver/execute-driver
semanage fcontext -d %{_exec_prefix}/lib/%{name}/driver/driver-generator
fi
Expand All @@ -90,6 +90,10 @@ if [ "$1" -eq 0 ]; then
fi

%changelog
* Mon Jul 4 2022 Maxime Dirksen <[email protected]> - 4.1.2-1
- Asynchronous camera triggering
- Fix camera triggering issue
- Fix device symlink boot service side effect
* Sat Jun 19 2022 Maxime Dirksen <[email protected]> - 4.0.0-1
- Rework, optimization and improvement of driver generation
- Remove manual configuration commands
Expand Down
8 changes: 8 additions & 0 deletions PPA/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
linux-enable-ir-emitter (4.1.2) jammy; urgency=medium

* Asynchronous camera triggering
* Fix camera triggering issue
* Fix device symlink boot service side effect

-- Maxime Dirksen <[email protected]> Mon, 4 July 2022 12:00:00 +0200

linux-enable-ir-emitter (4.0.0) impish; urgency=medium

* Rework, optimization and improvement of driver generation
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ You can easily uninstall the software by executing `sudo bash installer.sh unins
## How to enable your infrared emitter ?
1. Ensure to not use the camera during the execution.
2. Be patient, do not kill the process, and whatever the reason.
3. Be aware, you will have to look at the ir emitter.
4. Execute `sudo linux-enable-ir-emitter configure`. You can specify your infrared camera with the option `-d /dev/videoX`, by default it is /dev/video2.
5. Answer to the asked questions.
3. Execute `sudo linux-enable-ir-emitter configure`. You can specify your infrared camera with the option `-d /dev/videoX`, by default it is /dev/video2.
4. Answer to the asked questions.

If you like the project, do not hesitate to star the repository to support me, thank you !

Expand Down
54 changes: 16 additions & 38 deletions sources/Systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,28 @@
from configparser import ConfigParser
from typing import List

from globals import SYSTEMD_PATH, UDEV_RULE_PATH, SYSTEMD_NAME
from globals import SYSTEMD_PATH, UDEV_RULE_PATH, SYSTEMD_NAME, get_kernels, get_index


"""DOCUMENTATION
- https://www.freedesktop.org/software/systemd/man/systemd.unit.html
info 1: systemd service type
info 2: systemctl exit code
info 3: systemd service dependencies
- https://github.com/EmixamPP/linux-enable-ir-emitter/issues/1
info 1: systemd wait for /dev/video
info 2: systemd service dependencies
- https://stackoverflow.com/questions/47630139/camera-dev-video0-dependencies-in-systemd-service-ubuntu-16-04
info 1: modprobe uvcvideo command
- https://wiki.archlinux.org/title/udev
info 1: udev rule run script
"""


def get_vid(device: str):
"""Get the vendor id of the camera device
Args:
device: the infrared camera '/dev/videoX'
Returns:
str: vendor id
"""
return subprocess.check_output("udevadm info {} | grep -oP 'E: ID_VENDOR_ID=\\K.*'".format(device), shell=True).decode("utf-8").strip()


def get_pid(device: str):
"""Get the product id of the camera device
Args:
device: the infrared camera '/dev/videoX'
Returns:
str: product id
"""
return subprocess.check_output("udevadm info {} | grep -oP 'E: ID_MODEL_ID=\\K.*'".format(device), shell=True).decode("utf-8").strip()


class Systemd:
"""Manage the boot service of linux-enable-ir-emitter"""
def __init__(self, devices: List[str]) -> None:
"""Create a boot service for run the drivers
Args:
devices : devices for which a driver will be run
"""
self.devices = devices

@staticmethod
Expand Down Expand Up @@ -82,7 +60,7 @@ def enable(self) -> int:
if exit_code:
logging.error("Error with the udev boot service.")

exit_code = subprocess.run(["systemctl", "enable", "--now", SYSTEMD_NAME], capture_output=True).returncode
exit_code = subprocess.run(["systemctl", "enable", "--now", SYSTEMD_NAME], capture_output=True).returncode
if exit_code:
logging.error("Error with the systemd boot service.")

Expand Down Expand Up @@ -113,11 +91,11 @@ def _create_udev(self) -> None:
"""Create the rule file at UDEV_RULE_PATH"""
with open(UDEV_RULE_PATH, 'w') as rule_file:
for device in self.devices:
vid = get_vid(device)
pid = get_pid(device)
kernels = get_kernels(device)
index = get_index(device)

rule1 = 'KERNEL=="{}", SYMLINK="{}", TAG+="systemd"'.format(device[5:], device[5:])
rule2 = 'ACTION=="add|change", ATTRS{idVendor}=="%s", ATTRS{idProduct}=="%s", RUN+="/usr/bin/linux-enable-ir-emitter run"' %(vid, pid)
rule1 = 'ACTION=="add|change", KERNELS==%s, ATTR{index}==%s, RUN+="/usr/bin/linux-enable-ir-emitter run"'%(kernels, index)
rule2 = 'KERNELS==%s, ATTR{index}==%s, TAG+="systemd"'%(kernels, index) # create systemd .device for all device

rule_file.write(rule1 + "\n")
rule_file.write(rule2 + "\n")
Expand All @@ -135,10 +113,10 @@ def _initialize_systemd(self) -> ConfigParser:
service["Unit"]["Description"] = "enable the infrared emitter"
service["Unit"]["Requires"] = ""
service["Unit"]["After"] = "multi-user.target suspend.target hybrid-sleep.target hibernate.target suspend-then-hibernate.target"
for device in self.devices:
target = " dev-{}.device".format(device[5:])
service["Unit"]["After"] += target
service["Unit"]["Requires"] += target
for device in self.devices: # wait for all device
dev = " dev-{}.device".format(device[5:])
service["Unit"]["After"] += dev
service["Unit"]["Requires"] += dev

service["Service"] = {}
service["Service"]["Type"] = "oneshot"
Expand Down
2 changes: 0 additions & 2 deletions sources/command/boot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ def execute(boot_status: str) -> NoReturn:
args:
boot_status: "enable" or "disable" or "status"
device: path to the infrared camera, /dev/videoX
None to execute all driver.
Raises:
Exception: boot status arg can only be equal to
Expand Down
6 changes: 3 additions & 3 deletions sources/command/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ def execute(device: str, neg_answer_limit: int) -> NoReturn:
"""Find a driver for the infrared camera
Args:
device: the infrared camera '/dev/videoX'
device: path to the infrared camera, /dev/videoX
neg_answer_limit: after k negative answer the pattern will be skiped. Use 256 for unlimited
"""
log_level = int(logging.getLogger().level == logging.DEBUG)
driver_path = get_driver_path(device)
logging.info("Ensure to not use the camera during the execution.")
logging.info("Warning to do not kill the process !")

log_level = int(logging.getLogger().level == logging.DEBUG)
driver_path = get_driver_path(device)
exit_code = subprocess.call([DRIVER_GENERATOR_PATH, device, str(neg_answer_limit), driver_path, str(log_level)])

if exit_code != ExitCode.SUCCESS:
Expand Down
2 changes: 1 addition & 1 deletion sources/command/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

def execute(device: str) -> NoReturn:
"""Remove the driver associated to a device,
without causing error if the driver deos not exists
without causing error if the driver does not exists
Args:
device: path to the infrared camera, /dev/videoX
Expand Down
87 changes: 43 additions & 44 deletions sources/driver/driver-generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
info 1: selector is on 8 bits and since the manufacturer does not provide a driver, it is impossible to know which value it is.
***/

#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
Expand All @@ -15,7 +16,7 @@
#include <vector>
using namespace std;

// opencv (for triger_camera())
// opencv (used in is_emitter_working())
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wconversion"
Expand All @@ -31,8 +32,7 @@ using namespace cv::utils::logging;
#include "executequery.h"
#include "driver.hpp"

#define EXIT_FD_ERROR 126;
constexpr int CAMERA_TRIGER_TIME = 2; // triger the camera during how many seconds
#define EXIT_FD_ERROR 126

/**
* @brief Print the control value in the standart output (without eol character)
Expand Down Expand Up @@ -86,27 +86,6 @@ inline string *shell_exec(const string cmd)
return result;
}

/**
* @brief Trigger the infrared emitter
*
* @param deviceID id of the camera device
*
* @return 1 if unable to open the device, otherwise 0
*/
inline int triger_camera(const int deviceID)
{
VideoCapture cap;
cap.open(deviceID);
if (!cap.isOpened())
{
cerr << "CRITICAL: Cannot access to /dev/video" << deviceID << endl;
return 1;
}
this_thread::sleep_for(chrono::seconds(CAMERA_TRIGER_TIME));
cap.release();
return 0;
}

/**
* @brief Trigger the infrared emitter and ask the question:
* "Did you see the ir emitter flashing (not just turn on) ? Yes/No ? "
Expand All @@ -117,17 +96,23 @@ inline int triger_camera(const int deviceID)
*/
inline int is_emitter_working(const int deviceID)
{
if (triger_camera(deviceID))
VideoCapture cap(deviceID);
if (!cap.isOpened())
{
cerr << "CRITICAL: Cannot access to /dev/video" << deviceID << endl;
return 126;
}

string answer;
cout << "Did you see the ir emitter flashing (not just turn on) ? Yes/No ? ";
cout << "Is the ir emitter flashing (not just turn on) ? Yes/No ? ";
cin >> answer;
while (answer != "yes" && answer != "y" && answer != "Yes" && answer != "no" && answer != "n" && answer != "No")
{
cout << "Yes/No ? ";
cin >> answer;
}

cap.release();
return answer == "no" || answer == "n" || answer == "No";
}

Expand Down Expand Up @@ -213,6 +198,24 @@ inline void print_driver_debug(const uint8_t unit, const uint8_t selector, const
cout << endl;
}

/**
* @brief Open a file descriptor
*
* @param device device to open a fd
* @return fd or -1 if unable to open
*/
inline int open_fd(const char *device) {
errno = 0;
int fd = open(device, O_WRONLY);
if (fd < 0 || errno)
{
cerr << "CRITICAL: Cannot access to " << device << endl;
return -1;
}

return fd;
}

/**
* Generate a driver for the infrared emitter
*
Expand All @@ -237,28 +240,20 @@ int main(int, const char *argv[])
const int negAnswerLimit = atoi(argv[2]);
const char *driverFile = argv[3];
const bool debug = atoi(argv[4]);
int result;

errno = 0;
const int fd = open(device, O_WRONLY);
if (fd < 0 || errno)
{
cerr << "CRITICAL: Cannot access to " << device << endl;
return EXIT_FD_ERROR;
}

result = is_emitter_working(deviceID);
int result = is_emitter_working(deviceID);
if (!result)
{
cerr << "ERROR: Your emiter is already working, skipping the configuration." << endl;
close(fd);
return EXIT_FAILURE;
}
else if (result == 126)
{
close(fd);
else if (result == 126)
return EXIT_FD_ERROR;
}

int fd = open_fd(device);
if (fd < 0)
return EXIT_FD_ERROR;


// begin research
const vector<uint8_t> *units = get_units(device);
Expand Down Expand Up @@ -315,19 +310,23 @@ int main(int, const char *argv[])
{
result = set_uvc_query(fd, unit, selector, ctrlSize, nextCtrl);
if (!result)
{
{
close (fd);
result = is_emitter_working(deviceID);
if (!result) // found
{
close(fd);
delete units;
return write_driver(driverFile, device, unit, selector, ctrlSize, nextCtrl);
}
else if (result == 126) // if unable to test the camera, reset the control and exit
{
if (set_uvc_query(fd, unit, selector, ctrlSize, curCtrl))
print_error_reset_debug(unit, selector, curCtrl, ctrlSize);
close(fd);
delete units;
return EXIT_FD_ERROR;
}
fd = open_fd(device);
if (fd < 0) {
delete units;
return EXIT_FD_ERROR;
}
Expand Down
Loading

0 comments on commit 0cea32a

Please sign in to comment.