blob: f1c8330e8e6f9e6baf1224bac9ec4aca75ed266f [file] [log] [blame]
// Copyright 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "GoldfishAddressSpaceStream.h"
#include "goldfish_address_space.h"
AddressSpaceStream* createGoldfishAddressSpaceStream(size_t ignored_bufSize) {
// Ignore incoming ignored_bufSize
(void)ignored_bufSize;
auto handle = goldfish_address_space_open();
address_space_handle_t child_device_handle;
if (!goldfish_address_space_set_subdevice_type(handle, GoldfishAddressSpaceSubdeviceType::Graphics, &child_device_handle)) {
ALOGE("AddressSpaceStream::create failed (initial device create)\n");
goldfish_address_space_close(handle);
return nullptr;
}
struct address_space_ping request;
request.metadata = ASG_GET_RING;
if (!goldfish_address_space_ping(child_device_handle, &request)) {
ALOGE("AddressSpaceStream::create failed (get ring)\n");
goldfish_address_space_close(child_device_handle);
return nullptr;
}
uint64_t ringOffset = request.metadata;
request.metadata = ASG_GET_BUFFER;
if (!goldfish_address_space_ping(child_device_handle, &request)) {
ALOGE("AddressSpaceStream::create failed (get buffer)\n");
goldfish_address_space_close(child_device_handle);
return nullptr;
}
uint64_t bufferOffset = request.metadata;
uint64_t bufferSize = request.size;
if (!goldfish_address_space_claim_shared(
child_device_handle, ringOffset, sizeof(asg_ring_storage))) {
ALOGE("AddressSpaceStream::create failed (claim ring storage)\n");
goldfish_address_space_close(child_device_handle);
return nullptr;
}
if (!goldfish_address_space_claim_shared(
child_device_handle, bufferOffset, bufferSize)) {
ALOGE("AddressSpaceStream::create failed (claim buffer storage)\n");
goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
goldfish_address_space_close(child_device_handle);
return nullptr;
}
char* ringPtr = (char*)goldfish_address_space_map(
child_device_handle, ringOffset, sizeof(struct asg_ring_storage));
if (!ringPtr) {
ALOGE("AddressSpaceStream::create failed (map ring storage)\n");
goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
goldfish_address_space_close(child_device_handle);
return nullptr;
}
char* bufferPtr = (char*)goldfish_address_space_map(
child_device_handle, bufferOffset, bufferSize);
if (!bufferPtr) {
ALOGE("AddressSpaceStream::create failed (map buffer storage)\n");
goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
goldfish_address_space_close(child_device_handle);
return nullptr;
}
struct asg_context context =
asg_context_create(
ringPtr, bufferPtr, bufferSize);
request.metadata = ASG_SET_VERSION;
request.size = 1; // version 1
if (!goldfish_address_space_ping(child_device_handle, &request)) {
ALOGE("AddressSpaceStream::create failed (get buffer)\n");
goldfish_address_space_unmap(bufferPtr, bufferSize);
goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
goldfish_address_space_close(child_device_handle);
return nullptr;
}
uint32_t version = request.size;
context.ring_config->transfer_mode = 1;
context.ring_config->host_consumed_pos = 0;
context.ring_config->guest_write_pos = 0;
struct address_space_ops ops = {
.open = goldfish_address_space_open,
.close = goldfish_address_space_close,
.claim_shared = goldfish_address_space_claim_shared,
.unclaim_shared = goldfish_address_space_unclaim_shared,
.map = goldfish_address_space_map,
.unmap = goldfish_address_space_unmap,
.set_subdevice_type = goldfish_address_space_set_subdevice_type,
.ping = goldfish_address_space_ping,
};
AddressSpaceStream* res = new AddressSpaceStream(child_device_handle, version, context,
ringOffset, bufferOffset, ops);
return res;
}