#define CHANNEL_PS 3
#define CHANNEL_SAT 2
#define CHANNEL_SS 2
+#define CHANNEL_DATA_1 6
+#define CHANNEL_DATA_2 7
#define CHANNEL_NONE -1
struct custom_data {
return ret;
}
+static guint register_gio_watch(TcoreHal *h, int fd, void *callback)
+{
+ GIOChannel *channel = NULL;
+ guint source;
+
+ if (fd < 0 || !callback)
+ return 0;
+
+ channel = g_io_channel_unix_new(fd);
+ source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) callback, h);
+ g_io_channel_unref(channel);
+ channel = NULL;
+
+ return source;
+}
+
+static int create_tun(const char **interface)
+{
+ GIOChannel *channel;
+ struct ifreq ifr;
+ int fd, err;
+
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0)
+ return fd;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ strcpy(ifr.ifr_name, "gprs%d");
+
+ err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (err < 0) {
+ close(fd);
+ return -1;
+ }
+
+ *interface = g_strdup(ifr.ifr_name);
+
+ channel = g_io_channel_unix_new(fd);
+ if (channel == NULL) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+/*
+ * This function is reading data from /dev/net/tun and sending it to logical
+ * HAL bound to DATA multiplexed channel
+ */
+static gboolean on_recv_data_message(GIOChannel *channel, GIOCondition condition, gpointer data)
+{
+ TcoreHal *hal = data;
+ struct custom_data *custom;
+ char buf[BUF_LEN_MAX];
+ int n = 0;
+
+ custom = tcore_hal_ref_user_data(hal);
+ memset(buf, 0, BUF_LEN_MAX);
+ n = fd_read(custom->hal_fd, buf, BUF_LEN_MAX);
+ if (n < 0) {
+ err("fd_read error. return_valute = %d", n);
+ return TRUE;
+ }
+
+ msg("=== TX %s data DUMP =====", tcore_hal_get_name(hal));
+ util_hex_dump(" ", n, buf);
+ msg("=== TX %s data DUMP =====", tcore_hal_get_name(hal));
+
+ /* Send to cmux data channel for encoding */
+ tcore_hal_send_data(hal, n, buf);
+
+ return TRUE;
+}
+
+/*
+ * This function is receiving data from logical HAL bound to DATA multiplexed
+ * channel and writing it to /dev/net/tun
+ */
+static void on_hal_recv(TcoreHal *hal, unsigned int data_len, const void *data, void *user_data)
+{
+ int ret;
+ struct custom_data *cdata;
+ cdata = tcore_hal_ref_user_data(hal);
+
+ if (!cdata) {
+ err("hal user data is NULL");
+ return;
+ }
+
+ ret = fd_write(cdata->hal_fd, (void *)data, data_len);
+ if(ret < 0)
+ err("fd_write failed");
+
+ msg("=== RX %s data DUMP =====", tcore_hal_get_name(hal));
+ util_hex_dump(" ", data_len, data);
+ msg("=== RX %s data DUMP =====", tcore_hal_get_name(hal));
+}
+
+static void on_response_setup_pdp(TcorePending *p, int data_len, const void *data, void *user_data)
+{
+ TcoreHal *hal = user_data;
+ const TcoreATResponse *resp = data;
+ const char *interface = NULL;
+ struct custom_data *cdata = tcore_hal_ref_user_data(hal);
+ CoreObject *co = tcore_pending_ref_core_object(p);
+ TcoreHalSetupPDPCallBack func = (TcoreHalSetupPDPCallBack)cdata->cb;
+
+ dbg("Entered");
+
+ if (resp->success) {
+ dbg("Response Ok");
+
+ cdata->hal_fd = create_tun(&interface);
+ if (cdata->hal_fd < 0) {
+ func(co, NULL, cdata->cb_data);
+
+ g_free(cdata);
+ cdata = NULL;
+
+ return;
+ }
+
+ dbg("interface: %s", interface);
+
+ cdata->watch_id= register_gio_watch(hal, cdata->hal_fd, on_recv_data_message);
+ tcore_hal_set_mode(hal, TCORE_HAL_MODE_DATA);
+ tcore_hal_add_recv_callback(hal, on_hal_recv, NULL);
+
+ func(co, interface, cdata->cb_data);
+
+ return;
+ }
+
+ func(co, NULL, cdata->cb_data);
+ g_free(cdata);
+
+ dbg("Response NOk");
+
+ return;
+}
+
+static TReturn hal_setup_pdp(CoreObject *co, TcoreHalSetupPDPCallBack func,
+ void *user_data, unsigned int cid)
+{
+ TcorePending *pending = NULL;
+ TcoreHal *hal = NULL;
+ char *cmd_str = NULL;
+ struct custom_data *cdata;
+
+ dbg("entry");
+
+ if (cid == 1)
+ hal = tcore_cmux_get_hal_channel(CHANNEL_DATA_1);
+ else if (cid == 2)
+ hal = tcore_cmux_get_hal_channel(CHANNEL_DATA_2);
+
+ if (hal == NULL) {
+ err("Fail to get channel data");
+ return TCORE_RETURN_FAILURE;
+ }
+
+ /*
+ * If data call was previously UP, hal was in MODE_DATA
+ * Set it back to MODE_AT to configure the channel and
+ * remove the hal receive callback.
+ */
+ if (tcore_hal_get_mode(hal) == TCORE_HAL_MODE_DATA) {
+ cdata = tcore_hal_ref_user_data(hal);
+
+ if (cdata->hal_fd) {
+ close(cdata->hal_fd);
+ cdata->hal_fd = -1;
+ }
+
+ g_source_remove(cdata->watch_id);
+
+ g_free(cdata);
+ cdata = NULL;
+
+ dbg("Set MODE_AT");
+ tcore_hal_set_mode(hal, TCORE_HAL_MODE_AT);
+ dbg("Remove old reveice cb");
+ tcore_hal_remove_recv_callback(hal, on_hal_recv);
+ }
+
+ cdata = g_new0(struct custom_data, 1);
+
+ cdata->cb = (void *)func;
+ cdata->cb_data = user_data;
+
+ tcore_hal_link_user_data(hal, cdata);
+
+ cmd_str = g_strdup_printf("AT+CGDATA=\"M-RAW_IP\",%d", cid);
+ pending = tcore_at_pending_new(co, cmd_str, NULL, TCORE_AT_NO_RESULT, on_response_setup_pdp, hal);
+ g_free(cmd_str);
+
+ if (pending == NULL) {
+ err("Fail to create AT+CGDATA pending request");
+
+ g_free(cdata);
+
+ return TCORE_RETURN_FAILURE;
+ }
+
+ tcore_hal_send_request(hal, pending);
+
+ return TCORE_RETURN_SUCCESS;
+}
+
static struct tcore_hal_operations hops =
{
.power = hal_power,
.send = hal_send,
.set_sound_path = pr3_audio_set_sound_path,
.link_object_channel = hal_link_object_channel,
+ .setup_pdp = hal_setup_pdp,
};
static gboolean on_recv_tty_message(GIOChannel *channel, GIOCondition condition, gpointer data)
return TRUE;
}
-static guint register_gio_watch(TcoreHal *h, int fd, void *callback)
-{
- GIOChannel *channel = NULL;
- guint source;
-
- if (fd < 0 || !callback)
- return 0;
-
- channel = g_io_channel_unix_new(fd);
- source = g_io_add_watch(channel, G_IO_IN, (GIOFunc) callback, h);
- g_io_channel_unref(channel);
- channel = NULL;
-
- return source;
-}
-
static gboolean on_load()
{
dbg("I'm load!");