3 * neard - Near Field Communication manager
5 * Copyright (C) 2012 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
29 #include <sys/socket.h>
31 #include <linux/socket.h>
32 #include <linux/nfc.h>
34 #include <near/plugin.h>
36 #include <near/types.h>
37 #include <near/adapter.h>
38 #include <near/device.h>
39 #include <near/ndef.h>
44 #define SNEP_VERSION 0x10
47 #define SNEP_REQ_CONTINUE 0x00
48 #define SNEP_REQ_GET 0x01
49 #define SNEP_REQ_PUT 0x02
50 #define SNEP_REQ_REJECT 0x7f
53 #define SNEP_RESP_CONTINUE 0x80
54 #define SNEP_RESP_SUCCESS 0x81
55 #define SNEP_RESP_NOT_FOUND 0xc0
56 #define SNEP_RESP_EXCESS 0xc1
57 #define SNEP_RESP_BAD_REQ 0xc2
58 #define SNEP_RESP_NOT_IMPL 0xe0
59 #define SNEP_RESP_VERSION 0xe1
60 #define SNEP_RESP_REJECT 0xff
62 #define SNEP_REQ_PUT_HEADER_LENGTH 6
63 /* TODO: Right now it is dummy, need to get correct value
64 * from lower layers */
65 #define SNEP_REQ_MAX_FRAGMENT_LENGTH 128
67 struct p2p_snep_data {
69 uint32_t nfc_data_length;
70 uint32_t nfc_data_current_length;
71 uint8_t *nfc_data_ptr;
74 gboolean respond_continue;
78 struct snep_fragment {
83 struct p2p_snep_put_req_data {
93 struct p2p_snep_req_frame {
98 } __attribute__((packed));
100 struct p2p_snep_resp_frame {
105 } __attribute__((packed));
107 static GHashTable *snep_client_hash = NULL;
109 static void free_snep_client(gpointer data)
111 struct p2p_snep_data *snep_data = data;
113 g_free(snep_data->nfc_data);
117 static void snep_response_noinfo(int client_fd, uint8_t response)
119 struct p2p_snep_resp_frame resp;
121 DBG("Response 0x%x", response);
123 resp.version = SNEP_VERSION;
124 resp.response = response;
127 send(client_fd, &resp, sizeof(resp), 0);
130 static void snep_close(int client_fd, int err)
132 struct p2p_snep_data *snep_data;
136 snep_data = g_hash_table_lookup(snep_client_hash,
137 GINT_TO_POINTER(client_fd));
138 if (snep_data == NULL)
141 snep_data->cb(snep_data->adapter_idx, snep_data->target_idx, err);
143 g_hash_table_remove(snep_client_hash, GINT_TO_POINTER(client_fd));
146 static near_bool_t snep_read_ndef(int client_fd,
147 struct p2p_snep_data *snep_data)
149 int bytes_recv, remaining_bytes;
150 struct near_device *device;
155 remaining_bytes = snep_data->nfc_data_length -
156 snep_data->nfc_data_current_length;
158 DBG("Remaining bytes %d", remaining_bytes);
160 bytes_recv = recv(client_fd, snep_data->nfc_data_ptr, remaining_bytes,
162 if (bytes_recv < 0) {
163 near_error("%d %s", bytes_recv, strerror(errno));
165 /* Some more data should show up */
172 DBG("Received %d bytes", bytes_recv);
174 snep_data->nfc_data_current_length += bytes_recv;
175 snep_data->nfc_data_ptr += bytes_recv;
177 if (snep_data->nfc_data_length != snep_data->nfc_data_current_length) {
178 if (snep_data->respond_continue == FALSE) {
180 snep_data->respond_continue = TRUE;
181 snep_response_noinfo(client_fd, SNEP_RESP_CONTINUE);
187 snep_response_noinfo(client_fd, SNEP_RESP_SUCCESS);
188 if (near_device_add_data(snep_data->adapter_idx, snep_data->target_idx,
190 snep_data->nfc_data_length) < 0)
193 device = near_device_get_device(snep_data->adapter_idx,
194 snep_data->target_idx);
198 records = near_ndef_parse(snep_data->nfc_data,
199 snep_data->nfc_data_length);
200 near_device_add_records(device, records, snep_data->cb, 0);
203 g_hash_table_remove(snep_client_hash, GINT_TO_POINTER(client_fd));
208 static near_bool_t snep_read(int client_fd,
209 uint32_t adapter_idx, uint32_t target_idx,
212 struct p2p_snep_data *snep_data;
213 struct p2p_snep_req_frame frame;
215 uint32_t ndef_length;
219 snep_data = g_hash_table_lookup(snep_client_hash,
220 GINT_TO_POINTER(client_fd));
223 * We already got something from this client, we should try
224 * to continue reading.
226 if (snep_data != NULL)
227 return snep_read_ndef(client_fd, snep_data);
229 /* TODO Try with PEEK */
230 bytes_recv = recv(client_fd, &frame, sizeof(frame), 0);
231 if (bytes_recv < 0) {
232 near_error("Could not read SNEP frame %d", bytes_recv);
236 ndef_length = GINT_FROM_BE(frame.length);
238 DBG("Allocating SNEP data %d", ndef_length);
240 snep_data = g_try_malloc0(sizeof(struct p2p_snep_data));
241 if (snep_data == NULL)
244 snep_data->nfc_data = g_try_malloc0(ndef_length + TLV_SIZE);
245 if (snep_data->nfc_data == NULL) {
250 snep_data->nfc_data_length = ndef_length;
251 snep_data->nfc_data_ptr = snep_data->nfc_data;
252 snep_data->adapter_idx = adapter_idx;
253 snep_data->target_idx = target_idx;
254 snep_data->respond_continue = FALSE;
257 g_hash_table_insert(snep_client_hash,
258 GINT_TO_POINTER(client_fd), snep_data);
260 DBG("Request 0x%x", frame.request);
262 switch (frame.request) {
263 case SNEP_REQ_CONTINUE:
265 near_error("Unsupported SNEP request code");
266 snep_response_noinfo(client_fd, SNEP_RESP_NOT_IMPL);
269 return snep_read_ndef(client_fd, snep_data);
275 static void free_snep_fragment(gpointer data)
277 struct snep_fragment *fragment = data;
279 if (fragment != NULL)
280 g_free(fragment->data);
286 static void free_snep_push_data(gpointer userdata, int status)
288 struct p2p_snep_put_req_data *data;
292 data = (struct p2p_snep_put_req_data *)userdata;
297 data->cb(data->adapter_idx, data->target_idx, status);
300 g_source_remove(data->watch);
302 g_slist_free_full(data->fragments, free_snep_fragment);
306 static int snep_send_fragment(struct p2p_snep_put_req_data *req)
308 struct snep_fragment *fragment;
313 if (req == NULL || req->fragments == NULL ||
314 g_slist_length(req->fragments) == 0)
317 fragment = req->fragments->data;
319 err = send(req->fd, fragment->data, fragment->len, 0);
321 req->fragments = g_slist_remove(req->fragments, fragment);
322 g_free(fragment->data);
328 static int snep_push_response(struct p2p_snep_put_req_data *req)
330 struct p2p_snep_resp_frame frame;
335 bytes_recv = recv(req->fd, &frame, sizeof(frame), 0);
336 if (bytes_recv < 0) {
337 near_error("Could not read SNEP frame %d", bytes_recv);
341 DBG("Response 0x%x", frame.response);
343 switch (frame.response) {
344 case SNEP_RESP_CONTINUE:
345 while (g_slist_length(req->fragments) != 0) {
346 err = snep_send_fragment(req);
351 return frame.response;
353 case SNEP_RESP_SUCCESS:
360 static gboolean snep_push_event(GIOChannel *channel,
361 GIOCondition condition, gpointer data)
365 DBG("condition 0x%x", condition);
367 if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
369 near_error("Error with SNEP channel");
371 free_snep_push_data(data, -1);
376 err = snep_push_response(data);
378 free_snep_push_data(data, err);
386 static int snep_push_prepare_fragments(struct p2p_snep_put_req_data *req,
387 struct near_ndef_message *ndef)
389 struct snep_fragment *fragment;
390 uint32_t max_fragment_len;
394 max_fragment_len = SNEP_REQ_MAX_FRAGMENT_LENGTH;
396 while (ndef->offset < ndef->length) {
398 fragment = g_try_malloc0(sizeof(struct snep_fragment));
399 if (fragment == NULL)
402 if (max_fragment_len <= (ndef->length - ndef->offset))
403 fragment->len = max_fragment_len;
405 fragment->len = ndef->length - ndef->offset;
407 fragment->data = g_try_malloc0(fragment->len);
408 if (fragment->data == NULL) {
413 memcpy(fragment->data, ndef->data + ndef->offset,
415 ndef->offset += fragment->len;
416 req->fragments = g_slist_append(req->fragments, fragment);
422 static int snep_push(int fd, uint32_t adapter_idx, uint32_t target_idx,
423 struct near_ndef_message *ndef,
424 near_device_io_cb cb)
426 struct p2p_snep_put_req_data *req;
427 struct p2p_snep_req_frame header;
428 struct snep_fragment *fragment;
429 uint32_t max_fragment_len;
431 gboolean fragmenting;
436 req = g_try_malloc0(sizeof(struct p2p_snep_put_req_data));
442 channel = g_io_channel_unix_new(fd);
443 g_io_channel_set_close_on_unref(channel, TRUE);
446 req->adapter_idx = adapter_idx;
447 req->target_idx = target_idx;
450 req->watch = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_NVAL |
451 G_IO_ERR, snep_push_event,
454 max_fragment_len = SNEP_REQ_MAX_FRAGMENT_LENGTH;
455 header.version = SNEP_VERSION;
456 header.request = SNEP_REQ_PUT;
457 header.length = GUINT32_TO_BE(ndef->length);
459 fragment = g_try_malloc0(sizeof(struct snep_fragment));
460 if (fragment == NULL) {
465 if (max_fragment_len >= (ndef->length + SNEP_REQ_PUT_HEADER_LENGTH)) {
466 fragment->len = ndef->length + SNEP_REQ_PUT_HEADER_LENGTH;
469 fragment->len = max_fragment_len;
473 fragment->data = g_try_malloc0(fragment->len);
474 if (fragment->data == NULL) {
480 memcpy(fragment->data, (uint8_t *)&header,
481 SNEP_REQ_PUT_HEADER_LENGTH);
483 if (fragmenting == TRUE) {
484 memcpy(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH,
486 max_fragment_len - SNEP_REQ_PUT_HEADER_LENGTH);
487 ndef->offset = max_fragment_len - SNEP_REQ_PUT_HEADER_LENGTH;
489 err = snep_push_prepare_fragments(req, ndef);
491 g_free(fragment->data);
497 memcpy(fragment->data + SNEP_REQ_PUT_HEADER_LENGTH,
498 ndef->data, ndef->length);
501 err = send(fd, fragment->data, fragment->len, 0);
503 near_error("Sending failed %d", err);
504 g_free(fragment->data);
510 g_free(fragment->data);
516 free_snep_push_data(req, err);
521 struct near_p2p_driver snep_driver = {
523 .service_name = NEAR_DEVICE_SN_SNEP,
531 snep_client_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
532 NULL, free_snep_client);
534 return near_p2p_register(&snep_driver);
539 near_p2p_unregister(&snep_driver);
541 g_hash_table_destroy(snep_client_hash);
542 snep_client_hash = NULL;