blob: 4d3f36893523fe9539d0f59f58f8277062c6792c [file] [log] [blame]
/*
* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* qmidev: internal interface to the top-level QMI device object.
*
* (Also see ../include/qmidev.h for the public interface.)
*/
#ifndef LIBQMI_QMIDEV_H
#define LIBQMI_QMIDEV_H
#include <libqmi.h>
#include <stddef.h>
#include <stdint.h>
struct qmidev;
struct qmimsg;
struct callback;
struct client;
typedef void (*client_create_fn)(struct qmidev *qmidev,
struct client *client);
typedef void (*client_destroy_fn)(struct qmidev *qmidev,
struct client *client);
typedef int (*request_fn)(void *context,
struct qmimsg *message);
typedef void (*response_fn)(struct qmidev *qmidev,
void *context,
int status,
struct qmimsg *message);
typedef void (*event_fn)(struct qmidev *qmidev,
void *user_callback,
void *user_context,
uint16_t length,
void *value);
struct event {
uint8_t type;
struct listener *listener;
event_fn callback;
void *user_callback;
void *user_context;
};
struct service {
uint8_t service_id;
uint16_t event_msg_id;
client_create_fn create_fn;
client_destroy_fn destroy_fn;
};
#define INIT_SERVICE(id, event_msg_id) { (id), (event_msg_id), NULL, NULL }
void *client_priv(struct client *client);
void client_set_priv(struct client *client, void *priv);
/**
* Fills in a struct event.
*
* @event: the struct event to fill in
* @type: the type of the TLV element representing the event
* @callback: the callback used to call the user's callback when the event
* happens
*/
void event_init(struct event *event, uint8_t type, event_fn callback);
/** Callback type for qmidev_get_client */
typedef void (*qmidev_client_fn)(struct qmidev *qmidev,
void *context,
int status,
struct client *client);
/**
* Allocates a client for a particular service on the card.
*/
int qmidev_get_client(struct qmidev *qmidev,
struct service *service,
qmidev_client_fn callback,
void *context);
/**
* Releases an allocated client.
*/
int qmidev_release_client(struct qmidev *qmidev,
struct client *client,
qmidev_response_fn callback,
void *context);
/**
* Returns the default client for a given service.
*/
struct client *qmidev_default_client(struct qmidev *qmidev,
struct service *service);
/*
* General request structure:
*
* Most requests will have four declarations:
*
* 1. a context struct to be passed to the response handler. This stores the
* callback and context passed to the main request function, so the
* response handler can call the callback after extracting any returned
* data from the response message.
*
* 2. (optional) a make_request function. If the request requires any TLVs to
* be included in the request message, this function takes a QMI message
* and a context pointer and adds the data to the message. (This is a
* separate function because it makes things neater for requests that don't
* have any parameter -- a NULL make_request function simply isn't called.)
*
* 3. a handle_response function. This is called when a response to the
* request is received, and is responsible for getting any returned data
* from the response message, calling the original callback, and freeing
* the context.
*
* 4. the main request function. This allocates a context and calls
* qmidev_request with pointers to the request and response functions and
* associated contexts.
*/
/**
* Makes a request on a particular client (as opposed to the default one) of a
* service.
*
* @qmidev: the QMI device
* @client: the client on which to make the request
* @msg_id: the message ID of the request and response messages
* @make_request_fn: a function to be called to fill in the request message,
* if it requires a payload (otherwise NULL). Will be
* called before qmidev_client_request returns.
* @request_context: the context for make_request_fn
* @handle_response_fn: the function to call when the response is received
* @response_context: the context for handle_response_fn
*/
int qmidev_client_request(struct qmidev *qmidev,
struct client *client,
uint16_t msg_id,
request_fn make_request_fn,
void *request_context,
response_fn handle_response_fn,
void *response_context);
/**
* Makes a request on the default client of a service.
*
* Arguments are otherwise the same as qmidev_client_request.
*/
int qmidev_request(struct qmidev *qmidev,
struct service *service,
uint16_t msg_id,
request_fn make_request_fn,
void *request_context,
response_fn handle_response_fn,
void *response_context);
/**
* Makes a void request on the default client of a service.
*
* Immediately calls the response function without doing anything with the
* response message besides getting the result code.
*
* Arguments are otherwise the same as qmidev_request.
*/
int qmidev_void_request(struct qmidev *qmidev,
struct service *service,
uint16_t msg_id,
request_fn make_request_fn,
void *request_context,
qmidev_response_fn handle_response_fn,
void *response_context);
/**
* Sets or clears a callback.
*
* @qmidev: the QMI device
* @client: the client on which to set/clear the callback
* @event: the event structure representing the event whose callback we are
* setting or clearing
* @new_callback: the new callback to set, or NULL if clearing
* @new_context: the context for new_callback
* @caller_callback: the callback to call once new_callback is set
* @caller_context: the context for caller_callback
*/
int qmidev_set_callback(struct qmidev *qmidev,
struct client *client,
struct event *event,
void *new_callback,
void *new_context,
qmidev_response_fn caller_callback,
void *caller_context);
/* TODO: These should be replaced by qmidev_poll. */
/**
* Sets a file descriptor belonging to the dev underlying this qmidev.
* The qmidev will read from the dev when this filehandle is ready to read.
* Returns zero on success, errno on failure.
*/
int qmidev_set_dev_fd(struct qmidev *qmidev, int fd);
/**
* Clears the file descriptor set by qmidev_set_dev_fd.
* Returns zero on success, errno on failure.
*/
int qmidev_clear_dev_fd(struct qmidev *qmidev);
/**
* Adds a file descriptor to the poller in this qmidev.
* Returns the new struct polled * on success, NULL on failure.
*/
struct polled *qmidev_poll(struct qmidev *qmidev, int fd);
/**
* Callback type for QMI requests made with qmidev_send_request.
*
* @resp_msg: The response message received, or NULL if none.
*/
typedef void (*qmidev_request_fn)(struct qmidev *qmidev,
void *context,
int status,
struct qmimsg *resp_msg);
enum {
LISTEN_MATCH_QMI_FLAGS = 0x1,
LISTEN_MATCH_TRANSACTION = 0x2,
LISTEN_MATCH_MESSAGE = 0x4
};
struct listen_criteria {
int flags;
uint8_t qmi_flags;
uint16_t transaction;
uint16_t message;
};
/**
* Callback type for qmidev_listen.
*
* Will be called when a message matching the listen criteria is received.
*
* @qmidev: the QMI device on which a message was received
* @context: the context passed to qmidev_listen
* @message: the message received
*
* The callback should return zero to continue listening for such messages,
* or non-zero to remove the listener.
*/
typedef int (*qmidev_listen_callback_fn)(struct qmidev *qmidev,
void *context,
struct qmimsg *message);
struct listener *qmidev_listen(struct qmidev *qmidev,
struct client *client,
struct listen_criteria *criteria,
qmidev_listen_callback_fn callback,
void *context);
void qmidev_cancel_listen(struct qmidev *qmidev, struct listener *listener);
/**
* Sends a QMI message.
* Returns zero on success, errno on failure.
*/
int qmidev_send(struct qmidev *qmidev, struct qmimsg *msg);
typedef void (*callback_fn)(struct qmidev *qmidev, void *context);
/**
* Calls a callback from qmidev_process instead of the current call stack.
*/
void qmidev_call_later(struct qmidev *qmidev, callback_fn func,
void *context);
/* Mock qmidev functions: */
/* Create a new mock QMI device (backed by pipes instead of a real file.) */
struct qmidev *qmidev_new_mock(void);
/* Check if the mock device os open. */
int qmidev_mock_is_open(struct qmidev *qmidev);
/* Inject a message "received from" the mock device. */
int qmidev_mock_inject(struct qmidev *qmidev, const void *buf, size_t len);
/* Extract a message "sent to" the mock device.
*
* @len: A pointer to the length of buf; it will be replaced with the size of
* the message read. Cannot be NULL.
*
* Returns 0 on success,
* ENOSPC if len is too small for the next message.
*/
int qmidev_mock_extract(struct qmidev *qmidev, void *buf, size_t *len);
#endif /* LIBQMI_QMIDEV_H */