blob: b9d6d563aad5c300262f38661e37bea2275905d1 [file] [log] [blame]
// Copyright 2020 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.
#ifndef _HW_GOLDFISH_PIPE_H
#define _HW_GOLDFISH_PIPE_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
class QEMUFile;
/* The Android pipe virtual device expects an implementation of
* pipe services to be provided according to the following interface
*/
typedef struct GoldfishPipeBuffer {
void* data;
size_t size;
} GoldfishPipeBuffer;
/* List of bitflags returned by guest_poll() */
typedef enum {
GOLDFISH_PIPE_POLL_IN = (1 << 0), /* means guest can read */
GOLDFISH_PIPE_POLL_OUT = (1 << 1), /* means guest can write */
GOLDFISH_PIPE_POLL_HUP = (1 << 2), /* means closed by host */
} GoldfishPipePollFlags;
/* List of bitflags used to call goldfish_pipe_signal_wake() and
* guest_wake_on() */
typedef enum {
GOLDFISH_PIPE_WAKE_CLOSED = (1 << 0), /* emulator closed the pipe */
GOLDFISH_PIPE_WAKE_READ = (1 << 1), /* pipe can now be read from */
GOLDFISH_PIPE_WAKE_WRITE = (1 << 2), /* pipe can now be written to */
GOLDFISH_PIPE_WAKE_UNLOCK_DMA = (1 << 3),/* unlock this pipe's DMA buffer */
} GoldfishPipeWakeFlags;
/* List of error values possibly returned by guest_recv() and
* guest_send(). */
typedef enum {
GOLDFISH_PIPE_ERROR_INVAL = -1,
GOLDFISH_PIPE_ERROR_AGAIN = -2,
GOLDFISH_PIPE_ERROR_NOMEM = -3,
GOLDFISH_PIPE_ERROR_IO = -4,
} GoldfishPipeError;
/* List of reasons why pipe is closed. */
typedef enum {
GOLDFISH_PIPE_CLOSE_GRACEFUL = 0,
GOLDFISH_PIPE_CLOSE_REBOOT = 1,
GOLDFISH_PIPE_CLOSE_LOAD_SNAPSHOT = 2,
GOLDFISH_PIPE_CLOSE_ERROR = 3,
} GoldfishPipeCloseReason;
/* Opaque type of the hardware-side view of a pipe connection. This structure
* is implemented by the virtual device and is hidden from the host service
* implementation. */
typedef struct GoldfishHwPipe GoldfishHwPipe;
/* Opaque type of the host-side view of a pipe connection. This structure is
* implemented by the host pipe service implementation, and is hidden from
* the virtual device. */
typedef struct GoldfishHostPipe GoldfishHostPipe;
typedef struct {
// Open a new pipe. |hw_pipe| is a unique pointer value identifying the
// hardware-side view of the pipe, and will be passed to the
// goldfish_pipe_xxx() functions below. This returns a new host-specific
// pipe value that is only used by the virtual device to call other
// callbacks here. There is a one-to-one association between a |hw_pipe|
// and its |host_pipe| value, which can be reset by calling
// goldfish_pipe_reset().
GoldfishHostPipe* (*guest_open)(GoldfishHwPipe *hw_pipe);
GoldfishHostPipe* (*guest_open_with_flags)(GoldfishHwPipe *hw_pipe, uint32_t flags);
// Close and free a pipe. |host_pipe| must be the result of a previous
// guest_open() or guest_load() call, or the second parameter to
// goldfish_pipe_reset(). |reason| is why the pipe was closed.
void (*guest_close)(GoldfishHostPipe *host_pipe,
GoldfishPipeCloseReason reason);
// A set of hooks to prepare and cleanup save/load operations. These are
// called once per each snapshot operation, as opposed to the following
// guest_load()/guest_save().
void (*guest_pre_load)(QEMUFile *file);
void (*guest_post_load)(QEMUFile *file);
void (*guest_pre_save)(QEMUFile *file);
void (*guest_post_save)(QEMUFile *file);
// Load the state of a pipe from a stream. |file| is the input stream,
// |hw_pipe| is the hardware-side pipe descriptor. On success, return a new
// internal pipe instance (similar to one returned by guest_open()), and
// sets |*force_close| to 1 to indicate that the pipe must be force-closed
// just after its load/creation (only useful for certain services that can't
// preserve state into streams). Return NULL on faillure.
GoldfishHostPipe* (*guest_load)(QEMUFile *file, GoldfishHwPipe *hw_pipe,
char *force_close);
// Save the state of a pipe to a stream. |host_pipe| is the pipe
// instance from guest_open() or guest_load(). and |file| is the
// output stream.
void (*guest_save)(GoldfishHostPipe *host_pipe, QEMUFile *file);
// Poll the state of the pipe associated with |host_pipe|.
// This returns a combination of GoldfishPipePollFlags.
GoldfishPipePollFlags (*guest_poll)(GoldfishHostPipe *host_pipe);
// Called when the guest tries to receive data from the host through
// |host_pipe|. This will try to copy data to the memory ranges
// decribed by the array |buffers| or |num_buffers| items.
// Return number of bytes transferred, or a (negative) GoldfishPipeError
// value otherwise.
int (*guest_recv)(GoldfishHostPipe *host_pipe,
GoldfishPipeBuffer *buffers,
int num_buffers);
// Called when the guest tries to send data to the host through
// |host_pipe|. This will try to copy data from the memory ranges
// decribed by the array |buffers| or |num_buffers| items.
// Return number of bytes transferred, or a (negative) GoldfishPipeError
// value otherwise.
int (*guest_send)(GoldfishHostPipe **host_pipe,
const GoldfishPipeBuffer *buffers,
int num_buffers);
// Called when the guest wants to be waked on specific events.
// identified by the |wake_flags| bitmask. The host should call
// goldfish_pipe_signal_wake() with the appropriate bitmask when
// any of these events occur.
void (*guest_wake_on)(GoldfishHostPipe *host_pipe,
GoldfishPipeWakeFlags wake_flags);
// called to register a new DMA buffer that can be mapped in guest + host.
void (*dma_add_buffer)(void* pipe, uint64_t guest_paddr, uint64_t);
// called when the guest is done with a particular DMA buffer.
void (*dma_remove_buffer)(uint64_t guest_paddr);
// called when host mappings change, such
// as on pipe save/load during snapshots.
void (*dma_invalidate_host_mappings)(void);
// called when device reboots and we need to reset pipe state completely.
void (*dma_reset_host_mappings)(void);
// For snapshot save/load of DMA buffer state.
void (*dma_save_mappings)(QEMUFile* file);
void (*dma_load_mappings)(QEMUFile* file);
} GoldfishPipeServiceOps;
/* Called by the service implementation to register its callbacks.
* The default implementation doesn't do anything except returning
* an error when |guest_open| or |guest_load| are called. */
extern void goldfish_pipe_set_service_ops(
const GoldfishPipeServiceOps* ops);
/* Query the service ops struct from other places. For use with
* virtio. */
extern const GoldfishPipeServiceOps* goldfish_pipe_get_service_ops(void);
extern GoldfishHwPipe* goldfish_pipe_lookup_by_id(int id);
#endif /* _HW_GOLDFISH_PIPE_H */