From: Jessica Nilsson <jessica.j.nils...@stericsson.com>

---
 gisi/message.c |    8 ++
 gisi/message.h |    1 +
 gisi/modem.c   |   20 ++++
 gisi/modem.h   |    1 +
 gisi/pep.c     |  330 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gisi/pep.h     |    6 +
 gisi/pipe.c    |  180 ++++++++++++++++++++++++++++--
 gisi/pipe.h    |   17 +++
 8 files changed, 551 insertions(+), 12 deletions(-)

diff --git a/gisi/message.c b/gisi/message.c
index 8f4fe5a..9d00108 100644
--- a/gisi/message.c
+++ b/gisi/message.c
@@ -65,6 +65,14 @@ uint8_t g_isi_msg_resource(const GIsiMessage *msg)
        return msg->addr->spn_resource;
 }
 
+uint8_t g_isi_msg_device(const GIsiMessage *msg)
+{
+       if (msg == NULL || msg->addr == NULL)
+               return 0;
+
+       return msg->addr->spn_dev;
+}
+
 uint16_t g_isi_msg_object(const GIsiMessage *msg)
 {
        if (msg == NULL || msg->addr == NULL)
diff --git a/gisi/message.h b/gisi/message.h
index 95348f8..f34ce57 100644
--- a/gisi/message.h
+++ b/gisi/message.h
@@ -52,6 +52,7 @@ int g_isi_msg_version_minor(const GIsiMessage *msg);
 int g_isi_msg_error(const GIsiMessage *msg);
 const char *g_isi_msg_strerror(const GIsiMessage *msg);
 uint8_t g_isi_msg_resource(const GIsiMessage *msg);
+uint8_t g_isi_msg_device(const GIsiMessage *msg);
 uint16_t g_isi_msg_object(const GIsiMessage *msg);
 
 uint8_t g_isi_msg_id(const GIsiMessage *msg);
diff --git a/gisi/modem.c b/gisi/modem.c
index f745bb2..7657bd1 100644
--- a/gisi/modem.c
+++ b/gisi/modem.c
@@ -519,6 +519,26 @@ GIsiModem *g_isi_modem_create_by_name(const char *name)
        return g_isi_modem_create(if_nametoindex(name));
 }
 
+guint g_isi_modem_add_to_watch(GIsiModem *modem, int fd)
+{
+       GIOChannel *channel;
+       guint watch;
+
+       if (modem == NULL || fd < 0)
+               return 0;
+
+       channel = g_io_channel_unix_new(fd);
+       g_io_channel_set_close_on_unref(channel, TRUE);
+       g_io_channel_set_encoding(channel, NULL, NULL);
+       g_io_channel_set_buffered(channel, FALSE);
+       watch = g_io_add_watch(channel,
+                               G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+                               isi_callback, modem);
+       g_io_channel_unref(channel);
+
+       return watch;
+}
+
 void *g_isi_modem_set_userdata(GIsiModem *modem, void *data)
 {
        void *old;
diff --git a/gisi/modem.h b/gisi/modem.h
index 0397a87..83ba92c 100644
--- a/gisi/modem.h
+++ b/gisi/modem.h
@@ -48,6 +48,7 @@ typedef void (*GIsiDebugFunc)(const char *fmt, ...);
 GIsiModem *g_isi_modem_create(unsigned index);
 GIsiModem *g_isi_modem_create_by_name(const char *name);
 void g_isi_modem_destroy(GIsiModem *modem);
+guint g_isi_modem_add_to_watch(GIsiModem *modem, int fd);
 
 unsigned g_isi_modem_index(GIsiModem *modem);
 
diff --git a/gisi/pep.c b/gisi/pep.c
index c82dc39..98b5ee0 100644
--- a/gisi/pep.c
+++ b/gisi/pep.c
@@ -3,6 +3,7 @@
  *  oFono - Open Source Telephony
  *
  *  Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ *  Copyright (C) ST-Ericsson SA 2011.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -30,10 +31,18 @@
 #include <unistd.h>
 #include <glib.h>
 
+#include "common.h"
 #include "phonet.h"
 #include "socket.h"
+#include "modem.h"
+#include "client.h"
+#include "server.h"
 #include "pep.h"
 
+#define PN_PIPE                                        0xD9
+#define PN_PIPE_INVALID_HANDLE 0xFF
+#define PN_OBJ_PEP_GPRS                        0x30
+
 struct _GIsiPEP {
        GIsiPEPCallback ready;
        void *opaque;
@@ -42,6 +51,88 @@ struct _GIsiPEP {
        uint16_t handle;
 };
 
+struct isi_pipe_created_ind{
+       uint8_t cmd;
+       uint8_t pipe_handle;
+       uint8_t n_sb;
+       uint8_t sb_neg_fc;
+       uint8_t sb_len;
+       uint8_t tx_fc;
+       uint8_t rx_fc;
+};
+
+struct isi_pep_resp {
+       uint8_t pipe_handle;
+       uint8_t error_code;
+};
+
+struct isi_pep_connect_req{
+       uint8_t cmd;
+       uint8_t pipe_handle;
+       uint8_t state_after;
+       uint8_t other_pep_type;
+       uint8_t filler1;
+       uint8_t filler2;
+       uint8_t n_sb;
+       uint8_t data_sb;
+       uint8_t sb_len;
+       uint8_t alignment;
+       uint8_t filler;
+};
+
+struct isi_pipe_enabled_ind{
+       uint8_t cmd;
+       uint8_t pipe_handle;
+       uint8_t filler;
+};
+
+
+struct isi_pep_enable_req{
+       uint8_t cmd;
+       uint8_t pipe_handle;
+       uint8_t filler;
+};
+
+struct isi_pep_disconnect_req{
+       uint8_t cmd;
+       uint8_t pipe_handle;
+       uint8_t filler;
+};
+
+enum pn_flow_control {
+       PN_NO_FLOW_CONTROL =            0x00,
+       PN_LEGACY_FLOW_CONTROL =        0x01,
+       PN_ONE_CREDIT_FLOW_CONTROL =    0x02,
+       PN_MULTI_CREDIT_FLOW_CONTROL =  0x03,
+};
+
+enum isi_pep_message_id {
+       PNS_PEP_CONNECT_REQ =           0x40,
+       PNS_PEP_CONNECT_RESP =          0x41,
+       PNS_PEP_DISCONNECT_REQ =        0x42,
+       PNS_PEP_DISCONNECT_RESP =       0x43,
+       PNS_PEP_ENABLE_REQ =            0x46,
+       PNS_PEP_ENABLE_RESP =           0x47,
+       PNS_PIPE_CREATED_IND =          0x61,
+       PNS_PIPE_ENABLED_IND =          0x64,
+};
+
+enum isi_pep_sb_id {
+       PN_PIPE_SB_NEGOTIATED_FC =      0x03,
+       PN_PIPE_SB_ALIGNED_DATA =       0x06,
+};
+
+enum isi_pep_type {
+       PN_PEP_TYPE_COMMON
+};
+
+enum pn_pep_state {    /* initial pep state */
+       PN_PEP_DISABLE,
+       PN_PEP_ENABLE,
+};
+
+
+static void g_isi_pep_disconnected(const GIsiMessage *msg, void *data);
 
 static gboolean g_isi_pep_callback(GIOChannel *channel, GIOCondition cond,
                                        gpointer data)
@@ -153,3 +244,242 @@ char *g_isi_pep_get_ifname(const GIsiPEP *pep, char 
*ifname)
 
        return if_indextoname(g_isi_pep_get_ifindex(pep), ifname);
 }
+
+static void g_isi_pep_connected(const GIsiMessage *msg, void *data)
+{
+       struct isi_pep_resp *resp;
+       size_t len = sizeof(struct isi_pep_resp);
+       GIsiPipe *pipe = data;
+       GIsiClient *client = g_isi_pipe_client(pipe);
+       struct isi_pipe_created_ind ind = {
+               .cmd = PNS_PIPE_CREATED_IND,
+               .pipe_handle = 0x00,
+               .n_sb = 0x01,
+               .sb_neg_fc = PN_PIPE_SB_NEGOTIATED_FC,
+               .sb_len = 0x04,
+               .tx_fc = PN_LEGACY_FLOW_CONTROL,
+               .rx_fc = PN_LEGACY_FLOW_CONTROL,
+       };
+
+       if (g_isi_msg_error(msg) < 0) {
+               g_isi_pipe_set_error_timeout(pipe);
+               return;
+       }
+
+       if (g_isi_msg_id(msg) != PNS_PEP_CONNECT_RESP)
+               return;
+
+       if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &resp, len))
+               return;
+
+       if (resp->pipe_handle == PN_PIPE_INVALID_HANDLE) {
+               g_isi_pipe_handle_error(pipe, resp->error_code);
+               return;
+       }
+
+       g_isi_pipe_set_handle(pipe, resp->pipe_handle);
+       ind.pipe_handle = resp->pipe_handle;
+
+       if (g_isi_request_sendto(g_isi_client_modem(client), msg->addr, &ind,
+                       sizeof(ind), G_ISI_CLIENT_DEFAULT_TIMEOUT,
+                       NULL, NULL, NULL) == NULL) {
+                       g_isi_pipe_set_error_general(pipe);
+                       return;
+       }
+
+       if (g_isi_msg_device(msg) == PN_DEV_HOST) {
+               g_isi_pep_connect(pipe, g_isi_pipe_get_handle(pipe),
+                                       PN_DEV_MODEM);
+               return;
+       }
+
+       if (g_isi_pipe_get_enabling(pipe))
+               g_isi_pipe_start(pipe);
+
+       g_isi_pipe_start_handler(pipe);
+
+}
+
+gboolean g_isi_pep_connect(GIsiPipe *pipe, uint8_t obj, uint8_t dev)
+{
+       GIsiClient *client =  g_isi_pipe_client(pipe);
+       struct sockaddr_pn dst = {
+               .spn_family = AF_PHONET,
+       };
+       struct isi_pep_connect_req msg = {
+               .cmd = PNS_PEP_CONNECT_REQ,
+               .pipe_handle = obj,
+               .state_after = PN_PEP_DISABLE,
+               .other_pep_type = PN_PEP_TYPE_COMMON,
+               .filler1 = 0x00,
+               .filler2 = 0x00,
+               .n_sb = 0x00,
+       };
+
+       if (dev == PN_DEV_HOST) {
+               dst.spn_dev = PN_DEV_HOST;
+               dst.spn_resource = PN_PIPE;
+               dst.spn_obj = obj;
+       } else if (dev == PN_DEV_MODEM) {
+               dst.spn_dev = PN_DEV_MODEM;
+               dst.spn_resource = g_isi_client_resource(client);
+               dst.spn_obj = PN_OBJ_PEP_GPRS;
+       } else
+               return FALSE;
+
+       if (g_isi_request_sendto(g_isi_client_modem(client), &dst, &msg,
+                       sizeof(msg), G_ISI_CLIENT_DEFAULT_TIMEOUT,
+                       g_isi_pep_connected, pipe, NULL) == NULL)
+               return FALSE;
+
+       return TRUE;
+}
+
+static void g_isi_pep_enabled(const GIsiMessage *msg, void *data)
+{
+       struct isi_pep_resp *resp;
+       size_t len = sizeof(struct isi_pep_resp);
+       GIsiPipe *pipe = data;
+       GIsiClient *client = g_isi_pipe_client(pipe);
+       struct isi_pipe_enabled_ind ind = {
+               .cmd = PNS_PIPE_ENABLED_IND,
+               .pipe_handle = g_isi_pipe_get_handle(pipe),
+               .filler = 0x00,
+       };
+
+       if (g_isi_msg_error(msg) < 0) {
+               g_isi_pipe_set_error_timeout(pipe);
+               return;
+       }
+
+       if (g_isi_msg_id(msg) != PNS_PEP_ENABLE_RESP)
+               return;
+
+       if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &resp, len))
+               return;
+
+       if (g_isi_pipe_get_handle(pipe) != resp->pipe_handle) {
+               g_isi_pipe_set_error_invalid_handle(pipe);
+               return;
+       }
+
+       g_isi_pipe_handle_error(pipe, resp->error_code);
+       if (g_isi_pipe_get_error(pipe))
+               return;
+
+       if (g_isi_request_sendto(g_isi_client_modem(client), msg->addr, &ind,
+                       sizeof(ind), G_ISI_CLIENT_DEFAULT_TIMEOUT,
+                       NULL, NULL, NULL) == NULL) {
+                       g_isi_pipe_set_error_general(pipe);
+                       return;
+       }
+
+       if (g_isi_msg_device(msg) == PN_DEV_MODEM) {
+               g_isi_pep_enable(pipe, PN_DEV_HOST);
+               return;
+       }
+       g_isi_pipe_set_enabling(pipe, FALSE);
+
+       if (!g_isi_pipe_get_error(pipe))
+               g_isi_pipe_set_enabled(pipe, TRUE);
+}
+
+void g_isi_pep_enable(GIsiPipe *pipe, uint8_t dev)
+{
+       GIsiClient *client = g_isi_pipe_client(pipe);
+       struct sockaddr_pn dst = {
+               .spn_family = AF_PHONET,
+       };
+       struct isi_pep_enable_req msg = {
+               .cmd = PNS_PEP_ENABLE_REQ,
+               .pipe_handle = g_isi_pipe_get_handle(pipe),
+               .filler = 0x00,
+       };
+
+       if (dev == PN_DEV_HOST) {
+               dst.spn_dev = PN_DEV_HOST;
+               dst.spn_resource = PN_PIPE;
+               dst.spn_obj = g_isi_pipe_get_handle(pipe);
+       } else if (dev == PN_DEV_MODEM) {
+               dst.spn_dev = PN_DEV_MODEM;
+               dst.spn_resource = g_isi_client_resource(client);
+               dst.spn_obj = PN_OBJ_PEP_GPRS;
+       } else
+               return;
+
+       if (g_isi_request_sendto(g_isi_client_modem(client), &dst, &msg,
+                       sizeof(msg), G_ISI_CLIENT_DEFAULT_TIMEOUT,
+                       g_isi_pep_enabled, pipe, NULL) == NULL)
+               return;
+
+       return;
+}
+
+static void g_isi_pep_disconnected(const GIsiMessage *msg, void *data)
+{
+       struct isi_pep_resp *resp;
+       size_t len = sizeof(struct isi_pep_resp);
+       GIsiPipe *pipe = data;
+
+       if (g_isi_msg_error(msg) < 0) {
+               g_isi_pipe_set_error_timeout(pipe);
+               return;
+       }
+
+       if (g_isi_msg_id(msg) != PNS_PEP_DISCONNECT_RESP)
+               return;
+
+       if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &resp, len))
+               return;
+
+       if (resp->pipe_handle == PN_PIPE_INVALID_HANDLE) {
+               g_isi_pipe_handle_error(pipe, resp->error_code);
+               return;
+       }
+
+       if (g_isi_pipe_get_handle(pipe) != resp->pipe_handle) {
+               g_isi_pipe_set_error_invalid_handle(pipe);
+               return;
+       }
+
+       if (g_isi_msg_device(msg) == PN_DEV_HOST) {
+               g_isi_pep_disconnect(pipe, PN_DEV_MODEM);
+               return;
+       }
+
+       g_isi_pipe_server_destroy(pipe);
+       g_isi_client_destroy(g_isi_pipe_client(pipe));
+       g_free(pipe);
+}
+
+
+void g_isi_pep_disconnect(GIsiPipe *pipe, uint8_t dev)
+{
+       GIsiClient *client = g_isi_pipe_client(pipe);
+       struct sockaddr_pn dst = {
+               .spn_family = AF_PHONET,
+       };
+       struct isi_pep_disconnect_req msg = {
+               .cmd = PNS_PEP_DISCONNECT_REQ,
+               .pipe_handle = g_isi_pipe_get_handle(pipe),
+               .filler = 0x00,
+       };
+
+       if (dev == PN_DEV_HOST) {
+               dst.spn_dev = PN_DEV_HOST;
+               dst.spn_resource = PN_PIPE;
+               dst.spn_obj = g_isi_pipe_get_handle(pipe);
+       } else if (dev == PN_DEV_MODEM) {
+               dst.spn_dev = PN_DEV_MODEM;
+               dst.spn_resource = g_isi_client_resource(client);
+               dst.spn_obj = PN_OBJ_PEP_GPRS;
+       } else
+               return;
+
+       if (g_isi_request_sendto(g_isi_client_modem(client), &dst, &msg,
+                       sizeof(msg), G_ISI_CLIENT_DEFAULT_TIMEOUT,
+                       g_isi_pep_disconnected, pipe, NULL) == NULL)
+               return;
+
+       return;
+}
diff --git a/gisi/pep.h b/gisi/pep.h
index d46c8d0..1be5e10 100644
--- a/gisi/pep.h
+++ b/gisi/pep.h
@@ -23,6 +23,7 @@
 #define __GISI_PEP_H
 
 #include "modem.h"
+#include "pipe.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,6 +38,11 @@ uint16_t g_isi_pep_get_object(const GIsiPEP *pep);
 unsigned g_isi_pep_get_ifindex(const GIsiPEP *pep);
 char *g_isi_pep_get_ifname(const GIsiPEP *pep, char *ifname);
 
+void g_isi_pep_enable(GIsiPipe *pipe, uint8_t dev);
+gboolean g_isi_pep_connect(GIsiPipe *pipe, uint8_t obj, uint8_t dev);
+void g_isi_pep_disconnect(GIsiPipe *pipe, uint8_t dev);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/gisi/pipe.c b/gisi/pipe.c
index 1bd5140..cf7d3c6 100644
--- a/gisi/pipe.c
+++ b/gisi/pipe.c
@@ -24,15 +24,23 @@
 #endif
 
 #include <stdint.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <errno.h>
 #include <glib.h>
 
 #include "client.h"
 #include "pipe.h"
+#include "pep.h"
+#include "common.h"
 
 #define PN_PIPE                        0xD9
 #define PN_PIPE_INVALID_HANDLE 0xFF
 
+#define PN_OBJ_PEP_GPRS                0x30
+
 struct isi_pipe_create_req {
        uint8_t cmd;
        uint8_t state_after;
@@ -73,6 +81,8 @@ struct isi_pipe_resp {
        uint8_t error2;
 };
 
+
+
 enum isi_pipe_message_id {
        PNS_PIPE_CREATE_REQ,
        PNS_PIPE_CREATE_RESP,
@@ -86,6 +96,8 @@ enum isi_pipe_message_id {
        PNS_PIPE_REDIRECT_RESP,
        PNS_PIPE_DISABLE_REQ,
        PNS_PIPE_DISABLE_RESP,
+       PNS_PIPE_CREATED_IND =          0x61,
+       PNS_PIPE_ENABLED_IND =          0x64,
 };
 
 enum pn_pipe_error {   /* error codes */
@@ -103,6 +115,7 @@ enum pn_pipe_error {        /* error codes */
        PN_PIPE_ERR_NOT_SUPPORTED,
 };
 
+
 enum pn_pipe_state {   /* initial pipe state */
        PN_PIPE_DISABLE,
        PN_PIPE_ENABLE,
@@ -113,6 +126,14 @@ enum pn_msg_priority {
        PN_MSG_PRIORITY_HIGH,
 };
 
+
+
+struct _GIsiPipeServer {
+       int fd;
+       guint watch;
+};
+typedef struct _GIsiPipeServer GIsiPipeServer;
+
 struct _GIsiPipe {
        GIsiClient *client;
        GIsiPipeHandler handler;
@@ -122,8 +143,11 @@ struct _GIsiPipe {
        uint8_t handle;
        gboolean enabled;
        gboolean enabling;
+       GIsiPipeServer *server;
 };
 
+
+
 static int g_isi_pipe_error(enum pn_pipe_error code)
 {
        switch (code) {
@@ -155,7 +179,7 @@ static int g_isi_pipe_error(enum pn_pipe_error code)
        return -EBADMSG;
 }
 
-static void g_isi_pipe_handle_error(GIsiPipe *pipe, uint8_t code)
+void g_isi_pipe_handle_error(GIsiPipe *pipe, uint8_t code)
 {
        int err = g_isi_pipe_error(code);
 
@@ -168,6 +192,61 @@ static void g_isi_pipe_handle_error(GIsiPipe *pipe, 
uint8_t code)
                pipe->error_handler(pipe);
 }
 
+
+GIsiClient *g_isi_pipe_client(GIsiPipe *pipe)
+{
+       return pipe != NULL ? pipe->client : NULL;
+}
+
+
+void g_isi_pipe_set_handle(GIsiPipe *pipe, uint8_t handle)
+{
+       pipe->handle = handle;
+}
+
+static GIsiPipeServer *g_isi_pipe_server_create(GIsiModem *modem)
+{
+       GIsiPipeServer *server;
+       unsigned ifindex = g_isi_modem_index(modem);
+       struct sockaddr_pn addr = {
+               .spn_family = AF_PHONET,
+               .spn_resource = PN_PIPE,
+               .spn_obj = PN_OBJ_PEP_GPRS,
+       };
+       char buf[IF_NAMESIZE];
+       int fd = socket(PF_PHONET, SOCK_DGRAM, 0);
+
+       if (fd == -1)
+               return NULL;
+
+       server = g_try_new0(GIsiPipeServer, 1);
+       if (server == NULL)
+               goto error;
+
+       fcntl(fd, F_SETFD, FD_CLOEXEC);
+       /* Use blocking mode on purpose. */
+
+       if (ifindex == 0)
+               g_warning("Unspecified modem interface index");
+       else if (if_indextoname(ifindex, buf) == NULL ||
+               setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, IF_NAMESIZE))
+               goto error;
+
+       if (bind(fd, (void *)&addr, sizeof(addr)))
+               goto error;
+
+       server->fd = fd;
+       server->watch = g_isi_modem_add_to_watch(modem, fd);
+       if (!server->watch)
+               goto error;
+
+       return server;
+
+error:
+       close(fd);
+       return NULL;
+}
+
 static void g_isi_pipe_created(const GIsiMessage *msg, void *data)
 {
        struct isi_pipe_resp *resp;
@@ -226,6 +305,7 @@ GIsiPipe *g_isi_pipe_create(GIsiModem *modem, 
GIsiPipeHandler cb, uint16_t obj1,
        };
        size_t len = sizeof(msg);
        GIsiPipe *pipe;
+       gboolean legacy = g_isi_modem_flags(modem);
 
        pipe = g_try_new0(GIsiPipe, 1);
        if (pipe == NULL) {
@@ -247,16 +327,34 @@ GIsiPipe *g_isi_pipe_create(GIsiModem *modem, 
GIsiPipeHandler cb, uint16_t obj1,
        pipe->enabled = FALSE;
        pipe->handle = PN_PIPE_INVALID_HANDLE;
 
-       if (g_isi_client_send(pipe->client, &msg, len,
-                                       g_isi_pipe_created, pipe, NULL))
-               return pipe;
+       if (legacy) {
+               if (!g_isi_client_send(pipe->client, &msg, len,
+                       g_isi_pipe_created, pipe, NULL))
+                       goto error;
+
+       } else {
+               pipe->server = g_isi_pipe_server_create(modem);
+               if (pipe->server == NULL)
+                       goto error;
+
+               if (!g_isi_pep_connect(pipe, obj1 & 0xFF, PN_DEV_HOST)) {
+                                       g_isi_pipe_server_destroy(pipe);
+               goto error;
+               }
+       }
 
+       return pipe;
+
+
+error:
        g_isi_client_destroy(pipe->client);
        g_free(pipe);
 
        return NULL;
 }
 
+
+
 static void g_isi_pipe_enabled(const GIsiMessage *msg, void *data)
 {
        GIsiPipe *pipe = data;
@@ -287,14 +385,20 @@ static void g_isi_pipe_enabled(const GIsiMessage *msg, 
void *data)
 
 static void g_isi_pipe_enable(GIsiPipe *pipe)
 {
+       GIsiModem *modem = g_isi_client_modem(pipe->client);
+       gboolean legacy = g_isi_modem_flags(modem);
        struct isi_pipe_enable_req msg = {
                .cmd = PNS_PIPE_ENABLE_REQ,
                .pipe_handle = pipe->handle,
        };
        size_t len = sizeof(msg);
 
-       g_isi_client_send(pipe->client, &msg, len,
-                               g_isi_pipe_enabled, pipe, NULL);
+       if (legacy)
+               g_isi_client_send(pipe->client, &msg, len,
+                                       g_isi_pipe_enabled, pipe, NULL);
+       else
+               g_isi_pep_enable(pipe, PN_DEV_MODEM);
+
 }
 
 /**
@@ -339,8 +443,8 @@ static void g_isi_pipe_removed(const GIsiMessage *msg, void 
*data)
        if (pipe->handle != resp->pipe_handle)
                return;
 
-       pipe->handle = PN_PIPE_INVALID_HANDLE;
-       pipe->error = -EPIPE;
+       g_isi_client_destroy(pipe->client);
+       g_free(pipe);
 }
 
 
@@ -356,17 +460,32 @@ static void g_isi_pipe_remove(GIsiPipe *pipe)
                                g_isi_pipe_removed, pipe, NULL);
 }
 
+
 /**
  * Destroy a pipe. If it was connected, it is removed.
  * @param pipe pipe as returned from g_isi_pipe_create()
  */
 void g_isi_pipe_destroy(GIsiPipe *pipe)
 {
-       if (!pipe->error)
-               g_isi_pipe_remove(pipe);
+       GIsiModem *modem = g_isi_client_modem(pipe->client);
+       gboolean legacy = g_isi_modem_flags(modem);
+
+       if (!pipe->error) {
+               if (legacy)
+                       g_isi_pipe_remove(pipe);
+               else
+                       g_isi_pep_disconnect(pipe, PN_DEV_HOST);
+       }
 
-       g_isi_client_destroy(pipe->client);
-       g_free(pipe);
+}
+
+
+void g_isi_pipe_server_destroy(GIsiPipe *pipe)
+{
+       if (pipe->server->watch > 0)
+               g_source_remove(pipe->server->watch);
+
+       g_free(pipe->server);
 }
 
 void g_isi_pipe_set_error_handler(GIsiPipe *pipe, GIsiPipeErrorHandler cb)
@@ -403,3 +522,40 @@ uint8_t g_isi_pipe_get_handle(GIsiPipe *pipe)
 {
        return pipe->handle;
 }
+
+void g_isi_pipe_start_handler(GIsiPipe *pipe)
+{
+       if (pipe->handler)
+               pipe->handler(pipe);
+}
+
+gboolean g_isi_pipe_get_enabling(GIsiPipe *pipe)
+{
+       return pipe->enabling;
+}
+
+void g_isi_pipe_set_enabling(GIsiPipe *pipe, gboolean value)
+{
+       pipe->enabling = value;
+}
+
+void g_isi_pipe_set_enabled(GIsiPipe *pipe, gboolean value)
+{
+       pipe->enabled = value;
+}
+
+void g_isi_pipe_set_error_general(GIsiPipe *pipe)
+{
+       g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_GENERAL);
+
+}
+
+void g_isi_pipe_set_error_timeout(GIsiPipe *pipe)
+{
+       g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_TIMEOUT);
+}
+
+void g_isi_pipe_set_error_invalid_handle(GIsiPipe *pipe)
+{
+       g_isi_pipe_handle_error(pipe, PN_PIPE_ERR_INVALID_HANDLE);
+}
\ No newline at end of file
diff --git a/gisi/pipe.h b/gisi/pipe.h
index 01265a9..4570821 100644
--- a/gisi/pipe.h
+++ b/gisi/pipe.h
@@ -26,24 +26,41 @@
 extern "C" {
 #endif
 
+#include "client.h"
+
 struct _GIsiPipe;
 typedef struct _GIsiPipe GIsiPipe;
 
+
 typedef void (*GIsiPipeHandler)(GIsiPipe *pipe);
 typedef void (*GIsiPipeErrorHandler)(GIsiPipe *pipe);
 
 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_server_destroy(GIsiPipe *pipe);
 
 void g_isi_pipe_set_error_handler(GIsiPipe *pipe, GIsiPipeErrorHandler cb);
 int g_isi_pipe_get_error(const GIsiPipe *pipe);
 void *g_isi_pipe_set_userdata(GIsiPipe *pipe, void *data);
 void *g_isi_pipe_get_userdata(GIsiPipe *pipe);
 uint8_t g_isi_pipe_get_handle(GIsiPipe *pipe);
+gboolean g_isi_pipe_get_enabling(GIsiPipe *pipe);
+void g_isi_pipe_set_enabling(GIsiPipe *pipe, gboolean value);
+void g_isi_pipe_set_enabled(GIsiPipe *pipe, gboolean value);
 
 int g_isi_pipe_start(GIsiPipe *pipe);
 
+GIsiClient *g_isi_pipe_client(GIsiPipe *pipe);
+void g_isi_pipe_set_handle(GIsiPipe *pipe, uint8_t handle);
+void g_isi_pipe_start_handler(GIsiPipe *pipe);
+
+void g_isi_pipe_handle_error(GIsiPipe *pipe, uint8_t code);
+void g_isi_pipe_set_error_general(GIsiPipe *pipe);
+void g_isi_pipe_set_error_timeout(GIsiPipe *pipe);
+void g_isi_pipe_set_error_invalid_handle(GIsiPipe *pipe);
+
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.7.3.5

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to