gisi: Adapt and refactor pipe module

Make use of the new client API and refactor the code.
This commit is contained in:
Aki Niemi 2010-11-14 18:29:09 +02:00
parent 7cd90666be
commit 068233c370
2 changed files with 153 additions and 113 deletions

View File

@ -26,12 +26,13 @@
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
#include <glib.h> #include <glib.h>
#include "client.h" #include "client.h"
#include "pipe.h" #include "pipe.h"
#define PN_PIPE 0xd9 #define PN_PIPE 0xd9
typedef struct { struct isi_pipe_create_req {
uint8_t cmd; uint8_t cmd;
uint8_t state_after; uint8_t state_after;
uint8_t priority; uint8_t priority;
@ -45,37 +46,35 @@ typedef struct {
uint8_t object2; uint8_t object2;
uint8_t type2; uint8_t type2;
uint8_t n_sb; uint8_t n_sb;
} isi_pipe_create_req_t; };
typedef struct { struct isi_pipe_enable_req {
uint8_t cmd; uint8_t cmd;
uint8_t pipe_handle; uint8_t pipe_handle;
uint8_t pad; uint8_t pad;
} isi_pipe_enable_req_t; };
typedef struct { struct isi_pipe_reset_req {
uint8_t cmd; uint8_t cmd;
uint8_t pipe_handle; uint8_t pipe_handle;
uint8_t state_after; uint8_t state_after;
} isi_pipe_reset_req_t; };
typedef struct { struct isi_pipe_remove_req {
uint8_t cmd; uint8_t cmd;
uint8_t pipe_handle; uint8_t pipe_handle;
} isi_pipe_remove_req_t; };
typedef struct { struct isi_pipe_resp {
uint8_t cmd;
uint8_t pipe_handle; uint8_t pipe_handle;
uint8_t error_code; uint8_t error_code;
uint8_t error1; uint8_t error1;
uint8_t error2; uint8_t error2;
} isi_pipe_resp_t; };
#define PN_PIPE_INVALID_HANDLE 0xff #define PN_PIPE_INVALID_HANDLE 0xff
enum { enum isi_pipe_message_id {
PNS_PIPE_CREATE_REQ, PNS_PIPE_CREATE_REQ,
PNS_PIPE_CREATE_RESP, PNS_PIPE_CREATE_RESP,
PNS_PIPE_REMOVE_REQ, PNS_PIPE_REMOVE_REQ,
@ -90,8 +89,8 @@ enum {
PNS_PIPE_DISABLE_RESP, PNS_PIPE_DISABLE_RESP,
}; };
enum { /* error codes */ enum pn_pipe_error { /* error codes */
PN_PIPE_NO_ERROR, PN_PIPE_ERR_NO_ERROR,
PN_PIPE_ERR_INVALID_PARAM, PN_PIPE_ERR_INVALID_PARAM,
PN_PIPE_ERR_INVALID_HANDLE, PN_PIPE_ERR_INVALID_HANDLE,
PN_PIPE_ERR_INVALID_CTRL_ID, PN_PIPE_ERR_INVALID_CTRL_ID,
@ -105,20 +104,20 @@ enum { /* error codes */
PN_PIPE_ERR_NOT_SUPPORTED, PN_PIPE_ERR_NOT_SUPPORTED,
}; };
enum { /* initial pipe state */ enum pn_pipe_state { /* initial pipe state */
PN_PIPE_DISABLE, PN_PIPE_DISABLE,
PN_PIPE_ENABLE, PN_PIPE_ENABLE,
}; };
enum { enum pn_msg_priority {
PN_MSG_PRIORITY_LOW = 1, PN_MSG_PRIORITY_LOW = 1,
PN_MSG_PRIORITY_HIGH, PN_MSG_PRIORITY_HIGH,
}; };
struct _GIsiPipe { struct _GIsiPipe {
GIsiClient *client; GIsiClient *client;
void (*handler)(GIsiPipe *); GIsiPipeHandler handler;
void (*error_handler)(GIsiPipe *); GIsiPipeErrorHandler error_handler;
void *opaque; void *opaque;
int error; int error;
uint8_t handle; uint8_t handle;
@ -126,26 +125,34 @@ struct _GIsiPipe {
gboolean enabling; gboolean enabling;
}; };
static int g_isi_pipe_error(uint8_t code) static int g_isi_pipe_error(enum pn_pipe_error code)
{ {
static const int codes[] = { switch (code) {
[PN_PIPE_NO_ERROR] = 0, case PN_PIPE_ERR_NO_ERROR:
[PN_PIPE_ERR_INVALID_PARAM] = -EINVAL, return 0;
[PN_PIPE_ERR_INVALID_HANDLE] = -EBADF, case PN_PIPE_ERR_INVALID_PARAM:
[PN_PIPE_ERR_INVALID_CTRL_ID] = -ENOTSUP, return -EINVAL;
[PN_PIPE_ERR_NOT_ALLOWED] = -EPERM, case PN_PIPE_ERR_INVALID_HANDLE:
[PN_PIPE_ERR_PEP_IN_USE] = -EBUSY, return -EBADF;
[PN_PIPE_ERR_OVERLOAD] = -ENOBUFS, case PN_PIPE_ERR_INVALID_CTRL_ID:
[PN_PIPE_ERR_DEV_DISCONNECTED] = -ENETDOWN, return -ENOTSUP;
[PN_PIPE_ERR_TIMEOUT] = -ETIMEDOUT, case PN_PIPE_ERR_NOT_ALLOWED:
[PN_PIPE_ERR_ALL_PIPES_IN_USE] = -ENFILE, return -EPERM;
[PN_PIPE_ERR_GENERAL] = -EAGAIN, case PN_PIPE_ERR_PEP_IN_USE:
[PN_PIPE_ERR_NOT_SUPPORTED] = -ENOSYS, return -EBUSY;
}; case PN_PIPE_ERR_OVERLOAD:
return -ENOBUFS;
if (code == PN_PIPE_NO_ERROR || case PN_PIPE_ERR_DEV_DISCONNECTED:
((code < sizeof(codes) / sizeof(codes[0])) && codes[code])) return -ENETDOWN;
return codes[code]; case PN_PIPE_ERR_TIMEOUT:
return -ETIMEDOUT;
case PN_PIPE_ERR_ALL_PIPES_IN_USE:
return -ENFILE;
case PN_PIPE_ERR_GENERAL:
return -EAGAIN;
case PN_PIPE_ERR_NOT_SUPPORTED:
return -ENOSYS;
}
return -EBADMSG; return -EBADMSG;
} }
@ -155,31 +162,41 @@ static void g_isi_pipe_handle_error(GIsiPipe *pipe, uint8_t code)
if (err == 0) if (err == 0)
return; return;
pipe->error = err; pipe->error = err;
if (pipe->error_handler) if (pipe->error_handler)
pipe->error_handler(pipe); pipe->error_handler(pipe);
} }
static gboolean g_isi_pipe_created(GIsiClient *client, static void g_isi_pipe_created(const GIsiMessage *msg, void *data)
const void *restrict data, size_t len,
uint16_t object, void *opaque)
{ {
GIsiPipe *pipe = opaque; const struct isi_pipe_resp *resp = g_isi_msg_data(msg);
const isi_pipe_resp_t *resp = data; GIsiPipe *pipe = data;
if (len < 5 || if (g_isi_msg_error(msg) < 0) {
resp->cmd != PNS_PIPE_CREATE_RESP) g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_TIMEOUT);
return FALSE; return;
}
if (resp->pipe_handle != PN_PIPE_INVALID_HANDLE) { if (g_isi_msg_id(msg) != PNS_PIPE_CREATE_RESP)
pipe->handle = resp->pipe_handle; return;
if (pipe->enabling)
g_isi_pipe_start(pipe); if (!resp || g_isi_msg_data_len(msg) != sizeof(struct isi_pipe_resp))
if (pipe->handler) return;
pipe->handler(pipe);
} else if (resp->pipe_handle == PN_PIPE_INVALID_HANDLE) {
g_isi_pipe_handle_error(pipe, resp->error_code); g_isi_pipe_handle_error(pipe, resp->error_code);
return TRUE; return;
}
pipe->handle = resp->pipe_handle;
if (pipe->enabling)
g_isi_pipe_start(pipe);
if (pipe->handler)
pipe->handler(pipe);
} }
/** /**
@ -192,11 +209,10 @@ static gboolean g_isi_pipe_created(GIsiClient *client,
* @param type2 Type of the second end point * @param type2 Type of the second end point
* @return a pipe object on success, NULL on error. * @return a pipe object on success, NULL on error.
*/ */
GIsiPipe *g_isi_pipe_create(GIsiModem *modem, void (*created)(GIsiPipe *), GIsiPipe *g_isi_pipe_create(GIsiModem *modem, GIsiPipeHandler cb, uint16_t obj1,
uint16_t obj1, uint16_t obj2, uint16_t obj2, uint8_t type1, uint8_t type2)
uint8_t type1, uint8_t type2)
{ {
isi_pipe_create_req_t msg = { struct isi_pipe_create_req msg = {
.cmd = PNS_PIPE_CREATE_REQ, .cmd = PNS_PIPE_CREATE_REQ,
.state_after = PN_PIPE_DISABLE, .state_after = PN_PIPE_DISABLE,
.priority = PN_MSG_PRIORITY_LOW, .priority = PN_MSG_PRIORITY_LOW,
@ -208,73 +224,75 @@ GIsiPipe *g_isi_pipe_create(GIsiModem *modem, void (*created)(GIsiPipe *),
.type2 = type2, .type2 = type2,
.n_sb = 0, .n_sb = 0,
}; };
GIsiPipe *pipe = g_try_malloc(sizeof(GIsiPipe)); GIsiPipe *pipe;
if (pipe == NULL) pipe = g_try_new0(GIsiPipe, 1);
if (pipe == NULL) {
errno = ENOMEM;
return NULL; return NULL;
}
pipe->client = g_isi_client_create(modem, PN_PIPE); pipe->client = g_isi_client_create(modem, PN_PIPE);
pipe->handler = created; if (pipe->client == NULL) {
errno = ENOMEM;
g_free(pipe);
return NULL;
}
pipe->handler = cb;
pipe->error_handler = NULL; pipe->error_handler = NULL;
pipe->error = 0; pipe->error = 0;
pipe->enabling = FALSE; pipe->enabling = FALSE;
pipe->enabled = FALSE; pipe->enabled = FALSE;
pipe->handle = PN_PIPE_INVALID_HANDLE; pipe->handle = PN_PIPE_INVALID_HANDLE;
if (pipe->client == NULL || if (g_isi_client_send(pipe->client, &msg, sizeof(msg), 3,
g_isi_request_make(pipe->client, &msg, sizeof(msg), 3, g_isi_pipe_created, pipe, NULL))
g_isi_pipe_created, pipe) == NULL) return pipe;
goto error;
return pipe; g_isi_client_destroy(pipe->client);
error:
if (pipe->client)
g_isi_client_destroy(pipe->client);
g_free(pipe); g_free(pipe);
return NULL; return NULL;
} }
static const isi_pipe_resp_t * static void g_isi_pipe_enabled(const GIsiMessage *msg, void *data)
g_isi_pipe_check_resp(const GIsiPipe *pipe, uint8_t cmd,
const void *restrict data, size_t len)
{ {
const isi_pipe_resp_t *resp = data; GIsiPipe *pipe = data;
const struct isi_pipe_resp *resp = g_isi_msg_data(msg);
if ((len < 5) || (resp->cmd != cmd) || if (g_isi_msg_error(msg) < 0) {
(resp->pipe_handle != pipe->handle)) g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_TIMEOUT);
return NULL; return;
return resp; }
}
static gboolean g_isi_pipe_enabled(GIsiClient *client, if (g_isi_msg_id(msg) != PNS_PIPE_ENABLE_RESP)
const void *restrict data, size_t len, return;
uint16_t object, void *opaque)
{
GIsiPipe *pipe = opaque;
const isi_pipe_resp_t *resp;
resp = g_isi_pipe_check_resp(pipe, PNS_PIPE_ENABLE_RESP, data, len); if (!resp || g_isi_msg_data_len(msg) != sizeof(struct isi_pipe_resp))
if (!resp) return;
return FALSE;
if (pipe->handle != resp->pipe_handle)
return;
g_isi_pipe_handle_error(pipe, resp->error_code); g_isi_pipe_handle_error(pipe, resp->error_code);
pipe->enabling = FALSE; pipe->enabling = FALSE;
if (!pipe->error) if (!pipe->error)
pipe->enabled = TRUE; pipe->enabled = TRUE;
return TRUE;
} }
static GIsiRequest *g_isi_pipe_enable(GIsiPipe *pipe) static GIsiPending *g_isi_pipe_enable(GIsiPipe *pipe)
{ {
isi_pipe_enable_req_t msg = { struct isi_pipe_enable_req msg = {
.cmd = PNS_PIPE_ENABLE_REQ, .cmd = PNS_PIPE_ENABLE_REQ,
.pipe_handle = pipe->handle, .pipe_handle = pipe->handle,
}; };
const size_t len = 3; size_t len = sizeof(struct isi_pipe_enable_req);
return g_isi_request_make(pipe->client, &msg, len, 5, return g_isi_client_send(pipe->client, &msg, len, 5, g_isi_pipe_enabled,
g_isi_pipe_enabled, pipe); pipe, NULL);
} }
/** /**
@ -286,6 +304,7 @@ int g_isi_pipe_start(GIsiPipe *pipe)
{ {
if (pipe->error) if (pipe->error)
return pipe->error; return pipe->error;
if (pipe->enabling || pipe->enabled) if (pipe->enabling || pipe->enabled)
return 0; return 0;
@ -298,33 +317,37 @@ int g_isi_pipe_start(GIsiPipe *pipe)
} }
/* Not very useful, it will never have time to trigger */ /* Not very useful, it will never have time to trigger */
static gboolean g_isi_pipe_removed(GIsiClient *client, static void g_isi_pipe_removed(const GIsiMessage *msg, void *data)
const void *restrict data, size_t len,
uint16_t object, void *opaque)
{ {
GIsiPipe *pipe = opaque; GIsiPipe *pipe = data;
const isi_pipe_resp_t *resp; const struct isi_pipe_resp *resp = g_isi_msg_data(msg);
resp = g_isi_pipe_check_resp(pipe, PNS_PIPE_REMOVE_RESP, data, len); if (g_isi_msg_error(msg) < 0) {
if (!resp) g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_TIMEOUT);
return FALSE; return;
}
if (g_isi_msg_id(msg) != PNS_PIPE_REMOVE_RESP)
return;
if (!resp || g_isi_msg_data_len(msg) != sizeof(struct isi_pipe_resp))
return;
pipe->handle = PN_PIPE_INVALID_HANDLE; pipe->handle = PN_PIPE_INVALID_HANDLE;
pipe->error = -EPIPE; pipe->error = -EPIPE;
return TRUE;
} }
static GIsiRequest *g_isi_pipe_remove(GIsiPipe *pipe) static GIsiPending *g_isi_pipe_remove(GIsiPipe *pipe)
{ {
isi_pipe_remove_req_t msg = { struct isi_pipe_remove_req msg = {
.cmd = PNS_PIPE_REMOVE_REQ, .cmd = PNS_PIPE_REMOVE_REQ,
.pipe_handle = pipe->handle, .pipe_handle = pipe->handle,
}; };
const size_t len = 3; size_t len = sizeof(struct isi_pipe_remove_req);
return g_isi_request_make(pipe->client, &msg, len, 5, return g_isi_client_send(pipe->client, &msg, len, 5, g_isi_pipe_removed,
g_isi_pipe_removed, pipe); pipe, NULL);
} }
/** /**
@ -335,11 +358,12 @@ void g_isi_pipe_destroy(GIsiPipe *pipe)
{ {
if (!pipe->error) if (!pipe->error)
g_isi_pipe_remove(pipe); g_isi_pipe_remove(pipe);
g_isi_client_destroy(pipe->client); g_isi_client_destroy(pipe->client);
g_free(pipe); g_free(pipe);
} }
void g_isi_pipe_set_error_handler(GIsiPipe *pipe, void (*cb)(GIsiPipe *)) void g_isi_pipe_set_error_handler(GIsiPipe *pipe, GIsiPipeErrorHandler cb)
{ {
pipe->error_handler = cb; pipe->error_handler = cb;
} }

View File

@ -19,17 +19,33 @@
* *
*/ */
#ifndef __GISI_PIPE_H
#define __GISI_PIPE_H
#ifdef __cplusplus
extern "C" {
#endif
struct _GIsiPipe;
typedef struct _GIsiPipe GIsiPipe; typedef struct _GIsiPipe GIsiPipe;
GIsiPipe *g_isi_pipe_create(GIsiModem *, void (*cb)(GIsiPipe *), typedef void (*GIsiPipeHandler)(GIsiPipe *pipe);
uint16_t obj1, uint16_t obj2, typedef void (*GIsiPipeErrorHandler)(GIsiPipe *pipe);
uint8_t type1, uint8_t type2);
GIsiPipe *g_isi_pipe_create(GIsiModem *modem, GIsiPipeHandler cb, uint16_t obj1,
uint16_t obj2, uint8_t type1, uint8_t type2);
void g_isi_pipe_destroy(GIsiPipe *pipe); void g_isi_pipe_destroy(GIsiPipe *pipe);
void g_isi_pipe_set_error_handler(GIsiPipe *pipe, void (*cb)(GIsiPipe *)); void g_isi_pipe_set_error_handler(GIsiPipe *pipe, GIsiPipeErrorHandler cb);
int g_isi_pipe_get_error(const GIsiPipe *pipe); int g_isi_pipe_get_error(const GIsiPipe *pipe);
void *g_isi_pipe_set_userdata(GIsiPipe *pipe, void *data); void *g_isi_pipe_set_userdata(GIsiPipe *pipe, void *data);
void *g_isi_pipe_get_userdata(GIsiPipe *pipe); void *g_isi_pipe_get_userdata(GIsiPipe *pipe);
uint8_t g_isi_pipe_get_handle(GIsiPipe *pipe); uint8_t g_isi_pipe_get_handle(GIsiPipe *pipe);
int g_isi_pipe_start(GIsiPipe *pipe); int g_isi_pipe_start(GIsiPipe *pipe);
#ifdef __cplusplus
}
#endif
#endif /* __GISI_PIPE_H */