mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
avb: avbtp -> avb
This commit is contained in:
parent
d5b4c12684
commit
773bd610aa
39 changed files with 1975 additions and 2108 deletions
|
|
@ -35,7 +35,7 @@ context.modules = [
|
||||||
}
|
}
|
||||||
{ name = libpipewire-module-client-device }
|
{ name = libpipewire-module-client-device }
|
||||||
{ name = libpipewire-module-adapter }
|
{ name = libpipewire-module-adapter }
|
||||||
{ name = libpipewire-module-avbtp
|
{ name = libpipewire-module-avb
|
||||||
args = {
|
args = {
|
||||||
# contents of avb.properties can also be placed here
|
# contents of avb.properties can also be placed here
|
||||||
# to have config per server.
|
# to have config per server.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ subdir('spa')
|
||||||
module_sources = [
|
module_sources = [
|
||||||
'module-access.c',
|
'module-access.c',
|
||||||
'module-adapter.c',
|
'module-adapter.c',
|
||||||
'module-avbtp.c',
|
'module-avb.c',
|
||||||
'module-client-device.c',
|
'module-client-device.c',
|
||||||
'module-client-node.c',
|
'module-client-node.c',
|
||||||
'module-echo-cancel.c',
|
'module-echo-cancel.c',
|
||||||
|
|
@ -518,22 +518,22 @@ pipewire_module_fallback_sink = shared_library('pipewire-module-fallback-sink',
|
||||||
dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep],
|
dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep],
|
||||||
)
|
)
|
||||||
|
|
||||||
build_module_avbtp = get_option('avb').allowed()
|
build_module_avb = get_option('avb').allowed()
|
||||||
if build_module_avbtp
|
if build_module_avb
|
||||||
pipewire_module_avbtp = shared_library('pipewire-module-avbtp',
|
pipewire_module_avb = shared_library('pipewire-module-avb',
|
||||||
[ 'module-avbtp.c',
|
[ 'module-avb.c',
|
||||||
'module-avbtp/avb.c',
|
'module-avb/avb.c',
|
||||||
'module-avbtp/adp.c',
|
'module-avb/adp.c',
|
||||||
'module-avbtp/acmp.c',
|
'module-avb/acmp.c',
|
||||||
'module-avbtp/aecp.c',
|
'module-avb/aecp.c',
|
||||||
'module-avbtp/aecp-aem.c',
|
'module-avb/aecp-aem.c',
|
||||||
'module-avbtp/avdecc.c',
|
'module-avb/avdecc.c',
|
||||||
'module-avbtp/maap.c',
|
'module-avb/maap.c',
|
||||||
'module-avbtp/mmrp.c',
|
'module-avb/mmrp.c',
|
||||||
'module-avbtp/mrp.c',
|
'module-avb/mrp.c',
|
||||||
'module-avbtp/msrp.c',
|
'module-avb/msrp.c',
|
||||||
'module-avbtp/mvrp.c',
|
'module-avb/mvrp.c',
|
||||||
'module-avbtp/srp.c'
|
'module-avb/srp.c'
|
||||||
],
|
],
|
||||||
include_directories : [configinc],
|
include_directories : [configinc],
|
||||||
install : true,
|
install : true,
|
||||||
|
|
@ -542,4 +542,4 @@ pipewire_module_avbtp = shared_library('pipewire-module-avbtp',
|
||||||
dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep],
|
dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep],
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
summary({'avbtp': build_module_avbtp}, bool_yn: true, section: 'Optional Modules')
|
summary({'avb': build_module_avb}, bool_yn: true, section: 'Optional Modules')
|
||||||
|
|
|
||||||
140
src/modules/module-avb/aaf.h
Normal file
140
src/modules/module-avb/aaf.h
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_AAF_H
|
||||||
|
#define AVB_AAF_H
|
||||||
|
|
||||||
|
struct avb_packet_aaf {
|
||||||
|
struct avb_ethernet_header hdr;
|
||||||
|
uint8_t subtype;
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
unsigned sv:1;
|
||||||
|
unsigned version:3;
|
||||||
|
unsigned mr:1;
|
||||||
|
unsigned _r1:1;
|
||||||
|
unsigned gv:1;
|
||||||
|
unsigned tv:1;
|
||||||
|
|
||||||
|
uint8_t seq_number;
|
||||||
|
|
||||||
|
unsigned _r2:7;
|
||||||
|
unsigned tu:1;
|
||||||
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
unsigned tv:1;
|
||||||
|
unsigned gv:1;
|
||||||
|
unsigned _r1:1;
|
||||||
|
unsigned mr:1;
|
||||||
|
unsigned version:3;
|
||||||
|
unsigned sv:1;
|
||||||
|
|
||||||
|
uint8_t seq_num;
|
||||||
|
|
||||||
|
unsigned tu:1;
|
||||||
|
unsigned _r2:7;
|
||||||
|
#endif
|
||||||
|
uint64_t stream_id;
|
||||||
|
uint32_t timestamp;
|
||||||
|
#define AVB_AAF_FORMAT_USER 0x00
|
||||||
|
#define AVB_AAF_FORMAT_FLOAT_32BIT 0x01
|
||||||
|
#define AVB_AAF_FORMAT_INT_32BIT 0x02
|
||||||
|
#define AVB_AAF_FORMAT_INT_24BIT 0x03
|
||||||
|
#define AVB_AAF_FORMAT_INT_16BIT 0x04
|
||||||
|
#define AVB_AAF_FORMAT_AES3_32BIT 0x05
|
||||||
|
uint8_t format;
|
||||||
|
|
||||||
|
#define AVB_AAF_PCM_NSR_USER 0x00
|
||||||
|
#define AVB_AAF_PCM_NSR_8KHZ 0x01
|
||||||
|
#define AVB_AAF_PCM_NSR_16KHZ 0x02
|
||||||
|
#define AVB_AAF_PCM_NSR_32KHZ 0x03
|
||||||
|
#define AVB_AAF_PCM_NSR_44_1KHZ 0x04
|
||||||
|
#define AVB_AAF_PCM_NSR_48KHZ 0x05
|
||||||
|
#define AVB_AAF_PCM_NSR_88_2KHZ 0x06
|
||||||
|
#define AVB_AAF_PCM_NSR_96KHZ 0x07
|
||||||
|
#define AVB_AAF_PCM_NSR_176_4KHZ 0x08
|
||||||
|
#define AVB_AAF_PCM_NSR_192KHZ 0x09
|
||||||
|
#define AVB_AAF_PCM_NSR_24KHZ 0x0A
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
unsigned nsr:4;
|
||||||
|
unsigned _r3:4;
|
||||||
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
unsigned _r3:4;
|
||||||
|
unsigned nsr:4;
|
||||||
|
#endif
|
||||||
|
uint8_t chan_per_frame;
|
||||||
|
uint8_t bit_depth;
|
||||||
|
uint16_t data_len;
|
||||||
|
|
||||||
|
#define AVB_AAF_PCM_SP_NORMAL 0x00
|
||||||
|
#define AVB_AAF_PCM_SP_SPARSE 0x01
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
unsigned _r4:3;
|
||||||
|
unsigned sp:1;
|
||||||
|
unsigned event:4;
|
||||||
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
unsigned event:4;
|
||||||
|
unsigned sp:1;
|
||||||
|
unsigned _r4:3;
|
||||||
|
#endif
|
||||||
|
uint8_t _r5;
|
||||||
|
uint8_t payload[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_PACKET_AAF_SET_SUBTYPE(p,v) ((p)->subtype = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_SV(p,v) ((p)->sv = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_VERSION(p,v) ((p)->version = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_MR(p,v) ((p)->mr = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_GV(p,v) ((p)->gv = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_TV(p,v) ((p)->tv = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_SEQ_NUM(p,v) ((p)->seq_num = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_TU(p,v) ((p)->tu = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_STREAM_ID(p,v) ((p)->stream_id = htobe64(v))
|
||||||
|
#define AVB_PACKET_AAF_SET_TIMESTAMP(p,v) ((p)->timestamp = htonl(v))
|
||||||
|
#define AVB_PACKET_AAF_SET_DATA_LEN(p,v) ((p)->data_len = htons(v))
|
||||||
|
#define AVB_PACKET_AAF_SET_FORMAT(p,v) ((p)->format = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_NSR(p,v) ((p)->nsr = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_CHAN_PER_FRAME(p,v) ((p)->chan_per_frame = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_BIT_DEPTH(p,v) ((p)->bit_depth = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_SP(p,v) ((p)->sp = (v))
|
||||||
|
#define AVB_PACKET_AAF_SET_EVENT(p,v) ((p)->event = (v))
|
||||||
|
|
||||||
|
#define AVB_PACKET_AAF_GET_SUBTYPE(p) ((p)->subtype)
|
||||||
|
#define AVB_PACKET_AAF_GET_SV(p) ((p)->sv)
|
||||||
|
#define AVB_PACKET_AAF_GET_VERSION(p) ((p)->version)
|
||||||
|
#define AVB_PACKET_AAF_GET_MR(p) ((p)->mr)
|
||||||
|
#define AVB_PACKET_AAF_GET_GV(p) ((p)->gv)
|
||||||
|
#define AVB_PACKET_AAF_GET_TV(p) ((p)->tv)
|
||||||
|
#define AVB_PACKET_AAF_GET_SEQ_NUM(p) ((p)->seq_num)
|
||||||
|
#define AVB_PACKET_AAF_GET_TU(p) ((p)->tu)
|
||||||
|
#define AVB_PACKET_AAF_GET_STREAM_ID(p) be64toh((p)->stream_id)
|
||||||
|
#define AVB_PACKET_AAF_GET_TIMESTAMP(p) ntohl((p)->timestamp)
|
||||||
|
#define AVB_PACKET_AAF_GET_DATA_LEN(p) ntohs((p)->data_len)
|
||||||
|
#define AVB_PACKET_AAF_GET_FORMAT(p) ((p)->format)
|
||||||
|
#define AVB_PACKET_AAF_GET_NSR(p) ((p)->nsr)
|
||||||
|
#define AVB_PACKET_AAF_GET_CHAN_PER_FRAME(p) ((p)->chan_per_frame)
|
||||||
|
#define AVB_PACKET_AAF_GET_BIT_DEPTH(p) ((p)->bit_depth)
|
||||||
|
#define AVB_PACKET_AAF_GET_SP(p) ((p)->sp)
|
||||||
|
#define AVB_PACKET_AAF_GET_EVENT(p) ((p)->event)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* AVB_AAF_H */
|
||||||
|
|
@ -54,15 +54,15 @@ struct acmp {
|
||||||
struct spa_list pending[3];
|
struct spa_list pending[3];
|
||||||
uint16_t sequence_id[3];
|
uint16_t sequence_id[3];
|
||||||
|
|
||||||
struct avbtp_msrp_attribute *listener_attr;
|
struct avb_msrp_attribute *listener_attr;
|
||||||
struct avbtp_msrp_attribute *talker_attr;
|
struct avb_msrp_attribute *talker_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms,
|
static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms,
|
||||||
const struct avbtp_packet_acmp *m, size_t size)
|
const struct avb_packet_acmp *m, size_t size)
|
||||||
{
|
{
|
||||||
struct pending *p;
|
struct pending *p;
|
||||||
struct avbtp_packet_acmp *pm;
|
struct avb_packet_acmp *pm;
|
||||||
p = calloc(1, sizeof(*p) + size);
|
p = calloc(1, sizeof(*p) + size);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -105,22 +105,22 @@ static int reply_not_supported(struct acmp *acmp, const void *m, int len)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
uint8_t buf[len];
|
uint8_t buf[len];
|
||||||
struct avbtp_packet_acmp *reply = (struct avbtp_packet_acmp*)buf;
|
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||||
|
|
||||||
memcpy(reply, m, len);
|
memcpy(reply, m, len);
|
||||||
AVBTP_PACKET_ACMP_SET_STATUS(reply, AVBTP_ACMP_STATUS_NOT_SUPPORTED);
|
AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_NOT_SUPPORTED);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->hdr.eth.src,
|
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||||
AVB_TSN_ETH, reply, len);
|
AVB_TSN_ETH, reply, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p)
|
static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
struct avbtp_packet_acmp *cmd = p->ptr;
|
struct avb_packet_acmp *cmd = p->ptr;
|
||||||
p->retry++;
|
p->retry++;
|
||||||
p->last_time = now;
|
p->last_time = now;
|
||||||
return avbtp_server_send_packet(server, cmd->hdr.eth.dest,
|
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, cmd, p->size);
|
AVB_TSN_ETH, cmd, p->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,25 +128,25 @@ static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
uint8_t buf[len];
|
uint8_t buf[len];
|
||||||
const struct avbtp_packet_acmp *p = m;
|
const struct avb_packet_acmp *p = m;
|
||||||
struct avbtp_packet_acmp *reply = (struct avbtp_packet_acmp*)buf;
|
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||||
|
|
||||||
if (be64toh(p->talker_guid) != server->entity_id)
|
if (be64toh(p->talker_guid) != server->entity_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memcpy(reply, m, len);
|
memcpy(reply, m, len);
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE);
|
||||||
AVBTP_PACKET_ACMP_SET_STATUS(reply, AVBTP_ACMP_STATUS_SUCCESS);
|
AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_SUCCESS);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
return avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, reply, len);
|
AVB_TSN_ETH, reply, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
const struct avbtp_packet_acmp *resp = m;
|
const struct avb_packet_acmp *resp = m;
|
||||||
struct avbtp_packet_acmp *reply;
|
struct avb_packet_acmp *reply;
|
||||||
struct pending *pending;
|
struct pending *pending;
|
||||||
uint16_t sequence_id;
|
uint16_t sequence_id;
|
||||||
int res;
|
int res;
|
||||||
|
|
@ -163,17 +163,17 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
|
||||||
reply = pending->ptr;
|
reply = pending->ptr;
|
||||||
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
||||||
reply->sequence_id = htons(pending->old_sequence_id);
|
reply->sequence_id = htons(pending->old_sequence_id);
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE);
|
||||||
|
|
||||||
acmp->listener_attr->attr.listener.stream_id = reply->stream_id;
|
acmp->listener_attr->attr.listener.stream_id = reply->stream_id;
|
||||||
acmp->listener_attr->param = AVBTP_MSRP_LISTENER_PARAM_READY;
|
acmp->listener_attr->param = AVB_MSRP_LISTENER_PARAM_READY;
|
||||||
avbtp_mrp_mad_begin(server->mrp, now, acmp->listener_attr->mrp);
|
avb_mrp_mad_begin(server->mrp, now, acmp->listener_attr->mrp);
|
||||||
avbtp_mrp_mad_join(server->mrp, now, acmp->listener_attr->mrp, true);
|
avb_mrp_mad_join(server->mrp, now, acmp->listener_attr->mrp, true);
|
||||||
|
|
||||||
acmp->talker_attr->attr.talker.stream_id = reply->stream_id;
|
acmp->talker_attr->attr.talker.stream_id = reply->stream_id;
|
||||||
avbtp_mrp_mad_begin(server->mrp, now, acmp->talker_attr->mrp);
|
avb_mrp_mad_begin(server->mrp, now, acmp->talker_attr->mrp);
|
||||||
|
|
||||||
res = avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
res = avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, reply, pending->size);
|
AVB_TSN_ETH, reply, pending->size);
|
||||||
|
|
||||||
pending_free(acmp, pending);
|
pending_free(acmp, pending);
|
||||||
|
|
@ -185,25 +185,25 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
uint8_t buf[len];
|
uint8_t buf[len];
|
||||||
const struct avbtp_packet_acmp *p = m;
|
const struct avb_packet_acmp *p = m;
|
||||||
struct avbtp_packet_acmp *reply = (struct avbtp_packet_acmp*)buf;
|
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||||
|
|
||||||
if (be64toh(p->talker_guid) != server->entity_id)
|
if (be64toh(p->talker_guid) != server->entity_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memcpy(reply, m, len);
|
memcpy(reply, m, len);
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE);
|
||||||
AVBTP_PACKET_ACMP_SET_STATUS(reply, AVBTP_ACMP_STATUS_SUCCESS);
|
AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_SUCCESS);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
return avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, reply, len);
|
AVB_TSN_ETH, reply, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
const struct avbtp_packet_acmp *resp = m;
|
const struct avb_packet_acmp *resp = m;
|
||||||
struct avbtp_packet_acmp *reply;
|
struct avb_packet_acmp *reply;
|
||||||
struct pending *pending;
|
struct pending *pending;
|
||||||
uint16_t sequence_id;
|
uint16_t sequence_id;
|
||||||
int res;
|
int res;
|
||||||
|
|
@ -220,11 +220,11 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
||||||
reply = pending->ptr;
|
reply = pending->ptr;
|
||||||
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
||||||
reply->sequence_id = htons(pending->old_sequence_id);
|
reply->sequence_id = htons(pending->old_sequence_id);
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
|
||||||
|
|
||||||
avbtp_mrp_mad_leave(server->mrp, now, acmp->listener_attr->mrp);
|
avb_mrp_mad_leave(server->mrp, now, acmp->listener_attr->mrp);
|
||||||
|
|
||||||
res = avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
res = avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, reply, pending->size);
|
AVB_TSN_ETH, reply, pending->size);
|
||||||
|
|
||||||
pending_free(acmp, pending);
|
pending_free(acmp, pending);
|
||||||
|
|
@ -235,21 +235,21 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
||||||
static int handle_connect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
static int handle_connect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
const struct avbtp_packet_acmp *p = m;
|
const struct avb_packet_acmp *p = m;
|
||||||
struct avbtp_packet_acmp *cmd;
|
struct avb_packet_acmp *cmd;
|
||||||
|
|
||||||
if (be64toh(p->listener_guid) != server->entity_id)
|
if (be64toh(p->listener_guid) != server->entity_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cmd = pending_new(acmp, PENDING_TALKER, now,
|
cmd = pending_new(acmp, PENDING_TALKER, now,
|
||||||
AVBTP_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS, m, len);
|
AVB_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS, m, len);
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND);
|
||||||
AVBTP_PACKET_ACMP_SET_STATUS(cmd, AVBTP_ACMP_STATUS_SUCCESS);
|
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, cmd->hdr.eth.dest,
|
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, cmd, len);
|
AVB_TSN_ETH, cmd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,21 +261,21 @@ static int handle_connect_rx_response(struct acmp *acmp, uint64_t now, const voi
|
||||||
static int handle_disconnect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
static int handle_disconnect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||||
{
|
{
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
const struct avbtp_packet_acmp *p = m;
|
const struct avb_packet_acmp *p = m;
|
||||||
struct avbtp_packet_acmp *cmd;
|
struct avb_packet_acmp *cmd;
|
||||||
|
|
||||||
if (be64toh(p->listener_guid) != server->entity_id)
|
if (be64toh(p->listener_guid) != server->entity_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cmd = pending_new(acmp, PENDING_TALKER, now,
|
cmd = pending_new(acmp, PENDING_TALKER, now,
|
||||||
AVBTP_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS, m, len);
|
AVB_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS, m, len);
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND);
|
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND);
|
||||||
AVBTP_PACKET_ACMP_SET_STATUS(cmd, AVBTP_ACMP_STATUS_SUCCESS);
|
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, cmd->hdr.eth.dest,
|
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||||
AVB_TSN_ETH, cmd, len);
|
AVB_TSN_ETH, cmd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,20 +285,20 @@ static int handle_disconnect_rx_response(struct acmp *acmp, uint64_t now, const
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct msg_info msg_info[] = {
|
static const struct msg_info msg_info[] = {
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND, "connect-tx-command", handle_connect_tx_command, },
|
{ AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND, "connect-tx-command", handle_connect_tx_command, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE, "connect-tx-response", handle_connect_tx_response, },
|
{ AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE, "connect-tx-response", handle_connect_tx_response, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND, "disconnect-tx-command", handle_disconnect_tx_command, },
|
{ AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND, "disconnect-tx-command", handle_disconnect_tx_command, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE, "disconnect-tx-response", handle_disconnect_tx_response, },
|
{ AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE, "disconnect-tx-response", handle_disconnect_tx_response, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, "get-tx-state-command", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, "get-tx-state-command", NULL, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE, "get-tx-state-response", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE, "get-tx-state-response", NULL, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND, "connect-rx-command", handle_connect_rx_command, },
|
{ AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND, "connect-rx-command", handle_connect_rx_command, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE, "connect-rx-response", handle_connect_rx_response, },
|
{ AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE, "connect-rx-response", handle_connect_rx_response, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND, "disconnect-rx-command", handle_disconnect_rx_command, },
|
{ AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND, "disconnect-rx-command", handle_disconnect_rx_command, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE, "disconnect-rx-response", handle_disconnect_rx_response, },
|
{ AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE, "disconnect-rx-response", handle_disconnect_rx_response, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND, "get-rx-state-command", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND, "get-rx-state-command", NULL, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE, "get-rx-state-response", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE, "get-rx-state-response", NULL, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND, "get-tx-connection-command", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND, "get-tx-connection-command", NULL, },
|
||||||
{ AVBTP_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE, "get-tx-connection-response", NULL, },
|
{ AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE, "get-tx-connection-response", NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
|
static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
|
||||||
|
|
@ -316,7 +316,7 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct acmp *acmp = data;
|
struct acmp *acmp = data;
|
||||||
struct server *server = acmp->server;
|
struct server *server = acmp->server;
|
||||||
const struct avbtp_packet_acmp *p = message;
|
const struct avb_packet_acmp *p = message;
|
||||||
const struct msg_info *info;
|
const struct msg_info *info;
|
||||||
int message_type;
|
int message_type;
|
||||||
|
|
||||||
|
|
@ -326,10 +326,10 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (AVBTP_PACKET_GET_SUBTYPE(&p->hdr) != AVBTP_SUBTYPE_ACMP)
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
message_type = AVBTP_PACKET_ACMP_GET_MESSAGE_TYPE(p);
|
message_type = AVB_PACKET_ACMP_GET_MESSAGE_TYPE(p);
|
||||||
|
|
||||||
info = find_msg_info(message_type, NULL);
|
info = find_msg_info(message_type, NULL);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
|
|
@ -403,14 +403,14 @@ static int acmp_command(void *data, uint64_t now, const char *command, const cha
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = acmp_destroy,
|
.destroy = acmp_destroy,
|
||||||
.message = acmp_message,
|
.message = acmp_message,
|
||||||
.periodic = acmp_periodic,
|
.periodic = acmp_periodic,
|
||||||
.command = acmp_command
|
.command = acmp_command
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_acmp *avbtp_acmp_register(struct server *server)
|
struct avb_acmp *avb_acmp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct acmp *acmp;
|
struct acmp *acmp;
|
||||||
|
|
||||||
|
|
@ -423,17 +423,17 @@ struct avbtp_acmp *avbtp_acmp_register(struct server *server)
|
||||||
spa_list_init(&acmp->pending[PENDING_LISTENER]);
|
spa_list_init(&acmp->pending[PENDING_LISTENER]);
|
||||||
spa_list_init(&acmp->pending[PENDING_CONTROLLER]);
|
spa_list_init(&acmp->pending[PENDING_CONTROLLER]);
|
||||||
|
|
||||||
acmp->listener_attr = avbtp_msrp_attribute_new(server->msrp,
|
acmp->listener_attr = avb_msrp_attribute_new(server->msrp,
|
||||||
AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
AVB_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
||||||
acmp->talker_attr = avbtp_msrp_attribute_new(server->msrp,
|
acmp->talker_attr = avb_msrp_attribute_new(server->msrp,
|
||||||
AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE);
|
AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE);
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &acmp->server_listener, &server_events, acmp);
|
avdecc_server_add_listener(server, &acmp->server_listener, &server_events, acmp);
|
||||||
|
|
||||||
return (struct avbtp_acmp*)acmp;
|
return (struct avb_acmp*)acmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_acmp_unregister(struct avbtp_acmp *acmp)
|
void avb_acmp_unregister(struct avb_acmp *acmp)
|
||||||
{
|
{
|
||||||
acmp_destroy(acmp);
|
acmp_destroy(acmp);
|
||||||
}
|
}
|
||||||
99
src/modules/module-avb/acmp.h
Normal file
99
src/modules/module-avb/acmp.h
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_ACMP_H
|
||||||
|
#define AVB_ACMP_H
|
||||||
|
|
||||||
|
#include "packets.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND 0
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE 1
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND 2
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE 3
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND 4
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE 5
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND 6
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE 7
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND 8
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE 9
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND 10
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE 11
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND 12
|
||||||
|
#define AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE 13
|
||||||
|
|
||||||
|
#define AVB_ACMP_STATUS_SUCCESS 0
|
||||||
|
#define AVB_ACMP_STATUS_LISTENER_UNKNOWN_ID 1
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_UNKNOWN_ID 2
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_DEST_MAC_FAIL 3
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_NO_STREAM_INDEX 4
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_NO_BANDWIDTH 5
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_EXCLUSIVE 6
|
||||||
|
#define AVB_ACMP_STATUS_LISTENER_TALKER_TIMEOUT 7
|
||||||
|
#define AVB_ACMP_STATUS_LISTENER_EXCLUSIVE 8
|
||||||
|
#define AVB_ACMP_STATUS_STATE_UNAVAILABLE 9
|
||||||
|
#define AVB_ACMP_STATUS_NOT_CONNECTED 10
|
||||||
|
#define AVB_ACMP_STATUS_NO_SUCH_CONNECTION 11
|
||||||
|
#define AVB_ACMP_STATUS_COULD_NOT_SEND_MESSAGE 12
|
||||||
|
#define AVB_ACMP_STATUS_TALKER_MISBEHAVING 13
|
||||||
|
#define AVB_ACMP_STATUS_LISTENER_MISBEHAVING 14
|
||||||
|
#define AVB_ACMP_STATUS_RESERVED 15
|
||||||
|
#define AVB_ACMP_STATUS_CONTROLLER_NOT_AUTHORIZED 16
|
||||||
|
#define AVB_ACMP_STATUS_INCOMPATIBLE_REQUEST 17
|
||||||
|
#define AVB_ACMP_STATUS_LISTENER_INVALID_CONNECTION 18
|
||||||
|
#define AVB_ACMP_STATUS_NOT_SUPPORTED 31
|
||||||
|
|
||||||
|
#define AVB_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS 2000
|
||||||
|
#define AVB_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS 200
|
||||||
|
#define AVB_ACMP_TIMEOUT_GET_TX_STATE_COMMAND 200
|
||||||
|
#define AVB_ACMP_TIMEOUT_CONNECT_RX_COMMAND_MS 4500
|
||||||
|
#define AVB_ACMP_TIMEOUT_DISCONNECT_RX_COMMAND_MS 500
|
||||||
|
#define AVB_ACMP_TIMEOUT_GET_RX_STATE_COMMAND_MS 200
|
||||||
|
#define AVB_ACMP_TIMEOUT_GET_TX_CONNECTION_COMMAND 200
|
||||||
|
|
||||||
|
struct avb_packet_acmp {
|
||||||
|
struct avb_packet_header hdr;
|
||||||
|
uint64_t stream_id;
|
||||||
|
uint64_t controller_guid;
|
||||||
|
uint64_t talker_guid;
|
||||||
|
uint64_t listener_guid;
|
||||||
|
uint16_t talker_unique_id;
|
||||||
|
uint16_t listener_unique_id;
|
||||||
|
char stream_dest_mac[6];
|
||||||
|
uint16_t connection_count;
|
||||||
|
uint16_t sequence_id;
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t stream_vlan_id;
|
||||||
|
uint16_t reserved;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_PACKET_ACMP_SET_MESSAGE_TYPE(p,v) AVB_PACKET_SET_SUB1(&(p)->hdr, v)
|
||||||
|
#define AVB_PACKET_ACMP_SET_STATUS(p,v) AVB_PACKET_SET_SUB2(&(p)->hdr, v)
|
||||||
|
|
||||||
|
#define AVB_PACKET_ACMP_GET_MESSAGE_TYPE(p) AVB_PACKET_GET_SUB1(&(p)->hdr)
|
||||||
|
#define AVB_PACKET_ACMP_GET_STATUS(p) AVB_PACKET_GET_SUB2(&(p)->hdr)
|
||||||
|
|
||||||
|
struct avb_acmp *avb_acmp_register(struct server *server);
|
||||||
|
|
||||||
|
#endif /* AVB_ACMP_H */
|
||||||
|
|
@ -35,7 +35,7 @@ static const uint8_t mac[6] = AVB_BROADCAST_MAC;
|
||||||
|
|
||||||
struct entity {
|
struct entity {
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
struct avbtp_packet_adp packet;
|
struct avb_packet_adp packet;
|
||||||
uint64_t last_time;
|
uint64_t last_time;
|
||||||
unsigned advertise:1;
|
unsigned advertise:1;
|
||||||
};
|
};
|
||||||
|
|
@ -64,31 +64,31 @@ static void entity_free(struct entity *e)
|
||||||
|
|
||||||
static int send_departing(struct adp *adp, uint64_t now, struct entity *e)
|
static int send_departing(struct adp *adp, uint64_t now, struct entity *e)
|
||||||
{
|
{
|
||||||
AVBTP_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVBTP_ADP_MESSAGE_TYPE_ENTITY_DEPARTING);
|
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING);
|
||||||
e->packet.available_index = htonl(adp->available_index++);
|
e->packet.available_index = htonl(adp->available_index++);
|
||||||
avbtp_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
||||||
e->last_time = now;
|
e->last_time = now;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_advertise(struct adp *adp, uint64_t now, struct entity *e)
|
static int send_advertise(struct adp *adp, uint64_t now, struct entity *e)
|
||||||
{
|
{
|
||||||
AVBTP_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVBTP_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
||||||
e->packet.available_index = htonl(adp->available_index++);
|
e->packet.available_index = htonl(adp->available_index++);
|
||||||
avbtp_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
||||||
e->last_time = now;
|
e->last_time = now;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_discover(struct adp *adp, uint64_t entity_id)
|
static int send_discover(struct adp *adp, uint64_t entity_id)
|
||||||
{
|
{
|
||||||
struct avbtp_packet_adp p;
|
struct avb_packet_adp p;
|
||||||
spa_zero(p);
|
spa_zero(p);
|
||||||
AVBTP_PACKET_SET_SUBTYPE(&p.hdr, AVBTP_SUBTYPE_ADP);
|
AVB_PACKET_SET_SUBTYPE(&p.hdr, AVB_SUBTYPE_ADP);
|
||||||
AVBTP_PACKET_SET_LENGTH(&p.hdr, AVBTP_ADP_CONTROL_DATA_LENGTH);
|
AVB_PACKET_SET_LENGTH(&p.hdr, AVB_ADP_CONTROL_DATA_LENGTH);
|
||||||
AVBTP_PACKET_ADP_SET_MESSAGE_TYPE(&p, AVBTP_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
|
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&p, AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
|
||||||
p.entity_id = htonl(entity_id);
|
p.entity_id = htonl(entity_id);
|
||||||
avbtp_server_send_packet(adp->server, mac, AVB_TSN_ETH, &p, sizeof(p));
|
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &p, sizeof(p));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct adp *adp = data;
|
struct adp *adp = data;
|
||||||
struct server *server = adp->server;
|
struct server *server = adp->server;
|
||||||
const struct avbtp_packet_adp *p = message;
|
const struct avb_packet_adp *p = message;
|
||||||
struct entity *e;
|
struct entity *e;
|
||||||
int message_type;
|
int message_type;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
@ -108,17 +108,17 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (AVBTP_PACKET_GET_SUBTYPE(&p->hdr) != AVBTP_SUBTYPE_ADP ||
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ADP ||
|
||||||
AVBTP_PACKET_GET_LENGTH(&p->hdr) < AVBTP_ADP_CONTROL_DATA_LENGTH)
|
AVB_PACKET_GET_LENGTH(&p->hdr) < AVB_ADP_CONTROL_DATA_LENGTH)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
message_type = AVBTP_PACKET_ADP_GET_MESSAGE_TYPE(p);
|
message_type = AVB_PACKET_ADP_GET_MESSAGE_TYPE(p);
|
||||||
entity_id = be64toh(p->entity_id);
|
entity_id = be64toh(p->entity_id);
|
||||||
|
|
||||||
e = find_entity_by_id(adp, entity_id);
|
e = find_entity_by_id(adp, entity_id);
|
||||||
|
|
||||||
switch (message_type) {
|
switch (message_type) {
|
||||||
case AVBTP_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE:
|
case AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE:
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
e = calloc(1, sizeof(*e));
|
e = calloc(1, sizeof(*e));
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
|
|
@ -127,23 +127,23 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
e->packet = *p;
|
e->packet = *p;
|
||||||
spa_list_append(&adp->entities, &e->link);
|
spa_list_append(&adp->entities, &e->link);
|
||||||
pw_log_info("entity %s available",
|
pw_log_info("entity %s available",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf), entity_id));
|
avb_utils_format_id(buf, sizeof(buf), entity_id));
|
||||||
}
|
}
|
||||||
e->last_time = now;
|
e->last_time = now;
|
||||||
break;
|
break;
|
||||||
case AVBTP_ADP_MESSAGE_TYPE_ENTITY_DEPARTING:
|
case AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING:
|
||||||
if (e != NULL) {
|
if (e != NULL) {
|
||||||
pw_log_info("entity %s departing",
|
pw_log_info("entity %s departing",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf), entity_id));
|
avb_utils_format_id(buf, sizeof(buf), entity_id));
|
||||||
entity_free(e);
|
entity_free(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_ADP_MESSAGE_TYPE_ENTITY_DISCOVER:
|
case AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER:
|
||||||
if (entity_id == 0UL ||
|
if (entity_id == 0UL ||
|
||||||
(e != NULL && e->advertise &&
|
(e != NULL && e->advertise &&
|
||||||
be64toh(e->packet.entity_id) == entity_id)) {
|
be64toh(e->packet.entity_id) == entity_id)) {
|
||||||
pw_log_info("entity %s discover",
|
pw_log_info("entity %s discover",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf), entity_id));
|
avb_utils_format_id(buf, sizeof(buf), entity_id));
|
||||||
send_discover(adp, entity_id);
|
send_discover(adp, entity_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -166,13 +166,13 @@ static void check_timeout(struct adp *adp, uint64_t now)
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
spa_list_for_each_safe(e, t, &adp->entities, link) {
|
spa_list_for_each_safe(e, t, &adp->entities, link) {
|
||||||
int valid_time = AVBTP_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
||||||
|
|
||||||
if (e->last_time + (valid_time + 2) * SPA_NSEC_PER_SEC > now)
|
if (e->last_time + (valid_time + 2) * SPA_NSEC_PER_SEC > now)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pw_log_info("entity %s timeout",
|
pw_log_info("entity %s timeout",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf),
|
avb_utils_format_id(buf, sizeof(buf),
|
||||||
be64toh(e->packet.entity_id)));
|
be64toh(e->packet.entity_id)));
|
||||||
|
|
||||||
if (e->advertise)
|
if (e->advertise)
|
||||||
|
|
@ -183,7 +183,7 @@ static void check_timeout(struct adp *adp, uint64_t now)
|
||||||
}
|
}
|
||||||
static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e)
|
static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e)
|
||||||
{
|
{
|
||||||
int valid_time = AVBTP_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if (!e->advertise)
|
if (!e->advertise)
|
||||||
|
|
@ -193,7 +193,7 @@ static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pw_log_debug("entity %s readvertise",
|
pw_log_debug("entity %s readvertise",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf),
|
avb_utils_format_id(buf, sizeof(buf),
|
||||||
be64toh(e->packet.entity_id)));
|
be64toh(e->packet.entity_id)));
|
||||||
|
|
||||||
send_advertise(adp, now, e);
|
send_advertise(adp, now, e);
|
||||||
|
|
@ -203,14 +203,14 @@ static int check_advertise(struct adp *adp, uint64_t now)
|
||||||
{
|
{
|
||||||
struct server *server = adp->server;
|
struct server *server = adp->server;
|
||||||
const struct descriptor *d;
|
const struct descriptor *d;
|
||||||
struct avbtp_aem_desc_entity *entity;
|
struct avb_aem_desc_entity *entity;
|
||||||
struct avbtp_aem_desc_avb_interface *avb_interface;
|
struct avb_aem_desc_avb_interface *avb_interface;
|
||||||
struct entity *e;
|
struct entity *e;
|
||||||
uint64_t entity_id;
|
uint64_t entity_id;
|
||||||
struct avbtp_packet_adp *p;
|
struct avb_packet_adp *p;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
d = server_find_descriptor(server, AVBTP_AEM_DESC_ENTITY, 0);
|
d = server_find_descriptor(server, AVB_AEM_DESC_ENTITY, 0);
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -223,11 +223,11 @@ static int check_advertise(struct adp *adp, uint64_t now)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = server_find_descriptor(server, AVBTP_AEM_DESC_AVB_INTERFACE, 0);
|
d = server_find_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, 0);
|
||||||
avb_interface = d ? d->ptr : NULL;
|
avb_interface = d ? d->ptr : NULL;
|
||||||
|
|
||||||
pw_log_info("entity %s advertise",
|
pw_log_info("entity %s advertise",
|
||||||
avbtp_utils_format_id(buf, sizeof(buf), entity_id));
|
avb_utils_format_id(buf, sizeof(buf), entity_id));
|
||||||
|
|
||||||
e = calloc(1, sizeof(*e));
|
e = calloc(1, sizeof(*e));
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
|
|
@ -237,10 +237,10 @@ static int check_advertise(struct adp *adp, uint64_t now)
|
||||||
e->last_time = now;
|
e->last_time = now;
|
||||||
|
|
||||||
p = &e->packet;
|
p = &e->packet;
|
||||||
AVBTP_PACKET_SET_LENGTH(&p->hdr, AVBTP_ADP_CONTROL_DATA_LENGTH);
|
AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH);
|
||||||
AVBTP_PACKET_SET_SUBTYPE(&p->hdr, AVBTP_SUBTYPE_ADP);
|
AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP);
|
||||||
AVBTP_PACKET_ADP_SET_MESSAGE_TYPE(p, AVBTP_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
||||||
AVBTP_PACKET_ADP_SET_VALID_TIME(p, 10);
|
AVB_PACKET_ADP_SET_VALID_TIME(p, 10);
|
||||||
|
|
||||||
p->entity_id = entity->entity_id;
|
p->entity_id = entity->entity_id;
|
||||||
p->entity_model_id = entity->entity_model_id;
|
p->entity_model_id = entity->entity_model_id;
|
||||||
|
|
@ -303,7 +303,7 @@ static int do_discover(struct adp *adp, const char *args, FILE *out)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (spa_streq(key, "entity-id")) {
|
if (spa_streq(key, "entity-id")) {
|
||||||
if (avbtp_utils_parse_id(value, len, &id_val) >= 0)
|
if (avb_utils_parse_id(value, len, &id_val) >= 0)
|
||||||
entity_id = id_val;
|
entity_id = id_val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -332,14 +332,14 @@ static int adp_command(void *data, uint64_t now, const char *command, const char
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = adp_destroy,
|
.destroy = adp_destroy,
|
||||||
.message = adp_message,
|
.message = adp_message,
|
||||||
.periodic = adp_periodic,
|
.periodic = adp_periodic,
|
||||||
.command = adp_command
|
.command = adp_command
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_adp *avbtp_adp_register(struct server *server)
|
struct avb_adp *avb_adp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct adp *adp;
|
struct adp *adp;
|
||||||
|
|
||||||
|
|
@ -352,10 +352,10 @@ struct avbtp_adp *avbtp_adp_register(struct server *server)
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &adp->server_listener, &server_events, adp);
|
avdecc_server_add_listener(server, &adp->server_listener, &server_events, adp);
|
||||||
|
|
||||||
return (struct avbtp_adp*)adp;
|
return (struct avb_adp*)adp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_adp_unregister(struct avbtp_adp *adp)
|
void avb_adp_unregister(struct avb_adp *adp)
|
||||||
{
|
{
|
||||||
adp_destroy(adp);
|
adp_destroy(adp);
|
||||||
}
|
}
|
||||||
105
src/modules/module-avb/adp.h
Normal file
105
src/modules/module-avb/adp.h
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_ADP_H
|
||||||
|
#define AVB_ADP_H
|
||||||
|
|
||||||
|
#include "packets.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE 0
|
||||||
|
#define AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING 1
|
||||||
|
#define AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER 2
|
||||||
|
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_EFU_MODE (1u<<0)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_ADDRESS_ACCESS_SUPPORTED (1u<<1)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_GATEWAY_ENTITY (1u<<2)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_SUPPORTED (1u<<3)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_LEGACY_AVC (1u<<4)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_ASSOCIATION_ID_SUPPORTED (1u<<5)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_ASSOCIATION_ID_VALID (1u<<6)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_VENDOR_UNIQUE_SUPPORTED (1u<<7)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_CLASS_A_SUPPORTED (1u<<8)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_CLASS_B_SUPPORTED (1u<<9)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_GPTP_SUPPORTED (1u<<10)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_AUTHENTICATION_SUPPORTED (1u<<11)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_AUTHENTICATION_REQUIRED (1u<<12)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_PERSISTENT_ACQUIRE_SUPPORTED (1u<<13)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_IDENTIFY_CONTROL_INDEX_VALID (1u<<14)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_AEM_INTERFACE_INDEX_VALID (1u<<15)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_GENERAL_CONTROLLER_IGNORE (1u<<16)
|
||||||
|
#define AVB_ADP_ENTITY_CAPABILITY_ENTITY_NOT_READY (1u<<17)
|
||||||
|
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_IMPLEMENTED (1u<<0)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_OTHER_SOURCE (1u<<9)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_CONTROL_SOURCE (1u<<10)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_MEDIA_CLOCK_SOURCE (1u<<11)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_SMPTE_SOURCE (1u<<12)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_MIDI_SOURCE (1u<<13)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_AUDIO_SOURCE (1u<<14)
|
||||||
|
#define AVB_ADP_TALKER_CAPABILITY_VIDEO_SOURCE (1u<<15)
|
||||||
|
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_IMPLEMENTED (1u<<0)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_OTHER_SINK (1u<<9)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_CONTROL_SINK (1u<<10)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_MEDIA_CLOCK_SINK (1u<<11)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_SMPTE_SINK (1u<<12)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_MIDI_SINK (1u<<13)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_AUDIO_SINK (1u<<14)
|
||||||
|
#define AVB_ADP_LISTENER_CAPABILITY_VIDEO_SINK (1u<<15)
|
||||||
|
|
||||||
|
#define AVB_ADP_CONTROLLER_CAPABILITY_IMPLEMENTED (1u<<0)
|
||||||
|
#define AVB_ADP_CONTROLLER_CAPABILITY_LAYER3_PROXY (1u<<1)
|
||||||
|
|
||||||
|
#define AVB_ADP_CONTROL_DATA_LENGTH 56
|
||||||
|
|
||||||
|
struct avb_packet_adp {
|
||||||
|
struct avb_packet_header hdr;
|
||||||
|
uint64_t entity_id;
|
||||||
|
uint64_t entity_model_id;
|
||||||
|
uint32_t entity_capabilities;
|
||||||
|
uint16_t talker_stream_sources;
|
||||||
|
uint16_t talker_capabilities;
|
||||||
|
uint16_t listener_stream_sinks;
|
||||||
|
uint16_t listener_capabilities;
|
||||||
|
uint32_t controller_capabilities;
|
||||||
|
uint32_t available_index;
|
||||||
|
uint64_t gptp_grandmaster_id;
|
||||||
|
uint8_t gptp_domain_number;
|
||||||
|
uint8_t reserved0[3];
|
||||||
|
uint16_t identify_control_index;
|
||||||
|
uint16_t interface_index;
|
||||||
|
uint64_t association_id;
|
||||||
|
uint32_t reserved1;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_PACKET_ADP_SET_MESSAGE_TYPE(p,v) AVB_PACKET_SET_SUB1(&(p)->hdr, v)
|
||||||
|
#define AVB_PACKET_ADP_SET_VALID_TIME(p,v) AVB_PACKET_SET_SUB2(&(p)->hdr, v)
|
||||||
|
|
||||||
|
#define AVB_PACKET_ADP_GET_MESSAGE_TYPE(p) AVB_PACKET_GET_SUB1(&(p)->hdr)
|
||||||
|
#define AVB_PACKET_ADP_GET_VALID_TIME(p) AVB_PACKET_GET_SUB2(&(p)->hdr)
|
||||||
|
|
||||||
|
struct avb_adp *avb_adp_register(struct server *server);
|
||||||
|
|
||||||
|
#endif /* AVB_ADP_H */
|
||||||
|
|
@ -22,52 +22,52 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_AECP_AEM_DESCRIPTORS_H
|
#ifndef AVB_AECP_AEM_DESCRIPTORS_H
|
||||||
#define AVBTP_AECP_AEM_DESCRIPTORS_H
|
#define AVB_AECP_AEM_DESCRIPTORS_H
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#define AVBTP_AEM_DESC_ENTITY 0x0000
|
#define AVB_AEM_DESC_ENTITY 0x0000
|
||||||
#define AVBTP_AEM_DESC_CONFIGURATION 0x0001
|
#define AVB_AEM_DESC_CONFIGURATION 0x0001
|
||||||
#define AVBTP_AEM_DESC_AUDIO_UNIT 0x0002
|
#define AVB_AEM_DESC_AUDIO_UNIT 0x0002
|
||||||
#define AVBTP_AEM_DESC_VIDEO_UNIT 0x0003
|
#define AVB_AEM_DESC_VIDEO_UNIT 0x0003
|
||||||
#define AVBTP_AEM_DESC_SENSOR_UNIT 0x0004
|
#define AVB_AEM_DESC_SENSOR_UNIT 0x0004
|
||||||
#define AVBTP_AEM_DESC_STREAM_INPUT 0x0005
|
#define AVB_AEM_DESC_STREAM_INPUT 0x0005
|
||||||
#define AVBTP_AEM_DESC_STREAM_OUTPUT 0x0006
|
#define AVB_AEM_DESC_STREAM_OUTPUT 0x0006
|
||||||
#define AVBTP_AEM_DESC_JACK_INPUT 0x0007
|
#define AVB_AEM_DESC_JACK_INPUT 0x0007
|
||||||
#define AVBTP_AEM_DESC_JACK_OUTPUT 0x0008
|
#define AVB_AEM_DESC_JACK_OUTPUT 0x0008
|
||||||
#define AVBTP_AEM_DESC_AVB_INTERFACE 0x0009
|
#define AVB_AEM_DESC_AVB_INTERFACE 0x0009
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE 0x000a
|
#define AVB_AEM_DESC_CLOCK_SOURCE 0x000a
|
||||||
#define AVBTP_AEM_DESC_MEMORY_OBJECT 0x000b
|
#define AVB_AEM_DESC_MEMORY_OBJECT 0x000b
|
||||||
#define AVBTP_AEM_DESC_LOCALE 0x000c
|
#define AVB_AEM_DESC_LOCALE 0x000c
|
||||||
#define AVBTP_AEM_DESC_STRINGS 0x000d
|
#define AVB_AEM_DESC_STRINGS 0x000d
|
||||||
#define AVBTP_AEM_DESC_STREAM_PORT_INPUT 0x000e
|
#define AVB_AEM_DESC_STREAM_PORT_INPUT 0x000e
|
||||||
#define AVBTP_AEM_DESC_STREAM_PORT_OUTPUT 0x000f
|
#define AVB_AEM_DESC_STREAM_PORT_OUTPUT 0x000f
|
||||||
#define AVBTP_AEM_DESC_EXTERNAL_PORT_INPUT 0x0010
|
#define AVB_AEM_DESC_EXTERNAL_PORT_INPUT 0x0010
|
||||||
#define AVBTP_AEM_DESC_EXTERNAL_PORT_OUTPUT 0x0011
|
#define AVB_AEM_DESC_EXTERNAL_PORT_OUTPUT 0x0011
|
||||||
#define AVBTP_AEM_DESC_INTERNAL_PORT_INPUT 0x0012
|
#define AVB_AEM_DESC_INTERNAL_PORT_INPUT 0x0012
|
||||||
#define AVBTP_AEM_DESC_INTERNAL_PORT_OUTPUT 0x0013
|
#define AVB_AEM_DESC_INTERNAL_PORT_OUTPUT 0x0013
|
||||||
#define AVBTP_AEM_DESC_AUDIO_CLUSTER 0x0014
|
#define AVB_AEM_DESC_AUDIO_CLUSTER 0x0014
|
||||||
#define AVBTP_AEM_DESC_VIDEO_CLUSTER 0x0015
|
#define AVB_AEM_DESC_VIDEO_CLUSTER 0x0015
|
||||||
#define AVBTP_AEM_DESC_SENSOR_CLUSTER 0x0016
|
#define AVB_AEM_DESC_SENSOR_CLUSTER 0x0016
|
||||||
#define AVBTP_AEM_DESC_AUDIO_MAP 0x0017
|
#define AVB_AEM_DESC_AUDIO_MAP 0x0017
|
||||||
#define AVBTP_AEM_DESC_VIDEO_MAP 0x0018
|
#define AVB_AEM_DESC_VIDEO_MAP 0x0018
|
||||||
#define AVBTP_AEM_DESC_SENSOR_MAP 0x0019
|
#define AVB_AEM_DESC_SENSOR_MAP 0x0019
|
||||||
#define AVBTP_AEM_DESC_CONTROL 0x001a
|
#define AVB_AEM_DESC_CONTROL 0x001a
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_SELECTOR 0x001b
|
#define AVB_AEM_DESC_SIGNAL_SELECTOR 0x001b
|
||||||
#define AVBTP_AEM_DESC_MIXER 0x001c
|
#define AVB_AEM_DESC_MIXER 0x001c
|
||||||
#define AVBTP_AEM_DESC_MATRIX 0x001d
|
#define AVB_AEM_DESC_MATRIX 0x001d
|
||||||
#define AVBTP_AEM_DESC_MATRIX_SIGNAL 0x001e
|
#define AVB_AEM_DESC_MATRIX_SIGNAL 0x001e
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_SPLITTER 0x001f
|
#define AVB_AEM_DESC_SIGNAL_SPLITTER 0x001f
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_COMBINER 0x0020
|
#define AVB_AEM_DESC_SIGNAL_COMBINER 0x0020
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_DEMULTIPLEXER 0x0021
|
#define AVB_AEM_DESC_SIGNAL_DEMULTIPLEXER 0x0021
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_MULTIPLEXER 0x0022
|
#define AVB_AEM_DESC_SIGNAL_MULTIPLEXER 0x0022
|
||||||
#define AVBTP_AEM_DESC_SIGNAL_TRANSCODER 0x0023
|
#define AVB_AEM_DESC_SIGNAL_TRANSCODER 0x0023
|
||||||
#define AVBTP_AEM_DESC_CLOCK_DOMAIN 0x0024
|
#define AVB_AEM_DESC_CLOCK_DOMAIN 0x0024
|
||||||
#define AVBTP_AEM_DESC_CONTROL_BLOCK 0x0025
|
#define AVB_AEM_DESC_CONTROL_BLOCK 0x0025
|
||||||
#define AVBTP_AEM_DESC_INVALID 0xffff
|
#define AVB_AEM_DESC_INVALID 0xffff
|
||||||
|
|
||||||
struct avbtp_aem_desc_entity {
|
struct avb_aem_desc_entity {
|
||||||
uint64_t entity_id;
|
uint64_t entity_id;
|
||||||
uint64_t entity_model_id;
|
uint64_t entity_model_id;
|
||||||
uint32_t entity_capabilities;
|
uint32_t entity_capabilities;
|
||||||
|
|
@ -88,24 +88,24 @@ struct avbtp_aem_desc_entity {
|
||||||
uint16_t current_configuration;
|
uint16_t current_configuration;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_descriptor_count {
|
struct avb_aem_desc_descriptor_count {
|
||||||
uint16_t descriptor_type;
|
uint16_t descriptor_type;
|
||||||
uint16_t descriptor_count;
|
uint16_t descriptor_count;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_configuration {
|
struct avb_aem_desc_configuration {
|
||||||
char object_name[64];
|
char object_name[64];
|
||||||
uint16_t localized_description;
|
uint16_t localized_description;
|
||||||
uint16_t descriptor_counts_count;
|
uint16_t descriptor_counts_count;
|
||||||
uint16_t descriptor_counts_offset;
|
uint16_t descriptor_counts_offset;
|
||||||
struct avbtp_aem_desc_descriptor_count descriptor_counts[0];
|
struct avb_aem_desc_descriptor_count descriptor_counts[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_sampling_rate {
|
struct avb_aem_desc_sampling_rate {
|
||||||
uint32_t pull_frequency;
|
uint32_t pull_frequency;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_audio_unit {
|
struct avb_aem_desc_audio_unit {
|
||||||
char object_name[64];
|
char object_name[64];
|
||||||
uint16_t localized_description;
|
uint16_t localized_description;
|
||||||
uint16_t clock_domain_index;
|
uint16_t clock_domain_index;
|
||||||
|
|
@ -144,21 +144,21 @@ struct avbtp_aem_desc_audio_unit {
|
||||||
uint32_t current_sampling_rate;
|
uint32_t current_sampling_rate;
|
||||||
uint16_t sampling_rates_offset;
|
uint16_t sampling_rates_offset;
|
||||||
uint16_t sampling_rates_count;
|
uint16_t sampling_rates_count;
|
||||||
struct avbtp_aem_desc_sampling_rate sampling_rates[0];
|
struct avb_aem_desc_sampling_rate sampling_rates[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_SYNC_SOURCE (1u<<0)
|
#define AVB_AEM_DESC_STREAM_FLAG_SYNC_SOURCE (1u<<0)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_CLASS_A (1u<<1)
|
#define AVB_AEM_DESC_STREAM_FLAG_CLASS_A (1u<<1)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_CLASS_B (1u<<2)
|
#define AVB_AEM_DESC_STREAM_FLAG_CLASS_B (1u<<2)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_SUPPORTS_ENCRYPTED (1u<<3)
|
#define AVB_AEM_DESC_STREAM_FLAG_SUPPORTS_ENCRYPTED (1u<<3)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_PRIMARY_BACKUP_SUPPORTED (1u<<4)
|
#define AVB_AEM_DESC_STREAM_FLAG_PRIMARY_BACKUP_SUPPORTED (1u<<4)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_PRIMARY_BACKUP_VALID (1u<<5)
|
#define AVB_AEM_DESC_STREAM_FLAG_PRIMARY_BACKUP_VALID (1u<<5)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_SECONDARY_BACKUP_SUPPORTED (1u<<6)
|
#define AVB_AEM_DESC_STREAM_FLAG_SECONDARY_BACKUP_SUPPORTED (1u<<6)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_SECONDARY_BACKUP_VALID (1u<<7)
|
#define AVB_AEM_DESC_STREAM_FLAG_SECONDARY_BACKUP_VALID (1u<<7)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_TERTIARY_BACKUP_SUPPORTED (1u<<8)
|
#define AVB_AEM_DESC_STREAM_FLAG_TERTIARY_BACKUP_SUPPORTED (1u<<8)
|
||||||
#define AVBTP_AEM_DESC_STREAM_FLAG_TERTIARY_BACKUP_VALID (1u<<9)
|
#define AVB_AEM_DESC_STREAM_FLAG_TERTIARY_BACKUP_VALID (1u<<9)
|
||||||
|
|
||||||
struct avbtp_aem_desc_stream {
|
struct avb_aem_desc_stream {
|
||||||
char object_name[64];
|
char object_name[64];
|
||||||
uint16_t localized_description;
|
uint16_t localized_description;
|
||||||
uint16_t clock_domain_index;
|
uint16_t clock_domain_index;
|
||||||
|
|
@ -179,11 +179,11 @@ struct avbtp_aem_desc_stream {
|
||||||
uint64_t stream_formats[0];
|
uint64_t stream_formats[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_GRANDMASTER_SUPPORTED (1<<0)
|
#define AVB_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_GRANDMASTER_SUPPORTED (1<<0)
|
||||||
#define AVBTP_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_SUPPORTED (1<<1)
|
#define AVB_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_SUPPORTED (1<<1)
|
||||||
#define AVBTP_AEM_DESC_AVB_INTERFACE_FLAG_SRP_SUPPORTED (1<<2)
|
#define AVB_AEM_DESC_AVB_INTERFACE_FLAG_SRP_SUPPORTED (1<<2)
|
||||||
|
|
||||||
struct avbtp_aem_desc_avb_interface {
|
struct avb_aem_desc_avb_interface {
|
||||||
char object_name[64];
|
char object_name[64];
|
||||||
uint16_t localized_description;
|
uint16_t localized_description;
|
||||||
uint8_t mac_address[6];
|
uint8_t mac_address[6];
|
||||||
|
|
@ -201,13 +201,13 @@ struct avbtp_aem_desc_avb_interface {
|
||||||
uint16_t port_number;
|
uint16_t port_number;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_INTERNAL 0x0000
|
#define AVB_AEM_DESC_CLOCK_SOURCE_TYPE_INTERNAL 0x0000
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_EXTERNAL 0x0001
|
#define AVB_AEM_DESC_CLOCK_SOURCE_TYPE_EXTERNAL 0x0001
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_INPUT_STREAM 0x0002
|
#define AVB_AEM_DESC_CLOCK_SOURCE_TYPE_INPUT_STREAM 0x0002
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_MEDIA_CLOCK_STREAM 0x0003
|
#define AVB_AEM_DESC_CLOCK_SOURCE_TYPE_MEDIA_CLOCK_STREAM 0x0003
|
||||||
#define AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_EXPANSION 0xffff
|
#define AVB_AEM_DESC_CLOCK_SOURCE_TYPE_EXPANSION 0xffff
|
||||||
|
|
||||||
struct avbtp_aem_desc_clock_source {
|
struct avb_aem_desc_clock_source {
|
||||||
char object_name[64];
|
char object_name[64];
|
||||||
uint16_t localized_description;
|
uint16_t localized_description;
|
||||||
uint16_t clock_source_flags;
|
uint16_t clock_source_flags;
|
||||||
|
|
@ -217,13 +217,13 @@ struct avbtp_aem_desc_clock_source {
|
||||||
uint16_t clock_source_location_index;
|
uint16_t clock_source_location_index;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_locale {
|
struct avb_aem_desc_locale {
|
||||||
char locale_identifier[64];
|
char locale_identifier[64];
|
||||||
uint16_t number_of_strings;
|
uint16_t number_of_strings;
|
||||||
uint16_t base_strings;
|
uint16_t base_strings;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_strings {
|
struct avb_aem_desc_strings {
|
||||||
char string_0[64];
|
char string_0[64];
|
||||||
char string_1[64];
|
char string_1[64];
|
||||||
char string_2[64];
|
char string_2[64];
|
||||||
|
|
@ -233,7 +233,7 @@ struct avbtp_aem_desc_strings {
|
||||||
char string_6[64];
|
char string_6[64];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_aem_desc_stream_port {
|
struct avb_aem_desc_stream_port {
|
||||||
uint16_t clock_domain_index;
|
uint16_t clock_domain_index;
|
||||||
uint16_t port_flags;
|
uint16_t port_flags;
|
||||||
uint16_t number_of_controls;
|
uint16_t number_of_controls;
|
||||||
|
|
@ -244,4 +244,4 @@ struct avbtp_aem_desc_stream_port {
|
||||||
uint16_t base_map;
|
uint16_t base_map;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#endif /* AVBTP_AECP_AEM_DESCRIPTORS_H */
|
#endif /* AVB_AECP_AEM_DESCRIPTORS_H */
|
||||||
283
src/modules/module-avb/aecp-aem.c
Normal file
283
src/modules/module-avb/aecp-aem.c
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "aecp-aem.h"
|
||||||
|
#include "aecp-aem-descriptors.h"
|
||||||
|
|
||||||
|
static int reply_status(struct aecp *aecp, int status, const void *m, int len)
|
||||||
|
{
|
||||||
|
struct server *server = aecp->server;
|
||||||
|
uint8_t buf[len];
|
||||||
|
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf;
|
||||||
|
|
||||||
|
memcpy(reply, m, len);
|
||||||
|
AVB_PACKET_AECP_SET_MESSAGE_TYPE(reply, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||||
|
AVB_PACKET_AECP_SET_STATUS(reply, status);
|
||||||
|
|
||||||
|
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||||
|
AVB_TSN_ETH, reply, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reply_not_implemented(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_NOT_IMPLEMENTED, m, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reply_success(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_SUCCESS, m, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACQUIRE_ENTITY */
|
||||||
|
static int handle_acquire_entity(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
struct server *server = aecp->server;
|
||||||
|
const struct avb_packet_aecp_aem *p = m;
|
||||||
|
const struct avb_packet_aecp_aem_acquire *ae;
|
||||||
|
const struct descriptor *desc;
|
||||||
|
uint16_t desc_type, desc_id;
|
||||||
|
|
||||||
|
ae = (const struct avb_packet_aecp_aem_acquire*)p->payload;
|
||||||
|
|
||||||
|
desc_type = ntohs(ae->descriptor_type);
|
||||||
|
desc_id = ntohs(ae->descriptor_id);
|
||||||
|
|
||||||
|
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||||
|
if (desc == NULL)
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||||
|
|
||||||
|
if (desc_type != AVB_AEM_DESC_ENTITY || desc_id != 0)
|
||||||
|
return reply_not_implemented(aecp, m, len);
|
||||||
|
|
||||||
|
return reply_success(aecp, m, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LOCK_ENTITY */
|
||||||
|
static int handle_lock_entity(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
struct server *server = aecp->server;
|
||||||
|
const struct avb_packet_aecp_aem *p = m;
|
||||||
|
const struct avb_packet_aecp_aem_acquire *ae;
|
||||||
|
const struct descriptor *desc;
|
||||||
|
uint16_t desc_type, desc_id;
|
||||||
|
|
||||||
|
ae = (const struct avb_packet_aecp_aem_acquire*)p->payload;
|
||||||
|
|
||||||
|
desc_type = ntohs(ae->descriptor_type);
|
||||||
|
desc_id = ntohs(ae->descriptor_id);
|
||||||
|
|
||||||
|
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||||
|
if (desc == NULL)
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||||
|
|
||||||
|
if (desc_type != AVB_AEM_DESC_ENTITY || desc_id != 0)
|
||||||
|
return reply_not_implemented(aecp, m, len);
|
||||||
|
|
||||||
|
return reply_success(aecp, m, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* READ_DESCRIPTOR */
|
||||||
|
static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
struct server *server = aecp->server;
|
||||||
|
const struct avb_packet_aecp_aem *p = m;
|
||||||
|
struct avb_packet_aecp_aem *reply;
|
||||||
|
const struct avb_packet_aecp_aem_read_descriptor *rd;
|
||||||
|
uint16_t desc_type, desc_id;
|
||||||
|
const struct descriptor *desc;
|
||||||
|
uint8_t buf[2048];
|
||||||
|
size_t size, psize;
|
||||||
|
|
||||||
|
rd = (struct avb_packet_aecp_aem_read_descriptor*)p->payload;
|
||||||
|
|
||||||
|
desc_type = ntohs(rd->descriptor_type);
|
||||||
|
desc_id = ntohs(rd->descriptor_id);
|
||||||
|
|
||||||
|
pw_log_info("descriptor type:%04x index:%d", desc_type, desc_id);
|
||||||
|
|
||||||
|
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||||
|
if (desc == NULL)
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||||
|
|
||||||
|
memcpy(buf, p, len);
|
||||||
|
|
||||||
|
psize = sizeof(*rd);
|
||||||
|
size = sizeof(*reply) + psize;
|
||||||
|
|
||||||
|
memcpy(buf + size, desc->ptr, desc->size);
|
||||||
|
size += desc->size;
|
||||||
|
psize += desc->size;
|
||||||
|
|
||||||
|
reply = (struct avb_packet_aecp_aem*)buf;
|
||||||
|
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||||
|
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
|
||||||
|
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
||||||
|
|
||||||
|
return avb_server_send_packet(server, reply->aecp.hdr.eth.src,
|
||||||
|
AVB_TSN_ETH, reply, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GET_AVB_INFO */
|
||||||
|
static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
struct server *server = aecp->server;
|
||||||
|
const struct avb_packet_aecp_aem *p = m;
|
||||||
|
struct avb_packet_aecp_aem *reply;
|
||||||
|
struct avb_packet_aecp_aem_get_avb_info *i;
|
||||||
|
struct avb_aem_desc_avb_interface *avb_interface;
|
||||||
|
uint16_t desc_type, desc_id;
|
||||||
|
const struct descriptor *desc;
|
||||||
|
uint8_t buf[2048];
|
||||||
|
size_t size, psize;
|
||||||
|
|
||||||
|
i = (struct avb_packet_aecp_aem_get_avb_info*)p->payload;
|
||||||
|
|
||||||
|
desc_type = ntohs(i->descriptor_type);
|
||||||
|
desc_id = ntohs(i->descriptor_id);
|
||||||
|
|
||||||
|
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||||
|
if (desc == NULL)
|
||||||
|
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||||
|
|
||||||
|
if (desc_type != AVB_AEM_DESC_AVB_INTERFACE || desc_id != 0)
|
||||||
|
return reply_not_implemented(aecp, m, len);
|
||||||
|
|
||||||
|
avb_interface = desc->ptr;
|
||||||
|
|
||||||
|
memcpy(buf, p, len);
|
||||||
|
|
||||||
|
psize = sizeof(*i);
|
||||||
|
size = sizeof(*reply) + psize;
|
||||||
|
|
||||||
|
reply = (struct avb_packet_aecp_aem *)buf;
|
||||||
|
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||||
|
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
|
||||||
|
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
||||||
|
|
||||||
|
i = (struct avb_packet_aecp_aem_get_avb_info*)reply->payload;
|
||||||
|
i->gptp_grandmaster_id = avb_interface->clock_identity;
|
||||||
|
i->propagation_delay = htonl(0);
|
||||||
|
i->gptp_domain_number = avb_interface->domain_number;
|
||||||
|
i->flags = 0;
|
||||||
|
i->msrp_mappings_count = htons(0);
|
||||||
|
|
||||||
|
return avb_server_send_packet(server, reply->aecp.hdr.eth.src,
|
||||||
|
AVB_TSN_ETH, reply, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AEM_COMMAND */
|
||||||
|
struct cmd_info {
|
||||||
|
uint16_t type;
|
||||||
|
const char *name;
|
||||||
|
int (*handle) (struct aecp *aecp, const void *p, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct cmd_info cmd_info[] = {
|
||||||
|
{ AVB_AECP_AEM_CMD_ACQUIRE_ENTITY, "acquire-entity", handle_acquire_entity, },
|
||||||
|
{ AVB_AECP_AEM_CMD_LOCK_ENTITY, "lock-entity", handle_lock_entity, },
|
||||||
|
{ AVB_AECP_AEM_CMD_ENTITY_AVAILABLE, "entity-available", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_CONTROLLER_AVAILABLE, "controller-available", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_READ_DESCRIPTOR, "read-descriptor", handle_read_descriptor, },
|
||||||
|
{ AVB_AECP_AEM_CMD_WRITE_DESCRIPTOR, "write-descriptor", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_CONFIGURATION, "set-configuration", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_CONFIGURATION, "get-configuration", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_STREAM_FORMAT, "set-stream-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_STREAM_FORMAT, "get-stream-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_VIDEO_FORMAT, "set-video-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_VIDEO_FORMAT, "get-video-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_SENSOR_FORMAT, "set-sensor-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_SENSOR_FORMAT, "get-sensor-format", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_STREAM_INFO, "set-stream-info", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_STREAM_INFO, "get-stream-info", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_NAME, "set-name", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_NAME, "get-name", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_ASSOCIATION_ID, "set-association-id", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_ASSOCIATION_ID, "get-association-id", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_SAMPLING_RATE, "set-sampling-rate", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_SAMPLING_RATE, "get-sampling-rate", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_CLOCK_SOURCE, "set-clock-source", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_CLOCK_SOURCE, "get-clock-source", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_CONTROL, "set-control", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_CONTROL, "get-control", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_INCREMENT_CONTROL, "increment-control", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_DECREMENT_CONTROL, "decrement-control", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_SIGNAL_SELECTOR, "set-signal-selector", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_SIGNAL_SELECTOR, "get-signal-selector", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_MIXER, "set-mixer", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_MIXER, "get-mixer", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_SET_MATRIX, "set-matrix", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_MATRIX, "get-matrix", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_START_STREAMING, "start-streaming", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_STOP_STREAMING, "stop-streaming", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_REGISTER_UNSOLICITED_NOTIFICATION, "register-unsolicited-notification", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_DEREGISTER_UNSOLICITED_NOTIFICATION, "deregister-unsolicited-notification", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_IDENTIFY_NOTIFICATION, "identify-notification", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_AVB_INFO, "get-avb-info", handle_get_avb_info, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_AS_PATH, "get-as-path", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_COUNTERS, "get-counters", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_REBOOT, "reboot", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_AUDIO_MAP, "get-audio-map", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_ADD_AUDIO_MAPPINGS, "add-audio-mappings", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_REMOVE_AUDIO_MAPPINGS, "remove-audio-mappings", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_VIDEO_MAP, "get-video-map", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_ADD_VIDEO_MAPPINGS, "add-video-mappings", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_REMOVE_VIDEO_MAPPINGS, "remove-video-mappings", NULL, },
|
||||||
|
{ AVB_AECP_AEM_CMD_GET_SENSOR_MAP, "get-sensor-map", NULL, }
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline const struct cmd_info *find_cmd_info(uint16_t type, const char *name)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < SPA_N_ELEMENTS(cmd_info); i++) {
|
||||||
|
if ((name == NULL && type == cmd_info[i].type) ||
|
||||||
|
(name != NULL && spa_streq(name, cmd_info[i].name)))
|
||||||
|
return &cmd_info[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int avb_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
const struct avb_packet_aecp_aem *p = m;
|
||||||
|
uint16_t cmd_type;
|
||||||
|
const struct cmd_info *info;
|
||||||
|
|
||||||
|
cmd_type = AVB_PACKET_AEM_GET_COMMAND_TYPE(p);
|
||||||
|
|
||||||
|
info = find_cmd_info(cmd_type, NULL);
|
||||||
|
if (info == NULL)
|
||||||
|
return reply_not_implemented(aecp, m, len);
|
||||||
|
|
||||||
|
pw_log_info("aem command %s", info->name);
|
||||||
|
|
||||||
|
if (info->handle == NULL)
|
||||||
|
return reply_not_implemented(aecp, m, len);
|
||||||
|
|
||||||
|
return info->handle(aecp, m, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int avb_aecp_aem_handle_response(struct aecp *aecp, const void *m, int len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
345
src/modules/module-avb/aecp-aem.h
Normal file
345
src/modules/module-avb/aecp-aem.h
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_AEM_H
|
||||||
|
#define AVB_AEM_H
|
||||||
|
|
||||||
|
#include "aecp.h"
|
||||||
|
|
||||||
|
#define AVB_AECP_AEM_STATUS_SUCCESS 0
|
||||||
|
#define AVB_AECP_AEM_STATUS_NOT_IMPLEMENTED 1
|
||||||
|
#define AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR 2
|
||||||
|
#define AVB_AECP_AEM_STATUS_ENTITY_LOCKED 3
|
||||||
|
#define AVB_AECP_AEM_STATUS_ENTITY_ACQUIRED 4
|
||||||
|
#define AVB_AECP_AEM_STATUS_NOT_AUTHENTICATED 5
|
||||||
|
#define AVB_AECP_AEM_STATUS_AUTHENTICATION_DISABLED 6
|
||||||
|
#define AVB_AECP_AEM_STATUS_BAD_ARGUMENTS 7
|
||||||
|
#define AVB_AECP_AEM_STATUS_NO_RESOURCES 8
|
||||||
|
#define AVB_AECP_AEM_STATUS_IN_PROGRESS 9
|
||||||
|
#define AVB_AECP_AEM_STATUS_ENTITY_MISBEHAVING 10
|
||||||
|
#define AVB_AECP_AEM_STATUS_NOT_SUPPORTED 11
|
||||||
|
#define AVB_AECP_AEM_STATUS_STREAM_IS_RUNNING 12
|
||||||
|
|
||||||
|
#define AVB_AECP_AEM_CMD_ACQUIRE_ENTITY 0x0000
|
||||||
|
#define AVB_AECP_AEM_CMD_LOCK_ENTITY 0x0001
|
||||||
|
#define AVB_AECP_AEM_CMD_ENTITY_AVAILABLE 0x0002
|
||||||
|
#define AVB_AECP_AEM_CMD_CONTROLLER_AVAILABLE 0x0003
|
||||||
|
#define AVB_AECP_AEM_CMD_READ_DESCRIPTOR 0x0004
|
||||||
|
#define AVB_AECP_AEM_CMD_WRITE_DESCRIPTOR 0x0005
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_CONFIGURATION 0x0006
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_CONFIGURATION 0x0007
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_STREAM_FORMAT 0x0008
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_STREAM_FORMAT 0x0009
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_VIDEO_FORMAT 0x000a
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_VIDEO_FORMAT 0x000b
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_SENSOR_FORMAT 0x000c
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_SENSOR_FORMAT 0x000d
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_STREAM_INFO 0x000e
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_STREAM_INFO 0x000f
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_NAME 0x0010
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_NAME 0x0011
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_ASSOCIATION_ID 0x0012
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_ASSOCIATION_ID 0x0013
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_SAMPLING_RATE 0x0014
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_SAMPLING_RATE 0x0015
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_CLOCK_SOURCE 0x0016
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_CLOCK_SOURCE 0x0017
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_CONTROL 0x0018
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_CONTROL 0x0019
|
||||||
|
#define AVB_AECP_AEM_CMD_INCREMENT_CONTROL 0x001a
|
||||||
|
#define AVB_AECP_AEM_CMD_DECREMENT_CONTROL 0x001b
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_SIGNAL_SELECTOR 0x001c
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_SIGNAL_SELECTOR 0x001d
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_MIXER 0x001e
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_MIXER 0x001f
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_MATRIX 0x0020
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_MATRIX 0x0021
|
||||||
|
#define AVB_AECP_AEM_CMD_START_STREAMING 0x0022
|
||||||
|
#define AVB_AECP_AEM_CMD_STOP_STREAMING 0x0023
|
||||||
|
#define AVB_AECP_AEM_CMD_REGISTER_UNSOLICITED_NOTIFICATION 0x0024
|
||||||
|
#define AVB_AECP_AEM_CMD_DEREGISTER_UNSOLICITED_NOTIFICATION 0x0025
|
||||||
|
#define AVB_AECP_AEM_CMD_IDENTIFY_NOTIFICATION 0x0026
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_AVB_INFO 0x0027
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_AS_PATH 0x0028
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_COUNTERS 0x0029
|
||||||
|
#define AVB_AECP_AEM_CMD_REBOOT 0x002a
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_AUDIO_MAP 0x002b
|
||||||
|
#define AVB_AECP_AEM_CMD_ADD_AUDIO_MAPPINGS 0x002c
|
||||||
|
#define AVB_AECP_AEM_CMD_REMOVE_AUDIO_MAPPINGS 0x002d
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_VIDEO_MAP 0x002e
|
||||||
|
#define AVB_AECP_AEM_CMD_ADD_VIDEO_MAPPINGS 0x002f
|
||||||
|
#define AVB_AECP_AEM_CMD_REMOVE_VIDEO_MAPPINGS 0x0030
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_SENSOR_MAP 0x0031
|
||||||
|
#define AVB_AECP_AEM_CMD_ADD_SENSOR_MAPPINGS 0x0032
|
||||||
|
#define AVB_AECP_AEM_CMD_REMOVE_SENSOR_MAPPINGS 0x0033
|
||||||
|
#define AVB_AECP_AEM_CMD_START_OPERATION 0x0034
|
||||||
|
#define AVB_AECP_AEM_CMD_ABORT_OPERATION 0x0035
|
||||||
|
#define AVB_AECP_AEM_CMD_OPERATION_STATUS 0x0036
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_ADD_KEY 0x0037
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_DELETE_KEY 0x0038
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_GET_KEY_LIST 0x0039
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_GET_KEY 0x003a
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_ADD_KEY_TO_CHAIN 0x003b
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_DELETE_KEY_FROM_CHAIN 0x003c
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_GET_KEYCHAIN_LIST 0x003d
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_GET_IDENTITY 0x003e
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_ADD_TOKEN 0x003f
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTH_DELETE_TOKEN 0x0040
|
||||||
|
#define AVB_AECP_AEM_CMD_AUTHENTICATE 0x0041
|
||||||
|
#define AVB_AECP_AEM_CMD_DEAUTHENTICATE 0x0042
|
||||||
|
#define AVB_AECP_AEM_CMD_ENABLE_TRANSPORT_SECURITY 0x0043
|
||||||
|
#define AVB_AECP_AEM_CMD_DISABLE_TRANSPORT_SECURITY 0x0044
|
||||||
|
#define AVB_AECP_AEM_CMD_ENABLE_STREAM_ENCRYPTION 0x0045
|
||||||
|
#define AVB_AECP_AEM_CMD_DISABLE_STREAM_ENCRYPTION 0x0046
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_MEMORY_OBJECT_LENGTH 0x0047
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_MEMORY_OBJECT_LENGTH 0x0048
|
||||||
|
#define AVB_AECP_AEM_CMD_SET_STREAM_BACKUP 0x0049
|
||||||
|
#define AVB_AECP_AEM_CMD_GET_STREAM_BACKUP 0x004a
|
||||||
|
#define AVB_AECP_AEM_CMD_EXPANSION 0x7fff
|
||||||
|
|
||||||
|
#define AVB_AEM_ACQUIRE_ENTITY_PERSISTENT_FLAG (1<<0)
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_acquire {
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t owner_guid;
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_lock {
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t locked_guid;
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_read_descriptor {
|
||||||
|
uint16_t configuration;
|
||||||
|
uint8_t reserved[2];
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_configuration {
|
||||||
|
uint16_t reserved;
|
||||||
|
uint16_t configuration_index;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_stream_format {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint64_t stream_format;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_video_format {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint32_t format_specific;
|
||||||
|
uint16_t aspect_ratio;
|
||||||
|
uint16_t color_space;
|
||||||
|
uint32_t frame_size;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_sensor_format {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint64_t sensor_format;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_CLASS_B (1u<<0)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_FAST_CONNECT (1u<<1)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_SAVED_STATE (1u<<2)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_STREAMING_WAIT (1u<<3)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_ENCRYPTED_PDU (1u<<4)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_STREAM_VLAN_ID_VALID (1u<<25)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_CONNECTED (1u<<26)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_MSRP_FAILURE_VALID (1u<<27)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_STREAM_DEST_MAC_VALID (1u<<28)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_MSRP_ACC_LAT_VALID (1u<<29)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_STREAM_ID_VALID (1u<<30)
|
||||||
|
#define AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID (1u<<31)
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_stream_info {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_index;
|
||||||
|
uint32_t aem_stream_info_flags;
|
||||||
|
uint64_t stream_format;
|
||||||
|
uint64_t stream_id;
|
||||||
|
uint32_t msrp_accumulated_latency;
|
||||||
|
uint8_t stream_dest_mac[6];
|
||||||
|
uint8_t msrp_failure_code;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint64_t msrp_failure_bridge_id;
|
||||||
|
uint16_t stream_vlan_id;
|
||||||
|
uint16_t reserved2;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_name {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_index;
|
||||||
|
uint16_t name_index;
|
||||||
|
uint16_t configuration_index;
|
||||||
|
char name[64];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_association_id {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_index;
|
||||||
|
uint64_t association_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_sampling_rate {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint32_t sampling_rate;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_clock_source {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint16_t clock_source_index;
|
||||||
|
uint16_t reserved;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_control {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_incdec_control {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint16_t index_count;
|
||||||
|
uint16_t reserved;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_signal_selector {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint16_t signal_type;
|
||||||
|
uint16_t signal_index;
|
||||||
|
uint16_t signal_output;
|
||||||
|
uint16_t reserved;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_mixer {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_setget_matrix {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_index;
|
||||||
|
uint16_t matrix_column;
|
||||||
|
uint16_t matrix_row;
|
||||||
|
uint16_t region_width;
|
||||||
|
uint16_t region_height;
|
||||||
|
uint16_t rep_direction_value_count;
|
||||||
|
uint16_t item_offset;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_startstop_streaming {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_identify_notification {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_msrp_mapping {
|
||||||
|
uint8_t traffic_class;
|
||||||
|
uint8_t priority;
|
||||||
|
uint16_t vlan_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_AEM_AVB_INFO_FLAG_GPTP_GRANDMASTER_SUPPORTED (1u<<0)
|
||||||
|
#define AVB_AEM_AVB_INFO_FLAG_GPTP_ENABLED (1u<<1)
|
||||||
|
#define AVB_AEM_AVB_INFO_FLAG_SRP_ENABLED (1u<<2)
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_get_avb_info {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint64_t gptp_grandmaster_id;
|
||||||
|
uint32_t propagation_delay;
|
||||||
|
uint8_t gptp_domain_number;
|
||||||
|
uint8_t flags;
|
||||||
|
uint16_t msrp_mappings_count;
|
||||||
|
uint8_t msrp_mappings[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_get_as_path {
|
||||||
|
uint16_t descriptor_index;
|
||||||
|
uint16_t reserved;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_get_counters {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint32_t counters_valid;
|
||||||
|
uint8_t counters_block[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_reboot {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_start_operation {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint16_t operation_id;
|
||||||
|
uint16_t operation_type;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem_operation_status {
|
||||||
|
uint16_t descriptor_type;
|
||||||
|
uint16_t descriptor_id;
|
||||||
|
uint16_t operation_id;
|
||||||
|
uint16_t percent_complete;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_aecp_aem {
|
||||||
|
struct avb_packet_aecp_header aecp;
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
unsigned u:1;
|
||||||
|
unsigned cmd1:7;
|
||||||
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
unsigned cmd1:7;
|
||||||
|
unsigned u:1;
|
||||||
|
#endif
|
||||||
|
uint8_t cmd2;
|
||||||
|
uint8_t payload[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_PACKET_AEM_SET_COMMAND_TYPE(p,v) ((p)->cmd1 = ((v) >> 8),(p)->cmd2 = (v))
|
||||||
|
|
||||||
|
#define AVB_PACKET_AEM_GET_COMMAND_TYPE(p) ((p)->cmd1 << 8 | (p)->cmd2)
|
||||||
|
|
||||||
|
int avb_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len);
|
||||||
|
int avb_aecp_aem_handle_response(struct aecp *aecp, const void *m, int len);
|
||||||
|
|
||||||
|
#endif /* AVB_AEM_H */
|
||||||
|
|
@ -43,26 +43,26 @@ static int reply_not_implemented(struct aecp *aecp, const void *p, int len)
|
||||||
{
|
{
|
||||||
struct server *server = aecp->server;
|
struct server *server = aecp->server;
|
||||||
uint8_t buf[len];
|
uint8_t buf[len];
|
||||||
struct avbtp_packet_aecp_header *reply = (struct avbtp_packet_aecp_header*)buf;
|
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf;
|
||||||
|
|
||||||
memcpy(reply, p, len);
|
memcpy(reply, p, len);
|
||||||
AVBTP_PACKET_AECP_SET_STATUS(reply, AVBTP_AECP_STATUS_NOT_IMPLEMENTED);
|
AVB_PACKET_AECP_SET_STATUS(reply, AVB_AECP_STATUS_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->hdr.eth.src,
|
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||||
AVB_TSN_ETH, reply, len);
|
AVB_TSN_ETH, reply, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct msg_info msg_info[] = {
|
static const struct msg_info msg_info[] = {
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_AEM_COMMAND, "aem-command", avbtp_aecp_aem_handle_command, },
|
{ AVB_AECP_MESSAGE_TYPE_AEM_COMMAND, "aem-command", avb_aecp_aem_handle_command, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_AEM_RESPONSE, "aem-response", avbtp_aecp_aem_handle_response, },
|
{ AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE, "aem-response", avb_aecp_aem_handle_response, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_COMMAND, "address-access-command", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_COMMAND, "address-access-command", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_RESPONSE, "address-access-response", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_RESPONSE, "address-access-response", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_AVC_COMMAND, "avc-command", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_AVC_COMMAND, "avc-command", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_AVC_RESPONSE, "avc-response", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_AVC_RESPONSE, "avc-response", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_COMMAND, "vendor-unique-command", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_COMMAND, "vendor-unique-command", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE, "vendor-unique-response", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE, "vendor-unique-response", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_EXTENDED_COMMAND, "extended-command", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_EXTENDED_COMMAND, "extended-command", NULL, },
|
||||||
{ AVBTP_AECP_MESSAGE_TYPE_EXTENDED_RESPONSE, "extended-response", NULL, },
|
{ AVB_AECP_MESSAGE_TYPE_EXTENDED_RESPONSE, "extended-response", NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
|
static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
|
||||||
|
|
@ -80,7 +80,7 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct aecp *aecp = data;
|
struct aecp *aecp = data;
|
||||||
struct server *server = aecp->server;
|
struct server *server = aecp->server;
|
||||||
const struct avbtp_packet_aecp_header *p = message;
|
const struct avb_packet_aecp_header *p = message;
|
||||||
const struct msg_info *info;
|
const struct msg_info *info;
|
||||||
int message_type;
|
int message_type;
|
||||||
|
|
||||||
|
|
@ -89,10 +89,10 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
||||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (AVBTP_PACKET_GET_SUBTYPE(&p->hdr) != AVBTP_SUBTYPE_AECP)
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_AECP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
message_type = AVBTP_PACKET_AECP_GET_MESSAGE_TYPE(p);
|
message_type = AVB_PACKET_AECP_GET_MESSAGE_TYPE(p);
|
||||||
|
|
||||||
info = find_msg_info(message_type, NULL);
|
info = find_msg_info(message_type, NULL);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
|
|
@ -141,13 +141,13 @@ static int aecp_command(void *data, uint64_t now, const char *command, const cha
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = aecp_destroy,
|
.destroy = aecp_destroy,
|
||||||
.message = aecp_message,
|
.message = aecp_message,
|
||||||
.command = aecp_command
|
.command = aecp_command
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_aecp *avbtp_aecp_register(struct server *server)
|
struct avb_aecp *avb_aecp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct aecp *aecp;
|
struct aecp *aecp;
|
||||||
|
|
||||||
|
|
@ -159,10 +159,10 @@ struct avbtp_aecp *avbtp_aecp_register(struct server *server)
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &aecp->server_listener, &server_events, aecp);
|
avdecc_server_add_listener(server, &aecp->server_listener, &server_events, aecp);
|
||||||
|
|
||||||
return (struct avbtp_aecp*)aecp;
|
return (struct avb_aecp*)aecp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_aecp_unregister(struct avbtp_aecp *aecp)
|
void avb_aecp_unregister(struct avb_aecp *aecp)
|
||||||
{
|
{
|
||||||
aecp_destroy(aecp);
|
aecp_destroy(aecp);
|
||||||
}
|
}
|
||||||
|
|
@ -22,39 +22,39 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_AECP_H
|
#ifndef AVB_AECP_H
|
||||||
#define AVBTP_AECP_H
|
#define AVB_AECP_H
|
||||||
|
|
||||||
#include "packets.h"
|
#include "packets.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_AEM_COMMAND 0
|
#define AVB_AECP_MESSAGE_TYPE_AEM_COMMAND 0
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_AEM_RESPONSE 1
|
#define AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE 1
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_COMMAND 2
|
#define AVB_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_COMMAND 2
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_RESPONSE 3
|
#define AVB_AECP_MESSAGE_TYPE_ADDRESS_ACCESS_RESPONSE 3
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_AVC_COMMAND 4
|
#define AVB_AECP_MESSAGE_TYPE_AVC_COMMAND 4
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_AVC_RESPONSE 5
|
#define AVB_AECP_MESSAGE_TYPE_AVC_RESPONSE 5
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_COMMAND 6
|
#define AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_COMMAND 6
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE 7
|
#define AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE 7
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_EXTENDED_COMMAND 14
|
#define AVB_AECP_MESSAGE_TYPE_EXTENDED_COMMAND 14
|
||||||
#define AVBTP_AECP_MESSAGE_TYPE_EXTENDED_RESPONSE 15
|
#define AVB_AECP_MESSAGE_TYPE_EXTENDED_RESPONSE 15
|
||||||
|
|
||||||
#define AVBTP_AECP_STATUS_SUCCESS 0
|
#define AVB_AECP_STATUS_SUCCESS 0
|
||||||
#define AVBTP_AECP_STATUS_NOT_IMPLEMENTED 1
|
#define AVB_AECP_STATUS_NOT_IMPLEMENTED 1
|
||||||
|
|
||||||
struct avbtp_packet_aecp_header {
|
struct avb_packet_aecp_header {
|
||||||
struct avbtp_packet_header hdr;
|
struct avb_packet_header hdr;
|
||||||
uint64_t target_guid;
|
uint64_t target_guid;
|
||||||
uint64_t controller_guid;
|
uint64_t controller_guid;
|
||||||
uint16_t sequence_id;
|
uint16_t sequence_id;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_PACKET_AECP_SET_MESSAGE_TYPE(p,v) AVBTP_PACKET_SET_SUB1(&(p)->hdr, v)
|
#define AVB_PACKET_AECP_SET_MESSAGE_TYPE(p,v) AVB_PACKET_SET_SUB1(&(p)->hdr, v)
|
||||||
#define AVBTP_PACKET_AECP_SET_STATUS(p,v) AVBTP_PACKET_SET_SUB2(&(p)->hdr, v)
|
#define AVB_PACKET_AECP_SET_STATUS(p,v) AVB_PACKET_SET_SUB2(&(p)->hdr, v)
|
||||||
|
|
||||||
#define AVBTP_PACKET_AECP_GET_MESSAGE_TYPE(p) AVBTP_PACKET_GET_SUB1(&(p)->hdr)
|
#define AVB_PACKET_AECP_GET_MESSAGE_TYPE(p) AVB_PACKET_GET_SUB1(&(p)->hdr)
|
||||||
#define AVBTP_PACKET_AECP_GET_STATUS(p) AVBTP_PACKET_GET_SUB2(&(p)->hdr)
|
#define AVB_PACKET_AECP_GET_STATUS(p) AVB_PACKET_GET_SUB2(&(p)->hdr)
|
||||||
|
|
||||||
struct avbtp_aecp *avbtp_aecp_register(struct server *server);
|
struct avb_aecp *avb_aecp_register(struct server *server);
|
||||||
|
|
||||||
#endif /* AVBTP_AECP_H */
|
#endif /* AVB_AECP_H */
|
||||||
|
|
@ -78,9 +78,9 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
pw_log_warn("got recv error: %m");
|
pw_log_warn("got recv error: %m");
|
||||||
}
|
}
|
||||||
else if (len < (int)sizeof(struct avbtp_packet_header)) {
|
else if (len < (int)sizeof(struct avb_packet_header)) {
|
||||||
pw_log_warn("short packet received (%d < %d)", len,
|
pw_log_warn("short packet received (%d < %d)", len,
|
||||||
(int)sizeof(struct avbtp_packet_header));
|
(int)sizeof(struct avb_packet_header));
|
||||||
} else {
|
} else {
|
||||||
clock_gettime(CLOCK_REALTIME, &now);
|
clock_gettime(CLOCK_REALTIME, &now);
|
||||||
server_emit_message(server, SPA_TIMESPEC_TO_NSEC(&now), buffer, len);
|
server_emit_message(server, SPA_TIMESPEC_TO_NSEC(&now), buffer, len);
|
||||||
|
|
@ -88,10 +88,10 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int avbtp_server_send_packet(struct server *server, const uint8_t dest[6],
|
int avb_server_send_packet(struct server *server, const uint8_t dest[6],
|
||||||
uint16_t type, void *data, size_t size)
|
uint16_t type, void *data, size_t size)
|
||||||
{
|
{
|
||||||
struct avbtp_ethernet_header *hdr = (struct avbtp_ethernet_header*)data;
|
struct avb_ethernet_header *hdr = (struct avb_ethernet_header*)data;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
memcpy(hdr->dest, dest, ETH_ALEN);
|
memcpy(hdr->dest, dest, ETH_ALEN);
|
||||||
|
|
@ -216,31 +216,31 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
|
||||||
|
|
||||||
init_descriptors(server);
|
init_descriptors(server);
|
||||||
|
|
||||||
server->mrp = avbtp_mrp_new(server);
|
server->mrp = avb_mrp_new(server);
|
||||||
if (server->mrp == NULL)
|
if (server->mrp == NULL)
|
||||||
goto error_free;
|
goto error_free;
|
||||||
|
|
||||||
avbtp_aecp_register(server);
|
avb_aecp_register(server);
|
||||||
avbtp_maap_register(server);
|
avb_maap_register(server);
|
||||||
server->mmrp = avbtp_mmrp_register(server);
|
server->mmrp = avb_mmrp_register(server);
|
||||||
server->msrp = avbtp_msrp_register(server);
|
server->msrp = avb_msrp_register(server);
|
||||||
server->mvrp = avbtp_mvrp_register(server);
|
server->mvrp = avb_mvrp_register(server);
|
||||||
avbtp_adp_register(server);
|
avb_adp_register(server);
|
||||||
avbtp_acmp_register(server);
|
avb_acmp_register(server);
|
||||||
|
|
||||||
server->domain_attr = avbtp_msrp_attribute_new(server->msrp,
|
server->domain_attr = avb_msrp_attribute_new(server->msrp,
|
||||||
AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN);
|
AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN);
|
||||||
server->domain_attr->attr.domain.sr_class_id = 6;
|
server->domain_attr->attr.domain.sr_class_id = 6;
|
||||||
server->domain_attr->attr.domain.sr_class_priority = 3;
|
server->domain_attr->attr.domain.sr_class_priority = 3;
|
||||||
server->domain_attr->attr.domain.sr_class_vid = htons(2);
|
server->domain_attr->attr.domain.sr_class_vid = htons(2);
|
||||||
|
|
||||||
avbtp_mrp_mad_begin(server->mrp, 0, server->domain_attr->mrp);
|
avb_mrp_mad_begin(server->mrp, 0, server->domain_attr->mrp);
|
||||||
avbtp_mrp_mad_join(server->mrp, 0, server->domain_attr->mrp, true);
|
avb_mrp_mad_join(server->mrp, 0, server->domain_attr->mrp, true);
|
||||||
|
|
||||||
server->listener_attr = avbtp_msrp_attribute_new(server->msrp,
|
server->listener_attr = avb_msrp_attribute_new(server->msrp,
|
||||||
AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
AVB_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
||||||
server->listener_attr->attr.listener.stream_id = htobe64(0);
|
server->listener_attr->attr.listener.stream_id = htobe64(0);
|
||||||
avbtp_mrp_mad_begin(server->mrp, 0, server->listener_attr->mrp);
|
avb_mrp_mad_begin(server->mrp, 0, server->listener_attr->mrp);
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
|
|
||||||
|
|
@ -28,43 +28,43 @@
|
||||||
|
|
||||||
void init_descriptors(struct server *server)
|
void init_descriptors(struct server *server)
|
||||||
{
|
{
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_STRINGS, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_STRINGS, 0,
|
||||||
sizeof(struct avbtp_aem_desc_strings),
|
sizeof(struct avb_aem_desc_strings),
|
||||||
&(struct avbtp_aem_desc_strings)
|
&(struct avb_aem_desc_strings)
|
||||||
{
|
{
|
||||||
.string_0 = "PipeWire",
|
.string_0 = "PipeWire",
|
||||||
.string_1 = "Configuration 1",
|
.string_1 = "Configuration 1",
|
||||||
.string_2 = "Wim Taymans",
|
.string_2 = "Wim Taymans",
|
||||||
});
|
});
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_LOCALE, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_LOCALE, 0,
|
||||||
sizeof(struct avbtp_aem_desc_locale),
|
sizeof(struct avb_aem_desc_locale),
|
||||||
&(struct avbtp_aem_desc_locale)
|
&(struct avb_aem_desc_locale)
|
||||||
{
|
{
|
||||||
.locale_identifier = "en-EN",
|
.locale_identifier = "en-EN",
|
||||||
.number_of_strings = htons(1),
|
.number_of_strings = htons(1),
|
||||||
.base_strings = htons(0)
|
.base_strings = htons(0)
|
||||||
});
|
});
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_ENTITY, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_ENTITY, 0,
|
||||||
sizeof(struct avbtp_aem_desc_entity),
|
sizeof(struct avb_aem_desc_entity),
|
||||||
&(struct avbtp_aem_desc_entity)
|
&(struct avb_aem_desc_entity)
|
||||||
{
|
{
|
||||||
.entity_id = htobe64(server->entity_id),
|
.entity_id = htobe64(server->entity_id),
|
||||||
.entity_model_id = htobe64(0),
|
.entity_model_id = htobe64(0),
|
||||||
.entity_capabilities = htonl(
|
.entity_capabilities = htonl(
|
||||||
AVBTP_ADP_ENTITY_CAPABILITY_AEM_SUPPORTED |
|
AVB_ADP_ENTITY_CAPABILITY_AEM_SUPPORTED |
|
||||||
AVBTP_ADP_ENTITY_CAPABILITY_CLASS_A_SUPPORTED |
|
AVB_ADP_ENTITY_CAPABILITY_CLASS_A_SUPPORTED |
|
||||||
AVBTP_ADP_ENTITY_CAPABILITY_GPTP_SUPPORTED |
|
AVB_ADP_ENTITY_CAPABILITY_GPTP_SUPPORTED |
|
||||||
AVBTP_ADP_ENTITY_CAPABILITY_AEM_IDENTIFY_CONTROL_INDEX_VALID |
|
AVB_ADP_ENTITY_CAPABILITY_AEM_IDENTIFY_CONTROL_INDEX_VALID |
|
||||||
AVBTP_ADP_ENTITY_CAPABILITY_AEM_INTERFACE_INDEX_VALID),
|
AVB_ADP_ENTITY_CAPABILITY_AEM_INTERFACE_INDEX_VALID),
|
||||||
|
|
||||||
.talker_stream_sources = htons(8),
|
.talker_stream_sources = htons(8),
|
||||||
.talker_capabilities = htons(
|
.talker_capabilities = htons(
|
||||||
AVBTP_ADP_TALKER_CAPABILITY_IMPLEMENTED |
|
AVB_ADP_TALKER_CAPABILITY_IMPLEMENTED |
|
||||||
AVBTP_ADP_TALKER_CAPABILITY_AUDIO_SOURCE),
|
AVB_ADP_TALKER_CAPABILITY_AUDIO_SOURCE),
|
||||||
.listener_stream_sinks = htons(8),
|
.listener_stream_sinks = htons(8),
|
||||||
.listener_capabilities = htons(
|
.listener_capabilities = htons(
|
||||||
AVBTP_ADP_LISTENER_CAPABILITY_IMPLEMENTED |
|
AVB_ADP_LISTENER_CAPABILITY_IMPLEMENTED |
|
||||||
AVBTP_ADP_LISTENER_CAPABILITY_AUDIO_SINK),
|
AVB_ADP_LISTENER_CAPABILITY_AUDIO_SINK),
|
||||||
.controller_capabilities = htons(0),
|
.controller_capabilities = htons(0),
|
||||||
.available_index = htonl(0),
|
.available_index = htonl(0),
|
||||||
.association_id = htobe64(0),
|
.association_id = htobe64(0),
|
||||||
|
|
@ -78,8 +78,8 @@ void init_descriptors(struct server *server)
|
||||||
.current_configuration = htons(0)
|
.current_configuration = htons(0)
|
||||||
});
|
});
|
||||||
struct {
|
struct {
|
||||||
struct avbtp_aem_desc_configuration desc;
|
struct avb_aem_desc_configuration desc;
|
||||||
struct avbtp_aem_desc_descriptor_count descriptor_counts[8];
|
struct avb_aem_desc_descriptor_count descriptor_counts[8];
|
||||||
} __attribute__ ((__packed__)) config =
|
} __attribute__ ((__packed__)) config =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
@ -87,25 +87,25 @@ void init_descriptors(struct server *server)
|
||||||
.localized_description = htons(1),
|
.localized_description = htons(1),
|
||||||
.descriptor_counts_count = htons(8),
|
.descriptor_counts_count = htons(8),
|
||||||
.descriptor_counts_offset = htons(
|
.descriptor_counts_offset = htons(
|
||||||
4 + sizeof(struct avbtp_aem_desc_configuration)),
|
4 + sizeof(struct avb_aem_desc_configuration)),
|
||||||
},
|
},
|
||||||
.descriptor_counts = {
|
.descriptor_counts = {
|
||||||
{ htons(AVBTP_AEM_DESC_AUDIO_UNIT), htons(1) },
|
{ htons(AVB_AEM_DESC_AUDIO_UNIT), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_STREAM_INPUT), htons(1) },
|
{ htons(AVB_AEM_DESC_STREAM_INPUT), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_STREAM_OUTPUT), htons(1) },
|
{ htons(AVB_AEM_DESC_STREAM_OUTPUT), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_AVB_INTERFACE), htons(1) },
|
{ htons(AVB_AEM_DESC_AVB_INTERFACE), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_CLOCK_SOURCE), htons(1) },
|
{ htons(AVB_AEM_DESC_CLOCK_SOURCE), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_CONTROL), htons(2) },
|
{ htons(AVB_AEM_DESC_CONTROL), htons(2) },
|
||||||
{ htons(AVBTP_AEM_DESC_LOCALE), htons(1) },
|
{ htons(AVB_AEM_DESC_LOCALE), htons(1) },
|
||||||
{ htons(AVBTP_AEM_DESC_CLOCK_DOMAIN), htons(1) }
|
{ htons(AVB_AEM_DESC_CLOCK_DOMAIN), htons(1) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_CONFIGURATION, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_CONFIGURATION, 0,
|
||||||
sizeof(config), &config);
|
sizeof(config), &config);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct avbtp_aem_desc_audio_unit desc;
|
struct avb_aem_desc_audio_unit desc;
|
||||||
struct avbtp_aem_desc_sampling_rate sampling_rates[6];
|
struct avb_aem_desc_sampling_rate sampling_rates[6];
|
||||||
} __attribute__ ((__packed__)) audio_unit =
|
} __attribute__ ((__packed__)) audio_unit =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
@ -146,7 +146,7 @@ void init_descriptors(struct server *server)
|
||||||
.base_control_block = htons(0),
|
.base_control_block = htons(0),
|
||||||
.current_sampling_rate = htonl(48000),
|
.current_sampling_rate = htonl(48000),
|
||||||
.sampling_rates_offset = htons(
|
.sampling_rates_offset = htons(
|
||||||
4 + sizeof(struct avbtp_aem_desc_audio_unit)),
|
4 + sizeof(struct avb_aem_desc_audio_unit)),
|
||||||
.sampling_rates_count = htons(6),
|
.sampling_rates_count = htons(6),
|
||||||
},
|
},
|
||||||
.sampling_rates = {
|
.sampling_rates = {
|
||||||
|
|
@ -158,11 +158,11 @@ void init_descriptors(struct server *server)
|
||||||
{ .pull_frequency = htonl(192000) },
|
{ .pull_frequency = htonl(192000) },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_AUDIO_UNIT, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_AUDIO_UNIT, 0,
|
||||||
sizeof(audio_unit), &audio_unit);
|
sizeof(audio_unit), &audio_unit);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct avbtp_aem_desc_stream desc;
|
struct avb_aem_desc_stream desc;
|
||||||
uint64_t stream_formats[6];
|
uint64_t stream_formats[6];
|
||||||
} __attribute__ ((__packed__)) stream_input_0 =
|
} __attribute__ ((__packed__)) stream_input_0 =
|
||||||
{
|
{
|
||||||
|
|
@ -171,11 +171,11 @@ void init_descriptors(struct server *server)
|
||||||
.localized_description = htons(0xffff),
|
.localized_description = htons(0xffff),
|
||||||
.clock_domain_index = htons(0),
|
.clock_domain_index = htons(0),
|
||||||
.stream_flags = htons(
|
.stream_flags = htons(
|
||||||
AVBTP_AEM_DESC_STREAM_FLAG_SYNC_SOURCE |
|
AVB_AEM_DESC_STREAM_FLAG_SYNC_SOURCE |
|
||||||
AVBTP_AEM_DESC_STREAM_FLAG_CLASS_A),
|
AVB_AEM_DESC_STREAM_FLAG_CLASS_A),
|
||||||
.current_format = htobe64(0x00a0020840000800ULL),
|
.current_format = htobe64(0x00a0020840000800ULL),
|
||||||
.formats_offset = htons(
|
.formats_offset = htons(
|
||||||
4 + sizeof(struct avbtp_aem_desc_stream)),
|
4 + sizeof(struct avb_aem_desc_stream)),
|
||||||
.number_of_formats = htons(6),
|
.number_of_formats = htons(6),
|
||||||
.backup_talker_entity_id_0 = htobe64(0),
|
.backup_talker_entity_id_0 = htobe64(0),
|
||||||
.backup_talker_unique_id_0 = htons(0),
|
.backup_talker_unique_id_0 = htons(0),
|
||||||
|
|
@ -197,11 +197,11 @@ void init_descriptors(struct server *server)
|
||||||
htobe64(0x00a0060860000800ULL),
|
htobe64(0x00a0060860000800ULL),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_STREAM_INPUT, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_STREAM_INPUT, 0,
|
||||||
sizeof(stream_input_0), &stream_input_0);
|
sizeof(stream_input_0), &stream_input_0);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct avbtp_aem_desc_stream desc;
|
struct avb_aem_desc_stream desc;
|
||||||
uint64_t stream_formats[6];
|
uint64_t stream_formats[6];
|
||||||
} __attribute__ ((__packed__)) stream_output_0 =
|
} __attribute__ ((__packed__)) stream_output_0 =
|
||||||
{
|
{
|
||||||
|
|
@ -210,10 +210,10 @@ void init_descriptors(struct server *server)
|
||||||
.localized_description = htons(0xffff),
|
.localized_description = htons(0xffff),
|
||||||
.clock_domain_index = htons(0),
|
.clock_domain_index = htons(0),
|
||||||
.stream_flags = htons(
|
.stream_flags = htons(
|
||||||
AVBTP_AEM_DESC_STREAM_FLAG_CLASS_A),
|
AVB_AEM_DESC_STREAM_FLAG_CLASS_A),
|
||||||
.current_format = htobe64(0x00a0020840000800ULL),
|
.current_format = htobe64(0x00a0020840000800ULL),
|
||||||
.formats_offset = htons(
|
.formats_offset = htons(
|
||||||
4 + sizeof(struct avbtp_aem_desc_stream)),
|
4 + sizeof(struct avb_aem_desc_stream)),
|
||||||
.number_of_formats = htons(6),
|
.number_of_formats = htons(6),
|
||||||
.backup_talker_entity_id_0 = htobe64(0),
|
.backup_talker_entity_id_0 = htobe64(0),
|
||||||
.backup_talker_unique_id_0 = htons(0),
|
.backup_talker_unique_id_0 = htons(0),
|
||||||
|
|
@ -235,13 +235,13 @@ void init_descriptors(struct server *server)
|
||||||
htobe64(0x00a0060860000800ULL),
|
htobe64(0x00a0060860000800ULL),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_STREAM_OUTPUT, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_STREAM_OUTPUT, 0,
|
||||||
sizeof(stream_output_0), &stream_output_0);
|
sizeof(stream_output_0), &stream_output_0);
|
||||||
|
|
||||||
struct avbtp_aem_desc_avb_interface avb_interface = {
|
struct avb_aem_desc_avb_interface avb_interface = {
|
||||||
.localized_description = htons(0xffff),
|
.localized_description = htons(0xffff),
|
||||||
.interface_flags = htons(
|
.interface_flags = htons(
|
||||||
AVBTP_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_GRANDMASTER_SUPPORTED),
|
AVB_AEM_DESC_AVB_INTERFACE_FLAG_GPTP_GRANDMASTER_SUPPORTED),
|
||||||
.clock_identity = htobe64(0),
|
.clock_identity = htobe64(0),
|
||||||
.priority1 = 0,
|
.priority1 = 0,
|
||||||
.clock_class = 0,
|
.clock_class = 0,
|
||||||
|
|
@ -256,19 +256,19 @@ void init_descriptors(struct server *server)
|
||||||
};
|
};
|
||||||
strncpy(avb_interface.object_name, server->ifname, 63);
|
strncpy(avb_interface.object_name, server->ifname, 63);
|
||||||
memcpy(avb_interface.mac_address, server->mac_addr, 6);
|
memcpy(avb_interface.mac_address, server->mac_addr, 6);
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_AVB_INTERFACE, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, 0,
|
||||||
sizeof(avb_interface), &avb_interface);
|
sizeof(avb_interface), &avb_interface);
|
||||||
|
|
||||||
struct avbtp_aem_desc_clock_source clock_source = {
|
struct avb_aem_desc_clock_source clock_source = {
|
||||||
.object_name = "Stream Clock",
|
.object_name = "Stream Clock",
|
||||||
.localized_description = htons(0xffff),
|
.localized_description = htons(0xffff),
|
||||||
.clock_source_flags = htons(0),
|
.clock_source_flags = htons(0),
|
||||||
.clock_source_type = htons(
|
.clock_source_type = htons(
|
||||||
AVBTP_AEM_DESC_CLOCK_SOURCE_TYPE_INPUT_STREAM),
|
AVB_AEM_DESC_CLOCK_SOURCE_TYPE_INPUT_STREAM),
|
||||||
.clock_source_identifier = htobe64(0),
|
.clock_source_identifier = htobe64(0),
|
||||||
.clock_source_location_type = htons(AVBTP_AEM_DESC_STREAM_INPUT),
|
.clock_source_location_type = htons(AVB_AEM_DESC_STREAM_INPUT),
|
||||||
.clock_source_location_index = htons(0),
|
.clock_source_location_index = htons(0),
|
||||||
};
|
};
|
||||||
server_add_descriptor(server, AVBTP_AEM_DESC_CLOCK_SOURCE, 0,
|
server_add_descriptor(server, AVB_AEM_DESC_CLOCK_SOURCE, 0,
|
||||||
sizeof(clock_source), &clock_source);
|
sizeof(clock_source), &clock_source);
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ struct impl {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct server_events {
|
struct server_events {
|
||||||
#define AVBTP_VERSION_SERVER_EVENTS 0
|
#define AVB_VERSION_SERVER_EVENTS 0
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
||||||
/** the server is destroyed */
|
/** the server is destroyed */
|
||||||
|
|
@ -87,13 +87,13 @@ struct server {
|
||||||
|
|
||||||
unsigned debug_messages:1;
|
unsigned debug_messages:1;
|
||||||
|
|
||||||
struct avbtp_mrp *mrp;
|
struct avb_mrp *mrp;
|
||||||
struct avbtp_mmrp *mmrp;
|
struct avb_mmrp *mmrp;
|
||||||
struct avbtp_mvrp *mvrp;
|
struct avb_mvrp *mvrp;
|
||||||
struct avbtp_msrp *msrp;
|
struct avb_msrp *msrp;
|
||||||
|
|
||||||
struct avbtp_msrp_attribute *domain_attr;
|
struct avb_msrp_attribute *domain_attr;
|
||||||
struct avbtp_msrp_attribute *listener_attr;
|
struct avb_msrp_attribute *listener_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const struct descriptor *server_find_descriptor(struct server *server,
|
static inline const struct descriptor *server_find_descriptor(struct server *server,
|
||||||
|
|
@ -131,7 +131,7 @@ void avdecc_server_free(struct server *server);
|
||||||
void avdecc_server_add_listener(struct server *server, struct spa_hook *listener,
|
void avdecc_server_add_listener(struct server *server, struct spa_hook *listener,
|
||||||
const struct server_events *events, void *data);
|
const struct server_events *events, void *data);
|
||||||
|
|
||||||
int avbtp_server_send_packet(struct server *server, const uint8_t dest[6],
|
int avb_server_send_packet(struct server *server, const uint8_t dest[6],
|
||||||
uint16_t type, void *data, size_t size);
|
uint16_t type, void *data, size_t size);
|
||||||
|
|
||||||
struct aecp {
|
struct aecp {
|
||||||
|
|
@ -36,49 +36,49 @@ struct maap {
|
||||||
static const char *message_type_as_string(uint8_t message_type)
|
static const char *message_type_as_string(uint8_t message_type)
|
||||||
{
|
{
|
||||||
switch (message_type) {
|
switch (message_type) {
|
||||||
case AVBTP_MAAP_MESSAGE_TYPE_PROBE:
|
case AVB_MAAP_MESSAGE_TYPE_PROBE:
|
||||||
return "PROBE";
|
return "PROBE";
|
||||||
case AVBTP_MAAP_MESSAGE_TYPE_DEFEND:
|
case AVB_MAAP_MESSAGE_TYPE_DEFEND:
|
||||||
return "DEFEND";
|
return "DEFEND";
|
||||||
case AVBTP_MAAP_MESSAGE_TYPE_ANNOUNCE:
|
case AVB_MAAP_MESSAGE_TYPE_ANNOUNCE:
|
||||||
return "ANNOUNCE";
|
return "ANNOUNCE";
|
||||||
}
|
}
|
||||||
return "INVALID";
|
return "INVALID";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maap_message_debug(struct maap *maap, const struct avbtp_packet_maap *p)
|
static void maap_message_debug(struct maap *maap, const struct avb_packet_maap *p)
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
const uint8_t *addr;
|
const uint8_t *addr;
|
||||||
|
|
||||||
v = AVBTP_PACKET_MAAP_GET_MESSAGE_TYPE(p);
|
v = AVB_PACKET_MAAP_GET_MESSAGE_TYPE(p);
|
||||||
pw_log_info("message-type: %d (%s)", v, message_type_as_string(v));
|
pw_log_info("message-type: %d (%s)", v, message_type_as_string(v));
|
||||||
pw_log_info(" maap-version: %d", AVBTP_PACKET_MAAP_GET_MAAP_VERSION(p));
|
pw_log_info(" maap-version: %d", AVB_PACKET_MAAP_GET_MAAP_VERSION(p));
|
||||||
pw_log_info(" length: %d", AVBTP_PACKET_GET_LENGTH(&p->hdr));
|
pw_log_info(" length: %d", AVB_PACKET_GET_LENGTH(&p->hdr));
|
||||||
|
|
||||||
pw_log_info(" stream-id: 0x%"PRIx64, AVBTP_PACKET_MAAP_GET_STREAM_ID(p));
|
pw_log_info(" stream-id: 0x%"PRIx64, AVB_PACKET_MAAP_GET_STREAM_ID(p));
|
||||||
addr = AVBTP_PACKET_MAAP_GET_REQUEST_START(p);
|
addr = AVB_PACKET_MAAP_GET_REQUEST_START(p);
|
||||||
pw_log_info(" request-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
pw_log_info(" request-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||||
pw_log_info(" request-count: %d", AVBTP_PACKET_MAAP_GET_REQUEST_COUNT(p));
|
pw_log_info(" request-count: %d", AVB_PACKET_MAAP_GET_REQUEST_COUNT(p));
|
||||||
addr = AVBTP_PACKET_MAAP_GET_CONFLICT_START(p);
|
addr = AVB_PACKET_MAAP_GET_CONFLICT_START(p);
|
||||||
pw_log_info(" conflict-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
pw_log_info(" conflict-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||||
pw_log_info(" conflict-count: %d", AVBTP_PACKET_MAAP_GET_CONFLICT_COUNT(p));
|
pw_log_info(" conflict-count: %d", AVB_PACKET_MAAP_GET_CONFLICT_COUNT(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int maap_message(void *data, uint64_t now, const void *message, int len)
|
static int maap_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct maap *maap = data;
|
struct maap *maap = data;
|
||||||
struct server *server = maap->server;
|
struct server *server = maap->server;
|
||||||
const struct avbtp_packet_maap *p = message;
|
const struct avb_packet_maap *p = message;
|
||||||
|
|
||||||
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH)
|
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH)
|
||||||
return 0;
|
return 0;
|
||||||
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
||||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (AVBTP_PACKET_GET_SUBTYPE(&p->hdr) != AVBTP_SUBTYPE_MAAP)
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_MAAP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (maap->server->debug_messages)
|
if (maap->server->debug_messages)
|
||||||
|
|
@ -95,12 +95,12 @@ static void maap_destroy(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = maap_destroy,
|
.destroy = maap_destroy,
|
||||||
.message = maap_message
|
.message = maap_message
|
||||||
};
|
};
|
||||||
|
|
||||||
int avbtp_maap_register(struct server *server)
|
int avb_maap_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct maap *maap;
|
struct maap *maap;
|
||||||
|
|
||||||
62
src/modules/module-avb/maap.h
Normal file
62
src/modules/module-avb/maap.h
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_MAAP_H
|
||||||
|
#define AVB_MAAP_H
|
||||||
|
|
||||||
|
#include "packets.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define AVB_MAAP_MESSAGE_TYPE_PROBE 1
|
||||||
|
#define AVB_MAAP_MESSAGE_TYPE_DEFEND 2
|
||||||
|
#define AVB_MAAP_MESSAGE_TYPE_ANNOUNCE 3
|
||||||
|
|
||||||
|
struct avb_packet_maap {
|
||||||
|
struct avb_packet_header hdr;
|
||||||
|
uint64_t stream_id;
|
||||||
|
uint8_t request_start[6];
|
||||||
|
uint16_t request_count;
|
||||||
|
uint8_t conflict_start[6];
|
||||||
|
uint16_t conflict_count;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_PACKET_MAAP_SET_MESSAGE_TYPE(p,v) AVB_PACKET_SET_SUB1(&(p)->hdr, v)
|
||||||
|
#define AVB_PACKET_MAAP_SET_MAAP_VERSION(p,v) AVB_PACKET_SET_SUB2(&(p)->hdr, v)
|
||||||
|
#define AVB_PACKET_MAAP_SET_STREAM_ID(p,v) ((p)->stream_id = htobe64(v))
|
||||||
|
#define AVB_PACKET_MAAP_SET_REQUEST_START(p,v) memcpy((p)->request_start, (v), 6)
|
||||||
|
#define AVB_PACKET_MAAP_SET_REQUEST_COUNT(p,v) ((p)->request_count = htons(v))
|
||||||
|
#define AVB_PACKET_MAAP_SET_CONFLICT_START(p,v) memcpy((p)->conflict_start, (v), 6)
|
||||||
|
#define AVB_PACKET_MAAP_SET_CONFLICT_COUNT(p,v) ((p)->conflict_count = htons(v))
|
||||||
|
|
||||||
|
#define AVB_PACKET_MAAP_GET_MESSAGE_TYPE(p) AVB_PACKET_GET_SUB1(&(p)->hdr)
|
||||||
|
#define AVB_PACKET_MAAP_GET_MAAP_VERSION(p) AVB_PACKET_GET_SUB2(&(p)->hdr)
|
||||||
|
#define AVB_PACKET_MAAP_GET_STREAM_ID(p) be64toh((p)->stream_id)
|
||||||
|
#define AVB_PACKET_MAAP_GET_REQUEST_START(p) ((p)->request_start)
|
||||||
|
#define AVB_PACKET_MAAP_GET_REQUEST_COUNT(p) ntohs((p)->request_count)
|
||||||
|
#define AVB_PACKET_MAAP_GET_CONFLICT_START(p) ((p)->conflict_start)
|
||||||
|
#define AVB_PACKET_MAAP_GET_CONFLICT_COUNT(p) ntohs((p)->conflict_count)
|
||||||
|
|
||||||
|
int avb_maap_register(struct server *server);
|
||||||
|
|
||||||
|
#endif /* AVB_MAAP_H */
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
static const uint8_t mac[6] = AVB_MMRP_MAC;
|
static const uint8_t mac[6] = AVB_MMRP_MAC;
|
||||||
|
|
||||||
struct attr {
|
struct attr {
|
||||||
struct avbtp_mmrp_attribute attr;
|
struct avb_mmrp_attribute attr;
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -43,10 +43,10 @@ struct mmrp {
|
||||||
|
|
||||||
static bool mmrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
static bool mmrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_mmrp_msg *msg = hdr;
|
const struct avb_packet_mmrp_msg *msg = hdr;
|
||||||
uint8_t attr_type = msg->attribute_type;
|
uint8_t attr_type = msg->attribute_type;
|
||||||
|
|
||||||
if (!AVBTP_MMRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
if (!AVB_MMRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*hdr_size = sizeof(*msg);
|
*hdr_size = sizeof(*msg);
|
||||||
|
|
@ -60,21 +60,21 @@ static int mmrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &mmrp->attributes, link)
|
spa_list_for_each(a, &mmrp->attributes, link)
|
||||||
if (a->attr.type == attribute_type)
|
if (a->attr.type == attribute_type)
|
||||||
avbtp_mrp_update_state(mmrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_update_state(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_service_requirement(const struct avbtp_packet_mmrp_service_requirement *t)
|
static void debug_service_requirement(const struct avb_packet_mmrp_service_requirement *t)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
pw_log_info("service requirement");
|
pw_log_info("service requirement");
|
||||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
pw_log_info(" %s", avb_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_service_requirement(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
static int process_service_requirement(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num)
|
const void *m, uint8_t event, uint8_t param, int num)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_mmrp_service_requirement *t = m;
|
const struct avb_packet_mmrp_service_requirement *t = m;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
debug_service_requirement(t);
|
debug_service_requirement(t);
|
||||||
|
|
@ -82,21 +82,21 @@ static int process_service_requirement(struct mmrp *mmrp, uint64_t now, uint8_t
|
||||||
spa_list_for_each(a, &mmrp->attributes, link)
|
spa_list_for_each(a, &mmrp->attributes, link)
|
||||||
if (a->attr.type == attr_type &&
|
if (a->attr.type == attr_type &&
|
||||||
memcmp(a->attr.attr.service_requirement.addr, t->addr, 6) == 0)
|
memcmp(a->attr.attr.service_requirement.addr, t->addr, 6) == 0)
|
||||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_process_mac(const struct avbtp_packet_mmrp_mac *t)
|
static void debug_process_mac(const struct avb_packet_mmrp_mac *t)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
pw_log_info("mac");
|
pw_log_info("mac");
|
||||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
pw_log_info(" %s", avb_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_mac(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
static int process_mac(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num)
|
const void *m, uint8_t event, uint8_t param, int num)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_mmrp_mac *t = m;
|
const struct avb_packet_mmrp_mac *t = m;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
debug_process_mac(t);
|
debug_process_mac(t);
|
||||||
|
|
@ -104,7 +104,7 @@ static int process_mac(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||||
spa_list_for_each(a, &mmrp->attributes, link)
|
spa_list_for_each(a, &mmrp->attributes, link)
|
||||||
if (a->attr.type == attr_type &&
|
if (a->attr.type == attr_type &&
|
||||||
memcmp(a->attr.attr.mac.addr, t->addr, 6) == 0)
|
memcmp(a->attr.attr.mac.addr, t->addr, 6) == 0)
|
||||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,8 +112,8 @@ static const struct {
|
||||||
int (*dispatch) (struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
int (*dispatch) (struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num);
|
const void *m, uint8_t event, uint8_t param, int num);
|
||||||
} dispatch[] = {
|
} dispatch[] = {
|
||||||
[AVBTP_MMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT] = { process_service_requirement, },
|
[AVB_MMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT] = { process_service_requirement, },
|
||||||
[AVBTP_MMRP_ATTRIBUTE_TYPE_MAC] = { process_mac, },
|
[AVB_MMRP_ATTRIBUTE_TYPE_MAC] = { process_mac, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mmrp_process(void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
static int mmrp_process(void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
||||||
|
|
@ -124,8 +124,8 @@ static int mmrp_process(void *data, uint64_t now, uint8_t attribute_type, const
|
||||||
attribute_type, value, event, param, index);
|
attribute_type, value, event, param, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct avbtp_mrp_parse_info info = {
|
static const struct avb_mrp_parse_info info = {
|
||||||
AVBTP_VERSION_MRP_PARSE_INFO,
|
AVB_VERSION_MRP_PARSE_INFO,
|
||||||
.check_header = mmrp_check_header,
|
.check_header = mmrp_check_header,
|
||||||
.attr_event = mmrp_attr_event,
|
.attr_event = mmrp_attr_event,
|
||||||
.process = mmrp_process,
|
.process = mmrp_process,
|
||||||
|
|
@ -134,7 +134,7 @@ static const struct avbtp_mrp_parse_info info = {
|
||||||
static int mmrp_message(void *data, uint64_t now, const void *message, int len)
|
static int mmrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct mmrp *mmrp = data;
|
struct mmrp *mmrp = data;
|
||||||
const struct avbtp_packet_mrp *p = message;
|
const struct avb_packet_mrp *p = message;
|
||||||
|
|
||||||
if (ntohs(p->eth.type) != AVB_MMRP_ETH)
|
if (ntohs(p->eth.type) != AVB_MMRP_ETH)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -142,7 +142,7 @@ static int mmrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pw_log_debug("MMRP");
|
pw_log_debug("MMRP");
|
||||||
return avbtp_mrp_parse_packet(mmrp->server->mrp,
|
return avb_mrp_parse_packet(mmrp->server->mrp,
|
||||||
now, message, len, &info, mmrp);
|
now, message, len, &info, mmrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,19 +154,19 @@ static void mmrp_destroy(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = mmrp_destroy,
|
.destroy = mmrp_destroy,
|
||||||
.message = mmrp_message
|
.message = mmrp_message
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_mmrp_attribute *avbtp_mmrp_attribute_new(struct avbtp_mmrp *m,
|
struct avb_mmrp_attribute *avb_mmrp_attribute_new(struct avb_mmrp *m,
|
||||||
uint8_t type)
|
uint8_t type)
|
||||||
{
|
{
|
||||||
struct mmrp *mmrp = (struct mmrp*)m;
|
struct mmrp *mmrp = (struct mmrp*)m;
|
||||||
struct avbtp_mrp_attribute *attr;
|
struct avb_mrp_attribute *attr;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
attr = avbtp_mrp_attribute_new(mmrp->server->mrp, sizeof(struct attr));
|
attr = avb_mrp_attribute_new(mmrp->server->mrp, sizeof(struct attr));
|
||||||
|
|
||||||
a = attr->user_data;
|
a = attr->user_data;
|
||||||
a->attr.mrp = attr;
|
a->attr.mrp = attr;
|
||||||
|
|
@ -176,7 +176,7 @@ struct avbtp_mmrp_attribute *avbtp_mmrp_attribute_new(struct avbtp_mmrp *m,
|
||||||
return &a->attr;
|
return &a->attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct avbtp_mmrp *avbtp_mmrp_register(struct server *server)
|
struct avb_mmrp *avb_mmrp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct mmrp *mmrp;
|
struct mmrp *mmrp;
|
||||||
|
|
||||||
|
|
@ -189,5 +189,5 @@ struct avbtp_mmrp *avbtp_mmrp_register(struct server *server)
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &mmrp->server_listener, &server_events, mmrp);
|
avdecc_server_add_listener(server, &mmrp->server_listener, &server_events, mmrp);
|
||||||
|
|
||||||
return (struct avbtp_mmrp*)mmrp;
|
return (struct avb_mmrp*)mmrp;
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_MMRP_H
|
#ifndef AVB_MMRP_H
|
||||||
#define AVBTP_MMRP_H
|
#define AVB_MMRP_H
|
||||||
|
|
||||||
#include "mrp.h"
|
#include "mrp.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
@ -31,38 +31,38 @@
|
||||||
#define AVB_MMRP_ETH 0x88f6
|
#define AVB_MMRP_ETH 0x88f6
|
||||||
#define AVB_MMRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x20 }
|
#define AVB_MMRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x20 }
|
||||||
|
|
||||||
#define AVBTP_MMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT 1
|
#define AVB_MMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT 1
|
||||||
#define AVBTP_MMRP_ATTRIBUTE_TYPE_MAC 2
|
#define AVB_MMRP_ATTRIBUTE_TYPE_MAC 2
|
||||||
#define AVBTP_MMRP_ATTRIBUTE_TYPE_VALID(t) ((t)>=1 && (t)<=2)
|
#define AVB_MMRP_ATTRIBUTE_TYPE_VALID(t) ((t)>=1 && (t)<=2)
|
||||||
|
|
||||||
struct avbtp_packet_mmrp_msg {
|
struct avb_packet_mmrp_msg {
|
||||||
uint8_t attribute_type;
|
uint8_t attribute_type;
|
||||||
uint8_t attribute_length;
|
uint8_t attribute_length;
|
||||||
uint8_t attribute_list[0];
|
uint8_t attribute_list[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_packet_mmrp_service_requirement {
|
struct avb_packet_mmrp_service_requirement {
|
||||||
unsigned char addr[6];
|
unsigned char addr[6];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_packet_mmrp_mac {
|
struct avb_packet_mmrp_mac {
|
||||||
unsigned char addr[6];
|
unsigned char addr[6];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_mmrp;
|
struct avb_mmrp;
|
||||||
|
|
||||||
struct avbtp_mmrp_attribute {
|
struct avb_mmrp_attribute {
|
||||||
struct avbtp_mrp_attribute *mrp;
|
struct avb_mrp_attribute *mrp;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
union {
|
union {
|
||||||
struct avbtp_packet_mmrp_service_requirement service_requirement;
|
struct avb_packet_mmrp_service_requirement service_requirement;
|
||||||
struct avbtp_packet_mmrp_mac mac;
|
struct avb_packet_mmrp_mac mac;
|
||||||
} attr;
|
} attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_mmrp_attribute *avbtp_mmrp_attribute_new(struct avbtp_mmrp *mmrp,
|
struct avb_mmrp_attribute *avb_mmrp_attribute_new(struct avb_mmrp *mmrp,
|
||||||
uint8_t type);
|
uint8_t type);
|
||||||
|
|
||||||
struct avbtp_mmrp *avbtp_mmrp_register(struct server *server);
|
struct avb_mmrp *avb_mmrp_register(struct server *server);
|
||||||
|
|
||||||
#endif /* AVBTP_MMRP_H */
|
#endif /* AVB_MMRP_H */
|
||||||
|
|
@ -31,12 +31,12 @@
|
||||||
#define MRP_LVATIMER_MS 10000
|
#define MRP_LVATIMER_MS 10000
|
||||||
#define MRP_PERIODTIMER_MS 1000
|
#define MRP_PERIODTIMER_MS 1000
|
||||||
|
|
||||||
#define mrp_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct avbtp_mrp_events, m, v, ##__VA_ARGS__)
|
#define mrp_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct avb_mrp_events, m, v, ##__VA_ARGS__)
|
||||||
#define mrp_emit_event(s,n,e) mrp_emit(s,event,0,n,e)
|
#define mrp_emit_event(s,n,e) mrp_emit(s,event,0,n,e)
|
||||||
#define mrp_emit_notify(s,n,a,e) mrp_emit(s,notify,0,n,a,e)
|
#define mrp_emit_notify(s,n,a,e) mrp_emit(s,notify,0,n,a,e)
|
||||||
|
|
||||||
struct attribute {
|
struct attribute {
|
||||||
struct avbtp_mrp_attribute attr;
|
struct avb_mrp_attribute attr;
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
uint8_t applicant_state;
|
uint8_t applicant_state;
|
||||||
uint8_t registrar_state;
|
uint8_t registrar_state;
|
||||||
|
|
@ -67,7 +67,7 @@ static void global_event(struct mrp *mrp, uint64_t now, uint8_t event)
|
||||||
{
|
{
|
||||||
struct attribute *a;
|
struct attribute *a;
|
||||||
spa_list_for_each(a, &mrp->attributes, link)
|
spa_list_for_each(a, &mrp->attributes, link)
|
||||||
avbtp_mrp_update_state((struct avbtp_mrp*)mrp, now, &a->attr, event);
|
avb_mrp_update_state((struct avb_mrp*)mrp, now, &a->attr, event);
|
||||||
mrp_emit_event(mrp, now, event);
|
mrp_emit_event(mrp, now, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,12 +79,12 @@ static void mrp_periodic(void *data, uint64_t now)
|
||||||
|
|
||||||
if (now > mrp->periodic_timeout) {
|
if (now > mrp->periodic_timeout) {
|
||||||
if (mrp->periodic_timeout > 0)
|
if (mrp->periodic_timeout > 0)
|
||||||
global_event(mrp, now, AVBTP_MRP_EVENT_PERIODIC);
|
global_event(mrp, now, AVB_MRP_EVENT_PERIODIC);
|
||||||
mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC;
|
mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||||
}
|
}
|
||||||
if (now > mrp->leave_all_timeout) {
|
if (now > mrp->leave_all_timeout) {
|
||||||
if (mrp->leave_all_timeout > 0) {
|
if (mrp->leave_all_timeout > 0) {
|
||||||
global_event(mrp, now, AVBTP_MRP_EVENT_RX_LVA);
|
global_event(mrp, now, AVB_MRP_EVENT_RX_LVA);
|
||||||
leave_all = true;
|
leave_all = true;
|
||||||
}
|
}
|
||||||
mrp->leave_all_timeout = now + (MRP_LVATIMER_MS + (random() % (MRP_LVATIMER_MS / 2)))
|
mrp->leave_all_timeout = now + (MRP_LVATIMER_MS + (random() % (MRP_LVATIMER_MS / 2)))
|
||||||
|
|
@ -93,7 +93,7 @@ static void mrp_periodic(void *data, uint64_t now)
|
||||||
|
|
||||||
if (now > mrp->join_timeout) {
|
if (now > mrp->join_timeout) {
|
||||||
if (mrp->join_timeout > 0) {
|
if (mrp->join_timeout > 0) {
|
||||||
uint8_t event = leave_all ? AVBTP_MRP_EVENT_TX_LVA : AVBTP_MRP_EVENT_TX;
|
uint8_t event = leave_all ? AVB_MRP_EVENT_TX_LVA : AVB_MRP_EVENT_TX;
|
||||||
global_event(mrp, now, event);
|
global_event(mrp, now, event);
|
||||||
}
|
}
|
||||||
mrp->join_timeout = now + MRP_JOINTIMER_MS * SPA_NSEC_PER_MSEC;
|
mrp->join_timeout = now + MRP_JOINTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||||
|
|
@ -102,7 +102,7 @@ static void mrp_periodic(void *data, uint64_t now)
|
||||||
spa_list_for_each(a, &mrp->attributes, link) {
|
spa_list_for_each(a, &mrp->attributes, link) {
|
||||||
if (a->leave_timeout > 0 && now > a->leave_timeout) {
|
if (a->leave_timeout > 0 && now > a->leave_timeout) {
|
||||||
a->leave_timeout = 0;
|
a->leave_timeout = 0;
|
||||||
avbtp_mrp_update_state((struct avbtp_mrp*)mrp, now, &a->attr, AVBTP_MRP_EVENT_LV_TIMER);
|
avb_mrp_update_state((struct avb_mrp*)mrp, now, &a->attr, AVB_MRP_EVENT_LV_TIMER);
|
||||||
}
|
}
|
||||||
if (a->attr.pending_notify) {
|
if (a->attr.pending_notify) {
|
||||||
mrp_emit_notify(mrp, now, &a->attr, a->attr.pending_notify);
|
mrp_emit_notify(mrp, now, &a->attr, a->attr.pending_notify);
|
||||||
|
|
@ -112,19 +112,19 @@ static void mrp_periodic(void *data, uint64_t now)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = mrp_destroy,
|
.destroy = mrp_destroy,
|
||||||
.periodic = mrp_periodic,
|
.periodic = mrp_periodic,
|
||||||
};
|
};
|
||||||
|
|
||||||
int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt, int len,
|
int avb_mrp_parse_packet(struct avb_mrp *mrp, uint64_t now, const void *pkt, int len,
|
||||||
const struct avbtp_mrp_parse_info *info, void *data)
|
const struct avb_mrp_parse_info *info, void *data)
|
||||||
{
|
{
|
||||||
uint8_t *e = SPA_PTROFF(pkt, len, uint8_t);
|
uint8_t *e = SPA_PTROFF(pkt, len, uint8_t);
|
||||||
uint8_t *m = SPA_PTROFF(pkt, sizeof(struct avbtp_packet_mrp), uint8_t);
|
uint8_t *m = SPA_PTROFF(pkt, sizeof(struct avb_packet_mrp), uint8_t);
|
||||||
|
|
||||||
while (m < e && (m[0] != 0 || m[1] != 0)) {
|
while (m < e && (m[0] != 0 || m[1] != 0)) {
|
||||||
const struct avbtp_packet_mrp_hdr *hdr = (const struct avbtp_packet_mrp_hdr*)m;
|
const struct avb_packet_mrp_hdr *hdr = (const struct avb_packet_mrp_hdr*)m;
|
||||||
uint8_t attr_type = hdr->attribute_type;
|
uint8_t attr_type = hdr->attribute_type;
|
||||||
uint8_t attr_len = hdr->attribute_length;
|
uint8_t attr_len = hdr->attribute_length;
|
||||||
size_t hdr_size;
|
size_t hdr_size;
|
||||||
|
|
@ -136,9 +136,9 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
||||||
m += hdr_size;
|
m += hdr_size;
|
||||||
|
|
||||||
while (m < e && (m[0] != 0 || m[1] != 0)) {
|
while (m < e && (m[0] != 0 || m[1] != 0)) {
|
||||||
const struct avbtp_packet_mrp_vector *v =
|
const struct avb_packet_mrp_vector *v =
|
||||||
(const struct avbtp_packet_mrp_vector*)m;
|
(const struct avb_packet_mrp_vector*)m;
|
||||||
uint16_t i, num_values = AVBTP_MRP_VECTOR_GET_NUM_VALUES(v);
|
uint16_t i, num_values = AVB_MRP_VECTOR_GET_NUM_VALUES(v);
|
||||||
uint8_t event_len = (num_values+2)/3;
|
uint8_t event_len = (num_values+2)/3;
|
||||||
uint8_t param_len = has_param ? (num_values+3)/4 : 0;
|
uint8_t param_len = has_param ? (num_values+3)/4 : 0;
|
||||||
int plen = sizeof(*v) + attr_len + event_len + param_len;
|
int plen = sizeof(*v) + attr_len + event_len + param_len;
|
||||||
|
|
@ -149,7 +149,7 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
|
||||||
if (v->lva)
|
if (v->lva)
|
||||||
info->attr_event(data, now, attr_type, AVBTP_MRP_EVENT_RX_LVA);
|
info->attr_event(data, now, attr_type, AVB_MRP_EVENT_RX_LVA);
|
||||||
|
|
||||||
for (i = 0; i < num_values; i++) {
|
for (i = 0; i < num_values; i++) {
|
||||||
if (i % 3 == 0) {
|
if (i % 3 == 0) {
|
||||||
|
|
@ -175,7 +175,7 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *m,
|
struct avb_mrp_attribute *avb_mrp_attribute_new(struct avb_mrp *m,
|
||||||
size_t user_size)
|
size_t user_size)
|
||||||
{
|
{
|
||||||
struct mrp *mrp = (struct mrp*)m;
|
struct mrp *mrp = (struct mrp*)m;
|
||||||
|
|
@ -191,50 +191,50 @@ struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *m,
|
||||||
return &a->attr;
|
return &a->attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_pending_send(struct avbtp_mrp *mrp, struct attribute *a, bool leave_all)
|
static uint8_t get_pending_send(struct avb_mrp *mrp, struct attribute *a, bool leave_all)
|
||||||
{
|
{
|
||||||
uint8_t send = 0;
|
uint8_t send = 0;
|
||||||
|
|
||||||
switch (a->applicant_state) {
|
switch (a->applicant_state) {
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
if (leave_all && a->applicant_state == AVBTP_MRP_VP) {
|
if (leave_all && a->applicant_state == AVB_MRP_VP) {
|
||||||
switch (a->registrar_state) {
|
switch (a->registrar_state) {
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
send = AVBTP_MRP_SEND_IN;
|
send = AVB_MRP_SEND_IN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
send = AVBTP_MRP_SEND_MT;
|
send = AVB_MRP_SEND_MT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (leave_all || a->applicant_state != AVBTP_MRP_QP) {
|
} else if (leave_all || a->applicant_state != AVB_MRP_QP) {
|
||||||
switch (a->registrar_state) {
|
switch (a->registrar_state) {
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
send = AVBTP_MRP_SEND_JOININ;
|
send = AVB_MRP_SEND_JOININ;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
send = AVBTP_MRP_SEND_JOINMT;
|
send = AVB_MRP_SEND_JOINMT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
send = AVBTP_MRP_SEND_NEW;
|
send = AVB_MRP_SEND_NEW;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
send = AVBTP_MRP_SEND_LV;
|
send = AVB_MRP_SEND_LV;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_LO:
|
case AVB_MRP_LO:
|
||||||
switch (a->registrar_state) {
|
switch (a->registrar_state) {
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
send = AVBTP_MRP_SEND_IN;
|
send = AVB_MRP_SEND_IN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
send = AVBTP_MRP_SEND_MT;
|
send = AVB_MRP_SEND_MT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -242,8 +242,8 @@ static uint8_t get_pending_send(struct avbtp_mrp *mrp, struct attribute *a, bool
|
||||||
return send;
|
return send;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
|
||||||
struct avbtp_mrp_attribute *attr, int event)
|
struct avb_mrp_attribute *attr, int event)
|
||||||
{
|
{
|
||||||
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
|
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
|
||||||
uint8_t notify = 0, state;
|
uint8_t notify = 0, state;
|
||||||
|
|
@ -252,62 +252,62 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
||||||
state = a->registrar_state;
|
state = a->registrar_state;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AVBTP_MRP_EVENT_BEGIN:
|
case AVB_MRP_EVENT_BEGIN:
|
||||||
state = AVBTP_MRP_MT;
|
state = AVB_MRP_MT;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_RX_NEW:
|
case AVB_MRP_EVENT_RX_NEW:
|
||||||
notify = AVBTP_MRP_NOTIFY_JOIN_NEW;
|
notify = AVB_MRP_NOTIFY_JOIN_NEW;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_LV:
|
case AVB_MRP_LV:
|
||||||
a->leave_timeout = 0;
|
a->leave_timeout = 0;
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_MT:
|
case AVB_MRP_MT:
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
state = AVBTP_MRP_IN;
|
state = AVB_MRP_IN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_RX_JOININ:
|
case AVB_MRP_EVENT_RX_JOININ:
|
||||||
case AVBTP_MRP_EVENT_RX_JOINMT:
|
case AVB_MRP_EVENT_RX_JOINMT:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_LV:
|
case AVB_MRP_LV:
|
||||||
a->leave_timeout = 0;
|
a->leave_timeout = 0;
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_MT:
|
case AVB_MRP_MT:
|
||||||
notify = AVBTP_MRP_NOTIFY_JOIN;
|
notify = AVB_MRP_NOTIFY_JOIN;
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
state = AVBTP_MRP_IN;
|
state = AVB_MRP_IN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_RX_LV:
|
case AVB_MRP_EVENT_RX_LV:
|
||||||
notify = AVBTP_MRP_NOTIFY_LEAVE;
|
notify = AVB_MRP_NOTIFY_LEAVE;
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_EVENT_RX_LVA:
|
case AVB_MRP_EVENT_RX_LVA:
|
||||||
case AVBTP_MRP_EVENT_TX_LVA:
|
case AVB_MRP_EVENT_TX_LVA:
|
||||||
case AVBTP_MRP_EVENT_REDECLARE:
|
case AVB_MRP_EVENT_REDECLARE:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
a->leave_timeout = now + MRP_LVTIMER_MS * SPA_NSEC_PER_MSEC;
|
a->leave_timeout = now + MRP_LVTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||||
state = AVBTP_MRP_LV;
|
state = AVB_MRP_LV;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_LV_TIMER:
|
case AVB_MRP_EVENT_LV_TIMER:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_LV:
|
case AVB_MRP_LV:
|
||||||
notify = AVBTP_MRP_NOTIFY_LEAVE;
|
notify = AVB_MRP_NOTIFY_LEAVE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_FLUSH:
|
case AVB_MRP_EVENT_FLUSH:
|
||||||
notify = AVBTP_MRP_NOTIFY_LEAVE;
|
notify = AVB_MRP_NOTIFY_LEAVE;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_LV:
|
case AVB_MRP_LV:
|
||||||
case AVBTP_MRP_MT:
|
case AVB_MRP_MT:
|
||||||
case AVBTP_MRP_IN:
|
case AVB_MRP_IN:
|
||||||
state = AVBTP_MRP_MT;
|
state = AVB_MRP_MT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -323,185 +323,185 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
||||||
state = a->applicant_state;
|
state = a->applicant_state;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AVBTP_MRP_EVENT_BEGIN:
|
case AVB_MRP_EVENT_BEGIN:
|
||||||
state = AVBTP_MRP_VO;
|
state = AVB_MRP_VO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_NEW:
|
case AVB_MRP_EVENT_NEW:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state = AVBTP_MRP_VN;
|
state = AVB_MRP_VN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_JOIN:
|
case AVB_MRP_EVENT_JOIN:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VO:
|
case AVB_MRP_VO:
|
||||||
case AVBTP_MRP_LO:
|
case AVB_MRP_LO:
|
||||||
state = AVBTP_MRP_VP;
|
state = AVB_MRP_VP;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
state = AVBTP_MRP_AA;
|
state = AVB_MRP_AA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AO:
|
case AVB_MRP_AO:
|
||||||
state = AVBTP_MRP_AP;
|
state = AVB_MRP_AP;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_QO:
|
case AVB_MRP_QO:
|
||||||
state = AVBTP_MRP_QP;
|
state = AVB_MRP_QP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_LV:
|
case AVB_MRP_EVENT_LV:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
state = AVBTP_MRP_QO;
|
state = AVB_MRP_QO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
state = AVBTP_MRP_AO;
|
state = AVB_MRP_AO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
state = AVBTP_MRP_VO;
|
state = AVB_MRP_VO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
state = AVBTP_MRP_LA;
|
state = AVB_MRP_LA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_RX_JOININ:
|
case AVB_MRP_EVENT_RX_JOININ:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VO:
|
case AVB_MRP_VO:
|
||||||
state = AVBTP_MRP_AO;
|
state = AVB_MRP_AO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
state = AVBTP_MRP_AP;
|
state = AVB_MRP_AP;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
state = AVBTP_MRP_QA;
|
state = AVB_MRP_QA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AO:
|
case AVB_MRP_AO:
|
||||||
state = AVBTP_MRP_QO;
|
state = AVB_MRP_QO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
state = AVBTP_MRP_QP;
|
state = AVB_MRP_QP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_EVENT_RX_IN:
|
case AVB_MRP_EVENT_RX_IN:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
state = AVBTP_MRP_QA;
|
state = AVB_MRP_QA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SPA_FALLTHROUGH;
|
SPA_FALLTHROUGH;
|
||||||
case AVBTP_MRP_EVENT_RX_JOINMT:
|
case AVB_MRP_EVENT_RX_JOINMT:
|
||||||
case AVBTP_MRP_EVENT_RX_MT:
|
case AVB_MRP_EVENT_RX_MT:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
state = AVBTP_MRP_AA;
|
state = AVB_MRP_AA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_QO:
|
case AVB_MRP_QO:
|
||||||
state = AVBTP_MRP_AO;
|
state = AVB_MRP_AO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
state = AVBTP_MRP_AP;
|
state = AVB_MRP_AP;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_LO:
|
case AVB_MRP_LO:
|
||||||
state = AVBTP_MRP_VO;
|
state = AVB_MRP_VO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_RX_LV:
|
case AVB_MRP_EVENT_RX_LV:
|
||||||
case AVBTP_MRP_EVENT_RX_LVA:
|
case AVB_MRP_EVENT_RX_LVA:
|
||||||
case AVBTP_MRP_EVENT_REDECLARE:
|
case AVB_MRP_EVENT_REDECLARE:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VO:
|
case AVB_MRP_VO:
|
||||||
case AVBTP_MRP_AO:
|
case AVB_MRP_AO:
|
||||||
case AVBTP_MRP_QO:
|
case AVB_MRP_QO:
|
||||||
state = AVBTP_MRP_LO;
|
state = AVB_MRP_LO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
state = AVBTP_MRP_VN;
|
state = AVB_MRP_VN;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
state = AVBTP_MRP_VP;
|
state = AVB_MRP_VP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_PERIODIC:
|
case AVB_MRP_EVENT_PERIODIC:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
state = AVBTP_MRP_AA;
|
state = AVB_MRP_AA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
state = AVBTP_MRP_AP;
|
state = AVB_MRP_AP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_TX:
|
case AVB_MRP_EVENT_TX:
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
case AVBTP_MRP_LO:
|
case AVB_MRP_LO:
|
||||||
send = get_pending_send(mrp, a, false);
|
send = get_pending_send(mrp, a, false);
|
||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
state = AVBTP_MRP_AA;
|
state = AVB_MRP_AA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
state = AVBTP_MRP_AN;
|
state = AVB_MRP_AN;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
state = AVBTP_MRP_QA;
|
state = AVB_MRP_QA;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
case AVBTP_MRP_LO:
|
case AVB_MRP_LO:
|
||||||
state = AVBTP_MRP_VO;
|
state = AVB_MRP_VO;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_EVENT_TX_LVA:
|
case AVB_MRP_EVENT_TX_LVA:
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VP:
|
case AVB_MRP_VP:
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
case AVBTP_MRP_QA:
|
case AVB_MRP_QA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
send = get_pending_send(mrp, a, true);
|
send = get_pending_send(mrp, a, true);
|
||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVBTP_MRP_VO:
|
case AVB_MRP_VO:
|
||||||
case AVBTP_MRP_LA:
|
case AVB_MRP_LA:
|
||||||
case AVBTP_MRP_AO:
|
case AVB_MRP_AO:
|
||||||
case AVBTP_MRP_QO:
|
case AVB_MRP_QO:
|
||||||
state = AVBTP_MRP_LO;
|
state = AVB_MRP_LO;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_VN:
|
case AVB_MRP_VN:
|
||||||
state = AVBTP_MRP_AN;
|
state = AVB_MRP_AN;
|
||||||
break;
|
break;
|
||||||
case AVBTP_MRP_AN:
|
case AVB_MRP_AN:
|
||||||
case AVBTP_MRP_AA:
|
case AVB_MRP_AA:
|
||||||
case AVBTP_MRP_AP:
|
case AVB_MRP_AP:
|
||||||
case AVBTP_MRP_QP:
|
case AVB_MRP_QP:
|
||||||
state = AVBTP_MRP_QA;
|
state = AVB_MRP_QA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -516,46 +516,46 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
||||||
a->attr.pending_send = send;
|
a->attr.pending_send = send;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_rx_event(struct avbtp_mrp *mrp, uint64_t now,
|
void avb_mrp_rx_event(struct avb_mrp *mrp, uint64_t now,
|
||||||
struct avbtp_mrp_attribute *attr, uint8_t event)
|
struct avb_mrp_attribute *attr, uint8_t event)
|
||||||
{
|
{
|
||||||
static const int map[] = {
|
static const int map[] = {
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_NEW] = AVBTP_MRP_EVENT_RX_NEW,
|
[AVB_MRP_ATTRIBUTE_EVENT_NEW] = AVB_MRP_EVENT_RX_NEW,
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_JOININ] = AVBTP_MRP_EVENT_RX_JOININ,
|
[AVB_MRP_ATTRIBUTE_EVENT_JOININ] = AVB_MRP_EVENT_RX_JOININ,
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_IN] = AVBTP_MRP_EVENT_RX_IN,
|
[AVB_MRP_ATTRIBUTE_EVENT_IN] = AVB_MRP_EVENT_RX_IN,
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_JOINMT] = AVBTP_MRP_EVENT_RX_JOINMT,
|
[AVB_MRP_ATTRIBUTE_EVENT_JOINMT] = AVB_MRP_EVENT_RX_JOINMT,
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_MT] = AVBTP_MRP_EVENT_RX_MT,
|
[AVB_MRP_ATTRIBUTE_EVENT_MT] = AVB_MRP_EVENT_RX_MT,
|
||||||
[AVBTP_MRP_ATTRIBUTE_EVENT_LV] = AVBTP_MRP_EVENT_RX_LV,
|
[AVB_MRP_ATTRIBUTE_EVENT_LV] = AVB_MRP_EVENT_RX_LV,
|
||||||
};
|
};
|
||||||
avbtp_mrp_update_state(mrp, now, attr, map[event]);
|
avb_mrp_update_state(mrp, now, attr, map[event]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_mad_begin(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr)
|
void avb_mrp_mad_begin(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr)
|
||||||
{
|
{
|
||||||
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
|
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
|
||||||
a->leave_timeout = 0;
|
a->leave_timeout = 0;
|
||||||
avbtp_mrp_update_state(mrp, now, attr, AVBTP_MRP_EVENT_BEGIN);
|
avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_BEGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_mad_join(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr, bool is_new)
|
void avb_mrp_mad_join(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr, bool is_new)
|
||||||
{
|
{
|
||||||
if (is_new)
|
if (is_new)
|
||||||
avbtp_mrp_update_state(mrp, now, attr, AVBTP_MRP_EVENT_NEW);
|
avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_NEW);
|
||||||
else
|
else
|
||||||
avbtp_mrp_update_state(mrp, now, attr, AVBTP_MRP_EVENT_JOIN);
|
avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_JOIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_mad_leave(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr)
|
void avb_mrp_mad_leave(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr)
|
||||||
{
|
{
|
||||||
avbtp_mrp_update_state(mrp, now, attr, AVBTP_MRP_EVENT_LV);
|
avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_LV);
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_destroy(struct avbtp_mrp *mrp)
|
void avb_mrp_destroy(struct avb_mrp *mrp)
|
||||||
{
|
{
|
||||||
mrp_destroy(mrp);
|
mrp_destroy(mrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct avbtp_mrp *avbtp_mrp_new(struct server *server)
|
struct avb_mrp *avb_mrp_new(struct server *server)
|
||||||
{
|
{
|
||||||
struct mrp *mrp;
|
struct mrp *mrp;
|
||||||
|
|
||||||
|
|
@ -569,11 +569,11 @@ struct avbtp_mrp *avbtp_mrp_new(struct server *server)
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &mrp->server_listener, &server_events, mrp);
|
avdecc_server_add_listener(server, &mrp->server_listener, &server_events, mrp);
|
||||||
|
|
||||||
return (struct avbtp_mrp*)mrp;
|
return (struct avb_mrp*)mrp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avbtp_mrp_add_listener(struct avbtp_mrp *m, struct spa_hook *listener,
|
void avb_mrp_add_listener(struct avb_mrp *m, struct spa_hook *listener,
|
||||||
const struct avbtp_mrp_events *events, void *data)
|
const struct avb_mrp_events *events, void *data)
|
||||||
{
|
{
|
||||||
struct mrp *mrp = (struct mrp*)m;
|
struct mrp *mrp = (struct mrp*)m;
|
||||||
spa_hook_list_append(&mrp->listener_list, listener, events, data);
|
spa_hook_list_append(&mrp->listener_list, listener, events, data);
|
||||||
171
src/modules/module-avb/mrp.h
Normal file
171
src/modules/module-avb/mrp.h
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
/* AVB support
|
||||||
|
*
|
||||||
|
* Copyright © 2022 Wim Taymans
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVB_MRP_H
|
||||||
|
#define AVB_MRP_H
|
||||||
|
|
||||||
|
#include "packets.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define AVB_MRP_PROTOCOL_VERSION 0
|
||||||
|
|
||||||
|
struct avb_packet_mrp {
|
||||||
|
struct avb_ethernet_header eth;
|
||||||
|
uint8_t version;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_mrp_hdr {
|
||||||
|
uint8_t attribute_type;
|
||||||
|
uint8_t attribute_length;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
struct avb_packet_mrp_vector {
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
unsigned lva:3;
|
||||||
|
unsigned nv1:5;
|
||||||
|
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
unsigned nv1:5;
|
||||||
|
unsigned lva:3;
|
||||||
|
#endif
|
||||||
|
uint8_t nv2;
|
||||||
|
uint8_t first_value[0];
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
#define AVB_MRP_VECTOR_SET_NUM_VALUES(a,v) ((a)->nv1 = ((v) >> 8),(a)->nv2 = (v))
|
||||||
|
#define AVB_MRP_VECTOR_GET_NUM_VALUES(a) ((a)->nv1 << 8 | (a)->nv2)
|
||||||
|
|
||||||
|
struct avb_packet_mrp_footer {
|
||||||
|
uint16_t end_mark;
|
||||||
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
|
/* applicant states */
|
||||||
|
#define AVB_MRP_VO 0 /* Very anxious Observer */
|
||||||
|
#define AVB_MRP_VP 1 /* Very anxious Passive */
|
||||||
|
#define AVB_MRP_VN 2 /* Very anxious New */
|
||||||
|
#define AVB_MRP_AN 3 /* Anxious New */
|
||||||
|
#define AVB_MRP_AA 4 /* Anxious Active */
|
||||||
|
#define AVB_MRP_QA 5 /* Quiet Active */
|
||||||
|
#define AVB_MRP_LA 6 /* Leaving Active */
|
||||||
|
#define AVB_MRP_AO 7 /* Anxious Observer */
|
||||||
|
#define AVB_MRP_QO 8 /* Quiet Observer */
|
||||||
|
#define AVB_MRP_AP 9 /* Anxious Passive */
|
||||||
|
#define AVB_MRP_QP 10 /* Quiet Passive */
|
||||||
|
#define AVB_MRP_LO 11 /* Leaving Observer */
|
||||||
|
|
||||||
|
/* registrar states */
|
||||||
|
#define AVB_MRP_IN 16
|
||||||
|
#define AVB_MRP_LV 17
|
||||||
|
#define AVB_MRP_MT 18
|
||||||
|
|
||||||
|
/* events */
|
||||||
|
#define AVB_MRP_EVENT_BEGIN 0
|
||||||
|
#define AVB_MRP_EVENT_NEW 1
|
||||||
|
#define AVB_MRP_EVENT_JOIN 2
|
||||||
|
#define AVB_MRP_EVENT_LV 3
|
||||||
|
#define AVB_MRP_EVENT_TX 4
|
||||||
|
#define AVB_MRP_EVENT_TX_LVA 5
|
||||||
|
#define AVB_MRP_EVENT_TX_LVAF 6
|
||||||
|
#define AVB_MRP_EVENT_RX_NEW 7
|
||||||
|
#define AVB_MRP_EVENT_RX_JOININ 8
|
||||||
|
#define AVB_MRP_EVENT_RX_IN 9
|
||||||
|
#define AVB_MRP_EVENT_RX_JOINMT 10
|
||||||
|
#define AVB_MRP_EVENT_RX_MT 11
|
||||||
|
#define AVB_MRP_EVENT_RX_LV 12
|
||||||
|
#define AVB_MRP_EVENT_RX_LVA 13
|
||||||
|
#define AVB_MRP_EVENT_FLUSH 14
|
||||||
|
#define AVB_MRP_EVENT_REDECLARE 15
|
||||||
|
#define AVB_MRP_EVENT_PERIODIC 16
|
||||||
|
#define AVB_MRP_EVENT_LV_TIMER 17
|
||||||
|
#define AVB_MRP_EVENT_LVA_TIMER 18
|
||||||
|
|
||||||
|
/* attribute events */
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_NEW 0
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_JOININ 1
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_IN 2
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_JOINMT 3
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_MT 4
|
||||||
|
#define AVB_MRP_ATTRIBUTE_EVENT_LV 5
|
||||||
|
|
||||||
|
#define AVB_MRP_SEND_NEW 1
|
||||||
|
#define AVB_MRP_SEND_JOININ 2
|
||||||
|
#define AVB_MRP_SEND_IN 3
|
||||||
|
#define AVB_MRP_SEND_JOINMT 4
|
||||||
|
#define AVB_MRP_SEND_MT 5
|
||||||
|
#define AVB_MRP_SEND_LV 6
|
||||||
|
|
||||||
|
#define AVB_MRP_NOTIFY_JOIN_NEW (1u<<0)
|
||||||
|
#define AVB_MRP_NOTIFY_JOIN (1u<<1)
|
||||||
|
#define AVB_MRP_NOTIFY_LEAVE (1u<<2)
|
||||||
|
|
||||||
|
struct avb_mrp_attribute {
|
||||||
|
uint8_t pending_send;
|
||||||
|
uint8_t pending_notify;
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct avb_mrp_parse_info {
|
||||||
|
#define AVB_VERSION_MRP_PARSE_INFO 0
|
||||||
|
uint32_t version;
|
||||||
|
|
||||||
|
bool (*check_header) (void *data, const void *hdr, size_t *hdr_size, bool *has_params);
|
||||||
|
|
||||||
|
int (*attr_event) (void *data, uint64_t now, uint8_t attribute_type, uint8_t event);
|
||||||
|
|
||||||
|
int (*process) (void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
||||||
|
uint8_t event, uint8_t param, int index);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int avb_mrp_parse_packet(struct avb_mrp *mrp, uint64_t now, const void *pkt, int size,
|
||||||
|
const struct avb_mrp_parse_info *cb, void *data);
|
||||||
|
|
||||||
|
struct avb_mrp_attribute *avb_mrp_attribute_new(struct avb_mrp *mrp,
|
||||||
|
size_t user_size);
|
||||||
|
|
||||||
|
void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
|
||||||
|
struct avb_mrp_attribute *attr, int event);
|
||||||
|
|
||||||
|
void avb_mrp_rx_event(struct avb_mrp *mrp, uint64_t now,
|
||||||
|
struct avb_mrp_attribute *attr, uint8_t event);
|
||||||
|
|
||||||
|
void avb_mrp_mad_begin(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr);
|
||||||
|
void avb_mrp_mad_join(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr, bool is_new);
|
||||||
|
void avb_mrp_mad_leave(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr);
|
||||||
|
|
||||||
|
struct avb_mrp_events {
|
||||||
|
#define AVB_VERSION_MRP_ATTRIBUTE_CALLBACKS 0
|
||||||
|
uint32_t version;
|
||||||
|
|
||||||
|
void (*event) (void *data, uint64_t now, uint8_t event);
|
||||||
|
|
||||||
|
void (*notify) (void *data, uint64_t now, struct avb_mrp_attribute *attr, uint8_t notify);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct avb_mrp *avb_mrp_new(struct server *server);
|
||||||
|
void avb_mrp_destroy(struct avb_mrp *mrp);
|
||||||
|
|
||||||
|
void avb_mrp_add_listener(struct avb_mrp *mrp, struct spa_hook *listener,
|
||||||
|
const struct avb_mrp_events *events, void *data);
|
||||||
|
|
||||||
|
#endif /* AVB_MRP_H */
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
static const uint8_t mac[6] = AVB_MSRP_MAC;
|
static const uint8_t mac[6] = AVB_MSRP_MAC;
|
||||||
|
|
||||||
struct attr {
|
struct attr {
|
||||||
struct avbtp_msrp_attribute attr;
|
struct avb_msrp_attribute attr;
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -44,11 +44,11 @@ struct msrp {
|
||||||
struct spa_list attributes;
|
struct spa_list attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void debug_msrp_talker_common(const struct avbtp_packet_msrp_talker *t)
|
static void debug_msrp_talker_common(const struct avb_packet_msrp_talker *t)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
pw_log_info(" stream-id: %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(t->stream_id)));
|
pw_log_info(" stream-id: %s", avb_utils_format_id(buf, sizeof(buf), be64toh(t->stream_id)));
|
||||||
pw_log_info(" dest-addr: %s", avbtp_utils_format_addr(buf, sizeof(buf), t->dest_addr));
|
pw_log_info(" dest-addr: %s", avb_utils_format_addr(buf, sizeof(buf), t->dest_addr));
|
||||||
pw_log_info(" vlan-id: %d", ntohs(t->vlan_id));
|
pw_log_info(" vlan-id: %d", ntohs(t->vlan_id));
|
||||||
pw_log_info(" tspec-max-frame-size: %d", ntohs(t->tspec_max_frame_size));
|
pw_log_info(" tspec-max-frame-size: %d", ntohs(t->tspec_max_frame_size));
|
||||||
pw_log_info(" tspec-max-interval-frames: %d", ntohs(t->tspec_max_interval_frames));
|
pw_log_info(" tspec-max-interval-frames: %d", ntohs(t->tspec_max_interval_frames));
|
||||||
|
|
@ -57,7 +57,7 @@ static void debug_msrp_talker_common(const struct avbtp_packet_msrp_talker *t)
|
||||||
pw_log_info(" accumulated-latency: %d", ntohl(t->accumulated_latency));
|
pw_log_info(" accumulated-latency: %d", ntohl(t->accumulated_latency));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_msrp_talker(const struct avbtp_packet_msrp_talker *t)
|
static void debug_msrp_talker(const struct avb_packet_msrp_talker *t)
|
||||||
{
|
{
|
||||||
pw_log_info("talker");
|
pw_log_info("talker");
|
||||||
debug_msrp_talker_common(t);
|
debug_msrp_talker_common(t);
|
||||||
|
|
@ -72,30 +72,30 @@ static void notify_talker(struct msrp *msrp, uint64_t now, struct attr *attr, ui
|
||||||
static int process_talker(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
static int process_talker(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num)
|
const void *m, uint8_t event, uint8_t param, int num)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_msrp_talker *t = m;
|
const struct avb_packet_msrp_talker *t = m;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &msrp->attributes, link)
|
spa_list_for_each(a, &msrp->attributes, link)
|
||||||
if (a->attr.type == attr_type &&
|
if (a->attr.type == attr_type &&
|
||||||
a->attr.attr.talker.stream_id == t->stream_id) {
|
a->attr.attr.talker.stream_id == t->stream_id) {
|
||||||
a->attr.attr.talker = *t;
|
a->attr.attr.talker = *t;
|
||||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_msrp_talker_fail(const struct avbtp_packet_msrp_talker_fail *t)
|
static void debug_msrp_talker_fail(const struct avb_packet_msrp_talker_fail *t)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
pw_log_info("talker fail");
|
pw_log_info("talker fail");
|
||||||
debug_msrp_talker_common(&t->talker);
|
debug_msrp_talker_common(&t->talker);
|
||||||
pw_log_info(" bridge-id: %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(t->bridge_id)));
|
pw_log_info(" bridge-id: %s", avb_utils_format_id(buf, sizeof(buf), be64toh(t->bridge_id)));
|
||||||
pw_log_info(" failure-code: %d", t->failure_code);
|
pw_log_info(" failure-code: %d", t->failure_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_talker_fail(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
static int process_talker_fail(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num)
|
const void *m, uint8_t event, uint8_t param, int num)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_msrp_talker_fail *t = m;
|
const struct avb_packet_msrp_talker_fail *t = m;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
debug_msrp_talker_fail(t);
|
debug_msrp_talker_fail(t);
|
||||||
|
|
@ -103,15 +103,15 @@ static int process_talker_fail(struct msrp *msrp, uint64_t now, uint8_t attr_typ
|
||||||
spa_list_for_each(a, &msrp->attributes, link)
|
spa_list_for_each(a, &msrp->attributes, link)
|
||||||
if (a->attr.type == attr_type &&
|
if (a->attr.type == attr_type &&
|
||||||
a->attr.attr.talker_fail.talker.stream_id == t->talker.stream_id)
|
a->attr.attr.talker_fail.talker.stream_id == t->talker.stream_id)
|
||||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_msrp_listener(const struct avbtp_packet_msrp_listener *l)
|
static void debug_msrp_listener(const struct avb_packet_msrp_listener *l)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
pw_log_info("listener");
|
pw_log_info("listener");
|
||||||
pw_log_info(" %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(l->stream_id)));
|
pw_log_info(" %s", avb_utils_format_id(buf, sizeof(buf), be64toh(l->stream_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
||||||
|
|
@ -123,32 +123,32 @@ static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr,
|
||||||
static int process_listener(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
static int process_listener(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num)
|
const void *m, uint8_t event, uint8_t param, int num)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_msrp_listener *l = m;
|
const struct avb_packet_msrp_listener *l = m;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &msrp->attributes, link)
|
spa_list_for_each(a, &msrp->attributes, link)
|
||||||
if (a->attr.type == attr_type &&
|
if (a->attr.type == attr_type &&
|
||||||
a->attr.attr.listener.stream_id == l->stream_id)
|
a->attr.attr.listener.stream_id == l->stream_id)
|
||||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
|
static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
|
||||||
{
|
{
|
||||||
struct avbtp_packet_msrp_msg *msg = m;
|
struct avb_packet_msrp_msg *msg = m;
|
||||||
struct avbtp_packet_mrp_vector *v;
|
struct avb_packet_mrp_vector *v;
|
||||||
struct avbtp_packet_msrp_listener *l;
|
struct avb_packet_msrp_listener *l;
|
||||||
struct avbtp_packet_mrp_footer *f;
|
struct avb_packet_mrp_footer *f;
|
||||||
uint8_t *ev;
|
uint8_t *ev;
|
||||||
size_t attr_list_length = sizeof(*v) + sizeof(*l) + sizeof(*f) + 1 + 1;
|
size_t attr_list_length = sizeof(*v) + sizeof(*l) + sizeof(*f) + 1 + 1;
|
||||||
|
|
||||||
msg->attribute_type = AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER;
|
msg->attribute_type = AVB_MSRP_ATTRIBUTE_TYPE_LISTENER;
|
||||||
msg->attribute_length = sizeof(*l);
|
msg->attribute_length = sizeof(*l);
|
||||||
msg->attribute_list_length = htons(attr_list_length);
|
msg->attribute_list_length = htons(attr_list_length);
|
||||||
|
|
||||||
v = (struct avbtp_packet_mrp_vector *)msg->attribute_list;
|
v = (struct avb_packet_mrp_vector *)msg->attribute_list;
|
||||||
v->lva = 0;
|
v->lva = 0;
|
||||||
AVBTP_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
AVB_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
||||||
|
|
||||||
l = (struct avbtp_packet_msrp_listener *)v->first_value;
|
l = (struct avb_packet_msrp_listener *)v->first_value;
|
||||||
*l = a->attr.attr.listener;
|
*l = a->attr.attr.listener;
|
||||||
|
|
||||||
ev = SPA_PTROFF(l, sizeof(*l), uint8_t);
|
ev = SPA_PTROFF(l, sizeof(*l), uint8_t);
|
||||||
|
|
@ -157,14 +157,14 @@ static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
|
||||||
ev = SPA_PTROFF(ev, sizeof(*ev), uint8_t);
|
ev = SPA_PTROFF(ev, sizeof(*ev), uint8_t);
|
||||||
*ev = a->attr.param * 4 * 4 * 4;
|
*ev = a->attr.param * 4 * 4 * 4;
|
||||||
|
|
||||||
f = SPA_PTROFF(ev, sizeof(*ev), struct avbtp_packet_mrp_footer);
|
f = SPA_PTROFF(ev, sizeof(*ev), struct avb_packet_mrp_footer);
|
||||||
f->end_mark = 0;
|
f->end_mark = 0;
|
||||||
|
|
||||||
return attr_list_length + sizeof(*msg);
|
return attr_list_length + sizeof(*msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void debug_msrp_domain(const struct avbtp_packet_msrp_domain *d)
|
static void debug_msrp_domain(const struct avb_packet_msrp_domain *d)
|
||||||
{
|
{
|
||||||
pw_log_info("domain");
|
pw_log_info("domain");
|
||||||
pw_log_info(" %d", d->sr_class_id);
|
pw_log_info(" %d", d->sr_class_id);
|
||||||
|
|
@ -184,34 +184,34 @@ static int process_domain(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &msrp->attributes, link)
|
spa_list_for_each(a, &msrp->attributes, link)
|
||||||
if (a->attr.type == attr_type)
|
if (a->attr.type == attr_type)
|
||||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int encode_domain(struct msrp *msrp, struct attr *a, void *m)
|
static int encode_domain(struct msrp *msrp, struct attr *a, void *m)
|
||||||
{
|
{
|
||||||
struct avbtp_packet_msrp_msg *msg = m;
|
struct avb_packet_msrp_msg *msg = m;
|
||||||
struct avbtp_packet_mrp_vector *v;
|
struct avb_packet_mrp_vector *v;
|
||||||
struct avbtp_packet_msrp_domain *d;
|
struct avb_packet_msrp_domain *d;
|
||||||
struct avbtp_packet_mrp_footer *f;
|
struct avb_packet_mrp_footer *f;
|
||||||
uint8_t *ev;
|
uint8_t *ev;
|
||||||
size_t attr_list_length = sizeof(*v) + sizeof(*d) + sizeof(*f) + 1;
|
size_t attr_list_length = sizeof(*v) + sizeof(*d) + sizeof(*f) + 1;
|
||||||
|
|
||||||
msg->attribute_type = AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN;
|
msg->attribute_type = AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN;
|
||||||
msg->attribute_length = sizeof(*d);
|
msg->attribute_length = sizeof(*d);
|
||||||
msg->attribute_list_length = htons(attr_list_length);
|
msg->attribute_list_length = htons(attr_list_length);
|
||||||
|
|
||||||
v = (struct avbtp_packet_mrp_vector *)msg->attribute_list;
|
v = (struct avb_packet_mrp_vector *)msg->attribute_list;
|
||||||
v->lva = 0;
|
v->lva = 0;
|
||||||
AVBTP_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
AVB_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
||||||
|
|
||||||
d = (struct avbtp_packet_msrp_domain *)v->first_value;
|
d = (struct avb_packet_msrp_domain *)v->first_value;
|
||||||
*d = a->attr.attr.domain;
|
*d = a->attr.attr.domain;
|
||||||
|
|
||||||
ev = SPA_PTROFF(d, sizeof(*d), uint8_t);
|
ev = SPA_PTROFF(d, sizeof(*d), uint8_t);
|
||||||
*ev = a->attr.mrp->pending_send * 36;
|
*ev = a->attr.mrp->pending_send * 36;
|
||||||
|
|
||||||
f = SPA_PTROFF(ev, sizeof(*ev), struct avbtp_packet_mrp_footer);
|
f = SPA_PTROFF(ev, sizeof(*ev), struct avb_packet_mrp_footer);
|
||||||
f->end_mark = 0;
|
f->end_mark = 0;
|
||||||
|
|
||||||
return attr_list_length + sizeof(*msg);
|
return attr_list_length + sizeof(*msg);
|
||||||
|
|
@ -223,22 +223,22 @@ static const struct {
|
||||||
int (*encode) (struct msrp *msrp, struct attr *attr, void *m);
|
int (*encode) (struct msrp *msrp, struct attr *attr, void *m);
|
||||||
void (*notify) (struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify);
|
void (*notify) (struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify);
|
||||||
} dispatch[] = {
|
} dispatch[] = {
|
||||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { process_talker, NULL, notify_talker, },
|
[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { process_talker, NULL, notify_talker, },
|
||||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { process_talker_fail, NULL, NULL },
|
[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { process_talker_fail, NULL, NULL },
|
||||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER] = { process_listener, encode_listener, notify_listener },
|
[AVB_MSRP_ATTRIBUTE_TYPE_LISTENER] = { process_listener, encode_listener, notify_listener },
|
||||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { process_domain, encode_domain, notify_domain, },
|
[AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { process_domain, encode_domain, notify_domain, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool msrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
static bool msrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_msrp_msg *msg = hdr;
|
const struct avb_packet_msrp_msg *msg = hdr;
|
||||||
uint8_t attr_type = msg->attribute_type;
|
uint8_t attr_type = msg->attribute_type;
|
||||||
|
|
||||||
if (!AVBTP_MSRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
if (!AVB_MSRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*hdr_size = sizeof(*msg);
|
*hdr_size = sizeof(*msg);
|
||||||
*has_params = attr_type == AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER;
|
*has_params = attr_type == AVB_MSRP_ATTRIBUTE_TYPE_LISTENER;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,7 +248,7 @@ static int msrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &msrp->attributes, link)
|
spa_list_for_each(a, &msrp->attributes, link)
|
||||||
if (a->attr.type == attribute_type)
|
if (a->attr.type == attribute_type)
|
||||||
avbtp_mrp_update_state(msrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_update_state(msrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,8 +260,8 @@ static int msrp_process(void *data, uint64_t now, uint8_t attribute_type, const
|
||||||
attribute_type, value, event, param, index);
|
attribute_type, value, event, param, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct avbtp_mrp_parse_info info = {
|
static const struct avb_mrp_parse_info info = {
|
||||||
AVBTP_VERSION_MRP_PARSE_INFO,
|
AVB_VERSION_MRP_PARSE_INFO,
|
||||||
.check_header = msrp_check_header,
|
.check_header = msrp_check_header,
|
||||||
.attr_event = msrp_attr_event,
|
.attr_event = msrp_attr_event,
|
||||||
.process = msrp_process,
|
.process = msrp_process,
|
||||||
|
|
@ -271,7 +271,7 @@ static const struct avbtp_mrp_parse_info info = {
|
||||||
static int msrp_message(void *data, uint64_t now, const void *message, int len)
|
static int msrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct msrp *msrp = data;
|
struct msrp *msrp = data;
|
||||||
const struct avbtp_packet_mrp *p = message;
|
const struct avb_packet_mrp *p = message;
|
||||||
|
|
||||||
if (ntohs(p->eth.type) != AVB_MSRP_ETH)
|
if (ntohs(p->eth.type) != AVB_MSRP_ETH)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -279,7 +279,7 @@ static int msrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pw_log_debug("MSRP");
|
pw_log_debug("MSRP");
|
||||||
return avbtp_mrp_parse_packet(msrp->server->mrp,
|
return avb_mrp_parse_packet(msrp->server->mrp,
|
||||||
now, message, len, &info, msrp);
|
now, message, len, &info, msrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,19 +291,19 @@ static void msrp_destroy(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = msrp_destroy,
|
.destroy = msrp_destroy,
|
||||||
.message = msrp_message
|
.message = msrp_message
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_msrp_attribute *avbtp_msrp_attribute_new(struct avbtp_msrp *m,
|
struct avb_msrp_attribute *avb_msrp_attribute_new(struct avb_msrp *m,
|
||||||
uint8_t type)
|
uint8_t type)
|
||||||
{
|
{
|
||||||
struct msrp *msrp = (struct msrp*)m;
|
struct msrp *msrp = (struct msrp*)m;
|
||||||
struct avbtp_mrp_attribute *attr;
|
struct avb_mrp_attribute *attr;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
attr = avbtp_mrp_attribute_new(msrp->server->mrp, sizeof(struct attr));
|
attr = avb_mrp_attribute_new(msrp->server->mrp, sizeof(struct attr));
|
||||||
|
|
||||||
a = attr->user_data;
|
a = attr->user_data;
|
||||||
a->attr.mrp = attr;
|
a->attr.mrp = attr;
|
||||||
|
|
@ -317,14 +317,14 @@ static void msrp_event(void *data, uint64_t now, uint8_t event)
|
||||||
{
|
{
|
||||||
struct msrp *msrp = data;
|
struct msrp *msrp = data;
|
||||||
uint8_t buffer[2048];
|
uint8_t buffer[2048];
|
||||||
struct avbtp_packet_mrp *p = (struct avbtp_packet_mrp*)buffer;
|
struct avb_packet_mrp *p = (struct avb_packet_mrp*)buffer;
|
||||||
struct avbtp_packet_mrp_footer *f;
|
struct avb_packet_mrp_footer *f;
|
||||||
void *msg = SPA_PTROFF(buffer, sizeof(*p), void);
|
void *msg = SPA_PTROFF(buffer, sizeof(*p), void);
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
int len, count = 0;
|
int len, count = 0;
|
||||||
size_t total = sizeof(*p) + 2;
|
size_t total = sizeof(*p) + 2;
|
||||||
|
|
||||||
p->version = AVBTP_MRP_PROTOCOL_VERSION;
|
p->version = AVB_MRP_PROTOCOL_VERSION;
|
||||||
|
|
||||||
spa_list_for_each(a, &msrp->attributes, link) {
|
spa_list_for_each(a, &msrp->attributes, link) {
|
||||||
if (!a->attr.mrp->pending_send)
|
if (!a->attr.mrp->pending_send)
|
||||||
|
|
@ -340,15 +340,15 @@ static void msrp_event(void *data, uint64_t now, uint8_t event)
|
||||||
msg = SPA_PTROFF(msg, len, void);
|
msg = SPA_PTROFF(msg, len, void);
|
||||||
total += len;
|
total += len;
|
||||||
}
|
}
|
||||||
f = (struct avbtp_packet_mrp_footer *)msg;
|
f = (struct avb_packet_mrp_footer *)msg;
|
||||||
f->end_mark = 0;
|
f->end_mark = 0;
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
avbtp_server_send_packet(msrp->server, mac, AVB_MSRP_ETH,
|
avb_server_send_packet(msrp->server, mac, AVB_MSRP_ETH,
|
||||||
buffer, total);
|
buffer, total);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msrp_notify(void *data, uint64_t now, struct avbtp_mrp_attribute *attr, uint8_t notify)
|
static void msrp_notify(void *data, uint64_t now, struct avb_mrp_attribute *attr, uint8_t notify)
|
||||||
{
|
{
|
||||||
struct msrp *msrp = data;
|
struct msrp *msrp = data;
|
||||||
struct attr *a = attr->user_data;
|
struct attr *a = attr->user_data;
|
||||||
|
|
@ -356,13 +356,13 @@ static void msrp_notify(void *data, uint64_t now, struct avbtp_mrp_attribute *at
|
||||||
dispatch[a->attr.type].notify(msrp, now, a, notify);
|
dispatch[a->attr.type].notify(msrp, now, a, notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct avbtp_mrp_events mrp_events = {
|
static const struct avb_mrp_events mrp_events = {
|
||||||
AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS,
|
AVB_VERSION_MRP_ATTRIBUTE_CALLBACKS,
|
||||||
.event = msrp_event,
|
.event = msrp_event,
|
||||||
.notify = msrp_notify
|
.notify = msrp_notify
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_msrp *avbtp_msrp_register(struct server *server)
|
struct avb_msrp *avb_msrp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct msrp *msrp;
|
struct msrp *msrp;
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ struct avbtp_msrp *avbtp_msrp_register(struct server *server)
|
||||||
spa_list_init(&msrp->attributes);
|
spa_list_init(&msrp->attributes);
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &msrp->server_listener, &server_events, msrp);
|
avdecc_server_add_listener(server, &msrp->server_listener, &server_events, msrp);
|
||||||
avbtp_mrp_add_listener(server->mrp, &msrp->mrp_listener, &mrp_events, msrp);
|
avb_mrp_add_listener(server->mrp, &msrp->mrp_listener, &mrp_events, msrp);
|
||||||
|
|
||||||
return (struct avbtp_msrp*)msrp;
|
return (struct avb_msrp*)msrp;
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_MSRP_H
|
#ifndef AVB_MSRP_H
|
||||||
#define AVBTP_MSRP_H
|
#define AVB_MSRP_H
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "mrp.h"
|
#include "mrp.h"
|
||||||
|
|
@ -31,24 +31,24 @@
|
||||||
#define AVB_MSRP_ETH 0x22ea
|
#define AVB_MSRP_ETH 0x22ea
|
||||||
#define AVB_MSRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0xe };
|
#define AVB_MSRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0xe };
|
||||||
|
|
||||||
#define AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE 1
|
#define AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE 1
|
||||||
#define AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED 2
|
#define AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED 2
|
||||||
#define AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER 3
|
#define AVB_MSRP_ATTRIBUTE_TYPE_LISTENER 3
|
||||||
#define AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN 4
|
#define AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN 4
|
||||||
#define AVBTP_MSRP_ATTRIBUTE_TYPE_VALID(t) ((t)>=1 && (t)<=4)
|
#define AVB_MSRP_ATTRIBUTE_TYPE_VALID(t) ((t)>=1 && (t)<=4)
|
||||||
|
|
||||||
struct avbtp_packet_msrp_msg {
|
struct avb_packet_msrp_msg {
|
||||||
uint8_t attribute_type;
|
uint8_t attribute_type;
|
||||||
uint8_t attribute_length;
|
uint8_t attribute_length;
|
||||||
uint16_t attribute_list_length;
|
uint16_t attribute_list_length;
|
||||||
uint8_t attribute_list[0];
|
uint8_t attribute_list[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_MSRP_TSPEC_MAX_INTERVAL_FRAMES_DEFAULT 1
|
#define AVB_MSRP_TSPEC_MAX_INTERVAL_FRAMES_DEFAULT 1
|
||||||
#define AVBTP_MSRP_RANK_DEFAULT 1
|
#define AVB_MSRP_RANK_DEFAULT 1
|
||||||
#define AVBTP_MSRP_PRIORITY_DEFAULT 3
|
#define AVB_MSRP_PRIORITY_DEFAULT 3
|
||||||
|
|
||||||
struct avbtp_packet_msrp_talker {
|
struct avb_packet_msrp_talker {
|
||||||
uint64_t stream_id;
|
uint64_t stream_id;
|
||||||
uint8_t dest_addr[6];
|
uint8_t dest_addr[6];
|
||||||
uint16_t vlan_id;
|
uint16_t vlan_id;
|
||||||
|
|
@ -67,65 +67,65 @@ struct avbtp_packet_msrp_talker {
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
/* failure codes */
|
/* failure codes */
|
||||||
#define AVBTP_MRP_FAIL_BANDWIDTH 1
|
#define AVB_MRP_FAIL_BANDWIDTH 1
|
||||||
#define AVBTP_MRP_FAIL_BRIDGE 2
|
#define AVB_MRP_FAIL_BRIDGE 2
|
||||||
#define AVBTP_MRP_FAIL_TC_BANDWIDTH 3
|
#define AVB_MRP_FAIL_TC_BANDWIDTH 3
|
||||||
#define AVBTP_MRP_FAIL_ID_BUSY 4
|
#define AVB_MRP_FAIL_ID_BUSY 4
|
||||||
#define AVBTP_MRP_FAIL_DSTADDR_BUSY 5
|
#define AVB_MRP_FAIL_DSTADDR_BUSY 5
|
||||||
#define AVBTP_MRP_FAIL_PREEMPTED 6
|
#define AVB_MRP_FAIL_PREEMPTED 6
|
||||||
#define AVBTP_MRP_FAIL_LATENCY_CHNG 7
|
#define AVB_MRP_FAIL_LATENCY_CHNG 7
|
||||||
#define AVBTP_MRP_FAIL_PORT_NOT_AVB 8
|
#define AVB_MRP_FAIL_PORT_NOT_AVB 8
|
||||||
#define AVBTP_MRP_FAIL_DSTADDR_FULL 9
|
#define AVB_MRP_FAIL_DSTADDR_FULL 9
|
||||||
#define AVBTP_MRP_FAIL_AVBTP_MRP_RESOURCE 10
|
#define AVB_MRP_FAIL_AVB_MRP_RESOURCE 10
|
||||||
#define AVBTP_MRP_FAIL_MMRP_RESOURCE 11
|
#define AVB_MRP_FAIL_MMRP_RESOURCE 11
|
||||||
#define AVBTP_MRP_FAIL_DSTADDR_FAIL 12
|
#define AVB_MRP_FAIL_DSTADDR_FAIL 12
|
||||||
#define AVBTP_MRP_FAIL_PRIO_NOT_SR 13
|
#define AVB_MRP_FAIL_PRIO_NOT_SR 13
|
||||||
#define AVBTP_MRP_FAIL_FRAME_SIZE 14
|
#define AVB_MRP_FAIL_FRAME_SIZE 14
|
||||||
#define AVBTP_MRP_FAIL_FANIN_EXCEED 15
|
#define AVB_MRP_FAIL_FANIN_EXCEED 15
|
||||||
#define AVBTP_MRP_FAIL_STREAM_CHANGE 16
|
#define AVB_MRP_FAIL_STREAM_CHANGE 16
|
||||||
#define AVBTP_MRP_FAIL_VLAN_BLOCKED 17
|
#define AVB_MRP_FAIL_VLAN_BLOCKED 17
|
||||||
#define AVBTP_MRP_FAIL_VLAN_DISABLED 18
|
#define AVB_MRP_FAIL_VLAN_DISABLED 18
|
||||||
#define AVBTP_MRP_FAIL_SR_PRIO_ERR 19
|
#define AVB_MRP_FAIL_SR_PRIO_ERR 19
|
||||||
|
|
||||||
struct avbtp_packet_msrp_talker_fail {
|
struct avb_packet_msrp_talker_fail {
|
||||||
struct avbtp_packet_msrp_talker talker;
|
struct avb_packet_msrp_talker talker;
|
||||||
uint64_t bridge_id;
|
uint64_t bridge_id;
|
||||||
uint8_t failure_code;
|
uint8_t failure_code;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_packet_msrp_listener {
|
struct avb_packet_msrp_listener {
|
||||||
uint64_t stream_id;
|
uint64_t stream_id;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
/* domain discovery */
|
/* domain discovery */
|
||||||
struct avbtp_packet_msrp_domain {
|
struct avb_packet_msrp_domain {
|
||||||
uint8_t sr_class_id;
|
uint8_t sr_class_id;
|
||||||
uint8_t sr_class_priority;
|
uint8_t sr_class_priority;
|
||||||
uint16_t sr_class_vid;
|
uint16_t sr_class_vid;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_MSRP_LISTENER_PARAM_IGNORE 0
|
#define AVB_MSRP_LISTENER_PARAM_IGNORE 0
|
||||||
#define AVBTP_MSRP_LISTENER_PARAM_ASKING_FAILED 1
|
#define AVB_MSRP_LISTENER_PARAM_ASKING_FAILED 1
|
||||||
#define AVBTP_MSRP_LISTENER_PARAM_READY 2
|
#define AVB_MSRP_LISTENER_PARAM_READY 2
|
||||||
#define AVBTP_MSRP_LISTENER_PARAM_READY_FAILED 3
|
#define AVB_MSRP_LISTENER_PARAM_READY_FAILED 3
|
||||||
|
|
||||||
struct avbtp_msrp_attribute {
|
struct avb_msrp_attribute {
|
||||||
struct avbtp_mrp_attribute *mrp;
|
struct avb_mrp_attribute *mrp;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t param;
|
uint8_t param;
|
||||||
union {
|
union {
|
||||||
struct avbtp_packet_msrp_talker talker;
|
struct avb_packet_msrp_talker talker;
|
||||||
struct avbtp_packet_msrp_talker_fail talker_fail;
|
struct avb_packet_msrp_talker_fail talker_fail;
|
||||||
struct avbtp_packet_msrp_listener listener;
|
struct avb_packet_msrp_listener listener;
|
||||||
struct avbtp_packet_msrp_domain domain;
|
struct avb_packet_msrp_domain domain;
|
||||||
} attr;
|
} attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_msrp;
|
struct avb_msrp;
|
||||||
|
|
||||||
struct avbtp_msrp_attribute *avbtp_msrp_attribute_new(struct avbtp_msrp *msrp,
|
struct avb_msrp_attribute *avb_msrp_attribute_new(struct avb_msrp *msrp,
|
||||||
uint8_t type);
|
uint8_t type);
|
||||||
|
|
||||||
struct avbtp_msrp *avbtp_msrp_register(struct server *server);
|
struct avb_msrp *avb_msrp_register(struct server *server);
|
||||||
|
|
||||||
#endif /* AVBTP_MSRP_H */
|
#endif /* AVB_MSRP_H */
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
static const uint8_t mac[6] = AVB_MVRP_MAC;
|
static const uint8_t mac[6] = AVB_MVRP_MAC;
|
||||||
|
|
||||||
struct attr {
|
struct attr {
|
||||||
struct avbtp_mvrp_attribute attr;
|
struct avb_mvrp_attribute attr;
|
||||||
struct spa_list link;
|
struct spa_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -42,10 +42,10 @@ struct mvrp {
|
||||||
|
|
||||||
static bool mvrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
static bool mvrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_mvrp_msg *msg = hdr;
|
const struct avb_packet_mvrp_msg *msg = hdr;
|
||||||
uint8_t attr_type = msg->attribute_type;
|
uint8_t attr_type = msg->attribute_type;
|
||||||
|
|
||||||
if (!AVBTP_MVRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
if (!AVB_MVRP_ATTRIBUTE_TYPE_VALID(attr_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*hdr_size = sizeof(*msg);
|
*hdr_size = sizeof(*msg);
|
||||||
|
|
@ -59,13 +59,13 @@ static int mvrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
spa_list_for_each(a, &mvrp->attributes, link)
|
spa_list_for_each(a, &mvrp->attributes, link)
|
||||||
if (a->attr.type == attribute_type)
|
if (a->attr.type == attribute_type)
|
||||||
avbtp_mrp_update_state(mvrp->server->mrp, now, a->attr.mrp, event);
|
avb_mrp_update_state(mvrp->server->mrp, now, a->attr.mrp, event);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_vid(const void *p)
|
static void debug_vid(const void *p)
|
||||||
{
|
{
|
||||||
const struct avbtp_packet_mvrp_vid *t = p;
|
const struct avb_packet_mvrp_vid *t = p;
|
||||||
pw_log_info("vid");
|
pw_log_info("vid");
|
||||||
pw_log_info(" %d", ntohs(t->vlan));
|
pw_log_info(" %d", ntohs(t->vlan));
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ static const struct {
|
||||||
int (*dispatch) (struct mvrp *mvrp, uint64_t now, uint8_t attr_type,
|
int (*dispatch) (struct mvrp *mvrp, uint64_t now, uint8_t attr_type,
|
||||||
const void *m, uint8_t event, uint8_t param, int num);
|
const void *m, uint8_t event, uint8_t param, int num);
|
||||||
} dispatch[] = {
|
} dispatch[] = {
|
||||||
[AVBTP_MVRP_ATTRIBUTE_TYPE_VID] = { debug_vid, process_vid, },
|
[AVB_MVRP_ATTRIBUTE_TYPE_VID] = { debug_vid, process_vid, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mvrp_process(void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
static int mvrp_process(void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
||||||
|
|
@ -92,8 +92,8 @@ static int mvrp_process(void *data, uint64_t now, uint8_t attribute_type, const
|
||||||
attribute_type, value, event, param, index);
|
attribute_type, value, event, param, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct avbtp_mrp_parse_info info = {
|
static const struct avb_mrp_parse_info info = {
|
||||||
AVBTP_VERSION_MRP_PARSE_INFO,
|
AVB_VERSION_MRP_PARSE_INFO,
|
||||||
.check_header = mvrp_check_header,
|
.check_header = mvrp_check_header,
|
||||||
.attr_event = mvrp_attr_event,
|
.attr_event = mvrp_attr_event,
|
||||||
.process = mvrp_process,
|
.process = mvrp_process,
|
||||||
|
|
@ -102,7 +102,7 @@ static const struct avbtp_mrp_parse_info info = {
|
||||||
static int mvrp_message(void *data, uint64_t now, const void *message, int len)
|
static int mvrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
{
|
{
|
||||||
struct mvrp *mvrp = data;
|
struct mvrp *mvrp = data;
|
||||||
const struct avbtp_packet_mrp *p = message;
|
const struct avb_packet_mrp *p = message;
|
||||||
|
|
||||||
if (ntohs(p->eth.type) != AVB_MVRP_ETH)
|
if (ntohs(p->eth.type) != AVB_MVRP_ETH)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -110,7 +110,7 @@ static int mvrp_message(void *data, uint64_t now, const void *message, int len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pw_log_debug("MVRP");
|
pw_log_debug("MVRP");
|
||||||
return avbtp_mrp_parse_packet(mvrp->server->mrp,
|
return avb_mrp_parse_packet(mvrp->server->mrp,
|
||||||
now, message, len, &info, mvrp);
|
now, message, len, &info, mvrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,19 +122,19 @@ static void mvrp_destroy(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = mvrp_destroy,
|
.destroy = mvrp_destroy,
|
||||||
.message = mvrp_message
|
.message = mvrp_message
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_mvrp_attribute *avbtp_mvrp_attribute_new(struct avbtp_mvrp *m,
|
struct avb_mvrp_attribute *avb_mvrp_attribute_new(struct avb_mvrp *m,
|
||||||
uint8_t type)
|
uint8_t type)
|
||||||
{
|
{
|
||||||
struct mvrp *mvrp = (struct mvrp*)m;
|
struct mvrp *mvrp = (struct mvrp*)m;
|
||||||
struct avbtp_mrp_attribute *attr;
|
struct avb_mrp_attribute *attr;
|
||||||
struct attr *a;
|
struct attr *a;
|
||||||
|
|
||||||
attr = avbtp_mrp_attribute_new(mvrp->server->mrp, sizeof(struct attr));
|
attr = avb_mrp_attribute_new(mvrp->server->mrp, sizeof(struct attr));
|
||||||
|
|
||||||
a = attr->user_data;
|
a = attr->user_data;
|
||||||
a->attr.mrp = attr;
|
a->attr.mrp = attr;
|
||||||
|
|
@ -144,7 +144,7 @@ struct avbtp_mvrp_attribute *avbtp_mvrp_attribute_new(struct avbtp_mvrp *m,
|
||||||
return &a->attr;
|
return &a->attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct avbtp_mvrp *avbtp_mvrp_register(struct server *server)
|
struct avb_mvrp *avb_mvrp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct mvrp *mvrp;
|
struct mvrp *mvrp;
|
||||||
|
|
||||||
|
|
@ -157,5 +157,5 @@ struct avbtp_mvrp *avbtp_mvrp_register(struct server *server)
|
||||||
|
|
||||||
avdecc_server_add_listener(server, &mvrp->server_listener, &server_events, mvrp);
|
avdecc_server_add_listener(server, &mvrp->server_listener, &server_events, mvrp);
|
||||||
|
|
||||||
return (struct avbtp_mvrp*)mvrp;
|
return (struct avb_mvrp*)mvrp;
|
||||||
}
|
}
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_MVRP_H
|
#ifndef AVB_MVRP_H
|
||||||
#define AVBTP_MVRP_H
|
#define AVB_MVRP_H
|
||||||
|
|
||||||
#include "mrp.h"
|
#include "mrp.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
@ -31,32 +31,32 @@
|
||||||
#define AVB_MVRP_ETH 0x88f5
|
#define AVB_MVRP_ETH 0x88f5
|
||||||
#define AVB_MVRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 };
|
#define AVB_MVRP_MAC { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 };
|
||||||
|
|
||||||
struct avbtp_packet_mvrp_msg {
|
struct avb_packet_mvrp_msg {
|
||||||
uint8_t attribute_type;
|
uint8_t attribute_type;
|
||||||
uint8_t attribute_length;
|
uint8_t attribute_length;
|
||||||
uint8_t attribute_list[0];
|
uint8_t attribute_list[0];
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_MVRP_ATTRIBUTE_TYPE_VID 1
|
#define AVB_MVRP_ATTRIBUTE_TYPE_VID 1
|
||||||
#define AVBTP_MVRP_ATTRIBUTE_TYPE_VALID(t) ((t)==1)
|
#define AVB_MVRP_ATTRIBUTE_TYPE_VALID(t) ((t)==1)
|
||||||
|
|
||||||
struct avbtp_packet_mvrp_vid {
|
struct avb_packet_mvrp_vid {
|
||||||
uint16_t vlan;
|
uint16_t vlan;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_mvrp;
|
struct avb_mvrp;
|
||||||
|
|
||||||
struct avbtp_mvrp_attribute {
|
struct avb_mvrp_attribute {
|
||||||
struct avbtp_mrp_attribute *mrp;
|
struct avb_mrp_attribute *mrp;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
union {
|
union {
|
||||||
struct avbtp_packet_mvrp_vid vid;
|
struct avb_packet_mvrp_vid vid;
|
||||||
} attr;
|
} attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct avbtp_mvrp_attribute *avbtp_mvrp_attribute_new(struct avbtp_mvrp *mvrp,
|
struct avb_mvrp_attribute *avb_mvrp_attribute_new(struct avb_mvrp *mvrp,
|
||||||
uint8_t type);
|
uint8_t type);
|
||||||
|
|
||||||
struct avbtp_mvrp *avbtp_mvrp_register(struct server *server);
|
struct avb_mvrp *avb_mvrp_register(struct server *server);
|
||||||
|
|
||||||
#endif /* AVBTP_MVRP_H */
|
#endif /* AVB_MVRP_H */
|
||||||
|
|
@ -22,40 +22,40 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_PACKETS_H
|
#ifndef AVB_PACKETS_H
|
||||||
#define AVBTP_PACKETS_H
|
#define AVB_PACKETS_H
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#define AVBTP_SUBTYPE_61883_IIDC 0x00
|
#define AVB_SUBTYPE_61883_IIDC 0x00
|
||||||
#define AVBTP_SUBTYPE_MMA_STREAM 0x01
|
#define AVB_SUBTYPE_MMA_STREAM 0x01
|
||||||
#define AVBTP_SUBTYPE_AAF 0x02
|
#define AVB_SUBTYPE_AAF 0x02
|
||||||
#define AVBTP_SUBTYPE_CVF 0x03
|
#define AVB_SUBTYPE_CVF 0x03
|
||||||
#define AVBTP_SUBTYPE_CRF 0x04
|
#define AVB_SUBTYPE_CRF 0x04
|
||||||
#define AVBTP_SUBTYPE_TSCF 0x05
|
#define AVB_SUBTYPE_TSCF 0x05
|
||||||
#define AVBTP_SUBTYPE_SVF 0x06
|
#define AVB_SUBTYPE_SVF 0x06
|
||||||
#define AVBTP_SUBTYPE_RVF 0x07
|
#define AVB_SUBTYPE_RVF 0x07
|
||||||
#define AVBTP_SUBTYPE_AEF_CONTINUOUS 0x6E
|
#define AVB_SUBTYPE_AEF_CONTINUOUS 0x6E
|
||||||
#define AVBTP_SUBTYPE_VSF_STREAM 0x6F
|
#define AVB_SUBTYPE_VSF_STREAM 0x6F
|
||||||
#define AVBTP_SUBTYPE_EF_STREAM 0x7F
|
#define AVB_SUBTYPE_EF_STREAM 0x7F
|
||||||
#define AVBTP_SUBTYPE_NTSCF 0x82
|
#define AVB_SUBTYPE_NTSCF 0x82
|
||||||
#define AVBTP_SUBTYPE_ESCF 0xEC
|
#define AVB_SUBTYPE_ESCF 0xEC
|
||||||
#define AVBTP_SUBTYPE_EECF 0xED
|
#define AVB_SUBTYPE_EECF 0xED
|
||||||
#define AVBTP_SUBTYPE_AEF_DISCRETE 0xEE
|
#define AVB_SUBTYPE_AEF_DISCRETE 0xEE
|
||||||
#define AVBTP_SUBTYPE_ADP 0xFA
|
#define AVB_SUBTYPE_ADP 0xFA
|
||||||
#define AVBTP_SUBTYPE_AECP 0xFB
|
#define AVB_SUBTYPE_AECP 0xFB
|
||||||
#define AVBTP_SUBTYPE_ACMP 0xFC
|
#define AVB_SUBTYPE_ACMP 0xFC
|
||||||
#define AVBTP_SUBTYPE_MAAP 0xFE
|
#define AVB_SUBTYPE_MAAP 0xFE
|
||||||
#define AVBTP_SUBTYPE_EF_CONTROL 0xFF
|
#define AVB_SUBTYPE_EF_CONTROL 0xFF
|
||||||
|
|
||||||
struct avbtp_ethernet_header {
|
struct avb_ethernet_header {
|
||||||
uint8_t dest[6];
|
uint8_t dest[6];
|
||||||
uint8_t src[6];
|
uint8_t src[6];
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
struct avbtp_packet_header {
|
struct avb_packet_header {
|
||||||
struct avbtp_ethernet_header eth;
|
struct avb_ethernet_header eth;
|
||||||
uint8_t subtype;
|
uint8_t subtype;
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
unsigned sv:1; /* stream_id valid */
|
unsigned sv:1; /* stream_id valid */
|
||||||
|
|
@ -77,18 +77,18 @@ struct avbtp_packet_header {
|
||||||
uint8_t len2:8;
|
uint8_t len2:8;
|
||||||
} __attribute__ ((__packed__));
|
} __attribute__ ((__packed__));
|
||||||
|
|
||||||
#define AVBTP_PACKET_SET_SUBTYPE(p,v) ((p)->subtype = (v))
|
#define AVB_PACKET_SET_SUBTYPE(p,v) ((p)->subtype = (v))
|
||||||
#define AVBTP_PACKET_SET_SV(p,v) ((p)->sv = (v))
|
#define AVB_PACKET_SET_SV(p,v) ((p)->sv = (v))
|
||||||
#define AVBTP_PACKET_SET_VERSION(p,v) ((p)->version = (v))
|
#define AVB_PACKET_SET_VERSION(p,v) ((p)->version = (v))
|
||||||
#define AVBTP_PACKET_SET_SUB1(p,v) ((p)->subtype_data1 = (v))
|
#define AVB_PACKET_SET_SUB1(p,v) ((p)->subtype_data1 = (v))
|
||||||
#define AVBTP_PACKET_SET_SUB2(p,v) ((p)->subtype_data2 = (v))
|
#define AVB_PACKET_SET_SUB2(p,v) ((p)->subtype_data2 = (v))
|
||||||
#define AVBTP_PACKET_SET_LENGTH(p,v) ((p)->len1 = ((v) >> 8),(p)->len2 = (v))
|
#define AVB_PACKET_SET_LENGTH(p,v) ((p)->len1 = ((v) >> 8),(p)->len2 = (v))
|
||||||
|
|
||||||
#define AVBTP_PACKET_GET_SUBTYPE(p) ((p)->subtype)
|
#define AVB_PACKET_GET_SUBTYPE(p) ((p)->subtype)
|
||||||
#define AVBTP_PACKET_GET_SV(p) ((p)->sv)
|
#define AVB_PACKET_GET_SV(p) ((p)->sv)
|
||||||
#define AVBTP_PACKET_GET_VERSION(p) ((p)->version)
|
#define AVB_PACKET_GET_VERSION(p) ((p)->version)
|
||||||
#define AVBTP_PACKET_GET_SUB1(p) ((p)->subtype_data1)
|
#define AVB_PACKET_GET_SUB1(p) ((p)->subtype_data1)
|
||||||
#define AVBTP_PACKET_GET_SUB2(p) ((p)->subtype_data2)
|
#define AVB_PACKET_GET_SUB2(p) ((p)->subtype_data2)
|
||||||
#define AVBTP_PACKET_GET_LENGTH(p) ((p)->len1 << 8 | (p)->len2)
|
#define AVB_PACKET_GET_LENGTH(p) ((p)->len1 << 8 | (p)->len2)
|
||||||
|
|
||||||
#endif /* AVBTP_PACKETS_H */
|
#endif /* AVB_PACKETS_H */
|
||||||
|
|
@ -39,11 +39,11 @@ static void srp_destroy(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct server_events server_events = {
|
static const struct server_events server_events = {
|
||||||
AVBTP_VERSION_SERVER_EVENTS,
|
AVB_VERSION_SERVER_EVENTS,
|
||||||
.destroy = srp_destroy,
|
.destroy = srp_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
int avbtp_srp_register(struct server *server)
|
int avb_srp_register(struct server *server)
|
||||||
{
|
{
|
||||||
struct srp *srp;
|
struct srp *srp;
|
||||||
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_SRP_H
|
#ifndef AVB_SRP_H
|
||||||
#define AVBTP_SRP_H
|
#define AVB_SRP_H
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
int avbtp_srp_register(struct server *server);
|
int avb_srp_register(struct server *server);
|
||||||
|
|
||||||
#endif /* AVBTP_SRP_H */
|
#endif /* AVB_SRP_H */
|
||||||
|
|
@ -22,14 +22,14 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVBTP_UTILS_H
|
#ifndef AVB_UTILS_H
|
||||||
#define AVBTP_UTILS_H
|
#define AVB_UTILS_H
|
||||||
|
|
||||||
#include <spa/utils/json.h>
|
#include <spa/utils/json.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static inline char *avbtp_utils_format_id(char *str, size_t size, const uint64_t id)
|
static inline char *avb_utils_format_id(char *str, size_t size, const uint64_t id)
|
||||||
{
|
{
|
||||||
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x:%04x",
|
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x:%04x",
|
||||||
(uint8_t)(id >> 56),
|
(uint8_t)(id >> 56),
|
||||||
|
|
@ -42,7 +42,7 @@ static inline char *avbtp_utils_format_id(char *str, size_t size, const uint64_t
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int avbtp_utils_parse_id(const char *str, int len, uint64_t *id)
|
static inline int avb_utils_parse_id(const char *str, int len, uint64_t *id)
|
||||||
{
|
{
|
||||||
char s[64];
|
char s[64];
|
||||||
uint8_t v[6];
|
uint8_t v[6];
|
||||||
|
|
@ -64,11 +64,11 @@ static inline int avbtp_utils_parse_id(const char *str, int len, uint64_t *id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *avbtp_utils_format_addr(char *str, size_t size, const uint8_t addr[6])
|
static inline char *avb_utils_format_addr(char *str, size_t size, const uint8_t addr[6])
|
||||||
{
|
{
|
||||||
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x",
|
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* AVBTP_UTILS_H */
|
#endif /* AVB_UTILS_H */
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
/* PipeWire
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <spa/utils/result.h>
|
|
||||||
#include <spa/utils/string.h>
|
|
||||||
#include <spa/utils/json.h>
|
|
||||||
|
|
||||||
#include <pipewire/impl.h>
|
|
||||||
#include <pipewire/private.h>
|
|
||||||
#include <pipewire/i18n.h>
|
|
||||||
|
|
||||||
#include "module-avbtp/avb.h"
|
|
||||||
|
|
||||||
/** \page page_module_avb PipeWire Module: AVB
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NAME "avb"
|
|
||||||
|
|
||||||
PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
|
||||||
#define PW_LOG_TOPIC_DEFAULT mod_topic
|
|
||||||
|
|
||||||
#define MODULE_USAGE " "
|
|
||||||
|
|
||||||
static const struct spa_dict_item module_props[] = {
|
|
||||||
{ PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
|
|
||||||
{ PW_KEY_MODULE_DESCRIPTION, "Manage an AVB network" },
|
|
||||||
{ PW_KEY_MODULE_USAGE, MODULE_USAGE },
|
|
||||||
{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct impl {
|
|
||||||
struct pw_context *context;
|
|
||||||
|
|
||||||
struct pw_impl_module *module;
|
|
||||||
struct spa_hook module_listener;
|
|
||||||
|
|
||||||
struct pw_properties *properties;
|
|
||||||
|
|
||||||
struct pw_avb *avb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void impl_free(struct impl *impl)
|
|
||||||
{
|
|
||||||
pw_properties_free(impl->properties);
|
|
||||||
free(impl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void module_destroy(void *data)
|
|
||||||
{
|
|
||||||
struct impl *impl = data;
|
|
||||||
spa_hook_remove(&impl->module_listener);
|
|
||||||
impl_free(impl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct pw_impl_module_events module_events = {
|
|
||||||
PW_VERSION_IMPL_MODULE_EVENTS,
|
|
||||||
.destroy = module_destroy,
|
|
||||||
};
|
|
||||||
|
|
||||||
SPA_EXPORT
|
|
||||||
int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
|
||||||
{
|
|
||||||
struct pw_context *context = pw_impl_module_get_context(module);
|
|
||||||
struct pw_properties *props;
|
|
||||||
struct impl *impl;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
PW_LOG_TOPIC_INIT(mod_topic);
|
|
||||||
|
|
||||||
impl = calloc(1, sizeof(struct impl));
|
|
||||||
if (impl == NULL)
|
|
||||||
goto error_errno;
|
|
||||||
|
|
||||||
pw_log_debug("module %p: new %s", impl, args);
|
|
||||||
|
|
||||||
if (args == NULL)
|
|
||||||
args = "";
|
|
||||||
|
|
||||||
props = pw_properties_new_string(args);
|
|
||||||
if (props == NULL)
|
|
||||||
goto error_errno;
|
|
||||||
|
|
||||||
impl->module = module;
|
|
||||||
impl->context = context;
|
|
||||||
impl->properties = props;
|
|
||||||
|
|
||||||
impl->avb = pw_avb_new(context, props, 0);
|
|
||||||
if (impl->avb == NULL)
|
|
||||||
goto error_errno;
|
|
||||||
|
|
||||||
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
|
|
||||||
|
|
||||||
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_errno:
|
|
||||||
res = -errno;
|
|
||||||
if (impl)
|
|
||||||
impl_free(impl);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
@ -1,140 +0,0 @@
|
||||||
/* AVBTP support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_AAF_H
|
|
||||||
#define AVBTP_AAF_H
|
|
||||||
|
|
||||||
struct avbtp_packet_aaf {
|
|
||||||
struct avbtp_ethernet_header hdr;
|
|
||||||
uint8_t subtype;
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
unsigned sv:1;
|
|
||||||
unsigned version:3;
|
|
||||||
unsigned mr:1;
|
|
||||||
unsigned _r1:1;
|
|
||||||
unsigned gv:1;
|
|
||||||
unsigned tv:1;
|
|
||||||
|
|
||||||
uint8_t seq_number;
|
|
||||||
|
|
||||||
unsigned _r2:7;
|
|
||||||
unsigned tu:1;
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
unsigned tv:1;
|
|
||||||
unsigned gv:1;
|
|
||||||
unsigned _r1:1;
|
|
||||||
unsigned mr:1;
|
|
||||||
unsigned version:3;
|
|
||||||
unsigned sv:1;
|
|
||||||
|
|
||||||
uint8_t seq_num;
|
|
||||||
|
|
||||||
unsigned tu:1;
|
|
||||||
unsigned _r2:7;
|
|
||||||
#endif
|
|
||||||
uint64_t stream_id;
|
|
||||||
uint32_t timestamp;
|
|
||||||
#define AVBTP_AAF_FORMAT_USER 0x00
|
|
||||||
#define AVBTP_AAF_FORMAT_FLOAT_32BIT 0x01
|
|
||||||
#define AVBTP_AAF_FORMAT_INT_32BIT 0x02
|
|
||||||
#define AVBTP_AAF_FORMAT_INT_24BIT 0x03
|
|
||||||
#define AVBTP_AAF_FORMAT_INT_16BIT 0x04
|
|
||||||
#define AVBTP_AAF_FORMAT_AES3_32BIT 0x05
|
|
||||||
uint8_t format;
|
|
||||||
|
|
||||||
#define AVBTP_AAF_PCM_NSR_USER 0x00
|
|
||||||
#define AVBTP_AAF_PCM_NSR_8KHZ 0x01
|
|
||||||
#define AVBTP_AAF_PCM_NSR_16KHZ 0x02
|
|
||||||
#define AVBTP_AAF_PCM_NSR_32KHZ 0x03
|
|
||||||
#define AVBTP_AAF_PCM_NSR_44_1KHZ 0x04
|
|
||||||
#define AVBTP_AAF_PCM_NSR_48KHZ 0x05
|
|
||||||
#define AVBTP_AAF_PCM_NSR_88_2KHZ 0x06
|
|
||||||
#define AVBTP_AAF_PCM_NSR_96KHZ 0x07
|
|
||||||
#define AVBTP_AAF_PCM_NSR_176_4KHZ 0x08
|
|
||||||
#define AVBTP_AAF_PCM_NSR_192KHZ 0x09
|
|
||||||
#define AVBTP_AAF_PCM_NSR_24KHZ 0x0A
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
unsigned nsr:4;
|
|
||||||
unsigned _r3:4;
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
unsigned _r3:4;
|
|
||||||
unsigned nsr:4;
|
|
||||||
#endif
|
|
||||||
uint8_t chan_per_frame;
|
|
||||||
uint8_t bit_depth;
|
|
||||||
uint16_t data_len;
|
|
||||||
|
|
||||||
#define AVBTP_AAF_PCM_SP_NORMAL 0x00
|
|
||||||
#define AVBTP_AAF_PCM_SP_SPARSE 0x01
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
unsigned _r4:3;
|
|
||||||
unsigned sp:1;
|
|
||||||
unsigned event:4;
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
unsigned event:4;
|
|
||||||
unsigned sp:1;
|
|
||||||
unsigned _r4:3;
|
|
||||||
#endif
|
|
||||||
uint8_t _r5;
|
|
||||||
uint8_t payload[0];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_AAF_SET_SUBTYPE(p,v) ((p)->subtype = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_SV(p,v) ((p)->sv = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_VERSION(p,v) ((p)->version = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_MR(p,v) ((p)->mr = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_GV(p,v) ((p)->gv = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_TV(p,v) ((p)->tv = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_SEQ_NUM(p,v) ((p)->seq_num = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_TU(p,v) ((p)->tu = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_STREAM_ID(p,v) ((p)->stream_id = htobe64(v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_TIMESTAMP(p,v) ((p)->timestamp = htonl(v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_DATA_LEN(p,v) ((p)->data_len = htons(v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_FORMAT(p,v) ((p)->format = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_NSR(p,v) ((p)->nsr = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_CHAN_PER_FRAME(p,v) ((p)->chan_per_frame = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_BIT_DEPTH(p,v) ((p)->bit_depth = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_SP(p,v) ((p)->sp = (v))
|
|
||||||
#define AVBTP_PACKET_AAF_SET_EVENT(p,v) ((p)->event = (v))
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_AAF_GET_SUBTYPE(p) ((p)->subtype)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_SV(p) ((p)->sv)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_VERSION(p) ((p)->version)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_MR(p) ((p)->mr)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_GV(p) ((p)->gv)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_TV(p) ((p)->tv)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_SEQ_NUM(p) ((p)->seq_num)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_TU(p) ((p)->tu)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_STREAM_ID(p) be64toh((p)->stream_id)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_TIMESTAMP(p) ntohl((p)->timestamp)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_DATA_LEN(p) ntohs((p)->data_len)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_FORMAT(p) ((p)->format)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_NSR(p) ((p)->nsr)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_CHAN_PER_FRAME(p) ((p)->chan_per_frame)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_BIT_DEPTH(p) ((p)->bit_depth)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_SP(p) ((p)->sp)
|
|
||||||
#define AVBTP_PACKET_AAF_GET_EVENT(p) ((p)->event)
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* AVBTP_AAF_H */
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_ACMP_H
|
|
||||||
#define AVBTP_ACMP_H
|
|
||||||
|
|
||||||
#include "packets.h"
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND 0
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE 1
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND 2
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE 3
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND 4
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE 5
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND 6
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE 7
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND 8
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE 9
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND 10
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE 11
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND 12
|
|
||||||
#define AVBTP_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE 13
|
|
||||||
|
|
||||||
#define AVBTP_ACMP_STATUS_SUCCESS 0
|
|
||||||
#define AVBTP_ACMP_STATUS_LISTENER_UNKNOWN_ID 1
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_UNKNOWN_ID 2
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_DEST_MAC_FAIL 3
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_NO_STREAM_INDEX 4
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_NO_BANDWIDTH 5
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_EXCLUSIVE 6
|
|
||||||
#define AVBTP_ACMP_STATUS_LISTENER_TALKER_TIMEOUT 7
|
|
||||||
#define AVBTP_ACMP_STATUS_LISTENER_EXCLUSIVE 8
|
|
||||||
#define AVBTP_ACMP_STATUS_STATE_UNAVAILABLE 9
|
|
||||||
#define AVBTP_ACMP_STATUS_NOT_CONNECTED 10
|
|
||||||
#define AVBTP_ACMP_STATUS_NO_SUCH_CONNECTION 11
|
|
||||||
#define AVBTP_ACMP_STATUS_COULD_NOT_SEND_MESSAGE 12
|
|
||||||
#define AVBTP_ACMP_STATUS_TALKER_MISBEHAVING 13
|
|
||||||
#define AVBTP_ACMP_STATUS_LISTENER_MISBEHAVING 14
|
|
||||||
#define AVBTP_ACMP_STATUS_RESERVED 15
|
|
||||||
#define AVBTP_ACMP_STATUS_CONTROLLER_NOT_AUTHORIZED 16
|
|
||||||
#define AVBTP_ACMP_STATUS_INCOMPATIBLE_REQUEST 17
|
|
||||||
#define AVBTP_ACMP_STATUS_LISTENER_INVALID_CONNECTION 18
|
|
||||||
#define AVBTP_ACMP_STATUS_NOT_SUPPORTED 31
|
|
||||||
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS 2000
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS 200
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_GET_TX_STATE_COMMAND 200
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_CONNECT_RX_COMMAND_MS 4500
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_DISCONNECT_RX_COMMAND_MS 500
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_GET_RX_STATE_COMMAND_MS 200
|
|
||||||
#define AVBTP_ACMP_TIMEOUT_GET_TX_CONNECTION_COMMAND 200
|
|
||||||
|
|
||||||
struct avbtp_packet_acmp {
|
|
||||||
struct avbtp_packet_header hdr;
|
|
||||||
uint64_t stream_id;
|
|
||||||
uint64_t controller_guid;
|
|
||||||
uint64_t talker_guid;
|
|
||||||
uint64_t listener_guid;
|
|
||||||
uint16_t talker_unique_id;
|
|
||||||
uint16_t listener_unique_id;
|
|
||||||
char stream_dest_mac[6];
|
|
||||||
uint16_t connection_count;
|
|
||||||
uint16_t sequence_id;
|
|
||||||
uint16_t flags;
|
|
||||||
uint16_t stream_vlan_id;
|
|
||||||
uint16_t reserved;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(p,v) AVBTP_PACKET_SET_SUB1(&(p)->hdr, v)
|
|
||||||
#define AVBTP_PACKET_ACMP_SET_STATUS(p,v) AVBTP_PACKET_SET_SUB2(&(p)->hdr, v)
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_ACMP_GET_MESSAGE_TYPE(p) AVBTP_PACKET_GET_SUB1(&(p)->hdr)
|
|
||||||
#define AVBTP_PACKET_ACMP_GET_STATUS(p) AVBTP_PACKET_GET_SUB2(&(p)->hdr)
|
|
||||||
|
|
||||||
struct avbtp_acmp *avbtp_acmp_register(struct server *server);
|
|
||||||
|
|
||||||
#endif /* AVBTP_ACMP_H */
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_ADP_H
|
|
||||||
#define AVBTP_ADP_H
|
|
||||||
|
|
||||||
#include "packets.h"
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#define AVBTP_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE 0
|
|
||||||
#define AVBTP_ADP_MESSAGE_TYPE_ENTITY_DEPARTING 1
|
|
||||||
#define AVBTP_ADP_MESSAGE_TYPE_ENTITY_DISCOVER 2
|
|
||||||
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_EFU_MODE (1u<<0)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_ADDRESS_ACCESS_SUPPORTED (1u<<1)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_GATEWAY_ENTITY (1u<<2)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_SUPPORTED (1u<<3)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_LEGACY_AVC (1u<<4)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_ASSOCIATION_ID_SUPPORTED (1u<<5)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_ASSOCIATION_ID_VALID (1u<<6)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_VENDOR_UNIQUE_SUPPORTED (1u<<7)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_CLASS_A_SUPPORTED (1u<<8)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_CLASS_B_SUPPORTED (1u<<9)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_GPTP_SUPPORTED (1u<<10)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_AUTHENTICATION_SUPPORTED (1u<<11)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_AUTHENTICATION_REQUIRED (1u<<12)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_PERSISTENT_ACQUIRE_SUPPORTED (1u<<13)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_IDENTIFY_CONTROL_INDEX_VALID (1u<<14)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_AEM_INTERFACE_INDEX_VALID (1u<<15)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_GENERAL_CONTROLLER_IGNORE (1u<<16)
|
|
||||||
#define AVBTP_ADP_ENTITY_CAPABILITY_ENTITY_NOT_READY (1u<<17)
|
|
||||||
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_IMPLEMENTED (1u<<0)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_OTHER_SOURCE (1u<<9)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_CONTROL_SOURCE (1u<<10)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_MEDIA_CLOCK_SOURCE (1u<<11)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_SMPTE_SOURCE (1u<<12)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_MIDI_SOURCE (1u<<13)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_AUDIO_SOURCE (1u<<14)
|
|
||||||
#define AVBTP_ADP_TALKER_CAPABILITY_VIDEO_SOURCE (1u<<15)
|
|
||||||
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_IMPLEMENTED (1u<<0)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_OTHER_SINK (1u<<9)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_CONTROL_SINK (1u<<10)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_MEDIA_CLOCK_SINK (1u<<11)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_SMPTE_SINK (1u<<12)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_MIDI_SINK (1u<<13)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_AUDIO_SINK (1u<<14)
|
|
||||||
#define AVBTP_ADP_LISTENER_CAPABILITY_VIDEO_SINK (1u<<15)
|
|
||||||
|
|
||||||
#define AVBTP_ADP_CONTROLLER_CAPABILITY_IMPLEMENTED (1u<<0)
|
|
||||||
#define AVBTP_ADP_CONTROLLER_CAPABILITY_LAYER3_PROXY (1u<<1)
|
|
||||||
|
|
||||||
#define AVBTP_ADP_CONTROL_DATA_LENGTH 56
|
|
||||||
|
|
||||||
struct avbtp_packet_adp {
|
|
||||||
struct avbtp_packet_header hdr;
|
|
||||||
uint64_t entity_id;
|
|
||||||
uint64_t entity_model_id;
|
|
||||||
uint32_t entity_capabilities;
|
|
||||||
uint16_t talker_stream_sources;
|
|
||||||
uint16_t talker_capabilities;
|
|
||||||
uint16_t listener_stream_sinks;
|
|
||||||
uint16_t listener_capabilities;
|
|
||||||
uint32_t controller_capabilities;
|
|
||||||
uint32_t available_index;
|
|
||||||
uint64_t gptp_grandmaster_id;
|
|
||||||
uint8_t gptp_domain_number;
|
|
||||||
uint8_t reserved0[3];
|
|
||||||
uint16_t identify_control_index;
|
|
||||||
uint16_t interface_index;
|
|
||||||
uint64_t association_id;
|
|
||||||
uint32_t reserved1;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_ADP_SET_MESSAGE_TYPE(p,v) AVBTP_PACKET_SET_SUB1(&(p)->hdr, v)
|
|
||||||
#define AVBTP_PACKET_ADP_SET_VALID_TIME(p,v) AVBTP_PACKET_SET_SUB2(&(p)->hdr, v)
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_ADP_GET_MESSAGE_TYPE(p) AVBTP_PACKET_GET_SUB1(&(p)->hdr)
|
|
||||||
#define AVBTP_PACKET_ADP_GET_VALID_TIME(p) AVBTP_PACKET_GET_SUB2(&(p)->hdr)
|
|
||||||
|
|
||||||
struct avbtp_adp *avbtp_adp_register(struct server *server);
|
|
||||||
|
|
||||||
#endif /* AVBTP_ADP_H */
|
|
||||||
|
|
@ -1,283 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "aecp-aem.h"
|
|
||||||
#include "aecp-aem-descriptors.h"
|
|
||||||
|
|
||||||
static int reply_status(struct aecp *aecp, int status, const void *m, int len)
|
|
||||||
{
|
|
||||||
struct server *server = aecp->server;
|
|
||||||
uint8_t buf[len];
|
|
||||||
struct avbtp_packet_aecp_header *reply = (struct avbtp_packet_aecp_header*)buf;
|
|
||||||
|
|
||||||
memcpy(reply, m, len);
|
|
||||||
AVBTP_PACKET_AECP_SET_MESSAGE_TYPE(reply, AVBTP_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
|
||||||
AVBTP_PACKET_AECP_SET_STATUS(reply, status);
|
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->hdr.eth.src,
|
|
||||||
AVB_TSN_ETH, reply, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int reply_not_implemented(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_NOT_IMPLEMENTED, m, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int reply_success(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_SUCCESS, m, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ACQUIRE_ENTITY */
|
|
||||||
static int handle_acquire_entity(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
struct server *server = aecp->server;
|
|
||||||
const struct avbtp_packet_aecp_aem *p = m;
|
|
||||||
const struct avbtp_packet_aecp_aem_acquire *ae;
|
|
||||||
const struct descriptor *desc;
|
|
||||||
uint16_t desc_type, desc_id;
|
|
||||||
|
|
||||||
ae = (const struct avbtp_packet_aecp_aem_acquire*)p->payload;
|
|
||||||
|
|
||||||
desc_type = ntohs(ae->descriptor_type);
|
|
||||||
desc_id = ntohs(ae->descriptor_id);
|
|
||||||
|
|
||||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
|
||||||
if (desc == NULL)
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
|
||||||
|
|
||||||
if (desc_type != AVBTP_AEM_DESC_ENTITY || desc_id != 0)
|
|
||||||
return reply_not_implemented(aecp, m, len);
|
|
||||||
|
|
||||||
return reply_success(aecp, m, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* LOCK_ENTITY */
|
|
||||||
static int handle_lock_entity(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
struct server *server = aecp->server;
|
|
||||||
const struct avbtp_packet_aecp_aem *p = m;
|
|
||||||
const struct avbtp_packet_aecp_aem_acquire *ae;
|
|
||||||
const struct descriptor *desc;
|
|
||||||
uint16_t desc_type, desc_id;
|
|
||||||
|
|
||||||
ae = (const struct avbtp_packet_aecp_aem_acquire*)p->payload;
|
|
||||||
|
|
||||||
desc_type = ntohs(ae->descriptor_type);
|
|
||||||
desc_id = ntohs(ae->descriptor_id);
|
|
||||||
|
|
||||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
|
||||||
if (desc == NULL)
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
|
||||||
|
|
||||||
if (desc_type != AVBTP_AEM_DESC_ENTITY || desc_id != 0)
|
|
||||||
return reply_not_implemented(aecp, m, len);
|
|
||||||
|
|
||||||
return reply_success(aecp, m, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* READ_DESCRIPTOR */
|
|
||||||
static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
struct server *server = aecp->server;
|
|
||||||
const struct avbtp_packet_aecp_aem *p = m;
|
|
||||||
struct avbtp_packet_aecp_aem *reply;
|
|
||||||
const struct avbtp_packet_aecp_aem_read_descriptor *rd;
|
|
||||||
uint16_t desc_type, desc_id;
|
|
||||||
const struct descriptor *desc;
|
|
||||||
uint8_t buf[2048];
|
|
||||||
size_t size, psize;
|
|
||||||
|
|
||||||
rd = (struct avbtp_packet_aecp_aem_read_descriptor*)p->payload;
|
|
||||||
|
|
||||||
desc_type = ntohs(rd->descriptor_type);
|
|
||||||
desc_id = ntohs(rd->descriptor_id);
|
|
||||||
|
|
||||||
pw_log_info("descriptor type:%04x index:%d", desc_type, desc_id);
|
|
||||||
|
|
||||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
|
||||||
if (desc == NULL)
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
|
||||||
|
|
||||||
memcpy(buf, p, len);
|
|
||||||
|
|
||||||
psize = sizeof(*rd);
|
|
||||||
size = sizeof(*reply) + psize;
|
|
||||||
|
|
||||||
memcpy(buf + size, desc->ptr, desc->size);
|
|
||||||
size += desc->size;
|
|
||||||
psize += desc->size;
|
|
||||||
|
|
||||||
reply = (struct avbtp_packet_aecp_aem*)buf;
|
|
||||||
AVBTP_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVBTP_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
|
||||||
AVBTP_PACKET_AECP_SET_STATUS(&reply->aecp, AVBTP_AECP_AEM_STATUS_SUCCESS);
|
|
||||||
AVBTP_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->aecp.hdr.eth.src,
|
|
||||||
AVB_TSN_ETH, reply, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GET_AVB_INFO */
|
|
||||||
static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
struct server *server = aecp->server;
|
|
||||||
const struct avbtp_packet_aecp_aem *p = m;
|
|
||||||
struct avbtp_packet_aecp_aem *reply;
|
|
||||||
struct avbtp_packet_aecp_aem_get_avb_info *i;
|
|
||||||
struct avbtp_aem_desc_avb_interface *avb_interface;
|
|
||||||
uint16_t desc_type, desc_id;
|
|
||||||
const struct descriptor *desc;
|
|
||||||
uint8_t buf[2048];
|
|
||||||
size_t size, psize;
|
|
||||||
|
|
||||||
i = (struct avbtp_packet_aecp_aem_get_avb_info*)p->payload;
|
|
||||||
|
|
||||||
desc_type = ntohs(i->descriptor_type);
|
|
||||||
desc_id = ntohs(i->descriptor_id);
|
|
||||||
|
|
||||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
|
||||||
if (desc == NULL)
|
|
||||||
return reply_status(aecp, AVBTP_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
|
||||||
|
|
||||||
if (desc_type != AVBTP_AEM_DESC_AVB_INTERFACE || desc_id != 0)
|
|
||||||
return reply_not_implemented(aecp, m, len);
|
|
||||||
|
|
||||||
avb_interface = desc->ptr;
|
|
||||||
|
|
||||||
memcpy(buf, p, len);
|
|
||||||
|
|
||||||
psize = sizeof(*i);
|
|
||||||
size = sizeof(*reply) + psize;
|
|
||||||
|
|
||||||
reply = (struct avbtp_packet_aecp_aem *)buf;
|
|
||||||
AVBTP_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVBTP_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
|
||||||
AVBTP_PACKET_AECP_SET_STATUS(&reply->aecp, AVBTP_AECP_AEM_STATUS_SUCCESS);
|
|
||||||
AVBTP_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
|
||||||
|
|
||||||
i = (struct avbtp_packet_aecp_aem_get_avb_info*)reply->payload;
|
|
||||||
i->gptp_grandmaster_id = avb_interface->clock_identity;
|
|
||||||
i->propagation_delay = htonl(0);
|
|
||||||
i->gptp_domain_number = avb_interface->domain_number;
|
|
||||||
i->flags = 0;
|
|
||||||
i->msrp_mappings_count = htons(0);
|
|
||||||
|
|
||||||
return avbtp_server_send_packet(server, reply->aecp.hdr.eth.src,
|
|
||||||
AVB_TSN_ETH, reply, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AEM_COMMAND */
|
|
||||||
struct cmd_info {
|
|
||||||
uint16_t type;
|
|
||||||
const char *name;
|
|
||||||
int (*handle) (struct aecp *aecp, const void *p, int len);
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct cmd_info cmd_info[] = {
|
|
||||||
{ AVBTP_AECP_AEM_CMD_ACQUIRE_ENTITY, "acquire-entity", handle_acquire_entity, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_LOCK_ENTITY, "lock-entity", handle_lock_entity, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_ENTITY_AVAILABLE, "entity-available", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_CONTROLLER_AVAILABLE, "controller-available", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_READ_DESCRIPTOR, "read-descriptor", handle_read_descriptor, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_WRITE_DESCRIPTOR, "write-descriptor", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_CONFIGURATION, "set-configuration", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_CONFIGURATION, "get-configuration", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_STREAM_FORMAT, "set-stream-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_STREAM_FORMAT, "get-stream-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_VIDEO_FORMAT, "set-video-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_VIDEO_FORMAT, "get-video-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_SENSOR_FORMAT, "set-sensor-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_SENSOR_FORMAT, "get-sensor-format", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_STREAM_INFO, "set-stream-info", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_STREAM_INFO, "get-stream-info", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_NAME, "set-name", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_NAME, "get-name", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_ASSOCIATION_ID, "set-association-id", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_ASSOCIATION_ID, "get-association-id", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_SAMPLING_RATE, "set-sampling-rate", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_SAMPLING_RATE, "get-sampling-rate", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_CLOCK_SOURCE, "set-clock-source", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_CLOCK_SOURCE, "get-clock-source", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_CONTROL, "set-control", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_CONTROL, "get-control", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_INCREMENT_CONTROL, "increment-control", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_DECREMENT_CONTROL, "decrement-control", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_SIGNAL_SELECTOR, "set-signal-selector", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_SIGNAL_SELECTOR, "get-signal-selector", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_MIXER, "set-mixer", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_MIXER, "get-mixer", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_SET_MATRIX, "set-matrix", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_MATRIX, "get-matrix", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_START_STREAMING, "start-streaming", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_STOP_STREAMING, "stop-streaming", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_REGISTER_UNSOLICITED_NOTIFICATION, "register-unsolicited-notification", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_DEREGISTER_UNSOLICITED_NOTIFICATION, "deregister-unsolicited-notification", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_IDENTIFY_NOTIFICATION, "identify-notification", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_AVB_INFO, "get-avb-info", handle_get_avb_info, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_AS_PATH, "get-as-path", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_COUNTERS, "get-counters", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_REBOOT, "reboot", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_AUDIO_MAP, "get-audio-map", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_ADD_AUDIO_MAPPINGS, "add-audio-mappings", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_REMOVE_AUDIO_MAPPINGS, "remove-audio-mappings", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_VIDEO_MAP, "get-video-map", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_ADD_VIDEO_MAPPINGS, "add-video-mappings", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_REMOVE_VIDEO_MAPPINGS, "remove-video-mappings", NULL, },
|
|
||||||
{ AVBTP_AECP_AEM_CMD_GET_SENSOR_MAP, "get-sensor-map", NULL, }
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline const struct cmd_info *find_cmd_info(uint16_t type, const char *name)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < SPA_N_ELEMENTS(cmd_info); i++) {
|
|
||||||
if ((name == NULL && type == cmd_info[i].type) ||
|
|
||||||
(name != NULL && spa_streq(name, cmd_info[i].name)))
|
|
||||||
return &cmd_info[i];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int avbtp_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
const struct avbtp_packet_aecp_aem *p = m;
|
|
||||||
uint16_t cmd_type;
|
|
||||||
const struct cmd_info *info;
|
|
||||||
|
|
||||||
cmd_type = AVBTP_PACKET_AEM_GET_COMMAND_TYPE(p);
|
|
||||||
|
|
||||||
info = find_cmd_info(cmd_type, NULL);
|
|
||||||
if (info == NULL)
|
|
||||||
return reply_not_implemented(aecp, m, len);
|
|
||||||
|
|
||||||
pw_log_info("aem command %s", info->name);
|
|
||||||
|
|
||||||
if (info->handle == NULL)
|
|
||||||
return reply_not_implemented(aecp, m, len);
|
|
||||||
|
|
||||||
return info->handle(aecp, m, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
int avbtp_aecp_aem_handle_response(struct aecp *aecp, const void *m, int len)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,345 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_AEM_H
|
|
||||||
#define AVBTP_AEM_H
|
|
||||||
|
|
||||||
#include "aecp.h"
|
|
||||||
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_SUCCESS 0
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_NOT_IMPLEMENTED 1
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR 2
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_ENTITY_LOCKED 3
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_ENTITY_ACQUIRED 4
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_NOT_AUTHENTICATED 5
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_AUTHENTICATION_DISABLED 6
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_BAD_ARGUMENTS 7
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_NO_RESOURCES 8
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_IN_PROGRESS 9
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_ENTITY_MISBEHAVING 10
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_NOT_SUPPORTED 11
|
|
||||||
#define AVBTP_AECP_AEM_STATUS_STREAM_IS_RUNNING 12
|
|
||||||
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ACQUIRE_ENTITY 0x0000
|
|
||||||
#define AVBTP_AECP_AEM_CMD_LOCK_ENTITY 0x0001
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ENTITY_AVAILABLE 0x0002
|
|
||||||
#define AVBTP_AECP_AEM_CMD_CONTROLLER_AVAILABLE 0x0003
|
|
||||||
#define AVBTP_AECP_AEM_CMD_READ_DESCRIPTOR 0x0004
|
|
||||||
#define AVBTP_AECP_AEM_CMD_WRITE_DESCRIPTOR 0x0005
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_CONFIGURATION 0x0006
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_CONFIGURATION 0x0007
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_STREAM_FORMAT 0x0008
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_STREAM_FORMAT 0x0009
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_VIDEO_FORMAT 0x000a
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_VIDEO_FORMAT 0x000b
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_SENSOR_FORMAT 0x000c
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_SENSOR_FORMAT 0x000d
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_STREAM_INFO 0x000e
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_STREAM_INFO 0x000f
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_NAME 0x0010
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_NAME 0x0011
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_ASSOCIATION_ID 0x0012
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_ASSOCIATION_ID 0x0013
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_SAMPLING_RATE 0x0014
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_SAMPLING_RATE 0x0015
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_CLOCK_SOURCE 0x0016
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_CLOCK_SOURCE 0x0017
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_CONTROL 0x0018
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_CONTROL 0x0019
|
|
||||||
#define AVBTP_AECP_AEM_CMD_INCREMENT_CONTROL 0x001a
|
|
||||||
#define AVBTP_AECP_AEM_CMD_DECREMENT_CONTROL 0x001b
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_SIGNAL_SELECTOR 0x001c
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_SIGNAL_SELECTOR 0x001d
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_MIXER 0x001e
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_MIXER 0x001f
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_MATRIX 0x0020
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_MATRIX 0x0021
|
|
||||||
#define AVBTP_AECP_AEM_CMD_START_STREAMING 0x0022
|
|
||||||
#define AVBTP_AECP_AEM_CMD_STOP_STREAMING 0x0023
|
|
||||||
#define AVBTP_AECP_AEM_CMD_REGISTER_UNSOLICITED_NOTIFICATION 0x0024
|
|
||||||
#define AVBTP_AECP_AEM_CMD_DEREGISTER_UNSOLICITED_NOTIFICATION 0x0025
|
|
||||||
#define AVBTP_AECP_AEM_CMD_IDENTIFY_NOTIFICATION 0x0026
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_AVB_INFO 0x0027
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_AS_PATH 0x0028
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_COUNTERS 0x0029
|
|
||||||
#define AVBTP_AECP_AEM_CMD_REBOOT 0x002a
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_AUDIO_MAP 0x002b
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ADD_AUDIO_MAPPINGS 0x002c
|
|
||||||
#define AVBTP_AECP_AEM_CMD_REMOVE_AUDIO_MAPPINGS 0x002d
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_VIDEO_MAP 0x002e
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ADD_VIDEO_MAPPINGS 0x002f
|
|
||||||
#define AVBTP_AECP_AEM_CMD_REMOVE_VIDEO_MAPPINGS 0x0030
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_SENSOR_MAP 0x0031
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ADD_SENSOR_MAPPINGS 0x0032
|
|
||||||
#define AVBTP_AECP_AEM_CMD_REMOVE_SENSOR_MAPPINGS 0x0033
|
|
||||||
#define AVBTP_AECP_AEM_CMD_START_OPERATION 0x0034
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ABORT_OPERATION 0x0035
|
|
||||||
#define AVBTP_AECP_AEM_CMD_OPERATION_STATUS 0x0036
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_ADD_KEY 0x0037
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_DELETE_KEY 0x0038
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_GET_KEY_LIST 0x0039
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_GET_KEY 0x003a
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_ADD_KEY_TO_CHAIN 0x003b
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_DELETE_KEY_FROM_CHAIN 0x003c
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_GET_KEYCHAIN_LIST 0x003d
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_GET_IDENTITY 0x003e
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_ADD_TOKEN 0x003f
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTH_DELETE_TOKEN 0x0040
|
|
||||||
#define AVBTP_AECP_AEM_CMD_AUTHENTICATE 0x0041
|
|
||||||
#define AVBTP_AECP_AEM_CMD_DEAUTHENTICATE 0x0042
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ENABLE_TRANSPORT_SECURITY 0x0043
|
|
||||||
#define AVBTP_AECP_AEM_CMD_DISABLE_TRANSPORT_SECURITY 0x0044
|
|
||||||
#define AVBTP_AECP_AEM_CMD_ENABLE_STREAM_ENCRYPTION 0x0045
|
|
||||||
#define AVBTP_AECP_AEM_CMD_DISABLE_STREAM_ENCRYPTION 0x0046
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_MEMORY_OBJECT_LENGTH 0x0047
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_MEMORY_OBJECT_LENGTH 0x0048
|
|
||||||
#define AVBTP_AECP_AEM_CMD_SET_STREAM_BACKUP 0x0049
|
|
||||||
#define AVBTP_AECP_AEM_CMD_GET_STREAM_BACKUP 0x004a
|
|
||||||
#define AVBTP_AECP_AEM_CMD_EXPANSION 0x7fff
|
|
||||||
|
|
||||||
#define AVBTP_AEM_ACQUIRE_ENTITY_PERSISTENT_FLAG (1<<0)
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_acquire {
|
|
||||||
uint32_t flags;
|
|
||||||
uint64_t owner_guid;
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_lock {
|
|
||||||
uint32_t flags;
|
|
||||||
uint64_t locked_guid;
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_read_descriptor {
|
|
||||||
uint16_t configuration;
|
|
||||||
uint8_t reserved[2];
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_configuration {
|
|
||||||
uint16_t reserved;
|
|
||||||
uint16_t configuration_index;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_stream_format {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint64_t stream_format;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_video_format {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint32_t format_specific;
|
|
||||||
uint16_t aspect_ratio;
|
|
||||||
uint16_t color_space;
|
|
||||||
uint32_t frame_size;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_sensor_format {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint64_t sensor_format;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_CLASS_B (1u<<0)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_FAST_CONNECT (1u<<1)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_SAVED_STATE (1u<<2)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_STREAMING_WAIT (1u<<3)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_ENCRYPTED_PDU (1u<<4)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_STREAM_VLAN_ID_VALID (1u<<25)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_CONNECTED (1u<<26)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_MSRP_FAILURE_VALID (1u<<27)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_STREAM_DEST_MAC_VALID (1u<<28)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_MSRP_ACC_LAT_VALID (1u<<29)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_STREAM_ID_VALID (1u<<30)
|
|
||||||
#define AVBTP_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID (1u<<31)
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_stream_info {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_index;
|
|
||||||
uint32_t aem_stream_info_flags;
|
|
||||||
uint64_t stream_format;
|
|
||||||
uint64_t stream_id;
|
|
||||||
uint32_t msrp_accumulated_latency;
|
|
||||||
uint8_t stream_dest_mac[6];
|
|
||||||
uint8_t msrp_failure_code;
|
|
||||||
uint8_t reserved;
|
|
||||||
uint64_t msrp_failure_bridge_id;
|
|
||||||
uint16_t stream_vlan_id;
|
|
||||||
uint16_t reserved2;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_name {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_index;
|
|
||||||
uint16_t name_index;
|
|
||||||
uint16_t configuration_index;
|
|
||||||
char name[64];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_association_id {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_index;
|
|
||||||
uint64_t association_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_sampling_rate {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint32_t sampling_rate;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_clock_source {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint16_t clock_source_index;
|
|
||||||
uint16_t reserved;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_control {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_incdec_control {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint16_t index_count;
|
|
||||||
uint16_t reserved;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_signal_selector {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint16_t signal_type;
|
|
||||||
uint16_t signal_index;
|
|
||||||
uint16_t signal_output;
|
|
||||||
uint16_t reserved;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_mixer {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_setget_matrix {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_index;
|
|
||||||
uint16_t matrix_column;
|
|
||||||
uint16_t matrix_row;
|
|
||||||
uint16_t region_width;
|
|
||||||
uint16_t region_height;
|
|
||||||
uint16_t rep_direction_value_count;
|
|
||||||
uint16_t item_offset;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_startstop_streaming {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_identify_notification {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_msrp_mapping {
|
|
||||||
uint8_t traffic_class;
|
|
||||||
uint8_t priority;
|
|
||||||
uint16_t vlan_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_AEM_AVB_INFO_FLAG_GPTP_GRANDMASTER_SUPPORTED (1u<<0)
|
|
||||||
#define AVBTP_AEM_AVB_INFO_FLAG_GPTP_ENABLED (1u<<1)
|
|
||||||
#define AVBTP_AEM_AVB_INFO_FLAG_SRP_ENABLED (1u<<2)
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_get_avb_info {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint64_t gptp_grandmaster_id;
|
|
||||||
uint32_t propagation_delay;
|
|
||||||
uint8_t gptp_domain_number;
|
|
||||||
uint8_t flags;
|
|
||||||
uint16_t msrp_mappings_count;
|
|
||||||
uint8_t msrp_mappings[0];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_get_as_path {
|
|
||||||
uint16_t descriptor_index;
|
|
||||||
uint16_t reserved;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_get_counters {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint32_t counters_valid;
|
|
||||||
uint8_t counters_block[0];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_reboot {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_start_operation {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint16_t operation_id;
|
|
||||||
uint16_t operation_type;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem_operation_status {
|
|
||||||
uint16_t descriptor_type;
|
|
||||||
uint16_t descriptor_id;
|
|
||||||
uint16_t operation_id;
|
|
||||||
uint16_t percent_complete;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_aecp_aem {
|
|
||||||
struct avbtp_packet_aecp_header aecp;
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
unsigned u:1;
|
|
||||||
unsigned cmd1:7;
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
unsigned cmd1:7;
|
|
||||||
unsigned u:1;
|
|
||||||
#endif
|
|
||||||
uint8_t cmd2;
|
|
||||||
uint8_t payload[0];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_AEM_SET_COMMAND_TYPE(p,v) ((p)->cmd1 = ((v) >> 8),(p)->cmd2 = (v))
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_AEM_GET_COMMAND_TYPE(p) ((p)->cmd1 << 8 | (p)->cmd2)
|
|
||||||
|
|
||||||
int avbtp_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len);
|
|
||||||
int avbtp_aecp_aem_handle_response(struct aecp *aecp, const void *m, int len);
|
|
||||||
|
|
||||||
#endif /* AVBTP_AEM_H */
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_MAAP_H
|
|
||||||
#define AVBTP_MAAP_H
|
|
||||||
|
|
||||||
#include "packets.h"
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#define AVBTP_MAAP_MESSAGE_TYPE_PROBE 1
|
|
||||||
#define AVBTP_MAAP_MESSAGE_TYPE_DEFEND 2
|
|
||||||
#define AVBTP_MAAP_MESSAGE_TYPE_ANNOUNCE 3
|
|
||||||
|
|
||||||
struct avbtp_packet_maap {
|
|
||||||
struct avbtp_packet_header hdr;
|
|
||||||
uint64_t stream_id;
|
|
||||||
uint8_t request_start[6];
|
|
||||||
uint16_t request_count;
|
|
||||||
uint8_t conflict_start[6];
|
|
||||||
uint16_t conflict_count;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_MESSAGE_TYPE(p,v) AVBTP_PACKET_SET_SUB1(&(p)->hdr, v)
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_MAAP_VERSION(p,v) AVBTP_PACKET_SET_SUB2(&(p)->hdr, v)
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_STREAM_ID(p,v) ((p)->stream_id = htobe64(v))
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_REQUEST_START(p,v) memcpy((p)->request_start, (v), 6)
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_REQUEST_COUNT(p,v) ((p)->request_count = htons(v))
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_CONFLICT_START(p,v) memcpy((p)->conflict_start, (v), 6)
|
|
||||||
#define AVBTP_PACKET_MAAP_SET_CONFLICT_COUNT(p,v) ((p)->conflict_count = htons(v))
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_MESSAGE_TYPE(p) AVBTP_PACKET_GET_SUB1(&(p)->hdr)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_MAAP_VERSION(p) AVBTP_PACKET_GET_SUB2(&(p)->hdr)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_STREAM_ID(p) be64toh((p)->stream_id)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_REQUEST_START(p) ((p)->request_start)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_REQUEST_COUNT(p) ntohs((p)->request_count)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_CONFLICT_START(p) ((p)->conflict_start)
|
|
||||||
#define AVBTP_PACKET_MAAP_GET_CONFLICT_COUNT(p) ntohs((p)->conflict_count)
|
|
||||||
|
|
||||||
int avbtp_maap_register(struct server *server);
|
|
||||||
|
|
||||||
#endif /* AVBTP_MAAP_H */
|
|
||||||
|
|
@ -1,171 +0,0 @@
|
||||||
/* AVB support
|
|
||||||
*
|
|
||||||
* Copyright © 2022 Wim Taymans
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the next
|
|
||||||
* paragraph) shall be included in all copies or substantial portions of the
|
|
||||||
* Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVBTP_MRP_H
|
|
||||||
#define AVBTP_MRP_H
|
|
||||||
|
|
||||||
#include "packets.h"
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#define AVBTP_MRP_PROTOCOL_VERSION 0
|
|
||||||
|
|
||||||
struct avbtp_packet_mrp {
|
|
||||||
struct avbtp_ethernet_header eth;
|
|
||||||
uint8_t version;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_mrp_hdr {
|
|
||||||
uint8_t attribute_type;
|
|
||||||
uint8_t attribute_length;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
struct avbtp_packet_mrp_vector {
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
unsigned lva:3;
|
|
||||||
unsigned nv1:5;
|
|
||||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
unsigned nv1:5;
|
|
||||||
unsigned lva:3;
|
|
||||||
#endif
|
|
||||||
uint8_t nv2;
|
|
||||||
uint8_t first_value[0];
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
#define AVBTP_MRP_VECTOR_SET_NUM_VALUES(a,v) ((a)->nv1 = ((v) >> 8),(a)->nv2 = (v))
|
|
||||||
#define AVBTP_MRP_VECTOR_GET_NUM_VALUES(a) ((a)->nv1 << 8 | (a)->nv2)
|
|
||||||
|
|
||||||
struct avbtp_packet_mrp_footer {
|
|
||||||
uint16_t end_mark;
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
/* applicant states */
|
|
||||||
#define AVBTP_MRP_VO 0 /* Very anxious Observer */
|
|
||||||
#define AVBTP_MRP_VP 1 /* Very anxious Passive */
|
|
||||||
#define AVBTP_MRP_VN 2 /* Very anxious New */
|
|
||||||
#define AVBTP_MRP_AN 3 /* Anxious New */
|
|
||||||
#define AVBTP_MRP_AA 4 /* Anxious Active */
|
|
||||||
#define AVBTP_MRP_QA 5 /* Quiet Active */
|
|
||||||
#define AVBTP_MRP_LA 6 /* Leaving Active */
|
|
||||||
#define AVBTP_MRP_AO 7 /* Anxious Observer */
|
|
||||||
#define AVBTP_MRP_QO 8 /* Quiet Observer */
|
|
||||||
#define AVBTP_MRP_AP 9 /* Anxious Passive */
|
|
||||||
#define AVBTP_MRP_QP 10 /* Quiet Passive */
|
|
||||||
#define AVBTP_MRP_LO 11 /* Leaving Observer */
|
|
||||||
|
|
||||||
/* registrar states */
|
|
||||||
#define AVBTP_MRP_IN 16
|
|
||||||
#define AVBTP_MRP_LV 17
|
|
||||||
#define AVBTP_MRP_MT 18
|
|
||||||
|
|
||||||
/* events */
|
|
||||||
#define AVBTP_MRP_EVENT_BEGIN 0
|
|
||||||
#define AVBTP_MRP_EVENT_NEW 1
|
|
||||||
#define AVBTP_MRP_EVENT_JOIN 2
|
|
||||||
#define AVBTP_MRP_EVENT_LV 3
|
|
||||||
#define AVBTP_MRP_EVENT_TX 4
|
|
||||||
#define AVBTP_MRP_EVENT_TX_LVA 5
|
|
||||||
#define AVBTP_MRP_EVENT_TX_LVAF 6
|
|
||||||
#define AVBTP_MRP_EVENT_RX_NEW 7
|
|
||||||
#define AVBTP_MRP_EVENT_RX_JOININ 8
|
|
||||||
#define AVBTP_MRP_EVENT_RX_IN 9
|
|
||||||
#define AVBTP_MRP_EVENT_RX_JOINMT 10
|
|
||||||
#define AVBTP_MRP_EVENT_RX_MT 11
|
|
||||||
#define AVBTP_MRP_EVENT_RX_LV 12
|
|
||||||
#define AVBTP_MRP_EVENT_RX_LVA 13
|
|
||||||
#define AVBTP_MRP_EVENT_FLUSH 14
|
|
||||||
#define AVBTP_MRP_EVENT_REDECLARE 15
|
|
||||||
#define AVBTP_MRP_EVENT_PERIODIC 16
|
|
||||||
#define AVBTP_MRP_EVENT_LV_TIMER 17
|
|
||||||
#define AVBTP_MRP_EVENT_LVA_TIMER 18
|
|
||||||
|
|
||||||
/* attribute events */
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_NEW 0
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_JOININ 1
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_IN 2
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_JOINMT 3
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_MT 4
|
|
||||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_LV 5
|
|
||||||
|
|
||||||
#define AVBTP_MRP_SEND_NEW 1
|
|
||||||
#define AVBTP_MRP_SEND_JOININ 2
|
|
||||||
#define AVBTP_MRP_SEND_IN 3
|
|
||||||
#define AVBTP_MRP_SEND_JOINMT 4
|
|
||||||
#define AVBTP_MRP_SEND_MT 5
|
|
||||||
#define AVBTP_MRP_SEND_LV 6
|
|
||||||
|
|
||||||
#define AVBTP_MRP_NOTIFY_JOIN_NEW (1u<<0)
|
|
||||||
#define AVBTP_MRP_NOTIFY_JOIN (1u<<1)
|
|
||||||
#define AVBTP_MRP_NOTIFY_LEAVE (1u<<2)
|
|
||||||
|
|
||||||
struct avbtp_mrp_attribute {
|
|
||||||
uint8_t pending_send;
|
|
||||||
uint8_t pending_notify;
|
|
||||||
void *user_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct avbtp_mrp_parse_info {
|
|
||||||
#define AVBTP_VERSION_MRP_PARSE_INFO 0
|
|
||||||
uint32_t version;
|
|
||||||
|
|
||||||
bool (*check_header) (void *data, const void *hdr, size_t *hdr_size, bool *has_params);
|
|
||||||
|
|
||||||
int (*attr_event) (void *data, uint64_t now, uint8_t attribute_type, uint8_t event);
|
|
||||||
|
|
||||||
int (*process) (void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
|
||||||
uint8_t event, uint8_t param, int index);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt, int size,
|
|
||||||
const struct avbtp_mrp_parse_info *cb, void *data);
|
|
||||||
|
|
||||||
struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *mrp,
|
|
||||||
size_t user_size);
|
|
||||||
|
|
||||||
void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|
||||||
struct avbtp_mrp_attribute *attr, int event);
|
|
||||||
|
|
||||||
void avbtp_mrp_rx_event(struct avbtp_mrp *mrp, uint64_t now,
|
|
||||||
struct avbtp_mrp_attribute *attr, uint8_t event);
|
|
||||||
|
|
||||||
void avbtp_mrp_mad_begin(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr);
|
|
||||||
void avbtp_mrp_mad_join(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr, bool is_new);
|
|
||||||
void avbtp_mrp_mad_leave(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr);
|
|
||||||
|
|
||||||
struct avbtp_mrp_events {
|
|
||||||
#define AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS 0
|
|
||||||
uint32_t version;
|
|
||||||
|
|
||||||
void (*event) (void *data, uint64_t now, uint8_t event);
|
|
||||||
|
|
||||||
void (*notify) (void *data, uint64_t now, struct avbtp_mrp_attribute *attr, uint8_t notify);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct avbtp_mrp *avbtp_mrp_new(struct server *server);
|
|
||||||
void avbtp_mrp_destroy(struct avbtp_mrp *mrp);
|
|
||||||
|
|
||||||
void avbtp_mrp_add_listener(struct avbtp_mrp *mrp, struct spa_hook *listener,
|
|
||||||
const struct avbtp_mrp_events *events, void *data);
|
|
||||||
|
|
||||||
#endif /* AVBTP_MRP_H */
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue