#!/bin/bash PS4="\e[34m> ${0##*/}:\e[0m " set -x set -e if (( $# < 1 )); then echo Usage: ${0##*/} link-index peer-p2p-mac [nm-link-index] echo eg. sudo ${0##*/} 3 ac:a2:13:6e:f8:2f echo if the index of WNIC in wifid is different from NM, then echo eg. sudo ${0##*/} 4 ac:a2:13:6e:f8:2f 3 exit 1 fi if [[ ${#2} != 17 ]]; then echo Invalid peer-p2p-mac: $2 exit 1 fi # this wfd_subelems has no ID (00, device info) wfd_subelems=000600111c4400c8 link_index="_3${1:0:1}${1:1}" peer_id="${2//:/_3a}_40$1" if [[ -z "$3" ]]; then nm_link_index="$1" else nm_link_index="$3" fi # $1: service # $2: object # $3: interface # $4: member # $5: property value wait_prop_change() { for ((i=0; i<60; i++)); do read -a cols < <(busctl get-property "${@:1:4}") case ${cols[0]} in s | o) cols[1]="${cols[1]:1:${#cols[1]}-2}" ;; esac if [[ "$5" == "${cols[1]}" ]]; then return 0 fi sleep 1 done echo !!!timeout!!! return 1 } # $1: service # $2: object # $3: interface # $4: member wait_object() { while ! busctl get-property "$1" "$2" "$3" "$4" &>/dev/null; do sleep 1 done } # $1: service # $2: object # $3: interface # $4: property # $5: expected property value # $6: method # $...: arguments invoke() { set +x wait_object "${@:1:4}" busctl call "${@:1:3}" "${@:6}" wait_prop_change "${@:1:5}" set -x } # $1: service # $2: object # $3: interface # $4: member # $5: property spec # $6: property values set_prop() { set +x busctl set-property "$@" wait_prop_change "${@:1:4}" "${@:6:1}" set -x } # $1: service # $2: object # $3: interface # $4: member # $5: variable name get_prop() { read -a l < <(busctl get-property "${@:1:4}") eval $5=\"${l[1]}\" } cleanup() { trap '' TERM set +e while (( 0 != ${#cleanup[@]} )); do eval ${cleanup[${#cleanup[@]}-1]} unset cleanup[${#cleanup[@]}-1] done } cleanup_push() { cleanup+=("$*") } nm_manage() { set_prop org.freedesktop.NetworkManager \ /org/freedesktop/NetworkManager/Devices/"$nm_link_index" \ org.freedesktop.NetworkManager.Device \ Managed b true } link_unmanage() { invoke org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/link/$link_index \ org.freedesktop.miracle.wifi.Link \ Managed false \ Unmanage } link_stop_p2pscan() { set_prop org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/link/$link_index \ org.freedesktop.miracle.wifi.Link \ P2PScanning b false } peer_disconnect() { invoke org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/peer/$peer_id \ org.freedesktop.miracle.wifi.Peer \ Connected false \ Disconnect } sudo killall miracle-wifid &>/dev/null || true sudo killall miracle-wfwctl &>/dev/null || true trap cleanup EXIT trap 'exit 0' TERM trap '' CHLD set_prop org.freedesktop.NetworkManager \ /org/freedesktop/NetworkManager/Devices/"$nm_link_index" \ org.freedesktop.NetworkManager.Device \ Managed b false cleanup_push nm_manage invoke org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/link/$link_index \ org.freedesktop.miracle.wifi.Link \ Managed true \ Manage cleanup_push link_unmanage set_prop org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/link/$link_index \ org.freedesktop.miracle.wifi.Link \ WfdSubelements s "$wfd_subelems" # this one is tricky, we wait for wpa_supplicant fully started then start # P2P scaning, or "Invalid argument" will return sleep 0.5 echo wait for peer... set_prop org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/link/$link_index \ org.freedesktop.miracle.wifi.Link \ P2PScanning b true cleanup_push link_stop_p2pscan echo connect to peer... invoke org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/peer/$peer_id \ org.freedesktop.miracle.wifi.Peer \ Connected true \ Connect ss auto '' cleanup_push peer_disconnect get_prop org.freedesktop.miracle.wifi \ /org/freedesktop/miracle/wifi/peer/$peer_id \ org.freedesktop.miracle.wifi.Peer \ Interface p2p_iface sudo tcpdump -i $p2p_iface -w miraclecast.pcap -T rtp & cleanup_push "kill $!" while [[ -z "$nocheck" ]] && ! killall -0 miracle-wfdctl &>/dev/null; do echo please run miracle-wfdctl manually sleep 3 done echo starting WFD session... invoke org.freedesktop.miracle.wfd \ /org/freedesktop/miracle/wfd/sink/$peer_id \ org.freedesktop.miracle.wfd.Sink \ Peer /org/freedesktop/miracle/wifi/peer/$peer_id \ StartSession ssqqqqs \ "$XAUTHORITY" \ 'x://:0.0' \ 0 \ 0 \ 1920 \ 1080 \ 'alsa_output.pci-0000_00_1b.0.analog-stereo.monitor' wait