mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
Merge branch 'agusakov'
This commit is contained in:
commit
640f731d44
18 changed files with 562 additions and 44 deletions
|
@ -4,12 +4,15 @@ DEBUG='0'
|
||||||
AUDIO='0'
|
AUDIO='0'
|
||||||
SCALE='0'
|
SCALE='0'
|
||||||
|
|
||||||
while getopts "d:as:" optname
|
while getopts "r:d:as:" optname
|
||||||
do
|
do
|
||||||
case "$optname" in
|
case "$optname" in
|
||||||
"d")
|
"d")
|
||||||
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
DEBUG=`echo ${OPTARG} | tr -d ' '`
|
||||||
;;
|
;;
|
||||||
|
"r")
|
||||||
|
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
|
||||||
|
;;
|
||||||
"a")
|
"a")
|
||||||
AUDIO='1'
|
AUDIO='1'
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -19,6 +19,7 @@ miracle_sinkctl_SOURCES = \
|
||||||
ctl-cli.c \
|
ctl-cli.c \
|
||||||
ctl-sink.c \
|
ctl-sink.c \
|
||||||
ctl-wifi.c \
|
ctl-wifi.c \
|
||||||
|
wfd.c \
|
||||||
sinkctl.c
|
sinkctl.c
|
||||||
miracle_sinkctl_CPPFLAGS = \
|
miracle_sinkctl_CPPFLAGS = \
|
||||||
$(AM_CPPFLAGS) \
|
$(AM_CPPFLAGS) \
|
||||||
|
|
|
@ -97,11 +97,10 @@ int cli_help(const struct cli_cmd *cmds)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (is_cli()) {
|
if (!is_cli()) {
|
||||||
cli_printf("Available commands:\n");
|
|
||||||
} else {
|
|
||||||
cli_fn_help();
|
cli_fn_help();
|
||||||
}
|
}
|
||||||
|
cli_printf("Available commands:\n");
|
||||||
|
|
||||||
for (i = 0; cmds[i].cmd; ++i) {
|
for (i = 0; cmds[i].cmd; ++i) {
|
||||||
if (!cmds[i].desc)
|
if (!cmds[i].desc)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "rtsp.h"
|
#include "rtsp.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_util.h"
|
#include "shl_util.h"
|
||||||
|
#include "wfd.h"
|
||||||
|
|
||||||
struct ctl_sink {
|
struct ctl_sink {
|
||||||
sd_event *event;
|
sd_event *event;
|
||||||
|
@ -51,6 +52,13 @@ struct ctl_sink {
|
||||||
|
|
||||||
bool connected : 1;
|
bool connected : 1;
|
||||||
bool hup : 1;
|
bool hup : 1;
|
||||||
|
|
||||||
|
uint32_t resolutions_cea;
|
||||||
|
uint32_t resolutions_vesa;
|
||||||
|
uint32_t resolutions_hh;
|
||||||
|
|
||||||
|
int hres;
|
||||||
|
int vres;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -120,13 +128,37 @@ static void sink_handle_get_parameter(struct ctl_sink *s,
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return cli_vERR(r);
|
return cli_vERR(r);
|
||||||
|
|
||||||
r = rtsp_message_append(rep, "{&&&&}",
|
/* wfd_content_protection */
|
||||||
"wfd_content_protection: none",
|
if (rtsp_message_read(m, "{<>}", "wfd_content_protection") >= 0) {
|
||||||
"wfd_video_formats: 00 00 01 01 0000007f 003fffff 00000000 00 0000 0000 00 none none",
|
r = rtsp_message_append(rep, "{&}",
|
||||||
"wfd_audio_codecs: AAC 00000007 00",
|
"wfd_content_protection: none");
|
||||||
"wfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play");
|
if (r < 0)
|
||||||
if (r < 0)
|
return cli_vERR(r);
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
rtsp_message_seal(rep);
|
rtsp_message_seal(rep);
|
||||||
cli_debug("OUTGOING: %s\n", rtsp_message_get_raw(rep));
|
cli_debug("OUTGOING: %s\n", rtsp_message_get_raw(rep));
|
||||||
|
@ -182,6 +214,27 @@ static int sink_setup_fn(struct rtsp *bus, struct rtsp_message *m, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sink_set_format(struct ctl_sink *s,
|
||||||
|
unsigned int cea_res,
|
||||||
|
unsigned int vesa_res,
|
||||||
|
unsigned int hh_res)
|
||||||
|
{
|
||||||
|
int hres, vres;
|
||||||
|
|
||||||
|
if ((vfd_get_cea_resolution(cea_res, &hres, &vres) == 0) ||
|
||||||
|
(vfd_get_vesa_resolution(vesa_res, &hres, &vres) == 0) ||
|
||||||
|
(vfd_get_hh_resolution(hh_res, &hres, &vres) == 0)) {
|
||||||
|
if (hres && vres) {
|
||||||
|
s->hres = hres;
|
||||||
|
s->vres = vres;
|
||||||
|
ctl_fn_sink_resolution_set(s, hres, vres);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static void sink_handle_set_parameter(struct ctl_sink *s,
|
static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
struct rtsp_message *m)
|
struct rtsp_message *m)
|
||||||
{
|
{
|
||||||
|
@ -189,6 +242,7 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
const char *trigger;
|
const char *trigger;
|
||||||
const char *url;
|
const char *url;
|
||||||
char *nu;
|
char *nu;
|
||||||
|
unsigned int cea_res, vesa_res, hh_res;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
|
r = rtsp_message_new_reply_for(m, &rep, RTSP_CODE_OK, NULL);
|
||||||
|
@ -219,16 +273,19 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtsp_message_exit_header(m);
|
/* M4 again */
|
||||||
rtsp_message_exit_body(m);
|
r = rtsp_message_read(m, "{<****hhh>}", "wfd_video_formats",
|
||||||
|
&cea_res, &vesa_res, &hh_res);
|
||||||
|
if (r == 0) {
|
||||||
|
r = sink_set_format(s, cea_res, vesa_res, hh_res);
|
||||||
|
if (r)
|
||||||
|
return cli_vERR(r);
|
||||||
|
}
|
||||||
|
|
||||||
/* M5 */
|
/* M5 */
|
||||||
r = rtsp_message_read(m, "{<s>}", "wfd_trigger_method", &trigger);
|
r = rtsp_message_read(m, "{<s>}", "wfd_trigger_method", &trigger);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
rtsp_message_exit_header(m);
|
|
||||||
rtsp_message_exit_body(m);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(trigger, "SETUP")) {
|
if (!strcmp(trigger, "SETUP")) {
|
||||||
if (!s->url) {
|
if (!s->url) {
|
||||||
|
@ -453,6 +510,9 @@ int ctl_sink_new(struct ctl_sink **out,
|
||||||
|
|
||||||
s->event = sd_event_ref(event);
|
s->event = sd_event_ref(event);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
|
s->resolutions_cea = wfd_supported_res_cea;
|
||||||
|
s->resolutions_vesa = wfd_supported_res_vesa;
|
||||||
|
s->resolutions_hh = wfd_supported_res_hh;
|
||||||
|
|
||||||
*out = s;
|
*out = s;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -975,6 +975,17 @@ static int ctl_wifi_peer_fn(sd_bus *bus,
|
||||||
return cli_log_parser(r);
|
return cli_log_parser(r);
|
||||||
|
|
||||||
ctl_fn_peer_provision_discovery(p, prov, pin);
|
ctl_fn_peer_provision_discovery(p, prov, pin);
|
||||||
|
} else if (sd_bus_message_is_signal(m,
|
||||||
|
"org.freedesktop.miracle.wifi.Peer",
|
||||||
|
"GoNegRequest")) {
|
||||||
|
/* connection request */
|
||||||
|
const char *prov, *pin;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(m, "ss", &prov, &pin);
|
||||||
|
if (r < 0)
|
||||||
|
return cli_log_parser(r);
|
||||||
|
|
||||||
|
ctl_fn_peer_go_neg_request(p, prov, pin);
|
||||||
} else if (sd_bus_message_is_signal(m,
|
} else if (sd_bus_message_is_signal(m,
|
||||||
"org.freedesktop.miracle.wifi.Peer",
|
"org.freedesktop.miracle.wifi.Peer",
|
||||||
"FormationFailure")) {
|
"FormationFailure")) {
|
||||||
|
|
|
@ -236,6 +236,10 @@ struct cli_cmd {
|
||||||
extern sd_event *cli_event;
|
extern sd_event *cli_event;
|
||||||
extern sd_bus *cli_bus;
|
extern sd_bus *cli_bus;
|
||||||
|
|
||||||
|
extern unsigned int wfd_supported_res_cea;
|
||||||
|
extern unsigned int wfd_supported_res_vesa;
|
||||||
|
extern unsigned int wfd_supported_res_hh;
|
||||||
|
|
||||||
int cli_init(sd_bus *bus, const struct cli_cmd *cmds);
|
int cli_init(sd_bus *bus, const struct cli_cmd *cmds);
|
||||||
void cli_destroy(void);
|
void cli_destroy(void);
|
||||||
int cli_run(void);
|
int cli_run(void);
|
||||||
|
@ -252,6 +256,9 @@ void ctl_fn_peer_free(struct ctl_peer *p);
|
||||||
void ctl_fn_peer_provision_discovery(struct ctl_peer *p,
|
void ctl_fn_peer_provision_discovery(struct ctl_peer *p,
|
||||||
const char *prov,
|
const char *prov,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
|
void ctl_fn_peer_go_neg_request(struct ctl_peer *p,
|
||||||
|
const char *prov,
|
||||||
|
const char *pin);
|
||||||
void ctl_fn_peer_formation_failure(struct ctl_peer *p, const char *reason);
|
void ctl_fn_peer_formation_failure(struct ctl_peer *p, const char *reason);
|
||||||
void ctl_fn_peer_connected(struct ctl_peer *p);
|
void ctl_fn_peer_connected(struct ctl_peer *p);
|
||||||
void ctl_fn_peer_disconnected(struct ctl_peer *p);
|
void ctl_fn_peer_disconnected(struct ctl_peer *p);
|
||||||
|
@ -260,6 +267,7 @@ void ctl_fn_link_free(struct ctl_link *l);
|
||||||
|
|
||||||
void ctl_fn_sink_connected(struct ctl_sink *s);
|
void ctl_fn_sink_connected(struct ctl_sink *s);
|
||||||
void ctl_fn_sink_disconnected(struct ctl_sink *s);
|
void ctl_fn_sink_disconnected(struct ctl_sink *s);
|
||||||
|
void ctl_fn_sink_resolution_set(struct ctl_sink *s, int hres, int vres);
|
||||||
|
|
||||||
void cli_fn_help(void);
|
void cli_fn_help(void);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "ctl.h"
|
#include "ctl.h"
|
||||||
|
#include "wfd.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_util.h"
|
#include "shl_util.h"
|
||||||
|
|
||||||
|
@ -49,9 +50,13 @@ static pid_t sink_pid;
|
||||||
static char *bound_link;
|
static char *bound_link;
|
||||||
static struct ctl_link *running_link;
|
static struct ctl_link *running_link;
|
||||||
static struct ctl_peer *running_peer;
|
static struct ctl_peer *running_peer;
|
||||||
|
static struct ctl_peer *pending_peer;
|
||||||
|
|
||||||
char *gst_scale_res;
|
char *gst_scale_res;
|
||||||
int gst_audio_en = 1;
|
int gst_audio_en = 1;
|
||||||
|
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
|
* cmd list
|
||||||
|
@ -280,6 +285,14 @@ static int scan_timeout_fn(sd_event_source *s, uint64_t usec, void *data)
|
||||||
{
|
{
|
||||||
stop_timeout(&scan_timeout);
|
stop_timeout(&scan_timeout);
|
||||||
|
|
||||||
|
if (pending_peer) {
|
||||||
|
if (cli_running()) {
|
||||||
|
cli_printf("[" CLI_RED "TIMEOUT" CLI_DEFAULT "] waiting for %s\n",
|
||||||
|
pending_peer->friendly_name);
|
||||||
|
}
|
||||||
|
pending_peer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (running_link)
|
if (running_link)
|
||||||
ctl_link_set_p2p_scanning(running_link, true);
|
ctl_link_set_p2p_scanning(running_link, true);
|
||||||
|
|
||||||
|
@ -321,9 +334,10 @@ static const struct cli_cmd cli_cmds[] = {
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void spawn_gst(void)
|
static void spawn_gst(int hres, int vres)
|
||||||
{
|
{
|
||||||
char *argv[64];
|
char *argv[64];
|
||||||
|
char resolution[64];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int fd_journal, i;
|
int fd_journal, i;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
|
@ -363,6 +377,11 @@ static void spawn_gst(void)
|
||||||
argv[i++] = "-s";
|
argv[i++] = "-s";
|
||||||
argv[i++] = gst_scale_res;
|
argv[i++] = gst_scale_res;
|
||||||
}
|
}
|
||||||
|
if (hres && vres) {
|
||||||
|
sprintf(resolution, "%dx%d", hres, vres);
|
||||||
|
argv[i++] = "-r";
|
||||||
|
argv[i++] = resolution;
|
||||||
|
}
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
|
|
||||||
execve(argv[0], argv, environ);
|
execve(argv[0], argv, environ);
|
||||||
|
@ -385,7 +404,6 @@ void ctl_fn_sink_connected(struct ctl_sink *s)
|
||||||
{
|
{
|
||||||
cli_notice("SINK connected");
|
cli_notice("SINK connected");
|
||||||
sink_connected = true;
|
sink_connected = true;
|
||||||
spawn_gst();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctl_fn_sink_disconnected(struct ctl_sink *s)
|
void ctl_fn_sink_disconnected(struct ctl_sink *s)
|
||||||
|
@ -399,6 +417,13 @@ void ctl_fn_sink_disconnected(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", hres, vres);
|
||||||
|
if (sink_connected)
|
||||||
|
spawn_gst(hres, vres);
|
||||||
|
}
|
||||||
|
|
||||||
void ctl_fn_peer_new(struct ctl_peer *p)
|
void ctl_fn_peer_new(struct ctl_peer *p)
|
||||||
{
|
{
|
||||||
if (p->l != running_link || shl_isempty(p->wfd_subelements))
|
if (p->l != running_link || shl_isempty(p->wfd_subelements))
|
||||||
|
@ -414,6 +439,14 @@ void ctl_fn_peer_free(struct ctl_peer *p)
|
||||||
if (p->l != running_link || shl_isempty(p->wfd_subelements))
|
if (p->l != running_link || shl_isempty(p->wfd_subelements))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (p == pending_peer) {
|
||||||
|
cli_printf("no longer waiting for peer %s (%s)\n",
|
||||||
|
p->friendly_name, p->label);
|
||||||
|
pending_peer = NULL;
|
||||||
|
stop_timeout(&scan_timeout);
|
||||||
|
ctl_link_set_p2p_scanning(p->l, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (p == running_peer) {
|
if (p == running_peer) {
|
||||||
cli_printf("no longer running on peer %s\n",
|
cli_printf("no longer running on peer %s\n",
|
||||||
running_peer->label);
|
running_peer->label);
|
||||||
|
@ -440,10 +473,23 @@ void ctl_fn_peer_provision_discovery(struct ctl_peer *p,
|
||||||
if (cli_running())
|
if (cli_running())
|
||||||
cli_printf("[" CLI_YELLOW "PROV" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
|
cli_printf("[" CLI_YELLOW "PROV" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
|
||||||
p->label, prov, pin);
|
p->label, prov, pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctl_fn_peer_go_neg_request(struct ctl_peer *p,
|
||||||
|
const char *prov,
|
||||||
|
const char *pin)
|
||||||
|
{
|
||||||
|
if (p->l != running_link || shl_isempty(p->wfd_subelements))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cli_running())
|
||||||
|
cli_printf("[" CLI_YELLOW "GO NEG" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
|
||||||
|
p->label, prov, pin);
|
||||||
|
|
||||||
if (!running_peer) {
|
if (!running_peer) {
|
||||||
/* auto accept any incoming connection attempt */
|
/* auto accept any incoming connection attempt */
|
||||||
ctl_peer_connect(p, "auto", "");
|
ctl_peer_connect(p, "auto", "");
|
||||||
|
pending_peer = p;
|
||||||
|
|
||||||
/* 60s timeout in case the connect fails. Yes, stupid wpas does
|
/* 60s timeout in case the connect fails. Yes, stupid wpas does
|
||||||
* not catch this and notify us.. and as it turns out, DHCP
|
* not catch this and notify us.. and as it turns out, DHCP
|
||||||
|
@ -480,6 +526,8 @@ void ctl_fn_peer_connected(struct ctl_peer *p)
|
||||||
cli_printf("[" CLI_GREEN "CONNECT" CLI_DEFAULT "] Peer: %s\n",
|
cli_printf("[" CLI_GREEN "CONNECT" CLI_DEFAULT "] Peer: %s\n",
|
||||||
p->label);
|
p->label);
|
||||||
|
|
||||||
|
pending_peer = NULL;
|
||||||
|
|
||||||
if (!running_peer) {
|
if (!running_peer) {
|
||||||
running_peer = p;
|
running_peer = p;
|
||||||
cli_printf("now running on peer %s\n", running_peer->label);
|
cli_printf("now running on peer %s\n", running_peer->label);
|
||||||
|
@ -557,9 +605,15 @@ void cli_fn_help()
|
||||||
" --log-level <lvl> Maximum level for log messages\n"
|
" --log-level <lvl> Maximum level for log messages\n"
|
||||||
" --audio <0/1> Enable audio support (default %d)\n"
|
" --audio <0/1> Enable audio support (default %d)\n"
|
||||||
" --scale WxH Scale to resolution\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"
|
"\n"
|
||||||
"Commands:\n"
|
, program_invocation_short_name, gst_audio_en,
|
||||||
, 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:
|
* 80-char barrier:
|
||||||
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||||
|
@ -627,6 +681,7 @@ static int parse_argv(int argc, char *argv[])
|
||||||
ARG_LOG_LEVEL,
|
ARG_LOG_LEVEL,
|
||||||
ARG_AUDIO,
|
ARG_AUDIO,
|
||||||
ARG_SCALE,
|
ARG_SCALE,
|
||||||
|
ARG_RES,
|
||||||
};
|
};
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
@ -634,6 +689,7 @@ static int parse_argv(int argc, char *argv[])
|
||||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||||
{ "audio", required_argument, NULL, ARG_AUDIO },
|
{ "audio", required_argument, NULL, ARG_AUDIO },
|
||||||
{ "scale", required_argument, NULL, ARG_SCALE },
|
{ "scale", required_argument, NULL, ARG_SCALE },
|
||||||
|
{ "res", required_argument, NULL, ARG_RES },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
int c;
|
int c;
|
||||||
|
@ -654,6 +710,12 @@ static int parse_argv(int argc, char *argv[])
|
||||||
case ARG_SCALE:
|
case ARG_SCALE:
|
||||||
gst_scale_res = optarg;
|
gst_scale_res = optarg;
|
||||||
break;
|
break;
|
||||||
|
case ARG_RES:
|
||||||
|
sscanf(optarg, "%x,%x,%x",
|
||||||
|
&wfd_supported_res_cea,
|
||||||
|
&wfd_supported_res_vesa,
|
||||||
|
&wfd_supported_res_hh);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
220
src/ctl/wfd.c
Normal file
220
src/ctl/wfd.c
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/*
|
||||||
|
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Andrey Gusakov <andrey.gusakov@cogentembedded.com>
|
||||||
|
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ctl.h"
|
||||||
|
|
||||||
|
struct resolution_bitmap {
|
||||||
|
int index;
|
||||||
|
int hres;
|
||||||
|
int vres;
|
||||||
|
int fps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CEA resolutions and refrash rate bitmap/index table
|
||||||
|
* also used in native resolution field
|
||||||
|
*/
|
||||||
|
struct resolution_bitmap resolutions_cea[] = {
|
||||||
|
{0, 640, 480, 60}, /* p60 */
|
||||||
|
{1, 720, 480, 60}, /* p60 */
|
||||||
|
{2, 720, 480, 60}, /* i60 */
|
||||||
|
{3, 720, 576, 50}, /* p50 */
|
||||||
|
{4, 720, 576, 50}, /* i50 */
|
||||||
|
{5, 1280, 720, 30}, /* p30 */
|
||||||
|
{6, 1280, 720, 60}, /* p60 */
|
||||||
|
{7, 1920, 1080, 30}, /* p30 */
|
||||||
|
{8, 1920, 1080, 60}, /* p60 */
|
||||||
|
{9, 1920, 1080, 60}, /* i60 */
|
||||||
|
{10, 1280, 720, 25}, /* p25 */
|
||||||
|
{11, 1280, 720, 50}, /* p50 */
|
||||||
|
{12, 1920, 1080, 25}, /* p25 */
|
||||||
|
{13, 1920, 1080, 50}, /* p50 */
|
||||||
|
{14, 1920, 1080, 50}, /* i50 */
|
||||||
|
{15, 1280, 720, 24}, /* p24 */
|
||||||
|
{16, 1920, 1080, 24}, /* p24 */
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct resolution_bitmap resolutions_vesa[] = {
|
||||||
|
{0, 800, 600, 30}, /* p30 */
|
||||||
|
{1, 800, 600, 60}, /* p60 */
|
||||||
|
{2, 1024, 768, 30}, /* p30 */
|
||||||
|
{3, 1024, 768, 60}, /* p60 */
|
||||||
|
{4, 1152, 854, 30}, /* p30 */
|
||||||
|
{5, 1152, 854, 60}, /* p60 */
|
||||||
|
{6, 1280, 768, 30}, /* p30 */
|
||||||
|
{7, 1280, 768, 60}, /* p60 */
|
||||||
|
{8, 1280, 800, 30}, /* p30 */
|
||||||
|
{9, 1280, 800, 60}, /* p60 */
|
||||||
|
{10, 1360, 768, 30}, /* p30 */
|
||||||
|
{11, 1360, 768, 60}, /* p60 */
|
||||||
|
{12, 1366, 768, 30}, /* p30 */
|
||||||
|
{13, 1366, 768, 60}, /* p60 */
|
||||||
|
{14, 1280, 1024, 30}, /* p30 */
|
||||||
|
{15, 1280, 1024, 60}, /* p60 */
|
||||||
|
{16, 1440, 1050, 30}, /* p30 */
|
||||||
|
{17, 1440, 1050, 60}, /* p60 */
|
||||||
|
{18, 1440, 900, 30}, /* p30 */
|
||||||
|
{19, 1440, 900, 60}, /* p60 */
|
||||||
|
{20, 1600, 900, 30}, /* p30 */
|
||||||
|
{21, 1600, 900, 60}, /* p60 */
|
||||||
|
{22, 1600, 1200, 30}, /* p30 */
|
||||||
|
{23, 1600, 1200, 60}, /* p60 */
|
||||||
|
{24, 1680, 1024, 30}, /* p30 */
|
||||||
|
{25, 1680, 1024, 60}, /* p60 */
|
||||||
|
{26, 1680, 1050, 30}, /* p30 */
|
||||||
|
{27, 1680, 1050, 60}, /* p60 */
|
||||||
|
{28, 1920, 1200, 30}, /* p30 */
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct resolution_bitmap resolutions_hh[] = {
|
||||||
|
{0, 800, 480, 30}, /* p30 */
|
||||||
|
{1, 800, 480, 60}, /* p60 */
|
||||||
|
{2, 854, 480, 30}, /* p30 */
|
||||||
|
{3, 854, 480, 60}, /* p60 */
|
||||||
|
{4, 864, 480, 30}, /* p30 */
|
||||||
|
{5, 864, 480, 60}, /* p60 */
|
||||||
|
{6, 640, 360, 30}, /* p30 */
|
||||||
|
{7, 640, 360, 60}, /* p60 */
|
||||||
|
{8, 960, 540, 30}, /* p30 */
|
||||||
|
{9, 960, 540, 60}, /* p60 */
|
||||||
|
{10, 848, 480, 30}, /* p30 */
|
||||||
|
{11, 848, 480, 60}, /* p60 */
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
void wfd_print_resolutions(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("CEA resolutions:\n");
|
||||||
|
for (i = 0; resolutions_cea[i].hres != 0; i++) {
|
||||||
|
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("VESA resolutions:\n");
|
||||||
|
for (i = 0; resolutions_vesa[i].hres != 0; i++) {
|
||||||
|
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("HH resolutions:\n");
|
||||||
|
for (i = 0; resolutions_hh[i].hres != 0; i++) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vfd_generate_resolution_mask(unsigned int index)
|
||||||
|
{
|
||||||
|
return ((1 << (index + 1)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfd_dump_resolutions(uint32_t cea_mask, uint32_t vesa_mask, uint32_t hh_mask)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (cea_mask) {
|
||||||
|
cli_debug("CEA resolutions:");
|
||||||
|
for (i = 0; resolutions_cea[i].hres != 0; i++)
|
||||||
|
if ((1 << resolutions_cea[i].index) & cea_mask)
|
||||||
|
cli_debug("\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);
|
||||||
|
}
|
||||||
|
if (vesa_mask) {
|
||||||
|
cli_debug("VESA resolutions:");
|
||||||
|
for (i = 0; resolutions_vesa[i].hres != 0; i++)
|
||||||
|
if ((1 << resolutions_vesa[i].index) & vesa_mask)
|
||||||
|
cli_debug("\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);
|
||||||
|
}
|
||||||
|
if (hh_mask) {
|
||||||
|
cli_debug("HH resolutions:");
|
||||||
|
for (i = 0; resolutions_hh[i].hres != 0; i++)
|
||||||
|
if ((1 << resolutions_hh[i].index) & hh_mask)
|
||||||
|
cli_debug("\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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfd_get_cea_resolution(uint32_t mask, int *hres, int *vres)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!mask)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; resolutions_cea[i].hres != 0; i++) {
|
||||||
|
if ((1 << resolutions_cea[i].index) & mask) {
|
||||||
|
*vres = resolutions_cea[i].vres;
|
||||||
|
*hres = resolutions_cea[i].hres;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfd_get_vesa_resolution(uint32_t mask, int *hres, int *vres)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!mask)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; resolutions_vesa[i].hres != 0; i++) {
|
||||||
|
if ((1 << resolutions_vesa[i].index) & mask) {
|
||||||
|
*vres = resolutions_vesa[i].vres;
|
||||||
|
*hres = resolutions_vesa[i].hres;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfd_get_hh_resolution(uint32_t mask, int *hres, int *vres)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!mask)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; resolutions_hh[i].hres != 0; i++) {
|
||||||
|
if ((1 << resolutions_hh[i].index) & mask) {
|
||||||
|
*vres = resolutions_hh[i].vres;
|
||||||
|
*hres = resolutions_hh[i].hres;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
29
src/ctl/wfd.h
Normal file
29
src/ctl/wfd.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Andrey Gusakov <andrey.gusakov@cogentembedded.com>
|
||||||
|
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 WFD_H
|
||||||
|
#define WFD_H
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif /* WFD_H */
|
|
@ -363,7 +363,11 @@ void ctl_fn_peer_provision_discovery(struct ctl_peer *p,
|
||||||
cli_printf("[" CLI_YELLOW "PROV" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
|
cli_printf("[" CLI_YELLOW "PROV" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
|
||||||
p->label, prov, pin);
|
p->label, prov, pin);
|
||||||
}
|
}
|
||||||
|
void ctl_fn_peer_go_neg_request(struct ctl_peer *p,
|
||||||
|
const char *prov,
|
||||||
|
const char *pin)
|
||||||
|
{
|
||||||
|
}
|
||||||
void ctl_fn_peer_formation_failure(struct ctl_peer *p, const char *reason)
|
void ctl_fn_peer_formation_failure(struct ctl_peer *p, const char *reason)
|
||||||
{
|
{
|
||||||
if (cli_running())
|
if (cli_running())
|
||||||
|
|
|
@ -702,6 +702,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lease) {
|
||||||
|
/* check if requested address free */
|
||||||
|
lease = add_lease(dhcp_server, OFFER_TIME,
|
||||||
|
packet.chaddr, htonl(requested_nip));
|
||||||
|
}
|
||||||
|
|
||||||
if (lease && requested_nip == lease->lease_nip) {
|
if (lease && requested_nip == lease->lease_nip) {
|
||||||
debug(dhcp_server, "Sending ACK");
|
debug(dhcp_server, "Sending ACK");
|
||||||
send_ACK(dhcp_server, &packet,
|
send_ACK(dhcp_server, &packet,
|
||||||
|
|
|
@ -1549,6 +1549,18 @@ int rtsp_message_readv_basic(struct rtsp_message *m,
|
||||||
if (out_u32)
|
if (out_u32)
|
||||||
*out_u32 = u32;
|
*out_u32 = u32;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case RTSP_TYPE_HEX32:
|
||||||
|
if (sscanf(entry, "%" SCNx32, &u32) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
out_u32 = va_arg(*args, uint32_t*);
|
||||||
|
if (out_u32)
|
||||||
|
*out_u32 = u32;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case RTSP_TYPE_SKIP:
|
||||||
|
/* just increment token */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1588,8 +1600,13 @@ int rtsp_message_readv(struct rtsp_message *m,
|
||||||
|
|
||||||
for ( ; *types; ++types) {
|
for ( ; *types; ++types) {
|
||||||
r = rtsp_message_readv_basic(m, *types, args);
|
r = rtsp_message_readv_basic(m, *types, args);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
if (m->iter_body)
|
||||||
|
rtsp_message_exit_body(m);
|
||||||
|
if (m->iter_header)
|
||||||
|
rtsp_message_exit_header(m);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -45,6 +45,8 @@ enum {
|
||||||
#define RTSP_TYPE_STRING 's'
|
#define RTSP_TYPE_STRING 's'
|
||||||
#define RTSP_TYPE_INT32 'i'
|
#define RTSP_TYPE_INT32 'i'
|
||||||
#define RTSP_TYPE_UINT32 'u'
|
#define RTSP_TYPE_UINT32 'u'
|
||||||
|
#define RTSP_TYPE_HEX32 'h'
|
||||||
|
#define RTSP_TYPE_SKIP '*'
|
||||||
#define RTSP_TYPE_RAW '&'
|
#define RTSP_TYPE_RAW '&'
|
||||||
#define RTSP_TYPE_HEADER_START '<'
|
#define RTSP_TYPE_HEADER_START '<'
|
||||||
#define RTSP_TYPE_HEADER_END '>'
|
#define RTSP_TYPE_HEADER_END '>'
|
||||||
|
|
|
@ -308,6 +308,7 @@ static const sd_bus_vtable peer_dbus_vtable[] = {
|
||||||
0,
|
0,
|
||||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
|
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
|
||||||
|
SD_BUS_SIGNAL("GoNegRequest", "ss", 0),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -408,6 +409,31 @@ void peer_dbus_provision_discovery(struct peer *p,
|
||||||
log_vERR(r);
|
log_vERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void peer_dbus_go_neg_request(struct peer *p,
|
||||||
|
const char *type,
|
||||||
|
const char *pin)
|
||||||
|
{
|
||||||
|
_shl_free_ char *node = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!type)
|
||||||
|
return;
|
||||||
|
if (!pin)
|
||||||
|
pin = "";
|
||||||
|
|
||||||
|
node = peer_dbus_get_path(p);
|
||||||
|
if (!node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r = sd_bus_emit_signal(p->l->m->bus,
|
||||||
|
node,
|
||||||
|
"org.freedesktop.miracle.wifi.Peer",
|
||||||
|
"GoNegRequest",
|
||||||
|
"ss", type, pin);
|
||||||
|
if (r < 0)
|
||||||
|
log_vERR(r);
|
||||||
|
}
|
||||||
|
|
||||||
void peer_dbus_formation_failure(struct peer *p, const char *reason)
|
void peer_dbus_formation_failure(struct peer *p, const char *reason)
|
||||||
{
|
{
|
||||||
_shl_free_ char *node = NULL;
|
_shl_free_ char *node = NULL;
|
||||||
|
|
|
@ -200,6 +200,16 @@ void peer_supplicant_provision_discovery(struct peer *p,
|
||||||
peer_dbus_provision_discovery(p, prov, pin);
|
peer_dbus_provision_discovery(p, prov, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void peer_supplicant_go_neg_request(struct peer *p,
|
||||||
|
const char *prov,
|
||||||
|
const char *pin)
|
||||||
|
{
|
||||||
|
if (!p || !p->public)
|
||||||
|
return;
|
||||||
|
|
||||||
|
peer_dbus_go_neg_request(p, prov, pin);
|
||||||
|
}
|
||||||
|
|
||||||
void peer_supplicant_formation_failure(struct peer *p,
|
void peer_supplicant_formation_failure(struct peer *p,
|
||||||
const char *reason)
|
const char *reason)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,6 +94,17 @@ struct supplicant {
|
||||||
bool p2p_scanning : 1;
|
bool p2p_scanning : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Device Password ID */
|
||||||
|
enum wps_dev_password_id {
|
||||||
|
DEV_PW_DEFAULT = 0x0000,
|
||||||
|
DEV_PW_USER_SPECIFIED = 0x0001,
|
||||||
|
DEV_PW_MACHINE_SPECIFIED = 0x0002,
|
||||||
|
DEV_PW_REKEY = 0x0003,
|
||||||
|
DEV_PW_PUSHBUTTON = 0x0004,
|
||||||
|
DEV_PW_REGISTRAR_SPECIFIED = 0x0005,
|
||||||
|
DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007
|
||||||
|
};
|
||||||
|
|
||||||
static void supplicant_failed(struct supplicant *s);
|
static void supplicant_failed(struct supplicant *s);
|
||||||
static void supplicant_peer_drop_group(struct supplicant_peer *sp);
|
static void supplicant_peer_drop_group(struct supplicant_peer *sp);
|
||||||
|
|
||||||
|
@ -998,11 +1009,50 @@ static void supplicant_event_p2p_prov_disc_pbc_req(struct supplicant *s,
|
||||||
free(sp->pin);
|
free(sp->pin);
|
||||||
sp->pin = NULL;
|
sp->pin = NULL;
|
||||||
|
|
||||||
|
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void supplicant_event_p2p_go_neg_request(struct supplicant *s,
|
||||||
|
struct wpas_message *ev)
|
||||||
|
{
|
||||||
|
struct supplicant_peer *sp;
|
||||||
|
const char *mac;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
|
||||||
|
r = wpas_message_read(ev, "s", &mac);
|
||||||
|
if (r < 0) {
|
||||||
|
log_debug("no p2p-mac in P2P-GO-NEG-REQUEST information: %s",
|
||||||
|
wpas_message_get_raw(ev));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = find_peer_by_p2p_mac(s, mac);
|
||||||
|
if (!sp) {
|
||||||
|
log_debug("stale P2P-GO-NEG-REQUEST: %s",
|
||||||
|
wpas_message_get_raw(ev));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prov should be set by previous
|
||||||
|
* P2P-PROV-DISC-PBC-REQ
|
||||||
|
* P2P-PROV-DISC-SHOW-PIN
|
||||||
|
* or P2P-PROV-DISC-ENTER-PIN
|
||||||
|
* if not set pbc mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!sp->prov) {
|
||||||
|
sp->prov = strdup("pbc");
|
||||||
|
free(sp->pin);
|
||||||
|
sp->pin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sp->g) {
|
if (!sp->g) {
|
||||||
log_debug("PBC provision discovery for %s", mac);
|
log_debug("GO Negotiation Request from %s", mac);
|
||||||
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
peer_supplicant_go_neg_request(sp->p, sp->prov, sp->pin);
|
||||||
} else {
|
} else {
|
||||||
log_debug("PBC provision discovery for already connected peer %s",
|
log_debug("GO Negotiation Request from already connected peer %s",
|
||||||
mac);
|
mac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1051,13 +1101,7 @@ static void supplicant_event_p2p_prov_disc_show_pin(struct supplicant *s,
|
||||||
free(sp->pin);
|
free(sp->pin);
|
||||||
sp->pin = u;
|
sp->pin = u;
|
||||||
|
|
||||||
if (!sp->g) {
|
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
||||||
log_debug("DISPLAY provision discovery for %s", mac);
|
|
||||||
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
|
||||||
} else {
|
|
||||||
log_debug("DISPLAY provision discovery for already connected peer %s",
|
|
||||||
mac);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void supplicant_event_p2p_prov_disc_enter_pin(struct supplicant *s,
|
static void supplicant_event_p2p_prov_disc_enter_pin(struct supplicant *s,
|
||||||
|
@ -1091,13 +1135,7 @@ static void supplicant_event_p2p_prov_disc_enter_pin(struct supplicant *s,
|
||||||
free(sp->pin);
|
free(sp->pin);
|
||||||
sp->pin = NULL;
|
sp->pin = NULL;
|
||||||
|
|
||||||
if (!sp->g) {
|
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
||||||
log_debug("PIN provision discovery for %s", mac);
|
|
||||||
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
|
|
||||||
} else {
|
|
||||||
log_debug("PIN provision discovery for already connected peer %s",
|
|
||||||
mac);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void supplicant_event_p2p_go_neg_success(struct supplicant *s,
|
static void supplicant_event_p2p_go_neg_success(struct supplicant *s,
|
||||||
|
@ -1340,6 +1378,14 @@ static void supplicant_event_ap_sta_disconnected(struct supplicant *s,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sp->s->pending == sp) {
|
||||||
|
sp->s->pending = NULL;
|
||||||
|
if (sp->p->connected)
|
||||||
|
peer_supplicant_connected_changed(sp->p, false);
|
||||||
|
else
|
||||||
|
peer_supplicant_formation_failure(sp->p, "disconnected");
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("unbind peer %s from its group", p2p_mac);
|
log_debug("unbind peer %s from its group", p2p_mac);
|
||||||
supplicant_peer_drop_group(sp);
|
supplicant_peer_drop_group(sp);
|
||||||
}
|
}
|
||||||
|
@ -1394,6 +1440,8 @@ static void supplicant_event(struct supplicant *s, struct wpas_message *m)
|
||||||
supplicant_event_p2p_prov_disc_enter_pin(s, m);
|
supplicant_event_p2p_prov_disc_enter_pin(s, m);
|
||||||
else if (!strcmp(name, "P2P-GO-NEG-SUCCESS"))
|
else if (!strcmp(name, "P2P-GO-NEG-SUCCESS"))
|
||||||
supplicant_event_p2p_go_neg_success(s, m);
|
supplicant_event_p2p_go_neg_success(s, m);
|
||||||
|
else if (!strcmp(name, "P2P-GO-NEG-REQUEST"))
|
||||||
|
supplicant_event_p2p_go_neg_request(s, m);
|
||||||
else if (!strcmp(name, "P2P-GROUP-STARTED"))
|
else if (!strcmp(name, "P2P-GROUP-STARTED"))
|
||||||
supplicant_event_p2p_group_started(s, m);
|
supplicant_event_p2p_group_started(s, m);
|
||||||
else if (!strcmp(name, "P2P-GROUP-REMOVED"))
|
else if (!strcmp(name, "P2P-GROUP-REMOVED"))
|
||||||
|
@ -1621,7 +1669,7 @@ static int supplicant_status_fn(struct wpas *w,
|
||||||
|
|
||||||
r = wpas_message_append(m, "ss",
|
r = wpas_message_append(m, "ss",
|
||||||
"device_name",
|
"device_name",
|
||||||
s->l->friendly_name ? : "unknown");
|
s->l->friendly_name ? : "Miracle");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_vERR(r);
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wifid.h"
|
#include "wifid.h"
|
||||||
|
|
||||||
|
#define DO_NOT_RELY_UDEV 1
|
||||||
|
|
||||||
const char *arg_wpa_bindir = "/usr/bin";
|
const char *arg_wpa_bindir = "/usr/bin";
|
||||||
unsigned int arg_wpa_loglevel = LOG_NOTICE;
|
unsigned int arg_wpa_loglevel = LOG_NOTICE;
|
||||||
|
|
||||||
|
@ -97,9 +99,9 @@ static void manager_add_udev_link(struct manager *m,
|
||||||
|
|
||||||
link_set_friendly_name(l, m->friendly_name);
|
link_set_friendly_name(l, m->friendly_name);
|
||||||
|
|
||||||
#if 0
|
#if DO_NOT_RELY_UDEV
|
||||||
if (udev_device_has_tag(d, "miracle"))
|
if (udev_device_has_tag(d, "miracle"))
|
||||||
#endif
|
#endif
|
||||||
link_set_managed(l, true);
|
link_set_managed(l, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,10 +137,14 @@ static int manager_udev_fn(sd_event_source *source,
|
||||||
link_renamed(l, ifname);
|
link_renamed(l, ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DO_NOT_RELY_UDEV
|
||||||
|
link_set_managed(l, true);
|
||||||
|
#else
|
||||||
if (udev_device_has_tag(d, "miracle"))
|
if (udev_device_has_tag(d, "miracle"))
|
||||||
link_set_managed(l, true);
|
link_set_managed(l, true);
|
||||||
else
|
else
|
||||||
link_set_managed(l, false);
|
link_set_managed(l, false);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
manager_add_udev_link(m, d);
|
manager_add_udev_link(m, d);
|
||||||
}
|
}
|
||||||
|
@ -331,7 +337,7 @@ static void manager_read_name(struct manager *m)
|
||||||
|
|
||||||
r = sd_bus_message_read(rep, "s", &name);
|
r = sd_bus_message_read(rep, "s", &name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto error;
|
name = "undefined";
|
||||||
|
|
||||||
if (shl_isempty(name)) {
|
if (shl_isempty(name)) {
|
||||||
log_warning("no hostname set on systemd.hostname1, using: %s",
|
log_warning("no hostname set on systemd.hostname1, using: %s",
|
||||||
|
|
|
@ -101,6 +101,9 @@ void peer_supplicant_wfd_subelements_changed(struct peer *p);
|
||||||
void peer_supplicant_provision_discovery(struct peer *p,
|
void peer_supplicant_provision_discovery(struct peer *p,
|
||||||
const char *prov,
|
const char *prov,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
|
void peer_supplicant_go_neg_request(struct peer *p,
|
||||||
|
const char *prov,
|
||||||
|
const char *pin);
|
||||||
void peer_supplicant_formation_failure(struct peer *p, const char *reason);
|
void peer_supplicant_formation_failure(struct peer *p, const char *reason);
|
||||||
void peer_supplicant_connected_changed(struct peer *p, bool connected);
|
void peer_supplicant_connected_changed(struct peer *p, bool connected);
|
||||||
|
|
||||||
|
@ -109,6 +112,9 @@ void peer_dbus_properties_changed(struct peer *p, const char *prop, ...);
|
||||||
void peer_dbus_provision_discovery(struct peer *p,
|
void peer_dbus_provision_discovery(struct peer *p,
|
||||||
const char *prov,
|
const char *prov,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
|
void peer_dbus_go_neg_request(struct peer *p,
|
||||||
|
const char *type,
|
||||||
|
const char *pin);
|
||||||
void peer_dbus_formation_failure(struct peer *p, const char *reason);
|
void peer_dbus_formation_failure(struct peer *p, const char *reason);
|
||||||
void peer_dbus_added(struct peer *p);
|
void peer_dbus_added(struct peer *p);
|
||||||
void peer_dbus_removed(struct peer *p);
|
void peer_dbus_removed(struct peer *p);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue