| // 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 */ |