mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
Compare commits
No commits in common. "master" and "v1.0" have entirely different histories.
85 changed files with 850 additions and 4087 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -26,7 +26,6 @@ miracle-dhcp
|
||||||
miracle-sinkctl
|
miracle-sinkctl
|
||||||
miracle-wifictl
|
miracle-wifictl
|
||||||
miracle-wifid
|
miracle-wifid
|
||||||
miracle-uibcctl
|
|
||||||
miraclectl
|
miraclectl
|
||||||
miracled
|
miracled
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
@ -36,9 +35,3 @@ test_valgrind
|
||||||
test_wpas
|
test_wpas
|
||||||
wpa_cli
|
wpa_cli
|
||||||
wpa_supplicant
|
wpa_supplicant
|
||||||
CMakeFiles/
|
|
||||||
cmake_install.cmake
|
|
||||||
CMakeCache.txt
|
|
||||||
libmiracle-shared.a
|
|
||||||
install_manifest.txt
|
|
||||||
/build/
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
version: v1.0
|
|
||||||
name: Docker
|
|
||||||
|
|
||||||
agent:
|
|
||||||
machine:
|
|
||||||
type: e1-standard-2
|
|
||||||
os_image: ubuntu1804
|
|
||||||
|
|
||||||
global_job_config:
|
|
||||||
secrets:
|
|
||||||
- name: dockerhub
|
|
||||||
|
|
||||||
blocks:
|
|
||||||
- name: Checkout
|
|
||||||
task:
|
|
||||||
jobs:
|
|
||||||
- name: Checkout
|
|
||||||
commands:
|
|
||||||
- checkout
|
|
||||||
- name: Build
|
|
||||||
task:
|
|
||||||
jobs:
|
|
||||||
- name: Autotools
|
|
||||||
commands:
|
|
||||||
- checkout
|
|
||||||
- docker build -t autotools -f autotools.Dockerfile .
|
|
||||||
- name: Cmake
|
|
||||||
commands:
|
|
||||||
- checkout
|
|
||||||
- docker build -t cmake -f cmake.Dockerfile .
|
|
||||||
- name: meson
|
|
||||||
commands:
|
|
||||||
- checkout
|
|
||||||
- docker build -t meson -f meson.Dockerfile .
|
|
||||||
|
|
16
.travis.yml
16
.travis.yml
|
@ -1,16 +0,0 @@
|
||||||
language: c
|
|
||||||
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: autotools
|
|
||||||
script:
|
|
||||||
docker build -t autotools -f autotools.Dockerfile .
|
|
||||||
- stage: cmake
|
|
||||||
script:
|
|
||||||
docker build -t cmake -f cmake.Dockerfile .
|
|
||||||
- stage: meson
|
|
||||||
script:
|
|
||||||
docker build -t meson -f meson.Dockerfile .
|
|
|
@ -1,63 +1,28 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake
|
||||||
project(Miraclecast)
|
|
||||||
|
|
||||||
SET(PACKAGE_NAME miraclecast)
|
|
||||||
SET(PACKAGE_VERSION 1)
|
|
||||||
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake
|
|
||||||
${CMAKE_MODULE_PATH})
|
${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
|
set(CMAKE_C_FLAGS "-std=gnu11")
|
||||||
add_definitions(-D_GNU_SOURCE)
|
add_definitions(-D_GNU_SOURCE)
|
||||||
|
|
||||||
OPTION(ENABLE_SYSTEMD "Enable Systemd" ON)
|
project(Miraclecast)
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
find_package(PkgConfig)
|
|
||||||
|
|
||||||
if(ENABLE_SYSTEMD)
|
|
||||||
pkg_check_modules (SYSTEMD REQUIRED libsystemd>=213)
|
|
||||||
SET(SESSION_LIBRARIES "${SYSTEMD_LIBRARIES}")
|
|
||||||
else(ENABLE_SYSTEMD)
|
|
||||||
pkg_check_modules (ELOGIND REQUIRED libelogind>=213)
|
|
||||||
include_directories ("${ELOGIND_INCLUDEDIR}")
|
|
||||||
SET(SESSION_LIBRARIES "${ELOGIND_LIBRARIES}")
|
|
||||||
endif(ENABLE_SYSTEMD)
|
|
||||||
|
|
||||||
SET(BUILD_BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
|
|
||||||
OPTION(BUILD_ENABLE_DEBUG "Enable Debug" ON )
|
|
||||||
OPTION(RELY_UDEV "Rely in udev tag to select device" OFF )
|
|
||||||
OPTION(BUILD_TESTS "Enable TEST" ON )
|
|
||||||
OPTION(BUILD_ENABLE_CPPCHECK "Enable CPPCheck static analysis" OFF )
|
|
||||||
SET(IP_BINARY "/bin/ip" CACHE STRING "Path to ip binary")
|
|
||||||
|
|
||||||
if(BUILD_ENABLE_DEBUG)
|
|
||||||
add_definitions(-DBUILD_ENABLE_DEBUG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(SYSCONFDIR "/etc" CACHE STRING "system config dir")
|
|
||||||
set(DATADIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "shared data dir")
|
|
||||||
|
|
||||||
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
|
||||||
pkg_check_modules (UDEV REQUIRED libudev)
|
|
||||||
|
|
||||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
|
|
||||||
|
|
||||||
if(BUILD_ENABLE_CPPCHECK)
|
|
||||||
find_program(CMAKE_C_CPPCHECK NAMES cppcheck)
|
|
||||||
if (CMAKE_C_CPPCHECK)
|
|
||||||
list(
|
|
||||||
APPEND CMAKE_C_CPPCHECK
|
|
||||||
"--enable=warning"
|
|
||||||
"--inline-suppr"
|
|
||||||
"--std=c11"
|
|
||||||
"-D__SIZEOF_POINTER__=8"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(res)
|
add_subdirectory(res)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|
||||||
|
SET(BUILD_BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||||||
|
OPTION(BUILD_ENABLE_DEBUG "Enable Debug" ON )
|
||||||
|
OPTION(RELY_UDEV "Rely in udev tag to select device" OFF )
|
||||||
|
OPTION(BUILD_TESTS "Enable TEST" ON )
|
||||||
|
|
||||||
|
SET(PACKAGE_NAME miraclecast)
|
||||||
|
SET(PACKAGE_VERSION 1)
|
||||||
|
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
||||||
|
pkg_check_modules (UDEV REQUIRED libudev)
|
||||||
|
|
||||||
|
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
|
2
COPYING
2
COPYING
|
@ -8,7 +8,7 @@ This software was written by:
|
||||||
This software is licensed under the terms of the LGPL. Please see each source
|
This software is licensed under the terms of the LGPL. Please see each source
|
||||||
file for the related copyright notice and license.
|
file for the related copyright notice and license.
|
||||||
|
|
||||||
If a file does not contain a copyright notice, the following notice shall apply:
|
If a file does not contain a copright notice, the following notice shall apply:
|
||||||
|
|
||||||
MiracleCast - Wifi-Display/Miracast Implementation
|
MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
|
||||||
|
|
18
Makefile.am
18
Makefile.am
|
@ -4,21 +4,3 @@ EXTRA_DIST = README.md \
|
||||||
NEWS
|
NEWS
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
.PHONY: lcov genlcov lcov-clean
|
|
||||||
|
|
||||||
lcov:
|
|
||||||
-$(MAKE) $(AM_MAKEFLAGS) -k check
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) genlcov
|
|
||||||
|
|
||||||
# we have to massage the lcov.info file slightly to hide the effect of libtool
|
|
||||||
# placing the objects files in the .libs/ directory separate from the *.c
|
|
||||||
genlcov:
|
|
||||||
$(LTP) --directory $(top_builddir) --capture --output-file miraclecast-lcov.info --test-name GLIB_PERF --no-checksum
|
|
||||||
LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory miraclecast-lcov --title "Miraclecast Code Coverage" --legend --show-details miraclecast-lcov.info
|
|
||||||
|
|
||||||
lcov-clean:
|
|
||||||
-$(LTP) --directory $(top_builddir) -z
|
|
||||||
-rm -rf miraclecast-lcov.info miraclecast-lcov
|
|
||||||
-find -name '*.gcda' -print | xargs -Ix rm x
|
|
||||||
|
|
||||||
|
|
86
README.md
86
README.md
|
@ -1,46 +1,61 @@
|
||||||
# MiracleCast - Wifi-Display/Miracast Implementation
|
# MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
|
||||||
[](https://gitter.im/albfan/miraclecast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/albfan/miraclecast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://albfan.semaphoreci.com/projects/miraclecast)
|
|
||||||
[](https://travis-ci.org/albfan/miraclecast)
|
|
||||||
[](https://coveralls.io/github/albfan/miraclecast?branch=master)
|
|
||||||
|
|
||||||
The MiracleCast project provides software to connect external monitors to your system via Wi-Fi. It is compatible to the Wifi-Display specification also known as Miracast. MiracleCast implements the Display-Source as well as Display-Sink side.
|
The MiracleCast project provides software to connect external monitors to your system via Wi-Fi. It is compatible to the Wifi-Display specification also known as Miracast. MiracleCast implements the Display-Source as well as Display-Sink side.
|
||||||
|
|
||||||
The Display-Source side allows you to connect external displays to your system and stream local content to the device. A lot of effort is put into making this as easy as connecting external displays via HDMI. *Note: This is not implemented yet. Please see [#4](../../issues/4).*
|
The Display-Source side allows you to connect external displays to your system and stream local content to the device. A lot of effort is put into making this as easy as connecting external displays via HDMI.
|
||||||
|
|
||||||
On the other hand, the Display-Sink side allows you to create wifi-capable external displays yourself. You can use it on your embedded devices or even on full desktops to allow other systems to use your device as external display.
|
On the other hand, the Display-Sink side allows you to create wifi-capable external displays yourself. You can use it on your embedded devices or even on full desktops to allow other systems to use your device as external display.
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
The MiracleCast projects requires the following software to be installed:
|
The MiracleCast projects requires the following software to be installed:
|
||||||
- **systemd**: A system management daemon. It is used for device-management (udev), dbus management (sd-bus) and service management.
|
- **systemd**: A system management daemon. It is used for device-management (udev), dbus management (sd-bus) and service management.
|
||||||
Systemd >= 221 will work out of the box. For earlier versions systemd must be compiled with --enable-kdbus, even though kdbus isn't used, but only the independent, experimental sd-libraries.
|
Systemd must be compiled with --enable-kdbus, even though kdbus isn't used, but only the independent, experimental sd-libraries.
|
||||||
*required*: >=systemd-213
|
*required*: >=systemd-213
|
||||||
|
|
||||||
- **glib**: A utility library. Used by the current DHCP implementation. Will be removed once sd-dns gains DHCP-server capabilities.
|
- **glib**: A utility library. Used by the current DHCP implementation. Will be removed once sd-dns gains DHCP-server capabilities.
|
||||||
*required*: ~=glib2-2.38 (might work with older releases, untested..)
|
*required*: ~=glib2-2.38 (might work with older releases, untested..)
|
||||||
|
|
||||||
- **gstreamer**: MiracleCast rely on gstreamer to show cast its output. You can test if all needed is installed launching [res/test-viewer.sh](https://github.com/albfan/miraclecast/blob/master/res/test-viewer.sh)
|
|
||||||
|
|
||||||
- **wpa_supplicant**: MiracleCast spawns wpa_supplicant with a custom config.
|
|
||||||
|
|
||||||
- **P2P Wi-Fi device** Although widespread these days, there are some devices not compatible with [Wi-Fi Direct](http://en.wikipedia.org/wiki/Wi-Fi_Direct) (prior know as Wi-Fi P2P). Test yours with [res/test-hardware-capabilities.sh](https://github.com/albfan/miraclecast/blob/master/res/test-hardware-capabilities.sh)
|
|
||||||
|
|
||||||
- **check**: Test-suite for C programs. Used for optional tests of the MiracleCast code base.
|
- **check**: Test-suite for C programs. Used for optional tests of the MiracleCast code base.
|
||||||
*optional*: ~=check-0.9.11 (might work with older releases, untested..)
|
*optional*: ~=check-0.9.11 (might work with older releases, untested..)
|
||||||
|
|
||||||
|
- **gstreamer**: MiracleCast relay on gstreamer to show cast its output. You can test if all needed is installed launching [res/test-viewer.sh](https://github.com/albfan/miraclecast/blob/master/res/test-viewer.sh)
|
||||||
|
|
||||||
|
- **P2P Wi-Fi device** Although widespread this days, there are some devices not compatible with [Wi-Fi Direct](http://en.wikipedia.org/wiki/Wi-Fi_Direct) (prior know as Wi-Fi P2P). Test yours with [res/test-hardware-capabilities.sh](https://github.com/albfan/miraclecast/blob/master/res/test-hardware-capabilities.sh)
|
||||||
|
|
||||||
- copy the dbus policy **res/org.freedesktop.miracle.conf** to `/etc/dbus-1/system.d/`
|
- copy the dbus policy **res/org.freedesktop.miracle.conf** to `/etc/dbus-1/system.d/`
|
||||||
|
|
||||||
## Build and install
|
## Install
|
||||||
|
|
||||||
To compile MiracleCast, you can choose from:
|
To compile MiracleCast, you can choose from [autotools](http://en.wikipedia.org/wiki/GNU_build_system) or [cmake](http://en.wikipedia.org/wiki/CMake):
|
||||||
|
|
||||||
- [autotools](http://en.wikipedia.org/wiki/GNU_build_system)
|
Autotools:
|
||||||
- [cmake](http://en.wikipedia.org/wiki/CMake)
|
|
||||||
- [meson](http://mesonbuild.com/)
|
|
||||||
|
|
||||||
See more info on wiki [Building](https://github.com/albfan/miraclecast/wiki/Building)
|
$ ./autogen.sh
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build
|
||||||
|
$ ../configure --prefix=/usr/local #avoid --prefix for a standard install
|
||||||
|
|
||||||
|
Cmake:
|
||||||
|
|
||||||
|
$ mkdir build
|
||||||
|
$ cd build
|
||||||
|
$ cmake ..
|
||||||
|
|
||||||
|
Compile
|
||||||
|
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Test
|
||||||
|
|
||||||
|
$ make check #only with autotools by now
|
||||||
|
|
||||||
|
Install
|
||||||
|
|
||||||
|
$ sudo make install
|
||||||
|
|
||||||
## Automatic interface selection with udev
|
## Automatic interface selection with udev
|
||||||
|
|
||||||
|
@ -54,23 +69,17 @@ You can also choose the interface with `--interface` option for miracle-wifid.
|
||||||
|
|
||||||
### Ubuntu
|
### Ubuntu
|
||||||
|
|
||||||
Check your systemd version with:
|
This specific linux flavour is so hard to get miraclecast dependencies that an alternative repo was created to install systemd with dbus
|
||||||
|
|
||||||
$ systemctl --version
|
|
||||||
|
|
||||||
If you are on 221 or above your systemd has kdbus enabled.
|
|
||||||
|
|
||||||
If you are below 221, an alternative repo was created to install systemd with dbus
|
|
||||||
|
|
||||||
https://github.com/albfan/systemd-ubuntu-with-dbus
|
https://github.com/albfan/systemd-ubuntu-with-dbus
|
||||||
|
|
||||||
See there was interface changes on systemd 219, if you are below that version, use branch [systemd-219](https://github.com/albfan/miraclecast/tree/systemd-219) to compile miraclecast
|
At this time, ubuntu is on version 15.04 and systemd is stick on 219 version, use branch [systemd-219](https://github.com/albfan/miraclecast/tree/systemd-219) to compile miraclecast
|
||||||
|
|
||||||
> See specific instructions on that repo
|
> See specific instructions on that repo
|
||||||
|
|
||||||
### Arch linux
|
### Arch linux
|
||||||
|
|
||||||
Use existing [AUR package](https://aur.archlinux.org/packages/miraclecast-git/). Remember to enable kdbus to systemd-git dependency if you are below 221 systemd.
|
Use existing [AUR package](https://aur.archlinux.org/packages/miraclecast/). Remember to enable kdus to systemd-git dependency
|
||||||
|
|
||||||
$ export _systemd_git_kdbus=--enable-kdbus
|
$ export _systemd_git_kdbus=--enable-kdbus
|
||||||
|
|
||||||
|
@ -85,12 +94,15 @@ If you feel confidence enough (since systemd is the entrypoint for an OS) extrac
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
### Steps to use it as sink
|
Steps to use it as sink:
|
||||||
|
|
||||||
1. shutdown wpa_supplicant and NetworkManager
|
1. shutdown wpa_supplicant
|
||||||
|
|
||||||
$ systemctl stop NetworkManager.service
|
$ sudo kill -9 $(ps -ef | grep wpa_supplican[t] | awk '{print $2}')
|
||||||
$ systemctl stop wpa_supplicant.service
|
# now you can use `res/kill-wpa.sh`
|
||||||
|
|
||||||
|
>Remember to save your config to use with `res/normal-wifi.sh`
|
||||||
|
>it will be easily located with `ps -ef | grep wpa_supplicant` on `-c` option.
|
||||||
|
|
||||||
2. launch wifi daemon
|
2. launch wifi daemon
|
||||||
|
|
||||||
|
@ -109,7 +121,7 @@ If you feel confidence enough (since systemd is the entrypoint for an OS) extrac
|
||||||
|
|
||||||
6. See your screen device on this machine
|
6. See your screen device on this machine
|
||||||
|
|
||||||
### Steps to use it as peer
|
Steps to use it as peer:
|
||||||
|
|
||||||
1. Repeat steps 1 and 2 from "use as sink"
|
1. Repeat steps 1 and 2 from "use as sink"
|
||||||
|
|
||||||
|
@ -121,15 +133,9 @@ If you feel confidence enough (since systemd is the entrypoint for an OS) extrac
|
||||||
|
|
||||||
4. Locate them using scanning
|
4. Locate them using scanning
|
||||||
|
|
||||||
> p2p-scan
|
> psp-scan
|
||||||
|
|
||||||
5. Apart from list, or show info with peer <mac> there's nothing useful here by now. For a Q&D see [Using as peer](https://github.com/albfan/miraclecast/issues/4)
|
5. Apart from list, or show info with peer <mac> there's nothing useful here by now.
|
||||||
|
|
||||||
## UIBC
|
|
||||||
|
|
||||||
> The User Input Back Channel (UIBC) is an optional WFD feature that when implemented facilitates communication of user inputs to a User Interface, present at the WFD Sink, to the WFD Source.
|
|
||||||
|
|
||||||
To use it just add `--uibc` on `miracle-sinkctl` startup. Single mouse events and key events are implemented.
|
|
||||||
|
|
||||||
## Autocompletion
|
## Autocompletion
|
||||||
|
|
||||||
|
@ -152,4 +158,4 @@ If you have any questions, do not hesitate to contact one of the maintainers.
|
||||||
- Website: http://www.freedesktop.org/wiki/Software/miracle
|
- Website: http://www.freedesktop.org/wiki/Software/miracle
|
||||||
- Original repo: git://people.freedesktop.org/~dvdhrm/miracle
|
- Original repo: git://people.freedesktop.org/~dvdhrm/miracle
|
||||||
- Fork repo: https://github.com/albfan/miraclecast
|
- Fork repo: https://github.com/albfan/miraclecast
|
||||||
- Technical spec: https://www.wi-fi.org/file/wi-fi-display-technical-specification-v11 (free registration required)
|
|
||||||
|
|
68
autogen.sh
68
autogen.sh
|
@ -1,68 +1,2 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
autoreconf -f --install
|
||||||
set -e
|
|
||||||
|
|
||||||
oldpwd=$(pwd)
|
|
||||||
topdir=$(dirname $0)
|
|
||||||
cd $topdir
|
|
||||||
|
|
||||||
#intltoolize --force --automake
|
|
||||||
autoreconf --force --install --symlink
|
|
||||||
|
|
||||||
libdir() {
|
|
||||||
echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
args="\
|
|
||||||
--sysconfdir=/etc \
|
|
||||||
--localstatedir=/var \
|
|
||||||
--libdir=$(libdir /usr/lib) \
|
|
||||||
"
|
|
||||||
|
|
||||||
if [ -f "$topdir/.config.args" ]; then
|
|
||||||
args="$args $(cat $topdir/.config.args)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd $oldpwd
|
|
||||||
|
|
||||||
if [ "x$1" = "xc" ]; then
|
|
||||||
shift
|
|
||||||
args="$args $@"
|
|
||||||
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
|
|
||||||
elif [ "x$1" = "xg" ]; then
|
|
||||||
shift
|
|
||||||
args="$args $@"
|
|
||||||
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
|
|
||||||
elif [ "x$1" = "xa" ]; then
|
|
||||||
shift
|
|
||||||
args="$args $@"
|
|
||||||
$topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' $args
|
|
||||||
elif [ "x$1" = "xl" ]; then
|
|
||||||
shift
|
|
||||||
args="$args $@"
|
|
||||||
$topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' $args
|
|
||||||
elif [ "x$1" = "xs" ]; then
|
|
||||||
shift
|
|
||||||
args="$args $@"
|
|
||||||
scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args
|
|
||||||
scan-build make
|
|
||||||
else
|
|
||||||
cat <<EOF
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
|
||||||
Initialized build system. For a common configuration please run:
|
|
||||||
----------------------------------------------------------------
|
|
||||||
|
|
||||||
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
|
|
||||||
|
|
||||||
or run $0 with param:
|
|
||||||
|
|
||||||
- c: compilation
|
|
||||||
- g: debugging
|
|
||||||
- a: pure/const warning
|
|
||||||
- l: clang build
|
|
||||||
- s: scan-build reporting
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
FROM docker.io/albfan/miraclecast-ci
|
|
||||||
|
|
||||||
COPY . ./
|
|
||||||
|
|
||||||
RUN rm -rf build-autotools ; \
|
|
||||||
mkdir build-autotools; \
|
|
||||||
cd build-autotools; \
|
|
||||||
../autogen.sh; \
|
|
||||||
../configure; \
|
|
||||||
make; \
|
|
||||||
make check
|
|
|
@ -1,9 +0,0 @@
|
||||||
FROM docker.io/albfan/miraclecast-ci
|
|
||||||
|
|
||||||
RUN mkdir src
|
|
||||||
|
|
||||||
COPY . ./src
|
|
||||||
|
|
||||||
WORKDIR src
|
|
||||||
|
|
||||||
RUN cmake -Bbuild . && make -C build
|
|
|
@ -10,7 +10,8 @@ AM_CFLAGS = -Wall \
|
||||||
|
|
||||||
AM_CPPFLAGS = -include $(top_builddir)/config.h \
|
AM_CPPFLAGS = -include $(top_builddir)/config.h \
|
||||||
-I $(top_srcdir)/src \
|
-I $(top_srcdir)/src \
|
||||||
-I $(top_srcdir)/src/shared
|
-I $(top_srcdir)/src/shared \
|
||||||
|
'-DBUILD_BINDIR="$(bindir)"'
|
||||||
|
|
||||||
AM_LDFLAGS = -Wl,--as-needed \
|
AM_LDFLAGS = -Wl,--as-needed \
|
||||||
-Wl,--gc-sections \
|
-Wl,--gc-sections \
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
#cmakedefine ENABLE_SYSTEMD
|
#cmakedefine BUILD_ENABLE_DEBUG
|
||||||
|
|
||||||
#cmakedefine BUILD_BINDIR "@BUILD_BINDIR@"
|
#cmakedefine BUILD_BINDIR "@BUILD_BINDIR@"
|
||||||
#cmakedefine RELY_UDEV @RELY_UDEV@
|
|
||||||
#cmakedefine IP_BINARY @IP_BINARY@
|
|
||||||
|
|
||||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
|
|
||||||
|
|
120
configure.ac
120
configure.ac
|
@ -35,45 +35,17 @@ AC_PROG_AWK
|
||||||
|
|
||||||
LT_PREREQ(2.2)
|
LT_PREREQ(2.2)
|
||||||
LT_INIT
|
LT_INIT
|
||||||
LT_LIB_M
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([rely-udev],
|
AC_ARG_ENABLE([rely-udev],
|
||||||
AS_HELP_STRING([--enable-rely-udev], [Use tagged device with miraclecast]), AC_DEFINE([RELY_UDEV], [], [Rely on udev to find miraclecast device]))
|
AS_HELP_STRING([--enable-rely-udev], [Use tagged device with miraclecast]), AC_DEFINE([RELY_UDEV], [], [Rely on udev to find miraclecast device]))
|
||||||
AC_ARG_ENABLE([log-debug],
|
AC_ARG_ENABLE([log-debug],
|
||||||
AS_HELP_STRING([--disable-log-debug], [Disable log debug]), , AC_DEFINE([BUILD_ENABLE_DEBUG], [], [Enable debug log level]))
|
AS_HELP_STRING([--disable-log-debug], [Disable log debug]), , AC_DEFINE([BUILD_ENABLE_DEBUG], [], [Enable debug log level]))
|
||||||
AC_ARG_VAR(IP_BINARY, [Path for ip binary])
|
|
||||||
if test -z "$IP_BINARY"; then
|
|
||||||
IP_BINARY=/bin/ip
|
|
||||||
fi
|
|
||||||
AC_ARG_ENABLE([systemd],
|
|
||||||
AS_HELP_STRING([--disable-systemd], [Disable systemd]),
|
|
||||||
[case "${enableval}" in
|
|
||||||
yes) use_libsystemd=yes ;;
|
|
||||||
no) use_libsystemd=no ;;
|
|
||||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-systemd]) ;;
|
|
||||||
esac],
|
|
||||||
[use_libsystemd=yes])
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED([IP_BINARY], [$IP_BINARY], [Path for ip binary])
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Mandatory dependencies
|
# Mandatory dependencies
|
||||||
#
|
#
|
||||||
|
|
||||||
AS_IF([test "$use_libsystemd" = "yes"],
|
PKG_CHECK_MODULES([DEPS], [libudev libsystemd > 219])
|
||||||
[
|
PKG_CHECK_MODULES([GDHCP], [glib-2.0])
|
||||||
AC_DEFINE([ENABLE_SYSTEMD], [], [Use systemd])
|
|
||||||
m4_ifdef([PKG_CHECK_MODULES], [
|
|
||||||
PKG_CHECK_MODULES([DEPS], [libudev libsystemd > 219])
|
|
||||||
PKG_CHECK_MODULES([GLIB], [glib-2.0])
|
|
||||||
])
|
|
||||||
],
|
|
||||||
[
|
|
||||||
m4_ifdef([PKG_CHECK_MODULES], [
|
|
||||||
PKG_CHECK_MODULES([DEPS], [libudev libelogind])
|
|
||||||
PKG_CHECK_MODULES([GLIB], [glib-2.0])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(readline/readline.h,, AC_MSG_ERROR(GNU readline not found))
|
AC_CHECK_HEADERS(readline/readline.h,, AC_MSG_ERROR(GNU readline not found))
|
||||||
|
|
||||||
|
@ -82,84 +54,10 @@ AC_CHECK_HEADERS(readline/readline.h,, AC_MSG_ERROR(GNU readline not found))
|
||||||
# all tests.
|
# all tests.
|
||||||
#
|
#
|
||||||
|
|
||||||
m4_ifdef([PKG_CHECK_MODULES], [
|
PKG_CHECK_MODULES([CHECK], [check],
|
||||||
PKG_CHECK_MODULES([CHECK], [check],
|
[have_check=yes], [have_check=no])
|
||||||
[have_check=yes], [have_check=no])
|
|
||||||
])
|
|
||||||
AM_CONDITIONAL([BUILD_HAVE_CHECK], [test "x$have_check" = "xyes"])
|
AM_CONDITIONAL([BUILD_HAVE_CHECK], [test "x$have_check" = "xyes"])
|
||||||
|
|
||||||
if test "x$have_check" = "xyes"
|
|
||||||
then
|
|
||||||
|
|
||||||
dnl ************************************
|
|
||||||
dnl *** Enable lcov coverage reports ***
|
|
||||||
dnl ************************************
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(gcov,
|
|
||||||
AS_HELP_STRING([--enable-gcov],
|
|
||||||
[Enable gcov]),
|
|
||||||
[use_gcov=$enableval], [use_gcov=no])
|
|
||||||
|
|
||||||
if test "x$use_gcov" = "xyes"; then
|
|
||||||
dnl we need gcc:
|
|
||||||
if test "$GCC" != "yes"; then
|
|
||||||
AC_MSG_ERROR([GCC is required for --enable-gcov])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Check if ccache is being used
|
|
||||||
AC_CHECK_PROG(SHTOOL, shtool, shtool)
|
|
||||||
case `$SHTOOL path $CC` in
|
|
||||||
*ccache*[)] gcc_ccache=yes;;
|
|
||||||
*[)] gcc_ccache=no;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
|
|
||||||
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
ltp_version_list="1.6 1.7 1.8 1.10 1.11 1.12"
|
|
||||||
AC_CHECK_PROG(LTP, lcov, lcov)
|
|
||||||
AC_CHECK_PROG(LTP_GENHTML, genhtml, genhtml)
|
|
||||||
|
|
||||||
if test "$LTP"; then
|
|
||||||
AC_CACHE_CHECK([for ltp version], glib_cv_ltp_version, [
|
|
||||||
glib_cv_ltp_version=invalid
|
|
||||||
ltp_version=`$LTP -v 2>/dev/null | $SED -e 's/^.* //'`
|
|
||||||
for ltp_check_version in $ltp_version_list; do
|
|
||||||
if test "$ltp_version" = "$ltp_check_version"; then
|
|
||||||
glib_cv_ltp_version="$ltp_check_version (ok)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
])
|
|
||||||
else
|
|
||||||
ltp_msg="To enable code coverage reporting you must have one of the following LTP versions installed: $ltp_version_list"
|
|
||||||
AC_MSG_ERROR([$ltp_msg])
|
|
||||||
fi
|
|
||||||
|
|
||||||
case $glib_cv_ltp_version in
|
|
||||||
""|invalid[)]
|
|
||||||
ltp_msg="You must have one of the following versions of LTP: $ltp_version_list (found: $ltp_version)."
|
|
||||||
AC_MSG_ERROR([$ltp_msg])
|
|
||||||
LTP="exit 0;"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if test -z "$LTP_GENHTML"; then
|
|
||||||
AC_MSG_ERROR([Could not find genhtml from the LTP package])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_DEFINE(HAVE_GCOV, 1, [Whether you have gcov])
|
|
||||||
|
|
||||||
dnl Remove all optimization flags from CFLAGS
|
|
||||||
changequote({,})
|
|
||||||
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
|
|
||||||
changequote([,])
|
|
||||||
|
|
||||||
dnl Add the special gcc flags
|
|
||||||
CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage"
|
|
||||||
LDFLAGS="$LDFLAGS -lgcov"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
#
|
#
|
||||||
# Makefile vars
|
# Makefile vars
|
||||||
# After everything is configured, we create all makefiles.
|
# After everything is configured, we create all makefiles.
|
||||||
|
@ -172,7 +70,6 @@ AC_CONFIG_FILES([Makefile
|
||||||
src/dhcp/Makefile
|
src/dhcp/Makefile
|
||||||
src/shared/Makefile
|
src/shared/Makefile
|
||||||
src/wifi/Makefile
|
src/wifi/Makefile
|
||||||
src/uibc/Makefile
|
|
||||||
test/Makefile])
|
test/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
@ -190,15 +87,12 @@ AC_MSG_NOTICE([Build configuration:
|
||||||
bindir: $bindir
|
bindir: $bindir
|
||||||
libdir: $libdir
|
libdir: $libdir
|
||||||
includedir: $includedir
|
includedir: $includedir
|
||||||
sysconfdir: $sysconfdir
|
|
||||||
ip-binary: $IP_BINARY
|
|
||||||
|
|
||||||
Miscellaneous Options:
|
Miscellaneous Options:
|
||||||
building tests: $have_check
|
building tests: $have_check
|
||||||
code coverage: $use_gcov
|
|
||||||
rely udev: ${enable_rely_udev:-no}
|
|
||||||
|
|
||||||
Compilation
|
Compilation
|
||||||
|
mkdir build && cd build
|
||||||
"${MAKE-make}" to start compilation process
|
"${MAKE-make}" to start compilation process
|
||||||
"${MAKE-make}" check to pass test])
|
"${MAKE-make}" check to pass test])
|
||||||
else
|
else
|
||||||
|
@ -208,13 +102,11 @@ AC_MSG_NOTICE([Build configuration:
|
||||||
bindir: $bindir
|
bindir: $bindir
|
||||||
libdir: $libdir
|
libdir: $libdir
|
||||||
includedir: $includedir
|
includedir: $includedir
|
||||||
sysconfdir: $sysconfdir
|
|
||||||
ip-binary: $IP_BINARY
|
|
||||||
|
|
||||||
Miscellaneous Options:
|
Miscellaneous Options:
|
||||||
building tests: $have_check
|
building tests: $have_check
|
||||||
rely udev: ${enable_rely_udev:-no}
|
|
||||||
|
|
||||||
Compilation
|
Compilation
|
||||||
|
mkdir build && cd build
|
||||||
"${MAKE-make}" to start compilation process])
|
"${MAKE-make}" to start compilation process])
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
FROM docker.io/albfan/miraclecast-ci
|
|
||||||
|
|
||||||
COPY . ./
|
|
||||||
|
|
||||||
RUN rm -rf build-meson; \
|
|
||||||
meson build-meson; \
|
|
||||||
ninja -C build-meson
|
|
55
meson.build
55
meson.build
|
@ -1,55 +0,0 @@
|
||||||
project('Miraclecast',
|
|
||||||
'c',
|
|
||||||
version: '1',
|
|
||||||
meson_version: '>=0.39',
|
|
||||||
default_options: ['buildtype=debugoptimized', 'c_std=gnu11']
|
|
||||||
)
|
|
||||||
|
|
||||||
add_project_arguments('-D_GNU_SOURCE', language: 'c')
|
|
||||||
|
|
||||||
conf_data = configuration_data()
|
|
||||||
conf_data.set_quoted('BUILD_BINDIR',
|
|
||||||
join_paths(get_option('prefix'), get_option('bindir'))
|
|
||||||
)
|
|
||||||
conf_data.set_quoted('PACKAGE_STRING',
|
|
||||||
'@0@ @1@'.format(meson.project_name(), meson.project_version())
|
|
||||||
)
|
|
||||||
configure_file(output: 'config.h',
|
|
||||||
configuration: conf_data
|
|
||||||
)
|
|
||||||
|
|
||||||
c_compiler = meson.get_compiler('c')
|
|
||||||
readline = c_compiler.find_library('readline', required: true)
|
|
||||||
if readline.found()
|
|
||||||
add_project_arguments('-DHAVE_READLINE', language: 'c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('build-enable-debug')
|
|
||||||
add_project_arguments('-DBUILD_ENABLE_DEBUG', language: 'c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('rely-udev')
|
|
||||||
add_project_arguments('-DRELY_UDEV', language: 'c')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('enable-systemd')
|
|
||||||
add_project_arguments('-DENABLE_SYSTEMD', language: 'c')
|
|
||||||
libsystemd = dependency('libsystemd')
|
|
||||||
else
|
|
||||||
libsystemd = dependency('libelogind')
|
|
||||||
endif
|
|
||||||
|
|
||||||
add_project_arguments('-DIP_BINARY='+get_option('ip-binary'), language: 'c')
|
|
||||||
|
|
||||||
glib2 = dependency('glib-2.0')
|
|
||||||
udev = dependency('libudev')
|
|
||||||
|
|
||||||
m = c_compiler.find_library('m', required: false)
|
|
||||||
|
|
||||||
subdir('src')
|
|
||||||
subdir('res')
|
|
||||||
|
|
||||||
if get_option('build-tests')
|
|
||||||
subdir('test')
|
|
||||||
endif
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
option('build-enable-debug',
|
|
||||||
type: 'boolean',
|
|
||||||
value: true,
|
|
||||||
description: 'Enable Debug')
|
|
||||||
option('rely-udev',
|
|
||||||
type: 'boolean',
|
|
||||||
value: false,
|
|
||||||
description: 'Rely in udev tag to select device')
|
|
||||||
option('build-tests',
|
|
||||||
type: 'boolean',
|
|
||||||
value: true,
|
|
||||||
description: 'Enable TEST')
|
|
||||||
option('ip-binary',
|
|
||||||
type: 'string',
|
|
||||||
value: '/bin/ip',
|
|
||||||
description: 'Path for ip binary')
|
|
||||||
option('enable-systemd',
|
|
||||||
type: 'boolean',
|
|
||||||
value: 'true',
|
|
||||||
description: 'Enable systemd')
|
|
|
@ -1,14 +1,11 @@
|
||||||
INSTALL(
|
|
||||||
PROGRAMS miracle-gst gstplayer uibc-viewer
|
|
||||||
DESTINATION bin
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALL(
|
########### install files ###############
|
||||||
FILES org.freedesktop.miracle.conf
|
|
||||||
DESTINATION ${SYSCONFDIR}/dbus-1/system.d
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALL(
|
install(FILES miracle-gst.sh DESTINATION bin)
|
||||||
FILES miracle-wifid miracle-sinkctl miracle-wifictl
|
|
||||||
DESTINATION ${DATADIR}/bash-completion/completions
|
|
||||||
)
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#bin_SCRIPTS = miracle-gst.sh
|
||||||
|
#EXTRA_DIST = wpa.conf
|
||||||
|
|
|
@ -1,9 +1,2 @@
|
||||||
bin_SCRIPTS = miracle-gst gstplayer uibc-viewer miracle-omxplayer
|
bin_SCRIPTS = miracle-gst.sh
|
||||||
EXTRA_DIST = wpa.conf
|
EXTRA_DIST = wpa.conf
|
||||||
|
|
||||||
dbuspolicydir=$(sysconfdir)/dbus-1/system.d
|
|
||||||
dbuspolicy_DATA = org.freedesktop.miracle.conf
|
|
||||||
|
|
||||||
bashcompletiondir=${datadir}/bash-completion/completions
|
|
||||||
bashcompletion_DATA=miracle-wifid miracle-sinkctl miracle-wifictl
|
|
||||||
|
|
||||||
|
|
223
res/gstplayer
223
res/gstplayer
|
@ -1,223 +0,0 @@
|
||||||
#!/usr/bin/python3 -u
|
|
||||||
|
|
||||||
import gi
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
gi.require_version('Gst', '1.0')
|
|
||||||
gi.require_version('Gtk', '3.0')
|
|
||||||
gi.require_version('GstVideo', '1.0')
|
|
||||||
gi.require_version('GdkX11', '3.0')
|
|
||||||
|
|
||||||
from gi.repository import GObject, Gst, Gtk, Gdk, GLib
|
|
||||||
|
|
||||||
# Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
|
|
||||||
from gi.repository import GdkX11, GstVideo
|
|
||||||
|
|
||||||
GObject.threads_init()
|
|
||||||
Gst.init(None)
|
|
||||||
|
|
||||||
class Player(object):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
resolution = kwargs.get("resolution")
|
|
||||||
if resolution:
|
|
||||||
split = resolution.split("x")
|
|
||||||
self.width = int(split[0])
|
|
||||||
self.height = int(split[1])
|
|
||||||
|
|
||||||
scale = kwargs.get("scale")
|
|
||||||
if scale:
|
|
||||||
split = scale.split("x")
|
|
||||||
self.width = int(split[0])
|
|
||||||
self.height = int(split[1])
|
|
||||||
|
|
||||||
debug = kwargs.get("debug")
|
|
||||||
if debug:
|
|
||||||
Gst.debug_set_active(True)
|
|
||||||
Gst.debug_set_threshold_from_string(debug, True)
|
|
||||||
|
|
||||||
port = kwargs.get("port")
|
|
||||||
|
|
||||||
uri = kwargs.get("uri")
|
|
||||||
|
|
||||||
self.window = Gtk.Window()
|
|
||||||
self.window.set_name('gstplayer')
|
|
||||||
self.window.connect('destroy', self.quit)
|
|
||||||
|
|
||||||
title = kwargs.get("title")
|
|
||||||
if title:
|
|
||||||
self.window.set_title(title)
|
|
||||||
|
|
||||||
if hasattr(self,'width') and hasattr(self,'height'):
|
|
||||||
self.window.set_default_size(self.width, self.height)
|
|
||||||
|
|
||||||
self.drawingarea = Gtk.DrawingArea()
|
|
||||||
self.window.add(self.drawingarea)
|
|
||||||
|
|
||||||
if hasattr(self,'width') and hasattr(self,'height'):
|
|
||||||
self.drawingarea.set_size_request(self.width,self.height)
|
|
||||||
self.drawingarea.add_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.BUTTON_RELEASE_MASK)
|
|
||||||
self.drawingarea.connect('button-press-event', self.on_mouse_pressed)
|
|
||||||
self.drawingarea.connect('button-release-event', self.on_mouse_pressed)
|
|
||||||
self.drawingarea.add_events(Gdk.EventMask.KEY_PRESS_MASK)
|
|
||||||
self.window.connect('key-press-event', self.on_key_pressed)
|
|
||||||
|
|
||||||
audio = kwargs.get("audio")
|
|
||||||
|
|
||||||
self.playbin = None
|
|
||||||
|
|
||||||
#Create GStreamer pipeline
|
|
||||||
if uri is not None:
|
|
||||||
self.pipeline = Gst.Pipeline()
|
|
||||||
|
|
||||||
# Create GStreamer elements
|
|
||||||
self.playbin = Gst.ElementFactory.make('playbin', "source")
|
|
||||||
|
|
||||||
if not uri.startswith("http://") or not uri.startswith("http://") or not uri.startswith("file://"):
|
|
||||||
if not uri.startswith("/"):
|
|
||||||
import os
|
|
||||||
uri = os.path.abspath(uri)
|
|
||||||
uri = "file://"+uri
|
|
||||||
|
|
||||||
# Set properties
|
|
||||||
self.playbin.set_property('uri', uri)
|
|
||||||
|
|
||||||
|
|
||||||
# Add playbin to the pipeline
|
|
||||||
self.pipeline.add(self.playbin)
|
|
||||||
else:
|
|
||||||
gstcommand = "udpsrc port="+str(port)+" caps=\"application/x-rtp, media=video\" ! rtpjitterbuffer latency=100 ! rtpmp2tdepay ! tsdemux "
|
|
||||||
|
|
||||||
if audio:
|
|
||||||
gstcommand += "name=demuxer demuxer. "
|
|
||||||
|
|
||||||
gstcommand += "! queue max-size-buffers=0 max-size-time=0 ! h264parse ! avdec_h264 ! videoconvert ! "
|
|
||||||
|
|
||||||
if scale:
|
|
||||||
gstcommand += "videoscale method=1 ! video/x-raw,width="+str(self.width)+",height="+str(self.height)+" ! "
|
|
||||||
|
|
||||||
gstcommand += "autovideosink "
|
|
||||||
|
|
||||||
if audio:
|
|
||||||
gstcommand += "demuxer. ! queue max-size-buffers=0 max-size-time=0 ! aacparse ! avdec_aac ! audioconvert ! audioresample ! autoaudiosink "
|
|
||||||
|
|
||||||
self.pipeline = Gst.parse_launch(gstcommand)
|
|
||||||
|
|
||||||
|
|
||||||
# Create bus to get events from GStreamer pipeline
|
|
||||||
self.bus = self.pipeline.get_bus()
|
|
||||||
self.bus.add_signal_watch()
|
|
||||||
self.bus.connect('message::eos', self.on_eos)
|
|
||||||
self.bus.connect('message::error', self.on_error)
|
|
||||||
|
|
||||||
# This is needed to make the video output in our DrawingArea:
|
|
||||||
self.bus.enable_sync_message_emission()
|
|
||||||
self.bus.connect('sync-message::element', self.on_sync_message)
|
|
||||||
self.bus.connect('message', self.on_message)
|
|
||||||
|
|
||||||
self.success = False
|
|
||||||
|
|
||||||
def on_message(self, bus, message):
|
|
||||||
if self.playbin:
|
|
||||||
videoPad = self.playbin.emit("get-video-pad", 0)
|
|
||||||
if videoPad and not self.success:
|
|
||||||
videoPadCapabilities = videoPad.get_current_caps()
|
|
||||||
if videoPadCapabilities:
|
|
||||||
(self.success, self.videoWidth) = \
|
|
||||||
videoPadCapabilities.get_structure(0).get_int("width")
|
|
||||||
(self.success, self.videoHeight) = \
|
|
||||||
videoPadCapabilities.get_structure(0).get_int("height")
|
|
||||||
if self.success:
|
|
||||||
print("{0} {1}".format(self.videoWidth, self.videoHeight))
|
|
||||||
self.drawingarea.set_size_request(self.videoWidth, self.videoHeight)
|
|
||||||
|
|
||||||
def on_mouse_pressed(self, widget, event):
|
|
||||||
#<type>,<count>,<id>,<x>,<y>
|
|
||||||
if event.type == Gdk.EventType.BUTTON_PRESS:
|
|
||||||
type = 0
|
|
||||||
else:
|
|
||||||
type = 1
|
|
||||||
|
|
||||||
width = self.drawingarea.get_allocation().width
|
|
||||||
height = self.drawingarea.get_allocation().height
|
|
||||||
half_area_width = width / 2
|
|
||||||
half_area_height = height / 2
|
|
||||||
|
|
||||||
half_def_width = self.width / 2
|
|
||||||
half_def_height = self.height / 2
|
|
||||||
|
|
||||||
min_hor_pos = half_area_width - half_def_width
|
|
||||||
max_hor_pos = half_area_width + half_def_width
|
|
||||||
min_ver_pos = half_area_height - half_def_height
|
|
||||||
max_ver_pos = half_area_height + half_def_height
|
|
||||||
|
|
||||||
pos_event_x = event.x
|
|
||||||
pos_event_y = event.y
|
|
||||||
|
|
||||||
|
|
||||||
if min_hor_pos <= pos_event_x <= max_hor_pos and min_ver_pos <= pos_event_y <= max_ver_pos:
|
|
||||||
uibc_x = int(pos_event_x - (half_area_width - half_def_width))
|
|
||||||
uibc_y = int(pos_event_y - (half_area_height - half_def_height))
|
|
||||||
print('{0},1,0,{1},{2}'.format(type, uibc_x , uibc_y))
|
|
||||||
|
|
||||||
def on_key_pressed(self, widget, event):
|
|
||||||
print("3,0x%04X,0x0000" % event.keyval)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.window.show_all()
|
|
||||||
# You need to get the XID after window.show_all(). You shouldn't get it
|
|
||||||
# in the on_sync_message() handler because threading issues will cause
|
|
||||||
# segfaults there.
|
|
||||||
window = self.drawingarea.get_property('window')
|
|
||||||
if hasattr(window,'get_xid'):
|
|
||||||
self.xid = self.drawingarea.get_property('window').get_xid()
|
|
||||||
|
|
||||||
self.pipeline.set_state(Gst.State.PLAYING)
|
|
||||||
Gtk.main()
|
|
||||||
|
|
||||||
|
|
||||||
def quit(self, window):
|
|
||||||
self.pipeline.set_state(Gst.State.NULL)
|
|
||||||
Gtk.main_quit()
|
|
||||||
|
|
||||||
def on_sync_message(self, bus, msg):
|
|
||||||
if msg.get_structure().get_name() == 'prepare-window-handle':
|
|
||||||
print(self.drawingarea.get_allocation())
|
|
||||||
if hasattr(self,'xid'):
|
|
||||||
msg.src.set_window_handle(self.xid)
|
|
||||||
|
|
||||||
def on_eos(self, bus, msg):
|
|
||||||
print('on_eos(): seeking to start of video')
|
|
||||||
self.pipeline.seek_simple(
|
|
||||||
Gst.Format.TIME,
|
|
||||||
Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_error(self, bus, msg):
|
|
||||||
print('on_error():', msg.parse_error())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("uri", nargs="?", help="Uri to play")
|
|
||||||
parser.add_argument("-v", "--version", help="Show package version")
|
|
||||||
parser.add_argument("--log-level", metavar="lvl", help="Maximum level for log messages")
|
|
||||||
parser.add_argument("-p", "--port", type=int, default=7236, help="Port for rtsp")
|
|
||||||
parser.add_argument("-a", "--audio", dest="audio", action="store_true", help="Enable audio support")
|
|
||||||
parser.add_argument("-s", "--scale", metavar="WxH", help="Scale to resolution")
|
|
||||||
parser.add_argument("-d", "--debug", help="Debug")
|
|
||||||
parser.add_argument("--uibc", help="Enable UIBC")
|
|
||||||
parser.add_argument("--title", help="set player title")
|
|
||||||
parser.add_argument("--res", metavar="n,n,n", help="Supported resolutions masks (CEA, VESA, HH)")
|
|
||||||
# res
|
|
||||||
# " default CEA %08X\n"
|
|
||||||
# " default VESA %08X\n"
|
|
||||||
# " default HH %08X\n"
|
|
||||||
parser.add_argument("-r", "--resolution", help="Resolution")
|
|
||||||
parser.set_defaults(audio=True)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
p = Player(**vars(args))
|
|
||||||
p.run()
|
|
|
@ -1,10 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DIRNAME=$(dirname $0)
|
. miracle-utils.sh
|
||||||
|
|
||||||
. $DIRNAME/miracle-utils.sh
|
kill_ubuntu_network_manager
|
||||||
|
|
||||||
kill_network_manager
|
|
||||||
|
|
||||||
WPA_PID=$(find_wpa_supplicant_pid)
|
WPA_PID=$(find_wpa_supplicant_pid)
|
||||||
if [ -n "$WPA_PID" ]
|
if [ -n "$WPA_PID" ]
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
install_data(
|
|
||||||
'org.freedesktop.miracle.conf',
|
|
||||||
install_dir: join_paths(get_option('sysconfdir'), 'dbus-1', 'system.d')
|
|
||||||
)
|
|
||||||
|
|
||||||
install_data('miracle-gst', 'gstplayer', 'uibc-viewer',
|
|
||||||
install_dir: get_option('bindir'),
|
|
||||||
install_mode: 'rwxr-xr-x')
|
|
||||||
|
|
||||||
install_data(
|
|
||||||
'miracle-wifid', 'miracle-sinkctl', 'miracle-wifictl',
|
|
||||||
install_dir: join_paths(get_option('datadir'), 'bash-completion', 'completions')
|
|
||||||
)
|
|
|
@ -1,46 +1,12 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
function help {
|
|
||||||
local scriptname="$(basename $0)"
|
|
||||||
cat >&2 <<EOF
|
|
||||||
|
|
||||||
$scriptname [options]
|
|
||||||
|
|
||||||
play rtp stream
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-r Resolution
|
|
||||||
-s <Width>x<height> Scale
|
|
||||||
-d <level> Log level for gst
|
|
||||||
-p <port> Port for stream
|
|
||||||
-a Enables audio
|
|
||||||
-h Show this help
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# play stream on port 7236
|
|
||||||
$ $scriptname -p 7236
|
|
||||||
# play stream with resolution 800x600
|
|
||||||
$ $scriptname -s 800x600
|
|
||||||
# play stream with audio
|
|
||||||
$ $scriptname -a
|
|
||||||
# play stream with debug level 3
|
|
||||||
$ $scriptname -d 3
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG='0'
|
DEBUG='0'
|
||||||
AUDIO='0'
|
AUDIO='0'
|
||||||
SCALE='0'
|
SCALE='0'
|
||||||
|
|
||||||
while getopts "r:d:as:p:h" optname
|
while getopts "r:d:as:" optname
|
||||||
do
|
do
|
||||||
case "$optname" in
|
case "$optname" in
|
||||||
"h")
|
|
||||||
help
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
"d")
|
"d")
|
||||||
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
||||||
;;
|
;;
|
||||||
|
@ -50,9 +16,6 @@ while getopts "r:d:as:p:h" optname
|
||||||
"a")
|
"a")
|
||||||
AUDIO='1'
|
AUDIO='1'
|
||||||
;;
|
;;
|
||||||
"p")
|
|
||||||
PORT=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"s")
|
"s")
|
||||||
SCALE='1'
|
SCALE='1'
|
||||||
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
|
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
|
||||||
|
@ -62,9 +25,8 @@ while getopts "r:d:as:p:h" optname
|
||||||
echo "Unknown option $OPTARG"
|
echo "Unknown option $OPTARG"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown parameter $OPTARG"
|
# Should not occur
|
||||||
help
|
echo "Unknown error while processing options"
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
@ -75,7 +37,7 @@ then
|
||||||
RUN+="--gst-debug=${DEBUG} "
|
RUN+="--gst-debug=${DEBUG} "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RUN+="udpsrc port=$PORT caps=\"application/x-rtp, media=video\" ! rtpjitterbuffer latency=100 ! rtpmp2tdepay ! tsdemux "
|
RUN+="udpsrc port=1991 caps=\"application/x-rtp, media=video\" ! rtpjitterbuffer latency=100 ! rtpmp2tdepay ! tsdemux "
|
||||||
|
|
||||||
if [ $AUDIO == '1' ]
|
if [ $AUDIO == '1' ]
|
||||||
then
|
then
|
|
@ -1,69 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function help {
|
|
||||||
local scriptname="$(basename $0)"
|
|
||||||
cat >&2 <<EOF
|
|
||||||
|
|
||||||
$scriptname [options]
|
|
||||||
|
|
||||||
play rtp stream with omxplayer
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-r Resolution
|
|
||||||
-s <Width>x<height> Scale
|
|
||||||
-d <level> Log level for gst
|
|
||||||
-p <port> Port for stream
|
|
||||||
-a Enables audio
|
|
||||||
-h Show this help
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# play stream on port 7236
|
|
||||||
$ $scriptname -p 7236
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG='0'
|
|
||||||
AUDIO='0'
|
|
||||||
SCALE='0'
|
|
||||||
|
|
||||||
while getopts "r:d:as:p:h" optname
|
|
||||||
do
|
|
||||||
case "$optname" in
|
|
||||||
"h")
|
|
||||||
help
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
"d")
|
|
||||||
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"r")
|
|
||||||
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"a")
|
|
||||||
AUDIO='1'
|
|
||||||
;;
|
|
||||||
"p")
|
|
||||||
PORT=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"s")
|
|
||||||
SCALE='1'
|
|
||||||
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
|
|
||||||
HEIGHT=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 2`
|
|
||||||
;;
|
|
||||||
"?")
|
|
||||||
echo "Unknown option $OPTARG"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown parameter $OPTARG"
|
|
||||||
help
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
RUN="omxplayer -live -b -o hdmi rtp://@:$PORT"
|
|
||||||
|
|
||||||
echo "running: $RUN"
|
|
||||||
exec ${RUN}
|
|
|
@ -1,85 +0,0 @@
|
||||||
#
|
|
||||||
# Autocompletion for miraclecast commands
|
|
||||||
#
|
|
||||||
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
|
|
||||||
#
|
|
||||||
|
|
||||||
function _miracle-sinkctl() {
|
|
||||||
local cur prev
|
|
||||||
|
|
||||||
_get_comp_words_by_ref cur
|
|
||||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
|
||||||
|
|
||||||
case "$prev" in
|
|
||||||
--log-level)
|
|
||||||
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
COMPREPLY=($(compgen -W "$(_parse_help miracle-sinkctl) $(_parse_short_help miracle-sinkctl)" -- "$cur"))
|
|
||||||
}
|
|
||||||
|
|
||||||
_parse_short_help ()
|
|
||||||
{
|
|
||||||
eval local cmd=$( quote "$1" );
|
|
||||||
local line;
|
|
||||||
{
|
|
||||||
case $cmd in
|
|
||||||
-)
|
|
||||||
cat
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
} | while read -r line; do
|
|
||||||
[[ $line == *([[:blank:]])-* ]] || continue;
|
|
||||||
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
|
|
||||||
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
|
|
||||||
done;
|
|
||||||
__parse_short_options "${line// or /, }";
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
__parse_short_options ()
|
|
||||||
{
|
|
||||||
local option option2 i IFS='
|
|
||||||
,/|';
|
|
||||||
option=;
|
|
||||||
local -a array;
|
|
||||||
read -a array <<< "$1";
|
|
||||||
for i in "${array[@]}";
|
|
||||||
do
|
|
||||||
case "$i" in
|
|
||||||
---*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
--?*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
-?*)
|
|
||||||
option=$i;
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac;
|
|
||||||
done;
|
|
||||||
[[ -n $option ]] || return;
|
|
||||||
IFS='
|
|
||||||
';
|
|
||||||
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
|
|
||||||
option2=${option/"${BASH_REMATCH[1]}"/};
|
|
||||||
option2=${option2%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option2/=*/=}";
|
|
||||||
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
|
|
||||||
fi;
|
|
||||||
option=${option%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option/=*/=}"
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _miracle-sinkctl miracle-sinkctl
|
|
||||||
|
|
||||||
# ex: filetype=sh
|
|
|
@ -27,13 +27,6 @@ function find_wireless_network_interfaces {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# show pci slot
|
|
||||||
#
|
|
||||||
function show_pci_slot {
|
|
||||||
basename $(readlink /sys/class/net/$1/device) | cut -d: -f2 | sed 's/^0*//'
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# test if interface is connected
|
# test if interface is connected
|
||||||
#
|
#
|
||||||
|
@ -41,26 +34,6 @@ function is_interface_connected {
|
||||||
test x$( cat /sys/class/net/$1/carrier 2>/dev/null) = x1
|
test x$( cat /sys/class/net/$1/carrier 2>/dev/null) = x1
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# find wireless pci slot
|
|
||||||
#
|
|
||||||
function find_wireless_pci_slot {
|
|
||||||
for i in $( find_wireless_network_interfaces )
|
|
||||||
do
|
|
||||||
show_pci_slot $i
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
|
||||||
# find wireless pci slot
|
|
||||||
#
|
|
||||||
function find_wireless_ifindex {
|
|
||||||
for i in $( find_wireless_network_interfaces )
|
|
||||||
do
|
|
||||||
show_ifindex $i
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# find wireless connected interfaces
|
# find wireless connected interfaces
|
||||||
#
|
#
|
||||||
|
@ -79,23 +52,12 @@ function find_wireless_connected_network_interfaces {
|
||||||
#
|
#
|
||||||
function find_physical_for_network_interface {
|
function find_physical_for_network_interface {
|
||||||
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
|
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
|
||||||
if [ -n "$PHY_INDEX" ]
|
if [ -n $PHY_INDEX ]
|
||||||
then
|
then
|
||||||
echo phy$PHY_INDEX
|
echo phy$PHY_INDEX
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# find interface index for interface
|
|
||||||
#
|
|
||||||
function show_ifindex {
|
|
||||||
IF_INDEX=$(iw dev $1 info | grep ifindex | awk '{print $2}')
|
|
||||||
if [ -n "$IF_INDEX" ]
|
|
||||||
then
|
|
||||||
echo $IF_INDEX
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check interface for P2P capabilities
|
# Check interface for P2P capabilities
|
||||||
#
|
#
|
||||||
|
@ -103,12 +65,6 @@ function search_p2p_capabilities {
|
||||||
WI_DEVICE=$1
|
WI_DEVICE=$1
|
||||||
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
|
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
|
||||||
|
|
||||||
if [ -z "$PHY_DEVICE" ]
|
|
||||||
then
|
|
||||||
echo "cannot find physical device for $WI_DEVICE"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P" &> /dev/null
|
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P" &> /dev/null
|
||||||
then
|
then
|
||||||
echo $WI_DEVICE supports P2P
|
echo $WI_DEVICE supports P2P
|
||||||
|
@ -139,55 +95,31 @@ function find_wpa_supplicant_pid {
|
||||||
show_wpa_supplicant_process | awk '{print $2}'
|
show_wpa_supplicant_process | awk '{print $2}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# checking if distro is archlinux
|
|
||||||
#
|
|
||||||
function check_archlinux_distro {
|
|
||||||
test -f "/etc/arch-release"
|
|
||||||
}
|
|
||||||
#
|
#
|
||||||
# checking if distro is ubuntu
|
# checking if distro is ubuntu
|
||||||
#
|
#
|
||||||
function check_ubuntu_distro {
|
function check_ubuntu_distro {
|
||||||
cat /proc/version | grep -i ubuntu
|
cat /proc/version | grep -i ubuntu
|
||||||
}
|
}
|
||||||
#
|
|
||||||
# checking if distro is debian
|
|
||||||
#
|
|
||||||
function check_debian_distro {
|
|
||||||
cat /proc/version | grep -i debian
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# kills network manager
|
# ubuntu manager restarts automatically wpa_supplicant
|
||||||
#
|
#
|
||||||
function kill_network_manager {
|
function kill_ubuntu_network_manager {
|
||||||
echo stopping NetworkManager
|
if check_ubuntu_distro
|
||||||
if check_ubuntu_distro || check_debian_distro
|
|
||||||
then
|
then
|
||||||
# ubuntu manager restarts automatically wpa_supplicant
|
echo stopping NetworkManager
|
||||||
sudo service NetworkManager stop
|
sudo service NetworkManager stop
|
||||||
elif check_archlinux_distro
|
|
||||||
then
|
|
||||||
sudo systemctl stop Network.service
|
|
||||||
else
|
|
||||||
sudo systemctl stop NetworkManager
|
|
||||||
sudo systemctl stop wpa_supplicant
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# start network manager
|
# start ubuntu manager
|
||||||
#
|
#
|
||||||
function start_network_manager {
|
function start_ubuntu_network_manager {
|
||||||
echo starting NetworkManager
|
if check_ubuntu_distro
|
||||||
if check_ubuntu_distro || check_debian_distro
|
|
||||||
then
|
then
|
||||||
sudo service NetworkManager start
|
echo starting NetworkManager
|
||||||
elif check_archlinux_distro
|
|
||||||
then
|
|
||||||
sudo systemctl start Network.service
|
|
||||||
else
|
|
||||||
sudo service NetworkManager start
|
sudo service NetworkManager start
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function help {
|
|
||||||
local scriptname="$(basename $0)"
|
|
||||||
cat >&2 <<EOF
|
|
||||||
|
|
||||||
$scriptname [options]
|
|
||||||
|
|
||||||
play rtp stream with vlc
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-r Resolution
|
|
||||||
-s <Width>x<height> Scale
|
|
||||||
-d <level> Log level for gst
|
|
||||||
-p <port> Port for stream
|
|
||||||
-a Enables audio
|
|
||||||
-h Show this help
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# play stream on port 7236
|
|
||||||
$ $scriptname -p 7236
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG='0'
|
|
||||||
AUDIO='0'
|
|
||||||
SCALE='0'
|
|
||||||
|
|
||||||
while getopts "r:d:as:p:h" optname
|
|
||||||
do
|
|
||||||
case "$optname" in
|
|
||||||
"h")
|
|
||||||
help
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
"d")
|
|
||||||
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"r")
|
|
||||||
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"a")
|
|
||||||
AUDIO='1'
|
|
||||||
;;
|
|
||||||
"p")
|
|
||||||
PORT=`echo ${OPTARG} | tr -d ' '`
|
|
||||||
;;
|
|
||||||
"s")
|
|
||||||
SCALE='1'
|
|
||||||
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
|
|
||||||
HEIGHT=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 2`
|
|
||||||
;;
|
|
||||||
"?")
|
|
||||||
echo "Unknown option $OPTARG"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown parameter $OPTARG"
|
|
||||||
help
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
RUN="vlc rtp://@:$PORT"
|
|
||||||
|
|
||||||
echo "running: $RUN"
|
|
||||||
exec ${RUN}
|
|
|
@ -1,85 +0,0 @@
|
||||||
#
|
|
||||||
# Autocompletion for miracle-wifictl
|
|
||||||
#
|
|
||||||
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
|
|
||||||
#
|
|
||||||
|
|
||||||
function _miracle-wifictl() {
|
|
||||||
local cur prev
|
|
||||||
|
|
||||||
_get_comp_words_by_ref cur
|
|
||||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
|
||||||
|
|
||||||
case "$prev" in
|
|
||||||
--log-level)
|
|
||||||
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifictl) $(_parse_short_help miracle-wifictl)" -- "$cur"))
|
|
||||||
}
|
|
||||||
|
|
||||||
_parse_short_help ()
|
|
||||||
{
|
|
||||||
eval local cmd=$( quote "$1" );
|
|
||||||
local line;
|
|
||||||
{
|
|
||||||
case $cmd in
|
|
||||||
-)
|
|
||||||
cat
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
} | while read -r line; do
|
|
||||||
[[ $line == *([[:blank:]])-* ]] || continue;
|
|
||||||
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
|
|
||||||
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
|
|
||||||
done;
|
|
||||||
__parse_short_options "${line// or /, }";
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
__parse_short_options ()
|
|
||||||
{
|
|
||||||
local option option2 i IFS='
|
|
||||||
,/|';
|
|
||||||
option=;
|
|
||||||
local -a array;
|
|
||||||
read -a array <<< "$1";
|
|
||||||
for i in "${array[@]}";
|
|
||||||
do
|
|
||||||
case "$i" in
|
|
||||||
---*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
--?*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
-?*)
|
|
||||||
option=$i;
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac;
|
|
||||||
done;
|
|
||||||
[[ -n $option ]] || return;
|
|
||||||
IFS='
|
|
||||||
';
|
|
||||||
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
|
|
||||||
option2=${option/"${BASH_REMATCH[1]}"/};
|
|
||||||
option2=${option2%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option2/=*/=}";
|
|
||||||
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
|
|
||||||
fi;
|
|
||||||
option=${option%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option/=*/=}"
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _miracle-wifictl miracle-wifictl
|
|
||||||
|
|
||||||
# ex: filetype=sh
|
|
|
@ -1,95 +0,0 @@
|
||||||
#
|
|
||||||
# Autocompletion for miracle-wifid
|
|
||||||
#
|
|
||||||
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
|
|
||||||
#
|
|
||||||
|
|
||||||
function _miracle-wifid() {
|
|
||||||
local cur prev
|
|
||||||
|
|
||||||
_get_comp_words_by_ref cur
|
|
||||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
|
||||||
|
|
||||||
case "$prev" in
|
|
||||||
--config-methods)
|
|
||||||
COMPREPLY=($(compgen -W 'pbc pin usba ethernet label display ext_nfc_token int_nfc_token nfc_interface push_button keypad virtual_display physical_display virtual_push_button physical_push_button' -- "$cur"))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
--log-level)
|
|
||||||
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
--wpa-loglevel)
|
|
||||||
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifid) $(_parse_short_help miracle-wifid)" -- "$cur"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_parse_short_help ()
|
|
||||||
{
|
|
||||||
eval local cmd=$( quote "$1" );
|
|
||||||
local line;
|
|
||||||
{
|
|
||||||
case $cmd in
|
|
||||||
-)
|
|
||||||
cat
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
} | while read -r line; do
|
|
||||||
[[ $line == *([[:blank:]])-* ]] || continue;
|
|
||||||
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
|
|
||||||
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
|
|
||||||
done;
|
|
||||||
__parse_short_options "${line// or /, }";
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
__parse_short_options ()
|
|
||||||
{
|
|
||||||
local option option2 i IFS='
|
|
||||||
,/|';
|
|
||||||
option=;
|
|
||||||
local -a array;
|
|
||||||
read -a array <<< "$1";
|
|
||||||
for i in "${array[@]}";
|
|
||||||
do
|
|
||||||
case "$i" in
|
|
||||||
---*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
--?*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
-?*)
|
|
||||||
option=$i;
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
esac;
|
|
||||||
done;
|
|
||||||
[[ -n $option ]] || return;
|
|
||||||
IFS='
|
|
||||||
';
|
|
||||||
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
|
|
||||||
option2=${option/"${BASH_REMATCH[1]}"/};
|
|
||||||
option2=${option2%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option2/=*/=}";
|
|
||||||
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
|
|
||||||
fi;
|
|
||||||
option=${option%%[<{().[]*};
|
|
||||||
printf '%s\n' "${option/=*/=}"
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _miracle-wifid miracle-wifid
|
|
||||||
|
|
||||||
|
|
||||||
# ex: filetype=sh
|
|
|
@ -1,18 +0,0 @@
|
||||||
FROM debian:buster-slim
|
|
||||||
|
|
||||||
RUN dpkg --add-architecture i386
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
|
||||||
build-essential \
|
|
||||||
systemd \
|
|
||||||
libglib2.0-dev \
|
|
||||||
libreadline-dev \
|
|
||||||
libudev-dev \
|
|
||||||
libsystemd-dev \
|
|
||||||
libusb-dev \
|
|
||||||
automake \
|
|
||||||
autoconf \
|
|
||||||
libtool \
|
|
||||||
cmake \
|
|
||||||
meson
|
|
||||||
|
|
57
res/miraclecast-completion
Executable file
57
res/miraclecast-completion
Executable file
|
@ -0,0 +1,57 @@
|
||||||
|
function _miracle-wifid() {
|
||||||
|
local cur prev
|
||||||
|
|
||||||
|
_get_comp_words_by_ref cur
|
||||||
|
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
|
|
||||||
|
case "$prev" in
|
||||||
|
--log-level)
|
||||||
|
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
--wpa-loglevel)
|
||||||
|
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifid)" -- "$cur"))
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _miracle-wifid miracle-wifid
|
||||||
|
|
||||||
|
function _miracle-sinkctl() {
|
||||||
|
local cur prev
|
||||||
|
|
||||||
|
_get_comp_words_by_ref cur
|
||||||
|
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
|
|
||||||
|
case "$prev" in
|
||||||
|
--log-level)
|
||||||
|
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
COMPREPLY=($(compgen -W "$(_parse_help miracle-sinkctl)" -- "$cur"))
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _miracle-sinkctl miracle-sinkctl
|
||||||
|
|
||||||
|
function _miracle-wifictl() {
|
||||||
|
local cur prev
|
||||||
|
|
||||||
|
_get_comp_words_by_ref cur
|
||||||
|
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
|
|
||||||
|
case "$prev" in
|
||||||
|
--log-level)
|
||||||
|
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifictl)" -- "$cur"))
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _miracle-wifictl miracle-wifictl
|
|
@ -1,68 +0,0 @@
|
||||||
%global commit 264a222d242734da369ca287aa6cfc6ca4f1f7bf
|
|
||||||
%global shortcommit %(c=%{commit}; echo ${c:0:7})
|
|
||||||
|
|
||||||
Name: miraclecast
|
|
||||||
Version: 1.0
|
|
||||||
Release: 2.git%{shortcommit}%{?dist}
|
|
||||||
Summary: Connect external monitors to your system via Wi-Fi Display (miracast)
|
|
||||||
License: LGPLv2
|
|
||||||
URL: https://github.com/albfan/miraclecast
|
|
||||||
Source0: https://github.com/albfan/miraclecast/archive/%{commit}/%{name}-%{shortcommit}.tar.gz
|
|
||||||
|
|
||||||
BuildRequires: autoconf
|
|
||||||
BuildRequires: automake
|
|
||||||
BuildRequires: libtool
|
|
||||||
|
|
||||||
BuildRequires: glib2-devel
|
|
||||||
BuildRequires: readline-devel
|
|
||||||
BuildRequires: systemd-devel
|
|
||||||
|
|
||||||
# "Recommends" is stronger than "Suggests", and gets installed by default by DNF.
|
|
||||||
|
|
||||||
# for gstplayer
|
|
||||||
Recommends: python3-gobject-base
|
|
||||||
|
|
||||||
# for miracle-gst (/usr/bin/gst-launch-1.0)
|
|
||||||
Suggests: gstreamer
|
|
||||||
|
|
||||||
# for miracle-omxplayer
|
|
||||||
Suggests: omxplayer
|
|
||||||
|
|
||||||
%description
|
|
||||||
The MiracleCast project provides software to connect external monitors to your
|
|
||||||
system via Wi-Fi. It is compatible to the Wi-Fi Display specification also
|
|
||||||
known as Miracast. MiracleCast implements the Display-Source as well as
|
|
||||||
Display-Sink side.
|
|
||||||
|
|
||||||
The Display-Source side allows you to connect external displays to your system
|
|
||||||
and stream local content to the device. A lot of effort is put into making
|
|
||||||
this as easy as connecting external displays via HDMI.
|
|
||||||
|
|
||||||
On the other hand, the Display-Sink side allows you to create Wi-Fi capable
|
|
||||||
external displays yourself. You can use it on your embedded devices or even on
|
|
||||||
full desktops to allow other systems to use your device as external display.
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%autosetup -n %{name}-%{commit}
|
|
||||||
|
|
||||||
%build
|
|
||||||
autoreconf -fiv
|
|
||||||
%configure
|
|
||||||
%make_build
|
|
||||||
|
|
||||||
%install
|
|
||||||
%make_install
|
|
||||||
|
|
||||||
%files
|
|
||||||
%license COPYING LICENSE_gdhcp LICENSE_htable LICENSE_lgpl
|
|
||||||
%doc README.md
|
|
||||||
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freedesktop.miracle.conf
|
|
||||||
%{_bindir}/*
|
|
||||||
%{_datadir}/bash-completion/completions/*
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
* Wed Jan 05 2022 Korenberg Mark
|
|
||||||
- Fix .spec-file, bump version
|
|
||||||
|
|
||||||
* Wed Nov 21 2018 Graham White
|
|
||||||
- first build
|
|
|
@ -1,24 +0,0 @@
|
||||||
This file can be used with the rpmbuild or mock commands to create a binary RPM. Tested and working on Fedora 28 x86\_64.
|
|
||||||
|
|
||||||
Example usage (for Fedora 28 systems):
|
|
||||||
1. Create a tar.gz file of the source code and add the short name of the commit to the tar file, for the most recent commit at the time of writing this would be:
|
|
||||||
* `git clone https://github.com/albfan/miraclecast.git miraclecast-c3c868e`
|
|
||||||
* `tar -zcf miraclecast-c3c868e.tar.gz miraclecast-c3c868e`
|
|
||||||
|
|
||||||
2. Create a Source RPM
|
|
||||||
* `rpmbuild -bs miraclecast.spec --define "_sourcedir $PWD"`
|
|
||||||
|
|
||||||
Then build the RPM with one of the following:
|
|
||||||
|
|
||||||
* Using mock (assuming you're in the dir where the .src.rpm file is):
|
|
||||||
* `mock --arch=x86_64 -r fedora-28-x86_64 --resultdir=results miraclecast-1.0-1.gitc3c868e.fc28.src.rpm`
|
|
||||||
|
|
||||||
OR
|
|
||||||
|
|
||||||
* Using rpmbuild (assuming you're in the dir where the .src.rpm file is):
|
|
||||||
* `rpmbuild -ra miraclecast-1.0-1.gitc3c868e.fc28.src.rpm`
|
|
||||||
|
|
||||||
OR
|
|
||||||
|
|
||||||
* Using rpmbuild (assuming you're in the dir where the .spec and .tar.gz files are):
|
|
||||||
* `rpmbuild -bs miraclecast.spec --define "_sourcedir $PWD"``
|
|
|
@ -1,9 +1,57 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DIRNAME=$(dirname $0)
|
./kill-wpa.sh
|
||||||
|
|
||||||
. $DIRNAME/miracle-utils.sh
|
. miracle-utils.sh
|
||||||
|
|
||||||
./$DIRNAME/kill-wpa.sh
|
ETHER_NAMES=$(find_choosable_networknames)
|
||||||
|
|
||||||
|
ETHER_COUNT=$(echo "$ETHER_NAMES" | wc -l)
|
||||||
|
|
||||||
|
if [ 0 = $ETHER_COUNT ]
|
||||||
|
then
|
||||||
|
echo There is no net devices avaliable
|
||||||
|
exit 1
|
||||||
|
elif [ 1 = $ETHER_COUNT ]
|
||||||
|
then
|
||||||
|
ETHERNAME="$ETHER_NAMES"
|
||||||
|
elif [ 2 -le $ETHER_COUNT ]
|
||||||
|
then
|
||||||
|
echo choose device for normal connection:
|
||||||
|
QUIT="exit"
|
||||||
|
select et_name in $ETHER_NAMES $QUIT
|
||||||
|
do
|
||||||
|
case $et_name
|
||||||
|
in
|
||||||
|
"$QUIT")
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
"")
|
||||||
|
if [ "$REPLY" = $QUIT ]
|
||||||
|
then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
echo unknow $REPLY
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ETHERNAME=$et_name
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# default path for config file
|
||||||
|
CONFIG_FILE=${1:-/run/network/wpa_supplicant_${ETHERNAME}.conf}
|
||||||
|
|
||||||
|
|
||||||
|
echo starting wpa_supplicant for normal connection
|
||||||
|
if check_ubuntu_distro
|
||||||
|
then
|
||||||
|
start_ubuntu_network_manager
|
||||||
|
sudo wpa_supplicant -B -u -s -O /var/run/wpa_supplicant
|
||||||
|
else
|
||||||
|
sudo wpa_supplicant -B -u -P /run/wpa_supplicant_${ETHERNAME}pid -i ${ETHERNAME} -D nl80211 -c$CONFIG_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
start_network_manager
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
#Example of extra parameters to extend sink request
|
|
||||||
|
|
||||||
[sinkctl]
|
|
||||||
extends.wfd_video_formats=40 00 01 10 0001bdeb 051557ff 00000fff 10 0000 001f 11 0780 0438, 02 10 0001bdeb 155557ff 00000fff 10 0000 001f 11 0780 0438
|
|
||||||
extends.wfd_audio_codecs=LPCM 00000003 00, AAC 0000000f 00, AC3 00000007 00
|
|
||||||
extends.wfd_display_edid=0001 00ffffffffffff0051f38f50010000000e100104a51d10ff2f0000a057499b2610484f000000010101010101010101010101010101011a36809c70381f403020350025a510000018000000fc00496e7465726e616c204c43440a000000fd003c3c9a9a0e00000000000000000000000000000000000000000000000000000030
|
|
||||||
extends.wfd_connector_type=05
|
|
||||||
extends.microsoft_cursor=none
|
|
||||||
extends.microsoft_rtcp_capability=none
|
|
||||||
extends.wfd_idr_request_capability=1
|
|
||||||
extends.microsoft_latency_management_capability=none
|
|
||||||
extends.microsoft_format_change_capability=none
|
|
||||||
extends.microsoft_diagnostics_capability=none
|
|
||||||
extends.intel_friendly_name=miraclecast
|
|
||||||
extends.intel_sink_manufacturer_name=GNU Linux
|
|
||||||
extends.intel_sink_model_name=Arch linux
|
|
||||||
extends.intel_sink_device_URL=http://github.com/albfan/miraclecast
|
|
||||||
extends.wfd_uibc_capability=input_category_list=GENERIC, HIDC;generic_cap_list=Keyboard;hidc_cap_list=Keyboard/USB, Mouse/USB, MultiTouch/USB, Gesture/USB, RemoteControl/USB;port=none
|
|
|
@ -1,34 +1,18 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
|
. miracle-utils.sh
|
||||||
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
|
|
||||||
|
|
||||||
if [ "$SCRIPT_DEBUG" -ge 1 ]
|
WIFI_NAMES=$(find_wireless_network_interfaces)
|
||||||
then
|
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
if [ "$SCRIPT_DEBUG" -ge 10 ]
|
|
||||||
then
|
|
||||||
set -v
|
|
||||||
fi
|
|
||||||
|
|
||||||
. ./miracle-utils.sh
|
|
||||||
|
|
||||||
WIFI_COUNT=0
|
|
||||||
WIFI_NAMES="$(find_wireless_network_interfaces)"
|
|
||||||
if [ -n "$WIFI_NAMES" ]
|
|
||||||
then
|
|
||||||
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ 0 = $WIFI_COUNT ]
|
if [ 0 = $WIFI_COUNT ]
|
||||||
then
|
then
|
||||||
echo There is no wireless devices available
|
echo There is no wireless devices avaliable
|
||||||
exit 1
|
exit 1
|
||||||
elif [ 1 = $WIFI_COUNT ]
|
elif [ 1 = $WIFI_COUNT ]
|
||||||
then
|
then
|
||||||
WIFI_NAME="$WIFI_NAMES"
|
WIFI_NAME="$WIFI_NAMES"
|
||||||
elif [ 2 -le $WIFI_COUNT ]
|
elif [ 2 -ge $WIFI_COUNT ]
|
||||||
then
|
then
|
||||||
echo Choose wireless device:
|
echo Choose wireless device:
|
||||||
PS3="device: "
|
PS3="device: "
|
||||||
|
|
|
@ -35,7 +35,7 @@ Try installing packages "gst-plugins-bad, gst-plugins-base, gst-plugins-base-lib
|
||||||
|
|
||||||
If that fails too, try:
|
If that fails too, try:
|
||||||
|
|
||||||
$ vlc rtp://@:7236
|
$ vlc rtp://@1991
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function kill_child() {
|
|
||||||
CHILDREN="$(ps -o pid= --ppid $$)"
|
|
||||||
echo killing $CHILDREN
|
|
||||||
kill $CHILDREN
|
|
||||||
}
|
|
||||||
|
|
||||||
IP=$1
|
|
||||||
shift
|
|
||||||
UIBC_PORT=$1
|
|
||||||
shift
|
|
||||||
|
|
||||||
echo $$
|
|
||||||
|
|
||||||
trap 'kill_child' SIGTERM
|
|
||||||
|
|
||||||
gstplayer $@ | miracle-uibcctl $IP $UIBC_PORT --daemon &
|
|
||||||
wait
|
|
|
@ -8,7 +8,7 @@ ETHER_COUNT=$(echo "$ETHER_NAMES" | wc -l)
|
||||||
|
|
||||||
if [ 0 = $ETHER_COUNT ]
|
if [ 0 = $ETHER_COUNT ]
|
||||||
then
|
then
|
||||||
echo There is no net devices available
|
echo There is no net devices avaliable
|
||||||
exit 1
|
exit 1
|
||||||
elif [ 1 = $ETHER_COUNT ]
|
elif [ 1 = $ETHER_COUNT ]
|
||||||
then
|
then
|
||||||
|
|
|
@ -1,15 +1,37 @@
|
||||||
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
|
set(CMAKE_C_FLAGS "-std=gnu11")
|
||||||
|
|
||||||
add_subdirectory(shared)
|
add_subdirectory(shared)
|
||||||
add_subdirectory(wifi)
|
add_subdirectory(wifi)
|
||||||
add_subdirectory(dhcp)
|
add_subdirectory(dhcp)
|
||||||
add_subdirectory(ctl)
|
add_subdirectory(ctl)
|
||||||
add_subdirectory(uibc)
|
|
||||||
|
|
||||||
set(miracled_SRCS miracled.h miracled.c)
|
set(miracled_SRCS miracled.h miracled.c)
|
||||||
add_executable(miracled ${miracled_SRCS})
|
add_executable(miracled ${miracled_SRCS})
|
||||||
target_link_libraries(miracled miracle-shared)
|
target_link_libraries(miracled miracle-shared)
|
||||||
target_link_libraries(miracled m)
|
|
||||||
install(TARGETS miracled DESTINATION bin)
|
install(TARGETS miracled DESTINATION bin)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
||||||
|
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#SUBDIRS = shared wifi dhcp ctl
|
||||||
|
#
|
||||||
|
#bin_PROGRAMS = miracled
|
||||||
|
#
|
||||||
|
#miracled_SOURCES = \
|
||||||
|
# miracled.h \
|
||||||
|
# miracled.c
|
||||||
|
#miracled_CPPFLAGS = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS)
|
||||||
|
#miracled_LDADD = \
|
||||||
|
# shared/libmiracle-shared.la \
|
||||||
|
# $(DEPS_LIBS)
|
||||||
|
#
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
include $(top_srcdir)/common.am
|
include $(top_srcdir)/common.am
|
||||||
SUBDIRS = shared wifi dhcp ctl uibc
|
SUBDIRS = shared wifi dhcp ctl
|
||||||
|
|
||||||
bin_PROGRAMS = miracled
|
bin_PROGRAMS = miracled
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,9 +1,6 @@
|
||||||
find_package(PkgConfig)
|
|
||||||
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
find_package(Readline)
|
||||||
link_directories( ${GLIB2_LIBRARY_DIRS})
|
########### next target ###############
|
||||||
include_directories( ${GLIB2_INCLUDE_DIRS})
|
|
||||||
find_package(Readline REQUIRED)
|
|
||||||
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
|
||||||
|
|
||||||
set(miracle-wifictl_SRCS ctl.h
|
set(miracle-wifictl_SRCS ctl.h
|
||||||
ctl-cli.c
|
ctl-cli.c
|
||||||
|
@ -23,20 +20,17 @@ if(READLINE_FOUND)
|
||||||
endif(READLINE_FOUND)
|
endif(READLINE_FOUND)
|
||||||
|
|
||||||
target_link_libraries(miracle-wifictl miracle-shared)
|
target_link_libraries(miracle-wifictl miracle-shared)
|
||||||
target_link_libraries(miracle-wifictl m)
|
########### next target ###############
|
||||||
target_link_libraries(miracle-wifictl ${GLIB2_LIBRARIES})
|
|
||||||
|
|
||||||
set(miracle-sinkctl_SRCS ctl.h
|
set(miracle-sinkctl_SRCS ctl.h
|
||||||
ctl-cli.c
|
ctl-cli.c
|
||||||
ctl-sink.h
|
|
||||||
ctl-sink.c
|
ctl-sink.c
|
||||||
ctl-wifi.c
|
ctl-wifi.c
|
||||||
sinkctl.c
|
sinkctl.c
|
||||||
wfd.c)
|
wfd.c)
|
||||||
|
|
||||||
|
|
||||||
add_executable(miracle-sinkctl ${miracle-sinkctl_SRCS})
|
add_executable(miracle-sinkctl ${miracle-sinkctl_SRCS})
|
||||||
target_link_libraries(miracle-sinkctl ${GLIB2_LIBRARIES})
|
|
||||||
target_link_libraries(miracle-sinkctl m)
|
|
||||||
|
|
||||||
install(TARGETS miracle-sinkctl DESTINATION bin)
|
install(TARGETS miracle-sinkctl DESTINATION bin)
|
||||||
|
|
||||||
|
@ -51,3 +45,42 @@ endif(READLINE_FOUND)
|
||||||
target_link_libraries(miracle-sinkctl miracle-shared)
|
target_link_libraries(miracle-sinkctl miracle-shared)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#bin_PROGRAMS = miracle-wifictl miracle-sinkctl
|
||||||
|
#
|
||||||
|
#miracle_wifictl_SOURCES = \
|
||||||
|
# ctl.h \
|
||||||
|
# ctl-cli.c \
|
||||||
|
# ctl-wifi.c \
|
||||||
|
# wifictl.c
|
||||||
|
#miracle_wifictl_CPPFLAGS = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS)
|
||||||
|
#miracle_wifictl_LDADD = \
|
||||||
|
# ../shared/libmiracle-shared.la \
|
||||||
|
# -lreadline \
|
||||||
|
# $(DEPS_LIBS)
|
||||||
|
#
|
||||||
|
#miracle_sinkctl_SOURCES = \
|
||||||
|
# ctl.h \
|
||||||
|
# ctl-cli.c \
|
||||||
|
# ctl-sink.c \
|
||||||
|
# ctl-wifi.c \
|
||||||
|
# sinkctl.c
|
||||||
|
#miracle_sinkctl_CPPFLAGS = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS)
|
||||||
|
#miracle_sinkctl_LDADD = \
|
||||||
|
# ../shared/libmiracle-shared.la \
|
||||||
|
# -lreadline \
|
||||||
|
# $(DEPS_LIBS)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
|
@ -8,8 +8,7 @@ miracle_wifictl_SOURCES = \
|
||||||
wifictl.c
|
wifictl.c
|
||||||
miracle_wifictl_CPPFLAGS = \
|
miracle_wifictl_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
$(DEPS_CFLAGS) \
|
$(DEPS_CFLAGS)
|
||||||
$(GLIB_CFLAGS)
|
|
||||||
miracle_wifictl_LDADD = \
|
miracle_wifictl_LDADD = \
|
||||||
../shared/libmiracle-shared.la \
|
../shared/libmiracle-shared.la \
|
||||||
-lreadline \
|
-lreadline \
|
||||||
|
@ -18,19 +17,16 @@ miracle_wifictl_LDADD = \
|
||||||
miracle_sinkctl_SOURCES = \
|
miracle_sinkctl_SOURCES = \
|
||||||
ctl.h \
|
ctl.h \
|
||||||
ctl-cli.c \
|
ctl-cli.c \
|
||||||
ctl-sink.h \
|
|
||||||
ctl-sink.c \
|
ctl-sink.c \
|
||||||
ctl-wifi.c \
|
ctl-wifi.c \
|
||||||
wfd.c \
|
wfd.c \
|
||||||
sinkctl.c
|
sinkctl.c
|
||||||
miracle_sinkctl_CPPFLAGS = \
|
miracle_sinkctl_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
$(DEPS_CFLAGS) \
|
$(DEPS_CFLAGS)
|
||||||
$(GLIB_CFLAGS)
|
|
||||||
miracle_sinkctl_LDADD = \
|
miracle_sinkctl_LDADD = \
|
||||||
../shared/libmiracle-shared.la \
|
../shared/libmiracle-shared.la \
|
||||||
-lreadline \
|
-lreadline \
|
||||||
$(DEPS_LIBS) \
|
$(DEPS_LIBS)
|
||||||
$(GLIB_LIBS)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,15 +27,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include "ctl.h"
|
#include "ctl.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_util.h"
|
#include "shl_util.h"
|
||||||
#include "shl_log.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
|
/* *sigh* readline doesn't include all their deps, so put them last */
|
||||||
|
#include <readline/history.h>
|
||||||
|
#include <readline/readline.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers for interactive commands
|
* Helpers for interactive commands
|
||||||
|
@ -47,14 +47,14 @@ static sd_event_source *cli_sigs[_NSIG];
|
||||||
static sd_event_source *cli_stdin;
|
static sd_event_source *cli_stdin;
|
||||||
static bool cli_rl;
|
static bool cli_rl;
|
||||||
static const struct cli_cmd *cli_cmds;
|
static const struct cli_cmd *cli_cmds;
|
||||||
unsigned int cli_max_sev = LOG_NOTICE;
|
int cli_max_sev = LOG_NOTICE;
|
||||||
|
|
||||||
static bool is_cli(void)
|
static bool is_cli(void)
|
||||||
{
|
{
|
||||||
return cli_rl;
|
return cli_rl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_printv(const char *fmt, bool prefix_time, va_list args)
|
void cli_printv(const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
SHL_PROTECT_ERRNO;
|
SHL_PROTECT_ERRNO;
|
||||||
_shl_free_ char *line = NULL;
|
_shl_free_ char *line = NULL;
|
||||||
|
@ -73,10 +73,6 @@ void cli_printv(const char *fmt, bool prefix_time, va_list args)
|
||||||
rl_redisplay();
|
rl_redisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefix_time) {
|
|
||||||
cli_printf_time_prefix();
|
|
||||||
}
|
|
||||||
|
|
||||||
vprintf(fmt, args);
|
vprintf(fmt, args);
|
||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
|
@ -87,65 +83,24 @@ void cli_printv(const char *fmt, bool prefix_time, va_list args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_printf_time_prefix(const char *fmt, va_list args)
|
|
||||||
{
|
|
||||||
long long sec, usec;
|
|
||||||
time_t now;
|
|
||||||
struct tm *timeinfo;
|
|
||||||
struct timeval tv;
|
|
||||||
char buffertmp[80];
|
|
||||||
char buffer[120];
|
|
||||||
int millisec;
|
|
||||||
|
|
||||||
|
|
||||||
log__time(&sec, &usec);
|
|
||||||
|
|
||||||
if (log_date_time) {
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
millisec = lrint(tv.tv_usec/1000.0);
|
|
||||||
if (millisec>=1000) {
|
|
||||||
millisec -=1000;
|
|
||||||
tv.tv_sec++;
|
|
||||||
}
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
timeinfo = localtime(&now);
|
|
||||||
|
|
||||||
strftime(buffertmp, 80, "%x - %X.%03d", timeinfo);
|
|
||||||
sprintf(buffer, "%s.%03d", buffertmp, millisec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log_date_time)
|
|
||||||
printf("[%s] ", buffer);
|
|
||||||
else if (log__have_time())
|
|
||||||
printf("[%.4lld.%.6lld] ", sec, usec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cli_command_printf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
SHL_PROTECT_ERRNO;
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
cli_printv(fmt, false, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cli_printf(const char *fmt, ...)
|
void cli_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
SHL_PROTECT_ERRNO;
|
SHL_PROTECT_ERRNO;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
cli_printv(fmt, true, args);
|
cli_printv(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cli_help(const struct cli_cmd *cmds, int whitespace)
|
int cli_help(const struct cli_cmd *cmds)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
cli_command_printf("Available commands:\n");
|
if (!is_cli()) {
|
||||||
|
cli_fn_help();
|
||||||
|
}
|
||||||
|
cli_printf("Available commands:\n");
|
||||||
|
|
||||||
for (i = 0; cmds[i].cmd; ++i) {
|
for (i = 0; cmds[i].cmd; ++i) {
|
||||||
if (!cmds[i].desc)
|
if (!cmds[i].desc)
|
||||||
|
@ -155,11 +110,11 @@ int cli_help(const struct cli_cmd *cmds, int whitespace)
|
||||||
if (!is_cli() && cmds[i].cli_cmp == CLI_Y)
|
if (!is_cli() && cmds[i].cli_cmp == CLI_Y)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cli_command_printf(" %s %-*s %s\n",
|
cli_printf(" %s %-*s %s\n",
|
||||||
cmds[i].cmd,
|
cmds[i].cmd,
|
||||||
(int)(whitespace - strlen(cmds[i].cmd)),
|
(int)(40 - strlen(cmds[i].cmd)),
|
||||||
cmds[i].args ? : "",
|
cmds[i].args ? : "",
|
||||||
cmds[i].desc ? : "");
|
cmds[i].desc ? : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -188,21 +143,21 @@ int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n)
|
||||||
switch (cmds[i].argc_cmp) {
|
switch (cmds[i].argc_cmp) {
|
||||||
case CLI_EQUAL:
|
case CLI_EQUAL:
|
||||||
if (n != cmds[i].argc) {
|
if (n != cmds[i].argc) {
|
||||||
cli_command_printf("Invalid number of arguments\n");
|
cli_printf("Invalid number of arguments\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CLI_MORE:
|
case CLI_MORE:
|
||||||
if (n < cmds[i].argc) {
|
if (n < cmds[i].argc) {
|
||||||
cli_command_printf("too few arguments\n");
|
cli_printf("too few arguments\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CLI_LESS:
|
case CLI_LESS:
|
||||||
if (n > cmds[i].argc) {
|
if (n > cmds[i].argc) {
|
||||||
cli_command_printf("too many arguments\n");
|
cli_printf("too many arguments\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +173,7 @@ int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(cmd, "help"))
|
if (!strcmp(cmd, "help"))
|
||||||
return cli_help(cmds, 40);
|
return cli_help(cmds);
|
||||||
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -243,15 +198,12 @@ static void cli_handler_fn(char *input)
|
||||||
else if (!r)
|
else if (!r)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(strcmp(original, "quit") == 0 || strcmp(original, "exit") == 0)) {
|
add_history(original);
|
||||||
add_history(original);
|
|
||||||
write_history(get_history_filename());
|
|
||||||
}
|
|
||||||
r = cli_do(cli_cmds, args, r);
|
r = cli_do(cli_cmds, args, r);
|
||||||
if (r != -EAGAIN)
|
if (r != -EAGAIN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cli_command_printf("Command not found\n");
|
cli_printf("Command not found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cli_stdin_fn(sd_event_source *source,
|
static int cli_stdin_fn(sd_event_source *source,
|
||||||
|
@ -325,312 +277,6 @@ void cli_destroy(void)
|
||||||
cli_event = NULL;
|
cli_event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *yes_no_options[] = {"yes", "no", NULL};
|
|
||||||
|
|
||||||
char *
|
|
||||||
yes_no_generator (const char *text, int state)
|
|
||||||
{
|
|
||||||
static int list_index, len;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
/* If this is a new word to complete, initialize now. This includes
|
|
||||||
saving the length of TEXT for efficiency, and initializing the index
|
|
||||||
variable to 0. */
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the next name which partially matches from the command list. */
|
|
||||||
while ((name = yes_no_options[list_index]) != NULL)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
return (strdup(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no names matched, then return NULL. */
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
links_peers_generator (const char *text, int state)
|
|
||||||
{
|
|
||||||
static int list_index, len;
|
|
||||||
size_t peer_cnt = 0;
|
|
||||||
size_t link_cnt = 0;
|
|
||||||
struct shl_dlist *i, *j;
|
|
||||||
struct ctl_link *l;
|
|
||||||
struct ctl_peer *p;
|
|
||||||
|
|
||||||
/* If this is a new word to complete, initialize now. This includes
|
|
||||||
saving the length of TEXT for efficiency, and initializing the index
|
|
||||||
variable to 0. */
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
shl_dlist_for_each(i, &get_wifi()->links) {
|
|
||||||
l = link_from_dlist(i);
|
|
||||||
|
|
||||||
char *name = l->label;
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (link_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
link_cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = l->friendly_name;
|
|
||||||
if (!shl_isempty(name))
|
|
||||||
{
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (link_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
link_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
peer_cnt = link_cnt;
|
|
||||||
|
|
||||||
shl_dlist_for_each(i, &get_wifi()->links) {
|
|
||||||
l = link_from_dlist(i);
|
|
||||||
|
|
||||||
shl_dlist_for_each(j, &l->peers) {
|
|
||||||
p = peer_from_dlist(j);
|
|
||||||
char *name = p->label;
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (peer_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
peer_cnt++;
|
|
||||||
}
|
|
||||||
name = p->friendly_name;
|
|
||||||
if (!shl_isempty(name))
|
|
||||||
{
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (peer_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
peer_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If no names matched, then return NULL. */
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
peers_generator (const char *text, int state)
|
|
||||||
{
|
|
||||||
static int list_index, len;
|
|
||||||
size_t peer_cnt = 0;
|
|
||||||
struct shl_dlist *i, *j;
|
|
||||||
struct ctl_link *l;
|
|
||||||
struct ctl_peer *p;
|
|
||||||
|
|
||||||
/* If this is a new word to complete, initialize now. This includes
|
|
||||||
saving the length of TEXT for efficiency, and initializing the index
|
|
||||||
variable to 0. */
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
shl_dlist_for_each(i, &get_wifi()->links) {
|
|
||||||
l = link_from_dlist(i);
|
|
||||||
|
|
||||||
shl_dlist_for_each(j, &l->peers) {
|
|
||||||
p = peer_from_dlist(j);
|
|
||||||
char *name = p->label;
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (peer_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
peer_cnt++;
|
|
||||||
}
|
|
||||||
name = p->friendly_name;
|
|
||||||
if (!shl_isempty(name))
|
|
||||||
{
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (peer_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
peer_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If no names matched, then return NULL. */
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
links_generator (const char *text, int state)
|
|
||||||
{
|
|
||||||
static int list_index, len;
|
|
||||||
size_t link_cnt = 0;
|
|
||||||
struct shl_dlist *i;
|
|
||||||
struct ctl_link *l;
|
|
||||||
|
|
||||||
|
|
||||||
/* If this is a new word to complete, initialize now. This includes
|
|
||||||
saving the length of TEXT for efficiency, and initializing the index
|
|
||||||
variable to 0. */
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
shl_dlist_for_each(i, &get_wifi()->links) {
|
|
||||||
l = link_from_dlist(i);
|
|
||||||
|
|
||||||
|
|
||||||
char *name = l->label;
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (link_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
link_cnt++;
|
|
||||||
}
|
|
||||||
name = l->friendly_name;
|
|
||||||
if (!shl_isempty(name))
|
|
||||||
{
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
{
|
|
||||||
if (link_cnt == list_index)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
return strdup(name);
|
|
||||||
}
|
|
||||||
link_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If no names matched, then return NULL. */
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generator function for command completion. STATE lets us know whether
|
|
||||||
* to start from scratch; without any state (i.e. STATE == 0), then we
|
|
||||||
* start at the top of the list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
command_generator (const char *text, int state)
|
|
||||||
{
|
|
||||||
static int list_index, len;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
/* If this is a new word to complete, initialize now. This includes
|
|
||||||
saving the length of TEXT for efficiency, and initializing the index
|
|
||||||
variable to 0. */
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
list_index = 0;
|
|
||||||
len = strlen (text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the next name which partially matches from the command list. */
|
|
||||||
while ((name = cli_cmds[list_index].cmd) != NULL)
|
|
||||||
{
|
|
||||||
list_index++;
|
|
||||||
|
|
||||||
if (strncmp (name, text, len) == 0)
|
|
||||||
return (strdup(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no names matched, then return NULL. */
|
|
||||||
return ((char *)NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_args(char* line)
|
|
||||||
{
|
|
||||||
char* tmp = line;
|
|
||||||
char* last_delim = tmp;
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
/* Count how many elements will be extracted. */
|
|
||||||
while (*tmp)
|
|
||||||
{
|
|
||||||
if (' ' == *tmp)
|
|
||||||
{
|
|
||||||
if (last_delim+1 < tmp)
|
|
||||||
count++;
|
|
||||||
last_delim = tmp;
|
|
||||||
}
|
|
||||||
tmp++;
|
|
||||||
}
|
|
||||||
if (' ' != *last_delim)
|
|
||||||
count++;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Attempt to complete on the contents of TEXT. START and END bound the
|
|
||||||
* region of rl_line_buffer that contains the word to complete. TEXT is
|
|
||||||
* the word to complete. We can use the entire contents of rl_line_buffer
|
|
||||||
* in case we want to do some simple parsing. Return the array of matches,
|
|
||||||
* or NULL if there aren't any.
|
|
||||||
*/
|
|
||||||
char **
|
|
||||||
completion_fn (const char *text, int start, int end)
|
|
||||||
{
|
|
||||||
char **matches;
|
|
||||||
|
|
||||||
rl_attempted_completion_over = 1;
|
|
||||||
if (start == 0)
|
|
||||||
matches = rl_completion_matches (text, command_generator);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matches = (char **)NULL;
|
|
||||||
struct cli_cmd cmd;
|
|
||||||
int cmd_pos = 0;
|
|
||||||
while ((cmd = cli_cmds[cmd_pos++]).cmd)
|
|
||||||
{
|
|
||||||
if (strncmp(cmd.cmd, rl_line_buffer, strlen(cmd.cmd)) == 0)
|
|
||||||
{
|
|
||||||
int nargs = get_args(rl_line_buffer);
|
|
||||||
rl_compentry_func_t* completion_fn = cmd.completion_fns[nargs-2];
|
|
||||||
if (completion_fn)
|
|
||||||
matches = rl_completion_matches (text, completion_fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (matches);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cli_init(sd_bus *bus, const struct cli_cmd *cmds)
|
int cli_init(sd_bus *bus, const struct cli_cmd *cmds)
|
||||||
{
|
{
|
||||||
static const int sigs[] = {
|
static const int sigs[] = {
|
||||||
|
@ -674,31 +320,27 @@ int cli_init(sd_bus *bus, const struct cli_cmd *cmds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isatty(fileno(stdin))) {
|
r = sd_event_add_io(cli_event,
|
||||||
r = sd_event_add_io(cli_event,
|
|
||||||
&cli_stdin,
|
&cli_stdin,
|
||||||
fileno(stdin),
|
fileno(stdin),
|
||||||
EPOLLHUP | EPOLLERR | EPOLLIN,
|
EPOLLHUP | EPOLLERR | EPOLLIN,
|
||||||
cli_stdin_fn,
|
cli_stdin_fn,
|
||||||
NULL);
|
NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
cli_vERR(r);
|
cli_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
cli_rl = true;
|
|
||||||
|
|
||||||
rl_erase_empty_line = 1;
|
|
||||||
rl_attempted_completion_function = completion_fn;
|
|
||||||
rl_callback_handler_install(get_cli_prompt(), cli_handler_fn);
|
|
||||||
using_history();
|
|
||||||
read_history(get_history_filename());
|
|
||||||
rl_end_of_history(0, 0);
|
|
||||||
|
|
||||||
printf("\r");
|
|
||||||
rl_on_new_line();
|
|
||||||
rl_redisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli_rl = true;
|
||||||
|
|
||||||
|
rl_erase_empty_line = 1;
|
||||||
|
rl_callback_handler_install(NULL, cli_handler_fn);
|
||||||
|
|
||||||
|
rl_set_prompt(CLI_PROMPT);
|
||||||
|
printf("\r");
|
||||||
|
rl_on_new_line();
|
||||||
|
rl_redisplay();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -17,7 +17,49 @@
|
||||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ctl-sink.h"
|
#include <arpa/inet.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <systemd/sd-event.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "ctl.h"
|
||||||
|
#include "rtsp.h"
|
||||||
|
#include "shl_macro.h"
|
||||||
|
#include "shl_util.h"
|
||||||
|
#include "wfd.h"
|
||||||
|
|
||||||
|
struct ctl_sink {
|
||||||
|
sd_event *event;
|
||||||
|
|
||||||
|
char *target;
|
||||||
|
char *session;
|
||||||
|
char *url;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
size_t addr_size;
|
||||||
|
int fd;
|
||||||
|
sd_event_source *fd_source;
|
||||||
|
|
||||||
|
struct rtsp *rtsp;
|
||||||
|
|
||||||
|
bool connected : 1;
|
||||||
|
bool hup : 1;
|
||||||
|
|
||||||
|
uint32_t resolutions_cea;
|
||||||
|
uint32_t resolutions_vesa;
|
||||||
|
uint32_t resolutions_hh;
|
||||||
|
|
||||||
|
int hres;
|
||||||
|
int vres;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RTSP Session
|
* RTSP Session
|
||||||
|
@ -77,92 +119,53 @@ static void sink_handle_options(struct ctl_sink *s,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sink_handle_get_parameter(struct ctl_sink *s,
|
static void sink_handle_get_parameter(struct ctl_sink *s,
|
||||||
struct rtsp_message *m)
|
struct rtsp_message *m)
|
||||||
{
|
{
|
||||||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
|
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return cli_vERR(r);
|
return cli_vERR(r);
|
||||||
|
|
||||||
/* wfd_content_protection */
|
/* wfd_content_protection */
|
||||||
check_and_response_option("wfd_content_protection", "none");
|
if (rtsp_message_read(m, "{<>}", "wfd_content_protection") >= 0) {
|
||||||
GHashTable* protocol_extensions = s->protocol_extensions;
|
r = rtsp_message_append(rep, "{&}",
|
||||||
/* wfd_video_formats */
|
"wfd_content_protection: none");
|
||||||
gchar* wfd_video_formats = NULL;
|
if (r < 0)
|
||||||
if (protocol_extensions != NULL) {
|
return cli_vERR(r);
|
||||||
gchar* wfd_video_formats_extension = g_hash_table_lookup(protocol_extensions, WFD_VIDEO_FORMATS);
|
}
|
||||||
if (wfd_video_formats_extension != NULL) {
|
/* wfd_video_formats */
|
||||||
wfd_video_formats = wfd_video_formats_extension;
|
if (rtsp_message_read(m, "{<>}", "wfd_video_formats") >= 0) {
|
||||||
}
|
char wfd_video_formats[128];
|
||||||
}
|
sprintf(wfd_video_formats,
|
||||||
bool create_wfd_video_formats = wfd_video_formats == NULL;
|
"wfd_video_formats: 00 00 03 10 %08x %08x %08x 00 0000 0000 10 none none",
|
||||||
if (create_wfd_video_formats) {
|
s->resolutions_cea, s->resolutions_vesa, s->resolutions_hh);
|
||||||
gchar video_formats[128];
|
r = rtsp_message_append(rep, "{&}", wfd_video_formats);
|
||||||
sprintf(video_formats, "00 00 03 10 %08x %08x %08x 00 0000 0000 10 none none",
|
if (r < 0)
|
||||||
s->resolutions_cea, s->resolutions_vesa, s->resolutions_hh);
|
return cli_vERR(r);
|
||||||
wfd_video_formats = strdup(video_formats);
|
}
|
||||||
}
|
/* wfd_audio_codecs */
|
||||||
check_and_response_option(WFD_VIDEO_FORMATS, wfd_video_formats);
|
if (rtsp_message_read(m, "{<>}", "wfd_audio_codecs") >= 0) {
|
||||||
if (create_wfd_video_formats) {
|
r = rtsp_message_append(rep, "{&}",
|
||||||
g_free(wfd_video_formats);
|
"wfd_audio_codecs: AAC 00000007 00");
|
||||||
}
|
if (r < 0)
|
||||||
|
return cli_vERR(r);
|
||||||
|
}
|
||||||
|
/* wfd_client_rtp_ports */
|
||||||
|
if (rtsp_message_read(m, "{<>}", "wfd_client_rtp_ports") >= 0) {
|
||||||
|
r = rtsp_message_append(rep, "{&}",
|
||||||
|
"wfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play");
|
||||||
|
if (r < 0)
|
||||||
|
return cli_vERR(r);
|
||||||
|
}
|
||||||
|
|
||||||
/* wfd_audio_codecs */
|
rtsp_message_seal(rep);
|
||||||
gchar* wfd_audio_codecs = "AAC 00000007 00";
|
cli_debug("OUTGOING: %s\n", rtsp_message_get_raw(rep));
|
||||||
if (protocol_extensions != NULL) {
|
|
||||||
gchar* wfd_audio_codecs_extension = g_hash_table_lookup(protocol_extensions, WFD_AUDIO_CODECS);
|
|
||||||
if (wfd_audio_codecs_extension != NULL) {
|
|
||||||
wfd_audio_codecs = wfd_audio_codecs_extension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check_and_response_option(WFD_AUDIO_CODECS, wfd_audio_codecs);
|
|
||||||
|
|
||||||
/* wfd_client_rtp_ports */
|
r = rtsp_send(s->rtsp, rep);
|
||||||
char wfd_client_rtp_ports[128];
|
if (r < 0)
|
||||||
sprintf(wfd_client_rtp_ports, "RTP/AVP/UDP;unicast %d 0 mode=play", rstp_port);
|
return cli_vERR(r);
|
||||||
check_and_response_option("wfd_client_rtp_ports", wfd_client_rtp_ports);
|
|
||||||
|
|
||||||
if (protocol_extensions != NULL) {
|
|
||||||
GList* extension_keys = g_hash_table_get_keys(protocol_extensions);
|
|
||||||
for (int i = 0; i<g_list_length(extension_keys); i++) {
|
|
||||||
gchar* key = g_list_nth_data(extension_keys, i);
|
|
||||||
if (g_strcmp0(key, WFD_VIDEO_FORMATS) == 0
|
|
||||||
|| g_strcmp0(key, WFD_AUDIO_CODECS) == 0
|
|
||||||
|| g_strcmp0(key, WFD_UIBC_CAPABILITY) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
gchar* value = g_hash_table_lookup(protocol_extensions, key);
|
|
||||||
check_and_response_option(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wfd_uibc_capability */
|
|
||||||
if (uibc_option) {
|
|
||||||
gchar* wfd_uibc_capability = "input_category_list=GENERIC;"
|
|
||||||
"generic_cap_list=Mouse,SingleTouch;"
|
|
||||||
"hidc_cap_list=none;"
|
|
||||||
"port=none";
|
|
||||||
if (protocol_extensions != NULL) {
|
|
||||||
gchar* wfd_uibc_capability_extension = g_hash_table_lookup(protocol_extensions, WFD_UIBC_CAPABILITY);
|
|
||||||
if (wfd_uibc_capability_extension != NULL) {
|
|
||||||
wfd_uibc_capability = wfd_uibc_capability_extension;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check_and_response_option(WFD_UIBC_CAPABILITY, wfd_uibc_capability);
|
|
||||||
}
|
|
||||||
|
|
||||||
rtsp_message_seal(rep);
|
|
||||||
cli_debug("OUTGOING: %s\n", rtsp_message_get_raw(rep));
|
|
||||||
|
|
||||||
r = rtsp_send(s->rtsp, rep);
|
|
||||||
if (r < 0)
|
|
||||||
return cli_vERR(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check_rtsp_option(struct rtsp_message *m, char *option) {
|
|
||||||
return rtsp_message_read(m, "{<>}", option) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sink_setup_fn(struct rtsp *bus, struct rtsp_message *m, void *data)
|
static int sink_setup_fn(struct rtsp *bus, struct rtsp_message *m, void *data)
|
||||||
|
@ -224,7 +227,7 @@ static int sink_set_format(struct ctl_sink *s,
|
||||||
if (hres && vres) {
|
if (hres && vres) {
|
||||||
s->hres = hres;
|
s->hres = hres;
|
||||||
s->vres = vres;
|
s->vres = vres;
|
||||||
ctl_fn_sink_resolution_set(s);
|
ctl_fn_sink_resolution_set(s, hres, vres);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,8 +241,6 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||||
const char *trigger;
|
const char *trigger;
|
||||||
const char *url;
|
const char *url;
|
||||||
char *uibc_config;
|
|
||||||
const char *uibc_setting;
|
|
||||||
char *nu;
|
char *nu;
|
||||||
unsigned int cea_res, vesa_res, hh_res;
|
unsigned int cea_res, vesa_res, hh_res;
|
||||||
int r;
|
int r;
|
||||||
|
@ -272,49 +273,6 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* M4 (or any other) can pass presentation URLs */
|
|
||||||
r = rtsp_message_read(m, "{<&>}", "wfd_uibc_capability", &uibc_config);
|
|
||||||
if (r >= 0) {
|
|
||||||
if (!s->uibc_config || strcmp(s->uibc_config, uibc_config)) {
|
|
||||||
nu = strdup(uibc_config);
|
|
||||||
if (!nu)
|
|
||||||
return cli_vENOMEM();
|
|
||||||
|
|
||||||
free(s->uibc_config);
|
|
||||||
s->uibc_config = nu;
|
|
||||||
|
|
||||||
if (!strcasecmp(uibc_config, "none")) {
|
|
||||||
uibc_enabled = false;
|
|
||||||
} else {
|
|
||||||
char* token = strtok(uibc_config, ";");
|
|
||||||
|
|
||||||
while (token) {
|
|
||||||
if (sscanf(token, "port=%d", &uibc_port)) {
|
|
||||||
log_debug("UIBC port: %d\n", uibc_port);
|
|
||||||
if (uibc_option) {
|
|
||||||
uibc_enabled = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok(0, ";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* M4 (or any other) can pass presentation URLs */
|
|
||||||
r = rtsp_message_read(m, "{<s>}", "wfd_uibc_setting", &uibc_setting);
|
|
||||||
if (r >= 0) {
|
|
||||||
if (!s->uibc_setting || strcmp(s->uibc_setting, uibc_setting)) {
|
|
||||||
nu = strdup(uibc_setting);
|
|
||||||
if (!nu)
|
|
||||||
return cli_vENOMEM();
|
|
||||||
|
|
||||||
free(s->uibc_setting);
|
|
||||||
s->uibc_setting = nu;
|
|
||||||
cli_debug("uibc setting: %s\n", s->uibc_setting);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* M4 again */
|
/* M4 again */
|
||||||
r = rtsp_message_read(m, "{<****hhh>}", "wfd_video_formats",
|
r = rtsp_message_read(m, "{<****hhh>}", "wfd_video_formats",
|
||||||
&cea_res, &vesa_res, &hh_res);
|
&cea_res, &vesa_res, &hh_res);
|
||||||
|
@ -342,9 +300,9 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return cli_vERR(r);
|
return cli_vERR(r);
|
||||||
|
|
||||||
char rtsp_setup[128];
|
r = rtsp_message_append(rep, "<s>",
|
||||||
sprintf(rtsp_setup, "RTP/AVP/UDP;unicast;client_port=%d", rstp_port);
|
"Transport",
|
||||||
r = rtsp_message_append(rep, "<s>", "Transport", rtsp_setup);
|
"RTP/AVP/UDP;unicast;client_port=1991");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return cli_vERR(r);
|
return cli_vERR(r);
|
||||||
|
|
||||||
|
@ -570,8 +528,6 @@ void ctl_sink_free(struct ctl_sink *s)
|
||||||
free(s->session);
|
free(s->session);
|
||||||
free(s->url);
|
free(s->url);
|
||||||
sd_event_unref(s->event);
|
sd_event_unref(s->event);
|
||||||
if (s->protocol_extensions)
|
|
||||||
g_hash_table_destroy(s->protocol_extensions);
|
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
|
||||||
*
|
|
||||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* MiracleCast is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CTL_SINK_H
|
|
||||||
#define CTL_SINK_H
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <systemd/sd-event.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include "ctl.h"
|
|
||||||
|
|
||||||
#include "rtsp.h"
|
|
||||||
#include "shl_macro.h"
|
|
||||||
#include "shl_util.h"
|
|
||||||
#include "wfd.h"
|
|
||||||
|
|
||||||
#define WFD_VIDEO_FORMATS "wfd_video_formats"
|
|
||||||
#define WFD_AUDIO_CODECS "wfd_audio_codecs"
|
|
||||||
#define WFD_UIBC_CAPABILITY "wfd_uibc_capability"
|
|
||||||
|
|
||||||
extern int rstp_port;
|
|
||||||
extern bool uibc_option;
|
|
||||||
extern bool uibc_enabled;
|
|
||||||
extern int uibc_port;
|
|
||||||
|
|
||||||
struct ctl_sink {
|
|
||||||
sd_event *event;
|
|
||||||
|
|
||||||
char *target;
|
|
||||||
char *session;
|
|
||||||
char *url;
|
|
||||||
char *uibc_config;
|
|
||||||
char *uibc_setting;
|
|
||||||
struct sockaddr_storage addr;
|
|
||||||
size_t addr_size;
|
|
||||||
int fd;
|
|
||||||
sd_event_source *fd_source;
|
|
||||||
|
|
||||||
struct rtsp *rtsp;
|
|
||||||
|
|
||||||
bool connected : 1;
|
|
||||||
bool hup : 1;
|
|
||||||
|
|
||||||
uint32_t resolutions_cea;
|
|
||||||
uint32_t resolutions_vesa;
|
|
||||||
uint32_t resolutions_hh;
|
|
||||||
|
|
||||||
int hres;
|
|
||||||
int vres;
|
|
||||||
|
|
||||||
GHashTable* protocol_extensions;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool check_rtsp_option(struct rtsp_message *m, char *option);
|
|
||||||
|
|
||||||
#define check_and_response_option(option, response) \
|
|
||||||
if (check_rtsp_option(m, option)) { \
|
|
||||||
char option_response[512]; \
|
|
||||||
sprintf(option_response, "%s: %s", option, response); \
|
|
||||||
r = rtsp_message_append(rep, "{&}", option_response); \
|
|
||||||
if (r < 0) {\
|
|
||||||
return cli_vERR(r); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CTL_SINK_H */
|
|
|
@ -414,8 +414,6 @@ static int ctl_link_parse_properties(struct ctl_link *l,
|
||||||
bool p2p_scanning_set = false;
|
bool p2p_scanning_set = false;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
int p2p_scanning, r;
|
int p2p_scanning, r;
|
||||||
bool managed_set = false;
|
|
||||||
int managed;
|
|
||||||
|
|
||||||
if (!l || !m)
|
if (!l || !m)
|
||||||
return cli_EINVAL();
|
return cli_EINVAL();
|
||||||
|
@ -446,13 +444,6 @@ static int ctl_link_parse_properties(struct ctl_link *l,
|
||||||
&friendly_name);
|
&friendly_name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return cli_log_parser(r);
|
return cli_log_parser(r);
|
||||||
} else if (!strcmp(t, "Managed")) {
|
|
||||||
r = bus_message_read_basic_variant(m, "b",
|
|
||||||
&managed);
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_parser(r);
|
|
||||||
|
|
||||||
managed_set = true;
|
|
||||||
} else if (!strcmp(t, "P2PScanning")) {
|
} else if (!strcmp(t, "P2PScanning")) {
|
||||||
r = bus_message_read_basic_variant(m, "b",
|
r = bus_message_read_basic_variant(m, "b",
|
||||||
&p2p_scanning);
|
&p2p_scanning);
|
||||||
|
@ -503,9 +494,6 @@ static int ctl_link_parse_properties(struct ctl_link *l,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (managed_set)
|
|
||||||
l->managed = managed;
|
|
||||||
|
|
||||||
if (p2p_scanning_set)
|
if (p2p_scanning_set)
|
||||||
l->p2p_scanning = p2p_scanning;
|
l->p2p_scanning = p2p_scanning;
|
||||||
|
|
||||||
|
@ -632,63 +620,6 @@ int ctl_link_set_wfd_subelements(struct ctl_link *l, const char *val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctl_link_set_managed(struct ctl_link *l, bool val)
|
|
||||||
{
|
|
||||||
_sd_bus_message_unref_ sd_bus_message *m = NULL;
|
|
||||||
_sd_bus_error_free_ sd_bus_error err = SD_BUS_ERROR_NULL;
|
|
||||||
_shl_free_ char *node = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (!l)
|
|
||||||
return cli_EINVAL();
|
|
||||||
if (l->managed == val)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = sd_bus_path_encode("/org/freedesktop/miracle/wifi/link",
|
|
||||||
l->label,
|
|
||||||
&node);
|
|
||||||
if (r < 0)
|
|
||||||
return cli_ERR(r);
|
|
||||||
|
|
||||||
r = sd_bus_message_new_method_call(l->w->bus,
|
|
||||||
&m,
|
|
||||||
"org.freedesktop.miracle.wifi",
|
|
||||||
node,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"Set");
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_create(r);
|
|
||||||
|
|
||||||
r = sd_bus_message_append(m, "ss",
|
|
||||||
"org.freedesktop.miracle.wifi.Link",
|
|
||||||
"Managed");
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_create(r);
|
|
||||||
|
|
||||||
r = sd_bus_message_open_container(m, 'v', "b");
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_create(r);
|
|
||||||
|
|
||||||
r = sd_bus_message_append(m, "b", val);
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_create(r);
|
|
||||||
|
|
||||||
r = sd_bus_message_close_container(m);
|
|
||||||
if (r < 0)
|
|
||||||
return cli_log_create(r);
|
|
||||||
|
|
||||||
r = sd_bus_call(l->w->bus, m, 0, &err, NULL);
|
|
||||||
if (r < 0) {
|
|
||||||
cli_error("cannot change managed state on link %s to %d: %s",
|
|
||||||
l->label, val, bus_error_message(&err, r));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
l->managed = val;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ctl_link_set_p2p_scanning(struct ctl_link *l, bool val)
|
int ctl_link_set_p2p_scanning(struct ctl_link *l, bool val)
|
||||||
{
|
{
|
||||||
_sd_bus_message_unref_ sd_bus_message *m = NULL;
|
_sd_bus_message_unref_ sd_bus_message *m = NULL;
|
||||||
|
@ -823,7 +754,7 @@ static int ctl_wifi_parse_peer(struct ctl_wifi *w,
|
||||||
|
|
||||||
l = ctl_wifi_find_link_by_peer(w, label);
|
l = ctl_wifi_find_link_by_peer(w, label);
|
||||||
if (!l)
|
if (!l)
|
||||||
return 0;
|
return cli_EINVAL();
|
||||||
|
|
||||||
r = ctl_peer_new(&p, l, label);
|
r = ctl_peer_new(&p, l, label);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CTL_CTL_H
|
|
||||||
#define CTL_CTL_H
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -32,22 +29,13 @@
|
||||||
#include "shl_dlist.h"
|
#include "shl_dlist.h"
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
|
|
||||||
/* *sigh* readline doesn't include all their deps, so put them last */
|
#ifndef CTL_CTL_H
|
||||||
#include <readline/history.h>
|
#define CTL_CTL_H
|
||||||
#include <readline/readline.h>
|
|
||||||
#include <readline/rltypedefs.h>
|
|
||||||
|
|
||||||
struct ctl_wifi;
|
struct ctl_wifi;
|
||||||
struct ctl_link;
|
struct ctl_link;
|
||||||
struct ctl_peer;
|
struct ctl_peer;
|
||||||
|
|
||||||
char* get_history_filename ();
|
|
||||||
struct ctl_wifi * get_wifi ();
|
|
||||||
char * links_peers_generator (const char *text, int state);
|
|
||||||
char * links_generator (const char *text, int state);
|
|
||||||
char * peers_generator (const char *text, int state);
|
|
||||||
char * yes_no_generator (const char *text, int state);
|
|
||||||
|
|
||||||
/* wifi handling */
|
/* wifi handling */
|
||||||
|
|
||||||
struct ctl_peer {
|
struct ctl_peer {
|
||||||
|
@ -83,7 +71,6 @@ struct ctl_link {
|
||||||
unsigned int ifindex;
|
unsigned int ifindex;
|
||||||
char *ifname;
|
char *ifname;
|
||||||
char *friendly_name;
|
char *friendly_name;
|
||||||
bool managed;
|
|
||||||
char *wfd_subelements;
|
char *wfd_subelements;
|
||||||
bool p2p_scanning;
|
bool p2p_scanning;
|
||||||
};
|
};
|
||||||
|
@ -91,7 +78,6 @@ struct ctl_link {
|
||||||
#define link_from_dlist(_l) shl_dlist_entry((_l), struct ctl_link, list);
|
#define link_from_dlist(_l) shl_dlist_entry((_l), struct ctl_link, list);
|
||||||
|
|
||||||
int ctl_link_set_friendly_name(struct ctl_link *l, const char *name);
|
int ctl_link_set_friendly_name(struct ctl_link *l, const char *name);
|
||||||
int ctl_link_set_managed(struct ctl_link *l, bool val);
|
|
||||||
int ctl_link_set_wfd_subelements(struct ctl_link *l, const char *val);
|
int ctl_link_set_wfd_subelements(struct ctl_link *l, const char *val);
|
||||||
int ctl_link_set_p2p_scanning(struct ctl_link *l, bool val);
|
int ctl_link_set_p2p_scanning(struct ctl_link *l, bool val);
|
||||||
|
|
||||||
|
@ -134,11 +120,9 @@ bool ctl_sink_is_closed(struct ctl_sink *s);
|
||||||
|
|
||||||
/* CLI handling */
|
/* CLI handling */
|
||||||
|
|
||||||
extern unsigned int cli_max_sev;
|
extern int cli_max_sev;
|
||||||
void cli_printv(const char *fmt, bool prefix_time, va_list args);
|
void cli_printv(const char *fmt, va_list args);
|
||||||
void cli_printf_time_prefix();
|
|
||||||
void cli_printf(const char *fmt, ...);
|
void cli_printf(const char *fmt, ...);
|
||||||
void cli_command_printf(const char *fmt, ...);
|
|
||||||
|
|
||||||
#define cli_log(_fmt, ...) \
|
#define cli_log(_fmt, ...) \
|
||||||
cli_printf(_fmt "\n", ##__VA_ARGS__)
|
cli_printf(_fmt "\n", ##__VA_ARGS__)
|
||||||
|
@ -202,6 +186,7 @@ void cli_command_printf(const char *fmt, ...);
|
||||||
#define CLI_BLUE "\x1B[0;94m"
|
#define CLI_BLUE "\x1B[0;94m"
|
||||||
#define CLI_BOLDGRAY "\x1B[1;30m"
|
#define CLI_BOLDGRAY "\x1B[1;30m"
|
||||||
#define CLI_BOLDWHITE "\x1B[1;37m"
|
#define CLI_BOLDWHITE "\x1B[1;37m"
|
||||||
|
#define CLI_PROMPT CLI_BLUE "[miraclectl] # " CLI_DEFAULT
|
||||||
|
|
||||||
struct cli_cmd {
|
struct cli_cmd {
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
|
@ -219,7 +204,6 @@ struct cli_cmd {
|
||||||
int argc;
|
int argc;
|
||||||
int (*fn) (char **args, unsigned int n);
|
int (*fn) (char **args, unsigned int n);
|
||||||
const char *desc;
|
const char *desc;
|
||||||
rl_compentry_func_t *completion_fns[2];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern sd_event *cli_event;
|
extern sd_event *cli_event;
|
||||||
|
@ -229,14 +213,13 @@ extern unsigned int wfd_supported_res_cea;
|
||||||
extern unsigned int wfd_supported_res_vesa;
|
extern unsigned int wfd_supported_res_vesa;
|
||||||
extern unsigned int wfd_supported_res_hh;
|
extern unsigned int wfd_supported_res_hh;
|
||||||
|
|
||||||
char* get_cli_prompt();
|
|
||||||
int cli_init(sd_bus *bus, const struct cli_cmd *cmds);
|
int cli_init(sd_bus *bus, const struct cli_cmd *cmds);
|
||||||
void cli_destroy(void);
|
void cli_destroy(void);
|
||||||
int cli_run(void);
|
int cli_run(void);
|
||||||
void cli_exit(void);
|
void cli_exit(void);
|
||||||
bool cli_running(void);
|
bool cli_running(void);
|
||||||
|
|
||||||
int cli_help(const struct cli_cmd *cmds, int whitespace);
|
int cli_help(const struct cli_cmd *cmds);
|
||||||
int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n);
|
int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n);
|
||||||
|
|
||||||
/* callback functions */
|
/* callback functions */
|
||||||
|
@ -257,7 +240,7 @@ void ctl_fn_link_free(struct ctl_link *l);
|
||||||
|
|
||||||
void ctl_fn_sink_connected(struct ctl_sink *s);
|
void ctl_fn_sink_connected(struct ctl_sink *s);
|
||||||
void ctl_fn_sink_disconnected(struct ctl_sink *s);
|
void ctl_fn_sink_disconnected(struct ctl_sink *s);
|
||||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s);
|
void ctl_fn_sink_resolution_set(struct ctl_sink *s, int hres, int vres);
|
||||||
|
|
||||||
void cli_fn_help(void);
|
void cli_fn_help(void);
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
inc = include_directories('../..')
|
|
||||||
deps = [libsystemd, libmiracle_shared_dep, glib2, m]
|
|
||||||
if readline.found()
|
|
||||||
deps += readline
|
|
||||||
endif
|
|
||||||
|
|
||||||
miracle_wifictl_srcs = ['ctl-cli.c', 'ctl-wifi.c', 'wifictl.c']
|
|
||||||
executable('miracle-wifictl', miracle_wifictl_srcs,
|
|
||||||
install: true,
|
|
||||||
include_directories: inc,
|
|
||||||
dependencies: deps
|
|
||||||
)
|
|
||||||
|
|
||||||
miracle_sinkctl_srcs = ['ctl-cli.c',
|
|
||||||
'ctl-sink.c',
|
|
||||||
'ctl-wifi.c',
|
|
||||||
'sinkctl.c',
|
|
||||||
'wfd.c'
|
|
||||||
]
|
|
||||||
executable('miracle-sinkctl', miracle_sinkctl_srcs,
|
|
||||||
install: true,
|
|
||||||
include_directories: inc,
|
|
||||||
dependencies: deps
|
|
||||||
)
|
|
|
@ -17,8 +17,6 @@
|
||||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
@ -32,27 +30,15 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include <systemd/sd-event.h>
|
#include <systemd/sd-event.h>
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
#include <systemd/sd-journal.h>
|
#include <systemd/sd-journal.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "ctl.h"
|
#include "ctl.h"
|
||||||
#include "ctl-sink.h"
|
|
||||||
#include "wfd.h"
|
#include "wfd.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_util.h"
|
#include "shl_util.h"
|
||||||
#include "util.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <readline/readline.h>
|
|
||||||
|
|
||||||
#define HISTORY_FILENAME ".miracle-sink.history"
|
|
||||||
|
|
||||||
#define CLI_PROMPT "\001" CLI_BLUE "\002" "[sinkctl] # " "\001" CLI_DEFAULT "\002"
|
|
||||||
|
|
||||||
static sd_bus *bus;
|
static sd_bus *bus;
|
||||||
static struct ctl_wifi *wifi;
|
static struct ctl_wifi *wifi;
|
||||||
static struct ctl_sink *sink;
|
static struct ctl_sink *sink;
|
||||||
|
@ -67,41 +53,11 @@ static struct ctl_link *running_link;
|
||||||
static struct ctl_peer *running_peer;
|
static struct ctl_peer *running_peer;
|
||||||
static struct ctl_peer *pending_peer;
|
static struct ctl_peer *pending_peer;
|
||||||
|
|
||||||
void launch_player(struct ctl_sink *s);
|
|
||||||
|
|
||||||
char *gst_scale_res;
|
char *gst_scale_res;
|
||||||
int gst_audio_en = 1;
|
int gst_audio_en = 1;
|
||||||
static const int DEFAULT_RSTP_PORT = 7236;
|
unsigned int wfd_supported_res_cea = 0x0000001f; /* up to 720x576 */
|
||||||
bool uibc_option;
|
unsigned int wfd_supported_res_vesa = 0x00000003; /* up to 800x600 */
|
||||||
bool uibc_enabled;
|
unsigned int wfd_supported_res_hh = 0x00000000; /* not supported */
|
||||||
bool external_player;
|
|
||||||
int rstp_port;
|
|
||||||
int uibc_port;
|
|
||||||
char* player;
|
|
||||||
GHashTable* protocol_extensions;
|
|
||||||
|
|
||||||
unsigned int wfd_supported_res_cea = 0x0001ffff;
|
|
||||||
unsigned int wfd_supported_res_vesa = 0x1fffffff;
|
|
||||||
unsigned int wfd_supported_res_hh = 0x00001fff;
|
|
||||||
|
|
||||||
struct ctl_wifi *get_wifi()
|
|
||||||
{
|
|
||||||
return wifi;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* get_cli_prompt()
|
|
||||||
{
|
|
||||||
return CLI_PROMPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get history filename
|
|
||||||
*/
|
|
||||||
|
|
||||||
char* get_history_filename()
|
|
||||||
{
|
|
||||||
return HISTORY_FILENAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd list
|
* cmd list
|
||||||
|
@ -116,28 +72,27 @@ static int cmd_list(char **args, unsigned int n)
|
||||||
|
|
||||||
/* list links */
|
/* list links */
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s\n",
|
||||||
"LINK", "INTERFACE", "FRIENDLY-NAME", "MANAGED");
|
"LINK", "INTERFACE", "FRIENDLY-NAME");
|
||||||
|
|
||||||
shl_dlist_for_each(i, &wifi->links) {
|
shl_dlist_for_each(i, &wifi->links) {
|
||||||
l = link_from_dlist(i);
|
l = link_from_dlist(i);
|
||||||
++link_cnt;
|
++link_cnt;
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s\n",
|
||||||
l->label,
|
l->label,
|
||||||
shl_isempty(l->ifname) ?
|
shl_isempty(l->ifname) ?
|
||||||
"<unknown>" : l->ifname,
|
"<unknown>" : l->ifname,
|
||||||
shl_isempty(l->friendly_name) ?
|
shl_isempty(l->friendly_name) ?
|
||||||
"<unknown>" : l->friendly_name,
|
"<unknown>" : l->friendly_name);
|
||||||
l->managed ? "yes": "no");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_command_printf("\n");
|
cli_printf("\n");
|
||||||
|
|
||||||
/* list peers */
|
/* list peers */
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s %-10s\n",
|
||||||
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
|
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
|
||||||
|
|
||||||
shl_dlist_for_each(i, &wifi->links) {
|
shl_dlist_for_each(i, &wifi->links) {
|
||||||
l = link_from_dlist(i);
|
l = link_from_dlist(i);
|
||||||
|
@ -146,16 +101,16 @@ static int cmd_list(char **args, unsigned int n)
|
||||||
p = peer_from_dlist(j);
|
p = peer_from_dlist(j);
|
||||||
++peer_cnt;
|
++peer_cnt;
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s %-10s\n",
|
||||||
p->l->label,
|
p->l->label,
|
||||||
p->label,
|
p->label,
|
||||||
shl_isempty(p->friendly_name) ?
|
shl_isempty(p->friendly_name) ?
|
||||||
"<unknown>" : p->friendly_name,
|
"<unknown>" : p->friendly_name,
|
||||||
p->connected ? "yes" : "no");
|
p->connected ? "yes" : "no");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_command_printf("\n %u peers and %u links listed.\n", peer_cnt, link_cnt);
|
cli_printf("\n %u peers and %u links listed.\n", peer_cnt, link_cnt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -174,81 +129,45 @@ static int cmd_show(char **args, unsigned int n)
|
||||||
!(p = ctl_wifi_find_peer(wifi, args[0])) &&
|
!(p = ctl_wifi_find_peer(wifi, args[0])) &&
|
||||||
!(l = ctl_wifi_search_link(wifi, args[0])) &&
|
!(l = ctl_wifi_search_link(wifi, args[0])) &&
|
||||||
!(p = ctl_wifi_search_peer(wifi, args[0]))) {
|
!(p = ctl_wifi_search_peer(wifi, args[0]))) {
|
||||||
cli_error("unknown %s", args[0]);
|
cli_error("unknown link or peer %s", args[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l) {
|
if (l) {
|
||||||
cli_command_printf("Link=%s\n", l->label);
|
cli_printf("Link=%s\n", l->label);
|
||||||
if (l->ifindex > 0)
|
if (l->ifindex > 0)
|
||||||
cli_command_printf("InterfaceIndex=%u\n", l->ifindex);
|
cli_printf("InterfaceIndex=%u\n", l->ifindex);
|
||||||
if (l->ifname && *l->ifname)
|
if (l->ifname && *l->ifname)
|
||||||
cli_command_printf("InterfaceName=%s\n", l->ifname);
|
cli_printf("InterfaceName=%s\n", l->ifname);
|
||||||
if (l->friendly_name && *l->friendly_name)
|
if (l->friendly_name && *l->friendly_name)
|
||||||
cli_command_printf("FriendlyName=%s\n", l->friendly_name);
|
cli_printf("FriendlyName=%s\n", l->friendly_name);
|
||||||
cli_command_printf("P2PScanning=%d\n", l->p2p_scanning);
|
cli_printf("P2PScanning=%d\n", l->p2p_scanning);
|
||||||
if (l->wfd_subelements && *l->wfd_subelements)
|
if (l->wfd_subelements && *l->wfd_subelements)
|
||||||
cli_command_printf("WfdSubelements=%s\n", l->wfd_subelements);
|
cli_printf("WfdSubelements=%s\n", l->wfd_subelements);
|
||||||
cli_command_printf("Managed=%d\n", l->managed);
|
|
||||||
} else if (p) {
|
} else if (p) {
|
||||||
cli_command_printf("Peer=%s\n", p->label);
|
cli_printf("Peer=%s\n", p->label);
|
||||||
if (p->p2p_mac && *p->p2p_mac)
|
if (p->p2p_mac && *p->p2p_mac)
|
||||||
cli_command_printf("P2PMac=%s\n", p->p2p_mac);
|
cli_printf("P2PMac=%s\n", p->p2p_mac);
|
||||||
if (p->friendly_name && *p->friendly_name)
|
if (p->friendly_name && *p->friendly_name)
|
||||||
cli_command_printf("FriendlyName=%s\n", p->friendly_name);
|
cli_printf("FriendlyName=%s\n", p->friendly_name);
|
||||||
cli_command_printf("Connected=%d\n", p->connected);
|
cli_printf("Connected=%d\n", p->connected);
|
||||||
if (p->interface && *p->interface)
|
if (p->interface && *p->interface)
|
||||||
cli_command_printf("Interface=%s\n", p->interface);
|
cli_printf("Interface=%s\n", p->interface);
|
||||||
if (p->local_address && *p->local_address)
|
if (p->local_address && *p->local_address)
|
||||||
cli_command_printf("LocalAddress=%s\n", p->local_address);
|
cli_printf("LocalAddress=%s\n", p->local_address);
|
||||||
if (p->remote_address && *p->remote_address)
|
if (p->remote_address && *p->remote_address)
|
||||||
cli_command_printf("RemoteAddress=%s\n", p->remote_address);
|
cli_printf("RemoteAddress=%s\n", p->remote_address);
|
||||||
if (p->wfd_subelements && *p->wfd_subelements)
|
if (p->wfd_subelements && *p->wfd_subelements)
|
||||||
cli_command_printf("WfdSubelements=%s\n", p->wfd_subelements);
|
cli_printf("WfdSubelements=%s\n", p->wfd_subelements);
|
||||||
} else {
|
} else {
|
||||||
cli_command_printf("Show what?\n");
|
cli_printf("Show what?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* cmd: set-friendly-name
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int cmd_set_friendly_name(char **args, unsigned int n)
|
|
||||||
{
|
|
||||||
struct ctl_link *l = NULL;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
if (n < 1) {
|
|
||||||
cli_command_printf("To what?\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > 1) {
|
|
||||||
l = ctl_wifi_search_link(wifi, args[0]);
|
|
||||||
if (!l) {
|
|
||||||
cli_error("unknown link %s", args[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = args[1];
|
|
||||||
} else {
|
|
||||||
name = args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
l = l ? : running_link;
|
|
||||||
if (!l) {
|
|
||||||
cli_error("no running link");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctl_link_set_friendly_name(l, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd: run
|
* cmd: run
|
||||||
*/
|
*/
|
||||||
|
@ -279,11 +198,6 @@ static int cmd_run(char **args, unsigned int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!l->managed) {
|
|
||||||
cli_printf("link %s not managed\n", l->label);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_on(l);
|
run_on(l);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -314,37 +228,11 @@ static int cmd_bind(char **args, unsigned int n)
|
||||||
if (!l)
|
if (!l)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!l->managed) {
|
|
||||||
cli_printf("link %s not managed\n", l->label);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_on(l);
|
run_on(l);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* cmd: set-managed
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int cmd_set_managed(char **args, unsigned int n)
|
|
||||||
{
|
|
||||||
struct ctl_link *l = NULL;
|
|
||||||
bool managed = true;
|
|
||||||
|
|
||||||
l = ctl_wifi_search_link(wifi, args[0]);
|
|
||||||
if (!l) {
|
|
||||||
cli_error("unknown link %s", args[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(args[1], "no")) {
|
|
||||||
managed = false;
|
|
||||||
}
|
|
||||||
return ctl_link_set_managed(l, managed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd: quit/exit
|
* cmd: quit/exit
|
||||||
*/
|
*/
|
||||||
|
@ -437,22 +325,22 @@ static int sink_timeout_fn(sd_event_source *s, uint64_t usec, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct cli_cmd cli_cmds[] = {
|
static const struct cli_cmd cli_cmds[] = {
|
||||||
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects", {NULL} },
|
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects" },
|
||||||
{ "show", "<link|peer>", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information", {links_peers_generator, NULL} },
|
{ "show", "<link|peer>", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information" },
|
||||||
{ "run", "<link>", CLI_M, CLI_EQUAL, 1, cmd_run, "Run sink on given link", {links_generator, NULL} },
|
{ "run", "<link>", CLI_M, CLI_EQUAL, 1, cmd_run, "Run sink on given link" },
|
||||||
{ "bind", "<link>", CLI_M, CLI_EQUAL, 1, cmd_bind, "Like 'run' but bind the link name to run when it is hotplugged", {links_generator, NULL} },
|
{ "bind", "<link>", CLI_M, CLI_EQUAL, 1, cmd_bind, "Like 'run' but bind the link name to run when it is hotplugged" },
|
||||||
{ "set-friendly-name", "[link] <name>", CLI_M, CLI_LESS, 2, cmd_set_friendly_name, "Set friendly name of an object", {links_generator, NULL} },
|
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program" },
|
||||||
{ "set-managed", "<link> <yes|no>", CLI_M, CLI_EQUAL, 2, cmd_set_managed, "Manage or unmnage a link", {links_generator, yes_no_generator} },
|
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL },
|
||||||
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program", {NULL} },
|
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" },
|
||||||
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL, {NULL} },
|
|
||||||
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help", {NULL} },
|
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void spawn_gst(struct ctl_sink *s)
|
static void spawn_gst(int hres, int vres)
|
||||||
{
|
{
|
||||||
|
char *argv[64];
|
||||||
|
char resolution[64];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fd_journal;
|
int fd_journal, i;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
|
|
||||||
if (sink_pid > 0)
|
if (sink_pid > 0)
|
||||||
|
@ -467,113 +355,43 @@ static void spawn_gst(struct ctl_sink *s)
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
/* redirect stdout/stderr to journal */
|
/* redirect stdout/stderr to journal */
|
||||||
fd_journal = sd_journal_stream_fd("miracle-sinkctl-gst",
|
fd_journal = sd_journal_stream_fd("miracle-sinkctl-gst",
|
||||||
LOG_DEBUG,
|
LOG_INFO,
|
||||||
false);
|
false);
|
||||||
if (fd_journal >= 0) {
|
if (fd_journal >= 0) {
|
||||||
/* dup journal-fd to stdout and stderr */
|
/* dup journal-fd to stdout and stderr */
|
||||||
dup2(fd_journal, 1);
|
dup2(fd_journal, 1);
|
||||||
dup2(fd_journal, 2);
|
dup2(fd_journal, 2);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
|
||||||
/* no journal? redirect stdout to parent's stderr */
|
/* no journal? redirect stdout to parent's stderr */
|
||||||
dup2(2, 1);
|
dup2(2, 1);
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
launch_player(s);
|
i = 0;
|
||||||
|
argv[i++] = (char*) BUILD_BINDIR "/miracle-gst.sh";
|
||||||
|
if (cli_max_sev >= 7)
|
||||||
|
argv[i++] = "-d 3";
|
||||||
|
if (gst_audio_en)
|
||||||
|
argv[i++] = "-a";
|
||||||
|
if (gst_scale_res) {
|
||||||
|
argv[i++] = "-s";
|
||||||
|
argv[i++] = gst_scale_res;
|
||||||
|
}
|
||||||
|
if (hres && vres) {
|
||||||
|
sprintf(resolution, "%dx%d", hres, vres);
|
||||||
|
argv[i++] = "-r";
|
||||||
|
argv[i++] = resolution;
|
||||||
|
}
|
||||||
|
argv[i] = NULL;
|
||||||
|
|
||||||
|
execve(argv[0], argv, environ);
|
||||||
_exit(1);
|
_exit(1);
|
||||||
} else {
|
} else {
|
||||||
sink_pid = pid;
|
sink_pid = pid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void launch_player(struct ctl_sink *s) {
|
|
||||||
char *argv[64];
|
|
||||||
char resolution[64];
|
|
||||||
char port[64];
|
|
||||||
char uibc_portStr[64];
|
|
||||||
int i = 0;
|
|
||||||
if (!external_player) {
|
|
||||||
if (uibc_enabled) {
|
|
||||||
player = "uibc-viewer";
|
|
||||||
} else {
|
|
||||||
player = "miracle-gst";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[i++] = player;
|
|
||||||
if (uibc_enabled) {
|
|
||||||
argv[i++] = s->target;
|
|
||||||
sprintf(uibc_portStr, "%d", uibc_port);
|
|
||||||
argv[i++] = uibc_portStr;
|
|
||||||
}
|
|
||||||
if (gst_debug) {
|
|
||||||
argv[i++] = "-d";
|
|
||||||
argv[i++] = gst_debug;
|
|
||||||
} else if (cli_max_sev >= LOG_DEBUG) {
|
|
||||||
argv[i++] = "-d";
|
|
||||||
argv[i++] = "3";
|
|
||||||
}
|
|
||||||
if (gst_audio_en)
|
|
||||||
argv[i++] = "-a";
|
|
||||||
if (gst_scale_res) {
|
|
||||||
argv[i++] = "-s";
|
|
||||||
argv[i++] = gst_scale_res;
|
|
||||||
}
|
|
||||||
argv[i++] = "-p";
|
|
||||||
sprintf(port, "%d", rstp_port);
|
|
||||||
argv[i++] = port;
|
|
||||||
|
|
||||||
if (s->hres && s->vres) {
|
|
||||||
sprintf(resolution, "%dx%d", s->hres, s->vres);
|
|
||||||
argv[i++] = "-r";
|
|
||||||
argv[i++] = resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[i] = NULL;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
size_t size = 0;
|
|
||||||
while (argv[i]) {
|
|
||||||
size += strlen(argv[i++]) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* player_command = malloc(size);
|
|
||||||
i = 0;
|
|
||||||
strcpy(player_command, argv[i++]);
|
|
||||||
while (argv[i]) {
|
|
||||||
strcat(player_command, " ");
|
|
||||||
strcat(player_command, argv[i++]);
|
|
||||||
}
|
|
||||||
log_debug("player command: %s", player_command);
|
|
||||||
if (execvpe(argv[0], argv, environ) < 0) {
|
|
||||||
cli_debug("stream player failed (%d): %m", errno);
|
|
||||||
int i = 0;
|
|
||||||
cli_debug("printing environment: ");
|
|
||||||
while (environ[i]) {
|
|
||||||
cli_debug("%s", environ[i++]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void launch_uibc_daemon(int port) {
|
|
||||||
char *argv[64];
|
|
||||||
char portStr[64];
|
|
||||||
int i = 0;
|
|
||||||
argv[i++] = "miracle-uibcctl";
|
|
||||||
argv[i++] = "localhost";
|
|
||||||
sprintf(portStr, "%d", port);
|
|
||||||
argv[i++] = portStr;
|
|
||||||
argv[i] = NULL;
|
|
||||||
|
|
||||||
cli_debug("uibc daemon: %s", argv[0]);
|
|
||||||
execvpe(argv[0], argv, environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kill_gst(void)
|
static void kill_gst(void)
|
||||||
{
|
{
|
||||||
if (sink_pid <= 0)
|
if (sink_pid <= 0)
|
||||||
|
@ -600,11 +418,11 @@ void ctl_fn_sink_disconnected(struct ctl_sink *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s)
|
void ctl_fn_sink_resolution_set(struct ctl_sink *s, int hres, int vres)
|
||||||
{
|
{
|
||||||
cli_printf("SINK set resolution %dx%d\n", s->hres, s->vres);
|
cli_printf("SINK set resolution %dx%d\n", hres, vres);
|
||||||
if (sink_connected)
|
if (sink_connected)
|
||||||
spawn_gst(s);
|
spawn_gst(hres, vres);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctl_fn_peer_new(struct ctl_peer *p)
|
void ctl_fn_peer_new(struct ctl_peer *p)
|
||||||
|
@ -783,29 +601,20 @@ void cli_fn_help()
|
||||||
*/
|
*/
|
||||||
printf("%s [OPTIONS...] ...\n\n"
|
printf("%s [OPTIONS...] ...\n\n"
|
||||||
"Control a dedicated local sink via MiracleCast.\n"
|
"Control a dedicated local sink via MiracleCast.\n"
|
||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --help-commands Show available commands\n"
|
" --version Show package version\n"
|
||||||
" --version Show package version\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
" --audio <0/1> Enable audio support (default %d)\n"
|
||||||
" --log-time Prefix log-messages with timestamp\n"
|
" --scale WxH Scale to resolution\n"
|
||||||
" --log-date-time Prefix log-messages with date time\n"
|
" --res <n,n,n> Supported resolutions masks (CEA, VESA, HH)\n"
|
||||||
|
" default CEA %08X\n"
|
||||||
|
" default VESA %08X\n"
|
||||||
|
" default HH %08X\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --log-journal-level <lvl> Maximum level for journal log messages\n"
|
, program_invocation_short_name, gst_audio_en,
|
||||||
" --gst-debug [cat:]lvl[,...] List of categories an level of debug\n"
|
|
||||||
" --audio <0/1> Enable audio support (default %d)\n"
|
|
||||||
" --scale WxH Scale to resolution\n"
|
|
||||||
" -p --port <port> Port for rtsp (default %d)\n"
|
|
||||||
" --uibc Enables UIBC\n"
|
|
||||||
" -e --external-player Configure player to use\n"
|
|
||||||
" --res <n,n,n> Supported resolutions masks (CEA, VESA, HH)\n"
|
|
||||||
" default CEA %08X\n"
|
|
||||||
" default VESA %08X\n"
|
|
||||||
" default HH %08X\n"
|
|
||||||
" --help-res Shows available values for res\n"
|
|
||||||
"\n"
|
|
||||||
, program_invocation_short_name, gst_audio_en, DEFAULT_RSTP_PORT,
|
|
||||||
wfd_supported_res_cea, wfd_supported_res_vesa, wfd_supported_res_hh
|
wfd_supported_res_cea, wfd_supported_res_vesa, wfd_supported_res_hh
|
||||||
);
|
);
|
||||||
|
wfd_print_resolutions();
|
||||||
/*
|
/*
|
||||||
* 80-char barrier:
|
* 80-char barrier:
|
||||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||||
|
@ -823,7 +632,6 @@ static int ctl_interactive(char **argv, int argc)
|
||||||
r = ctl_sink_new(&sink, cli_event);
|
r = ctl_sink_new(&sink, cli_event);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto error;
|
goto error;
|
||||||
sink->protocol_extensions = protocol_extensions;
|
|
||||||
|
|
||||||
r = ctl_wifi_fetch(wifi);
|
r = ctl_wifi_fetch(wifi);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -849,19 +657,12 @@ static int ctl_main(int argc, char *argv[])
|
||||||
struct ctl_link *l;
|
struct ctl_link *l;
|
||||||
int r, left;
|
int r, left;
|
||||||
|
|
||||||
if (getuid() != 0) {
|
|
||||||
r = EACCES;
|
|
||||||
log_notice("Must run as root");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = ctl_wifi_new(&wifi, bus);
|
r = ctl_wifi_new(&wifi, bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
left = argc - optind;
|
left = argc - optind;
|
||||||
left = left <= 0 ? 0 : left;
|
r = ctl_interactive(argv + optind, left <= 0 ? 0 : left);
|
||||||
r = ctl_interactive(argv + optind, left);
|
|
||||||
|
|
||||||
/* stop all scans */
|
/* stop all scans */
|
||||||
shl_dlist_for_each(i, &wifi->links) {
|
shl_dlist_for_each(i, &wifi->links) {
|
||||||
|
@ -879,70 +680,31 @@ static int parse_argv(int argc, char *argv[])
|
||||||
enum {
|
enum {
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_LOG_TIME,
|
|
||||||
ARG_LOG_DATE_TIME,
|
|
||||||
ARG_JOURNAL_LEVEL,
|
|
||||||
ARG_GST_DEBUG,
|
|
||||||
ARG_AUDIO,
|
ARG_AUDIO,
|
||||||
ARG_SCALE,
|
ARG_SCALE,
|
||||||
ARG_RES,
|
ARG_RES,
|
||||||
ARG_HELP_RES,
|
|
||||||
ARG_UIBC,
|
|
||||||
ARG_HELP_COMMANDS,
|
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "help-commands", no_argument, NULL, ARG_HELP_COMMANDS },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "version" , no_argument, NULL, ARG_VERSION },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
|
||||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
|
||||||
{ "log-date-time", no_argument, NULL, ARG_LOG_DATE_TIME },
|
|
||||||
{ "log-journal-level", required_argument, NULL, ARG_JOURNAL_LEVEL },
|
|
||||||
{ "gst-debug", required_argument, NULL, ARG_GST_DEBUG },
|
|
||||||
{ "audio", required_argument, NULL, ARG_AUDIO },
|
{ "audio", required_argument, NULL, ARG_AUDIO },
|
||||||
{ "scale", required_argument, NULL, ARG_SCALE },
|
{ "scale", required_argument, NULL, ARG_SCALE },
|
||||||
{ "res", required_argument, NULL, ARG_RES },
|
{ "res", required_argument, NULL, ARG_RES },
|
||||||
{ "help-res", no_argument, NULL, ARG_HELP_RES },
|
|
||||||
{ "port", required_argument, NULL, 'p' },
|
|
||||||
{ "uibc", no_argument, NULL, ARG_UIBC },
|
|
||||||
{ "external-player", required_argument, NULL, 'e' },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
uibc_option = false;
|
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
|
||||||
uibc_enabled = false;
|
|
||||||
external_player = false;
|
|
||||||
rstp_port = DEFAULT_RSTP_PORT;
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "he:p:", options, NULL)) >= 0) {
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
cli_fn_help();
|
return cli_help(cli_cmds);
|
||||||
return 0;
|
|
||||||
case ARG_HELP_COMMANDS:
|
|
||||||
return cli_help(cli_cmds, 20);
|
|
||||||
case ARG_HELP_RES:
|
|
||||||
wfd_print_resolutions("");
|
|
||||||
return 0;
|
|
||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
puts(PACKAGE_STRING);
|
puts(PACKAGE_STRING);
|
||||||
return 0;
|
return 0;
|
||||||
case ARG_LOG_LEVEL:
|
case ARG_LOG_LEVEL:
|
||||||
cli_max_sev = log_parse_arg(optarg);
|
cli_max_sev = log_parse_arg(optarg);
|
||||||
break;
|
break;
|
||||||
case ARG_LOG_TIME:
|
|
||||||
log_init_time();
|
|
||||||
break;
|
|
||||||
case ARG_LOG_DATE_TIME:
|
|
||||||
log_date_time = true;
|
|
||||||
break;
|
|
||||||
case ARG_GST_DEBUG:
|
|
||||||
gst_debug = optarg;
|
|
||||||
break;
|
|
||||||
case ARG_JOURNAL_LEVEL:
|
|
||||||
log_max_sev = log_parse_arg(optarg);
|
|
||||||
break;
|
|
||||||
case ARG_AUDIO:
|
case ARG_AUDIO:
|
||||||
gst_audio_en = atoi(optarg);
|
gst_audio_en = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -955,16 +717,6 @@ static int parse_argv(int argc, char *argv[])
|
||||||
&wfd_supported_res_vesa,
|
&wfd_supported_res_vesa,
|
||||||
&wfd_supported_res_hh);
|
&wfd_supported_res_hh);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
|
||||||
rstp_port = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
external_player = true;
|
|
||||||
player = optarg;
|
|
||||||
break;
|
|
||||||
case ARG_UIBC:
|
|
||||||
uibc_option = true;
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -976,75 +728,9 @@ static int parse_argv(int argc, char *argv[])
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
bool free_argv = false;
|
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
GKeyFile* gkf = load_ini_file();
|
|
||||||
|
|
||||||
gchar** autocmds_free = NULL;
|
|
||||||
if (gkf) {
|
|
||||||
player = g_key_file_get_string (gkf, "sinkctl", "external-player", NULL);
|
|
||||||
if (player) {
|
|
||||||
external_player = true;
|
|
||||||
}
|
|
||||||
gchar* log_level;
|
|
||||||
log_level = g_key_file_get_string (gkf, "sinkctl", "log-journal-level", NULL);
|
|
||||||
if (log_level) {
|
|
||||||
log_max_sev = log_parse_arg(log_level);
|
|
||||||
g_free(log_level);
|
|
||||||
}
|
|
||||||
log_level = g_key_file_get_string (gkf, "sinkctl", "log-level", NULL);
|
|
||||||
if (log_level) {
|
|
||||||
cli_max_sev = log_parse_arg(log_level);
|
|
||||||
g_free(log_level);
|
|
||||||
}
|
|
||||||
gchar* rstp_port_str = g_key_file_get_string (gkf, "sinkctl", "rstp-port", NULL);
|
|
||||||
if (rstp_port_str) {
|
|
||||||
rstp_port = atoi(rstp_port_str);
|
|
||||||
g_free(rstp_port_str);
|
|
||||||
}
|
|
||||||
gchar* autocmd;
|
|
||||||
autocmd = g_key_file_get_string (gkf, "sinkctl", "autocmd", NULL);
|
|
||||||
if (autocmd) {
|
|
||||||
gchar** autocmds = g_strsplit(autocmd, " ", -1);
|
|
||||||
autocmds_free = autocmds;
|
|
||||||
while (*autocmds) {
|
|
||||||
if (strcmp(*autocmds, "") != 0) {
|
|
||||||
gchar **newv = malloc((argc + 2) * sizeof(gchar*));
|
|
||||||
memmove(newv, argv, sizeof(gchar*) * argc);
|
|
||||||
newv[argc] = *autocmds;
|
|
||||||
newv[argc+1] = NULL;
|
|
||||||
argc++;
|
|
||||||
if (free_argv) {
|
|
||||||
free(argv);
|
|
||||||
}
|
|
||||||
argv = newv;
|
|
||||||
free_argv = true;
|
|
||||||
}
|
|
||||||
autocmds++;
|
|
||||||
}
|
|
||||||
g_free(autocmd);
|
|
||||||
}
|
|
||||||
gchar** sinkctl_keys;
|
|
||||||
gsize len = 0;
|
|
||||||
protocol_extensions = g_hash_table_new(g_str_hash, g_str_equal);
|
|
||||||
|
|
||||||
sinkctl_keys = g_key_file_get_keys (gkf,
|
|
||||||
"sinkctl",
|
|
||||||
&len,
|
|
||||||
NULL);
|
|
||||||
for (int i = 0; i < (int)len; i++) {
|
|
||||||
if (g_str_has_prefix(sinkctl_keys[i], "extends.")) {
|
|
||||||
gchar* orig_key = sinkctl_keys[i];
|
|
||||||
gchar* key = orig_key+8;
|
|
||||||
gchar* value = g_key_file_get_string (gkf, "sinkctl", orig_key, NULL);
|
|
||||||
g_hash_table_insert(protocol_extensions, key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_key_file_free(gkf);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -1058,10 +744,6 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
r = ctl_main(argc, argv);
|
r = ctl_main(argc, argv);
|
||||||
g_strfreev(autocmds_free);
|
|
||||||
if (free_argv) {
|
|
||||||
free(argv);
|
|
||||||
}
|
|
||||||
sd_bus_unref(bus);
|
sd_bus_unref(bus);
|
||||||
|
|
||||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
|
|
@ -103,27 +103,27 @@ struct resolution_bitmap resolutions_hh[] = {
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
void wfd_print_resolutions(char * prefix)
|
void wfd_print_resolutions(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("%sCEA resolutions:\n", prefix);
|
printf("CEA resolutions:\n");
|
||||||
for (i = 0; resolutions_cea[i].hres != 0; i++) {
|
for (i = 0; resolutions_cea[i].hres != 0; i++) {
|
||||||
printf("%s\t%2d %08x %4dx%4d@%d\n", prefix,
|
printf("\t%2d %08x %4dx%4d@%d\n",
|
||||||
resolutions_cea[i].index, 1 << resolutions_cea[i].index,
|
resolutions_cea[i].index, 1 << resolutions_cea[i].index,
|
||||||
resolutions_cea[i].hres, resolutions_cea[i].vres,
|
resolutions_cea[i].hres, resolutions_cea[i].vres,
|
||||||
resolutions_cea[i].fps);
|
resolutions_cea[i].fps);
|
||||||
}
|
}
|
||||||
printf("%sVESA resolutions:\n", prefix);
|
printf("VESA resolutions:\n");
|
||||||
for (i = 0; resolutions_vesa[i].hres != 0; i++) {
|
for (i = 0; resolutions_vesa[i].hres != 0; i++) {
|
||||||
printf("%s\t%2d %08x %4dx%4d@%d\n", prefix,
|
printf("\t%2d %08x %4dx%4d@%d\n",
|
||||||
resolutions_vesa[i].index, 1 << resolutions_vesa[i].index,
|
resolutions_vesa[i].index, 1 << resolutions_vesa[i].index,
|
||||||
resolutions_vesa[i].hres, resolutions_vesa[i].vres,
|
resolutions_vesa[i].hres, resolutions_vesa[i].vres,
|
||||||
resolutions_vesa[i].fps);
|
resolutions_vesa[i].fps);
|
||||||
}
|
}
|
||||||
printf("%sHH resolutions:\n", prefix);
|
printf("HH resolutions:\n");
|
||||||
for (i = 0; resolutions_hh[i].hres != 0; i++) {
|
for (i = 0; resolutions_hh[i].hres != 0; i++) {
|
||||||
printf("%s\t%2d %08x %4dx%4d@%d\n", prefix,
|
printf("\t%2d %08x %4dx%4d@%d\n",
|
||||||
resolutions_hh[i].index, 1 << resolutions_hh[i].index,
|
resolutions_hh[i].index, 1 << resolutions_hh[i].index,
|
||||||
resolutions_hh[i].hres, resolutions_hh[i].vres,
|
resolutions_hh[i].hres, resolutions_hh[i].vres,
|
||||||
resolutions_hh[i].fps);
|
resolutions_hh[i].fps);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#ifndef WFD_H
|
#ifndef WFD_H
|
||||||
#define WFD_H
|
#define WFD_H
|
||||||
|
|
||||||
void wfd_print_resolutions(char * prefix);
|
void wfd_print_resolutions(void);
|
||||||
int vfd_get_cea_resolution(uint32_t mask, int *hres, int *vres);
|
int vfd_get_cea_resolution(uint32_t mask, int *hres, int *vres);
|
||||||
int vfd_get_vesa_resolution(uint32_t mask, int *hres, int *vres);
|
int vfd_get_vesa_resolution(uint32_t mask, int *hres, int *vres);
|
||||||
int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres);
|
int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres);
|
||||||
|
|
|
@ -31,39 +31,13 @@
|
||||||
#include "ctl.h"
|
#include "ctl.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_util.h"
|
#include "shl_util.h"
|
||||||
#include "util.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <readline/readline.h>
|
|
||||||
|
|
||||||
#define HISTORY_FILENAME ".miracle-wifi.history"
|
|
||||||
|
|
||||||
#define CLI_PROMPT "\001" CLI_BLUE "\002" "[wifictl] # " "\001" CLI_DEFAULT "\002"
|
|
||||||
|
|
||||||
static sd_bus *bus;
|
static sd_bus *bus;
|
||||||
static struct ctl_wifi *wifi;
|
static struct ctl_wifi *wifi;
|
||||||
|
|
||||||
static struct ctl_link *selected_link;
|
static struct ctl_link *selected_link;
|
||||||
|
|
||||||
char* get_cli_prompt()
|
|
||||||
{
|
|
||||||
return CLI_PROMPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get history filename
|
|
||||||
*/
|
|
||||||
|
|
||||||
char* get_history_filename()
|
|
||||||
{
|
|
||||||
return HISTORY_FILENAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ctl_wifi *get_wifi()
|
|
||||||
{
|
|
||||||
return wifi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd list
|
* cmd list
|
||||||
*/
|
*/
|
||||||
|
@ -77,27 +51,26 @@ static int cmd_list(char **args, unsigned int n)
|
||||||
|
|
||||||
/* list links */
|
/* list links */
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s\n",
|
||||||
"LINK", "INTERFACE", "FRIENDLY-NAME", "MANAGED");
|
"LINK", "INTERFACE", "FRIENDLY-NAME");
|
||||||
|
|
||||||
shl_dlist_for_each(i, &wifi->links) {
|
shl_dlist_for_each(i, &wifi->links) {
|
||||||
l = link_from_dlist(i);
|
l = link_from_dlist(i);
|
||||||
++link_cnt;
|
++link_cnt;
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s\n",
|
||||||
l->label,
|
l->label,
|
||||||
shl_isempty(l->ifname) ?
|
shl_isempty(l->ifname) ?
|
||||||
"<unknown>" : l->ifname,
|
"<unknown>" : l->ifname,
|
||||||
shl_isempty(l->friendly_name) ?
|
shl_isempty(l->friendly_name) ?
|
||||||
"<unknown>" : l->friendly_name,
|
"<unknown>" : l->friendly_name);
|
||||||
l->managed ? "yes": "no");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_command_printf("\n");
|
cli_printf("\n");
|
||||||
|
|
||||||
/* list peers */
|
/* list peers */
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s %-10s\n",
|
||||||
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
|
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
|
||||||
|
|
||||||
shl_dlist_for_each(i, &wifi->links) {
|
shl_dlist_for_each(i, &wifi->links) {
|
||||||
|
@ -107,16 +80,16 @@ static int cmd_list(char **args, unsigned int n)
|
||||||
p = peer_from_dlist(j);
|
p = peer_from_dlist(j);
|
||||||
++peer_cnt;
|
++peer_cnt;
|
||||||
|
|
||||||
cli_command_printf("%6s %-24s %-30s %-10s\n",
|
cli_printf("%6s %-24s %-30s %-10s\n",
|
||||||
p->l->label,
|
p->l->label,
|
||||||
p->label,
|
p->label,
|
||||||
shl_isempty(p->friendly_name) ?
|
shl_isempty(p->friendly_name) ?
|
||||||
"<unknown>" : p->friendly_name,
|
"<unknown>" : p->friendly_name,
|
||||||
p->connected ? "yes" : "no");
|
p->connected ? "yes" : "no");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cli_command_printf("\n %u peers and %u links listed.\n", peer_cnt, link_cnt);
|
cli_printf("\n %u peers and %u links listed.\n", peer_cnt, link_cnt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +119,6 @@ static int cmd_select(char **args, unsigned int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
selected_link = l;
|
selected_link = l;
|
||||||
ctl_link_set_wfd_subelements(l, "000600111c4400c8");
|
|
||||||
cli_printf("link %s selected\n", selected_link->label);
|
cli_printf("link %s selected\n", selected_link->label);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -174,34 +146,33 @@ static int cmd_show(char **args, unsigned int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l) {
|
if (l) {
|
||||||
cli_command_printf("Link=%s\n", l->label);
|
cli_printf("Link=%s\n", l->label);
|
||||||
if (l->ifindex > 0)
|
if (l->ifindex > 0)
|
||||||
cli_command_printf("InterfaceIndex=%u\n", l->ifindex);
|
cli_printf("InterfaceIndex=%u\n", l->ifindex);
|
||||||
if (l->ifname && *l->ifname)
|
if (l->ifname && *l->ifname)
|
||||||
cli_command_printf("InterfaceName=%s\n", l->ifname);
|
cli_printf("InterfaceName=%s\n", l->ifname);
|
||||||
if (l->friendly_name && *l->friendly_name)
|
if (l->friendly_name && *l->friendly_name)
|
||||||
cli_command_printf("FriendlyName=%s\n", l->friendly_name);
|
cli_printf("FriendlyName=%s\n", l->friendly_name);
|
||||||
cli_command_printf("P2PScanning=%d\n", l->p2p_scanning);
|
cli_printf("P2PScanning=%d\n", l->p2p_scanning);
|
||||||
if (l->wfd_subelements && *l->wfd_subelements)
|
if (l->wfd_subelements && *l->wfd_subelements)
|
||||||
cli_command_printf("WfdSubelements=%s\n", l->wfd_subelements);
|
cli_printf("WfdSubelements=%s\n", l->wfd_subelements);
|
||||||
cli_command_printf("Managed=%d\n", l->managed);
|
|
||||||
} else if (p) {
|
} else if (p) {
|
||||||
cli_command_printf("Peer=%s\n", p->label);
|
cli_printf("Peer=%s\n", p->label);
|
||||||
if (p->p2p_mac && *p->p2p_mac)
|
if (p->p2p_mac && *p->p2p_mac)
|
||||||
cli_command_printf("P2PMac=%s\n", p->p2p_mac);
|
cli_printf("P2PMac=%s\n", p->p2p_mac);
|
||||||
if (p->friendly_name && *p->friendly_name)
|
if (p->friendly_name && *p->friendly_name)
|
||||||
cli_command_printf("FriendlyName=%s\n", p->friendly_name);
|
cli_printf("FriendlyName=%s\n", p->friendly_name);
|
||||||
cli_command_printf("Connected=%d\n", p->connected);
|
cli_printf("Connected=%d\n", p->connected);
|
||||||
if (p->interface && *p->interface)
|
if (p->interface && *p->interface)
|
||||||
cli_command_printf("Interface=%s\n", p->interface);
|
cli_printf("Interface=%s\n", p->interface);
|
||||||
if (p->local_address && *p->local_address)
|
if (p->local_address && *p->local_address)
|
||||||
cli_command_printf("LocalAddress=%s\n", p->local_address);
|
cli_printf("LocalAddress=%s\n", p->local_address);
|
||||||
if (p->remote_address && *p->remote_address)
|
if (p->remote_address && *p->remote_address)
|
||||||
cli_command_printf("RemoteAddress=%s\n", p->remote_address);
|
cli_printf("RemoteAddress=%s\n", p->remote_address);
|
||||||
if (p->wfd_subelements && *p->wfd_subelements)
|
if (p->wfd_subelements && *p->wfd_subelements)
|
||||||
cli_command_printf("WfdSubelements=%s\n", p->wfd_subelements);
|
cli_printf("WfdSubelements=%s\n", p->wfd_subelements);
|
||||||
} else {
|
} else {
|
||||||
cli_command_printf("Show what?\n");
|
cli_printf("Show what?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +189,7 @@ static int cmd_set_friendly_name(char **args, unsigned int n)
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
cli_command_printf("To what?\n");
|
cli_printf("To what?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,45 +214,6 @@ static int cmd_set_friendly_name(char **args, unsigned int n)
|
||||||
return ctl_link_set_friendly_name(l, name);
|
return ctl_link_set_friendly_name(l, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* cmd: set-managed
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int cmd_set_managed(char **args, unsigned int n)
|
|
||||||
{
|
|
||||||
struct ctl_link *l = NULL;
|
|
||||||
const char *value;
|
|
||||||
bool managed = true;
|
|
||||||
|
|
||||||
if (n < 1) {
|
|
||||||
cli_command_printf("To what?\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > 1) {
|
|
||||||
l = ctl_wifi_search_link(wifi, args[0]);
|
|
||||||
if (!l) {
|
|
||||||
cli_error("unknown link %s", args[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = args[1];
|
|
||||||
} else {
|
|
||||||
value = args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
l = l ? : selected_link;
|
|
||||||
if (!l) {
|
|
||||||
cli_error("no link selected");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(value, "no")) {
|
|
||||||
managed = false;
|
|
||||||
}
|
|
||||||
return ctl_link_set_managed(l, managed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cmd: p2p-scan
|
* cmd: p2p-scan
|
||||||
*/
|
*/
|
||||||
|
@ -310,11 +242,6 @@ static int cmd_p2p_scan(char **args, unsigned int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!l->managed) {
|
|
||||||
cli_printf("link %s not managed\n", l->label);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctl_link_set_p2p_scanning(l, !stop);
|
return ctl_link_set_p2p_scanning(l, !stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +263,7 @@ static int cmd_connect(char **args, unsigned int n)
|
||||||
const char *prov, *pin;
|
const char *prov, *pin;
|
||||||
|
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
cli_command_printf("To whom?\n");
|
cli_printf("To whom?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,11 +289,6 @@ static int cmd_connect(char **args, unsigned int n)
|
||||||
pin = "";
|
pin = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->l->managed) {
|
|
||||||
cli_printf("link %s not managed\n", p->l->label);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctl_peer_connect(p, prov, pin);
|
return ctl_peer_connect(p, prov, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +301,7 @@ static int cmd_disconnect(char **args, unsigned int n)
|
||||||
struct ctl_peer *p;
|
struct ctl_peer *p;
|
||||||
|
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
cli_command_printf("From whom?\n");
|
cli_printf("From whom?\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,11 +311,6 @@ static int cmd_disconnect(char **args, unsigned int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p->l->managed) {
|
|
||||||
cli_printf("link %s not managed\n", p->l->label);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctl_peer_disconnect(p);
|
return ctl_peer_disconnect(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,17 +329,16 @@ static int cmd_quit(char **args, unsigned int n)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const struct cli_cmd cli_cmds[] = {
|
static const struct cli_cmd cli_cmds[] = {
|
||||||
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects", {NULL}},
|
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects" },
|
||||||
{ "select", "[link]", CLI_Y, CLI_LESS, 1, cmd_select, "Select default link", {links_generator, NULL} },
|
{ "select", "[link]", CLI_Y, CLI_LESS, 1, cmd_select, "Select default link" },
|
||||||
{ "show", "[link|peer]", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information", {links_peers_generator, NULL} },
|
{ "show", "[link|peer]", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information" },
|
||||||
{ "set-friendly-name", "[link] <name>", CLI_M, CLI_LESS, 2, cmd_set_friendly_name, "Set friendly name of an object", {links_generator, yes_no_generator} },
|
{ "set-friendly-name", "[link] <name>", CLI_M, CLI_LESS, 2, cmd_set_friendly_name, "Set friendly name of an object" },
|
||||||
{ "set-managed", "[link] <yes|no>", CLI_M, CLI_LESS, 2, cmd_set_managed, "Manage or unmnage a link" },
|
{ "p2p-scan", "[link] [stop]", CLI_Y, CLI_LESS, 2, cmd_p2p_scan, "Control neighborhood P2P scanning" },
|
||||||
{ "p2p-scan", "[link] [stop]", CLI_Y, CLI_LESS, 2, cmd_p2p_scan, "Control neighborhood P2P scanning", {links_generator, NULL} },
|
{ "connect", "<peer> [provision] [pin]", CLI_M, CLI_LESS, 3, cmd_connect, "Connect to peer" },
|
||||||
{ "connect", "<peer> [provision] [pin]", CLI_M, CLI_LESS, 3, cmd_connect, "Connect to peer", {peers_generator, NULL} },
|
{ "disconnect", "<peer>", CLI_M, CLI_EQUAL, 1, cmd_disconnect, "Disconnect from peer" },
|
||||||
{ "disconnect", "<peer>", CLI_M, CLI_EQUAL, 1, cmd_disconnect, "Disconnect from peer", {peers_generator, NULL} },
|
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program" },
|
||||||
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program", {NULL} },
|
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL },
|
||||||
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL , {NULL}},
|
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" },
|
||||||
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" , {NULL} },
|
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -503,13 +419,9 @@ void cli_fn_help()
|
||||||
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
|
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
|
||||||
"Send control command to or query the MiracleCast Wifi-Manager. If no arguments\n"
|
"Send control command to or query the MiracleCast Wifi-Manager. If no arguments\n"
|
||||||
"are given, an interactive command-line tool is provided.\n\n"
|
"are given, an interactive command-line tool is provided.\n\n"
|
||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --help-commands Show available commands\n"
|
" --version Show package version\n"
|
||||||
" --version Show package version\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
|
||||||
" --log-time Prefix log-messages with timestamp\n"
|
|
||||||
" --log-date-time Prefix log-messages with date time\n"
|
|
||||||
" --log-journal-level <lvl> Maximum level for journal log messages\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"Commands:\n"
|
"Commands:\n"
|
||||||
, program_invocation_short_name);
|
, program_invocation_short_name);
|
||||||
|
@ -585,19 +497,11 @@ static int parse_argv(int argc, char *argv[])
|
||||||
enum {
|
enum {
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_LOG_TIME,
|
|
||||||
ARG_LOG_DATE_TIME,
|
|
||||||
ARG_JOURNAL_LEVEL,
|
|
||||||
ARG_HELP_COMMANDS,
|
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "help-commands", no_argument, NULL, ARG_HELP_COMMANDS },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
|
||||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
|
||||||
{ "log-date-time", no_argument, NULL, ARG_LOG_DATE_TIME },
|
|
||||||
{ "log-journal-level", required_argument, NULL, ARG_JOURNAL_LEVEL },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
@ -605,25 +509,13 @@ static int parse_argv(int argc, char *argv[])
|
||||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
|
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
cli_fn_help();
|
return cli_help(cli_cmds);
|
||||||
return 0;
|
|
||||||
case ARG_HELP_COMMANDS:
|
|
||||||
return cli_help(cli_cmds, 20);
|
|
||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
puts(PACKAGE_STRING);
|
puts(PACKAGE_STRING);
|
||||||
return 0;
|
return 0;
|
||||||
case ARG_LOG_LEVEL:
|
case ARG_LOG_LEVEL:
|
||||||
cli_max_sev = log_parse_arg(optarg);
|
cli_max_sev = log_parse_arg(optarg);
|
||||||
break;
|
break;
|
||||||
case ARG_LOG_TIME:
|
|
||||||
log_init_time();
|
|
||||||
break;
|
|
||||||
case ARG_LOG_DATE_TIME:
|
|
||||||
log_date_time = true;
|
|
||||||
break;
|
|
||||||
case ARG_JOURNAL_LEVEL:
|
|
||||||
log_max_sev = log_parse_arg(optarg);
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -638,23 +530,6 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
GKeyFile* gkf = load_ini_file();
|
|
||||||
|
|
||||||
if (gkf) {
|
|
||||||
gchar* log_level;
|
|
||||||
log_level = g_key_file_get_string (gkf, "wifictl", "log-journal-level", NULL);
|
|
||||||
if (log_level) {
|
|
||||||
log_max_sev = log_parse_arg(log_level);
|
|
||||||
g_free(log_level);
|
|
||||||
}
|
|
||||||
log_level = g_key_file_get_string (gkf, "wifictl", "log-level", NULL);
|
|
||||||
if (log_level) {
|
|
||||||
cli_max_sev = log_parse_arg(log_level);
|
|
||||||
g_free(log_level);
|
|
||||||
}
|
|
||||||
g_key_file_free(gkf);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
|
||||||
|
########### next target ###############
|
||||||
|
|
||||||
set(miracle-dhcp_SRCS dhcp.c
|
set(miracle-dhcp_SRCS dhcp.c
|
||||||
gdhcp.h
|
gdhcp.h
|
||||||
unaligned.h
|
unaligned.h
|
||||||
|
@ -13,15 +16,47 @@ add_executable(miracle-dhcp ${miracle-dhcp_SRCS})
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
||||||
pkg_check_modules (UDEV REQUIRED libudev)
|
pkg_check_modules (UDEV REQUIRED libudev)
|
||||||
target_link_libraries(miracle-dhcp miracle-shared)
|
|
||||||
link_directories( ${UDEV_LIBRARY_DIRS})
|
link_directories( ${UDEV_LIBRARY_DIRS})
|
||||||
include_directories( ${UDEV_INCLUDE_DIRS})
|
include_directories( ${UDEV_INCLUDE_DIRS})
|
||||||
target_link_libraries(miracle-dhcp ${UDEV_LIBRARIES})
|
target_link_libraries(miracle-dhcp ${UDEV_LIBRARIES})
|
||||||
target_link_libraries(miracle-dhcp m)
|
|
||||||
link_directories( ${GLIB2_LIBRARY_DIRS})
|
link_directories( ${GLIB2_LIBRARY_DIRS})
|
||||||
include_directories( ${GLIB2_INCLUDE_DIRS})
|
include_directories( ${GLIB2_INCLUDE_DIRS})
|
||||||
target_link_libraries(miracle-dhcp ${GLIB2_LIBRARIES})
|
target_link_libraries(miracle-dhcp ${GLIB2_LIBRARIES})
|
||||||
|
|
||||||
|
target_link_libraries(miracle-dhcp miracle-shared)
|
||||||
|
|
||||||
install(TARGETS miracle-dhcp DESTINATION bin)
|
install(TARGETS miracle-dhcp DESTINATION bin)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
||||||
|
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#bin_PROGRAMS = miracle-dhcp
|
||||||
|
#
|
||||||
|
#miracle_dhcp_SOURCES = \
|
||||||
|
# dhcp.c \
|
||||||
|
# gdhcp.h \
|
||||||
|
# unaligned.h \
|
||||||
|
# common.h \
|
||||||
|
# common.c \
|
||||||
|
# ipv4ll.h \
|
||||||
|
# ipv4ll.c \
|
||||||
|
# client.c \
|
||||||
|
# server.c
|
||||||
|
#miracle_dhcp_CPPFLAGS = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS) \
|
||||||
|
# $(GDHCP_CFLAGS)
|
||||||
|
#miracle_dhcp_LDADD = \
|
||||||
|
# ../shared/libmiracle-shared.la \
|
||||||
|
# $(DEPS_LIBS) \
|
||||||
|
# $(GDHCP_LIBS)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
|
@ -14,11 +14,11 @@ miracle_dhcp_SOURCES = \
|
||||||
miracle_dhcp_CPPFLAGS = \
|
miracle_dhcp_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
$(DEPS_CFLAGS) \
|
$(DEPS_CFLAGS) \
|
||||||
$(GLIB_CFLAGS)
|
$(GDHCP_CFLAGS)
|
||||||
miracle_dhcp_LDADD = \
|
miracle_dhcp_LDADD = \
|
||||||
../shared/libmiracle-shared.la \
|
../shared/libmiracle-shared.la \
|
||||||
$(DEPS_LIBS) \
|
$(DEPS_LIBS) \
|
||||||
$(GLIB_LIBS)
|
$(GDHCP_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2785,7 +2785,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
|
||||||
addr = ntohl(inet_addr(last_address));
|
addr = ntohl(inet_addr(last_address));
|
||||||
if (addr == 0xFFFFFFFF) {
|
if (addr == 0xFFFFFFFF) {
|
||||||
addr = 0;
|
addr = 0;
|
||||||
} else if (dhcp_client->last_address != last_address) { // Avoiding use-after-free
|
} else {
|
||||||
g_free(dhcp_client->last_address);
|
g_free(dhcp_client->last_address);
|
||||||
dhcp_client->last_address = g_strdup(last_address);
|
dhcp_client->last_address = g_strdup(last_address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
* of Wifi-P2P support in common network managers. Once they gain proper
|
* of Wifi-P2P support in common network managers. Once they gain proper
|
||||||
* support, we will drop this helper!
|
* support, we will drop this helper!
|
||||||
*
|
*
|
||||||
* The "ip" invocation is quite fragile and ugly. However, performing these
|
* The "ip" invokation is quite fragile and ugly. However, performing these
|
||||||
* steps directly involves netlink operations and more. As no-one came up with
|
* steps directly involves netlink operations and more. As no-one came up with
|
||||||
* patches, yet, we keep the hack. To anyone trying to fix it: Please, spend
|
* patches, yet, we keep the hack. To anyone trying to fix it: Please, spend
|
||||||
* this time hacking on NetworkManager, connman and friends instead! If they
|
* this time hacking on NetworkManager, connman and friends instead! If they
|
||||||
|
@ -67,11 +67,8 @@
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define XSTR(x) STR(x)
|
|
||||||
#define STR(x) #x
|
|
||||||
|
|
||||||
static const char *arg_netdev;
|
static const char *arg_netdev;
|
||||||
static const char *arg_ip_binary = XSTR(IP_BINARY);
|
static const char *arg_ip_binary = "/bin/ip";
|
||||||
static bool arg_server;
|
static bool arg_server;
|
||||||
static char arg_local[INET_ADDRSTRLEN];
|
static char arg_local[INET_ADDRSTRLEN];
|
||||||
static char arg_gateway[INET_ADDRSTRLEN];
|
static char arg_gateway[INET_ADDRSTRLEN];
|
||||||
|
@ -750,10 +747,9 @@ static int help(void)
|
||||||
" --version Show package version\n"
|
" --version Show package version\n"
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --log-time Prefix log-messages with timestamp\n"
|
" --log-time Prefix log-messages with timestamp\n"
|
||||||
" --log-date-time Prefix log-messages with date time\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
" --netdev <dev> Network device to run on\n"
|
" --netdev <dev> Network device to run on\n"
|
||||||
" --ip-binary <path> Path to 'ip' binary [default: "XSTR(IP_BINARY)"]\n"
|
" --ip-binary <path> Path to 'ip' binary [default: /bin/ip]\n"
|
||||||
" --comm-fd <int> Comm-socket FD passed through execve()\n"
|
" --comm-fd <int> Comm-socket FD passed through execve()\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Server Options:\n"
|
"Server Options:\n"
|
||||||
|
@ -776,7 +772,6 @@ static int parse_argv(int argc, char *argv[])
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_LOG_TIME,
|
ARG_LOG_TIME,
|
||||||
ARG_LOG_DATE_TIME,
|
|
||||||
|
|
||||||
ARG_NETDEV,
|
ARG_NETDEV,
|
||||||
ARG_IP_BINARY,
|
ARG_IP_BINARY,
|
||||||
|
@ -792,11 +787,10 @@ static int parse_argv(int argc, char *argv[])
|
||||||
ARG_TO,
|
ARG_TO,
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
||||||
{ "log-date-time", no_argument, NULL, ARG_LOG_DATE_TIME },
|
|
||||||
|
|
||||||
{ "netdev", required_argument, NULL, ARG_NETDEV },
|
{ "netdev", required_argument, NULL, ARG_NETDEV },
|
||||||
{ "ip-binary", required_argument, NULL, ARG_IP_BINARY },
|
{ "ip-binary", required_argument, NULL, ARG_IP_BINARY },
|
||||||
|
@ -829,9 +823,6 @@ static int parse_argv(int argc, char *argv[])
|
||||||
case ARG_LOG_TIME:
|
case ARG_LOG_TIME:
|
||||||
log_init_time();
|
log_init_time();
|
||||||
break;
|
break;
|
||||||
case ARG_LOG_DATE_TIME:
|
|
||||||
log_date_time = true;
|
|
||||||
break;
|
|
||||||
case ARG_NETDEV:
|
case ARG_NETDEV:
|
||||||
arg_netdev = optarg;
|
arg_netdev = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
miracle_dhcp_srcs = ['dhcp.c',
|
|
||||||
'common.c',
|
|
||||||
'ipv4ll.c',
|
|
||||||
'client.c',
|
|
||||||
'server.c'
|
|
||||||
]
|
|
||||||
executable('miracle-dhcp', miracle_dhcp_srcs,
|
|
||||||
install: true,
|
|
||||||
include_directories: include_directories('../..'),
|
|
||||||
dependencies: [glib2, udev, libmiracle_shared_dep, m]
|
|
||||||
)
|
|
|
@ -1,11 +0,0 @@
|
||||||
subdir('shared')
|
|
||||||
subdir('wifi')
|
|
||||||
subdir('dhcp')
|
|
||||||
subdir('ctl')
|
|
||||||
subdir('uibc')
|
|
||||||
|
|
||||||
executable('miracled', 'miracled.c',
|
|
||||||
dependencies: [libmiracle_shared_dep, m],
|
|
||||||
include_directories: include_directories('..'),
|
|
||||||
install: true
|
|
||||||
)
|
|
|
@ -66,7 +66,6 @@ static int help(void)
|
||||||
" --version Show package version\n"
|
" --version Show package version\n"
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --log-time Prefix log-messages with timestamp\n"
|
" --log-time Prefix log-messages with timestamp\n"
|
||||||
" --log-date-time Prefix log-messages with date time\n"
|
|
||||||
, program_invocation_short_name);
|
, program_invocation_short_name);
|
||||||
/*
|
/*
|
||||||
* 80-char barrier:
|
* 80-char barrier:
|
||||||
|
@ -82,14 +81,12 @@ static int parse_argv(int argc, char *argv[])
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_LOG_TIME,
|
ARG_LOG_TIME,
|
||||||
ARG_LOG_DATE_TIME,
|
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
||||||
{ "log-date-time", no_argument, NULL, ARG_LOG_DATE_TIME },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
@ -107,9 +104,6 @@ static int parse_argv(int argc, char *argv[])
|
||||||
case ARG_LOG_TIME:
|
case ARG_LOG_TIME:
|
||||||
log_init_time();
|
log_init_time();
|
||||||
break;
|
break;
|
||||||
case ARG_LOG_DATE_TIME:
|
|
||||||
log_date_time = true;
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
set(CMAKE_C_FLAGS "-std=gnu11")
|
set(CMAKE_C_FLAGS "-std=gnu11")
|
||||||
|
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules (SYSTEMD REQUIRED systemd>=213)
|
||||||
set(miracle-shared_SOURCES rtsp.h
|
set(miracle-shared_SOURCES rtsp.h
|
||||||
rtsp.c
|
rtsp.c
|
||||||
shl_dlist.h
|
shl_dlist.h
|
||||||
|
@ -16,4 +18,36 @@ set(miracle-shared_SOURCES rtsp.h
|
||||||
wpas.h
|
wpas.h
|
||||||
wpas.c)
|
wpas.c)
|
||||||
add_library(miracle-shared STATIC ${miracle-shared_SOURCES})
|
add_library(miracle-shared STATIC ${miracle-shared_SOURCES})
|
||||||
target_link_libraries (miracle-shared ${SESSION_LIBRARIES})
|
target_link_libraries (miracle-shared systemd)
|
||||||
|
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#noinst_LTLIBRARIES = libmiracle-shared.la
|
||||||
|
#
|
||||||
|
#libmiracle_shared_la_SOURCES = \
|
||||||
|
# rtsp.h \
|
||||||
|
# rtsp.c \
|
||||||
|
# shl_dlist.h \
|
||||||
|
# shl_htable.h \
|
||||||
|
# shl_htable.c \
|
||||||
|
# shl_log.h \
|
||||||
|
# shl_log.c \
|
||||||
|
# shl_macro.h \
|
||||||
|
# shl_ring.h \
|
||||||
|
# shl_ring.c \
|
||||||
|
# shl_util.h \
|
||||||
|
# shl_util.c \
|
||||||
|
# util.h \
|
||||||
|
# wpas.h \
|
||||||
|
# wpas.c
|
||||||
|
#libmiracle_shared_la_LIBADD = -lsystemd
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
|
@ -17,8 +17,7 @@ libmiracle_shared_la_SOURCES = \
|
||||||
util.h \
|
util.h \
|
||||||
wpas.h \
|
wpas.h \
|
||||||
wpas.c
|
wpas.c
|
||||||
libmiracle_shared_la_LIBADD = \
|
libmiracle_shared_la_LIBADD = -lsystemd
|
||||||
$(DEPS_LIBS) \
|
|
||||||
$(GLIB_LIBS) \
|
|
||||||
$(LIBM)
|
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
libmiracle_shared = static_library('miracle-shared',
|
|
||||||
'rtsp.h',
|
|
||||||
'rtsp.c',
|
|
||||||
'shl_dlist.h',
|
|
||||||
'shl_htable.h',
|
|
||||||
'shl_htable.c',
|
|
||||||
'shl_log.h',
|
|
||||||
'shl_log.c',
|
|
||||||
'shl_macro.h',
|
|
||||||
'shl_ring.h',
|
|
||||||
'shl_ring.c',
|
|
||||||
'shl_util.h',
|
|
||||||
'shl_util.c',
|
|
||||||
'util.h',
|
|
||||||
'wpas.h',
|
|
||||||
'wpas.c',
|
|
||||||
dependencies: [libsystemd]
|
|
||||||
)
|
|
||||||
libmiracle_shared_dep = declare_dependency(
|
|
||||||
include_directories: include_directories('.'),
|
|
||||||
link_with: libmiracle_shared
|
|
||||||
)
|
|
|
@ -2169,6 +2169,7 @@ static int parser_submit_data(struct rtsp *bus, uint8_t *p)
|
||||||
p,
|
p,
|
||||||
dec->data_size);
|
dec->data_size);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
free(p);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2716,7 +2717,7 @@ error:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rtsp_unlink_waiting(struct rtsp_message *m)
|
static void rtsp_unlink_waiting(struct rtsp_message *m)
|
||||||
{
|
{
|
||||||
if (m->is_waiting) {
|
if (m->is_waiting) {
|
||||||
sd_event_source_unref(m->timer_source);
|
sd_event_source_unref(m->timer_source);
|
||||||
|
@ -2725,9 +2726,7 @@ static bool rtsp_unlink_waiting(struct rtsp_message *m)
|
||||||
m->is_waiting = false;
|
m->is_waiting = false;
|
||||||
--m->bus->waiting_cnt;
|
--m->bus->waiting_cnt;
|
||||||
rtsp_message_unref(m);
|
rtsp_message_unref(m);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtsp_link_outgoing(struct rtsp_message *m)
|
static void rtsp_link_outgoing(struct rtsp_message *m)
|
||||||
|
@ -2738,7 +2737,7 @@ static void rtsp_link_outgoing(struct rtsp_message *m)
|
||||||
rtsp_message_ref(m);
|
rtsp_message_ref(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rtsp_unlink_outgoing(struct rtsp_message *m)
|
static void rtsp_unlink_outgoing(struct rtsp_message *m)
|
||||||
{
|
{
|
||||||
if (m->is_outgoing) {
|
if (m->is_outgoing) {
|
||||||
shl_dlist_unlink(&m->list);
|
shl_dlist_unlink(&m->list);
|
||||||
|
@ -2746,9 +2745,7 @@ static bool rtsp_unlink_outgoing(struct rtsp_message *m)
|
||||||
m->is_sending = false;
|
m->is_sending = false;
|
||||||
--m->bus->outgoing_cnt;
|
--m->bus->outgoing_cnt;
|
||||||
rtsp_message_unref(m);
|
rtsp_message_unref(m);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtsp_incoming_message(struct rtsp_message *m)
|
static int rtsp_incoming_message(struct rtsp_message *m)
|
||||||
|
@ -2826,11 +2823,10 @@ static int rtsp_write_message(struct rtsp_message *m)
|
||||||
if (m->sent >= m->raw_size) {
|
if (m->sent >= m->raw_size) {
|
||||||
/* no need to wait for answer if no-body listens */
|
/* no need to wait for answer if no-body listens */
|
||||||
if (!m->cb_fn)
|
if (!m->cb_fn)
|
||||||
if (rtsp_unlink_waiting(m))
|
rtsp_unlink_waiting(m);
|
||||||
m = NULL;
|
|
||||||
/* might destroy the message */
|
/* might destroy the message */
|
||||||
if (m)
|
rtsp_unlink_outgoing(m);
|
||||||
rtsp_unlink_outgoing(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3250,12 +3246,10 @@ static void rtsp_drop_message(struct rtsp_message *m)
|
||||||
|
|
||||||
/* never interrupt messages while being partly sent */
|
/* never interrupt messages while being partly sent */
|
||||||
if (!m->is_sending)
|
if (!m->is_sending)
|
||||||
if (rtsp_unlink_outgoing(m))
|
rtsp_unlink_outgoing(m);
|
||||||
m = NULL;
|
|
||||||
|
|
||||||
/* remove from waiting list so neither timeouts nor completions fire */
|
/* remove from waiting list so neither timeouts nor completions fire */
|
||||||
if (m)
|
rtsp_unlink_waiting(m);
|
||||||
rtsp_unlink_waiting(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtsp_call_async_cancel(struct rtsp *bus, uint64_t cookie)
|
void rtsp_call_async_cancel(struct rtsp *bus, uint64_t cookie)
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -39,7 +36,7 @@ static inline void log_unlock()
|
||||||
|
|
||||||
static struct timeval log__ftime;
|
static struct timeval log__ftime;
|
||||||
|
|
||||||
bool log__have_time(void)
|
static bool log__have_time(void)
|
||||||
{
|
{
|
||||||
return !(log__ftime.tv_sec == 0 && log__ftime.tv_usec == 0);
|
return !(log__ftime.tv_sec == 0 && log__ftime.tv_usec == 0);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +47,7 @@ void log_init_time(void)
|
||||||
gettimeofday(&log__ftime, NULL);
|
gettimeofday(&log__ftime, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log__time(long long *sec, long long *usec)
|
static void log__time(long long *sec, long long *usec)
|
||||||
{
|
{
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
|
|
||||||
|
@ -86,9 +83,6 @@ const char *LOG_SUBSYSTEM = NULL;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int log_max_sev = LOG_NOTICE;
|
unsigned int log_max_sev = LOG_NOTICE;
|
||||||
bool log_date_time = false;
|
|
||||||
|
|
||||||
char *gst_debug = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declaration so we can use the locked-versions in other functions
|
* Forward declaration so we can use the locked-versions in other functions
|
||||||
|
@ -141,51 +135,25 @@ static void log__submit(const char *file,
|
||||||
const char *prefix = NULL;
|
const char *prefix = NULL;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
long long sec, usec;
|
long long sec, usec;
|
||||||
time_t now;
|
|
||||||
struct tm *timeinfo;
|
|
||||||
struct timeval tv;
|
|
||||||
char buffertmp[80];
|
|
||||||
char buffer[120];
|
|
||||||
int millisec;
|
|
||||||
|
|
||||||
out = stderr;
|
out = stderr;
|
||||||
|
log__time(&sec, &usec);
|
||||||
|
|
||||||
if (sev < LOG_SEV_NUM && sev > log_max_sev)
|
if (sev < LOG_SEV_NUM && sev > log_max_sev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log__time(&sec, &usec);
|
|
||||||
|
|
||||||
if (log_date_time) {
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
millisec = lrint(tv.tv_usec/1000.0);
|
|
||||||
if (millisec>=1000) {
|
|
||||||
millisec -=1000;
|
|
||||||
tv.tv_sec++;
|
|
||||||
}
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
timeinfo = localtime(&now);
|
|
||||||
|
|
||||||
strftime(buffertmp, 80, "%x - %X.%03d", timeinfo);
|
|
||||||
sprintf(buffer, "%s.%03d", buffertmp, millisec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sev < LOG_SEV_NUM)
|
if (sev < LOG_SEV_NUM)
|
||||||
prefix = log__sev2str[sev];
|
prefix = log__sev2str[sev];
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
if (subs) {
|
if (subs) {
|
||||||
if (log_date_time)
|
if (log__have_time())
|
||||||
fprintf(out, "[%s] %s: %s: ", buffer, prefix, subs);
|
|
||||||
else if (log__have_time())
|
|
||||||
fprintf(out, "[%.4lld.%.6lld] %s: %s: ",
|
fprintf(out, "[%.4lld.%.6lld] %s: %s: ",
|
||||||
sec, usec, prefix, subs);
|
sec, usec, prefix, subs);
|
||||||
else
|
else
|
||||||
fprintf(out, "%s: %s: ", prefix, subs);
|
fprintf(out, "%s: %s: ", prefix, subs);
|
||||||
} else {
|
} else {
|
||||||
if (log_date_time)
|
if (log__have_time())
|
||||||
fprintf(out, "[%s] %s: ", buffer, prefix);
|
|
||||||
else if (log__have_time())
|
|
||||||
fprintf(out, "[%.4lld.%.6lld] %s: ",
|
fprintf(out, "[%.4lld.%.6lld] %s: ",
|
||||||
sec, usec, prefix);
|
sec, usec, prefix);
|
||||||
else
|
else
|
||||||
|
@ -193,18 +161,13 @@ static void log__submit(const char *file,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (subs) {
|
if (subs) {
|
||||||
if (log_date_time)
|
if (log__have_time())
|
||||||
fprintf(out, "[%s] %s: ",
|
|
||||||
buffer, subs);
|
|
||||||
else if (log__have_time())
|
|
||||||
fprintf(out, "[%.4lld.%.6lld] %s: ",
|
fprintf(out, "[%.4lld.%.6lld] %s: ",
|
||||||
sec, usec, subs);
|
sec, usec, subs);
|
||||||
else
|
else
|
||||||
fprintf(out, "%s: ", subs);
|
fprintf(out, "%s: ", subs);
|
||||||
} else {
|
} else {
|
||||||
if (log_date_time)
|
if (log__have_time())
|
||||||
fprintf(out, "[%s] ", buffer);
|
|
||||||
else if (log__have_time())
|
|
||||||
fprintf(out, "[%.4lld.%.6lld] ", sec, usec);
|
fprintf(out, "[%.4lld.%.6lld] ", sec, usec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,9 +239,9 @@ void log_llog(void *data,
|
||||||
log_submit(file, line, func, subs, sev, format, args);
|
log_submit(file, line, func, subs, sev, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int log_parse_arg(char *optarg)
|
int log_parse_arg(char *optarg)
|
||||||
{
|
{
|
||||||
unsigned int log_max_sev;
|
int log_max_sev;
|
||||||
if(!strcasecmp(optarg, "fatal")) {
|
if(!strcasecmp(optarg, "fatal")) {
|
||||||
log_max_sev = LOG_FATAL;
|
log_max_sev = LOG_FATAL;
|
||||||
} else if(!strcasecmp(optarg, "alert")) {
|
} else if(!strcasecmp(optarg, "alert")) {
|
||||||
|
@ -298,23 +261,7 @@ unsigned int log_parse_arg(char *optarg)
|
||||||
} else if(!strcasecmp(optarg, "trace")) {
|
} else if(!strcasecmp(optarg, "trace")) {
|
||||||
log_max_sev = LOG_TRACE;
|
log_max_sev = LOG_TRACE;
|
||||||
} else {
|
} else {
|
||||||
errno = 0;
|
log_max_sev = atoi(optarg);
|
||||||
char *temp;
|
|
||||||
long val = strtoul(optarg, &temp, 0);
|
|
||||||
|
|
||||||
if (temp == optarg || *temp != '\0'
|
|
||||||
|| ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE)) {
|
|
||||||
log_error("Could not convert '%s' to long and leftover string is: '%s'\n", optarg, temp);
|
|
||||||
}
|
|
||||||
if (val > INT_MAX) {
|
|
||||||
errno = ERANGE;
|
|
||||||
return INT_MAX;
|
|
||||||
}
|
|
||||||
if (val < INT_MIN) {
|
|
||||||
errno = ERANGE;
|
|
||||||
return INT_MIN;
|
|
||||||
}
|
|
||||||
log_max_sev = (unsigned int) val;
|
|
||||||
}
|
}
|
||||||
return log_max_sev;
|
return log_max_sev;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,17 +61,6 @@ enum log_severity {
|
||||||
|
|
||||||
extern unsigned int log_max_sev;
|
extern unsigned int log_max_sev;
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines if log time should use local time
|
|
||||||
* Default: false
|
|
||||||
*/
|
|
||||||
extern bool log_date_time;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Defines the debug configuration for gstreamer
|
|
||||||
*/
|
|
||||||
extern char* gst_debug;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timestamping
|
* Timestamping
|
||||||
* Call this to initialize timestamps and cause all log-messages to be prefixed
|
* Call this to initialize timestamps and cause all log-messages to be prefixed
|
||||||
|
@ -80,10 +69,6 @@ extern char* gst_debug;
|
||||||
|
|
||||||
void log_init_time(void);
|
void log_init_time(void);
|
||||||
|
|
||||||
void log__time(long long *sec, long long *usec);
|
|
||||||
|
|
||||||
bool log__have_time(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log-Functions
|
* Log-Functions
|
||||||
* These functions pass a log-message to the log-subsystem. Handy helpers are
|
* These functions pass a log-message to the log-subsystem. Handy helpers are
|
||||||
|
@ -131,7 +116,7 @@ void log_llog(void *data,
|
||||||
const char *format,
|
const char *format,
|
||||||
va_list args);
|
va_list args);
|
||||||
|
|
||||||
unsigned int log_parse_arg(char *optarg);
|
int log_parse_arg(char *optarg);
|
||||||
|
|
||||||
static inline __attribute__((format(printf, 2, 3)))
|
static inline __attribute__((format(printf, 2, 3)))
|
||||||
void log_dummyf(unsigned int sev, const char *format, ...)
|
void log_dummyf(unsigned int sev, const char *format, ...)
|
||||||
|
@ -241,9 +226,4 @@ extern const char *LOG_SUBSYSTEM;
|
||||||
#define log_vERR(_r) \
|
#define log_vERR(_r) \
|
||||||
((void)log_ERR(_r))
|
((void)log_ERR(_r))
|
||||||
|
|
||||||
#define log_EUNMANAGED() \
|
|
||||||
(log_error("interface unmanaged"), -EFAULT)
|
|
||||||
#define log_vEUNMANAGED() \
|
|
||||||
((void)log_EUNMANAGED())
|
|
||||||
|
|
||||||
#endif /* SHL_LOG_H */
|
#endif /* SHL_LOG_H */
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
* variants to allow these.
|
* variants to allow these.
|
||||||
* Base-prefix parsing is only done if base=0 is requested. Otherwise,
|
* Base-prefix parsing is only done if base=0 is requested. Otherwise,
|
||||||
* base-prefixes are forbidden.
|
* base-prefixes are forbidden.
|
||||||
* The input string must be ASCII compatible (which includes UTF8).
|
* The input string must be ASCII compatbile (which includes UTF8).
|
||||||
*
|
*
|
||||||
* We also always check for overflows and return errors (but continue parsing!)
|
* We also always check for overflows and return errors (but continue parsing!)
|
||||||
* so callers can catch it correctly.
|
* so callers can catch it correctly.
|
||||||
|
@ -826,9 +826,8 @@ int shl__mkdir_parents(const char *prefix, const char *path, mode_t mode)
|
||||||
if (!e || e == path)
|
if (!e || e == path)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
p = strndup(path, e - path);
|
p = strndupa(path, e - path);
|
||||||
r = shl__is_dir(p);
|
r = shl__is_dir(p);
|
||||||
free((char*)p);
|
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
|
|
|
@ -31,26 +31,6 @@
|
||||||
#include <systemd/sd-bus.h>
|
#include <systemd/sd-bus.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
static inline GKeyFile* load_ini_file() {
|
|
||||||
GKeyFile* gkf = NULL;
|
|
||||||
gchar* config_file;
|
|
||||||
|
|
||||||
gkf = g_key_file_new();
|
|
||||||
|
|
||||||
config_file = g_build_filename(g_get_home_dir(), ".config", "miraclecastrc", NULL);
|
|
||||||
if (!g_key_file_load_from_file(gkf, config_file, G_KEY_FILE_NONE, NULL)) {
|
|
||||||
g_free(config_file);
|
|
||||||
config_file = g_build_filename(g_get_home_dir(), ".miraclecast", NULL);
|
|
||||||
if (!g_key_file_load_from_file(gkf, config_file, G_KEY_FILE_NONE, NULL)) {
|
|
||||||
g_key_file_free(gkf);
|
|
||||||
gkf = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_free(config_file);
|
|
||||||
return gkf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -742,7 +742,6 @@ static int wpas__parse_message(struct wpas *w,
|
||||||
const char *ifname = NULL;
|
const char *ifname = NULL;
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
char *pos;
|
char *pos;
|
||||||
char *orig_raw = raw;
|
|
||||||
int r, num;
|
int r, num;
|
||||||
bool is_event = false;
|
bool is_event = false;
|
||||||
|
|
||||||
|
@ -752,7 +751,7 @@ static int wpas__parse_message(struct wpas *w,
|
||||||
ifname = pos;
|
ifname = pos;
|
||||||
pos = strchrnul(pos, ' ');
|
pos = strchrnul(pos, ' ');
|
||||||
if (*pos)
|
if (*pos)
|
||||||
pos++;
|
*pos++ = 0;
|
||||||
|
|
||||||
len -= pos - raw;
|
len -= pos - raw;
|
||||||
raw = pos;
|
raw = pos;
|
||||||
|
@ -812,12 +811,15 @@ static int wpas__parse_message(struct wpas *w,
|
||||||
|
|
||||||
m->sealed = true;
|
m->sealed = true;
|
||||||
m->rawlen = len;
|
m->rawlen = len;
|
||||||
m->raw = strdup(orig_raw);
|
m->raw = malloc(len + 1);
|
||||||
if (!m->raw)
|
if (!m->raw)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* copy with 0-terminator */
|
||||||
|
memcpy(m->raw, raw, len + 1);
|
||||||
|
|
||||||
if (ifname) {
|
if (ifname) {
|
||||||
m->ifname = strndup(ifname, strchrnul(ifname, ' ') - ifname);
|
m->ifname = strdup(ifname);
|
||||||
if (!m->ifname)
|
if (!m->ifname)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -1054,7 +1056,7 @@ static int wpas__bind_server_socket(int fd, const char *ctrl_path, char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(name, src.sun_path, UNIX_PATH_MAX);
|
strncpy(name, src.sun_path, UNIX_PATH_MAX - 1);
|
||||||
name[UNIX_PATH_MAX - 1] = 0;
|
name[UNIX_PATH_MAX - 1] = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
set(miracle-uibcctl_SRCS miracle-uibcctl.h
|
|
||||||
miracle-uibcctl.c)
|
|
||||||
|
|
||||||
add_executable(miracle-uibcctl ${miracle-uibcctl_SRCS})
|
|
||||||
target_link_libraries(miracle-uibcctl miracle-shared)
|
|
||||||
target_link_libraries(miracle-uibcctl m)
|
|
||||||
|
|
||||||
install(TARGETS miracle-uibcctl DESTINATION bin)
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
|
|
@ -1,16 +0,0 @@
|
||||||
include $(top_srcdir)/common.am
|
|
||||||
|
|
||||||
bin_PROGRAMS = miracle-uibcctl
|
|
||||||
|
|
||||||
miracle_uibcctl_SOURCES = \
|
|
||||||
miracle-uibcctl.h \
|
|
||||||
miracle-uibcctl.c
|
|
||||||
|
|
||||||
miracle_uibctcl_CPPFLAGS = \
|
|
||||||
$(AM_CPPFLAGS) \
|
|
||||||
$(DEPS_CFLAGS)
|
|
||||||
|
|
||||||
miracle_uibcctl_LDADD = \
|
|
||||||
../shared/libmiracle-shared.la \
|
|
||||||
$(LIBM)
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
executable('miracle-uibcctl', 'miracle-uibcctl.h', 'miracle-uibcctl.c',
|
|
||||||
install: true,
|
|
||||||
dependencies: [m, libmiracle_shared_dep]
|
|
||||||
)
|
|
|
@ -1,624 +0,0 @@
|
||||||
|
|
||||||
#include "miracle-uibcctl.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
//TODO: Add miracle TUI interface
|
|
||||||
//TODO: Add parsearg
|
|
||||||
//--daemon (read stdin)
|
|
||||||
|
|
||||||
int portno;
|
|
||||||
struct hostent *server;
|
|
||||||
int sockfd;
|
|
||||||
struct sockaddr_in serv_addr;
|
|
||||||
char buffer[256];
|
|
||||||
int r;
|
|
||||||
|
|
||||||
log_max_sev = LOG_INFO;
|
|
||||||
|
|
||||||
if (argc < 3) {
|
|
||||||
fprintf(stderr, "Usage:\n");
|
|
||||||
fprintf(stderr, " %s <hostname> <port>\n", argv[0]);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
server = gethostbyname(argv[1]);
|
|
||||||
portno = atoi(argv[2]);
|
|
||||||
|
|
||||||
log_info("server %s port %d", argv[1], portno);
|
|
||||||
|
|
||||||
if (server == NULL) {
|
|
||||||
fprintf(stderr,"ERROR, no such host\n");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
|
|
||||||
if (sockfd < 0) {
|
|
||||||
perror("ERROR opening socket");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
|
||||||
serv_addr.sin_family = AF_INET;
|
|
||||||
bcopy(server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
|
|
||||||
serv_addr.sin_port = htons(portno);
|
|
||||||
|
|
||||||
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
|
|
||||||
perror("ERROR connecting");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool daemon = true;
|
|
||||||
while(1) {
|
|
||||||
if (!daemon) {
|
|
||||||
printf("enter event <type>,<count>,<id>,<x>,<y>: ");
|
|
||||||
}
|
|
||||||
bzero(buffer, 256);
|
|
||||||
fgets(buffer, 255, stdin);
|
|
||||||
if (strlen(buffer) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!daemon) {
|
|
||||||
printf("input: %s", buffer);
|
|
||||||
}
|
|
||||||
char type = buffer[0];
|
|
||||||
UibcMessage uibcmessage;
|
|
||||||
if (type == '0' || type == '1') {
|
|
||||||
uibcmessage = buildUibcMessage(GENERIC_TOUCH_DOWN, buffer, 1, 1);
|
|
||||||
} else if (type == '3' || type == '4') {
|
|
||||||
uibcmessage = buildUibcMessage(GENERIC_KEY_DOWN, buffer, 1, 1);
|
|
||||||
} else {
|
|
||||||
if (!daemon) {
|
|
||||||
printf("unknow event type: %s", buffer);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sendUibcMessage(&uibcmessage, sockfd);
|
|
||||||
if (r) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(sockfd);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *int2binary(int x, int padding)
|
|
||||||
{
|
|
||||||
char *b;
|
|
||||||
int min_padding = x > 0 ? floor(log2(x)) : 0;
|
|
||||||
if (padding < min_padding) {
|
|
||||||
padding = min_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
b = (char *)malloc (sizeof (char *) * padding + 1);
|
|
||||||
strcpy(b, "");
|
|
||||||
|
|
||||||
int z;
|
|
||||||
for (z = pow(2,padding); z > 0; z >>= 1) {
|
|
||||||
strcat(b, ((x & z) == z) ? "1" : "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sendUibcMessage(UibcMessage* uibcmessage, int sockfd) {
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
printf("sending %zu bytes\n", uibcmessage->m_PacketDataLen);
|
|
||||||
|
|
||||||
n = write(sockfd, uibcmessage->m_PacketData , uibcmessage->m_PacketDataLen);
|
|
||||||
|
|
||||||
if (n < 0) {
|
|
||||||
perror("ERROR writing to socket");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
UibcMessage buildUibcMessage(MessageType type,
|
|
||||||
const char* inEventDesc,
|
|
||||||
double widthRatio,
|
|
||||||
double heightRatio) {
|
|
||||||
UibcMessage uibcmessage;
|
|
||||||
uibcmessage.m_PacketData = NULL;
|
|
||||||
uibcmessage.m_PacketDataLen = 0;
|
|
||||||
uibcmessage.m_DataValid = false;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case GENERIC_TOUCH_DOWN:
|
|
||||||
case GENERIC_TOUCH_UP:
|
|
||||||
case GENERIC_TOUCH_MOVE:
|
|
||||||
getUIBCGenericTouchPacket(inEventDesc,
|
|
||||||
&uibcmessage,
|
|
||||||
widthRatio,
|
|
||||||
heightRatio);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GENERIC_KEY_DOWN:
|
|
||||||
case GENERIC_KEY_UP:
|
|
||||||
getUIBCGenericKeyPacket(inEventDesc, &uibcmessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GENERIC_ZOOM:
|
|
||||||
getUIBCGenericZoomPacket(inEventDesc, &uibcmessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GENERIC_VERTICAL_SCROLL:
|
|
||||||
case GENERIC_HORIZONTAL_SCROLL:
|
|
||||||
getUIBCGenericScalePacket(inEventDesc, &uibcmessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GENERIC_ROTATE:
|
|
||||||
getUIBCGenericRotatePacket(inEventDesc, &uibcmessage);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
return uibcmessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// format: "typeId, number of pointers, pointer Id1, X coordnate, Y coordinate, pointer Id2, X coordnate, Y coordnate,..."
|
|
||||||
void getUIBCGenericTouchPacket(const char *inEventDesc,
|
|
||||||
UibcMessage* uibcmessage,
|
|
||||||
double widthRatio,
|
|
||||||
double heightRatio) {
|
|
||||||
log_info("getUIBCGenericTouchPacket (%s)", inEventDesc);
|
|
||||||
char* outData;
|
|
||||||
int32_t typeId = 0;
|
|
||||||
int32_t numberOfPointers = 0;
|
|
||||||
size_t uibcBodyLen = 0;
|
|
||||||
int32_t genericPacketLen = 0;
|
|
||||||
int32_t temp;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
|
||||||
|
|
||||||
if ((int)size - 5 < 0 || ((int)size - 5) % 3 != 0) {
|
|
||||||
log_error("getUIBCGenericTouchPacket (%s)", "bad input event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int offset_split = 0;
|
|
||||||
typeId = atoi(*(splitedStr + offset_split++));
|
|
||||||
numberOfPointers = atoi(*(splitedStr + offset_split++));
|
|
||||||
|
|
||||||
genericPacketLen = numberOfPointers * 5 + 1;
|
|
||||||
uibcBodyLen = genericPacketLen + 7; // Generic header length = 7
|
|
||||||
//Padding to even number
|
|
||||||
uibcBodyLen = (uibcBodyLen % 2 == 0) ? uibcBodyLen : (uibcBodyLen + 1);
|
|
||||||
|
|
||||||
outData = (char*)malloc(uibcBodyLen);
|
|
||||||
// UIBC header Octets
|
|
||||||
int offset_header = 0;
|
|
||||||
//Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[offset_header++] = 0x00; // 000 0 0000
|
|
||||||
outData[offset_header++] = 0x00; // 0000 0000
|
|
||||||
|
|
||||||
//Length(16 bits)
|
|
||||||
outData[offset_header++] = (uibcBodyLen >> 8) & 0xFF; // first 8 bytes
|
|
||||||
outData[offset_header++] = uibcBodyLen & 0xFF; // last 8 bytes
|
|
||||||
|
|
||||||
//Generic Input Body Format
|
|
||||||
outData[offset_header++] = typeId & 0xFF; // Tyoe ID, 1 octet
|
|
||||||
|
|
||||||
// Length, 2 octets
|
|
||||||
outData[offset_header++] = (genericPacketLen >> 8) & 0xFF; // first 8 bytes
|
|
||||||
outData[offset_header++] = genericPacketLen & 0xFF; //last 8 bytes
|
|
||||||
|
|
||||||
// Number of pointers, 1 octet
|
|
||||||
outData[offset_header++] = numberOfPointers & 0xFF;
|
|
||||||
|
|
||||||
int offset = 0;
|
|
||||||
log_info("getUIBCGenericTouchPacket numberOfPointers=[%d]\n", numberOfPointers);
|
|
||||||
for (int i = 0; i < numberOfPointers; i++) {
|
|
||||||
int splitoffset = offset_split + (i * 3);
|
|
||||||
temp = atoi(*(splitedStr + splitoffset++));
|
|
||||||
offset = offset_header + ( i * 5);
|
|
||||||
outData[offset++] = temp & 0xFF;
|
|
||||||
log_info("getUIBCGenericTouchPacket PointerId=[%d]\n", temp);
|
|
||||||
|
|
||||||
temp = atoi(*(splitedStr + splitoffset++));
|
|
||||||
temp = (int32_t)((double)temp / widthRatio);
|
|
||||||
log_info("getUIBCGenericTouchPacket X-coordinate=[%d]\n", temp);
|
|
||||||
outData[offset++] = (temp >> 8) & 0xFF;
|
|
||||||
outData[offset++] = temp & 0xFF;
|
|
||||||
|
|
||||||
temp = atoi(*(splitedStr + splitoffset++));
|
|
||||||
temp = (int32_t)((double)temp / heightRatio);
|
|
||||||
log_info("getUIBCGenericTouchPacket Y-coordinate=[%d]\n", temp);
|
|
||||||
outData[offset++] = (temp >> 8) & 0xFF;
|
|
||||||
outData[offset++] = temp & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (offset <= uibcBodyLen) {
|
|
||||||
outData[offset++] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
free(*(splitedStr + i));
|
|
||||||
}
|
|
||||||
free(splitedStr);
|
|
||||||
|
|
||||||
binarydump(outData, uibcBodyLen);
|
|
||||||
uibcmessage->m_DataValid = true;
|
|
||||||
uibcmessage->m_PacketData = outData;
|
|
||||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hexdump(void *_data, size_t len)
|
|
||||||
{
|
|
||||||
unsigned char *data = _data;
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
int line = 15;
|
|
||||||
for (count = 0; count < len; count++) {
|
|
||||||
if ((count & line) == 0) {
|
|
||||||
fprintf(stderr,"%04zu: ", count);
|
|
||||||
}
|
|
||||||
fprintf(stderr,"%02x ", *data);
|
|
||||||
data++;
|
|
||||||
if ((count & line) == line) {
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((count & line) != 0) {
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void binarydump(void *_data, size_t len)
|
|
||||||
{
|
|
||||||
unsigned char *data = _data;
|
|
||||||
size_t count;
|
|
||||||
|
|
||||||
int line = 7;
|
|
||||||
for (count = 0; count < len; count++) {
|
|
||||||
if ((count & line) == 0) {
|
|
||||||
fprintf(stderr,"%04zu: ", count);
|
|
||||||
}
|
|
||||||
fprintf(stderr,"%s ", int2binary(*data, 8));
|
|
||||||
data++;
|
|
||||||
if ((count & line) == line) {
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((count & line) != 0) {
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// format: "typeId, Key code 1(0x00), Key code 2(0x00)"
|
|
||||||
void getUIBCGenericKeyPacket(const char *inEventDesc,
|
|
||||||
UibcMessage* uibcmessage) {
|
|
||||||
log_info("getUIBCGenericKeyPacket (%s)", inEventDesc);
|
|
||||||
char* outData = uibcmessage->m_PacketData;
|
|
||||||
int32_t typeId = 0;
|
|
||||||
int32_t uibcBodyLen = 0;
|
|
||||||
int32_t genericPacketLen = 0;
|
|
||||||
int32_t temp = 0;
|
|
||||||
size_t size;
|
|
||||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
|
|
||||||
if (((int)size) % 3 != 0) {
|
|
||||||
log_error("getUIBCGenericKeyPacket (%s)", "bad input event");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
log_info("getUIBCGenericKeyPacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0: {
|
|
||||||
typeId = atoi(*(splitedStr + i));
|
|
||||||
log_info("getUIBCGenericKeyPacket typeId=[%d]\n", typeId);
|
|
||||||
genericPacketLen = 5;
|
|
||||||
uibcBodyLen = genericPacketLen + 7; // Generic header length = 7
|
|
||||||
outData = (char*)malloc(uibcBodyLen + 1);
|
|
||||||
// UIBC header
|
|
||||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
|
||||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
|
||||||
//Generic Input Body Format
|
|
||||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
|
||||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
|
||||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
|
||||||
outData[7] = 0x00; // reserved
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
sscanf(*(splitedStr + i), " 0x%04X", &temp);
|
|
||||||
if (temp == 0) {
|
|
||||||
outData[8] = 0x00;
|
|
||||||
outData[9] = 0x00;
|
|
||||||
}
|
|
||||||
log_info("getUIBCGenericKeyPacket key code 1=[%d]\n", temp);
|
|
||||||
outData[8] = (temp >> 8) & 0xFF;
|
|
||||||
outData[9] = temp & 0xFF;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
sscanf(*(splitedStr + i), " 0x%04X", &temp);
|
|
||||||
if (temp == 0) {
|
|
||||||
outData[10] = 0x00;
|
|
||||||
outData[11] = 0x00;
|
|
||||||
}
|
|
||||||
log_info("getUIBCGenericKeyPacket key code 2=[%d]\n", temp);
|
|
||||||
outData[10] = (temp >> 8) & 0xFF;
|
|
||||||
outData[11] = temp & 0xFF;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(*(splitedStr + i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(splitedStr);
|
|
||||||
|
|
||||||
binarydump(outData, uibcBodyLen);
|
|
||||||
uibcmessage->m_DataValid = true;
|
|
||||||
uibcmessage->m_PacketData = outData;
|
|
||||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format: "typeId, X coordnate, Y coordnate, integer part, fraction part"
|
|
||||||
void getUIBCGenericZoomPacket(const char *inEventDesc, UibcMessage* uibcmessage) {
|
|
||||||
log_info("getUIBCGenericZoomPacket (%s)", inEventDesc);
|
|
||||||
char* outData = uibcmessage->m_PacketData;
|
|
||||||
int32_t typeId;
|
|
||||||
int32_t uibcBodyLen, genericPacketLen;
|
|
||||||
int32_t xCoord, yCoord, integerPart, FractionPart;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
|
||||||
|
|
||||||
if (splitedStr) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; * (splitedStr + i); i++) {
|
|
||||||
//log_info("getUIBCGenericZoomPacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0: {
|
|
||||||
typeId = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericZoomPacket typeId=[%d]\n", typeId);
|
|
||||||
|
|
||||||
genericPacketLen = 6;
|
|
||||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
|
||||||
outData = (char*)malloc(uibcBodyLen + 1);
|
|
||||||
// UIBC header
|
|
||||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
|
||||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
|
||||||
//Generic Input Body Format
|
|
||||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
|
||||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
|
||||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: {
|
|
||||||
xCoord = atoi(*(splitedStr + i));
|
|
||||||
outData[7] = (xCoord >> 8) & 0xFF;
|
|
||||||
outData[8] = xCoord & 0xFF;
|
|
||||||
log_info("getUIBCGenericZoomPacket xCoord=[%d]\n", xCoord);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
yCoord = atoi(*(splitedStr + i));
|
|
||||||
log_info("getUIBCGenericZoomPacket yCoord=[%d]\n", yCoord);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
integerPart = atoi(*(splitedStr + i));
|
|
||||||
outData[11] = integerPart & 0xFF;
|
|
||||||
//log_info("getUIBCGenericZoomPacket integerPart=[%d]\n", integerPart);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: {
|
|
||||||
FractionPart = atoi(*(splitedStr + i));
|
|
||||||
outData[12] = FractionPart & 0xFF;
|
|
||||||
//log_info("getUIBCGenericZoomPacket FractionPart=[%d]\n", FractionPart);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(*(splitedStr + i));
|
|
||||||
}
|
|
||||||
free(splitedStr);
|
|
||||||
}
|
|
||||||
//hexdump(outData, uibcBodyLen);
|
|
||||||
uibcmessage->m_DataValid = true;
|
|
||||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format: "typeId, unit, direction, amount to scroll"
|
|
||||||
void getUIBCGenericScalePacket(const char *inEventDesc, UibcMessage* uibcmessage) {
|
|
||||||
log_info("getUIBCGenericScalePacket (%s)", inEventDesc);
|
|
||||||
char* outData = uibcmessage->m_PacketData;
|
|
||||||
int32_t typeId;
|
|
||||||
int32_t uibcBodyLen, genericPacketLen;
|
|
||||||
int32_t temp;
|
|
||||||
size_t size;
|
|
||||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
|
||||||
|
|
||||||
if (splitedStr) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; * (splitedStr + i); i++) {
|
|
||||||
//log_info("getUIBCGenericScalePacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0: {
|
|
||||||
typeId = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericScalePacket typeId=[%d]\n", typeId);
|
|
||||||
genericPacketLen = 2;
|
|
||||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
|
||||||
outData = (char*)malloc(uibcBodyLen + 1);
|
|
||||||
// UIBC header
|
|
||||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
|
||||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
|
||||||
//Generic Input Body Format
|
|
||||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
|
||||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
|
||||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
|
||||||
outData[7] = 0x00; // Clear the byte
|
|
||||||
outData[8] = 0x00; // Clear the byte
|
|
||||||
/*
|
|
||||||
B15B14; Scroll Unit Indication bits.
|
|
||||||
0b00; the unit is a pixel (normalized with respect to the WFD Source display resolution that is conveyed in an RTSP M4 request message).
|
|
||||||
0b01; the unit is a mouse notch (where the application is responsible for representing the number of pixels per notch).
|
|
||||||
0b10-0b11; Reserved.
|
|
||||||
|
|
||||||
B13; Scroll Direction Indication bit.
|
|
||||||
0b0; Scrolling to the right. Scrolling to the right means the displayed content being shifted to the left from a user perspective.
|
|
||||||
0b1; Scrolling to the left. Scrolling to the left means the displayed content being shifted to the right from a user perspective.
|
|
||||||
|
|
||||||
B12:B0; Number of Scroll bits.
|
|
||||||
Number of units for a Horizontal scroll.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
temp = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericScalePacket unit=[%d]\n", temp);
|
|
||||||
outData[7] = (temp >> 8) & 0xFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
temp = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericScalePacket direction=[%d]\n", temp);
|
|
||||||
outData[7] |= ((temp >> 10) & 0xFF);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
temp = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericScalePacket amount to scroll=[%d]\n", temp);
|
|
||||||
outData[7] |= ((temp >> 12) & 0xFF);
|
|
||||||
outData[8] = temp & 0xFF;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(*(splitedStr + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(splitedStr);
|
|
||||||
}
|
|
||||||
//hexdump(outData, uibcBodyLen);
|
|
||||||
uibcmessage->m_DataValid = true;
|
|
||||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format: "typeId, integer part, fraction part"
|
|
||||||
void getUIBCGenericRotatePacket(const char * inEventDesc, UibcMessage* uibcmessage) {
|
|
||||||
log_info("getUIBCGenericRotatePacket (%s)", inEventDesc);
|
|
||||||
char* outData = uibcmessage->m_PacketData;
|
|
||||||
int32_t typeId;
|
|
||||||
int32_t uibcBodyLen, genericPacketLen;
|
|
||||||
int32_t integerPart, FractionPart;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
|
||||||
|
|
||||||
if (splitedStr) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; * (splitedStr + i); i++) {
|
|
||||||
//log_info("getUIBCGenericRotatePacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0: {
|
|
||||||
typeId = atoi(*(splitedStr + i));
|
|
||||||
//log_info("getUIBCGenericRotatePacket typeId=[%d]\n", typeId);
|
|
||||||
genericPacketLen = 2;
|
|
||||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
|
||||||
outData = (char*)malloc(uibcBodyLen + 1);
|
|
||||||
// UIBC header
|
|
||||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
|
||||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
|
||||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
|
||||||
//Generic Input Body Format
|
|
||||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
|
||||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
|
||||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
integerPart = atoi(*(splitedStr + i));
|
|
||||||
outData[7] = integerPart & 0xFF;
|
|
||||||
//log_info("getUIBCGenericRotatePacket integerPart=[%d]\n", integerPart);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
FractionPart = atoi(*(splitedStr + i));
|
|
||||||
outData[8] = FractionPart & 0xFF;
|
|
||||||
//log_info("getUIBCGenericRotatePacket FractionPart=[%d]\n", FractionPart);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(*(splitedStr + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(splitedStr);
|
|
||||||
}
|
|
||||||
//hexdump(outData, uibcBodyLen);
|
|
||||||
uibcmessage->m_DataValid = true;
|
|
||||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char** str_split(char* pStr, const char* pDelim, size_t* size) {
|
|
||||||
char** result = 0;
|
|
||||||
size_t count = 0;
|
|
||||||
char* tmp = pStr;
|
|
||||||
char* tmpStr = NULL;
|
|
||||||
char* last_comma = 0;
|
|
||||||
|
|
||||||
asprintf(&tmpStr, "%s", pStr);
|
|
||||||
|
|
||||||
/* Count how many elements will be extracted. */
|
|
||||||
while (*tmp) {
|
|
||||||
if (*pDelim == *tmp) {
|
|
||||||
count++;
|
|
||||||
last_comma = tmp;
|
|
||||||
}
|
|
||||||
tmp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add space for trailing token. */
|
|
||||||
count += last_comma < (pStr + strlen(pStr) - 1) ? 1 : 0;
|
|
||||||
|
|
||||||
result = (char**)malloc(sizeof(char*) * count);
|
|
||||||
|
|
||||||
*size = count;
|
|
||||||
|
|
||||||
tmp = tmpStr = strdup(pStr);
|
|
||||||
size_t idx = 0;
|
|
||||||
char* token;
|
|
||||||
while ((token = strsep(&tmp, pDelim)) != NULL) {
|
|
||||||
* (result + idx++) = strdup(token);
|
|
||||||
}
|
|
||||||
free(tmpStr);
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
|
|
||||||
#ifndef MIRACLE_UIBCCTL_H
|
|
||||||
#define MIRACLE_UIBCCTL_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include<arpa/inet.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "shl_log.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GENERIC_TOUCH_DOWN = 0,
|
|
||||||
GENERIC_TOUCH_UP,
|
|
||||||
GENERIC_TOUCH_MOVE,
|
|
||||||
GENERIC_KEY_DOWN,
|
|
||||||
GENERIC_KEY_UP,
|
|
||||||
GENERIC_ZOOM,
|
|
||||||
GENERIC_VERTICAL_SCROLL,
|
|
||||||
GENERIC_HORIZONTAL_SCROLL,
|
|
||||||
GENERIC_ROTATE
|
|
||||||
} MessageType;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* m_PacketData;
|
|
||||||
size_t m_PacketDataLen;
|
|
||||||
bool m_DataValid;
|
|
||||||
} UibcMessage;
|
|
||||||
|
|
||||||
UibcMessage buildUibcMessage(MessageType type, const char* inEventDesc, double widthRatio, double heightRatio);
|
|
||||||
|
|
||||||
static char** str_split(char* pStr, const char* pDelim, size_t* size);
|
|
||||||
|
|
||||||
void getUIBCGenericTouchPacket(const char *inEventDesc, UibcMessage* uibcmessage, double widthRatio, double heightRatio);
|
|
||||||
void getUIBCGenericKeyPacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
|
||||||
void getUIBCGenericZoomPacket(const char *inEventDesc,UibcMessage* uibcmessage);
|
|
||||||
void getUIBCGenericScalePacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
|
||||||
void getUIBCGenericRotatePacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
|
||||||
|
|
||||||
void hexdump(void *_data, size_t len);
|
|
||||||
void binarydump(void *_data, size_t len);
|
|
||||||
|
|
||||||
int sendUibcMessage(UibcMessage* uibcmessage, int sockfd);
|
|
||||||
#endif
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
|
||||||
|
########### next target ###############
|
||||||
|
|
||||||
set(miracle-wifid_SRCS wifid.h
|
set(miracle-wifid_SRCS wifid.h
|
||||||
wifid.c
|
wifid.c
|
||||||
wifid-dbus.c
|
wifid-dbus.c
|
||||||
|
@ -9,7 +12,6 @@ add_executable(miracle-wifid ${miracle-wifid_SRCS})
|
||||||
|
|
||||||
target_link_libraries(miracle-wifid ${KDE4_KDECORE_LIBS})
|
target_link_libraries(miracle-wifid ${KDE4_KDECORE_LIBS})
|
||||||
|
|
||||||
cmake_policy(SET CMP0015 NEW)
|
|
||||||
include_directories(shared)
|
include_directories(shared)
|
||||||
link_directories(shared)
|
link_directories(shared)
|
||||||
target_link_libraries(miracle-wifid miracle-shared)
|
target_link_libraries(miracle-wifid miracle-shared)
|
||||||
|
@ -17,11 +19,40 @@ target_link_libraries(miracle-wifid miracle-shared)
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
|
||||||
pkg_check_modules (UDEV REQUIRED libudev)
|
pkg_check_modules (UDEV REQUIRED libudev)
|
||||||
|
#link_directories( ${UDEV_LIBRARY_DIRS})
|
||||||
|
#include_directories( ${UDEV_INCLUDE_DIRS})
|
||||||
target_link_libraries(miracle-wifid ${UDEV_LIBRARIES})
|
target_link_libraries(miracle-wifid ${UDEV_LIBRARIES})
|
||||||
target_link_libraries(miracle-wifid m)
|
#link_directories( ${GLIB2_LIBRARY_DIRS})
|
||||||
link_directories( ${GLIB2_LIBRARY_DIRS})
|
#include_directories( ${GLIB2_INCLUDE_DIRS})
|
||||||
include_directories( ${GLIB2_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(miracle-wifid ${GLIB2_LIBRARIES})
|
target_link_libraries(miracle-wifid ${GLIB2_LIBRARIES})
|
||||||
|
|
||||||
install(TARGETS miracle-wifid DESTINATION bin)
|
install(TARGETS miracle-wifid DESTINATION bin)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
#set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake-extensions/ )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#bin_PROGRAMS = miracle-wifid
|
||||||
|
#
|
||||||
|
#miracle_wifid_SOURCES = \
|
||||||
|
# wifid.h \
|
||||||
|
# wifid.c \
|
||||||
|
# wifid-dbus.c \
|
||||||
|
# wifid-link.c \
|
||||||
|
# wifid-peer.c \
|
||||||
|
# wifid-supplicant.c
|
||||||
|
#miracle_wifid_CPPFLAGS = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS)
|
||||||
|
#miracle_wifid_LDADD = \
|
||||||
|
# ../shared/libmiracle-shared.la \
|
||||||
|
# $(DEPS_LIBS)
|
||||||
|
#
|
||||||
|
|
|
@ -10,10 +10,8 @@ miracle_wifid_SOURCES = \
|
||||||
wifid-supplicant.c
|
wifid-supplicant.c
|
||||||
miracle_wifid_CPPFLAGS = \
|
miracle_wifid_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
$(DEPS_CFLAGS) \
|
$(DEPS_CFLAGS)
|
||||||
$(GLIB_CFLAGS)
|
|
||||||
miracle_wifid_LDADD = \
|
miracle_wifid_LDADD = \
|
||||||
../shared/libmiracle-shared.la \
|
../shared/libmiracle-shared.la \
|
||||||
$(DEPS_LIBS) \
|
$(DEPS_LIBS)
|
||||||
$(GLIB_LIBS)
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
inc = include_directories('../..')
|
|
||||||
miracle_wifid_src = ['wifid.h',
|
|
||||||
'wifid.c',
|
|
||||||
'wifid-dbus.c',
|
|
||||||
'wifid-link.c',
|
|
||||||
'wifid-peer.c',
|
|
||||||
'wifid-supplicant.c'
|
|
||||||
]
|
|
||||||
executable('miracle-wifid', miracle_wifid_src,
|
|
||||||
include_directories: inc,
|
|
||||||
install: true,
|
|
||||||
dependencies: [udev, glib2, libsystemd, libmiracle_shared_dep, m]
|
|
||||||
)
|
|
||||||
|
|
|
@ -309,7 +309,6 @@ static const sd_bus_vtable peer_dbus_vtable[] = {
|
||||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
|
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
|
||||||
SD_BUS_SIGNAL("GoNegRequest", "ss", 0),
|
SD_BUS_SIGNAL("GoNegRequest", "ss", 0),
|
||||||
SD_BUS_SIGNAL("FormationFailure", "s", 0),
|
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -571,42 +570,6 @@ static int link_dbus_set_friendly_name(sd_bus *bus,
|
||||||
return link_set_friendly_name(l, name);
|
return link_set_friendly_name(l, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int link_dbus_get_managed(sd_bus *bus,
|
|
||||||
const char *path,
|
|
||||||
const char *interface,
|
|
||||||
const char *property,
|
|
||||||
sd_bus_message *reply,
|
|
||||||
void *data,
|
|
||||||
sd_bus_error *err)
|
|
||||||
{
|
|
||||||
struct link *l = data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = sd_bus_message_append(reply, "b", link_get_managed(l));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int link_dbus_set_managed(sd_bus *bus,
|
|
||||||
const char *path,
|
|
||||||
const char *interface,
|
|
||||||
const char *property,
|
|
||||||
sd_bus_message *value,
|
|
||||||
void *data,
|
|
||||||
sd_bus_error *err)
|
|
||||||
{
|
|
||||||
struct link *l = data;
|
|
||||||
int val, r;
|
|
||||||
|
|
||||||
r = sd_bus_message_read(value, "b", &val);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return link_set_managed(l, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int link_dbus_get_p2p_scanning(sd_bus *bus,
|
static int link_dbus_get_p2p_scanning(sd_bus *bus,
|
||||||
const char *path,
|
const char *path,
|
||||||
const char *interface,
|
const char *interface,
|
||||||
|
@ -698,12 +661,6 @@ static const sd_bus_vtable link_dbus_vtable[] = {
|
||||||
link_dbus_set_friendly_name,
|
link_dbus_set_friendly_name,
|
||||||
0,
|
0,
|
||||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_WRITABLE_PROPERTY("Managed",
|
|
||||||
"b",
|
|
||||||
link_dbus_get_managed,
|
|
||||||
link_dbus_set_managed,
|
|
||||||
0,
|
|
||||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
||||||
SD_BUS_WRITABLE_PROPERTY("P2PScanning",
|
SD_BUS_WRITABLE_PROPERTY("P2PScanning",
|
||||||
"b",
|
"b",
|
||||||
link_dbus_get_p2p_scanning,
|
link_dbus_get_p2p_scanning,
|
||||||
|
@ -937,12 +894,8 @@ int manager_dbus_connect(struct manager *m)
|
||||||
|
|
||||||
r = sd_bus_request_name(m->bus, "org.freedesktop.miracle.wifi", 0);
|
r = sd_bus_request_name(m->bus, "org.freedesktop.miracle.wifi", 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (r == -EEXIST) {
|
log_error("cannot claim org.freedesktop.miracle.wifi bus-name: %d",
|
||||||
log_info("cannot claim org.freedesktop.miracle.wifi bus-name: it is already being acquired");
|
|
||||||
} else {
|
|
||||||
log_error("cannot claim org.freedesktop.miracle.wifi bus-name: %d",
|
|
||||||
r);
|
r);
|
||||||
}
|
|
||||||
goto error_silent;
|
goto error_silent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,6 @@ int link_new(struct manager *m,
|
||||||
if (out)
|
if (out)
|
||||||
*out = l;
|
*out = l;
|
||||||
|
|
||||||
l->public = true;
|
|
||||||
link_dbus_added(l);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -118,9 +116,6 @@ void link_free(struct link *l)
|
||||||
|
|
||||||
link_set_managed(l, false);
|
link_set_managed(l, false);
|
||||||
|
|
||||||
link_dbus_removed(l);
|
|
||||||
l->public = false;
|
|
||||||
|
|
||||||
if (shl_htable_remove_uint(&l->m->links, l->ifindex, NULL)) {
|
if (shl_htable_remove_uint(&l->m->links, l->ifindex, NULL)) {
|
||||||
log_info("remove link: %s", l->ifname);
|
log_info("remove link: %s", l->ifname);
|
||||||
--l->m->link_cnt;
|
--l->m->link_cnt;
|
||||||
|
@ -134,66 +129,17 @@ void link_free(struct link *l)
|
||||||
free(l->wfd_subelements);
|
free(l->wfd_subelements);
|
||||||
free(l->friendly_name);
|
free(l->friendly_name);
|
||||||
free(l->ifname);
|
free(l->ifname);
|
||||||
free(l->config_methods);
|
|
||||||
free(l->ip_binary);
|
|
||||||
free(l);
|
free(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void link_use_dev(struct link *l)
|
void link_set_managed(struct link *l, bool set)
|
||||||
{
|
|
||||||
l->use_dev = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool link_is_using_dev(struct link *l)
|
|
||||||
{
|
|
||||||
return l->use_dev;
|
|
||||||
}
|
|
||||||
|
|
||||||
int link_set_config_methods(struct link *l, char *config_methods)
|
|
||||||
{
|
|
||||||
char *cm;
|
|
||||||
|
|
||||||
if (!config_methods)
|
|
||||||
return log_EINVAL();
|
|
||||||
|
|
||||||
cm = strdup(config_methods);
|
|
||||||
if (!cm)
|
|
||||||
return log_ENOMEM();
|
|
||||||
|
|
||||||
free(l->config_methods);
|
|
||||||
l->config_methods = cm;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int link_set_ip_binary(struct link *l, const char *ip_binary)
|
|
||||||
{
|
|
||||||
char *ipb;
|
|
||||||
|
|
||||||
if (!ip_binary)
|
|
||||||
return log_EINVAL();
|
|
||||||
|
|
||||||
ipb = strdup(ip_binary);
|
|
||||||
if (!ipb)
|
|
||||||
return log_ENOMEM();
|
|
||||||
|
|
||||||
free(l->ip_binary);
|
|
||||||
l->ip_binary = ipb;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool link_get_managed(struct link *l)
|
|
||||||
{
|
|
||||||
return l->managed;
|
|
||||||
}
|
|
||||||
|
|
||||||
int link_set_managed(struct link *l, bool set)
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!l)
|
if (!l)
|
||||||
return log_EINVAL();
|
return log_vEINVAL();
|
||||||
if (l->managed == set)
|
if (l->managed == set)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (set) {
|
if (set) {
|
||||||
log_info("manage link %s", l->ifname);
|
log_info("manage link %s", l->ifname);
|
||||||
|
@ -201,7 +147,7 @@ int link_set_managed(struct link *l, bool set)
|
||||||
r = supplicant_start(l->s);
|
r = supplicant_start(l->s);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error("cannot start supplicant on %s", l->ifname);
|
log_error("cannot start supplicant on %s", l->ifname);
|
||||||
return -EFAULT;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_info("link %s no longer managed", l->ifname);
|
log_info("link %s no longer managed", l->ifname);
|
||||||
|
@ -209,7 +155,6 @@ int link_set_managed(struct link *l, bool set)
|
||||||
}
|
}
|
||||||
|
|
||||||
l->managed = set;
|
l->managed = set;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_renamed(struct link *l, const char *ifname)
|
int link_renamed(struct link *l, const char *ifname)
|
||||||
|
@ -279,9 +224,6 @@ int link_set_wfd_subelements(struct link *l, const char *val)
|
||||||
if (!l || !val)
|
if (!l || !val)
|
||||||
return log_EINVAL();
|
return log_EINVAL();
|
||||||
|
|
||||||
if (!l->managed)
|
|
||||||
return log_EUNMANAGED();
|
|
||||||
|
|
||||||
t = strdup(val);
|
t = strdup(val);
|
||||||
if (!t)
|
if (!t)
|
||||||
return log_ENOMEM();
|
return log_ENOMEM();
|
||||||
|
@ -314,9 +256,6 @@ int link_set_p2p_scanning(struct link *l, bool set)
|
||||||
if (!l)
|
if (!l)
|
||||||
return log_EINVAL();
|
return log_EINVAL();
|
||||||
|
|
||||||
if (!l->managed)
|
|
||||||
return log_EUNMANAGED();
|
|
||||||
|
|
||||||
if (set) {
|
if (set) {
|
||||||
return supplicant_p2p_start_scan(l->s);
|
return supplicant_p2p_start_scan(l->s);
|
||||||
} else {
|
} else {
|
||||||
|
@ -327,16 +266,7 @@ int link_set_p2p_scanning(struct link *l, bool set)
|
||||||
|
|
||||||
bool link_get_p2p_scanning(struct link *l)
|
bool link_get_p2p_scanning(struct link *l)
|
||||||
{
|
{
|
||||||
if (!l) {
|
return l && supplicant_p2p_scanning(l->s);
|
||||||
log_vEINVAL();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!l->managed) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return supplicant_p2p_scanning(l->s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void link_supplicant_started(struct link *l)
|
void link_supplicant_started(struct link *l)
|
||||||
|
@ -344,9 +274,9 @@ void link_supplicant_started(struct link *l)
|
||||||
if (!l || l->public)
|
if (!l || l->public)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (l->m->friendly_name && l->managed)
|
log_debug("link %s started", l->ifname);
|
||||||
link_set_friendly_name(l, l->m->friendly_name);
|
l->public = true;
|
||||||
log_info("link %s managed", l->ifname);
|
link_dbus_added(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void link_supplicant_stopped(struct link *l)
|
void link_supplicant_stopped(struct link *l)
|
||||||
|
@ -354,7 +284,9 @@ void link_supplicant_stopped(struct link *l)
|
||||||
if (!l || !l->public)
|
if (!l || !l->public)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_info("link %s unmanaged", l->ifname);
|
log_debug("link %s stopped", l->ifname);
|
||||||
|
link_dbus_removed(l);
|
||||||
|
l->public = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void link_supplicant_p2p_scan_changed(struct link *l, bool new_value)
|
void link_supplicant_p2p_scan_changed(struct link *l, bool new_value)
|
||||||
|
|
|
@ -61,8 +61,7 @@ int peer_new(struct link *l,
|
||||||
r = log_ENOMEM();
|
r = log_ENOMEM();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
strncpy(p->p2p_mac, mac, MAC_STRLEN);
|
strncpy(p->p2p_mac, mac, MAC_STRLEN - 1);
|
||||||
p->p2p_mac[MAC_STRLEN - 1] = 0;
|
|
||||||
|
|
||||||
r = shl_htable_insert_str(&l->peers, &p->p2p_mac, NULL);
|
r = shl_htable_insert_str(&l->peers, &p->p2p_mac, NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|
|
@ -19,21 +19,14 @@
|
||||||
|
|
||||||
#define LOG_SUBSYSTEM "supplicant"
|
#define LOG_SUBSYSTEM "supplicant"
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <systemd/sd-event.h>
|
#include <systemd/sd-event.h>
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
#include <systemd/sd-journal.h>
|
#include <systemd/sd-journal.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "shl_dlist.h"
|
#include "shl_dlist.h"
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
|
@ -41,6 +34,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wifid.h"
|
#include "wifid.h"
|
||||||
#include "wpas.h"
|
#include "wpas.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
struct supplicant_group {
|
struct supplicant_group {
|
||||||
unsigned long users;
|
unsigned long users;
|
||||||
|
@ -379,7 +373,6 @@ static int supplicant_group_spawn_dhcp_server(struct supplicant_group *g,
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
/* redirect stdout/stderr to journal */
|
/* redirect stdout/stderr to journal */
|
||||||
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
|
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
|
||||||
fd_journal = sd_journal_stream_fd(journal_id, LOG_INFO, false);
|
fd_journal = sd_journal_stream_fd(journal_id, LOG_INFO, false);
|
||||||
|
@ -388,15 +381,12 @@ static int supplicant_group_spawn_dhcp_server(struct supplicant_group *g,
|
||||||
dup2(fd_journal, 1);
|
dup2(fd_journal, 1);
|
||||||
dup2(fd_journal, 2);
|
dup2(fd_journal, 2);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
|
||||||
/* no journal? redirect stdout to parent's stderr */
|
/* no journal? redirect stdout to parent's stderr */
|
||||||
dup2(2, 1);
|
dup2(2, 1);
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
argv[i++] = (char*) "miracle-dhcp";
|
argv[i++] = (char*) BUILD_BINDIR "/miracle-dhcp";
|
||||||
argv[i++] = "--server";
|
argv[i++] = "--server";
|
||||||
argv[i++] = "--prefix";
|
argv[i++] = "--prefix";
|
||||||
argv[i++] = prefix;
|
argv[i++] = prefix;
|
||||||
|
@ -406,15 +396,9 @@ static int supplicant_group_spawn_dhcp_server(struct supplicant_group *g,
|
||||||
argv[i++] = g->ifname;
|
argv[i++] = g->ifname;
|
||||||
argv[i++] = "--comm-fd";
|
argv[i++] = "--comm-fd";
|
||||||
argv[i++] = commfd;
|
argv[i++] = commfd;
|
||||||
if (g->s->l->ip_binary) {
|
|
||||||
argv[i++] = "--ip-binary";
|
|
||||||
argv[i++] = g->s->l->ip_binary;
|
|
||||||
}
|
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
|
|
||||||
if (execvpe(argv[0], argv, environ)< 0) {
|
execve(argv[0], argv, environ);
|
||||||
log_error("dhcp failed (%d): %m", errno);
|
|
||||||
}
|
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +435,6 @@ static int supplicant_group_spawn_dhcp_client(struct supplicant_group *g)
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
/* redirect stdout/stderr to journal */
|
/* redirect stdout/stderr to journal */
|
||||||
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
|
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
|
||||||
fd_journal = sd_journal_stream_fd(journal_id, LOG_INFO, false);
|
fd_journal = sd_journal_stream_fd(journal_id, LOG_INFO, false);
|
||||||
|
@ -460,30 +443,21 @@ static int supplicant_group_spawn_dhcp_client(struct supplicant_group *g)
|
||||||
dup2(fd_journal, 1);
|
dup2(fd_journal, 1);
|
||||||
dup2(fd_journal, 2);
|
dup2(fd_journal, 2);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
|
||||||
/* no journal? redirect stdout to parent's stderr */
|
/* no journal? redirect stdout to parent's stderr */
|
||||||
dup2(2, 1);
|
dup2(2, 1);
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
argv[i++] = (char*) "miracle-dhcp";
|
argv[i++] = (char*) BUILD_BINDIR "/miracle-dhcp";
|
||||||
argv[i++] = "--log-level";
|
argv[i++] = "--log-level";
|
||||||
argv[i++] = loglevel;
|
argv[i++] = loglevel;
|
||||||
argv[i++] = "--netdev";
|
argv[i++] = "--netdev";
|
||||||
argv[i++] = g->ifname;
|
argv[i++] = g->ifname;
|
||||||
argv[i++] = "--comm-fd";
|
argv[i++] = "--comm-fd";
|
||||||
argv[i++] = commfd;
|
argv[i++] = commfd;
|
||||||
if (g->s->l->ip_binary) {
|
|
||||||
argv[i++] = "--ip-binary";
|
|
||||||
argv[i++] = g->s->l->ip_binary;
|
|
||||||
}
|
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
|
|
||||||
if (execvpe(argv[0], argv, environ) < 0) {
|
execve(argv[0], argv, environ);
|
||||||
log_error("dhcp failed (%d): %m", errno);
|
|
||||||
}
|
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +504,7 @@ static int supplicant_group_new(struct supplicant *s,
|
||||||
j = shl_dlist_entry(i,
|
j = shl_dlist_entry(i,
|
||||||
struct supplicant_group,
|
struct supplicant_group,
|
||||||
list);
|
list);
|
||||||
if (j->subnet == subnet)
|
if (j->subnet == j->subnet)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +871,7 @@ static void supplicant_parse_peer(struct supplicant *s,
|
||||||
/* TODO: wfd_dev_info only contains the dev-info sub-elem,
|
/* TODO: wfd_dev_info only contains the dev-info sub-elem,
|
||||||
* while wfd_sublemens contains all. Fix that! The user has no
|
* while wfd_sublemens contains all. Fix that! The user has no
|
||||||
* chance to distinguish both.
|
* chance to distinguish both.
|
||||||
* We currently use it only as boolean (set/unset) but once we
|
* We currently use it only as boolen (set/unset) but once we
|
||||||
* parse it we _definitely_ have to provide proper data. */
|
* parse it we _definitely_ have to provide proper data. */
|
||||||
r = wpas_message_dict_read(m, "wfd_dev_info", 's', &val);
|
r = wpas_message_dict_read(m, "wfd_dev_info", 's', &val);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
|
@ -1313,20 +1287,6 @@ static void supplicant_event_p2p_group_removed(struct supplicant *s,
|
||||||
supplicant_group_free(g);
|
supplicant_group_free(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void supplicant_event_p2p_go_neg_failure(struct supplicant *s,
|
|
||||||
struct wpas_message *ev)
|
|
||||||
{
|
|
||||||
struct peer *p;
|
|
||||||
|
|
||||||
if (s->pending) {
|
|
||||||
log_debug("peer %s group owner negotiation failed",
|
|
||||||
s->pending->friendly_name);
|
|
||||||
p = s->pending->p;
|
|
||||||
s->pending = NULL;
|
|
||||||
peer_supplicant_formation_failure(p, "group owner negotiation failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void supplicant_event_p2p_group_formation_failure(struct supplicant *s,
|
static void supplicant_event_p2p_group_formation_failure(struct supplicant *s,
|
||||||
struct wpas_message *ev)
|
struct wpas_message *ev)
|
||||||
{
|
{
|
||||||
|
@ -1472,6 +1432,7 @@ static void supplicant_event(struct supplicant *s, struct wpas_message *m)
|
||||||
!strcmp(name, "WPS-AP-AVAILABLE-PIN") ||
|
!strcmp(name, "WPS-AP-AVAILABLE-PIN") ||
|
||||||
!strcmp(name, "CTRL-EVENT-EAP-STATUS") ||
|
!strcmp(name, "CTRL-EVENT-EAP-STATUS") ||
|
||||||
!strcmp(name, "CTRL-EVENT-EAP-METHOD") ||
|
!strcmp(name, "CTRL-EVENT-EAP-METHOD") ||
|
||||||
|
!strcmp(name, "CTRL-EVENT-EAP-STATUS") ||
|
||||||
!strcmp(name, "WPS-CRED-RECEIVED") ||
|
!strcmp(name, "WPS-CRED-RECEIVED") ||
|
||||||
!strcmp(name, "WPS-AP-AVAILABLE") ||
|
!strcmp(name, "WPS-AP-AVAILABLE") ||
|
||||||
!strcmp(name, "WPS-REG-SUCCESS") ||
|
!strcmp(name, "WPS-REG-SUCCESS") ||
|
||||||
|
@ -1506,8 +1467,6 @@ static void supplicant_event(struct supplicant *s, struct wpas_message *m)
|
||||||
supplicant_event_p2p_group_started(s, m);
|
supplicant_event_p2p_group_started(s, m);
|
||||||
else if (!strcmp(name, "P2P-GROUP-REMOVED"))
|
else if (!strcmp(name, "P2P-GROUP-REMOVED"))
|
||||||
supplicant_event_p2p_group_removed(s, m);
|
supplicant_event_p2p_group_removed(s, m);
|
||||||
else if (!strcmp(name, "P2P-GO-NEG-FAILURE"))
|
|
||||||
supplicant_event_p2p_go_neg_failure(s, m);
|
|
||||||
else if (!strcmp(name, "P2P-GROUP-FORMATION-FAILURE"))
|
else if (!strcmp(name, "P2P-GROUP-FORMATION-FAILURE"))
|
||||||
supplicant_event_p2p_group_formation_failure(s, m);
|
supplicant_event_p2p_group_formation_failure(s, m);
|
||||||
else if (!strcmp(name, "AP-STA-CONNECTED"))
|
else if (!strcmp(name, "AP-STA-CONNECTED"))
|
||||||
|
@ -2183,9 +2142,6 @@ static int supplicant_global_fn(struct wpas *w,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore events on the global-iface, we only listen on dev-iface */
|
/* ignore events on the global-iface, we only listen on dev-iface */
|
||||||
if(link_is_using_dev(s->l) && wpas_message_get_ifname(m)) {
|
|
||||||
supplicant_event(s, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2232,7 +2188,7 @@ static int supplicant_global_attach_fn(struct wpas *w,
|
||||||
* Devices with P2P_DEVICE support (instead of direct P2P_GO/CLIENT
|
* Devices with P2P_DEVICE support (instead of direct P2P_GO/CLIENT
|
||||||
* support) are broken with a *lot* of wpa_supplicant versions on the
|
* support) are broken with a *lot* of wpa_supplicant versions on the
|
||||||
* global interface. Therefore, try to open the p2p-dev-* interface
|
* global interface. Therefore, try to open the p2p-dev-* interface
|
||||||
* after the global-ATTACH succeeded (which means the iface is properly
|
* after the global-ATTACH succeded (which means the iface is properly
|
||||||
* set up). If this works, use the p2p-dev-* interface, otherwise, just
|
* set up). If this works, use the p2p-dev-* interface, otherwise, just
|
||||||
* copy the global interface over to bus_dev.
|
* copy the global interface over to bus_dev.
|
||||||
* Event-forwarding is broken on the global-interface in such cases,
|
* Event-forwarding is broken on the global-interface in such cases,
|
||||||
|
@ -2400,7 +2356,6 @@ static void supplicant_run(struct supplicant *s, const char *binary)
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
/* redirect stdout/stderr to journal */
|
/* redirect stdout/stderr to journal */
|
||||||
sprintf(journal_id, "miracle-wifid-%s-%u",
|
sprintf(journal_id, "miracle-wifid-%s-%u",
|
||||||
s->l->ifname, s->l->ifindex);
|
s->l->ifname, s->l->ifindex);
|
||||||
|
@ -2410,12 +2365,9 @@ static void supplicant_run(struct supplicant *s, const char *binary)
|
||||||
dup2(fd_journal, 1);
|
dup2(fd_journal, 1);
|
||||||
dup2(fd_journal, 2);
|
dup2(fd_journal, 2);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
|
||||||
/* no journal? redirect stdout to parent's stderr */
|
/* no journal? redirect stdout to parent's stderr */
|
||||||
dup2(2, 1);
|
dup2(2, 1);
|
||||||
#ifdef ENABLE_SYSTEMD
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* initialize wpa_supplicant args */
|
/* initialize wpa_supplicant args */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -2439,60 +2391,12 @@ static void supplicant_run(struct supplicant *s, const char *binary)
|
||||||
argv[i++] = s->l->ifname;
|
argv[i++] = s->l->ifname;
|
||||||
argv[i++] = "-g";
|
argv[i++] = "-g";
|
||||||
argv[i++] = s->global_ctrl;
|
argv[i++] = s->global_ctrl;
|
||||||
|
|
||||||
if (arg_wpa_syslog) {
|
|
||||||
argv[i++] = "-s";
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
|
|
||||||
/* execute wpa_supplicant; if it fails, the caller issues exit(1) */
|
/* execute wpa_supplicant; if it fails, the caller issues exit(1) */
|
||||||
execve(argv[0], argv, environ);
|
execve(argv[0], argv, environ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int supplicant_find(char **binary)
|
|
||||||
{
|
|
||||||
_shl_free_ char *path = getenv("PATH");
|
|
||||||
if(!path) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = strdup(path);
|
|
||||||
if(!path) {
|
|
||||||
return log_ENOMEM();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stat bin_stat;
|
|
||||||
char *curr = path, *next;
|
|
||||||
while(1) {
|
|
||||||
curr = strtok_r(curr, ":", &next);
|
|
||||||
if(!curr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_shl_free_ char *bin = shl_strcat(curr, "/wpa_supplicant");
|
|
||||||
if (!bin)
|
|
||||||
return log_ENOMEM();
|
|
||||||
|
|
||||||
if(stat(bin, &bin_stat) < 0) {
|
|
||||||
if(ENOENT == errno || ENOTDIR == errno) {
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
return log_ERRNO();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!access(bin, X_OK)) {
|
|
||||||
*binary = strdup(bin);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
curr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int supplicant_spawn(struct supplicant *s)
|
static int supplicant_spawn(struct supplicant *s)
|
||||||
{
|
{
|
||||||
_shl_free_ char *binary = NULL;
|
_shl_free_ char *binary = NULL;
|
||||||
|
@ -2506,16 +2410,14 @@ static int supplicant_spawn(struct supplicant *s)
|
||||||
|
|
||||||
log_debug("spawn supplicant of %s", s->l->ifname);
|
log_debug("spawn supplicant of %s", s->l->ifname);
|
||||||
|
|
||||||
if (supplicant_find(&binary) < 0) {
|
binary = shl_strcat(arg_wpa_bindir, "/wpa_supplicant");
|
||||||
if (binary != NULL) {
|
if (!binary)
|
||||||
log_error("execution of wpas (%s) not possible: %m", binary);
|
return log_ENOMEM();
|
||||||
} else {
|
|
||||||
log_error("execution of wpas not possible: %m");
|
|
||||||
}
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("wpa_supplicant found: %s", binary);
|
if (access(binary, X_OK) < 0) {
|
||||||
|
log_error("execution of wpas (%s) not possible: %m", binary);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
|
@ -2630,9 +2532,10 @@ static int supplicant_write_config(struct supplicant *s)
|
||||||
"driver_param=%s\n"
|
"driver_param=%s\n"
|
||||||
"ap_scan=%s\n"
|
"ap_scan=%s\n"
|
||||||
"# End of configuration\n",
|
"# End of configuration\n",
|
||||||
s->l->friendly_name ?: "unknown",
|
s->l->friendly_name ? : "unknown",
|
||||||
"1-0050F204-1",
|
"1-0050F204-1",
|
||||||
s->l->config_methods ?: "pbc",
|
"pbc",
|
||||||
|
//"pbc keypad pin display",
|
||||||
"p2p_device=1",
|
"p2p_device=1",
|
||||||
"1");
|
"1");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|
110
src/wifi/wifid.c
110
src/wifi/wifid.c
|
@ -40,16 +40,9 @@
|
||||||
#include "wifid.h"
|
#include "wifid.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define XSTR(x) STR(x)
|
const char *arg_wpa_bindir = "/usr/bin";
|
||||||
#define STR(x) #x
|
|
||||||
const char *interface_name = NULL;
|
const char *interface_name = NULL;
|
||||||
const char *config_methods = NULL;
|
|
||||||
unsigned int arg_wpa_loglevel = LOG_NOTICE;
|
unsigned int arg_wpa_loglevel = LOG_NOTICE;
|
||||||
bool arg_wpa_syslog = false;
|
|
||||||
bool use_dev = false;
|
|
||||||
bool lazy_managed = false;
|
|
||||||
const char *arg_ip_binary = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Manager Handling
|
* Manager Handling
|
||||||
|
@ -108,22 +101,13 @@ static void manager_add_udev_link(struct manager *m,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m->friendly_name && l->managed)
|
link_set_friendly_name(l, m->friendly_name);
|
||||||
link_set_friendly_name(l, m->friendly_name);
|
|
||||||
if (m->config_methods)
|
|
||||||
link_set_config_methods(l, m->config_methods);
|
|
||||||
|
|
||||||
if(use_dev)
|
|
||||||
link_use_dev(l);
|
|
||||||
if(arg_ip_binary)
|
|
||||||
link_set_ip_binary(l, arg_ip_binary);
|
|
||||||
|
|
||||||
#ifdef RELY_UDEV
|
#ifdef RELY_UDEV
|
||||||
bool managed = udev_device_has_tag(d, "miracle") && !lazy_managed;
|
if (udev_device_has_tag(d, "miracle")) {
|
||||||
#else
|
#else
|
||||||
bool managed = (!interface_name || !strcmp(interface_name, ifname)) && !lazy_managed;
|
if (!interface_name || !strcmp(interface_name, ifname)) {
|
||||||
#endif
|
#endif
|
||||||
if (managed) {
|
|
||||||
link_set_managed(l, true);
|
link_set_managed(l, true);
|
||||||
} else {
|
} else {
|
||||||
log_debug("ignored device: %s", ifname);
|
log_debug("ignored device: %s", ifname);
|
||||||
|
@ -163,12 +147,12 @@ static int manager_udev_fn(sd_event_source *source,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RELY_UDEV
|
#ifdef RELY_UDEV
|
||||||
if (udev_device_has_tag(d, "miracle") && !lazy_managed)
|
if (udev_device_has_tag(d, "miracle"))
|
||||||
link_set_managed(l, true);
|
link_set_managed(l, true);
|
||||||
else
|
else
|
||||||
link_set_managed(l, false);
|
link_set_managed(l, false);
|
||||||
#else
|
#else
|
||||||
if ((!interface_name || !strcmp(interface_name, ifname)) && !lazy_managed) {
|
if (!interface_name || !strcmp(interface_name, ifname)) {
|
||||||
link_set_managed(l, true);
|
link_set_managed(l, true);
|
||||||
} else {
|
} else {
|
||||||
log_debug("ignored device: %s", ifname);
|
log_debug("ignored device: %s", ifname);
|
||||||
|
@ -228,7 +212,6 @@ static void manager_free(struct manager *m)
|
||||||
sd_event_unref(m->event);
|
sd_event_unref(m->event);
|
||||||
|
|
||||||
free(m->friendly_name);
|
free(m->friendly_name);
|
||||||
free(m->config_methods);
|
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +224,6 @@ static int manager_new(struct manager **out)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
int r;
|
int r;
|
||||||
char *cm;
|
|
||||||
|
|
||||||
m = calloc(1, sizeof(*m));
|
m = calloc(1, sizeof(*m));
|
||||||
if (!m)
|
if (!m)
|
||||||
|
@ -249,16 +231,6 @@ static int manager_new(struct manager **out)
|
||||||
|
|
||||||
shl_htable_init_uint(&m->links);
|
shl_htable_init_uint(&m->links);
|
||||||
|
|
||||||
|
|
||||||
if (config_methods) {
|
|
||||||
cm = strdup(config_methods);
|
|
||||||
if (!cm)
|
|
||||||
return log_ENOMEM();
|
|
||||||
|
|
||||||
free(m->config_methods);
|
|
||||||
m->config_methods = cm;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_event_default(&m->event);
|
r = sd_event_default(&m->event);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_vERR(r);
|
log_vERR(r);
|
||||||
|
@ -482,16 +454,11 @@ static int help(void)
|
||||||
" --version Show package version\n"
|
" --version Show package version\n"
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --log-time Prefix log-messages with timestamp\n"
|
" --log-time Prefix log-messages with timestamp\n"
|
||||||
" --log-date-time Prefix log-messages with date time\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
" -i --interface Choose the interface to use\n"
|
" -i --interface Choose the interface to use\n"
|
||||||
" --config-methods Define config methods for pairing, default 'pbc'\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
" --wpa-loglevel <lvl> wpa_supplicant log-level\n"
|
" --wpa-bindir <dir> wpa_supplicant binary dir [/usr/bin]\n"
|
||||||
" --wpa-syslog wpa_supplicant use syslog\n"
|
" --wpa-loglevel <lvl wpa_supplicant log-level\n"
|
||||||
" --use-dev enable workaround for 'no ifname' issue\n"
|
|
||||||
" --lazy-managed manage interface only when user decide to do\n"
|
|
||||||
" --ip-binary <path> path to 'ip' binary [default: "XSTR(IP_BINARY)"]\n"
|
|
||||||
, program_invocation_short_name);
|
, program_invocation_short_name);
|
||||||
/*
|
/*
|
||||||
* 80-char barrier:
|
* 80-char barrier:
|
||||||
|
@ -507,28 +474,19 @@ static int parse_argv(int argc, char *argv[])
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_LOG_TIME,
|
ARG_LOG_TIME,
|
||||||
ARG_LOG_DATE_TIME,
|
|
||||||
|
ARG_WPA_BINDIR,
|
||||||
ARG_WPA_LOGLEVEL,
|
ARG_WPA_LOGLEVEL,
|
||||||
ARG_WPA_SYSLOG,
|
|
||||||
ARG_USE_DEV,
|
|
||||||
ARG_CONFIG_METHODS,
|
|
||||||
ARG_LAZY_MANAGED,
|
|
||||||
ARG_IP_BINARY,
|
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
|
||||||
{ "log-date-time", no_argument, NULL, ARG_LOG_DATE_TIME },
|
|
||||||
|
|
||||||
|
{ "wpa-bindir", required_argument, NULL, ARG_WPA_BINDIR },
|
||||||
{ "wpa-loglevel", required_argument, NULL, ARG_WPA_LOGLEVEL },
|
{ "wpa-loglevel", required_argument, NULL, ARG_WPA_LOGLEVEL },
|
||||||
{ "wpa-syslog", no_argument, NULL, ARG_WPA_SYSLOG },
|
|
||||||
{ "interface", required_argument, NULL, 'i' },
|
{ "interface", required_argument, NULL, 'i' },
|
||||||
{ "use-dev", no_argument, NULL, ARG_USE_DEV },
|
|
||||||
{ "config-methods", required_argument, NULL, ARG_CONFIG_METHODS },
|
|
||||||
{ "lazy-managed", no_argument, NULL, ARG_LAZY_MANAGED },
|
|
||||||
{ "ip-binary", required_argument, NULL, ARG_IP_BINARY },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
@ -549,27 +507,13 @@ static int parse_argv(int argc, char *argv[])
|
||||||
case ARG_LOG_TIME:
|
case ARG_LOG_TIME:
|
||||||
log_init_time();
|
log_init_time();
|
||||||
break;
|
break;
|
||||||
case ARG_LOG_DATE_TIME:
|
|
||||||
log_date_time = true;
|
case ARG_WPA_BINDIR:
|
||||||
break;
|
arg_wpa_bindir = optarg;
|
||||||
case ARG_USE_DEV:
|
|
||||||
use_dev = true;
|
|
||||||
break;
|
|
||||||
case ARG_CONFIG_METHODS:
|
|
||||||
config_methods = optarg;
|
|
||||||
break;
|
|
||||||
case ARG_LAZY_MANAGED:
|
|
||||||
lazy_managed = true;
|
|
||||||
break;
|
break;
|
||||||
case ARG_WPA_LOGLEVEL:
|
case ARG_WPA_LOGLEVEL:
|
||||||
arg_wpa_loglevel = log_parse_arg(optarg);
|
arg_wpa_loglevel = log_parse_arg(optarg);
|
||||||
break;
|
break;
|
||||||
case ARG_WPA_SYSLOG:
|
|
||||||
arg_wpa_syslog = true;
|
|
||||||
break;
|
|
||||||
case ARG_IP_BINARY:
|
|
||||||
arg_ip_binary = optarg;
|
|
||||||
break;
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -595,30 +539,12 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
GKeyFile* gkf = load_ini_file();
|
|
||||||
|
|
||||||
if (gkf) {
|
|
||||||
gchar* log_level;
|
|
||||||
log_level = g_key_file_get_string (gkf, "wifid", "log-level", NULL);
|
|
||||||
if (log_level) {
|
|
||||||
log_max_sev = log_parse_arg(log_level);
|
|
||||||
g_free(log_level);
|
|
||||||
}
|
|
||||||
g_key_file_free(gkf);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
if (!r)
|
if (!r)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
if (getuid() != 0) {
|
|
||||||
r = EACCES;
|
|
||||||
log_notice("Must run as root");
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = manager_new(&m);
|
r = manager_new(&m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
@ -129,15 +129,12 @@ struct link {
|
||||||
char *ifname;
|
char *ifname;
|
||||||
char *friendly_name;
|
char *friendly_name;
|
||||||
char *wfd_subelements;
|
char *wfd_subelements;
|
||||||
char *config_methods;
|
|
||||||
char *ip_binary;
|
|
||||||
|
|
||||||
size_t peer_cnt;
|
size_t peer_cnt;
|
||||||
struct shl_htable peers;
|
struct shl_htable peers;
|
||||||
|
|
||||||
bool managed : 1;
|
bool managed : 1;
|
||||||
bool public : 1;
|
bool public : 1;
|
||||||
bool use_dev : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define link_from_htable(_l) \
|
#define link_from_htable(_l) \
|
||||||
|
@ -156,17 +153,9 @@ int link_new(struct manager *m,
|
||||||
struct link **out);
|
struct link **out);
|
||||||
void link_free(struct link *l);
|
void link_free(struct link *l);
|
||||||
|
|
||||||
/* workaround for the 'no ifname' issue */
|
void link_set_managed(struct link *l, bool set);
|
||||||
void link_use_dev(struct link *l);
|
|
||||||
bool link_is_using_dev(struct link *l);
|
|
||||||
|
|
||||||
int link_set_ip_binary(struct link *l, const char *ip_binary);
|
|
||||||
|
|
||||||
int link_set_managed(struct link *l, bool set);
|
|
||||||
bool link_get_managed(struct link *l);
|
|
||||||
int link_renamed(struct link *l, const char *ifname);
|
int link_renamed(struct link *l, const char *ifname);
|
||||||
|
|
||||||
int link_set_config_methods(struct link *l, char *config_methods);
|
|
||||||
int link_set_friendly_name(struct link *l, const char *name);
|
int link_set_friendly_name(struct link *l, const char *name);
|
||||||
const char *link_get_friendly_name(struct link *l);
|
const char *link_get_friendly_name(struct link *l);
|
||||||
int link_set_wfd_subelements(struct link *l, const char *val);
|
int link_set_wfd_subelements(struct link *l, const char *val);
|
||||||
|
@ -194,7 +183,6 @@ struct manager {
|
||||||
sd_event_source *udev_mon_source;
|
sd_event_source *udev_mon_source;
|
||||||
|
|
||||||
char *friendly_name;
|
char *friendly_name;
|
||||||
char *config_methods;
|
|
||||||
|
|
||||||
size_t link_cnt;
|
size_t link_cnt;
|
||||||
struct shl_htable links;
|
struct shl_htable links;
|
||||||
|
@ -215,7 +203,7 @@ void manager_dbus_disconnect(struct manager *m);
|
||||||
|
|
||||||
/* cli arguments */
|
/* cli arguments */
|
||||||
|
|
||||||
|
extern const char *arg_wpa_bindir;
|
||||||
extern unsigned int arg_wpa_loglevel;
|
extern unsigned int arg_wpa_loglevel;
|
||||||
extern bool arg_wpa_syslog;
|
|
||||||
|
|
||||||
#endif /* WIFID_H */
|
#endif /* WIFID_H */
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
|
|
||||||
|
########### next target ###############
|
||||||
|
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules (CHECK check)
|
pkg_check_modules (CHECK check)
|
||||||
|
|
||||||
if(CHECK_FOUND)
|
if(CHECK_FOUND)
|
||||||
|
|
||||||
set(test_rtsp_SOURCES test_common.h test_rtsp.c)
|
set(test_rtsp_SOURCES test_common.h test_rtsp.c)
|
||||||
add_executable(test_rtsp ${test_rtsp_SOURCES})
|
add_executable(test_rtsp ${test_rtsp_SOURCES})
|
||||||
target_link_libraries(test_rtsp miracle-shared)
|
target_link_libraries(test_rtsp miracle-shared)
|
||||||
|
target_link_libraries(test_rtsp ${CHECK_LIBRARIES})
|
||||||
target_link_libraries(test_rtsp ${UDEV_LIBRARIES})
|
target_link_libraries(test_rtsp ${UDEV_LIBRARIES})
|
||||||
target_link_libraries(test_rtsp ${GLIB2_LIBRARIES})
|
target_link_libraries(test_rtsp ${GLIB2_LIBRARIES})
|
||||||
target_link_libraries(test_rtsp ${CHECK_LIBRARIES})
|
|
||||||
target_link_libraries(test_rtsp ${CHECK_CFLAGS})
|
|
||||||
|
|
||||||
set(test_wpas_SOURCES test_common.h test_wpas.c)
|
set(test_wpas_SOURCES test_common.h test_wpas.c)
|
||||||
add_executable(test_wpas ${test_wpas_SOURCES})
|
add_executable(test_wpas ${test_wpas_SOURCES})
|
||||||
target_link_libraries(test_wpas miracle-shared)
|
target_link_libraries(test_wpas miracle-shared)
|
||||||
|
target_link_libraries(test_wpas ${CHECK_LIBRARIES})
|
||||||
target_link_libraries(test_wpas ${UDEV_LIBRARIES})
|
target_link_libraries(test_wpas ${UDEV_LIBRARIES})
|
||||||
target_link_libraries(test_wpas ${GLIB2_LIBRARIES})
|
target_link_libraries(test_wpas ${GLIB2_LIBRARIES})
|
||||||
target_link_libraries(test_wpas ${CHECK_LIBRARIES})
|
|
||||||
target_link_libraries(test_wpas ${CHECK_CFLAGS})
|
|
||||||
target_link_libraries(test_wpas m)
|
|
||||||
|
|
||||||
set(test_valgrind_SOURCES test_common.h test_valgrind.c)
|
set(test_valgrind_SOURCES test_common.h test_valgrind.c)
|
||||||
add_executable(test_valgrind ${test_valgrind_SOURCES})
|
add_executable(test_valgrind ${test_valgrind_SOURCES})
|
||||||
target_link_libraries(test_valgrind miracle-shared)
|
target_link_libraries(test_valgrind miracle-shared)
|
||||||
|
target_link_libraries(test_valgrind ${CHECK_LIBRARIES})
|
||||||
target_link_libraries(test_valgrind ${UDEV_LIBRARIES})
|
target_link_libraries(test_valgrind ${UDEV_LIBRARIES})
|
||||||
target_link_libraries(test_valgrind ${GLIB2_LIBRARIES})
|
target_link_libraries(test_valgrind ${GLIB2_LIBRARIES})
|
||||||
target_link_libraries(test_valgrind ${CHECK_LIBRARIES})
|
|
||||||
target_link_libraries(test_valgrind ${CHECK_CFLAGS})
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/shared)
|
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/shared)
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ if(CHECK_FOUND)
|
||||||
|
|
||||||
add_custom_target(memcheck
|
add_custom_target(memcheck
|
||||||
DEPENDS memcheck-verify
|
DEPENDS memcheck-verify
|
||||||
COMMAND for i in $$(MEMTESTS) |
|
COMMAND for i in $(MEMTESTS) |
|
||||||
do |
|
do |
|
||||||
${VALGRIND} --log-file=${CMAKE_SOURCE_DIR}/$$i.memlog |
|
${VALGRIND} --log-file=${CMAKE_SOURCE_DIR}/$$i.memlog |
|
||||||
${CMAKE_SOURCE_DIR}/$$i >/dev/null || (echo "memcheck failed on: $$i" ; exit 1) ; |
|
${CMAKE_SOURCE_DIR}/$$i >/dev/null || (echo "memcheck failed on: $$i" ; exit 1) ; |
|
||||||
|
@ -48,3 +48,69 @@ if(CHECK_FOUND)
|
||||||
COMMENT "verify memcheck")
|
COMMENT "verify memcheck")
|
||||||
|
|
||||||
endif(CHECK_FOUND)
|
endif(CHECK_FOUND)
|
||||||
|
|
||||||
|
########### install files ###############
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#original Makefile.am contents follow:
|
||||||
|
|
||||||
|
#include $(top_srcdir)/common.am
|
||||||
|
#tests = \
|
||||||
|
# test_rtsp \
|
||||||
|
# test_wpas
|
||||||
|
#
|
||||||
|
#if BUILD_HAVE_CHECK
|
||||||
|
#check_PROGRAMS = $(tests) test_valgrind
|
||||||
|
#TESTS = $(tests) test_valgrind
|
||||||
|
#MEMTESTS = $(tests)
|
||||||
|
#endif
|
||||||
|
#
|
||||||
|
#test_sources = \
|
||||||
|
# test_common.h
|
||||||
|
#test_libs = \
|
||||||
|
# ../src/shared/libmiracle-shared.la \
|
||||||
|
# $(DEPS_LIBS) \
|
||||||
|
# $(CHECK_LIBS)
|
||||||
|
#test_cflags = \
|
||||||
|
# $(AM_CPPFLAGS) \
|
||||||
|
# $(DEPS_CFLAGS) \
|
||||||
|
# $(CHECK_CFLAGS)
|
||||||
|
#
|
||||||
|
#test_rtsp_SOURCES = test_rtsp.c $(test_sources)
|
||||||
|
#test_rtsp_CPPFLAGS = $(test_cflags)
|
||||||
|
#test_rtsp_LDADD = $(test_libs)
|
||||||
|
#
|
||||||
|
#test_valgrind_SOURCES = test_valgrind.c $(test_sources)
|
||||||
|
#test_valgrind_CPPFLAGS = $(test_cflags)
|
||||||
|
#test_valgrind_LDADD = $(test_libs)
|
||||||
|
#
|
||||||
|
#test_wpas_SOURCES = test_wpas.c $(test_sources)
|
||||||
|
#test_wpas_CPPFLAGS = $(test_cflags)
|
||||||
|
#test_wpas_LDADD = $(test_libs)
|
||||||
|
#
|
||||||
|
### custom recipes
|
||||||
|
#
|
||||||
|
#VALGRIND = CK_FORK=no valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --leak-resolution=high --error-exitcode=1 --suppressions=$(top_builddir)/test.supp
|
||||||
|
#
|
||||||
|
## verify that test_valgrind actually leaks data
|
||||||
|
#memcheck-verify: check
|
||||||
|
# $(AM_V_GEN)$(VALGRIND) --log-file=/dev/null ./test_valgrind >/dev/null ; test 1 = $$?
|
||||||
|
#
|
||||||
|
## run memcheck tests via valgrind
|
||||||
|
#memcheck: memcheck-verify
|
||||||
|
# $(AM_V_GEN)for i in $(MEMTESTS) ; do \
|
||||||
|
# $(VALGRIND) --log-file=$(top_builddir)/$$i.memlog \
|
||||||
|
# $(top_builddir)/$$i >/dev/null || (echo "memcheck failed on: $$i" ; exit 1) ; \
|
||||||
|
# done
|
||||||
|
#
|
||||||
|
#distcheck-hook: memcheck
|
||||||
|
#AM_MAKEFLAGS = --no-print-directory
|
||||||
|
#AUTOMAKE_OPTIONS = color-tests
|
||||||
|
#
|
||||||
|
##
|
||||||
|
## Phony targets
|
||||||
|
##
|
||||||
|
#
|
||||||
|
#.PHONY: memcheck-verify
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
check = dependency('check', required: false)
|
|
||||||
deps = [udev, glib2, check, libsystemd, libmiracle_shared_dep, m]
|
|
||||||
|
|
||||||
if check.found()
|
|
||||||
test_rtsp = executable('test_rtsp', 'test_rtsp.c', dependencies: deps)
|
|
||||||
|
|
||||||
test_wpas = executable('test_wpas', 'test_wpas.c', dependencies: deps)
|
|
||||||
|
|
||||||
test_valgrind = executable('test_valgrind',
|
|
||||||
'test_valgrind.c',
|
|
||||||
dependencies: deps
|
|
||||||
)
|
|
||||||
|
|
||||||
test('rtsp test', test_rtsp)
|
|
||||||
test('wpas test', test_wpas)
|
|
||||||
test('valgrind test', test_valgrind)
|
|
||||||
|
|
||||||
# set(VALGRIND CK_FORK=no valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --leak-resolution=high --error-exitcode=1 --suppressions=${CMAKE_SOURCE_DIR}/test.supp)
|
|
||||||
#
|
|
||||||
# add_custom_target(memcheck-verify
|
|
||||||
# DEPENDS test_rtsp test_wpas test_valgrind
|
|
||||||
# COMMAND ${VALGRIND} --log-file=/dev/null ./test_valgrind >/dev/null |
|
|
||||||
# test 1 = $$?
|
|
||||||
# COMMENT "verify memcheck")
|
|
||||||
#
|
|
||||||
# add_custom_target(memcheck
|
|
||||||
# DEPENDS memcheck-verify
|
|
||||||
# COMMAND for i in $(MEMTESTS) |
|
|
||||||
# do |
|
|
||||||
# ${VALGRIND} --log-file=${CMAKE_SOURCE_DIR}/$$i.memlog |
|
|
||||||
# ${CMAKE_SOURCE_DIR}/$$i >/dev/null || (echo "memcheck failed on: $$i" ; exit 1) ; |
|
|
||||||
# done
|
|
||||||
# SOURCES test_rtsp test_valgrind test_wpas
|
|
||||||
# COMMENT "verify memcheck")
|
|
||||||
endif
|
|
Loading…
Add table
Add a link
Reference in a new issue