1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-14 18:41:54 +00:00

Merge branch 'agusakov'

This commit is contained in:
albfan 2015-03-30 12:29:37 +02:00
commit 640f731d44
18 changed files with 562 additions and 44 deletions

View file

@ -4,12 +4,15 @@ DEBUG='0'
AUDIO='0'
SCALE='0'
while getopts "d:as:" optname
while getopts "r:d:as:" optname
do
case "$optname" in
"d")
DEBUG=`echo ${OPTARG} | tr -d ' '`
;;
"r")
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
;;
"a")
AUDIO='1'
;;

View file

@ -19,6 +19,7 @@ miracle_sinkctl_SOURCES = \
ctl-cli.c \
ctl-sink.c \
ctl-wifi.c \
wfd.c \
sinkctl.c
miracle_sinkctl_CPPFLAGS = \
$(AM_CPPFLAGS) \

View file

@ -97,11 +97,10 @@ int cli_help(const struct cli_cmd *cmds)
{
unsigned int i;
if (is_cli()) {
cli_printf("Available commands:\n");
} else {
if (!is_cli()) {
cli_fn_help();
}
cli_printf("Available commands:\n");
for (i = 0; cmds[i].cmd; ++i) {
if (!cmds[i].desc)

View file

@ -35,6 +35,7 @@
#include "rtsp.h"
#include "shl_macro.h"
#include "shl_util.h"
#include "wfd.h"
struct ctl_sink {
sd_event *event;
@ -51,6 +52,13 @@ struct ctl_sink {
bool connected : 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)
return cli_vERR(r);
r = rtsp_message_append(rep, "{&&&&}",
"wfd_content_protection: none",
"wfd_video_formats: 00 00 01 01 0000007f 003fffff 00000000 00 0000 0000 00 none none",
"wfd_audio_codecs: AAC 00000007 00",
"wfd_client_rtp_ports: RTP/AVP/UDP;unicast 1991 0 mode=play");
if (r < 0)
return cli_vERR(r);
/* 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);
}
rtsp_message_seal(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;
}
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,
struct rtsp_message *m)
{
@ -189,6 +242,7 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
const char *trigger;
const char *url;
char *nu;
unsigned int cea_res, vesa_res, hh_res;
int r;
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);
rtsp_message_exit_body(m);
/* M4 again */
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 */
r = rtsp_message_read(m, "{<s>}", "wfd_trigger_method", &trigger);
if (r < 0) {
rtsp_message_exit_header(m);
rtsp_message_exit_body(m);
if (r < 0)
return;
}
if (!strcmp(trigger, "SETUP")) {
if (!s->url) {
@ -453,6 +510,9 @@ int ctl_sink_new(struct ctl_sink **out,
s->event = sd_event_ref(event);
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;
return 0;

View file

@ -975,6 +975,17 @@ static int ctl_wifi_peer_fn(sd_bus *bus,
return cli_log_parser(r);
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,
"org.freedesktop.miracle.wifi.Peer",
"FormationFailure")) {

View file

@ -236,6 +236,10 @@ struct cli_cmd {
extern sd_event *cli_event;
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);
void cli_destroy(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,
const char *prov,
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_connected(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_disconnected(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

@ -34,6 +34,7 @@
#include <time.h>
#include <unistd.h>
#include "ctl.h"
#include "wfd.h"
#include "shl_macro.h"
#include "shl_util.h"
@ -49,9 +50,13 @@ static pid_t sink_pid;
static char *bound_link;
static struct ctl_link *running_link;
static struct ctl_peer *running_peer;
static struct ctl_peer *pending_peer;
char *gst_scale_res;
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
@ -280,6 +285,14 @@ static int scan_timeout_fn(sd_event_source *s, uint64_t usec, void *data)
{
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)
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 resolution[64];
pid_t pid;
int fd_journal, i;
sigset_t mask;
@ -363,6 +377,11 @@ static void spawn_gst(void)
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);
@ -385,7 +404,6 @@ void ctl_fn_sink_connected(struct ctl_sink *s)
{
cli_notice("SINK connected");
sink_connected = true;
spawn_gst();
}
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)
{
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))
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) {
cli_printf("no longer running on peer %s\n",
running_peer->label);
@ -440,10 +473,23 @@ void ctl_fn_peer_provision_discovery(struct ctl_peer *p,
if (cli_running())
cli_printf("[" CLI_YELLOW "PROV" CLI_DEFAULT "] Peer: %s Type: %s PIN: %s\n",
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) {
/* auto accept any incoming connection attempt */
ctl_peer_connect(p, "auto", "");
pending_peer = p;
/* 60s timeout in case the connect fails. Yes, stupid wpas does
* 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",
p->label);
pending_peer = NULL;
if (!running_peer) {
running_peer = p;
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"
" --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"
"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:
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
@ -627,6 +681,7 @@ static int parse_argv(int argc, char *argv[])
ARG_LOG_LEVEL,
ARG_AUDIO,
ARG_SCALE,
ARG_RES,
};
static const struct option options[] = {
{ "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 },
{ "audio", required_argument, NULL, ARG_AUDIO },
{ "scale", required_argument, NULL, ARG_SCALE },
{ "res", required_argument, NULL, ARG_RES },
{}
};
int c;
@ -654,6 +710,12 @@ static int parse_argv(int argc, char *argv[])
case ARG_SCALE:
gst_scale_res = optarg;
break;
case ARG_RES:
sscanf(optarg, "%x,%x,%x",
&wfd_supported_res_cea,
&wfd_supported_res_vesa,
&wfd_supported_res_hh);
break;
case '?':
return -EINVAL;
}

220
src/ctl/wfd.c Normal file
View 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
View 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 */

View file

@ -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",
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)
{
if (cli_running())

View file

@ -702,6 +702,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
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) {
debug(dhcp_server, "Sending ACK");
send_ACK(dhcp_server, &packet,

View file

@ -1549,6 +1549,18 @@ int rtsp_message_readv_basic(struct rtsp_message *m,
if (out_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;
default:
return -EINVAL;
@ -1588,8 +1600,13 @@ int rtsp_message_readv(struct rtsp_message *m,
for ( ; *types; ++types) {
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 0;

View file

@ -45,6 +45,8 @@ enum {
#define RTSP_TYPE_STRING 's'
#define RTSP_TYPE_INT32 'i'
#define RTSP_TYPE_UINT32 'u'
#define RTSP_TYPE_HEX32 'h'
#define RTSP_TYPE_SKIP '*'
#define RTSP_TYPE_RAW '&'
#define RTSP_TYPE_HEADER_START '<'
#define RTSP_TYPE_HEADER_END '>'

View file

@ -308,6 +308,7 @@ static const sd_bus_vtable peer_dbus_vtable[] = {
0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_SIGNAL("ProvisionDiscovery", "ss", 0),
SD_BUS_SIGNAL("GoNegRequest", "ss", 0),
SD_BUS_VTABLE_END
};
@ -408,6 +409,31 @@ void peer_dbus_provision_discovery(struct peer *p,
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)
{
_shl_free_ char *node = NULL;

View file

@ -200,6 +200,16 @@ void peer_supplicant_provision_discovery(struct peer *p,
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,
const char *reason)
{

View file

@ -94,6 +94,17 @@ struct supplicant {
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_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);
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) {
log_debug("PBC provision discovery for %s", mac);
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
log_debug("GO Negotiation Request from %s", mac);
peer_supplicant_go_neg_request(sp->p, sp->prov, sp->pin);
} else {
log_debug("PBC provision discovery for already connected peer %s",
log_debug("GO Negotiation Request from already connected peer %s",
mac);
}
}
@ -1051,13 +1101,7 @@ static void supplicant_event_p2p_prov_disc_show_pin(struct supplicant *s,
free(sp->pin);
sp->pin = u;
if (!sp->g) {
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);
}
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
}
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);
sp->pin = NULL;
if (!sp->g) {
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);
}
peer_supplicant_provision_discovery(sp->p, sp->prov, sp->pin);
}
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;
}
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);
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);
else if (!strcmp(name, "P2P-GO-NEG-SUCCESS"))
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"))
supplicant_event_p2p_group_started(s, m);
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",
"device_name",
s->l->friendly_name ? : "unknown");
s->l->friendly_name ? : "Miracle");
if (r < 0) {
log_vERR(r);
goto error;

View file

@ -39,6 +39,8 @@
#include "util.h"
#include "wifid.h"
#define DO_NOT_RELY_UDEV 1
const char *arg_wpa_bindir = "/usr/bin";
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);
#if 0
#if DO_NOT_RELY_UDEV
if (udev_device_has_tag(d, "miracle"))
#endif
#endif
link_set_managed(l, true);
}
@ -135,10 +137,14 @@ static int manager_udev_fn(sd_event_source *source,
link_renamed(l, ifname);
}
#if DO_NOT_RELY_UDEV
link_set_managed(l, true);
#else
if (udev_device_has_tag(d, "miracle"))
link_set_managed(l, true);
else
link_set_managed(l, false);
#endif
} else {
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);
if (r < 0)
goto error;
name = "undefined";
if (shl_isempty(name)) {
log_warning("no hostname set on systemd.hostname1, using: %s",

View file

@ -101,6 +101,9 @@ void peer_supplicant_wfd_subelements_changed(struct peer *p);
void peer_supplicant_provision_discovery(struct peer *p,
const char *prov,
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_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,
const char *prov,
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_added(struct peer *p);
void peer_dbus_removed(struct peer *p);