int cwiid_set_mesg_callback(cwiid_wiimote_t *wiimote, cwiid_mesg_callback_t *callback) { if (wiimote->mesg_callback) { if (cancel_mesg_callback(wiimote)) { /* prints it's own errors */ return -1; } } wiimote->mesg_callback = callback; if (wiimote->mesg_callback) { if (pthread_create(&wiimote->mesg_callback_thread, NULL, (void *(*)(void *))&mesg_callback_thread, wiimote)) { cwiid_err(wiimote, "Thread creation error (callback thread)"); return -1; } } return 0; }
int cwiid_close(cwiid_wiimote_t *wiimote) { void *pthread_ret; int err; /* Stop rumbling, otherwise wiimote continues to rumble for few seconds after closing the connection! There should be no need to check if stopping fails: we are closing the connection in any case. */ if (wiimote->state.rumble) { cwiid_set_rumble(wiimote, 0); } /* Cancel and join router_thread and status_thread */ if (pthread_cancel(wiimote->router_thread)) { /* if thread quit abnormally, would have printed it's own error */ } err = pthread_join(wiimote->router_thread, &pthread_ret); if (err) { cwiid_err(wiimote, "Thread join error (router thread): %s", strerror(err)); } else if (!((pthread_ret == PTHREAD_CANCELED) || (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from router thread"); } if (pthread_cancel(wiimote->status_thread)) { /* if thread quit abnormally, would have printed it's own error */ } err = pthread_join(wiimote->status_thread, &pthread_ret); if (err) { cwiid_err(wiimote, "Thread join error (status thread): %s", strerror(err)); } else if (!((pthread_ret == PTHREAD_CANCELED) || (pthread_ret == NULL))) { cwiid_err(wiimote, "Bad return value from status thread"); } if (wiimote->mesg_callback) { if (cancel_mesg_callback(wiimote)) { /* prints it's own errors */ } } if (cancel_rw(wiimote)) { /* prints it's own errors */ } /* Close sockets */ if (close(wiimote->int_socket)) { cwiid_err(wiimote, "Socket close error (interrupt socket): %s", strerror(errno)); } if (close(wiimote->ctl_socket)) { cwiid_err(wiimote, "Socket close error (control socket): %s", strerror(errno)); } /* Close Pipes */ if (close(wiimote->mesg_pipe[0]) || close(wiimote->mesg_pipe[1])) { cwiid_err(wiimote, "Pipe close error (mesg pipe): %s", strerror(errno)); } if (close(wiimote->status_pipe[0]) || close(wiimote->status_pipe[1])) { cwiid_err(wiimote, "Pipe close error (status pipe): %s", strerror(errno)); } if (close(wiimote->rw_pipe[0]) || close(wiimote->rw_pipe[1])) { cwiid_err(wiimote, "Pipe close error (rw pipe): %s", strerror(errno)); } /* Destroy mutexes */ err = pthread_mutex_destroy(&wiimote->state_mutex); if (err) { cwiid_err(wiimote, "Mutex destroy error (state): %s", strerror(err)); } err = pthread_mutex_destroy(&wiimote->rw_mutex); if (err) { cwiid_err(wiimote, "Mutex destroy error (rw): %s", strerror(err)); } err = pthread_mutex_destroy(&wiimote->rpt_mutex); if (err) { cwiid_err(wiimote, "Mutex destroy error (rpt): %s", strerror(err)); } free(wiimote); return 0; }