From ecc73a015d5670296febd3e07aae3301db3a4158 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 18 Nov 2013 01:48:15 +0100 Subject: adapter: Catch polling errors Receiving a NFC_EVENT_TARGETS_FOUND with a NULL payload means the driver entered an error state. This is handled by checking if the devices and targets arrays are empty from the GET_TARGET finish handler. In the polling error case, neard resets the adapter and starts polling again. The polling error handler runs asynchrounously for the D-Bus properties toggle to be exported properly. --- src/adapter.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/near.h | 1 + src/netlink.c | 16 ++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index 52f11a6..98331a5 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -854,6 +854,50 @@ int __near_adapter_remove_target(uint32_t idx, uint32_t target_idx) return 0; } +static gboolean poll_error(gpointer user_data) +{ + struct near_adapter *adapter = user_data; + + DBG("adapter %d", adapter->idx); + + /* + * Resettting the adapter upon polling errors. + * This could be handled through a configuration setting. + */ + __near_netlink_adapter_enable(adapter->idx, false); + __near_netlink_adapter_enable(adapter->idx, true); + + adapter_start_poll(adapter); + + return FALSE; +} + +int __near_adapter_get_targets_done(uint32_t idx) +{ + struct near_adapter *adapter; + + DBG("idx %d", idx); + + adapter = g_hash_table_lookup(adapter_hash, GINT_TO_POINTER(idx)); + if (!adapter) + return -ENODEV; + + if (g_hash_table_size(adapter->devices) > 0) + return 0; + + if (g_hash_table_size(adapter->tags) > 0) + return 0; + + near_error("No targets found - Polling error"); + + adapter->polling = false; + polling_changed(adapter); + + g_idle_add(poll_error, adapter); + + return 0; +} + int __near_adapter_add_device(uint32_t idx, uint8_t *nfcid, uint8_t nfcid_len) { struct near_adapter *adapter; diff --git a/src/near.h b/src/near.h index cf00675..c75aefe 100644 --- a/src/near.h +++ b/src/near.h @@ -86,6 +86,7 @@ int __near_adapter_add_target(uint32_t idx, uint32_t target_idx, uint32_t protocols, uint16_t sens_res, uint8_t sel_res, uint8_t *nfcid, uint8_t nfcid_len); int __near_adapter_remove_target(uint32_t idx, uint32_t target_idx); +int __near_adapter_get_targets_done(uint32_t idx); int __near_adapter_add_device(uint32_t idx, uint8_t *nfcid, uint8_t nfcid_len); int __near_adapter_remove_device(uint32_t idx); int __near_adapter_set_dep_state(uint32_t idx, bool dep); diff --git a/src/netlink.c b/src/netlink.c index 936f65a..65e42a8 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -492,6 +492,17 @@ static int get_targets_handler(struct nl_msg *n, void *arg) return 0; } +static int get_targets_finish_handler(struct nl_msg *n, void *arg) +{ + uint32_t adapter_idx; + + DBG(""); + + adapter_idx = *((uint32_t *)arg); + + return __near_adapter_get_targets_done(adapter_idx); +} + static int nfc_netlink_event_targets_found(struct genlmsghdr *gnlh) { struct nlattr *attr[NFC_ATTR_MAX + 1]; @@ -526,8 +537,9 @@ static int nfc_netlink_event_targets_found(struct genlmsghdr *gnlh) NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, adapter_idx); - err = nl_send_msg(nfc_state->cmd_sock, msg, - get_targets_handler, &adapter_idx); + err = __nl_send_msg(nfc_state->cmd_sock, msg, + get_targets_handler, get_targets_finish_handler, + &adapter_idx); nla_put_failure: nlmsg_free(msg); -- cgit v1.2.3