#include "platform_adapter.hpp" #include namespace tai::mux { static void notification_callback(void* context, tai_object_id_t oid, uint32_t attr_count, tai_attribute_t const * const attr_list) { if ( context == nullptr || attr_list == nullptr ) { return; } auto ctx = static_cast(context); if ( ctx->pa != nullptr ) { ctx->pa->notify(ctx, oid, attr_count, attr_list); } } void PlatformAdapter::notify(NotificationContext* ctx, tai_object_id_t real_oid, uint32_t attr_count, tai_attribute_t const * const attr_list) { auto oid = ctx->muxed_oid; std::vector attrs; for ( int i = 0; i < attr_count; i++ ) { auto src = attr_list[i]; auto meta = tai_metadata_get_attr_metadata(ctx->object_type, src.id); if ( meta == nullptr ) { continue; } auto dst = std::make_shared(meta, src); auto ret = convert_oid(ctx->object_type, oid, dst, dst, true); if ( ret != TAI_STATUS_SUCCESS ) { ERROR("failed to convert oid of attribute: %d", src.id); continue; } attrs.emplace_back(dst); } { std::vector raw_attrs; std::transform(attrs.begin(), attrs.end(), std::back_inserter(raw_attrs), [](S_Attribute a) { return *a->raw(); }); std::unique_lock lk(ctx->mutex); ctx->real_handler.notify(ctx->real_handler.context, oid, raw_attrs.size(), raw_attrs.data()); } } tai_status_t PlatformAdapter::convert_oid(const tai_object_type_t& type, const tai_object_id_t& id, const S_ConstAttribute src, const S_Attribute dst, bool reversed) { return convert_oid(type, id, src->raw(), const_cast(dst->raw()), reversed); } tai_status_t PlatformAdapter::convert_oid(const tai_object_type_t& type, const tai_object_id_t& id, const tai_attribute_t * const src, tai_attribute_t * const dst, bool reversed) { auto meta = tai_metadata_get_attr_metadata(type, src->id); const tai_object_map_list_t *oml; S_ModuleAdapter adapter; if ( get_mapping(id, &adapter, nullptr) != 0 ) { return TAI_STATUS_FAILURE; } auto convert = [&](tai_object_id_t s) -> tai_object_id_t { if ( reversed ) { return get_reverse_mapping(s, adapter); } tai_object_id_t oid; if ( get_mapping(s, nullptr, &oid) < 0 ) { return TAI_NULL_OBJECT_ID; } return oid; }; switch (meta->attrvaluetype) { case TAI_ATTR_VALUE_TYPE_OID: dst->value.oid = convert(src->value.oid); if ( dst->value.oid == TAI_NULL_OBJECT_ID ) { return TAI_STATUS_FAILURE; } break; case TAI_ATTR_VALUE_TYPE_OBJLIST: for ( auto i = 0 ; i < src->value.objlist.count; i++ ) { dst->value.objlist.list[i] = convert(src->value.objlist.list[i]); if ( dst->value.objlist.list[i] == TAI_NULL_OBJECT_ID ) { return TAI_STATUS_FAILURE; } } break; case TAI_ATTR_VALUE_TYPE_OBJMAPLIST: oml = &src->value.objmaplist; for ( auto i = 0 ; i < oml->count; i++ ) { dst->value.objmaplist.list[i].key = convert(oml->list[i].key); if ( dst->value.objmaplist.list[i].key == TAI_NULL_OBJECT_ID ) { return TAI_STATUS_FAILURE; } for ( auto j = 0; j < oml->list[i].value.count; j++ ) { dst->value.objmaplist.list[i].value.list[j] = convert(oml->list[i].value.list[j]); if ( dst->value.objmaplist.list[i].value.list[j] == TAI_NULL_OBJECT_ID ) { return TAI_STATUS_FAILURE; } } } break; case TAI_ATTR_VALUE_TYPE_NOTIFICATION: { auto key = notification_key(id, src->id); if ( reversed ) { if ( m_notification_map.find(key) != m_notification_map.end() ) { auto n = m_notification_map[key]; dst->value.notification.context = n->real_handler.context; dst->value.notification.notify = n->real_handler.notify; } break; } if ( src->value.notification.notify != nullptr ) { if ( m_notification_map.find(key) == m_notification_map.end() ) { m_notification_map[key] = std::make_shared(); } auto n = m_notification_map[key]; std::unique_lock lk(n->mutex); n->pa = this; n->real_handler = src->value.notification; n->muxed_oid = id; n->object_type = type; dst->value.notification.context = static_cast(n.get()); dst->value.notification.notify = notification_callback; } else { // notification context cleanup can't be handled here since the callback can still get // called by the underneath TAI library. // we'll clean the context after disabling the callback } } } return TAI_STATUS_SUCCESS; } tai_status_t PlatformAdapter::set(const tai_object_type_t& type, const tai_object_id_t& id, const tai_attribute_t* const attribute) { S_ModuleAdapter adapter; tai_object_id_t real_id; if ( get_mapping(id, &adapter, &real_id) != 0 ) { return TAI_STATUS_FAILURE; } auto meta = tai_metadata_get_attr_metadata(type, attribute->id); if ( meta == nullptr ) { return TAI_STATUS_FAILURE; } auto attr = std::make_shared(meta, attribute); auto ret = convert_oid(type, id, attribute, const_cast(attr->raw()), false); if ( ret != TAI_STATUS_SUCCESS ) { return ret; } ret = adapter->set_attributes(type, real_id, 1, attr->raw()); if ( ret != TAI_STATUS_SUCCESS ) { return ret; } if ( meta->attrvaluetype == TAI_ATTR_VALUE_TYPE_NOTIFICATION && attribute->value.notification.notify == nullptr ) { auto key = notification_key(id, attribute->id); m_notification_map.erase(key); } return TAI_STATUS_SUCCESS; } }