return 0;
}
+static void _interface_disconnect(struct tfm_interface *intf)
+{
+ if (!intf)
+ return;
+
+ if (intf->ops && intf->ops->disconnect) {
+ intf->ops->disconnect(intf);
+ intf->ready = 0;
+ fprintf(stdout, "interface %s is disconnected successfully.\n", intf->name);
+ }
+}
+
+static void cleanup_connection(void *ptr)
+{
+ struct tfm_interface *intf = ptr;
+
+ if (intf->ready)
+ _interface_disconnect(intf);
+}
+
static void *connect_thread_main(void *ptr)
{
struct tfm_interface *intf = ptr;
struct tfm_interface_context *ictx = intf->ctx;
int ret;
+ pthread_cleanup_push(cleanup_connection, intf);
+
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
/* for checking which interface is connected */
return NULL;
}
+ intf->ready = 1;
fprintf(stdout, "interface %s is ready.\n", intf->name);
/*
ret = thor_handshake(intf);
if (ret < 0) {
fprintf(stderr, "failed to handshake: %s\n", intf->name);
- intf->ops->disconnect(intf);
+ _interface_disconnect(intf);
return NULL;
}
fprintf(stderr,
"interface %s will be ignored due to %s\n",
intf->name, ictx->connected->name);
- intf->ops->disconnect(intf);
+ _interface_disconnect(intf);
return NULL;
}
pthread_cond_signal(&ictx->signal);
+ /*
+ * At this point, the corresponding interface is connected and done
+ * hand-shake successfully, and it will be used for transmission.
+ * Thus, to keep connection, pthread_cleanup_pop is called with
+ * zero parameter; cleanup function will not be invoked. The connected
+ * interface will be closed via tfm_interface_disconnect() in main.c
+ */
+ pthread_cleanup_pop(0);
+
return NULL;
}
void tfm_interface_disconnect(struct tfm_interface *intf)
{
- if (!intf)
- return;
-
- if (intf->ops && intf->ops->disconnect)
- intf->ops->disconnect(intf);
+ _interface_disconnect(intf);
intf->ctx->connected = NULL;
}
intf->name = driver->name;
intf->rxd = intf->txd = -1;
+ intf->ready = 0;
intf->ops = &driver->ops;
intf->priv = NULL;
intf->tid = 0;