1
0
Fork 0
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.
master ... v1.0

85 changed files with 850 additions and 4087 deletions

7
.gitignore vendored
View file

@ -26,7 +26,6 @@ miracle-dhcp
miracle-sinkctl
miracle-wifictl
miracle-wifid
miracle-uibcctl
miraclectl
miracled
stamp-h1
@ -36,9 +35,3 @@ test_valgrind
test_wpas
wpa_cli
wpa_supplicant
CMakeFiles/
cmake_install.cmake
CMakeCache.txt
libmiracle-shared.a
install_manifest.txt
/build/

View file

@ -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 .

View file

@ -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 .

View file

@ -1,63 +1,28 @@
cmake_minimum_required(VERSION 2.8)
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
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake
${CMAKE_MODULE_PATH})
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
set(CMAKE_C_FLAGS "-std=gnu11")
add_definitions(-D_GNU_SOURCE)
OPTION(ENABLE_SYSTEMD "Enable Systemd" ON)
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()
project(Miraclecast)
cmake_minimum_required(VERSION 3.0)
add_subdirectory(src)
add_subdirectory(res)
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)

View file

@ -8,7 +8,7 @@ This software was written by:
This software is licensed under the terms of the LGPL. Please see each source
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

View file

@ -4,21 +4,3 @@ EXTRA_DIST = README.md \
NEWS
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

View file

@ -1,46 +1,61 @@
# MiracleCast - Wifi-Display/Miracast Implementation
[![Join the chat at https://gitter.im/albfan/miraclecast](https://badges.gitter.im/albfan/miraclecast.svg)](https://gitter.im/albfan/miraclecast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Semaphore CI Build Status](https://albfan.semaphoreci.com/badges/miraclecast/branches/master.svg?style=shields)](https://albfan.semaphoreci.com/projects/miraclecast)
[![Travis CI Build Status](https://travis-ci.org/albfan/miraclecast.svg?branch=master)](https://travis-ci.org/albfan/miraclecast)
[![Coverage Status](https://coveralls.io/repos/github/albfan/miraclecast/badge.svg?branch=master)](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 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.
## Requirements
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 >= 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
- **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..)
- **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.
*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/`
## 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)
- [cmake](http://en.wikipedia.org/wiki/CMake)
- [meson](http://mesonbuild.com/)
Autotools:
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
@ -54,23 +69,17 @@ You can also choose the interface with `--interface` option for miracle-wifid.
### Ubuntu
Check your systemd version with:
$ 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
This specific linux flavour is so hard to get miraclecast dependencies that an alternative repo was created to install systemd 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
### 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
@ -85,12 +94,15 @@ If you feel confidence enough (since systemd is the entrypoint for an OS) extrac
## 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
$ systemctl stop wpa_supplicant.service
$ sudo kill -9 $(ps -ef | grep wpa_supplican[t] | awk '{print $2}')
# 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
@ -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
### Steps to use it as peer
Steps to use it as peer:
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
> 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)
## 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.
5. Apart from list, or show info with peer <mac> there's nothing useful here by now.
## 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
- Original repo: git://people.freedesktop.org/~dvdhrm/miracle
- Fork repo: https://github.com/albfan/miraclecast
- Technical spec: https://www.wi-fi.org/file/wi-fi-display-technical-specification-v11 (free registration required)

View file

@ -1,68 +1,2 @@
#!/bin/sh
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
autoreconf -f --install

View file

@ -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

View file

@ -1,9 +0,0 @@
FROM docker.io/albfan/miraclecast-ci
RUN mkdir src
COPY . ./src
WORKDIR src
RUN cmake -Bbuild . && make -C build

View file

@ -10,7 +10,8 @@ AM_CFLAGS = -Wall \
AM_CPPFLAGS = -include $(top_builddir)/config.h \
-I $(top_srcdir)/src \
-I $(top_srcdir)/src/shared
-I $(top_srcdir)/src/shared \
'-DBUILD_BINDIR="$(bindir)"'
AM_LDFLAGS = -Wl,--as-needed \
-Wl,--gc-sections \

View file

@ -1,11 +1,9 @@
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine ENABLE_SYSTEMD
#cmakedefine BUILD_ENABLE_DEBUG
#cmakedefine BUILD_BINDIR "@BUILD_BINDIR@"
#cmakedefine RELY_UDEV @RELY_UDEV@
#cmakedefine IP_BINARY @IP_BINARY@
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"

View file

@ -35,45 +35,17 @@ AC_PROG_AWK
LT_PREREQ(2.2)
LT_INIT
LT_LIB_M
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]))
AC_ARG_ENABLE([log-debug],
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
#
AS_IF([test "$use_libsystemd" = "yes"],
[
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])
])
])
PKG_CHECK_MODULES([DEPS], [libudev libsystemd > 219])
PKG_CHECK_MODULES([GDHCP], [glib-2.0])
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.
#
m4_ifdef([PKG_CHECK_MODULES], [
PKG_CHECK_MODULES([CHECK], [check],
[have_check=yes], [have_check=no])
])
PKG_CHECK_MODULES([CHECK], [check],
[have_check=yes], [have_check=no])
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
# After everything is configured, we create all makefiles.
@ -172,7 +70,6 @@ AC_CONFIG_FILES([Makefile
src/dhcp/Makefile
src/shared/Makefile
src/wifi/Makefile
src/uibc/Makefile
test/Makefile])
AC_OUTPUT
@ -190,15 +87,12 @@ AC_MSG_NOTICE([Build configuration:
bindir: $bindir
libdir: $libdir
includedir: $includedir
sysconfdir: $sysconfdir
ip-binary: $IP_BINARY
Miscellaneous Options:
building tests: $have_check
code coverage: $use_gcov
rely udev: ${enable_rely_udev:-no}
Compilation
mkdir build && cd build
"${MAKE-make}" to start compilation process
"${MAKE-make}" check to pass test])
else
@ -208,13 +102,11 @@ AC_MSG_NOTICE([Build configuration:
bindir: $bindir
libdir: $libdir
includedir: $includedir
sysconfdir: $sysconfdir
ip-binary: $IP_BINARY
Miscellaneous Options:
building tests: $have_check
rely udev: ${enable_rely_udev:-no}
Compilation
mkdir build && cd build
"${MAKE-make}" to start compilation process])
fi

View file

@ -1,7 +0,0 @@
FROM docker.io/albfan/miraclecast-ci
COPY . ./
RUN rm -rf build-meson; \
meson build-meson; \
ninja -C build-meson

View file

@ -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

View file

@ -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')

View file

@ -1,14 +1,11 @@
INSTALL(
PROGRAMS miracle-gst gstplayer uibc-viewer
DESTINATION bin
)
INSTALL(
FILES org.freedesktop.miracle.conf
DESTINATION ${SYSCONFDIR}/dbus-1/system.d
)
########### install files ###############
INSTALL(
FILES miracle-wifid miracle-sinkctl miracle-wifictl
DESTINATION ${DATADIR}/bash-completion/completions
)
install(FILES miracle-gst.sh DESTINATION bin)
#original Makefile.am contents follow:
#bin_SCRIPTS = miracle-gst.sh
#EXTRA_DIST = wpa.conf

View file

@ -1,9 +1,2 @@
bin_SCRIPTS = miracle-gst gstplayer uibc-viewer miracle-omxplayer
bin_SCRIPTS = miracle-gst.sh
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

View file

@ -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()

View file

@ -1,10 +1,8 @@
#!/bin/bash
DIRNAME=$(dirname $0)
. miracle-utils.sh
. $DIRNAME/miracle-utils.sh
kill_network_manager
kill_ubuntu_network_manager
WPA_PID=$(find_wpa_supplicant_pid)
if [ -n "$WPA_PID" ]

View file

@ -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')
)

View file

@ -1,46 +1,12 @@
#!/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'
AUDIO='0'
SCALE='0'
while getopts "r:d:as:p:h" optname
while getopts "r:d:as:" optname
do
case "$optname" in
"h")
help
exit 0
;;
"d")
DEBUG=`echo ${OPTARG} | tr -d ' '`
;;
@ -50,9 +16,6 @@ while getopts "r:d:as:p:h" optname
"a")
AUDIO='1'
;;
"p")
PORT=`echo ${OPTARG} | tr -d ' '`
;;
"s")
SCALE='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 parameter $OPTARG"
help
exit 1
# Should not occur
echo "Unknown error while processing options"
;;
esac
done
@ -75,7 +37,7 @@ then
RUN+="--gst-debug=${DEBUG} "
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' ]
then

View file

@ -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}

View file

@ -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

View file

@ -27,13 +27,6 @@ function find_wireless_network_interfaces {
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
#
@ -41,26 +34,6 @@ function is_interface_connected {
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
#
@ -79,23 +52,12 @@ function find_wireless_connected_network_interfaces {
#
function find_physical_for_network_interface {
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
if [ -n "$PHY_INDEX" ]
if [ -n $PHY_INDEX ]
then
echo phy$PHY_INDEX
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
#
@ -103,12 +65,6 @@ function search_p2p_capabilities {
WI_DEVICE=$1
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
then
echo $WI_DEVICE supports P2P
@ -139,55 +95,31 @@ function find_wpa_supplicant_pid {
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
#
function check_ubuntu_distro {
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 {
echo stopping NetworkManager
if check_ubuntu_distro || check_debian_distro
function kill_ubuntu_network_manager {
if check_ubuntu_distro
then
# ubuntu manager restarts automatically wpa_supplicant
echo stopping NetworkManager
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
}
#
# start network manager
# start ubuntu manager
#
function start_network_manager {
echo starting NetworkManager
if check_ubuntu_distro || check_debian_distro
function start_ubuntu_network_manager {
if check_ubuntu_distro
then
sudo service NetworkManager start
elif check_archlinux_distro
then
sudo systemctl start Network.service
else
echo starting NetworkManager
sudo service NetworkManager start
fi
}

View file

@ -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}

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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"``

View file

@ -1,9 +1,57 @@
#!/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

View file

@ -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

View file

@ -1,34 +1,18 @@
#!/bin/bash
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
. miracle-utils.sh
if [ "$SCRIPT_DEBUG" -ge 1 ]
then
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
WIFI_NAMES=$(find_wireless_network_interfaces)
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
if [ 0 = $WIFI_COUNT ]
then
echo There is no wireless devices available
echo There is no wireless devices avaliable
exit 1
elif [ 1 = $WIFI_COUNT ]
then
WIFI_NAME="$WIFI_NAMES"
elif [ 2 -le $WIFI_COUNT ]
elif [ 2 -ge $WIFI_COUNT ]
then
echo Choose wireless device:
PS3="device: "

View file

@ -35,7 +35,7 @@ Try installing packages "gst-plugins-bad, gst-plugins-base, gst-plugins-base-lib
If that fails too, try:
$ vlc rtp://@:7236
$ vlc rtp://@1991
EOF
else

View file

@ -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

View file

@ -8,7 +8,7 @@ ETHER_COUNT=$(echo "$ETHER_NAMES" | wc -l)
if [ 0 = $ETHER_COUNT ]
then
echo There is no net devices available
echo There is no net devices avaliable
exit 1
elif [ 1 = $ETHER_COUNT ]
then

View file

@ -1,15 +1,37 @@
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
set(CMAKE_C_FLAGS "-std=gnu11")
add_subdirectory(shared)
add_subdirectory(wifi)
add_subdirectory(dhcp)
add_subdirectory(ctl)
add_subdirectory(uibc)
set(miracled_SRCS miracled.h miracled.c)
add_executable(miracled ${miracled_SRCS})
target_link_libraries(miracled miracle-shared)
target_link_libraries(miracled m)
install(TARGETS miracled DESTINATION bin)
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)
#

View file

@ -1,5 +1,5 @@
include $(top_srcdir)/common.am
SUBDIRS = shared wifi dhcp ctl uibc
SUBDIRS = shared wifi dhcp ctl
bin_PROGRAMS = miracled

Binary file not shown.

View file

@ -1,9 +1,6 @@
find_package(PkgConfig)
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
link_directories( ${GLIB2_LIBRARY_DIRS})
include_directories( ${GLIB2_INCLUDE_DIRS})
find_package(Readline REQUIRED)
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
find_package(Readline)
########### next target ###############
set(miracle-wifictl_SRCS ctl.h
ctl-cli.c
@ -23,20 +20,17 @@ if(READLINE_FOUND)
endif(READLINE_FOUND)
target_link_libraries(miracle-wifictl miracle-shared)
target_link_libraries(miracle-wifictl m)
target_link_libraries(miracle-wifictl ${GLIB2_LIBRARIES})
########### next target ###############
set(miracle-sinkctl_SRCS ctl.h
ctl-cli.c
ctl-sink.h
ctl-sink.c
ctl-wifi.c
sinkctl.c
wfd.c)
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)
@ -51,3 +45,42 @@ endif(READLINE_FOUND)
target_link_libraries(miracle-sinkctl miracle-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)
#
#

View file

@ -8,8 +8,7 @@ miracle_wifictl_SOURCES = \
wifictl.c
miracle_wifictl_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(DEPS_CFLAGS) \
$(GLIB_CFLAGS)
$(DEPS_CFLAGS)
miracle_wifictl_LDADD = \
../shared/libmiracle-shared.la \
-lreadline \
@ -18,19 +17,16 @@ miracle_wifictl_LDADD = \
miracle_sinkctl_SOURCES = \
ctl.h \
ctl-cli.c \
ctl-sink.h \
ctl-sink.c \
ctl-wifi.c \
wfd.c \
sinkctl.c
miracle_sinkctl_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(DEPS_CFLAGS) \
$(GLIB_CFLAGS)
$(DEPS_CFLAGS)
miracle_sinkctl_LDADD = \
../shared/libmiracle-shared.la \
-lreadline \
$(DEPS_LIBS) \
$(GLIB_LIBS)
$(DEPS_LIBS)

View file

@ -27,15 +27,15 @@
#include <string.h>
#include <strings.h>
#include <sys/signalfd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <systemd/sd-bus.h>
#include "ctl.h"
#include "shl_macro.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
@ -47,14 +47,14 @@ static sd_event_source *cli_sigs[_NSIG];
static sd_event_source *cli_stdin;
static bool cli_rl;
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)
{
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_free_ char *line = NULL;
@ -73,10 +73,6 @@ void cli_printv(const char *fmt, bool prefix_time, va_list args)
rl_redisplay();
}
if (prefix_time) {
cli_printf_time_prefix();
}
vprintf(fmt, args);
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, ...)
{
SHL_PROTECT_ERRNO;
va_list args;
va_start(args, fmt);
cli_printv(fmt, true, args);
cli_printv(fmt, 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;
cli_command_printf("Available commands:\n");
if (!is_cli()) {
cli_fn_help();
}
cli_printf("Available commands:\n");
for (i = 0; cmds[i].cmd; ++i) {
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)
continue;
cli_command_printf(" %s %-*s %s\n",
cmds[i].cmd,
(int)(whitespace - strlen(cmds[i].cmd)),
cmds[i].args ? : "",
cmds[i].desc ? : "");
cli_printf(" %s %-*s %s\n",
cmds[i].cmd,
(int)(40 - strlen(cmds[i].cmd)),
cmds[i].args ? : "",
cmds[i].desc ? : "");
}
return 0;
@ -188,21 +143,21 @@ int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n)
switch (cmds[i].argc_cmp) {
case CLI_EQUAL:
if (n != cmds[i].argc) {
cli_command_printf("Invalid number of arguments\n");
cli_printf("Invalid number of arguments\n");
return -EINVAL;
}
break;
case CLI_MORE:
if (n < cmds[i].argc) {
cli_command_printf("too few arguments\n");
cli_printf("too few arguments\n");
return -EINVAL;
}
break;
case CLI_LESS:
if (n > cmds[i].argc) {
cli_command_printf("too many arguments\n");
cli_printf("too many arguments\n");
return -EINVAL;
}
@ -218,7 +173,7 @@ int cli_do(const struct cli_cmd *cmds, char **args, unsigned int n)
}
if (!strcmp(cmd, "help"))
return cli_help(cmds, 40);
return cli_help(cmds);
return -EAGAIN;
}
@ -243,15 +198,12 @@ static void cli_handler_fn(char *input)
else if (!r)
return;
if (!(strcmp(original, "quit") == 0 || strcmp(original, "exit") == 0)) {
add_history(original);
write_history(get_history_filename());
}
add_history(original);
r = cli_do(cli_cmds, args, r);
if (r != -EAGAIN)
return;
cli_command_printf("Command not found\n");
cli_printf("Command not found\n");
}
static int cli_stdin_fn(sd_event_source *source,
@ -325,312 +277,6 @@ void cli_destroy(void)
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)
{
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,
fileno(stdin),
EPOLLHUP | EPOLLERR | EPOLLIN,
cli_stdin_fn,
NULL);
if (r < 0) {
cli_vERR(r);
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();
if (r < 0) {
cli_vERR(r);
goto error;
}
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;
error:

View file

@ -17,7 +17,49 @@
* 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
@ -77,92 +119,53 @@ static void sink_handle_options(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;
int r;
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
int r;
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
if (r < 0)
return cli_vERR(r);
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
if (r < 0)
return cli_vERR(r);
/* wfd_content_protection */
check_and_response_option("wfd_content_protection", "none");
GHashTable* protocol_extensions = s->protocol_extensions;
/* wfd_video_formats */
gchar* wfd_video_formats = NULL;
if (protocol_extensions != NULL) {
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_extension;
}
}
bool create_wfd_video_formats = wfd_video_formats == NULL;
if (create_wfd_video_formats) {
gchar video_formats[128];
sprintf(video_formats, "00 00 03 10 %08x %08x %08x 00 0000 0000 10 none none",
s->resolutions_cea, s->resolutions_vesa, s->resolutions_hh);
wfd_video_formats = strdup(video_formats);
}
check_and_response_option(WFD_VIDEO_FORMATS, wfd_video_formats);
if (create_wfd_video_formats) {
g_free(wfd_video_formats);
}
/* wfd_content_protection */
if (rtsp_message_read(m, "{<>}", "wfd_content_protection") >= 0) {
r = rtsp_message_append(rep, "{&}",
"wfd_content_protection: none");
if (r < 0)
return cli_vERR(r);
}
/* wfd_video_formats */
if (rtsp_message_read(m, "{<>}", "wfd_video_formats") >= 0) {
char wfd_video_formats[128];
sprintf(wfd_video_formats,
"wfd_video_formats: 00 00 03 10 %08x %08x %08x 00 0000 0000 10 none none",
s->resolutions_cea, s->resolutions_vesa, s->resolutions_hh);
r = rtsp_message_append(rep, "{&}", wfd_video_formats);
if (r < 0)
return cli_vERR(r);
}
/* wfd_audio_codecs */
if (rtsp_message_read(m, "{<>}", "wfd_audio_codecs") >= 0) {
r = rtsp_message_append(rep, "{&}",
"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 */
gchar* wfd_audio_codecs = "AAC 00000007 00";
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);
rtsp_message_seal(rep);
cli_debug("OUTGOING: %s\n", rtsp_message_get_raw(rep));
/* wfd_client_rtp_ports */
char wfd_client_rtp_ports[128];
sprintf(wfd_client_rtp_ports, "RTP/AVP/UDP;unicast %d 0 mode=play", rstp_port);
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;
r = rtsp_send(s->rtsp, rep);
if (r < 0)
return cli_vERR(r);
}
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) {
s->hres = hres;
s->vres = vres;
ctl_fn_sink_resolution_set(s);
ctl_fn_sink_resolution_set(s, hres, vres);
return 0;
}
}
@ -238,8 +241,6 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
const char *trigger;
const char *url;
char *uibc_config;
const char *uibc_setting;
char *nu;
unsigned int cea_res, vesa_res, hh_res;
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 */
r = rtsp_message_read(m, "{<****hhh>}", "wfd_video_formats",
&cea_res, &vesa_res, &hh_res);
@ -342,9 +300,9 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
if (r < 0)
return cli_vERR(r);
char rtsp_setup[128];
sprintf(rtsp_setup, "RTP/AVP/UDP;unicast;client_port=%d", rstp_port);
r = rtsp_message_append(rep, "<s>", "Transport", rtsp_setup);
r = rtsp_message_append(rep, "<s>",
"Transport",
"RTP/AVP/UDP;unicast;client_port=1991");
if (r < 0)
return cli_vERR(r);
@ -570,8 +528,6 @@ void ctl_sink_free(struct ctl_sink *s)
free(s->session);
free(s->url);
sd_event_unref(s->event);
if (s->protocol_extensions)
g_hash_table_destroy(s->protocol_extensions);
free(s);
}

View file

@ -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 */

View file

@ -414,8 +414,6 @@ static int ctl_link_parse_properties(struct ctl_link *l,
bool p2p_scanning_set = false;
char *tmp;
int p2p_scanning, r;
bool managed_set = false;
int managed;
if (!l || !m)
return cli_EINVAL();
@ -446,13 +444,6 @@ static int ctl_link_parse_properties(struct ctl_link *l,
&friendly_name);
if (r < 0)
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")) {
r = bus_message_read_basic_variant(m, "b",
&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)
l->p2p_scanning = p2p_scanning;
@ -632,63 +620,6 @@ int ctl_link_set_wfd_subelements(struct ctl_link *l, const char *val)
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)
{
_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);
if (!l)
return 0;
return cli_EINVAL();
r = ctl_peer_new(&p, l, label);
if (r < 0)

View file

@ -17,9 +17,6 @@
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CTL_CTL_H
#define CTL_CTL_H
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
@ -32,22 +29,13 @@
#include "shl_dlist.h"
#include "shl_log.h"
/* *sigh* readline doesn't include all their deps, so put them last */
#include <readline/history.h>
#include <readline/readline.h>
#include <readline/rltypedefs.h>
#ifndef CTL_CTL_H
#define CTL_CTL_H
struct ctl_wifi;
struct ctl_link;
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 */
struct ctl_peer {
@ -83,7 +71,6 @@ struct ctl_link {
unsigned int ifindex;
char *ifname;
char *friendly_name;
bool managed;
char *wfd_subelements;
bool p2p_scanning;
};
@ -91,7 +78,6 @@ struct ctl_link {
#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_managed(struct ctl_link *l, bool 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);
@ -134,11 +120,9 @@ bool ctl_sink_is_closed(struct ctl_sink *s);
/* CLI handling */
extern unsigned int cli_max_sev;
void cli_printv(const char *fmt, bool prefix_time, va_list args);
void cli_printf_time_prefix();
extern int cli_max_sev;
void cli_printv(const char *fmt, va_list args);
void cli_printf(const char *fmt, ...);
void cli_command_printf(const char *fmt, ...);
#define cli_log(_fmt, ...) \
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_BOLDGRAY "\x1B[1;30m"
#define CLI_BOLDWHITE "\x1B[1;37m"
#define CLI_PROMPT CLI_BLUE "[miraclectl] # " CLI_DEFAULT
struct cli_cmd {
const char *cmd;
@ -219,7 +204,6 @@ struct cli_cmd {
int argc;
int (*fn) (char **args, unsigned int n);
const char *desc;
rl_compentry_func_t *completion_fns[2];
};
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_hh;
char* get_cli_prompt();
int cli_init(sd_bus *bus, const struct cli_cmd *cmds);
void cli_destroy(void);
int cli_run(void);
void cli_exit(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);
/* 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_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);

View file

@ -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
)

View file

@ -17,8 +17,6 @@
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <errno.h>
#include <getopt.h>
#include <locale.h>
@ -32,27 +30,15 @@
#include <sys/time.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#ifdef ENABLE_SYSTEMD
#include <systemd/sd-journal.h>
#endif
#include <time.h>
#include <unistd.h>
#include "ctl.h"
#include "ctl-sink.h"
#include "wfd.h"
#include "shl_macro.h"
#include "shl_util.h"
#include "util.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 struct ctl_wifi *wifi;
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 *pending_peer;
void launch_player(struct ctl_sink *s);
char *gst_scale_res;
int gst_audio_en = 1;
static const int DEFAULT_RSTP_PORT = 7236;
bool uibc_option;
bool uibc_enabled;
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;
}
unsigned int wfd_supported_res_cea = 0x0000001f; /* up to 720x576 */
unsigned int wfd_supported_res_vesa = 0x00000003; /* up to 800x600 */
unsigned int wfd_supported_res_hh = 0x00000000; /* not supported */
/*
* cmd list
@ -116,28 +72,27 @@ static int cmd_list(char **args, unsigned int n)
/* list links */
cli_command_printf("%6s %-24s %-30s %-10s\n",
"LINK", "INTERFACE", "FRIENDLY-NAME", "MANAGED");
cli_printf("%6s %-24s %-30s\n",
"LINK", "INTERFACE", "FRIENDLY-NAME");
shl_dlist_for_each(i, &wifi->links) {
l = link_from_dlist(i);
++link_cnt;
cli_command_printf("%6s %-24s %-30s %-10s\n",
l->label,
shl_isempty(l->ifname) ?
"<unknown>" : l->ifname,
cli_printf("%6s %-24s %-30s\n",
l->label,
shl_isempty(l->ifname) ?
"<unknown>" : l->ifname,
shl_isempty(l->friendly_name) ?
"<unknown>" : l->friendly_name,
l->managed ? "yes": "no");
"<unknown>" : l->friendly_name);
}
cli_command_printf("\n");
cli_printf("\n");
/* list peers */
cli_command_printf("%6s %-24s %-30s %-10s\n",
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
cli_printf("%6s %-24s %-30s %-10s\n",
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
shl_dlist_for_each(i, &wifi->links) {
l = link_from_dlist(i);
@ -146,16 +101,16 @@ static int cmd_list(char **args, unsigned int n)
p = peer_from_dlist(j);
++peer_cnt;
cli_command_printf("%6s %-24s %-30s %-10s\n",
p->l->label,
p->label,
shl_isempty(p->friendly_name) ?
cli_printf("%6s %-24s %-30s %-10s\n",
p->l->label,
p->label,
shl_isempty(p->friendly_name) ?
"<unknown>" : p->friendly_name,
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;
}
@ -174,81 +129,45 @@ static int cmd_show(char **args, unsigned int n)
!(p = ctl_wifi_find_peer(wifi, args[0])) &&
!(l = ctl_wifi_search_link(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;
}
}
if (l) {
cli_command_printf("Link=%s\n", l->label);
cli_printf("Link=%s\n", l->label);
if (l->ifindex > 0)
cli_command_printf("InterfaceIndex=%u\n", l->ifindex);
cli_printf("InterfaceIndex=%u\n", l->ifindex);
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)
cli_command_printf("FriendlyName=%s\n", l->friendly_name);
cli_command_printf("P2PScanning=%d\n", l->p2p_scanning);
cli_printf("FriendlyName=%s\n", l->friendly_name);
cli_printf("P2PScanning=%d\n", l->p2p_scanning);
if (l->wfd_subelements && *l->wfd_subelements)
cli_command_printf("WfdSubelements=%s\n", l->wfd_subelements);
cli_command_printf("Managed=%d\n", l->managed);
cli_printf("WfdSubelements=%s\n", l->wfd_subelements);
} 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)
cli_command_printf("P2PMac=%s\n", p->p2p_mac);
cli_printf("P2PMac=%s\n", p->p2p_mac);
if (p->friendly_name && *p->friendly_name)
cli_command_printf("FriendlyName=%s\n", p->friendly_name);
cli_command_printf("Connected=%d\n", p->connected);
cli_printf("FriendlyName=%s\n", p->friendly_name);
cli_printf("Connected=%d\n", p->connected);
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)
cli_command_printf("LocalAddress=%s\n", p->local_address);
cli_printf("LocalAddress=%s\n", p->local_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)
cli_command_printf("WfdSubelements=%s\n", p->wfd_subelements);
cli_printf("WfdSubelements=%s\n", p->wfd_subelements);
} else {
cli_command_printf("Show what?\n");
cli_printf("Show what?\n");
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
*/
@ -279,11 +198,6 @@ static int cmd_run(char **args, unsigned int n)
return 0;
}
if (!l->managed) {
cli_printf("link %s not managed\n", l->label);
return 0;
}
run_on(l);
return 0;
@ -314,37 +228,11 @@ static int cmd_bind(char **args, unsigned int n)
if (!l)
return 0;
if (!l->managed) {
cli_printf("link %s not managed\n", l->label);
return 0;
}
run_on(l);
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
*/
@ -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[] = {
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects", {NULL} },
{ "show", "<link|peer>", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information", {links_peers_generator, NULL} },
{ "run", "<link>", CLI_M, CLI_EQUAL, 1, cmd_run, "Run sink on given link", {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", {links_generator, NULL} },
{ "set-friendly-name", "[link] <name>", CLI_M, CLI_LESS, 2, cmd_set_friendly_name, "Set friendly name of an object", {links_generator, NULL} },
{ "set-managed", "<link> <yes|no>", CLI_M, CLI_EQUAL, 2, cmd_set_managed, "Manage or unmnage a link", {links_generator, yes_no_generator} },
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program", {NULL} },
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL, {NULL} },
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help", {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" },
{ "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" },
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program" },
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL },
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" },
{ },
};
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;
int fd_journal;
int fd_journal, i;
sigset_t mask;
if (sink_pid > 0)
@ -467,113 +355,43 @@ static void spawn_gst(struct ctl_sink *s)
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
#ifdef ENABLE_SYSTEMD
/* redirect stdout/stderr to journal */
fd_journal = sd_journal_stream_fd("miracle-sinkctl-gst",
LOG_DEBUG,
LOG_INFO,
false);
if (fd_journal >= 0) {
/* dup journal-fd to stdout and stderr */
dup2(fd_journal, 1);
dup2(fd_journal, 2);
} else {
#endif
/* no journal? redirect stdout to parent's stderr */
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);
} else {
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)
{
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)
spawn_gst(s);
spawn_gst(hres, vres);
}
void ctl_fn_peer_new(struct ctl_peer *p)
@ -783,29 +601,20 @@ void cli_fn_help()
*/
printf("%s [OPTIONS...] ...\n\n"
"Control a dedicated local sink via MiracleCast.\n"
" -h --help Show this help\n"
" --help-commands Show available commands\n"
" --version Show package version\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"
" -h --help Show this help\n"
" --version Show package version\n"
" --log-level <lvl> Maximum level for log messages\n"
" --audio <0/1> Enable audio support (default %d)\n"
" --scale WxH Scale to resolution\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"
" --log-journal-level <lvl> Maximum level for journal log messages\n"
" --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,
, program_invocation_short_name, gst_audio_en,
wfd_supported_res_cea, wfd_supported_res_vesa, wfd_supported_res_hh
);
wfd_print_resolutions();
/*
* 80-char barrier:
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
@ -823,7 +632,6 @@ static int ctl_interactive(char **argv, int argc)
r = ctl_sink_new(&sink, cli_event);
if (r < 0)
goto error;
sink->protocol_extensions = protocol_extensions;
r = ctl_wifi_fetch(wifi);
if (r < 0)
@ -849,19 +657,12 @@ static int ctl_main(int argc, char *argv[])
struct ctl_link *l;
int r, left;
if (getuid() != 0) {
r = EACCES;
log_notice("Must run as root");
return r;
}
r = ctl_wifi_new(&wifi, bus);
if (r < 0)
return r;
left = argc - optind;
left = left <= 0 ? 0 : left;
r = ctl_interactive(argv + optind, left);
left = argc - optind;
r = ctl_interactive(argv + optind, left <= 0 ? 0 : left);
/* stop all scans */
shl_dlist_for_each(i, &wifi->links) {
@ -879,70 +680,31 @@ static int parse_argv(int argc, char *argv[])
enum {
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_LOG_DATE_TIME,
ARG_JOURNAL_LEVEL,
ARG_GST_DEBUG,
ARG_AUDIO,
ARG_SCALE,
ARG_RES,
ARG_HELP_RES,
ARG_UIBC,
ARG_HELP_COMMANDS,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "help-commands", no_argument, NULL, ARG_HELP_COMMANDS },
{ "version" , no_argument, NULL, ARG_VERSION },
{ "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 },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "audio", required_argument, NULL, ARG_AUDIO },
{ "scale", required_argument, NULL, ARG_SCALE },
{ "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;
uibc_option = false;
uibc_enabled = false;
external_player = false;
rstp_port = DEFAULT_RSTP_PORT;
while ((c = getopt_long(argc, argv, "he:p:", options, NULL)) >= 0) {
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
switch (c) {
case 'h':
cli_fn_help();
return 0;
case ARG_HELP_COMMANDS:
return cli_help(cli_cmds, 20);
case ARG_HELP_RES:
wfd_print_resolutions("");
return 0;
return cli_help(cli_cmds);
case ARG_VERSION:
puts(PACKAGE_STRING);
return 0;
case ARG_LOG_LEVEL:
cli_max_sev = log_parse_arg(optarg);
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:
gst_audio_en = atoi(optarg);
break;
@ -955,16 +717,6 @@ static int parse_argv(int argc, char *argv[])
&wfd_supported_res_vesa,
&wfd_supported_res_hh);
break;
case 'p':
rstp_port = atoi(optarg);
break;
case 'e':
external_player = true;
player = optarg;
break;
case ARG_UIBC:
uibc_option = true;
break;
case '?':
return -EINVAL;
}
@ -976,75 +728,9 @@ static int parse_argv(int argc, char *argv[])
int main(int argc, char **argv)
{
int r;
bool free_argv = false;
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);
if (r < 0)
return EXIT_FAILURE;
@ -1058,10 +744,6 @@ int main(int argc, char **argv)
}
r = ctl_main(argc, argv);
g_strfreev(autocmds_free);
if (free_argv) {
free(argv);
}
sd_bus_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;

View file

@ -103,27 +103,27 @@ struct resolution_bitmap resolutions_hh[] = {
{0, 0, 0, 0},
};
void wfd_print_resolutions(char * prefix)
void wfd_print_resolutions(void)
{
int i;
printf("%sCEA resolutions:\n", prefix);
printf("CEA resolutions:\n");
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].hres, resolutions_cea[i].vres,
resolutions_cea[i].fps);
}
printf("%sVESA resolutions:\n", prefix);
printf("VESA resolutions:\n");
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].hres, resolutions_vesa[i].vres,
resolutions_vesa[i].fps);
}
printf("%sHH resolutions:\n", prefix);
printf("HH resolutions:\n");
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].hres, resolutions_hh[i].vres,
resolutions_hh[i].fps);

View file

@ -21,7 +21,7 @@
#ifndef 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_vesa_resolution(uint32_t mask, int *hres, int *vres);
int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres);

View file

@ -31,39 +31,13 @@
#include "ctl.h"
#include "shl_macro.h"
#include "shl_util.h"
#include "util.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 struct ctl_wifi *wifi;
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
*/
@ -77,27 +51,26 @@ static int cmd_list(char **args, unsigned int n)
/* list links */
cli_command_printf("%6s %-24s %-30s %-10s\n",
"LINK", "INTERFACE", "FRIENDLY-NAME", "MANAGED");
cli_printf("%6s %-24s %-30s\n",
"LINK", "INTERFACE", "FRIENDLY-NAME");
shl_dlist_for_each(i, &wifi->links) {
l = link_from_dlist(i);
++link_cnt;
cli_command_printf("%6s %-24s %-30s %-10s\n",
l->label,
shl_isempty(l->ifname) ?
"<unknown>" : l->ifname,
shl_isempty(l->friendly_name) ?
"<unknown>" : l->friendly_name,
l->managed ? "yes": "no");
cli_printf("%6s %-24s %-30s\n",
l->label,
shl_isempty(l->ifname) ?
"<unknown>" : l->ifname,
shl_isempty(l->friendly_name) ?
"<unknown>" : l->friendly_name);
}
cli_command_printf("\n");
cli_printf("\n");
/* list peers */
cli_command_printf("%6s %-24s %-30s %-10s\n",
cli_printf("%6s %-24s %-30s %-10s\n",
"LINK", "PEER-ID", "FRIENDLY-NAME", "CONNECTED");
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);
++peer_cnt;
cli_command_printf("%6s %-24s %-30s %-10s\n",
p->l->label,
p->label,
shl_isempty(p->friendly_name) ?
"<unknown>" : p->friendly_name,
p->connected ? "yes" : "no");
cli_printf("%6s %-24s %-30s %-10s\n",
p->l->label,
p->label,
shl_isempty(p->friendly_name) ?
"<unknown>" : p->friendly_name,
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;
}
@ -146,7 +119,6 @@ static int cmd_select(char **args, unsigned int n)
}
selected_link = l;
ctl_link_set_wfd_subelements(l, "000600111c4400c8");
cli_printf("link %s selected\n", selected_link->label);
return 0;
@ -174,34 +146,33 @@ static int cmd_show(char **args, unsigned int n)
}
if (l) {
cli_command_printf("Link=%s\n", l->label);
cli_printf("Link=%s\n", l->label);
if (l->ifindex > 0)
cli_command_printf("InterfaceIndex=%u\n", l->ifindex);
cli_printf("InterfaceIndex=%u\n", l->ifindex);
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)
cli_command_printf("FriendlyName=%s\n", l->friendly_name);
cli_command_printf("P2PScanning=%d\n", l->p2p_scanning);
cli_printf("FriendlyName=%s\n", l->friendly_name);
cli_printf("P2PScanning=%d\n", l->p2p_scanning);
if (l->wfd_subelements && *l->wfd_subelements)
cli_command_printf("WfdSubelements=%s\n", l->wfd_subelements);
cli_command_printf("Managed=%d\n", l->managed);
cli_printf("WfdSubelements=%s\n", l->wfd_subelements);
} 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)
cli_command_printf("P2PMac=%s\n", p->p2p_mac);
cli_printf("P2PMac=%s\n", p->p2p_mac);
if (p->friendly_name && *p->friendly_name)
cli_command_printf("FriendlyName=%s\n", p->friendly_name);
cli_command_printf("Connected=%d\n", p->connected);
cli_printf("FriendlyName=%s\n", p->friendly_name);
cli_printf("Connected=%d\n", p->connected);
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)
cli_command_printf("LocalAddress=%s\n", p->local_address);
cli_printf("LocalAddress=%s\n", p->local_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)
cli_command_printf("WfdSubelements=%s\n", p->wfd_subelements);
cli_printf("WfdSubelements=%s\n", p->wfd_subelements);
} else {
cli_command_printf("Show what?\n");
cli_printf("Show what?\n");
return 0;
}
@ -218,7 +189,7 @@ static int cmd_set_friendly_name(char **args, unsigned int n)
const char *name;
if (n < 1) {
cli_command_printf("To what?\n");
cli_printf("To what?\n");
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);
}
/*
* 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
*/
@ -310,11 +242,6 @@ static int cmd_p2p_scan(char **args, unsigned int n)
return 0;
}
if (!l->managed) {
cli_printf("link %s not managed\n", l->label);
return 0;
}
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;
if (n < 1) {
cli_command_printf("To whom?\n");
cli_printf("To whom?\n");
return 0;
}
@ -362,11 +289,6 @@ static int cmd_connect(char **args, unsigned int n)
pin = "";
}
if (!p->l->managed) {
cli_printf("link %s not managed\n", p->l->label);
return 0;
}
return ctl_peer_connect(p, prov, pin);
}
@ -379,7 +301,7 @@ static int cmd_disconnect(char **args, unsigned int n)
struct ctl_peer *p;
if (n < 1) {
cli_command_printf("From whom?\n");
cli_printf("From whom?\n");
return 0;
}
@ -389,11 +311,6 @@ static int cmd_disconnect(char **args, unsigned int n)
return 0;
}
if (!p->l->managed) {
cli_printf("link %s not managed\n", p->l->label);
return 0;
}
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[] = {
{ "list", NULL, CLI_M, CLI_LESS, 0, cmd_list, "List all objects", {NULL}},
{ "select", "[link]", CLI_Y, CLI_LESS, 1, cmd_select, "Select default link", {links_generator, NULL} },
{ "show", "[link|peer]", CLI_M, CLI_LESS, 1, cmd_show, "Show detailed object information", {links_peers_generator, NULL} },
{ "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-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", {links_generator, NULL} },
{ "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", {peers_generator, NULL} },
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program", {NULL} },
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL , {NULL}},
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" , {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" },
{ "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" },
{ "p2p-scan", "[link] [stop]", CLI_Y, CLI_LESS, 2, cmd_p2p_scan, "Control neighborhood P2P scanning" },
{ "connect", "<peer> [provision] [pin]", CLI_M, CLI_LESS, 3, cmd_connect, "Connect to peer" },
{ "disconnect", "<peer>", CLI_M, CLI_EQUAL, 1, cmd_disconnect, "Disconnect from peer" },
{ "quit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, "Quit program" },
{ "exit", NULL, CLI_Y, CLI_MORE, 0, cmd_quit, NULL },
{ "help", NULL, CLI_M, CLI_MORE, 0, NULL, "Print help" },
{ },
};
@ -503,13 +419,9 @@ void cli_fn_help()
printf("%s [OPTIONS...] {COMMAND} ...\n\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"
" -h --help Show this help\n"
" --help-commands Show available commands\n"
" --version Show package version\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"
" -h --help Show this help\n"
" --version Show package version\n"
" --log-level <lvl> Maximum level for log messages\n"
"\n"
"Commands:\n"
, program_invocation_short_name);
@ -585,19 +497,11 @@ static int parse_argv(int argc, char *argv[])
enum {
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_LOG_DATE_TIME,
ARG_JOURNAL_LEVEL,
ARG_HELP_COMMANDS,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "help-commands", no_argument, NULL, ARG_HELP_COMMANDS },
{ "version", no_argument, NULL, ARG_VERSION },
{ "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 },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{}
};
int c;
@ -605,25 +509,13 @@ static int parse_argv(int argc, char *argv[])
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
switch (c) {
case 'h':
cli_fn_help();
return 0;
case ARG_HELP_COMMANDS:
return cli_help(cli_cmds, 20);
return cli_help(cli_cmds);
case ARG_VERSION:
puts(PACKAGE_STRING);
return 0;
case ARG_LOG_LEVEL:
cli_max_sev = log_parse_arg(optarg);
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 '?':
return -EINVAL;
}
@ -638,23 +530,6 @@ int main(int argc, char **argv)
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);
if (r < 0)
return EXIT_FAILURE;

View file

@ -1,3 +1,6 @@
########### next target ###############
set(miracle-dhcp_SRCS dhcp.c
gdhcp.h
unaligned.h
@ -13,15 +16,47 @@ add_executable(miracle-dhcp ${miracle-dhcp_SRCS})
find_package(PkgConfig)
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
pkg_check_modules (UDEV REQUIRED libudev)
target_link_libraries(miracle-dhcp miracle-shared)
link_directories( ${UDEV_LIBRARY_DIRS})
include_directories( ${UDEV_INCLUDE_DIRS})
target_link_libraries(miracle-dhcp ${UDEV_LIBRARIES})
target_link_libraries(miracle-dhcp m)
link_directories( ${GLIB2_LIBRARY_DIRS})
include_directories( ${GLIB2_INCLUDE_DIRS})
target_link_libraries(miracle-dhcp ${GLIB2_LIBRARIES})
target_link_libraries(miracle-dhcp miracle-shared)
install(TARGETS miracle-dhcp DESTINATION bin)
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)
#
#
#

View file

@ -14,11 +14,11 @@ miracle_dhcp_SOURCES = \
miracle_dhcp_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(DEPS_CFLAGS) \
$(GLIB_CFLAGS)
$(GDHCP_CFLAGS)
miracle_dhcp_LDADD = \
../shared/libmiracle-shared.la \
$(DEPS_LIBS) \
$(GLIB_LIBS)
$(GDHCP_LIBS)

View file

@ -2785,7 +2785,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
addr = ntohl(inet_addr(last_address));
if (addr == 0xFFFFFFFF) {
addr = 0;
} else if (dhcp_client->last_address != last_address) { // Avoiding use-after-free
} else {
g_free(dhcp_client->last_address);
dhcp_client->last_address = g_strdup(last_address);
}

View file

@ -35,7 +35,7 @@
* of Wifi-P2P support in common network managers. Once they gain proper
* 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
* 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
@ -67,11 +67,8 @@
#include "shl_log.h"
#include "config.h"
#define XSTR(x) STR(x)
#define STR(x) #x
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 char arg_local[INET_ADDRSTRLEN];
static char arg_gateway[INET_ADDRSTRLEN];
@ -750,10 +747,9 @@ static int help(void)
" --version Show package version\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"
"\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"
"\n"
"Server Options:\n"
@ -776,7 +772,6 @@ static int parse_argv(int argc, char *argv[])
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_LOG_DATE_TIME,
ARG_NETDEV,
ARG_IP_BINARY,
@ -792,11 +787,10 @@ static int parse_argv(int argc, char *argv[])
ARG_TO,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "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 },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
{ "netdev", required_argument, NULL, ARG_NETDEV },
{ "ip-binary", required_argument, NULL, ARG_IP_BINARY },
@ -829,9 +823,6 @@ static int parse_argv(int argc, char *argv[])
case ARG_LOG_TIME:
log_init_time();
break;
case ARG_LOG_DATE_TIME:
log_date_time = true;
break;
case ARG_NETDEV:
arg_netdev = optarg;
break;

View file

@ -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]
)

View file

@ -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
)

View file

@ -66,7 +66,6 @@ static int help(void)
" --version Show package version\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"
, program_invocation_short_name);
/*
* 80-char barrier:
@ -82,14 +81,12 @@ static int parse_argv(int argc, char *argv[])
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_LOG_DATE_TIME,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "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 },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
{}
};
int c;
@ -107,9 +104,6 @@ static int parse_argv(int argc, char *argv[])
case ARG_LOG_TIME:
log_init_time();
break;
case ARG_LOG_DATE_TIME:
log_date_time = true;
break;
case '?':
return -EINVAL;
}

View file

@ -1,5 +1,7 @@
set(CMAKE_C_FLAGS "-std=gnu11")
find_package(PkgConfig)
pkg_check_modules (SYSTEMD REQUIRED systemd>=213)
set(miracle-shared_SOURCES rtsp.h
rtsp.c
shl_dlist.h
@ -16,4 +18,36 @@ set(miracle-shared_SOURCES rtsp.h
wpas.h
wpas.c)
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
#
#
#

View file

@ -17,8 +17,7 @@ libmiracle_shared_la_SOURCES = \
util.h \
wpas.h \
wpas.c
libmiracle_shared_la_LIBADD = \
$(DEPS_LIBS) \
$(GLIB_LIBS) \
$(LIBM)
libmiracle_shared_la_LIBADD = -lsystemd

View file

@ -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
)

View file

@ -2169,6 +2169,7 @@ static int parser_submit_data(struct rtsp *bus, uint8_t *p)
p,
dec->data_size);
if (r < 0) {
free(p);
return r;
}
@ -2716,7 +2717,7 @@ error:
return r;
}
static bool rtsp_unlink_waiting(struct rtsp_message *m)
static void rtsp_unlink_waiting(struct rtsp_message *m)
{
if (m->is_waiting) {
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->bus->waiting_cnt;
rtsp_message_unref(m);
return true;
}
return false;
}
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);
}
static bool rtsp_unlink_outgoing(struct rtsp_message *m)
static void rtsp_unlink_outgoing(struct rtsp_message *m)
{
if (m->is_outgoing) {
shl_dlist_unlink(&m->list);
@ -2746,9 +2745,7 @@ static bool rtsp_unlink_outgoing(struct rtsp_message *m)
m->is_sending = false;
--m->bus->outgoing_cnt;
rtsp_message_unref(m);
return true;
}
return false;
}
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) {
/* no need to wait for answer if no-body listens */
if (!m->cb_fn)
if (rtsp_unlink_waiting(m))
m = NULL;
rtsp_unlink_waiting(m);
/* might destroy the message */
if (m)
rtsp_unlink_outgoing(m);
rtsp_unlink_outgoing(m);
}
return 0;
@ -3250,12 +3246,10 @@ static void rtsp_drop_message(struct rtsp_message *m)
/* never interrupt messages while being partly sent */
if (!m->is_sending)
if (rtsp_unlink_outgoing(m))
m = NULL;
rtsp_unlink_outgoing(m);
/* 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)

View file

@ -12,9 +12,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <limits.h>
#include "shl_log.h"
/*
@ -39,7 +36,7 @@ static inline void log_unlock()
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);
}
@ -50,7 +47,7 @@ void log_init_time(void)
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;
@ -86,9 +83,6 @@ const char *LOG_SUBSYSTEM = NULL;
*/
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
@ -141,51 +135,25 @@ static void log__submit(const char *file,
const char *prefix = NULL;
FILE *out;
long long sec, usec;
time_t now;
struct tm *timeinfo;
struct timeval tv;
char buffertmp[80];
char buffer[120];
int millisec;
out = stderr;
log__time(&sec, &usec);
if (sev < LOG_SEV_NUM && sev > log_max_sev)
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)
prefix = log__sev2str[sev];
if (prefix) {
if (subs) {
if (log_date_time)
fprintf(out, "[%s] %s: %s: ", buffer, prefix, subs);
else if (log__have_time())
if (log__have_time())
fprintf(out, "[%.4lld.%.6lld] %s: %s: ",
sec, usec, prefix, subs);
else
fprintf(out, "%s: %s: ", prefix, subs);
} else {
if (log_date_time)
fprintf(out, "[%s] %s: ", buffer, prefix);
else if (log__have_time())
if (log__have_time())
fprintf(out, "[%.4lld.%.6lld] %s: ",
sec, usec, prefix);
else
@ -193,18 +161,13 @@ static void log__submit(const char *file,
}
} else {
if (subs) {
if (log_date_time)
fprintf(out, "[%s] %s: ",
buffer, subs);
else if (log__have_time())
if (log__have_time())
fprintf(out, "[%.4lld.%.6lld] %s: ",
sec, usec, subs);
else
fprintf(out, "%s: ", subs);
} else {
if (log_date_time)
fprintf(out, "[%s] ", buffer);
else if (log__have_time())
if (log__have_time())
fprintf(out, "[%.4lld.%.6lld] ", sec, usec);
}
}
@ -276,9 +239,9 @@ void log_llog(void *data,
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")) {
log_max_sev = LOG_FATAL;
} else if(!strcasecmp(optarg, "alert")) {
@ -298,23 +261,7 @@ unsigned int log_parse_arg(char *optarg)
} else if(!strcasecmp(optarg, "trace")) {
log_max_sev = LOG_TRACE;
} else {
errno = 0;
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;
log_max_sev = atoi(optarg);
}
return log_max_sev;
}

View file

@ -61,17 +61,6 @@ enum log_severity {
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
* 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__time(long long *sec, long long *usec);
bool log__have_time(void);
/*
* Log-Functions
* 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,
va_list args);
unsigned int log_parse_arg(char *optarg);
int log_parse_arg(char *optarg);
static inline __attribute__((format(printf, 2, 3)))
void log_dummyf(unsigned int sev, const char *format, ...)
@ -241,9 +226,4 @@ extern const char *LOG_SUBSYSTEM;
#define log_vERR(_r) \
((void)log_ERR(_r))
#define log_EUNMANAGED() \
(log_error("interface unmanaged"), -EFAULT)
#define log_vEUNMANAGED() \
((void)log_EUNMANAGED())
#endif /* SHL_LOG_H */

View file

@ -31,7 +31,7 @@
* variants to allow these.
* Base-prefix parsing is only done if base=0 is requested. Otherwise,
* 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!)
* 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)
return 0;
p = strndup(path, e - path);
p = strndupa(path, e - path);
r = shl__is_dir(p);
free((char*)p);
if (r > 0)
return 0;
if (r == 0)

View file

@ -31,26 +31,6 @@
#include <systemd/sd-bus.h>
#include <time.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)
{

View file

@ -742,7 +742,6 @@ static int wpas__parse_message(struct wpas *w,
const char *ifname = NULL;
unsigned int level;
char *pos;
char *orig_raw = raw;
int r, num;
bool is_event = false;
@ -752,7 +751,7 @@ static int wpas__parse_message(struct wpas *w,
ifname = pos;
pos = strchrnul(pos, ' ');
if (*pos)
pos++;
*pos++ = 0;
len -= pos - raw;
raw = pos;
@ -812,12 +811,15 @@ static int wpas__parse_message(struct wpas *w,
m->sealed = true;
m->rawlen = len;
m->raw = strdup(orig_raw);
m->raw = malloc(len + 1);
if (!m->raw)
return -ENOMEM;
/* copy with 0-terminator */
memcpy(m->raw, raw, len + 1);
if (ifname) {
m->ifname = strndup(ifname, strchrnul(ifname, ' ') - ifname);
m->ifname = strdup(ifname);
if (!m->ifname)
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;
return 0;

View file

@ -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)

View file

@ -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)

View file

@ -1,4 +0,0 @@
executable('miracle-uibcctl', 'miracle-uibcctl.h', 'miracle-uibcctl.c',
install: true,
dependencies: [m, libmiracle_shared_dep]
)

View file

@ -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;
}

View file

@ -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

View file

@ -1,3 +1,6 @@
########### next target ###############
set(miracle-wifid_SRCS wifid.h
wifid.c
wifid-dbus.c
@ -9,7 +12,6 @@ add_executable(miracle-wifid ${miracle-wifid_SRCS})
target_link_libraries(miracle-wifid ${KDE4_KDECORE_LIBS})
cmake_policy(SET CMP0015 NEW)
include_directories(shared)
link_directories(shared)
target_link_libraries(miracle-wifid miracle-shared)
@ -17,11 +19,40 @@ target_link_libraries(miracle-wifid miracle-shared)
find_package(PkgConfig)
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
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 m)
link_directories( ${GLIB2_LIBRARY_DIRS})
include_directories( ${GLIB2_INCLUDE_DIRS})
#link_directories( ${GLIB2_LIBRARY_DIRS})
#include_directories( ${GLIB2_INCLUDE_DIRS})
target_link_libraries(miracle-wifid ${GLIB2_LIBRARIES})
install(TARGETS miracle-wifid DESTINATION bin)
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)
#

View file

@ -10,10 +10,8 @@ miracle_wifid_SOURCES = \
wifid-supplicant.c
miracle_wifid_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(DEPS_CFLAGS) \
$(GLIB_CFLAGS)
$(DEPS_CFLAGS)
miracle_wifid_LDADD = \
../shared/libmiracle-shared.la \
$(DEPS_LIBS) \
$(GLIB_LIBS)
$(DEPS_LIBS)

View file

@ -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]
)

View file

@ -309,7 +309,6 @@ static const sd_bus_vtable peer_dbus_vtable[] = {
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
SD_BUS_SIGNAL("GoNegRequest", "ss", 0),
SD_BUS_SIGNAL("FormationFailure", "s", 0),
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);
}
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,
const char *path,
const char *interface,
@ -698,12 +661,6 @@ static const sd_bus_vtable link_dbus_vtable[] = {
link_dbus_set_friendly_name,
0,
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",
"b",
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);
if (r < 0) {
if (r == -EEXIST) {
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",
log_error("cannot claim org.freedesktop.miracle.wifi bus-name: %d",
r);
}
goto error_silent;
}

View file

@ -100,8 +100,6 @@ int link_new(struct manager *m,
if (out)
*out = l;
l->public = true;
link_dbus_added(l);
return 0;
error:
@ -118,9 +116,6 @@ void link_free(struct link *l)
link_set_managed(l, false);
link_dbus_removed(l);
l->public = false;
if (shl_htable_remove_uint(&l->m->links, l->ifindex, NULL)) {
log_info("remove link: %s", l->ifname);
--l->m->link_cnt;
@ -134,66 +129,17 @@ void link_free(struct link *l)
free(l->wfd_subelements);
free(l->friendly_name);
free(l->ifname);
free(l->config_methods);
free(l->ip_binary);
free(l);
}
void link_use_dev(struct link *l)
{
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)
void link_set_managed(struct link *l, bool set)
{
int r;
if (!l)
return log_EINVAL();
return log_vEINVAL();
if (l->managed == set)
return 0;
return;
if (set) {
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);
if (r < 0) {
log_error("cannot start supplicant on %s", l->ifname);
return -EFAULT;
return;
}
} else {
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;
return 0;
}
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)
return log_EINVAL();
if (!l->managed)
return log_EUNMANAGED();
t = strdup(val);
if (!t)
return log_ENOMEM();
@ -314,9 +256,6 @@ int link_set_p2p_scanning(struct link *l, bool set)
if (!l)
return log_EINVAL();
if (!l->managed)
return log_EUNMANAGED();
if (set) {
return supplicant_p2p_start_scan(l->s);
} else {
@ -327,16 +266,7 @@ int link_set_p2p_scanning(struct link *l, bool set)
bool link_get_p2p_scanning(struct link *l)
{
if (!l) {
log_vEINVAL();
return false;
}
if (!l->managed) {
return false;
}
return supplicant_p2p_scanning(l->s);
return l && supplicant_p2p_scanning(l->s);
}
void link_supplicant_started(struct link *l)
@ -344,9 +274,9 @@ void link_supplicant_started(struct link *l)
if (!l || l->public)
return;
if (l->m->friendly_name && l->managed)
link_set_friendly_name(l, l->m->friendly_name);
log_info("link %s managed", l->ifname);
log_debug("link %s started", l->ifname);
l->public = true;
link_dbus_added(l);
}
void link_supplicant_stopped(struct link *l)
@ -354,7 +284,9 @@ void link_supplicant_stopped(struct link *l)
if (!l || !l->public)
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)

View file

@ -61,8 +61,7 @@ int peer_new(struct link *l,
r = log_ENOMEM();
goto error;
}
strncpy(p->p2p_mac, mac, MAC_STRLEN);
p->p2p_mac[MAC_STRLEN - 1] = 0;
strncpy(p->p2p_mac, mac, MAC_STRLEN - 1);
r = shl_htable_insert_str(&l->peers, &p->p2p_mac, NULL);
if (r < 0) {

View file

@ -19,21 +19,14 @@
#define LOG_SUBSYSTEM "supplicant"
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <systemd/sd-event.h>
#ifdef ENABLE_SYSTEMD
#include <systemd/sd-journal.h>
#endif
#include <unistd.h>
#include "shl_dlist.h"
#include "shl_log.h"
@ -41,6 +34,7 @@
#include "util.h"
#include "wifid.h"
#include "wpas.h"
#include "config.h"
struct supplicant_group {
unsigned long users;
@ -379,7 +373,6 @@ static int supplicant_group_spawn_dhcp_server(struct supplicant_group *g,
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
#ifdef ENABLE_SYSTEMD
/* redirect stdout/stderr to journal */
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
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, 2);
} else {
#endif
/* no journal? redirect stdout to parent's stderr */
dup2(2, 1);
#ifdef ENABLE_SYSTEMD
}
#endif
i = 0;
argv[i++] = (char*) "miracle-dhcp";
argv[i++] = (char*) BUILD_BINDIR "/miracle-dhcp";
argv[i++] = "--server";
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++] = "--comm-fd";
argv[i++] = commfd;
if (g->s->l->ip_binary) {
argv[i++] = "--ip-binary";
argv[i++] = g->s->l->ip_binary;
}
argv[i] = NULL;
if (execvpe(argv[0], argv, environ)< 0) {
log_error("dhcp failed (%d): %m", errno);
}
execve(argv[0], argv, environ);
_exit(1);
}
@ -451,7 +435,6 @@ static int supplicant_group_spawn_dhcp_client(struct supplicant_group *g)
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
#ifdef ENABLE_SYSTEMD
/* redirect stdout/stderr to journal */
sprintf(journal_id, "miracle-dhcp-%s", g->ifname);
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, 2);
} else {
#endif
/* no journal? redirect stdout to parent's stderr */
dup2(2, 1);
#ifdef ENABLE_SYSTEMD
}
#endif
i = 0;
argv[i++] = (char*) "miracle-dhcp";
argv[i++] = (char*) BUILD_BINDIR "/miracle-dhcp";
argv[i++] = "--log-level";
argv[i++] = loglevel;
argv[i++] = "--netdev";
argv[i++] = g->ifname;
argv[i++] = "--comm-fd";
argv[i++] = commfd;
if (g->s->l->ip_binary) {
argv[i++] = "--ip-binary";
argv[i++] = g->s->l->ip_binary;
}
argv[i] = NULL;
if (execvpe(argv[0], argv, environ) < 0) {
log_error("dhcp failed (%d): %m", errno);
}
execve(argv[0], argv, environ);
_exit(1);
}
@ -530,7 +504,7 @@ static int supplicant_group_new(struct supplicant *s,
j = shl_dlist_entry(i,
struct supplicant_group,
list);
if (j->subnet == subnet)
if (j->subnet == j->subnet)
break;
}
@ -897,7 +871,7 @@ static void supplicant_parse_peer(struct supplicant *s,
/* TODO: wfd_dev_info only contains the dev-info sub-elem,
* while wfd_sublemens contains all. Fix that! The user has no
* 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. */
r = wpas_message_dict_read(m, "wfd_dev_info", 's', &val);
if (r >= 0) {
@ -1313,20 +1287,6 @@ static void supplicant_event_p2p_group_removed(struct supplicant *s,
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,
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, "CTRL-EVENT-EAP-STATUS") ||
!strcmp(name, "CTRL-EVENT-EAP-METHOD") ||
!strcmp(name, "CTRL-EVENT-EAP-STATUS") ||
!strcmp(name, "WPS-CRED-RECEIVED") ||
!strcmp(name, "WPS-AP-AVAILABLE") ||
!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);
else if (!strcmp(name, "P2P-GROUP-REMOVED"))
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"))
supplicant_event_p2p_group_formation_failure(s, m);
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 */
if(link_is_using_dev(s->l) && wpas_message_get_ifname(m)) {
supplicant_event(s, m);
}
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
* support) are broken with a *lot* of wpa_supplicant versions on the
* 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
* copy the global interface over to bus_dev.
* 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);
sigprocmask(SIG_SETMASK, &mask, NULL);
#ifdef ENABLE_SYSTEMD
/* redirect stdout/stderr to journal */
sprintf(journal_id, "miracle-wifid-%s-%u",
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, 2);
} else {
#endif
/* no journal? redirect stdout to parent's stderr */
dup2(2, 1);
#ifdef ENABLE_SYSTEMD
}
#endif
/* initialize wpa_supplicant args */
i = 0;
@ -2439,60 +2391,12 @@ static void supplicant_run(struct supplicant *s, const char *binary)
argv[i++] = s->l->ifname;
argv[i++] = "-g";
argv[i++] = s->global_ctrl;
if (arg_wpa_syslog) {
argv[i++] = "-s";
}
argv[i] = NULL;
/* execute wpa_supplicant; if it fails, the caller issues exit(1) */
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)
{
_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);
if (supplicant_find(&binary) < 0) {
if (binary != NULL) {
log_error("execution of wpas (%s) not possible: %m", binary);
} else {
log_error("execution of wpas not possible: %m");
}
return -EINVAL;
}
binary = shl_strcat(arg_wpa_bindir, "/wpa_supplicant");
if (!binary)
return log_ENOMEM();
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();
if (pid < 0) {
@ -2630,9 +2532,10 @@ static int supplicant_write_config(struct supplicant *s)
"driver_param=%s\n"
"ap_scan=%s\n"
"# End of configuration\n",
s->l->friendly_name ?: "unknown",
s->l->friendly_name ? : "unknown",
"1-0050F204-1",
s->l->config_methods ?: "pbc",
"pbc",
//"pbc keypad pin display",
"p2p_device=1",
"1");
if (r < 0) {

View file

@ -40,16 +40,9 @@
#include "wifid.h"
#include "config.h"
#define XSTR(x) STR(x)
#define STR(x) #x
const char *arg_wpa_bindir = "/usr/bin";
const char *interface_name = NULL;
const char *config_methods = NULL;
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
@ -108,22 +101,13 @@ static void manager_add_udev_link(struct manager *m,
if (r < 0)
return;
if (m->friendly_name && l->managed)
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);
link_set_friendly_name(l, m->friendly_name);
#ifdef RELY_UDEV
bool managed = udev_device_has_tag(d, "miracle") && !lazy_managed;
if (udev_device_has_tag(d, "miracle")) {
#else
bool managed = (!interface_name || !strcmp(interface_name, ifname)) && !lazy_managed;
if (!interface_name || !strcmp(interface_name, ifname)) {
#endif
if (managed) {
link_set_managed(l, true);
} else {
log_debug("ignored device: %s", ifname);
@ -163,12 +147,12 @@ static int manager_udev_fn(sd_event_source *source,
}
#ifdef RELY_UDEV
if (udev_device_has_tag(d, "miracle") && !lazy_managed)
if (udev_device_has_tag(d, "miracle"))
link_set_managed(l, true);
else
link_set_managed(l, false);
#else
if ((!interface_name || !strcmp(interface_name, ifname)) && !lazy_managed) {
if (!interface_name || !strcmp(interface_name, ifname)) {
link_set_managed(l, true);
} else {
log_debug("ignored device: %s", ifname);
@ -228,7 +212,6 @@ static void manager_free(struct manager *m)
sd_event_unref(m->event);
free(m->friendly_name);
free(m->config_methods);
free(m);
}
@ -241,7 +224,6 @@ static int manager_new(struct manager **out)
unsigned int i;
sigset_t mask;
int r;
char *cm;
m = calloc(1, sizeof(*m));
if (!m)
@ -249,16 +231,6 @@ static int manager_new(struct manager **out)
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);
if (r < 0) {
log_vERR(r);
@ -482,16 +454,11 @@ static int help(void)
" --version Show package version\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"
"\n"
" -i --interface Choose the interface to use\n"
" --config-methods Define config methods for pairing, default 'pbc'\n"
"\n"
" --wpa-loglevel <lvl> wpa_supplicant log-level\n"
" --wpa-syslog wpa_supplicant use syslog\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"
" --wpa-bindir <dir> wpa_supplicant binary dir [/usr/bin]\n"
" --wpa-loglevel <lvl wpa_supplicant log-level\n"
, program_invocation_short_name);
/*
* 80-char barrier:
@ -507,28 +474,19 @@ static int parse_argv(int argc, char *argv[])
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_LOG_DATE_TIME,
ARG_WPA_BINDIR,
ARG_WPA_LOGLEVEL,
ARG_WPA_SYSLOG,
ARG_USE_DEV,
ARG_CONFIG_METHODS,
ARG_LAZY_MANAGED,
ARG_IP_BINARY,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "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 },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
{ "wpa-bindir", required_argument, NULL, ARG_WPA_BINDIR },
{ "wpa-loglevel", required_argument, NULL, ARG_WPA_LOGLEVEL },
{ "wpa-syslog", no_argument, NULL, ARG_WPA_SYSLOG },
{ "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;
@ -549,27 +507,13 @@ static int parse_argv(int argc, char *argv[])
case ARG_LOG_TIME:
log_init_time();
break;
case ARG_LOG_DATE_TIME:
log_date_time = true;
break;
case ARG_USE_DEV:
use_dev = true;
break;
case ARG_CONFIG_METHODS:
config_methods = optarg;
break;
case ARG_LAZY_MANAGED:
lazy_managed = true;
case ARG_WPA_BINDIR:
arg_wpa_bindir = optarg;
break;
case ARG_WPA_LOGLEVEL:
arg_wpa_loglevel = log_parse_arg(optarg);
break;
case ARG_WPA_SYSLOG:
arg_wpa_syslog = true;
break;
case ARG_IP_BINARY:
arg_ip_binary = optarg;
break;
case '?':
return -EINVAL;
}
@ -595,30 +539,12 @@ int main(int argc, char **argv)
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);
if (r < 0)
return EXIT_FAILURE;
if (!r)
return EXIT_SUCCESS;
if (getuid() != 0) {
r = EACCES;
log_notice("Must run as root");
goto finish;
}
r = manager_new(&m);
if (r < 0)
goto finish;

View file

@ -129,15 +129,12 @@ struct link {
char *ifname;
char *friendly_name;
char *wfd_subelements;
char *config_methods;
char *ip_binary;
size_t peer_cnt;
struct shl_htable peers;
bool managed : 1;
bool public : 1;
bool use_dev : 1;
};
#define link_from_htable(_l) \
@ -156,17 +153,9 @@ int link_new(struct manager *m,
struct link **out);
void link_free(struct link *l);
/* workaround for the 'no ifname' issue */
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);
void link_set_managed(struct link *l, bool set);
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);
const char *link_get_friendly_name(struct link *l);
int link_set_wfd_subelements(struct link *l, const char *val);
@ -194,7 +183,6 @@ struct manager {
sd_event_source *udev_mon_source;
char *friendly_name;
char *config_methods;
size_t link_cnt;
struct shl_htable links;
@ -215,7 +203,7 @@ void manager_dbus_disconnect(struct manager *m);
/* cli arguments */
extern const char *arg_wpa_bindir;
extern unsigned int arg_wpa_loglevel;
extern bool arg_wpa_syslog;
#endif /* WIFID_H */

View file

@ -1,31 +1,31 @@
########### next target ###############
find_package(PkgConfig)
pkg_check_modules (CHECK check)
if(CHECK_FOUND)
set(test_rtsp_SOURCES test_common.h test_rtsp.c)
add_executable(test_rtsp ${test_rtsp_SOURCES})
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 ${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)
add_executable(test_wpas ${test_wpas_SOURCES})
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 ${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)
add_executable(test_valgrind ${test_valgrind_SOURCES})
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 ${GLIB2_LIBRARIES})
target_link_libraries(test_valgrind ${CHECK_LIBRARIES})
target_link_libraries(test_valgrind ${CHECK_CFLAGS})
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/shared)
@ -39,7 +39,7 @@ if(CHECK_FOUND)
add_custom_target(memcheck
DEPENDS memcheck-verify
COMMAND for i in $$(MEMTESTS) |
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) ; |
@ -48,3 +48,69 @@ if(CHECK_FOUND)
COMMENT "verify memcheck")
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

View file

@ -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