3 * neard - Near Field Communication manager
5 * Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
30 #include <sys/socket.h>
32 #include <linux/socket.h>
33 #include <linux/nfc.h>
35 #include <near/plugin.h>
37 #include <near/types.h>
39 #include <near/device.h>
40 #include <near/adapter.h>
42 #include <near/ndef.h>
46 static GSList *driver_list = NULL;
47 static GList *server_list = NULL;
50 struct near_p2p_driver *driver;
60 static gboolean p2p_client_event(GIOChannel *channel, GIOCondition condition,
63 struct p2p_data *client_data = user_data;
66 DBG("condition 0x%x", condition);
68 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
71 if (client_data->watch > 0)
72 g_source_remove(client_data->watch);
73 client_data->watch = 0;
75 if (condition & (G_IO_NVAL | G_IO_ERR))
80 if (client_data->driver->close != NULL)
81 client_data->driver->close(client_data->fd, err);
83 near_error("%s client channel closed",
84 client_data->driver->name);
89 more = client_data->driver->read(client_data->fd,
90 client_data->adapter_idx,
91 client_data->target_idx,
95 if (client_data->driver->close != NULL)
96 client_data->driver->close(client_data->fd, 0);
97 close(client_data->fd);
103 static void free_client_data(gpointer data)
105 struct p2p_data *client_data;
109 client_data = (struct p2p_data *) data;
111 if (client_data->driver->close != NULL)
112 client_data->driver->close(client_data->fd, 0);
114 if (client_data->watch > 0)
115 g_source_remove(client_data->watch);
120 static void free_server_data(gpointer data)
122 struct p2p_data *server_data;
126 server_data = (struct p2p_data *)data;
128 if (server_data->watch > 0)
129 g_source_remove(server_data->watch);
130 server_data->watch = 0;
131 g_list_free_full(server_data->client_list, free_client_data);
132 server_data->client_list = NULL;
134 DBG("Closing server socket");
136 close(server_data->fd);
141 static gboolean p2p_listener_event(GIOChannel *channel, GIOCondition condition,
144 struct sockaddr_nfc_llcp client_addr;
145 socklen_t client_addr_len;
146 int server_fd, client_fd;
147 struct p2p_data *client_data, *server_data = user_data;
148 GIOChannel *client_channel;
149 struct near_p2p_driver *driver = server_data->driver;
151 DBG("condition 0x%x", condition);
153 server_fd = g_io_channel_unix_get_fd(channel);
155 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
156 if (server_data->watch > 0)
157 g_source_remove(server_data->watch);
158 server_data->watch = 0;
160 g_list_free_full(server_data->client_list, free_client_data);
161 server_data->client_list = NULL;
163 near_error("Error with %s server channel", driver->name);
168 client_addr_len = sizeof(client_addr);
169 client_fd = accept(server_fd, (struct sockaddr *) &client_addr,
172 near_error("accept failed %d", client_fd);
177 DBG("client dsap %d ssap %d",
178 client_addr.dsap, client_addr.ssap);
179 DBG("target idx %d", client_addr.target_idx);
181 client_data = g_try_malloc0(sizeof(struct p2p_data));
182 if (client_data == NULL) {
187 client_data->driver = server_data->driver;
188 client_data->adapter_idx = server_data->adapter_idx;
189 client_data->target_idx = client_addr.target_idx;
190 client_data->fd = client_fd;
191 client_data->cb = server_data->cb;
193 client_channel = g_io_channel_unix_new(client_fd);
194 g_io_channel_set_close_on_unref(client_channel, TRUE);
196 client_data->watch = g_io_add_watch(client_channel,
197 G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
201 server_data->client_list = g_list_append(server_data->client_list, client_data);
206 static int p2p_bind(struct near_p2p_driver *driver, uint32_t adapter_idx,
207 near_device_io_cb cb)
210 struct sockaddr_nfc_llcp addr;
212 struct p2p_data *server_data;
214 DBG("Binding %s", driver->name);
216 fd = socket(AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP);
220 memset(&addr, 0, sizeof(struct sockaddr_nfc_llcp));
221 addr.sa_family = AF_NFC;
222 addr.dev_idx = adapter_idx;
223 addr.nfc_protocol = NFC_PROTO_NFC_DEP;
224 addr.service_name_len = strlen(driver->service_name);
225 strcpy(addr.service_name, driver->service_name);
227 err = bind(fd, (struct sockaddr *) &addr,
228 sizeof(struct sockaddr_nfc_llcp));
230 if (errno == EADDRINUSE) {
231 DBG("%s is already bound", driver->name);
235 near_error("%s bind failed %d %d", driver->name, err, errno);
241 err = listen(fd, 10);
243 near_error("%s listen failed %d", driver->name, err);
249 server_data = g_try_malloc0(sizeof(struct p2p_data));
250 if (server_data == NULL) {
255 server_data->driver = driver;
256 server_data->adapter_idx = adapter_idx;
257 server_data->fd = fd;
258 server_data->cb = cb;
260 channel = g_io_channel_unix_new(fd);
261 g_io_channel_set_close_on_unref(channel, TRUE);
263 server_data->watch = g_io_add_watch(channel,
264 G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
266 (gpointer) server_data);
267 g_io_channel_unref(channel);
269 server_list = g_list_append(server_list, server_data);
274 static int p2p_listen(uint32_t adapter_idx, near_device_io_cb cb)
279 for (list = driver_list; list != NULL; list = list->next) {
280 struct near_p2p_driver *driver = list->data;
282 if (p2p_bind(driver, adapter_idx, cb) == 0)
289 static int p2p_connect(uint32_t adapter_idx, uint32_t target_idx,
290 struct near_ndef_message *ndef,
291 near_device_io_cb cb, struct near_p2p_driver *driver)
294 struct sockaddr_nfc_llcp addr;
298 fd = socket(AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP);
302 memset(&addr, 0, sizeof(struct sockaddr_nfc_llcp));
303 addr.sa_family = AF_NFC;
304 addr.dev_idx = adapter_idx;
305 addr.target_idx = target_idx;
306 addr.nfc_protocol = NFC_PROTO_NFC_DEP;
307 addr.service_name_len = strlen(driver->service_name);
308 strcpy(addr.service_name, driver->service_name);
310 err = connect(fd, (struct sockaddr *) &addr,
311 sizeof(struct sockaddr_nfc_llcp));
313 near_error("Connect failed %d", err);
322 static int p2p_push(uint32_t adapter_idx, uint32_t target_idx,
323 struct near_ndef_message *ndef, char *service_name,
324 near_device_io_cb cb)
331 for (list = driver_list; list != NULL; list = list->next) {
332 struct near_p2p_driver *driver = list->data;
334 if (strcmp(driver->service_name, service_name) != 0)
337 * Because of Android's implementation, we have use SNEP for
338 * Handover. So, on Handover session, we try to connect to
339 * the handover service and fallback to SNEP on connect fail.
341 fd = p2p_connect(adapter_idx, target_idx, ndef, cb, driver);
343 return p2p_push(adapter_idx, target_idx, ndef,
344 (char *) driver->fallback_service_name, cb);
346 return driver->push(fd, adapter_idx, target_idx,
353 static struct near_device_driver p2p_driver = {
354 .priority = NEAR_DEVICE_PRIORITY_HIGH,
355 .listen = p2p_listen,
360 int near_p2p_register(struct near_p2p_driver *driver)
362 DBG("driver %p name %s", driver, driver->name);
364 driver_list = g_slist_prepend(driver_list, driver);
369 void near_p2p_unregister(struct near_p2p_driver *driver)
371 DBG("driver %p name %s", driver, driver->name);
373 driver_list = g_slist_remove(driver_list, driver);
376 static int p2p_init(void)
384 return near_device_driver_register(&p2p_driver);
387 static void p2p_exit(void)
391 g_list_free_full(server_list, free_server_data);
397 near_device_driver_unregister(&p2p_driver);
400 NEAR_PLUGIN_DEFINE(p2p, "NFC Forum peer to peer mode support", VERSION,
401 NEAR_PLUGIN_PRIORITY_HIGH, p2p_init, p2p_exit)