Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gisi / socket.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2009-2010  Nokia Corporation and/or its subsidiary(-ies).
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdint.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/ioctl.h>
30 #include <unistd.h>
31 #include <net/if.h>
32 #include <fcntl.h>
33 #include <glib.h>
34
35 #include "phonet.h"
36 #include "socket.h"
37
38 GIOChannel *g_isi_phonet_new(unsigned ifindex)
39 {
40         GIOChannel *channel;
41         struct sockaddr_pn addr = {
42                 .spn_family = AF_PHONET,
43         };
44         char buf[IF_NAMESIZE];
45
46         int fd = socket(PF_PHONET, SOCK_DGRAM, 0);
47         if (fd == -1)
48                 return NULL;
49
50         fcntl(fd, F_SETFD, FD_CLOEXEC);
51         /* Use blocking mode on purpose. */
52
53         if (ifindex == 0)
54                 g_warning("Unspecified modem interface index");
55         else if (if_indextoname(ifindex, buf) == NULL ||
56                 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, IF_NAMESIZE))
57                 goto error;
58
59         if (bind(fd, (void *)&addr, sizeof(addr)))
60                 goto error;
61
62         channel = g_io_channel_unix_new(fd);
63         g_io_channel_set_close_on_unref(channel, TRUE);
64         g_io_channel_set_encoding(channel, NULL, NULL);
65         g_io_channel_set_buffered(channel, FALSE);
66         return channel;
67
68 error:
69         close(fd);
70         return NULL;
71 }
72
73 size_t g_isi_phonet_peek_length(GIOChannel *channel)
74 {
75         int len;
76         int fd = g_io_channel_unix_get_fd(channel);
77
78         return ioctl(fd, FIONREAD, &len) ? 0 : len;
79 }
80
81 ssize_t g_isi_phonet_read(GIOChannel *channel, void *restrict buf, size_t len,
82                                 struct sockaddr_pn *addr)
83 {
84         socklen_t addrlen = sizeof(struct sockaddr_pn);
85         ssize_t ret;
86
87         ret = recvfrom(g_io_channel_unix_get_fd(channel), buf, len,
88                         MSG_DONTWAIT, (void *)addr, &addrlen);
89         if (ret == -1)
90                 return -1;
91
92         return ret;
93 }